summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin David <valentin.david@codethink.co.uk>2018-12-07 16:59:41 +0100
committerValentin David <valentin.david@codethink.co.uk>2018-12-11 14:56:30 +0100
commitd898cb9e21f8b291def0dd5b44478c51c3b083fd (patch)
treeaee160932d0ec9c174354e3afed645a325f57e39
parentf70eba734a937f54719de657ca1c38a9b7801e0c (diff)
downloadbuildstream-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.py2
-rw-r--r--tests/sources/git.py98
-rw-r--r--tests/testutils/repo/git.py15
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()