Merge lp:~johnf-inodes/autoppa/johnf into lp:autoppa

Proposed by John Ferlito
Status: Needs review
Proposed branch: lp:~johnf-inodes/autoppa/johnf
Merge into: lp:autoppa
Diff against target: 396 lines
9 files modified
.bzrignore (+1/-0)
README (+6/-6)
autoppa/target.py (+59/-72)
debian/changelog (+16/-0)
debian/control (+7/-5)
debian/control.autoppa (+8/-6)
debian/pycompat (+1/-0)
debian/rules (+1/-1)
debian/watch (+2/-0)
To merge this branch: bzr merge lp:~johnf-inodes/autoppa/johnf
Reviewer Review Type Date Requested Status
Jamu Kakar Needs Fixing
Review via email: mp+13512@code.launchpad.net

This proposal supersedes a proposal from 2009-10-07.

To post a comment you must log in.
Revision history for this message
John Ferlito (johnf-inodes) wrote : Posted in a previous version of this proposal

Hi,

This branch has a couple of patches in it. Let me know if you need me to break them up.

r29 - Use sensible-editor as a fallback for EDITOR and VISUAL
r30 - Be conformant with PPA policy and use ~hardy instead of 8.04
r31..33 Use bzrlib and builddeb builds off jelmers branch
r34..39 Improve debian packing

Cheers,
John

Revision history for this message
John Ferlito (johnf-inodes) wrote :

Hi,

Just updated this with an extra patch to make sure that -sa is passed to the builder.

This branch has a couple of patches in it. Let me know if you need me to break them up.

r29 - Use sensible-editor as a fallback for EDITOR and VISUAL
r30 - Be conformant with PPA policy and use ~hardy instead of 8.04
r31..33 - Use bzrlib and builddeb builds off jelmers branch
r34..40 - Improve debian packaging

Cheers,
John

Revision history for this message
Jamu Kakar (jkakar) wrote :

Sorry for the delay on this, but I somehow missed that this was
awaiting review. Robert Collins was kind enough to point it out to
me.

[1]

The tests haven't been updated to match the changes and, as a
result, there are many failures. We'll need to fix that before the
branch can be merged. You can run the tests with 'make check' to
see what-all is breaking. I can help with this (though probably not
until the end of this week, realistically).

