Merge lp:~jelmer/bzr-builddeb/auto-apply-quilt into lp:bzr-builddeb

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
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.

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.

Revision history for this message
James Westby (james-w) wrote :

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

review: Approve

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'builder.py'
--- builder.py 2009-12-01 17:14:15 +0000
+++ builder.py 2012-01-02 22:09:25 +0000
@@ -28,10 +28,13 @@
28 NoSourceDirError,28 NoSourceDirError,
29 BuildFailedError,29 BuildFailedError,
30 )30 )
31from bzrlib.plugins.builddeb.quilt import quilt_push_all
31from bzrlib.plugins.builddeb.util import (32from bzrlib.plugins.builddeb.util import (
32 get_parent_dir,33 get_parent_dir,
33 subprocess_setup,34 tree_get_source_format,
34 )35 subprocess_setup,
36 FORMAT_3_0_QUILT,
37 )
3538
3639
37class DebBuild(object):40class DebBuild(object):
@@ -71,8 +74,20 @@
71 if self.use_existing:74 if self.use_existing:
72 raise NoSourceDirError75 raise NoSourceDirError
7376
74 def export(self):77 def export(self, apply_quilt_patches=True):
75 self.distiller.distill(self.target_dir)78 self.distiller.distill(self.target_dir)
79 if apply_quilt_patches:
80 self._apply_quilt_patches()
81
82 def _apply_quilt_patches(self):
83 if not os.path.isfile(os.path.join(self.target_dir, "debian/patches/series")):
84 return
85 format_path = os.path.join(self.target_dir, "debian/source/format")
86 if not os.path.isfile(format_path):
87 return
88 with file(format_path, 'r') as f:
89 if f.read().strip() == FORMAT_3_0_QUILT:
90 quilt_push_all(os.path.abspath(self.target_dir))
7691
77 def build(self):92 def build(self):
78 """This builds the package using the supplied command."""93 """This builds the package using the supplied command."""
7994
=== modified file 'cmds.py'
--- cmds.py 2012-01-02 22:09:25 +0000
+++ cmds.py 2012-01-02 22:09:25 +0000
@@ -697,7 +697,7 @@
697 from bzrlib.plugins.builddeb.util import (697 from bzrlib.plugins.builddeb.util import (
698 FORMAT_3_0_QUILT,698 FORMAT_3_0_QUILT,
699 FORMAT_3_0_NATIVE,699 FORMAT_3_0_NATIVE,
700 get_source_format,700 tree_get_source_format,
701 guess_build_type,701 guess_build_type,
702 tree_contains_upstream_source,702 tree_contains_upstream_source,
703 )703 )
@@ -824,7 +824,7 @@
824 revisions=upstream_revisions)824 revisions=upstream_revisions)
825 else:825 else:
826 raise826 raise
827 source_format = get_source_format(tree)827 source_format = tree_get_source_format(tree)
828 v3 = (source_format in [828 v3 = (source_format in [
829 FORMAT_3_0_QUILT, FORMAT_3_0_NATIVE])829 FORMAT_3_0_QUILT, FORMAT_3_0_NATIVE])
830 tarball_filenames = self._get_tarballs(config, tree, package,830 tarball_filenames = self._get_tarballs(config, tree, package,
831831
=== modified file 'debian/changelog'
--- debian/changelog 2012-01-02 18:01:36 +0000
+++ debian/changelog 2012-01-02 22:09:25 +0000
@@ -5,8 +5,10 @@
5 commands like 'bzr bash-completion'. LP: #9036505 commands like 'bzr bash-completion'. LP: #903650
6 * Provide merge-package functionality as a hook for 'bzr merge'.6 * Provide merge-package functionality as a hook for 'bzr merge'.
7 LP: #486075, LP: #9109007 LP: #486075, LP: #910900
8 * Automatically apply patches for 3.0 (quilt) packages in 'bzr bd-do'
9 and 'bzr bd'. LP: #616791
810
9 -- Jelmer Vernooij <jelmer@debian.org> Mon, 02 Jan 2012 17:57:33 +010011 -- Jelmer Vernooij <jelmer@debian.org> Mon, 02 Jan 2012 23:02:44 +0100
1012
11bzr-builddeb (2.8.0) unstable; urgency=low13bzr-builddeb (2.8.0) unstable; urgency=low
1214
1315
=== modified file 'merge_quilt.py'
--- merge_quilt.py 2011-12-20 14:44:17 +0000
+++ merge_quilt.py 2012-01-02 22:09:25 +0000
@@ -21,3 +21,27 @@
21"""Quilt patch handling."""21"""Quilt patch handling."""
2222
23from __future__ import absolute_import23from __future__ import absolute_import
24import tempfile
25
26from bzrlib import trace
27from bzrlib.plugins.builddeb.quilt import quilt_pop_all
28
29
30def tree_unapply_patches(orig_tree):
31 """Return a tree with patches unapplied.
32
33 :param tree: Tree from which to unapply quilt patches
34 :return: Tuple with tree and temp path.
35 The tree is a tree with unapplied patches; either a checkout of
36 tree or tree itself if there were no patches
37 """
38 series_file_id = orig_tree.path2id("debian/patches/series")
39 if series_file_id is None:
40 # No quilt patches
41 return orig_tree, None
42
43 target_dir = tempfile.mkdtemp()
44 tree = orig_tree.branch.create_checkout(target_dir, lightweight=True)
45 trace.warning("Applying quilt patches for %r in %s", orig_tree, target_dir)
46 quilt_pop_all(working_dir=tree.basedir)
47 return tree, target_dir
2448
=== added file 'quilt.py'
--- quilt.py 1970-01-01 00:00:00 +0000
+++ quilt.py 2012-01-02 22:09:25 +0000
@@ -0,0 +1,151 @@
1# quilt.py -- Quilt patch handling
2# Copyright (C) 2011 Canonical Ltd.
3#
4# This file is part of bzr-builddeb.
5#
6# bzr-builddeb is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# bzr-builddeb is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with bzr-builddeb; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19#
20
21"""Quilt patch handling."""
22
23from __future__ import absolute_import
24
25import errno
26import os
27import signal
28import subprocess
29from bzrlib import (
30 errors,
31 trace,
32 )
33
34
35class QuiltError(errors.BzrError):
36
37 _fmt = "An error (%(retcode)d) occurred running quilt: %(msg)s"
38
39 def __init__(self, retcode, msg):
40 self.retcode = retcode
41 self.msg = msg
42
43
44def run_quilt(args, working_dir, series_file=None, patches_dir=None, quiet=None):
45 """Run quilt.
46
47 :param args: Arguments to quilt
48 :param working_dir: Working dir
49 :param series_file: Optional path to the series file
50 :param patches_dir: Optional path to the patches
51 :param quilt: Whether to be quiet (quilt stderr not to terminal)
52 :raise QuiltError: When running quilt fails
53 """
54 def subprocess_setup():
55 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
56 env = {}
57 if patches_dir is not None:
58 env["QUILT_PATCHES"] = patches_dir
59 else:
60 env["QUILT_PATCHES"] = os.path.join(working_dir, "debian", "patches")
61 if series_file is not None:
62 env["QUILT_SERIES"] = series_file
63 else:
64 env["QUILT_SERIES"] = os.path.join(env["QUILT_PATCHES"], "series")
65 # Hide output if -q is in use.
66 if quiet is None:
67 quiet = trace.is_quiet()
68 if quiet:
69 stderr = subprocess.STDOUT
70 else:
71 stderr = subprocess.PIPE
72 command = ["quilt"] + args
73 trace.mutter("running: %r", command)
74 if not os.path.isdir(working_dir):
75 raise AssertionError("%s is not a valid directory" % working_dir)
76 try:
77 proc = subprocess.Popen(command, cwd=working_dir, env=env,
78 stdin=subprocess.PIPE, preexec_fn=subprocess_setup,
79 stdout=subprocess.PIPE, stderr=stderr)
80 except OSError, e:
81 if e.errno != errno.ENOENT:
82 raise
83 raise errors.BzrError("quilt is not installed, please install it")
84 output = proc.communicate()
85 if proc.returncode not in (0, 2):
86 raise QuiltError(proc.returncode, output[1])
87 if output[0] is None:
88 return ""
89 return output[0]
90
91
92def quilt_pop_all(working_dir, patches_dir=None, series_file=None, quiet=None):
93 """Pop all patches.
94
95 :param working_dir: Directory to work in
96 :param patches_dir: Optional patches directory
97 :param series_file: Optional series file
98 """
99 return run_quilt(["pop", "-a", "-v"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file, quiet=quiet)
100
101
102def quilt_push_all(working_dir, patches_dir=None, series_file=None, quiet=None):
103 """Push all patches.
104
105 :param working_dir: Directory to work in
106 :param patches_dir: Optional patches directory
107 :param series_file: Optional series file
108 """
109 return run_quilt(["push", "-a", "-v"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file, quiet=quiet)
110
111
112def quilt_applied(working_dir, patches_dir=None, series_file=None):
113 """Find the list of applied quilt patches.
114
115 :param working_dir: Directory to work in
116 :param patches_dir: Optional patches directory
117 :param series_file: Optional series file
118 """
119 try:
120 return run_quilt(["applied"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file).splitlines()
121 except QuiltError, e:
122 if e.retcode == 1:
123 return []
124 raise
125
126
127def quilt_unapplied(working_dir, patches_dir=None, series_file=None):
128 """Find the list of unapplied quilt patches.
129
130 :param working_dir: Directory to work in
131 :param patches_dir: Optional patches directory
132 :param series_file: Optional series file
133 """
134 try:
135 return run_quilt(["unapplied"], working_dir=working_dir,
136 patches_dir=patches_dir, series_file=series_file).splitlines()
137 except QuiltError, e:
138 if e.retcode == 1:
139 return []
140 raise
141
142
143def quilt_series(working_dir, patches_dir=None, series_file=None):
144 """Find the list of patches.
145
146 :param working_dir: Directory to work in
147 :param patches_dir: Optional patches directory
148 :param series_file: Optional series file
149 """
150 return run_quilt(["series"], working_dir=working_dir, patches_dir=patches_dir, series_file=series_file).splitlines()
151
0152
=== modified file 'tests/__init__.py'
--- tests/__init__.py 2011-12-20 14:44:17 +0000
+++ tests/__init__.py 2012-01-02 22:09:25 +0000
@@ -37,11 +37,13 @@
37from bzrlib.tests import TestUtil, multiply_tests37from bzrlib.tests import TestUtil, multiply_tests
38try:38try:
39 from bzrlib.tests.features import (39 from bzrlib.tests.features import (
40 ExecutableFeature,
40 ModuleAvailableFeature,41 ModuleAvailableFeature,
41 UnicodeFilenameFeature,42 UnicodeFilenameFeature,
42 )43 )
43except ImportError: # bzr < 2.544except ImportError: # bzr < 2.5
44 from bzrlib.tests import (45 from bzrlib.tests import (
46 ExecutableFeature,
45 ModuleAvailableFeature,47 ModuleAvailableFeature,
46 UnicodeFilenameFeature,48 UnicodeFilenameFeature,
47 )49 )
@@ -135,6 +137,7 @@
135 'test_merge_package',137 'test_merge_package',
136 'test_merge_quilt',138 'test_merge_quilt',
137 'test_merge_upstream',139 'test_merge_upstream',
140 'test_quilt',
138 'test_repack_tarball_extra',141 'test_repack_tarball_extra',
139 'test_revspec',142 'test_revspec',
140 'test_source_distiller',143 'test_source_distiller',
141144
=== added file 'tests/test_quilt.py'
--- tests/test_quilt.py 1970-01-01 00:00:00 +0000
+++ tests/test_quilt.py 2012-01-02 22:09:25 +0000
@@ -0,0 +1,87 @@
1# Copyright (C) 2011 Canonical Ltd
2#
3# This file is part of bzr-builddeb.
4#
5# bzr-builddeb is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# bzr-builddeb is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with bzr-builddeb; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18#
19
20"""Tests for the quilt code."""
21
22import os
23
24from bzrlib.plugins.builddeb.tests import ExecutableFeature
25from bzrlib.plugins.builddeb.quilt import (
26 quilt_pop_all,
27 quilt_applied,
28 quilt_unapplied,
29 quilt_push_all,
30 quilt_series,
31 )
32
33from bzrlib.tests import TestCaseWithTransport
34
35quilt_feature = ExecutableFeature('quilt')
36
37TRIVIAL_PATCH = """--- /dev/null 2012-01-02 01:09:10.986490031 +0100
38+++ a 2012-01-02 20:03:59.710666215 +0100
39@@ -0,0 +1 @@
40+a
41"""
42
43class QuiltTests(TestCaseWithTransport):
44
45 _test_needs_features = [quilt_feature]
46
47 def make_empty_quilt_dir(self, path):
48 source = self.make_branch_and_tree(path)
49 self.build_tree([os.path.join(path, n) for n in ['debian/',
50 'debian/patches/']])
51 self.build_tree_contents([
52 (os.path.join(path, "debian/patches/series"), "\n")])
53 source.add(["debian", "debian/patches", "debian/patches/series"])
54 return source
55
56 def test_series_all_empty(self):
57 self.make_empty_quilt_dir("source")
58 self.assertEquals([], quilt_series("source"))
59
60 def test_series_all(self):
61 self.make_empty_quilt_dir("source")
62 self.build_tree_contents([
63 ("source/debian/patches/series", "patch1.diff\n"),
64 ("source/debian/patches/patch1.diff", TRIVIAL_PATCH)])
65 self.assertEquals(["patch1.diff"], quilt_series("source"))
66
67 def test_push_all_empty(self):
68 self.make_empty_quilt_dir("source")
69 quilt_push_all("source", quiet=True)
70
71 def test_poph_all_empty(self):
72 self.make_empty_quilt_dir("source")
73 quilt_pop_all("source", quiet=True)
74
75 def test_applied_empty(self):
76 self.make_empty_quilt_dir("source")
77 self.build_tree_contents([
78 ("source/debian/patches/series", "patch1.diff\n"),
79 ("source/debian/patches/patch1.diff", "foob ar")])
80 self.assertEquals([], quilt_applied("source"))
81
82 def test_unapplied(self):
83 self.make_empty_quilt_dir("source")
84 self.build_tree_contents([
85 ("source/debian/patches/series", "patch1.diff\n"),
86 ("source/debian/patches/patch1.diff", "foob ar")])
87 self.assertEquals(["patch1.diff"], quilt_unapplied("source"))
088
=== modified file 'tests/test_util.py'
--- tests/test_util.py 2011-09-09 13:20:42 +0000
+++ tests/test_util.py 2012-01-02 22:09:25 +0000
@@ -63,7 +63,6 @@
63 _find_previous_upload,63 _find_previous_upload,
64 find_thanks,64 find_thanks,
65 get_commit_info_from_changelog,65 get_commit_info_from_changelog,
66 get_source_format,
67 guess_build_type,66 guess_build_type,
68 lookup_distribution,67 lookup_distribution,
69 move_file_if_different,68 move_file_if_different,
@@ -74,6 +73,7 @@
74 suite_to_distribution,73 suite_to_distribution,
75 tarball_name,74 tarball_name,
76 tree_contains_upstream_source,75 tree_contains_upstream_source,
76 tree_get_source_format,
77 write_if_different,77 write_if_different,
78 )78 )
7979
@@ -773,27 +773,27 @@
773773
774 def test_no_source_format_file(self):774 def test_no_source_format_file(self):
775 tree = self.make_branch_and_tree('.')775 tree = self.make_branch_and_tree('.')
776 self.assertEquals("1.0", get_source_format(tree))776 self.assertEquals("1.0", tree_get_source_format(tree))
777777
778 def test_source_format_newline(self):778 def test_source_format_newline(self):
779 tree = self.make_branch_and_tree('.')779 tree = self.make_branch_and_tree('.')
780 self.build_tree_contents([("debian/", ), ("debian/source/",),780 self.build_tree_contents([("debian/", ), ("debian/source/",),
781 ("debian/source/format", "3.0 (native)\n")])781 ("debian/source/format", "3.0 (native)\n")])
782 tree.add(["debian", "debian/source", "debian/source/format"])782 tree.add(["debian", "debian/source", "debian/source/format"])
783 self.assertEquals("3.0 (native)", get_source_format(tree))783 self.assertEquals("3.0 (native)", tree_get_source_format(tree))
784784
785 def test_source_format(self):785 def test_source_format(self):
786 tree = self.make_branch_and_tree('.')786 tree = self.make_branch_and_tree('.')
787 self.build_tree_contents([("debian/",), ("debian/source/",),787 self.build_tree_contents([("debian/",), ("debian/source/",),
788 ("debian/source/format", "3.0 (quilt)")])788 ("debian/source/format", "3.0 (quilt)")])
789 tree.add(["debian", "debian/source", "debian/source/format"])789 tree.add(["debian", "debian/source", "debian/source/format"])
790 self.assertEquals("3.0 (quilt)", get_source_format(tree))790 self.assertEquals("3.0 (quilt)", tree_get_source_format(tree))
791791
792 def test_source_format_file_unversioned(self):792 def test_source_format_file_unversioned(self):
793 tree = self.make_branch_and_tree('.')793 tree = self.make_branch_and_tree('.')
794 self.build_tree_contents([("debian/",), ("debian/source/",),794 self.build_tree_contents([("debian/",), ("debian/source/",),
795 ("debian/source/format", "3.0 (quilt)")])795 ("debian/source/format", "3.0 (quilt)")])
796 self.assertEquals("3.0 (quilt)", get_source_format(tree))796 self.assertEquals("3.0 (quilt)", tree_get_source_format(tree))
797797
798798
799class GuessBuildTypeTests(TestCaseWithTransport):799class GuessBuildTypeTests(TestCaseWithTransport):
800800
=== modified file 'util.py'
--- util.py 2011-10-28 16:32:42 +0000
+++ util.py 2012-01-02 22:09:25 +0000
@@ -648,16 +648,17 @@
648 return (len(present_files - packaging_files) > 0)648 return (len(present_files - packaging_files) > 0)
649649
650650
651def get_source_format(tree):651def tree_get_source_format(tree):
652 """Retrieve the source format name from a package.652 """Retrieve the source format name from a package.
653653
654 :param path: Path to the package654 :param path: Path to the package
655 :return: String with package format655 :return: String with package format
656 """656 """
657 filename = "debian/source/format"657 filename = "debian/source/format"
658 if not tree.has_filename(filename):658 file_id = tree.path2id(filename)
659 if file_id is None:
659 return FORMAT_1_0660 return FORMAT_1_0
660 text = tree.get_file_text(tree.path2id(filename), filename)661 text = tree.get_file_text(file_id, filename)
661 return text.strip()662 return text.strip()
662663
663664
@@ -677,7 +678,7 @@
677 :param contains_upstream_source: Whether this branch contains the upstream source.678 :param contains_upstream_source: Whether this branch contains the upstream source.
678 :return: A build_type value.679 :return: A build_type value.
679 """680 """
680 source_format = get_source_format(tree)681 source_format = tree_get_source_format(tree)
681 if source_format in NATIVE_SOURCE_FORMATS:682 if source_format in NATIVE_SOURCE_FORMATS:
682 format_native = True683 format_native = True
683 elif source_format in NORMAL_SOURCE_FORMATS:684 elif source_format in NORMAL_SOURCE_FORMATS:

Subscribers

People subscribed via source and target branches