Jürg Billeter pushed to branch juerg/git-describe at BuildStream / buildstream
Commits:
-
900e8900
by Jürg Billeter at 2018-09-27T13:12:34Z
-
107269c1
by Jürg Billeter at 2018-09-27T13:12:34Z
-
8060ad8c
by Jürg Billeter at 2018-09-27T13:12:34Z
3 changed files:
Changes:
... | ... | @@ -43,6 +43,12 @@ git - stage files from a git repository |
43 | 43 |
# will be used to update the 'ref' when refreshing the pipeline.
|
44 | 44 |
track: master
|
45 | 45 |
|
46 |
+ # Optionally specify the ref format used for tracking.
|
|
47 |
+ # The default is 'sha1' for the raw commit hash.
|
|
48 |
+ # If you specify 'git-describe', the commit hash will be prefixed
|
|
49 |
+ # with the closest tag.
|
|
50 |
+ ref-format: sha1
|
|
51 |
+ |
|
46 | 52 |
# Specify the commit ref, this must be specified in order to
|
47 | 53 |
# checkout sources and build, but can be automatically updated
|
48 | 54 |
# if the 'track' attribute was specified.
|
... | ... | @@ -205,7 +211,18 @@ class GitMirror(SourceFetcher): |
205 | 211 |
[self.source.host_git, 'rev-parse', tracking],
|
206 | 212 |
fail="Unable to find commit for specified branch name '{}'".format(tracking),
|
207 | 213 |
cwd=self.mirror)
|
208 |
- return output.rstrip('\n')
|
|
214 |
+ ref = output.rstrip('\n')
|
|
215 |
+ |
|
216 |
+ if self.source.ref_format == 'git-describe':
|
|
217 |
+ # Prefix the ref with the closest tag, if available,
|
|
218 |
+ # to make the ref human readable
|
|
219 |
+ exit_code, output = self.source.check_output(
|
|
220 |
+ [self.source.host_git, 'describe', '--tags', '--abbrev=40', '--long', ref],
|
|
221 |
+ cwd=self.mirror)
|
|
222 |
+ if exit_code == 0:
|
|
223 |
+ ref = output.rstrip('\n')
|
|
224 |
+ |
|
225 |
+ return ref
|
|
209 | 226 |
|
210 | 227 |
def stage(self, directory, track=None):
|
211 | 228 |
fullpath = os.path.join(directory, self.path)
|
... | ... | @@ -341,13 +358,18 @@ class GitSource(Source): |
341 | 358 |
def configure(self, node):
|
342 | 359 |
ref = self.node_get_member(node, str, 'ref', None)
|
343 | 360 |
|
344 |
- config_keys = ['url', 'track', 'ref', 'submodules', 'checkout-submodules']
|
|
361 |
+ config_keys = ['url', 'track', 'ref', 'submodules', 'checkout-submodules', 'ref-format']
|
|
345 | 362 |
self.node_validate(node, config_keys + Source.COMMON_CONFIG_KEYS)
|
346 | 363 |
|
347 | 364 |
self.original_url = self.node_get_member(node, str, 'url')
|
348 | 365 |
self.mirror = GitMirror(self, '', self.original_url, ref, primary=True)
|
349 | 366 |
self.tracking = self.node_get_member(node, str, 'track', None)
|
350 | 367 |
|
368 |
+ self.ref_format = self.node_get_member(node, str, 'ref-format', 'sha1')
|
|
369 |
+ if self.ref_format not in ['sha1', 'git-describe']:
|
|
370 |
+ provenance = self.node_provenance(node, member_name='ref-format')
|
|
371 |
+ raise SourceError("{}: Unexpected value for ref-format: {}".format(provenance, self.ref_format))
|
|
372 |
+ |
|
351 | 373 |
# At this point we now know if the source has a ref and/or a track.
|
352 | 374 |
# If it is missing both then we will be unable to track or build.
|
353 | 375 |
if self.mirror.ref is None and self.tracking is None:
|
... | ... | @@ -476,3 +476,50 @@ def test_ref_not_in_track_warn_error(cli, tmpdir, datafiles): |
476 | 476 |
result = cli.run(project=project, args=['build', 'target.bst'])
|
477 | 477 |
result.assert_main_error(ErrorDomain.STREAM, None)
|
478 | 478 |
result.assert_task_error(ErrorDomain.PLUGIN, CoreWarnings.REF_NOT_IN_TRACK)
|
479 |
+ |
|
480 |
+ |
|
481 |
+@pytest.mark.skipif(HAVE_GIT is False, reason="git is not available")
|
|
482 |
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'template'))
|
|
483 |
+@pytest.mark.parametrize("ref_format", ['sha1', 'git-describe'])
|
|
484 |
+@pytest.mark.parametrize("tag,extra_commit", [(False, False), (True, False), (True, True)])
|
|
485 |
+def test_track_fetch(cli, tmpdir, datafiles, ref_format, tag, extra_commit):
|
|
486 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
487 |
+ |
|
488 |
+ # Create the repo from 'repofiles' subdir
|
|
489 |
+ repo = create_repo('git', str(tmpdir))
|
|
490 |
+ ref = repo.create(os.path.join(project, 'repofiles'))
|
|
491 |
+ if tag:
|
|
492 |
+ repo.add_tag('tag')
|
|
493 |
+ if extra_commit:
|
|
494 |
+ repo.add_commit()
|
|
495 |
+ |
|
496 |
+ # Write out our test target
|
|
497 |
+ element = {
|
|
498 |
+ 'kind': 'import',
|
|
499 |
+ 'sources': [
|
|
500 |
+ repo.source_config()
|
|
501 |
+ ]
|
|
502 |
+ }
|
|
503 |
+ element['sources'][0]['ref-format'] = ref_format
|
|
504 |
+ element_path = os.path.join(project, 'target.bst')
|
|
505 |
+ _yaml.dump(element, element_path)
|
|
506 |
+ |
|
507 |
+ # Track it
|
|
508 |
+ result = cli.run(project=project, args=['track', 'target.bst'])
|
|
509 |
+ result.assert_success()
|
|
510 |
+ |
|
511 |
+ element = _yaml.load(element_path)
|
|
512 |
+ new_ref = element['sources'][0]['ref']
|
|
513 |
+ |
|
514 |
+ if ref_format == 'git-describe' and tag:
|
|
515 |
+ # Check and strip prefix
|
|
516 |
+ prefix = 'tag-{}-g'.format(0 if not extra_commit else 1)
|
|
517 |
+ assert new_ref.startswith(prefix)
|
|
518 |
+ new_ref = new_ref[len(prefix):]
|
|
519 |
+ |
|
520 |
+ # 40 chars for SHA-1
|
|
521 |
+ assert len(new_ref) == 40
|
|
522 |
+ |
|
523 |
+ # Fetch it
|
|
524 |
+ result = cli.run(project=project, args=['fetch', 'target.bst'])
|
|
525 |
+ result.assert_success()
|
... | ... | @@ -42,6 +42,9 @@ class Git(Repo): |
42 | 42 |
self._run_git('commit', '-m', 'Initial commit')
|
43 | 43 |
return self.latest_commit()
|
44 | 44 |
|
45 |
+ def add_tag(self, tag):
|
|
46 |
+ self._run_git('tag', tag)
|
|
47 |
+ |
|
45 | 48 |
def add_commit(self):
|
46 | 49 |
self._run_git('commit', '--allow-empty', '-m', 'Additional commit')
|
47 | 50 |
return self.latest_commit()
|