Merge ~rhansen/git-build-recipe:pristine-tar-refs into git-build-recipe:master

Proposed by Richard Hansen
Status: Needs review
Proposed branch: ~rhansen/git-build-recipe:pristine-tar-refs
Merge into: git-build-recipe:master
Diff against target: 91 lines (+67/-2)
2 files modified
gitbuildrecipe/recipe.py (+25/-2)
gitbuildrecipe/tests/test_functional.py (+42/-0)
Reviewer Review Type Date Requested Status
Clinton Fung Pending
William Grant Pending
Canonical Launchpad Engineering Pending
Loïc Minier Pending
Review via email: mp+446358@code.launchpad.net

Description of the change

Fetch all references so that the pristine-tar trees are guaranteed to be fetched.

This is an alternative to:
https://code.launchpad.net/~lool/git-build-recipe/+git/git-build-recipe/+merge/443942

Changes from that merge request:
  - Tags are put in refs/tags/<remote>/* instead of refs/remotes/<remote>/* (to avoid potential name collisions).
  - I added some comments explaining why fetching is done the way it is.
  - I added tests.

To post a comment you must log in.

Unmerged commits

39f83d9... by Richard Hansen

fetch everything for pristine-tar

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/gitbuildrecipe/recipe.py b/gitbuildrecipe/recipe.py
index f932ca7..f8ffd45 100644
--- a/gitbuildrecipe/recipe.py
+++ b/gitbuildrecipe/recipe.py
@@ -339,11 +339,34 @@ def fetch_branches(child_branch):
339 logging.info(339 logging.info(
340 "Failed to fetch HEAD; recipe instructions for this repository "340 "Failed to fetch HEAD; recipe instructions for this repository "
341 "that do not specify a branch name will fail.")341 "that do not specify a branch name will fail.")
342 # Fetch all remote branches and (implicitly) any tags that reference342 # Fetch all remote branches and (implicitly) any tags in the commit history
343 # commits in those refs. Tags that aren't on a branch won't be fetched.343 # of the remote branches. Tags that aren't on a branch will be fetched in a
344 # separate fetch call below. Note that if two remotes have an identically
345 # named tag, the tag from the first fetched remote wins; the second fetch
346 # will silently skip the tag (fetch will not return an error).
347 # Note: extract_upstream_tarball looks for the tags upstream/<version> and
348 # upstream-<version> if the <remote>/pristine-tar branch doesn't exist.
344 child_branch.git_call(349 child_branch.git_call(
345 "fetch", url,350 "fetch", url,
346 "refs/heads/*:refs/remotes/%s/*" % child_branch.remote_name)351 "refs/heads/*:refs/remotes/%s/*" % child_branch.remote_name)
352 # All refs must be fetched for pristine-tar to work because pristine-tar
353 # stores Git tree object IDs in blobs, not as tree objects referenced from
354 # the pristine-tar commits. Git has no way to know that the blobs reference
355 # the tree objects, so it won't include the trees in the fetched packfile
356 # unless another fetched ref brings them along. The trees are likely to be
357 # in the upstream branch (already fetched above), but they could
358 # theoretically be anywhere.
359 #
360 # The tags are prefixed with the remote name to avoid collision with other
361 # remotes. The refspec could instead be the usual
362 # "refs/tags/*:refs/tags/*", but then fetch would fail if two remotes have
363 # an identically named tag pointing at different commits. The refspec could
364 # be prefixed with "+" (or pass "--force"), but that would change the
365 # semantics from first-fetched-wins to last-fetched-wins, which might break
366 # existing recipes.
367 child_branch.git_call(
368 "fetch", url,
369 "refs/tags/*:refs/tags/%s/*" % child_branch.remote_name)
347370
348371
349@lru_cache(maxsize=1)372@lru_cache(maxsize=1)
diff --git a/gitbuildrecipe/tests/test_functional.py b/gitbuildrecipe/tests/test_functional.py
index 56fd216..33ed43d 100644
--- a/gitbuildrecipe/tests/test_functional.py
+++ b/gitbuildrecipe/tests/test_functional.py
@@ -579,3 +579,45 @@ class FunctionalBuilderTests(GitTestCase):
579 out, err = self.run_recipe(579 out, err = self.run_recipe(
580 "--allow-fallback-to-native test.recipe working", retcode=1)580 "--allow-fallback-to-native test.recipe working", retcode=1)
581 self.assertIn("Unknown source format 2.0\n", err)581 self.assertIn("Unknown source format 2.0\n", err)
582
583 def test_all_refs_fetched(self):
584 source = self.make_simple_package("source")
585 main_branch = source._git_output(
586 "branch", "--show-current").rstrip("\n")
587 source._git_call("switch", "--orphan", "branch-for-unconnected-tag")
588 source.build_tree(["a"])
589 source.add(["a"])
590 commit = source.commit("unconnected tag")
591 source.tag("unconnected-tag", commit)
592 source._git_call("switch", main_branch)
593 source._git_call("branch", "-D", "branch-for-unconnected-tag")
594 with open("package-0.1.recipe", "w") as recipe:
595 recipe.write(
596 "# git-build-recipe format 0.4 deb-version 0.1-1\n"
597 "source\n")
598 self.run_recipe("--allow-fallback-to-native package-0.1.recipe working")
599 working = GitRepository("working/package-0.1", allow_create=False)
600 working.rev_parse(commit)
601 working.rev_parse("refs/tags/unconnected-tag")
602
603 def test_tag_conflict_first_fetched_wins(self):
604 # If a tag exists in two remote repositories pointing to different
605 # revisions, the first fetched repository "wins" (its tag appears in the
606 # clone), and the losing tag is silently ignored. This is probably not
607 # the ideal behavior, but changing it would require bumping the format
608 # version number or else it might break existing recipes.
609 source = GitRepository("source")
610 source.build_tree(["a"])
611 source.add(["a"])
612 commit = source.commit("pristine")
613 source.tag("upstream/0.1", commit)
614 debianized = self.make_simple_package("debianized")
615 debianized.tag("upstream/0.1", "HEAD")
616 with open("package-0.1.recipe", "w") as recipe:
617 recipe.write(
618 "# git-build-recipe format 0.4 deb-version 0.1-1\n"
619 "source\n"
620 "nest-part debianized debianized debian\n")
621 self.run_recipe("package-0.1.recipe working")
622 working = GitRepository("working/package-0.1", allow_create=False)
623 self.assertEqual(working.rev_parse("refs/tags/upstream/0.1"), commit)

Subscribers

People subscribed via source and target branches