Merge lp:~barry/bzr/609186-shortcuts into lp:bzr

Proposed by Barry Warsaw
Status: Merged
Merged at revision: 5486
Proposed branch: lp:~barry/bzr/609186-shortcuts
Merge into: lp:bzr
Diff against target: 374 lines (+276/-9)
5 files modified
NEWS (+7/-0)
bzrlib/plugins/launchpad/__init__.py (+9/-0)
bzrlib/plugins/launchpad/lp_directory.py (+47/-1)
bzrlib/plugins/launchpad/test_lp_directory.py (+178/-8)
doc/en/tutorials/using_bazaar_with_launchpad.txt (+35/-0)
To merge this branch: bzr merge lp:~barry/bzr/609186-shortcuts
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Martin Pool Needs Fixing
John A Meinel Approve
Review via email: mp+37787@code.launchpad.net

Description of the change

Add ubuntu: and debianlp: shortcuts.

To post a comment you must log in.
Revision history for this message
John A Meinel (jameinel) wrote :

some comments, I didn't look closely:

1) Isn't 'n' already known? (natty). I realize you can't push to it, but might as well have it for future.
2) I thought having the short forms was quite useful. "u:foo" is very nice and succinct. Any way we could (potentially via configuration) keep that? The whole point of having "lp:bzr" is because how much you have to type really does matter. lp:ubuntu/maverick/bzr is a whole lot wordier than u:bzr or u:m/bzr

Revision history for this message
Martin Pool (mbp) wrote :

Having the names hardcoded into bzr is a bit ugly (though it may be
the best tradeoff.)

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On Wed, 2010-10-06 at 20:59 +0000, John A Meinel wrote:
> some comments, I didn't look closely:
>
> 1) Isn't 'n' already known? (natty). I realize you can't push to it, but might as well have it for future.
Would it perhaps be possible to have a set of shortcuts available but
not limit the possible names in general? I can imagine a dictionary like
this:

k: karmic,
l: lucid,
m: maverick

That way it will still be possible to check out ubuntu:natty/foo when
natty is opened and you're using an older version of bzr, you just won't
be able to use ubuntu:n/foo. It also means we don't have to get the list
of hardcoded names in bzr completely right.

> 2) I thought having the short forms was quite useful. "u:foo" is very
> nice and succinct. Any way we could (potentially via configuration)
> keep that? The whole point of having "lp:bzr" is because how much you
> have to type really does matter. lp:ubuntu/maverick/bzr is a whole lot
> wordier than u:bzr or u:m/bzr
I think "ubuntu:foo" is much clearer than "u:foo" or, for that matter,
"lp:ubuntu/maverick/foo" while not being that much more effort to type.

Cheers,

Jelmer

Revision history for this message
Vincent Ladeuil (vila) wrote :

>>>>> Jelmer Vernooij <email address hidden> writes:

    > On Wed, 2010-10-06 at 20:59 +0000, John A Meinel wrote:
    >> some comments, I didn't look closely:
    >>
    >> 1) Isn't 'n' already known? (natty). I realize you can't push to it, but might as well have it for future.
    > Would it perhaps be possible to have a set of shortcuts available but
    > not limit the possible names in general? I can imagine a dictionary like
    > this:

    > k: karmic,
    > l: lucid,
    > m: maverick

    > That way it will still be possible to check out ubuntu:natty/foo when
    > natty is opened and you're using an older version of bzr, you just won't
    > be able to use ubuntu:n/foo. It also means we don't have to get the list
    > of hardcoded names in bzr completely right.

+1

Also, how would this interact with drives on windows ? Should we use two
letters shortcuts instead ?

ka: karmic,
lu: lucid,

etc

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On Thu, 2010-10-07 at 09:00 -0500, John Arbash Meinel wrote:
> >> 2) I thought having the short forms was quite useful. "u:foo" is very
> >> nice and succinct. Any way we could (potentially via configuration)
> >> keep that? The whole point of having "lp:bzr" is because how much you
> >> have to type really does matter. lp:ubuntu/maverick/bzr is a whole lot
> >> wordier than u:bzr or u:m/bzr
> > I think "ubuntu:foo" is much clearer than "u:foo" or, for that matter,
> > "lp:ubuntu/maverick/foo" while not being that much more effort to type.
> Well, we don't call it "launchpad:" for a reason. We've had several
> people ask us to support "ssh:" rather than "bzr+ssh:" because it is (at
> least mentally) an overhead that seems redundant.