I see that you've use bzr pipeline and I'm guessing from the log
(haven't looked at the individual pipes) that these changes came
from jelmer's build-deb branch.

[2]

A minor issue is that the version number format has changed. What
you've changed it to is close to what it was before the change to
the current format. I think it makes sense to follow the PPA
guidelines, so I'm in favour of the change, but some users will
probably be unhappy about it. Is this change necessary for your use
case?

[3]

Also, there are some minor cosmetic issues:

1. Please use double-quotes instead of single-quotes.

2. Whole words are preferred to abbreviations. 'branch_wt', for
   example, would be better as 'branch_working_tree' or
   'working_tree'.

3. There are some lines that are longer than 80 characters that need
   wrapping.

[4]

+import shutil

This import is unnecessary.

[5]

Something I'll need to double check is copyright assignment
requirements, given that this is a Canonical project. Have you
signed the contributor agreement?

[6]

+ # TODO: This merge doesn't make any sense...

I don't understand this comment. The merge does make sense, as far
as I understand it...? Am I missing something?

[7]

+ # Sometimes we might have a rules.autoppa and no rules file.
+ # We bzr mv .autoppa in place so as to keep perms right
+ self.working_tree.remove(path[:-len(".autoppa")])
+ self.working_tree.rename_one(path[start:end] + '.autoppa', path[start:end])

I don't think this is correct. This will effectively cause the
.autoppa file to "disappear" when/if the build branch is merged back
into the source branch, which will likely break subsequent builds.

[8]

+ cmd_builddeb().run([self.working_tree.basedir], ['-sa'], source=True)

Yay for reuse! One thing to note is that the bzrlib.ui module isn't
setup properly. I guess if you've been using this branch, it
doesn't matter, but I do wonder if the output would be better with a
properly-initialized bzrlib.ui. The code required to do this is:

    import bzrlib.ui
    bzrlib.ui.ui_factory = bzrlib.ui.make_ui_for_terminal(
        sys.stdin, sys.stdout, sys.stderr)

I think this really ought to go in Commandant. Anyway, just thought
I'd mention it in case doing this would improve the user experience.

[9]

=== added file 'debian/pycompat'
=== added file 'debian/watch'

I'm not a packaging expert and so I don't really understand what
problem the addition of these two files solves. Would you mind
explaining, please?

[10]

Thanks for merging in jelmer's build-deb branch. I didn't realize
there were outstanding merge proposals because Launchpad doesn't
tell me by default. I'll fix that now.

review: Needs Fixing
Revision history for this message
Robert Collins (lifeless) wrote :

>[9]
>
>=== added file 'debian/pycompat'
>=== added file 'debian/watch'
>
>I'm not a packaging expert and so I don't really understand what
>problem the addition of these two files solves. Would you mind
>explaining, please?

The pycompat file tells the python helpers how to behave; the watch file tells 'uupdate' and 'uscan' where to find newer releases.

Revision history for this message
John Ferlito (johnf-inodes) wrote :
Download full text (4.2 KiB)

Hi,

I've made some comments inline below. Also I'm going to do a bit more
work on these patches and then send separate merge requests for
separate branches to keep things a bit simpler.

On Wed, Oct 21, 2009 at 12:31:34AM -0000, Jamu Kakar wrote:
> [1]
>
> The tests haven't been updated to match the changes and, as a
> result, there are many failures. We'll need to fix that before the
> branch can be merged. You can run the tests with 'make check' to
> see what-all is breaking. I can help with this (though probably not
> until the end of this week, realistically).

Opps should have checked the tests. I'll sort that out.

> I see that you've use bzr pipeline and I'm guessing from the log
> (haven't looked at the individual pipes) that these changes came
> from jelmer's build-deb branch.

Most of them. I had to fix them up a bit as his was based on a much
older revision.

I'm using pipes for other reasons which aren't related :)

>
> [2]
>
> A minor issue is that the version number format has changed. What
> you've changed it to is close to what it was before the change to
> the current format. I think it makes sense to follow the PPA
> guidelines, so I'm in favour of the change, but some users will
> probably be unhappy about it. Is this change necessary for your use
> case?

I prefer my version :) I noticed later there was a bug to implement
version templates. I'll do some work on that instead and resubmit so
we can support both.

> [3]
>
> Also, there are some minor cosmetic issues:
>
> 1. Please use double-quotes instead of single-quotes.
>
> 2. Whole words are preferred to abbreviations. 'branch_wt', for
> example, would be better as 'branch_working_tree' or
> 'working_tree'.
>
> 3. There are some lines that are longer than 80 characters that need
> wrapping.

ok No problems.

>
>
> [4]
>
> +import shutil
>
> This import is unnecessary.

OK.

>
>
> [5]
>
> Something I'll need to double check is copyright assignment
> requirements, given that this is a Canonical project. Have you
> signed the contributor agreement?

I need to do that for some bzr patches as well. So I'll get it sorted
shortly.

> [6]
>
> + # TODO: This merge doesn't make any sense...
>
> I don't understand this comment. The merge does make sense, as far
> as I understand it...? Am I missing something?

That was one of jelmer's comments. I'll look into it a bit further.

>
> [7]
>
> + # Sometimes we might have a rules.autoppa and no rules file.
> + # We bzr mv .autoppa in place so as to keep perms right
> + self.working_tree.remove(path[:-len(".autoppa")])
> + self.working_tree.rename_one(path[start:end] + '.autoppa', path[start:end])
>
> I don't think this is correct. This will effectively cause the
> .autoppa file to "disappear" when/if the build branch is merged back
> into the source branch, which will likely break subsequent builds.

OK I'll check that out.

>
>
> [8]
>
> + cmd_builddeb().run([self.working_tree.basedir], ['-sa'], source=True)
>
> Yay for reuse! One thing to note is that the bzrlib.ui module isn't
> setup properly. I guess if you've been using this br...

Read more...

Unmerged revisions

40. By John Ferlito

make sure source is included in the .changes we generate

39. By John Ferlito

Improve description

38. By John Ferlito

* debian/control
* debian/rules
  + Install into /usr instead of /usr/local

37. By John Ferlito

[John Ferlito]
* debian/rules
  + Added ${misc:Depends}
  + Added version to debhelper
  + Bumped standards to 3.8.3
