Merge lp:~jelmer/bzr-builddeb/pristine-tar-refactor into lp:bzr-builddeb
- pristine-tar-refactor
- Merge into trunk
Proposed by
Jelmer Vernooij
Status: | Merged |
---|---|
Approved by: | James Westby |
Approved revision: | no longer in the source branch. |
Merged at revision: | 563 |
Proposed branch: | lp:~jelmer/bzr-builddeb/pristine-tar-refactor |
Merge into: | lp:bzr-builddeb |
Diff against target: |
688 lines (+281/-233) 7 files modified
cmds.py (+3/-1) errors.py (+0/-7) import_dsc.py (+7/-30) tests/test_upstream.py (+3/-2) upstream/__init__.py (+0/-141) upstream/pristinetar.py (+267/-0) util.py (+1/-52) |
To merge this branch: | bzr merge lp:~jelmer/bzr-builddeb/pristine-tar-refactor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Westby | Approve | ||
Review via email: mp+63381@code.launchpad.net |
Commit message
Description of the change
Move all pristine-tar related code into upstream/
This makes import_dsc.py a bit smaller, and makes it a bit easier to understand how pristine tar is involved. I'm looking at this so we can use pristine tar in bzr-builder too.
To post a comment you must log in.
Revision history for this message
James Westby (james-w) : | # |
review:
Approve
- 563. By Jelmer Vernooij
-
Merge refactoring of pristine tar upstream source.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'cmds.py' | |||
2 | --- cmds.py 2011-05-16 14:21:31 +0000 | |||
3 | +++ cmds.py 2011-06-03 13:28:25 +0000 | |||
4 | @@ -93,7 +93,6 @@ | |||
5 | 93 | from bzrlib.plugins.builddeb.upstream import ( | 93 | from bzrlib.plugins.builddeb.upstream import ( |
6 | 94 | AptSource, | 94 | AptSource, |
7 | 95 | GetOrigSourceSource, | 95 | GetOrigSourceSource, |
8 | 96 | PristineTarSource, | ||
9 | 97 | SelfSplitSource, | 96 | SelfSplitSource, |
10 | 98 | TarfileSource, | 97 | TarfileSource, |
11 | 99 | UScanSource, | 98 | UScanSource, |
12 | @@ -103,6 +102,9 @@ | |||
13 | 103 | LazyUpstreamBranchSource, | 102 | LazyUpstreamBranchSource, |
14 | 104 | UpstreamBranchSource, | 103 | UpstreamBranchSource, |
15 | 105 | ) | 104 | ) |
16 | 105 | from bzrlib.plugins.builddeb.upstream.pristinetar import ( | ||
17 | 106 | PristineTarSource, | ||
18 | 107 | ) | ||
19 | 106 | from bzrlib.plugins.builddeb.util import ( | 108 | from bzrlib.plugins.builddeb.util import ( |
20 | 107 | FORMAT_3_0_QUILT, | 109 | FORMAT_3_0_QUILT, |
21 | 108 | FORMAT_3_0_NATIVE, | 110 | FORMAT_3_0_NATIVE, |
22 | 109 | 111 | ||
23 | === modified file 'errors.py' | |||
24 | --- errors.py 2011-05-15 17:21:54 +0000 | |||
25 | +++ errors.py 2011-06-03 13:28:25 +0000 | |||
26 | @@ -163,13 +163,6 @@ | |||
27 | 163 | BzrError.__init__(self, location=location) | 163 | BzrError.__init__(self, location=location) |
28 | 164 | 164 | ||
29 | 165 | 165 | ||
30 | 166 | class PristineTarError(BzrError): | ||
31 | 167 | _fmt = 'There was an error using pristine-tar: %(error)s.' | ||
32 | 168 | |||
33 | 169 | def __init__(self, error): | ||
34 | 170 | BzrError.__init__(self, error=error) | ||
35 | 171 | |||
36 | 172 | |||
37 | 173 | class SharedUpstreamConflictsWithTargetPackaging(BzrError): | 166 | class SharedUpstreamConflictsWithTargetPackaging(BzrError): |
38 | 174 | _fmt = ('The upstream branches for the merge source and target have ' | 167 | _fmt = ('The upstream branches for the merge source and target have ' |
39 | 175 | 'diverged. Unfortunately, the attempt to fix this problem ' | 168 | 'diverged. Unfortunately, the attempt to fix this problem ' |
40 | 176 | 169 | ||
41 | === modified file 'import_dsc.py' | |||
42 | --- import_dsc.py 2011-04-29 12:54:58 +0000 | |||
43 | +++ import_dsc.py 2011-06-03 13:28:25 +0000 | |||
44 | @@ -25,9 +25,6 @@ | |||
45 | 25 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 25 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
46 | 26 | # | 26 | # |
47 | 27 | 27 | ||
48 | 28 | from base64 import ( | ||
49 | 29 | standard_b64encode, | ||
50 | 30 | ) | ||
51 | 31 | 28 | ||
52 | 32 | import os | 29 | import os |
53 | 33 | import re | 30 | import re |
54 | @@ -74,19 +71,18 @@ | |||
55 | 74 | FORMAT_3_0_NATIVE, | 71 | FORMAT_3_0_NATIVE, |
56 | 75 | export, | 72 | export, |
57 | 76 | get_commit_info_from_changelog, | 73 | get_commit_info_from_changelog, |
58 | 77 | make_pristine_tar_delta, | ||
59 | 78 | md5sum_filename, | 74 | md5sum_filename, |
60 | 79 | open_file_via_transport, | 75 | open_file_via_transport, |
61 | 80 | open_transport, | 76 | open_transport, |
62 | 81 | safe_decode, | 77 | safe_decode, |
63 | 82 | subprocess_setup, | 78 | subprocess_setup, |
64 | 83 | ) | 79 | ) |
65 | 84 | from bzrlib.plugins.builddeb.upstream import ( | ||
66 | 85 | PristineTarSource, | ||
67 | 86 | ) | ||
68 | 87 | from bzrlib.plugins.builddeb.upstream.branch import ( | 80 | from bzrlib.plugins.builddeb.upstream.branch import ( |
69 | 88 | UpstreamBranchSource, | 81 | UpstreamBranchSource, |
70 | 89 | ) | 82 | ) |
71 | 83 | from bzrlib.plugins.builddeb.upstream.pristinetar import ( | ||
72 | 84 | PristineTarSource, | ||
73 | 85 | ) | ||
74 | 90 | 86 | ||
75 | 91 | 87 | ||
76 | 92 | class DscCache(object): | 88 | class DscCache(object): |
77 | @@ -912,16 +908,12 @@ | |||
78 | 912 | self.upstream_tree.set_parent_ids(upstream_parents) | 908 | self.upstream_tree.set_parent_ids(upstream_parents) |
79 | 913 | revprops = {"deb-md5": md5} | 909 | revprops = {"deb-md5": md5} |
80 | 914 | if upstream_tarball is not None: | 910 | if upstream_tarball is not None: |
82 | 915 | delta = self.make_pristine_tar_delta( | 911 | delta_revprops = self.pristine_tar_source.create_delta_revprops( |
83 | 916 | self.upstream_tree, upstream_tarball) | 912 | self.upstream_tree, upstream_tarball) |
89 | 917 | uuencoded = standard_b64encode(delta) | 913 | revprops.update(delta_revprops) |
85 | 918 | if upstream_tarball.endswith(".tar.bz2"): | ||
86 | 919 | revprops["deb-pristine-delta-bz2"] = uuencoded | ||
87 | 920 | else: | ||
88 | 921 | revprops["deb-pristine-delta"] = uuencoded | ||
90 | 922 | if author is not None: | 914 | if author is not None: |
91 | 923 | revprops['authors'] = author | 915 | revprops['authors'] = author |
93 | 924 | timezone=None | 916 | timezone = None |
94 | 925 | if timestamp is not None: | 917 | if timestamp is not None: |
95 | 926 | timezone = timestamp[1] | 918 | timezone = timestamp[1] |
96 | 927 | timestamp = timestamp[0] | 919 | timestamp = timestamp[0] |
97 | @@ -1075,7 +1067,7 @@ | |||
98 | 1075 | if message is None: | 1067 | if message is None: |
99 | 1076 | message = 'Import packaging changes for version %s' % \ | 1068 | message = 'Import packaging changes for version %s' % \ |
100 | 1077 | (str(version),) | 1069 | (str(version),) |
102 | 1078 | revprops={"deb-md5":md5} | 1070 | revprops={"deb-md5": md5} |
103 | 1079 | if native: | 1071 | if native: |
104 | 1080 | revprops['deb-native'] = "True" | 1072 | revprops['deb-native'] = "True" |
105 | 1081 | if authors: | 1073 | if authors: |
106 | @@ -1470,21 +1462,6 @@ | |||
107 | 1470 | finally: | 1462 | finally: |
108 | 1471 | shutil.rmtree(tempdir) | 1463 | shutil.rmtree(tempdir) |
109 | 1472 | 1464 | ||
110 | 1473 | def make_pristine_tar_delta(self, tree, tarball_path): | ||
111 | 1474 | tmpdir = tempfile.mkdtemp(prefix="builddeb-pristine-") | ||
112 | 1475 | try: | ||
113 | 1476 | dest = os.path.join(tmpdir, "orig") | ||
114 | 1477 | tree.lock_read() | ||
115 | 1478 | try: | ||
116 | 1479 | for (dp, ie) in tree.inventory.iter_entries(): | ||
117 | 1480 | ie._read_tree_state(dp, tree) | ||
118 | 1481 | export(tree, dest, format='dir') | ||
119 | 1482 | finally: | ||
120 | 1483 | tree.unlock() | ||
121 | 1484 | return make_pristine_tar_delta(dest, tarball_path) | ||
122 | 1485 | finally: | ||
123 | 1486 | shutil.rmtree(tmpdir) | ||
124 | 1487 | |||
125 | 1488 | 1465 | ||
126 | 1489 | class SourceExtractor(object): | 1466 | class SourceExtractor(object): |
127 | 1490 | """A class to extract a source package to its constituent parts""" | 1467 | """A class to extract a source package to its constituent parts""" |
128 | 1491 | 1468 | ||
129 | === modified file 'tests/test_upstream.py' | |||
130 | --- tests/test_upstream.py 2011-04-29 12:34:12 +0000 | |||
131 | +++ tests/test_upstream.py 2011-06-03 13:28:25 +0000 | |||
132 | @@ -48,13 +48,11 @@ | |||
133 | 48 | ) | 48 | ) |
134 | 49 | from bzrlib.plugins.builddeb.upstream import ( | 49 | from bzrlib.plugins.builddeb.upstream import ( |
135 | 50 | AptSource, | 50 | AptSource, |
136 | 51 | PristineTarSource, | ||
137 | 52 | StackedUpstreamSource, | 51 | StackedUpstreamSource, |
138 | 53 | TarfileSource, | 52 | TarfileSource, |
139 | 54 | UpstreamProvider, | 53 | UpstreamProvider, |
140 | 55 | UpstreamSource, | 54 | UpstreamSource, |
141 | 56 | UScanSource, | 55 | UScanSource, |
142 | 57 | Version, | ||
143 | 58 | extract_tarball_version, | 56 | extract_tarball_version, |
144 | 59 | ) | 57 | ) |
145 | 60 | from bzrlib.plugins.builddeb.upstream.branch import ( | 58 | from bzrlib.plugins.builddeb.upstream.branch import ( |
146 | @@ -66,6 +64,9 @@ | |||
147 | 66 | upstream_tag_to_version, | 64 | upstream_tag_to_version, |
148 | 67 | upstream_version_add_revision | 65 | upstream_version_add_revision |
149 | 68 | ) | 66 | ) |
150 | 67 | from bzrlib.plugins.builddeb.upstream.pristinetar import ( | ||
151 | 68 | PristineTarSource, | ||
152 | 69 | ) | ||
153 | 69 | 70 | ||
154 | 70 | 71 | ||
155 | 71 | # Unless bug #712474 is fixed and available in the minimum bzrlib required, we | 72 | # Unless bug #712474 is fixed and available in the minimum bzrlib required, we |
156 | 72 | 73 | ||
157 | === modified file 'upstream/__init__.py' | |||
158 | --- upstream/__init__.py 2011-04-29 12:34:12 +0000 | |||
159 | +++ upstream/__init__.py 2011-06-03 13:28:25 +0000 | |||
160 | @@ -25,21 +25,12 @@ | |||
161 | 25 | import tarfile | 25 | import tarfile |
162 | 26 | import tempfile | 26 | import tempfile |
163 | 27 | 27 | ||
164 | 28 | from base64 import ( | ||
165 | 29 | standard_b64decode, | ||
166 | 30 | ) | ||
167 | 31 | |||
168 | 32 | |||
169 | 33 | try: | 28 | try: |
170 | 34 | from debian.changelog import Version | 29 | from debian.changelog import Version |
171 | 35 | except ImportError: | 30 | except ImportError: |
172 | 36 | # Prior to 0.1.15 the debian module was called debian_bundle | 31 | # Prior to 0.1.15 the debian module was called debian_bundle |
173 | 37 | from debian_bundle.changelog import Version | 32 | from debian_bundle.changelog import Version |
174 | 38 | 33 | ||
175 | 39 | from bzrlib.errors import ( | ||
176 | 40 | NoSuchRevision, | ||
177 | 41 | NoSuchTag, | ||
178 | 42 | ) | ||
179 | 43 | from bzrlib.trace import ( | 34 | from bzrlib.trace import ( |
180 | 44 | note, | 35 | note, |
181 | 45 | warning, | 36 | warning, |
182 | @@ -48,14 +39,11 @@ | |||
183 | 48 | from bzrlib.plugins.builddeb.errors import ( | 39 | from bzrlib.plugins.builddeb.errors import ( |
184 | 49 | MissingUpstreamTarball, | 40 | MissingUpstreamTarball, |
185 | 50 | PackageVersionNotPresent, | 41 | PackageVersionNotPresent, |
186 | 51 | PerFileTimestampsNotSupported, | ||
187 | 52 | PristineTarError, | ||
188 | 53 | WatchFileMissing, | 42 | WatchFileMissing, |
189 | 54 | ) | 43 | ) |
190 | 55 | from bzrlib.plugins.builddeb.repack_tarball import repack_tarball | 44 | from bzrlib.plugins.builddeb.repack_tarball import repack_tarball |
191 | 56 | from bzrlib.plugins.builddeb.util import ( | 45 | from bzrlib.plugins.builddeb.util import ( |
192 | 57 | export, | 46 | export, |
193 | 58 | reconstruct_pristine_tar, | ||
194 | 59 | tarball_name, | 47 | tarball_name, |
195 | 60 | ) | 48 | ) |
196 | 61 | 49 | ||
197 | @@ -106,135 +94,6 @@ | |||
198 | 106 | format=format)) | 94 | format=format)) |
199 | 107 | 95 | ||
200 | 108 | 96 | ||
201 | 109 | class PristineTarSource(UpstreamSource): | ||
202 | 110 | """Source that uses the pristine-tar revisions in the packaging branch.""" | ||
203 | 111 | |||
204 | 112 | def __init__(self, tree, branch): | ||
205 | 113 | self.branch = branch | ||
206 | 114 | self.tree = tree | ||
207 | 115 | |||
208 | 116 | def tag_name(self, version, distro=None): | ||
209 | 117 | """Gets the tag name for the upstream part of version. | ||
210 | 118 | |||
211 | 119 | :param version: the Version object to extract the upstream | ||
212 | 120 | part of the version number from. | ||
213 | 121 | :return: a String with the name of the tag. | ||
214 | 122 | """ | ||
215 | 123 | assert isinstance(version, str) | ||
216 | 124 | if distro is None: | ||
217 | 125 | return "upstream-" + version | ||
218 | 126 | return "upstream-%s-%s" % (distro, version) | ||
219 | 127 | |||
220 | 128 | def fetch_tarball(self, package, version, target_dir): | ||
221 | 129 | revid = self.version_as_revision(package, version) | ||
222 | 130 | try: | ||
223 | 131 | rev = self.branch.repository.get_revision(revid) | ||
224 | 132 | except NoSuchRevision: | ||
225 | 133 | raise PackageVersionNotPresent(package, version, self) | ||
226 | 134 | note("Using pristine-tar to reconstruct the needed tarball.") | ||
227 | 135 | if self.has_pristine_tar_delta(rev): | ||
228 | 136 | format = self.pristine_tar_format(rev) | ||
229 | 137 | else: | ||
230 | 138 | format = 'gz' | ||
231 | 139 | target_filename = self._tarball_path(package, version, | ||
232 | 140 | target_dir, format=format) | ||
233 | 141 | try: | ||
234 | 142 | self.reconstruct_pristine_tar(revid, package, version, target_filename) | ||
235 | 143 | except PristineTarError: | ||
236 | 144 | raise PackageVersionNotPresent(package, version, self) | ||
237 | 145 | except PerFileTimestampsNotSupported: | ||
238 | 146 | raise PackageVersionNotPresent(package, version, self) | ||
239 | 147 | return target_filename | ||
240 | 148 | |||
241 | 149 | def _has_version(self, tag_name, md5=None): | ||
242 | 150 | if not self.branch.tags.has_tag(tag_name): | ||
243 | 151 | return False | ||
244 | 152 | revid = self.branch.tags.lookup_tag(tag_name) | ||
245 | 153 | self.branch.lock_read() | ||
246 | 154 | try: | ||
247 | 155 | graph = self.branch.repository.get_graph() | ||
248 | 156 | if not graph.is_ancestor(revid, self.branch.last_revision()): | ||
249 | 157 | return False | ||
250 | 158 | finally: | ||
251 | 159 | self.branch.unlock() | ||
252 | 160 | if md5 is None: | ||
253 | 161 | return True | ||
254 | 162 | rev = self.branch.repository.get_revision(revid) | ||
255 | 163 | try: | ||
256 | 164 | return rev.properties['deb-md5'] == md5 | ||
257 | 165 | except KeyError: | ||
258 | 166 | warning("tag %s present in branch, but there is no " | ||
259 | 167 | "associated 'deb-md5' property" % tag_name) | ||
260 | 168 | return True | ||
261 | 169 | |||
262 | 170 | def version_as_revision(self, package, version): | ||
263 | 171 | assert isinstance(version, str) | ||
264 | 172 | for tag_name in self.possible_tag_names(version): | ||
265 | 173 | if self._has_version(tag_name): | ||
266 | 174 | return self.branch.tags.lookup_tag(tag_name) | ||
267 | 175 | tag_name = self.tag_name(version) | ||
268 | 176 | try: | ||
269 | 177 | return self.branch.tags.lookup_tag(tag_name) | ||
270 | 178 | except NoSuchTag: | ||
271 | 179 | raise PackageVersionNotPresent(package, version, self) | ||
272 | 180 | |||
273 | 181 | def has_version(self, package, version, md5=None): | ||
274 | 182 | assert isinstance(version, str), str(type(version)) | ||
275 | 183 | for tag_name in self.possible_tag_names(version): | ||
276 | 184 | if self._has_version(tag_name, md5=md5): | ||
277 | 185 | return True | ||
278 | 186 | return False | ||
279 | 187 | |||
280 | 188 | def possible_tag_names(self, version): | ||
281 | 189 | assert isinstance(version, str) | ||
282 | 190 | tags = [self.tag_name(version), | ||
283 | 191 | self.tag_name(version, distro="debian"), | ||
284 | 192 | self.tag_name(version, distro="ubuntu"), | ||
285 | 193 | "upstream/%s" % version] | ||
286 | 194 | return tags | ||
287 | 195 | |||
288 | 196 | def has_pristine_tar_delta(self, rev): | ||
289 | 197 | return ('deb-pristine-delta' in rev.properties | ||
290 | 198 | or 'deb-pristine-delta-bz2' in rev.properties) | ||
291 | 199 | |||
292 | 200 | def pristine_tar_format(self, rev): | ||
293 | 201 | if 'deb-pristine-delta' in rev.properties: | ||
294 | 202 | return 'gz' | ||
295 | 203 | elif 'deb-pristine-delta-bz2' in rev.properties: | ||
296 | 204 | return 'bz2' | ||
297 | 205 | assert self.has_pristine_tar_delta(rev) | ||
298 | 206 | raise AssertionError("Not handled new delta type in " | ||
299 | 207 | "pristine_tar_format") | ||
300 | 208 | |||
301 | 209 | def pristine_tar_delta(self, rev): | ||
302 | 210 | if 'deb-pristine-delta' in rev.properties: | ||
303 | 211 | uuencoded = rev.properties['deb-pristine-delta'] | ||
304 | 212 | elif 'deb-pristine-delta-bz2' in rev.properties: | ||
305 | 213 | uuencoded = rev.properties['deb-pristine-delta-bz2'] | ||
306 | 214 | else: | ||
307 | 215 | assert self.has_pristine_tar_delta(rev) | ||
308 | 216 | raise AssertionError("Not handled new delta type in " | ||
309 | 217 | "pristine_tar_delta") | ||
310 | 218 | return standard_b64decode(uuencoded) | ||
311 | 219 | |||
312 | 220 | def reconstruct_pristine_tar(self, revid, package, version, | ||
313 | 221 | dest_filename): | ||
314 | 222 | """Reconstruct a pristine-tar tarball from a bzr revision.""" | ||
315 | 223 | tree = self.branch.repository.revision_tree(revid) | ||
316 | 224 | tmpdir = tempfile.mkdtemp(prefix="builddeb-pristine-") | ||
317 | 225 | try: | ||
318 | 226 | dest = os.path.join(tmpdir, "orig") | ||
319 | 227 | rev = self.branch.repository.get_revision(revid) | ||
320 | 228 | if self.has_pristine_tar_delta(rev): | ||
321 | 229 | export(tree, dest, format='dir') | ||
322 | 230 | delta = self.pristine_tar_delta(rev) | ||
323 | 231 | reconstruct_pristine_tar(dest, delta, dest_filename) | ||
324 | 232 | else: | ||
325 | 233 | export(tree, dest_filename, require_per_file_timestamps=True) | ||
326 | 234 | finally: | ||
327 | 235 | shutil.rmtree(tmpdir) | ||
328 | 236 | |||
329 | 237 | |||
330 | 238 | class AptSource(UpstreamSource): | 97 | class AptSource(UpstreamSource): |
331 | 239 | """Upstream source that uses apt-source.""" | 98 | """Upstream source that uses apt-source.""" |
332 | 240 | 99 | ||
333 | 241 | 100 | ||
334 | === added file 'upstream/pristinetar.py' | |||
335 | --- upstream/pristinetar.py 1970-01-01 00:00:00 +0000 | |||
336 | +++ upstream/pristinetar.py 2011-06-03 13:28:25 +0000 | |||
337 | @@ -0,0 +1,267 @@ | |||
338 | 1 | # pristinetar.py -- Providers of upstream source | ||
339 | 2 | # Copyright (C) 2009-2011 Canonical Ltd. | ||
340 | 3 | # Copyright (C) 2009 Jelmer Vernooij <jelmer@debian.org> | ||
341 | 4 | # | ||
342 | 5 | # This file is part of bzr-builddeb. | ||
343 | 6 | # | ||
344 | 7 | # bzr-builddeb is free software; you can redistribute it and/or modify | ||
345 | 8 | # it under the terms of the GNU General Public License as published by | ||
346 | 9 | # the Free Software Foundation; either version 2 of the License, or | ||
347 | 10 | # (at your option) any later version. | ||
348 | 11 | # | ||
349 | 12 | # bzr-builddeb is distributed in the hope that it will be useful, | ||
350 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
351 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
352 | 15 | # GNU General Public License for more details. | ||
353 | 16 | # | ||
354 | 17 | # You should have received a copy of the GNU General Public License | ||
355 | 18 | # along with bzr-builddeb; if not, write to the Free Software | ||
356 | 19 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
357 | 20 | |||
358 | 21 | from base64 import ( | ||
359 | 22 | standard_b64decode, | ||
360 | 23 | standard_b64encode, | ||
361 | 24 | ) | ||
362 | 25 | import errno | ||
363 | 26 | import os | ||
364 | 27 | import shutil | ||
365 | 28 | import subprocess | ||
366 | 29 | import tempfile | ||
367 | 30 | |||
368 | 31 | from bzrlib.plugins.builddeb.errors import ( | ||
369 | 32 | PackageVersionNotPresent, | ||
370 | 33 | PerFileTimestampsNotSupported, | ||
371 | 34 | ) | ||
372 | 35 | from bzrlib.plugins.builddeb.upstream import UpstreamSource | ||
373 | 36 | from bzrlib.plugins.builddeb.util import ( | ||
374 | 37 | export, | ||
375 | 38 | subprocess_setup, | ||
376 | 39 | ) | ||
377 | 40 | |||
378 | 41 | from bzrlib import osutils | ||
379 | 42 | from bzrlib.errors import ( | ||
380 | 43 | BzrError, | ||
381 | 44 | NoSuchRevision, | ||
382 | 45 | NoSuchTag, | ||
383 | 46 | ) | ||
384 | 47 | from bzrlib.trace import ( | ||
385 | 48 | note, | ||
386 | 49 | warning, | ||
387 | 50 | ) | ||
388 | 51 | |||
389 | 52 | |||
390 | 53 | class PristineTarError(BzrError): | ||
391 | 54 | _fmt = 'There was an error using pristine-tar: %(error)s.' | ||
392 | 55 | |||
393 | 56 | def __init__(self, error): | ||
394 | 57 | BzrError.__init__(self, error=error) | ||
395 | 58 | |||
396 | 59 | |||
397 | 60 | def reconstruct_pristine_tar(dest, delta, dest_filename): | ||
398 | 61 | """Reconstruct a pristine tarball from a directory and a delta. | ||
399 | 62 | |||
400 | 63 | :param dest: Directory to pack | ||
401 | 64 | :param delta: pristine-tar delta | ||
402 | 65 | :param dest_filename: Destination filename | ||
403 | 66 | """ | ||
404 | 67 | command = ["pristine-tar", "gentar", "-", | ||
405 | 68 | os.path.abspath(dest_filename)] | ||
406 | 69 | try: | ||
407 | 70 | proc = subprocess.Popen(command, stdin=subprocess.PIPE, | ||
408 | 71 | cwd=dest, preexec_fn=subprocess_setup, | ||
409 | 72 | stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | ||
410 | 73 | except OSError, e: | ||
411 | 74 | if e.errno == errno.ENOENT: | ||
412 | 75 | raise PristineTarError("pristine-tar is not installed") | ||
413 | 76 | else: | ||
414 | 77 | raise | ||
415 | 78 | (stdout, stderr) = proc.communicate(delta) | ||
416 | 79 | if proc.returncode != 0: | ||
417 | 80 | raise PristineTarError("Generating tar from delta failed: %s" % stdout) | ||
418 | 81 | |||
419 | 82 | |||
420 | 83 | def make_pristine_tar_delta(dest, tarball_path): | ||
421 | 84 | """Create a pristine-tar delta for a tarball. | ||
422 | 85 | |||
423 | 86 | :param dest: Directory to generate pristine tar delta for | ||
424 | 87 | :param tarball_path: Path to the tarball | ||
425 | 88 | :return: pristine-tarball | ||
426 | 89 | """ | ||
427 | 90 | # If tarball_path is relative, the cwd=dest parameter to Popen will make | ||
428 | 91 | # pristine-tar faaaail. pristine-tar doesn't use the VFS either, so we | ||
429 | 92 | # assume local paths. | ||
430 | 93 | tarball_path = osutils.abspath(tarball_path) | ||
431 | 94 | command = ["pristine-tar", "gendelta", tarball_path, "-"] | ||
432 | 95 | try: | ||
433 | 96 | proc = subprocess.Popen(command, stdout=subprocess.PIPE, | ||
434 | 97 | cwd=dest, preexec_fn=subprocess_setup, | ||
435 | 98 | stderr=subprocess.PIPE) | ||
436 | 99 | except OSError, e: | ||
437 | 100 | if e.errno == errno.ENOENT: | ||
438 | 101 | raise PristineTarError("pristine-tar is not installed") | ||
439 | 102 | else: | ||
440 | 103 | raise | ||
441 | 104 | (stdout, stderr) = proc.communicate() | ||
442 | 105 | if proc.returncode != 0: | ||
443 | 106 | raise PristineTarError("Generating delta from tar failed: %s" % stderr) | ||
444 | 107 | return stdout | ||
445 | 108 | |||
446 | 109 | |||
447 | 110 | class PristineTarSource(UpstreamSource): | ||
448 | 111 | """Source that uses the pristine-tar revisions in the packaging branch.""" | ||
449 | 112 | |||
450 | 113 | def __init__(self, tree, branch): | ||
451 | 114 | self.branch = branch | ||
452 | 115 | self.tree = tree | ||
453 | 116 | |||
454 | 117 | def tag_name(self, version, distro=None): | ||
455 | 118 | """Gets the tag name for the upstream part of version. | ||
456 | 119 | |||
457 | 120 | :param version: the Version object to extract the upstream | ||
458 | 121 | part of the version number from. | ||
459 | 122 | :return: a String with the name of the tag. | ||
460 | 123 | """ | ||
461 | 124 | assert isinstance(version, str) | ||
462 | 125 | if distro is None: | ||
463 | 126 | return "upstream-" + version | ||
464 | 127 | return "upstream-%s-%s" % (distro, version) | ||
465 | 128 | |||
466 | 129 | def fetch_tarball(self, package, version, target_dir): | ||
467 | 130 | revid = self.version_as_revision(package, version) | ||
468 | 131 | try: | ||
469 | 132 | rev = self.branch.repository.get_revision(revid) | ||
470 | 133 | except NoSuchRevision: | ||
471 | 134 | raise PackageVersionNotPresent(package, version, self) | ||
472 | 135 | note("Using pristine-tar to reconstruct the needed tarball.") | ||
473 | 136 | if self.has_pristine_tar_delta(rev): | ||
474 | 137 | format = self.pristine_tar_format(rev) | ||
475 | 138 | else: | ||
476 | 139 | format = 'gz' | ||
477 | 140 | target_filename = self._tarball_path(package, version, | ||
478 | 141 | target_dir, format=format) | ||
479 | 142 | try: | ||
480 | 143 | self.reconstruct_pristine_tar(revid, package, version, target_filename) | ||
481 | 144 | except PristineTarError: | ||
482 | 145 | raise PackageVersionNotPresent(package, version, self) | ||
483 | 146 | except PerFileTimestampsNotSupported: | ||
484 | 147 | raise PackageVersionNotPresent(package, version, self) | ||
485 | 148 | return target_filename | ||
486 | 149 | |||
487 | 150 | def _has_version(self, tag_name, md5=None): | ||
488 | 151 | if not self.branch.tags.has_tag(tag_name): | ||
489 | 152 | return False | ||
490 | 153 | revid = self.branch.tags.lookup_tag(tag_name) | ||
491 | 154 | self.branch.lock_read() | ||
492 | 155 | try: | ||
493 | 156 | graph = self.branch.repository.get_graph() | ||
494 | 157 | if not graph.is_ancestor(revid, self.branch.last_revision()): | ||
495 | 158 | return False | ||
496 | 159 | finally: | ||
497 | 160 | self.branch.unlock() | ||
498 | 161 | if md5 is None: | ||
499 | 162 | return True | ||
500 | 163 | rev = self.branch.repository.get_revision(revid) | ||
501 | 164 | try: | ||
502 | 165 | return rev.properties['deb-md5'] == md5 | ||
503 | 166 | except KeyError: | ||
504 | 167 | warning("tag %s present in branch, but there is no " | ||
505 | 168 | "associated 'deb-md5' property" % tag_name) | ||
506 | 169 | return True | ||
507 | 170 | |||
508 | 171 | def version_as_revision(self, package, version): | ||
509 | 172 | assert isinstance(version, str) | ||
510 | 173 | for tag_name in self.possible_tag_names(version): | ||
511 | 174 | if self._has_version(tag_name): | ||
512 | 175 | return self.branch.tags.lookup_tag(tag_name) | ||
513 | 176 | tag_name = self.tag_name(version) | ||
514 | 177 | try: | ||
515 | 178 | return self.branch.tags.lookup_tag(tag_name) | ||
516 | 179 | except NoSuchTag: | ||
517 | 180 | raise PackageVersionNotPresent(package, version, self) | ||
518 | 181 | |||
519 | 182 | def has_version(self, package, version, md5=None): | ||
520 | 183 | assert isinstance(version, str), str(type(version)) | ||
521 | 184 | for tag_name in self.possible_tag_names(version): | ||
522 | 185 | if self._has_version(tag_name, md5=md5): | ||
523 | 186 | return True | ||
524 | 187 | return False | ||
525 | 188 | |||
526 | 189 | def possible_tag_names(self, version): | ||
527 | 190 | assert isinstance(version, str) | ||
528 | 191 | tags = [self.tag_name(version), | ||
529 | 192 | self.tag_name(version, distro="debian"), | ||
530 | 193 | self.tag_name(version, distro="ubuntu"), | ||
531 | 194 | "upstream/%s" % version] | ||
532 | 195 | return tags | ||
533 | 196 | |||
534 | 197 | def has_pristine_tar_delta(self, rev): | ||
535 | 198 | return ('deb-pristine-delta' in rev.properties | ||
536 | 199 | or 'deb-pristine-delta-bz2' in rev.properties) | ||
537 | 200 | |||
538 | 201 | def pristine_tar_format(self, rev): | ||
539 | 202 | if 'deb-pristine-delta' in rev.properties: | ||
540 | 203 | return 'gz' | ||
541 | 204 | elif 'deb-pristine-delta-bz2' in rev.properties: | ||
542 | 205 | return 'bz2' | ||
543 | 206 | assert self.has_pristine_tar_delta(rev) | ||
544 | 207 | raise AssertionError("Not handled new delta type in " | ||
545 | 208 | "pristine_tar_format") | ||
546 | 209 | |||
547 | 210 | def pristine_tar_delta(self, rev): | ||
548 | 211 | if 'deb-pristine-delta' in rev.properties: | ||
549 | 212 | uuencoded = rev.properties['deb-pristine-delta'] | ||
550 | 213 | elif 'deb-pristine-delta-bz2' in rev.properties: | ||
551 | 214 | uuencoded = rev.properties['deb-pristine-delta-bz2'] | ||
552 | 215 | else: | ||
553 | 216 | assert self.has_pristine_tar_delta(rev) | ||
554 | 217 | raise AssertionError("Not handled new delta type in " | ||
555 | 218 | "pristine_tar_delta") | ||
556 | 219 | return standard_b64decode(uuencoded) | ||
557 | 220 | |||
558 | 221 | def reconstruct_pristine_tar(self, revid, package, version, | ||
559 | 222 | dest_filename): | ||
560 | 223 | """Reconstruct a pristine-tar tarball from a bzr revision.""" | ||
561 | 224 | tree = self.branch.repository.revision_tree(revid) | ||
562 | 225 | tmpdir = tempfile.mkdtemp(prefix="builddeb-pristine-") | ||
563 | 226 | try: | ||
564 | 227 | dest = os.path.join(tmpdir, "orig") | ||
565 | 228 | rev = self.branch.repository.get_revision(revid) | ||
566 | 229 | if self.has_pristine_tar_delta(rev): | ||
567 | 230 | export(tree, dest, format='dir') | ||
568 | 231 | delta = self.pristine_tar_delta(rev) | ||
569 | 232 | reconstruct_pristine_tar(dest, delta, dest_filename) | ||
570 | 233 | else: | ||
571 | 234 | export(tree, dest_filename, require_per_file_timestamps=True) | ||
572 | 235 | finally: | ||
573 | 236 | shutil.rmtree(tmpdir) | ||
574 | 237 | |||
575 | 238 | def make_pristine_tar_delta(self, tree, tarball_path): | ||
576 | 239 | tmpdir = tempfile.mkdtemp(prefix="builddeb-pristine-") | ||
577 | 240 | try: | ||
578 | 241 | dest = os.path.join(tmpdir, "orig") | ||
579 | 242 | tree.lock_read() | ||
580 | 243 | try: | ||
581 | 244 | for (dp, ie) in tree.inventory.iter_entries(): | ||
582 | 245 | ie._read_tree_state(dp, tree) | ||
583 | 246 | export(tree, dest, format='dir') | ||
584 | 247 | finally: | ||
585 | 248 | tree.unlock() | ||
586 | 249 | return make_pristine_tar_delta(dest, tarball_path) | ||
587 | 250 | finally: | ||
588 | 251 | shutil.rmtree(tmpdir) | ||
589 | 252 | |||
590 | 253 | def create_delta_revprops(self, tree, tarball): | ||
591 | 254 | """Create the revision properties with the pristine tar delta. | ||
592 | 255 | |||
593 | 256 | :param tree: Bazaar Tree to diff against | ||
594 | 257 | :param tarball: The pristine tarball | ||
595 | 258 | :return: Dictionary with extra revision properties | ||
596 | 259 | """ | ||
597 | 260 | ret = {} | ||
598 | 261 | delta = self.make_pristine_tar_delta(tree, tarball) | ||
599 | 262 | uuencoded = standard_b64encode(delta) | ||
600 | 263 | if tarball.endswith(".tar.bz2"): | ||
601 | 264 | ret["deb-pristine-delta-bz2"] = uuencoded | ||
602 | 265 | else: | ||
603 | 266 | ret["deb-pristine-delta"] = uuencoded | ||
604 | 267 | return ret | ||
605 | 0 | 268 | ||
606 | === modified file 'util.py' | |||
607 | --- util.py 2011-04-08 18:47:10 +0000 | |||
608 | +++ util.py 2011-06-03 13:28:25 +0000 | |||
609 | @@ -22,10 +22,8 @@ | |||
610 | 22 | import hashlib as md5 | 22 | import hashlib as md5 |
611 | 23 | except ImportError: | 23 | except ImportError: |
612 | 24 | import md5 | 24 | import md5 |
613 | 25 | import errno | ||
614 | 26 | import signal | 25 | import signal |
615 | 27 | import shutil | 26 | import shutil |
616 | 28 | import subprocess | ||
617 | 29 | import tempfile | 27 | import tempfile |
618 | 30 | import os | 28 | import os |
619 | 31 | import re | 29 | import re |
620 | @@ -43,7 +41,6 @@ | |||
621 | 43 | from bzrlib import ( | 41 | from bzrlib import ( |
622 | 44 | bugtracker, | 42 | bugtracker, |
623 | 45 | errors, | 43 | errors, |
624 | 46 | osutils, | ||
625 | 47 | urlutils, | 44 | urlutils, |
626 | 48 | version_info as bzr_version_info, | 45 | version_info as bzr_version_info, |
627 | 49 | ) | 46 | ) |
628 | @@ -69,7 +66,6 @@ | |||
629 | 69 | AddChangelogError, | 66 | AddChangelogError, |
630 | 70 | InconsistentSourceFormatError, | 67 | InconsistentSourceFormatError, |
631 | 71 | NoPreviousUpload, | 68 | NoPreviousUpload, |
632 | 72 | PristineTarError, | ||
633 | 73 | UnableToFindPreviousUpload, | 69 | UnableToFindPreviousUpload, |
634 | 74 | UnparseableChangelog, | 70 | UnparseableChangelog, |
635 | 75 | ) | 71 | ) |
636 | @@ -686,51 +682,4 @@ | |||
637 | 686 | return BUILD_TYPE_NORMAL | 682 | return BUILD_TYPE_NORMAL |
638 | 687 | 683 | ||
639 | 688 | 684 | ||
688 | 689 | def reconstruct_pristine_tar(dest, delta, dest_filename): | 685 | |
641 | 690 | """Reconstruct a pristine tarball from a directory and a delta. | ||
642 | 691 | |||
643 | 692 | :param dest: Directory to pack | ||
644 | 693 | :param delta: pristine-tar delta | ||
645 | 694 | :param dest_filename: Destination filename | ||
646 | 695 | """ | ||
647 | 696 | command = ["pristine-tar", "gentar", "-", | ||
648 | 697 | os.path.abspath(dest_filename)] | ||
649 | 698 | try: | ||
650 | 699 | proc = subprocess.Popen(command, stdin=subprocess.PIPE, | ||
651 | 700 | cwd=dest, preexec_fn=subprocess_setup, | ||
652 | 701 | stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | ||
653 | 702 | except OSError, e: | ||
654 | 703 | if e.errno == errno.ENOENT: | ||
655 | 704 | raise PristineTarError("pristine-tar is not installed") | ||
656 | 705 | else: | ||
657 | 706 | raise | ||
658 | 707 | (stdout, stderr) = proc.communicate(delta) | ||
659 | 708 | if proc.returncode != 0: | ||
660 | 709 | raise PristineTarError("Generating tar from delta failed: %s" % stdout) | ||
661 | 710 | |||
662 | 711 | |||
663 | 712 | def make_pristine_tar_delta(dest, tarball_path): | ||
664 | 713 | """Create a pristine-tar delta for a tarball. | ||
665 | 714 | |||
666 | 715 | :param dest: Directory to generate pristine tar delta for | ||
667 | 716 | :param tarball_path: Path to the tarball | ||
668 | 717 | :return: pristine-tarball | ||
669 | 718 | """ | ||
670 | 719 | # If tarball_path is relative, the cwd=dest parameter to Popen will make | ||
671 | 720 | # pristine-tar faaaail. pristine-tar doesn't use the VFS either, so we | ||
672 | 721 | # assume local paths. | ||
673 | 722 | tarball_path = osutils.abspath(tarball_path) | ||
674 | 723 | command = ["pristine-tar", "gendelta", tarball_path, "-"] | ||
675 | 724 | try: | ||
676 | 725 | proc = subprocess.Popen(command, stdout=subprocess.PIPE, | ||
677 | 726 | cwd=dest, preexec_fn=subprocess_setup, | ||
678 | 727 | stderr=subprocess.PIPE) | ||
679 | 728 | except OSError, e: | ||
680 | 729 | if e.errno == errno.ENOENT: | ||
681 | 730 | raise PristineTarError("pristine-tar is not installed") | ||
682 | 731 | else: | ||
683 | 732 | raise | ||
684 | 733 | (stdout, stderr) = proc.communicate() | ||
685 | 734 | if proc.returncode != 0: | ||
686 | 735 | raise PristineTarError("Generating delta from tar failed: %s" % stderr) | ||
687 | 736 | return stdout |