launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #23674
[Merge] ~cjwatson/git-build-recipe:tolerate-missing-HEAD into git-build-recipe:master
Colin Watson has proposed merging ~cjwatson/git-build-recipe:tolerate-missing-HEAD into git-build-recipe:master.
Commit message:
Tolerate remote repositories with no HEAD
We want to fetch the remote HEAD if it exists, but if the recipe doesn't
rely on it then a failure to do so doesn't need to be fatal.
LP: #1683913
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1683913 in git-build-recipe: "git-build-recipe assumes that HEAD exists in the source repositories"
https://bugs.launchpad.net/git-build-recipe/+bug/1683913
For more details, see:
https://code.launchpad.net/~cjwatson/git-build-recipe/+git/git-build-recipe/+merge/368050
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/git-build-recipe:tolerate-missing-HEAD into git-build-recipe:master.
diff --git a/gitbuildrecipe/recipe.py b/gitbuildrecipe/recipe.py
index d1700f2..0ff215f 100644
--- a/gitbuildrecipe/recipe.py
+++ b/gitbuildrecipe/recipe.py
@@ -327,12 +327,22 @@ def fetch_branches(child_branch):
parsed_url = urlparse(url)
if not parsed_url.scheme and not parsed_url.path.startswith("/"):
url = os.path.abspath(url)
- # Fetch all remote branches, the remote HEAD, and (implicitly) any
- # tags that reference commits in those refs. Tags that aren't on a
- # branch won't be fetched.
+ # Fetch the remote HEAD. This may not exist, which is OK as long as the
+ # recipe uses explicit branch names.
+ try:
+ child_branch.git_call(
+ "fetch", url,
+ "HEAD:refs/remotes/%s/HEAD" % child_branch.remote_name,
+ silent=True)
+ except subprocess.CalledProcessError as e:
+ logging.info(e.output)
+ logging.info(
+ "Failed to fetch HEAD; recipe instructions for this repository "
+ "that do not specify a branch name will fail.")
+ # Fetch all remote branches and (implicitly) any tags that reference
+ # commits in those refs. Tags that aren't on a branch won't be fetched.
child_branch.git_call(
"fetch", url,
- "HEAD:refs/remotes/%s/HEAD" % child_branch.remote_name,
"refs/heads/*:refs/remotes/%s/*" % child_branch.remote_name)
@@ -650,10 +660,10 @@ class RecipeBranch:
output = subprocess.check_output(
cmd, stderr=subprocess.STDOUT, universal_newlines=True,
**kwargs)
- if silent:
+ if not silent:
sys.stdout.write(output)
except subprocess.CalledProcessError as e:
- if silent:
+ if not silent:
sys.stderr.write(e.output)
raise
diff --git a/gitbuildrecipe/tests/__init__.py b/gitbuildrecipe/tests/__init__.py
index 4962e50..6b41396 100644
--- a/gitbuildrecipe/tests/__init__.py
+++ b/gitbuildrecipe/tests/__init__.py
@@ -58,6 +58,9 @@ class GitRepository:
self._git_call("commit", "-q", "--allow-empty", "-m", message, env=env)
return self.last_revision()
+ def branch(self, branch_name, commit):
+ self._git_call("branch", branch_name, commit)
+
def tag(self, tag_name, commit, force=False):
args = ["tag"]
if force:
@@ -65,6 +68,9 @@ class GitRepository:
args.extend([tag_name, commit])
self._git_call(*args, stdout=subprocess.DEVNULL)
+ def set_head(self, ref_path):
+ self._git_call("symbolic-ref", "HEAD", ref_path)
+
def get_parents(self, commit):
return self._git_output(
"log", "-1", "--format=%P", commit).rstrip("\n").split()
diff --git a/gitbuildrecipe/tests/test_recipe.py b/gitbuildrecipe/tests/test_recipe.py
index ed7634d..7628a45 100644
--- a/gitbuildrecipe/tests/test_recipe.py
+++ b/gitbuildrecipe/tests/test_recipe.py
@@ -891,6 +891,20 @@ class BuildTreeTests(GitTestCase):
self.assertRaises(
TargetAlreadyExists, pull_or_clone, base_branch, "target")
+ def test_pull_or_clone_with_no_HEAD(self):
+ source = GitRepository("source")
+ source.build_tree(["a"])
+ source.add(["a"])
+ commit = source.commit("one")
+ source.branch("source/master", commit)
+ source.set_head("refs/heads/nonexistent")
+ base_branch = BaseRecipeBranch(
+ "source", "1", 0.2, revspec="source/master")
+ pull_or_clone(base_branch, "target")
+ target = GitRepository("target", allow_create=False)
+ self.assertEqual(commit, target.last_revision())
+ self.assertEqual(commit, target.rev_parse("source/master"))
+
def test_build_tree_runs_commands(self):
source = GitRepository("source")
commit = source.commit("one")
Follow ups