summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.van.berkom@gmail.com>2019-08-04 02:11:31 +0000
committerTristan Van Berkom <tristan.van.berkom@gmail.com>2019-08-04 02:11:31 +0000
commitd1316fa759d71d531bf6a1802e3827ccf4b5cc23 (patch)
tree12b60ff999505bd65966192477ee0462f6112d4e
parent6320c08dfff12d3c19e4a98afde03f127c08ebe0 (diff)
parenta155ba93df2073f233a2f2569e6cbd6b2df91aab (diff)
downloadbuildstream-d1316fa759d71d531bf6a1802e3827ccf4b5cc23.tar.gz
Merge branch 'tristan/bst-1/ref-not-in-track' into 'bst-1'
Backport git support for ref-not-in-track configurable warnings See merge request BuildStream/buildstream!1514
-rw-r--r--buildstream/plugins/sources/git.py45
-rw-r--r--tests/sources/git.py68
2 files changed, 109 insertions, 4 deletions
diff --git a/buildstream/plugins/sources/git.py b/buildstream/plugins/sources/git.py
index 041fed123..4b099b5ab 100644
--- a/buildstream/plugins/sources/git.py
+++ b/buildstream/plugins/sources/git.py
@@ -74,6 +74,9 @@ This plugin provides the following configurable warnings:
- 'git:inconsistent-submodule' - A submodule was found to be missing from the underlying git repository.
+This plugin also utilises the following configurable core plugin warnings:
+
+- 'ref-not-in-track' - The provided ref was not found in the provided track in the element's git repository.
"""
import os
@@ -86,6 +89,7 @@ from configparser import RawConfigParser
from buildstream import Source, SourceError, Consistency, SourceFetcher
from buildstream import utils
+from buildstream.plugin import CoreWarnings
GIT_MODULES = '.gitmodules'
@@ -210,7 +214,7 @@ class GitMirror(SourceFetcher):
cwd=self.mirror)
return output.rstrip('\n')
- def stage(self, directory):
+ def stage(self, directory, track=None):
fullpath = os.path.join(directory, self.path)
# We need to pass '--no-hardlinks' because there's nothing to
@@ -224,7 +228,11 @@ class GitMirror(SourceFetcher):
fail="Failed to checkout git ref {}".format(self.ref),
cwd=fullpath)
- def init_workspace(self, directory):
+ # Check that the user specified ref exists in the track if provided & not already tracked
+ if track:
+ self.assert_ref_in_track(fullpath, track)
+
+ def init_workspace(self, directory, track=None):
fullpath = os.path.join(directory, self.path)
url = self.source.translate_url(self.url)
@@ -240,6 +248,10 @@ class GitMirror(SourceFetcher):
fail="Failed to checkout git ref {}".format(self.ref),
cwd=fullpath)
+ # Check that the user specified ref exists in the track if provided & not already tracked
+ if track:
+ self.assert_ref_in_track(fullpath, track)
+
# List the submodules (path/url tuples) present at the given ref of this repo
def submodule_list(self):
modules = "{}:{}".format(self.ref, GIT_MODULES)
@@ -304,6 +316,28 @@ class GitMirror(SourceFetcher):
return None
+ # Assert that ref exists in track, if track has been specified.
+ def assert_ref_in_track(self, fullpath, track):
+ _, branch = self.source.check_output([self.source.host_git, 'branch', '--list', track,
+ '--contains', self.ref],
+ cwd=fullpath,)
+ if branch:
+ return True
+ else:
+ _, tag = self.source.check_output([self.source.host_git, 'tag', '--list', track,
+ '--contains', self.ref],
+ cwd=fullpath,)
+ if tag:
+ return True
+
+ detail = "The ref provided for the element does not exist locally in the provided track branch / tag " + \
+ "'{}'.\nYou may wish to track the element to update the ref from '{}' ".format(track, track) + \
+ "with `bst track`,\nor examine the upstream at '{}' for the specific ref.".format(self.url)
+
+ self.source.warn("{}: expected ref '{}' was not found in given track '{}' for staged repository: '{}'\n"
+ .format(self.source, self.ref, track, self.url),
+ detail=detail, warning_token=CoreWarnings.REF_NOT_IN_TRACK)
+
class GitSource(Source):
# pylint: disable=attribute-defined-outside-init
@@ -346,6 +380,7 @@ class GitSource(Source):
self.submodule_checkout_overrides[path] = checkout
self.mark_download_url(self.original_url)
+ self.tracked = False
def preflight(self):
# Check if git is installed, get the binary at the same time
@@ -405,6 +440,8 @@ class GitSource(Source):
# Update self.mirror.ref and node.ref from the self.tracking branch
ret = self.mirror.latest_commit(self.tracking)
+ # Set tracked attribute, parameter for if self.mirror.assert_ref_in_track is needed
+ self.tracked = True
return ret
def init_workspace(self, directory):
@@ -412,7 +449,7 @@ class GitSource(Source):
self.refresh_submodules()
with self.timed_activity('Setting up workspace "{}"'.format(directory), silent_nested=True):
- self.mirror.init_workspace(directory)
+ self.mirror.init_workspace(directory, track=(self.tracking if not self.tracked else None))
for mirror in self.submodules:
mirror.init_workspace(directory)
@@ -428,7 +465,7 @@ class GitSource(Source):
# Stage the main repo in the specified directory
#
with self.timed_activity("Staging {}".format(self.mirror.url), silent_nested=True):
- self.mirror.stage(directory)
+ self.mirror.stage(directory, track=(self.tracking if not self.tracked else None))
for mirror in self.submodules:
mirror.stage(directory)
diff --git a/tests/sources/git.py b/tests/sources/git.py
index 82778e6df..db433f813 100644
--- a/tests/sources/git.py
+++ b/tests/sources/git.py
@@ -26,6 +26,7 @@ import shutil
from buildstream._exceptions import ErrorDomain
from buildstream import _yaml
+from buildstream.plugin import CoreWarnings
from tests.testutils import cli, create_repo
from tests.testutils.site import HAVE_GIT
@@ -413,6 +414,73 @@ def test_submodule_track_no_ref_or_track(cli, tmpdir, datafiles):
@pytest.mark.skipif(HAVE_GIT is False, reason="git is not available")
@pytest.mark.datafiles(os.path.join(DATA_DIR, 'template'))
+def test_ref_not_in_track_warn(cli, tmpdir, datafiles):
+ project = os.path.join(datafiles.dirname, datafiles.basename)
+
+ # Create the repo from 'repofiles', create a branch without latest commit
+ repo = create_repo('git', str(tmpdir))
+ ref = repo.create(os.path.join(project, 'repofiles'))
+
+ gitsource = repo.source_config(ref=ref)
+
+ # Overwrite the track value to the added branch
+ gitsource['track'] = 'foo'
+
+ # Write out our test target
+ element = {
+ 'kind': 'import',
+ 'sources': [
+ gitsource
+ ]
+ }
+ _yaml.dump(element, os.path.join(project, 'target.bst'))
+
+ # Assert the warning is raised as ref is not in branch foo.
+ # Assert warning not error to the user, when not set as fatal.
+ result = cli.run(project=project, args=['build', 'target.bst'])
+ assert "The ref provided for the element does not exist locally" in result.stderr
+
+
+@pytest.mark.skipif(HAVE_GIT is False, reason="git is not available")
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'template'))
+def test_ref_not_in_track_warn_error(cli, tmpdir, datafiles):
+ project = os.path.join(datafiles.dirname, datafiles.basename)
+
+ # Add fatal-warnings ref-not-in-track to project.conf
+ project_template = {
+ "name": "foo",
+ "fatal-warnings": [CoreWarnings.REF_NOT_IN_TRACK]
+ }
+
+ _yaml.dump(project_template, os.path.join(project, 'project.conf'))
+
+ # Create the repo from 'repofiles', create a branch without latest commit
+ repo = create_repo('git', str(tmpdir))
+ ref = repo.create(os.path.join(project, 'repofiles'))
+
+ gitsource = repo.source_config(ref=ref)
+
+ # Overwrite the track value to the added branch
+ gitsource['track'] = 'foo'
+
+ # Write out our test target
+ element = {
+ 'kind': 'import',
+ 'sources': [
+ gitsource
+ ]
+ }
+ _yaml.dump(element, os.path.join(project, 'target.bst'))
+
+ # Assert that build raises a warning here that is captured
+ # as plugin error, due to the fatal warning being set
+ result = cli.run(project=project, args=['build', 'target.bst'])
+ result.assert_main_error(ErrorDomain.STREAM, None)
+ result.assert_task_error(ErrorDomain.PLUGIN, CoreWarnings.REF_NOT_IN_TRACK)
+
+
+@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