> I would like to see a config that would allow the short form (disabled
> by default if you prefer).

> I completely agree that "ubuntu:foo" is *clearer*, but the "not much
> more effort" is actually where I disagree. (In the absolute sense, yes,
> in the "hey this tool just does what I want without a lot of effort"
> sense, no)
I agree there's a tradeoff between readability and effort there. lp: is
an acceptable balance imo; I think having l: would be a step too far.
"bzr l l:bzr" might be short, it's also ambiguous and unreadable (does
it mean "bzr ls linaro:bzr"¸ "bzr log launchpad:bzr", ?)

I would favor a conf option to support ta short form (perhaps just a
generic mechanism alias mechanism for locations?).

Cheers,

Jelmer

Revision history for this message
John A Meinel (jameinel) wrote :

1) I think the code would be ok to land as is. We can always improve it more later.
2) To get the short form, I think you would have to always register it, and then at runtime you could see "oh, I've been disabled, fall back to the regular methods".
3) 79 + path_parts = result.path.split('/')
80 + series = distro_series.get(path_parts[0])
81 + # If there's a series, then the project name is the second part of
82 + # the path. Otherwise, it's the latest series as defined by
83 + # Launchpad.
84 + if series is None:
85 + lp_url_template = 'lp:%(distro)s/%(project)s'
86 + project = path_parts[0]
87 + else:
88 + lp_url_template = 'lp:%(distro)s/%(series)s/%(project)s'
89 + project = path_parts[1]

You throw away path parts you don't understand. For example:

  ubuntu:unknown_series/project

Why not just count the path parts instead? So you can do:

path_parts = result.path.split('/')
if len(path_parts) == 1:
 # just a project
 project = path_parts[0]
 series = None
 lp_url_template = "lp:%(distro)s/%(project)s
elif len(path_parts) == 2:
 series, project = path_parts
 lp_url_template = "lp:%(distro)s/%(series)s/%(project)s
 # [1]
else:
 # error, either 0 or >2 parts

I think the code was written this way, because you wanted to expand "m" =>
"maverick". However you could still do that at [1]. Specifically, just do:

series = _short_name_series.get(series, series)

So if the series is a known-registered value (like 'n') then it would expand to
the full value. Otherwise it falls back to the existing value (for natty, for
"o", etc.)

review: Approve
Revision history for this message
Barry Warsaw (barry) wrote :

On Oct 06, 2010, at 08:59 PM, John A Meinel wrote:

>1) Isn't 'n' already known? (natty). I realize you can't push to it,
>but might as well have it for future.

Good point. Added.

>2) I thought having the short forms was quite useful. "u:foo" is very nice
>and succinct. Any way we could (potentially via configuration) keep that? The
>whole point of having "lp:bzr" is because how much you have to type really
>does matter. lp:ubuntu/maverick/bzr is a whole lot wordier than u:bzr or
>u:m/bzr

A couple of thoughts (I agree, I like the shortcuts too :).

We could support shortcut for the distroseries name independently of the
distro name, thus giving us urls like:

    ubuntu:m/bzr
    ubuntu:n/bzr
    debianlp:l/foo
    debianlp:s/foo

I think it's pretty common to refer to Ubuntu releases by their first letter;
maybe the same is not common for Debian. Anyway 'ubuntu:n/bzr' seems okay to
me, though I still would not oppose adding u: and d: shortcuts.

Either distro or distroseries shortcuts would be easy to add (using the
hard-coded mappings). How do we decide whether to add them back or not?

Revision history for this message
Barry Warsaw (barry) wrote :

On Oct 07, 2010, at 04:43 PM, John A Meinel wrote:

>1) I think the code would be ok to land as is. We can always improve it more
>later.

Sounds good.

>2) To get the short form, I think you would have to always register it, and
>then at runtime you could see "oh, I've been disabled, fall back to the
>regular methods".

True for the scheme part, but I think we'd have to handle shortcuts in the
distroseries a little differently.

