summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.van.berkom@gmail.com>2019-08-04 17:19:26 +0000
committerTristan Van Berkom <tristan.van.berkom@gmail.com>2019-08-04 17:19:26 +0000
commit6481083503f034e3c38daebbe675433dc5b7818b (patch)
tree0cad63915cd9773256f6ab165a0957fdcc376315
parent20b6e7b455c6445ae966ee585825fbbbc89b1034 (diff)
parent36e42c7dc6f027ada7bdd72f19ec87d031828e05 (diff)
downloadbuildstream-6481083503f034e3c38daebbe675433dc5b7818b.tar.gz
Merge branch 'tristan/bst-1/pretty-git-refs' into 'bst-1'
Backport pretty git refs See merge request BuildStream/buildstream!1516
-rw-r--r--buildstream/plugins/sources/git.py26
-rw-r--r--tests/sources/git.py47
-rw-r--r--tests/testutils/repo/git.py3
3 files changed, 74 insertions, 2 deletions
diff --git a/buildstream/plugins/sources/git.py b/buildstream/plugins/sources/git.py
index 542fc8011..a44717a35 100644
--- a/buildstream/plugins/sources/git.py
+++ b/buildstream/plugins/sources/git.py
@@ -43,6 +43,12 @@ git - stage files from a git repository
# will be used to update the 'ref' when refreshing the pipeline.
track: master
+ # Optionally specify the ref format used for tracking.
+ # The default is 'sha1' for the raw commit hash.
+ # If you specify 'git-describe', the commit hash will be prefixed
+ # with the closest tag.
+ ref-format: sha1
+
# Specify the commit ref, this must be specified in order to
# checkout sources and build, but can be automatically updated
# if the 'track' attribute was specified.
@@ -229,7 +235,18 @@ class GitMirror(SourceFetcher):
[self.source.host_git, 'rev-parse', tracking],
fail="Unable to find commit for specified branch name '{}'".format(tracking),
cwd=self.mirror)
- return output.rstrip('\n')
+ ref = output.rstrip('\n')
+
+ if self.source.ref_format == 'git-describe':
+ # Prefix the ref with the closest tag, if available,
+ # to make the ref human readable
+ exit_code, output = self.source.check_output(
+ [self.source.host_git, 'describe', '--tags', '--abbrev=40', '--long', ref],
+ cwd=self.mirror)
+ if exit_code == 0:
+ ref = output.rstrip('\n')
+
+ return ref
def stage(self, directory):
fullpath = os.path.join(directory, self.path)
@@ -332,13 +349,18 @@ class GitSource(Source):
def configure(self, node):
ref = self.node_get_member(node, str, 'ref', None)
- config_keys = ['url', 'track', 'ref', 'submodules', 'checkout-submodules']
+ config_keys = ['url', 'track', 'ref', 'submodules', 'checkout-submodules', 'ref-format']
self.node_validate(node, config_keys + Source.COMMON_CONFIG_KEYS)
self.original_url = self.node_get_member(node, str, 'url')
self.mirror = GitMirror(self, '', self.original_url, ref, primary=True)
self.tracking = self.node_get_member(node, str, 'track', None)
+ self.ref_format = self.node_get_member(node, str, 'ref-format', 'sha1')
+ if self.ref_format not in ['sha1', 'git-describe']:
+ provenance = self.node_provenance(node, member_name='ref-format')
+ raise SourceError("{}: Unexpected value for ref-format: {}".format(provenance, self.ref_format))
+
# At this point we now know if the source has a ref and/or a track.
# If it is missing both then we will be unable to track or build.
if self.mirror.ref is None and self.tracking is None:
diff --git a/tests/sources/git.py b/tests/sources/git.py
index e7daa95a7..9b59e30fb 100644
--- a/tests/sources/git.py
+++ b/tests/sources/git.py
@@ -481,6 +481,53 @@ def test_ref_not_in_track_warn_error(cli, tmpdir, datafiles):
@pytest.mark.skipif(HAVE_GIT is False, reason="git is not available")
@pytest.mark.datafiles(os.path.join(DATA_DIR, 'template'))
+@pytest.mark.parametrize("ref_format", ['sha1', 'git-describe'])
+@pytest.mark.parametrize("tag,extra_commit", [(False, False), (True, False), (True, True)])
+def test_track_fetch(cli, tmpdir, datafiles, ref_format, tag, extra_commit):
+ project = os.path.join(datafiles.dirname, datafiles.basename)
+
+ # Create the repo from 'repofiles' subdir
+ repo = create_repo('git', str(tmpdir))
+ ref = repo.create(os.path.join(project, 'repofiles'))
+ if tag:
+ repo.add_tag('tag')
+ if extra_commit:
+ repo.add_commit()
+
+ # Write out our test target
+ element = {
+ 'kind': 'import',
+ 'sources': [
+ repo.source_config()
+ ]
+ }
+ element['sources'][0]['ref-format'] = ref_format
+ element_path = os.path.join(project, 'target.bst')
+ _yaml.dump(element, element_path)
+
+ # Track it
+ result = cli.run(project=project, args=['track', 'target.bst'])
+ result.assert_success()
+
+ element = _yaml.load(element_path)
+ new_ref = element['sources'][0]['ref']
+
+ if ref_format == 'git-describe' and tag:
+ # Check and strip prefix
+ prefix = 'tag-{}-g'.format(0 if not extra_commit else 1)
+ assert new_ref.startswith(prefix)
+ new_ref = new_ref[len(prefix):]
+
+ # 40 chars for SHA-1
+ assert len(new_ref) == 40
+
+ # Fetch it
+ result = cli.run(project=project, args=['fetch', 'target.bst'])
+ result.assert_success()
+
+
+@pytest.mark.skipif(HAVE_GIT is False, reason="git is not available")
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'template'))
@pytest.mark.parametrize("fail", ['warn', 'error'])
def test_unlisted_submodule(cli, tmpdir, datafiles, fail):
project = os.path.join(datafiles.dirname, datafiles.basename)
diff --git a/tests/testutils/repo/git.py b/tests/testutils/repo/git.py
index 5587baacb..1adc096dd 100644
--- a/tests/testutils/repo/git.py
+++ b/tests/testutils/repo/git.py
@@ -33,6 +33,9 @@ class Git(Repo):
subprocess.call(['git', 'commit', '-m', 'Initial commit'], env=GIT_ENV, cwd=self.repo)
return self.latest_commit()
+ def add_tag(self, tag):
+ subprocess.call(['git', 'tag', tag], env=GIT_ENV, cwd=self.repo)
+
def add_commit(self):
subprocess.call(['git', 'commit', '--allow-empty', '-m', 'Additional commit'],
env=GIT_ENV, cwd=self.repo)