def test_unknown_group() -> None: group_list = GroupList(elements=["a", "b", "c"]) group_list.add("default", ["a", "b"]) with pytest.raises(GroupNotFound) as e: group_list.get_elements(groups=["no-such-group"]) assert e.value.parent_group is None assert e.value.group_name == "no-such-group"
def test_circle() -> None: group_list = GroupList(elements=["a", "b", "c"]) group_list.add("a", ["a"], includes=["b"]) group_list.add("b", ["b"], includes=["c"]) group_list.add("c", ["c"], includes=["a"]) actual = group_list.get_elements(groups=["a"]) assert actual == ["c", "b", "a"]
def test_remove_duplicates() -> None: group_list = GroupList(elements=["a", "b", "c", "z"]) group_list.add("one", ["a", "z"]) group_list.add("two", ["b", "z"]) group_list.add("all", ["c"], includes=["one", "two"]) actual = group_list.get_elements(groups=["all"]) assert actual == ["a", "z", "b", "c"]
def test_diamond() -> None: group_list = GroupList(elements=["a", "b", "c", "d"]) group_list.add("top", ["a"]) group_list.add("left", ["b"], includes=["top"]) group_list.add("right", ["c"], includes=["top"]) group_list.add("bottom", ["d"], includes=["left", "right"]) actual = group_list.get_elements(groups=["bottom"]) assert actual == ["a", "b", "c", "d"]
def test_ping_pong() -> None: group_list = GroupList(elements=["a", "b"]) group_list.add("ping", ["a"], includes=["pong"]) group_list.add("pong", ["b"], includes=["ping"]) actual = group_list.get_elements(groups=["ping"]) assert actual == ["b", "a"]
def test_happy_grouping() -> None: group_list = GroupList(elements=["a", "b", "c"]) group_list.add("default", ["a", "b"]) group_list.add("other", ["c"], includes=["default"]) actual = group_list.get_elements(groups=["other"]) assert actual == ["a", "b", "c"]
class Manifest: """Contains a list of `Repo` instances, and optionally a group list. """ def __init__(self) -> None: self._repos: List[Repo] = [] self.group_list: Optional[GroupList[str]] = None def apply_config(self, config: Any) -> None: """Apply config coming form the yaml file""" # Note: we cannot just serialize the yaml file into the class, # because we need to convert the plain old dicts into # higher-level classes. self.file_system_operations: List[FileSystemOperation] = [] self.symlinks: List[Link] = [] repos_config = config["repos"] for repo_config in repos_config: self._handle_repo(repo_config) self._handle_copies(repo_config) self._handle_links(repo_config) groups_config = config.get("groups") self._handle_groups(groups_config) def _handle_repo(self, repo_config: Any) -> None: dest = repo_config["dest"] branch = repo_config.get("branch", "master") tag = repo_config.get("tag") sha1 = repo_config.get("sha1") url = repo_config.get("url") ignore_submodules = repo_config.get("ignore_submodules", False) if url: origin = Remote(name="origin", url=url) remotes = [origin] else: remotes = self._handle_remotes(repo_config) repo = Repo( dest=dest, branch=branch, sha1=sha1, tag=tag, remotes=remotes, ignore_submodules=ignore_submodules, ) self._repos.append(repo) def _handle_remotes(self, repo_config: Any) -> List[Remote]: remotes_config = repo_config.get("remotes") res = [] if remotes_config: for remote_config in remotes_config: remote = Remote(name=remote_config["name"], url=remote_config["url"]) res.append(remote) return res def _handle_copies(self, repo_config: Any) -> None: if "copy" not in repo_config: return to_cp = repo_config["copy"] for item in to_cp: src = item["file"] dest = item.get("dest", src) copy = Copy(repo_config["dest"], src, dest) self.file_system_operations.append(copy) def _handle_links(self, repo_config: Any) -> None: if "symlink" not in repo_config: return to_link = repo_config["symlink"] for item in to_link: source = item["source"] target = item["target"] link = Link(repo_config["dest"], source, target) self.file_system_operations.append(link) def _handle_groups(self, groups_config: Any) -> None: elements = [repo.dest for repo in self._repos] self.group_list = GroupList(elements=elements) if not groups_config: return for name, group_config in groups_config.items(): elements = group_config["repos"] includes = group_config.get("includes", []) self.group_list.add(name, elements, includes=includes) def get_repos(self, groups: Optional[List[str]] = None, all_: bool = False) -> List[Repo]: if all_: return self._repos if not groups: if self._has_default_group(): return self._get_repos_in_groups(["default"]) else: return self._repos return self._get_repos_in_groups(groups) def _has_default_group(self) -> bool: assert self.group_list return self.group_list.get_group("default") is not None def _get_repos_in_groups(self, groups: List[str]) -> List[Repo]: assert self.group_list elements = self.group_list.get_elements(groups=groups) res = [] for dest in elements: res.append(self.get_repo(dest)) return res def get_repo(self, dest: str) -> Repo: for repo in self._repos: if repo.dest == dest: return repo raise RepoNotFound(dest)