My preference would be to include Ubuntu distroseries shortcuts out of the box
- I don't think we need to disable them or add a config to handle this. Let's
not include shortcuts for Debian distroseries; these are much more rare and I
don't think Debian has quite the same history of abbreviating their releases
to just the first character (i.e. they don't use an alphabetical naming
scheme).

I think I'll add back the Ubuntu distroseries abbreviations, and see if there
is a huge outrage about them. ;)

As for shortcuts in the scheme (i.e. u: and d:), it might be better to write a
generic url rewriting plugin. Or maybe bzr-bookmarks is good enough?

>3) 79 + path_parts = result.path.split('/')
>80 + series = distro_series.get(path_parts[0])
>81 + # If there's a series, then the project name is the second part of
>82 + # the path. Otherwise, it's the latest series as defined by
>83 + # Launchpad.
>84 + if series is None:
>85 + lp_url_template = 'lp:%(distro)s/%(project)s'
>86 + project = path_parts[0]
>87 + else:
>88 + lp_url_template = 'lp:%(distro)s/%(series)s/%(project)s'
>89 + project = path_parts[1]
>
>You throw away path parts you don't understand. For example:
>
> ubuntu:unknown_series/project
>
>Why not just count the path parts instead? So you can do:
>
>path_parts = result.path.split('/')
>if len(path_parts) == 1:
> # just a project
> project = path_parts[0]
> series = None
> lp_url_template = "lp:%(distro)s/%(project)s
>elif len(path_parts) == 2:
> series, project = path_parts
> lp_url_template = "lp:%(distro)s/%(series)s/%(project)s
> # [1]
>else:
> # error, either 0 or >2 parts
>
>I think the code was written this way, because you wanted to expand "m" =>
>"maverick". However you could still do that at [1]. Specifically, just do:
>
>series = _short_name_series.get(series, series)
>
>So if the series is a known-registered value (like 'n') then it would expand to
>the full value. Otherwise it falls back to the existing value (for natty, for
>"o", etc.)

Good idea. Done.

Pushing a new version soon. BTW, I fixed some pyflakes complaints while I was
at it.

Revision history for this message
Barry Warsaw (barry) wrote :

On Oct 07, 2010, at 02:49 PM, Jelmer Vernooij wrote:

>> I would like to see a config that would allow the short form (disabled
>> by default if you prefer).
>
>> I completely agree that "ubuntu:foo" is *clearer*, but the "not much
>> more effort" is actually where I disagree. (In the absolute sense, yes,
>> in the "hey this tool just does what I want without a lot of effort"
>> sense, no)
>I agree there's a tradeoff between readability and effort there. lp: is
>an acceptable balance imo; I think having l: would be a step too far.
>"bzr l l:bzr" might be short, it's also ambiguous and unreadable (does
>it mean "bzr ls linaro:bzr"¸ "bzr log launchpad:bzr", ?)
>
>I would favor a conf option to support ta short form (perhaps just a
>generic mechanism alias mechanism for locations?).

After thinking about this more, requiring ubuntu: and not having a distro
shortcut seems fine. Adding back the Ubuntu (but not Debian!) distroseries
shortcuts seem like a win - Ubuntu has a tradition of referring to releases by
their first letter. Thus we support:

ubuntu:foo
ubuntu:maverick/foo
ubuntu:m/foo

I think this is as far as I want to go with the branch. I'd favor a generic
alias mechanism for locations, though that's out of scope for this particular
branch. There is also bzr-bookmarks which might fit the bill. My inclination
is to go with this compromise and wait for feedback from users.

Revision history for this message
Barry Warsaw (barry) wrote :

On Oct 07, 2010, at 09:52 AM, Jelmer Vernooij wrote:

>On Wed, 2010-10-06 at 20:59 +0000, John A Meinel wrote:
>> some comments, I didn't look closely:
>>
>> 1) Isn't 'n' already known? (natty). I realize you can't push to it, but might as well have it for future.
>Would it perhaps be possible to have a set of shortcuts available but
>not limit the possible names in general? I can imagine a dictionary like
>this:
>
>k: karmic,
>l: lucid,
>m: maverick
>
>That way it will still be possible to check out ubuntu:natty/foo when
>natty is opened and you're using an older version of bzr, you just won't
>be able to use ubuntu:n/foo. It also means we don't have to get the list
>of hardcoded names in bzr completely right.

