diff --git a/.moban.cd/moban.yml b/.moban.cd/moban.yml index 7be5db79..3ded3086 100644 --- a/.moban.cd/moban.yml +++ b/.moban.cd/moban.yml @@ -15,7 +15,7 @@ keywords: - jinja2 - moban dependencies: - - ruamel.yaml==0.15.86 + - ruamel.yaml==0.15.87 - jinja2>=2.7.1 - lml>=0.0.9 - appdirs==1.4.3 diff --git a/docs/level-10-moban-dependency-as-git-repo/README.rst b/docs/level-10-moban-dependency-as-git-repo/README.rst index 6733c3e2..cf5052c3 100644 --- a/docs/level-10-moban-dependency-as-git-repo/README.rst +++ b/docs/level-10-moban-dependency-as-git-repo/README.rst @@ -35,5 +35,6 @@ The alternative syntax is:: - type: git url: https://github.com/your-git-url submodule: true + branch: your_choice_or_default_branch_if_not_specified ... diff --git a/moban/constants.py b/moban/constants.py index d8268fda..9e95dcbe 100644 --- a/moban/constants.py +++ b/moban/constants.py @@ -84,6 +84,7 @@ GIT_REQUIRE = "GIT" GIT_HAS_SUBMODULE = "submodule" GIT_URL = "url" +GIT_BRANCH = "branch" PYPI_REQUIRE = "PYPI" PYPI_PACKAGE_NAME = "name" REQUIRE_TYPE = "type" diff --git a/moban/definitions.py b/moban/definitions.py new file mode 100644 index 00000000..32c7699e --- /dev/null +++ b/moban/definitions.py @@ -0,0 +1,21 @@ +class GitRequire(object): + def __init__(self, git_url=None, branch=None, submodule=False): + self.git_url = git_url + self.submodule = submodule + self.branch = branch + + def clone_params(self): + clone_params = {"single_branch": True} + if self.branch is not None: + clone_params["branch"] = self.branch + return clone_params + + def __eq__(self, other): + return ( + self.git_url == other.git_url + and self.submodule == other.submodule + and self.branch == other.branch + ) + + def __repr__(self): + return "%s,%s,%s" % (self.git_url, self.branch, self.submodule) diff --git a/moban/mobanfile.py b/moban/mobanfile.py index 2e0dd1da..eea481a1 100644 --- a/moban/mobanfile.py +++ b/moban/mobanfile.py @@ -16,6 +16,7 @@ expand_directories, ) from moban.copier import Copier +from moban.definitions import GitRequire try: from urllib.parse import urlparse @@ -165,29 +166,30 @@ def extract_target(options): def handle_requires(requires): pypi_pkgs = [] git_repos = [] - git_repos_with_sub = [] for require in requires: if isinstance(require, dict): require_type = require.get(constants.REQUIRE_TYPE, "") if require_type.upper() == constants.GIT_REQUIRE: - submodule_flag = require.get(constants.GIT_HAS_SUBMODULE) - if submodule_flag is True: - git_repos_with_sub.append(require.get(constants.GIT_URL)) - else: - git_repos.append(require.get(constants.GIT_URL)) + git_repos.append( + GitRequire( + git_url=require.get(constants.GIT_URL), + branch=require.get(constants.GIT_BRANCH), + submodule=require.get( + constants.GIT_HAS_SUBMODULE, False + ), + ) + ) elif require_type.upper() == constants.PYPI_REQUIRE: pypi_pkgs.append(require.get(constants.PYPI_PACKAGE_NAME)) else: if is_repo(require): - git_repos.append(require) + git_repos.append(GitRequire(require)) else: pypi_pkgs.append(require) if pypi_pkgs: pip_install(pypi_pkgs) if git_repos: git_clone(git_repos) - if git_repos_with_sub: - git_clone(git_repos_with_sub, submodule=True) def is_repo(require): diff --git a/moban/utils.py b/moban/utils.py index ee869971..c0aed56c 100644 --- a/moban/utils.py +++ b/moban/utils.py @@ -132,26 +132,28 @@ def pip_install(packages): ) -def git_clone(repos, submodule=False): +def git_clone(requires): from git import Repo moban_home = get_moban_home() mkdir_p(moban_home) - for repo in repos: - repo_name = get_repo_name(repo) + for require in requires: + repo_name = get_repo_name(require.git_url) local_repo_folder = os.path.join(moban_home, repo_name) if os.path.exists(local_repo_folder): reporter.report_git_pull(repo_name) repo = Repo(local_repo_folder) repo.git.pull() - if submodule: + if require.submodule: reporter.report_info_message("updating submodule") repo.git.submodule("update") else: - reporter.report_git_clone(repo_name) - repo = Repo.clone_from(repo, local_repo_folder) - if submodule: + reporter.report_git_clone(require.git_url) + repo = Repo.clone_from( + require.git_url, local_repo_folder, **require.clone_params() + ) + if require.submodule: reporter.report_info_message("checking out submodule") repo.git.submodule("update", "--init") diff --git a/requirements.txt b/requirements.txt index c1dcc49d..3c66b4f8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -ruamel.yaml==0.15.86 +ruamel.yaml==0.15.87 jinja2>=2.7.1 lml>=0.0.9 appdirs==1.4.3 diff --git a/setup.py b/setup.py index 4e3f1fde..b8c617a8 100644 --- a/setup.py +++ b/setup.py @@ -46,7 +46,7 @@ ] INSTALL_REQUIRES = [ - 'ruamel.yaml==0.15.86', + 'ruamel.yaml==0.15.87', 'jinja2>=2.7.1', 'lml>=0.0.9', 'appdirs==1.4.3', diff --git a/tests/test_moban_file.py b/tests/test_moban_file.py index 8c07531f..78c28070 100644 --- a/tests/test_moban_file.py +++ b/tests/test_moban_file.py @@ -1,6 +1,8 @@ from mock import patch from nose.tools import eq_ +from moban.definitions import GitRequire + class TestFinder: def setUp(self): @@ -57,8 +59,12 @@ def test_handle_requires_repos(fake_git_clone): repos = ["https://github.com/my/repo", "https://gitlab.com/my/repo"] from moban.mobanfile import handle_requires + expected = [] + for repo in repos: + expected.append(GitRequire(git_url=repo, submodule=False)) + handle_requires(repos) - fake_git_clone.assert_called_with(repos) + fake_git_clone.assert_called_with(expected) @patch("moban.mobanfile.git_clone") @@ -67,19 +73,26 @@ def test_handle_requires_repos_with_alternative_syntax(fake_git_clone): from moban.mobanfile import handle_requires handle_requires(repos) - fake_git_clone.assert_called_with(["https://github.com/my/repo"]) + fake_git_clone.assert_called_with( + [GitRequire(git_url="https://github.com/my/repo")] + ) +@patch("moban.mobanfile.pip_install") @patch("moban.mobanfile.git_clone") -def test_handle_requires_repos_with_submodule(fake_git_clone): +def test_handle_requires_repos_with_submodule( + fake_git_clone, fake_pip_install +): repos = [ {"type": "git", "url": "https://github.com/my/repo", "submodule": True} ] from moban.mobanfile import handle_requires - expected = ["https://github.com/my/repo"] handle_requires(repos) - fake_git_clone.assert_called_with(expected, submodule=True) + fake_git_clone.assert_called_with( + [GitRequire(git_url="https://github.com/my/repo", submodule=True)] + ) + eq_(fake_pip_install.called, False) def test_is_repo(): diff --git a/tests/test_utils.py b/tests/test_utils.py index 5d18b92c..d88e0fae 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -20,6 +20,7 @@ strip_off_trailing_new_lines, ) from moban.exceptions import FileNotFound +from moban.definitions import GitRequire def create_file(test_file, permission): @@ -147,15 +148,22 @@ class TestGitFunctions: def setUp(self): self.repo_name = "repoA" self.repo = "https://github.com/my/" + self.repo_name + self.require = GitRequire(git_url=self.repo) + self.require_with_submodule = GitRequire( + git_url=self.repo, submodule=True + ) + self.require_with_branch = GitRequire( + git_url=self.repo, branch="ghpages" + ) self.expected_local_repo_path = os.path.join( "root", "repos", self.repo_name ) def test_checkout_new(self, fake_repo, local_folder_exists, *_): local_folder_exists.return_value = False - git_clone([self.repo]) + git_clone([self.require]) fake_repo.clone_from.assert_called_with( - self.repo, self.expected_local_repo_path + self.repo, self.expected_local_repo_path, single_branch=True ) repo = fake_repo.return_value eq_(repo.git.submodule.called, False) @@ -164,29 +172,43 @@ def test_checkout_new_with_submodules( self, fake_repo, local_folder_exists, *_ ): local_folder_exists.return_value = False - git_clone([self.repo], submodule=True) + git_clone([self.require_with_submodule]) fake_repo.clone_from.assert_called_with( - self.repo, self.expected_local_repo_path + self.repo, self.expected_local_repo_path, single_branch=True ) repo = fake_repo.clone_from.return_value repo.git.submodule.assert_called_with("update", "--init") def test_git_update(self, fake_repo, local_folder_exists, *_): local_folder_exists.return_value = True - git_clone([self.repo]) + git_clone([self.require]) fake_repo.assert_called_with(self.expected_local_repo_path) repo = fake_repo.return_value - eq_(repo.git.pull.called, True) + repo.git.pull.assert_called() def test_git_update_with_submodules( self, fake_repo, local_folder_exists, *_ ): local_folder_exists.return_value = True - git_clone([self.repo], submodule=True) + git_clone([self.require_with_submodule]) fake_repo.assert_called_with(self.expected_local_repo_path) repo = fake_repo.return_value repo.git.submodule.assert_called_with("update") + def test_checkout_new_with_branch( + self, fake_repo, local_folder_exists, *_ + ): + local_folder_exists.return_value = False + git_clone([self.require_with_branch]) + fake_repo.clone_from.assert_called_with( + self.repo, + self.expected_local_repo_path, + branch="ghpages", + single_branch=True, + ) + repo = fake_repo.return_value + eq_(repo.git.submodule.called, False) + def test_get_repo_name(): repos = ["https://github.com/abc/repo", "https://github.com/abc/repo/"]