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
diff --git a/buildstream/plugins/sources/git.py b/buildstream/plugins/sources/git.py
index ae8f36b..74d632b 100644
--- a/buildstream/plugins/sources/git.py
+++ b/buildstream/plugins/sources/git.py
@@ -247,7 +247,7 @@
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 b9251e3..c9e8062 100644
--- a/tests/sources/git.py
+++ b/tests/sources/git.py
@@ -23,6 +23,7 @@
import os
import pytest
import subprocess
+import shutil
from buildstream._exceptions import ErrorDomain
from buildstream import _yaml
@@ -920,3 +921,100 @@
element = _yaml.load(element_path)
assert 'tags' not in element['sources'][0]
+
+
+@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 b2d4809..3eb8c65 100644
--- a/tests/testutils/repo/git.py
+++ b/tests/testutils/repo/git.py
@@ -99,12 +99,15 @@
return config
def latest_commit(self):
- output = self._run_git('rev-parse', 'master', stdout=subprocess.PIPE).stdout
+ output = self._run_git('rev-parse', 'HEAD', stdout=subprocess.PIPE).stdout
return output.decode('UTF-8').strip()
def branch(self, branch_name):
self._run_git('checkout', '-b', branch_name)
+ def delete_tag(self, tag_name):
+ self._run_git('tag', '-d', tag_name)
+
def checkout(self, commit):
self._run_git('checkout', commit)