Merge ~cjwatson/git-build-recipe:nest-part into git-build-recipe:master

Proposed by Colin Watson
Status: Merged
Merged at revision: d3ce4262671b366b44ec1b59fbc8527378e60ade
Proposed branch: ~cjwatson/git-build-recipe:nest-part
Merge into: git-build-recipe:master
Diff against target: 183 lines (+36/-23)
3 files modified
debian/changelog (+6/-0)
gitbuildrecipe/recipe.py (+19/-5)
gitbuildrecipe/tests/test_recipe.py (+11/-18)
Reviewer Review Type Date Requested Status
Launchpad code reviewers Pending
Review via email: mp+283756@code.launchpad.net

Commit message

Implement nest-part (LP: #1537579).

Description of the change

Implement nest-part (LP: #1537579). Not too difficult once I finally figured out the right sequence of filter-branch and subtree operations needed.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 0c8e1bd..8a94f44 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,9 @@
6+git-build-recipe (0.3) UNRELEASED; urgency=medium
7+
8+ * Implement nest-part (LP: #1537579).
9+
10+ -- Colin Watson <cjwatson@ubuntu.com> Mon, 25 Jan 2016 02:51:00 +0000
11+
12 git-build-recipe (0.2.1) trusty; urgency=medium
13
14 * Configure "lp:" as shorthand for "https://git.launchpad.net/".
15diff --git a/gitbuildrecipe/recipe.py b/gitbuildrecipe/recipe.py
16index 1d0faa3..a961997 100644
17--- a/gitbuildrecipe/recipe.py
18+++ b/gitbuildrecipe/recipe.py
19@@ -385,14 +385,28 @@ def nest_part_branch(child_branch, target_path, subpath, target_subdir=None):
20 target_subdir = os.path.basename(subpath)
21 # XXX should handle updating as well
22 assert not os.path.exists(target_subdir)
23+ target_subdir_parent = os.path.dirname(target_subdir)
24+ if target_subdir_parent:
25+ target_subdir_parent_path = os.path.join(
26+ target_path, target_subdir_parent)
27+ if not os.path.exists(target_subdir_parent_path):
28+ os.makedirs(target_subdir_parent_path)
29 child_branch.path = target_path
30 ensure_remote(child_branch)
31 child_branch.resolve_commit()
32- subtree_commit = child_branch.git_output(
33- "subtree", "split", "-P", subpath, child_branch.commit)
34- child_branch.path = os.path.join(target_path, target_subdir)
35- git_clone(".", child_branch.path)
36- child_branch.git_call("checkout", subtree_commit)
37+ child_branch.git_call(
38+ "branch", "-q", "-f", "tmp-gbr-nest-part", child_branch.commit)
39+ if subpath != ".":
40+ child_branch.git_call(
41+ "filter-branch", "-f", "--original", "refs/git-build-recipe",
42+ "--subdirectory-filter", subpath, "tmp-gbr-nest-part")
43+ for original in child_branch.git_output(
44+ "for-each-ref", "--format=%(refname)",
45+ "refs/git-build-recipe").splitlines():
46+ child_branch.git_call("update-ref", "-d", original)
47+ child_branch.git_output(
48+ "subtree", "add", "-q", "-P", target_subdir, "tmp-gbr-nest-part")
49+ child_branch.git_call("branch", "-q", "-D", "tmp-gbr-nest-part")
50
51
52 def _build_inner_tree(base_branch, target_path):
53diff --git a/gitbuildrecipe/tests/test_recipe.py b/gitbuildrecipe/tests/test_recipe.py
54index 298eea7..337b741 100644
55--- a/gitbuildrecipe/tests/test_recipe.py
56+++ b/gitbuildrecipe/tests/test_recipe.py
57@@ -14,10 +14,10 @@
58
59 import os
60 import shutil
61-import unittest
62
63 from testtools.matchers import (
64 FileContains,
65+ Not,
66 PathExists,
67 )
68
69@@ -287,7 +287,6 @@ class RecipeParserTests(GitTestCase):
70 self.assertEqual(None, location)
71 self.check_recipe_branch(child_branch, "bar", "http://bar.org")
72
73- @unittest.skip("nest_part broken")
74 def test_builds_recipe_with_nest_part(self):
75 base_branch = self.get_recipe(self.basic_header_and_branch
76 + "nest-part bar http://bar.org some/path")
77@@ -300,7 +299,6 @@ class RecipeParserTests(GitTestCase):
78 self.assertEqual("some/path", instruction.subpath)
79 self.assertEqual(None, instruction.target_subdir)
80
81- @unittest.skip("nest_part broken")
82 def test_builds_recipe_with_nest_part_subdir(self):
83 base_branch = self.get_recipe(self.basic_header_and_branch
84 + "nest-part bar http://bar.org some/path target-subdir")
85@@ -313,7 +311,6 @@ class RecipeParserTests(GitTestCase):
86 self.assertEqual("some/path", instruction.subpath)
87 self.assertEqual("target-subdir", instruction.target_subdir)
88
89- @unittest.skip("nest_part broken")
90 def test_builds_recipe_with_nest_part_subdir_and_revspec(self):
91 base_branch = self.get_recipe(self.basic_header_and_branch
92 + "nest-part bar http://bar.org some/path target-subdir 1234")
93@@ -631,7 +628,6 @@ class BuildTreeTests(GitTestCase):
94 self.assertEqual(source1_commit, base_branch.commit)
95 self.assertEqual(source2_commit, merged_branch.commit)
96
97- @unittest.skip("nest_part broken")
98 def test_build_tree_implicit_dir(self):
99 # Branches nested into non-existent directories trigger creation of
100 # those directories.
101@@ -659,7 +655,6 @@ class BuildTreeTests(GitTestCase):
102 "target/moreimplicit/another/c/yetanotherfile",
103 FileContains("rugby"))
104
105- @unittest.skip("nest_part broken")
106 def test_build_tree_nest_part(self):
107 """A recipe can specify a merge of just part of an unrelated tree."""
108 source1 = self.make_source_branch("source1")
109@@ -667,7 +662,9 @@ class BuildTreeTests(GitTestCase):
110 source1_commit = source1.last_revision()
111 # Add 'b' to source2.
112 source2.build_tree_contents([
113- ("b", "new file"), ("not-b", "other file")])
114+ ("b/",), ("b/a", "new file"),
115+ ("not-b/",), ("not-b/a", "other file"),
116+ ])
117 source2.add(["b", "not-b"])
118 source2_commit = source2.commit("two")
119 base_branch = BaseRecipeBranch("source1", "1", 0.2)
120@@ -675,15 +672,13 @@ class BuildTreeTests(GitTestCase):
121 # Merge just 'b' from source2; 'a' is untouched.
122 base_branch.nest_part_branch(merged_branch, "b")
123 build_tree(base_branch, "target")
124- file_id = source1.path2id("a")
125 self.assertThat(
126- "target/a", FileContains(source1.get_file_text(file_id)))
127- self.assertThat("target/b", FileContains("new file"))
128- self.assertNotInWorkingTree("not-b", "target")
129+ "target/a", FileContains(source1._git_output("show", "HEAD:a")))
130+ self.assertThat("target/b/a", FileContains("new file"))
131+ self.assertThat("target/not-b", Not(PathExists()))
132 self.assertEqual(source1_commit, base_branch.commit)
133 self.assertEqual(source2_commit, merged_branch.commit)
134
135- @unittest.skip("nest_part broken")
136 def test_build_tree_nest_part_explicit_target(self):
137 """A recipe can specify a merge of just part of an unrelated tree into
138 a specific subdirectory of the target tree.
139@@ -696,7 +691,8 @@ class BuildTreeTests(GitTestCase):
140 source1_commit = source1.last_revision()
141 # Add 'b' to source2.
142 source2.build_tree_contents([
143- ("b", "new file"), ("not-b", "other file")])
144+ ("b/",), ("b/a", "new file"),
145+ ("not-b/",), ("not-b/a", "other file")])
146 source2.add(["b", "not-b"])
147 source2_commit = source2.commit("two")
148 base_branch = BaseRecipeBranch("source1", "1", 0.2)
149@@ -704,8 +700,8 @@ class BuildTreeTests(GitTestCase):
150 # Merge just 'b' from source2; 'a' is untouched.
151 base_branch.nest_part_branch(merged_branch, "b", "dir/b")
152 build_tree(base_branch, "target")
153- self.assertThat("target/dir/b", FileContains("new file"))
154- self.assertNotInWorkingTree("dir/not-b", "target")
155+ self.assertThat("target/dir/b/a", FileContains("new file"))
156+ self.assertThat("target/dir/not-b", Not(PathExists()))
157 self.assertEqual(source1_commit, base_branch.commit)
158 self.assertEqual(source2_commit, merged_branch.commit)
159
160@@ -1006,7 +1002,6 @@ class StringifyTests(GitTestCase):
161 base_branch.nest_branch(".", nested_branch1)
162 self.assertRaises(InstructionParseError, str, base_branch)
163
164- @unittest.skip("nest_part broken")
165 def test_with_nest_part(self):
166 base_branch = BaseRecipeBranch("base_url", "1", 0.1)
167 base_branch.commit = "base_revid"
168@@ -1019,7 +1014,6 @@ class StringifyTests(GitTestCase):
169 "nest-part nested1 nested1_url foo bar tag:foo\n",
170 manifest)
171
172- @unittest.skip("nest_part broken")
173 def test_with_nest_part_with_no_target_dir(self):
174 base_branch = BaseRecipeBranch("base_url", "1", 0.1)
175 base_branch.commit = "base_revid"
176@@ -1032,7 +1026,6 @@ class StringifyTests(GitTestCase):
177 "nest-part nested1 nested1_url foo foo tag:foo\n",
178 manifest)
179
180- @unittest.skip("nest_part broken")
181 def test_with_nest_part_with_no_target_dir_no_revspec(self):
182 base_branch = BaseRecipeBranch("base_url", "1", 0.1)
183 base_branch.commit = "base_revid"

Subscribers

People subscribed via source and target branches