Merge lp:~jelmer/ubuntu/oneiric/bzr-builder/oneiric into lp:ubuntu/oneiric/bzr-builder

Proposed by Jelmer Vernooij
Status: Merged
Merge reported by: James Westby
Merged at revision: not available
Proposed branch: lp:~jelmer/ubuntu/oneiric/bzr-builder/oneiric
Merge into: lp:ubuntu/oneiric/bzr-builder
Diff against target: 10319 lines (+54/-4428)
19 files modified
.bzr-builddeb/default.conf (+3/-0)
COPYING (+0/-674)
TODO (+0/-5)
__init__.py (+0/-165)
bzrlibbackports.py (+0/-227)
cmds.py (+0/-507)
debian/changelog (+10/-0)
debian/control (+5/-3)
debian/patches/01_broken_test (+24/-0)
debian/patches/series (+1/-0)
debian/rules (+10/-0)
debian/source/format (+1/-0)
ppa.py (+0/-124)
recipe.py (+0/-1189)
setup.py (+0/-17)
tests/__init__.py (+0/-29)
tests/test_blackbox.py (+0/-286)
tests/test_ppa.py (+0/-28)
tests/test_recipe.py (+0/-1174)
To merge this branch: bzr merge lp:~jelmer/ubuntu/oneiric/bzr-builder/oneiric
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+64579@code.launchpad.net

Description of the change