* Added debian/pycompat

36. By John Ferlito

Added debian/watch file.

35. By John Ferlito

Add python dependencies to debian/control

34. By John Ferlito

only commit changelog and remove files correctly

33. By John Ferlito

I branch from debian when using autoppa. So I do something like

    bzr mv rules rules.autoppa

So just before we bzr-builddeb we need to

    rm rules
    bzr mv rules.autoppa rules

to ensure we have no autoppa file in the diff and the permissions are
correct on the file.

32. By John Ferlito

Fix for new cmd_buildeb API

31. By Jelmer Vernooij

Manually merge in Jelmer's build-deb branch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2009-09-20 18:42:28 +0000
3+++ .bzrignore 2009-10-17 01:10:21 +0000
4@@ -3,3 +3,4 @@
5 apidocs
6 dist
7 MANIFEST
8+./pipes
9
10=== modified file 'README'
11--- README 2009-09-21 03:13:54 +0000
12+++ README 2009-10-17 01:10:21 +0000
13@@ -104,17 +104,17 @@
14 ---------------
15
16 AutoPPA automatically inserts a release version into package version
17-numbers. The conventions specified by Ubuntu's SRU [1] policy
18+numbers. The conventions specified by the PPA Build manual [1]
19 should be followed when generating version numbers. In the above
20 example, the smart-0.51-landscape12 would build packages with the
21 following versions:
22
23-0.51-landscape12.6.06
24-0.51-landscape12.6.10
25-0.51-landscape12.7.04
26-0.51-landscape12.7.10
27+0.51-landscape12~dapper
28+0.51-landscape12~edgy
29+0.51-landscape12~feisty
30+0.51-landscape12~gutsy
31
32-[1] https://wiki.ubuntu.com/MOTU/SRU
33+[1] https://help.launchpad.net/Packaging/PPA/BuildingASourcePackage#versioning
34
35
36 Special file processing
37
38=== modified file 'autoppa/target.py'
39--- autoppa/target.py 2009-09-21 01:35:24 +0000
40+++ autoppa/target.py 2009-10-17 01:10:21 +0000
41@@ -1,6 +1,7 @@
42 # Copyright (C) 2007-2009 Canonical
43 #
44 # Written by Jamshed Kakar <jkakar@kakar.ca>
45+# Jelmer Vernooij <jelmer@ubuntu.com>
46 #
47 # This file is part of AutoPPA.
48 #
49@@ -20,9 +21,14 @@
50 from datetime import datetime
51 import tempfile
52 import os
53+import shutil
54
55 import pexpect
56
57+from bzrlib import osutils
58+from bzrlib.branch import Branch
59+from bzrlib.plugins.builddeb.cmds import cmd_builddeb
60+
61 from autoppa.errors import ChangelogError, EditorError
62 from autoppa.file import ReleaseSpecificInclude, VersionReplacement
63 from autoppa.path import match_path_except, match_path_if
64@@ -73,6 +79,7 @@
65 self.system = system
66 self.version_replacement = True
67 self._prepared_files = set()
68+ self._branch = None
69
70 def _log_info(self, message):
71 """Write C{message} the log, if one is present."""
72@@ -99,6 +106,8 @@
73 editor = os.environ["VISUAL"]
74 elif "EDITOR" in os.environ:
75 editor = os.environ["EDITOR"]
76+ elif os.path.exists("/usr/bin/sensible-editor"):
77+ editor = "/usr/bin/sensible-editor"
78 else:
79 raise EditorError("The VISUAL or EDITOR environment variable must "
80 "be set to prepare the changelog.")
81@@ -152,15 +161,18 @@
82 def prepare_working_tree(self):
83 """Prepare a working tree for the new release."""
84 self._log_info("== Preparing working tree for %s ==" % self.name)
85- self.expect.run("mkdir -p %s" % self.repository, logfile=self.log_file)
86- self.working_tree = "%s/%s" % (self.repository,
87- self._get_working_tree())
88- self.expect.run("bzr branch %s %s" % (self.branch, self.working_tree),
89- logfile=self.log_file, timeout=None)
90+ tree_path = os.path.join(self.repository, self._get_working_tree())
91+ to_dir = self._get_branch().bzrdir.sprout(tree_path)
92+ self.working_tree = to_dir.open_workingtree()
93
94 def _get_working_tree(self):
95 return "%s_%s" % (self.name, self.version)
96
97+ def _get_branch(self):
98+ if self._branch is None:
99+ self._branch = Branch.open(self.branch)
100+ return self._branch
101+
102 def prepare_custom_files(self, release, datetime_factory=None):
103 """Prepare the release-specific files for the new release.
104
105@@ -196,26 +208,35 @@
106
107 def _prepare_custom_autoppa_files(self, release):
108 include = ReleaseSpecificInclude(release)
109- for path in match_path_if(self.working_tree, ".*\.autoppa"):
110- start = len(self.working_tree)+1
111+ for path in match_path_if(self.working_tree.basedir, ".*\.autoppa"):
112+ start = len(self.working_tree.basedir)+1
113 end = -(len(".autoppa"))
114 self._prepared_files.add(path[start:end])
115+
116+ # Read in the template
117+ file = open(path, "r")
118+ try:
119+ lines = [line for line in file]
120+ finally:
121+ file.close()
122+
123+ # Sometimes we might have a rules.autoppa and no rules file.
124+ # We bzr mv .autoppa in place so as to keep perms right
125+ self.working_tree.remove(path[:-len(".autoppa")])
126+ self.working_tree.rename_one(path[start:end] + '.autoppa', path[start:end])
127+
128 file = open(path[:-len(".autoppa")], "w")
129 try:
130- template = open(path, "r")
131- try:
132- for i, line in enumerate(template):
133- line = include.process(line, path, i+1)
134- if line is not None:
135- file.write(line)
136- finally:
137- template.close()
138+ for i, line in enumerate(lines):
139+ line = include.process(line, path, i+1)
140+ if line is not None:
141+ file.write(line)
142 finally:
143 file.close()
144
145 def _prepare_custom_autoppa_version(self, release):
146 version = VersionReplacement(self._get_version(release))
147- for path in match_path_except(self.working_tree, ".*\.autoppa"):
148+ for path in match_path_except(self.working_tree.basedir, ".*\.autoppa"):
149 start = len(self.working_tree)+1
150 self._prepared_files.add(path[start:])
151 file = open(path, "r")
152@@ -232,20 +253,13 @@
153 finally:
154 file.close()
155
156- def _get_release_number(self, release_name):
157- numbers = {"dapper": "6.06", "edgy": "6.10", "feisty": "7.04",
158- "gutsy": "7.10", "hardy": "8.04", "intrepid": "8.10",
159- "jaunty": "9.04", "karmic": "9.10"}
160- return numbers[release_name]
161-
162 def _get_version(self, release):
163 parts = self.version.split("-", 1)
164- return "%s-%s.%s" % (parts[0], parts[1],
165- self._get_release_number(release))
166+ return "%s-%s~%s" % (parts[0], parts[1], release)
167
168 def _prepare_custom_changelog(self, release, datetime_factory):
169 try:
170- path = os.path.join(self.working_tree, "debian/changelog")
171+ path = os.path.join(self.working_tree.basedir, "debian/changelog")
172 file = open(path, "r")
173 try:
174 old_changelog = file.read()
175@@ -279,13 +293,8 @@
176 """Prepare signed source files that can be uploaded to a PPA."""
177 self._log_info("== Preparing signed sources for %s on %s =="
178 % (self.name, release))
179- working_directory = os.getcwd()
180- os.chdir(self.working_tree)
181- try:
182- self.expect.run("debuild --no-tgz-check -S", logfile=self.log_file,
183- timeout=None)
184- finally:
185- os.chdir(working_directory)
186+ self._log_info(self.working_tree.basedir)
187+ cmd_builddeb().run([self.working_tree.basedir], ['-sa'], source=True)
188
189 def commit_changes(self, release):
190 """Commit changes made to the working tree for C{release}."""
191@@ -294,19 +303,15 @@
192 % (self.name, release))
193 message = "Updated files for %s_%s." % (self.name,
194 self._get_version(release))
195- working_directory = os.getcwd()
196- os.chdir(self.working_tree)
197- try:
198- self.expect.run('bzr commit -m "%s"' % message,
199- logfile=self.log_file, timeout=None)
200- finally:
201- os.chdir(working_directory)
202+ # We only want the changlog commited
203+ self.working_tree.revert(self._prepared_files)
204+ self.working_tree.commit(message=message)
205
206 def upload_signed_sources(self, release):
207 """Upload signed sources to PPA for C{release}."""
208 self._log_info("== Uploading signed sources for %s on %s =="
209 % (self.name, release))
210- path = "/".join(self.working_tree.split("/")[:-1])
211+ path = "/".join(self.working_tree.basedir.split("/")[:-1])
212 filename = "%s_%s_source.changes" % (self.name,
213 self._get_version(release))
214
215@@ -319,61 +324,43 @@
216 finally:
217 os.chdir(working_directory)
218
219- def merge_changes(self, filename=None):
220+ def merge_changes(self):
221 """Merge changes from the working tree back into the source branch.
222
223 @param filename: Optionally, the temporary file the merge
224 commit message is written to.
225 """
226 self._log_info("== Merging changes for %s ==" % self.name)
227- if not filename:
228- filename = tempfile.mktemp()
229 changelog = """\
230 Merged %s [a=autoppa].
231
232 %s
233 """ % (self._get_working_tree(), self.changelog)
234- file = open(filename, "w")
235- try:
236- file.write(changelog)
237- finally:
238- file.close()
239-
240- working_directory = os.getcwd()
241- os.chdir(self.branch)
242- try:
243- self.expect.run("bzr merge %s" % self.working_tree,
244- logfile=self.log_file, timeout=None)
245- for path in self._prepared_files:
246- self.expect.run("bzr revert %s" % path)
247- self.expect.run("bzr commit -F %s" % filename,
248- logfile=self.log_file, timeout=None)
249- finally:
250- os.chdir(working_directory)
251+ # TODO: This merge doesn't make any sense...
252+ branch_wt = self._get_branch().bzrdir.open_workingtree()
253+ branch_wt.add_pending_merge(self.working_tree.last_revision())
254+ branch_wt.commit(message=changelog, specific_files=[],
255+ allow_pointless=True)
256
257 def tag_changes(self):
258 """Tag the source branch revision with the merged changes."""
259 self._log_info("== Tagging changes for %s ==" % self.name)
260- working_directory = os.getcwd()
261- os.chdir(self.branch)
262- try:
263- self.expect.run("bzr tag %s" % self.version,
264- logfile=self.log_file, timeout=None)
265- finally:
266- os.chdir(working_directory)
267+ self._get_branch().tags.set_tag(self.version, self._get_branch().last_revision())
268
269 def cleanup(self):
270 """Cleanup signed sources and the release branch."""
271 self._log_info("== Cleaning up signed sources and build branch "
272 "for %s ==" % self.name)
273- self.expect.run("rm -rf %s" % self.working_tree,
274- logfile=self.log_file, timeout=None)
275+ osutils.rmtree(self.working_tree.basedir)
276
277 for release in self.releases:
278 version = self._get_version(release)
279- for end in [".dsc", ".tar.gz",
280+ for end in [".dsc", ".tar.gz", ".diff.gz",
281 "_source.build", "_source.changes", "_source.upload"]:
282 filename = "%s_%s%s" % (self.name, version, end)
283 path = os.path.join(self.repository, filename)
284- self.expect.run("rm '%s'" % path,
285- logfile=self.log_file, timeout=None)
286+ try:
287+ os.remove(path)
288+ except OSError:
289+ pass
290+
291
292=== modified file 'debian/changelog'
293--- debian/changelog 2009-09-20 18:21:25 +0000
294+++ debian/changelog 2009-10-17 01:10:21 +0000
295@@ -1,3 +1,19 @@
296+autoppa (0.0.6-2) karmic; urgency=low
297+
298+ [John Ferlito]
299+ * Added debian/watch file.
300+ * debian/control
301+ + Added ${misc:Depends}
302+ + Added version to debhelper
303+ + Bumped standards to 3.8.3
304+ + Improve description
305+ * Added debian/pycompat
306+ * debian/rules
307+ + Install into /usr instead of /usr/local
308+
309+
310+ -- Jamshed Kakar <jkakar@kakar.ca> Mon, 05 Oct 2009 00:40:50 +1100
311+
312 autoppa (0.0.6-1~autoppa1.9.10) karmic; urgency=low
313
314 * A new tool 'autoppa-switch' allows for easy ad hoc switching of
315
316=== modified file 'debian/control'
317--- debian/control 2009-09-20 18:21:58 +0000
318+++ debian/control 2009-10-17 01:10:21 +0000
319@@ -2,15 +2,17 @@
320 Section: universe/devel
321 Priority: optional
322 Maintainer: Jamshed Kakar <jamshed.kakar@canonical.com>
323-Build-Depends: debhelper, python-central, lsb-release
324+Build-Depends: debhelper (>= 5), python-central, lsb-release
325 Standards-Version: 3.7.2
326 XS-Python-Version: current
327
328 Package: autoppa
329 Architecture: any
330-Depends: ${python:Depends}, ${shlibs:Depends}
331+Depends: ${python:Depends}, ${shlibs:Depends}, python-pexpect, ${misc:Depends}, python-commandant, bzr-builddeb
332 Provides: ${python:Provides}
333 XB-Python-Version: ${python:Versions}
334-Description: A tool that automates generating and uploading signed
335- source files to Launchpad's PPA service for projects stored in Bazaar
336- branches.
337+Description: A tool to automate PPA uploading for multiple releases.
338+ Automates generating and uploading signed source files to Launchpad's PPA
339+ service for projects stored in Bazaar branches. Supports automatically making
340+ small changes for different releases. eg python-support vs python-central for
341+ dapper vs intrepid.
342
343=== modified file 'debian/control.autoppa'
344--- debian/control.autoppa 2009-09-20 17:28:46 +0000
345+++ debian/control.autoppa 2009-10-17 01:10:21 +0000
346@@ -2,16 +2,18 @@
347 Section: universe/devel
348 Priority: optional
349 Maintainer: Jamu Kakar <jkakar@canonical.com>
350-AUTOPPA_INCLUDE(dapper):Build-Depends: debhelper, python-support, lsb-release
351-AUTOPPA_INCLUDE(hardy,intrepid,jaunty,karmic):Build-Depends: debhelper, python-central, lsb-release
352+AUTOPPA_INCLUDE(dapper):Build-Depends: debhelper (>= 5), python-support, lsb-release
353+AUTOPPA_INCLUDE(hardy,intrepid,jaunty,karmic):Build-Depends: debhelper (>= 5), python-central, lsb-release
354 Standards-Version: 3.7.2
355 XS-Python-Version: current
356
357 Package: autoppa
358 Architecture: any
359-Depends: ${python:Depends}, ${shlibs:Depends}, python-pexpect
360+Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, python-pexpect, python-commandant, bzr-builddeb
361 Provides: ${python:Provides}
362 XB-Python-Version: ${python:Versions}
363-Description: A tool that automates generating and uploading signed
364- source files to Launchpad's PPA service for projects stored in Bazaar
365- branches.
366+Description: A tool to automate PPA uploading for multiple releases.
367+ Automates generating and uploading signed source files to Launchpad's PPA
368+ service for projects stored in Bazaar branches. Supports automatically making
369+ small changes for different releases. eg python-support vs python-central for
370+ dapper vs intrepid.
371
372=== added file 'debian/pycompat'
373--- debian/pycompat 1970-01-01 00:00:00 +0000
374+++ debian/pycompat 2009-10-17 01:10:21 +0000
375@@ -0,0 +1,1 @@
376+2
377
378=== modified file 'debian/rules'
379--- debian/rules 2007-09-27 22:59:02 +0000
380+++ debian/rules 2009-10-17 01:10:21 +0000
381@@ -25,7 +25,7 @@
382 dh_testdir
383 dh_testroot
384 dh_clean -k
385- python setup.py install --root $(root_dir)
386+ python setup.py install --root $(root_dir) --install-layout=deb
387
388 binary-indep: build install
389
390
391=== added file 'debian/watch'
392--- debian/watch 1970-01-01 00:00:00 +0000
393+++ debian/watch 2009-10-17 01:10:21 +0000
394@@ -0,0 +1,2 @@
395+version=3
396+https://launchpad.net/autoppa/+download http://launchpad.net/autoppa/.*/AutoPPA-(.+).tar.bz2

Subscribers

People subscribed via source and target branches

to all changes: