diff options
author | Valentin David <valentin.david@codethink.co.uk> | 2018-12-07 16:59:41 +0100 |
---|---|---|
committer | Valentin David <valentin.david@codethink.co.uk> | 2018-12-11 14:56:30 +0100 |
commit | d898cb9e21f8b291def0dd5b44478c51c3b083fd (patch) | |
tree | aee160932d0ec9c174354e3afed645a325f57e39 | |
parent | f70eba734a937f54719de657ca1c38a9b7801e0c (diff) | |
download | buildstream-d898cb9e21f8b291def0dd5b44478c51c3b083fd.tar.gz |
Force updating tags when fetching git repository
When using aliases there are multiple remotes used in the cache
repository. When fetching, tags are not updated if the were previously
fetched from a different remote. Commits that not in a branch and only
tagged do not get fetched if the tag is not fetched.
Fixes #812
-rw-r--r-- | buildstream/plugins/sources/git.py | 2 | ||||
-rw-r--r-- | tests/sources/git.py | 98 | ||||
-rw-r--r-- | tests/testutils/repo/git.py | 15 |
3 files changed, 113 insertions, 2 deletions
diff --git a/buildstream/plugins/sources/git.py b/buildstream/plugins/sources/git.py index 1ff2f3287..0ff46803f 100644 --- a/buildstream/plugins/sources/git.py +++ b/buildstream/plugins/sources/git.py @@ -158,7 +158,7 @@ class GitMirror(SourceFetcher): else: remote_name = "origin" - self.source.call([self.source.host_git, 'fetch', remote_name, '--prune'], + self.source.call([self.source.host_git, 'fetch', remote_name, '--prune', '--force', '--tags'], fail="Failed to fetch from remote git repository: {}".format(url), fail_temporarily=True, cwd=self.mirror) diff --git a/tests/sources/git.py b/tests/sources/git.py index 781d6d4d1..82778e6df 100644 --- a/tests/sources/git.py +++ b/tests/sources/git.py @@ -22,6 +22,7 @@ import os import pytest +import shutil from buildstream._exceptions import ErrorDomain from buildstream import _yaml @@ -408,3 +409,100 @@ def test_submodule_track_no_ref_or_track(cli, tmpdir, datafiles): result = cli.run(project=project, args=['show', 'target.bst']) result.assert_main_error(ErrorDomain.SOURCE, "missing-track-and-ref") result.assert_task_error(None, None) + + +@pytest.mark.skipif(HAVE_GIT is False, reason="git is not available") +@pytest.mark.datafiles(os.path.join(DATA_DIR, 'template')) +def test_overwrite_rogue_tag_multiple_remotes(cli, tmpdir, datafiles): + """When using multiple remotes in cache (i.e. when using aliases), we + need to make sure we override tags. This is not allowed to fetch + tags that were present from different origins + """ + + project = str(datafiles) + + repofiles = os.path.join(str(tmpdir), 'repofiles') + os.makedirs(repofiles, exist_ok=True) + file0 = os.path.join(repofiles, 'file0') + with open(file0, 'w') as f: + f.write('test\n') + + repo = create_repo('git', str(tmpdir)) + + top_commit = repo.create(repofiles) + + repodir, reponame = os.path.split(repo.repo) + project_config = _yaml.load(os.path.join(project, 'project.conf')) + project_config['aliases'] = { + 'repo': 'http://example.com/' + } + project_config['mirrors'] = [ + { + 'name': 'middle-earth', + 'aliases': { + 'repo': ['file://{}/'.format(repodir)] + } + } + ] + _yaml.dump(_yaml.node_sanitize(project_config), os.path.join(project, 'project.conf')) + + repo.add_annotated_tag('tag', 'tag') + + file1 = os.path.join(repofiles, 'file1') + with open(file1, 'w') as f: + f.write('test\n') + + ref = repo.add_file(file1) + + config = repo.source_config(ref=ref) + del config['track'] + config['url'] = 'repo:{}'.format(reponame) + + # Write out our test target + element = { + 'kind': 'import', + 'sources': [ + config + ], + } + element_path = os.path.join(project, 'target.bst') + _yaml.dump(element, element_path) + + result = cli.run(project=project, args=['build', 'target.bst']) + result.assert_success() + + repo.checkout(top_commit) + + file2 = os.path.join(repofiles, 'file2') + with open(file2, 'w') as f: + f.write('test\n') + + new_ref = repo.add_file(file2) + + repo.delete_tag('tag') + repo.add_annotated_tag('tag', 'tag') + repo.checkout('master') + + otherpath = os.path.join(str(tmpdir), 'other_path') + shutil.copytree(repo.repo, + os.path.join(otherpath, 'repo')) + new_repo = create_repo('git', otherpath) + + repodir, reponame = os.path.split(repo.repo) + + _yaml.dump(_yaml.node_sanitize(project_config), os.path.join(project, 'project.conf')) + + config = repo.source_config(ref=new_ref) + del config['track'] + config['url'] = 'repo:{}'.format(reponame) + + element = { + 'kind': 'import', + 'sources': [ + config + ], + } + _yaml.dump(element, element_path) + + result = cli.run(project=project, args=['build', 'target.bst']) + result.assert_success() diff --git a/tests/testutils/repo/git.py b/tests/testutils/repo/git.py index 75624d597..99b6bb384 100644 --- a/tests/testutils/repo/git.py +++ b/tests/testutils/repo/git.py @@ -82,9 +82,22 @@ class Git(Repo): def latest_commit(self): output = subprocess.check_output([ - 'git', 'rev-parse', 'master' + 'git', 'rev-parse', 'HEAD' ], env=GIT_ENV, cwd=self.repo) return output.decode('UTF-8').strip() def branch(self, branch_name): subprocess.call(['git', 'checkout', '-b', branch_name], env=GIT_ENV, cwd=self.repo) + + def delete_tag(self, tag_name): + subprocess.call(['git', 'tag', '-d', tag_name], + env=GIT_ENV, cwd=self.repo) + + def checkout(self, commit): + subprocess.call(['git', 'checkout', commit], + env=GIT_ENV, cwd=self.repo) + + def add_annotated_tag(self, tag, message): + subprocess.call(['git', 'tag', '-a', tag, '-m', message], + env=GIT_ENV, cwd=self.repo) + return self.latest_commit() |