Merge lp:~jelmer/bzr-builddeb/quilt into lp:bzr-builddeb
- quilt
- Merge into trunk
Proposed by
Jelmer Vernooij
Status: | Merged |
---|---|
Merged at revision: | 680 |
Proposed branch: | lp:~jelmer/bzr-builddeb/quilt |
Merge into: | lp:bzr-builddeb |
Diff against target: |
305 lines (+265/-0) 4 files modified
merge_quilt.py (+24/-0) quilt.py (+151/-0) tests/__init__.py (+3/-0) tests/test_quilt.py (+87/-0) |
To merge this branch: | bzr merge lp:~jelmer/bzr-builddeb/quilt |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Westby | Approve | ||
Review via email: mp+87284@code.launchpad.net |
Commit message
Description of the change
Add utility methods for using quilt.
To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote : | # |
> I think there's no tests for tree_unapply_
I've added two while landing this.
Thanks, as always, for the quick reviews!
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'merge_quilt.py' | |||
2 | --- merge_quilt.py 2011-12-20 14:44:17 +0000 | |||
3 | +++ merge_quilt.py 2012-01-02 19:24:23 +0000 | |||
4 | @@ -21,3 +21,27 @@ | |||
5 | 21 | """Quilt patch handling.""" | 21 | """Quilt patch handling.""" |
6 | 22 | 22 | ||
7 | 23 | from __future__ import absolute_import | 23 | from __future__ import absolute_import |
8 | 24 | import tempfile | ||
9 | 25 | |||
10 | 26 | from bzrlib import trace | ||
11 | 27 | from bzrlib.plugins.builddeb.quilt import quilt_pop_all | ||
12 | 28 | |||
13 | 29 | |||
14 | 30 | def tree_unapply_patches(orig_tree): | ||
15 | 31 | """Return a tree with patches unapplied. | ||
16 | 32 | |||
17 | 33 | :param tree: Tree from which to unapply quilt patches | ||
18 | 34 | :return: Tuple with tree and temp path. | ||
19 | 35 | The tree is a tree with unapplied patches; either a checkout of | ||
20 | 36 | tree or tree itself if there were no patches | ||
21 | 37 | """ | ||
22 | 38 | series_file_id = orig_tree.path2id("debian/patches/series") | ||
23 | 39 | if series_file_id is None: | ||
24 | 40 | # No quilt patches | ||
25 | 41 | return orig_tree, None | ||
26 | 42 | |||
27 | 43 | target_dir = tempfile.mkdtemp() | ||
28 | 44 | tree = orig_tree.branch.create_checkout(target_dir, lightweight=True) | ||
29 | 45 | trace.warning("Applying quilt patches for %r in %s", orig_tree, target_dir) | ||
30 | 46 | quilt_pop_all(working_dir=tree.basedir) | ||
31 | 47 | return tree, target_dir | ||
32 | 24 | 48 | ||
33 | === added file 'quilt.py' | |||
34 | --- quilt.py 1970-01-01 00:00:00 +0000 | |||
35 | +++ quilt.py 2012-01-02 19:24:23 +0000 | |||
36 | @@ -0,0 +1,151 @@ | |||
37 | 1 | # quilt.py -- Quilt patch handling | ||
38 | 2 | # Copyright (C) 2011 Canonical Ltd. | ||
39 | 3 | # | ||
40 | 4 | # This file is part of bzr-builddeb. | ||
41 | 5 | # | ||
42 | 6 | # bzr-builddeb is free software; you can redistribute it and/or modify | ||
43 | 7 | # it under the terms of the GNU General Public License as published by | ||
44 | 8 | # the Free Software Foundation; either version 2 of the License, or | ||
45 | 9 | # (at your option) any later version. | ||
46 | 10 | # | ||
47 | 11 | # bzr-builddeb is distributed in the hope that it will be useful, | ||
48 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
49 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
50 | 14 | # GNU General Public License for more details. | ||
51 | 15 | # | ||
52 | 16 | # You should have received a copy of the GNU General Public License | ||
53 | 17 | # along with bzr-builddeb; if not, write to the Free Software | ||
54 | 18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
55 | 19 | # | ||
56 | 20 | |||
57 | 21 | """Quilt patch handling.""" | ||
58 | 22 | |||
59 | 23 | from __future__ import absolute_import | ||
60 | 24 | |||
61 | 25 | import errno | ||
62 | 26 | import os | ||
63 | 27 | import signal | ||
64 | 28 | import subprocess | ||
65 | 29 | from bzrlib import ( | ||
66 | 30 | errors, | ||
67 | 31 | trace, | ||
68 | 32 | ) | ||
69 | 33 | |||
70 | 34 | |||
71 | 35 | class QuiltError(errors.BzrError): | ||
72 | 36 | |||
73 | 37 | _fmt = "An error (%(retcode)d) occurred running quilt: %(msg)s" | ||
74 | 38 | |||
75 | 39 | def __init__(self, retcode, msg): | ||
76 | 40 | self.retcode = retcode | ||
77 | 41 | self.msg = msg | ||
78 | 42 | |||
79 | 43 | |||
80 | 44 | def run_quilt(args, working_dir, series_file=None, patches_dir=None, quiet=None): | ||
81 | 45 | """Run quilt. | ||
82 | 46 | |||
83 | 47 | :param args: Arguments to quilt | ||
84 | 48 | :param working_dir: Working dir | ||
85 | 49 | :param series_file: Optional path to the series file | ||
86 | 50 | :param patches_dir: Optional path to the patches | ||
87 | 51 | :param quilt: Whether to be quiet (quilt stderr not to terminal) | ||
88 | 52 | :raise QuiltError: When running quilt fails | ||
89 | 53 | """ | ||
90 | 54 | def subprocess_setup(): | ||
91 | 55 | signal.signal(signal.SIGPIPE, signal.SIG_DFL) | ||
92 | 56 | env = {} | ||
93 | 57 | if patches_dir is not None: | ||
94 | 58 | env["QUILT_PATCHES"] = patches_dir | ||
95 | 59 | else: | ||
96 | 60 | env["QUILT_PATCHES"] = os.path.join(working_dir, "debian", "patches") | ||
97 | 61 | if series_file is not None: | ||
98 | 62 | env["QUILT_SERIES"] = series_file | ||
99 | 63 | else: | ||
100 | 64 | env["QUILT_SERIES"] = os.path.join(env["QUILT_PATCHES"], "series") | ||
101 | 65 | # Hide output if -q is in use. | ||
102 | 66 | if quiet is None: | ||
103 | 67 | quiet = trace.is_quiet() | ||
104 | 68 | if quiet: | ||
105 | 69 | stderr = subprocess.STDOUT | ||
106 | 70 | else: | ||
107 | 71 | stderr = subprocess.PIPE | ||
108 | 72 | command = ["quilt"] + args | ||
109 | 73 | trace.mutter("running: %r", command) | ||
110 | 74 | if not os.path.isdir(working_dir): | ||
111 | 75 | raise AssertionError("%s is not a valid directory" % working_dir) | ||
112 | 76 | try: | ||
113 | 77 | proc = subprocess.Popen(command, cwd=working_dir, env=env, | ||
114 | 78 | stdin=subprocess.PIPE, preexec_fn=subprocess_setup, | ||
115 | 79 | stdout=subprocess.PIPE, stderr=stderr) | ||
116 | 80 | except OSError, e: | ||
117 | 81 | if e.errno != errno.ENOENT: | ||
118 | 82 | raise | ||
119 | 83 | raise errors.BzrError("quilt is not installed, please install it") | ||
120 | 84 | output = proc.communicate() | ||
121 | 85 | if proc.returncode not in (0, 2): | ||
122 | 86 | raise QuiltError(proc.returncode, output[1]) | ||
123 | 87 | if output[0] is None: | ||
124 | 88 | return "" | ||
125 | 89 | return output[0] | ||
126 | 90 | |||
127 | 91 | |||
128 | 92 | def quilt_pop_all(working_dir, patches_dir=None, series_file=None, quiet=None): | ||
129 | 93 | """Pop all patches. | ||
130 | 94 | |||
131 | 95 | :param working_dir: Directory to work in | ||
132 | 96 | :param patches_dir: Optional patches directory | ||
133 | 97 | :param series_file: Optional series file | ||
134 | 98 | """ | ||
135 | 99 | return run_quilt(["pop", "-a", "-v"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file, quiet=quiet) | ||
136 | 100 | |||
137 | 101 | |||
138 | 102 | def quilt_push_all(working_dir, patches_dir=None, series_file=None, quiet=None): | ||
139 | 103 | """Push all patches. | ||
140 | 104 | |||
141 | 105 | :param working_dir: Directory to work in | ||
142 | 106 | :param patches_dir: Optional patches directory | ||
143 | 107 | :param series_file: Optional series file | ||
144 | 108 | """ | ||
145 | 109 | return run_quilt(["push", "-a", "-v"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file, quiet=quiet) | ||
146 | 110 | |||
147 | 111 | |||
148 | 112 | def quilt_applied(working_dir, patches_dir=None, series_file=None): | ||
149 | 113 | """Find the list of applied quilt patches. | ||
150 | 114 | |||
151 | 115 | :param working_dir: Directory to work in | ||
152 | 116 | :param patches_dir: Optional patches directory | ||
153 | 117 | :param series_file: Optional series file | ||
154 | 118 | """ | ||
155 | 119 | try: | ||
156 | 120 | return run_quilt(["applied"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file).splitlines() | ||
157 | 121 | except QuiltError, e: | ||
158 | 122 | if e.retcode == 1: | ||
159 | 123 | return [] | ||
160 | 124 | raise | ||
161 | 125 | |||
162 | 126 | |||
163 | 127 | def quilt_unapplied(working_dir, patches_dir=None, series_file=None): | ||
164 | 128 | """Find the list of unapplied quilt patches. | ||
165 | 129 | |||
166 | 130 | :param working_dir: Directory to work in | ||
167 | 131 | :param patches_dir: Optional patches directory | ||
168 | 132 | :param series_file: Optional series file | ||
169 | 133 | """ | ||
170 | 134 | try: | ||
171 | 135 | return run_quilt(["unapplied"], working_dir=working_dir, | ||
172 | 136 | patches_dir=patches_dir, series_file=series_file).splitlines() | ||
173 | 137 | except QuiltError, e: | ||
174 | 138 | if e.retcode == 1: | ||
175 | 139 | return [] | ||
176 | 140 | raise | ||
177 | 141 | |||
178 | 142 | |||
179 | 143 | def quilt_series(working_dir, patches_dir=None, series_file=None): | ||
180 | 144 | """Find the list of patches. | ||
181 | 145 | |||
182 | 146 | :param working_dir: Directory to work in | ||
183 | 147 | :param patches_dir: Optional patches directory | ||
184 | 148 | :param series_file: Optional series file | ||
185 | 149 | """ | ||
186 | 150 | return run_quilt(["series"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file).splitlines() | ||
187 | 151 | |||
188 | 0 | 152 | ||
189 | === modified file 'tests/__init__.py' | |||
190 | --- tests/__init__.py 2011-12-20 14:44:17 +0000 | |||
191 | +++ tests/__init__.py 2012-01-02 19:24:23 +0000 | |||
192 | @@ -37,11 +37,13 @@ | |||
193 | 37 | from bzrlib.tests import TestUtil, multiply_tests | 37 | from bzrlib.tests import TestUtil, multiply_tests |
194 | 38 | try: | 38 | try: |
195 | 39 | from bzrlib.tests.features import ( | 39 | from bzrlib.tests.features import ( |
196 | 40 | ExecutableFeature, | ||
197 | 40 | ModuleAvailableFeature, | 41 | ModuleAvailableFeature, |
198 | 41 | UnicodeFilenameFeature, | 42 | UnicodeFilenameFeature, |
199 | 42 | ) | 43 | ) |
200 | 43 | except ImportError: # bzr < 2.5 | 44 | except ImportError: # bzr < 2.5 |
201 | 44 | from bzrlib.tests import ( | 45 | from bzrlib.tests import ( |
202 | 46 | ExecutableFeature, | ||
203 | 45 | ModuleAvailableFeature, | 47 | ModuleAvailableFeature, |
204 | 46 | UnicodeFilenameFeature, | 48 | UnicodeFilenameFeature, |
205 | 47 | ) | 49 | ) |
206 | @@ -135,6 +137,7 @@ | |||
207 | 135 | 'test_merge_package', | 137 | 'test_merge_package', |
208 | 136 | 'test_merge_quilt', | 138 | 'test_merge_quilt', |
209 | 137 | 'test_merge_upstream', | 139 | 'test_merge_upstream', |
210 | 140 | 'test_quilt', | ||
211 | 138 | 'test_repack_tarball_extra', | 141 | 'test_repack_tarball_extra', |
212 | 139 | 'test_revspec', | 142 | 'test_revspec', |
213 | 140 | 'test_source_distiller', | 143 | 'test_source_distiller', |
214 | 141 | 144 | ||
215 | === added file 'tests/test_quilt.py' | |||
216 | --- tests/test_quilt.py 1970-01-01 00:00:00 +0000 | |||
217 | +++ tests/test_quilt.py 2012-01-02 19:24:23 +0000 | |||
218 | @@ -0,0 +1,87 @@ | |||
219 | 1 | # Copyright (C) 2011 Canonical Ltd | ||
220 | 2 | # | ||
221 | 3 | # This file is part of bzr-builddeb. | ||
222 | 4 | # | ||
223 | 5 | # bzr-builddeb is free software; you can redistribute it and/or modify | ||
224 | 6 | # it under the terms of the GNU General Public License as published by | ||
225 | 7 | # the Free Software Foundation; either version 2 of the License, or | ||
226 | 8 | # (at your option) any later version. | ||
227 | 9 | # | ||
228 | 10 | # bzr-builddeb is distributed in the hope that it will be useful, | ||
229 | 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
230 | 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
231 | 13 | # GNU General Public License for more details. | ||
232 | 14 | # | ||
233 | 15 | # You should have received a copy of the GNU General Public License | ||
234 | 16 | # along with bzr-builddeb; if not, write to the Free Software | ||
235 | 17 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
236 | 18 | # | ||
237 | 19 | |||
238 | 20 | """Tests for the quilt code.""" | ||
239 | 21 | |||
240 | 22 | import os | ||
241 | 23 | |||
242 | 24 | from bzrlib.plugins.builddeb.tests import ExecutableFeature | ||
243 | 25 | from bzrlib.plugins.builddeb.quilt import ( | ||
244 | 26 | quilt_pop_all, | ||
245 | 27 | quilt_applied, | ||
246 | 28 | quilt_unapplied, | ||
247 | 29 | quilt_push_all, | ||
248 | 30 | quilt_series, | ||
249 | 31 | ) | ||
250 | 32 | |||
251 | 33 | from bzrlib.tests import TestCaseWithTransport | ||
252 | 34 | |||
253 | 35 | quilt_feature = ExecutableFeature('quilt') | ||
254 | 36 | |||
255 | 37 | TRIVIAL_PATCH = """--- /dev/null 2012-01-02 01:09:10.986490031 +0100 | ||
256 | 38 | +++ a 2012-01-02 20:03:59.710666215 +0100 | ||
257 | 39 | @@ -0,0 +1 @@ | ||
258 | 40 | +a | ||
259 | 41 | """ | ||
260 | 42 | |||
261 | 43 | class QuiltTests(TestCaseWithTransport): | ||
262 | 44 | |||
263 | 45 | _test_needs_features = [quilt_feature] | ||
264 | 46 | |||
265 | 47 | def make_empty_quilt_dir(self, path): | ||
266 | 48 | source = self.make_branch_and_tree(path) | ||
267 | 49 | self.build_tree([os.path.join(path, n) for n in ['debian/', | ||
268 | 50 | 'debian/patches/']]) | ||
269 | 51 | self.build_tree_contents([ | ||
270 | 52 | (os.path.join(path, "debian/patches/series"), "\n")]) | ||
271 | 53 | source.add(["debian", "debian/patches", "debian/patches/series"]) | ||
272 | 54 | return source | ||
273 | 55 | |||
274 | 56 | def test_series_all_empty(self): | ||
275 | 57 | self.make_empty_quilt_dir("source") | ||
276 | 58 | self.assertEquals([], quilt_series("source")) | ||
277 | 59 | |||
278 | 60 | def test_series_all(self): | ||
279 | 61 | self.make_empty_quilt_dir("source") | ||
280 | 62 | self.build_tree_contents([ | ||
281 | 63 | ("source/debian/patches/series", "patch1.diff\n"), | ||
282 | 64 | ("source/debian/patches/patch1.diff", TRIVIAL_PATCH)]) | ||
283 | 65 | self.assertEquals(["patch1.diff"], quilt_series("source")) | ||
284 | 66 | |||
285 | 67 | def test_push_all_empty(self): | ||
286 | 68 | self.make_empty_quilt_dir("source") | ||
287 | 69 | quilt_push_all("source", quiet=True) | ||
288 | 70 | |||
289 | 71 | def test_poph_all_empty(self): | ||
290 | 72 | self.make_empty_quilt_dir("source") | ||
291 | 73 | quilt_pop_all("source", quiet=True) | ||
292 | 74 | |||
293 | 75 | def test_applied_empty(self): | ||
294 | 76 | self.make_empty_quilt_dir("source") | ||
295 | 77 | self.build_tree_contents([ | ||
296 | 78 | ("source/debian/patches/series", "patch1.diff\n"), | ||
297 | 79 | ("source/debian/patches/patch1.diff", "foob ar")]) | ||
298 | 80 | self.assertEquals([], quilt_applied("source")) | ||
299 | 81 | |||
300 | 82 | def test_unapplied(self): | ||
301 | 83 | self.make_empty_quilt_dir("source") | ||
302 | 84 | self.build_tree_contents([ | ||
303 | 85 | ("source/debian/patches/series", "patch1.diff\n"), | ||
304 | 86 | ("source/debian/patches/patch1.diff", "foob ar")]) | ||
305 | 87 | self.assertEquals(["patch1.diff"], quilt_unapplied("source")) |
87 + :param quilt: Whether to be quiet (quilt stderr not to terminal)
muscle memory I think :-)
I think there's no tests for tree_unapply_ patches?
However, it looks good to me.
Thanks,
James