With other changes suggested by JAM, this is what the branch will do now.
When Obscene Otter is opened, you'll be able to branch ubuntu:obscene/foo but
not ubuntu:o/foo (at least until a Bazaar update is issued). This seems like
a decent compromise.

Note that I did consider downloading the distroseries from Launchpad, but
since they change very infrequently, I didn't want to pay the penalty to do
this every time. We could of course cache this, but then how often do we
update the cache? Given the change above, a new distroseries is still
basically supported, just the shortcut is not. Seems good enough to me, for
now anyway.

Revision history for this message
Barry Warsaw (barry) wrote :

On Oct 07, 2010, at 11:24 AM, Vincent Ladeuil wrote:

>Also, how would this interact with drives on windows ? Should we use two
>letters shortcuts instead ?
>
>ka: karmic,
>lu: lucid,

Are you worried about interference with the scheme part? That will always be
ubuntu: or debianlp: so I don't think we have any possible collisions with the
distroseries name. It might be an argument against u: and d: but for now
we're not going to support that.

Revision history for this message
Martin Pool (mbp) wrote :

You should mention the short form in the documentation.

If the series are defined in here only for the sake of abbreviations, maybe you can delete the 'natty: natty' entries? Saying we know about certain abbreviations is cleaner for me than saying we know about all series. Probably that should be done on the server, but it's a bit harder to change that than to change bzr.

