Merge lp:~jelmer/bzr-builddeb/auto-apply-quilt into lp:bzr-builddeb
- auto-apply-quilt
- Merge into trunk
Proposed by
Jelmer Vernooij
Status: | Superseded |
---|---|
Proposed branch: | lp:~jelmer/bzr-builddeb/auto-apply-quilt |
Merge into: | lp:bzr-builddeb |
Prerequisite: | lp:~jelmer/bzr-builddeb/fix-bd-do-build-type-guessing |
Diff against target: |
472 lines (+299/-16) 9 files modified
builder.py (+19/-4) cmds.py (+2/-2) debian/changelog (+3/-1) merge_quilt.py (+24/-0) quilt.py (+151/-0) tests/__init__.py (+3/-0) tests/test_quilt.py (+87/-0) tests/test_util.py (+5/-5) util.py (+5/-4) |
To merge this branch: | bzr merge lp:~jelmer/bzr-builddeb/auto-apply-quilt |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Westby | Approve | ||
Review via email: mp+87296@code.launchpad.net |
This proposal supersedes a proposal from 2012-01-02.
This proposal has been superseded by a proposal from 2012-01-05.
Commit message
Description of the change
Automatically apply patches for 3.0 (quilt) packages in 'bzr bd' or 'bzr bd-do'.
To post a comment you must log in.
- 685. By Jelmer Vernooij
-
Fix changelog.
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'builder.py' |
2 | --- builder.py 2009-12-01 17:14:15 +0000 |
3 | +++ builder.py 2012-01-02 22:09:25 +0000 |
4 | @@ -28,10 +28,13 @@ |
5 | NoSourceDirError, |
6 | BuildFailedError, |
7 | ) |
8 | +from bzrlib.plugins.builddeb.quilt import quilt_push_all |
9 | from bzrlib.plugins.builddeb.util import ( |
10 | - get_parent_dir, |
11 | - subprocess_setup, |
12 | - ) |
13 | + get_parent_dir, |
14 | + tree_get_source_format, |
15 | + subprocess_setup, |
16 | + FORMAT_3_0_QUILT, |
17 | + ) |
18 | |
19 | |
20 | class DebBuild(object): |
21 | @@ -71,8 +74,20 @@ |
22 | if self.use_existing: |
23 | raise NoSourceDirError |
24 | |
25 | - def export(self): |
26 | + def export(self, apply_quilt_patches=True): |
27 | self.distiller.distill(self.target_dir) |
28 | + if apply_quilt_patches: |
29 | + self._apply_quilt_patches() |
30 | + |
31 | + def _apply_quilt_patches(self): |
32 | + if not os.path.isfile(os.path.join(self.target_dir, "debian/patches/series")): |
33 | + return |
34 | + format_path = os.path.join(self.target_dir, "debian/source/format") |
35 | + if not os.path.isfile(format_path): |
36 | + return |
37 | + with file(format_path, 'r') as f: |
38 | + if f.read().strip() == FORMAT_3_0_QUILT: |
39 | + quilt_push_all(os.path.abspath(self.target_dir)) |
40 | |
41 | def build(self): |
42 | """This builds the package using the supplied command.""" |
43 | |
44 | === modified file 'cmds.py' |
45 | --- cmds.py 2012-01-02 22:09:25 +0000 |
46 | +++ cmds.py 2012-01-02 22:09:25 +0000 |
47 | @@ -697,7 +697,7 @@ |
48 | from bzrlib.plugins.builddeb.util import ( |
49 | FORMAT_3_0_QUILT, |
50 | FORMAT_3_0_NATIVE, |
51 | - get_source_format, |
52 | + tree_get_source_format, |
53 | guess_build_type, |
54 | tree_contains_upstream_source, |
55 | ) |
56 | @@ -824,7 +824,7 @@ |
57 | revisions=upstream_revisions) |
58 | else: |
59 | raise |
60 | - source_format = get_source_format(tree) |
61 | + source_format = tree_get_source_format(tree) |
62 | v3 = (source_format in [ |
63 | FORMAT_3_0_QUILT, FORMAT_3_0_NATIVE]) |
64 | tarball_filenames = self._get_tarballs(config, tree, package, |
65 | |
66 | === modified file 'debian/changelog' |
67 | --- debian/changelog 2012-01-02 18:01:36 +0000 |
68 | +++ debian/changelog 2012-01-02 22:09:25 +0000 |
69 | @@ -5,8 +5,10 @@ |
70 | commands like 'bzr bash-completion'. LP: #903650 |
71 | * Provide merge-package functionality as a hook for 'bzr merge'. |
72 | LP: #486075, LP: #910900 |
73 | + * Automatically apply patches for 3.0 (quilt) packages in 'bzr bd-do' |
74 | + and 'bzr bd'. LP: #616791 |
75 | |
76 | - -- Jelmer Vernooij <jelmer@debian.org> Mon, 02 Jan 2012 17:57:33 +0100 |
77 | + -- Jelmer Vernooij <jelmer@debian.org> Mon, 02 Jan 2012 23:02:44 +0100 |
78 | |
79 | bzr-builddeb (2.8.0) unstable; urgency=low |
80 | |
81 | |
82 | === modified file 'merge_quilt.py' |
83 | --- merge_quilt.py 2011-12-20 14:44:17 +0000 |
84 | +++ merge_quilt.py 2012-01-02 22:09:25 +0000 |
85 | @@ -21,3 +21,27 @@ |
86 | """Quilt patch handling.""" |
87 | |
88 | from __future__ import absolute_import |
89 | +import tempfile |
90 | + |
91 | +from bzrlib import trace |
92 | +from bzrlib.plugins.builddeb.quilt import quilt_pop_all |
93 | + |
94 | + |
95 | +def tree_unapply_patches(orig_tree): |
96 | + """Return a tree with patches unapplied. |
97 | + |
98 | + :param tree: Tree from which to unapply quilt patches |
99 | + :return: Tuple with tree and temp path. |
100 | + The tree is a tree with unapplied patches; either a checkout of |
101 | + tree or tree itself if there were no patches |
102 | + """ |
103 | + series_file_id = orig_tree.path2id("debian/patches/series") |
104 | + if series_file_id is None: |
105 | + # No quilt patches |
106 | + return orig_tree, None |
107 | + |
108 | + target_dir = tempfile.mkdtemp() |
109 | + tree = orig_tree.branch.create_checkout(target_dir, lightweight=True) |
110 | + trace.warning("Applying quilt patches for %r in %s", orig_tree, target_dir) |
111 | + quilt_pop_all(working_dir=tree.basedir) |
112 | + return tree, target_dir |
113 | |
114 | === added file 'quilt.py' |
115 | --- quilt.py 1970-01-01 00:00:00 +0000 |
116 | +++ quilt.py 2012-01-02 22:09:25 +0000 |
117 | @@ -0,0 +1,151 @@ |
118 | +# quilt.py -- Quilt patch handling |
119 | +# Copyright (C) 2011 Canonical Ltd. |
120 | +# |
121 | +# This file is part of bzr-builddeb. |
122 | +# |
123 | +# bzr-builddeb is free software; you can redistribute it and/or modify |
124 | +# it under the terms of the GNU General Public License as published by |
125 | +# the Free Software Foundation; either version 2 of the License, or |
126 | +# (at your option) any later version. |
127 | +# |
128 | +# bzr-builddeb is distributed in the hope that it will be useful, |
129 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
130 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
131 | +# GNU General Public License for more details. |
132 | +# |
133 | +# You should have received a copy of the GNU General Public License |
134 | +# along with bzr-builddeb; if not, write to the Free Software |
135 | +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
136 | +# |
137 | + |
138 | +"""Quilt patch handling.""" |
139 | + |
140 | +from __future__ import absolute_import |
141 | + |
142 | +import errno |
143 | +import os |
144 | +import signal |
145 | +import subprocess |
146 | +from bzrlib import ( |
147 | + errors, |
148 | + trace, |
149 | + ) |
150 | + |
151 | + |
152 | +class QuiltError(errors.BzrError): |
153 | + |
154 | + _fmt = "An error (%(retcode)d) occurred running quilt: %(msg)s" |
155 | + |
156 | + def __init__(self, retcode, msg): |
157 | + self.retcode = retcode |
158 | + self.msg = msg |
159 | + |
160 | + |
161 | +def run_quilt(args, working_dir, series_file=None, patches_dir=None, quiet=None): |
162 | + """Run quilt. |
163 | + |
164 | + :param args: Arguments to quilt |
165 | + :param working_dir: Working dir |
166 | + :param series_file: Optional path to the series file |
167 | + :param patches_dir: Optional path to the patches |
168 | + :param quilt: Whether to be quiet (quilt stderr not to terminal) |
169 | + :raise QuiltError: When running quilt fails |
170 | + """ |
171 | + def subprocess_setup(): |
172 | + signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
173 | + env = {} |
174 | + if patches_dir is not None: |
175 | + env["QUILT_PATCHES"] = patches_dir |
176 | + else: |
177 | + env["QUILT_PATCHES"] = os.path.join(working_dir, "debian", "patches") |
178 | + if series_file is not None: |
179 | + env["QUILT_SERIES"] = series_file |
180 | + else: |
181 | + env["QUILT_SERIES"] = os.path.join(env["QUILT_PATCHES"], "series") |
182 | + # Hide output if -q is in use. |
183 | + if quiet is None: |
184 | + quiet = trace.is_quiet() |
185 | + if quiet: |
186 | + stderr = subprocess.STDOUT |
187 | + else: |
188 | + stderr = subprocess.PIPE |
189 | + command = ["quilt"] + args |
190 | + trace.mutter("running: %r", command) |
191 | + if not os.path.isdir(working_dir): |
192 | + raise AssertionError("%s is not a valid directory" % working_dir) |
193 | + try: |
194 | + proc = subprocess.Popen(command, cwd=working_dir, env=env, |
195 | + stdin=subprocess.PIPE, preexec_fn=subprocess_setup, |
196 | + stdout=subprocess.PIPE, stderr=stderr) |
197 | + except OSError, e: |
198 | + if e.errno != errno.ENOENT: |
199 | + raise |
200 | + raise errors.BzrError("quilt is not installed, please install it") |
201 | + output = proc.communicate() |
202 | + if proc.returncode not in (0, 2): |
203 | + raise QuiltError(proc.returncode, output[1]) |
204 | + if output[0] is None: |
205 | + return "" |
206 | + return output[0] |
207 | + |
208 | + |
209 | +def quilt_pop_all(working_dir, patches_dir=None, series_file=None, quiet=None): |
210 | + """Pop all patches. |
211 | + |
212 | + :param working_dir: Directory to work in |
213 | + :param patches_dir: Optional patches directory |
214 | + :param series_file: Optional series file |
215 | + """ |
216 | + return run_quilt(["pop", "-a", "-v"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file, quiet=quiet) |
217 | + |
218 | + |
219 | +def quilt_push_all(working_dir, patches_dir=None, series_file=None, quiet=None): |
220 | + """Push all patches. |
221 | + |
222 | + :param working_dir: Directory to work in |
223 | + :param patches_dir: Optional patches directory |
224 | + :param series_file: Optional series file |
225 | + """ |
226 | + return run_quilt(["push", "-a", "-v"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file, quiet=quiet) |
227 | + |
228 | + |
229 | +def quilt_applied(working_dir, patches_dir=None, series_file=None): |
230 | + """Find the list of applied quilt patches. |
231 | + |
232 | + :param working_dir: Directory to work in |
233 | + :param patches_dir: Optional patches directory |
234 | + :param series_file: Optional series file |
235 | + """ |
236 | + try: |
237 | + return run_quilt(["applied"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file).splitlines() |
238 | + except QuiltError, e: |
239 | + if e.retcode == 1: |
240 | + return [] |
241 | + raise |
242 | + |
243 | + |
244 | +def quilt_unapplied(working_dir, patches_dir=None, series_file=None): |
245 | + """Find the list of unapplied quilt patches. |
246 | + |
247 | + :param working_dir: Directory to work in |
248 | + :param patches_dir: Optional patches directory |
249 | + :param series_file: Optional series file |
250 | + """ |
251 | + try: |
252 | + return run_quilt(["unapplied"], working_dir=working_dir, |
253 | + patches_dir=patches_dir, series_file=series_file).splitlines() |
254 | + except QuiltError, e: |
255 | + if e.retcode == 1: |
256 | + return [] |
257 | + raise |
258 | + |
259 | + |
260 | +def quilt_series(working_dir, patches_dir=None, series_file=None): |
261 | + """Find the list of patches. |
262 | + |
263 | + :param working_dir: Directory to work in |
264 | + :param patches_dir: Optional patches directory |
265 | + :param series_file: Optional series file |
266 | + """ |
267 | + return run_quilt(["series"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file).splitlines() |
268 | + |
269 | |
270 | === modified file 'tests/__init__.py' |
271 | --- tests/__init__.py 2011-12-20 14:44:17 +0000 |
272 | +++ tests/__init__.py 2012-01-02 22:09:25 +0000 |
273 | @@ -37,11 +37,13 @@ |
274 | from bzrlib.tests import TestUtil, multiply_tests |
275 | try: |
276 | from bzrlib.tests.features import ( |
277 | + ExecutableFeature, |
278 | ModuleAvailableFeature, |
279 | UnicodeFilenameFeature, |
280 | ) |
281 | except ImportError: # bzr < 2.5 |
282 | from bzrlib.tests import ( |
283 | + ExecutableFeature, |
284 | ModuleAvailableFeature, |
285 | UnicodeFilenameFeature, |
286 | ) |
287 | @@ -135,6 +137,7 @@ |
288 | 'test_merge_package', |
289 | 'test_merge_quilt', |
290 | 'test_merge_upstream', |
291 | + 'test_quilt', |
292 | 'test_repack_tarball_extra', |
293 | 'test_revspec', |
294 | 'test_source_distiller', |
295 | |
296 | === added file 'tests/test_quilt.py' |
297 | --- tests/test_quilt.py 1970-01-01 00:00:00 +0000 |
298 | +++ tests/test_quilt.py 2012-01-02 22:09:25 +0000 |
299 | @@ -0,0 +1,87 @@ |
300 | +# Copyright (C) 2011 Canonical Ltd |
301 | +# |
302 | +# This file is part of bzr-builddeb. |
303 | +# |
304 | +# bzr-builddeb is free software; you can redistribute it and/or modify |
305 | +# it under the terms of the GNU General Public License as published by |
306 | +# the Free Software Foundation; either version 2 of the License, or |
307 | +# (at your option) any later version. |
308 | +# |
309 | +# bzr-builddeb is distributed in the hope that it will be useful, |
310 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
311 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
312 | +# GNU General Public License for more details. |
313 | +# |
314 | +# You should have received a copy of the GNU General Public License |
315 | +# along with bzr-builddeb; if not, write to the Free Software |
316 | +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
317 | +# |
318 | + |
319 | +"""Tests for the quilt code.""" |
320 | + |
321 | +import os |
322 | + |
323 | +from bzrlib.plugins.builddeb.tests import ExecutableFeature |
324 | +from bzrlib.plugins.builddeb.quilt import ( |
325 | + quilt_pop_all, |
326 | + quilt_applied, |
327 | + quilt_unapplied, |
328 | + quilt_push_all, |
329 | + quilt_series, |
330 | + ) |
331 | + |
332 | +from bzrlib.tests import TestCaseWithTransport |
333 | + |
334 | +quilt_feature = ExecutableFeature('quilt') |
335 | + |
336 | +TRIVIAL_PATCH = """--- /dev/null 2012-01-02 01:09:10.986490031 +0100 |
337 | ++++ a 2012-01-02 20:03:59.710666215 +0100 |
338 | +@@ -0,0 +1 @@ |
339 | ++a |
340 | +""" |
341 | + |
342 | +class QuiltTests(TestCaseWithTransport): |
343 | + |
344 | + _test_needs_features = [quilt_feature] |
345 | + |
346 | + def make_empty_quilt_dir(self, path): |
347 | + source = self.make_branch_and_tree(path) |
348 | + self.build_tree([os.path.join(path, n) for n in ['debian/', |
349 | + 'debian/patches/']]) |
350 | + self.build_tree_contents([ |
351 | + (os.path.join(path, "debian/patches/series"), "\n")]) |
352 | + source.add(["debian", "debian/patches", "debian/patches/series"]) |
353 | + return source |
354 | + |
355 | + def test_series_all_empty(self): |
356 | + self.make_empty_quilt_dir("source") |
357 | + self.assertEquals([], quilt_series("source")) |
358 | + |
359 | + def test_series_all(self): |
360 | + self.make_empty_quilt_dir("source") |
361 | + self.build_tree_contents([ |
362 | + ("source/debian/patches/series", "patch1.diff\n"), |
363 | + ("source/debian/patches/patch1.diff", TRIVIAL_PATCH)]) |
364 | + self.assertEquals(["patch1.diff"], quilt_series("source")) |
365 | + |
366 | + def test_push_all_empty(self): |
367 | + self.make_empty_quilt_dir("source") |
368 | + quilt_push_all("source", quiet=True) |
369 | + |
370 | + def test_poph_all_empty(self): |
371 | + self.make_empty_quilt_dir("source") |
372 | + quilt_pop_all("source", quiet=True) |
373 | + |
374 | + def test_applied_empty(self): |
375 | + self.make_empty_quilt_dir("source") |
376 | + self.build_tree_contents([ |
377 | + ("source/debian/patches/series", "patch1.diff\n"), |
378 | + ("source/debian/patches/patch1.diff", "foob ar")]) |
379 | + self.assertEquals([], quilt_applied("source")) |
380 | + |
381 | + def test_unapplied(self): |
382 | + self.make_empty_quilt_dir("source") |
383 | + self.build_tree_contents([ |
384 | + ("source/debian/patches/series", "patch1.diff\n"), |
385 | + ("source/debian/patches/patch1.diff", "foob ar")]) |
386 | + self.assertEquals(["patch1.diff"], quilt_unapplied("source")) |
387 | |
388 | === modified file 'tests/test_util.py' |
389 | --- tests/test_util.py 2011-09-09 13:20:42 +0000 |
390 | +++ tests/test_util.py 2012-01-02 22:09:25 +0000 |
391 | @@ -63,7 +63,6 @@ |
392 | _find_previous_upload, |
393 | find_thanks, |
394 | get_commit_info_from_changelog, |
395 | - get_source_format, |
396 | guess_build_type, |
397 | lookup_distribution, |
398 | move_file_if_different, |
399 | @@ -74,6 +73,7 @@ |
400 | suite_to_distribution, |
401 | tarball_name, |
402 | tree_contains_upstream_source, |
403 | + tree_get_source_format, |
404 | write_if_different, |
405 | ) |
406 | |
407 | @@ -773,27 +773,27 @@ |
408 | |
409 | def test_no_source_format_file(self): |
410 | tree = self.make_branch_and_tree('.') |
411 | - self.assertEquals("1.0", get_source_format(tree)) |
412 | + self.assertEquals("1.0", tree_get_source_format(tree)) |
413 | |
414 | def test_source_format_newline(self): |
415 | tree = self.make_branch_and_tree('.') |
416 | self.build_tree_contents([("debian/", ), ("debian/source/",), |
417 | ("debian/source/format", "3.0 (native)\n")]) |
418 | tree.add(["debian", "debian/source", "debian/source/format"]) |
419 | - self.assertEquals("3.0 (native)", get_source_format(tree)) |
420 | + self.assertEquals("3.0 (native)", tree_get_source_format(tree)) |
421 | |
422 | def test_source_format(self): |
423 | tree = self.make_branch_and_tree('.') |
424 | self.build_tree_contents([("debian/",), ("debian/source/",), |
425 | ("debian/source/format", "3.0 (quilt)")]) |
426 | tree.add(["debian", "debian/source", "debian/source/format"]) |
427 | - self.assertEquals("3.0 (quilt)", get_source_format(tree)) |
428 | + self.assertEquals("3.0 (quilt)", tree_get_source_format(tree)) |
429 | |
430 | def test_source_format_file_unversioned(self): |
431 | tree = self.make_branch_and_tree('.') |
432 | self.build_tree_contents([("debian/",), ("debian/source/",), |
433 | ("debian/source/format", "3.0 (quilt)")]) |
434 | - self.assertEquals("3.0 (quilt)", get_source_format(tree)) |
435 | + self.assertEquals("3.0 (quilt)", tree_get_source_format(tree)) |
436 | |
437 | |
438 | class GuessBuildTypeTests(TestCaseWithTransport): |
439 | |
440 | === modified file 'util.py' |
441 | --- util.py 2011-10-28 16:32:42 +0000 |
442 | +++ util.py 2012-01-02 22:09:25 +0000 |
443 | @@ -648,16 +648,17 @@ |
444 | return (len(present_files - packaging_files) > 0) |
445 | |
446 | |
447 | -def get_source_format(tree): |
448 | +def tree_get_source_format(tree): |
449 | """Retrieve the source format name from a package. |
450 | |
451 | :param path: Path to the package |
452 | :return: String with package format |
453 | """ |
454 | filename = "debian/source/format" |
455 | - if not tree.has_filename(filename): |
456 | + file_id = tree.path2id(filename) |
457 | + if file_id is None: |
458 | return FORMAT_1_0 |
459 | - text = tree.get_file_text(tree.path2id(filename), filename) |
460 | + text = tree.get_file_text(file_id, filename) |
461 | return text.strip() |
462 | |
463 | |
464 | @@ -677,7 +678,7 @@ |
465 | :param contains_upstream_source: Whether this branch contains the upstream source. |
466 | :return: A build_type value. |
467 | """ |
468 | - source_format = get_source_format(tree) |
469 | + source_format = tree_get_source_format(tree) |
470 | if source_format in NATIVE_SOURCE_FORMATS: |
471 | format_native = True |
472 | elif source_format in NORMAL_SOURCE_FORMATS: |
This looks good.
However, the diff on LP includes a bit much. Is that a bug with
added files + prerequisite branches on Launchpad?
Thanks,
James