Update bzr-builder to the next version.

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=== added directory '.bzr-builddeb'
2=== added file '.bzr-builddeb/default.conf'
3--- .bzr-builddeb/default.conf 1970-01-01 00:00:00 +0000
4+++ .bzr-builddeb/default.conf 2011-06-14 17:23:32 +0000
5@@ -0,0 +1,3 @@
6+[BUILDDEB]
7+upstream-branch = lp:bzr-builder
8+export-upstream-revision = tag:$UPSTREAM_VERSION
9
10=== added file 'COPYING'
11--- COPYING 1970-01-01 00:00:00 +0000
12+++ COPYING 2011-06-14 17:23:32 +0000
13@@ -0,0 +1,674 @@
14+ GNU GENERAL PUBLIC LICENSE
15+ Version 3, 29 June 2007
16+
17+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
18+ Everyone is permitted to copy and distribute verbatim copies
19+ of this license document, but changing it is not allowed.
20+
21+ Preamble
22+
23+ The GNU General Public License is a free, copyleft license for
24+software and other kinds of works.
25+
26+ The licenses for most software and other practical works are designed
27+to take away your freedom to share and change the works. By contrast,
28+the GNU General Public License is intended to guarantee your freedom to
29+share and change all versions of a program--to make sure it remains free
30+software for all its users. We, the Free Software Foundation, use the
31+GNU General Public License for most of our software; it applies also to
32+any other work released this way by its authors. You can apply it to
33+your programs, too.
34+
35+ When we speak of free software, we are referring to freedom, not
36+price. Our General Public Licenses are designed to make sure that you
37+have the freedom to distribute copies of free software (and charge for
38+them if you wish), that you receive source code or can get it if you
39+want it, that you can change the software or use pieces of it in new
40+free programs, and that you know you can do these things.
41+
42+ To protect your rights, we need to prevent others from denying you
43+these rights or asking you to surrender the rights. Therefore, you have
44+certain responsibilities if you distribute copies of the software, or if
45+you modify it: responsibilities to respect the freedom of others.
46+
47+ For example, if you distribute copies of such a program, whether
48+gratis or for a fee, you must pass on to the recipients the same
49+freedoms that you received. You must make sure that they, too, receive
50+or can get the source code. And you must show them these terms so they
51+know their rights.
52+
53+ Developers that use the GNU GPL protect your rights with two steps:
54+(1) assert copyright on the software, and (2) offer you this License
55+giving you legal permission to copy, distribute and/or modify it.
56+
57+ For the developers' and authors' protection, the GPL clearly explains
58+that there is no warranty for this free software. For both users' and
59+authors' sake, the GPL requires that modified versions be marked as
60+changed, so that their problems will not be attributed erroneously to
61+authors of previous versions.
62+
63+ Some devices are designed to deny users access to install or run
64+modified versions of the software inside them, although the manufacturer
65+can do so. This is fundamentally incompatible with the aim of
66+protecting users' freedom to change the software. The systematic
67+pattern of such abuse occurs in the area of products for individuals to
68+use, which is precisely where it is most unacceptable. Therefore, we
69+have designed this version of the GPL to prohibit the practice for those
70+products. If such problems arise substantially in other domains, we
71+stand ready to extend this provision to those domains in future versions
72+of the GPL, as needed to protect the freedom of users.
73+
74+ Finally, every program is threatened constantly by software patents.
75+States should not allow patents to restrict development and use of
76+software on general-purpose computers, but in those that do, we wish to
77+avoid the special danger that patents applied to a free program could
78+make it effectively proprietary. To prevent this, the GPL assures that
79+patents cannot be used to render the program non-free.
80+
81+ The precise terms and conditions for copying, distribution and
82+modification follow.
83+
84+ TERMS AND CONDITIONS
85+
86+ 0. Definitions.
87+
88+ "This License" refers to version 3 of the GNU General Public License.
89+
90+ "Copyright" also means copyright-like laws that apply to other kinds of
91+works, such as semiconductor masks.
92+
93+ "The Program" refers to any copyrightable work licensed under this
94+License. Each licensee is addressed as "you". "Licensees" and
95+"recipients" may be individuals or organizations.
96+
97+ To "modify" a work means to copy from or adapt all or part of the work
98+in a fashion requiring copyright permission, other than the making of an
99+exact copy. The resulting work is called a "modified version" of the
100+earlier work or a work "based on" the earlier work.
101+
102+ A "covered work" means either the unmodified Program or a work based
103+on the Program.
104+
105+ To "propagate" a work means to do anything with it that, without
106+permission, would make you directly or secondarily liable for
107+infringement under applicable copyright law, except executing it on a
108+computer or modifying a private copy. Propagation includes copying,
109+distribution (with or without modification), making available to the
110+public, and in some countries other activities as well.
111+
112+ To "convey" a work means any kind of propagation that enables other
113+parties to make or receive copies. Mere interaction with a user through
114+a computer network, with no transfer of a copy, is not conveying.
115+
116+ An interactive user interface displays "Appropriate Legal Notices"
117+to the extent that it includes a convenient and prominently visible
118+feature that (1) displays an appropriate copyright notice, and (2)
119+tells the user that there is no warranty for the work (except to the
120+extent that warranties are provided), that licensees may convey the
121+work under this License, and how to view a copy of this License. If
122+the interface presents a list of user commands or options, such as a
123+menu, a prominent item in the list meets this criterion.
124+
125+ 1. Source Code.
126+
127+ The "source code" for a work means the preferred form of the work
128+for making modifications to it. "Object code" means any non-source
129+form of a work.
130+
131+ A "Standard Interface" means an interface that either is an official
132+standard defined by a recognized standards body, or, in the case of
133+interfaces specified for a particular programming language, one that
134+is widely used among developers working in that language.
135+
136+ The "System Libraries" of an executable work include anything, other
137+than the work as a whole, that (a) is included in the normal form of
138+packaging a Major Component, but which is not part of that Major
139+Component, and (b) serves only to enable use of the work with that
140+Major Component, or to implement a Standard Interface for which an
141+implementation is available to the public in source code form. A
142+"Major Component", in this context, means a major essential component
143+(kernel, window system, and so on) of the specific operating system
144+(if any) on which the executable work runs, or a compiler used to
145+produce the work, or an object code interpreter used to run it.
146+
147+ The "Corresponding Source" for a work in object code form means all
148+the source code needed to generate, install, and (for an executable
149+work) run the object code and to modify the work, including scripts to
150+control those activities. However, it does not include the work's
151+System Libraries, or general-purpose tools or generally available free
152+programs which are used unmodified in performing those activities but
153+which are not part of the work. For example, Corresponding Source
154+includes interface definition files associated with source files for
155+the work, and the source code for shared libraries and dynamically
156+linked subprograms that the work is specifically designed to require,
157+such as by intimate data communication or control flow between those
158+subprograms and other parts of the work.
159+
160+ The Corresponding Source need not include anything that users
161+can regenerate automatically from other parts of the Corresponding
162+Source.
163+
164+ The Corresponding Source for a work in source code form is that
165+same work.
166+
167+ 2. Basic Permissions.
168+
169+ All rights granted under this License are granted for the term of
170+copyright on the Program, and are irrevocable provided the stated
171+conditions are met. This License explicitly affirms your unlimited
172+permission to run the unmodified Program. The output from running a
173+covered work is covered by this License only if the output, given its
174+content, constitutes a covered work. This License acknowledges your
175+rights of fair use or other equivalent, as provided by copyright law.
176+
177+ You may make, run and propagate covered works that you do not
178+convey, without conditions so long as your license otherwise remains
179+in force. You may convey covered works to others for the sole purpose
180+of having them make modifications exclusively for you, or provide you
181+with facilities for running those works, provided that you comply with
182+the terms of this License in conveying all material for which you do
183+not control copyright. Those thus making or running the covered works
184+for you must do so exclusively on your behalf, under your direction
185+and control, on terms that prohibit them from making any copies of
186+your copyrighted material outside their relationship with you.
187+
188+ Conveying under any other circumstances is permitted solely under
189+the conditions stated below. Sublicensing is not allowed; section 10
190+makes it unnecessary.
191+
192+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
193+
194+ No covered work shall be deemed part of an effective technological
195+measure under any applicable law fulfilling obligations under article
196+11 of the WIPO copyright treaty adopted on 20 December 1996, or
197+similar laws prohibiting or restricting circumvention of such
198+measures.
199+
200+ When you convey a covered work, you waive any legal power to forbid
201+circumvention of technological measures to the extent such circumvention
202+is effected by exercising rights under this License with respect to
203+the covered work, and you disclaim any intention to limit operation or
204+modification of the work as a means of enforcing, against the work's
205+users, your or third parties' legal rights to forbid circumvention of
206+technological measures.
207+
208+ 4. Conveying Verbatim Copies.
209+
210+ You may convey verbatim copies of the Program's source code as you
211+receive it, in any medium, provided that you conspicuously and
212+appropriately publish on each copy an appropriate copyright notice;
213+keep intact all notices stating that this License and any
214+non-permissive terms added in accord with section 7 apply to the code;
215+keep intact all notices of the absence of any warranty; and give all
216+recipients a copy of this License along with the Program.
217+
218+ You may charge any price or no price for each copy that you convey,
219+and you may offer support or warranty protection for a fee.
220+
221+ 5. Conveying Modified Source Versions.
222+
223+ You may convey a work based on the Program, or the modifications to
224+produce it from the Program, in the form of source code under the
225+terms of section 4, provided that you also meet all of these conditions:
226+
227+ a) The work must carry prominent notices stating that you modified
228+ it, and giving a relevant date.
229+
230+ b) The work must carry prominent notices stating that it is
231+ released under this License and any conditions added under section
232+ 7. This requirement modifies the requirement in section 4 to
233+ "keep intact all notices".
234+
235+ c) You must license the entire work, as a whole, under this
236+ License to anyone who comes into possession of a copy. This
237+ License will therefore apply, along with any applicable section 7
238+ additional terms, to the whole of the work, and all its parts,
239+ regardless of how they are packaged. This License gives no
240+ permission to license the work in any other way, but it does not
241+ invalidate such permission if you have separately received it.
242+
243+ d) If the work has interactive user interfaces, each must display
244+ Appropriate Legal Notices; however, if the Program has interactive
245+ interfaces that do not display Appropriate Legal Notices, your
246+ work need not make them do so.
247+
248+ A compilation of a covered work with other separate and independent
249+works, which are not by their nature extensions of the covered work,
250+and which are not combined with it such as to form a larger program,
251+in or on a volume of a storage or distribution medium, is called an
252+"aggregate" if the compilation and its resulting copyright are not
253+used to limit the access or legal rights of the compilation's users
254+beyond what the individual works permit. Inclusion of a covered work
255+in an aggregate does not cause this License to apply to the other
256+parts of the aggregate.
257+
258+ 6. Conveying Non-Source Forms.
259+
260+ You may convey a covered work in object code form under the terms
261+of sections 4 and 5, provided that you also convey the
262+machine-readable Corresponding Source under the terms of this License,
263+in one of these ways:
264+
265+ a) Convey the object code in, or embodied in, a physical product
266+ (including a physical distribution medium), accompanied by the
267+ Corresponding Source fixed on a durable physical medium
268+ customarily used for software interchange.
269+
270+ b) Convey the object code in, or embodied in, a physical product
271+ (including a physical distribution medium), accompanied by a
272+ written offer, valid for at least three years and valid for as
273+ long as you offer spare parts or customer support for that product
274+ model, to give anyone who possesses the object code either (1) a
275+ copy of the Corresponding Source for all the software in the
276+ product that is covered by this License, on a durable physical
277+ medium customarily used for software interchange, for a price no
278+ more than your reasonable cost of physically performing this
279+ conveying of source, or (2) access to copy the
280+ Corresponding Source from a network server at no charge.
281+
282+ c) Convey individual copies of the object code with a copy of the
283+ written offer to provide the Corresponding Source. This
284+ alternative is allowed only occasionally and noncommercially, and
285+ only if you received the object code with such an offer, in accord
286+ with subsection 6b.
287+
288+ d) Convey the object code by offering access from a designated
289+ place (gratis or for a charge), and offer equivalent access to the
290+ Corresponding Source in the same way through the same place at no
291+ further charge. You need not require recipients to copy the
292+ Corresponding Source along with the object code. If the place to
293+ copy the object code is a network server, the Corresponding Source
294+ may be on a different server (operated by you or a third party)
295+ that supports equivalent copying facilities, provided you maintain
296+ clear directions next to the object code saying where to find the
297+ Corresponding Source. Regardless of what server hosts the
298+ Corresponding Source, you remain obligated to ensure that it is
299+ available for as long as needed to satisfy these requirements.
300+
301+ e) Convey the object code using peer-to-peer transmission, provided
302+ you inform other peers where the object code and Corresponding
303+ Source of the work are being offered to the general public at no
304+ charge under subsection 6d.
305+
306+ A separable portion of the object code, whose source code is excluded
307+from the Corresponding Source as a System Library, need not be
308+included in conveying the object code work.
309+
310+ A "User Product" is either (1) a "consumer product", which means any
311+tangible personal property which is normally used for personal, family,
312+or household purposes, or (2) anything designed or sold for incorporation
313+into a dwelling. In determining whether a product is a consumer product,
314+doubtful cases shall be resolved in favor of coverage. For a particular
315+product received by a particular user, "normally used" refers to a
316+typical or common use of that class of product, regardless of the status
317+of the particular user or of the way in which the particular user
318+actually uses, or expects or is expected to use, the product. A product
319+is a consumer product regardless of whether the product has substantial
320+commercial, industrial or non-consumer uses, unless such uses represent
321+the only significant mode of use of the product.
322+
323+ "Installation Information" for a User Product means any methods,
324+procedures, authorization keys, or other information required to install
325+and execute modified versions of a covered work in that User Product from
326+a modified version of its Corresponding Source. The information must
327+suffice to ensure that the continued functioning of the modified object
328+code is in no case prevented or interfered with solely because
329+modification has been made.
330+
331+ If you convey an object code work under this section in, or with, or
332+specifically for use in, a User Product, and the conveying occurs as
333+part of a transaction in which the right of possession and use of the
334+User Product is transferred to the recipient in perpetuity or for a
335+fixed term (regardless of how the transaction is characterized), the
336+Corresponding Source conveyed under this section must be accompanied
337+by the Installation Information. But this requirement does not apply
338+if neither you nor any third party retains the ability to install
339+modified object code on the User Product (for example, the work has
340+been installed in ROM).
341+
342+ The requirement to provide Installation Information does not include a
343+requirement to continue to provide support service, warranty, or updates
344+for a work that has been modified or installed by the recipient, or for
345+the User Product in which it has been modified or installed. Access to a
346+network may be denied when the modification itself materially and
347+adversely affects the operation of the network or violates the rules and
348+protocols for communication across the network.
349+
350+ Corresponding Source conveyed, and Installation Information provided,
351+in accord with this section must be in a format that is publicly
352+documented (and with an implementation available to the public in
353+source code form), and must require no special password or key for
354+unpacking, reading or copying.
355+
356+ 7. Additional Terms.
357+
358+ "Additional permissions" are terms that supplement the terms of this
359+License by making exceptions from one or more of its conditions.
360+Additional permissions that are applicable to the entire Program shall
361+be treated as though they were included in this License, to the extent
362+that they are valid under applicable law. If additional permissions
363+apply only to part of the Program, that part may be used separately
364+under those permissions, but the entire Program remains governed by
365+this License without regard to the additional permissions.
366+
367+ When you convey a copy of a covered work, you may at your option
368+remove any additional permissions from that copy, or from any part of
369+it. (Additional permissions may be written to require their own
370+removal in certain cases when you modify the work.) You may place
371+additional permissions on material, added by you to a covered work,
372+for which you have or can give appropriate copyright permission.
373+
374+ Notwithstanding any other provision of this License, for material you
375+add to a covered work, you may (if authorized by the copyright holders of
376+that material) supplement the terms of this License with terms:
377+
378+ a) Disclaiming warranty or limiting liability differently from the
379+ terms of sections 15 and 16 of this License; or
380+
381+ b) Requiring preservation of specified reasonable legal notices or
382+ author attributions in that material or in the Appropriate Legal
383+ Notices displayed by works containing it; or
384+
385+ c) Prohibiting misrepresentation of the origin of that material, or
386+ requiring that modified versions of such material be marked in
387+ reasonable ways as different from the original version; or
388+
389+ d) Limiting the use for publicity purposes of names of licensors or
390+ authors of the material; or
391+
392+ e) Declining to grant rights under trademark law for use of some
393+ trade names, trademarks, or service marks; or
394+
395+ f) Requiring indemnification of licensors and authors of that
396+ material by anyone who conveys the material (or modified versions of
397+ it) with contractual assumptions of liability to the recipient, for
398+ any liability that these contractual assumptions directly impose on
399+ those licensors and authors.
400+
401+ All other non-permissive additional terms are considered "further
402+restrictions" within the meaning of section 10. If the Program as you
403+received it, or any part of it, contains a notice stating that it is
404+governed by this License along with a term that is a further
405+restriction, you may remove that term. If a license document contains
406+a further restriction but permits relicensing or conveying under this
407+License, you may add to a covered work material governed by the terms
408+of that license document, provided that the further restriction does
409+not survive such relicensing or conveying.
410+
411+ If you add terms to a covered work in accord with this section, you
412+must place, in the relevant source files, a statement of the
413+additional terms that apply to those files, or a notice indicating
414+where to find the applicable terms.
415+
416+ Additional terms, permissive or non-permissive, may be stated in the
417+form of a separately written license, or stated as exceptions;
418+the above requirements apply either way.
419+
420+ 8. Termination.
421+
422+ You may not propagate or modify a covered work except as expressly
423+provided under this License. Any attempt otherwise to propagate or
424+modify it is void, and will automatically terminate your rights under
425+this License (including any patent licenses granted under the third
426+paragraph of section 11).
427+
428+ However, if you cease all violation of this License, then your
429+license from a particular copyright holder is reinstated (a)
430+provisionally, unless and until the copyright holder explicitly and
431+finally terminates your license, and (b) permanently, if the copyright
432+holder fails to notify you of the violation by some reasonable means
433+prior to 60 days after the cessation.
434+
435+ Moreover, your license from a particular copyright holder is
436+reinstated permanently if the copyright holder notifies you of the
437+violation by some reasonable means, this is the first time you have
438+received notice of violation of this License (for any work) from that
439+copyright holder, and you cure the violation prior to 30 days after
440+your receipt of the notice.
441+
442+ Termination of your rights under this section does not terminate the
443+licenses of parties who have received copies or rights from you under
444+this License. If your rights have been terminated and not permanently
445+reinstated, you do not qualify to receive new licenses for the same
446+material under section 10.
447+
448+ 9. Acceptance Not Required for Having Copies.
449+
450+ You are not required to accept this License in order to receive or
451+run a copy of the Program. Ancillary propagation of a covered work
452+occurring solely as a consequence of using peer-to-peer transmission
453+to receive a copy likewise does not require acceptance. However,
454+nothing other than this License grants you permission to propagate or
455+modify any covered work. These actions infringe copyright if you do
456+not accept this License. Therefore, by modifying or propagating a
457+covered work, you indicate your acceptance of this License to do so.
458+
459+ 10. Automatic Licensing of Downstream Recipients.
460+
461+ Each time you convey a covered work, the recipient automatically
462+receives a license from the original licensors, to run, modify and
463+propagate that work, subject to this License. You are not responsible
464+for enforcing compliance by third parties with this License.
465+
466+ An "entity transaction" is a transaction transferring control of an
467+organization, or substantially all assets of one, or subdividing an
468+organization, or merging organizations. If propagation of a covered
469+work results from an entity transaction, each party to that
470+transaction who receives a copy of the work also receives whatever
471+licenses to the work the party's predecessor in interest had or could
472+give under the previous paragraph, plus a right to possession of the
473+Corresponding Source of the work from the predecessor in interest, if
474+the predecessor has it or can get it with reasonable efforts.
475+
476+ You may not impose any further restrictions on the exercise of the
477+rights granted or affirmed under this License. For example, you may
478+not impose a license fee, royalty, or other charge for exercise of
479+rights granted under this License, and you may not initiate litigation
480+(including a cross-claim or counterclaim in a lawsuit) alleging that
481+any patent claim is infringed by making, using, selling, offering for
482+sale, or importing the Program or any portion of it.
483+
484+ 11. Patents.
485+
486+ A "contributor" is a copyright holder who authorizes use under this
487+License of the Program or a work on which the Program is based. The
488+work thus licensed is called the contributor's "contributor version".
489+
490+ A contributor's "essential patent claims" are all patent claims
491+owned or controlled by the contributor, whether already acquired or
492+hereafter acquired, that would be infringed by some manner, permitted
493+by this License, of making, using, or selling its contributor version,
494+but do not include claims that would be infringed only as a
495+consequence of further modification of the contributor version. For
496+purposes of this definition, "control" includes the right to grant
497+patent sublicenses in a manner consistent with the requirements of
498+this License.
499+
500+ Each contributor grants you a non-exclusive, worldwide, royalty-free
501+patent license under the contributor's essential patent claims, to
502+make, use, sell, offer for sale, import and otherwise run, modify and
503+propagate the contents of its contributor version.
504+
505+ In the following three paragraphs, a "patent license" is any express
506+agreement or commitment, however denominated, not to enforce a patent
507+(such as an express permission to practice a patent or covenant not to
508+sue for patent infringement). To "grant" such a patent license to a
509+party means to make such an agreement or commitment not to enforce a
510+patent against the party.
511+
512+ If you convey a covered work, knowingly relying on a patent license,
513+and the Corresponding Source of the work is not available for anyone
514+to copy, free of charge and under the terms of this License, through a
515+publicly available network server or other readily accessible means,
516+then you must either (1) cause the Corresponding Source to be so
517+available, or (2) arrange to deprive yourself of the benefit of the
518+patent license for this particular work, or (3) arrange, in a manner
519+consistent with the requirements of this License, to extend the patent
520+license to downstream recipients. "Knowingly relying" means you have
521+actual knowledge that, but for the patent license, your conveying the
522+covered work in a country, or your recipient's use of the covered work
523+in a country, would infringe one or more identifiable patents in that
524+country that you have reason to believe are valid.
525+
526+ If, pursuant to or in connection with a single transaction or
527+arrangement, you convey, or propagate by procuring conveyance of, a
528+covered work, and grant a patent license to some of the parties
529+receiving the covered work authorizing them to use, propagate, modify
530+or convey a specific copy of the covered work, then the patent license
531+you grant is automatically extended to all recipients of the covered
532+work and works based on it.
533+
534+ A patent license is "discriminatory" if it does not include within
535+the scope of its coverage, prohibits the exercise of, or is
536+conditioned on the non-exercise of one or more of the rights that are
537+specifically granted under this License. You may not convey a covered
538+work if you are a party to an arrangement with a third party that is
539+in the business of distributing software, under which you make payment
540+to the third party based on the extent of your activity of conveying
541+the work, and under which the third party grants, to any of the
542+parties who would receive the covered work from you, a discriminatory
543+patent license (a) in connection with copies of the covered work
544+conveyed by you (or copies made from those copies), or (b) primarily
545+for and in connection with specific products or compilations that
546+contain the covered work, unless you entered into that arrangement,
547+or that patent license was granted, prior to 28 March 2007.
548+
549+ Nothing in this License shall be construed as excluding or limiting
550+any implied license or other defenses to infringement that may
551+otherwise be available to you under applicable patent law.
552+
553+ 12. No Surrender of Others' Freedom.
554+
555+ If conditions are imposed on you (whether by court order, agreement or
556+otherwise) that contradict the conditions of this License, they do not
557+excuse you from the conditions of this License. If you cannot convey a
558+covered work so as to satisfy simultaneously your obligations under this
559+License and any other pertinent obligations, then as a consequence you may
560+not convey it at all. For example, if you agree to terms that obligate you
561+to collect a royalty for further conveying from those to whom you convey
562+the Program, the only way you could satisfy both those terms and this
563+License would be to refrain entirely from conveying the Program.
564+
565+ 13. Use with the GNU Affero General Public License.
566+
567+ Notwithstanding any other provision of this License, you have
568+permission to link or combine any covered work with a work licensed
569+under version 3 of the GNU Affero General Public License into a single
570+combined work, and to convey the resulting work. The terms of this
571+License will continue to apply to the part which is the covered work,
572+but the special requirements of the GNU Affero General Public License,
573+section 13, concerning interaction through a network will apply to the
574+combination as such.
575+
576+ 14. Revised Versions of this License.
577+
578+ The Free Software Foundation may publish revised and/or new versions of
579+the GNU General Public License from time to time. Such new versions will
580+be similar in spirit to the present version, but may differ in detail to
581+address new problems or concerns.
582+
583+ Each version is given a distinguishing version number. If the
584+Program specifies that a certain numbered version of the GNU General
585+Public License "or any later version" applies to it, you have the
586+option of following the terms and conditions either of that numbered
587+version or of any later version published by the Free Software
588+Foundation. If the Program does not specify a version number of the
589+GNU General Public License, you may choose any version ever published
590+by the Free Software Foundation.
591+
592+ If the Program specifies that a proxy can decide which future
593+versions of the GNU General Public License can be used, that proxy's
594+public statement of acceptance of a version permanently authorizes you
595+to choose that version for the Program.
596+
597+ Later license versions may give you additional or different
598+permissions. However, no additional obligations are imposed on any
599+author or copyright holder as a result of your choosing to follow a
600+later version.
601+
602+ 15. Disclaimer of Warranty.
603+
604+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
605+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
606+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
607+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
608+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
609+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
610+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
611+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
612+
613+ 16. Limitation of Liability.
614+
615+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
616+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
617+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
618+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
619+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
620+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
621+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
622+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
623+SUCH DAMAGES.
624+
625+ 17. Interpretation of Sections 15 and 16.
626+
627+ If the disclaimer of warranty and limitation of liability provided
628+above cannot be given local legal effect according to their terms,
629+reviewing courts shall apply local law that most closely approximates
630+an absolute waiver of all civil liability in connection with the
631+Program, unless a warranty or assumption of liability accompanies a
632+copy of the Program in return for a fee.
633+
634+ END OF TERMS AND CONDITIONS
635+
636+ How to Apply These Terms to Your New Programs
637+
638+ If you develop a new program, and you want it to be of the greatest
639+possible use to the public, the best way to achieve this is to make it
640+free software which everyone can redistribute and change under these terms.
641+
642+ To do so, attach the following notices to the program. It is safest
643+to attach them to the start of each source file to most effectively
644+state the exclusion of warranty; and each file should have at least
645+the "copyright" line and a pointer to where the full notice is found.
646+
647+ <one line to give the program's name and a brief idea of what it does.>
648+ Copyright (C) <year> <name of author>
649+
650+ This program is free software: you can redistribute it and/or modify
651+ it under the terms of the GNU General Public License as published by
652+ the Free Software Foundation, either version 3 of the License, or
653+ (at your option) any later version.
654+
655+ This program is distributed in the hope that it will be useful,
656+ but WITHOUT ANY WARRANTY; without even the implied warranty of
657+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
658+ GNU General Public License for more details.
659+
660+ You should have received a copy of the GNU General Public License
661+ along with this program. If not, see <http://www.gnu.org/licenses/>.
662+
663+Also add information on how to contact you by electronic and paper mail.
664+
665+ If the program does terminal interaction, make it output a short
666+notice like this when it starts in an interactive mode:
667+
668+ <program> Copyright (C) <year> <name of author>
669+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
670+ This is free software, and you are welcome to redistribute it
671+ under certain conditions; type `show c' for details.
672+
673+The hypothetical commands `show w' and `show c' should show the appropriate
674+parts of the General Public License. Of course, your program's commands
675+might be different; for a GUI interface, you would use an "about box".
676+
677+ You should also get your employer (if you work as a programmer) or school,
678+if any, to sign a "copyright disclaimer" for the program, if necessary.
679+For more information on this, and how to apply and follow the GNU GPL, see
680+<http://www.gnu.org/licenses/>.
681+
682+ The GNU General Public License does not permit incorporating your program
683+into proprietary programs. If your program is a subroutine library, you
684+may consider it more useful to permit linking proprietary applications with
685+the library. If this is what you want to do, use the GNU Lesser General
686+Public License instead of this License. But first, please read
687+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
688
689=== removed file 'COPYING'
690--- COPYING 2009-08-25 23:59:46 +0000
691+++ COPYING 1970-01-01 00:00:00 +0000
692@@ -1,674 +0,0 @@
693- GNU GENERAL PUBLIC LICENSE
694- Version 3, 29 June 2007
695-
696- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
697- Everyone is permitted to copy and distribute verbatim copies
698- of this license document, but changing it is not allowed.
699-
700- Preamble
701-
702- The GNU General Public License is a free, copyleft license for
703-software and other kinds of works.
704-
705- The licenses for most software and other practical works are designed
706-to take away your freedom to share and change the works. By contrast,
707-the GNU General Public License is intended to guarantee your freedom to
708-share and change all versions of a program--to make sure it remains free
709-software for all its users. We, the Free Software Foundation, use the
710-GNU General Public License for most of our software; it applies also to
711-any other work released this way by its authors. You can apply it to
712-your programs, too.
713-
714- When we speak of free software, we are referring to freedom, not
715-price. Our General Public Licenses are designed to make sure that you
716-have the freedom to distribute copies of free software (and charge for
717-them if you wish), that you receive source code or can get it if you
718-want it, that you can change the software or use pieces of it in new
719-free programs, and that you know you can do these things.
720-
721- To protect your rights, we need to prevent others from denying you
722-these rights or asking you to surrender the rights. Therefore, you have
723-certain responsibilities if you distribute copies of the software, or if
724-you modify it: responsibilities to respect the freedom of others.
725-
726- For example, if you distribute copies of such a program, whether
727-gratis or for a fee, you must pass on to the recipients the same
728-freedoms that you received. You must make sure that they, too, receive
729-or can get the source code. And you must show them these terms so they
730-know their rights.
731-
732- Developers that use the GNU GPL protect your rights with two steps:
733-(1) assert copyright on the software, and (2) offer you this License
734-giving you legal permission to copy, distribute and/or modify it.
735-
736- For the developers' and authors' protection, the GPL clearly explains
737-that there is no warranty for this free software. For both users' and
738-authors' sake, the GPL requires that modified versions be marked as
739-changed, so that their problems will not be attributed erroneously to
740-authors of previous versions.
741-
742- Some devices are designed to deny users access to install or run
743-modified versions of the software inside them, although the manufacturer
744-can do so. This is fundamentally incompatible with the aim of
745-protecting users' freedom to change the software. The systematic
746-pattern of such abuse occurs in the area of products for individuals to
747-use, which is precisely where it is most unacceptable. Therefore, we
748-have designed this version of the GPL to prohibit the practice for those
749-products. If such problems arise substantially in other domains, we
750-stand ready to extend this provision to those domains in future versions
751-of the GPL, as needed to protect the freedom of users.
752-
753- Finally, every program is threatened constantly by software patents.
754-States should not allow patents to restrict development and use of
755-software on general-purpose computers, but in those that do, we wish to
756-avoid the special danger that patents applied to a free program could
757-make it effectively proprietary. To prevent this, the GPL assures that
758-patents cannot be used to render the program non-free.
759-
760- The precise terms and conditions for copying, distribution and
761-modification follow.
762-
763- TERMS AND CONDITIONS
764-
765- 0. Definitions.
766-
767- "This License" refers to version 3 of the GNU General Public License.
768-
769- "Copyright" also means copyright-like laws that apply to other kinds of
770-works, such as semiconductor masks.
771-
772- "The Program" refers to any copyrightable work licensed under this
773-License. Each licensee is addressed as "you". "Licensees" and
774-"recipients" may be individuals or organizations.
775-
776- To "modify" a work means to copy from or adapt all or part of the work
777-in a fashion requiring copyright permission, other than the making of an
778-exact copy. The resulting work is called a "modified version" of the
779-earlier work or a work "based on" the earlier work.
780-
781- A "covered work" means either the unmodified Program or a work based
782-on the Program.
783-
784- To "propagate" a work means to do anything with it that, without
785-permission, would make you directly or secondarily liable for
786-infringement under applicable copyright law, except executing it on a
787-computer or modifying a private copy. Propagation includes copying,
788-distribution (with or without modification), making available to the
789-public, and in some countries other activities as well.
790-
791- To "convey" a work means any kind of propagation that enables other
792-parties to make or receive copies. Mere interaction with a user through
793-a computer network, with no transfer of a copy, is not conveying.
794-
795- An interactive user interface displays "Appropriate Legal Notices"
796-to the extent that it includes a convenient and prominently visible
797-feature that (1) displays an appropriate copyright notice, and (2)
798-tells the user that there is no warranty for the work (except to the
799-extent that warranties are provided), that licensees may convey the
800-work under this License, and how to view a copy of this License. If
801-the interface presents a list of user commands or options, such as a
802-menu, a prominent item in the list meets this criterion.
803-
804- 1. Source Code.
805-
806- The "source code" for a work means the preferred form of the work
807-for making modifications to it. "Object code" means any non-source
808-form of a work.
809-
810- A "Standard Interface" means an interface that either is an official
811-standard defined by a recognized standards body, or, in the case of
812-interfaces specified for a particular programming language, one that
813-is widely used among developers working in that language.
814-
815- The "System Libraries" of an executable work include anything, other
816-than the work as a whole, that (a) is included in the normal form of
817-packaging a Major Component, but which is not part of that Major
818-Component, and (b) serves only to enable use of the work with that
819-Major Component, or to implement a Standard Interface for which an
820-implementation is available to the public in source code form. A
821-"Major Component", in this context, means a major essential component
822-(kernel, window system, and so on) of the specific operating system
823-(if any) on which the executable work runs, or a compiler used to
824-produce the work, or an object code interpreter used to run it.
825-
826- The "Corresponding Source" for a work in object code form means all
827-the source code needed to generate, install, and (for an executable
828-work) run the object code and to modify the work, including scripts to
829-control those activities. However, it does not include the work's
830-System Libraries, or general-purpose tools or generally available free
831-programs which are used unmodified in performing those activities but
832-which are not part of the work. For example, Corresponding Source
833-includes interface definition files associated with source files for
834-the work, and the source code for shared libraries and dynamically
835-linked subprograms that the work is specifically designed to require,
836-such as by intimate data communication or control flow between those
837-subprograms and other parts of the work.
838-
839- The Corresponding Source need not include anything that users
840-can regenerate automatically from other parts of the Corresponding
841-Source.
842-
843- The Corresponding Source for a work in source code form is that
844-same work.
845-
846- 2. Basic Permissions.
847-
848- All rights granted under this License are granted for the term of
849-copyright on the Program, and are irrevocable provided the stated
850-conditions are met. This License explicitly affirms your unlimited
851-permission to run the unmodified Program. The output from running a
852-covered work is covered by this License only if the output, given its
853-content, constitutes a covered work. This License acknowledges your
854-rights of fair use or other equivalent, as provided by copyright law.
855-
856- You may make, run and propagate covered works that you do not
857-convey, without conditions so long as your license otherwise remains
858-in force. You may convey covered works to others for the sole purpose
859-of having them make modifications exclusively for you, or provide you
860-with facilities for running those works, provided that you comply with
861-the terms of this License in conveying all material for which you do
862-not control copyright. Those thus making or running the covered works
863-for you must do so exclusively on your behalf, under your direction
864-and control, on terms that prohibit them from making any copies of
865-your copyrighted material outside their relationship with you.
866-
867- Conveying under any other circumstances is permitted solely under
868-the conditions stated below. Sublicensing is not allowed; section 10
869-makes it unnecessary.
870-
871- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
872-
873- No covered work shall be deemed part of an effective technological
874-measure under any applicable law fulfilling obligations under article
875-11 of the WIPO copyright treaty adopted on 20 December 1996, or
876-similar laws prohibiting or restricting circumvention of such
877-measures.
878-
879- When you convey a covered work, you waive any legal power to forbid
880-circumvention of technological measures to the extent such circumvention
881-is effected by exercising rights under this License with respect to
882-the covered work, and you disclaim any intention to limit operation or
883-modification of the work as a means of enforcing, against the work's
884-users, your or third parties' legal rights to forbid circumvention of
885-technological measures.
886-
887- 4. Conveying Verbatim Copies.
888-
889- You may convey verbatim copies of the Program's source code as you
890-receive it, in any medium, provided that you conspicuously and
891-appropriately publish on each copy an appropriate copyright notice;
892-keep intact all notices stating that this License and any
893-non-permissive terms added in accord with section 7 apply to the code;
894-keep intact all notices of the absence of any warranty; and give all
895-recipients a copy of this License along with the Program.
896-
897- You may charge any price or no price for each copy that you convey,
898-and you may offer support or warranty protection for a fee.
899-
900- 5. Conveying Modified Source Versions.
901-
902- You may convey a work based on the Program, or the modifications to
903-produce it from the Program, in the form of source code under the
904-terms of section 4, provided that you also meet all of these conditions:
905-
906- a) The work must carry prominent notices stating that you modified
907- it, and giving a relevant date.
908-
909- b) The work must carry prominent notices stating that it is
910- released under this License and any conditions added under section
911- 7. This requirement modifies the requirement in section 4 to
912- "keep intact all notices".
913-
914- c) You must license the entire work, as a whole, under this
915- License to anyone who comes into possession of a copy. This
916- License will therefore apply, along with any applicable section 7
917- additional terms, to the whole of the work, and all its parts,
918- regardless of how they are packaged. This License gives no
919- permission to license the work in any other way, but it does not
920- invalidate such permission if you have separately received it.
921-
922- d) If the work has interactive user interfaces, each must display
923- Appropriate Legal Notices; however, if the Program has interactive
924- interfaces that do not display Appropriate Legal Notices, your
925- work need not make them do so.
926-
927- A compilation of a covered work with other separate and independent
928-works, which are not by their nature extensions of the covered work,
929-and which are not combined with it such as to form a larger program,
930-in or on a volume of a storage or distribution medium, is called an
931-"aggregate" if the compilation and its resulting copyright are not
932-used to limit the access or legal rights of the compilation's users
933-beyond what the individual works permit. Inclusion of a covered work
934-in an aggregate does not cause this License to apply to the other
935-parts of the aggregate.
936-
937- 6. Conveying Non-Source Forms.
938-
939- You may convey a covered work in object code form under the terms
940-of sections 4 and 5, provided that you also convey the
941-machine-readable Corresponding Source under the terms of this License,
942-in one of these ways:
943-
944- a) Convey the object code in, or embodied in, a physical product
945- (including a physical distribution medium), accompanied by the
946- Corresponding Source fixed on a durable physical medium
947- customarily used for software interchange.
948-
949- b) Convey the object code in, or embodied in, a physical product
950- (including a physical distribution medium), accompanied by a
951- written offer, valid for at least three years and valid for as
952- long as you offer spare parts or customer support for that product
953- model, to give anyone who possesses the object code either (1) a
954- copy of the Corresponding Source for all the software in the
955- product that is covered by this License, on a durable physical
956- medium customarily used for software interchange, for a price no
957- more than your reasonable cost of physically performing this
958- conveying of source, or (2) access to copy the
959- Corresponding Source from a network server at no charge.
960-
961- c) Convey individual copies of the object code with a copy of the
962- written offer to provide the Corresponding Source. This
963- alternative is allowed only occasionally and noncommercially, and
964- only if you received the object code with such an offer, in accord
965- with subsection 6b.
966-
967- d) Convey the object code by offering access from a designated
968- place (gratis or for a charge), and offer equivalent access to the
969- Corresponding Source in the same way through the same place at no
970- further charge. You need not require recipients to copy the
971- Corresponding Source along with the object code. If the place to
972- copy the object code is a network server, the Corresponding Source
973- may be on a different server (operated by you or a third party)
974- that supports equivalent copying facilities, provided you maintain
975- clear directions next to the object code saying where to find the
976- Corresponding Source. Regardless of what server hosts the
977- Corresponding Source, you remain obligated to ensure that it is
978- available for as long as needed to satisfy these requirements.
979-
980- e) Convey the object code using peer-to-peer transmission, provided
981- you inform other peers where the object code and Corresponding
982- Source of the work are being offered to the general public at no
983- charge under subsection 6d.
984-
985- A separable portion of the object code, whose source code is excluded
986-from the Corresponding Source as a System Library, need not be
987-included in conveying the object code work.
988-
989- A "User Product" is either (1) a "consumer product", which means any
990-tangible personal property which is normally used for personal, family,
991-or household purposes, or (2) anything designed or sold for incorporation
992-into a dwelling. In determining whether a product is a consumer product,
993-doubtful cases shall be resolved in favor of coverage. For a particular
994-product received by a particular user, "normally used" refers to a
995-typical or common use of that class of product, regardless of the status
996-of the particular user or of the way in which the particular user
997-actually uses, or expects or is expected to use, the product. A product
998-is a consumer product regardless of whether the product has substantial
999-commercial, industrial or non-consumer uses, unless such uses represent
1000-the only significant mode of use of the product.
1001-
1002- "Installation Information" for a User Product means any methods,
1003-procedures, authorization keys, or other information required to install
1004-and execute modified versions of a covered work in that User Product from
1005-a modified version of its Corresponding Source. The information must
1006-suffice to ensure that the continued functioning of the modified object
1007-code is in no case prevented or interfered with solely because
1008-modification has been made.
1009-
1010- If you convey an object code work under this section in, or with, or
1011-specifically for use in, a User Product, and the conveying occurs as
1012-part of a transaction in which the right of possession and use of the
1013-User Product is transferred to the recipient in perpetuity or for a
1014-fixed term (regardless of how the transaction is characterized), the
1015-Corresponding Source conveyed under this section must be accompanied
1016-by the Installation Information. But this requirement does not apply
1017-if neither you nor any third party retains the ability to install
1018-modified object code on the User Product (for example, the work has
1019-been installed in ROM).
1020-
1021- The requirement to provide Installation Information does not include a
1022-requirement to continue to provide support service, warranty, or updates
1023-for a work that has been modified or installed by the recipient, or for
1024-the User Product in which it has been modified or installed. Access to a
1025-network may be denied when the modification itself materially and
1026-adversely affects the operation of the network or violates the rules and
1027-protocols for communication across the network.
1028-
1029- Corresponding Source conveyed, and Installation Information provided,
1030-in accord with this section must be in a format that is publicly
1031-documented (and with an implementation available to the public in
1032-source code form), and must require no special password or key for
1033-unpacking, reading or copying.
1034-
1035- 7. Additional Terms.
1036-
1037- "Additional permissions" are terms that supplement the terms of this
1038-License by making exceptions from one or more of its conditions.
1039-Additional permissions that are applicable to the entire Program shall
1040-be treated as though they were included in this License, to the extent
1041-that they are valid under applicable law. If additional permissions
1042-apply only to part of the Program, that part may be used separately
1043-under those permissions, but the entire Program remains governed by
1044-this License without regard to the additional permissions.
1045-
1046- When you convey a copy of a covered work, you may at your option
1047-remove any additional permissions from that copy, or from any part of
1048-it. (Additional permissions may be written to require their own
1049-removal in certain cases when you modify the work.) You may place
1050-additional permissions on material, added by you to a covered work,
1051-for which you have or can give appropriate copyright permission.
1052-
1053- Notwithstanding any other provision of this License, for material you
1054-add to a covered work, you may (if authorized by the copyright holders of
1055-that material) supplement the terms of this License with terms:
1056-
1057- a) Disclaiming warranty or limiting liability differently from the
1058- terms of sections 15 and 16 of this License; or
1059-
1060- b) Requiring preservation of specified reasonable legal notices or
1061- author attributions in that material or in the Appropriate Legal
1062- Notices displayed by works containing it; or
1063-
1064- c) Prohibiting misrepresentation of the origin of that material, or
1065- requiring that modified versions of such material be marked in
1066- reasonable ways as different from the original version; or
1067-
1068- d) Limiting the use for publicity purposes of names of licensors or
1069- authors of the material; or
1070-
1071- e) Declining to grant rights under trademark law for use of some
1072- trade names, trademarks, or service marks; or
1073-
1074- f) Requiring indemnification of licensors and authors of that
1075- material by anyone who conveys the material (or modified versions of
1076- it) with contractual assumptions of liability to the recipient, for
1077- any liability that these contractual assumptions directly impose on
1078- those licensors and authors.
1079-
1080- All other non-permissive additional terms are considered "further
1081-restrictions" within the meaning of section 10. If the Program as you
1082-received it, or any part of it, contains a notice stating that it is
1083-governed by this License along with a term that is a further
1084-restriction, you may remove that term. If a license document contains
1085-a further restriction but permits relicensing or conveying under this
1086-License, you may add to a covered work material governed by the terms
1087-of that license document, provided that the further restriction does
1088-not survive such relicensing or conveying.
1089-
1090- If you add terms to a covered work in accord with this section, you
1091-must place, in the relevant source files, a statement of the
1092-additional terms that apply to those files, or a notice indicating
1093-where to find the applicable terms.
1094-
1095- Additional terms, permissive or non-permissive, may be stated in the
1096-form of a separately written license, or stated as exceptions;
1097-the above requirements apply either way.
1098-
1099- 8. Termination.
1100-
1101- You may not propagate or modify a covered work except as expressly
1102-provided under this License. Any attempt otherwise to propagate or
1103-modify it is void, and will automatically terminate your rights under
1104-this License (including any patent licenses granted under the third
1105-paragraph of section 11).
1106-
1107- However, if you cease all violation of this License, then your
1108-license from a particular copyright holder is reinstated (a)
1109-provisionally, unless and until the copyright holder explicitly and
1110-finally terminates your license, and (b) permanently, if the copyright
1111-holder fails to notify you of the violation by some reasonable means
1112-prior to 60 days after the cessation.
1113-
1114- Moreover, your license from a particular copyright holder is
1115-reinstated permanently if the copyright holder notifies you of the
1116-violation by some reasonable means, this is the first time you have
1117-received notice of violation of this License (for any work) from that
1118-copyright holder, and you cure the violation prior to 30 days after
1119-your receipt of the notice.
1120-
1121- Termination of your rights under this section does not terminate the
1122-licenses of parties who have received copies or rights from you under
1123-this License. If your rights have been terminated and not permanently
1124-reinstated, you do not qualify to receive new licenses for the same
1125-material under section 10.
1126-
1127- 9. Acceptance Not Required for Having Copies.
1128-
1129- You are not required to accept this License in order to receive or
1130-run a copy of the Program. Ancillary propagation of a covered work
1131-occurring solely as a consequence of using peer-to-peer transmission
1132-to receive a copy likewise does not require acceptance. However,
1133-nothing other than this License grants you permission to propagate or
1134-modify any covered work. These actions infringe copyright if you do
1135-not accept this License. Therefore, by modifying or propagating a
1136-covered work, you indicate your acceptance of this License to do so.
1137-
1138- 10. Automatic Licensing of Downstream Recipients.
1139-
1140- Each time you convey a covered work, the recipient automatically
1141-receives a license from the original licensors, to run, modify and
1142-propagate that work, subject to this License. You are not responsible
1143-for enforcing compliance by third parties with this License.
1144-
1145- An "entity transaction" is a transaction transferring control of an
1146-organization, or substantially all assets of one, or subdividing an
1147-organization, or merging organizations. If propagation of a covered
1148-work results from an entity transaction, each party to that
1149-transaction who receives a copy of the work also receives whatever
1150-licenses to the work the party's predecessor in interest had or could
1151-give under the previous paragraph, plus a right to possession of the
1152-Corresponding Source of the work from the predecessor in interest, if
1153-the predecessor has it or can get it with reasonable efforts.
1154-
1155- You may not impose any further restrictions on the exercise of the
1156-rights granted or affirmed under this License. For example, you may
1157-not impose a license fee, royalty, or other charge for exercise of
1158-rights granted under this License, and you may not initiate litigation
1159-(including a cross-claim or counterclaim in a lawsuit) alleging that
1160-any patent claim is infringed by making, using, selling, offering for
1161-sale, or importing the Program or any portion of it.
1162-
1163- 11. Patents.
1164-
1165- A "contributor" is a copyright holder who authorizes use under this
1166-License of the Program or a work on which the Program is based. The
1167-work thus licensed is called the contributor's "contributor version".
1168-
1169- A contributor's "essential patent claims" are all patent claims
1170-owned or controlled by the contributor, whether already acquired or
1171-hereafter acquired, that would be infringed by some manner, permitted
1172-by this License, of making, using, or selling its contributor version,
1173-but do not include claims that would be infringed only as a
1174-consequence of further modification of the contributor version. For
1175-purposes of this definition, "control" includes the right to grant
1176-patent sublicenses in a manner consistent with the requirements of
1177-this License.
1178-
1179- Each contributor grants you a non-exclusive, worldwide, royalty-free
1180-patent license under the contributor's essential patent claims, to
1181-make, use, sell, offer for sale, import and otherwise run, modify and
1182-propagate the contents of its contributor version.
1183-
1184- In the following three paragraphs, a "patent license" is any express
1185-agreement or commitment, however denominated, not to enforce a patent
1186-(such as an express permission to practice a patent or covenant not to
1187-sue for patent infringement). To "grant" such a patent license to a
1188-party means to make such an agreement or commitment not to enforce a
1189-patent against the party.
1190-
1191- If you convey a covered work, knowingly relying on a patent license,
1192-and the Corresponding Source of the work is not available for anyone
1193-to copy, free of charge and under the terms of this License, through a
1194-publicly available network server or other readily accessible means,
1195-then you must either (1) cause the Corresponding Source to be so
1196-available, or (2) arrange to deprive yourself of the benefit of the
1197-patent license for this particular work, or (3) arrange, in a manner
1198-consistent with the requirements of this License, to extend the patent
1199-license to downstream recipients. "Knowingly relying" means you have
1200-actual knowledge that, but for the patent license, your conveying the
1201-covered work in a country, or your recipient's use of the covered work
1202-in a country, would infringe one or more identifiable patents in that
1203-country that you have reason to believe are valid.
1204-
1205- If, pursuant to or in connection with a single transaction or
1206-arrangement, you convey, or propagate by procuring conveyance of, a
1207-covered work, and grant a patent license to some of the parties
1208-receiving the covered work authorizing them to use, propagate, modify
1209-or convey a specific copy of the covered work, then the patent license
1210-you grant is automatically extended to all recipients of the covered
1211-work and works based on it.
1212-
1213- A patent license is "discriminatory" if it does not include within
1214-the scope of its coverage, prohibits the exercise of, or is
1215-conditioned on the non-exercise of one or more of the rights that are
1216-specifically granted under this License. You may not convey a covered
1217-work if you are a party to an arrangement with a third party that is
1218-in the business of distributing software, under which you make payment
1219-to the third party based on the extent of your activity of conveying
1220-the work, and under which the third party grants, to any of the
1221-parties who would receive the covered work from you, a discriminatory
1222-patent license (a) in connection with copies of the covered work
1223-conveyed by you (or copies made from those copies), or (b) primarily
1224-for and in connection with specific products or compilations that
1225-contain the covered work, unless you entered into that arrangement,
1226-or that patent license was granted, prior to 28 March 2007.
1227-
1228- Nothing in this License shall be construed as excluding or limiting
1229-any implied license or other defenses to infringement that may
1230-otherwise be available to you under applicable patent law.
1231-
1232- 12. No Surrender of Others' Freedom.
1233-
1234- If conditions are imposed on you (whether by court order, agreement or
1235-otherwise) that contradict the conditions of this License, they do not
1236-excuse you from the conditions of this License. If you cannot convey a
1237-covered work so as to satisfy simultaneously your obligations under this
1238-License and any other pertinent obligations, then as a consequence you may
1239-not convey it at all. For example, if you agree to terms that obligate you
1240-to collect a royalty for further conveying from those to whom you convey
1241-the Program, the only way you could satisfy both those terms and this
1242-License would be to refrain entirely from conveying the Program.
1243-
1244- 13. Use with the GNU Affero General Public License.
1245-
1246- Notwithstanding any other provision of this License, you have
1247-permission to link or combine any covered work with a work licensed
1248-under version 3 of the GNU Affero General Public License into a single
1249-combined work, and to convey the resulting work. The terms of this
1250-License will continue to apply to the part which is the covered work,
1251-but the special requirements of the GNU Affero General Public License,
1252-section 13, concerning interaction through a network will apply to the
1253-combination as such.
1254-
1255- 14. Revised Versions of this License.
1256-
1257- The Free Software Foundation may publish revised and/or new versions of
1258-the GNU General Public License from time to time. Such new versions will
1259-be similar in spirit to the present version, but may differ in detail to
1260-address new problems or concerns.
1261-
1262- Each version is given a distinguishing version number. If the
1263-Program specifies that a certain numbered version of the GNU General
1264-Public License "or any later version" applies to it, you have the
1265-option of following the terms and conditions either of that numbered
1266-version or of any later version published by the Free Software
1267-Foundation. If the Program does not specify a version number of the
1268-GNU General Public License, you may choose any version ever published
1269-by the Free Software Foundation.
1270-
1271- If the Program specifies that a proxy can decide which future
1272-versions of the GNU General Public License can be used, that proxy's
1273-public statement of acceptance of a version permanently authorizes you
1274-to choose that version for the Program.
1275-
1276- Later license versions may give you additional or different
1277-permissions. However, no additional obligations are imposed on any
1278-author or copyright holder as a result of your choosing to follow a
1279-later version.
1280-
1281- 15. Disclaimer of Warranty.
1282-
1283- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
1284-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
1285-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
1286-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
1287-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1288-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
1289-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
1290-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
1291-
1292- 16. Limitation of Liability.
1293-
1294- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
1295-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
1296-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
1297-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
1298-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
1299-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
1300-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
1301-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
1302-SUCH DAMAGES.
1303-
1304- 17. Interpretation of Sections 15 and 16.
1305-
1306- If the disclaimer of warranty and limitation of liability provided
1307-above cannot be given local legal effect according to their terms,
1308-reviewing courts shall apply local law that most closely approximates
1309-an absolute waiver of all civil liability in connection with the
1310-Program, unless a warranty or assumption of liability accompanies a
1311-copy of the Program in return for a fee.
1312-
1313- END OF TERMS AND CONDITIONS
1314-
1315- How to Apply These Terms to Your New Programs
1316-
1317- If you develop a new program, and you want it to be of the greatest
1318-possible use to the public, the best way to achieve this is to make it
1319-free software which everyone can redistribute and change under these terms.
1320-
1321- To do so, attach the following notices to the program. It is safest
1322-to attach them to the start of each source file to most effectively
1323-state the exclusion of warranty; and each file should have at least
1324-the "copyright" line and a pointer to where the full notice is found.
1325-
1326- <one line to give the program's name and a brief idea of what it does.>
1327- Copyright (C) <year> <name of author>
1328-
1329- This program is free software: you can redistribute it and/or modify
1330- it under the terms of the GNU General Public License as published by
1331- the Free Software Foundation, either version 3 of the License, or
1332- (at your option) any later version.
1333-
1334- This program is distributed in the hope that it will be useful,
1335- but WITHOUT ANY WARRANTY; without even the implied warranty of
1336- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1337- GNU General Public License for more details.
1338-
1339- You should have received a copy of the GNU General Public License
1340- along with this program. If not, see <http://www.gnu.org/licenses/>.
1341-
1342-Also add information on how to contact you by electronic and paper mail.
1343-
1344- If the program does terminal interaction, make it output a short
1345-notice like this when it starts in an interactive mode:
1346-
1347- <program> Copyright (C) <year> <name of author>
1348- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
1349- This is free software, and you are welcome to redistribute it
1350- under certain conditions; type `show c' for details.
1351-
1352-The hypothetical commands `show w' and `show c' should show the appropriate
1353-parts of the General Public License. Of course, your program's commands
1354-might be different; for a GUI interface, you would use an "about box".
1355-
1356- You should also get your employer (if you work as a programmer) or school,
1357-if any, to sign a "copyright disclaimer" for the program, if necessary.
1358-For more information on this, and how to apply and follow the GNU GPL, see
1359-<http://www.gnu.org/licenses/>.
1360-
1361- The GNU General Public License does not permit incorporating your program
1362-into proprietary programs. If your program is a subroutine library, you
1363-may consider it more useful to permit linking proprietary applications with
1364-the library. If this is what you want to do, use the GNU Lesser General
1365-Public License instead of this License. But first, please read
1366-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
1367
1368=== added file 'TODO'
1369--- TODO 1970-01-01 00:00:00 +0000
1370+++ TODO 2011-06-14 17:23:32 +0000
1371@@ -0,0 +1,5 @@
1372+- Documentation.
1373+- Work out how to get tarballs for non-native packages if we want that.
1374+- Decide on error on existing target directory vs. re-use and pull changes.
1375+- Decide what should happen if you nest in to a directory that exists in
1376+ the branch that you are nesting in to.
1377
1378=== removed file 'TODO'
1379--- TODO 2010-10-21 21:17:28 +0000
1380+++ TODO 1970-01-01 00:00:00 +0000
1381@@ -1,5 +0,0 @@
1382-- Documentation.
1383-- Work out how to get tarballs for non-native packages if we want that.
1384-- Decide on error on existing target directory vs. re-use and pull changes.
1385-- Decide what should happen if you nest in to a directory that exists in
1386- the branch that you are nesting in to.
1387
1388=== added file '__init__.py'
1389--- __init__.py 1970-01-01 00:00:00 +0000
1390+++ __init__.py 2011-06-14 17:23:32 +0000
1391@@ -0,0 +1,166 @@
1392+# bzr-builder: a bzr plugin to constuct trees based on recipes
1393+# Copyright 2009 Canonical Ltd.
1394+
1395+# This program is free software: you can redistribute it and/or modify it
1396+# under the terms of the GNU General Public License version 3, as published
1397+# by the Free Software Foundation.
1398+
1399+# This program is distributed in the hope that it will be useful, but
1400+# WITHOUT ANY WARRANTY; without even the implied warranties of
1401+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1402+# PURPOSE. See the GNU General Public License for more details.
1403+
1404+# You should have received a copy of the GNU General Public License along
1405+# with this program. If not, see <http://www.gnu.org/licenses/>.
1406+
1407+"""The bzr-builder plugin allows you to construct a branch from a 'recipe'.
1408+
1409+The recipe is a series of pointers to branches and instructions for how they
1410+should be combined. There are two ways to combine branches, by merging, and
1411+by nesting, allowing much flexibility.
1412+
1413+A recipe is just a text file that starts with a line such as::
1414+
1415+ # bzr-builder format 0.3 deb-version 1.0+{revno}-{revno:packaging}
1416+
1417+The format specifier is there to allow the syntax to be changed in later
1418+versions, and the meaning of "deb-version" will be explained later.
1419+
1420+The next step is the define the base branch, this is the branch that will
1421+be places at the root, e.g. just put::
1422+
1423+ lp:foo
1424+
1425+to use the trunk of "foo" hosted on Launchpad.
1426+
1427+Next comes any number of lines of other branches to be merged in, but using
1428+a slightly different format. To merge a branch in to the base specify
1429+something like::
1430+
1431+ merge packaging lp:~foo-dev/foo/packaging
1432+
1433+which specifies we are merging a branch we will refer to as "packaging", which
1434+can be found at the given URI. The name you give to the branch as the second
1435+item doesn't have to match anything else, it's just an identifier specific
1436+to the recipe.
1437+
1438+If you wish to nest a branch then you use a similar line::
1439+
1440+ nest artwork lp:foo-images images
1441+
1442+This specifies that we are nesting the branch at lp:foo-images, which we will
1443+call "artwork", and we will place it locally in to the "images" directory.
1444+
1445+You can then continue in this fashion for as many branches as you like. It
1446+is also possible to nest and merge branches into nested branches. For example
1447+to merge a branch in to the "artwork" branch we put the following on the line
1448+below that one, indented by two spaces::
1449+
1450+ merge artwork-fixes lp:~bob/foo-images/fix-12345
1451+
1452+which will merge Bob's fixes branch into the "artwork" branch which we nested
1453+at "images".
1454+
1455+It is also possible to specify a particular revision of a branch by appending
1456+a revisionspec to the line. For instance::
1457+
1458+ nest docs lp:foo-docs doc tag:1.0
1459+
1460+will nest the revision pointed to by the "1.0" tag of that branch. The format
1461+for the revisionspec is identical to that taken by the "--revision" argument
1462+to many bzr commands. See "bzr help revisionspec" for details.
1463+
1464+You can also merge specific subdirectories from a branch with a "nest-part"
1465+line like
1466+
1467+ nest-part packaging lp:~foo-dev/foo/packaging debian
1468+
1469+which specifies that the only the debian/ subdirectory should be merged. This
1470+works even if the branches share no revision history. You can optionally
1471+specify the subdirectory and revision in the target with a line like
1472+
1473+ nest-part libfoo lp:libfoo src lib/foo tag:release-1.2
1474+
1475+which will put the "src" directory of libfoo in "lib/foo", using the revision
1476+of libfoo tagged "release-1.2".
1477+
1478+It is also possible to run an arbitrary command at a particular point in the
1479+construction process. For example::
1480+
1481+ run autoreconf -i
1482+
1483+will run autotools at a particular point. Doing things with branches is usually
1484+preferred, but sometimes it is the easier or only way to achieve something.
1485+Note that you usually shouldn't rely on having general Internet access when
1486+assembling the recipe, so commands that require it should be avoided.
1487+
1488+You can then build this branch by running::
1489+
1490+ bzr build foo.recipe working-dir
1491+
1492+(assuming you saved it as foo.recipe in your current directory).
1493+
1494+Once the command finished it will have placed the result in "working-dir".
1495+
1496+It is also possible to produce Debian source packages from a recipe, assuming
1497+that one of the branches in the recipe contains some appropriate packaging.
1498+You can do this using the "bzr dailydeb" command, which takes the same
1499+arguments as "build". Only this time in the working dir you will find a source
1500+package and a directory containing the code that the packages was built from
1501+once it is done. Also take a look at the "--key-id" and "--dput" arguments to
1502+have "bzr dailydeb" sign and upload the source package somewhere.
1503+
1504+To build Debian source package that you desire you should make sure that
1505+"deb-version" is set to an appropriate value on the first line of your
1506+recipe. This will be used as the version number of the package. The
1507+value you put there also allows for substitution of values in to it based
1508+on various things when the recipe is processed:
1509+
1510+ * {time} will be substituted with the current date and time, such as
1511+ 200908191512.
1512+ * {date} will be substituted with just the current date, such as
1513+ 20090819.
1514+ * {revno} will be the revno of the base branch (the first specified).
1515+ * {revno:<branch name>} will be substituted with the revno for the
1516+ branch named <branch name> in the recipe.
1517+ * {debupstream} will be replaced by the upstream portion of the version
1518+ number taken from debian/changelog in the final tree. If when the
1519+ tree is built the top of debian/changelog has a version number of
1520+ "1.0-1" then this would evaluate to "1.0".
1521+
1522+Instruction syntax summary:
1523+
1524+ * nest NAME BRANCH TARGET-DIR [REVISION]
1525+ * merge NAME BRANCH [REVISION]
1526+ * nest-part NAME BRANCH SUBDIR [TARGET-DIR [REVISION]]
1527+ * run COMMAND
1528+
1529+Format versions:
1530+
1531+ 0.1 - original format.
1532+ 0.2 - added "run" instruction.
1533+ 0.3 - added "nest-part" instruction.
1534+ 0.4 - made "deb-version" optional, added several new substitution variables
1535+"""
1536+
1537+if __name__ == '__main__':
1538+ import os
1539+ import subprocess
1540+ import sys
1541+ dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "plugins")
1542+ retcode = subprocess.call("bzr selftest -s bzrlib.plugins.builder",
1543+ shell=True, env={"BZR_PLUGIN_PATH": dir})
1544+ sys.exit(retcode)
1545+
1546+
1547+from bzrlib.commands import plugin_cmds
1548+plugin_cmds.register_lazy("cmd_build", [], "bzrlib.plugins.builder.cmds")
1549+plugin_cmds.register_lazy("cmd_dailydeb", [], "bzrlib.plugins.builder.cmds")
1550+
1551+
1552+def test_suite():
1553+ from unittest import TestSuite
1554+ from bzrlib.plugins.builder import tests
1555+ result = TestSuite()
1556+ result.addTest(tests.test_suite())
1557+ return result
1558
1559=== removed file '__init__.py'
1560--- __init__.py 2010-10-21 21:17:28 +0000
1561+++ __init__.py 1970-01-01 00:00:00 +0000
1562@@ -1,165 +0,0 @@
1563-# bzr-builder: a bzr plugin to constuct trees based on recipes
1564-# Copyright 2009 Canonical Ltd.
1565-
1566-# This program is free software: you can redistribute it and/or modify it
1567-# under the terms of the GNU General Public License version 3, as published
1568-# by the Free Software Foundation.
1569-
1570-# This program is distributed in the hope that it will be useful, but
1571-# WITHOUT ANY WARRANTY; without even the implied warranties of
1572-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1573-# PURPOSE. See the GNU General Public License for more details.
1574-
1575-# You should have received a copy of the GNU General Public License along
1576-# with this program. If not, see <http://www.gnu.org/licenses/>.
1577-
1578-"""The bzr-builder plugin allows you to construct a branch from a 'recipe'.
1579-
1580-The recipe is a series of pointers to branches and instructions for how they
1581-should be combined. There are two ways to combine branches, by merging, and
1582-by nesting, allowing much flexibility.
1583-
1584-A recipe is just a text file that starts with a line such as::
1585-
1586- # bzr-builder format 0.3 deb-version 1.0+{revno}-{revno:packaging}
1587-
1588-The format specifier is there to allow the syntax to be changed in later
1589-versions, and the meaning of "deb-version" will be explained later.
1590-
1591-The next step is the define the base branch, this is the branch that will
1592-be places at the root, e.g. just put::
1593-
1594- lp:foo
1595-
1596-to use the trunk of "foo" hosted on Launchpad.
1597-
1598-Next comes any number of lines of other branches to be merged in, but using
1599-a slightly different format. To merge a branch in to the base specify
1600-something like::
1601-
1602- merge packaging lp:~foo-dev/foo/packaging
1603-
1604-which specifies we are merging a branch we will refer to as "packaging", which
1605-can be found at the given URI. The name you give to the branch as the second
1606-item doesn't have to match anything else, it's just an identifier specific
1607-to the recipe.
1608-
1609-If you wish to nest a branch then you use a similar line::
1610-
1611- nest artwork lp:foo-images images
1612-
1613-This specifies that we are nesting the branch at lp:foo-images, which we will
1614-call "artwork", and we will place it locally in to the "images" directory.
1615-
1616-You can then continue in this fashion for as many branches as you like. It
1617-is also possible to nest and merge branches into nested branches. For example
1618-to merge a branch in to the "artwork" branch we put the following on the line
1619-below that one, indented by two spaces::
1620-
1621- merge artwork-fixes lp:~bob/foo-images/fix-12345
1622-
1623-which will merge Bob's fixes branch into the "artwork" branch which we nested
1624-at "images".
1625-
1626-It is also possible to specify a particular revision of a branch by appending
1627-a revisionspec to the line. For instance::
1628-
1629- nest docs lp:foo-docs doc tag:1.0
1630-
1631-will nest the revision pointed to by the "1.0" tag of that branch. The format
1632-for the revisionspec is identical to that taken by the "--revision" argument
1633-to many bzr commands. See "bzr help revisionspec" for details.
1634-
1635-You can also merge specific subdirectories from a branch with a "nest-part"
1636-line like
1637-
1638- nest-part packaging lp:~foo-dev/foo/packaging debian
1639-
1640-which specifies that the only the debian/ subdirectory should be merged. This
1641-works even if the branches share no revision history. You can optionally
1642-specify the subdirectory and revision in the target with a line like
1643-
1644- nest-part libfoo lp:libfoo src lib/foo tag:release-1.2
1645-
1646-which will put the "src" directory of libfoo in "lib/foo", using the revision
1647-of libfoo tagged "release-1.2".
1648-
1649-It is also possible to run an arbitrary command at a particular point in the
1650-construction process. For example::
1651-
1652- run autoreconf -i
1653-
1654-will run autotools at a particular point. Doing things with branches is usually
1655-preferred, but sometimes it is the easier or only way to achieve something.
1656-Note that you usually shouldn't rely on having general Internet access when
1657-assembling the recipe, so commands that require it should be avoided.
1658-
1659-You can then build this branch by running::
1660-
1661- bzr build foo.recipe working-dir
1662-
1663-(assuming you saved it as foo.recipe in your current directory).
1664-
1665-Once the command finished it will have placed the result in "working-dir".
1666-
1667-It is also possible to produce Debian source packages from a recipe, assuming
1668-that one of the branches in the recipe contains some appropriate packaging.
1669-You can do this using the "bzr dailydeb" command, which takes the same
1670-arguments as "build". Only this time in the working dir you will find a source
1671-package and a directory containing the code that the packages was built from
1672-once it is done. Also take a look at the "--key-id" and "--dput" arguments to
1673-have "bzr dailydeb" sign and upload the source package somewhere.
1674-
1675-To build Debian source package that you desire you should make sure that
1676-"deb-version" is set to an appropriate value on the first line of your
1677-recipe. This will be used as the version number of the package. The
1678-value you put there also allows for substitution of values in to it based
1679-on various things when the recipe is processed:
1680-
1681- * {time} will be substituted with the current date and time, such as
1682- 200908191512.
1683- * {date} will be substituted with just the current date, such as
1684- 20090819.
1685- * {revno} will be the revno of the base branch (the first specified).
1686- * {revno:<branch name>} will be substituted with the revno for the
1687- branch named <branch name> in the recipe.
1688- * {debupstream} will be replaced by the upstream portion of the version
1689- number taken from debian/changelog in the final tree. If when the
1690- tree is built the top of debian/changelog has a version number of
1691- "1.0-1" then this would evaluate to "1.0".
1692-
1693-Instruction syntax summary:
1694-
1695- * nest NAME BRANCH TARGET-DIR [REVISION]
1696- * merge NAME BRANCH [REVISION]
1697- * nest-part NAME BRANCH SUBDIR [TARGET-DIR [REVISION]]
1698- * run COMMAND
1699-
1700-Format versions:
1701-
1702- 0.1 - original format.
1703- 0.2 - added "run" instruction.
1704- 0.3 - added "nest-part" instruction.
1705-"""
1706-
1707-if __name__ == '__main__':
1708- import os
1709- import subprocess
1710- import sys
1711- dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "plugins")
1712- retcode = subprocess.call("bzr selftest -s bzrlib.plugins.builder",
1713- shell=True, env={"BZR_PLUGIN_PATH": dir})
1714- sys.exit(retcode)
1715-
1716-
1717-from bzrlib.commands import plugin_cmds
1718-plugin_cmds.register_lazy("cmd_build", [], "bzrlib.plugins.builder.cmds")
1719-plugin_cmds.register_lazy("cmd_dailydeb", [], "bzrlib.plugins.builder.cmds")
1720-
1721-
1722-def test_suite():
1723- from unittest import TestSuite
1724- from bzrlib.plugins.builder import tests
1725- result = TestSuite()
1726- result.addTest(tests.test_suite())
1727- return result
1728
1729=== added file 'bzrlibbackports.py'
1730--- bzrlibbackports.py 1970-01-01 00:00:00 +0000
1731+++ bzrlibbackports.py 2011-06-14 17:23:32 +0000
1732@@ -0,0 +1,227 @@
1733+# bzr-builder: a bzr plugin to constuct trees based on recipes
1734+# Copyright 2010 Canonical Ltd.
1735+
1736+# This program is free software: you can redistribute it and/or modify it
1737+# under the terms of the GNU General Public License version 3, as published
1738+# by the Free Software Foundation.
1739+
1740+# This program is distributed in the hope that it will be useful, but
1741+# WITHOUT ANY WARRANTY; without even the implied warranties of
1742+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1743+# PURPOSE. See the GNU General Public License for more details.
1744+
1745+# You should have received a copy of the GNU General Public License along
1746+# with this program. If not, see <http://www.gnu.org/licenses/>.
1747+
1748+"""Copies/backports features from recent bzrlib versions.
1749+
1750+This allows bzr-builder to continue to work with older bzrlib versions while
1751+using features from newer versions.
1752+"""
1753+
1754+# NOTE FOR DEVELOPERS: with each backport please include a comment saying which
1755+# version of bzr you are backporting from, to make it easier to copy bugfixes
1756+# made in bzr (and so that we know which things we can drop from this module if
1757+# bzr-builder ever raises which version of bzr it depends on).
1758+
1759+from bzrlib.merge import (
1760+ Merger,
1761+ Merge3Merger,
1762+ )
1763+from bzrlib import (
1764+ errors,
1765+ generate_ids,
1766+ osutils,
1767+ revision as _mod_revision,
1768+ transform,
1769+ ui,
1770+ )
1771+
1772+# Backport of bzrlib.merge.MergeIntoMerger, introduced in bzr 2.2rc1.
1773+# (Also backports PathNotInTree, _MergeTypeParameterizer, MergeIntoMergeType)
1774+class PathNotInTree(errors.BzrError):
1775+
1776+ _fmt = """Merge-into failed because %(tree)s does not contain %(path)s."""
1777+
1778+ def __init__(self, path, tree):
1779+ errors.BzrError.__init__(self, path=path, tree=tree)
1780+
1781+
1782+class MergeIntoMerger(Merger):
1783+ """Merger that understands other_tree will be merged into a subdir.
1784+
1785+ This also changes the Merger api so that it uses real Branch, revision_id,
1786+ and RevisonTree objects, rather than using revision specs.
1787+ """
1788+
1789+ def __init__(self, this_tree, other_branch, other_tree, target_subdir,
1790+ source_subpath, other_rev_id=None):
1791+ """Create a new MergeIntoMerger object.
1792+
1793+ source_subpath in other_tree will be effectively copied to
1794+ target_subdir in this_tree.
1795+
1796+ :param this_tree: The tree that we will be merging into.
1797+ :param other_branch: The Branch we will be merging from.
1798+ :param other_tree: The RevisionTree object we want to merge.
1799+ :param target_subdir: The relative path where we want to merge
1800+ other_tree into this_tree
1801+ :param source_subpath: The relative path specifying the subtree of
1802+ other_tree to merge into this_tree.
1803+ """
1804+ # It is assumed that we are merging a tree that is not in our current
1805+ # ancestry, which means we are using the "EmptyTree" as our basis.
1806+ null_ancestor_tree = this_tree.branch.repository.revision_tree(
1807+ _mod_revision.NULL_REVISION)
1808+ super(MergeIntoMerger, self).__init__(
1809+ this_branch=this_tree.branch,
1810+ this_tree=this_tree,
1811+ other_tree=other_tree,
1812+ base_tree=null_ancestor_tree,
1813+ )
1814+ self._target_subdir = target_subdir
1815+ self._source_subpath = source_subpath
1816+ self.other_branch = other_branch
1817+ if other_rev_id is None:
1818+ other_rev_id = other_tree.get_revision_id()
1819+ self.other_rev_id = self.other_basis = other_rev_id
1820+ self.base_is_ancestor = True
1821+ self.backup_files = True
1822+ self.merge_type = Merge3Merger
1823+ self.show_base = False
1824+ self.reprocess = False
1825+ self.interesting_ids = None
1826+ self.merge_type = _MergeTypeParameterizer(MergeIntoMergeType,
1827+ target_subdir=self._target_subdir,
1828+ source_subpath=self._source_subpath)
1829+ if self._source_subpath != '':
1830+ # If this isn't a partial merge make sure the revisions will be
1831+ # present.
1832+ self._maybe_fetch(self.other_branch, self.this_branch,
1833+ self.other_basis)
1834+
1835+ def set_pending(self):
1836+ if self._source_subpath != '':
1837+ return
1838+ Merger.set_pending(self)
1839+
1840+
1841+class _MergeTypeParameterizer(object):
1842+ """Wrap a merge-type class to provide extra parameters.
1843+
1844+ This is hack used by MergeIntoMerger to pass some extra parameters to its
1845+ merge_type. Merger.do_merge() sets up its own set of parameters to pass to
1846+ the 'merge_type' member. It is difficult override do_merge without
1847+ re-writing the whole thing, so instead we create a wrapper which will pass
1848+ the extra parameters.
1849+ """
1850+
1851+ def __init__(self, merge_type, **kwargs):
1852+ self._extra_kwargs = kwargs
1853+ self._merge_type = merge_type
1854+
1855+ def __call__(self, *args, **kwargs):
1856+ kwargs.update(self._extra_kwargs)
1857+ return self._merge_type(*args, **kwargs)
1858+
1859+ def __getattr__(self, name):
1860+ return getattr(self._merge_type, name)
1861+
1862+
1863+class MergeIntoMergeType(Merge3Merger):
1864+ """Merger that incorporates a tree (or part of a tree) into another."""
1865+
1866+ # Backport note: the definition of _finish_computing_transform is copied
1867+ # from Merge3Merger in bzr 2.2 (it is supposed to be inherited from
1868+ # Merge3Merger, but was only introduced in 2.2).
1869+ def _finish_computing_transform(self):
1870+ """Finalize the transform and report the changes.
1871+
1872+ This is the second half of _compute_transform.
1873+ """
1874+ child_pb = ui.ui_factory.nested_progress_bar()
1875+ try:
1876+ fs_conflicts = transform.resolve_conflicts(self.tt, child_pb,
1877+ lambda t, c: transform.conflict_pass(t, c, self.other_tree))
1878+ finally:
1879+ child_pb.finished()
1880+ if self.change_reporter is not None:
1881+ from bzrlib import delta
1882+ delta.report_changes(
1883+ self.tt.iter_changes(), self.change_reporter)
1884+ self.cook_conflicts(fs_conflicts)
1885+ from bzrlib import trace
1886+ for conflict in self.cooked_conflicts:
1887+ trace.warning(conflict)
1888+
1889+ def __init__(self, *args, **kwargs):
1890+ """Initialize the merger object.
1891+
1892+ :param args: See Merge3Merger.__init__'s args.
1893+ :param kwargs: See Merge3Merger.__init__'s keyword args, except for
1894+ source_subpath and target_subdir.
1895+ :keyword source_subpath: The relative path specifying the subtree of
1896+ other_tree to merge into this_tree.
1897+ :keyword target_subdir: The relative path where we want to merge
1898+ other_tree into this_tree
1899+ """
1900+ # All of the interesting work happens during Merge3Merger.__init__(),
1901+ # so we have have to hack in to get our extra parameters set.
1902+ self._source_subpath = kwargs.pop('source_subpath')
1903+ self._target_subdir = kwargs.pop('target_subdir')
1904+ super(MergeIntoMergeType, self).__init__(*args, **kwargs)
1905+
1906+ def _compute_transform(self):
1907+ child_pb = ui.ui_factory.nested_progress_bar()
1908+ try:
1909+ entries = self._entries_to_incorporate()
1910+ entries = list(entries)
1911+ for num, (entry, parent_id) in enumerate(entries):
1912+ child_pb.update('Preparing file merge', num, len(entries))
1913+ parent_trans_id = self.tt.trans_id_file_id(parent_id)
1914+ trans_id = transform.new_by_entry(self.tt, entry,
1915+ parent_trans_id, self.other_tree)
1916+ finally:
1917+ child_pb.finished()
1918+ self._finish_computing_transform()
1919+
1920+ def _entries_to_incorporate(self):
1921+ """Yields pairs of (inventory_entry, new_parent)."""
1922+ other_inv = self.other_tree.inventory
1923+ subdir_id = other_inv.path2id(self._source_subpath)
1924+ if subdir_id is None:
1925+ # XXX: The error would be clearer if it gave the URL of the source
1926+ # branch, but we don't have a reference to that here.
1927+ raise PathNotInTree(self._source_subpath, "Source tree")
1928+ subdir = other_inv[subdir_id]
1929+ parent_in_target = osutils.dirname(self._target_subdir)
1930+ target_id = self.this_tree.inventory.path2id(parent_in_target)
1931+ if target_id is None:
1932+ raise PathNotInTree(self._target_subdir, "Target tree")
1933+ name_in_target = osutils.basename(self._target_subdir)
1934+ merge_into_root = subdir.copy()
1935+ merge_into_root.name = name_in_target
1936+ if merge_into_root.file_id in self.this_tree.inventory:
1937+ # Give the root a new file-id.
1938+ # This can happen fairly easily if the directory we are
1939+ # incorporating is the root, and both trees have 'TREE_ROOT' as
1940+ # their root_id. Users will expect this to Just Work, so we
1941+ # change the file-id here.
1942+ # Non-root file-ids could potentially conflict too. That's really
1943+ # an edge case, so we don't do anything special for those. We let
1944+ # them cause conflicts.
1945+ merge_into_root.file_id = generate_ids.gen_file_id(name_in_target)
1946+ yield (merge_into_root, target_id)
1947+ if subdir.kind != 'directory':
1948+ # No children, so we are done.
1949+ return
1950+ for ignored_path, entry in other_inv.iter_entries_by_dir(subdir_id):
1951+ parent_id = entry.parent_id
1952+ if parent_id == subdir.file_id:
1953+ # The root's parent ID has changed, so make sure children of
1954+ # the root refer to the new ID.
1955+ parent_id = merge_into_root.file_id
1956+ yield (entry, parent_id)
1957+
1958+
1959+
1960
1961=== removed file 'bzrlibbackports.py'
1962--- bzrlibbackports.py 2010-10-21 21:17:28 +0000
1963+++ bzrlibbackports.py 1970-01-01 00:00:00 +0000
1964@@ -1,227 +0,0 @@
1965-# bzr-builder: a bzr plugin to constuct trees based on recipes
1966-# Copyright 2010 Canonical Ltd.
1967-
1968-# This program is free software: you can redistribute it and/or modify it
1969-# under the terms of the GNU General Public License version 3, as published
1970-# by the Free Software Foundation.
1971-
1972-# This program is distributed in the hope that it will be useful, but
1973-# WITHOUT ANY WARRANTY; without even the implied warranties of
1974-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1975-# PURPOSE. See the GNU General Public License for more details.
1976-
1977-# You should have received a copy of the GNU General Public License along
1978-# with this program. If not, see <http://www.gnu.org/licenses/>.
1979-
1980-"""Copies/backports features from recent bzrlib versions.
1981-
1982-This allows bzr-builder to continue to work with older bzrlib versions while
1983-using features from newer versions.
1984-"""
1985-
1986-# NOTE FOR DEVELOPERS: with each backport please include a comment saying which
1987-# version of bzr you are backporting from, to make it easier to copy bugfixes
1988-# made in bzr (and so that we know which things we can drop from this module if
1989-# bzr-builder ever raises which version of bzr it depends on).
1990-
1991-from bzrlib.merge import (
1992- Merger,
1993- Merge3Merger,
1994- )
1995-from bzrlib import (
1996- errors,
1997- generate_ids,
1998- osutils,
1999- revision as _mod_revision,
2000- transform,
2001- ui,
2002- )
2003-
2004-# Backport of bzrlib.merge.MergeIntoMerger, introduced in bzr 2.2rc1.
2005-# (Also backports PathNotInTree, _MergeTypeParameterizer, MergeIntoMergeType)
2006-class PathNotInTree(errors.BzrError):
2007-
2008- _fmt = """Merge-into failed because %(tree)s does not contain %(path)s."""
2009-
2010- def __init__(self, path, tree):
2011- errors.BzrError.__init__(self, path=path, tree=tree)
2012-
2013-
2014-class MergeIntoMerger(Merger):
2015- """Merger that understands other_tree will be merged into a subdir.
2016-
2017- This also changes the Merger api so that it uses real Branch, revision_id,
2018- and RevisonTree objects, rather than using revision specs.
2019- """
2020-
2021- def __init__(self, this_tree, other_branch, other_tree, target_subdir,
2022- source_subpath, other_rev_id=None):
2023- """Create a new MergeIntoMerger object.
2024-
2025- source_subpath in other_tree will be effectively copied to
2026- target_subdir in this_tree.
2027-
2028- :param this_tree: The tree that we will be merging into.
2029- :param other_branch: The Branch we will be merging from.
2030- :param other_tree: The RevisionTree object we want to merge.
2031- :param target_subdir: The relative path where we want to merge
2032- other_tree into this_tree
2033- :param source_subpath: The relative path specifying the subtree of
2034- other_tree to merge into this_tree.
2035- """
2036- # It is assumed that we are merging a tree that is not in our current
2037- # ancestry, which means we are using the "EmptyTree" as our basis.
2038- null_ancestor_tree = this_tree.branch.repository.revision_tree(
2039- _mod_revision.NULL_REVISION)
2040- super(MergeIntoMerger, self).__init__(
2041- this_branch=this_tree.branch,
2042- this_tree=this_tree,
2043- other_tree=other_tree,
2044- base_tree=null_ancestor_tree,
2045- )
2046- self._target_subdir = target_subdir
2047- self._source_subpath = source_subpath
2048- self.other_branch = other_branch
2049- if other_rev_id is None:
2050- other_rev_id = other_tree.get_revision_id()
2051- self.other_rev_id = self.other_basis = other_rev_id
2052- self.base_is_ancestor = True
2053- self.backup_files = True
2054- self.merge_type = Merge3Merger
2055- self.show_base = False
2056- self.reprocess = False
2057- self.interesting_ids = None
2058- self.merge_type = _MergeTypeParameterizer(MergeIntoMergeType,
2059- target_subdir=self._target_subdir,
2060- source_subpath=self._source_subpath)
2061- if self._source_subpath != '':
2062- # If this isn't a partial merge make sure the revisions will be
2063- # present.
2064- self._maybe_fetch(self.other_branch, self.this_branch,
2065- self.other_basis)
2066-
2067- def set_pending(self):
2068- if self._source_subpath != '':
2069- return
2070- Merger.set_pending(self)
2071-
2072-
2073-class _MergeTypeParameterizer(object):
2074- """Wrap a merge-type class to provide extra parameters.
2075-
2076- This is hack used by MergeIntoMerger to pass some extra parameters to its
2077- merge_type. Merger.do_merge() sets up its own set of parameters to pass to
2078- the 'merge_type' member. It is difficult override do_merge without
2079- re-writing the whole thing, so instead we create a wrapper which will pass
2080- the extra parameters.
2081- """
2082-
2083- def __init__(self, merge_type, **kwargs):
2084- self._extra_kwargs = kwargs
2085- self._merge_type = merge_type
2086-
2087- def __call__(self, *args, **kwargs):
2088- kwargs.update(self._extra_kwargs)
2089- return self._merge_type(*args, **kwargs)
2090-
2091- def __getattr__(self, name):
2092- return getattr(self._merge_type, name)
2093-
2094-
2095-class MergeIntoMergeType(Merge3Merger):
2096- """Merger that incorporates a tree (or part of a tree) into another."""
2097-
2098- # Backport note: the definition of _finish_computing_transform is copied
2099- # from Merge3Merger in bzr 2.2 (it is supposed to be inherited from
2100- # Merge3Merger, but was only introduced in 2.2).
2101- def _finish_computing_transform(self):
2102- """Finalize the transform and report the changes.
2103-
2104- This is the second half of _compute_transform.
2105- """
2106- child_pb = ui.ui_factory.nested_progress_bar()
2107- try:
2108- fs_conflicts = transform.resolve_conflicts(self.tt, child_pb,
2109- lambda t, c: transform.conflict_pass(t, c, self.other_tree))
2110- finally:
2111- child_pb.finished()
2112- if self.change_reporter is not None:
2113- from bzrlib import delta
2114- delta.report_changes(
2115- self.tt.iter_changes(), self.change_reporter)
2116- self.cook_conflicts(fs_conflicts)
2117- from bzrlib import trace
2118- for conflict in self.cooked_conflicts:
2119- trace.warning(conflict)
2120-
2121- def __init__(self, *args, **kwargs):
2122- """Initialize the merger object.
2123-
2124- :param args: See Merge3Merger.__init__'s args.
2125- :param kwargs: See Merge3Merger.__init__'s keyword args, except for
2126- source_subpath and target_subdir.
2127- :keyword source_subpath: The relative path specifying the subtree of
2128- other_tree to merge into this_tree.
2129- :keyword target_subdir: The relative path where we want to merge
2130- other_tree into this_tree
2131- """
2132- # All of the interesting work happens during Merge3Merger.__init__(),
2133- # so we have have to hack in to get our extra parameters set.
2134- self._source_subpath = kwargs.pop('source_subpath')
2135- self._target_subdir = kwargs.pop('target_subdir')
2136- super(MergeIntoMergeType, self).__init__(*args, **kwargs)
2137-
2138- def _compute_transform(self):
2139- child_pb = ui.ui_factory.nested_progress_bar()
2140- try:
2141- entries = self._entries_to_incorporate()
2142- entries = list(entries)
2143- for num, (entry, parent_id) in enumerate(entries):
2144- child_pb.update('Preparing file merge', num, len(entries))
2145- parent_trans_id = self.tt.trans_id_file_id(parent_id)
2146- trans_id = transform.new_by_entry(self.tt, entry,
2147- parent_trans_id, self.other_tree)
2148- finally:
2149- child_pb.finished()
2150- self._finish_computing_transform()
2151-
2152- def _entries_to_incorporate(self):
2153- """Yields pairs of (inventory_entry, new_parent)."""
2154- other_inv = self.other_tree.inventory
2155- subdir_id = other_inv.path2id(self._source_subpath)
2156- if subdir_id is None:
2157- # XXX: The error would be clearer if it gave the URL of the source
2158- # branch, but we don't have a reference to that here.
2159- raise PathNotInTree(self._source_subpath, "Source tree")
2160- subdir = other_inv[subdir_id]
2161- parent_in_target = osutils.dirname(self._target_subdir)
2162- target_id = self.this_tree.inventory.path2id(parent_in_target)
2163- if target_id is None:
2164- raise PathNotInTree(self._target_subdir, "Target tree")
2165- name_in_target = osutils.basename(self._target_subdir)
2166- merge_into_root = subdir.copy()
2167- merge_into_root.name = name_in_target
2168- if merge_into_root.file_id in self.this_tree.inventory:
2169- # Give the root a new file-id.
2170- # This can happen fairly easily if the directory we are
2171- # incorporating is the root, and both trees have 'TREE_ROOT' as
2172- # their root_id. Users will expect this to Just Work, so we
2173- # change the file-id here.
2174- # Non-root file-ids could potentially conflict too. That's really
2175- # an edge case, so we don't do anything special for those. We let
2176- # them cause conflicts.
2177- merge_into_root.file_id = generate_ids.gen_file_id(name_in_target)
2178- yield (merge_into_root, target_id)
2179- if subdir.kind != 'directory':
2180- # No children, so we are done.
2181- return
2182- for ignored_path, entry in other_inv.iter_entries_by_dir(subdir_id):
2183- parent_id = entry.parent_id
2184- if parent_id == subdir.file_id:
2185- # The root's parent ID has changed, so make sure children of
2186- # the root refer to the new ID.
2187- parent_id = merge_into_root.file_id
2188- yield (entry, parent_id)
2189-
2190-
2191-
2192
2193=== added file 'cmds.py'
2194--- cmds.py 1970-01-01 00:00:00 +0000
2195+++ cmds.py 2011-06-14 17:23:32 +0000
2196@@ -0,0 +1,778 @@
2197+# bzr-builder: a bzr plugin to constuct trees based on recipes
2198+# Copyright 2009 Canonical Ltd.
2199+
2200+# This program is free software: you can redistribute it and/or modify it
2201+# under the terms of the GNU General Public License version 3, as published
2202+# by the Free Software Foundation.
2203+
2204+# This program is distributed in the hope that it will be useful, but
2205+# WITHOUT ANY WARRANTY; without even the implied warranties of
2206+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2207+# PURPOSE. See the GNU General Public License for more details.
2208+
2209+# You should have received a copy of the GNU General Public License along
2210+# with this program. If not, see <http://www.gnu.org/licenses/>.
2211+
2212+"""Subcommands provided by bzr-builder."""
2213+
2214+from base64 import standard_b64decode
2215+from StringIO import StringIO
2216+import datetime
2217+from email import utils
2218+import errno
2219+import os
2220+import pwd
2221+import re
2222+import signal
2223+import socket
2224+import shutil
2225+import subprocess
2226+import tempfile
2227+
2228+try:
2229+ from debian import changelog, deb822
2230+except ImportError:
2231+ # In older versions of python-debian the main package was named
2232+ # debian_bundle
2233+ from debian_bundle import changelog, deb822
2234+
2235+from bzrlib import (
2236+ errors,
2237+ export as _mod_export,
2238+ lazy_regex,
2239+ trace,
2240+ transport as _mod_transport,
2241+ urlutils,
2242+ )
2243+from bzrlib.branch import Branch
2244+from bzrlib.commands import Command
2245+from bzrlib.option import Option
2246+
2247+from bzrlib.plugins.builder.recipe import (
2248+ BaseRecipeBranch,
2249+ build_tree,
2250+ RecipeParser,
2251+ resolve_revisions,
2252+ SAFE_INSTRUCTIONS,
2253+ )
2254+
2255+
2256+# The default distribution used by add_autobuild_changelog_entry()
2257+DEFAULT_UBUNTU_DISTRIBUTION = "lucid"
2258+
2259+
2260+class MissingDependency(errors.BzrError):
2261+ pass
2262+
2263+
2264+def write_manifest_to_transport(location, base_branch,
2265+ possible_transports=None):
2266+ """Write a manifest to disk.
2267+
2268+ :param location: Location to write to
2269+ :param base_branch: Recipe base branch
2270+ """
2271+ child_transport = _mod_transport.get_transport(location,
2272+ possible_transports=possible_transports)
2273+ base_transport = child_transport.clone('..')
2274+ base_transport.create_prefix()
2275+ basename = base_transport.relpath(child_transport.base)
2276+ base_transport.put_bytes(basename, str(base_branch))
2277+
2278+
2279+def get_branch_from_recipe_location(recipe_location, safe=False,
2280+ possible_transports=None):
2281+ """Return the base branch for the specified recipe.
2282+
2283+ :param recipe_location: The URL of the recipe file to retrieve.
2284+ :param safe: if True, reject recipes that would cause arbitrary code
2285+ execution.
2286+ """
2287+ if safe:
2288+ permitted_instructions = SAFE_INSTRUCTIONS
2289+ else:
2290+ permitted_instructions = None
2291+ try:
2292+ (basename, f) = get_recipe_from_location(recipe_location, possible_transports)
2293+ except errors.NoSuchFile:
2294+ raise errors.BzrCommandError("Specified recipe does not exist: "
2295+ "%s" % recipe_location)
2296+ try:
2297+ parser = RecipeParser(f, filename=recipe_location)
2298+ finally:
2299+ f.close()
2300+ return parser.parse(permitted_instructions=permitted_instructions)
2301+
2302+
2303+def get_branch_from_branch_location(branch_location, possible_transports=None,
2304+ revspec=None):
2305+ """Return the base branch for the branch location.
2306+
2307+ :param branch_location: The URL of the branch to retrieve.
2308+ """
2309+ # Make sure it's actually a branch
2310+ Branch.open(branch_location)
2311+ return BaseRecipeBranch(branch_location, None,
2312+ RecipeParser.NEWEST_VERSION, revspec=revspec)
2313+
2314+
2315+def get_old_recipe(if_changed_from, possible_transports=None):
2316+ try:
2317+ (basename, f) = get_recipe_from_location(if_changed_from, possible_transports)
2318+ except errors.NoSuchFile:
2319+ return None
2320+ try:
2321+ old_recipe = RecipeParser(f,
2322+ filename=if_changed_from).parse()
2323+ finally:
2324+ f.close()
2325+ return old_recipe
2326+
2327+
2328+def get_maintainer():
2329+ """Create maintainer string using the same algorithm as in dch.
2330+ """
2331+ env = os.environ
2332+ regex = re.compile(r"^(.*)\s+<(.*)>$")
2333+
2334+ # Split email and name
2335+ if 'DEBEMAIL' in env:
2336+ match_obj = regex.match(env['DEBEMAIL'])
2337+ if match_obj:
2338+ if not 'DEBFULLNAME' in env:
2339+ env['DEBFULLNAME'] = match_obj.group(1)
2340+ env['DEBEMAIL'] = match_obj.group(2)
2341+ if 'DEBEMAIL' not in env or 'DEBFULLNAME' not in env:
2342+ if 'EMAIL' in env:
2343+ match_obj = regex.match(env['EMAIL'])
2344+ if match_obj:
2345+ if not 'DEBFULLNAME' in env:
2346+ env['DEBFULLNAME'] = match_obj.group(1)
2347+ env['EMAIL'] = match_obj.group(2)
2348+
2349+ # Get maintainer's name
2350+ if 'DEBFULLNAME' in env:
2351+ maintainer = env['DEBFULLNAME']
2352+ elif 'NAME' in env:
2353+ maintainer = env['NAME']
2354+ else:
2355+ # Use password database if no data in environment variables
2356+ try:
2357+ maintainer = re.sub(r',.*', '', pwd.getpwuid(os.getuid()).pw_gecos)
2358+ except (KeyError, AttributeError):
2359+ # TBD: Use last changelog entry value
2360+ maintainer = "bzr-builder"
2361+
2362+ # Get maintainer's mail address
2363+ if 'DEBEMAIL' in env:
2364+ email = env['DEBEMAIL']
2365+ elif 'EMAIL' in env:
2366+ email = env['EMAIL']
2367+ else:
2368+ addr = None
2369+ if os.path.exists('/etc/mailname'):
2370+ f = open('/etc/mailname')
2371+ try:
2372+ addr = f.readline().strip()
2373+ finally:
2374+ f.close()
2375+ if not addr:
2376+ addr = socket.getfqdn()
2377+ if addr:
2378+ user = pwd.getpwuid(os.getuid()).pw_name
2379+ if not user:
2380+ addr = None
2381+ else:
2382+ addr = "%s@%s" % (user, addr)
2383+
2384+ if addr:
2385+ email = addr
2386+ else:
2387+ # TBD: Use last changelog entry value
2388+ email = "none@example.org"
2389+
2390+ return (maintainer, email)
2391+
2392+
2393+def add_autobuild_changelog_entry(base_branch, basedir, package,
2394+ distribution=None, author_name=None, author_email=None,
2395+ append_version=None):
2396+ """Add a new changelog entry for an autobuild.
2397+
2398+ :param base_branch: Recipe base branch
2399+ :param basedir: Base working directory
2400+ :param package: package name
2401+ :param distribution: Optional distribution (defaults to last entry
2402+ distribution)
2403+ :param author_name: Name of the build requester
2404+ :param author_email: Email of the build requester
2405+ :param append_version: Optional version suffix to add
2406+ """
2407+ debian_dir = os.path.join(basedir, "debian")
2408+ if not os.path.exists(debian_dir):
2409+ os.makedirs(debian_dir)
2410+ cl_path = os.path.join(debian_dir, "changelog")
2411+ file_found = False
2412+ if os.path.exists(cl_path):
2413+ file_found = True
2414+ cl_f = open(cl_path)
2415+ try:
2416+ contents = cl_f.read()
2417+ finally:
2418+ cl_f.close()
2419+ cl = changelog.Changelog(file=contents)
2420+ else:
2421+ cl = changelog.Changelog()
2422+ if len(cl._blocks) > 0:
2423+ if distribution is None:
2424+ distribution = cl._blocks[0].distributions.split()[0]
2425+ else:
2426+ if file_found:
2427+ if len(contents.strip()) > 0:
2428+ reason = ("debian/changelog didn't contain any "
2429+ "parseable stanzas")
2430+ else:
2431+ reason = "debian/changelog was empty"
2432+ else:
2433+ reason = "debian/changelog was not present"
2434+ if distribution is None:
2435+ distribution = DEFAULT_UBUNTU_DISTRIBUTION
2436+ # Use debian packaging environment variables
2437+ # or default values if they don't exist
2438+ if author_name is None or author_email is None:
2439+ author_name, author_email = get_maintainer()
2440+ author = "%s <%s>" % (author_name, author_email)
2441+
2442+ date = utils.formatdate(localtime=True)
2443+ version = base_branch.deb_version
2444+ if append_version is not None:
2445+ version += append_version
2446+ try:
2447+ changelog.Version(version)
2448+ except (changelog.VersionError, ValueError), e:
2449+ raise errors.BzrCommandError("Invalid deb-version: %s: %s"
2450+ % (version, e))
2451+ cl.new_block(package=package, version=version,
2452+ distributions=distribution, urgency="low",
2453+ changes=['', ' * Auto build.', ''],
2454+ author=author, date=date)
2455+ cl_f = open(cl_path, 'wb')
2456+ try:
2457+ cl.write_to_open_file(cl_f)
2458+ finally:
2459+ cl_f.close()
2460+
2461+
2462+def calculate_package_dir(package_name, package_version, working_basedir):
2463+ """Calculate the directory name that should be used while debuilding.
2464+
2465+ :param base_branch: Recipe base branch
2466+ :param package_version: Version of the package
2467+ :param package_name: Package name
2468+ :param working_basedir: Base directory
2469+ """
2470+ package_basedir = "%s-%s" % (package_name, package_version.upstream_version)
2471+ package_dir = os.path.join(working_basedir, package_basedir)
2472+ return package_dir
2473+
2474+
2475+def _run_command(command, basedir, msg, error_msg,
2476+ not_installed_msg=None, env=None, success_exit_codes=None, indata=None):
2477+ """ Run a command in a subprocess.
2478+
2479+ :param command: list with command and parameters
2480+ :param msg: message to display to the user
2481+ :param error_msg: message to display if something fails.
2482+ :param not_installed_msg: the message to display if the command
2483+ isn't available.
2484+ :param env: Optional environment to use rather than os.environ.
2485+ :param success_exit_codes: Exit codes to consider succesfull, defaults to [0].
2486+ :param indata: Data to write to standard input
2487+ """
2488+ def subprocess_setup():
2489+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
2490+ trace.note(msg)
2491+ # Hide output if -q is in use.
2492+ quiet = trace.is_quiet()
2493+ if quiet:
2494+ kwargs = {"stderr": subprocess.STDOUT, "stdout": subprocess.PIPE}
2495+ else:
2496+ kwargs = {}
2497+ if env is not None:
2498+ kwargs["env"] = env
2499+ trace.mutter("running: %r", command)
2500+ try:
2501+ proc = subprocess.Popen(command, cwd=basedir,
2502+ stdin=subprocess.PIPE, preexec_fn=subprocess_setup, **kwargs)
2503+ except OSError, e:
2504+ if e.errno != errno.ENOENT:
2505+ raise
2506+ if not_installed_msg is None:
2507+ raise
2508+ raise MissingDependency(msg=not_installed_msg)
2509+ output = proc.communicate(indata)
2510+ if success_exit_codes is None:
2511+ success_exit_codes = [0]
2512+ if proc.returncode not in success_exit_codes:
2513+ if quiet:
2514+ raise errors.BzrCommandError("%s: %s" % (error_msg, output))
2515+ else:
2516+ raise errors.BzrCommandError(error_msg)
2517+
2518+
2519+def build_source_package(basedir, tgz_check=True):
2520+ command = ["/usr/bin/debuild"]
2521+ if tgz_check:
2522+ command.append("--tgz-check")
2523+ else:
2524+ command.append("--no-tgz-check")
2525+ command.extend(["-i", "-I", "-S", "-uc", "-us"])
2526+ _run_command(command, basedir,
2527+ "Building the source package",
2528+ "Failed to build the source package",
2529+ not_installed_msg="debuild is not installed, please install "
2530+ "the devscripts package.")
2531+
2532+
2533+def get_source_format(path):
2534+ """Retrieve the source format name from a package.
2535+
2536+ :param path: Path to the package
2537+ :return: String with package format
2538+ """
2539+ source_format_path = os.path.join(path, "debian", "source", "format")
2540+ if not os.path.exists(source_format_path):
2541+ return "1.0"
2542+ f = open(source_format_path, 'r')
2543+ try:
2544+ return f.read().strip()
2545+ finally:
2546+ f.close()
2547+
2548+
2549+def convert_3_0_quilt_to_native(path):
2550+ """Convert a package in 3.0 (quilt) format to 3.0 (native).
2551+
2552+ This applies all patches in the package and updates the
2553+ debian/source/format file.
2554+
2555+ :param path: Path to the package on disk
2556+ """
2557+ path = os.path.abspath(path)
2558+ patches_dir = os.path.join(path, "debian", "patches")
2559+ series_file = os.path.join(patches_dir, "series")
2560+ if os.path.exists(series_file):
2561+ _run_command(["quilt", "push", "-a", "-v"], path,
2562+ "Applying quilt patches",
2563+ "Failed to apply quilt patches",
2564+ not_installed_msg="quilt is not installed, please install it.",
2565+ env={"QUILT_SERIES": series_file, "QUILT_PATCHES": patches_dir},
2566+ success_exit_codes=(0, 2))
2567+ if os.path.exists(patches_dir):
2568+ shutil.rmtree(patches_dir)
2569+ f = open(os.path.join(path, "debian", "source", "format"), 'w')
2570+ try:
2571+ f.write("3.0 (native)\n")
2572+ finally:
2573+ f.close()
2574+
2575+
2576+def force_native_format(working_tree_path):
2577+ """Make sure a package is a format that supports native packages.
2578+
2579+ :param working_tree_path: Path to the package
2580+ """
2581+ current_format = get_source_format(working_tree_path)
2582+ if current_format == "3.0 (quilt)":
2583+ convert_3_0_quilt_to_native(working_tree_path)
2584+ elif current_format not in ("1.0", "3.0 (native)"):
2585+ raise errors.BzrCommandError("Unknown source format %s" %
2586+ current_format)
2587+
2588+
2589+def sign_source_package(basedir, key_id):
2590+ command = ["/usr/bin/debsign", "-S", "-k%s" % key_id]
2591+ _run_command(command, basedir,
2592+ "Signing the source package",
2593+ "Signing the package failed",
2594+ not_installed_msg="debsign is not installed, please install "
2595+ "the devscripts package.")
2596+
2597+
2598+def dput_source_package(basedir, target):
2599+ command = ["/usr/bin/debrelease", "-S", "--dput", target]
2600+ _run_command(command, basedir,
2601+ "Uploading the source package",
2602+ "Uploading the package failed",
2603+ not_installed_msg="debrelease is not installed, please "
2604+ "install the devscripts package.")
2605+
2606+
2607+launchpad_recipe_re = lazy_regex.lazy_compile(
2608+ r'^https://code.launchpad.net/~(.*)/\+recipe/(.*)$')
2609+
2610+
2611+def get_recipe_from_launchpad(username, recipe_name, location):
2612+ """Load a recipe from Launchpad.
2613+
2614+ :param username: The launchpad user name
2615+ :param recipe_name: Recipe name
2616+ :param location: Original location (used for error reporting)
2617+ :return: Text of the recipe
2618+ """
2619+ from launchpadlib.launchpad import Launchpad
2620+ lp = Launchpad.login_with("bzr-builder", "production")
2621+ try:
2622+ person = lp.people[username]
2623+ except KeyError:
2624+ raise errors.NoSuchFile(location,
2625+ "No such Launchpad user %s" % username)
2626+ recipe = person.getRecipe(name=recipe_name)
2627+ if recipe is None:
2628+ raise errors.NoSuchFile(location,
2629+ "Launchpad user %s has no recipe %s" % (
2630+ username, recipe_name))
2631+ return recipe.recipe_text
2632+
2633+
2634+def get_recipe_from_location(location, possible_transports=None):
2635+ """Open a recipe as a file-like object from a URL.
2636+
2637+ :param location: The recipe location
2638+ :param possible_transports: Possible transports to use
2639+ :return: Tuple with basename and file-like object
2640+ """
2641+ m = launchpad_recipe_re.match(location)
2642+ if m:
2643+ (username, recipe_name) = m.groups()
2644+ text = get_recipe_from_launchpad(username, recipe_name,
2645+ location)
2646+ return (recipe_name, StringIO(text))
2647+ child_transport = _mod_transport.get_transport(location,
2648+ possible_transports=possible_transports)
2649+ recipe_transport = child_transport.clone('..')
2650+ basename = recipe_transport.relpath(child_transport.base)
2651+ return basename, recipe_transport.get(basename)
2652+
2653+
2654+class cmd_build(Command):
2655+ """Build a tree based on a branch or a recipe.
2656+
2657+ Pass the path of a recipe file or a branch to build and the directory to
2658+ work in.
2659+
2660+ See "bzr help builder" for more information on what a recipe is.
2661+ """
2662+ takes_args = ["location", "working_directory"]
2663+ takes_options = [
2664+ Option('manifest', type=str, argname="path",
2665+ help="Path to write the manifest to."),
2666+ Option('if-changed-from', type=str, argname="path",
2667+ help="Only build if the outcome would be different "
2668+ "to that specified in the specified manifest."),
2669+ 'revision',
2670+ ]
2671+
2672+ def _get_prepared_branch_from_location(self, location,
2673+ if_changed_from=None, safe=False, possible_transports=None,
2674+ revspec=None):
2675+ """Common code to prepare a branch and do substitutions.
2676+
2677+ :param location: a path to a recipe file or branch to work from.
2678+ :param if_changed_from: an optional location of a manifest to
2679+ compare the recipe against.
2680+ :param safe: if True, reject recipes that would cause arbitrary code
2681+ execution.
2682+ :return: A tuple with (retcode, base_branch). If retcode is None
2683+ then the command execution should continue.
2684+ """
2685+ try:
2686+ base_branch = get_branch_from_recipe_location(location, safe=safe,
2687+ possible_transports=possible_transports)
2688+ except (_mod_transport.LateReadError, errors.ReadError):
2689+ # Presume unable to read means location is a directory rather than a file
2690+ base_branch = get_branch_from_branch_location(location,
2691+ possible_transports=possible_transports)
2692+ else:
2693+ if revspec is not None:
2694+ raise errors.BzrCommandError("--revision only supported when "
2695+ "building from branch")
2696+ time = datetime.datetime.utcnow()
2697+ base_branch.substitute_time(time)
2698+ old_recipe = None
2699+ if if_changed_from is not None:
2700+ old_recipe = get_old_recipe(if_changed_from, possible_transports)
2701+ # Save the unsubstituted version for dailydeb.
2702+ self._template_version = base_branch.deb_version
2703+ changed = resolve_revisions(base_branch, if_changed_from=old_recipe)
2704+ if not changed:
2705+ trace.note("Unchanged")
2706+ return 0, base_branch
2707+ return None, base_branch
2708+
2709+ def run(self, location, working_directory, manifest=None,
2710+ if_changed_from=None, revision=None):
2711+ if revision is not None and len(revision) > 0:
2712+ if len(revision) != 1:
2713+ raise errors.BzrCommandError("only a single revision can be "
2714+ "specified")
2715+ revspec = revision[0]
2716+ else:
2717+ revspec = None
2718+ possible_transports = []
2719+ result, base_branch = self._get_prepared_branch_from_location(location,
2720+ if_changed_from=if_changed_from,
2721+ possible_transports=possible_transports, revspec=revspec)
2722+ if result is not None:
2723+ return result
2724+ manifest_path = manifest or os.path.join(working_directory,
2725+ "bzr-builder.manifest")
2726+ build_tree(base_branch, working_directory)
2727+ write_manifest_to_transport(manifest_path, base_branch,
2728+ possible_transports)
2729+
2730+
2731+def debian_source_package_name(control_path):
2732+ """Open a debian control file and extract the package name.
2733+
2734+ """
2735+ with open(control_path, 'r') as f:
2736+ control = deb822.Deb822(f)
2737+ return control["Source"]
2738+
2739+
2740+def reconstruct_pristine_tar(dest, delta, dest_filename):
2741+ """Reconstruct a pristine tarball from a directory and a delta.
2742+
2743+ :param dest: Directory to pack
2744+ :param delta: pristine-tar delta
2745+ :param dest_filename: Destination filename
2746+ """
2747+ command = ["pristine-tar", "gentar", "-",
2748+ os.path.abspath(dest_filename)]
2749+ _run_command(command, dest,
2750+ "Reconstructing pristine tarball",
2751+ "Generating tar from delta failed",
2752+ not_installed_msg="pristine-tar is not installed",
2753+ indata=delta)
2754+
2755+
2756+def extract_upstream_tarball(branch, package, version, dest_dir):
2757+ """Extract the upstream tarball from a branch.
2758+
2759+ :param branch: Branch with the upstream pristine tar data
2760+ :param package: Package name
2761+ :param version: Package version
2762+ :param dest_dir: Destination directory
2763+ """
2764+ tag_name = "upstream-%s" % version
2765+ revid = branch.tags.lookup_tag(tag_name)
2766+ tree = branch.repository.revision_tree(revid)
2767+ rev = branch.repository.get_revision(revid)
2768+ if 'deb-pristine-delta' in rev.properties:
2769+ uuencoded = rev.properties['deb-pristine-delta']
2770+ dest_filename = "%s_%s.orig.tar.gz" % (package, version)
2771+ elif 'deb-pristine-delta-bz2' in rev.properties:
2772+ uuencoded = rev.properties['deb-pristine-delta-bz2']
2773+ dest_filename = "%s_%s.orig.tar.bz2" % (package, version)
2774+ else:
2775+ uuencoded = None
2776+ if uuencoded is not None:
2777+ delta = standard_b64decode(uuencoded)
2778+ dest = os.path.join(dest_dir, "orig")
2779+ try:
2780+ _mod_export.export(tree, dest, format='dir')
2781+ reconstruct_pristine_tar(dest, delta,
2782+ os.path.join(dest_dir, dest_filename))
2783+ finally:
2784+ if os.path.exists(dest):
2785+ shutil.rmtree(dest)
2786+ else:
2787+ # Default to .tar.gz
2788+ dest_filename = "%s_%s.orig.tar.gz" % (package, version)
2789+ _mod_export.export(tree, os.path.join(dest_dir, dest_filename),
2790+ per_file_timestamps=True)
2791+
2792+
2793+class cmd_dailydeb(cmd_build):
2794+ """Build a deb based on a 'recipe' or from a branch.
2795+
2796+ See "bzr help builder" for more information on what a recipe is.
2797+
2798+ If you do not specify a working directory then a temporary
2799+ directory will be used and it will be removed when the command
2800+ finishes.
2801+ """
2802+
2803+ takes_options = cmd_build.takes_options + [
2804+ Option("package", type=str,
2805+ help="The package name to use in the changelog entry. "
2806+ "If not specified then the package from the "
2807+ "previous changelog entry will be used, so it "
2808+ "must be specified if there is no changelog."),
2809+ Option("distribution", type=str,
2810+ help="The distribution to target. If not specified "
2811+ "then the same distribution as the last entry "
2812+ "in debian/changelog will be used."),
2813+ Option("dput", type=str, argname="target",
2814+ help="dput the built package to the specified "
2815+ "dput target."),
2816+ Option("key-id", type=str, short_name="k",
2817+ help="Sign the packages with the specified GnuPG key. "
2818+ "Must be specified if you use --dput."),
2819+ Option("no-build",
2820+ help="Just ready the source package and don't "
2821+ "actually build it."),
2822+ Option("watch-ppa", help="Watch the PPA the package was "
2823+ "dput to and exit with 0 only if it builds and "
2824+ "publishes successfully."),
2825+ Option("append-version", type=str, help="Append the "
2826+ "specified string to the end of the version used "
2827+ "in debian/changelog."),
2828+ Option("safe", help="Error if the recipe would cause"
2829+ " arbitrary code execution."),
2830+ Option("allow-fallback-to-native",
2831+ help="Allow falling back to a native package if the upstream "
2832+ "tarball can not be found."),
2833+ ]
2834+
2835+ takes_args = ["location", "working_basedir?"]
2836+
2837+ def run(self, location, working_basedir=None, manifest=None,
2838+ if_changed_from=None, package=None, distribution=None,
2839+ dput=None, key_id=None, no_build=None, watch_ppa=False,
2840+ append_version=None, safe=False, allow_fallback_to_native=False):
2841+
2842+ if dput is not None and key_id is None:
2843+ raise errors.BzrCommandError("You must specify --key-id if you "
2844+ "specify --dput.")
2845+ if watch_ppa:
2846+ if not dput:
2847+ raise errors.BzrCommandError(
2848+ "cannot watch a ppa without doing dput.")
2849+ else:
2850+ # Check we can calculate a PPA url.
2851+ target_from_dput(dput)
2852+
2853+ possible_transports = []
2854+ result, base_branch = self._get_prepared_branch_from_location(location,
2855+ if_changed_from=if_changed_from, safe=safe,
2856+ possible_transports=possible_transports)
2857+ if result is not None:
2858+ return result
2859+ if working_basedir is None:
2860+ temp_dir = tempfile.mkdtemp(prefix="bzr-builder-")
2861+ working_basedir = temp_dir
2862+ else:
2863+ temp_dir = None
2864+ if not os.path.exists(working_basedir):
2865+ os.makedirs(working_basedir)
2866+ package_name = self._calculate_package_name(location, package)
2867+ if self._template_version is None:
2868+ working_directory = os.path.join(working_basedir,
2869+ "%s-direct" % (package_name,))
2870+ else:
2871+ working_directory = os.path.join(working_basedir,
2872+ "%s-%s" % (package_name, self._template_version))
2873+ try:
2874+ # we want to use a consistent package_dir always to support
2875+ # updates in place, but debuild etc want PACKAGE-UPSTREAMVERSION
2876+ # on disk, so we build_tree with the unsubstituted version number
2877+ # and do a final rename-to step before calling into debian build
2878+ # tools. We then rename the working dir back.
2879+ manifest_path = os.path.join(working_directory, "debian",
2880+ "bzr-builder.manifest")
2881+ build_tree(base_branch, working_directory)
2882+ control_path = os.path.join(working_directory, "debian", "control")
2883+ if not os.path.exists(control_path):
2884+ if package is None:
2885+ raise errors.BzrCommandError("No control file to "
2886+ "take the package name from, and --package not "
2887+ "specified.")
2888+ else:
2889+ package = debian_source_package_name(control_path)
2890+ write_manifest_to_transport(manifest_path, base_branch,
2891+ possible_transports)
2892+ autobuild = (base_branch.deb_version is not None)
2893+ if autobuild:
2894+ # Add changelog also substitutes {debupstream}.
2895+ add_autobuild_changelog_entry(base_branch, working_directory,
2896+ package, distribution=distribution,
2897+ append_version=append_version)
2898+ else:
2899+ if append_version:
2900+ raise errors.BzrCommandError("--append-version only "
2901+ "supported for autobuild recipes (with a 'deb-version' "
2902+ "header)")
2903+ with open(os.path.join(working_directory, "debian", "changelog")) as cl_f:
2904+ contents = cl_f.read()
2905+ cl = changelog.Changelog(file=contents)
2906+ package_name = cl.package
2907+ package_version = cl.version
2908+ package_dir = calculate_package_dir(package_name, package_version,
2909+ working_basedir)
2910+ # working_directory -> package_dir: after this debian stuff works.
2911+ os.rename(working_directory, package_dir)
2912+ if no_build:
2913+ if manifest is not None:
2914+ write_manifest_to_transport(manifest, base_branch,
2915+ possible_transports)
2916+ return 0
2917+ if package_version.debian_revision is not None:
2918+ # Non-native package
2919+ try:
2920+ extract_upstream_tarball(base_branch.branch, package_name,
2921+ package_version.upstream_version, working_basedir)
2922+ except errors.NoSuchTag:
2923+ if not allow_fallback_to_native:
2924+ raise
2925+ if allow_fallback_to_native:
2926+ force_native_format(package_dir)
2927+ try:
2928+ build_source_package(package_dir,
2929+ tgz_check=not allow_fallback_to_native)
2930+ if key_id is not None:
2931+ sign_source_package(package_dir, key_id)
2932+ if dput is not None:
2933+ dput_source_package(package_dir, dput)
2934+ finally:
2935+ # package_dir -> working_directory
2936+ # FIXME: may fail in error unwind, masking the original exception.
2937+ os.rename(package_dir, working_directory)
2938+ # Note that this may write a second manifest.
2939+ if manifest is not None:
2940+ write_manifest_to_transport(manifest, base_branch,
2941+ possible_transports)
2942+ finally:
2943+ if temp_dir is not None:
2944+ shutil.rmtree(temp_dir)
2945+ if watch_ppa:
2946+ from bzrlib.plugins.builder.ppa import watch
2947+ (owner, archive) = target_from_dput(dput)
2948+ if not watch(owner, archive, package_name, base_branch.deb_version):
2949+ return 2
2950+
2951+ def _calculate_package_name(self, recipe_location, package):
2952+ """Calculate the directory name that should be used while debuilding."""
2953+ recipe_name = urlutils.basename(recipe_location)
2954+ if recipe_name.endswith(".recipe"):
2955+ recipe_name = recipe_name[:-len(".recipe")]
2956+ return package or recipe_name
2957+
2958+
2959+def target_from_dput(dput):
2960+ """Convert a dput specification to a LP API specification.
2961+
2962+ :param dput: A dput command spec like ppa:team-name.
2963+ :return: A LP API target like team-name/ppa.
2964+ """
2965+ ppa_prefix = 'ppa:'
2966+ if not dput.startswith(ppa_prefix):
2967+ raise errors.BzrCommandError('%r does not appear to be a PPA. '
2968+ 'A dput target like \'%suser[/name]\' must be used.'
2969+ % (dput, ppa_prefix))
2970+ base, _, suffix = dput[len(ppa_prefix):].partition('/')
2971+ if not suffix:
2972+ suffix = 'ppa'
2973+ return base, suffix
2974+
2975
2976=== removed file 'cmds.py'
2977--- cmds.py 2010-10-21 21:17:28 +0000
2978+++ cmds.py 1970-01-01 00:00:00 +0000
2979@@ -1,507 +0,0 @@
2980-# bzr-builder: a bzr plugin to constuct trees based on recipes
2981-# Copyright 2009 Canonical Ltd.
2982-
2983-# This program is free software: you can redistribute it and/or modify it
2984-# under the terms of the GNU General Public License version 3, as published
2985-# by the Free Software Foundation.
2986-
2987-# This program is distributed in the hope that it will be useful, but
2988-# WITHOUT ANY WARRANTY; without even the implied warranties of
2989-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2990-# PURPOSE. See the GNU General Public License for more details.
2991-
2992-# You should have received a copy of the GNU General Public License along
2993-# with this program. If not, see <http://www.gnu.org/licenses/>.
2994-
2995-"""Subcommands provided by bzr-builder."""
2996-
2997-import datetime
2998-from email import utils
2999-import errno
3000-import os
3001-import pwd
3002-import re
3003-import socket
3004-import shutil
3005-import subprocess
3006-import tempfile
3007-
3008-try:
3009- from debian import changelog
3010-except ImportError:
3011- # In older versions of python-debian the main package was named
3012- # debian_bundle
3013- from debian_bundle import changelog
3014-
3015-from bzrlib import (
3016- errors,
3017- trace,
3018- transport,
3019- )
3020-from bzrlib.commands import Command
3021-from bzrlib.option import Option
3022-
3023-from bzrlib.plugins.builder.recipe import (
3024- build_tree,
3025- DEBUPSTREAM_VAR,
3026- RecipeParser,
3027- resolve_revisions,
3028- SAFE_INSTRUCTIONS,
3029- )
3030-
3031-
3032-# The default distribution used by add_changelog_entry()
3033-DEFAULT_UBUNTU_DISTRIBUTION = "lucid"
3034-
3035-
3036-class MissingDependency(errors.BzrError):
3037- pass
3038-
3039-
3040-def write_manifest_to_path(path, base_branch):
3041- parent_dir = os.path.dirname(path)
3042- if parent_dir != '' and not os.path.exists(parent_dir):
3043- os.makedirs(parent_dir)
3044- manifest_f = open(path, 'wb')
3045- try:
3046- manifest_f.write(str(base_branch))
3047- finally:
3048- manifest_f.close()
3049-
3050-
3051-def get_branch_from_recipe_file(recipe_file, safe=False):
3052- """Return the base branch for the specified recipe.
3053-
3054- :param recipe_file: The URL of the recipe file to retrieve.
3055- :param safe: if True, reject recipes that would cause arbitrary code
3056- execution.
3057- """
3058- recipe_transport = transport.get_transport(os.path.dirname(recipe_file))
3059- try:
3060- recipe_contents = recipe_transport.get_bytes(
3061- os.path.basename(recipe_file))
3062- except errors.NoSuchFile:
3063- raise errors.BzrCommandError("Specified recipe does not exist: "
3064- "%s" % recipe_file)
3065- if safe:
3066- permitted_instructions = SAFE_INSTRUCTIONS
3067- else:
3068- permitted_instructions = None
3069- parser = RecipeParser(recipe_contents, filename=recipe_file)
3070- return parser.parse(permitted_instructions=permitted_instructions)
3071-
3072-
3073-def get_old_recipe(if_changed_from):
3074- old_manifest_transport = transport.get_transport(os.path.dirname(
3075- if_changed_from))
3076- try:
3077- old_manifest_contents = old_manifest_transport.get_bytes(
3078- os.path.basename(if_changed_from))
3079- except errors.NoSuchFile:
3080- return None
3081- old_recipe = RecipeParser(old_manifest_contents,
3082- filename=if_changed_from).parse()
3083- return old_recipe
3084-
3085-
3086-def get_maintainer():
3087- """Create maintainer string using the same algorithm as in dch.
3088- """
3089- env = os.environ
3090- regex = re.compile(r"^(.*)\s+<(.*)>$")
3091-
3092- # Split email and name
3093- if 'DEBEMAIL' in env:
3094- match_obj = regex.match(env['DEBEMAIL'])
3095- if match_obj:
3096- if not 'DEBFULLNAME' in env:
3097- env['DEBFULLNAME'] = match_obj.group(1)
3098- env['DEBEMAIL'] = match_obj.group(2)
3099- if 'DEBEMAIL' not in env or 'DEBFULLNAME' not in env:
3100- if 'EMAIL' in env:
3101- match_obj = regex.match(env['EMAIL'])
3102- if match_obj:
3103- if not 'DEBFULLNAME' in env:
3104- env['DEBFULLNAME'] = match_obj.group(1)
3105- env['EMAIL'] = match_obj.group(2)
3106-
3107- # Get maintainer's name
3108- if 'DEBFULLNAME' in env:
3109- maintainer = env['DEBFULLNAME']
3110- elif 'NAME' in env:
3111- maintainer = env['NAME']
3112- else:
3113- # Use password database if no data in environment variables
3114- try:
3115- maintainer = re.sub(r',.*', '', pwd.getpwuid(os.getuid()).pw_gecos)
3116- except (KeyError, AttributeError):
3117- # TBD: Use last changelog entry value
3118- maintainer = "bzr-builder"
3119-
3120- # Get maintainer's mail address
3121- if 'DEBEMAIL' in env:
3122- email = env['DEBEMAIL']
3123- elif 'EMAIL' in env:
3124- email = env['EMAIL']
3125- else:
3126- addr = None
3127- if os.path.exists('/etc/mailname'):
3128- f = open('/etc/mailname')
3129- try:
3130- addr = f.readline().strip()
3131- finally:
3132- f.close()
3133- if not addr:
3134- addr = socket.getfqdn()
3135- if addr:
3136- user = pwd.getpwuid(os.getuid()).pw_name
3137- if not user:
3138- addr = None
3139- else:
3140- addr = "%s@%s" % (user, addr)
3141-
3142- if addr:
3143- email = addr
3144- else:
3145- # TBD: Use last changelog entry value
3146- email = "none@example.org"
3147-
3148- return (maintainer, email)
3149-
3150-
3151-def add_changelog_entry(base_branch, basedir, distribution=None,
3152- package=None, author_name=None, author_email=None,
3153- append_version=None):
3154- debian_dir = os.path.join(basedir, "debian")
3155- if not os.path.exists(debian_dir):
3156- os.makedirs(debian_dir)
3157- cl_path = os.path.join(debian_dir, "changelog")
3158- file_found = False
3159- if os.path.exists(cl_path):
3160- file_found = True
3161- cl_f = open(cl_path)
3162- try:
3163- contents = cl_f.read()
3164- finally:
3165- cl_f.close()
3166- cl = changelog.Changelog(file=contents)
3167- else:
3168- cl = changelog.Changelog()
3169- if len(cl._blocks) > 0:
3170- if distribution is None:
3171- distribution = cl._blocks[0].distributions.split()[0]
3172- if package is None:
3173- package = cl._blocks[0].package
3174- if DEBUPSTREAM_VAR in base_branch.deb_version:
3175- cl_version = cl._blocks[0].version
3176- base_branch.substitute_debupstream(cl_version)
3177- else:
3178- if file_found:
3179- if len(contents.strip()) > 0:
3180- reason = ("debian/changelog didn't contain any "
3181- "parseable stanzas")
3182- else:
3183- reason = "debian/changelog was empty"
3184- else:
3185- reason = "debian/changelog was not present"
3186- if package is None:
3187- raise errors.BzrCommandError("No previous changelog to "
3188- "take the package name from, and --package not "
3189- "specified: %s." % reason)
3190- if DEBUPSTREAM_VAR in base_branch.deb_version:
3191- raise errors.BzrCommandError("No previous changelog to "
3192- "take the upstream version from as %s was "
3193- "used: %s." % (DEBUPSTREAM_VAR, reason))
3194- if distribution is None:
3195- distribution = DEFAULT_UBUNTU_DISTRIBUTION
3196- # Use debian packaging environment variables
3197- # or default values if they don't exist
3198- if author_name is None or author_email is None:
3199- author_name, author_email = get_maintainer()
3200- author = "%s <%s>" % (author_name, author_email)
3201-
3202- date = utils.formatdate(localtime=True)
3203- version = base_branch.deb_version
3204- if append_version is not None:
3205- version += append_version
3206- try:
3207- changelog.Version(version)
3208- except (changelog.VersionError, ValueError), e:
3209- raise errors.BzrCommandError("Invalid deb-version: %s: %s"
3210- % (version, e))
3211- cl.new_block(package=package, version=version,
3212- distributions=distribution, urgency="low",
3213- changes=['', ' * Auto build.', ''],
3214- author=author, date=date)
3215- cl_f = open(cl_path, 'wb')
3216- try:
3217- cl.write_to_open_file(cl_f)
3218- finally:
3219- cl_f.close()
3220-
3221-
3222-def calculate_package_dir(base_branch, package_name, working_basedir):
3223- """Calculate the directory name that should be used while debuilding."""
3224- version = base_branch.deb_version
3225- if "-" in version:
3226- version = version[:version.rindex("-")]
3227- package_basedir = "%s-%s" % (package_name, version)
3228- package_dir = os.path.join(working_basedir, package_basedir)
3229- return package_dir
3230-
3231-
3232-def _run_command(command, basedir, msg, error_msg,
3233- not_installed_msg=None):
3234- """ Run a command in a subprocess.
3235-
3236- :param command: list with command and parameters
3237- :param msg: message to display to the user
3238- :param error_msg: message to display if something fails.
3239- :param not_installed_msg: the message to display if the command
3240- isn't available.
3241- """
3242- trace.note(msg)
3243- # Hide output if -q is in use.
3244- quiet = trace.is_quiet()
3245- if quiet:
3246- kwargs = {"stderr": subprocess.STDOUT, "stdout": subprocess.PIPE}
3247- else:
3248- kwargs = {}
3249- try:
3250- proc = subprocess.Popen(command, cwd=basedir,
3251- stdin=subprocess.PIPE, **kwargs)
3252- except OSError, e:
3253- if e.errno != errno.ENOENT:
3254- raise
3255- if not_installed_msg is None:
3256- raise
3257- raise MissingDependency(msg=not_installed_msg)
3258- output = proc.communicate()
3259- if proc.returncode != 0:
3260- if quiet:
3261- raise errors.BzrCommandError("%s: %s" % (error_msg, output))
3262- else:
3263- raise errors.BzrCommandError(error_msg)
3264-
3265-
3266-def build_source_package(basedir):
3267- command = ["/usr/bin/debuild", "--no-tgz-check", "-i", "-I", "-S",
3268- "-uc", "-us"]
3269- _run_command(command, basedir,
3270- "Building the source package",
3271- "Failed to build the source package",
3272- not_installed_msg="debuild is not installed, please install "
3273- "the devscripts package.")
3274-
3275-
3276-def sign_source_package(basedir, key_id):
3277- command = ["/usr/bin/debsign", "-S", "-k%s" % key_id]
3278- _run_command(command, basedir,
3279- "Signing the source package",
3280- "Signing the package failed",
3281- not_installed_msg="debsign is not installed, please install "
3282- "the devscripts package.")
3283-
3284-
3285-def dput_source_package(basedir, target):
3286- command = ["/usr/bin/debrelease", "-S", "--dput", target]
3287- _run_command(command, basedir,
3288- "Uploading the source package",
3289- "Uploading the package failed",
3290- not_installed_msg="debrelease is not installed, please "
3291- "install the devscripts package.")
3292-
3293-
3294-class cmd_build(Command):
3295- """Build a tree based on a 'recipe'.
3296-
3297- Pass the name of the recipe file and the directory to work in.
3298-
3299- See "bzr help builder" for more information on what a recipe is.
3300- """
3301- takes_args = ["recipe_file", "working_directory"]
3302- takes_options = [
3303- Option('manifest', type=str, argname="path",
3304- help="Path to write the manifest to."),
3305- Option('if-changed-from', type=str, argname="path",
3306- help="Only build if the outcome would be different "
3307- "to that specified in the specified manifest."),
3308- ]
3309-
3310- def _get_prepared_branch_from_recipe(self, recipe_file,
3311- if_changed_from=None, safe=False):
3312- """Common code to prepare a branch and do substitutions.
3313-
3314- :param recipe_file: a path to a recipe file to work from.
3315- :param if_changed_from: an optional path to a manifest to
3316- compare the recipe against.
3317- :param safe: if True, reject recipes that would cause arbitrary code
3318- execution.
3319- :return: A tuple with (retcode, base_branch). If retcode is None
3320- then the command execution should continue.
3321- """
3322- base_branch = get_branch_from_recipe_file(recipe_file, safe=safe)
3323- time = datetime.datetime.utcnow()
3324- base_branch.substitute_time(time)
3325- old_recipe = None
3326- if if_changed_from is not None:
3327- old_recipe = get_old_recipe(if_changed_from)
3328- # Save the unsubstituted version for dailydeb.
3329- self._template_version = base_branch.deb_version
3330- changed = resolve_revisions(base_branch, if_changed_from=old_recipe)
3331- if not changed:
3332- trace.note("Unchanged")
3333- return 0, base_branch
3334- return None, base_branch
3335-
3336- def run(self, recipe_file, working_directory, manifest=None,
3337- if_changed_from=None):
3338- result, base_branch = self._get_prepared_branch_from_recipe(recipe_file,
3339- if_changed_from=if_changed_from)
3340- if result is not None:
3341- return result
3342- manifest_path = manifest or os.path.join(working_directory,
3343- "bzr-builder.manifest")
3344- build_tree(base_branch, working_directory)
3345- write_manifest_to_path(manifest_path, base_branch)
3346-
3347-
3348-class cmd_dailydeb(cmd_build):
3349- """Build a deb based on a 'recipe'.
3350-
3351- See "bzr help builder" for more information on what a recipe is.
3352-
3353- If you do not specify a working directory then a temporary
3354- directory will be used and it will be removed when the command
3355- finishes.
3356- """
3357-
3358- takes_options = cmd_build.takes_options + [
3359- Option("package", type=str,
3360- help="The package name to use in the changelog entry. "
3361- "If not specified then the package from the "
3362- "previous changelog entry will be used, so it "
3363- "must be specified if there is no changelog."),
3364- Option("distribution", type=str,
3365- help="The distribution to target. If not specified "
3366- "then the same distribution as the last entry "
3367- "in debian/changelog will be used."),
3368- Option("dput", type=str, argname="target",
3369- help="dput the built package to the specified "
3370- "dput target."),
3371- Option("key-id", type=str, short_name="k",
3372- help="Sign the packages with the specified GnuPG key. "
3373- "Must be specified if you use --dput."),
3374- Option("no-build",
3375- help="Just ready the source package and don't "
3376- "actually build it."),
3377- Option("watch-ppa", help="Watch the PPA the package was "
3378- "dput to and exit with 0 only if it builds and "
3379- "publishes successfully."),
3380- Option("append-version", type=str, help="Append the "
3381- "specified string to the end of the version used "
3382- "in debian/changelog."),
3383- Option("safe", help="Error if the recipe would cause"
3384- " arbitrary code execution.")
3385- ]
3386-
3387- takes_args = ["recipe_file", "working_basedir?"]
3388-
3389- def run(self, recipe_file, working_basedir=None, manifest=None,
3390- if_changed_from=None, package=None, distribution=None,
3391- dput=None, key_id=None, no_build=None, watch_ppa=False,
3392- append_version=None, safe=False):
3393-
3394- if dput is not None and key_id is None:
3395- raise errors.BzrCommandError("You must specify --key-id if you "
3396- "specify --dput.")
3397- if watch_ppa:
3398- if not dput:
3399- raise errors.BzrCommandError(
3400- "cannot watch a ppa without doing dput.")
3401- else:
3402- # Check we can calculate a PPA url.
3403- target_from_dput(dput)
3404-
3405- result, base_branch = self._get_prepared_branch_from_recipe(recipe_file,
3406- if_changed_from=if_changed_from, safe=safe)
3407- if result is not None:
3408- return result
3409- if working_basedir is None:
3410- temp_dir = tempfile.mkdtemp(prefix="bzr-builder-")
3411- working_basedir = temp_dir
3412- else:
3413- temp_dir = None
3414- if not os.path.exists(working_basedir):
3415- os.makedirs(working_basedir)
3416- package_name = self._calculate_package_name(recipe_file, package)
3417- working_directory = os.path.join(working_basedir,
3418- "%s-%s" % (package_name, self._template_version))
3419- try:
3420- # we want to use a consistent package_dir always to support
3421- # updates in place, but debuild etc want PACKAGE-UPSTREAMVERSION
3422- # on disk, so we build_tree with the unsubstituted version number
3423- # and do a final rename-to step before calling into debian build
3424- # tools. We then rename the working dir back.
3425- manifest_path = os.path.join(working_directory, "debian",
3426- "bzr-builder.manifest")
3427- build_tree(base_branch, working_directory)
3428- write_manifest_to_path(manifest_path, base_branch)
3429- # Add changelog also substitutes {debupstream}.
3430- add_changelog_entry(base_branch, working_directory,
3431- distribution=distribution, package=package,
3432- append_version=append_version)
3433- package_dir = calculate_package_dir(base_branch,
3434- package_name, working_basedir)
3435- # working_directory -> package_dir: after this debian stuff works.
3436- os.rename(working_directory, package_dir)
3437- if no_build:
3438- if manifest is not None:
3439- write_manifest_to_path(manifest, base_branch)
3440- return 0
3441- try:
3442- build_source_package(package_dir)
3443- if key_id is not None:
3444- sign_source_package(package_dir, key_id)
3445- if dput is not None:
3446- dput_source_package(package_dir, dput)
3447- finally:
3448- # package_dir -> working_directory
3449- # FIXME: may fail in error unwind, masking the original exception.
3450- os.rename(package_dir, working_directory)
3451- # Note that this may write a second manifest.
3452- if manifest is not None:
3453- write_manifest_to_path(manifest, base_branch)
3454- finally:
3455- if temp_dir is not None:
3456- shutil.rmtree(temp_dir)
3457- if watch_ppa:
3458- from bzrlib.plugins.builder.ppa import watch
3459- target = target_from_dput(dput)
3460- if not watch(target, self.package, base_branch.deb_version):
3461- return 2
3462-
3463- def _calculate_package_name(self, recipe_file, package):
3464- """Calculate the directory name that should be used while debuilding."""
3465- recipe_name = os.path.basename(recipe_file)
3466- if recipe_name.endswith(".recipe"):
3467- recipe_name = recipe_name[:-len(".recipe")]
3468- return package or recipe_name
3469-
3470-
3471-def target_from_dput(dput):
3472- """Convert a dput specification to a LP API specification.
3473-
3474- :param dput: A dput command spec like ppa:team-name.
3475- :return: A LP API target like team-name/ppa.
3476- """
3477- ppa_prefix = 'ppa:'
3478- if not dput.startswith(ppa_prefix):
3479- raise errors.BzrCommandError('%r does not appear to be a PPA. '
3480- 'A dput target like \'%suser[/name]\' must be used.'
3481- % (dput, ppa_prefix))
3482- base, _, suffix = dput[len(ppa_prefix):].partition('/')
3483- if not suffix:
3484- suffix = 'ppa'
3485- return base + '/' + suffix
3486-
3487
3488=== modified file 'debian/changelog'
3489--- debian/changelog 2011-06-10 17:46:25 +0000
3490+++ debian/changelog 2011-06-14 17:23:32 +0000
3491@@ -1,3 +1,13 @@
3492+bzr-builder (0.7-0ubuntu1) oneiric; urgency=low
3493+
3494+ * New upstream release.
3495+ + Fixes attribute error in "bzr dailydeb". LP: #744087
3496+ * Bump standards version to 3.9.2 (no changes).
3497+ * Run test suite during build.
3498+ * Switch to source format 3.
3499+
3500+ -- Jelmer Vernooij <jelmer@ubuntu.com> Tue, 14 Jun 2011 15:29:07 +0200
3501+
3502 bzr-builder (0.6-0ubuntu2) oneiric; urgency=low
3503
3504 * Convert to dh_python2 from deprecated py-central.
3505
3506=== modified file 'debian/control'
3507--- debian/control 2011-06-10 17:46:25 +0000
3508+++ debian/control 2011-06-14 17:23:32 +0000
3509@@ -3,18 +3,20 @@
3510 Priority: optional
3511 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
3512 XSBC-Original-Maintainer: James Westby <james.westby@ubuntu.com>
3513-Build-Depends: debhelper (>= 7), python (>= 2.6.6-3~)
3514-Build-Depends-Indep: bzr, python-debian
3515+Build-Depends: debhelper (>= 7.0.50~), python (>= 2.6.6-3~)
3516+Build-Depends-Indep: bzr, python-debian, python-subunit, python-testtools, python-bzrlib.tests | bzr (<< 2.4.0~beta1-2), devscripts, quilt
3517 X-Python-Version: >= 2.4
3518-Standards-Version: 3.9.1
3519+Standards-Version: 3.9.2
3520 Homepage: http://launchpad.net/bzr-builder
3521
3522 Package: bzr-builder
3523 Architecture: all
3524+Recommends: pristine-tar
3525 Depends: bzr,
3526 devscripts,
3527 dput,
3528 python-debian,
3529+ quilt,
3530 ${misc:Depends},
3531 ${python:Depends}
3532 Description: construct a bzr branch from a recipe
3533
3534=== added directory 'debian/patches'
3535=== added file 'debian/patches/01_broken_test'
3536--- debian/patches/01_broken_test 1970-01-01 00:00:00 +0000
3537+++ debian/patches/01_broken_test 2011-06-14 17:23:32 +0000
3538@@ -0,0 +1,24 @@
3539+Author: Jelmer Vernooij <jelmer@ubuntu.com>
3540+Description: Disable known broken test
3541+Status: Not applicable for upstream (test will be fixed instead)
3542+
3543+=== modified file 'tests/test_recipe.py'
3544+--- old/tests/test_recipe.py 2011-06-14 12:58:17 +0000
3545++++ new/tests/test_recipe.py 2011-06-14 13:26:29 +0000
3546+@@ -23,6 +23,7 @@
3547+ workingtree,
3548+ )
3549+ from bzrlib.tests import (
3550++ KnownFailure,
3551+ TestCase,
3552+ TestCaseInTempDir,
3553+ TestCaseWithTransport,
3554+@@ -1334,6 +1335,7 @@
3555+ self.assertEqual("1-19700101", base_branch.deb_version)
3556+
3557+ def test_substitute_branch_vars(self):
3558++ raise KnownFailure("Known broken test")
3559+ base_branch = BaseRecipeBranch("base_url", "1", 0.2)
3560+ base_branch.substitute_branch_vars(None, None, None)
3561+ self.assertEqual("1", base_branch.deb_version)
3562+
3563
3564=== added file 'debian/patches/series'
3565--- debian/patches/series 1970-01-01 00:00:00 +0000
3566+++ debian/patches/series 2011-06-14 17:23:32 +0000
3567@@ -0,0 +1,1 @@
3568+01_broken_test
3569
3570=== modified file 'debian/rules'
3571--- debian/rules 2011-06-10 17:46:25 +0000
3572+++ debian/rules 2011-06-14 17:23:32 +0000
3573@@ -2,3 +2,13 @@
3574
3575 %:
3576 dh $@ --with python2
3577+
3578+ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
3579+CONCURRENCY = BZR_CONCURRENCY=$(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
3580+endif
3581+
3582+ifeq (,$(findstring nocheck,$(DEB_BUILD_OPTIONS)))
3583+override_dh_auto_test:
3584+ $(CONCURRENCY) BZR_PLUGINS_AT=builder@$(CURDIR) /usr/bin/bzr selftest \
3585+ --parallel=fork -v -s bp.builder
3586+endif
3587
3588=== added directory 'debian/source'
3589=== added file 'debian/source/format'
3590--- debian/source/format 1970-01-01 00:00:00 +0000
3591+++ debian/source/format 2011-06-14 17:23:32 +0000
3592@@ -0,0 +1,1 @@
3593+3.0 (quilt)
3594
3595=== removed directory 'plugins'
3596=== removed symlink 'plugins/builder'
3597=== target was u'..'
3598=== added file 'ppa.py'
3599--- ppa.py 1970-01-01 00:00:00 +0000
3600+++ ppa.py 2011-06-14 17:23:32 +0000
3601@@ -0,0 +1,100 @@
3602+# ppa support for bzr builder.
3603+#
3604+# Copyright: Canonical Ltd. (C) 2009
3605+#
3606+# This program is free software: you can redistribute it and/or modify it
3607+# under the terms of the GNU General Public License version 3, as published
3608+# by the Free Software Foundation.
3609+
3610+# This program is distributed in the hope that it will be useful, but
3611+# WITHOUT ANY WARRANTY; without even the implied warranties of
3612+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3613+# PURPOSE. See the GNU General Public License for more details.
3614+
3615+# You should have received a copy of the GNU General Public License along
3616+# with this program. If not, see <http://www.gnu.org/licenses/>.
3617+
3618+import time
3619+
3620+from bzrlib import (
3621+ errors,
3622+ trace,
3623+ )
3624+from launchpadlib.launchpad import Launchpad
3625+
3626+
3627+def get_lp():
3628+ return Launchpad.login_with('bzr-builder', 'production')
3629+
3630+
3631+def watch(owner_name, archive_name, package_name, version):
3632+ """Watch a package build.
3633+
3634+ :return: True once the package built and published, or False if it fails
3635+ or there is a timeout waiting.
3636+ """
3637+ version = str(version)
3638+ trace.note("Logging into Launchpad")
3639+
3640+ launchpad = get_lp()
3641+ owner = launchpad.people[owner_name]
3642+ archive = owner.getPPAByName(name=archive_name)
3643+ end_states = ['FAILEDTOBUILD', 'FULLYBUILT']
3644+ important_arches = ['amd64', 'i386', 'armel']
3645+ trace.note("Waiting for version %s of %s to build." % (version, package_name))
3646+ start = time.time()
3647+ while True:
3648+ sourceRecords = list(archive.getPublishedSources(
3649+ source_name=package_name, version=version))
3650+ if not sourceRecords:
3651+ if time.time() - 900 > start:
3652+ # Over 15 minutes and no source yet, upload FAIL.
3653+ raise errors.BzrCommandError("No source record in %s/%s for "
3654+ "package %s=%s after 15 minutes." % (owner_name,
3655+ archive_name, package_name, version))
3656+ return False
3657+ trace.note("Source not available yet - waiting.")
3658+ time.sleep(60)
3659+ continue
3660+ pkg = sourceRecords[0]
3661+ if pkg.status.lower() not in ('published', 'pending'):
3662+ trace.note("Package status: %s" % (pkg.status,))
3663+ time.sleep(60)
3664+ continue
3665+ # FIXME: LP should export this as an attribute.
3666+ source_id = pkg.self_link.rsplit('/', 1)[1]
3667+ buildSummaries = archive.getBuildSummariesForSourceIds(
3668+ source_ids=[source_id])[source_id]
3669+ if buildSummaries['status'] in end_states:
3670+ break
3671+ if buildSummaries['status'] == 'NEEDSBUILD':
3672+ # We ignore non-virtual PPA architectures that are sparsely
3673+ # supplied with buildds.
3674+ missing = []
3675+ for build in buildSummaries['builds']:
3676+ arch = build['arch_tag']
3677+ if arch in important_arches:
3678+ missing.append(arch)
3679+ if not missing:
3680+ break
3681+ extra = ' on ' + ', '.join(missing)
3682+ else:
3683+ extra = ''
3684+ trace.note("%s is still in %s%s" % (pkg.display_name,
3685+ buildSummaries['status'], extra))
3686+ time.sleep(60)
3687+ trace.note("%s is now %s" % (pkg.display_name, buildSummaries['status']))
3688+ result = True
3689+ if pkg.status.lower() != 'published':
3690+ result = False # should this perhaps keep waiting?
3691+ if buildSummaries['status'] != 'FULLYBUILT':
3692+ if buildSummaries['status'] == 'NEEDSBUILD':
3693+ # We're stopping early cause the important_arches are built.
3694+ builds = pkg.getBuilds()
3695+ for build in builds:
3696+ if build.arch_tag in important_arches:
3697+ if build.buildstate != 'Successfully built':
3698+ result = False
3699+ else:
3700+ result = False
3701+ return result
3702
3703=== removed file 'ppa.py'
3704--- ppa.py 2010-10-21 21:17:28 +0000
3705+++ ppa.py 1970-01-01 00:00:00 +0000
3706@@ -1,124 +0,0 @@
3707-# ppa support for bzr builder.
3708-#
3709-# Copyright: Canonical Ltd. (C) 2009
3710-#
3711-# This program is free software: you can redistribute it and/or modify it
3712-# under the terms of the GNU General Public License version 3, as published
3713-# by the Free Software Foundation.
3714-
3715-# This program is distributed in the hope that it will be useful, but
3716-# WITHOUT ANY WARRANTY; without even the implied warranties of
3717-# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3718-# PURPOSE. See the GNU General Public License for more details.
3719-
3720-# You should have received a copy of the GNU General Public License along
3721-# with this program. If not, see <http://www.gnu.org/licenses/>.
3722-
3723-import os
3724-import time
3725-
3726-
3727-from launchpadlib.launchpad import (
3728- Launchpad,
3729- EDGE_SERVICE_ROOT,
3730- )
3731-from launchpadlib.credentials import Credentials
3732-
3733-from bzrlib import (
3734- errors,
3735- trace,
3736- )
3737-
3738-
3739-def get_lp():
3740- credentials = Credentials()
3741- oauth_file = os.path.expanduser('~/.cache/launchpadlib/bzr-builder')
3742- if os.path.exists(oauth_file):
3743- f = open(oauth_file)
3744- try:
3745- credentials.load(f)
3746- finally:
3747- f.close()
3748- launchpad = Launchpad(credentials, EDGE_SERVICE_ROOT)
3749- else:
3750- launchpad = Launchpad.get_token_and_login('bzr-builder',
3751- EDGE_SERVICE_ROOT)
3752- f = open(oauth_file, 'wb')
3753- try:
3754- launchpad.credentials.save(f)
3755- finally:
3756- f.close()
3757- return launchpad
3758-
3759-
3760-def watch(owner_name, archive_name, package_name, version):
3761- """Watch a package build.
3762-
3763- :return: True once the package built and published, or False if it fails
3764- or there is a timeout waiting.
3765- """
3766- version = str(version)
3767- trace.note("Logging into Launchpad")
3768-
3769- launchpad = get_lp()
3770- owner = launchpad.people[owner_name]
3771- archive = owner.getPPAByName(name=archive_name)
3772- end_states = ['FAILEDTOBUILD', 'FULLYBUILT']
3773- important_arches = ['amd64', 'i386', 'armel']
3774- trace.note("Waiting for version %s of %s to build." % (version, package_name))
3775- start = time.time()
3776- while True:
3777- sourceRecords = list(archive.getPublishedSources(
3778- source_name=package_name, version=version))
3779- if not sourceRecords:
3780- if time.time() - 900 > start:
3781- # Over 15 minutes and no source yet, upload FAIL.
3782- raise errors.BzrCommandError("No source record in %s/%s for "
3783- "package %s=%s after 15 minutes." % (owner_name,
3784- archive_name, package_name, version))
3785- return False
3786- trace.note("Source not available yet - waiting.")
3787- time.sleep(60)
3788- continue
3789- pkg = sourceRecords[0]
3790- if pkg.status.lower() not in ('published', 'pending'):
3791- trace.note("Package status: %s" % (pkg.status,))
3792- time.sleep(60)
3793- continue
3794- # FIXME: LP should export this as an attribute.
3795- source_id = pkg.self_link.rsplit('/', 1)[1]
3796- buildSummaries = archive.getBuildSummariesForSourceIds(
3797- source_ids=[source_id])[source_id]
3798- if buildSummaries['status'] in end_states:
3799- break
3800- if buildSummaries['status'] == 'NEEDSBUILD':
3801- # We ignore non-virtual PPA architectures that are sparsely
3802- # supplied with buildds.
3803- missing = []
3804- for build in buildSummaries['builds']:
3805- arch = build['arch_tag']
3806- if arch in important_arches:
3807- missing.append(arch)
3808- if not missing:
3809- break
3810- extra = ' on ' + ', '.join(missing)
3811- else:
3812- extra = ''
3813- trace.note("%s is still in %s%s" % (pkg.display_name,
3814- buildSummaries['status'], extra))
3815- time.sleep(60)
3816- trace.note("%s is now %s" % (pkg.display_name, buildSummaries['status']))
3817- result = True
3818- if pkg.status.lower() != 'published':
3819- result = False # should this perhaps keep waiting?
3820- if buildSummaries['status'] != 'FULLYBUILT':
3821- if buildSummaries['status'] == 'NEEDSBUILD':
3822- # We're stopping early cause the important_arches are built.
3823- builds = pkg.getBuilds()
3824- for build in builds:
3825- if build.arch_tag in important_arches:
3826- if build.buildstate != 'Successfully built':
3827- result = False
3828- else:
3829- result = False
3830- return result
3831
3832=== added file 'recipe.py'
3833--- recipe.py 1970-01-01 00:00:00 +0000
3834+++ recipe.py 2011-06-14 17:23:32 +0000
3835@@ -0,0 +1,1535 @@
3836+# bzr-builder: a bzr plugin to constuct trees based on recipes
3837+# Copyright 2009 Canonical Ltd.
3838+
3839+# This program is free software: you can redistribute it and/or modify it
3840+# under the terms of the GNU General Public License version 3, as published
3841+# by the Free Software Foundation.
3842+
3843+# This program is distributed in the hope that it will be useful, but
3844+# WITHOUT ANY WARRANTY; without even the implied warranties of
3845+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
3846+# PURPOSE. See the GNU General Public License for more details.
3847+
3848+# You should have received a copy of the GNU General Public License along
3849+# with this program. If not, see <http://www.gnu.org/licenses/>.
3850+
3851+import os
3852+import signal
3853+import subprocess
3854+import time
3855+
3856+from bzrlib import (
3857+ branch as _mod_branch,
3858+ bzrdir,
3859+ errors,
3860+ lazy_regex,
3861+ merge,
3862+ revision,
3863+ revisionspec,
3864+ tag,
3865+ trace,
3866+ transport,
3867+ urlutils,
3868+ version_info as bzr_version_info,
3869+ )
3870+
3871+try:
3872+ from bzrlib.errors import NoWhoami
3873+except ImportError:
3874+ NoWhoami = object()
3875+
3876+
3877+try:
3878+ from debian import changelog
3879+except ImportError:
3880+ from debian_bundle import changelog
3881+
3882+try:
3883+ MergeIntoMerger = merge.MergeIntoMerger
3884+except (AttributeError, NameError):
3885+ from bzrlib.plugins.builder.bzrlibbackports import MergeIntoMerger
3886+
3887+
3888+def subprocess_setup():
3889+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
3890+
3891+
3892+MERGE_INSTRUCTION = "merge"
3893+NEST_PART_INSTRUCTION = "nest-part"
3894+NEST_INSTRUCTION = "nest"
3895+RUN_INSTRUCTION = "run"
3896+USAGE = {
3897+ MERGE_INSTRUCTION: 'merge NAME BRANCH [REVISION]',
3898+ NEST_INSTRUCTION: 'nest NAME BRANCH TARGET-DIR [REVISION]',
3899+ NEST_PART_INSTRUCTION:
3900+ 'nest-part NAME BRANCH SUBDIR [TARGET-DIR [REVISION]]',
3901+ RUN_INSTRUCTION: 'run COMMAND',
3902+ }
3903+
3904+SAFE_INSTRUCTIONS = [
3905+ MERGE_INSTRUCTION, NEST_PART_INSTRUCTION, NEST_INSTRUCTION]
3906+
3907+
3908+class SubstitutionUnavailable(errors.BzrError):
3909+ _fmt = """Substitution for %(name)s not available: %(reason)s"""
3910+
3911+ def __init__(self, name, reason):
3912+ errors.BzrError.__init__(self, name=name, reason=reason)
3913+
3914+
3915+class SubstitutionVariable(object):
3916+ """A substitution variable for a version string."""
3917+
3918+ def replace(self, value):
3919+ """Replace name with value."""
3920+ raise NotImplementedError(self.replace)
3921+
3922+
3923+class SimpleSubstitutionVariable(SubstitutionVariable):
3924+
3925+ name = None
3926+
3927+ def replace(self, value):
3928+ if not self.name in value:
3929+ return value
3930+ return value.replace(self.name, self.get())
3931+
3932+ def get(self):
3933+ raise NotImplementedError(self.value)
3934+
3935+
3936+class BranchSubstitutionVariable(SimpleSubstitutionVariable):
3937+
3938+ basename = None
3939+
3940+ def __init__(self, branch_name=None):
3941+ super(BranchSubstitutionVariable, self).__init__()
3942+ self.branch_name = branch_name
3943+
3944+ @classmethod
3945+ def determine_name(cls, branch_name):
3946+ if branch_name is None:
3947+ return "{%s}" % cls.basename
3948+ else:
3949+ return "{%s:%s}" % (cls.basename, branch_name)
3950+
3951+ @property
3952+ def name(self):
3953+ return self.determine_name(self.branch_name)
3954+
3955+
3956+class TimeVariable(SimpleSubstitutionVariable):
3957+
3958+ name = "{time}"
3959+
3960+ def __init__(self, time):
3961+ self._time = time
3962+
3963+ def get(self):
3964+ return self._time.strftime("%Y%m%d%H%M")
3965+
3966+
3967+class DateVariable(SimpleSubstitutionVariable):
3968+
3969+ name = "{date}"
3970+
3971+ def __init__(self, time):
3972+ self._time = time
3973+
3974+ def get(self):
3975+ return self._time.strftime("%Y%m%d")
3976+
3977+
3978+class DebUpstreamVariable(BranchSubstitutionVariable):
3979+
3980+ basename = "debupstream"
3981+
3982+ def __init__(self, branch_name, version):
3983+ super(DebUpstreamVariable, self).__init__(branch_name)
3984+ self._version = version
3985+
3986+ @classmethod
3987+ def from_changelog(cls, branch_name, changelog):
3988+ if len(changelog._blocks) > 0:
3989+ return cls(branch_name, changelog._blocks[0].version)
3990+ else:
3991+ return cls(branch_name, None)
3992+
3993+ def get(self):
3994+ if self._version is None:
3995+ raise SubstitutionUnavailable(self.name,
3996+ "No previous changelog to take the upstream version from")
3997+ # Should we include the epoch?
3998+ return self._version.upstream_version
3999+
4000+
4001+class DebVersionVariable(BranchSubstitutionVariable):
4002+
4003+ basename = "debversion"
4004+
4005+ def __init__(self, branch_name, version):
4006+ super(DebVersionVariable, self).__init__(branch_name)
4007+ self._version = version
4008+
4009+ @classmethod
4010+ def from_changelog(cls, branch_name, changelog):
4011+ if len(changelog._blocks) > 0:
4012+ return cls(branch_name, changelog._blocks[0].version)
4013+ else:
4014+ return cls(branch_name, None)
4015+
4016+ def get(self):
4017+ if self._version is None:
4018+ raise SubstitutionUnavailable(self.name,
4019+ "No previous changelog to take the version from")
4020+ return str(self._version)
4021+
4022+
4023+class DebUpstreamBaseVariable(DebUpstreamVariable):
4024+
4025+ basename = "{debupstream-base}"
4026+ version_regex = lazy_regex.lazy_compile(r'([~+])(svn[0-9]+|bzr[0-9]+|git[0-9a-f]+)')
4027+
4028+ def get(self):
4029+ version = super(DebUpstreamBaseVariable, self).get()
4030+ version = self.version_regex.sub("\\1", version)
4031+ if version[-1] not in ("~", "+"):
4032+ version += "+"
4033+ return version
4034+
4035+
4036+class RevisionVariable(BranchSubstitutionVariable):
4037+
4038+ def __init__(self, branch_name, branch, revid):
4039+ super(RevisionVariable, self).__init__(branch_name)
4040+ self.branch = branch
4041+ self.revid = revid
4042+
4043+
4044+class RevnoVariable(RevisionVariable):
4045+
4046+ basename = "revno"
4047+
4048+ def get_revno(self):
4049+ try:
4050+ revno = self.branch.revision_id_to_revno(self.revid)
4051+ return str(revno)
4052+ except errors.NoSuchRevision:
4053+ # We need to load and use the full revno map after all
4054+ result = self.branch.get_revision_id_to_revno_map().get(
4055+ self.revid)
4056+ if result is None:
4057+ return result
4058+ return ".".join(result)
4059+
4060+ def get(self):
4061+ revno = self.get_revno()
4062+ if revno is None:
4063+ raise errors.BzrCommandError("Can't substitute revno of "
4064+ "branch %s in deb-version, as it's revno can't be "
4065+ "determined" % revno)
4066+ return revno
4067+
4068+
4069+class RevtimeVariable(RevisionVariable):
4070+
4071+ basename = "revtime"
4072+
4073+ def get(self):
4074+ rev = self.branch.repository.get_revision(self.revid)
4075+ return time.strftime("%Y%m%d%H%M", time.gmtime(rev.timestamp))
4076+
4077+
4078+class RevdateVariable(RevisionVariable):
4079+
4080+ basename = "revdate"
4081+
4082+ def get(self):
4083+ rev = self.branch.repository.get_revision(self.revid)
4084+ return time.strftime("%Y%m%d", time.gmtime(rev.timestamp))
4085+
4086+
4087+def extract_svn_revnum(rev):
4088+ try:
4089+ foreign_revid = rev.foreign_revid
4090+ except AttributeError:
4091+ try:
4092+ (mapping_name, uuid, bp, srevnum) = rev.revision_id.split(":", 3)
4093+ except ValueError:
4094+ raise errors.InvalidRevisionId(rev.revision_id, None)
4095+ if not mapping_name.startswith("svn-"):
4096+ raise errors.InvalidRevisionId(rev.revision_id, None)
4097+ return int(srevnum)
4098+ else:
4099+ if rev.mapping.vcs.abbreviation == "svn":
4100+ return foreign_revid[2]
4101+ else:
4102+ raise errors.InvalidRevisionId(rev.revision_id, None)
4103+
4104+
4105+class SubversionRevnumVariable(RevisionVariable):
4106+
4107+ basename = "svn-revno"
4108+
4109+ def get(self):
4110+ rev = self.branch.repository.get_revision(self.revid)
4111+ try:
4112+ revno = extract_svn_revnum(rev)
4113+ except errors.InvalidRevisionId:
4114+ raise errors.BzrCommandError("unable to expand %s for %r in %r: "
4115+ "not a Subversion revision" % (
4116+ self.name, self.revid, self.branch))
4117+ return str(revno)
4118+
4119+
4120+def extract_git_foreign_revid(rev):
4121+ try:
4122+ foreign_revid = rev.foreign_revid
4123+ except AttributeError:
4124+ try:
4125+ (mapping_name, foreign_revid) = rev.revision_id.split(":", 1)
4126+ except ValueError:
4127+ raise errors.InvalidRevisionId(rev.revision_id, None)
4128+ if not mapping_name.startswith("git-"):
4129+ raise errors.InvalidRevisionId(rev.revision_id, None)
4130+ return foreign_revid
4131+ else:
4132+ if rev.mapping.vcs.abbreviation == "git":
4133+ return foreign_revid
4134+ else:
4135+ raise errors.InvalidRevisionId(rev.revision_id, None)
4136+
4137+
4138+class GitCommitVariable(RevisionVariable):
4139+
4140+ basename = "git-commit"
4141+
4142+ def get(self):
4143+ rev = self.branch.repository.get_revision(self.revid)
4144+ try:
4145+ commit_sha = extract_git_foreign_revid(rev)
4146+ except errors.InvalidRevisionId:
4147+ raise errors.BzrCommandError("unable to expand %s for %r in %r: "
4148+ "not a Git revision" % (
4149+ self.name, self.revid, self.branch))
4150+ return commit_sha[:7]
4151+
4152+
4153+class LatestTagVariable(RevisionVariable):
4154+
4155+ basename = "latest-tag"
4156+
4157+ def get(self):
4158+ reverse_tag_dict = self.branch.tags.get_reverse_tag_dict()
4159+ for revid in self.branch.repository.iter_reverse_revision_history(self.revid):
4160+ if revid in reverse_tag_dict:
4161+ return reverse_tag_dict[revid][0]
4162+ else:
4163+ raise errors.BzrCommandError("No tags set on branch %s mainline" %
4164+ self.branch_name)
4165+
4166+
4167+ok_to_preserve = [DebUpstreamVariable, DebUpstreamBaseVariable,
4168+ DebVersionVariable]
4169+# The variables that don't require substitution in their name
4170+simple_vars = [TimeVariable, DateVariable]
4171+branch_vars = [RevnoVariable, SubversionRevnumVariable,
4172+ GitCommitVariable, LatestTagVariable, DebVersionVariable,
4173+ DebUpstreamBaseVariable, DebUpstreamVariable, RevdateVariable,
4174+ RevtimeVariable]
4175+
4176+
4177+def check_expanded_deb_version(base_branch):
4178+ checked_version = base_branch.deb_version
4179+ if checked_version is None:
4180+ return
4181+ for token in ok_to_preserve:
4182+ if issubclass(token, BranchSubstitutionVariable):
4183+ for name in base_branch.list_branch_names():
4184+ checked_version = checked_version.replace(
4185+ token.determine_name(name), "")
4186+ checked_version = checked_version.replace(
4187+ token.determine_name(None), "")
4188+ else:
4189+ checked_version = checked_version.replace(
4190+ token.name, "")
4191+ if "{" in checked_version:
4192+ available_tokens = [var.name for var in simple_vars]
4193+ for var_kls in branch_vars:
4194+ for name in base_branch.list_branch_names():
4195+ available_tokens.append(var_kls.determine_name(name))
4196+ available_tokens.append(var_kls.determine_name(None))
4197+ raise errors.BzrCommandError("deb-version not fully "
4198+ "expanded: %s. Valid substitutions are: %s"
4199+ % (base_branch.deb_version, available_tokens))
4200+
4201+
4202+class CommandFailedError(errors.BzrError):
4203+
4204+ _fmt = "The command \"%(command)s\" failed."
4205+
4206+ def __init__(self, command):
4207+ super(CommandFailedError, self).__init__()
4208+ self.command = command
4209+
4210+
4211+def ensure_basedir(to_transport):
4212+ """Ensure that the basedir of to_transport exists.
4213+
4214+ It is allowed to already exist currently, to reuse directories.
4215+
4216+ :param to_transport: The Transport to ensure that the basedir of
4217+ exists.
4218+ """
4219+ try:
4220+ to_transport.mkdir('.')
4221+ except errors.FileExists:
4222+ pass
4223+ except errors.NoSuchFile:
4224+ raise errors.BzrCommandError('Parent of "%s" does not exist.'
4225+ % to_transport.base)
4226+
4227+
4228+def pull_or_branch(tree_to, br_to, br_from, to_transport, revision_id,
4229+ accelerator_tree=None, possible_transports=None):
4230+ """Either pull or branch from a branch.
4231+
4232+ Depending on whether the target branch and tree exist already this
4233+ will either pull from the source branch, or branch from it. If it
4234+ returns this function will return a branch and tree for the target,
4235+ after creating either if necessary.
4236+
4237+ :param tree_to: The WorkingTree to pull in to, or None. If not None then
4238+ br_to must not be None.
4239+ :param br_to: The Branch to pull in to, or None to branch.
4240+ :param br_from: The Branch to pull/branch from.
4241+ :param to_transport: A Transport for the root of the target.
4242+ :param revision_id: the revision id to pull/branch.
4243+ :param accelerator_tree: A tree to take contents from that is faster than
4244+ extracting from br_from, or None.
4245+ :param possible_transports: A list of transports that can be reused, or
4246+ None.
4247+ :return: A tuple of (target tree, target branch) which are the updated
4248+ tree and branch, created if necessary. They are locked, and you
4249+ should use these instead of tree_to and br_to if they were passed
4250+ in, including for unlocking.
4251+ """
4252+ created_tree_to = False
4253+ created_br_to = False
4254+ if br_to is None:
4255+ # We do a "branch"
4256+ ensure_basedir(to_transport)
4257+ dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
4258+ possible_transports=possible_transports,
4259+ accelerator_tree=accelerator_tree,
4260+ source_branch=br_from,
4261+ stacked=(bzr_version_info >= (2, 3, 0)))
4262+ try:
4263+ tree_to = dir.open_workingtree()
4264+ except errors.NoWorkingTree:
4265+ # There's no working tree, so it's probably in a no-trees repo,
4266+ # but the whole point of this is to create trees, so we should
4267+ # forcibly create one.
4268+ tree_to = dir.create_workingtree()
4269+ br_to = tree_to.branch
4270+ created_br_to = True
4271+ tag._merge_tags_if_possible(br_from, br_to)
4272+ created_tree_to = True
4273+ else:
4274+ # We do a "pull"
4275+ if tree_to is not None:
4276+ # FIXME: should these pulls overwrite?
4277+ tree_to.pull(br_from, stop_revision=revision_id,
4278+ possible_transports=possible_transports)
4279+ else:
4280+ br_to.pull(br_from, stop_revision=revision_id,
4281+ possible_transports=possible_transports)
4282+ tree_to = br_to.bzrdir.create_workingtree()
4283+ # Ugh, we have to assume that the caller replaces their reference
4284+ # to the branch with the one we return.
4285+ br_to.unlock()
4286+ br_to = tree_to.branch
4287+ br_to.lock_write()
4288+ created_tree_to = True
4289+ if created_tree_to:
4290+ tree_to.lock_write()
4291+ try:
4292+ if created_br_to:
4293+ br_to.lock_write()
4294+ try:
4295+ conflicts = tree_to.conflicts()
4296+ if len(conflicts) > 0:
4297+ # FIXME: better reporting
4298+ raise errors.BzrCommandError("Conflicts... aborting.")
4299+ except:
4300+ if created_br_to:
4301+ br_to.unlock()
4302+ raise
4303+ except:
4304+ if created_tree_to:
4305+ tree_to.unlock()
4306+ raise
4307+ return tree_to, br_to
4308+
4309+
4310+def merge_branch(child_branch, tree_to, br_to, possible_transports=None):
4311+ """Merge the branch specified by child_branch.
4312+
4313+ :param child_branch: the RecipeBranch to retrieve the branch and revision to
4314+ merge from.
4315+ :param tree_to: the WorkingTree to merge in to.
4316+ :param br_to: the Branch to merge in to.
4317+ """
4318+ if child_branch.branch is None:
4319+ child_branch.branch = _mod_branch.Branch.open(child_branch.url,
4320+ possible_transports=possible_transports)
4321+ child_branch.branch.lock_read()
4322+ try:
4323+ tag._merge_tags_if_possible(child_branch.branch, br_to)
4324+ if child_branch.revspec is not None:
4325+ merge_revspec = revisionspec.RevisionSpec.from_string(
4326+ child_branch.revspec)
4327+ try:
4328+ merge_revid = merge_revspec.as_revision_id(
4329+ child_branch.branch)
4330+ except errors.InvalidRevisionSpec, e:
4331+ # Give the user a hint if they didn't mean to speciy
4332+ # a revspec.
4333+ e.extra = (". Did you not mean to specify a revspec "
4334+ "at the end of the merge line?")
4335+ raise e
4336+ else:
4337+ merge_revid = child_branch.branch.last_revision()
4338+ child_branch.revid = merge_revid
4339+ try:
4340+ merger = merge.Merger.from_revision_ids(None, tree_to, merge_revid,
4341+ other_branch=child_branch.branch, tree_branch=br_to)
4342+ except errors.UnrelatedBranches:
4343+ # Let's just try and hope for the best.
4344+ merger = merge.Merger.from_revision_ids(None, tree_to, merge_revid,
4345+ other_branch=child_branch.branch, tree_branch=br_to,
4346+ base=revision.NULL_REVISION)
4347+ merger.merge_type = merge.Merge3Merger
4348+ if (merger.base_rev_id == merger.other_rev_id and
4349+ merger.other_rev_id is not None):
4350+ # Nothing to do.
4351+ return
4352+ conflict_count = merger.do_merge()
4353+
4354+ merger.set_pending()
4355+ if conflict_count:
4356+ # FIXME: better reporting
4357+ raise errors.BzrCommandError("Conflicts from merge")
4358+ config = br_to.get_config()
4359+ try:
4360+ committer = config.username()
4361+ except NoWhoami:
4362+ committer = "bzr-builder <nobody@example.com>"
4363+ tree_to.commit("Merge %s" %
4364+ urlutils.unescape_for_display(child_branch.url, 'utf-8'),
4365+ committer=committer)
4366+ finally:
4367+ child_branch.branch.unlock()
4368+
4369+
4370+def nest_part_branch(child_branch, tree_to, br_to, subpath, target_subdir=None):
4371+ """Merge the branch subdirectory specified by child_branch.
4372+
4373+ :param child_branch: the RecipeBranch to retrieve the branch and revision to
4374+ merge from.
4375+ :param tree_to: the WorkingTree to merge in to.
4376+ :param br_to: the Branch to merge in to.
4377+ :param subpath: only merge files from branch that are from this path.
4378+ e.g. subpath='/debian' will only merge changes from that directory.
4379+ :param target_subdir: (optional) directory in target to merge that
4380+ subpath into. Defaults to basename of subpath.
4381+ """
4382+ child_branch.branch = _mod_branch.Branch.open(child_branch.url)
4383+ child_branch.branch.lock_read()
4384+ try:
4385+ child_branch.resolve_revision_id()
4386+ other_tree = child_branch.branch.basis_tree()
4387+ other_tree.lock_read()
4388+ try:
4389+ if target_subdir is None:
4390+ target_subdir = os.path.basename(subpath)
4391+ merger = MergeIntoMerger(this_tree=tree_to, other_tree=other_tree,
4392+ other_branch=child_branch.branch, target_subdir=target_subdir,
4393+ source_subpath=subpath, other_rev_id=child_branch.revid)
4394+ merger.set_base_revision(revision.NULL_REVISION, child_branch.branch)
4395+ conflict_count = merger.do_merge()
4396+ merger.set_pending()
4397+ finally:
4398+ other_tree.unlock()
4399+ finally:
4400+ child_branch.branch.unlock()
4401+
4402+ if conflict_count:
4403+ # FIXME: better reporting
4404+ raise errors.BzrCommandError("Conflicts from merge")
4405+ tree_to.commit("Merge %s of %s" %
4406+ (subpath, urlutils.unescape_for_display(child_branch.url, 'utf-8')))
4407+
4408+
4409+def update_branch(base_branch, tree_to, br_to, to_transport,
4410+ possible_transports=None):
4411+ if base_branch.branch is None:
4412+ base_branch.branch = _mod_branch.Branch.open(base_branch.url,
4413+ possible_transports=possible_transports)
4414+ base_branch.branch.lock_read()
4415+ try:
4416+ base_branch.resolve_revision_id()
4417+ tree_to, br_to = pull_or_branch(tree_to, br_to, base_branch.branch,
4418+ to_transport, base_branch.revid,
4419+ possible_transports=possible_transports)
4420+ finally:
4421+ base_branch.branch.unlock()
4422+ return tree_to, br_to
4423+
4424+
4425+def _resolve_revisions_recurse(new_branch, substitute_branch_vars,
4426+ if_changed_from=None):
4427+ changed = False
4428+ new_branch.branch = _mod_branch.Branch.open(new_branch.url)
4429+ new_branch.branch.lock_read()
4430+ try:
4431+ new_branch.resolve_revision_id()
4432+ substitute_branch_vars(new_branch.name, new_branch.branch, new_branch.revid)
4433+ if (if_changed_from is not None
4434+ and (new_branch.revspec is not None
4435+ or if_changed_from.revspec is not None)):
4436+ if if_changed_from.revspec is not None:
4437+ changed_revspec = revisionspec.RevisionSpec.from_string(
4438+ if_changed_from.revspec)
4439+ changed_revision_id = changed_revspec.as_revision_id(
4440+ new_branch.branch)
4441+ else:
4442+ changed_revision_id = new_branch.branch.last_revision()
4443+ if new_branch.revid != changed_revision_id:
4444+ changed = True
4445+ for index, instruction in enumerate(new_branch.child_branches):
4446+ child_branch = instruction.recipe_branch
4447+ if_changed_child = None
4448+ if if_changed_from is not None:
4449+ if_changed_child = if_changed_from.child_branches[index].recipe_branch
4450+ if child_branch is not None:
4451+ child_changed = _resolve_revisions_recurse(child_branch,
4452+ substitute_branch_vars,
4453+ if_changed_from=if_changed_child)
4454+ if child_changed:
4455+ changed = child_changed
4456+ return changed
4457+ finally:
4458+ new_branch.branch.unlock()
4459+
4460+
4461+def resolve_revisions(base_branch, if_changed_from=None):
4462+ """Resolve all the unknowns in base_branch.
4463+
4464+ This walks the RecipeBranch and substitutes in revnos and deb_version.
4465+
4466+ If if_changed_from is not None then it should be a second RecipeBranch
4467+ to compare base_branch against. If the shape, or the revision ids differ
4468+ then the function will return True.
4469+
4470+ :param base_branch: the RecipeBranch we plan to build.
4471+ :param if_changed_from: the RecipeBranch that we want to compare against.
4472+ :return: False if if_changed_from is not None, and the shape and revisions
4473+ of the two branches don't differ. True otherwise.
4474+ """
4475+ changed = False
4476+ if if_changed_from is not None:
4477+ changed = base_branch.different_shape_to(if_changed_from)
4478+ if_changed_from_revisions = if_changed_from
4479+ if changed:
4480+ if_changed_from_revisions = None
4481+ changed_revisions = _resolve_revisions_recurse(base_branch,
4482+ base_branch.substitute_branch_vars,
4483+ if_changed_from=if_changed_from_revisions)
4484+ if not changed:
4485+ changed = changed_revisions
4486+ check_expanded_deb_version(base_branch)
4487+ if if_changed_from is not None and not changed:
4488+ return False
4489+ return True
4490+
4491+
4492+def _build_inner_tree(base_branch, target_path, possible_transports=None):
4493+ revision_of = ""
4494+ if base_branch.revspec is not None:
4495+ revision_of = "revision '%s' of " % base_branch.revspec
4496+ trace.note("Retrieving %s'%s' to put at '%s'."
4497+ % (revision_of, base_branch.url, target_path))
4498+ to_transport = transport.get_transport(target_path,
4499+ possible_transports=possible_transports)
4500+ try:
4501+ tree_to, br_to = bzrdir.BzrDir.open_tree_or_branch(target_path)
4502+ # Should we commit any changes in the tree here? If we don't
4503+ # then they will get folded up in to the first merge.
4504+ except errors.NotBranchError:
4505+ tree_to = None
4506+ br_to = None
4507+ if tree_to is not None:
4508+ tree_to.lock_write()
4509+ try:
4510+ if br_to is not None:
4511+ br_to.lock_write()
4512+ try:
4513+ tree_to, br_to = update_branch(base_branch, tree_to, br_to,
4514+ to_transport, possible_transports=possible_transports)
4515+ for instruction in base_branch.child_branches:
4516+ instruction.apply(target_path, tree_to, br_to)
4517+ finally:
4518+ # Is this ok if tree_to is created by pull_or_branch?
4519+ if br_to is not None:
4520+ br_to.unlock()
4521+ finally:
4522+ if tree_to is not None:
4523+ tree_to.unlock()
4524+
4525+
4526+def build_tree(base_branch, target_path, possible_transports=None):
4527+ """Build the RecipeBranch at a path.
4528+
4529+ Follow the instructions embodied in RecipeBranch and build a tree
4530+ based on them rooted at target_path. If target_path exists and
4531+ is the root of the branch then the branch will be updated based on
4532+ what the RecipeBranch requires.
4533+
4534+ :param base_branch: a RecipeBranch to build.
4535+ :param target_path: the path to the base of the desired output.
4536+ """
4537+ trace.note("Building tree.")
4538+ _build_inner_tree(base_branch, target_path,
4539+ possible_transports=possible_transports)
4540+
4541+
4542+class ChildBranch(object):
4543+ """A child branch in a recipe.
4544+
4545+ If the nest path is not None it is the path relative to the recipe branch
4546+ where the child branch should be placed. If it is None then the child
4547+ branch should be merged instead of nested.
4548+ """
4549+
4550+ can_have_children = False
4551+
4552+ def __init__(self, recipe_branch, nest_path=None):
4553+ self.recipe_branch = recipe_branch
4554+ self.nest_path = nest_path
4555+
4556+ def apply(self, target_path, tree_to, br_to, possible_transports=None):
4557+ raise NotImplementedError(self.apply)
4558+
4559+ def as_tuple(self):
4560+ return (self.recipe_branch, self.nest_path)
4561+
4562+ def _get_revid_part(self):
4563+ if self.recipe_branch.revid is not None:
4564+ revid_part = " revid:%s" % self.recipe_branch.revid
4565+ elif self.recipe_branch.revspec is not None:
4566+ revid_part = " %s" % self.recipe_branch.revspec
4567+ else:
4568+ revid_part = ""
4569+ return revid_part
4570+
4571+ def __repr__(self):
4572+ return "<%s %r>" % (self.__class__.__name__, self.nest_path)
4573+
4574+
4575+class CommandInstruction(ChildBranch):
4576+
4577+ def apply(self, target_path, tree_to, br_to, possible_transports=None):
4578+ # it's a command
4579+ trace.note("Running '%s' in '%s'." % (self.nest_path, target_path))
4580+ proc = subprocess.Popen(self.nest_path, cwd=target_path,
4581+ preexec_fn=subprocess_setup, shell=True, stdin=subprocess.PIPE)
4582+ proc.communicate()
4583+ if proc.returncode != 0:
4584+ raise CommandFailedError(self.nest_path)
4585+
4586+ def as_text(self):
4587+ return "%s %s" % (RUN_INSTRUCTION, self.nest_path)
4588+
4589+
4590+class MergeInstruction(ChildBranch):
4591+
4592+ def apply(self, target_path, tree_to, br_to, possible_transports=None):
4593+ revision_of = ""
4594+ if self.recipe_branch.revspec is not None:
4595+ revision_of = "revision '%s' of " % self.recipe_branch.revspec
4596+ trace.note("Merging %s'%s' in to '%s'."
4597+ % (revision_of, self.recipe_branch.url, target_path))
4598+ merge_branch(self.recipe_branch, tree_to, br_to,
4599+ possible_transports=possible_transports)
4600+
4601+ def as_text(self):
4602+ revid_part = self._get_revid_part()
4603+ return "%s %s %s%s" % (
4604+ MERGE_INSTRUCTION, self.recipe_branch.name,
4605+ self.recipe_branch.url, revid_part)
4606+
4607+ def __repr__(self):
4608+ return "<%s %r>" % (self.__class__.__name__, self.recipe_branch.name)
4609+
4610+
4611+class NestPartInstruction(ChildBranch):
4612+
4613+ def __init__(self, recipe_branch, subpath, target_subdir):
4614+ ChildBranch.__init__(self, recipe_branch)
4615+ self.subpath = subpath
4616+ self.target_subdir = target_subdir
4617+
4618+ def apply(self, target_path, tree_to, br_to):
4619+ nest_part_branch(self.recipe_branch, tree_to, br_to, self.subpath,
4620+ self.target_subdir)
4621+
4622+ def as_text(self):
4623+ revid_part = self._get_revid_part()
4624+ if revid_part:
4625+ target_subdir = self.target_subdir
4626+ if target_subdir is None:
4627+ target_subdir = self.subpath
4628+ target_revid_part = " %s%s" % (
4629+ target_subdir, revid_part)
4630+ elif self.target_subdir is not None:
4631+ target_revid_part = " %s" % self.target_subdir
4632+ else:
4633+ target_revid_part = ""
4634+ return "%s %s %s %s%s" % (
4635+ NEST_PART_INSTRUCTION, self.recipe_branch.name,
4636+ self.recipe_branch.url, self.subpath, target_revid_part)
4637+
4638+
4639+class NestInstruction(ChildBranch):
4640+
4641+ can_have_children = True
4642+
4643+ def apply(self, target_path, tree_to, br_to, possible_transports=None):
4644+ _build_inner_tree(self.recipe_branch,
4645+ target_path=os.path.join(target_path, self.nest_path),
4646+ possible_transports=possible_transports)
4647+
4648+ def as_text(self):
4649+ revid_part = self._get_revid_part()
4650+ return "%s %s %s %s%s" % (
4651+ NEST_INSTRUCTION, self.recipe_branch.name,
4652+ self.recipe_branch.url, self.nest_path, revid_part)
4653+
4654+ def __repr__(self):
4655+ return "<%s %r>" % (self.__class__.__name__,
4656+ self.recipe_branch.name)
4657+
4658+
4659+class RecipeBranch(object):
4660+ """A nested structure that represents a Recipe.
4661+
4662+ A RecipeBranch has a name and a url (the name can be None for the
4663+ root branch), and optionally child branches that are either merged
4664+ or nested.
4665+
4666+ The child_branches attribute is a list of tuples of ChildBranch objects.
4667+ The revid attribute records the revid that the url and revspec resolved
4668+ to when the RecipeBranch was built, or None if it has not been built.
4669+
4670+ :ivar revid: after this recipe branch has been built this is set to the
4671+ revision ID that was merged/nested from the branch at self.url.
4672+ """
4673+
4674+ def __init__(self, name, url, revspec=None):
4675+ """Create a RecipeBranch.
4676+
4677+ :param name: the name for the branch, or None if it is the root.
4678+ :param url: the URL from which to retrieve the branch.
4679+ :param revspec: a revision specifier for the revision of the branch
4680+ to use, or None (the default) to use the last revision.
4681+ """
4682+ self.name = name
4683+ self.url = url
4684+ self.revspec = revspec
4685+ self.child_branches = []
4686+ self.revid = None
4687+ self.branch = None
4688+
4689+ def resolve_revision_id(self):
4690+ """Resolve the revision id for this branch.
4691+ """
4692+ if self.revspec is not None:
4693+ revspec = revisionspec.RevisionSpec.from_string(self.revspec)
4694+ revision_id = revspec.as_revision_id(self.branch)
4695+ else:
4696+ revision_id = self.branch.last_revision()
4697+ self.revid = revision_id
4698+
4699+ def merge_branch(self, branch):
4700+ """Merge a child branch in to this one.
4701+
4702+ :param branch: the RecipeBranch to merge.
4703+ """
4704+ self.child_branches.append(MergeInstruction(branch))
4705+
4706+ def nest_part_branch(self, branch, subpath=None, target_subdir=None):
4707+ """Merge subdir of a child branch into this one.
4708+
4709+ :param branch: the RecipeBranch to merge.
4710+ :param subpath: only merge files from branch that are from this path.
4711+ e.g. subpath='/debian' will only merge changes from that directory.
4712+ :param target_subdir: (optional) directory in target to merge that
4713+ subpath into. Defaults to basename of subpath.
4714+ """
4715+ self.child_branches.append(
4716+ NestPartInstruction(branch, subpath, target_subdir))
4717+
4718+ def nest_branch(self, location, branch):
4719+ """Nest a child branch in to this one.
4720+
4721+ :param location: the relative path at which this branch should be nested.
4722+ :param branch: the RecipeBranch to nest.
4723+ """
4724+ assert location not in [b.nest_path for b in self.child_branches],\
4725+ "%s already has branch nested there" % location
4726+ self.child_branches.append(NestInstruction(branch, location))
4727+
4728+ def run_command(self, command):
4729+ """Set a command to be run.
4730+
4731+ :param command: the command to be run
4732+ """
4733+ self.child_branches.append(CommandInstruction(None, command))
4734+
4735+ def different_shape_to(self, other_branch):
4736+ """Tests whether the name, url and child_branches are the same"""
4737+ if self.name != other_branch.name:
4738+ return True
4739+ if self.url != other_branch.url:
4740+ return True
4741+ if len(self.child_branches) != len(other_branch.child_branches):
4742+ return True
4743+ for index, instruction in enumerate(self.child_branches):
4744+ child_branch = instruction.recipe_branch
4745+ nest_location = instruction.nest_path
4746+ other_instruction = other_branch.child_branches[index]
4747+ other_child_branch = other_instruction.recipe_branch
4748+ other_nest_location = other_instruction.nest_path
4749+ if nest_location != other_nest_location:
4750+ return True
4751+ if ((child_branch is None and other_child_branch is not None)
4752+ or (child_branch is not None and other_child_branch is None)):
4753+ return True
4754+ # if child_branch is None then other_child_branch must be
4755+ # None too, meaning that they are both run instructions,
4756+ # we would compare their nest locations (commands), but
4757+ # that has already been done, so just guard
4758+ if (child_branch is not None
4759+ and child_branch.different_shape_to(other_child_branch)):
4760+ return True
4761+ return False
4762+
4763+ def iter_all_instructions(self):
4764+ """Iter over all instructions under this branch."""
4765+ for instruction in self.child_branches:
4766+ yield instruction
4767+ child_branch = instruction.recipe_branch
4768+ if child_branch is None:
4769+ continue
4770+ for instruction in child_branch.iter_all_instructions():
4771+ yield instruction
4772+
4773+ def iter_all_branches(self):
4774+ """Iterate over all branches."""
4775+ yield self
4776+ for instruction in self.child_branches:
4777+ child_branch = instruction.recipe_branch
4778+ if child_branch is None:
4779+ continue
4780+ for subbranch in child_branch.iter_all_branches():
4781+ yield subbranch
4782+
4783+ def lookup_branch(self, name):
4784+ """Lookup a branch by its name."""
4785+ for branch in self.iter_all_branches():
4786+ if branch.name == name:
4787+ return branch
4788+ else:
4789+ raise KeyError(name)
4790+
4791+ def list_branch_names(self):
4792+ """List all of the branch names under this one.
4793+
4794+ :return: a list of the branch names.
4795+ :rtype: list(str)
4796+ """
4797+ return [branch.name for branch in self.iter_all_branches()
4798+ if branch.name is not None]
4799+
4800+ def __repr__(self):
4801+ return "<%s %r>" % (self.__class__.__name__, self.name)
4802+
4803+
4804+class BaseRecipeBranch(RecipeBranch):
4805+ """The RecipeBranch that is at the root of a recipe."""
4806+
4807+ def __init__(self, url, deb_version, format, revspec=None):
4808+ """Create a BaseRecipeBranch.
4809+
4810+ :param deb_version: the template to use for the version number.
4811+ Should be None for anything except the root branch.
4812+ """
4813+ super(BaseRecipeBranch, self).__init__(None, url, revspec=revspec)
4814+ self.deb_version = deb_version
4815+ self.format = format
4816+
4817+ def substitute_branch_vars(self, branch_name, branch, revid):
4818+ """Substitute the branch variables for the given branch name in deb_version.
4819+
4820+ Where deb_version has a place to substitute the revno for a branch
4821+ this will substitute it for the given branch name.
4822+
4823+ :param branch_name: the name of the RecipeBranch to substitute.
4824+ :param branch: Branch object for the branch
4825+ :param revid: Revision id in the branch for which to return the revno
4826+ """
4827+ if self.deb_version is None:
4828+ return
4829+ revno_var = RevnoVariable(branch_name, branch, revid)
4830+ self.deb_version = revno_var.replace(self.deb_version)
4831+ svn_revno_var = SubversionRevnumVariable(branch_name, branch, revid)
4832+ self.deb_version = svn_revno_var.replace(self.deb_version)
4833+ git_commit_var = GitCommitVariable(branch_name, branch, revid)
4834+ self.deb_version = git_commit_var.replace(self.deb_version)
4835+ latest_tag_var = LatestTagVariable(branch_name, branch, revid)
4836+ self.deb_version = latest_tag_var.replace(self.deb_version)
4837+ revdate_var = RevdateVariable(branch_name, branch, revid)
4838+ self.deb_version = revdate_var.replace(self.deb_version)
4839+ revtime_var = RevtimeVariable(branch_name, branch, revid)
4840+ self.deb_version = revtime_var.replace(self.deb_version)
4841+ tree = branch.repository.revision_tree(revid)
4842+ cl_file_id = tree.path2id("debian/changelog")
4843+ if cl_file_id is not None:
4844+ cl = changelog.Changelog(tree.get_file(cl_file_id))
4845+ debupstream_var = DebUpstreamVariable.from_changelog(branch_name, cl)
4846+ self.deb_version = debupstream_var.replace(self.deb_version)
4847+ debupstreambase_var = DebUpstreamBaseVariable.from_changelog(
4848+ branch_name, cl)
4849+ self.deb_version = debupstreambase_var.replace(self.deb_version)
4850+ pkgversion_var = DebVersionVariable.from_changelog(branch_name, cl)
4851+ self.deb_version = pkgversion_var.replace(self.deb_version)
4852+
4853+ def substitute_time(self, time):
4854+ """Substitute the time in to deb_version if needed.
4855+
4856+ :param time: a datetime.datetime with the desired time.
4857+ """
4858+ if self.deb_version is None:
4859+ return
4860+ self.deb_version = TimeVariable(time).replace(self.deb_version)
4861+ self.deb_version = DateVariable(time).replace(self.deb_version)
4862+
4863+ def _add_child_branches_to_manifest(self, child_branches, indent_level):
4864+ manifest = ""
4865+ for instruction in child_branches:
4866+ manifest += "%s%s\n" % (
4867+ " " * indent_level, instruction.as_text())
4868+ if instruction.can_have_children:
4869+ manifest += self._add_child_branches_to_manifest(
4870+ instruction.recipe_branch.child_branches,
4871+ indent_level+1)
4872+ return manifest
4873+
4874+ def __str__(self):
4875+ return self.get_recipe_text(validate=True)
4876+
4877+ def get_recipe_text(self, validate=False):
4878+ manifest = "# bzr-builder format %s" % str(self.format)
4879+ if self.deb_version is not None:
4880+ # TODO: should we store the expanded version that was used?
4881+ manifest += " deb-version %s" % (self.deb_version,)
4882+ manifest += "\n"
4883+ if self.revid is not None:
4884+ manifest += "%s revid:%s\n" % (self.url, self.revid)
4885+ elif self.revspec is not None:
4886+ manifest += "%s %s\n" % (self.url, self.revspec)
4887+ else:
4888+ manifest += "%s\n" % (self.url,)
4889+ manifest += self._add_child_branches_to_manifest(self.child_branches,
4890+ 0)
4891+ if validate:
4892+ # Sanity check.
4893+ # TODO: write a function that compares the result of this parse with
4894+ # the branch that we built it from.
4895+ RecipeParser(manifest).parse()
4896+ return manifest
4897+
4898+
4899+class RecipeParseError(errors.BzrError):
4900+ _fmt = "Error parsing %(filename)s:%(line)s:%(char)s: %(problem)s."
4901+
4902+ def __init__(self, filename, line, char, problem):
4903+ errors.BzrError.__init__(self, filename=filename, line=line, char=char,
4904+ problem=problem)
4905+
4906+
4907+class InstructionParseError(RecipeParseError):
4908+ _fmt = RecipeParseError._fmt + "\nUsage: %(usage)s"
4909+
4910+ def __init__(self, filename, line, char, problem, instruction):
4911+ RecipeParseError.__init__(self, filename, line, char, problem)
4912+ self.usage = USAGE[instruction]
4913+
4914+
4915+class ForbiddenInstructionError(RecipeParseError):
4916+
4917+ def __init__(self, filename, line, char, problem, instruction_name=None):
4918+ RecipeParseError.__init__(self, filename, line, char, problem)
4919+ self.instruction_name = instruction_name
4920+
4921+
4922+class RecipeParser(object):
4923+ """Parse a recipe.
4924+
4925+ The parse() method is probably the only one that interests you.
4926+ """
4927+
4928+ whitespace_chars = " \t"
4929+ eol_char = "\n"
4930+ digit_chars = ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9")
4931+
4932+ NEWEST_VERSION = 0.4
4933+
4934+ def __init__(self, f, filename=None):
4935+ """Create a RecipeParser.
4936+
4937+ :param f: either the recipe as a string, or a file like object to
4938+ take it from.
4939+ :param filename: the filename of the recipe if known (for error
4940+ reporting).
4941+ """
4942+ if getattr(f, "read", None) is not None:
4943+ self.text = f.read()
4944+ else:
4945+ self.text = f
4946+ self.filename = filename
4947+ if filename is None:
4948+ self.filename = "recipe"
4949+
4950+ def parse(self, permitted_instructions=None):
4951+ """Parse the recipe.
4952+
4953+ :param permitted_instructions: a list of instructions that you
4954+ want to allow. Defaults to None allowing them all.
4955+ :type permitted_instructions: list(str) or None
4956+ :return: a RecipeBranch representing the recipe.
4957+ """
4958+ self.lines = self.text.split("\n")
4959+ self.index = 0
4960+ self.line_index = 0
4961+ self.current_line = self.lines[self.line_index]
4962+ self.current_indent_level = 0
4963+ self.seen_nicks = set()
4964+ self.seen_paths = {".": 1}
4965+ (version, deb_version) = self.parse_header()
4966+ self.version = version
4967+ last_instruction = None
4968+ active_branches = []
4969+ last_branch = None
4970+ while self.line_index < len(self.lines):
4971+ if self.is_blankline():
4972+ self.new_line()
4973+ continue
4974+ comment = self.parse_comment_line()
4975+ if comment is not None:
4976+ self.new_line()
4977+ continue
4978+ old_indent_level = self.parse_indent()
4979+ if old_indent_level is not None:
4980+ if (old_indent_level < self.current_indent_level
4981+ and last_instruction != NEST_INSTRUCTION):
4982+ self.throw_parse_error("Not allowed to indent unless "
4983+ "after a '%s' line" % NEST_INSTRUCTION)
4984+ if old_indent_level < self.current_indent_level:
4985+ active_branches.append(last_branch)
4986+ else:
4987+ unindent = self.current_indent_level - old_indent_level
4988+ active_branches = active_branches[:unindent]
4989+ if last_instruction is None:
4990+ url = self.take_to_whitespace("branch to start from")
4991+ revspec = self.parse_optional_revspec()
4992+ self.new_line()
4993+ last_branch = BaseRecipeBranch(url, deb_version,
4994+ self.version, revspec=revspec)
4995+ active_branches = [last_branch]
4996+ last_instruction = ""
4997+ else:
4998+ instruction = self.parse_instruction(
4999+ permitted_instructions=permitted_instructions)
5000+ if instruction == RUN_INSTRUCTION:
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches