Merge lp:~logan/ubuntu/quantal/bzr-builder/0.7.3 into lp:ubuntu/quantal/bzr-builder
- Quantal (12.10)
- 0.7.3
- Merge into quantal
Proposed by
Logan Rosen
Status: | Merged |
---|---|
Merged at revision: | 13 |
Proposed branch: | lp:~logan/ubuntu/quantal/bzr-builder/0.7.3 |
Merge into: | lp:ubuntu/quantal/bzr-builder |
Diff against target: |
2786 lines (+1341/-1005) 14 files modified
__init__.py (+36/-13) cmds.py (+123/-427) deb_util.py (+379/-0) deb_version.py (+214/-0) debian/changelog (+6/-0) info.py (+17/-0) recipe.py (+52/-160) setup.py (+6/-1) tests/__init__.py (+2/-1) tests/test_blackbox.py (+9/-9) tests/test_deb_util.py (+28/-0) tests/test_deb_version.py (+441/-0) tests/test_ppa.py (+0/-28) tests/test_recipe.py (+28/-366) |
To merge this branch: | bzr merge lp:~logan/ubuntu/quantal/bzr-builder/0.7.3 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Holbach (community) | Approve | ||
Ubuntu branches | Pending | ||
Review via email: mp+109506@code.launchpad.net |
Commit message
Description of the change
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 | === modified file '__init__.py' | |||
2 | --- __init__.py 2011-07-21 13:30:56 +0000 | |||
3 | +++ __init__.py 2012-06-10 06:51:21 +0000 | |||
4 | @@ -123,10 +123,31 @@ | |||
5 | 123 | * {revno} will be the revno of the base branch (the first specified). | 123 | * {revno} will be the revno of the base branch (the first specified). |
6 | 124 | * {revno:<branch name>} will be substituted with the revno for the | 124 | * {revno:<branch name>} will be substituted with the revno for the |
7 | 125 | branch named <branch name> in the recipe. | 125 | branch named <branch name> in the recipe. |
12 | 126 | * {debupstream} will be replaced by the upstream portion of the version | 126 | * {debupstream}/{debupstream:<branch name>} will be replaced by the upstream |
13 | 127 | number taken from debian/changelog in the final tree. If when the | 127 | portion of the version number taken from debian/changelog in the branch. |
14 | 128 | tree is built the top of debian/changelog has a version number of | 128 | For example, if debian/changelog has a version number of "1.0-1" then this |
15 | 129 | "1.0-1" then this would evaluate to "1.0". | 129 | would evaluate to "1.0". |
16 | 130 | * {debupstream-base}/{debupstream-base:<branch name>} will be replaced by the | ||
17 | 131 | upstream portion of the version number taken from debian/changelog in the | ||
18 | 132 | branch, with any VCS markers stripped. For example, if debian/changelog | ||
19 | 133 | has a version number of "1.0~bzr43-1" then this would evaluate to "1.0~". | ||
20 | 134 | For any upstream versions without a VCS marker, a "+" is added to the | ||
21 | 135 | version ("1.0-1" becomes "1.0+"). | ||
22 | 136 | * {debversion}/{debversion:<branch name>} will be substituted with | ||
23 | 137 | the exact version string from debian/changelog in the branch. | ||
24 | 138 | * {revtime}/{revtime:<branch name>} will be substituted with the date and | ||
25 | 139 | time of the revision that was built, such as 201108191512. | ||
26 | 140 | * {revdate}/{revdate:<branch name>} will be substituted with the date | ||
27 | 141 | of the revision that was built, such as 20111222. | ||
28 | 142 | * {latest-tag}/{latest-tag:<branch name>} will be replaced with the | ||
29 | 143 | name of the tag found on the most recent revision in the | ||
30 | 144 | branch mainline that has a tag. | ||
31 | 145 | * {git-commit}/{git-commit:<branch name>} will be substituted with the last 7 | ||
32 | 146 | characters of the SHA1 checksum of the revision that was built, if the | ||
33 | 147 | revision was imported from a Git repository. | ||
34 | 148 | * {svn-revno}/{svn-revno:<branch name>} will be substituted with the | ||
35 | 149 | Subversion revision number of the revision that was built, if the | ||
36 | 150 | revision was imported from a Subversion repository. | ||
37 | 130 | 151 | ||
38 | 131 | Instruction syntax summary: | 152 | Instruction syntax summary: |
39 | 132 | 153 | ||
40 | @@ -145,15 +166,17 @@ | |||
41 | 145 | resulting tree | 166 | resulting tree |
42 | 146 | """ | 167 | """ |
43 | 147 | 168 | ||
53 | 148 | if __name__ == '__main__': | 169 | from __future__ import absolute_import |
54 | 149 | import os | 170 | |
55 | 150 | import subprocess | 171 | from bzrlib.plugins.builder.info import ( |
56 | 151 | import sys | 172 | bzr_plugin_version as version_info, |
57 | 152 | dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "plugins") | 173 | ) |
58 | 153 | retcode = subprocess.call("bzr selftest -s bzrlib.plugins.builder", | 174 | |
59 | 154 | shell=True, env={"BZR_PLUGIN_PATH": dir}) | 175 | if version_info[3] == 'final': |
60 | 155 | sys.exit(retcode) | 176 | version_string = '%d.%d.%d' % version_info[:3] |
61 | 156 | 177 | else: | |
62 | 178 | version_string = '%d.%d.%d%s%d' % version_info | ||
63 | 179 | __version__ = version_string | ||
64 | 157 | 180 | ||
65 | 158 | from bzrlib.commands import plugin_cmds | 181 | from bzrlib.commands import plugin_cmds |
66 | 159 | plugin_cmds.register_lazy("cmd_build", [], "bzrlib.plugins.builder.cmds") | 182 | plugin_cmds.register_lazy("cmd_build", [], "bzrlib.plugins.builder.cmds") |
67 | 160 | 183 | ||
68 | === modified file 'cmds.py' | |||
69 | --- cmds.py 2011-11-10 13:29:10 +0000 | |||
70 | +++ cmds.py 2012-06-10 06:51:21 +0000 | |||
71 | @@ -15,60 +15,31 @@ | |||
72 | 15 | 15 | ||
73 | 16 | """Subcommands provided by bzr-builder.""" | 16 | """Subcommands provided by bzr-builder.""" |
74 | 17 | 17 | ||
75 | 18 | from base64 import standard_b64decode | ||
76 | 19 | from StringIO import StringIO | 18 | from StringIO import StringIO |
77 | 20 | import datetime | 19 | import datetime |
78 | 21 | from email import utils | ||
79 | 22 | import errno | ||
80 | 23 | import os | 20 | import os |
81 | 24 | import signal | ||
82 | 25 | import shutil | 21 | import shutil |
83 | 26 | import subprocess | ||
84 | 27 | import tempfile | 22 | import tempfile |
85 | 28 | 23 | ||
86 | 29 | try: | ||
87 | 30 | from debian import changelog, deb822 | ||
88 | 31 | except ImportError: | ||
89 | 32 | # In older versions of python-debian the main package was named | ||
90 | 33 | # debian_bundle | ||
91 | 34 | from debian_bundle import changelog, deb822 | ||
92 | 35 | |||
93 | 36 | try: | ||
94 | 37 | get_maintainer = changelog.get_maintainer | ||
95 | 38 | except AttributeError: | ||
96 | 39 | # Implementation of get_maintainer was added after 0.1.18 so import same | ||
97 | 40 | # function from backports module if python-debian doesn't have it. | ||
98 | 41 | from bzrlib.plugins.builder.backports import get_maintainer | ||
99 | 42 | |||
100 | 43 | from bzrlib import ( | 24 | from bzrlib import ( |
109 | 44 | errors, | 25 | errors, |
110 | 45 | export as _mod_export, | 26 | lazy_regex, |
111 | 46 | lazy_regex, | 27 | trace, |
112 | 47 | osutils, | 28 | transport as _mod_transport, |
113 | 48 | trace, | 29 | urlutils, |
114 | 49 | transport as _mod_transport, | 30 | ) |
107 | 50 | urlutils, | ||
108 | 51 | ) | ||
115 | 52 | from bzrlib.branch import Branch | 31 | from bzrlib.branch import Branch |
116 | 53 | from bzrlib.commands import Command | 32 | from bzrlib.commands import Command |
117 | 54 | from bzrlib.option import Option | 33 | from bzrlib.option import Option |
118 | 55 | 34 | ||
119 | 56 | from bzrlib.plugins.builder.recipe import ( | 35 | from bzrlib.plugins.builder.recipe import ( |
135 | 57 | BaseRecipeBranch, | 36 | BaseRecipeBranch, |
136 | 58 | build_tree, | 37 | build_tree, |
137 | 59 | RecipeParser, | 38 | RecipeParser, |
138 | 60 | resolve_revisions, | 39 | resolve_revisions, |
139 | 61 | SAFE_INSTRUCTIONS, | 40 | SAFE_INSTRUCTIONS, |
140 | 62 | SubstitutionUnavailable, | 41 | ) |
141 | 63 | ) | 42 | |
127 | 64 | |||
128 | 65 | |||
129 | 66 | # The default distribution used by add_autobuild_changelog_entry() | ||
130 | 67 | DEFAULT_UBUNTU_DISTRIBUTION = "lucid" | ||
131 | 68 | |||
132 | 69 | |||
133 | 70 | class MissingDependency(errors.BzrError): | ||
134 | 71 | pass | ||
142 | 72 | 43 | ||
143 | 73 | 44 | ||
144 | 74 | def write_manifest_to_transport(location, base_branch, | 45 | def write_manifest_to_transport(location, base_branch, |
145 | @@ -135,233 +106,6 @@ | |||
146 | 135 | return old_recipe | 106 | return old_recipe |
147 | 136 | 107 | ||
148 | 137 | 108 | ||
149 | 138 | def add_autobuild_changelog_entry(base_branch, basedir, package, | ||
150 | 139 | distribution=None, author_name=None, author_email=None, | ||
151 | 140 | append_version=None): | ||
152 | 141 | """Add a new changelog entry for an autobuild. | ||
153 | 142 | |||
154 | 143 | :param base_branch: Recipe base branch | ||
155 | 144 | :param basedir: Base working directory | ||
156 | 145 | :param package: package name | ||
157 | 146 | :param distribution: Optional distribution (defaults to last entry | ||
158 | 147 | distribution) | ||
159 | 148 | :param author_name: Name of the build requester | ||
160 | 149 | :param author_email: Email of the build requester | ||
161 | 150 | :param append_version: Optional version suffix to add | ||
162 | 151 | """ | ||
163 | 152 | debian_dir = os.path.join(basedir, "debian") | ||
164 | 153 | if not os.path.exists(debian_dir): | ||
165 | 154 | os.makedirs(debian_dir) | ||
166 | 155 | cl_path = os.path.join(debian_dir, "changelog") | ||
167 | 156 | file_found = False | ||
168 | 157 | if os.path.exists(cl_path): | ||
169 | 158 | file_found = True | ||
170 | 159 | cl_f = open(cl_path) | ||
171 | 160 | try: | ||
172 | 161 | contents = cl_f.read() | ||
173 | 162 | finally: | ||
174 | 163 | cl_f.close() | ||
175 | 164 | cl = changelog.Changelog(file=contents) | ||
176 | 165 | else: | ||
177 | 166 | cl = changelog.Changelog() | ||
178 | 167 | if len(cl._blocks) > 0: | ||
179 | 168 | if distribution is None: | ||
180 | 169 | distribution = cl._blocks[0].distributions.split()[0] | ||
181 | 170 | else: | ||
182 | 171 | if file_found: | ||
183 | 172 | if len(contents.strip()) > 0: | ||
184 | 173 | reason = ("debian/changelog didn't contain any " | ||
185 | 174 | "parseable stanzas") | ||
186 | 175 | else: | ||
187 | 176 | reason = "debian/changelog was empty" | ||
188 | 177 | else: | ||
189 | 178 | reason = "debian/changelog was not present" | ||
190 | 179 | if distribution is None: | ||
191 | 180 | distribution = DEFAULT_UBUNTU_DISTRIBUTION | ||
192 | 181 | if base_branch.format in (0.1, 0.2, 0.3): | ||
193 | 182 | try: | ||
194 | 183 | base_branch.substitute_changelog_vars(None, cl) | ||
195 | 184 | except SubstitutionUnavailable, e: | ||
196 | 185 | raise errors.BzrCommandError("No previous changelog to " | ||
197 | 186 | "take the upstream version from as %s was " | ||
198 | 187 | "used: %s: %s." % (e.name, e.reason, reason)) | ||
199 | 188 | # Use debian packaging environment variables | ||
200 | 189 | # or default values if they don't exist | ||
201 | 190 | if author_name is None or author_email is None: | ||
202 | 191 | author_name, author_email = get_maintainer() | ||
203 | 192 | # The python-debian package breaks compatibility at version 0.1.20 by | ||
204 | 193 | # switching to expecting (but not checking for) unicode rather than | ||
205 | 194 | # bytestring inputs. Detect this and decode environment if needed. | ||
206 | 195 | if getattr(changelog.Changelog, "__unicode__", None) is not None: | ||
207 | 196 | enc = osutils.get_user_encoding() | ||
208 | 197 | author_name = author_name.decode(enc) | ||
209 | 198 | author_email = author_email.decode(enc) | ||
210 | 199 | author = "%s <%s>" % (author_name, author_email) | ||
211 | 200 | |||
212 | 201 | date = utils.formatdate(localtime=True) | ||
213 | 202 | version = base_branch.deb_version | ||
214 | 203 | if append_version is not None: | ||
215 | 204 | version += append_version | ||
216 | 205 | try: | ||
217 | 206 | changelog.Version(version) | ||
218 | 207 | except (changelog.VersionError, ValueError), e: | ||
219 | 208 | raise errors.BzrCommandError("Invalid deb-version: %s: %s" | ||
220 | 209 | % (version, e)) | ||
221 | 210 | cl.new_block(package=package, version=version, | ||
222 | 211 | distributions=distribution, urgency="low", | ||
223 | 212 | changes=['', ' * Auto build.', ''], | ||
224 | 213 | author=author, date=date) | ||
225 | 214 | cl_f = open(cl_path, 'wb') | ||
226 | 215 | try: | ||
227 | 216 | cl.write_to_open_file(cl_f) | ||
228 | 217 | finally: | ||
229 | 218 | cl_f.close() | ||
230 | 219 | |||
231 | 220 | |||
232 | 221 | def calculate_package_dir(package_name, package_version, working_basedir): | ||
233 | 222 | """Calculate the directory name that should be used while debuilding. | ||
234 | 223 | |||
235 | 224 | :param base_branch: Recipe base branch | ||
236 | 225 | :param package_version: Version of the package | ||
237 | 226 | :param package_name: Package name | ||
238 | 227 | :param working_basedir: Base directory | ||
239 | 228 | """ | ||
240 | 229 | package_basedir = "%s-%s" % (package_name, package_version.upstream_version) | ||
241 | 230 | package_dir = os.path.join(working_basedir, package_basedir) | ||
242 | 231 | return package_dir | ||
243 | 232 | |||
244 | 233 | |||
245 | 234 | def _run_command(command, basedir, msg, error_msg, | ||
246 | 235 | not_installed_msg=None, env=None, success_exit_codes=None, indata=None): | ||
247 | 236 | """ Run a command in a subprocess. | ||
248 | 237 | |||
249 | 238 | :param command: list with command and parameters | ||
250 | 239 | :param msg: message to display to the user | ||
251 | 240 | :param error_msg: message to display if something fails. | ||
252 | 241 | :param not_installed_msg: the message to display if the command | ||
253 | 242 | isn't available. | ||
254 | 243 | :param env: Optional environment to use rather than os.environ. | ||
255 | 244 | :param success_exit_codes: Exit codes to consider succesfull, defaults to [0]. | ||
256 | 245 | :param indata: Data to write to standard input | ||
257 | 246 | """ | ||
258 | 247 | def subprocess_setup(): | ||
259 | 248 | signal.signal(signal.SIGPIPE, signal.SIG_DFL) | ||
260 | 249 | trace.note(msg) | ||
261 | 250 | # Hide output if -q is in use. | ||
262 | 251 | quiet = trace.is_quiet() | ||
263 | 252 | if quiet: | ||
264 | 253 | kwargs = {"stderr": subprocess.STDOUT, "stdout": subprocess.PIPE} | ||
265 | 254 | else: | ||
266 | 255 | kwargs = {} | ||
267 | 256 | if env is not None: | ||
268 | 257 | kwargs["env"] = env | ||
269 | 258 | trace.mutter("running: %r", command) | ||
270 | 259 | try: | ||
271 | 260 | proc = subprocess.Popen(command, cwd=basedir, | ||
272 | 261 | stdin=subprocess.PIPE, preexec_fn=subprocess_setup, **kwargs) | ||
273 | 262 | except OSError, e: | ||
274 | 263 | if e.errno != errno.ENOENT: | ||
275 | 264 | raise | ||
276 | 265 | if not_installed_msg is None: | ||
277 | 266 | raise | ||
278 | 267 | raise MissingDependency(msg=not_installed_msg) | ||
279 | 268 | output = proc.communicate(indata) | ||
280 | 269 | if success_exit_codes is None: | ||
281 | 270 | success_exit_codes = [0] | ||
282 | 271 | if proc.returncode not in success_exit_codes: | ||
283 | 272 | if quiet: | ||
284 | 273 | raise errors.BzrCommandError("%s: %s" % (error_msg, output)) | ||
285 | 274 | else: | ||
286 | 275 | raise errors.BzrCommandError(error_msg) | ||
287 | 276 | |||
288 | 277 | |||
289 | 278 | def build_source_package(basedir, tgz_check=True): | ||
290 | 279 | command = ["/usr/bin/debuild"] | ||
291 | 280 | if tgz_check: | ||
292 | 281 | command.append("--tgz-check") | ||
293 | 282 | else: | ||
294 | 283 | command.append("--no-tgz-check") | ||
295 | 284 | command.extend(["-i", "-I", "-S", "-uc", "-us"]) | ||
296 | 285 | _run_command(command, basedir, | ||
297 | 286 | "Building the source package", | ||
298 | 287 | "Failed to build the source package", | ||
299 | 288 | not_installed_msg="debuild is not installed, please install " | ||
300 | 289 | "the devscripts package.") | ||
301 | 290 | |||
302 | 291 | |||
303 | 292 | def get_source_format(path): | ||
304 | 293 | """Retrieve the source format name from a package. | ||
305 | 294 | |||
306 | 295 | :param path: Path to the package | ||
307 | 296 | :return: String with package format | ||
308 | 297 | """ | ||
309 | 298 | source_format_path = os.path.join(path, "debian", "source", "format") | ||
310 | 299 | if not os.path.exists(source_format_path): | ||
311 | 300 | return "1.0" | ||
312 | 301 | f = open(source_format_path, 'r') | ||
313 | 302 | try: | ||
314 | 303 | return f.read().strip() | ||
315 | 304 | finally: | ||
316 | 305 | f.close() | ||
317 | 306 | |||
318 | 307 | |||
319 | 308 | def convert_3_0_quilt_to_native(path): | ||
320 | 309 | """Convert a package in 3.0 (quilt) format to 3.0 (native). | ||
321 | 310 | |||
322 | 311 | This applies all patches in the package and updates the | ||
323 | 312 | debian/source/format file. | ||
324 | 313 | |||
325 | 314 | :param path: Path to the package on disk | ||
326 | 315 | """ | ||
327 | 316 | path = os.path.abspath(path) | ||
328 | 317 | patches_dir = os.path.join(path, "debian", "patches") | ||
329 | 318 | series_file = os.path.join(patches_dir, "series") | ||
330 | 319 | if os.path.exists(series_file): | ||
331 | 320 | _run_command(["quilt", "push", "-a", "-v"], path, | ||
332 | 321 | "Applying quilt patches", | ||
333 | 322 | "Failed to apply quilt patches", | ||
334 | 323 | not_installed_msg="quilt is not installed, please install it.", | ||
335 | 324 | env={"QUILT_SERIES": series_file, "QUILT_PATCHES": patches_dir}, | ||
336 | 325 | success_exit_codes=(0, 2)) | ||
337 | 326 | if os.path.exists(patches_dir): | ||
338 | 327 | shutil.rmtree(patches_dir) | ||
339 | 328 | f = open(os.path.join(path, "debian", "source", "format"), 'w') | ||
340 | 329 | try: | ||
341 | 330 | f.write("3.0 (native)\n") | ||
342 | 331 | finally: | ||
343 | 332 | f.close() | ||
344 | 333 | |||
345 | 334 | |||
346 | 335 | def force_native_format(working_tree_path, current_format): | ||
347 | 336 | """Make sure a package is a format that supports native packages. | ||
348 | 337 | |||
349 | 338 | :param working_tree_path: Path to the package | ||
350 | 339 | """ | ||
351 | 340 | if current_format == "3.0 (quilt)": | ||
352 | 341 | convert_3_0_quilt_to_native(working_tree_path) | ||
353 | 342 | elif current_format not in ("1.0", "3.0 (native)"): | ||
354 | 343 | raise errors.BzrCommandError("Unknown source format %s" % | ||
355 | 344 | current_format) | ||
356 | 345 | |||
357 | 346 | |||
358 | 347 | def sign_source_package(basedir, key_id): | ||
359 | 348 | command = ["/usr/bin/debsign", "-S", "-k%s" % key_id] | ||
360 | 349 | _run_command(command, basedir, | ||
361 | 350 | "Signing the source package", | ||
362 | 351 | "Signing the package failed", | ||
363 | 352 | not_installed_msg="debsign is not installed, please install " | ||
364 | 353 | "the devscripts package.") | ||
365 | 354 | |||
366 | 355 | |||
367 | 356 | def dput_source_package(basedir, target): | ||
368 | 357 | command = ["/usr/bin/debrelease", "-S", "--dput", target] | ||
369 | 358 | _run_command(command, basedir, | ||
370 | 359 | "Uploading the source package", | ||
371 | 360 | "Uploading the package failed", | ||
372 | 361 | not_installed_msg="debrelease is not installed, please " | ||
373 | 362 | "install the devscripts package.") | ||
374 | 363 | |||
375 | 364 | |||
376 | 365 | launchpad_recipe_re = lazy_regex.lazy_compile( | 109 | launchpad_recipe_re = lazy_regex.lazy_compile( |
377 | 366 | r'^https://code.launchpad.net/~(.*)/\+recipe/(.*)$') | 110 | r'^https://code.launchpad.net/~(.*)/\+recipe/(.*)$') |
378 | 367 | 111 | ||
379 | @@ -409,6 +153,33 @@ | |||
380 | 409 | return basename, recipe_transport.get(basename) | 153 | return basename, recipe_transport.get(basename) |
381 | 410 | 154 | ||
382 | 411 | 155 | ||
383 | 156 | def get_prepared_branch_from_location(location, | ||
384 | 157 | safe=False, possible_transports=None, | ||
385 | 158 | revspec=None): | ||
386 | 159 | """Common code to prepare a branch and do substitutions. | ||
387 | 160 | |||
388 | 161 | :param location: a path to a recipe file or branch to work from. | ||
389 | 162 | :param if_changed_from: an optional location of a manifest to | ||
390 | 163 | compare the recipe against. | ||
391 | 164 | :param safe: if True, reject recipes that would cause arbitrary code | ||
392 | 165 | execution. | ||
393 | 166 | :return: A tuple with (retcode, base_branch). If retcode is None | ||
394 | 167 | then the command execution should continue. | ||
395 | 168 | """ | ||
396 | 169 | try: | ||
397 | 170 | base_branch = get_branch_from_recipe_location(location, safe=safe, | ||
398 | 171 | possible_transports=possible_transports) | ||
399 | 172 | except (_mod_transport.LateReadError, errors.ReadError): | ||
400 | 173 | # Presume unable to read means location is a directory rather than a file | ||
401 | 174 | base_branch = get_branch_from_branch_location(location, | ||
402 | 175 | possible_transports=possible_transports) | ||
403 | 176 | else: | ||
404 | 177 | if revspec is not None: | ||
405 | 178 | raise errors.BzrCommandError("--revision only supported when " | ||
406 | 179 | "building from branch") | ||
407 | 180 | return base_branch | ||
408 | 181 | |||
409 | 182 | |||
410 | 412 | class cmd_build(Command): | 183 | class cmd_build(Command): |
411 | 413 | """Build a tree based on a branch or a recipe. | 184 | """Build a tree based on a branch or a recipe. |
412 | 414 | 185 | ||
413 | @@ -427,43 +198,6 @@ | |||
414 | 427 | 'revision', | 198 | 'revision', |
415 | 428 | ] | 199 | ] |
416 | 429 | 200 | ||
417 | 430 | def _get_prepared_branch_from_location(self, location, | ||
418 | 431 | if_changed_from=None, safe=False, possible_transports=None, | ||
419 | 432 | revspec=None): | ||
420 | 433 | """Common code to prepare a branch and do substitutions. | ||
421 | 434 | |||
422 | 435 | :param location: a path to a recipe file or branch to work from. | ||
423 | 436 | :param if_changed_from: an optional location of a manifest to | ||
424 | 437 | compare the recipe against. | ||
425 | 438 | :param safe: if True, reject recipes that would cause arbitrary code | ||
426 | 439 | execution. | ||
427 | 440 | :return: A tuple with (retcode, base_branch). If retcode is None | ||
428 | 441 | then the command execution should continue. | ||
429 | 442 | """ | ||
430 | 443 | try: | ||
431 | 444 | base_branch = get_branch_from_recipe_location(location, safe=safe, | ||
432 | 445 | possible_transports=possible_transports) | ||
433 | 446 | except (_mod_transport.LateReadError, errors.ReadError): | ||
434 | 447 | # Presume unable to read means location is a directory rather than a file | ||
435 | 448 | base_branch = get_branch_from_branch_location(location, | ||
436 | 449 | possible_transports=possible_transports) | ||
437 | 450 | else: | ||
438 | 451 | if revspec is not None: | ||
439 | 452 | raise errors.BzrCommandError("--revision only supported when " | ||
440 | 453 | "building from branch") | ||
441 | 454 | time = datetime.datetime.utcnow() | ||
442 | 455 | base_branch.substitute_time(time) | ||
443 | 456 | old_recipe = None | ||
444 | 457 | if if_changed_from is not None: | ||
445 | 458 | old_recipe = get_old_recipe(if_changed_from, possible_transports) | ||
446 | 459 | # Save the unsubstituted version for dailydeb. | ||
447 | 460 | self._template_version = base_branch.deb_version | ||
448 | 461 | changed = resolve_revisions(base_branch, if_changed_from=old_recipe) | ||
449 | 462 | if not changed: | ||
450 | 463 | trace.note("Unchanged") | ||
451 | 464 | return 0, base_branch | ||
452 | 465 | return None, base_branch | ||
453 | 466 | |||
454 | 467 | def run(self, location, working_directory, manifest=None, | 201 | def run(self, location, working_directory, manifest=None, |
455 | 468 | if_changed_from=None, revision=None): | 202 | if_changed_from=None, revision=None): |
456 | 469 | if revision is not None and len(revision) > 0: | 203 | if revision is not None and len(revision) > 0: |
457 | @@ -474,11 +208,16 @@ | |||
458 | 474 | else: | 208 | else: |
459 | 475 | revspec = None | 209 | revspec = None |
460 | 476 | possible_transports = [] | 210 | possible_transports = [] |
463 | 477 | result, base_branch = self._get_prepared_branch_from_location(location, | 211 | base_branch = get_prepared_branch_from_location(location, |
462 | 478 | if_changed_from=if_changed_from, | ||
464 | 479 | possible_transports=possible_transports, revspec=revspec) | 212 | possible_transports=possible_transports, revspec=revspec) |
467 | 480 | if result is not None: | 213 | if if_changed_from is not None: |
468 | 481 | return result | 214 | old_recipe = get_old_recipe(if_changed_from, possible_transports) |
469 | 215 | else: | ||
470 | 216 | old_recipe = None | ||
471 | 217 | changed = resolve_revisions(base_branch, if_changed_from=old_recipe) | ||
472 | 218 | if not changed: | ||
473 | 219 | trace.note("Unchanged") | ||
474 | 220 | return 0 | ||
475 | 482 | manifest_path = manifest or os.path.join(working_directory, | 221 | manifest_path = manifest or os.path.join(working_directory, |
476 | 483 | "bzr-builder.manifest") | 222 | "bzr-builder.manifest") |
477 | 484 | build_tree(base_branch, working_directory) | 223 | build_tree(base_branch, working_directory) |
478 | @@ -486,73 +225,7 @@ | |||
479 | 486 | possible_transports) | 225 | possible_transports) |
480 | 487 | 226 | ||
481 | 488 | 227 | ||
549 | 489 | def debian_source_package_name(control_path): | 228 | class cmd_dailydeb(Command): |
483 | 490 | """Open a debian control file and extract the package name. | ||
484 | 491 | |||
485 | 492 | """ | ||
486 | 493 | f = open(control_path, 'r') | ||
487 | 494 | try: | ||
488 | 495 | control = deb822.Deb822(f) | ||
489 | 496 | # Debian policy states package names are [a-z0-9][a-z0-9.+-]+ so ascii | ||
490 | 497 | return control["Source"].encode("ascii") | ||
491 | 498 | finally: | ||
492 | 499 | f.close() | ||
493 | 500 | |||
494 | 501 | |||
495 | 502 | def reconstruct_pristine_tar(dest, delta, dest_filename): | ||
496 | 503 | """Reconstruct a pristine tarball from a directory and a delta. | ||
497 | 504 | |||
498 | 505 | :param dest: Directory to pack | ||
499 | 506 | :param delta: pristine-tar delta | ||
500 | 507 | :param dest_filename: Destination filename | ||
501 | 508 | """ | ||
502 | 509 | command = ["pristine-tar", "gentar", "-", | ||
503 | 510 | os.path.abspath(dest_filename)] | ||
504 | 511 | _run_command(command, dest, | ||
505 | 512 | "Reconstructing pristine tarball", | ||
506 | 513 | "Generating tar from delta failed", | ||
507 | 514 | not_installed_msg="pristine-tar is not installed", | ||
508 | 515 | indata=delta) | ||
509 | 516 | |||
510 | 517 | |||
511 | 518 | def extract_upstream_tarball(branch, package, version, dest_dir): | ||
512 | 519 | """Extract the upstream tarball from a branch. | ||
513 | 520 | |||
514 | 521 | :param branch: Branch with the upstream pristine tar data | ||
515 | 522 | :param package: Package name | ||
516 | 523 | :param version: Package version | ||
517 | 524 | :param dest_dir: Destination directory | ||
518 | 525 | """ | ||
519 | 526 | tag_name = "upstream-%s" % version | ||
520 | 527 | revid = branch.tags.lookup_tag(tag_name) | ||
521 | 528 | tree = branch.repository.revision_tree(revid) | ||
522 | 529 | rev = branch.repository.get_revision(revid) | ||
523 | 530 | if 'deb-pristine-delta' in rev.properties: | ||
524 | 531 | uuencoded = rev.properties['deb-pristine-delta'] | ||
525 | 532 | dest_filename = "%s_%s.orig.tar.gz" % (package, version) | ||
526 | 533 | elif 'deb-pristine-delta-bz2' in rev.properties: | ||
527 | 534 | uuencoded = rev.properties['deb-pristine-delta-bz2'] | ||
528 | 535 | dest_filename = "%s_%s.orig.tar.bz2" % (package, version) | ||
529 | 536 | else: | ||
530 | 537 | uuencoded = None | ||
531 | 538 | if uuencoded is not None: | ||
532 | 539 | delta = standard_b64decode(uuencoded) | ||
533 | 540 | dest = os.path.join(dest_dir, "orig") | ||
534 | 541 | try: | ||
535 | 542 | _mod_export.export(tree, dest, format='dir') | ||
536 | 543 | reconstruct_pristine_tar(dest, delta, | ||
537 | 544 | os.path.join(dest_dir, dest_filename)) | ||
538 | 545 | finally: | ||
539 | 546 | if os.path.exists(dest): | ||
540 | 547 | shutil.rmtree(dest) | ||
541 | 548 | else: | ||
542 | 549 | # Default to .tar.gz | ||
543 | 550 | dest_filename = "%s_%s.orig.tar.gz" % (package, version) | ||
544 | 551 | _mod_export.export(tree, os.path.join(dest_dir, dest_filename), | ||
545 | 552 | per_file_timestamps=True) | ||
546 | 553 | |||
547 | 554 | |||
548 | 555 | class cmd_dailydeb(cmd_build): | ||
550 | 556 | """Build a deb based on a 'recipe' or from a branch. | 229 | """Build a deb based on a 'recipe' or from a branch. |
551 | 557 | 230 | ||
552 | 558 | See "bzr help builder" for more information on what a recipe is. | 231 | See "bzr help builder" for more information on what a recipe is. |
553 | @@ -600,6 +273,36 @@ | |||
554 | 600 | if_changed_from=None, package=None, distribution=None, | 273 | if_changed_from=None, package=None, distribution=None, |
555 | 601 | dput=None, key_id=None, no_build=None, watch_ppa=False, | 274 | dput=None, key_id=None, no_build=None, watch_ppa=False, |
556 | 602 | append_version=None, safe=False, allow_fallback_to_native=False): | 275 | append_version=None, safe=False, allow_fallback_to_native=False): |
557 | 276 | try: | ||
558 | 277 | try: | ||
559 | 278 | import debian | ||
560 | 279 | except ImportError: | ||
561 | 280 | # In older versions of python-debian the main package was named | ||
562 | 281 | # debian_bundle | ||
563 | 282 | import debian_bundle | ||
564 | 283 | except ImportError: | ||
565 | 284 | raise errors.BzrCommandError("The 'debian' python module " | ||
566 | 285 | "is required for 'bzr dailydeb'. Install the " | ||
567 | 286 | "python-debian package.") | ||
568 | 287 | |||
569 | 288 | from bzrlib.plugins.builder.deb_util import ( | ||
570 | 289 | add_autobuild_changelog_entry, | ||
571 | 290 | build_source_package, | ||
572 | 291 | calculate_package_dir, | ||
573 | 292 | changelog, | ||
574 | 293 | debian_source_package_name, | ||
575 | 294 | dput_source_package, | ||
576 | 295 | extract_upstream_tarball, | ||
577 | 296 | force_native_format, | ||
578 | 297 | get_source_format, | ||
579 | 298 | sign_source_package, | ||
580 | 299 | target_from_dput, | ||
581 | 300 | ) | ||
582 | 301 | from bzrlib.plugins.builder.deb_version import ( | ||
583 | 302 | check_expanded_deb_version, | ||
584 | 303 | substitute_branch_vars, | ||
585 | 304 | substitute_time, | ||
586 | 305 | ) | ||
587 | 603 | 306 | ||
588 | 604 | if dput is not None and key_id is None: | 307 | if dput is not None and key_id is None: |
589 | 605 | raise errors.BzrCommandError("You must specify --key-id if you " | 308 | raise errors.BzrCommandError("You must specify --key-id if you " |
590 | @@ -613,11 +316,25 @@ | |||
591 | 613 | target_from_dput(dput) | 316 | target_from_dput(dput) |
592 | 614 | 317 | ||
593 | 615 | possible_transports = [] | 318 | possible_transports = [] |
596 | 616 | result, base_branch = self._get_prepared_branch_from_location(location, | 319 | base_branch = get_prepared_branch_from_location(location, safe=safe, |
595 | 617 | if_changed_from=if_changed_from, safe=safe, | ||
597 | 618 | possible_transports=possible_transports) | 320 | possible_transports=possible_transports) |
600 | 619 | if result is not None: | 321 | # Save the unsubstituted version |
601 | 620 | return result | 322 | template_version = base_branch.deb_version |
602 | 323 | if if_changed_from is not None: | ||
603 | 324 | old_recipe = get_old_recipe(if_changed_from, possible_transports) | ||
604 | 325 | else: | ||
605 | 326 | old_recipe = None | ||
606 | 327 | if base_branch.deb_version is not None: | ||
607 | 328 | time = datetime.datetime.utcnow() | ||
608 | 329 | substitute_time(base_branch, time) | ||
609 | 330 | changed = resolve_revisions(base_branch, if_changed_from=old_recipe, | ||
610 | 331 | substitute_branch_vars=substitute_branch_vars) | ||
611 | 332 | check_expanded_deb_version(base_branch) | ||
612 | 333 | else: | ||
613 | 334 | changed = resolve_revisions(base_branch, if_changed_from=old_recipe) | ||
614 | 335 | if not changed: | ||
615 | 336 | trace.note("Unchanged") | ||
616 | 337 | return 0 | ||
617 | 621 | if working_basedir is None: | 338 | if working_basedir is None: |
618 | 622 | temp_dir = tempfile.mkdtemp(prefix="bzr-builder-") | 339 | temp_dir = tempfile.mkdtemp(prefix="bzr-builder-") |
619 | 623 | working_basedir = temp_dir | 340 | working_basedir = temp_dir |
620 | @@ -626,12 +343,12 @@ | |||
621 | 626 | if not os.path.exists(working_basedir): | 343 | if not os.path.exists(working_basedir): |
622 | 627 | os.makedirs(working_basedir) | 344 | os.makedirs(working_basedir) |
623 | 628 | package_name = self._calculate_package_name(location, package) | 345 | package_name = self._calculate_package_name(location, package) |
625 | 629 | if self._template_version is None: | 346 | if template_version is None: |
626 | 630 | working_directory = os.path.join(working_basedir, | 347 | working_directory = os.path.join(working_basedir, |
627 | 631 | "%s-direct" % (package_name,)) | 348 | "%s-direct" % (package_name,)) |
628 | 632 | else: | 349 | else: |
629 | 633 | working_directory = os.path.join(working_basedir, | 350 | working_directory = os.path.join(working_basedir, |
631 | 634 | "%s-%s" % (package_name, self._template_version)) | 351 | "%s-%s" % (package_name, template_version)) |
632 | 635 | try: | 352 | try: |
633 | 636 | # we want to use a consistent package_dir always to support | 353 | # we want to use a consistent package_dir always to support |
634 | 637 | # updates in place, but debuild etc want PACKAGE-UPSTREAMVERSION | 354 | # updates in place, but debuild etc want PACKAGE-UPSTREAMVERSION |
635 | @@ -655,7 +372,7 @@ | |||
636 | 655 | if autobuild: | 372 | if autobuild: |
637 | 656 | # Add changelog also substitutes {debupstream}. | 373 | # Add changelog also substitutes {debupstream}. |
638 | 657 | add_autobuild_changelog_entry(base_branch, working_directory, | 374 | add_autobuild_changelog_entry(base_branch, working_directory, |
640 | 658 | package, distribution=distribution, | 375 | package, distribution=distribution, |
641 | 659 | append_version=append_version) | 376 | append_version=append_version) |
642 | 660 | else: | 377 | else: |
643 | 661 | if append_version: | 378 | if append_version: |
644 | @@ -671,33 +388,29 @@ | |||
645 | 671 | working_basedir) | 388 | working_basedir) |
646 | 672 | # working_directory -> package_dir: after this debian stuff works. | 389 | # working_directory -> package_dir: after this debian stuff works. |
647 | 673 | os.rename(working_directory, package_dir) | 390 | os.rename(working_directory, package_dir) |
648 | 674 | if no_build: | ||
649 | 675 | if manifest is not None: | ||
650 | 676 | write_manifest_to_transport(manifest, base_branch, | ||
651 | 677 | possible_transports) | ||
652 | 678 | return 0 | ||
653 | 679 | current_format = get_source_format(package_dir) | ||
654 | 680 | if (package_version.debian_version is not None or | ||
655 | 681 | current_format == "3.0 (quilt)"): | ||
656 | 682 | # Non-native package | ||
657 | 683 | try: | ||
658 | 684 | extract_upstream_tarball(base_branch.branch, package_name, | ||
659 | 685 | package_version.upstream_version, working_basedir) | ||
660 | 686 | except errors.NoSuchTag, e: | ||
661 | 687 | if not allow_fallback_to_native: | ||
662 | 688 | raise errors.BzrCommandError( | ||
663 | 689 | "Unable to find the upstream source. Import it " | ||
664 | 690 | "as tag %s or build with " | ||
665 | 691 | "--allow-fallback-to-native." % e.tag_name) | ||
666 | 692 | else: | ||
667 | 693 | force_native_format(package_dir, current_format) | ||
668 | 694 | try: | 391 | try: |
675 | 695 | build_source_package(package_dir, | 392 | current_format = get_source_format(package_dir) |
676 | 696 | tgz_check=not allow_fallback_to_native) | 393 | if (package_version.debian_version is not None or |
677 | 697 | if key_id is not None: | 394 | current_format == "3.0 (quilt)"): |
678 | 698 | sign_source_package(package_dir, key_id) | 395 | # Non-native package |
679 | 699 | if dput is not None: | 396 | try: |
680 | 700 | dput_source_package(package_dir, dput) | 397 | extract_upstream_tarball(base_branch.branch, package_name, |
681 | 398 | package_version.upstream_version, working_basedir) | ||
682 | 399 | except errors.NoSuchTag, e: | ||
683 | 400 | if not allow_fallback_to_native: | ||
684 | 401 | raise errors.BzrCommandError( | ||
685 | 402 | "Unable to find the upstream source. Import it " | ||
686 | 403 | "as tag %s or build with " | ||
687 | 404 | "--allow-fallback-to-native." % e.tag_name) | ||
688 | 405 | else: | ||
689 | 406 | force_native_format(package_dir, current_format) | ||
690 | 407 | if not no_build: | ||
691 | 408 | build_source_package(package_dir, | ||
692 | 409 | tgz_check=not allow_fallback_to_native) | ||
693 | 410 | if key_id is not None: | ||
694 | 411 | sign_source_package(package_dir, key_id) | ||
695 | 412 | if dput is not None: | ||
696 | 413 | dput_source_package(package_dir, dput) | ||
697 | 701 | finally: | 414 | finally: |
698 | 702 | # package_dir -> working_directory | 415 | # package_dir -> working_directory |
699 | 703 | # FIXME: may fail in error unwind, masking the original exception. | 416 | # FIXME: may fail in error unwind, masking the original exception. |
700 | @@ -722,20 +435,3 @@ | |||
701 | 722 | recipe_name = recipe_name[:-len(".recipe")] | 435 | recipe_name = recipe_name[:-len(".recipe")] |
702 | 723 | return package or recipe_name | 436 | return package or recipe_name |
703 | 724 | 437 | ||
704 | 725 | |||
705 | 726 | def target_from_dput(dput): | ||
706 | 727 | """Convert a dput specification to a LP API specification. | ||
707 | 728 | |||
708 | 729 | :param dput: A dput command spec like ppa:team-name. | ||
709 | 730 | :return: A LP API target like team-name/ppa. | ||
710 | 731 | """ | ||
711 | 732 | ppa_prefix = 'ppa:' | ||
712 | 733 | if not dput.startswith(ppa_prefix): | ||
713 | 734 | raise errors.BzrCommandError('%r does not appear to be a PPA. ' | ||
714 | 735 | 'A dput target like \'%suser[/name]\' must be used.' | ||
715 | 736 | % (dput, ppa_prefix)) | ||
716 | 737 | base, _, suffix = dput[len(ppa_prefix):].partition('/') | ||
717 | 738 | if not suffix: | ||
718 | 739 | suffix = 'ppa' | ||
719 | 740 | return base, suffix | ||
720 | 741 | |||
721 | 742 | 438 | ||
722 | === added file 'deb_util.py' | |||
723 | --- deb_util.py 1970-01-01 00:00:00 +0000 | |||
724 | +++ deb_util.py 2012-06-10 06:51:21 +0000 | |||
725 | @@ -0,0 +1,379 @@ | |||
726 | 1 | # bzr-builder: a bzr plugin to constuct trees based on recipes | ||
727 | 2 | # Copyright 2009-2011 Canonical Ltd. | ||
728 | 3 | |||
729 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
730 | 5 | # under the terms of the GNU General Public License version 3, as published | ||
731 | 6 | # by the Free Software Foundation. | ||
732 | 7 | |||
733 | 8 | # This program is distributed in the hope that it will be useful, but | ||
734 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
735 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
736 | 11 | # PURPOSE. See the GNU General Public License for more details. | ||
737 | 12 | |||
738 | 13 | # You should have received a copy of the GNU General Public License along | ||
739 | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
740 | 15 | |||
741 | 16 | """Debian-specific utility functions.""" | ||
742 | 17 | |||
743 | 18 | from base64 import standard_b64decode | ||
744 | 19 | from email import utils | ||
745 | 20 | import errno | ||
746 | 21 | import os | ||
747 | 22 | import shutil | ||
748 | 23 | import signal | ||
749 | 24 | import subprocess | ||
750 | 25 | |||
751 | 26 | from bzrlib import ( | ||
752 | 27 | errors, | ||
753 | 28 | export as _mod_export, | ||
754 | 29 | osutils, | ||
755 | 30 | trace, | ||
756 | 31 | ) | ||
757 | 32 | |||
758 | 33 | from bzrlib.plugins.builder.deb_version import substitute_changelog_vars | ||
759 | 34 | from bzrlib.plugins.builder.recipe import ( | ||
760 | 35 | SubstitutionUnavailable, | ||
761 | 36 | ) | ||
762 | 37 | |||
763 | 38 | try: | ||
764 | 39 | from debian import changelog, deb822 | ||
765 | 40 | except ImportError: | ||
766 | 41 | # In older versions of python-debian the main package was named | ||
767 | 42 | # debian_bundle | ||
768 | 43 | from debian_bundle import changelog, deb822 | ||
769 | 44 | |||
770 | 45 | |||
771 | 46 | try: | ||
772 | 47 | get_maintainer = changelog.get_maintainer | ||
773 | 48 | except AttributeError: | ||
774 | 49 | # Implementation of get_maintainer was added after 0.1.18 so import same | ||
775 | 50 | # function from backports module if python-debian doesn't have it. | ||
776 | 51 | from bzrlib.plugins.builder.backports import get_maintainer | ||
777 | 52 | |||
778 | 53 | # The default distribution used by add_autobuild_changelog_entry() | ||
779 | 54 | DEFAULT_UBUNTU_DISTRIBUTION = "lucid" | ||
780 | 55 | |||
781 | 56 | |||
782 | 57 | class MissingDependency(errors.BzrError): | ||
783 | 58 | pass | ||
784 | 59 | |||
785 | 60 | |||
786 | 61 | def target_from_dput(dput): | ||
787 | 62 | """Convert a dput specification to a LP API specification. | ||
788 | 63 | |||
789 | 64 | :param dput: A dput command spec like ppa:team-name. | ||
790 | 65 | :return: A LP API target like team-name/ppa. | ||
791 | 66 | """ | ||
792 | 67 | ppa_prefix = 'ppa:' | ||
793 | 68 | if not dput.startswith(ppa_prefix): | ||
794 | 69 | raise errors.BzrCommandError('%r does not appear to be a PPA. ' | ||
795 | 70 | 'A dput target like \'%suser[/name]\' must be used.' | ||
796 | 71 | % (dput, ppa_prefix)) | ||
797 | 72 | base, _, suffix = dput[len(ppa_prefix):].partition('/') | ||
798 | 73 | if not suffix: | ||
799 | 74 | suffix = 'ppa' | ||
800 | 75 | return base, suffix | ||
801 | 76 | |||
802 | 77 | |||
803 | 78 | def debian_source_package_name(control_path): | ||
804 | 79 | """Open a debian control file and extract the package name. | ||
805 | 80 | |||
806 | 81 | """ | ||
807 | 82 | f = open(control_path, 'r') | ||
808 | 83 | try: | ||
809 | 84 | control = deb822.Deb822(f) | ||
810 | 85 | # Debian policy states package names are [a-z0-9][a-z0-9.+-]+ so ascii | ||
811 | 86 | return control["Source"].encode("ascii") | ||
812 | 87 | finally: | ||
813 | 88 | f.close() | ||
814 | 89 | |||
815 | 90 | |||
816 | 91 | def reconstruct_pristine_tar(dest, delta, dest_filename): | ||
817 | 92 | """Reconstruct a pristine tarball from a directory and a delta. | ||
818 | 93 | |||
819 | 94 | :param dest: Directory to pack | ||
820 | 95 | :param delta: pristine-tar delta | ||
821 | 96 | :param dest_filename: Destination filename | ||
822 | 97 | """ | ||
823 | 98 | command = ["pristine-tar", "gentar", "-", | ||
824 | 99 | os.path.abspath(dest_filename)] | ||
825 | 100 | _run_command(command, dest, | ||
826 | 101 | "Reconstructing pristine tarball", | ||
827 | 102 | "Generating tar from delta failed", | ||
828 | 103 | not_installed_msg="pristine-tar is not installed", | ||
829 | 104 | indata=delta) | ||
830 | 105 | |||
831 | 106 | |||
832 | 107 | def extract_upstream_tarball(branch, package, version, dest_dir): | ||
833 | 108 | """Extract the upstream tarball from a branch. | ||
834 | 109 | |||
835 | 110 | :param branch: Branch with the upstream pristine tar data | ||
836 | 111 | :param package: Package name | ||
837 | 112 | :param version: Package version | ||
838 | 113 | :param dest_dir: Destination directory | ||
839 | 114 | """ | ||
840 | 115 | tag_names = ["upstream-%s" % version, "upstream/%s" % version] | ||
841 | 116 | for tag_name in tag_names: | ||
842 | 117 | try: | ||
843 | 118 | revid = branch.tags.lookup_tag(tag_name) | ||
844 | 119 | except errors.NoSuchTag: | ||
845 | 120 | pass | ||
846 | 121 | else: | ||
847 | 122 | break | ||
848 | 123 | else: | ||
849 | 124 | raise errors.NoSuchTag(tag_names[0]) | ||
850 | 125 | tree = branch.repository.revision_tree(revid) | ||
851 | 126 | rev = branch.repository.get_revision(revid) | ||
852 | 127 | if 'deb-pristine-delta' in rev.properties: | ||
853 | 128 | uuencoded = rev.properties['deb-pristine-delta'] | ||
854 | 129 | dest_filename = "%s_%s.orig.tar.gz" % (package, version) | ||
855 | 130 | elif 'deb-pristine-delta-bz2' in rev.properties: | ||
856 | 131 | uuencoded = rev.properties['deb-pristine-delta-bz2'] | ||
857 | 132 | dest_filename = "%s_%s.orig.tar.bz2" % (package, version) | ||
858 | 133 | else: | ||
859 | 134 | uuencoded = None | ||
860 | 135 | if uuencoded is not None: | ||
861 | 136 | delta = standard_b64decode(uuencoded) | ||
862 | 137 | dest = os.path.join(dest_dir, "orig") | ||
863 | 138 | try: | ||
864 | 139 | _mod_export.export(tree, dest, format='dir') | ||
865 | 140 | reconstruct_pristine_tar(dest, delta, | ||
866 | 141 | os.path.join(dest_dir, dest_filename)) | ||
867 | 142 | finally: | ||
868 | 143 | if os.path.exists(dest): | ||
869 | 144 | shutil.rmtree(dest) | ||
870 | 145 | else: | ||
871 | 146 | # Default to .tar.gz | ||
872 | 147 | dest_filename = "%s_%s.orig.tar.gz" % (package, version) | ||
873 | 148 | _mod_export.export(tree, os.path.join(dest_dir, dest_filename), | ||
874 | 149 | per_file_timestamps=True) | ||
875 | 150 | |||
876 | 151 | |||
877 | 152 | def add_autobuild_changelog_entry(base_branch, basedir, package, | ||
878 | 153 | distribution=None, author_name=None, author_email=None, | ||
879 | 154 | append_version=None): | ||
880 | 155 | """Add a new changelog entry for an autobuild. | ||
881 | 156 | |||
882 | 157 | :param base_branch: Recipe base branch | ||
883 | 158 | :param basedir: Base working directory | ||
884 | 159 | :param package: package name | ||
885 | 160 | :param distribution: Optional distribution (defaults to last entry | ||
886 | 161 | distribution) | ||
887 | 162 | :param author_name: Name of the build requester | ||
888 | 163 | :param author_email: Email of the build requester | ||
889 | 164 | :param append_version: Optional version suffix to add | ||
890 | 165 | """ | ||
891 | 166 | debian_dir = os.path.join(basedir, "debian") | ||
892 | 167 | if not os.path.exists(debian_dir): | ||
893 | 168 | os.makedirs(debian_dir) | ||
894 | 169 | cl_path = os.path.join(debian_dir, "changelog") | ||
895 | 170 | file_found = False | ||
896 | 171 | if os.path.exists(cl_path): | ||
897 | 172 | file_found = True | ||
898 | 173 | cl_f = open(cl_path) | ||
899 | 174 | try: | ||
900 | 175 | contents = cl_f.read() | ||
901 | 176 | finally: | ||
902 | 177 | cl_f.close() | ||
903 | 178 | cl = changelog.Changelog(file=contents) | ||
904 | 179 | else: | ||
905 | 180 | cl = changelog.Changelog() | ||
906 | 181 | if len(cl._blocks) > 0: | ||
907 | 182 | if distribution is None: | ||
908 | 183 | distribution = cl._blocks[0].distributions.split()[0] | ||
909 | 184 | else: | ||
910 | 185 | if file_found: | ||
911 | 186 | if len(contents.strip()) > 0: | ||
912 | 187 | reason = ("debian/changelog didn't contain any " | ||
913 | 188 | "parseable stanzas") | ||
914 | 189 | else: | ||
915 | 190 | reason = "debian/changelog was empty" | ||
916 | 191 | else: | ||
917 | 192 | reason = "debian/changelog was not present" | ||
918 | 193 | if distribution is None: | ||
919 | 194 | distribution = DEFAULT_UBUNTU_DISTRIBUTION | ||
920 | 195 | if base_branch.format in (0.1, 0.2, 0.3): | ||
921 | 196 | try: | ||
922 | 197 | substitute_changelog_vars(base_branch, None, cl) | ||
923 | 198 | except SubstitutionUnavailable, e: | ||
924 | 199 | raise errors.BzrCommandError("No previous changelog to " | ||
925 | 200 | "take the upstream version from as %s was " | ||
926 | 201 | "used: %s: %s." % (e.name, e.reason, reason)) | ||
927 | 202 | # Use debian packaging environment variables | ||
928 | 203 | # or default values if they don't exist | ||
929 | 204 | if author_name is None or author_email is None: | ||
930 | 205 | author_name, author_email = get_maintainer() | ||
931 | 206 | # The python-debian package breaks compatibility at version 0.1.20 by | ||
932 | 207 | # switching to expecting (but not checking for) unicode rather than | ||
933 | 208 | # bytestring inputs. Detect this and decode environment if needed. | ||
934 | 209 | if getattr(changelog.Changelog, "__unicode__", None) is not None: | ||
935 | 210 | enc = osutils.get_user_encoding() | ||
936 | 211 | author_name = author_name.decode(enc) | ||
937 | 212 | author_email = author_email.decode(enc) | ||
938 | 213 | author = "%s <%s>" % (author_name, author_email) | ||
939 | 214 | |||
940 | 215 | date = utils.formatdate(localtime=True) | ||
941 | 216 | version = base_branch.deb_version | ||
942 | 217 | if append_version is not None: | ||
943 | 218 | version += append_version | ||
944 | 219 | try: | ||
945 | 220 | changelog.Version(version) | ||
946 | 221 | except (changelog.VersionError, ValueError), e: | ||
947 | 222 | raise errors.BzrCommandError("Invalid deb-version: %s: %s" | ||
948 | 223 | % (version, e)) | ||
949 | 224 | cl.new_block(package=package, version=version, | ||
950 | 225 | distributions=distribution, urgency="low", | ||
951 | 226 | changes=['', ' * Auto build.', ''], | ||
952 | 227 | author=author, date=date) | ||
953 | 228 | cl_f = open(cl_path, 'wb') | ||
954 | 229 | try: | ||
955 | 230 | cl.write_to_open_file(cl_f) | ||
956 | 231 | finally: | ||
957 | 232 | cl_f.close() | ||
958 | 233 | |||
959 | 234 | |||
960 | 235 | def calculate_package_dir(package_name, package_version, working_basedir): | ||
961 | 236 | """Calculate the directory name that should be used while debuilding. | ||
962 | 237 | |||
963 | 238 | :param base_branch: Recipe base branch | ||
964 | 239 | :param package_version: Version of the package | ||
965 | 240 | :param package_name: Package name | ||
966 | 241 | :param working_basedir: Base directory | ||
967 | 242 | """ | ||
968 | 243 | package_basedir = "%s-%s" % (package_name, package_version.upstream_version) | ||
969 | 244 | package_dir = os.path.join(working_basedir, package_basedir) | ||
970 | 245 | return package_dir | ||
971 | 246 | |||
972 | 247 | |||
973 | 248 | def _run_command(command, basedir, msg, error_msg, | ||
974 | 249 | not_installed_msg=None, env=None, success_exit_codes=None, indata=None): | ||
975 | 250 | """ Run a command in a subprocess. | ||
976 | 251 | |||
977 | 252 | :param command: list with command and parameters | ||
978 | 253 | :param msg: message to display to the user | ||
979 | 254 | :param error_msg: message to display if something fails. | ||
980 | 255 | :param not_installed_msg: the message to display if the command | ||
981 | 256 | isn't available. | ||
982 | 257 | :param env: Optional environment to use rather than os.environ. | ||
983 | 258 | :param success_exit_codes: Exit codes to consider succesfull, defaults to [0]. | ||
984 | 259 | :param indata: Data to write to standard input | ||
985 | 260 | """ | ||
986 | 261 | def subprocess_setup(): | ||
987 | 262 | signal.signal(signal.SIGPIPE, signal.SIG_DFL) | ||
988 | 263 | trace.note(msg) | ||
989 | 264 | # Hide output if -q is in use. | ||
990 | 265 | quiet = trace.is_quiet() | ||
991 | 266 | if quiet: | ||
992 | 267 | kwargs = {"stderr": subprocess.STDOUT, "stdout": subprocess.PIPE} | ||
993 | 268 | else: | ||
994 | 269 | kwargs = {} | ||
995 | 270 | if env is not None: | ||
996 | 271 | kwargs["env"] = env | ||
997 | 272 | trace.mutter("running: %r", command) | ||
998 | 273 | try: | ||
999 | 274 | proc = subprocess.Popen(command, cwd=basedir, | ||
1000 | 275 | stdin=subprocess.PIPE, preexec_fn=subprocess_setup, **kwargs) | ||
1001 | 276 | except OSError, e: | ||
1002 | 277 | if e.errno != errno.ENOENT: | ||
1003 | 278 | raise | ||
1004 | 279 | if not_installed_msg is None: | ||
1005 | 280 | raise | ||
1006 | 281 | raise MissingDependency(msg=not_installed_msg) | ||
1007 | 282 | output = proc.communicate(indata) | ||
1008 | 283 | if success_exit_codes is None: | ||
1009 | 284 | success_exit_codes = [0] | ||
1010 | 285 | if proc.returncode not in success_exit_codes: | ||
1011 | 286 | if quiet: | ||
1012 | 287 | raise errors.BzrCommandError("%s: %s" % (error_msg, output)) | ||
1013 | 288 | else: | ||
1014 | 289 | raise errors.BzrCommandError(error_msg) | ||
1015 | 290 | |||
1016 | 291 | |||
1017 | 292 | def build_source_package(basedir, tgz_check=True): | ||
1018 | 293 | command = ["/usr/bin/debuild"] | ||
1019 | 294 | if tgz_check: | ||
1020 | 295 | command.append("--tgz-check") | ||
1021 | 296 | else: | ||
1022 | 297 | command.append("--no-tgz-check") | ||
1023 | 298 | command.extend(["-i", "-I", "-S", "-uc", "-us"]) | ||
1024 | 299 | _run_command(command, basedir, | ||
1025 | 300 | "Building the source package", | ||
1026 | 301 | "Failed to build the source package", | ||
1027 | 302 | not_installed_msg="debuild is not installed, please install " | ||
1028 | 303 | "the devscripts package.") | ||
1029 | 304 | |||
1030 | 305 | |||
1031 | 306 | def get_source_format(path): | ||
1032 | 307 | """Retrieve the source format name from a package. | ||
1033 | 308 | |||
1034 | 309 | :param path: Path to the package | ||
1035 | 310 | :return: String with package format | ||
1036 | 311 | """ | ||
1037 | 312 | source_format_path = os.path.join(path, "debian", "source", "format") | ||
1038 | 313 | if not os.path.exists(source_format_path): | ||
1039 | 314 | return "1.0" | ||
1040 | 315 | f = open(source_format_path, 'r') | ||
1041 | 316 | try: | ||
1042 | 317 | return f.read().strip() | ||
1043 | 318 | finally: | ||
1044 | 319 | f.close() | ||
1045 | 320 | |||
1046 | 321 | |||
1047 | 322 | def convert_3_0_quilt_to_native(path): | ||
1048 | 323 | """Convert a package in 3.0 (quilt) format to 3.0 (native). | ||
1049 | 324 | |||
1050 | 325 | This applies all patches in the package and updates the | ||
1051 | 326 | debian/source/format file. | ||
1052 | 327 | |||
1053 | 328 | :param path: Path to the package on disk | ||
1054 | 329 | """ | ||
1055 | 330 | path = os.path.abspath(path) | ||
1056 | 331 | patches_dir = os.path.join(path, "debian", "patches") | ||
1057 | 332 | series_file = os.path.join(patches_dir, "series") | ||
1058 | 333 | if os.path.exists(series_file): | ||
1059 | 334 | _run_command(["quilt", "push", "-a", "-v"], path, | ||
1060 | 335 | "Applying quilt patches", | ||
1061 | 336 | "Failed to apply quilt patches", | ||
1062 | 337 | not_installed_msg="quilt is not installed, please install it.", | ||
1063 | 338 | env={"QUILT_SERIES": series_file, "QUILT_PATCHES": patches_dir}, | ||
1064 | 339 | success_exit_codes=(0, 2)) | ||
1065 | 340 | if os.path.exists(patches_dir): | ||
1066 | 341 | shutil.rmtree(patches_dir) | ||
1067 | 342 | f = open(os.path.join(path, "debian", "source", "format"), 'w') | ||
1068 | 343 | try: | ||
1069 | 344 | f.write("3.0 (native)\n") | ||
1070 | 345 | finally: | ||
1071 | 346 | f.close() | ||
1072 | 347 | |||
1073 | 348 | |||
1074 | 349 | def force_native_format(working_tree_path, current_format): | ||
1075 | 350 | """Make sure a package is a format that supports native packages. | ||
1076 | 351 | |||
1077 | 352 | :param working_tree_path: Path to the package | ||
1078 | 353 | """ | ||
1079 | 354 | if current_format == "3.0 (quilt)": | ||
1080 | 355 | convert_3_0_quilt_to_native(working_tree_path) | ||
1081 | 356 | elif current_format not in ("1.0", "3.0 (native)"): | ||
1082 | 357 | raise errors.BzrCommandError("Unknown source format %s" % | ||
1083 | 358 | current_format) | ||
1084 | 359 | |||
1085 | 360 | |||
1086 | 361 | def sign_source_package(basedir, key_id): | ||
1087 | 362 | command = ["/usr/bin/debsign", "-S", "-k%s" % key_id] | ||
1088 | 363 | _run_command(command, basedir, | ||
1089 | 364 | "Signing the source package", | ||
1090 | 365 | "Signing the package failed", | ||
1091 | 366 | not_installed_msg="debsign is not installed, please install " | ||
1092 | 367 | "the devscripts package.") | ||
1093 | 368 | |||
1094 | 369 | |||
1095 | 370 | def dput_source_package(basedir, target): | ||
1096 | 371 | command = ["/usr/bin/debrelease", "-S", "--dput", target] | ||
1097 | 372 | _run_command(command, basedir, | ||
1098 | 373 | "Uploading the source package", | ||
1099 | 374 | "Uploading the package failed", | ||
1100 | 375 | not_installed_msg="debrelease is not installed, please " | ||
1101 | 376 | "install the devscripts package.") | ||
1102 | 377 | |||
1103 | 378 | |||
1104 | 379 | |||
1105 | 0 | 380 | ||
1106 | === added file 'deb_version.py' | |||
1107 | --- deb_version.py 1970-01-01 00:00:00 +0000 | |||
1108 | +++ deb_version.py 2012-06-10 06:51:21 +0000 | |||
1109 | @@ -0,0 +1,214 @@ | |||
1110 | 1 | # bzr-builder: a bzr plugin to constuct trees based on recipes | ||
1111 | 2 | # Copyright 2009-2011 Canonical Ltd. | ||
1112 | 3 | |||
1113 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
1114 | 5 | # under the terms of the GNU General Public License version 3, as published | ||
1115 | 6 | # by the Free Software Foundation. | ||
1116 | 7 | |||
1117 | 8 | # This program is distributed in the hope that it will be useful, but | ||
1118 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1119 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1120 | 11 | # PURPOSE. See the GNU General Public License for more details. | ||
1121 | 12 | |||
1122 | 13 | # You should have received a copy of the GNU General Public License along | ||
1123 | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1124 | 15 | |||
1125 | 16 | from bzrlib import ( | ||
1126 | 17 | errors, | ||
1127 | 18 | lazy_regex, | ||
1128 | 19 | ) | ||
1129 | 20 | |||
1130 | 21 | from bzrlib.plugins.builder.recipe import ( | ||
1131 | 22 | BranchSubstitutionVariable, | ||
1132 | 23 | DateVariable, | ||
1133 | 24 | GitCommitVariable, | ||
1134 | 25 | LatestTagVariable, | ||
1135 | 26 | RevdateVariable, | ||
1136 | 27 | RevtimeVariable, | ||
1137 | 28 | RevnoVariable, | ||
1138 | 29 | SubstitutionUnavailable, | ||
1139 | 30 | SubversionRevnumVariable, | ||
1140 | 31 | TimeVariable, | ||
1141 | 32 | branch_vars, | ||
1142 | 33 | simple_vars, | ||
1143 | 34 | ) | ||
1144 | 35 | try: | ||
1145 | 36 | from debian import changelog | ||
1146 | 37 | except ImportError: | ||
1147 | 38 | # In older versions of python-debian the main package was named | ||
1148 | 39 | # debian_bundle | ||
1149 | 40 | from debian_bundle import changelog | ||
1150 | 41 | |||
1151 | 42 | |||
1152 | 43 | class DebUpstreamVariable(BranchSubstitutionVariable): | ||
1153 | 44 | |||
1154 | 45 | basename = "debupstream" | ||
1155 | 46 | |||
1156 | 47 | minimum_format = 0.1 | ||
1157 | 48 | |||
1158 | 49 | def __init__(self, branch_name, version): | ||
1159 | 50 | super(DebUpstreamVariable, self).__init__(branch_name) | ||
1160 | 51 | self._version = version | ||
1161 | 52 | |||
1162 | 53 | @classmethod | ||
1163 | 54 | def from_changelog(cls, branch_name, changelog): | ||
1164 | 55 | if len(changelog._blocks) > 0: | ||
1165 | 56 | return cls(branch_name, changelog._blocks[0].version) | ||
1166 | 57 | else: | ||
1167 | 58 | return cls(branch_name, None) | ||
1168 | 59 | |||
1169 | 60 | def get(self): | ||
1170 | 61 | if self._version is None: | ||
1171 | 62 | raise SubstitutionUnavailable(self.name, | ||
1172 | 63 | "No previous changelog to take the upstream version from") | ||
1173 | 64 | # Should we include the epoch? | ||
1174 | 65 | return self._version.upstream_version | ||
1175 | 66 | |||
1176 | 67 | |||
1177 | 68 | class DebVersionVariable(BranchSubstitutionVariable): | ||
1178 | 69 | |||
1179 | 70 | basename = "debversion" | ||
1180 | 71 | |||
1181 | 72 | minimum_format = 0.4 | ||
1182 | 73 | |||
1183 | 74 | def __init__(self, branch_name, version): | ||
1184 | 75 | super(DebVersionVariable, self).__init__(branch_name) | ||
1185 | 76 | self._version = version | ||
1186 | 77 | |||
1187 | 78 | @classmethod | ||
1188 | 79 | def from_changelog(cls, branch_name, changelog): | ||
1189 | 80 | if len(changelog._blocks) > 0: | ||
1190 | 81 | return cls(branch_name, changelog._blocks[0].version) | ||
1191 | 82 | else: | ||
1192 | 83 | return cls(branch_name, None) | ||
1193 | 84 | |||
1194 | 85 | def get(self): | ||
1195 | 86 | if self._version is None: | ||
1196 | 87 | raise SubstitutionUnavailable(self.name, | ||
1197 | 88 | "No previous changelog to take the version from") | ||
1198 | 89 | return str(self._version) | ||
1199 | 90 | |||
1200 | 91 | dfsg_regex = lazy_regex.lazy_compile( | ||
1201 | 92 | r'[+.]*dfsg[.]*[0-9]+') | ||
1202 | 93 | |||
1203 | 94 | version_regex = lazy_regex.lazy_compile( | ||
1204 | 95 | r'([~+])(svn[0-9]+|bzr[0-9]+|git[0-9a-f]+)') | ||
1205 | 96 | |||
1206 | 97 | def version_extract_base(version): | ||
1207 | 98 | version = dfsg_regex.sub("", version) | ||
1208 | 99 | return version_regex.sub("\\1", version) | ||
1209 | 100 | |||
1210 | 101 | |||
1211 | 102 | class DebUpstreamBaseVariable(DebUpstreamVariable): | ||
1212 | 103 | |||
1213 | 104 | basename = "debupstream-base" | ||
1214 | 105 | minimum_format = 0.4 | ||
1215 | 106 | |||
1216 | 107 | def get(self): | ||
1217 | 108 | version = super(DebUpstreamBaseVariable, self).get() | ||
1218 | 109 | version = version_extract_base(version) | ||
1219 | 110 | if version[-1] not in ("~", "+"): | ||
1220 | 111 | version += "+" | ||
1221 | 112 | return version | ||
1222 | 113 | |||
1223 | 114 | |||
1224 | 115 | ok_to_preserve = [DebUpstreamVariable, DebUpstreamBaseVariable, | ||
1225 | 116 | DebVersionVariable] | ||
1226 | 117 | deb_branch_vars = [DebVersionVariable, DebUpstreamBaseVariable, DebUpstreamVariable] | ||
1227 | 118 | |||
1228 | 119 | |||
1229 | 120 | def check_expanded_deb_version(base_branch): | ||
1230 | 121 | checked_version = base_branch.deb_version | ||
1231 | 122 | if checked_version is None: | ||
1232 | 123 | return | ||
1233 | 124 | for token in ok_to_preserve: | ||
1234 | 125 | if issubclass(token, BranchSubstitutionVariable): | ||
1235 | 126 | for name in base_branch.list_branch_names(): | ||
1236 | 127 | checked_version = checked_version.replace( | ||
1237 | 128 | token.determine_name(name), "") | ||
1238 | 129 | checked_version = checked_version.replace( | ||
1239 | 130 | token.determine_name(None), "") | ||
1240 | 131 | else: | ||
1241 | 132 | checked_version = checked_version.replace( | ||
1242 | 133 | token.name, "") | ||
1243 | 134 | if "{" in checked_version: | ||
1244 | 135 | available_tokens = [var.name for var in simple_vars if | ||
1245 | 136 | var.available_in(base_branch.format)] | ||
1246 | 137 | for var_kls in branch_vars + deb_branch_vars: | ||
1247 | 138 | if not var_kls.available_in(base_branch.format): | ||
1248 | 139 | continue | ||
1249 | 140 | for name in base_branch.list_branch_names(): | ||
1250 | 141 | available_tokens.append(var_kls.determine_name(name)) | ||
1251 | 142 | available_tokens.append(var_kls.determine_name(None)) | ||
1252 | 143 | raise errors.BzrCommandError("deb-version not fully " | ||
1253 | 144 | "expanded: %s. Valid substitutions in recipe format %s are: %s" | ||
1254 | 145 | % (base_branch.deb_version, base_branch.format, | ||
1255 | 146 | available_tokens)) | ||
1256 | 147 | |||
1257 | 148 | |||
1258 | 149 | def substitute_branch_vars(base_branch, branch_name, branch, revid): | ||
1259 | 150 | """Substitute the branch variables for the given branch name in deb_version. | ||
1260 | 151 | |||
1261 | 152 | Where deb_version has a place to substitute the revno for a branch | ||
1262 | 153 | this will substitute it for the given branch name. | ||
1263 | 154 | |||
1264 | 155 | :param branch_name: the name of the RecipeBranch to substitute. | ||
1265 | 156 | :param branch: Branch object for the branch | ||
1266 | 157 | :param revid: Revision id in the branch for which to return the revno | ||
1267 | 158 | """ | ||
1268 | 159 | if base_branch.deb_version is None: | ||
1269 | 160 | return | ||
1270 | 161 | revno_var = RevnoVariable(branch_name, branch, revid) | ||
1271 | 162 | base_branch.deb_version = revno_var.replace(base_branch.deb_version) | ||
1272 | 163 | if base_branch.format < 0.4: | ||
1273 | 164 | # The other variables were introduced in recipe format 0.4 | ||
1274 | 165 | return | ||
1275 | 166 | svn_revno_var = SubversionRevnumVariable(branch_name, branch, revid) | ||
1276 | 167 | base_branch.deb_version = svn_revno_var.replace(base_branch.deb_version) | ||
1277 | 168 | git_commit_var = GitCommitVariable(branch_name, branch, revid) | ||
1278 | 169 | base_branch.deb_version = git_commit_var.replace(base_branch.deb_version) | ||
1279 | 170 | latest_tag_var = LatestTagVariable(branch_name, branch, revid) | ||
1280 | 171 | base_branch.deb_version = latest_tag_var.replace(base_branch.deb_version) | ||
1281 | 172 | revdate_var = RevdateVariable(branch_name, branch, revid) | ||
1282 | 173 | base_branch.deb_version = revdate_var.replace(base_branch.deb_version) | ||
1283 | 174 | revtime_var = RevtimeVariable(branch_name, branch, revid) | ||
1284 | 175 | base_branch.deb_version = revtime_var.replace(base_branch.deb_version) | ||
1285 | 176 | tree = branch.repository.revision_tree(revid) | ||
1286 | 177 | cl_file_id = tree.path2id("debian/changelog") | ||
1287 | 178 | if cl_file_id is not None: | ||
1288 | 179 | tree.lock_read() | ||
1289 | 180 | try: | ||
1290 | 181 | cl = changelog.Changelog(tree.get_file_text(cl_file_id)) | ||
1291 | 182 | substitute_changelog_vars(base_branch, branch_name, cl) | ||
1292 | 183 | finally: | ||
1293 | 184 | tree.unlock() | ||
1294 | 185 | |||
1295 | 186 | |||
1296 | 187 | def substitute_changelog_vars(base_branch, branch_name, changelog): | ||
1297 | 188 | """Substitute variables related from a changelog. | ||
1298 | 189 | |||
1299 | 190 | :param branch_name: Branch name (None for root branch) | ||
1300 | 191 | :param changelog: Changelog object to use | ||
1301 | 192 | """ | ||
1302 | 193 | from bzrlib.plugins.builder.deb_version import DebUpstreamVariable, DebUpstreamBaseVariable, DebVersionVariable | ||
1303 | 194 | debupstream_var = DebUpstreamVariable.from_changelog(branch_name, changelog) | ||
1304 | 195 | base_branch.deb_version = debupstream_var.replace(base_branch.deb_version) | ||
1305 | 196 | if base_branch.format < 0.4: | ||
1306 | 197 | # The other variables were introduced in recipe format 0.4 | ||
1307 | 198 | return | ||
1308 | 199 | debupstreambase_var = DebUpstreamBaseVariable.from_changelog( | ||
1309 | 200 | branch_name, changelog) | ||
1310 | 201 | base_branch.deb_version = debupstreambase_var.replace(base_branch.deb_version) | ||
1311 | 202 | pkgversion_var = DebVersionVariable.from_changelog(branch_name, changelog) | ||
1312 | 203 | base_branch.deb_version = pkgversion_var.replace(base_branch.deb_version) | ||
1313 | 204 | |||
1314 | 205 | |||
1315 | 206 | def substitute_time(base_branch, time): | ||
1316 | 207 | """Substitute the time in to deb_version if needed. | ||
1317 | 208 | |||
1318 | 209 | :param time: a datetime.datetime with the desired time. | ||
1319 | 210 | """ | ||
1320 | 211 | if base_branch.deb_version is None: | ||
1321 | 212 | return | ||
1322 | 213 | base_branch.deb_version = TimeVariable(time).replace(base_branch.deb_version) | ||
1323 | 214 | base_branch.deb_version = DateVariable(time).replace(base_branch.deb_version) | ||
1324 | 0 | 215 | ||
1325 | === modified file 'debian/changelog' | |||
1326 | --- debian/changelog 2011-11-11 12:27:27 +0000 | |||
1327 | +++ debian/changelog 2012-06-10 06:51:21 +0000 | |||
1328 | @@ -1,3 +1,9 @@ | |||
1329 | 1 | bzr-builder (0.7.3-0ubuntu1) UNRELEASED; urgency=low | ||
1330 | 2 | |||
1331 | 3 | * New upstream release. | ||
1332 | 4 | |||
1333 | 5 | -- Logan Rosen <logatronico@gmail.com> Sun, 10 Jun 2012 02:45:03 -0400 | ||
1334 | 6 | |||
1335 | 1 | bzr-builder (0.7.2-0ubuntu2) precise; urgency=low | 7 | bzr-builder (0.7.2-0ubuntu2) precise; urgency=low |
1336 | 2 | 8 | ||
1337 | 3 | * Add pristine-tar to build-dependencies, for use by the test suite. | 9 | * Add pristine-tar to build-dependencies, for use by the test suite. |
1338 | 4 | 10 | ||
1339 | === added file 'info.py' | |||
1340 | --- info.py 1970-01-01 00:00:00 +0000 | |||
1341 | +++ info.py 2012-06-10 06:51:21 +0000 | |||
1342 | @@ -0,0 +1,17 @@ | |||
1343 | 1 | # bzr-builder: a bzr plugin to constuct trees based on recipes | ||
1344 | 2 | # Copyright 2011 Canonical Ltd. | ||
1345 | 3 | |||
1346 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
1347 | 5 | # under the terms of the GNU General Public License version 3, as published | ||
1348 | 6 | # by the Free Software Foundation. | ||
1349 | 7 | |||
1350 | 8 | # This program is distributed in the hope that it will be useful, but | ||
1351 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1352 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1353 | 11 | # PURPOSE. See the GNU General Public License for more details. | ||
1354 | 12 | |||
1355 | 13 | # You should have received a copy of the GNU General Public License along | ||
1356 | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1357 | 15 | |||
1358 | 16 | |||
1359 | 17 | bzr_plugin_version = (0, 7, 3, 'final', 0) | ||
1360 | 0 | 18 | ||
1361 | === modified file 'recipe.py' | |||
1362 | --- recipe.py 2011-11-10 13:29:10 +0000 | |||
1363 | +++ recipe.py 2012-06-10 06:51:21 +0000 | |||
1364 | @@ -22,7 +22,6 @@ | |||
1365 | 22 | branch as _mod_branch, | 22 | branch as _mod_branch, |
1366 | 23 | bzrdir, | 23 | bzrdir, |
1367 | 24 | errors, | 24 | errors, |
1368 | 25 | lazy_regex, | ||
1369 | 26 | merge, | 25 | merge, |
1370 | 27 | revision, | 26 | revision, |
1371 | 28 | revisionspec, | 27 | revisionspec, |
1372 | @@ -40,11 +39,6 @@ | |||
1373 | 40 | 39 | ||
1374 | 41 | 40 | ||
1375 | 42 | try: | 41 | try: |
1376 | 43 | from debian import changelog | ||
1377 | 44 | except ImportError: | ||
1378 | 45 | from debian_bundle import changelog | ||
1379 | 46 | |||
1380 | 47 | try: | ||
1381 | 48 | MergeIntoMerger = merge.MergeIntoMerger | 42 | MergeIntoMerger = merge.MergeIntoMerger |
1382 | 49 | except (AttributeError, NameError): | 43 | except (AttributeError, NameError): |
1383 | 50 | from bzrlib.plugins.builder.backports import MergeIntoMerger | 44 | from bzrlib.plugins.builder.backports import MergeIntoMerger |
1384 | @@ -84,11 +78,18 @@ | |||
1385 | 84 | """Replace name with value.""" | 78 | """Replace name with value.""" |
1386 | 85 | raise NotImplementedError(self.replace) | 79 | raise NotImplementedError(self.replace) |
1387 | 86 | 80 | ||
1388 | 81 | @classmethod | ||
1389 | 82 | def available_in(cls, format): | ||
1390 | 83 | """Check if this variable is available in a particular format.""" | ||
1391 | 84 | raise NotImplementedError(cls.available_in) | ||
1392 | 85 | |||
1393 | 87 | 86 | ||
1394 | 88 | class SimpleSubstitutionVariable(SubstitutionVariable): | 87 | class SimpleSubstitutionVariable(SubstitutionVariable): |
1395 | 89 | 88 | ||
1396 | 90 | name = None | 89 | name = None |
1397 | 91 | 90 | ||
1398 | 91 | minimum_format = None | ||
1399 | 92 | |||
1400 | 92 | def replace(self, value): | 93 | def replace(self, value): |
1401 | 93 | if not self.name in value: | 94 | if not self.name in value: |
1402 | 94 | return value | 95 | return value |
1403 | @@ -97,6 +98,10 @@ | |||
1404 | 97 | def get(self): | 98 | def get(self): |
1405 | 98 | raise NotImplementedError(self.value) | 99 | raise NotImplementedError(self.value) |
1406 | 99 | 100 | ||
1407 | 101 | @classmethod | ||
1408 | 102 | def available_in(self, format): | ||
1409 | 103 | return (format >= self.minimum_format) | ||
1410 | 104 | |||
1411 | 100 | 105 | ||
1412 | 101 | class BranchSubstitutionVariable(SimpleSubstitutionVariable): | 106 | class BranchSubstitutionVariable(SimpleSubstitutionVariable): |
1413 | 102 | 107 | ||
1414 | @@ -122,6 +127,8 @@ | |||
1415 | 122 | 127 | ||
1416 | 123 | name = "{time}" | 128 | name = "{time}" |
1417 | 124 | 129 | ||
1418 | 130 | minimum_format = 0.1 | ||
1419 | 131 | |||
1420 | 125 | def __init__(self, time): | 132 | def __init__(self, time): |
1421 | 126 | self._time = time | 133 | self._time = time |
1422 | 127 | 134 | ||
1423 | @@ -133,6 +140,8 @@ | |||
1424 | 133 | 140 | ||
1425 | 134 | name = "{date}" | 141 | name = "{date}" |
1426 | 135 | 142 | ||
1427 | 143 | minimum_format = 0.1 | ||
1428 | 144 | |||
1429 | 136 | def __init__(self, time): | 145 | def __init__(self, time): |
1430 | 137 | self._time = time | 146 | self._time = time |
1431 | 138 | 147 | ||
1432 | @@ -140,66 +149,10 @@ | |||
1433 | 140 | return self._time.strftime("%Y%m%d") | 149 | return self._time.strftime("%Y%m%d") |
1434 | 141 | 150 | ||
1435 | 142 | 151 | ||
1436 | 143 | class DebUpstreamVariable(BranchSubstitutionVariable): | ||
1437 | 144 | |||
1438 | 145 | basename = "debupstream" | ||
1439 | 146 | |||
1440 | 147 | def __init__(self, branch_name, version): | ||
1441 | 148 | super(DebUpstreamVariable, self).__init__(branch_name) | ||
1442 | 149 | self._version = version | ||
1443 | 150 | |||
1444 | 151 | @classmethod | ||
1445 | 152 | def from_changelog(cls, branch_name, changelog): | ||
1446 | 153 | if len(changelog._blocks) > 0: | ||
1447 | 154 | return cls(branch_name, changelog._blocks[0].version) | ||
1448 | 155 | else: | ||
1449 | 156 | return cls(branch_name, None) | ||
1450 | 157 | |||
1451 | 158 | def get(self): | ||
1452 | 159 | if self._version is None: | ||
1453 | 160 | raise SubstitutionUnavailable(self.name, | ||
1454 | 161 | "No previous changelog to take the upstream version from") | ||
1455 | 162 | # Should we include the epoch? | ||
1456 | 163 | return self._version.upstream_version | ||
1457 | 164 | |||
1458 | 165 | |||
1459 | 166 | class DebVersionVariable(BranchSubstitutionVariable): | ||
1460 | 167 | |||
1461 | 168 | basename = "debversion" | ||
1462 | 169 | |||
1463 | 170 | def __init__(self, branch_name, version): | ||
1464 | 171 | super(DebVersionVariable, self).__init__(branch_name) | ||
1465 | 172 | self._version = version | ||
1466 | 173 | |||
1467 | 174 | @classmethod | ||
1468 | 175 | def from_changelog(cls, branch_name, changelog): | ||
1469 | 176 | if len(changelog._blocks) > 0: | ||
1470 | 177 | return cls(branch_name, changelog._blocks[0].version) | ||
1471 | 178 | else: | ||
1472 | 179 | return cls(branch_name, None) | ||
1473 | 180 | |||
1474 | 181 | def get(self): | ||
1475 | 182 | if self._version is None: | ||
1476 | 183 | raise SubstitutionUnavailable(self.name, | ||
1477 | 184 | "No previous changelog to take the version from") | ||
1478 | 185 | return str(self._version) | ||
1479 | 186 | |||
1480 | 187 | |||
1481 | 188 | class DebUpstreamBaseVariable(DebUpstreamVariable): | ||
1482 | 189 | |||
1483 | 190 | basename = "debupstream-base" | ||
1484 | 191 | version_regex = lazy_regex.lazy_compile(r'([~+])(svn[0-9]+|bzr[0-9]+|git[0-9a-f]+)') | ||
1485 | 192 | |||
1486 | 193 | def get(self): | ||
1487 | 194 | version = super(DebUpstreamBaseVariable, self).get() | ||
1488 | 195 | version = self.version_regex.sub("\\1", version) | ||
1489 | 196 | if version[-1] not in ("~", "+"): | ||
1490 | 197 | version += "+" | ||
1491 | 198 | return version | ||
1492 | 199 | |||
1493 | 200 | |||
1494 | 201 | class RevisionVariable(BranchSubstitutionVariable): | 152 | class RevisionVariable(BranchSubstitutionVariable): |
1495 | 202 | 153 | ||
1496 | 154 | minimum_format = 0.1 | ||
1497 | 155 | |||
1498 | 203 | def __init__(self, branch_name, branch, revid): | 156 | def __init__(self, branch_name, branch, revid): |
1499 | 204 | super(RevisionVariable, self).__init__(branch_name) | 157 | super(RevisionVariable, self).__init__(branch_name) |
1500 | 205 | self.branch = branch | 158 | self.branch = branch |
1501 | @@ -210,6 +163,8 @@ | |||
1502 | 210 | 163 | ||
1503 | 211 | basename = "revno" | 164 | basename = "revno" |
1504 | 212 | 165 | ||
1505 | 166 | minimum_format = 0.1 | ||
1506 | 167 | |||
1507 | 213 | def get_revno(self): | 168 | def get_revno(self): |
1508 | 214 | try: | 169 | try: |
1509 | 215 | revno = self.branch.revision_id_to_revno(self.revid) | 170 | revno = self.branch.revision_id_to_revno(self.revid) |
1510 | @@ -235,6 +190,8 @@ | |||
1511 | 235 | 190 | ||
1512 | 236 | basename = "revtime" | 191 | basename = "revtime" |
1513 | 237 | 192 | ||
1514 | 193 | minimum_format = 0.4 | ||
1515 | 194 | |||
1516 | 238 | def get(self): | 195 | def get(self): |
1517 | 239 | rev = self.branch.repository.get_revision(self.revid) | 196 | rev = self.branch.repository.get_revision(self.revid) |
1518 | 240 | return time.strftime("%Y%m%d%H%M", time.gmtime(rev.timestamp)) | 197 | return time.strftime("%Y%m%d%H%M", time.gmtime(rev.timestamp)) |
1519 | @@ -244,6 +201,8 @@ | |||
1520 | 244 | 201 | ||
1521 | 245 | basename = "revdate" | 202 | basename = "revdate" |
1522 | 246 | 203 | ||
1523 | 204 | minimum_format = 0.4 | ||
1524 | 205 | |||
1525 | 247 | def get(self): | 206 | def get(self): |
1526 | 248 | rev = self.branch.repository.get_revision(self.revid) | 207 | rev = self.branch.repository.get_revision(self.revid) |
1527 | 249 | return time.strftime("%Y%m%d", time.gmtime(rev.timestamp)) | 208 | return time.strftime("%Y%m%d", time.gmtime(rev.timestamp)) |
1528 | @@ -271,6 +230,8 @@ | |||
1529 | 271 | 230 | ||
1530 | 272 | basename = "svn-revno" | 231 | basename = "svn-revno" |
1531 | 273 | 232 | ||
1532 | 233 | minimum_format = 0.4 | ||
1533 | 234 | |||
1534 | 274 | def get(self): | 235 | def get(self): |
1535 | 275 | rev = self.branch.repository.get_revision(self.revid) | 236 | rev = self.branch.repository.get_revision(self.revid) |
1536 | 276 | try: | 237 | try: |
1537 | @@ -304,6 +265,8 @@ | |||
1538 | 304 | 265 | ||
1539 | 305 | basename = "git-commit" | 266 | basename = "git-commit" |
1540 | 306 | 267 | ||
1541 | 268 | minimum_format = 0.4 | ||
1542 | 269 | |||
1543 | 307 | def get(self): | 270 | def get(self): |
1544 | 308 | rev = self.branch.repository.get_revision(self.revid) | 271 | rev = self.branch.repository.get_revision(self.revid) |
1545 | 309 | try: | 272 | try: |
1546 | @@ -319,6 +282,8 @@ | |||
1547 | 319 | 282 | ||
1548 | 320 | basename = "latest-tag" | 283 | basename = "latest-tag" |
1549 | 321 | 284 | ||
1550 | 285 | minimum_format = 0.4 | ||
1551 | 286 | |||
1552 | 322 | def get(self): | 287 | def get(self): |
1553 | 323 | reverse_tag_dict = self.branch.tags.get_reverse_tag_dict() | 288 | reverse_tag_dict = self.branch.tags.get_reverse_tag_dict() |
1554 | 324 | self.branch.lock_read() | 289 | self.branch.lock_read() |
1555 | @@ -334,39 +299,10 @@ | |||
1556 | 334 | self.branch.unlock() | 299 | self.branch.unlock() |
1557 | 335 | 300 | ||
1558 | 336 | 301 | ||
1559 | 337 | ok_to_preserve = [DebUpstreamVariable, DebUpstreamBaseVariable, | ||
1560 | 338 | DebVersionVariable] | ||
1561 | 339 | # The variables that don't require substitution in their name | ||
1562 | 340 | simple_vars = [TimeVariable, DateVariable] | ||
1563 | 341 | branch_vars = [RevnoVariable, SubversionRevnumVariable, | 302 | branch_vars = [RevnoVariable, SubversionRevnumVariable, |
1566 | 342 | GitCommitVariable, LatestTagVariable, DebVersionVariable, | 303 | GitCommitVariable, LatestTagVariable, RevdateVariable, |
1565 | 343 | DebUpstreamBaseVariable, DebUpstreamVariable, RevdateVariable, | ||
1567 | 344 | RevtimeVariable] | 304 | RevtimeVariable] |
1593 | 345 | 305 | simple_vars = [TimeVariable, DateVariable] | |
1569 | 346 | |||
1570 | 347 | def check_expanded_deb_version(base_branch): | ||
1571 | 348 | checked_version = base_branch.deb_version | ||
1572 | 349 | if checked_version is None: | ||
1573 | 350 | return | ||
1574 | 351 | for token in ok_to_preserve: | ||
1575 | 352 | if issubclass(token, BranchSubstitutionVariable): | ||
1576 | 353 | for name in base_branch.list_branch_names(): | ||
1577 | 354 | checked_version = checked_version.replace( | ||
1578 | 355 | token.determine_name(name), "") | ||
1579 | 356 | checked_version = checked_version.replace( | ||
1580 | 357 | token.determine_name(None), "") | ||
1581 | 358 | else: | ||
1582 | 359 | checked_version = checked_version.replace( | ||
1583 | 360 | token.name, "") | ||
1584 | 361 | if "{" in checked_version: | ||
1585 | 362 | available_tokens = [var.name for var in simple_vars] | ||
1586 | 363 | for var_kls in branch_vars: | ||
1587 | 364 | for name in base_branch.list_branch_names(): | ||
1588 | 365 | available_tokens.append(var_kls.determine_name(name)) | ||
1589 | 366 | available_tokens.append(var_kls.determine_name(None)) | ||
1590 | 367 | raise errors.BzrCommandError("deb-version not fully " | ||
1591 | 368 | "expanded: %s. Valid substitutions are: %s" | ||
1592 | 369 | % (base_branch.deb_version, available_tokens)) | ||
1594 | 370 | 306 | ||
1595 | 371 | 307 | ||
1596 | 372 | class CommandFailedError(errors.BzrError): | 308 | class CommandFailedError(errors.BzrError): |
1597 | @@ -558,6 +494,14 @@ | |||
1598 | 558 | try: | 494 | try: |
1599 | 559 | if target_subdir is None: | 495 | if target_subdir is None: |
1600 | 560 | target_subdir = os.path.basename(subpath) | 496 | target_subdir = os.path.basename(subpath) |
1601 | 497 | # Create any missing parent directories | ||
1602 | 498 | target_subdir_parent = os.path.dirname(target_subdir) | ||
1603 | 499 | missing = [] | ||
1604 | 500 | while tree_to.path2id(target_subdir_parent) is None: | ||
1605 | 501 | missing.append(target_subdir_parent) | ||
1606 | 502 | target_subdir_parent = os.path.dirname(target_subdir_parent) | ||
1607 | 503 | for path in reversed(missing): | ||
1608 | 504 | tree_to.mkdir(path) | ||
1609 | 561 | merger = MergeIntoMerger(this_tree=tree_to, other_tree=other_tree, | 505 | merger = MergeIntoMerger(this_tree=tree_to, other_tree=other_tree, |
1610 | 562 | other_branch=child_branch.branch, target_subdir=target_subdir, | 506 | other_branch=child_branch.branch, target_subdir=target_subdir, |
1611 | 563 | source_subpath=subpath, other_rev_id=child_branch.revid) | 507 | source_subpath=subpath, other_rev_id=child_branch.revid) |
1612 | @@ -599,7 +543,8 @@ | |||
1613 | 599 | new_branch.branch.lock_read() | 543 | new_branch.branch.lock_read() |
1614 | 600 | try: | 544 | try: |
1615 | 601 | new_branch.resolve_revision_id() | 545 | new_branch.resolve_revision_id() |
1617 | 602 | substitute_branch_vars(new_branch.name, new_branch.branch, new_branch.revid) | 546 | if substitute_branch_vars is not None: |
1618 | 547 | substitute_branch_vars(new_branch.name, new_branch.branch, new_branch.revid) | ||
1619 | 603 | if (if_changed_from is not None | 548 | if (if_changed_from is not None |
1620 | 604 | and (new_branch.revspec is not None | 549 | and (new_branch.revspec is not None |
1621 | 605 | or if_changed_from.revspec is not None)): | 550 | or if_changed_from.revspec is not None)): |
1622 | @@ -628,10 +573,11 @@ | |||
1623 | 628 | new_branch.branch.unlock() | 573 | new_branch.branch.unlock() |
1624 | 629 | 574 | ||
1625 | 630 | 575 | ||
1627 | 631 | def resolve_revisions(base_branch, if_changed_from=None): | 576 | def resolve_revisions(base_branch, if_changed_from=None, substitute_branch_vars=None): |
1628 | 632 | """Resolve all the unknowns in base_branch. | 577 | """Resolve all the unknowns in base_branch. |
1629 | 633 | 578 | ||
1631 | 634 | This walks the RecipeBranch and substitutes in revnos and deb_version. | 579 | This walks the RecipeBranch and calls substitute_branch_vars for |
1632 | 580 | each child branch. | ||
1633 | 635 | 581 | ||
1634 | 636 | If if_changed_from is not None then it should be a second RecipeBranch | 582 | If if_changed_from is not None then it should be a second RecipeBranch |
1635 | 637 | to compare base_branch against. If the shape, or the revision ids differ | 583 | to compare base_branch against. If the shape, or the revision ids differ |
1636 | @@ -639,6 +585,8 @@ | |||
1637 | 639 | 585 | ||
1638 | 640 | :param base_branch: the RecipeBranch we plan to build. | 586 | :param base_branch: the RecipeBranch we plan to build. |
1639 | 641 | :param if_changed_from: the RecipeBranch that we want to compare against. | 587 | :param if_changed_from: the RecipeBranch that we want to compare against. |
1640 | 588 | :param substitute_branch_vars: Callable called for | ||
1641 | 589 | each branch with (name, bzr branch and last revision) | ||
1642 | 642 | :return: False if if_changed_from is not None, and the shape and revisions | 590 | :return: False if if_changed_from is not None, and the shape and revisions |
1643 | 643 | of the two branches don't differ. True otherwise. | 591 | of the two branches don't differ. True otherwise. |
1644 | 644 | """ | 592 | """ |
1645 | @@ -648,12 +596,16 @@ | |||
1646 | 648 | if_changed_from_revisions = if_changed_from | 596 | if_changed_from_revisions = if_changed_from |
1647 | 649 | if changed: | 597 | if changed: |
1648 | 650 | if_changed_from_revisions = None | 598 | if_changed_from_revisions = None |
1649 | 599 | |||
1650 | 600 | if substitute_branch_vars is not None: | ||
1651 | 601 | real_subsitute_branch_vars = lambda n, b, r: substitute_branch_vars(base_branch, n, b, r) | ||
1652 | 602 | else: | ||
1653 | 603 | real_subsitute_branch_vars = None | ||
1654 | 651 | changed_revisions = _resolve_revisions_recurse(base_branch, | 604 | changed_revisions = _resolve_revisions_recurse(base_branch, |
1656 | 652 | base_branch.substitute_branch_vars, | 605 | real_subsitute_branch_vars, |
1657 | 653 | if_changed_from=if_changed_from_revisions) | 606 | if_changed_from=if_changed_from_revisions) |
1658 | 654 | if not changed: | 607 | if not changed: |
1659 | 655 | changed = changed_revisions | 608 | changed = changed_revisions |
1660 | 656 | check_expanded_deb_version(base_branch) | ||
1661 | 657 | if if_changed_from is not None and not changed: | 609 | if if_changed_from is not None and not changed: |
1662 | 658 | return False | 610 | return False |
1663 | 659 | return True | 611 | return True |
1664 | @@ -984,66 +936,6 @@ | |||
1665 | 984 | self.deb_version = deb_version | 936 | self.deb_version = deb_version |
1666 | 985 | self.format = format | 937 | self.format = format |
1667 | 986 | 938 | ||
1668 | 987 | def substitute_branch_vars(self, branch_name, branch, revid): | ||
1669 | 988 | """Substitute the branch variables for the given branch name in deb_version. | ||
1670 | 989 | |||
1671 | 990 | Where deb_version has a place to substitute the revno for a branch | ||
1672 | 991 | this will substitute it for the given branch name. | ||
1673 | 992 | |||
1674 | 993 | :param branch_name: the name of the RecipeBranch to substitute. | ||
1675 | 994 | :param branch: Branch object for the branch | ||
1676 | 995 | :param revid: Revision id in the branch for which to return the revno | ||
1677 | 996 | """ | ||
1678 | 997 | if self.deb_version is None: | ||
1679 | 998 | return | ||
1680 | 999 | revno_var = RevnoVariable(branch_name, branch, revid) | ||
1681 | 1000 | self.deb_version = revno_var.replace(self.deb_version) | ||
1682 | 1001 | if self.format in (0.1, 0.2, 0.3): | ||
1683 | 1002 | return | ||
1684 | 1003 | svn_revno_var = SubversionRevnumVariable(branch_name, branch, revid) | ||
1685 | 1004 | self.deb_version = svn_revno_var.replace(self.deb_version) | ||
1686 | 1005 | git_commit_var = GitCommitVariable(branch_name, branch, revid) | ||
1687 | 1006 | self.deb_version = git_commit_var.replace(self.deb_version) | ||
1688 | 1007 | latest_tag_var = LatestTagVariable(branch_name, branch, revid) | ||
1689 | 1008 | self.deb_version = latest_tag_var.replace(self.deb_version) | ||
1690 | 1009 | revdate_var = RevdateVariable(branch_name, branch, revid) | ||
1691 | 1010 | self.deb_version = revdate_var.replace(self.deb_version) | ||
1692 | 1011 | revtime_var = RevtimeVariable(branch_name, branch, revid) | ||
1693 | 1012 | self.deb_version = revtime_var.replace(self.deb_version) | ||
1694 | 1013 | tree = branch.repository.revision_tree(revid) | ||
1695 | 1014 | cl_file_id = tree.path2id("debian/changelog") | ||
1696 | 1015 | if cl_file_id is not None: | ||
1697 | 1016 | tree.lock_read() | ||
1698 | 1017 | try: | ||
1699 | 1018 | cl = changelog.Changelog(tree.get_file(cl_file_id)) | ||
1700 | 1019 | self.substitute_changelog_vars(branch_name, cl) | ||
1701 | 1020 | finally: | ||
1702 | 1021 | tree.unlock() | ||
1703 | 1022 | |||
1704 | 1023 | def substitute_changelog_vars(self, branch_name, changelog): | ||
1705 | 1024 | """Substitute variables related from a changelog. | ||
1706 | 1025 | |||
1707 | 1026 | :param branch_name: Branch name (None for root branch) | ||
1708 | 1027 | :param changelog: Changelog object to use | ||
1709 | 1028 | """ | ||
1710 | 1029 | debupstream_var = DebUpstreamVariable.from_changelog(branch_name, changelog) | ||
1711 | 1030 | self.deb_version = debupstream_var.replace(self.deb_version) | ||
1712 | 1031 | debupstreambase_var = DebUpstreamBaseVariable.from_changelog( | ||
1713 | 1032 | branch_name, changelog) | ||
1714 | 1033 | self.deb_version = debupstreambase_var.replace(self.deb_version) | ||
1715 | 1034 | pkgversion_var = DebVersionVariable.from_changelog(branch_name, changelog) | ||
1716 | 1035 | self.deb_version = pkgversion_var.replace(self.deb_version) | ||
1717 | 1036 | |||
1718 | 1037 | def substitute_time(self, time): | ||
1719 | 1038 | """Substitute the time in to deb_version if needed. | ||
1720 | 1039 | |||
1721 | 1040 | :param time: a datetime.datetime with the desired time. | ||
1722 | 1041 | """ | ||
1723 | 1042 | if self.deb_version is None: | ||
1724 | 1043 | return | ||
1725 | 1044 | self.deb_version = TimeVariable(time).replace(self.deb_version) | ||
1726 | 1045 | self.deb_version = DateVariable(time).replace(self.deb_version) | ||
1727 | 1046 | |||
1728 | 1047 | def _add_child_branches_to_manifest(self, child_branches, indent_level): | 939 | def _add_child_branches_to_manifest(self, child_branches, indent_level): |
1729 | 1048 | manifest = "" | 940 | manifest = "" |
1730 | 1049 | for instruction in child_branches: | 941 | for instruction in child_branches: |
1731 | 1050 | 942 | ||
1732 | === modified file 'setup.py' | |||
1733 | --- setup.py 2011-11-10 13:34:01 +0000 | |||
1734 | +++ setup.py 2012-06-10 06:51:21 +0000 | |||
1735 | @@ -1,10 +1,15 @@ | |||
1736 | 1 | #!/usr/bin/python | 1 | #!/usr/bin/python |
1737 | 2 | 2 | ||
1738 | 3 | from info import * | ||
1739 | 4 | |||
1740 | 3 | from distutils.core import setup | 5 | from distutils.core import setup |
1741 | 4 | 6 | ||
1742 | 5 | if __name__ == '__main__': | 7 | if __name__ == '__main__': |
1743 | 8 | version = bzr_plugin_version[:3] | ||
1744 | 9 | version_string = ".".join([str(x) for x in version]) | ||
1745 | 10 | |||
1746 | 6 | setup(name="bzr-builder", | 11 | setup(name="bzr-builder", |
1748 | 7 | version="0.7.2", | 12 | version=version_string, |
1749 | 8 | description="Turn a recipe in to a bzr branch", | 13 | description="Turn a recipe in to a bzr branch", |
1750 | 9 | author="James Westby", | 14 | author="James Westby", |
1751 | 10 | author_email="james.westby@canonical.com", | 15 | author_email="james.westby@canonical.com", |
1752 | 11 | 16 | ||
1753 | === modified file 'tests/__init__.py' | |||
1754 | --- tests/__init__.py 2011-11-10 13:29:10 +0000 | |||
1755 | +++ tests/__init__.py 2012-06-10 06:51:21 +0000 | |||
1756 | @@ -45,7 +45,8 @@ | |||
1757 | 45 | suite = TestSuite() | 45 | suite = TestSuite() |
1758 | 46 | testmod_names = [ | 46 | testmod_names = [ |
1759 | 47 | 'blackbox', | 47 | 'blackbox', |
1761 | 48 | 'ppa', | 48 | 'deb_util', |
1762 | 49 | 'deb_version', | ||
1763 | 49 | 'recipe', | 50 | 'recipe', |
1764 | 50 | ] | 51 | ] |
1765 | 51 | suite.addTest(loader.loadTestsFromModuleNames(["%s.test_%s" % (__name__, i) | 52 | suite.addTest(loader.loadTestsFromModuleNames(["%s.test_%s" % (__name__, i) |
1766 | 52 | 53 | ||
1767 | === modified file 'tests/test_blackbox.py' | |||
1768 | --- tests/test_blackbox.py 2011-11-10 13:29:10 +0000 | |||
1769 | +++ tests/test_blackbox.py 2012-06-10 06:51:21 +0000 | |||
1770 | @@ -26,13 +26,13 @@ | |||
1771 | 26 | ) | 26 | ) |
1772 | 27 | from bzrlib.branch import Branch | 27 | from bzrlib.branch import Branch |
1773 | 28 | from bzrlib.tests import ( | 28 | from bzrlib.tests import ( |
1781 | 29 | TestCaseWithTransport, | 29 | TestCaseWithTransport, |
1782 | 30 | TestSkipped, | 30 | ) |
1783 | 31 | ) | 31 | |
1784 | 32 | from bzrlib.tests.features import Feature | 32 | from bzrlib.plugins.builder.tests import ( |
1785 | 33 | 33 | Feature, | |
1786 | 34 | 34 | PristineTarFeature, | |
1787 | 35 | from bzrlib.plugins.builder.tests import PristineTarFeature | 35 | ) |
1788 | 36 | 36 | ||
1789 | 37 | try: | 37 | try: |
1790 | 38 | from debian import changelog | 38 | from debian import changelog |
1791 | @@ -359,7 +359,7 @@ | |||
1792 | 359 | new_cl_contents = ("package (1) unstable; urgency=low\n\n" | 359 | new_cl_contents = ("package (1) unstable; urgency=low\n\n" |
1793 | 360 | " * Auto build.\n\n -- M. Maintainer <maint@maint.org> ") | 360 | " * Auto build.\n\n -- M. Maintainer <maint@maint.org> ") |
1794 | 361 | actual_cl_contents = self._get_file_contents( | 361 | actual_cl_contents = self._get_file_contents( |
1796 | 362 | "working/package-1/debian/changelog") | 362 | "working/test-1/debian/changelog") |
1797 | 363 | self.assertStartsWith(actual_cl_contents, new_cl_contents) | 363 | self.assertStartsWith(actual_cl_contents, new_cl_contents) |
1798 | 364 | for fn in os.listdir("working"): | 364 | for fn in os.listdir("working"): |
1799 | 365 | self.assertFalse(fn.endswith(".changes")) | 365 | self.assertFalse(fn.endswith(".changes")) |
1800 | @@ -381,7 +381,7 @@ | |||
1801 | 381 | def test_cmd_dailydeb_with_version_from_changelog(self): | 381 | def test_cmd_dailydeb_with_version_from_changelog(self): |
1802 | 382 | self.requireFeature(NotUnderFakeRootFeature) | 382 | self.requireFeature(NotUnderFakeRootFeature) |
1803 | 383 | self.make_simple_package("source") | 383 | self.make_simple_package("source") |
1805 | 384 | self.build_tree_contents([("test.recipe", "# bzr-builder format 0.1 " | 384 | self.build_tree_contents([("test.recipe", "# bzr-builder format 0.4 " |
1806 | 385 | "deb-version {debversion}-2\nsource 1\n")]) | 385 | "deb-version {debversion}-2\nsource 1\n")]) |
1807 | 386 | out, err = self.run_bzr( | 386 | out, err = self.run_bzr( |
1808 | 387 | "dailydeb --allow-fallback-to-native -q test.recipe working") | 387 | "dailydeb --allow-fallback-to-native -q test.recipe working") |
1809 | 388 | 388 | ||
1810 | === added file 'tests/test_deb_util.py' | |||
1811 | --- tests/test_deb_util.py 1970-01-01 00:00:00 +0000 | |||
1812 | +++ tests/test_deb_util.py 2012-06-10 06:51:21 +0000 | |||
1813 | @@ -0,0 +1,28 @@ | |||
1814 | 1 | # bzr-builder: a bzr plugin to construct trees based on recipes | ||
1815 | 2 | # Copyright 2009 Canonical Ltd. | ||
1816 | 3 | |||
1817 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
1818 | 5 | # under the terms of the GNU General Public License version 3, as published | ||
1819 | 6 | # by the Free Software Foundation. | ||
1820 | 7 | |||
1821 | 8 | # This program is distributed in the hope that it will be useful, but | ||
1822 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1823 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1824 | 11 | # PURPOSE. See the GNU General Public License for more details. | ||
1825 | 12 | |||
1826 | 13 | # You should have received a copy of the GNU General Public License along | ||
1827 | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1828 | 15 | |||
1829 | 16 | from bzrlib.plugins.builder.deb_util import target_from_dput | ||
1830 | 17 | from bzrlib.tests import ( | ||
1831 | 18 | TestCase, | ||
1832 | 19 | ) | ||
1833 | 20 | |||
1834 | 21 | |||
1835 | 22 | class TestTargetFromDPut(TestCase): | ||
1836 | 23 | |||
1837 | 24 | def test_default_ppa(self): | ||
1838 | 25 | self.assertEqual(('team-name', 'ppa'), target_from_dput('ppa:team-name')) | ||
1839 | 26 | |||
1840 | 27 | def test_named_ppa(self): | ||
1841 | 28 | self.assertEqual(('team', 'ppa2'), target_from_dput('ppa:team/ppa2')) | ||
1842 | 0 | 29 | ||
1843 | === added file 'tests/test_deb_version.py' | |||
1844 | --- tests/test_deb_version.py 1970-01-01 00:00:00 +0000 | |||
1845 | +++ tests/test_deb_version.py 2012-06-10 06:51:21 +0000 | |||
1846 | @@ -0,0 +1,441 @@ | |||
1847 | 1 | # bzr-builder: a bzr plugin to constuct trees based on recipes | ||
1848 | 2 | # Copyright 2009-2011 Canonical Ltd. | ||
1849 | 3 | |||
1850 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
1851 | 5 | # under the terms of the GNU General Public License version 3, as published | ||
1852 | 6 | # by the Free Software Foundation. | ||
1853 | 7 | |||
1854 | 8 | # This program is distributed in the hope that it will be useful, but | ||
1855 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1856 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1857 | 11 | # PURPOSE. See the GNU General Public License for more details. | ||
1858 | 12 | |||
1859 | 13 | # You should have received a copy of the GNU General Public License along | ||
1860 | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1861 | 15 | |||
1862 | 16 | import datetime | ||
1863 | 17 | import textwrap | ||
1864 | 18 | |||
1865 | 19 | from bzrlib import ( | ||
1866 | 20 | errors, | ||
1867 | 21 | ) | ||
1868 | 22 | from bzrlib.tests import ( | ||
1869 | 23 | TestCase, | ||
1870 | 24 | TestCaseWithTransport, | ||
1871 | 25 | ) | ||
1872 | 26 | from bzrlib.plugins.builder.deb_version import ( | ||
1873 | 27 | DebUpstreamBaseVariable, | ||
1874 | 28 | DebUpstreamVariable, | ||
1875 | 29 | DebVersionVariable, | ||
1876 | 30 | SubstitutionUnavailable, | ||
1877 | 31 | check_expanded_deb_version, | ||
1878 | 32 | version_extract_base, | ||
1879 | 33 | substitute_branch_vars, | ||
1880 | 34 | substitute_time, | ||
1881 | 35 | ) | ||
1882 | 36 | from bzrlib.plugins.builder.recipe import ( | ||
1883 | 37 | BaseRecipeBranch, | ||
1884 | 38 | RecipeBranch, | ||
1885 | 39 | resolve_revisions, | ||
1886 | 40 | ) | ||
1887 | 41 | |||
1888 | 42 | try: | ||
1889 | 43 | from debian import changelog | ||
1890 | 44 | except ImportError: | ||
1891 | 45 | # In older versions of python-debian the main package was named | ||
1892 | 46 | # debian_bundle | ||
1893 | 47 | from debian_bundle import changelog | ||
1894 | 48 | |||
1895 | 49 | |||
1896 | 50 | class ResolveRevisionsTests(TestCaseWithTransport): | ||
1897 | 51 | |||
1898 | 52 | def test_unchanged(self): | ||
1899 | 53 | source =self.make_branch_and_tree("source") | ||
1900 | 54 | revid = source.commit("one") | ||
1901 | 55 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2, revspec="1") | ||
1902 | 56 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
1903 | 57 | revspec="revid:%s" % revid) | ||
1904 | 58 | self.assertEqual(False, resolve_revisions(branch1, | ||
1905 | 59 | if_changed_from=branch2, | ||
1906 | 60 | substitute_branch_vars=substitute_branch_vars)) | ||
1907 | 61 | self.assertEqual("source", branch1.url) | ||
1908 | 62 | self.assertEqual(revid, branch1.revid) | ||
1909 | 63 | self.assertEqual("1", branch1.revspec) | ||
1910 | 64 | self.assertEqual("1", branch1.deb_version) | ||
1911 | 65 | |||
1912 | 66 | def test_unchanged_not_explicit(self): | ||
1913 | 67 | source =self.make_branch_and_tree("source") | ||
1914 | 68 | revid = source.commit("one") | ||
1915 | 69 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
1916 | 70 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
1917 | 71 | revspec="revid:%s" % revid) | ||
1918 | 72 | self.assertEqual(False, resolve_revisions(branch1, | ||
1919 | 73 | if_changed_from=branch2, | ||
1920 | 74 | substitute_branch_vars=substitute_branch_vars)) | ||
1921 | 75 | self.assertEqual("source", branch1.url) | ||
1922 | 76 | self.assertEqual(revid, branch1.revid) | ||
1923 | 77 | self.assertEqual(None, branch1.revspec) | ||
1924 | 78 | self.assertEqual("1", branch1.deb_version) | ||
1925 | 79 | |||
1926 | 80 | def test_unchanged_multilevel(self): | ||
1927 | 81 | source =self.make_branch_and_tree("source") | ||
1928 | 82 | revid = source.commit("one") | ||
1929 | 83 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
1930 | 84 | branch2 = RecipeBranch("nested1", "source") | ||
1931 | 85 | branch3 = RecipeBranch("nested2", "source") | ||
1932 | 86 | branch2.nest_branch("bar", branch3) | ||
1933 | 87 | branch1.nest_branch("foo", branch2) | ||
1934 | 88 | branch4 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
1935 | 89 | revspec="revid:%s" % revid) | ||
1936 | 90 | branch5 = RecipeBranch("nested1", "source", | ||
1937 | 91 | revspec="revid:%s" % revid) | ||
1938 | 92 | branch6 = RecipeBranch("nested2", "source", | ||
1939 | 93 | revspec="revid:%s" % revid) | ||
1940 | 94 | branch5.nest_branch("bar", branch6) | ||
1941 | 95 | branch4.nest_branch("foo", branch5) | ||
1942 | 96 | self.assertEqual(False, resolve_revisions(branch1, | ||
1943 | 97 | if_changed_from=branch4, | ||
1944 | 98 | substitute_branch_vars=substitute_branch_vars)) | ||
1945 | 99 | self.assertEqual("source", branch1.url) | ||
1946 | 100 | self.assertEqual(revid, branch1.revid) | ||
1947 | 101 | self.assertEqual(None, branch1.revspec) | ||
1948 | 102 | self.assertEqual("1", branch1.deb_version) | ||
1949 | 103 | |||
1950 | 104 | def test_changed(self): | ||
1951 | 105 | source =self.make_branch_and_tree("source") | ||
1952 | 106 | revid = source.commit("one") | ||
1953 | 107 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2, revspec="1") | ||
1954 | 108 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
1955 | 109 | revspec="revid:foo") | ||
1956 | 110 | self.assertEqual(True, resolve_revisions(branch1, | ||
1957 | 111 | if_changed_from=branch2, | ||
1958 | 112 | substitute_branch_vars=substitute_branch_vars)) | ||
1959 | 113 | self.assertEqual("source", branch1.url) | ||
1960 | 114 | self.assertEqual(revid, branch1.revid) | ||
1961 | 115 | self.assertEqual("1", branch1.revspec) | ||
1962 | 116 | self.assertEqual("1", branch1.deb_version) | ||
1963 | 117 | |||
1964 | 118 | def test_changed_shape(self): | ||
1965 | 119 | source =self.make_branch_and_tree("source") | ||
1966 | 120 | revid = source.commit("one") | ||
1967 | 121 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2, revspec="1") | ||
1968 | 122 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
1969 | 123 | revspec="revid:%s" % revid) | ||
1970 | 124 | branch3 = RecipeBranch("nested", "source") | ||
1971 | 125 | branch1.nest_branch("foo", branch3) | ||
1972 | 126 | self.assertEqual(True, resolve_revisions(branch1, | ||
1973 | 127 | if_changed_from=branch2, | ||
1974 | 128 | substitute_branch_vars=substitute_branch_vars)) | ||
1975 | 129 | self.assertEqual("source", branch1.url) | ||
1976 | 130 | self.assertEqual(revid, branch1.revid) | ||
1977 | 131 | self.assertEqual("1", branch1.revspec) | ||
1978 | 132 | self.assertEqual("1", branch1.deb_version) | ||
1979 | 133 | |||
1980 | 134 | def test_changed_command(self): | ||
1981 | 135 | source =self.make_branch_and_tree("source") | ||
1982 | 136 | source.commit("one") | ||
1983 | 137 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
1984 | 138 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
1985 | 139 | branch1.run_command("touch test1") | ||
1986 | 140 | branch2.run_command("touch test2") | ||
1987 | 141 | self.assertEqual(True, resolve_revisions(branch1, | ||
1988 | 142 | if_changed_from=branch2, | ||
1989 | 143 | substitute_branch_vars=substitute_branch_vars)) | ||
1990 | 144 | self.assertEqual("source", branch1.url) | ||
1991 | 145 | |||
1992 | 146 | def test_unchanged_command(self): | ||
1993 | 147 | source =self.make_branch_and_tree("source") | ||
1994 | 148 | source.commit("one") | ||
1995 | 149 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
1996 | 150 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
1997 | 151 | branch1.run_command("touch test1") | ||
1998 | 152 | branch2.run_command("touch test1") | ||
1999 | 153 | self.assertEqual(False, resolve_revisions(branch1, | ||
2000 | 154 | if_changed_from=branch2, | ||
2001 | 155 | substitute_branch_vars=substitute_branch_vars)) | ||
2002 | 156 | self.assertEqual("source", branch1.url) | ||
2003 | 157 | |||
2004 | 158 | def test_substitute(self): | ||
2005 | 159 | source =self.make_branch_and_tree("source") | ||
2006 | 160 | revid1 = source.commit("one") | ||
2007 | 161 | source.commit("two") | ||
2008 | 162 | branch1 = BaseRecipeBranch("source", | ||
2009 | 163 | "{revno}-{revno:packaging}", 0.2, revspec="1") | ||
2010 | 164 | branch2 = RecipeBranch("packaging", "source") | ||
2011 | 165 | branch1.nest_branch("debian", branch2) | ||
2012 | 166 | self.assertEqual(True, resolve_revisions(branch1, | ||
2013 | 167 | substitute_branch_vars=substitute_branch_vars)) | ||
2014 | 168 | self.assertEqual("source", branch1.url) | ||
2015 | 169 | self.assertEqual(revid1, branch1.revid) | ||
2016 | 170 | self.assertEqual("1", branch1.revspec) | ||
2017 | 171 | self.assertEqual("1-2", branch1.deb_version) | ||
2018 | 172 | |||
2019 | 173 | def test_substitute_supports_debupstream(self): | ||
2020 | 174 | # resolve_revisions should leave debupstream parameters alone and not | ||
2021 | 175 | # complain. | ||
2022 | 176 | source =self.make_branch_and_tree("source") | ||
2023 | 177 | source.commit("one") | ||
2024 | 178 | source.commit("two") | ||
2025 | 179 | branch1 = BaseRecipeBranch("source", "{debupstream}-{revno}", 0.2) | ||
2026 | 180 | resolve_revisions(branch1, | ||
2027 | 181 | substitute_branch_vars=substitute_branch_vars) | ||
2028 | 182 | self.assertEqual("{debupstream}-2", branch1.deb_version) | ||
2029 | 183 | |||
2030 | 184 | def test_subsitute_not_fully_expanded(self): | ||
2031 | 185 | source =self.make_branch_and_tree("source") | ||
2032 | 186 | source.commit("one") | ||
2033 | 187 | source.commit("two") | ||
2034 | 188 | branch1 = BaseRecipeBranch("source", "{revno:packaging}", 0.2) | ||
2035 | 189 | resolve_revisions(branch1, substitute_branch_vars=substitute_branch_vars) | ||
2036 | 190 | self.assertRaises(errors.BzrCommandError, check_expanded_deb_version, branch1) | ||
2037 | 191 | |||
2038 | 192 | def test_substitute_svn_not_svn(self): | ||
2039 | 193 | br = self.make_branch("source") | ||
2040 | 194 | source = br.create_checkout("checkout") | ||
2041 | 195 | source.commit("one") | ||
2042 | 196 | source.commit("two") | ||
2043 | 197 | branch1 = BaseRecipeBranch("source", "foo-{svn-revno}", 0.4) | ||
2044 | 198 | e = self.assertRaises(errors.BzrCommandError, resolve_revisions, | ||
2045 | 199 | branch1, None, substitute_branch_vars) | ||
2046 | 200 | self.assertTrue(str(e).startswith("unable to expand {svn-revno} "), | ||
2047 | 201 | e) | ||
2048 | 202 | |||
2049 | 203 | def test_substitute_svn(self): | ||
2050 | 204 | br = self.make_branch("source") | ||
2051 | 205 | source = br.create_checkout("checkout") | ||
2052 | 206 | source.commit("one") | ||
2053 | 207 | source.commit("two", | ||
2054 | 208 | rev_id="svn-v4:be7e6eca-30d4-0310-a8e5-ac0d63af7070:trunk:5344") | ||
2055 | 209 | branch1 = BaseRecipeBranch("source", "foo-{svn-revno}", 0.4) | ||
2056 | 210 | resolve_revisions(branch1, substitute_branch_vars=substitute_branch_vars) | ||
2057 | 211 | self.assertEqual("foo-5344", branch1.deb_version) | ||
2058 | 212 | |||
2059 | 213 | def test_substitute_git_not_git(self): | ||
2060 | 214 | source = self.make_branch_and_tree("source") | ||
2061 | 215 | source.commit("one") | ||
2062 | 216 | source.commit("two") | ||
2063 | 217 | branch1 = BaseRecipeBranch("source", "foo-{git-commit}", 0.4) | ||
2064 | 218 | e = self.assertRaises(errors.BzrCommandError, resolve_revisions, | ||
2065 | 219 | branch1, None, substitute_branch_vars) | ||
2066 | 220 | self.assertTrue(str(e).startswith("unable to expand {git-commit} "), | ||
2067 | 221 | e) | ||
2068 | 222 | |||
2069 | 223 | def test_substitute_git(self): | ||
2070 | 224 | source = self.make_branch_and_tree("source") | ||
2071 | 225 | source.commit("one", | ||
2072 | 226 | rev_id="git-v1:a029d7b2cc83c26a53d8b2a24fa12c340fcfac58") | ||
2073 | 227 | branch1 = BaseRecipeBranch("source", "foo-{git-commit}", 0.4) | ||
2074 | 228 | resolve_revisions(branch1, | ||
2075 | 229 | substitute_branch_vars=substitute_branch_vars) | ||
2076 | 230 | self.assertEqual("foo-a029d7b", branch1.deb_version) | ||
2077 | 231 | |||
2078 | 232 | def test_latest_tag(self): | ||
2079 | 233 | source = self.make_branch_and_tree("source") | ||
2080 | 234 | revid = source.commit("one") | ||
2081 | 235 | source.branch.tags.set_tag("millbank", revid) | ||
2082 | 236 | source.commit("two") | ||
2083 | 237 | branch1 = BaseRecipeBranch("source", "foo-{latest-tag}", 0.4) | ||
2084 | 238 | resolve_revisions(branch1, | ||
2085 | 239 | substitute_branch_vars=substitute_branch_vars) | ||
2086 | 240 | self.assertEqual("foo-millbank", branch1.deb_version) | ||
2087 | 241 | |||
2088 | 242 | def test_latest_tag_no_tag(self): | ||
2089 | 243 | source = self.make_branch_and_tree("source") | ||
2090 | 244 | revid = source.commit("one") | ||
2091 | 245 | source.commit("two") | ||
2092 | 246 | branch1 = BaseRecipeBranch("source", "foo-{latest-tag}", 0.4) | ||
2093 | 247 | e = self.assertRaises(errors.BzrCommandError, | ||
2094 | 248 | resolve_revisions, branch1, | ||
2095 | 249 | substitute_branch_vars=substitute_branch_vars) | ||
2096 | 250 | self.assertTrue(str(e).startswith("No tags set on branch None mainline"), | ||
2097 | 251 | e) | ||
2098 | 252 | |||
2099 | 253 | def test_substitute_revdate(self): | ||
2100 | 254 | br = self.make_branch("source") | ||
2101 | 255 | source = br.create_checkout("checkout") | ||
2102 | 256 | source.commit("one") | ||
2103 | 257 | source.commit("two", timestamp=1307708628, timezone=0) | ||
2104 | 258 | branch1 = BaseRecipeBranch("source", "foo-{revdate}", 0.4) | ||
2105 | 259 | resolve_revisions(branch1, | ||
2106 | 260 | substitute_branch_vars=substitute_branch_vars) | ||
2107 | 261 | self.assertEqual("foo-20110610", branch1.deb_version) | ||
2108 | 262 | |||
2109 | 263 | def test_substitute_revtime(self): | ||
2110 | 264 | br = self.make_branch("source") | ||
2111 | 265 | source = br.create_checkout("checkout") | ||
2112 | 266 | source.commit("one") | ||
2113 | 267 | source.commit("two", timestamp=1307708628, timezone=0) | ||
2114 | 268 | branch1 = BaseRecipeBranch("source", "foo-{revtime}", 0.4) | ||
2115 | 269 | resolve_revisions(branch1, | ||
2116 | 270 | substitute_branch_vars=substitute_branch_vars) | ||
2117 | 271 | self.assertEqual("foo-201106101223", branch1.deb_version) | ||
2118 | 272 | |||
2119 | 273 | |||
2120 | 274 | class DebUpstreamVariableTests(TestCase): | ||
2121 | 275 | |||
2122 | 276 | def write_changelog(self, version): | ||
2123 | 277 | contents = textwrap.dedent(""" | ||
2124 | 278 | package (%s) experimental; urgency=low | ||
2125 | 279 | |||
2126 | 280 | * Initial release. (Closes: #XXXXXX) | ||
2127 | 281 | |||
2128 | 282 | -- Jelmer Vernooij <jelmer@debian.org> Thu, 19 May 2011 10:07:41 +0100 | ||
2129 | 283 | """ % version)[1:] | ||
2130 | 284 | return changelog.Changelog(file=contents) | ||
2131 | 285 | |||
2132 | 286 | def test_empty_changelog(self): | ||
2133 | 287 | var = DebUpstreamVariable.from_changelog(None, changelog.Changelog()) | ||
2134 | 288 | self.assertRaises(SubstitutionUnavailable, var.get) | ||
2135 | 289 | |||
2136 | 290 | def test_version(self): | ||
2137 | 291 | var = DebUpstreamVariable.from_changelog(None, | ||
2138 | 292 | self.write_changelog("2.3")) | ||
2139 | 293 | self.assertEquals("2.3", var.get()) | ||
2140 | 294 | |||
2141 | 295 | def test_epoch(self): | ||
2142 | 296 | # The epoch is (currently) ignored by {debupstream}. | ||
2143 | 297 | var = DebUpstreamVariable.from_changelog(None, | ||
2144 | 298 | self.write_changelog("2:2.3")) | ||
2145 | 299 | self.assertEquals("2.3", var.get()) | ||
2146 | 300 | |||
2147 | 301 | def test_base_without_snapshot(self): | ||
2148 | 302 | var = DebUpstreamBaseVariable.from_changelog(None, | ||
2149 | 303 | self.write_changelog("2.4")) | ||
2150 | 304 | self.assertEquals("2.4+", var.get()) | ||
2151 | 305 | |||
2152 | 306 | def test_base_with_svn_snapshot(self): | ||
2153 | 307 | var = DebUpstreamBaseVariable.from_changelog(None, | ||
2154 | 308 | self.write_changelog("2.4~svn4")) | ||
2155 | 309 | self.assertEquals("2.4~", var.get()) | ||
2156 | 310 | |||
2157 | 311 | def test_base_with_bzr_snapshot(self): | ||
2158 | 312 | var = DebUpstreamBaseVariable.from_changelog(None, | ||
2159 | 313 | self.write_changelog("2.4+bzr343")) | ||
2160 | 314 | self.assertEquals("2.4+", var.get()) | ||
2161 | 315 | |||
2162 | 316 | |||
2163 | 317 | class VersionExtractBaseTests(TestCase): | ||
2164 | 318 | |||
2165 | 319 | def test_simple_extract(self): | ||
2166 | 320 | self.assertEquals("2.4", version_extract_base("2.4")) | ||
2167 | 321 | self.assertEquals("2.4+foobar", version_extract_base("2.4+foobar")) | ||
2168 | 322 | |||
2169 | 323 | def test_with_bzr(self): | ||
2170 | 324 | self.assertEquals("2.4+", version_extract_base("2.4+bzr32")) | ||
2171 | 325 | self.assertEquals("2.4~", version_extract_base("2.4~bzr32")) | ||
2172 | 326 | |||
2173 | 327 | def test_with_git(self): | ||
2174 | 328 | self.assertEquals("2.4+", version_extract_base("2.4+git20101010")) | ||
2175 | 329 | self.assertEquals("2.4~", version_extract_base("2.4~gitaabbccdd")) | ||
2176 | 330 | |||
2177 | 331 | def test_with_svn(self): | ||
2178 | 332 | self.assertEquals("2.4+", version_extract_base("2.4+svn45")) | ||
2179 | 333 | self.assertEquals("2.4~", version_extract_base("2.4~svn45")) | ||
2180 | 334 | |||
2181 | 335 | def test_with_dfsg(self): | ||
2182 | 336 | self.assertEquals("2.4+", version_extract_base("2.4+bzr32+dfsg1")) | ||
2183 | 337 | self.assertEquals("2.4~", version_extract_base("2.4~bzr32+dfsg.1")) | ||
2184 | 338 | self.assertEquals("2.4~", version_extract_base("2.4~bzr32.dfsg.1")) | ||
2185 | 339 | self.assertEquals("2.4~", version_extract_base("2.4~bzr32dfsg.1")) | ||
2186 | 340 | self.assertEquals("1.6~", version_extract_base("1.6~git20120320.dfsg.1")) | ||
2187 | 341 | |||
2188 | 342 | |||
2189 | 343 | class DebVersionVariableTests(TestCase): | ||
2190 | 344 | |||
2191 | 345 | def write_changelog(self, version): | ||
2192 | 346 | contents = textwrap.dedent(""" | ||
2193 | 347 | package (%s) experimental; urgency=low | ||
2194 | 348 | |||
2195 | 349 | * Initial release. (Closes: #XXXXXX) | ||
2196 | 350 | |||
2197 | 351 | -- Jelmer Vernooij <jelmer@debian.org> Thu, 19 May 2011 10:07:41 +0100 | ||
2198 | 352 | """ % version)[1:] | ||
2199 | 353 | return changelog.Changelog(file=contents) | ||
2200 | 354 | |||
2201 | 355 | def test_empty_changelog(self): | ||
2202 | 356 | var = DebVersionVariable.from_changelog(None, changelog.Changelog()) | ||
2203 | 357 | self.assertRaises(SubstitutionUnavailable, var.get) | ||
2204 | 358 | |||
2205 | 359 | def test_simple(self): | ||
2206 | 360 | var = DebVersionVariable.from_changelog( | ||
2207 | 361 | None, self.write_changelog("2.3-1")) | ||
2208 | 362 | self.assertEquals("2.3-1", var.get()) | ||
2209 | 363 | |||
2210 | 364 | def test_epoch(self): | ||
2211 | 365 | var = DebVersionVariable.from_changelog( | ||
2212 | 366 | None, self.write_changelog("4:2.3-1")) | ||
2213 | 367 | self.assertEquals("4:2.3-1", var.get()) | ||
2214 | 368 | |||
2215 | 369 | |||
2216 | 370 | class RecipeBranchTests(TestCaseWithTransport): | ||
2217 | 371 | |||
2218 | 372 | def test_substitute_time(self): | ||
2219 | 373 | time = datetime.datetime.utcfromtimestamp(1) | ||
2220 | 374 | base_branch = BaseRecipeBranch("base_url", "1-{time}", 0.2) | ||
2221 | 375 | substitute_time(base_branch, time) | ||
2222 | 376 | self.assertEqual("1-197001010000", base_branch.deb_version) | ||
2223 | 377 | substitute_time(base_branch, time) | ||
2224 | 378 | self.assertEqual("1-197001010000", base_branch.deb_version) | ||
2225 | 379 | |||
2226 | 380 | def test_substitute_date(self): | ||
2227 | 381 | time = datetime.datetime.utcfromtimestamp(1) | ||
2228 | 382 | base_branch = BaseRecipeBranch("base_url", "1-{date}", 0.2) | ||
2229 | 383 | substitute_time(base_branch, time) | ||
2230 | 384 | self.assertEqual("1-19700101", base_branch.deb_version) | ||
2231 | 385 | substitute_time(base_branch, time) | ||
2232 | 386 | self.assertEqual("1-19700101", base_branch.deb_version) | ||
2233 | 387 | |||
2234 | 388 | def test_substitute_branch_vars(self): | ||
2235 | 389 | base_branch = BaseRecipeBranch("base_url", "1", 0.2) | ||
2236 | 390 | wt = self.make_branch_and_tree("br") | ||
2237 | 391 | revid = wt.commit("acommit") | ||
2238 | 392 | substitute_branch_vars(base_branch, None, wt.branch, revid) | ||
2239 | 393 | self.assertEqual("1", base_branch.deb_version) | ||
2240 | 394 | substitute_branch_vars(base_branch, None, wt.branch, revid) | ||
2241 | 395 | self.assertEqual("1", base_branch.deb_version) | ||
2242 | 396 | base_branch = BaseRecipeBranch("base_url", "{revno}", 0.2) | ||
2243 | 397 | substitute_branch_vars(base_branch, None, wt.branch, revid) | ||
2244 | 398 | self.assertEqual("1", base_branch.deb_version) | ||
2245 | 399 | base_branch = BaseRecipeBranch("base_url", "{revno}", 0.2) | ||
2246 | 400 | substitute_branch_vars(base_branch, "foo", wt.branch, revid) | ||
2247 | 401 | self.assertEqual("{revno}", base_branch.deb_version) | ||
2248 | 402 | substitute_branch_vars(base_branch, "foo", wt.branch, revid) | ||
2249 | 403 | self.assertEqual("{revno}", base_branch.deb_version) | ||
2250 | 404 | base_branch = BaseRecipeBranch("base_url", "{revno:foo}", 0.2) | ||
2251 | 405 | substitute_branch_vars(base_branch, "foo", wt.branch, revid) | ||
2252 | 406 | self.assertEqual("1", base_branch.deb_version) | ||
2253 | 407 | |||
2254 | 408 | def test_substitute_branch_vars_debupstream(self): | ||
2255 | 409 | wt = self.make_branch_and_tree("br") | ||
2256 | 410 | revid1 = wt.commit("acommit") | ||
2257 | 411 | cl_contents = ("package (0.1-1) unstable; urgency=low\n * foo\n" | ||
2258 | 412 | " -- maint <maint@maint.org> Tue, 04 Aug 2009 " | ||
2259 | 413 | "10:03:10 +0100\n") | ||
2260 | 414 | self.build_tree_contents( | ||
2261 | 415 | [("br/debian/", ), ('br/debian/changelog', cl_contents)]) | ||
2262 | 416 | wt.add(['debian', 'debian/changelog']) | ||
2263 | 417 | revid2 = wt.commit("with changelog") | ||
2264 | 418 | base_branch = BaseRecipeBranch("base_url", "{debupstream}", 0.4) | ||
2265 | 419 | # No changelog file, so no substitution | ||
2266 | 420 | substitute_branch_vars(base_branch, None, wt.branch, revid1) | ||
2267 | 421 | self.assertEqual("{debupstream}", base_branch.deb_version) | ||
2268 | 422 | substitute_branch_vars(base_branch, None, wt.branch, revid2) | ||
2269 | 423 | self.assertEqual("0.1", base_branch.deb_version) | ||
2270 | 424 | base_branch = BaseRecipeBranch("base_url", "{debupstream:tehname}", 0.4) | ||
2271 | 425 | substitute_branch_vars(base_branch, "tehname", wt.branch, revid2) | ||
2272 | 426 | self.assertEqual("0.1", base_branch.deb_version) | ||
2273 | 427 | |||
2274 | 428 | def test_substitute_branch_vars_debupstream_pre_0_4(self): | ||
2275 | 429 | wt = self.make_branch_and_tree("br") | ||
2276 | 430 | cl_contents = ("package (0.1-1) unstable; urgency=low\n * foo\n" | ||
2277 | 431 | " -- maint <maint@maint.org> Tue, 04 Aug 2009 " | ||
2278 | 432 | "10:03:10 +0100\n") | ||
2279 | 433 | self.build_tree_contents( | ||
2280 | 434 | [("br/debian/", ), ('br/debian/changelog', cl_contents)]) | ||
2281 | 435 | wt.add(['debian', 'debian/changelog']) | ||
2282 | 436 | revid = wt.commit("with changelog") | ||
2283 | 437 | # In recipe format < 0.4 {debupstream} gets replaced from the resulting | ||
2284 | 438 | # tree, not from the branch vars. | ||
2285 | 439 | base_branch = BaseRecipeBranch("base_url", "{debupstream}", 0.2) | ||
2286 | 440 | substitute_branch_vars(base_branch, None, wt.branch, revid) | ||
2287 | 441 | self.assertEqual("{debupstream}", base_branch.deb_version) | ||
2288 | 0 | 442 | ||
2289 | === removed file 'tests/test_ppa.py' | |||
2290 | --- tests/test_ppa.py 2011-06-14 19:21:54 +0000 | |||
2291 | +++ tests/test_ppa.py 1970-01-01 00:00:00 +0000 | |||
2292 | @@ -1,28 +0,0 @@ | |||
2293 | 1 | # bzr-builder: a bzr plugin to construct trees based on recipes | ||
2294 | 2 | # Copyright 2009 Canonical Ltd. | ||
2295 | 3 | |||
2296 | 4 | # This program is free software: you can redistribute it and/or modify it | ||
2297 | 5 | # under the terms of the GNU General Public License version 3, as published | ||
2298 | 6 | # by the Free Software Foundation. | ||
2299 | 7 | |||
2300 | 8 | # This program is distributed in the hope that it will be useful, but | ||
2301 | 9 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
2302 | 10 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
2303 | 11 | # PURPOSE. See the GNU General Public License for more details. | ||
2304 | 12 | |||
2305 | 13 | # You should have received a copy of the GNU General Public License along | ||
2306 | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2307 | 15 | |||
2308 | 16 | from bzrlib.plugins.builder.cmds import target_from_dput | ||
2309 | 17 | from bzrlib.tests import ( | ||
2310 | 18 | TestCase, | ||
2311 | 19 | ) | ||
2312 | 20 | |||
2313 | 21 | |||
2314 | 22 | class TestTargetFromDPut(TestCase): | ||
2315 | 23 | |||
2316 | 24 | def test_default_ppa(self): | ||
2317 | 25 | self.assertEqual(('team-name', 'ppa'), target_from_dput('ppa:team-name')) | ||
2318 | 26 | |||
2319 | 27 | def test_named_ppa(self): | ||
2320 | 28 | self.assertEqual(('team', 'ppa2'), target_from_dput('ppa:team/ppa2')) | ||
2321 | 29 | 0 | ||
2322 | === modified file 'tests/test_recipe.py' | |||
2323 | --- tests/test_recipe.py 2011-07-21 13:30:56 +0000 | |||
2324 | +++ tests/test_recipe.py 2012-06-10 06:51:21 +0000 | |||
2325 | @@ -13,9 +13,7 @@ | |||
2326 | 13 | # You should have received a copy of the GNU General Public License along | 13 | # You should have received a copy of the GNU General Public License along |
2327 | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
2328 | 15 | 15 | ||
2329 | 16 | import datetime | ||
2330 | 17 | import os | 16 | import os |
2331 | 18 | import textwrap | ||
2332 | 19 | 17 | ||
2333 | 20 | from bzrlib import ( | 18 | from bzrlib import ( |
2334 | 21 | errors, | 19 | errors, |
2335 | @@ -23,41 +21,27 @@ | |||
2336 | 23 | workingtree, | 21 | workingtree, |
2337 | 24 | ) | 22 | ) |
2338 | 25 | from bzrlib.tests import ( | 23 | from bzrlib.tests import ( |
2339 | 26 | TestCase, | ||
2340 | 27 | TestCaseInTempDir, | 24 | TestCaseInTempDir, |
2341 | 28 | TestCaseWithTransport, | 25 | TestCaseWithTransport, |
2342 | 29 | ) | 26 | ) |
2343 | 30 | from bzrlib.plugins.builder.recipe import ( | 27 | from bzrlib.plugins.builder.recipe import ( |
2344 | 31 | BaseRecipeBranch, | 28 | BaseRecipeBranch, |
2345 | 32 | build_tree, | 29 | build_tree, |
2346 | 33 | DebUpstreamBaseVariable, | ||
2347 | 34 | DebUpstreamVariable, | ||
2348 | 35 | ensure_basedir, | 30 | ensure_basedir, |
2349 | 36 | InstructionParseError, | 31 | InstructionParseError, |
2350 | 37 | ForbiddenInstructionError, | 32 | ForbiddenInstructionError, |
2351 | 38 | MERGE_INSTRUCTION, | 33 | MERGE_INSTRUCTION, |
2352 | 39 | NEST_INSTRUCTION, | 34 | NEST_INSTRUCTION, |
2353 | 40 | NEST_PART_INSTRUCTION, | 35 | NEST_PART_INSTRUCTION, |
2354 | 41 | DebVersionVariable, | ||
2355 | 42 | pull_or_branch, | 36 | pull_or_branch, |
2356 | 43 | RecipeParser, | 37 | RecipeParser, |
2357 | 44 | RecipeBranch, | 38 | RecipeBranch, |
2358 | 45 | RecipeParseError, | 39 | RecipeParseError, |
2359 | 46 | resolve_revisions, | ||
2360 | 47 | RUN_INSTRUCTION, | 40 | RUN_INSTRUCTION, |
2361 | 48 | SAFE_INSTRUCTIONS, | 41 | SAFE_INSTRUCTIONS, |
2362 | 49 | SubstitutionUnavailable, | ||
2363 | 50 | USAGE, | 42 | USAGE, |
2364 | 51 | ) | 43 | ) |
2365 | 52 | 44 | ||
2366 | 53 | try: | ||
2367 | 54 | from debian import changelog | ||
2368 | 55 | except ImportError: | ||
2369 | 56 | # In older versions of python-debian the main package was named | ||
2370 | 57 | # debian_bundle | ||
2371 | 58 | from debian_bundle import changelog | ||
2372 | 59 | |||
2373 | 60 | |||
2374 | 61 | class RecipeParserTests(TestCaseInTempDir): | 45 | class RecipeParserTests(TestCaseInTempDir): |
2375 | 62 | 46 | ||
2376 | 63 | deb_version = "0.1-{revno}" | 47 | deb_version = "0.1-{revno}" |
2377 | @@ -654,6 +638,33 @@ | |||
2378 | 654 | self.assertEqual(source1_rev_id, base_branch.revid) | 638 | self.assertEqual(source1_rev_id, base_branch.revid) |
2379 | 655 | self.assertEqual(source2_rev_id, merged_branch.revid) | 639 | self.assertEqual(source2_rev_id, merged_branch.revid) |
2380 | 656 | 640 | ||
2381 | 641 | def test_build_tree_implicit_dir(self): | ||
2382 | 642 | # Branches nested into non-existant directories trigger creation of | ||
2383 | 643 | # those directories. | ||
2384 | 644 | source1 = self.make_source_branch("source1") | ||
2385 | 645 | source2 = self.make_source_branch("source2") | ||
2386 | 646 | source3 = self.make_source_branch("source3") | ||
2387 | 647 | self.build_tree_contents([ | ||
2388 | 648 | ("source2/file", "new file"), | ||
2389 | 649 | ("source3/yetanotherfile", "rugby")]) | ||
2390 | 650 | source2.add(["file"]) | ||
2391 | 651 | source2.commit("two") | ||
2392 | 652 | source3.add(["yetanotherfile"]) | ||
2393 | 653 | source3.commit("three") | ||
2394 | 654 | base_branch = BaseRecipeBranch("source1", "1", 0.4) | ||
2395 | 655 | merged_branch_2 = RecipeBranch("merged", "source2") | ||
2396 | 656 | # Merge source2 into path implicit/b | ||
2397 | 657 | base_branch.nest_part_branch(merged_branch_2, ".", | ||
2398 | 658 | target_subdir="implicit/b") | ||
2399 | 659 | # Merge source3 into path implicit/moreimplicit/c | ||
2400 | 660 | merged_branch_3 = RecipeBranch("merged", "source3") | ||
2401 | 661 | base_branch.nest_part_branch(merged_branch_3, ".", | ||
2402 | 662 | target_subdir="moreimplicit/another/c") | ||
2403 | 663 | build_tree(base_branch, "target") | ||
2404 | 664 | self.check_file_contents("target/implicit/b/file", "new file") | ||
2405 | 665 | self.check_file_contents("target/moreimplicit/another/c/yetanotherfile", | ||
2406 | 666 | "rugby") | ||
2407 | 667 | |||
2408 | 657 | def test_build_tree_nest_part(self): | 668 | def test_build_tree_nest_part(self): |
2409 | 658 | """A recipe can specify a merge of just part of an unrelated tree.""" | 669 | """A recipe can specify a merge of just part of an unrelated tree.""" |
2410 | 659 | source1 = self.make_source_branch("source1") | 670 | source1 = self.make_source_branch("source1") |
2411 | @@ -723,7 +734,7 @@ | |||
2412 | 723 | self.assertPathExists("target") | 734 | self.assertPathExists("target") |
2413 | 724 | tree = workingtree.WorkingTree.open("target") | 735 | tree = workingtree.WorkingTree.open("target") |
2414 | 725 | last_revid = tree.last_revision() | 736 | last_revid = tree.last_revision() |
2416 | 726 | previous_revid = tree.branch.revision_history()[-2] | 737 | previous_revid = tree.branch.repository.get_revision(tree.branch.last_revision()).parent_ids[0] |
2417 | 727 | last_revtree = tree.branch.repository.revision_tree(last_revid) | 738 | last_revtree = tree.branch.repository.revision_tree(last_revid) |
2418 | 728 | previous_revtree = tree.branch.repository.revision_tree(previous_revid) | 739 | previous_revtree = tree.branch.repository.revision_tree(previous_revid) |
2419 | 729 | self.assertEqual([previous_revid, source3_rev_id], | 740 | self.assertEqual([previous_revid, source3_rev_id], |
2420 | @@ -932,214 +943,6 @@ | |||
2421 | 932 | "revspec at the end of the merge line?")) | 943 | "revspec at the end of the merge line?")) |
2422 | 933 | 944 | ||
2423 | 934 | 945 | ||
2424 | 935 | class ResolveRevisionsTests(TestCaseWithTransport): | ||
2425 | 936 | |||
2426 | 937 | def test_unchanged(self): | ||
2427 | 938 | source =self.make_branch_and_tree("source") | ||
2428 | 939 | revid = source.commit("one") | ||
2429 | 940 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2, revspec="1") | ||
2430 | 941 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
2431 | 942 | revspec="revid:%s" % revid) | ||
2432 | 943 | self.assertEqual(False, resolve_revisions(branch1, | ||
2433 | 944 | if_changed_from=branch2)) | ||
2434 | 945 | self.assertEqual("source", branch1.url) | ||
2435 | 946 | self.assertEqual(revid, branch1.revid) | ||
2436 | 947 | self.assertEqual("1", branch1.revspec) | ||
2437 | 948 | self.assertEqual("1", branch1.deb_version) | ||
2438 | 949 | |||
2439 | 950 | def test_unchanged_not_explicit(self): | ||
2440 | 951 | source =self.make_branch_and_tree("source") | ||
2441 | 952 | revid = source.commit("one") | ||
2442 | 953 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
2443 | 954 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
2444 | 955 | revspec="revid:%s" % revid) | ||
2445 | 956 | self.assertEqual(False, resolve_revisions(branch1, | ||
2446 | 957 | if_changed_from=branch2)) | ||
2447 | 958 | self.assertEqual("source", branch1.url) | ||
2448 | 959 | self.assertEqual(revid, branch1.revid) | ||
2449 | 960 | self.assertEqual(None, branch1.revspec) | ||
2450 | 961 | self.assertEqual("1", branch1.deb_version) | ||
2451 | 962 | |||
2452 | 963 | def test_unchanged_multilevel(self): | ||
2453 | 964 | source =self.make_branch_and_tree("source") | ||
2454 | 965 | revid = source.commit("one") | ||
2455 | 966 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
2456 | 967 | branch2 = RecipeBranch("nested1", "source") | ||
2457 | 968 | branch3 = RecipeBranch("nested2", "source") | ||
2458 | 969 | branch2.nest_branch("bar", branch3) | ||
2459 | 970 | branch1.nest_branch("foo", branch2) | ||
2460 | 971 | branch4 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
2461 | 972 | revspec="revid:%s" % revid) | ||
2462 | 973 | branch5 = RecipeBranch("nested1", "source", | ||
2463 | 974 | revspec="revid:%s" % revid) | ||
2464 | 975 | branch6 = RecipeBranch("nested2", "source", | ||
2465 | 976 | revspec="revid:%s" % revid) | ||
2466 | 977 | branch5.nest_branch("bar", branch6) | ||
2467 | 978 | branch4.nest_branch("foo", branch5) | ||
2468 | 979 | self.assertEqual(False, resolve_revisions(branch1, | ||
2469 | 980 | if_changed_from=branch4)) | ||
2470 | 981 | self.assertEqual("source", branch1.url) | ||
2471 | 982 | self.assertEqual(revid, branch1.revid) | ||
2472 | 983 | self.assertEqual(None, branch1.revspec) | ||
2473 | 984 | self.assertEqual("1", branch1.deb_version) | ||
2474 | 985 | |||
2475 | 986 | def test_changed(self): | ||
2476 | 987 | source =self.make_branch_and_tree("source") | ||
2477 | 988 | revid = source.commit("one") | ||
2478 | 989 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2, revspec="1") | ||
2479 | 990 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
2480 | 991 | revspec="revid:foo") | ||
2481 | 992 | self.assertEqual(True, resolve_revisions(branch1, | ||
2482 | 993 | if_changed_from=branch2)) | ||
2483 | 994 | self.assertEqual("source", branch1.url) | ||
2484 | 995 | self.assertEqual(revid, branch1.revid) | ||
2485 | 996 | self.assertEqual("1", branch1.revspec) | ||
2486 | 997 | self.assertEqual("1", branch1.deb_version) | ||
2487 | 998 | |||
2488 | 999 | def test_changed_shape(self): | ||
2489 | 1000 | source =self.make_branch_and_tree("source") | ||
2490 | 1001 | revid = source.commit("one") | ||
2491 | 1002 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2, revspec="1") | ||
2492 | 1003 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2, | ||
2493 | 1004 | revspec="revid:%s" % revid) | ||
2494 | 1005 | branch3 = RecipeBranch("nested", "source") | ||
2495 | 1006 | branch1.nest_branch("foo", branch3) | ||
2496 | 1007 | self.assertEqual(True, resolve_revisions(branch1, | ||
2497 | 1008 | if_changed_from=branch2)) | ||
2498 | 1009 | self.assertEqual("source", branch1.url) | ||
2499 | 1010 | self.assertEqual(revid, branch1.revid) | ||
2500 | 1011 | self.assertEqual("1", branch1.revspec) | ||
2501 | 1012 | self.assertEqual("1", branch1.deb_version) | ||
2502 | 1013 | |||
2503 | 1014 | def test_changed_command(self): | ||
2504 | 1015 | source =self.make_branch_and_tree("source") | ||
2505 | 1016 | source.commit("one") | ||
2506 | 1017 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
2507 | 1018 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
2508 | 1019 | branch1.run_command("touch test1") | ||
2509 | 1020 | branch2.run_command("touch test2") | ||
2510 | 1021 | self.assertEqual(True, resolve_revisions(branch1, | ||
2511 | 1022 | if_changed_from=branch2)) | ||
2512 | 1023 | self.assertEqual("source", branch1.url) | ||
2513 | 1024 | |||
2514 | 1025 | def test_unchanged_command(self): | ||
2515 | 1026 | source =self.make_branch_and_tree("source") | ||
2516 | 1027 | source.commit("one") | ||
2517 | 1028 | branch1 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
2518 | 1029 | branch2 = BaseRecipeBranch("source", "{revno}", 0.2) | ||
2519 | 1030 | branch1.run_command("touch test1") | ||
2520 | 1031 | branch2.run_command("touch test1") | ||
2521 | 1032 | self.assertEqual(False, resolve_revisions(branch1, | ||
2522 | 1033 | if_changed_from=branch2)) | ||
2523 | 1034 | self.assertEqual("source", branch1.url) | ||
2524 | 1035 | |||
2525 | 1036 | def test_substitute(self): | ||
2526 | 1037 | source =self.make_branch_and_tree("source") | ||
2527 | 1038 | revid1 = source.commit("one") | ||
2528 | 1039 | source.commit("two") | ||
2529 | 1040 | branch1 = BaseRecipeBranch("source", | ||
2530 | 1041 | "{revno}-{revno:packaging}", 0.2, revspec="1") | ||
2531 | 1042 | branch2 = RecipeBranch("packaging", "source") | ||
2532 | 1043 | branch1.nest_branch("debian", branch2) | ||
2533 | 1044 | self.assertEqual(True, resolve_revisions(branch1)) | ||
2534 | 1045 | self.assertEqual("source", branch1.url) | ||
2535 | 1046 | self.assertEqual(revid1, branch1.revid) | ||
2536 | 1047 | self.assertEqual("1", branch1.revspec) | ||
2537 | 1048 | self.assertEqual("1-2", branch1.deb_version) | ||
2538 | 1049 | |||
2539 | 1050 | def test_substitute_supports_debupstream(self): | ||
2540 | 1051 | # resolve_revisions should leave debupstream parameters alone and not | ||
2541 | 1052 | # complain. | ||
2542 | 1053 | source =self.make_branch_and_tree("source") | ||
2543 | 1054 | source.commit("one") | ||
2544 | 1055 | source.commit("two") | ||
2545 | 1056 | branch1 = BaseRecipeBranch("source", "{debupstream}-{revno}", 0.2) | ||
2546 | 1057 | resolve_revisions(branch1) | ||
2547 | 1058 | self.assertEqual("{debupstream}-2", branch1.deb_version) | ||
2548 | 1059 | |||
2549 | 1060 | def test_subsitute_not_fully_expanded(self): | ||
2550 | 1061 | source =self.make_branch_and_tree("source") | ||
2551 | 1062 | source.commit("one") | ||
2552 | 1063 | source.commit("two") | ||
2553 | 1064 | branch1 = BaseRecipeBranch("source", "{revno:packaging}", 0.2) | ||
2554 | 1065 | self.assertRaises(errors.BzrCommandError, resolve_revisions, branch1) | ||
2555 | 1066 | |||
2556 | 1067 | def test_substitute_svn_not_svn(self): | ||
2557 | 1068 | br = self.make_branch("source") | ||
2558 | 1069 | source = br.create_checkout("checkout") | ||
2559 | 1070 | source.commit("one") | ||
2560 | 1071 | source.commit("two") | ||
2561 | 1072 | branch1 = BaseRecipeBranch("source", "foo-{svn-revno}", 0.4) | ||
2562 | 1073 | e = self.assertRaises(errors.BzrCommandError, resolve_revisions, | ||
2563 | 1074 | branch1) | ||
2564 | 1075 | self.assertTrue(str(e).startswith("unable to expand {svn-revno} "), | ||
2565 | 1076 | e) | ||
2566 | 1077 | |||
2567 | 1078 | def test_substitute_svn(self): | ||
2568 | 1079 | br = self.make_branch("source") | ||
2569 | 1080 | source = br.create_checkout("checkout") | ||
2570 | 1081 | source.commit("one") | ||
2571 | 1082 | source.commit("two", | ||
2572 | 1083 | rev_id="svn-v4:be7e6eca-30d4-0310-a8e5-ac0d63af7070:trunk:5344") | ||
2573 | 1084 | branch1 = BaseRecipeBranch("source", "foo-{svn-revno}", 0.4) | ||
2574 | 1085 | resolve_revisions(branch1) | ||
2575 | 1086 | self.assertEqual("foo-5344", branch1.deb_version) | ||
2576 | 1087 | |||
2577 | 1088 | def test_substitute_git_not_git(self): | ||
2578 | 1089 | source = self.make_branch_and_tree("source") | ||
2579 | 1090 | source.commit("one") | ||
2580 | 1091 | source.commit("two") | ||
2581 | 1092 | branch1 = BaseRecipeBranch("source", "foo-{git-commit}", 0.4) | ||
2582 | 1093 | e = self.assertRaises(errors.BzrCommandError, resolve_revisions, | ||
2583 | 1094 | branch1) | ||
2584 | 1095 | self.assertTrue(str(e).startswith("unable to expand {git-commit} "), | ||
2585 | 1096 | e) | ||
2586 | 1097 | |||
2587 | 1098 | def test_substitute_git(self): | ||
2588 | 1099 | source = self.make_branch_and_tree("source") | ||
2589 | 1100 | source.commit("one", | ||
2590 | 1101 | rev_id="git-v1:a029d7b2cc83c26a53d8b2a24fa12c340fcfac58") | ||
2591 | 1102 | branch1 = BaseRecipeBranch("source", "foo-{git-commit}", 0.4) | ||
2592 | 1103 | resolve_revisions(branch1) | ||
2593 | 1104 | self.assertEqual("foo-a029d7b", branch1.deb_version) | ||
2594 | 1105 | |||
2595 | 1106 | def test_latest_tag(self): | ||
2596 | 1107 | source = self.make_branch_and_tree("source") | ||
2597 | 1108 | revid = source.commit("one") | ||
2598 | 1109 | source.branch.tags.set_tag("millbank", revid) | ||
2599 | 1110 | source.commit("two") | ||
2600 | 1111 | branch1 = BaseRecipeBranch("source", "foo-{latest-tag}", 0.4) | ||
2601 | 1112 | resolve_revisions(branch1) | ||
2602 | 1113 | self.assertEqual("foo-millbank", branch1.deb_version) | ||
2603 | 1114 | |||
2604 | 1115 | def test_latest_tag_no_tag(self): | ||
2605 | 1116 | source = self.make_branch_and_tree("source") | ||
2606 | 1117 | revid = source.commit("one") | ||
2607 | 1118 | source.commit("two") | ||
2608 | 1119 | branch1 = BaseRecipeBranch("source", "foo-{latest-tag}", 0.4) | ||
2609 | 1120 | e = self.assertRaises(errors.BzrCommandError, resolve_revisions, branch1) | ||
2610 | 1121 | self.assertTrue(str(e).startswith("No tags set on branch None mainline"), | ||
2611 | 1122 | e) | ||
2612 | 1123 | |||
2613 | 1124 | def test_substitute_revdate(self): | ||
2614 | 1125 | br = self.make_branch("source") | ||
2615 | 1126 | source = br.create_checkout("checkout") | ||
2616 | 1127 | source.commit("one") | ||
2617 | 1128 | source.commit("two", timestamp=1307708628, timezone=0) | ||
2618 | 1129 | branch1 = BaseRecipeBranch("source", "foo-{revdate}", 0.4) | ||
2619 | 1130 | resolve_revisions(branch1) | ||
2620 | 1131 | self.assertEqual("foo-20110610", branch1.deb_version) | ||
2621 | 1132 | |||
2622 | 1133 | def test_substitute_revtime(self): | ||
2623 | 1134 | br = self.make_branch("source") | ||
2624 | 1135 | source = br.create_checkout("checkout") | ||
2625 | 1136 | source.commit("one") | ||
2626 | 1137 | source.commit("two", timestamp=1307708628, timezone=0) | ||
2627 | 1138 | branch1 = BaseRecipeBranch("source", "foo-{revtime}", 0.4) | ||
2628 | 1139 | resolve_revisions(branch1) | ||
2629 | 1140 | self.assertEqual("foo-201106101223", branch1.deb_version) | ||
2630 | 1141 | |||
2631 | 1142 | |||
2632 | 1143 | class StringifyTests(TestCaseInTempDir): | 946 | class StringifyTests(TestCaseInTempDir): |
2633 | 1144 | 947 | ||
2634 | 1145 | def test_missing_debversion(self): | 948 | def test_missing_debversion(self): |
2635 | @@ -1317,77 +1120,6 @@ | |||
2636 | 1317 | rbranch2 = RecipeBranch("name", "other_url2") | 1120 | rbranch2 = RecipeBranch("name", "other_url2") |
2637 | 1318 | self.assertTrue(rbranch1.different_shape_to(rbranch2)) | 1121 | self.assertTrue(rbranch1.different_shape_to(rbranch2)) |
2638 | 1319 | 1122 | ||
2639 | 1320 | def test_substitute_time(self): | ||
2640 | 1321 | time = datetime.datetime.utcfromtimestamp(1) | ||
2641 | 1322 | base_branch = BaseRecipeBranch("base_url", "1-{time}", 0.2) | ||
2642 | 1323 | base_branch.substitute_time(time) | ||
2643 | 1324 | self.assertEqual("1-197001010000", base_branch.deb_version) | ||
2644 | 1325 | base_branch.substitute_time(time) | ||
2645 | 1326 | self.assertEqual("1-197001010000", base_branch.deb_version) | ||
2646 | 1327 | |||
2647 | 1328 | def test_substitute_date(self): | ||
2648 | 1329 | time = datetime.datetime.utcfromtimestamp(1) | ||
2649 | 1330 | base_branch = BaseRecipeBranch("base_url", "1-{date}", 0.2) | ||
2650 | 1331 | base_branch.substitute_time(time) | ||
2651 | 1332 | self.assertEqual("1-19700101", base_branch.deb_version) | ||
2652 | 1333 | base_branch.substitute_time(time) | ||
2653 | 1334 | self.assertEqual("1-19700101", base_branch.deb_version) | ||
2654 | 1335 | |||
2655 | 1336 | def test_substitute_branch_vars(self): | ||
2656 | 1337 | base_branch = BaseRecipeBranch("base_url", "1", 0.2) | ||
2657 | 1338 | wt = self.make_branch_and_tree("br") | ||
2658 | 1339 | revid = wt.commit("acommit") | ||
2659 | 1340 | base_branch.substitute_branch_vars(None, wt.branch, revid) | ||
2660 | 1341 | self.assertEqual("1", base_branch.deb_version) | ||
2661 | 1342 | base_branch.substitute_branch_vars(None, wt.branch, revid) | ||
2662 | 1343 | self.assertEqual("1", base_branch.deb_version) | ||
2663 | 1344 | base_branch = BaseRecipeBranch("base_url", "{revno}", 0.2) | ||
2664 | 1345 | base_branch.substitute_branch_vars(None, wt.branch, revid) | ||
2665 | 1346 | self.assertEqual("1", base_branch.deb_version) | ||
2666 | 1347 | base_branch = BaseRecipeBranch("base_url", "{revno}", 0.2) | ||
2667 | 1348 | base_branch.substitute_branch_vars("foo", wt.branch, revid) | ||
2668 | 1349 | self.assertEqual("{revno}", base_branch.deb_version) | ||
2669 | 1350 | base_branch.substitute_branch_vars("foo", wt.branch, revid) | ||
2670 | 1351 | self.assertEqual("{revno}", base_branch.deb_version) | ||
2671 | 1352 | base_branch = BaseRecipeBranch("base_url", "{revno:foo}", 0.2) | ||
2672 | 1353 | base_branch.substitute_branch_vars("foo", wt.branch, revid) | ||
2673 | 1354 | self.assertEqual("1", base_branch.deb_version) | ||
2674 | 1355 | |||
2675 | 1356 | def test_substitute_branch_vars_debupstream(self): | ||
2676 | 1357 | wt = self.make_branch_and_tree("br") | ||
2677 | 1358 | revid1 = wt.commit("acommit") | ||
2678 | 1359 | cl_contents = ("package (0.1-1) unstable; urgency=low\n * foo\n" | ||
2679 | 1360 | " -- maint <maint@maint.org> Tue, 04 Aug 2009 " | ||
2680 | 1361 | "10:03:10 +0100\n") | ||
2681 | 1362 | self.build_tree_contents( | ||
2682 | 1363 | [("br/debian/", ), ('br/debian/changelog', cl_contents)]) | ||
2683 | 1364 | wt.add(['debian', 'debian/changelog']) | ||
2684 | 1365 | revid2 = wt.commit("with changelog") | ||
2685 | 1366 | base_branch = BaseRecipeBranch("base_url", "{debupstream}", 0.4) | ||
2686 | 1367 | # No changelog file, so no substitution | ||
2687 | 1368 | base_branch.substitute_branch_vars(None, wt.branch, revid1) | ||
2688 | 1369 | self.assertEqual("{debupstream}", base_branch.deb_version) | ||
2689 | 1370 | base_branch.substitute_branch_vars(None, wt.branch, revid2) | ||
2690 | 1371 | self.assertEqual("0.1", base_branch.deb_version) | ||
2691 | 1372 | base_branch = BaseRecipeBranch("base_url", "{debupstream:tehname}", 0.4) | ||
2692 | 1373 | base_branch.substitute_branch_vars("tehname", wt.branch, revid2) | ||
2693 | 1374 | self.assertEqual("0.1", base_branch.deb_version) | ||
2694 | 1375 | |||
2695 | 1376 | def test_substitute_branch_vars_debupstream_pre_0_4(self): | ||
2696 | 1377 | wt = self.make_branch_and_tree("br") | ||
2697 | 1378 | cl_contents = ("package (0.1-1) unstable; urgency=low\n * foo\n" | ||
2698 | 1379 | " -- maint <maint@maint.org> Tue, 04 Aug 2009 " | ||
2699 | 1380 | "10:03:10 +0100\n") | ||
2700 | 1381 | self.build_tree_contents( | ||
2701 | 1382 | [("br/debian/", ), ('br/debian/changelog', cl_contents)]) | ||
2702 | 1383 | wt.add(['debian', 'debian/changelog']) | ||
2703 | 1384 | revid = wt.commit("with changelog") | ||
2704 | 1385 | # In recipe format < 0.4 {debupstream} gets replaced from the resulting | ||
2705 | 1386 | # tree, not from the branch vars. | ||
2706 | 1387 | base_branch = BaseRecipeBranch("base_url", "{debupstream}", 0.2) | ||
2707 | 1388 | base_branch.substitute_branch_vars(None, wt.branch, revid) | ||
2708 | 1389 | self.assertEqual("{debupstream}", base_branch.deb_version) | ||
2709 | 1390 | |||
2710 | 1391 | def test_list_branch_names(self): | 1123 | def test_list_branch_names(self): |
2711 | 1392 | base_branch = BaseRecipeBranch("base_url", "1", 0.2) | 1124 | base_branch = BaseRecipeBranch("base_url", "1", 0.2) |
2712 | 1393 | base_branch.merge_branch(RecipeBranch("merged", "merged_url")) | 1125 | base_branch.merge_branch(RecipeBranch("merged", "merged_url")) |
2713 | @@ -1431,73 +1163,3 @@ | |||
2714 | 1431 | self.assertEqual([ | 1163 | self.assertEqual([ |
2715 | 1432 | cmd, nest, merge_into_nested], | 1164 | cmd, nest, merge_into_nested], |
2716 | 1433 | list(base_branch.iter_all_instructions())) | 1165 | list(base_branch.iter_all_instructions())) |
2717 | 1434 | |||
2718 | 1435 | |||
2719 | 1436 | class DebUpstreamVariableTests(TestCase): | ||
2720 | 1437 | |||
2721 | 1438 | def write_changelog(self, version): | ||
2722 | 1439 | contents = textwrap.dedent(""" | ||
2723 | 1440 | package (%s) experimental; urgency=low | ||
2724 | 1441 | |||
2725 | 1442 | * Initial release. (Closes: #XXXXXX) | ||
2726 | 1443 | |||
2727 | 1444 | -- Jelmer Vernooij <jelmer@debian.org> Thu, 19 May 2011 10:07:41 +0100 | ||
2728 | 1445 | """ % version)[1:] | ||
2729 | 1446 | return changelog.Changelog(file=contents) | ||
2730 | 1447 | |||
2731 | 1448 | def test_empty_changelog(self): | ||
2732 | 1449 | var = DebUpstreamVariable.from_changelog(None, changelog.Changelog()) | ||
2733 | 1450 | self.assertRaises(SubstitutionUnavailable, var.get) | ||
2734 | 1451 | |||
2735 | 1452 | def test_version(self): | ||
2736 | 1453 | var = DebUpstreamVariable.from_changelog(None, | ||
2737 | 1454 | self.write_changelog("2.3")) | ||
2738 | 1455 | self.assertEquals("2.3", var.get()) | ||
2739 | 1456 | |||
2740 | 1457 | def test_epoch(self): | ||
2741 | 1458 | # The epoch is (currently) ignored by {debupstream}. | ||
2742 | 1459 | var = DebUpstreamVariable.from_changelog(None, | ||
2743 | 1460 | self.write_changelog("2:2.3")) | ||
2744 | 1461 | self.assertEquals("2.3", var.get()) | ||
2745 | 1462 | |||
2746 | 1463 | def test_base_without_snapshot(self): | ||
2747 | 1464 | var = DebUpstreamBaseVariable.from_changelog(None, | ||
2748 | 1465 | self.write_changelog("2.4")) | ||
2749 | 1466 | self.assertEquals("2.4+", var.get()) | ||
2750 | 1467 | |||
2751 | 1468 | def test_base_with_svn_snapshot(self): | ||
2752 | 1469 | var = DebUpstreamBaseVariable.from_changelog(None, | ||
2753 | 1470 | self.write_changelog("2.4~svn4")) | ||
2754 | 1471 | self.assertEquals("2.4~", var.get()) | ||
2755 | 1472 | |||
2756 | 1473 | def test_base_with_bzr_snapshot(self): | ||
2757 | 1474 | var = DebUpstreamBaseVariable.from_changelog(None, | ||
2758 | 1475 | self.write_changelog("2.4+bzr343")) | ||
2759 | 1476 | self.assertEquals("2.4+", var.get()) | ||
2760 | 1477 | |||
2761 | 1478 | |||
2762 | 1479 | class DebVersionVariableTests(TestCase): | ||
2763 | 1480 | |||
2764 | 1481 | def write_changelog(self, version): | ||
2765 | 1482 | contents = textwrap.dedent(""" | ||
2766 | 1483 | package (%s) experimental; urgency=low | ||
2767 | 1484 | |||
2768 | 1485 | * Initial release. (Closes: #XXXXXX) | ||
2769 | 1486 | |||
2770 | 1487 | -- Jelmer Vernooij <jelmer@debian.org> Thu, 19 May 2011 10:07:41 +0100 | ||
2771 | 1488 | """ % version)[1:] | ||
2772 | 1489 | return changelog.Changelog(file=contents) | ||
2773 | 1490 | |||
2774 | 1491 | def test_empty_changelog(self): | ||
2775 | 1492 | var = DebVersionVariable.from_changelog(None, changelog.Changelog()) | ||
2776 | 1493 | self.assertRaises(SubstitutionUnavailable, var.get) | ||
2777 | 1494 | |||
2778 | 1495 | def test_simple(self): | ||
2779 | 1496 | var = DebVersionVariable.from_changelog( | ||
2780 | 1497 | None, self.write_changelog("2.3-1")) | ||
2781 | 1498 | self.assertEquals("2.3-1", var.get()) | ||
2782 | 1499 | |||
2783 | 1500 | def test_epoch(self): | ||
2784 | 1501 | var = DebVersionVariable.from_changelog( | ||
2785 | 1502 | None, self.write_changelog("4:2.3-1")) | ||
2786 | 1503 | self.assertEquals("4:2.3-1", var.get()) |
Good work!