Skip to content

Commit

Permalink
feat(config): Config object
Browse files Browse the repository at this point in the history
  • Loading branch information
tony committed Dec 31, 2022
1 parent 2654f9f commit bd8b741
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
84 changes: 84 additions & 0 deletions src/vcspull/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
A lot of these items are todo.
"""
import dataclasses
import fnmatch
import logging
import os
import pathlib
import typing as t

import yaml

from libvcs._internal.query_list import QueryList
from libvcs._internal.shortcuts import create_project
from libvcs.sync.git import GitRemote
from vcspull.validator import is_valid_config

Expand All @@ -24,6 +29,85 @@
if t.TYPE_CHECKING:
from typing_extensions import TypeGuard

from libvcs.sync.git import GitSync
from libvcs.sync.hg import HgSync
from libvcs.sync.svn import SvnSync

Repo = t.Union["GitSync", "HgSync", "SvnSync"]


@dataclasses.dataclass
class Config:
repo_dict_map: list["Repo"]
repos: list["Repo"] = dataclasses.field(init=False, default_factory=list)

def __post_init__(self) -> None:
for repo in self.repo_dict_map:
if isinstance(repo, dict):
self.repos.append(create_project(**repo))

def filter_repos(self, **kwargs: object) -> list["Repo"]:
return QueryList(self.repos).filter(**kwargs)

@classmethod
def from_yaml_file(
cls, file_path: pathlib.Path, cwd: pathlib.Path = pathlib.Path.cwd()
) -> "Config":
# load yaml
raw_config = yaml.load(open(file_path).read(), Loader=yaml.Loader)
repos: list[ConfigDict] = []
for directory, repo_map in raw_config.items():
assert isinstance(repo_map, dict)
for repo, repo_data in repo_map.items():
conf: dict[str, t.Any] = {}

if isinstance(repo_data, str):
conf["url"] = repo_data
else:
conf = update_dict(conf, repo_data)

if "repo" in conf:
if "url" not in conf:
conf["url"] = conf.pop("repo")
else:
conf.pop("repo", None)

if "name" not in conf:
conf["name"] = repo

if "dir" not in conf:
conf["dir"] = expand_dir(
pathlib.Path(expand_dir(pathlib.Path(directory), cwd=cwd))
/ conf["name"],
cwd,
)

if "remotes" in conf:
assert isinstance(conf["remotes"], dict)
for remote_name, url in conf["remotes"].items():
if isinstance(url, GitRemote):
continue
if isinstance(url, str):
conf["remotes"][remote_name] = GitRemote(
name=remote_name, fetch_url=url, push_url=url
)
elif isinstance(url, dict):
assert "push_url" in url
assert "fetch_url" in url
conf["remotes"][remote_name] = GitRemote(
name=remote_name, **url
)

def is_valid_config_dict(val: t.Any) -> "TypeGuard[ConfigDict]":
assert isinstance(val, dict)
return True

assert is_valid_config_dict(conf)
repos.append(conf)

# assert validate_config(config) # mypy happy
return cls(repo_dict_map=repos) # type:ignore


def expand_dir(
_dir: pathlib.Path, cwd: pathlib.Path = pathlib.Path.cwd()
Expand Down
51 changes: 51 additions & 0 deletions tests/test_config_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import pathlib
import typing as t

import pytest

from libvcs._internal.types import StrPath
from vcspull import config as config_tools


class LoadYaml(t.Protocol):
def __call__(
self, content: str, dir: StrPath = ..., filename: str = ...
) -> pathlib.Path:
...


@pytest.fixture
def load_yaml(tmp_path: pathlib.Path) -> LoadYaml:
def fn(
content: str, dir: StrPath = "randomdir", filename: str = "randomfilename.yaml"
) -> pathlib.Path:
_dir = tmp_path / dir
_dir.mkdir()
_config = _dir / filename
_config.write_text(content, encoding="utf-8")

return _config

return fn


def test_simple_format(load_yaml: LoadYaml) -> None:
config_file = load_yaml(
"""
vcspull:
libvcs: git+https://github.com/vcs-python/libvcs
"""
)

config = config_tools.Config.from_yaml_file(config_file)

assert len(config.repos) == 1
repo = config.repos[0]
dir = repo.dir.parent.parent

assert dir / "vcspull" == repo.dir.parent
assert dir / "vcspull" / "libvcs" == repo.dir

assert hasattr(config, "filter_repos")
assert callable(config.filter_repos)
assert config.filter_repos(dir=dir / "vcspull" / "libvcs") == [repo]

0 comments on commit bd8b741

Please sign in to comment.