Just as a style point (and you don't have to change it now) I would have defined a helper method to do the check rather than copy&pasting

 def test_debian_default_distroseries_expansion(self):
322 + factory = self._make_factory(package='foo', distro='debian')
323 + self.assertEqual(
324 + 'http://bazaar.launchpad.net/~branch/debian/foo',
325 + self.directory._resolve('debianlp:foo', factory))

Instead something like

  self.checkExpansion('foo', 'debian', 'debianlp:foo', 'http://bazaar.launchpad.net/~branch/debian/foo')
325 + self.directory._resolve('debianlp:foo',

review: Needs Fixing
Revision history for this message
Barry Warsaw (barry) wrote :

On Oct 07, 2010, at 09:49 PM, Martin Pool wrote:

>Review: Needs Fixing
>You should mention the short form in the documentation.

Actually done, but in a following revision (which should be pushed now).

>If the series are defined in here only for the sake of abbreviations, maybe
>you can delete the 'natty: natty' entries? Saying we know about certain
>abbreviations is cleaner for me than saying we know about all series.
>Probably that should be done on the server, but it's a bit harder to change
>that than to change bzr.

Actually, we don't need any of the 'series: series' entries now, so I've
simplified the code. Pushed in r5467.

>Just as a style point (and you don't have to change it now) I would have
>defined a helper method to do the check rather than copy&pasting
>
> def test_debian_default_distroseries_expansion(self):
>322 + factory = self._make_factory(package='foo', distro='debian')
>323 + self.assertEqual(
>324 + 'http://bazaar.launchpad.net/~branch/debian/foo',
>325 + self.directory._resolve('debianlp:foo', factory))
>
>
>Instead something like
>
> self.checkExpansion('foo', 'debian', 'debianlp:foo', 'http://bazaar.launchpad.net/~branch/debian/foo')
>325 + self.directory._resolve('debianlp:foo',

Thanks. Not changed for now.

-Barry

Revision history for this message
Vincent Ladeuil (vila) wrote :

Very nice addition, I've added a helper and will land the result.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-10-07 12:45:51 +0000
3+++ NEWS 2010-10-07 22:03:45 +0000
4@@ -21,6 +21,13 @@
5 New Features
6 ************
7
8+* New shortcut url schemes ``ubuntu:`` and ``debianlp:`` access source
9+ branches on Launchpad. E.g. ``bzr branch ubuntu:foo`` gives you the source
10+ branch for project ``foo`` in the current distroseries for Ubuntu while
11+ ``bzr branch debianlp:lenny/foo`` gives you the source branch (on Launchpad)
12+ for project ``foo`` in Debian Lenny.
13+ (Barry Warsaw, #609186)
14+
15 * Add ``mainline`` revision specifier, which selects the revision that
16 merged a specified revision into the mainline. (Aaron Bentley)
17
18
19=== modified file 'bzrlib/plugins/launchpad/__init__.py'
20--- bzrlib/plugins/launchpad/__init__.py 2010-10-05 15:52:15 +0000
21+++ bzrlib/plugins/launchpad/__init__.py 2010-10-07 22:03:45 +0000
22@@ -371,6 +371,15 @@
23 directories.register_lazy('lp:', 'bzrlib.plugins.launchpad.lp_directory',
24 'LaunchpadDirectory',
25 'Launchpad-based directory service',)
26+ directories.register_lazy(
27+ 'debianlp:', 'bzrlib.plugins.launchpad.lp_directory',
28+ 'LaunchpadDirectory',
29+ 'debianlp: shortcut')
30+ directories.register_lazy(
31+ 'ubuntu:', 'bzrlib.plugins.launchpad.lp_directory',
32+ 'LaunchpadDirectory',
33+ 'ubuntu: shortcut')
34+
35 _register_directory()
36
37
38
39=== modified file 'bzrlib/plugins/launchpad/lp_directory.py'
40--- bzrlib/plugins/launchpad/lp_directory.py 2010-07-26 17:19:33 +0000
41+++ bzrlib/plugins/launchpad/lp_directory.py 2010-10-07 22:03:45 +0000
42@@ -40,6 +40,16 @@
43 register_urlparse_netloc_protocol('bzr+ssh')
44 register_urlparse_netloc_protocol('lp')
45
46+_ubuntu_series_shortcuts = {
47+ 'n': 'natty',
48+ 'm': 'maverick',
49+ 'l': 'lucid',
50+ 'k': 'karmic',
51+ 'j': 'jaunty',
52+ 'h': 'hardy',
53+ 'd': 'dapper',
54+ }
55+
56
57 class LaunchpadDirectory(object):
58
59@@ -62,8 +72,44 @@
60 _request_factory=ResolveLaunchpadPathRequest,
61 _lp_login=None):
62 """Resolve the base URL for this transport."""
63+ # Do ubuntu: and debianlp: expansions.
64+ result = urlsplit(url)
65+ if result.scheme in ('ubuntu', 'debianlp'):
66+ if result.scheme == 'ubuntu':
67+ distro = 'ubuntu'
68+ distro_series = _ubuntu_series_shortcuts
69+ elif result.scheme == 'debianlp':
70+ distro = 'debian'
71+ # No shortcuts for Debian distroseries.
72+ distro_series = {}
73+ else:
74+ raise AssertionError('scheme should be ubuntu: or debianlp:')
75+ # Split the path. It's either going to be 'project' or
76+ # 'series/project', but recognize that it may be a series we don't
77+ # know about.
78+ path_parts = result.path.split('/')
79+ if len(path_parts) == 1:
80+ # It's just a project name.
81+ lp_url_template = 'lp:%(distro)s/%(project)s'
82+ project = path_parts[0]
83+ series = None
84+ elif len(path_parts) == 2:
85+ # It's a series and project.
86+ lp_url_template = 'lp:%(distro)s/%(series)s/%(project)s'
87+ series, project = path_parts
88+ else:
89+ # There are either 0 or > 2 path parts, neither of which is
90+ # supported for these schemes.
91+ raise errors.InvalidURL('Bad path: %s' % result.path)
92+ # Expand any series shortcuts, but keep unknown series.
93+ series = distro_series.get(series, series)
94+ # Hack the url and let the following do the final resolution.
95+ url = lp_url_template % dict(
96+ distro=distro,
97+ series=series,
98+ project=project)
99+ result = urlsplit(url)
100 service = LaunchpadService.for_url(url)
101- result = urlsplit(url)
102 if _lp_login is None:
103 _lp_login = get_lp_login()
104 path = result[2].strip('/')
105
106=== modified file 'bzrlib/plugins/launchpad/test_lp_directory.py'
107--- bzrlib/plugins/launchpad/test_lp_directory.py 2010-07-26 17:19:33 +0000
108+++ bzrlib/plugins/launchpad/test_lp_directory.py 2010-10-07 22:03:45 +0000
109@@ -37,10 +37,7 @@
110 from bzrlib.plugins.launchpad.lp_directory import (
111 LaunchpadDirectory)
112 from bzrlib.plugins.launchpad.account import get_lp_login, set_lp_login
113-from bzrlib.tests import (
114- http_server,
115- http_utils,
116- )
117+from bzrlib.tests import http_server
118
119
120 def load_tests(standard_tests, module, loader):
121@@ -219,8 +216,8 @@
122 'bzr+ssh://bazaar.launchpad.net/~username/apt/test']))
123 self.assertIs(None, get_lp_login())
124 directory = LaunchpadDirectory()
125- e = self.assertRaises(errors.InvalidURL,
126- directory._resolve, 'lp:~/apt/test', factory)
127+ self.assertRaises(errors.InvalidURL,
128+ directory._resolve, 'lp:~/apt/test', factory)
129
130
131 class DirectoryOpenBranchTests(TestCaseWithMemoryTransport):
132@@ -237,6 +234,8 @@
133 return '!unexpected look_up value!'
134
135 directories.remove('lp:')
136+ directories.remove('ubuntu:')
137+ directories.remove('debianlp:')
138 directories.register('lp:', FooService, 'Map lp URLs to local urls')
139 self.addCleanup(_register_directory)
140 self.addCleanup(directories.remove, 'lp:')
141@@ -259,11 +258,11 @@
142 def handle_one_request(self):
143 tcs = self.server.test_case_server
144 requestline = self.rfile.readline()
145- headers = self.MessageClass(self.rfile, 0)
146+ self.MessageClass(self.rfile, 0)
147 if requestline.startswith('POST'):
148 # The body should be a single line (or we don't know where it ends
149 # and we don't want to issue a blocking read)
150- body = self.rfile.readline()
151+ self.rfile.readline()
152
153 self.wfile.write(tcs.canned_response)
154
155@@ -356,3 +355,174 @@
156 # FIXME: we need to test with a real proxy, I can't find a way so simulate
157 # CONNECT without leaving one server hanging the test :-/ Since that maybe
158 # related to the leaking tests problems, I'll punt for now -- vila 20091030
159+
160+
161+class TestDebuntuExpansions(TestCaseInTempDir):
162+ """Test expansions for ubuntu: and debianlp: schemes."""
163+
164+ def setUp(self):
165+ tests.TestCase.setUp(self)
166+ self.directory = LaunchpadDirectory()
167+
168+ def _make_factory(self, package='foo', distro='ubuntu', series=None):
169+ if series is None:
170+ path = '%s/%s' % (distro, package)
171+ url_suffix = '~branch/%s/%s' % (distro, package)
172+ else:
173+ path = '%s/%s/%s' % (distro, series, package)
174+ url_suffix = '~branch/%s/%s/%s' % (distro, series, package)
175+ return FakeResolveFactory(
176+ self, path, dict(urls=[
177+ 'http://bazaar.launchpad.net/' + url_suffix]))
178+
179+ # Bogus distro.
180+
181+ def test_bogus_distro(self):
182+ self.assertRaises(errors.InvalidURL,
183+ self.directory._resolve, 'gentoo:foo')
184+
185+ def test_trick_bogus_distro_u(self):
186+ self.assertRaises(errors.InvalidURL,
187+ self.directory._resolve, 'utube:foo')
188+
189+ def test_trick_bogus_distro_d(self):
190+ self.assertRaises(errors.InvalidURL,
191+ self.directory._resolve, 'debuntu:foo')
192+
193+ def test_missing_ubuntu_distroseries_without_project(self):
194+ # Launchpad does not hold source packages for Intrepid. Missing or
195+ # bogus distroseries with no project name is treated like a project.
196+ factory = self._make_factory(package='intrepid')
197+ self.assertEqual(
198+ 'http://bazaar.launchpad.net/~branch/ubuntu/intrepid',
199+ self.directory._resolve('ubuntu:intrepid', factory))
200+
201+ def test_missing_ubuntu_distroseries_with_project(self):
202+ # Launchpad does not hold source packages for Intrepid. Missing or
203+ # bogus distroseries with a project name is treated like an unknown
204+ # series (i.e. we keep it verbatim).
205+ factory = self._make_factory(series='intrepid')
206+ self.assertEqual(
207+ 'http://bazaar.launchpad.net/~branch/ubuntu/intrepid/foo',
208+ self.directory._resolve('ubuntu:intrepid/foo', factory))
209+
210+ def test_missing_debian_distroseries(self):
211+ # Launchpad does not hold source packages for unstable. Missing or
212+ # bogus distroseries is treated like a project.
213+ factory = self._make_factory(package='sid', distro='debian')
214+ self.assertEqual(
215+ 'http://bazaar.launchpad.net/~branch/debian/sid',
216+ self.directory._resolve('debianlp:sid', factory))
217+
218+ # Ubuntu Default distro series.
219+
220+ def test_ubuntu_default_distroseries_expansion(self):
221+ factory = self._make_factory(package='foo')
222+ self.assertEqual('http://bazaar.launchpad.net/~branch/ubuntu/foo',
223+ self.directory._resolve('ubuntu:foo', factory)),
224+
225+ def test_ubuntu_natty_distroseries_expansion(self):
226+ factory = self._make_factory(package='foo', series='natty')
227+ self.assertEqual(
228+ 'http://bazaar.launchpad.net/~branch/ubuntu/natty/foo',
229+ self.directory._resolve('ubuntu:natty/foo', factory)),
230+
231+ def test_ubuntu_n_distroseries_expansion(self):
232+ factory = self._make_factory(package='foo', series='natty')
233+ self.assertEqual(
234+ 'http://bazaar.launchpad.net/~branch/ubuntu/natty/foo',
235+ self.directory._resolve('ubuntu:n/foo', factory)),
236+
237+ def test_ubuntu_maverick_distroseries_expansion(self):
238+ factory = self._make_factory(package='foo', series='maverick')
239+ self.assertEqual(
240+ 'http://bazaar.launchpad.net/~branch/ubuntu/maverick/foo',
241+ self.directory._resolve('ubuntu:maverick/foo', factory)),
242+
243+ def test_ubuntu_m_distroseries_expansion(self):
244+ factory = self._make_factory(package='foo', series='maverick')
245+ self.assertEqual(
246+ 'http://bazaar.launchpad.net/~branch/ubuntu/maverick/foo',
247+ self.directory._resolve('ubuntu:m/foo', factory)),
248+
249+ def test_ubuntu_lucid_distroseries_expansion(self):
250+ factory = self._make_factory(package='foo', series='lucid')
251+ self.assertEqual(
252+ 'http://bazaar.launchpad.net/~branch/ubuntu/lucid/foo',
253+ self.directory._resolve('ubuntu:lucid/foo', factory)),
254+
255+ def test_ubuntu_l_distroseries_expansion(self):
256+ factory = self._make_factory(package='foo', series='lucid')
257+ self.assertEqual(
258+ 'http://bazaar.launchpad.net/~branch/ubuntu/lucid/foo',
259+ self.directory._resolve('ubuntu:l/foo', factory)),
260+
261+ def test_ubuntu_karmic_distroseries_expansion(self):
262+ factory = self._make_factory(package='foo', series='karmic')
263+ self.assertEqual(
264+ 'http://bazaar.launchpad.net/~branch/ubuntu/karmic/foo',
265+ self.directory._resolve('ubuntu:karmic/foo', factory)),
266+
267+ def test_ubuntu_k_distroseries_expansion(self):
268+ factory = self._make_factory(package='foo', series='karmic')
269+ self.assertEqual(
270+ 'http://bazaar.launchpad.net/~branch/ubuntu/karmic/foo',
271+ self.directory._resolve('ubuntu:k/foo', factory)),
272+
273+ def test_ubuntu_jaunty_distroseries_expansion(self):
274+ factory = self._make_factory(package='foo', series='jaunty')
275+ self.assertEqual(
276+ 'http://bazaar.launchpad.net/~branch/ubuntu/jaunty/foo',
277+ self.directory._resolve('ubuntu:jaunty/foo', factory)),
278+
279+ def test_ubuntu_j_distroseries_expansion(self):
280+ factory = self._make_factory(package='foo', series='jaunty')
281+ self.assertEqual(
282+ 'http://bazaar.launchpad.net/~branch/ubuntu/jaunty/foo',
283+ self.directory._resolve('ubuntu:j/foo', factory)),
284+
285+ def test_ubuntu_hardy_distroseries_expansion(self):
286+ factory = self._make_factory(package='foo', series='hardy')
287+ self.assertEqual(
288+ 'http://bazaar.launchpad.net/~branch/ubuntu/hardy/foo',
289+ self.directory._resolve('ubuntu:hardy/foo', factory)),
290+
291+ def test_ubuntu_h_distroseries_expansion(self):
292+ factory = self._make_factory(package='foo', series='hardy')
293+ self.assertEqual(
294+ 'http://bazaar.launchpad.net/~branch/ubuntu/hardy/foo',
295+ self.directory._resolve('ubuntu:h/foo', factory)),
296+
297+ def test_ubuntu_dapper_distroseries_expansion(self):
298+ factory = self._make_factory(package='foo', series='dapper')
299+ self.assertEqual(
300+ 'http://bazaar.launchpad.net/~branch/ubuntu/dapper/foo',
301+ self.directory._resolve('ubuntu:dapper/foo', factory)),
302+
303+ def test_ubuntu_d_distroseries_expansion(self):
304+ factory = self._make_factory(package='foo', series='dapper')
305+ self.assertEqual(
306+ 'http://bazaar.launchpad.net/~branch/ubuntu/dapper/foo',
307+ self.directory._resolve('ubuntu:d/foo', factory)),
308+
309+ # Debian default distro series.
310+
311+ def test_debian_default_distroseries_expansion(self):
312+ factory = self._make_factory(package='foo', distro='debian')
313+ self.assertEqual(
314+ 'http://bazaar.launchpad.net/~branch/debian/foo',
315+ self.directory._resolve('debianlp:foo', factory))
316+
317+ def test_debian_squeeze_distroseries_expansion(self):
318+ factory = self._make_factory(
319+ package='foo', distro='debian', series='squeeze')
320+ self.assertEqual(
321+ 'http://bazaar.launchpad.net/~branch/debian/squeeze/foo',
322+ self.directory._resolve('debianlp:squeeze/foo', factory)),
323+
324+ def test_debian_lenny_distroseries_expansion(self):
325+ factory = self._make_factory(
326+ package='foo', distro='debian', series='lenny')
327+ self.assertEqual(
328+ 'http://bazaar.launchpad.net/~branch/debian/lenny/foo',
329+ self.directory._resolve('debianlp:lenny/foo', factory)),
330
331=== modified file 'doc/en/tutorials/using_bazaar_with_launchpad.txt'
332--- doc/en/tutorials/using_bazaar_with_launchpad.txt 2010-08-13 19:08:57 +0000
333+++ doc/en/tutorials/using_bazaar_with_launchpad.txt 2010-10-07 22:03:45 +0000
334@@ -244,6 +244,41 @@
335 quality standards.
336
337
338+Package source branches
339+-----------------------
340+
341+When `maintaining packages for Ubuntu using Bazaar`_ you can easily access the
342+package's source branch on Launchpad. The package's source branch in the
343+current (default) series can be downloaded like this::
344+
345+ bzr branch ubuntu:package
346+
347+where *package* is the name of the Ubuntu package you want to access. To
348+download the package branch for a specific series in Ubuntu (e.g. Maverick or
349+Lucid), use this::
350+
351+ bzr branch ubuntu:maverick/package
352+
353+Ubuntu distroseries can also be abbreviated to just their first letter. For
354+example, the above could also be written::
355+
356+ bzr branch ubuntu:m/package
357+
358+You can also download the package source branch from Launchpad for several
359+Debian series. The default series can be downloaded like this::
360+
361+ bzr branch debianlp:package
362+
363+and a specific series can be downloaded like this::
364+
365+ bzr branch debianlp:lenny/package
366+
367+Note that the ``debianlp:`` scheme access the Debian source branch for a
368+package from Launchpad only.
369+
370+.. _`maintaining packages for Ubuntu using Bazaar`: https://wiki.ubuntu.com/DistributedDevelopment
371+
372+
373 Linking branches using Launchpad
374 ================================
375