Merge ~cjwatson/git-build-recipe:nest-part into git-build-recipe:master
- Git
- lp:~cjwatson/git-build-recipe
- nest-part
- Merge into 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) |
Related bugs: |
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
1 | diff --git a/debian/changelog b/debian/changelog | |||
2 | index 0c8e1bd..8a94f44 100644 | |||
3 | --- a/debian/changelog | |||
4 | +++ b/debian/changelog | |||
5 | @@ -1,3 +1,9 @@ | |||
6 | 1 | git-build-recipe (0.3) UNRELEASED; urgency=medium | ||
7 | 2 | |||
8 | 3 | * Implement nest-part (LP: #1537579). | ||
9 | 4 | |||
10 | 5 | -- Colin Watson <cjwatson@ubuntu.com> Mon, 25 Jan 2016 02:51:00 +0000 | ||
11 | 6 | |||
12 | 1 | git-build-recipe (0.2.1) trusty; urgency=medium | 7 | git-build-recipe (0.2.1) trusty; urgency=medium |
13 | 2 | 8 | ||
14 | 3 | * Configure "lp:" as shorthand for "https://git.launchpad.net/". | 9 | * Configure "lp:" as shorthand for "https://git.launchpad.net/". |
15 | diff --git a/gitbuildrecipe/recipe.py b/gitbuildrecipe/recipe.py | |||
16 | index 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 | 385 | target_subdir = os.path.basename(subpath) | 385 | target_subdir = os.path.basename(subpath) |
21 | 386 | # XXX should handle updating as well | 386 | # XXX should handle updating as well |
22 | 387 | assert not os.path.exists(target_subdir) | 387 | assert not os.path.exists(target_subdir) |
23 | 388 | target_subdir_parent = os.path.dirname(target_subdir) | ||
24 | 389 | if target_subdir_parent: | ||
25 | 390 | target_subdir_parent_path = os.path.join( | ||
26 | 391 | target_path, target_subdir_parent) | ||
27 | 392 | if not os.path.exists(target_subdir_parent_path): | ||
28 | 393 | os.makedirs(target_subdir_parent_path) | ||
29 | 388 | child_branch.path = target_path | 394 | child_branch.path = target_path |
30 | 389 | ensure_remote(child_branch) | 395 | ensure_remote(child_branch) |
31 | 390 | child_branch.resolve_commit() | 396 | child_branch.resolve_commit() |
37 | 391 | subtree_commit = child_branch.git_output( | 397 | child_branch.git_call( |
38 | 392 | "subtree", "split", "-P", subpath, child_branch.commit) | 398 | "branch", "-q", "-f", "tmp-gbr-nest-part", child_branch.commit) |
39 | 393 | child_branch.path = os.path.join(target_path, target_subdir) | 399 | if subpath != ".": |
40 | 394 | git_clone(".", child_branch.path) | 400 | child_branch.git_call( |
41 | 395 | child_branch.git_call("checkout", subtree_commit) | 401 | "filter-branch", "-f", "--original", "refs/git-build-recipe", |
42 | 402 | "--subdirectory-filter", subpath, "tmp-gbr-nest-part") | ||
43 | 403 | for original in child_branch.git_output( | ||
44 | 404 | "for-each-ref", "--format=%(refname)", | ||
45 | 405 | "refs/git-build-recipe").splitlines(): | ||
46 | 406 | child_branch.git_call("update-ref", "-d", original) | ||
47 | 407 | child_branch.git_output( | ||
48 | 408 | "subtree", "add", "-q", "-P", target_subdir, "tmp-gbr-nest-part") | ||
49 | 409 | child_branch.git_call("branch", "-q", "-D", "tmp-gbr-nest-part") | ||
50 | 396 | 410 | ||
51 | 397 | 411 | ||
52 | 398 | def _build_inner_tree(base_branch, target_path): | 412 | def _build_inner_tree(base_branch, target_path): |
53 | diff --git a/gitbuildrecipe/tests/test_recipe.py b/gitbuildrecipe/tests/test_recipe.py | |||
54 | index 298eea7..337b741 100644 | |||
55 | --- a/gitbuildrecipe/tests/test_recipe.py | |||
56 | +++ b/gitbuildrecipe/tests/test_recipe.py | |||
57 | @@ -14,10 +14,10 @@ | |||
58 | 14 | 14 | ||
59 | 15 | import os | 15 | import os |
60 | 16 | import shutil | 16 | import shutil |
61 | 17 | import unittest | ||
62 | 18 | 17 | ||
63 | 19 | from testtools.matchers import ( | 18 | from testtools.matchers import ( |
64 | 20 | FileContains, | 19 | FileContains, |
65 | 20 | Not, | ||
66 | 21 | PathExists, | 21 | PathExists, |
67 | 22 | ) | 22 | ) |
68 | 23 | 23 | ||
69 | @@ -287,7 +287,6 @@ class RecipeParserTests(GitTestCase): | |||
70 | 287 | self.assertEqual(None, location) | 287 | self.assertEqual(None, location) |
71 | 288 | self.check_recipe_branch(child_branch, "bar", "http://bar.org") | 288 | self.check_recipe_branch(child_branch, "bar", "http://bar.org") |
72 | 289 | 289 | ||
73 | 290 | @unittest.skip("nest_part broken") | ||
74 | 291 | def test_builds_recipe_with_nest_part(self): | 290 | def test_builds_recipe_with_nest_part(self): |
75 | 292 | base_branch = self.get_recipe(self.basic_header_and_branch | 291 | base_branch = self.get_recipe(self.basic_header_and_branch |
76 | 293 | + "nest-part bar http://bar.org some/path") | 292 | + "nest-part bar http://bar.org some/path") |
77 | @@ -300,7 +299,6 @@ class RecipeParserTests(GitTestCase): | |||
78 | 300 | self.assertEqual("some/path", instruction.subpath) | 299 | self.assertEqual("some/path", instruction.subpath) |
79 | 301 | self.assertEqual(None, instruction.target_subdir) | 300 | self.assertEqual(None, instruction.target_subdir) |
80 | 302 | 301 | ||
81 | 303 | @unittest.skip("nest_part broken") | ||
82 | 304 | def test_builds_recipe_with_nest_part_subdir(self): | 302 | def test_builds_recipe_with_nest_part_subdir(self): |
83 | 305 | base_branch = self.get_recipe(self.basic_header_and_branch | 303 | base_branch = self.get_recipe(self.basic_header_and_branch |
84 | 306 | + "nest-part bar http://bar.org some/path target-subdir") | 304 | + "nest-part bar http://bar.org some/path target-subdir") |
85 | @@ -313,7 +311,6 @@ class RecipeParserTests(GitTestCase): | |||
86 | 313 | self.assertEqual("some/path", instruction.subpath) | 311 | self.assertEqual("some/path", instruction.subpath) |
87 | 314 | self.assertEqual("target-subdir", instruction.target_subdir) | 312 | self.assertEqual("target-subdir", instruction.target_subdir) |
88 | 315 | 313 | ||
89 | 316 | @unittest.skip("nest_part broken") | ||
90 | 317 | def test_builds_recipe_with_nest_part_subdir_and_revspec(self): | 314 | def test_builds_recipe_with_nest_part_subdir_and_revspec(self): |
91 | 318 | base_branch = self.get_recipe(self.basic_header_and_branch | 315 | base_branch = self.get_recipe(self.basic_header_and_branch |
92 | 319 | + "nest-part bar http://bar.org some/path target-subdir 1234") | 316 | + "nest-part bar http://bar.org some/path target-subdir 1234") |
93 | @@ -631,7 +628,6 @@ class BuildTreeTests(GitTestCase): | |||
94 | 631 | self.assertEqual(source1_commit, base_branch.commit) | 628 | self.assertEqual(source1_commit, base_branch.commit) |
95 | 632 | self.assertEqual(source2_commit, merged_branch.commit) | 629 | self.assertEqual(source2_commit, merged_branch.commit) |
96 | 633 | 630 | ||
97 | 634 | @unittest.skip("nest_part broken") | ||
98 | 635 | def test_build_tree_implicit_dir(self): | 631 | def test_build_tree_implicit_dir(self): |
99 | 636 | # Branches nested into non-existent directories trigger creation of | 632 | # Branches nested into non-existent directories trigger creation of |
100 | 637 | # those directories. | 633 | # those directories. |
101 | @@ -659,7 +655,6 @@ class BuildTreeTests(GitTestCase): | |||
102 | 659 | "target/moreimplicit/another/c/yetanotherfile", | 655 | "target/moreimplicit/another/c/yetanotherfile", |
103 | 660 | FileContains("rugby")) | 656 | FileContains("rugby")) |
104 | 661 | 657 | ||
105 | 662 | @unittest.skip("nest_part broken") | ||
106 | 663 | def test_build_tree_nest_part(self): | 658 | def test_build_tree_nest_part(self): |
107 | 664 | """A recipe can specify a merge of just part of an unrelated tree.""" | 659 | """A recipe can specify a merge of just part of an unrelated tree.""" |
108 | 665 | source1 = self.make_source_branch("source1") | 660 | source1 = self.make_source_branch("source1") |
109 | @@ -667,7 +662,9 @@ class BuildTreeTests(GitTestCase): | |||
110 | 667 | source1_commit = source1.last_revision() | 662 | source1_commit = source1.last_revision() |
111 | 668 | # Add 'b' to source2. | 663 | # Add 'b' to source2. |
112 | 669 | source2.build_tree_contents([ | 664 | source2.build_tree_contents([ |
114 | 670 | ("b", "new file"), ("not-b", "other file")]) | 665 | ("b/",), ("b/a", "new file"), |
115 | 666 | ("not-b/",), ("not-b/a", "other file"), | ||
116 | 667 | ]) | ||
117 | 671 | source2.add(["b", "not-b"]) | 668 | source2.add(["b", "not-b"]) |
118 | 672 | source2_commit = source2.commit("two") | 669 | source2_commit = source2.commit("two") |
119 | 673 | base_branch = BaseRecipeBranch("source1", "1", 0.2) | 670 | base_branch = BaseRecipeBranch("source1", "1", 0.2) |
120 | @@ -675,15 +672,13 @@ class BuildTreeTests(GitTestCase): | |||
121 | 675 | # Merge just 'b' from source2; 'a' is untouched. | 672 | # Merge just 'b' from source2; 'a' is untouched. |
122 | 676 | base_branch.nest_part_branch(merged_branch, "b") | 673 | base_branch.nest_part_branch(merged_branch, "b") |
123 | 677 | build_tree(base_branch, "target") | 674 | build_tree(base_branch, "target") |
124 | 678 | file_id = source1.path2id("a") | ||
125 | 679 | self.assertThat( | 675 | self.assertThat( |
129 | 680 | "target/a", FileContains(source1.get_file_text(file_id))) | 676 | "target/a", FileContains(source1._git_output("show", "HEAD:a"))) |
130 | 681 | self.assertThat("target/b", FileContains("new file")) | 677 | self.assertThat("target/b/a", FileContains("new file")) |
131 | 682 | self.assertNotInWorkingTree("not-b", "target") | 678 | self.assertThat("target/not-b", Not(PathExists())) |
132 | 683 | self.assertEqual(source1_commit, base_branch.commit) | 679 | self.assertEqual(source1_commit, base_branch.commit) |
133 | 684 | self.assertEqual(source2_commit, merged_branch.commit) | 680 | self.assertEqual(source2_commit, merged_branch.commit) |
134 | 685 | 681 | ||
135 | 686 | @unittest.skip("nest_part broken") | ||
136 | 687 | def test_build_tree_nest_part_explicit_target(self): | 682 | def test_build_tree_nest_part_explicit_target(self): |
137 | 688 | """A recipe can specify a merge of just part of an unrelated tree into | 683 | """A recipe can specify a merge of just part of an unrelated tree into |
138 | 689 | a specific subdirectory of the target tree. | 684 | a specific subdirectory of the target tree. |
139 | @@ -696,7 +691,8 @@ class BuildTreeTests(GitTestCase): | |||
140 | 696 | source1_commit = source1.last_revision() | 691 | source1_commit = source1.last_revision() |
141 | 697 | # Add 'b' to source2. | 692 | # Add 'b' to source2. |
142 | 698 | source2.build_tree_contents([ | 693 | source2.build_tree_contents([ |
144 | 699 | ("b", "new file"), ("not-b", "other file")]) | 694 | ("b/",), ("b/a", "new file"), |
145 | 695 | ("not-b/",), ("not-b/a", "other file")]) | ||
146 | 700 | source2.add(["b", "not-b"]) | 696 | source2.add(["b", "not-b"]) |
147 | 701 | source2_commit = source2.commit("two") | 697 | source2_commit = source2.commit("two") |
148 | 702 | base_branch = BaseRecipeBranch("source1", "1", 0.2) | 698 | base_branch = BaseRecipeBranch("source1", "1", 0.2) |
149 | @@ -704,8 +700,8 @@ class BuildTreeTests(GitTestCase): | |||
150 | 704 | # Merge just 'b' from source2; 'a' is untouched. | 700 | # Merge just 'b' from source2; 'a' is untouched. |
151 | 705 | base_branch.nest_part_branch(merged_branch, "b", "dir/b") | 701 | base_branch.nest_part_branch(merged_branch, "b", "dir/b") |
152 | 706 | build_tree(base_branch, "target") | 702 | build_tree(base_branch, "target") |
155 | 707 | self.assertThat("target/dir/b", FileContains("new file")) | 703 | self.assertThat("target/dir/b/a", FileContains("new file")) |
156 | 708 | self.assertNotInWorkingTree("dir/not-b", "target") | 704 | self.assertThat("target/dir/not-b", Not(PathExists())) |
157 | 709 | self.assertEqual(source1_commit, base_branch.commit) | 705 | self.assertEqual(source1_commit, base_branch.commit) |
158 | 710 | self.assertEqual(source2_commit, merged_branch.commit) | 706 | self.assertEqual(source2_commit, merged_branch.commit) |
159 | 711 | 707 | ||
160 | @@ -1006,7 +1002,6 @@ class StringifyTests(GitTestCase): | |||
161 | 1006 | base_branch.nest_branch(".", nested_branch1) | 1002 | base_branch.nest_branch(".", nested_branch1) |
162 | 1007 | self.assertRaises(InstructionParseError, str, base_branch) | 1003 | self.assertRaises(InstructionParseError, str, base_branch) |
163 | 1008 | 1004 | ||
164 | 1009 | @unittest.skip("nest_part broken") | ||
165 | 1010 | def test_with_nest_part(self): | 1005 | def test_with_nest_part(self): |
166 | 1011 | base_branch = BaseRecipeBranch("base_url", "1", 0.1) | 1006 | base_branch = BaseRecipeBranch("base_url", "1", 0.1) |
167 | 1012 | base_branch.commit = "base_revid" | 1007 | base_branch.commit = "base_revid" |
168 | @@ -1019,7 +1014,6 @@ class StringifyTests(GitTestCase): | |||
169 | 1019 | "nest-part nested1 nested1_url foo bar tag:foo\n", | 1014 | "nest-part nested1 nested1_url foo bar tag:foo\n", |
170 | 1020 | manifest) | 1015 | manifest) |
171 | 1021 | 1016 | ||
172 | 1022 | @unittest.skip("nest_part broken") | ||
173 | 1023 | def test_with_nest_part_with_no_target_dir(self): | 1017 | def test_with_nest_part_with_no_target_dir(self): |
174 | 1024 | base_branch = BaseRecipeBranch("base_url", "1", 0.1) | 1018 | base_branch = BaseRecipeBranch("base_url", "1", 0.1) |
175 | 1025 | base_branch.commit = "base_revid" | 1019 | base_branch.commit = "base_revid" |
176 | @@ -1032,7 +1026,6 @@ class StringifyTests(GitTestCase): | |||
177 | 1032 | "nest-part nested1 nested1_url foo foo tag:foo\n", | 1026 | "nest-part nested1 nested1_url foo foo tag:foo\n", |
178 | 1033 | manifest) | 1027 | manifest) |
179 | 1034 | 1028 | ||
180 | 1035 | @unittest.skip("nest_part broken") | ||
181 | 1036 | def test_with_nest_part_with_no_target_dir_no_revspec(self): | 1029 | def test_with_nest_part_with_no_target_dir_no_revspec(self): |
182 | 1037 | base_branch = BaseRecipeBranch("base_url", "1", 0.1) | 1030 | base_branch = BaseRecipeBranch("base_url", "1", 0.1) |
183 | 1038 | base_branch.commit = "base_revid" | 1031 | base_branch.commit = "base_revid" |