Merge lp:~mwhudson/launchpad/no-hosted-area-one-codehosting-endpoint into lp:launchpad

Proposed by Michael Hudson-Doyle
Status: Merged
Approved by: Michael Hudson-Doyle
Approved revision: no longer in the source branch.
Merged at revision: 10828
Proposed branch: lp:~mwhudson/launchpad/no-hosted-area-one-codehosting-endpoint
Merge into: lp:launchpad
Prerequisite: lp:~mwhudson/launchpad/no-hosted-area-puller
Diff against target: 2294 lines (+436/-531)
28 files modified
bzrplugins/lpserve.py (+4/-4)
configs/development/launchpad-lazr.conf (+1/-2)
cronscripts/supermirror-pull.py (+1/-1)
lib/canonical/config/schema-lazr.conf (+7/-9)
lib/canonical/launchpad/interfaces/launchpad.py (+1/-3)
lib/canonical/launchpad/systemhomes.py (+6/-14)
lib/canonical/launchpad/xmlrpc/application.py (+4/-10)
lib/canonical/launchpad/xmlrpc/configure.zcml (+9/-22)
lib/lp/code/doc/xmlrpc-branch-filesystem.txt (+0/-31)
lib/lp/code/doc/xmlrpc-branch-puller.txt (+0/-31)
lib/lp/code/doc/xmlrpc-codehosting.txt (+32/-0)
lib/lp/code/interfaces/codehosting.py (+10/-23)
lib/lp/code/xmlrpc/codehosting.py (+58/-64)
lib/lp/code/xmlrpc/tests/test_codehosting.py (+174/-184)
lib/lp/codehosting/inmemory.py (+15/-29)
lib/lp/codehosting/puller/scheduler.py (+9/-9)
lib/lp/codehosting/puller/tests/test_scheduler.py (+7/-6)
lib/lp/codehosting/sftp.py (+2/-1)
lib/lp/codehosting/sshserver/daemon.py (+11/-11)
lib/lp/codehosting/tests/test_acceptance.py (+3/-2)
lib/lp/codehosting/tests/test_sftp.py (+3/-3)
lib/lp/codehosting/vfs/branchfs.py (+40/-36)
lib/lp/codehosting/vfs/branchfsclient.py (+17/-14)
lib/lp/codehosting/vfs/tests/test_branchfs.py (+18/-18)
lib/lp/codehosting/vfs/tests/test_branchfsclient.py (+1/-1)
lib/lp/codehosting/vfs/tests/test_filesystem.py (+1/-1)
lib/lp/codehosting/vfs/tests/test_transport.py (+1/-1)
scripts/update-stacked-on.py (+1/-1)
To merge this branch: bzr merge lp:~mwhudson/launchpad/no-hosted-area-one-codehosting-endpoint
Reviewer Review Type Date Requested Status
Tim Penhey (community) Approve
Review via email: mp+23730@code.launchpad.net

Description of the change

Hi yet again Tim,

This large and EXTREMELY BORING branch combines the two codehosting api endpoints we currently have -- IBranchPuller and IBranchFileSystem -- into one -- ICodehostingAPI -- so that the puller can call the branchChanged method that is currently on IBranchPuller.

Cheers,
mwh

PS: it's very boring.

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

The xmlrpc-codehosting.txt file has the heading "The BranchPuller application".

Perhaps we could rename the 'self.storage' to 'self.codehosting' in the
CodehostingTest, or 'self.codehosting_api' to be even move verbose.
M-% FTW

lib/lp/codehosting/sshserver/daemon.py
 - still mentions the authserver :-)

Apart from that, your were right, it is a boring branch, but good to go some renames.

review: Approve
Revision history for this message
Jonathan Lange (jml) wrote :

There is still an XML-RPC interface called IAuthServer. It's not a great name, but it's not a terrible name either.

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

It's not too terrible a name for the endpoint that implements authentication. It's a bit silly for all the other ones :-)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrplugins/lpserve.py'
--- bzrplugins/lpserve.py 2010-04-27 02:11:16 +0000
+++ bzrplugins/lpserve.py 2010-04-27 02:11:35 +0000
@@ -45,9 +45,9 @@
45 Option('mirror-directory',45 Option('mirror-directory',
46 help='serve branches from this directory. Defaults to '46 help='serve branches from this directory. Defaults to '
47 'config.codehosting.mirrored_branches_root.'),47 'config.codehosting.mirrored_branches_root.'),
48 Option('branchfs-endpoint',48 Option('codehosting-endpoint',
49 help='the url of the internal XML-RPC server. Defaults to '49 help='the url of the internal XML-RPC server. Defaults to '
50 'config.codehosting.branchfs_endpoint.',50 'config.codehosting.codehosting_endpoint.',
51 type=unicode),51 type=unicode),
52 ]52 ]
5353
@@ -86,7 +86,7 @@
86 ui.ui_factory = old_factory86 ui.ui_factory = old_factory
8787
88 def run(self, user_id, port=None, branch_directory=None,88 def run(self, user_id, port=None, branch_directory=None,
89 branchfs_endpoint_url=None, inet=False):89 codehosting_endpoint_url=None, inet=False):
90 from lp.codehosting.bzrutils import install_oops_handler90 from lp.codehosting.bzrutils import install_oops_handler
91 from lp.codehosting.vfs import get_lp_server, hooks91 from lp.codehosting.vfs import get_lp_server, hooks
92 install_oops_handler(user_id)92 install_oops_handler(user_id)
@@ -94,7 +94,7 @@
94 resource.setrlimit(resource.RLIMIT_AS, (four_gig, four_gig))94 resource.setrlimit(resource.RLIMIT_AS, (four_gig, four_gig))
95 seen_new_branch = hooks.SetProcTitleHook()95 seen_new_branch = hooks.SetProcTitleHook()
96 lp_server = get_lp_server(96 lp_server = get_lp_server(
97 int(user_id), branchfs_endpoint_url, branch_directory,97 int(user_id), codehosting_endpoint_url, branch_directory,
98 seen_new_branch.seen)98 seen_new_branch.seen)
99 lp_server.start_server()99 lp_server.start_server()
100100
101101
=== modified file 'configs/development/launchpad-lazr.conf'
--- configs/development/launchpad-lazr.conf 2010-04-27 02:11:16 +0000
+++ configs/development/launchpad-lazr.conf 2010-04-27 02:11:35 +0000
@@ -52,8 +52,7 @@
52[codehosting]52[codehosting]
53launch: True53launch: True
54authentication_endpoint: http://xmlrpc-private.launchpad.dev:8087/authserver54authentication_endpoint: http://xmlrpc-private.launchpad.dev:8087/authserver
55branchfs_endpoint: http://xmlrpc-private.launchpad.dev:8087/branchfilesystem55codehosting_endpoint: http://xmlrpc-private.launchpad.dev:8087/codehosting
56branch_puller_endpoint: http://xmlrpc-private.launchpad.dev:8087/branch_puller
57supermirror_root: http://bazaar.launchpad.dev/56supermirror_root: http://bazaar.launchpad.dev/
58hosted_branches_root: /var/tmp/bazaar.launchpad.dev/push-branches/57hosted_branches_root: /var/tmp/bazaar.launchpad.dev/push-branches/
59codebrowse_root: http://bazaar.launchpad.dev/58codebrowse_root: http://bazaar.launchpad.dev/
6059
=== modified file 'cronscripts/supermirror-pull.py'
--- cronscripts/supermirror-pull.py 2010-03-25 18:06:39 +0000
+++ cronscripts/supermirror-pull.py 2010-04-27 02:11:35 +0000
@@ -44,7 +44,7 @@
44 parser.error("Unhandled arguments %s" % repr(arguments))44 parser.error("Unhandled arguments %s" % repr(arguments))
45 log = set_up_logging_for_script(options, 'supermirror_puller')45 log = set_up_logging_for_script(options, 'supermirror_puller')
46 manager = scheduler.JobScheduler(46 manager = scheduler.JobScheduler(
47 LoggingProxy(config.codehosting.branch_puller_endpoint, log), log,47 LoggingProxy(config.codehosting.codehosting_endpoint, log), log,
48 options.branch_type)48 options.branch_type)
4949
50 reactor.callWhenRunning(run_mirror, log, manager)50 reactor.callWhenRunning(run_mirror, log, manager)
5151
=== modified file 'lib/canonical/config/schema-lazr.conf'
--- lib/canonical/config/schema-lazr.conf 2010-04-27 02:11:16 +0000
+++ lib/canonical/config/schema-lazr.conf 2010-04-27 02:11:35 +0000
@@ -289,19 +289,17 @@
289# datatype: string289# datatype: string
290authentication_endpoint: none290authentication_endpoint: none
291291
292# The URL of the XML-RPC endpoint used to provide the data that drives the292# Obsolete.
293# virtual file systems used by the code hosting service. This should
294# implement IBranchFileSystem.
295#
296# datatype: string
297branchfs_endpoint: none293branchfs_endpoint: none
298294
299# The URL of the XML-RPC endpoint that provides the interface from the295# Obsolete.
300# puller to the rest of Launchpad. This should implement IPullerAPI.
301#
302# datatype: string
303branch_puller_endpoint: none296branch_puller_endpoint: none
304297
298# The URL of the XML-RPC endpoint that implements ICodehostingAPI.
299#
300# datatype: string
301codehosting_endpoint: none
302
305# See [error_reports].303# See [error_reports].
306oops_prefix: none304oops_prefix: none
307305
308306
=== added directory 'lib/canonical/launchpad/apidoc'
=== modified file 'lib/canonical/launchpad/interfaces/launchpad.py'
--- lib/canonical/launchpad/interfaces/launchpad.py 2010-04-19 14:47:49 +0000
+++ lib/canonical/launchpad/interfaces/launchpad.py 2010-04-27 02:11:35 +0000
@@ -292,9 +292,7 @@
292292
293 codeimportscheduler = Attribute("""Code import scheduler end point.""")293 codeimportscheduler = Attribute("""Code import scheduler end point.""")
294294
295 branch_puller = Attribute("""Branch puller end point.""")295 codehosting = Attribute("""Codehosting end point.""")
296
297 branchfilesystem = Attribute("""The branch filesystem end point.""")
298296
299 mailinglists = Attribute("""Mailing list XML-RPC end point.""")297 mailinglists = Attribute("""Mailing list XML-RPC end point.""")
300298
301299
=== modified file 'lib/canonical/launchpad/systemhomes.py'
--- lib/canonical/launchpad/systemhomes.py 2010-04-05 16:06:06 +0000
+++ lib/canonical/launchpad/systemhomes.py 2010-04-27 02:11:35 +0000
@@ -42,8 +42,7 @@
42from canonical.launchpad.webapp.interfaces import ICanonicalUrlData42from canonical.launchpad.webapp.interfaces import ICanonicalUrlData
43from lp.bugs.interfaces.bug import (43from lp.bugs.interfaces.bug import (
44 CreateBugParams, IBugSet, InvalidBugTargetType)44 CreateBugParams, IBugSet, InvalidBugTargetType)
45from lp.code.interfaces.codehosting import (45from lp.code.interfaces.codehosting import ICodehostingApplication
46 IBranchFileSystemApplication, IBranchPullerApplication)
47from lp.code.interfaces.codeimportscheduler import (46from lp.code.interfaces.codeimportscheduler import (
48 ICodeImportSchedulerApplication)47 ICodeImportSchedulerApplication)
49from lp.registry.interfaces.product import IProduct48from lp.registry.interfaces.product import IProduct
@@ -61,18 +60,11 @@
61 title = "Auth Server"60 title = "Auth Server"
6261
6362
64class BranchFileSystemApplication:63class CodehostingApplication:
65 """BranchFileSystem End-Point."""64 """Codehosting End-Point."""
66 implements(IBranchFileSystemApplication)65 implements(ICodehostingApplication)
6766
68 title = "Branch File System"67 title = "Codehosting API"
69
70
71class BranchPullerApplication:
72 """BranchPuller End-Point."""
73 implements(IBranchPullerApplication)
74
75 title = "Puller API"
7668
7769
78class CodeImportSchedulerApplication:70class CodeImportSchedulerApplication:
7971
=== modified file 'lib/canonical/launchpad/xmlrpc/application.py'
--- lib/canonical/launchpad/xmlrpc/application.py 2009-06-25 05:30:52 +0000
+++ lib/canonical/launchpad/xmlrpc/application.py 2010-04-27 02:11:35 +0000
@@ -24,8 +24,7 @@
24 IAuthServerApplication, ILaunchBag,24 IAuthServerApplication, ILaunchBag,
25 IMailingListApplication, IPrivateApplication,25 IMailingListApplication, IPrivateApplication,
26 IPrivateMaloneApplication)26 IPrivateMaloneApplication)
27from lp.code.interfaces.codehosting import (27from lp.code.interfaces.codehosting import ICodehostingApplication
28 IBranchFileSystemApplication, IBranchPullerApplication)
29from lp.code.interfaces.codeimportscheduler import (28from lp.code.interfaces.codeimportscheduler import (
30 ICodeImportSchedulerApplication)29 ICodeImportSchedulerApplication)
31from canonical.launchpad.webapp import LaunchpadXMLRPCView30from canonical.launchpad.webapp import LaunchpadXMLRPCView
@@ -45,14 +44,9 @@
45 return getUtility(IAuthServerApplication)44 return getUtility(IAuthServerApplication)
4645
47 @property46 @property
48 def branch_puller(self):47 def codehosting(self):
49 """See `IPrivateApplication`."""48 """See `IPrivateApplication`."""
50 return getUtility(IBranchPullerApplication)49 return getUtility(ICodehostingApplication)
51
52 @property
53 def branchfilesystem(self):
54 """See `IPrivateApplication`."""
55 return getUtility(IBranchFileSystemApplication)
5650
57 @property51 @property
58 def codeimportscheduler(self):52 def codeimportscheduler(self):
5953
=== modified file 'lib/canonical/launchpad/xmlrpc/configure.zcml'
--- lib/canonical/launchpad/xmlrpc/configure.zcml 2009-07-13 18:15:02 +0000
+++ lib/canonical/launchpad/xmlrpc/configure.zcml 2010-04-27 02:11:35 +0000
@@ -28,28 +28,15 @@
28 />28 />
2929
30 <securedutility30 <securedutility
31 class="canonical.launchpad.systemhomes.BranchPullerApplication"31 class="canonical.launchpad.systemhomes.CodehostingApplication"
32 provides="lp.code.interfaces.codehosting.IBranchPullerApplication">32 provides="lp.code.interfaces.codehosting.ICodehostingApplication">
33 <allow interface="lp.code.interfaces.codehosting.IBranchPullerApplication"/>33 <allow interface="lp.code.interfaces.codehosting.ICodehostingApplication"/>
34 </securedutility>34 </securedutility>
3535
36 <xmlrpc:view36 <xmlrpc:view
37 for="lp.code.interfaces.codehosting.IBranchPullerApplication"37 for="lp.code.interfaces.codehosting.ICodehostingApplication"
38 interface="lp.code.interfaces.codehosting.IBranchPuller"38 interface="lp.code.interfaces.codehosting.ICodehostingAPI"
39 class="lp.code.xmlrpc.codehosting.BranchPuller"39 class="lp.code.xmlrpc.codehosting.CodehostingAPI"
40 permission="zope.Public"
41 />
42
43 <securedutility
44 class="canonical.launchpad.systemhomes.BranchFileSystemApplication"
45 provides="lp.code.interfaces.codehosting.IBranchFileSystemApplication">
46 <allow interface="lp.code.interfaces.codehosting.IBranchFileSystemApplication"/>
47 </securedutility>
48
49 <xmlrpc:view
50 for="lp.code.interfaces.codehosting.IBranchFileSystemApplication"
51 interface="lp.code.interfaces.codehosting.IBranchFileSystem"
52 class="lp.code.xmlrpc.codehosting.BranchFileSystem"
53 permission="zope.Public"40 permission="zope.Public"
54 />41 />
5542
5643
=== removed file 'lib/lp/code/doc/xmlrpc-branch-filesystem.txt'
--- lib/lp/code/doc/xmlrpc-branch-filesystem.txt 2009-10-22 11:55:51 +0000
+++ lib/lp/code/doc/xmlrpc-branch-filesystem.txt 1970-01-01 00:00:00 +0000
@@ -1,31 +0,0 @@
1= The BranchFileSystem application =
2
3The branch file system application is an XMLRPC service that provides
4data for the virtual filesystems used by the codehosting service. It
5is available as the branchfilesystem attribute of our private XMLRPC
6instance.
7
8 >>> from canonical.launchpad.interfaces import (
9 ... IPrivateApplication)
10 >>> from lp.code.interfaces.codehosting import (
11 ... IBranchFileSystemApplication)
12 >>> from canonical.launchpad.webapp.testing import verifyObject
13
14 >>> private_root = getUtility(IPrivateApplication)
15 >>> verifyObject(
16 ... IBranchFileSystemApplication,
17 ... private_root.branchfilesystem)
18 True
19
20The end point is implemented by the BranchFileSystem, which implements
21the IBranchFileSystem class.
22
23 >>> from canonical.launchpad.webapp.servers import LaunchpadTestRequest
24 >>> from lp.code.interfaces.codehosting import IBranchFileSystem
25 >>> from lp.code.xmlrpc.codehosting import (
26 ... BranchFileSystem)
27
28 >>> branchfs_api = BranchFileSystem(
29 ... private_root.branchfilesystem, LaunchpadTestRequest())
30 >>> verifyObject(IBranchFileSystem, branchfs_api)
31 True
320
=== removed file 'lib/lp/code/doc/xmlrpc-branch-puller.txt'
--- lib/lp/code/doc/xmlrpc-branch-puller.txt 2010-02-24 01:57:35 +0000
+++ lib/lp/code/doc/xmlrpc-branch-puller.txt 1970-01-01 00:00:00 +0000
@@ -1,31 +0,0 @@
1= The BranchPuller application =
2
3The branch puller application is an XMLRPC service that allows the puller
4to find and update the status of branches. It is available as the
5branch_puller attribute of our private XMLRPC instance.
6
7 >>> from canonical.launchpad.interfaces import (
8 ... IPrivateApplication)
9 >>> from lp.code.interfaces.codehosting import (
10 ... IBranchPullerApplication)
11 >>> from canonical.launchpad.webapp.testing import verifyObject
12
13 >>> private_root = getUtility(IPrivateApplication)
14 >>> verifyObject(
15 ... IBranchPullerApplication,
16 ... private_root.branch_puller)
17 True
18
19The BranchPuller view provides the IBranchPuller XML-RPC API:
20
21 >>> from canonical.launchpad.webapp.servers import LaunchpadTestRequest
22 >>> from lp.code.interfaces.codehosting import IBranchPuller
23 >>> from lp.code.xmlrpc.codehosting import BranchPuller
24
25 >>> branch_puller = BranchPuller(
26 ... private_root.branch_puller, LaunchpadTestRequest())
27 >>> verifyObject(IBranchPuller, branch_puller)
28 True
29
30The IBranchPuller interface defines some methods, for which see the unit
31tests.
320
=== added file 'lib/lp/code/doc/xmlrpc-codehosting.txt'
--- lib/lp/code/doc/xmlrpc-codehosting.txt 1970-01-01 00:00:00 +0000
+++ lib/lp/code/doc/xmlrpc-codehosting.txt 2010-04-27 02:11:35 +0000
@@ -0,0 +1,32 @@
1= The BranchPuller application =
2
3The codehosting application is an XMLRPC service that allows the
4codehosting service and puller to find and update the status of
5branches. It is available as the codehosting attribute of our private
6XMLRPC instance.
7
8 >>> from canonical.launchpad.interfaces import (
9 ... IPrivateApplication)
10 >>> from lp.code.interfaces.codehosting import (
11 ... ICodehostingApplication)
12 >>> from canonical.launchpad.webapp.testing import verifyObject
13
14 >>> private_root = getUtility(IPrivateApplication)
15 >>> verifyObject(
16 ... ICodehostingApplication,
17 ... private_root.codehosting)
18 True
19
20The CodeHosting view provides the ICodehostingAPI XML-RPC API:
21
22 >>> from canonical.launchpad.webapp.servers import LaunchpadTestRequest
23 >>> from lp.code.interfaces.codehosting import ICodehostingAPI
24 >>> from lp.code.xmlrpc.codehosting import CodehostingAPI
25
26 >>> codehosting_api = CodehostingAPI(
27 ... private_root.codehosting, LaunchpadTestRequest())
28 >>> verifyObject(ICodehostingAPI, codehosting_api)
29 True
30
31The ICodehostingAPI interface defines some methods, for which see the
32unit tests.
033
=== modified file 'lib/lp/code/interfaces/codehosting.py'
--- lib/lp/code/interfaces/codehosting.py 2010-04-27 02:11:16 +0000
+++ lib/lp/code/interfaces/codehosting.py 2010-04-27 02:11:35 +0000
@@ -9,10 +9,8 @@
9__all__ = [9__all__ = [
10 'BRANCH_TRANSPORT',10 'BRANCH_TRANSPORT',
11 'CONTROL_TRANSPORT',11 'CONTROL_TRANSPORT',
12 'IBranchPuller',12 'ICodehostingAPI',
13 'IBranchPullerApplication',13 'ICodehostingApplication',
14 'IBranchFileSystem',
15 'IBranchFileSystemApplication',
16 'LAUNCHPAD_ANONYMOUS',14 'LAUNCHPAD_ANONYMOUS',
17 'LAUNCHPAD_SERVICES',15 'LAUNCHPAD_SERVICES',
18 'READ_ONLY',16 'READ_ONLY',
@@ -48,14 +46,17 @@
48CONTROL_TRANSPORT = 'CONTROL_TRANSPORT'46CONTROL_TRANSPORT = 'CONTROL_TRANSPORT'
4947
5048
51class IBranchPullerApplication(ILaunchpadApplication):49class ICodehostingApplication(ILaunchpadApplication):
52 """Branch Puller application root."""50 """Branch Puller application root."""
5351
5452
55class IBranchPuller(Interface):53class ICodehostingAPI(Interface):
56 """The puller's interface to the rest of Launchpad.54 """The codehosting XML-RPC interface to Launchpad.
5755
58 Published at 'branch_puller' on the private XML-RPC server.56 Published at 'codehosting' on the private XML-RPC server.
57
58 The code hosting service and puller use this to register branches, to
59 retrieve information about a user's branches, and to update their status.
59 """60 """
6061
61 def acquireBranchToPull(branch_type_names):62 def acquireBranchToPull(branch_type_names):
@@ -144,20 +145,6 @@
144 'stacked_on_location'.145 'stacked_on_location'.
145 """146 """
146147
147
148class IBranchFileSystemApplication(ILaunchpadApplication):
149 """Branch File System end point root."""
150
151
152class IBranchFileSystem(Interface):
153 """An interface for dealing with hosted branches in Launchpad.
154
155 Published at `branchfilesystem`.
156
157 The code hosting service uses this to register branches, to retrieve
158 information about a user's branches, and to update their status.
159 """
160
161 def createBranch(login_id, branch_path):148 def createBranch(login_id, branch_path):
162 """Register a new hosted branch in Launchpad.149 """Register a new hosted branch in Launchpad.
163150
164151
=== modified file 'lib/lp/code/xmlrpc/codehosting.py'
--- lib/lp/code/xmlrpc/codehosting.py 2010-04-27 02:11:16 +0000
+++ lib/lp/code/xmlrpc/codehosting.py 2010-04-27 02:11:35 +0000
@@ -5,8 +5,7 @@
55
6__metaclass__ = type6__metaclass__ = type
7__all__ = [7__all__ = [
8 'BranchFileSystem',8 'CodehostingAPI',
9 'BranchPuller',
10 'datetime_from_tuple',9 'datetime_from_tuple',
11 ]10 ]
1211
@@ -43,8 +42,8 @@
43 InvalidNamespace, lookup_branch_namespace, split_unique_name)42 InvalidNamespace, lookup_branch_namespace, split_unique_name)
44from lp.code.interfaces import branchpuller43from lp.code.interfaces import branchpuller
45from lp.code.interfaces.codehosting import (44from lp.code.interfaces.codehosting import (
46 BRANCH_TRANSPORT, CONTROL_TRANSPORT, IBranchFileSystem, IBranchPuller,45 BRANCH_TRANSPORT, CONTROL_TRANSPORT, ICodehostingAPI, LAUNCHPAD_ANONYMOUS,
47 LAUNCHPAD_ANONYMOUS, LAUNCHPAD_SERVICES)46 LAUNCHPAD_SERVICES)
48from lp.registry.interfaces.person import IPersonSet, NoSuchPerson47from lp.registry.interfaces.person import IPersonSet, NoSuchPerson
49from lp.registry.interfaces.product import NoSuchProduct48from lp.registry.interfaces.product import NoSuchProduct
50from lp.services.scripts.interfaces.scriptactivity import IScriptActivitySet49from lp.services.scripts.interfaces.scriptactivity import IScriptActivitySet
@@ -54,13 +53,54 @@
54UTC = pytz.timezone('UTC')53UTC = pytz.timezone('UTC')
5554
5655
57class BranchPuller(LaunchpadXMLRPCView):56def datetime_from_tuple(time_tuple):
58 """See `IBranchPuller`."""57 """Create a datetime from a sequence that quacks like time.struct_time.
5958
60 implements(IBranchPuller)59 The tm_isdst is (index 8) is ignored. The created datetime uses
60 tzinfo=UTC.
61 """
62 [year, month, day, hour, minute, second, unused, unused, unused] = (
63 time_tuple)
64 return datetime.datetime(
65 year, month, day, hour, minute, second, tzinfo=UTC)
66
67
68def run_with_login(login_id, function, *args, **kwargs):
69 """Run 'function' logged in with 'login_id'.
70
71 The first argument passed to 'function' will be the Launchpad
72 `Person` object corresponding to 'login_id'.
73
74 The exception is when the requesting login ID is `LAUNCHPAD_SERVICES`. In
75 that case, we'll pass through the `LAUNCHPAD_SERVICES` variable and the
76 method will do whatever security proxy hackery is required to provide read
77 privileges to the Launchpad services.
78 """
79 if login_id == LAUNCHPAD_SERVICES or login_id == LAUNCHPAD_ANONYMOUS:
80 # Don't pass in an actual user. Instead pass in LAUNCHPAD_SERVICES
81 # and expect `function` to use `removeSecurityProxy` or similar.
82 return function(login_id, *args, **kwargs)
83 if isinstance(login_id, basestring):
84 requester = getUtility(IPersonSet).getByName(login_id)
85 else:
86 requester = getUtility(IPersonSet).get(login_id)
87 if requester is None:
88 raise NotFoundError("No person with id %s." % login_id)
89 setupInteractionForPerson(requester)
90 try:
91 return function(requester, *args, **kwargs)
92 finally:
93 endInteraction()
94
95
96
97class CodehostingAPI(LaunchpadXMLRPCView):
98 """See `ICodehostingAPI`."""
99
100 implements(ICodehostingAPI)
61101
62 def acquireBranchToPull(self, branch_type_names):102 def acquireBranchToPull(self, branch_type_names):
63 """See `IBranchPuller`."""103 """See `ICodehostingAPI`."""
64 branch_types = []104 branch_types = []
65 for branch_type_name in branch_type_names:105 for branch_type_name in branch_type_names:
66 try:106 try:
@@ -86,7 +126,7 @@
86 return ()126 return ()
87127
88 def mirrorComplete(self, branch_id, last_revision_id):128 def mirrorComplete(self, branch_id, last_revision_id):
89 """See `IBranchPuller`."""129 """See `ICodehostingAPI`."""
90 branch = getUtility(IBranchLookup).get(branch_id)130 branch = getUtility(IBranchLookup).get(branch_id)
91 if branch is None:131 if branch is None:
92 return faults.NoBranchWithID(branch_id)132 return faults.NoBranchWithID(branch_id)
@@ -96,7 +136,7 @@
96 return True136 return True
97137
98 def mirrorFailed(self, branch_id, reason):138 def mirrorFailed(self, branch_id, reason):
99 """See `IBranchPuller`."""139 """See `ICodehostingAPI`."""
100 branch = getUtility(IBranchLookup).get(branch_id)140 branch = getUtility(IBranchLookup).get(branch_id)
101 if branch is None:141 if branch is None:
102 return faults.NoBranchWithID(branch_id)142 return faults.NoBranchWithID(branch_id)
@@ -105,7 +145,7 @@
105 return True145 return True
106146
107 def recordSuccess(self, name, hostname, started_tuple, completed_tuple):147 def recordSuccess(self, name, hostname, started_tuple, completed_tuple):
108 """See `IBranchPuller`."""148 """See `ICodehostingAPI`."""
109 date_started = datetime_from_tuple(started_tuple)149 date_started = datetime_from_tuple(started_tuple)
110 date_completed = datetime_from_tuple(completed_tuple)150 date_completed = datetime_from_tuple(completed_tuple)
111 getUtility(IScriptActivitySet).recordSuccess(151 getUtility(IScriptActivitySet).recordSuccess(
@@ -114,7 +154,7 @@
114 return True154 return True
115155
116 def startMirroring(self, branch_id):156 def startMirroring(self, branch_id):
117 """See `IBranchPuller`."""157 """See `ICodehostingAPI`."""
118 branch = getUtility(IBranchLookup).get(branch_id)158 branch = getUtility(IBranchLookup).get(branch_id)
119 if branch is None:159 if branch is None:
120 return faults.NoBranchWithID(branch_id)160 return faults.NoBranchWithID(branch_id)
@@ -124,7 +164,7 @@
124 return True164 return True
125165
126 def setStackedOn(self, branch_id, stacked_on_location):166 def setStackedOn(self, branch_id, stacked_on_location):
127 """See `IBranchPuller`."""167 """See `ICodehostingAPI`."""
128 # We don't want the security proxy on the branch set because this168 # We don't want the security proxy on the branch set because this
129 # method should be able to see all branches and set stacking169 # method should be able to see all branches and set stacking
130 # information on any of them.170 # information on any of them.
@@ -146,54 +186,8 @@
146 stacked_branch.stacked_on = stacked_on_branch186 stacked_branch.stacked_on = stacked_on_branch
147 return True187 return True
148188
149
150def datetime_from_tuple(time_tuple):
151 """Create a datetime from a sequence that quacks like time.struct_time.
152
153 The tm_isdst is (index 8) is ignored. The created datetime uses
154 tzinfo=UTC.
155 """
156 [year, month, day, hour, minute, second, unused, unused, unused] = (
157 time_tuple)
158 return datetime.datetime(
159 year, month, day, hour, minute, second, tzinfo=UTC)
160
161
162def run_with_login(login_id, function, *args, **kwargs):
163 """Run 'function' logged in with 'login_id'.
164
165 The first argument passed to 'function' will be the Launchpad
166 `Person` object corresponding to 'login_id'.
167
168 The exception is when the requesting login ID is `LAUNCHPAD_SERVICES`. In
169 that case, we'll pass through the `LAUNCHPAD_SERVICES` variable and the
170 method will do whatever security proxy hackery is required to provide read
171 privileges to the Launchpad services.
172 """
173 if login_id == LAUNCHPAD_SERVICES or login_id == LAUNCHPAD_ANONYMOUS:
174 # Don't pass in an actual user. Instead pass in LAUNCHPAD_SERVICES
175 # and expect `function` to use `removeSecurityProxy` or similar.
176 return function(login_id, *args, **kwargs)
177 if isinstance(login_id, basestring):
178 requester = getUtility(IPersonSet).getByName(login_id)
179 else:
180 requester = getUtility(IPersonSet).get(login_id)
181 if requester is None:
182 raise NotFoundError("No person with id %s." % login_id)
183 setupInteractionForPerson(requester)
184 try:
185 return function(requester, *args, **kwargs)
186 finally:
187 endInteraction()
188
189
190class BranchFileSystem(LaunchpadXMLRPCView):
191 """See `IBranchFileSystem`."""
192
193 implements(IBranchFileSystem)
194
195 def createBranch(self, login_id, branch_path):189 def createBranch(self, login_id, branch_path):
196 """See `IBranchFileSystem`."""190 """See `ICodehostingAPI`."""
197 def create_branch(requester):191 def create_branch(requester):
198 if not branch_path.startswith('/'):192 if not branch_path.startswith('/'):
199 return faults.InvalidPath(branch_path)193 return faults.InvalidPath(branch_path)
@@ -238,7 +232,7 @@
238 and check_permission('launchpad.Edit', branch))232 and check_permission('launchpad.Edit', branch))
239233
240 def requestMirror(self, login_id, branchID):234 def requestMirror(self, login_id, branchID):
241 """See `IBranchFileSystem`."""235 """See `ICodehostingAPI`."""
242 def request_mirror(requester):236 def request_mirror(requester):
243 branch = getUtility(IBranchLookup).get(branchID)237 branch = getUtility(IBranchLookup).get(branchID)
244 # We don't really care who requests a mirror of a branch.238 # We don't really care who requests a mirror of a branch.
@@ -248,7 +242,7 @@
248242
249 def branchChanged(self, branch_id, stacked_on_location, last_revision_id,243 def branchChanged(self, branch_id, stacked_on_location, last_revision_id,
250 control_string, branch_string, repository_string):244 control_string, branch_string, repository_string):
251 """See `IBranchFileSystem`."""245 """See `ICodehostingAPI`."""
252 branch_set = removeSecurityProxy(getUtility(IBranchLookup))246 branch_set = removeSecurityProxy(getUtility(IBranchLookup))
253 branch = branch_set.get(branch_id)247 branch = branch_set.get(branch_id)
254 if branch is None:248 if branch is None:
@@ -322,7 +316,7 @@
322 trailing_path)316 trailing_path)
323317
324 def translatePath(self, requester_id, path):318 def translatePath(self, requester_id, path):
325 """See `IBranchFileSystem`."""319 """See `ICodehostingAPI`."""
326 @return_fault320 @return_fault
327 def translate_path(requester):321 def translate_path(requester):
328 if not path.startswith('/'):322 if not path.startswith('/'):
329323
=== modified file 'lib/lp/code/xmlrpc/tests/test_codehosting.py'
--- lib/lp/code/xmlrpc/tests/test_codehosting.py 2010-04-27 02:11:16 +0000
+++ lib/lp/code/xmlrpc/tests/test_codehosting.py 2010-04-27 02:11:35 +0000
@@ -20,8 +20,7 @@
20from canonical.launchpad.ftests import ANONYMOUS, login, logout20from canonical.launchpad.ftests import ANONYMOUS, login, logout
21from lp.services.scripts.interfaces.scriptactivity import (21from lp.services.scripts.interfaces.scriptactivity import (
22 IScriptActivitySet)22 IScriptActivitySet)
23from lp.code.interfaces.codehosting import (23from lp.code.interfaces.codehosting import BRANCH_TRANSPORT, CONTROL_TRANSPORT
24 BRANCH_TRANSPORT, CONTROL_TRANSPORT)
25from canonical.launchpad.interfaces.launchpad import ILaunchBag24from canonical.launchpad.interfaces.launchpad import ILaunchBag
26from lp.testing import TestCaseWithFactory25from lp.testing import TestCaseWithFactory
27from lp.testing.factory import LaunchpadObjectFactory26from lp.testing.factory import LaunchpadObjectFactory
@@ -38,8 +37,7 @@
38from lp.code.interfaces.branchtarget import IBranchTarget37from lp.code.interfaces.branchtarget import IBranchTarget
39from lp.code.model.tests.test_branchpuller import AcquireBranchToPullTests38from lp.code.model.tests.test_branchpuller import AcquireBranchToPullTests
40from lp.code.xmlrpc.codehosting import (39from lp.code.xmlrpc.codehosting import (
41 BranchFileSystem, BranchPuller, LAUNCHPAD_ANONYMOUS, LAUNCHPAD_SERVICES,40 CodehostingAPI, LAUNCHPAD_ANONYMOUS, LAUNCHPAD_SERVICES, run_with_login)
42 run_with_login)
4341
44from lp.codehosting.inmemory import InMemoryFrontend42from lp.codehosting.inmemory import InMemoryFrontend
4543
@@ -126,17 +124,17 @@
126 self.assertEqual(None, login_id)124 self.assertEqual(None, login_id)
127125
128126
129class BranchPullerTest(TestCaseWithFactory):127class CodehostingTest(TestCaseWithFactory):
130 """Tests for the implementation of `IBranchPuller`.128 """Tests for the implementation of `ICodehostingAPI`.
131129
132 :ivar frontend: A nullary callable that returns an object that implements130 :ivar frontend: A nullary callable that returns an object that implements
133 getPullerEndpoint, getLaunchpadObjectFactory and getBranchLookup.131 getCodehostingEndpoint, getLaunchpadObjectFactory and getBranchLookup.
134 """132 """
135133
136 def setUp(self):134 def setUp(self):
137 TestCaseWithFactory.setUp(self)135 TestCaseWithFactory.setUp(self)
138 frontend = self.frontend()136 frontend = self.frontend()
139 self.storage = frontend.getPullerEndpoint()137 self.codehosting_api = frontend.getCodehostingEndpoint()
140 self.factory = frontend.getLaunchpadObjectFactory()138 self.factory = frontend.getLaunchpadObjectFactory()
141 self.branch_lookup = frontend.getBranchLookup()139 self.branch_lookup = frontend.getBranchLookup()
142 self.getLastActivity = frontend.getLastActivity140 self.getLastActivity = frontend.getLastActivity
@@ -189,7 +187,7 @@
189 branch = self.factory.makeAnyBranch()187 branch = self.factory.makeAnyBranch()
190 self.assertUnmirrored(branch)188 self.assertUnmirrored(branch)
191189
192 success = self.storage.startMirroring(branch.id)190 success = self.codehosting_api.startMirroring(branch.id)
193 self.assertEqual(success, True)191 self.assertEqual(success, True)
194192
195 self.assertSqlAttributeEqualsDate(193 self.assertSqlAttributeEqualsDate(
@@ -200,23 +198,23 @@
200 # startMirroring returns False when given a branch id which does not198 # startMirroring returns False when given a branch id which does not
201 # exist.199 # exist.
202 invalid_id = self.getUnusedBranchID()200 invalid_id = self.getUnusedBranchID()
203 fault = self.storage.startMirroring(invalid_id)201 fault = self.codehosting_api.startMirroring(invalid_id)
204 self.assertEqual(faults.NoBranchWithID(invalid_id), fault)202 self.assertEqual(faults.NoBranchWithID(invalid_id), fault)
205203
206 def test_mirrorFailed(self):204 def test_mirrorFailed(self):
207 branch = self.factory.makeAnyBranch()205 branch = self.factory.makeAnyBranch()
208 self.assertUnmirrored(branch)206 self.assertUnmirrored(branch)
209207
210 self.storage.startMirroring(branch.id)208 self.codehosting_api.startMirroring(branch.id)
211 failure_message = self.factory.getUniqueString()209 failure_message = self.factory.getUniqueString()
212 success = self.storage.mirrorFailed(branch.id, failure_message)210 success = self.codehosting_api.mirrorFailed(branch.id, failure_message)
213 self.assertEqual(True, success)211 self.assertEqual(True, success)
214 self.assertMirrorFailed(branch, failure_message)212 self.assertMirrorFailed(branch, failure_message)
215213
216 def test_mirrorFailedWithNotBranchID(self):214 def test_mirrorFailedWithNotBranchID(self):
217 branch_id = self.getUnusedBranchID()215 branch_id = self.getUnusedBranchID()
218 failure_message = self.factory.getUniqueString()216 failure_message = self.factory.getUniqueString()
219 fault = self.storage.mirrorFailed(branch_id, failure_message)217 fault = self.codehosting_api.mirrorFailed(branch_id, failure_message)
220 self.assertEqual(faults.NoBranchWithID(branch_id), fault)218 self.assertEqual(faults.NoBranchWithID(branch_id), fault)
221219
222 def test_mirrorComplete(self):220 def test_mirrorComplete(self):
@@ -225,9 +223,9 @@
225 branch = self.factory.makeAnyBranch()223 branch = self.factory.makeAnyBranch()
226 self.assertUnmirrored(branch)224 self.assertUnmirrored(branch)
227225
228 self.storage.startMirroring(branch.id)226 self.codehosting_api.startMirroring(branch.id)
229 revision_id = self.factory.getUniqueString()227 revision_id = self.factory.getUniqueString()
230 success = self.storage.mirrorComplete(branch.id, revision_id)228 success = self.codehosting_api.mirrorComplete(branch.id, revision_id)
231 self.assertEqual(True, success)229 self.assertEqual(True, success)
232 self.assertMirrorSucceeded(branch, revision_id)230 self.assertMirrorSucceeded(branch, revision_id)
233231
@@ -235,7 +233,7 @@
235 # mirrorComplete returns a Fault if there's no branch with the given233 # mirrorComplete returns a Fault if there's no branch with the given
236 # ID.234 # ID.
237 branch_id = self.getUnusedBranchID()235 branch_id = self.getUnusedBranchID()
238 fault = self.storage.mirrorComplete(236 fault = self.codehosting_api.mirrorComplete(
239 branch_id, self.factory.getUniqueString())237 branch_id, self.factory.getUniqueString())
240 self.assertEqual(faults.NoBranchWithID(branch_id), fault)238 self.assertEqual(faults.NoBranchWithID(branch_id), fault)
241239
@@ -245,15 +243,15 @@
245243
246 # First, mark the branch as failed.244 # First, mark the branch as failed.
247 branch = self.factory.makeAnyBranch()245 branch = self.factory.makeAnyBranch()
248 self.storage.startMirroring(branch.id)246 self.codehosting_api.startMirroring(branch.id)
249 failure_message = self.factory.getUniqueString()247 failure_message = self.factory.getUniqueString()
250 self.storage.mirrorFailed(branch.id, failure_message)248 self.codehosting_api.mirrorFailed(branch.id, failure_message)
251 self.assertMirrorFailed(branch, failure_message)249 self.assertMirrorFailed(branch, failure_message)
252250
253 # Start and successfully finish a mirror.251 # Start and successfully finish a mirror.
254 self.storage.startMirroring(branch.id)252 self.codehosting_api.startMirroring(branch.id)
255 revision_id = self.factory.getUniqueString()253 revision_id = self.factory.getUniqueString()
256 self.storage.mirrorComplete(branch.id, revision_id)254 self.codehosting_api.mirrorComplete(branch.id, revision_id)
257255
258 # Confirm that it succeeded.256 # Confirm that it succeeded.
259 self.assertMirrorSucceeded(branch, revision_id)257 self.assertMirrorSucceeded(branch, revision_id)
@@ -267,8 +265,9 @@
267 branch.requestMirror()265 branch.requestMirror()
268266
269 # Simulate successfully mirroring the branch.267 # Simulate successfully mirroring the branch.
270 self.storage.startMirroring(branch.id)268 self.codehosting_api.startMirroring(branch.id)
271 self.storage.mirrorComplete(branch.id, self.factory.getUniqueString())269 self.codehosting_api.mirrorComplete(
270 branch.id, self.factory.getUniqueString())
272271
273 self.assertIs(None, branch.next_mirror_time)272 self.assertIs(None, branch.next_mirror_time)
274273
@@ -278,7 +277,7 @@
278 completed = datetime.datetime(2007, 07, 05, 19, 34, 24, tzinfo=UTC)277 completed = datetime.datetime(2007, 07, 05, 19, 34, 24, tzinfo=UTC)
279 started_tuple = tuple(started.utctimetuple())278 started_tuple = tuple(started.utctimetuple())
280 completed_tuple = tuple(completed.utctimetuple())279 completed_tuple = tuple(completed.utctimetuple())
281 success = self.storage.recordSuccess(280 success = self.codehosting_api.recordSuccess(
282 'test-recordsuccess', 'vostok', started_tuple, completed_tuple)281 'test-recordsuccess', 'vostok', started_tuple, completed_tuple)
283 self.assertEqual(True, success)282 self.assertEqual(True, success)
284283
@@ -293,7 +292,7 @@
293 # generated as part of Launchpad's default stacking.292 # generated as part of Launchpad's default stacking.
294 stacked_branch = self.factory.makeAnyBranch()293 stacked_branch = self.factory.makeAnyBranch()
295 stacked_on_branch = self.factory.makeAnyBranch()294 stacked_on_branch = self.factory.makeAnyBranch()
296 self.storage.setStackedOn(295 self.codehosting_api.setStackedOn(
297 stacked_branch.id, '/%s' % stacked_on_branch.unique_name)296 stacked_branch.id, '/%s' % stacked_on_branch.unique_name)
298 self.assertEqual(stacked_branch.stacked_on, stacked_on_branch)297 self.assertEqual(stacked_branch.stacked_on, stacked_on_branch)
299298
@@ -304,7 +303,8 @@
304 stacked_branch = self.factory.makeAnyBranch()303 stacked_branch = self.factory.makeAnyBranch()
305 stacked_on_branch = self.factory.makeAnyBranch(304 stacked_on_branch = self.factory.makeAnyBranch(
306 branch_type=BranchType.MIRRORED)305 branch_type=BranchType.MIRRORED)
307 self.storage.setStackedOn(stacked_branch.id, stacked_on_branch.url)306 self.codehosting_api.setStackedOn(
307 stacked_branch.id, stacked_on_branch.url)
308 self.assertEqual(stacked_branch.stacked_on, stacked_on_branch)308 self.assertEqual(stacked_branch.stacked_on, stacked_on_branch)
309309
310 def test_setStackedOnExternalURLWithTrailingSlash(self):310 def test_setStackedOnExternalURLWithTrailingSlash(self):
@@ -315,7 +315,7 @@
315 stacked_on_branch = self.factory.makeAnyBranch(315 stacked_on_branch = self.factory.makeAnyBranch(
316 branch_type=BranchType.MIRRORED)316 branch_type=BranchType.MIRRORED)
317 url = stacked_on_branch.url + '/'317 url = stacked_on_branch.url + '/'
318 self.storage.setStackedOn(stacked_branch.id, url)318 self.codehosting_api.setStackedOn(stacked_branch.id, url)
319 self.assertEqual(stacked_branch.stacked_on, stacked_on_branch)319 self.assertEqual(stacked_branch.stacked_on, stacked_on_branch)
320320
321 def test_setStackedOnNothing(self):321 def test_setStackedOnNothing(self):
@@ -324,7 +324,7 @@
324 stacked_on_branch = self.factory.makeAnyBranch()324 stacked_on_branch = self.factory.makeAnyBranch()
325 stacked_branch = self.factory.makeAnyBranch(325 stacked_branch = self.factory.makeAnyBranch(
326 stacked_on=stacked_on_branch)326 stacked_on=stacked_on_branch)
327 self.storage.setStackedOn(stacked_branch.id, '')327 self.codehosting_api.setStackedOn(stacked_branch.id, '')
328 self.assertIs(stacked_branch.stacked_on, None)328 self.assertIs(stacked_branch.stacked_on, None)
329329
330 def test_setStackedOnBranchNotFound(self):330 def test_setStackedOnBranchNotFound(self):
@@ -332,7 +332,7 @@
332 # return a Fault.332 # return a Fault.
333 stacked_branch = self.factory.makeAnyBranch()333 stacked_branch = self.factory.makeAnyBranch()
334 url = self.factory.getUniqueURL()334 url = self.factory.getUniqueURL()
335 fault = self.storage.setStackedOn(stacked_branch.id, url)335 fault = self.codehosting_api.setStackedOn(stacked_branch.id, url)
336 self.assertEqual(faults.NoSuchBranch(url), fault)336 self.assertEqual(faults.NoSuchBranch(url), fault)
337337
338 def test_setStackedOnNoBranchWithID(self):338 def test_setStackedOnNoBranchWithID(self):
@@ -341,110 +341,17 @@
341 stacked_on_branch = self.factory.makeAnyBranch(341 stacked_on_branch = self.factory.makeAnyBranch(
342 branch_type=BranchType.MIRRORED)342 branch_type=BranchType.MIRRORED)
343 branch_id = self.getUnusedBranchID()343 branch_id = self.getUnusedBranchID()
344 fault = self.storage.setStackedOn(branch_id, stacked_on_branch.url)344 fault = self.codehosting_api.setStackedOn(
345 branch_id, stacked_on_branch.url)
345 self.assertEqual(faults.NoBranchWithID(branch_id), fault)346 self.assertEqual(faults.NoBranchWithID(branch_id), fault)
346347
347
348class AcquireBranchToPullTestsViaEndpoint(TestCaseWithFactory,
349 AcquireBranchToPullTests):
350 """Tests for `acquireBranchToPull` method of `IBranchPuller`."""
351
352 def setUp(self):
353 super(AcquireBranchToPullTestsViaEndpoint, self).setUp()
354 frontend = self.frontend()
355 self.storage = frontend.getPullerEndpoint()
356 self.factory = frontend.getLaunchpadObjectFactory()
357
358 def assertNoBranchIsAquired(self, *branch_types):
359 """See `AcquireBranchToPullTests`."""
360 branch_types = tuple(branch_type.name for branch_type in branch_types)
361 pull_info = self.storage.acquireBranchToPull(branch_types)
362 self.assertEqual((), pull_info)
363
364 def assertBranchIsAquired(self, branch, *branch_types):
365 """See `AcquireBranchToPullTests`."""
366 branch = removeSecurityProxy(branch)
367 branch_types = tuple(branch_type.name for branch_type in branch_types)
368 pull_info = self.storage.acquireBranchToPull(branch_types)
369 default_branch = branch.target.default_stacked_on_branch
370 if default_branch:
371 default_branch_name = default_branch
372 else:
373 default_branch_name = ''
374 self.assertEqual(
375 pull_info,
376 (branch.id, branch.getPullURL(), branch.unique_name,
377 default_branch_name, branch.branch_type.name))
378 self.assertIsNot(None, branch.last_mirror_attempt)
379 self.assertIs(None, branch.next_mirror_time)
380
381 def startMirroring(self, branch):
382 """See `AcquireBranchToPullTests`."""
383 self.storage.startMirroring(branch.id)
384
385 def test_branch_type_returned_mirrored(self):
386 branch = self.factory.makeAnyBranch(branch_type=BranchType.MIRRORED)
387 branch.requestMirror()
388 pull_info = self.storage.acquireBranchToPull(())
389 _, _, _, _, branch_type = pull_info
390 self.assertEqual('MIRRORED', branch_type)
391
392 def test_branch_type_returned_import(self):
393 branch = self.factory.makeAnyBranch(branch_type=BranchType.IMPORTED)
394 branch.requestMirror()
395 pull_info = self.storage.acquireBranchToPull(())
396 _, _, _, _, branch_type = pull_info
397 self.assertEqual('IMPORTED', branch_type)
398
399 def test_default_stacked_on_branch_returned(self):
400 branch = self.factory.makeProductBranch(
401 branch_type=BranchType.MIRRORED)
402 self.factory.enableDefaultStackingForProduct(branch.product)
403 branch.requestMirror()
404 pull_info = self.storage.acquireBranchToPull(())
405 _, _, _, default_stacked_on_branch, _ = pull_info
406 self.assertEqual(
407 default_stacked_on_branch,
408 '/' + branch.target.default_stacked_on_branch.unique_name)
409
410 def test_private_default_stacked_not_returned_for_mirrored_branch(self):
411 # We don't stack mirrored branches on a private default stacked on
412 # branch.
413 product = self.factory.makeProduct()
414 default_branch = self.factory.makeProductBranch(
415 product=product, private=True)
416 self.factory.enableDefaultStackingForProduct(product, default_branch)
417 mirrored_branch = self.factory.makeProductBranch(
418 branch_type=BranchType.MIRRORED, product=product)
419 mirrored_branch.requestMirror()
420 pull_info = self.storage.acquireBranchToPull(())
421 _, _, _, default_stacked_on_branch, _ = pull_info
422 self.assertEqual(
423 '', default_stacked_on_branch)
424
425 def test_unknown_branch_type_name_raises(self):
426 self.assertRaises(
427 UnknownBranchTypeError, self.storage.acquireBranchToPull,
428 ('NO_SUCH_TYPE',))
429
430
431class BranchFileSystemTest(TestCaseWithFactory):
432 """Tests for the implementation of `IBranchFileSystem`."""
433
434 def setUp(self):
435 super(BranchFileSystemTest, self).setUp()
436 frontend = self.frontend()
437 self.branchfs = frontend.getFilesystemEndpoint()
438 self.factory = frontend.getLaunchpadObjectFactory()
439 self.branch_lookup = frontend.getBranchLookup()
440
441 def test_createBranch(self):348 def test_createBranch(self):
442 # createBranch creates a branch with the supplied details and the349 # createBranch creates a branch with the supplied details and the
443 # caller as registrant.350 # caller as registrant.
444 owner = self.factory.makePerson()351 owner = self.factory.makePerson()
445 product = self.factory.makeProduct()352 product = self.factory.makeProduct()
446 name = self.factory.getUniqueString()353 name = self.factory.getUniqueString()
447 branch_id = self.branchfs.createBranch(354 branch_id = self.codehosting_api.createBranch(
448 owner.id, escape('/~%s/%s/%s' % (owner.name, product.name, name)))355 owner.id, escape('/~%s/%s/%s' % (owner.name, product.name, name)))
449 login(ANONYMOUS)356 login(ANONYMOUS)
450 branch = self.branch_lookup.get(branch_id)357 branch = self.branch_lookup.get(branch_id)
@@ -457,7 +364,7 @@
457 def test_createBranch_no_preceding_slash(self):364 def test_createBranch_no_preceding_slash(self):
458 requester = self.factory.makePerson()365 requester = self.factory.makePerson()
459 path = escape(u'invalid')366 path = escape(u'invalid')
460 fault = self.branchfs.createBranch(requester.id, path)367 fault = self.codehosting_api.createBranch(requester.id, path)
461 login(ANONYMOUS)368 login(ANONYMOUS)
462 self.assertEqual(faults.InvalidPath(path), fault)369 self.assertEqual(faults.InvalidPath(path), fault)
463370
@@ -465,7 +372,7 @@
465 # createBranch can create +junk branches.372 # createBranch can create +junk branches.
466 owner = self.factory.makePerson()373 owner = self.factory.makePerson()
467 name = self.factory.getUniqueString()374 name = self.factory.getUniqueString()
468 branch_id = self.branchfs.createBranch(375 branch_id = self.codehosting_api.createBranch(
469 owner.id, escape('/~%s/%s/%s' % (owner.name, '+junk', name)))376 owner.id, escape('/~%s/%s/%s' % (owner.name, '+junk', name)))
470 login(ANONYMOUS)377 login(ANONYMOUS)
471 branch = self.branch_lookup.get(branch_id)378 branch = self.branch_lookup.get(branch_id)
@@ -480,7 +387,7 @@
480 registrant = self.factory.makePerson()387 registrant = self.factory.makePerson()
481 team = self.factory.makeTeam(registrant)388 team = self.factory.makeTeam(registrant)
482 name = self.factory.getUniqueString()389 name = self.factory.getUniqueString()
483 branch_id = self.branchfs.createBranch(390 branch_id = self.codehosting_api.createBranch(
484 registrant.id, escape('/~%s/+junk/%s' % (team.name, name)))391 registrant.id, escape('/~%s/+junk/%s' % (team.name, name)))
485 login(ANONYMOUS)392 login(ANONYMOUS)
486 branch = self.branch_lookup.get(branch_id)393 branch = self.branch_lookup.get(branch_id)
@@ -495,7 +402,7 @@
495 owner = self.factory.makePerson()402 owner = self.factory.makePerson()
496 name = self.factory.getUniqueString()403 name = self.factory.getUniqueString()
497 message = "Project 'no-such-product' does not exist."404 message = "Project 'no-such-product' does not exist."
498 fault = self.branchfs.createBranch(405 fault = self.codehosting_api.createBranch(
499 owner.id, escape('/~%s/no-such-product/%s' % (owner.name, name)))406 owner.id, escape('/~%s/no-such-product/%s' % (owner.name, name)))
500 self.assertEqual(faults.NotFound(message), fault)407 self.assertEqual(faults.NotFound(message), fault)
501408
@@ -507,7 +414,7 @@
507 name = self.factory.getUniqueString()414 name = self.factory.getUniqueString()
508 message = ("%s cannot create branches owned by %s"415 message = ("%s cannot create branches owned by %s"
509 % (creator.displayname, other_person.displayname))416 % (creator.displayname, other_person.displayname))
510 fault = self.branchfs.createBranch(417 fault = self.codehosting_api.createBranch(
511 creator.id,418 creator.id,
512 escape('/~%s/%s/%s' % (other_person.name, product.name, name)))419 escape('/~%s/%s/%s' % (other_person.name, product.name, name)))
513 self.assertEqual(faults.PermissionDenied(message), fault)420 self.assertEqual(faults.PermissionDenied(message), fault)
@@ -519,7 +426,7 @@
519 invalid_name = 'invalid name!'426 invalid_name = 'invalid name!'
520 message = ("Invalid branch name '%s'. %s"427 message = ("Invalid branch name '%s'. %s"
521 % (invalid_name, BRANCH_NAME_VALIDATION_ERROR_MESSAGE))428 % (invalid_name, BRANCH_NAME_VALIDATION_ERROR_MESSAGE))
522 fault = self.branchfs.createBranch(429 fault = self.codehosting_api.createBranch(
523 owner.id, escape(430 owner.id, escape(
524 '/~%s/%s/%s' % (owner.name, product.name, invalid_name)))431 '/~%s/%s/%s' % (owner.name, product.name, invalid_name)))
525 self.assertEqual(faults.PermissionDenied(message), fault)432 self.assertEqual(faults.PermissionDenied(message), fault)
@@ -532,7 +439,7 @@
532 message = ("Invalid branch name '%s'. %s"439 message = ("Invalid branch name '%s'. %s"
533 % (invalid_name.encode('utf-8'),440 % (invalid_name.encode('utf-8'),
534 str(BRANCH_NAME_VALIDATION_ERROR_MESSAGE)))441 str(BRANCH_NAME_VALIDATION_ERROR_MESSAGE)))
535 fault = self.branchfs.createBranch(442 fault = self.codehosting_api.createBranch(
536 owner.id, escape(443 owner.id, escape(
537 '/~%s/%s/%s' % (owner.name, product.name, invalid_name)))444 '/~%s/%s/%s' % (owner.name, product.name, invalid_name)))
538 self.assertEqual(445 self.assertEqual(
@@ -544,7 +451,7 @@
544 product = self.factory.makeProduct()451 product = self.factory.makeProduct()
545 name = self.factory.getUniqueString()452 name = self.factory.getUniqueString()
546 message = "User/team 'no-one' does not exist."453 message = "User/team 'no-one' does not exist."
547 fault = self.branchfs.createBranch(454 fault = self.codehosting_api.createBranch(
548 owner.id, escape('/~no-one/%s/%s' % (product.name, name)))455 owner.id, escape('/~no-one/%s/%s' % (product.name, name)))
549 self.assertEqual(faults.NotFound(message), fault)456 self.assertEqual(faults.NotFound(message), fault)
550457
@@ -555,7 +462,7 @@
555 owner = self.factory.makePerson()462 owner = self.factory.makePerson()
556 name = self.factory.getUniqueString()463 name = self.factory.getUniqueString()
557 message = "User/team 'no-one' does not exist."464 message = "User/team 'no-one' does not exist."
558 fault = self.branchfs.createBranch(465 fault = self.codehosting_api.createBranch(
559 owner.id, escape('/~no-one/no-product/%s' % (name,)))466 owner.id, escape('/~no-one/no-product/%s' % (name,)))
560 self.assertEqual(faults.NotFound(message), fault)467 self.assertEqual(faults.NotFound(message), fault)
561468
@@ -564,7 +471,7 @@
564 # raises a PermissionDenied fault.471 # raises a PermissionDenied fault.
565 owner = self.factory.makePerson()472 owner = self.factory.makePerson()
566 path = escape('/~%s' % owner.name)473 path = escape('/~%s' % owner.name)
567 fault = self.branchfs.createBranch(owner.id, path)474 fault = self.codehosting_api.createBranch(owner.id, path)
568 message = "Cannot create branch at '%s'" % path475 message = "Cannot create branch at '%s'" % path
569 self.assertEqual(faults.PermissionDenied(message), fault)476 self.assertEqual(faults.PermissionDenied(message), fault)
570477
@@ -580,7 +487,8 @@
580 sourcepackage.distroseries.name,487 sourcepackage.distroseries.name,
581 sourcepackage.sourcepackagename.name,488 sourcepackage.sourcepackagename.name,
582 branch_name)489 branch_name)
583 branch_id = self.branchfs.createBranch(owner.id, escape(unique_name))490 branch_id = self.codehosting_api.createBranch(
491 owner.id, escape(unique_name))
584 login(ANONYMOUS)492 login(ANONYMOUS)
585 branch = self.branch_lookup.get(branch_id)493 branch = self.branch_lookup.get(branch_id)
586 self.assertEqual(owner, branch.owner)494 self.assertEqual(owner, branch.owner)
@@ -601,7 +509,7 @@
601 unique_name = '/~%s/ningnangnong/%s/%s/%s' % (509 unique_name = '/~%s/ningnangnong/%s/%s/%s' % (
602 owner.name, distroseries.name, sourcepackagename.name,510 owner.name, distroseries.name, sourcepackagename.name,
603 branch_name)511 branch_name)
604 fault = self.branchfs.createBranch(owner.id, escape(unique_name))512 fault = self.codehosting_api.createBranch(owner.id, escape(unique_name))
605 message = "No such distribution: 'ningnangnong'."513 message = "No such distribution: 'ningnangnong'."
606 self.assertEqual(faults.NotFound(message), fault)514 self.assertEqual(faults.NotFound(message), fault)
607515
@@ -615,7 +523,8 @@
615 unique_name = '/~%s/%s/ningnangnong/%s/%s' % (523 unique_name = '/~%s/%s/ningnangnong/%s/%s' % (
616 owner.name, distribution.name, sourcepackagename.name,524 owner.name, distribution.name, sourcepackagename.name,
617 branch_name)525 branch_name)
618 fault = self.branchfs.createBranch(owner.id, escape(unique_name))526 fault = self.codehosting_api.createBranch(
527 owner.id, escape(unique_name))
619 message = "No such distribution series: 'ningnangnong'."528 message = "No such distribution series: 'ningnangnong'."
620 self.assertEqual(faults.NotFound(message), fault)529 self.assertEqual(faults.NotFound(message), fault)
621530
@@ -628,7 +537,7 @@
628 unique_name = '/~%s/%s/%s/ningnangnong/%s' % (537 unique_name = '/~%s/%s/%s/ningnangnong/%s' % (
629 owner.name, distroseries.distribution.name, distroseries.name,538 owner.name, distroseries.distribution.name, distroseries.name,
630 branch_name)539 branch_name)
631 fault = self.branchfs.createBranch(owner.id, escape(unique_name))540 fault = self.codehosting_api.createBranch(owner.id, escape(unique_name))
632 message = "No such source package: 'ningnangnong'."541 message = "No such source package: 'ningnangnong'."
633 self.assertEqual(faults.NotFound(message), fault)542 self.assertEqual(faults.NotFound(message), fault)
634543
@@ -643,7 +552,7 @@
643 # current time.552 # current time.
644 requester = self.factory.makePerson()553 requester = self.factory.makePerson()
645 branch = self.factory.makeAnyBranch(branch_type=BranchType.HOSTED)554 branch = self.factory.makeAnyBranch(branch_type=BranchType.HOSTED)
646 self.branchfs.requestMirror(requester.id, branch.id)555 self.codehosting_api.requestMirror(requester.id, branch.id)
647 self.assertSqlAttributeEqualsDate(556 self.assertSqlAttributeEqualsDate(
648 branch, 'next_mirror_time', UTC_NOW)557 branch, 'next_mirror_time', UTC_NOW)
649558
@@ -652,7 +561,7 @@
652 requester = self.factory.makePerson()561 requester = self.factory.makePerson()
653 branch = self.factory.makeAnyBranch(owner=requester, private=True)562 branch = self.factory.makeAnyBranch(owner=requester, private=True)
654 branch = removeSecurityProxy(branch)563 branch = removeSecurityProxy(branch)
655 self.branchfs.requestMirror(requester.id, branch.id)564 self.codehosting_api.requestMirror(requester.id, branch.id)
656 self.assertSqlAttributeEqualsDate(565 self.assertSqlAttributeEqualsDate(
657 branch, 'next_mirror_time', UTC_NOW)566 branch, 'next_mirror_time', UTC_NOW)
658567
@@ -672,7 +581,7 @@
672 # branchChanged sets the last_mirrored_id attribute on the branch.581 # branchChanged sets the last_mirrored_id attribute on the branch.
673 revid = self.factory.getUniqueString()582 revid = self.factory.getUniqueString()
674 branch = self.factory.makeAnyBranch()583 branch = self.factory.makeAnyBranch()
675 self.branchfs.branchChanged(584 self.codehosting_api.branchChanged(
676 branch.id, '', revid, *self.arbitrary_format_strings)585 branch.id, '', revid, *self.arbitrary_format_strings)
677 self.assertEqual(revid, branch.last_mirrored_id)586 self.assertEqual(revid, branch.last_mirrored_id)
678587
@@ -681,7 +590,7 @@
681 # passed in.590 # passed in.
682 branch = self.factory.makeAnyBranch()591 branch = self.factory.makeAnyBranch()
683 stacked_on = self.factory.makeAnyBranch()592 stacked_on = self.factory.makeAnyBranch()
684 self.branchfs.branchChanged(593 self.codehosting_api.branchChanged(
685 branch.id, stacked_on.unique_name, '',594 branch.id, stacked_on.unique_name, '',
686 *self.arbitrary_format_strings)595 *self.arbitrary_format_strings)
687 self.assertEqual(stacked_on, branch.stacked_on)596 self.assertEqual(stacked_on, branch.stacked_on)
@@ -691,7 +600,7 @@
691 # passed in as the stacked_on location.600 # passed in as the stacked_on location.
692 branch = self.factory.makeAnyBranch()601 branch = self.factory.makeAnyBranch()
693 removeSecurityProxy(branch).stacked_on = self.factory.makeAnyBranch()602 removeSecurityProxy(branch).stacked_on = self.factory.makeAnyBranch()
694 self.branchfs.branchChanged(603 self.codehosting_api.branchChanged(
695 branch.id, '', '', *self.arbitrary_format_strings)604 branch.id, '', '', *self.arbitrary_format_strings)
696 self.assertIs(None, branch.stacked_on)605 self.assertIs(None, branch.stacked_on)
697606
@@ -699,7 +608,7 @@
699 # branchChanged sets the last_mirrored attribute on the branch to the608 # branchChanged sets the last_mirrored attribute on the branch to the
700 # current time.609 # current time.
701 branch = self.factory.makeAnyBranch()610 branch = self.factory.makeAnyBranch()
702 self.branchfs.branchChanged(611 self.codehosting_api.branchChanged(
703 branch.id, '', '', *self.arbitrary_format_strings)612 branch.id, '', '', *self.arbitrary_format_strings)
704 if self.frontend == LaunchpadDatabaseFrontend:613 if self.frontend == LaunchpadDatabaseFrontend:
705 self.assertSqlAttributeEqualsDate(614 self.assertSqlAttributeEqualsDate(
@@ -712,7 +621,7 @@
712 # mirror_status_message is set to indicate the problem and stacked_on621 # mirror_status_message is set to indicate the problem and stacked_on
713 # set to None.622 # set to None.
714 branch = self.factory.makeAnyBranch()623 branch = self.factory.makeAnyBranch()
715 self.branchfs.branchChanged(624 self.codehosting_api.branchChanged(
716 branch.id, '~does/not/exist', '', *self.arbitrary_format_strings)625 branch.id, '~does/not/exist', '', *self.arbitrary_format_strings)
717 self.assertIs(None, branch.stacked_on)626 self.assertIs(None, branch.stacked_on)
718 self.assertTrue('~does/not/exist' in branch.mirror_status_message)627 self.assertTrue('~does/not/exist' in branch.mirror_status_message)
@@ -722,7 +631,7 @@
722 # mirror_status_message.631 # mirror_status_message.
723 branch = self.factory.makeAnyBranch()632 branch = self.factory.makeAnyBranch()
724 removeSecurityProxy(branch).mirror_status_message = 'foo'633 removeSecurityProxy(branch).mirror_status_message = 'foo'
725 self.branchfs.branchChanged(634 self.codehosting_api.branchChanged(
726 branch.id, '', '', *self.arbitrary_format_strings)635 branch.id, '', '', *self.arbitrary_format_strings)
727 self.assertIs(None, branch.mirror_status_message)636 self.assertIs(None, branch.mirror_status_message)
728637
@@ -731,7 +640,7 @@
731 # "NoBranchWithID" is returned.640 # "NoBranchWithID" is returned.
732 unused_id = -1641 unused_id = -1
733 expected_fault = faults.NoBranchWithID(unused_id)642 expected_fault = faults.NoBranchWithID(unused_id)
734 received_fault = self.branchfs.branchChanged(643 received_fault = self.codehosting_api.branchChanged(
735 unused_id, '', '', *self.arbitrary_format_strings)644 unused_id, '', '', *self.arbitrary_format_strings)
736 self.assertEqual(645 self.assertEqual(
737 (expected_fault.faultCode, expected_fault.faultString),646 (expected_fault.faultCode, expected_fault.faultString),
@@ -744,7 +653,7 @@
744 branch = self.factory.makeAnyBranch()653 branch = self.factory.makeAnyBranch()
745 jobs = list(getUtility(IBranchScanJobSource).iterReady())654 jobs = list(getUtility(IBranchScanJobSource).iterReady())
746 self.assertEqual(0, len(jobs))655 self.assertEqual(0, len(jobs))
747 self.branchfs.branchChanged(656 self.codehosting_api.branchChanged(
748 branch.id, '', 'rev1', *self.arbitrary_format_strings)657 branch.id, '', 'rev1', *self.arbitrary_format_strings)
749 jobs = list(getUtility(IBranchScanJobSource).iterReady())658 jobs = list(getUtility(IBranchScanJobSource).iterReady())
750 self.assertEqual(1, len(jobs))659 self.assertEqual(1, len(jobs))
@@ -756,14 +665,14 @@
756 removeSecurityProxy(branch).last_mirrored_id = 'rev1'665 removeSecurityProxy(branch).last_mirrored_id = 'rev1'
757 jobs = list(getUtility(IBranchScanJobSource).iterReady())666 jobs = list(getUtility(IBranchScanJobSource).iterReady())
758 self.assertEqual(0, len(jobs))667 self.assertEqual(0, len(jobs))
759 self.branchfs.branchChanged(668 self.codehosting_api.branchChanged(
760 branch.id, '', 'rev1', *self.arbitrary_format_strings)669 branch.id, '', 'rev1', *self.arbitrary_format_strings)
761 jobs = list(getUtility(IBranchScanJobSource).iterReady())670 jobs = list(getUtility(IBranchScanJobSource).iterReady())
762 self.assertEqual(0, len(jobs))671 self.assertEqual(0, len(jobs))
763672
764 def test_branchChanged_2a_format(self):673 def test_branchChanged_2a_format(self):
765 branch = self.factory.makeAnyBranch()674 branch = self.factory.makeAnyBranch()
766 self.branchfs.branchChanged(675 self.codehosting_api.branchChanged(
767 branch.id, '', 'rev1', *self.getFormatStringsForFormatName('2a'))676 branch.id, '', 'rev1', *self.getFormatStringsForFormatName('2a'))
768 self.assertEqual(677 self.assertEqual(
769 (ControlFormat.BZR_METADIR_1, BranchFormat.BZR_BRANCH_7,678 (ControlFormat.BZR_METADIR_1, BranchFormat.BZR_BRANCH_7,
@@ -773,7 +682,7 @@
773682
774 def test_branchChanged_packs_format(self):683 def test_branchChanged_packs_format(self):
775 branch = self.factory.makeAnyBranch()684 branch = self.factory.makeAnyBranch()
776 self.branchfs.branchChanged(685 self.codehosting_api.branchChanged(
777 branch.id, '', 'rev1',686 branch.id, '', 'rev1',
778 *self.getFormatStringsForFormatName('pack-0.92'))687 *self.getFormatStringsForFormatName('pack-0.92'))
779 self.assertEqual(688 self.assertEqual(
@@ -784,7 +693,7 @@
784693
785 def test_branchChanged_knits_format(self):694 def test_branchChanged_knits_format(self):
786 branch = self.factory.makeAnyBranch()695 branch = self.factory.makeAnyBranch()
787 self.branchfs.branchChanged(696 self.codehosting_api.branchChanged(
788 branch.id, '', 'rev1',697 branch.id, '', 'rev1',
789 *self.getFormatStringsForFormatName('knit'))698 *self.getFormatStringsForFormatName('knit'))
790 self.assertEqual(699 self.assertEqual(
@@ -795,21 +704,21 @@
795704
796 def assertCannotTranslate(self, requester, path):705 def assertCannotTranslate(self, requester, path):
797 """Assert that we cannot translate 'path'."""706 """Assert that we cannot translate 'path'."""
798 fault = self.branchfs.translatePath(requester.id, path)707 fault = self.codehosting_api.translatePath(requester.id, path)
799 self.assertEqual(faults.PathTranslationError(path), fault)708 self.assertEqual(faults.PathTranslationError(path), fault)
800709
801 def assertNotFound(self, requester, path):710 def assertNotFound(self, requester, path):
802 """Assert that the given path cannot be found."""711 """Assert that the given path cannot be found."""
803 if requester not in [LAUNCHPAD_ANONYMOUS, LAUNCHPAD_SERVICES]:712 if requester not in [LAUNCHPAD_ANONYMOUS, LAUNCHPAD_SERVICES]:
804 requester = requester.id713 requester = requester.id
805 fault = self.branchfs.translatePath(requester, path)714 fault = self.codehosting_api.translatePath(requester, path)
806 self.assertEqual(faults.PathTranslationError(path), fault)715 self.assertEqual(faults.PathTranslationError(path), fault)
807716
808 def assertPermissionDenied(self, requester, path):717 def assertPermissionDenied(self, requester, path):
809 """Assert that looking at the given path gives permission denied."""718 """Assert that looking at the given path gives permission denied."""
810 if requester not in [LAUNCHPAD_ANONYMOUS, LAUNCHPAD_SERVICES]:719 if requester not in [LAUNCHPAD_ANONYMOUS, LAUNCHPAD_SERVICES]:
811 requester = requester.id720 requester = requester.id
812 fault = self.branchfs.translatePath(requester, path)721 fault = self.codehosting_api.translatePath(requester, path)
813 self.assertEqual(faults.PermissionDenied(), fault)722 self.assertEqual(faults.PermissionDenied(), fault)
814723
815 def _makeProductWithDevFocus(self, private=False):724 def _makeProductWithDevFocus(self, private=False):
@@ -837,14 +746,14 @@
837 def test_translatePath_no_preceding_slash(self):746 def test_translatePath_no_preceding_slash(self):
838 requester = self.factory.makePerson()747 requester = self.factory.makePerson()
839 path = escape(u'invalid')748 path = escape(u'invalid')
840 fault = self.branchfs.translatePath(requester.id, path)749 fault = self.codehosting_api.translatePath(requester.id, path)
841 self.assertEqual(faults.InvalidPath(path), fault)750 self.assertEqual(faults.InvalidPath(path), fault)
842751
843 def test_translatePath_branch(self):752 def test_translatePath_branch(self):
844 requester = self.factory.makePerson()753 requester = self.factory.makePerson()
845 branch = self.factory.makeAnyBranch()754 branch = self.factory.makeAnyBranch()
846 path = escape(u'/%s' % branch.unique_name)755 path = escape(u'/%s' % branch.unique_name)
847 translation = self.branchfs.translatePath(requester.id, path)756 translation = self.codehosting_api.translatePath(requester.id, path)
848 login(ANONYMOUS)757 login(ANONYMOUS)
849 self.assertEqual(758 self.assertEqual(
850 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),759 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),
@@ -854,7 +763,7 @@
854 requester = self.factory.makePerson()763 requester = self.factory.makePerson()
855 branch = self.factory.makeAnyBranch()764 branch = self.factory.makeAnyBranch()
856 path = escape(u'/%s/' % branch.unique_name)765 path = escape(u'/%s/' % branch.unique_name)
857 translation = self.branchfs.translatePath(requester.id, path)766 translation = self.codehosting_api.translatePath(requester.id, path)
858 login(ANONYMOUS)767 login(ANONYMOUS)
859 self.assertEqual(768 self.assertEqual(
860 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),769 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),
@@ -864,7 +773,7 @@
864 requester = self.factory.makePerson()773 requester = self.factory.makePerson()
865 branch = self.factory.makeAnyBranch()774 branch = self.factory.makeAnyBranch()
866 path = escape(u'/%s/child' % branch.unique_name)775 path = escape(u'/%s/child' % branch.unique_name)
867 translation = self.branchfs.translatePath(requester.id, path)776 translation = self.codehosting_api.translatePath(requester.id, path)
868 login(ANONYMOUS)777 login(ANONYMOUS)
869 self.assertEqual(778 self.assertEqual(
870 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, 'child'),779 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, 'child'),
@@ -874,7 +783,7 @@
874 requester = self.factory.makePerson()783 requester = self.factory.makePerson()
875 branch = self.factory.makeAnyBranch()784 branch = self.factory.makeAnyBranch()
876 path = escape(u'/%s/a/b' % branch.unique_name)785 path = escape(u'/%s/a/b' % branch.unique_name)
877 translation = self.branchfs.translatePath(requester.id, path)786 translation = self.codehosting_api.translatePath(requester.id, path)
878 login(ANONYMOUS)787 login(ANONYMOUS)
879 self.assertEqual(788 self.assertEqual(
880 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, 'a/b'),789 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, 'a/b'),
@@ -888,7 +797,7 @@
888 # escaped.797 # escaped.
889 self.assertNotEqual(escape(child_path), child_path.encode('utf-8'))798 self.assertNotEqual(escape(child_path), child_path.encode('utf-8'))
890 path = escape(u'/%s/%s' % (branch.unique_name, child_path))799 path = escape(u'/%s/%s' % (branch.unique_name, child_path))
891 translation = self.branchfs.translatePath(requester.id, path)800 translation = self.codehosting_api.translatePath(requester.id, path)
892 login(ANONYMOUS)801 login(ANONYMOUS)
893 self.assertEqual(802 self.assertEqual(
894 (BRANCH_TRANSPORT,803 (BRANCH_TRANSPORT,
@@ -925,7 +834,7 @@
925 self.factory.makeAnyBranch(834 self.factory.makeAnyBranch(
926 branch_type=BranchType.HOSTED, private=True, owner=requester))835 branch_type=BranchType.HOSTED, private=True, owner=requester))
927 path = escape(u'/%s' % branch.unique_name)836 path = escape(u'/%s' % branch.unique_name)
928 translation = self.branchfs.translatePath(requester.id, path)837 translation = self.codehosting_api.translatePath(requester.id, path)
929 login(ANONYMOUS)838 login(ANONYMOUS)
930 self.assertEqual(839 self.assertEqual(
931 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': True}, ''),840 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': True}, ''),
@@ -946,7 +855,8 @@
946 def test_translatePath_launchpad_services_private(self):855 def test_translatePath_launchpad_services_private(self):
947 branch = removeSecurityProxy(self.factory.makeAnyBranch(private=True))856 branch = removeSecurityProxy(self.factory.makeAnyBranch(private=True))
948 path = escape(u'/%s' % branch.unique_name)857 path = escape(u'/%s' % branch.unique_name)
949 translation = self.branchfs.translatePath(LAUNCHPAD_SERVICES, path)858 translation = self.codehosting_api.translatePath(
859 LAUNCHPAD_SERVICES, path)
950 login(ANONYMOUS)860 login(ANONYMOUS)
951 self.assertEqual(861 self.assertEqual(
952 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),862 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),
@@ -960,7 +870,8 @@
960 def test_translatePath_anonymous_public_branch(self):870 def test_translatePath_anonymous_public_branch(self):
961 branch = self.factory.makeAnyBranch()871 branch = self.factory.makeAnyBranch()
962 path = escape(u'/%s' % branch.unique_name)872 path = escape(u'/%s' % branch.unique_name)
963 translation = self.branchfs.translatePath(LAUNCHPAD_ANONYMOUS, path)873 translation = self.codehosting_api.translatePath(
874 LAUNCHPAD_ANONYMOUS, path)
964 self.assertEqual(875 self.assertEqual(
965 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),876 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),
966 translation)877 translation)
@@ -970,7 +881,7 @@
970 branch = self.factory.makeAnyBranch(881 branch = self.factory.makeAnyBranch(
971 branch_type=BranchType.HOSTED, owner=requester)882 branch_type=BranchType.HOSTED, owner=requester)
972 path = escape(u'/%s' % branch.unique_name)883 path = escape(u'/%s' % branch.unique_name)
973 translation = self.branchfs.translatePath(requester.id, path)884 translation = self.codehosting_api.translatePath(requester.id, path)
974 login(ANONYMOUS)885 login(ANONYMOUS)
975 self.assertEqual(886 self.assertEqual(
976 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': True}, ''),887 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': True}, ''),
@@ -982,7 +893,7 @@
982 branch = self.factory.makeAnyBranch(893 branch = self.factory.makeAnyBranch(
983 branch_type=BranchType.HOSTED, owner=team)894 branch_type=BranchType.HOSTED, owner=team)
984 path = escape(u'/%s' % branch.unique_name)895 path = escape(u'/%s' % branch.unique_name)
985 translation = self.branchfs.translatePath(requester.id, path)896 translation = self.codehosting_api.translatePath(requester.id, path)
986 login(ANONYMOUS)897 login(ANONYMOUS)
987 self.assertEqual(898 self.assertEqual(
988 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': True}, ''),899 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': True}, ''),
@@ -994,7 +905,7 @@
994 branch = self.factory.makeAnyBranch(905 branch = self.factory.makeAnyBranch(
995 branch_type=BranchType.HOSTED, owner=team)906 branch_type=BranchType.HOSTED, owner=team)
996 path = escape(u'/%s' % branch.unique_name)907 path = escape(u'/%s' % branch.unique_name)
997 translation = self.branchfs.translatePath(requester.id, path)908 translation = self.codehosting_api.translatePath(requester.id, path)
998 login(ANONYMOUS)909 login(ANONYMOUS)
999 self.assertEqual(910 self.assertEqual(
1000 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),911 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),
@@ -1005,7 +916,7 @@
1005 branch = self.factory.makeAnyBranch(916 branch = self.factory.makeAnyBranch(
1006 branch_type=BranchType.MIRRORED, owner=requester)917 branch_type=BranchType.MIRRORED, owner=requester)
1007 path = escape(u'/%s' % branch.unique_name)918 path = escape(u'/%s' % branch.unique_name)
1008 translation = self.branchfs.translatePath(requester.id, path)919 translation = self.codehosting_api.translatePath(requester.id, path)
1009 login(ANONYMOUS)920 login(ANONYMOUS)
1010 self.assertEqual(921 self.assertEqual(
1011 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),922 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),
@@ -1016,7 +927,7 @@
1016 branch = self.factory.makeAnyBranch(927 branch = self.factory.makeAnyBranch(
1017 branch_type=BranchType.IMPORTED, owner=requester)928 branch_type=BranchType.IMPORTED, owner=requester)
1018 path = escape(u'/%s' % branch.unique_name)929 path = escape(u'/%s' % branch.unique_name)
1019 translation = self.branchfs.translatePath(requester.id, path)930 translation = self.codehosting_api.translatePath(requester.id, path)
1020 login(ANONYMOUS)931 login(ANONYMOUS)
1021 self.assertEqual(932 self.assertEqual(
1022 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),933 (BRANCH_TRANSPORT, {'id': branch.id, 'writable': False}, ''),
@@ -1036,7 +947,7 @@
1036 requester = self.factory.makePerson()947 requester = self.factory.makePerson()
1037 product, branch = self._makeProductWithDevFocus()948 product, branch = self._makeProductWithDevFocus()
1038 path = escape(u'/~%s/%s/.bzr' % (requester.name, product.name))949 path = escape(u'/~%s/%s/.bzr' % (requester.name, product.name))
1039 translation = self.branchfs.translatePath(requester.id, path)950 translation = self.codehosting_api.translatePath(requester.id, path)
1040 login(ANONYMOUS)951 login(ANONYMOUS)
1041 self.assertTranslationIsControlDirectory(952 self.assertTranslationIsControlDirectory(
1042 translation,953 translation,
@@ -1062,7 +973,7 @@
1062 branch = removeSecurityProxy(branch)973 branch = removeSecurityProxy(branch)
1063 requester = branch.owner974 requester = branch.owner
1064 path = escape(u'/~%s/%s/.bzr/' % (requester.name, product.name))975 path = escape(u'/~%s/%s/.bzr/' % (requester.name, product.name))
1065 translation = self.branchfs.translatePath(requester.id, path)976 translation = self.codehosting_api.translatePath(requester.id, path)
1066 login(ANONYMOUS)977 login(ANONYMOUS)
1067 self.assertTranslationIsControlDirectory(978 self.assertTranslationIsControlDirectory(
1068 translation,979 translation,
@@ -1074,7 +985,7 @@
1074 product, branch = self._makeProductWithDevFocus()985 product, branch = self._makeProductWithDevFocus()
1075 owner = self.factory.makePerson()986 owner = self.factory.makePerson()
1076 path = escape(u'/~%s/%s/.bzr' % (owner.name, product.name))987 path = escape(u'/~%s/%s/.bzr' % (owner.name, product.name))
1077 translation = self.branchfs.translatePath(requester.id, path)988 translation = self.codehosting_api.translatePath(requester.id, path)
1078 login(ANONYMOUS)989 login(ANONYMOUS)
1079 self.assertTranslationIsControlDirectory(990 self.assertTranslationIsControlDirectory(
1080 translation,991 translation,
@@ -1100,7 +1011,7 @@
1100 self.assertIsNot(1011 self.assertIsNot(
1101 None, IBranchTarget(package).default_stacked_on_branch)1012 None, IBranchTarget(package).default_stacked_on_branch)
1102 path = '/~%s/%s/.bzr/' % (requester.name, package.path)1013 path = '/~%s/%s/.bzr/' % (requester.name, package.path)
1103 translation = self.branchfs.translatePath(requester.id, path)1014 translation = self.codehosting_api.translatePath(requester.id, path)
1104 login(ANONYMOUS)1015 login(ANONYMOUS)
1105 self.assertTranslationIsControlDirectory(1016 self.assertTranslationIsControlDirectory(
1106 translation,1017 translation,
@@ -1108,6 +1019,89 @@
1108 trailing_path='.bzr')1019 trailing_path='.bzr')
11091020
11101021
1022class AcquireBranchToPullTestsViaEndpoint(TestCaseWithFactory,
1023 AcquireBranchToPullTests):
1024 """Tests for `acquireBranchToPull` method of `ICodehostingAPI`."""
1025
1026 def setUp(self):
1027 super(AcquireBranchToPullTestsViaEndpoint, self).setUp()
1028 frontend = self.frontend()
1029 self.codehosting_api = frontend.getCodehostingEndpoint()
1030 self.factory = frontend.getLaunchpadObjectFactory()
1031
1032 def assertNoBranchIsAquired(self, *branch_types):
1033 """See `AcquireBranchToPullTests`."""
1034 branch_types = tuple(branch_type.name for branch_type in branch_types)
1035 pull_info = self.codehosting_api.acquireBranchToPull(branch_types)
1036 self.assertEqual((), pull_info)
1037
1038 def assertBranchIsAquired(self, branch, *branch_types):
1039 """See `AcquireBranchToPullTests`."""
1040 branch = removeSecurityProxy(branch)
1041 branch_types = tuple(branch_type.name for branch_type in branch_types)
1042 pull_info = self.codehosting_api.acquireBranchToPull(branch_types)
1043 default_branch = branch.target.default_stacked_on_branch
1044 if default_branch:
1045 default_branch_name = default_branch
1046 else:
1047 default_branch_name = ''
1048 self.assertEqual(
1049 pull_info,
1050 (branch.id, branch.getPullURL(), branch.unique_name,
1051 default_branch_name, branch.branch_type.name))
1052 self.assertIsNot(None, branch.last_mirror_attempt)
1053 self.assertIs(None, branch.next_mirror_time)
1054
1055 def startMirroring(self, branch):
1056 """See `AcquireBranchToPullTests`."""
1057 self.codehosting_api.startMirroring(branch.id)
1058
1059 def test_branch_type_returned_mirrored(self):
1060 branch = self.factory.makeAnyBranch(branch_type=BranchType.MIRRORED)
1061 branch.requestMirror()
1062 pull_info = self.codehosting_api.acquireBranchToPull(())
1063 _, _, _, _, branch_type = pull_info
1064 self.assertEqual('MIRRORED', branch_type)
1065
1066 def test_branch_type_returned_import(self):
1067 branch = self.factory.makeAnyBranch(branch_type=BranchType.IMPORTED)
1068 branch.requestMirror()
1069 pull_info = self.codehosting_api.acquireBranchToPull(())
1070 _, _, _, _, branch_type = pull_info
1071 self.assertEqual('IMPORTED', branch_type)
1072
1073 def test_default_stacked_on_branch_returned(self):
1074 branch = self.factory.makeProductBranch(
1075 branch_type=BranchType.MIRRORED)
1076 self.factory.enableDefaultStackingForProduct(branch.product)
1077 branch.requestMirror()
1078 pull_info = self.codehosting_api.acquireBranchToPull(())
1079 _, _, _, default_stacked_on_branch, _ = pull_info
1080 self.assertEqual(
1081 default_stacked_on_branch,
1082 '/' + branch.target.default_stacked_on_branch.unique_name)
1083
1084 def test_private_default_stacked_not_returned_for_mirrored_branch(self):
1085 # We don't stack mirrored branches on a private default stacked on
1086 # branch.
1087 product = self.factory.makeProduct()
1088 default_branch = self.factory.makeProductBranch(
1089 product=product, private=True)
1090 self.factory.enableDefaultStackingForProduct(product, default_branch)
1091 mirrored_branch = self.factory.makeProductBranch(
1092 branch_type=BranchType.MIRRORED, product=product)
1093 mirrored_branch.requestMirror()
1094 pull_info = self.codehosting_api.acquireBranchToPull(())
1095 _, _, _, default_stacked_on_branch, _ = pull_info
1096 self.assertEqual(
1097 '', default_stacked_on_branch)
1098
1099 def test_unknown_branch_type_name_raises(self):
1100 self.assertRaises(
1101 UnknownBranchTypeError, self.codehosting_api.acquireBranchToPull,
1102 ('NO_SUCH_TYPE',))
1103
1104
1111class LaunchpadDatabaseFrontend:1105class LaunchpadDatabaseFrontend:
1112 """A 'frontend' to Launchpad's branch services.1106 """A 'frontend' to Launchpad's branch services.
11131107
@@ -1119,13 +1113,9 @@
1119 alternative implementations can be provided, see `InMemoryFrontend`.1113 alternative implementations can be provided, see `InMemoryFrontend`.
1120 """1114 """
11211115
1122 def getFilesystemEndpoint(self):1116 def getCodehostingEndpoint(self):
1123 """Return the branch filesystem endpoint for testing."""1117 """Return the branch filesystem endpoint for testing."""
1124 return BranchFileSystem(None, None)1118 return CodehostingAPI(None, None)
1125
1126 def getPullerEndpoint(self):
1127 """Return the branch puller endpoint for testing."""
1128 return BranchPuller(None, None)
11291119
1130 def getLaunchpadObjectFactory(self):1120 def getLaunchpadObjectFactory(self):
1131 """Return the Launchpad object factory for testing.1121 """Return the Launchpad object factory for testing.
@@ -1148,13 +1138,13 @@
1148 return getUtility(IScriptActivitySet).getLastActivity(activity_name)1138 return getUtility(IScriptActivitySet).getLastActivity(activity_name)
11491139
11501140
1141
1151def test_suite():1142def test_suite():
1152 loader = unittest.TestLoader()1143 loader = unittest.TestLoader()
1153 suite = unittest.TestSuite()1144 suite = unittest.TestSuite()
1154 puller_tests = unittest.TestSuite(1145 endpoint_tests = unittest.TestSuite(
1155 [loader.loadTestsFromTestCase(BranchPullerTest),1146 [loader.loadTestsFromTestCase(AcquireBranchToPullTestsViaEndpoint),
1156 loader.loadTestsFromTestCase(AcquireBranchToPullTestsViaEndpoint),1147 loader.loadTestsFromTestCase(CodehostingTest),
1157 loader.loadTestsFromTestCase(BranchFileSystemTest),
1158 ])1148 ])
1159 scenarios = [1149 scenarios = [
1160 ('db', {'frontend': LaunchpadDatabaseFrontend,1150 ('db', {'frontend': LaunchpadDatabaseFrontend,
@@ -1162,6 +1152,6 @@
1162 ('inmemory', {'frontend': InMemoryFrontend,1152 ('inmemory', {'frontend': InMemoryFrontend,
1163 'layer': FunctionalLayer}),1153 'layer': FunctionalLayer}),
1164 ]1154 ]
1165 multiply_tests(puller_tests, scenarios, suite)1155 multiply_tests(endpoint_tests, scenarios, suite)
1166 suite.addTests(loader.loadTestsFromTestCase(TestRunWithLogin))1156 suite.addTests(loader.loadTestsFromTestCase(TestRunWithLogin))
1167 return suite1157 return suite
11681158
=== modified file 'lib/lp/codehosting/inmemory.py'
--- lib/lp/codehosting/inmemory.py 2010-04-27 02:11:16 +0000
+++ lib/lp/codehosting/inmemory.py 2010-04-27 02:11:35 +0000
@@ -449,10 +449,18 @@
449 return branch449 return branch
450450
451451
452class FakeBranchPuller:452class FakeCodehosting:
453453
454 def __init__(self, branch_set, script_activity_set):454 def __init__(self, branch_set, person_set, product_set, distribution_set,
455 distroseries_set, sourcepackagename_set, factory,
456 script_activity_set):
455 self._branch_set = branch_set457 self._branch_set = branch_set
458 self._person_set = person_set
459 self._product_set = product_set
460 self._distribution_set = distribution_set
461 self._distroseries_set = distroseries_set
462 self._sourcepackagename_set = sourcepackagename_set
463 self._factory = factory
456 self._script_activity_set = script_activity_set464 self._script_activity_set = script_activity_set
457465
458 def acquireBranchToPull(self, branch_type_names):466 def acquireBranchToPull(self, branch_type_names):
@@ -538,19 +546,6 @@
538 return faults.NoSuchBranch(stacked_on_location)546 return faults.NoSuchBranch(stacked_on_location)
539 return True547 return True
540548
541
542class FakeBranchFilesystem:
543
544 def __init__(self, branch_set, person_set, product_set, distribution_set,
545 distroseries_set, sourcepackagename_set, factory):
546 self._branch_set = branch_set
547 self._person_set = person_set
548 self._product_set = product_set
549 self._distribution_set = distribution_set
550 self._distroseries_set = distroseries_set
551 self._sourcepackagename_set = sourcepackagename_set
552 self._factory = factory
553
554 def createBranch(self, requester_id, branch_path):549 def createBranch(self, requester_id, branch_path):
555 if not branch_path.startswith('/'):550 if not branch_path.startswith('/'):
556 return faults.InvalidPath(branch_path)551 return faults.InvalidPath(branch_path)
@@ -780,31 +775,22 @@
780 self._branch_set, self._person_set, self._product_set,775 self._branch_set, self._person_set, self._product_set,
781 self._distribution_set, self._distroseries_set,776 self._distribution_set, self._distroseries_set,
782 self._sourcepackagename_set)777 self._sourcepackagename_set)
783 self._puller = FakeBranchPuller(778 self._codehosting = FakeCodehosting(
784 self._branch_set, self._script_activity_set)
785 self._branchfs = FakeBranchFilesystem(
786 self._branch_set, self._person_set, self._product_set,779 self._branch_set, self._person_set, self._product_set,
787 self._distribution_set, self._distroseries_set,780 self._distribution_set, self._distroseries_set,
788 self._sourcepackagename_set, self._factory)781 self._sourcepackagename_set, self._factory,
782 self._script_activity_set)
789 sm = getSiteManager()783 sm = getSiteManager()
790 sm.registerAdapter(fake_product_to_branch_target)784 sm.registerAdapter(fake_product_to_branch_target)
791 sm.registerAdapter(fake_source_package_to_branch_target)785 sm.registerAdapter(fake_source_package_to_branch_target)
792786
793 def getFilesystemEndpoint(self):787 def getCodehostingEndpoint(self):
794 """See `LaunchpadDatabaseFrontend`.788 """See `LaunchpadDatabaseFrontend`.
795789
796 Return an in-memory implementation of IBranchFileSystem that passes790 Return an in-memory implementation of IBranchFileSystem that passes
797 the tests in `test_codehosting`.791 the tests in `test_codehosting`.
798 """792 """
799 return self._branchfs793 return self._codehosting
800
801 def getPullerEndpoint(self):
802 """See `LaunchpadDatabaseFrontend`.
803
804 Return an in-memory implementation of IBranchPuller that passes the
805 tests in `test_codehosting`.
806 """
807 return self._puller
808794
809 def getLaunchpadObjectFactory(self):795 def getLaunchpadObjectFactory(self):
810 """See `LaunchpadDatabaseFrontend`.796 """See `LaunchpadDatabaseFrontend`.
811797
=== modified file 'lib/lp/codehosting/puller/scheduler.py'
--- lib/lp/codehosting/puller/scheduler.py 2010-04-27 02:11:16 +0000
+++ lib/lp/codehosting/puller/scheduler.py 2010-04-27 02:11:35 +0000
@@ -296,7 +296,7 @@
296 self.branch_type_name = branch_type_name296 self.branch_type_name = branch_type_name
297 self.default_stacked_on_url = default_stacked_on_url297 self.default_stacked_on_url = default_stacked_on_url
298 self.logger = logger298 self.logger = logger
299 self.branch_puller_endpoint = client299 self.codehosting_endpoint = client
300 self._available_oops_prefixes = available_oops_prefixes300 self._available_oops_prefixes = available_oops_prefixes
301301
302 @cachedproperty302 @cachedproperty
@@ -348,7 +348,7 @@
348 return deferred348 return deferred
349349
350 def setStackedOn(self, stacked_on_location):350 def setStackedOn(self, stacked_on_location):
351 deferred = self.branch_puller_endpoint.callRemote(351 deferred = self.codehosting_endpoint.callRemote(
352 'setStackedOn', self.branch_id, stacked_on_location)352 'setStackedOn', self.branch_id, stacked_on_location)
353 def no_such_branch(failure):353 def no_such_branch(failure):
354 # If there's no branch for stacked_on_location, then we just354 # If there's no branch for stacked_on_location, then we just
@@ -365,7 +365,7 @@
365 def mirrorFailed(self, reason, oops):365 def mirrorFailed(self, reason, oops):
366 self.logger.info('Recorded %s', oops)366 self.logger.info('Recorded %s', oops)
367 self.logger.info('Recorded failure: %s', str(reason))367 self.logger.info('Recorded failure: %s', str(reason))
368 return self.branch_puller_endpoint.callRemote(368 return self.codehosting_endpoint.callRemote(
369 'mirrorFailed', self.branch_id, reason)369 'mirrorFailed', self.branch_id, reason)
370370
371 def mirrorSucceeded(self, revid_before, revid_after):371 def mirrorSucceeded(self, revid_before, revid_after):
@@ -377,7 +377,7 @@
377 'Successfully mirrored %s branch %d %s to %s to from rev %s to %s'377 'Successfully mirrored %s branch %d %s to %s to from rev %s to %s'
378 ' (%s)', self.branch_type_name, self.branch_id, self.source_url,378 ' (%s)', self.branch_type_name, self.branch_id, self.source_url,
379 self.destination_url, revid_before, revid_after, was_noop)379 self.destination_url, revid_before, revid_after, was_noop)
380 return self.branch_puller_endpoint.callRemote(380 return self.codehosting_endpoint.callRemote(
381 'mirrorComplete', self.branch_id, revid_after)381 'mirrorComplete', self.branch_id, revid_after)
382382
383 def log(self, message):383 def log(self, message):
@@ -411,8 +411,8 @@
411 branches.411 branches.
412 """412 """
413413
414 def __init__(self, branch_puller_endpoint, logger, branch_type_names):414 def __init__(self, codehosting_endpoint, logger, branch_type_names):
415 self.branch_puller_endpoint = branch_puller_endpoint415 self.codehosting_endpoint = codehosting_endpoint
416 self.logger = logger416 self.logger = logger
417 self.branch_type_names = branch_type_names417 self.branch_type_names = branch_type_names
418 self.actualLock = None418 self.actualLock = None
@@ -445,11 +445,11 @@
445 master = PullerMaster(445 master = PullerMaster(
446 branch_id, pull_url, unique_name, branch_type_name,446 branch_id, pull_url, unique_name, branch_type_name,
447 default_stacked_on_url, self.logger,447 default_stacked_on_url, self.logger,
448 self.branch_puller_endpoint, self.available_oops_prefixes)448 self.codehosting_endpoint, self.available_oops_prefixes)
449 return master.run449 return master.run
450450
451 def _poll(self):451 def _poll(self):
452 deferred = self.branch_puller_endpoint.callRemote(452 deferred = self.codehosting_endpoint.callRemote(
453 'acquireBranchToPull', self.branch_type_names)453 'acquireBranchToPull', self.branch_type_names)
454 deferred.addCallback(self._turnJobTupleIntoTask)454 deferred.addCallback(self._turnJobTupleIntoTask)
455 return deferred455 return deferred
@@ -483,7 +483,7 @@
483 """Record successful completion of the script."""483 """Record successful completion of the script."""
484 started_tuple = tuple(date_started.utctimetuple())484 started_tuple = tuple(date_started.utctimetuple())
485 completed_tuple = tuple(date_completed.utctimetuple())485 completed_tuple = tuple(date_completed.utctimetuple())
486 return self.branch_puller_endpoint.callRemote(486 return self.codehosting_endpoint.callRemote(
487 'recordSuccess', self.name, socket.gethostname(), started_tuple,487 'recordSuccess', self.name, socket.gethostname(), started_tuple,
488 completed_tuple)488 completed_tuple)
489489
490490
=== modified file 'lib/lp/codehosting/puller/tests/test_scheduler.py'
--- lib/lp/codehosting/puller/tests/test_scheduler.py 2010-04-27 02:11:16 +0000
+++ lib/lp/codehosting/puller/tests/test_scheduler.py 2010-04-27 02:11:35 +0000
@@ -40,7 +40,7 @@
40from lp.testing.factory import ObjectFactory40from lp.testing.factory import ObjectFactory
4141
4242
43class FakePullerEndpointProxy:43class FakeCodehostingEndpointProxy:
4444
45 def __init__(self):45 def __init__(self):
46 self.calls = []46 self.calls = []
@@ -81,7 +81,8 @@
8181
82 def makeJobScheduler(self, branch_type_names=()):82 def makeJobScheduler(self, branch_type_names=()):
83 return scheduler.JobScheduler(83 return scheduler.JobScheduler(
84 FakePullerEndpointProxy(), logging.getLogger(), branch_type_names)84 FakeCodehostingEndpointProxy(), logging.getLogger(),
85 branch_type_names)
8586
86 def testManagerCreatesLocks(self):87 def testManagerCreatesLocks(self):
87 manager = self.makeJobScheduler()88 manager = self.makeJobScheduler()
@@ -105,7 +106,7 @@
105 manager.run()106 manager.run()
106 self.assertEqual(107 self.assertEqual(
107 [('acquireBranchToPull', ('MIRRORED',))],108 [('acquireBranchToPull', ('MIRRORED',))],
108 manager.branch_puller_endpoint.calls)109 manager.codehosting_endpoint.calls)
109110
110111
111class TestPullerWireProtocol(TrialTestCase):112class TestPullerWireProtocol(TrialTestCase):
@@ -421,7 +422,7 @@
421 layer = TwistedLayer422 layer = TwistedLayer
422423
423 def setUp(self):424 def setUp(self):
424 self.status_client = FakePullerEndpointProxy()425 self.status_client = FakeCodehostingEndpointProxy()
425 self.arbitrary_branch_id = 1426 self.arbitrary_branch_id = 1
426 self.eventHandler = scheduler.PullerMaster(427 self.eventHandler = scheduler.PullerMaster(
427 self.arbitrary_branch_id, 'arbitrary-source', 'arbitrary-dest',428 self.arbitrary_branch_id, 'arbitrary-source', 'arbitrary-dest',
@@ -528,7 +529,7 @@
528 branch_type_name=branch_type_name,529 branch_type_name=branch_type_name,
529 default_stacked_on_url=default_stacked_on_url,530 default_stacked_on_url=default_stacked_on_url,
530 logger=logging.getLogger(),531 logger=logging.getLogger(),
531 client=FakePullerEndpointProxy(),532 client=FakeCodehostingEndpointProxy(),
532 available_oops_prefixes=oops_prefixes)533 available_oops_prefixes=oops_prefixes)
533534
534 @property535 @property
@@ -642,7 +643,7 @@
642 branch_type=BranchType.MIRRORED, url=url).id643 branch_type=BranchType.MIRRORED, url=url).id
643 self.layer.txn.commit()644 self.layer.txn.commit()
644 self.db_branch = getUtility(IBranchLookup).get(branch_id)645 self.db_branch = getUtility(IBranchLookup).get(branch_id)
645 self.client = FakePullerEndpointProxy()646 self.client = FakeCodehostingEndpointProxy()
646647
647 def run(self, result):648 def run(self, result):
648 # We want to use Trial's run() method so we can return Deferreds.649 # We want to use Trial's run() method so we can return Deferreds.
649650
=== modified file 'lib/lp/codehosting/sftp.py'
--- lib/lp/codehosting/sftp.py 2010-04-27 02:11:16 +0000
+++ lib/lp/codehosting/sftp.py 2010-04-27 02:11:35 +0000
@@ -244,7 +244,8 @@
244 user_id = avatar.user_id244 user_id = avatar.user_id
245 branch_transport = _get_transport_for_dir(245 branch_transport = _get_transport_for_dir(
246 config.codehosting.mirrored_branches_root)246 config.codehosting.mirrored_branches_root)
247 server = LaunchpadServer(avatar.branchfs_proxy, user_id, branch_transport)247 server = LaunchpadServer(
248 avatar.codehosting_proxy, user_id, branch_transport)
248 server.start_server()249 server.start_server()
249 transport = AsyncLaunchpadTransport(server, server.get_url())250 transport = AsyncLaunchpadTransport(server, server.get_url())
250 return TransportSFTPServer(transport)251 return TransportSFTPServer(transport)
251252
=== modified file 'lib/lp/codehosting/sshserver/daemon.py'
--- lib/lp/codehosting/sshserver/daemon.py 2010-04-15 15:27:30 +0000
+++ lib/lp/codehosting/sshserver/daemon.py 2010-04-27 02:11:35 +0000
@@ -45,13 +45,13 @@
45class CodehostingAvatar(LaunchpadAvatar):45class CodehostingAvatar(LaunchpadAvatar):
46 """An SSH avatar specific to codehosting.46 """An SSH avatar specific to codehosting.
4747
48 :ivar branchfs_proxy: A Twisted XML-RPC client for the authserver. The48 :ivar codehosting_proxy: A Twisted XML-RPC client for the private XML-RPC
49 server must implement `IBranchFileSystem`.49 server. The server must implement `ICodehostingAPI`.
50 """50 """
5151
52 def __init__(self, user_dict, branchfs_proxy):52 def __init__(self, user_dict, codehosting_proxy):
53 LaunchpadAvatar.__init__(self, user_dict)53 LaunchpadAvatar.__init__(self, user_dict)
54 self.branchfs_proxy = branchfs_proxy54 self.codehosting_proxy = codehosting_proxy
5555
5656
57components.registerAdapter(launch_smart_server, CodehostingAvatar, ISession)57components.registerAdapter(launch_smart_server, CodehostingAvatar, ISession)
@@ -63,9 +63,9 @@
63class Realm:63class Realm:
64 implements(IRealm)64 implements(IRealm)
6565
66 def __init__(self, authentication_proxy, branchfs_proxy):66 def __init__(self, authentication_proxy, codehosting_proxy):
67 self.authentication_proxy = authentication_proxy67 self.authentication_proxy = authentication_proxy
68 self.branchfs_proxy = branchfs_proxy68 self.codehosting_proxy = codehosting_proxy
6969
70 def requestAvatar(self, avatar_id, mind, *interfaces):70 def requestAvatar(self, avatar_id, mind, *interfaces):
71 # Fetch the user's details from the authserver71 # Fetch the user's details from the authserver
@@ -74,15 +74,15 @@
7474
75 # Once all those details are retrieved, we can construct the avatar.75 # Once all those details are retrieved, we can construct the avatar.
76 def got_user_dict(user_dict):76 def got_user_dict(user_dict):
77 avatar = CodehostingAvatar(user_dict, self.branchfs_proxy)77 avatar = CodehostingAvatar(user_dict, self.codehosting_proxy)
78 return interfaces[0], avatar, avatar.logout78 return interfaces[0], avatar, avatar.logout
7979
80 return deferred.addCallback(got_user_dict)80 return deferred.addCallback(got_user_dict)
8181
8282
83def get_portal(authentication_proxy, branchfs_proxy):83def get_portal(authentication_proxy, codehosting_proxy):
84 """Get a portal for connecting to Launchpad codehosting."""84 """Get a portal for connecting to Launchpad codehosting."""
85 portal = Portal(Realm(authentication_proxy, branchfs_proxy))85 portal = Portal(Realm(authentication_proxy, codehosting_proxy))
86 portal.registerChecker(86 portal.registerChecker(
87 PublicKeyFromLaunchpadChecker(authentication_proxy))87 PublicKeyFromLaunchpadChecker(authentication_proxy))
88 return portal88 return portal
@@ -101,5 +101,5 @@
101 """101 """
102 authentication_proxy = Proxy(102 authentication_proxy = Proxy(
103 config.codehosting.authentication_endpoint)103 config.codehosting.authentication_endpoint)
104 branchfs_proxy = Proxy(config.codehosting.branchfs_endpoint)104 codehosting_proxy = Proxy(config.codehosting.codehosting_endpoint)
105 return get_portal(authentication_proxy, branchfs_proxy)105 return get_portal(authentication_proxy, codehosting_proxy)
106106
=== modified file 'lib/lp/codehosting/tests/test_acceptance.py'
--- lib/lp/codehosting/tests/test_acceptance.py 2010-04-27 02:11:16 +0000
+++ lib/lp/codehosting/tests/test_acceptance.py 2010-04-27 02:11:35 +0000
@@ -230,14 +230,15 @@
230 """230 """
231 authserver = xmlrpclib.ServerProxy(231 authserver = xmlrpclib.ServerProxy(
232 config.codehosting.authentication_endpoint)232 config.codehosting.authentication_endpoint)
233 branchfs = xmlrpclib.ServerProxy(config.codehosting.branchfs_endpoint)233 codehosting_api = xmlrpclib.ServerProxy(
234 config.codehosting.codehosting_endpoint)
234 if creator is None:235 if creator is None:
235 creator_id = authserver.getUserAndSSHKeys(user)['id']236 creator_id = authserver.getUserAndSSHKeys(user)['id']
236 else:237 else:
237 creator_id = authserver.getUserAndSSHKeys(creator)['id']238 creator_id = authserver.getUserAndSSHKeys(creator)['id']
238 if branch_root is None:239 if branch_root is None:
239 branch_root = self.server._mirror_root240 branch_root = self.server._mirror_root
240 branch_id = branchfs.createBranch(241 branch_id = codehosting_api.createBranch(
241 creator_id, '/~%s/%s/%s' % (user, product, branch))242 creator_id, '/~%s/%s/%s' % (user, product, branch))
242 branch_url = 'file://' + os.path.abspath(243 branch_url = 'file://' + os.path.abspath(
243 os.path.join(branch_root, branch_id_to_path(branch_id)))244 os.path.join(branch_root, branch_id_to_path(branch_id)))
244245
=== modified file 'lib/lp/codehosting/tests/test_sftp.py'
--- lib/lp/codehosting/tests/test_sftp.py 2010-04-15 14:29:42 +0000
+++ lib/lp/codehosting/tests/test_sftp.py 2010-04-27 02:11:35 +0000
@@ -107,13 +107,13 @@
107 TrialTestCase.setUp(self)107 TrialTestCase.setUp(self)
108 frontend = InMemoryFrontend()108 frontend = InMemoryFrontend()
109 self.factory = frontend.getLaunchpadObjectFactory()109 self.factory = frontend.getLaunchpadObjectFactory()
110 self.branchfs_endpoint = XMLRPCWrapper(110 self.codehosting_endpoint = XMLRPCWrapper(
111 frontend.getFilesystemEndpoint())111 frontend.getCodehostingEndpoint())
112112
113 def makeCodehostingAvatar(self):113 def makeCodehostingAvatar(self):
114 user = self.factory.makePerson()114 user = self.factory.makePerson()
115 user_dict = dict(id=user.id, name=user.name)115 user_dict = dict(id=user.id, name=user.name)
116 return CodehostingAvatar(user_dict, self.branchfs_endpoint)116 return CodehostingAvatar(user_dict, self.codehosting_endpoint)
117117
118 def test_canAdaptToSFTPServer(self):118 def test_canAdaptToSFTPServer(self):
119 avatar = self.makeCodehostingAvatar()119 avatar = self.makeCodehostingAvatar()
120120
=== modified file 'lib/lp/codehosting/vfs/branchfs.py'
--- lib/lp/codehosting/vfs/branchfs.py 2010-04-27 02:11:16 +0000
+++ lib/lp/codehosting/vfs/branchfs.py 2010-04-27 02:11:35 +0000
@@ -68,8 +68,8 @@
68from bzrlib.bzrdir import BzrDir, BzrDirFormat68from bzrlib.bzrdir import BzrDir, BzrDirFormat
69from bzrlib.config import TransportConfig69from bzrlib.config import TransportConfig
70from bzrlib.errors import (70from bzrlib.errors import (
71 NoSuchFile, NotBranchError, NotStacked, PermissionDenied,71 NoSuchFile, NotStacked, PermissionDenied, TransportNotPossible,
72 TransportNotPossible, UnstackableBranchFormat)72 UnstackableBranchFormat)
73from bzrlib.plugins.loom.branch import LoomSupport73from bzrlib.plugins.loom.branch import LoomSupport
74from bzrlib.smart.request import jail_info74from bzrlib.smart.request import jail_info
75from bzrlib.transport import get_transport75from bzrlib.transport import get_transport
@@ -169,12 +169,12 @@
169169
170def get_scanner_server():170def get_scanner_server():
171 """Get a Launchpad internal server for scanning branches."""171 """Get a Launchpad internal server for scanning branches."""
172 proxy = xmlrpclib.ServerProxy(config.codehosting.branchfs_endpoint)172 proxy = xmlrpclib.ServerProxy(config.codehosting.codehosting_endpoint)
173 branchfs_endpoint = BlockingProxy(proxy)173 codehosting_endpoint = BlockingProxy(proxy)
174 branch_transport = get_readonly_transport(174 branch_transport = get_readonly_transport(
175 get_transport(config.codehosting.internal_branch_by_id_root))175 get_transport(config.codehosting.internal_branch_by_id_root))
176 return LaunchpadInternalServer(176 return LaunchpadInternalServer(
177 'lp-mirrored:///', branchfs_endpoint, branch_transport)177 'lp-mirrored:///', codehosting_endpoint, branch_transport)
178178
179179
180def get_rw_server():180def get_rw_server():
@@ -185,10 +185,10 @@
185 """185 """
186 hosted_transport = get_chrooted_transport(186 hosted_transport = get_chrooted_transport(
187 config.codehosting.mirrored_branches_root, mkdir=True)187 config.codehosting.mirrored_branches_root, mkdir=True)
188 proxy = xmlrpclib.ServerProxy(config.codehosting.branchfs_endpoint)188 proxy = xmlrpclib.ServerProxy(config.codehosting.codehosting_endpoint)
189 branchfs_endpoint = BlockingProxy(proxy)189 codehosting_endpoint = BlockingProxy(proxy)
190 return LaunchpadInternalServer(190 return LaunchpadInternalServer(
191 'lp-internal:///', branchfs_endpoint, hosted_transport)191 'lp-internal:///', codehosting_endpoint, hosted_transport)
192192
193193
194def get_multi_server(write_hosted=False, write_mirrored=False,194def get_multi_server(write_hosted=False, write_mirrored=False,
@@ -223,11 +223,11 @@
223 if direct_database:223 if direct_database:
224 make_server = DirectDatabaseLaunchpadServer224 make_server = DirectDatabaseLaunchpadServer
225 else:225 else:
226 proxy = xmlrpclib.ServerProxy(config.codehosting.branchfs_endpoint)226 proxy = xmlrpclib.ServerProxy(config.codehosting.codehosting_endpoint)
227 branchfs_endpoint = BlockingProxy(proxy)227 codehosting_endpoint = BlockingProxy(proxy)
228 def make_server(scheme, transport):228 def make_server(scheme, transport):
229 return LaunchpadInternalServer(229 return LaunchpadInternalServer(
230 scheme, branchfs_endpoint, transport)230 scheme, codehosting_endpoint, transport)
231 hosted_server = make_server('lp-hosted:///', hosted_transport)231 hosted_server = make_server('lp-hosted:///', hosted_transport)
232 mirrored_server = make_server('lp-mirrored:///', mirrored_transport)232 mirrored_server = make_server('lp-mirrored:///', mirrored_transport)
233 return _MultiServer(hosted_server, mirrored_server)233 return _MultiServer(hosted_server, mirrored_server)
@@ -367,39 +367,41 @@
367367
368 For more information, see the module docstring.368 For more information, see the module docstring.
369369
370 :ivar _authserver: An object that has a method 'translatePath' that370 :ivar _branchfs_client: An object that has a method 'translatePath' that
371 returns a Deferred that fires information about how a path can be371 returns a Deferred that fires information about how a path can be
372 translated into a transport. See `IBranchFilesystem['translatePath']`.372 translated into a transport. See `IBranchFilesystem['translatePath']`.
373373
374 :ivar _transport_dispatch: An `ITransportDispatch` provider used to374 :ivar _transport_dispatch: An `ITransportDispatch` provider used to
375 convert the data from the authserver into an actual transport and375 convert the data from the branchfs client into an actual transport and
376 path on that transport.376 path on that transport.
377 """377 """
378378
379 def __init__(self, scheme, authserver, user_id,379 def __init__(self, scheme, codehosting_api, user_id,
380 seen_new_branch_hook=None):380 seen_new_branch_hook=None):
381 """Construct a LaunchpadServer.381 """Construct a LaunchpadServer.
382382
383 :param scheme: The URL scheme to use.383 :param scheme: The URL scheme to use.
384 :param authserver: An XML-RPC client that implements callRemote.384 :param codehosting_api: An XML-RPC client that implements callRemote.
385 :param user_id: The database ID for the user who is accessing385 :param user_id: The database ID for the user who is accessing
386 branches.386 branches.
387 :param seen_new_branch_hook: A callable that will be called once for387 :param seen_new_branch_hook: A callable that will be called once for
388 each branch accessed via this server.388 each branch accessed via this server.
389 """389 """
390 AsyncVirtualServer.__init__(self, scheme)390 AsyncVirtualServer.__init__(self, scheme)
391 self._authserver = BranchFileSystemClient(391 self._branchfs_client = BranchFileSystemClient(
392 authserver, user_id, seen_new_branch_hook=seen_new_branch_hook)392 codehosting_api, user_id,
393 seen_new_branch_hook=seen_new_branch_hook)
393 self._is_start_server = False394 self._is_start_server = False
394395
395 def translateVirtualPath(self, virtual_url_fragment):396 def translateVirtualPath(self, virtual_url_fragment):
396 """See `AsyncVirtualServer.translateVirtualPath`.397 """See `AsyncVirtualServer.translateVirtualPath`.
397398
398 Call 'translatePath' on the authserver with the fragment and then use399 Call 'translatePath' on the branchfs client with the fragment and then
399 'makeTransport' on the _transport_dispatch to translate that result400 use 'makeTransport' on the _transport_dispatch to translate that
400 into a transport and trailing path.401 result into a transport and trailing path.
401 """402 """
402 deferred = self._authserver.translatePath('/' + virtual_url_fragment)403 deferred = self._branchfs_client.translatePath(
404 '/' + virtual_url_fragment)
403405
404 def path_not_translated(failure):406 def path_not_translated(failure):
405 trap_fault(407 trap_fault(
@@ -426,19 +428,20 @@
426 Intended for use with the branch puller and scanner.428 Intended for use with the branch puller and scanner.
427 """429 """
428430
429 def __init__(self, scheme, authserver, branch_transport):431 def __init__(self, scheme, codehosting_api, branch_transport):
430 """Construct a `LaunchpadInternalServer`.432 """Construct a `LaunchpadInternalServer`.
431433
432 :param scheme: The URL scheme to use.434 :param scheme: The URL scheme to use.
433435
434 :param authserver: An object that provides a 'translatePath' method.436 :param codehosting_api: An object that provides a 'translatePath'
437 method.
435438
436 :param branch_transport: A Bazaar `Transport` that refers to an439 :param branch_transport: A Bazaar `Transport` that refers to an
437 area where Launchpad branches are stored, generally either the440 area where Launchpad branches are stored, generally either the
438 hosted or mirrored areas.441 hosted or mirrored areas.
439 """442 """
440 super(LaunchpadInternalServer, self).__init__(443 super(LaunchpadInternalServer, self).__init__(
441 scheme, authserver, LAUNCHPAD_SERVICES)444 scheme, codehosting_api, LAUNCHPAD_SERVICES)
442 self._transport_dispatch = BranchTransportDispatch(branch_transport)445 self._transport_dispatch = BranchTransportDispatch(branch_transport)
443446
444 def start_server(self):447 def start_server(self):
@@ -564,13 +567,13 @@
564567
565 asyncTransportFactory = AsyncLaunchpadTransport568 asyncTransportFactory = AsyncLaunchpadTransport
566569
567 def __init__(self, authserver, user_id, branch_transport,570 def __init__(self, codehosting_api, user_id, branch_transport,
568 seen_new_branch_hook=None):571 seen_new_branch_hook=None):
569 """Construct a `LaunchpadServer`.572 """Construct a `LaunchpadServer`.
570573
571 See `_BaseLaunchpadServer` for more information.574 See `_BaseLaunchpadServer` for more information.
572575
573 :param authserver: An object that has 'createBranch' and576 :param codehosting_api: An object that has 'createBranch' and
574 'branchChanged' methods in addition to a 'translatePath' method.577 'branchChanged' methods in addition to a 'translatePath' method.
575 These methods should return Deferreds.578 These methods should return Deferreds.
576 XXX: JonathanLange 2008-11-19: Specify this interface better.579 XXX: JonathanLange 2008-11-19: Specify this interface better.
@@ -583,7 +586,7 @@
583 """586 """
584 scheme = 'lp-%d:///' % id(self)587 scheme = 'lp-%d:///' % id(self)
585 super(LaunchpadServer, self).__init__(588 super(LaunchpadServer, self).__init__(
586 scheme, authserver, user_id, seen_new_branch_hook)589 scheme, codehosting_api, user_id, seen_new_branch_hook)
587 self._transport_dispatch = TransportDispatch(branch_transport)590 self._transport_dispatch = TransportDispatch(branch_transport)
588591
589 def createBranch(self, virtual_url_fragment):592 def createBranch(self, virtual_url_fragment):
@@ -604,7 +607,7 @@
604 that its creation is forbidden by a policy.607 that its creation is forbidden by a policy.
605 :raise Fault: If the XML-RPC server raises errors.608 :raise Fault: If the XML-RPC server raises errors.
606 """609 """
607 deferred = self._authserver.createBranch(virtual_url_fragment)610 deferred = self._branchfs_client.createBranch(virtual_url_fragment)
608611
609 def translate_fault(failure):612 def translate_fault(failure):
610 # We turn faults.NotFound into a PermissionDenied, even613 # We turn faults.NotFound into a PermissionDenied, even
@@ -667,7 +670,8 @@
667 :param virtual_url_fragment: A url fragment that points to a path670 :param virtual_url_fragment: A url fragment that points to a path
668 owned by a branch.671 owned by a branch.
669 """672 """
670 deferred = self._authserver.translatePath('/' + virtual_url_fragment)673 deferred = self._branchfs_client.translatePath(
674 '/' + virtual_url_fragment)
671675
672 def got_path_info((transport_type, data, trailing_path)):676 def got_path_info((transport_type, data, trailing_path)):
673 if transport_type != BRANCH_TRANSPORT:677 if transport_type != BRANCH_TRANSPORT:
@@ -693,7 +697,7 @@
693 jail_info.transports.remove(transport)697 jail_info.transports.remove(transport)
694 if stacked_on_url is None:698 if stacked_on_url is None:
695 stacked_on_url = ''699 stacked_on_url = ''
696 return self._authserver.branchChanged(700 return self._branchfs_client.branchChanged(
697 data['id'], stacked_on_url, last_revision,701 data['id'], stacked_on_url, last_revision,
698 control_string, branch_string, repository_string)702 control_string, branch_string, repository_string)
699703
@@ -703,29 +707,29 @@
703 return deferred.addCallback(got_path_info).addErrback(log.err)707 return deferred.addCallback(got_path_info).addErrback(log.err)
704708
705709
706def get_lp_server(user_id, branchfs_endpoint_url=None, branch_directory=None,710def get_lp_server(user_id, codehosting_endpoint_url=None, branch_directory=None,
707 seen_new_branch_hook=None):711 seen_new_branch_hook=None):
708 """Create a Launchpad server.712 """Create a Launchpad server.
709713
710 :param user_id: A unique database ID of the user whose branches are714 :param user_id: A unique database ID of the user whose branches are
711 being served.715 being served.
712 :param branchfs_endpoint_url: URL for the branch file system end-point.716 :param codehosting_endpoint_url: URL for the branch file system end-point.
713 :param hosted_directory: Where the branches are uploaded to.717 :param hosted_directory: Where the branches are uploaded to.
714 :param mirror_directory: Where all Launchpad branches are mirrored.718 :param mirror_directory: Where all Launchpad branches are mirrored.
715 :param seen_new_branch_hook:719 :param seen_new_branch_hook:
716 :return: A `LaunchpadServer`.720 :return: A `LaunchpadServer`.
717 """721 """
718 # Get the defaults from the config.722 # Get the defaults from the config.
719 if branchfs_endpoint_url is None:723 if codehosting_endpoint_url is None:
720 branchfs_endpoint_url = config.codehosting.branchfs_endpoint724 codehosting_endpoint_url = config.codehosting.codehosting_endpoint
721 if branch_directory is None:725 if branch_directory is None:
722 branch_directory = config.codehosting.mirrored_branches_root726 branch_directory = config.codehosting.mirrored_branches_root
723727
724 branch_url = urlutils.local_path_to_url(branch_directory)728 branch_url = urlutils.local_path_to_url(branch_directory)
725 branchfs_client = xmlrpclib.ServerProxy(branchfs_endpoint_url)729 codehosting_client = xmlrpclib.ServerProxy(codehosting_endpoint_url)
726 branch_transport = get_chrooted_transport(branch_url)730 branch_transport = get_chrooted_transport(branch_url)
727 lp_server = LaunchpadServer(731 lp_server = LaunchpadServer(
728 BlockingProxy(branchfs_client), user_id, branch_transport,732 BlockingProxy(codehosting_client), user_id, branch_transport,
729 seen_new_branch_hook)733 seen_new_branch_hook)
730 return lp_server734 return lp_server
731735
732736
=== modified file 'lib/lp/codehosting/vfs/branchfsclient.py'
--- lib/lp/codehosting/vfs/branchfsclient.py 2010-04-27 02:11:16 +0000
+++ lib/lp/codehosting/vfs/branchfsclient.py 2010-04-27 02:11:35 +0000
@@ -34,20 +34,23 @@
3434
3535
36class BranchFileSystemClient:36class BranchFileSystemClient:
37 """Wrapper for the branch filesystem endpoint for a particular user.37 """Wrapper for some methods of the codehosting endpoint.
3838
39 This wrapper caches the results of calls to translatePath in order to39 Instances of this class wrap the methods of the codehosting endpoint
40 required by the VFS code, specialized for a particular user.
41
42 The wrapper also caches the results of calls to translatePath in order to
40 avoid a large number of roundtrips. In the normal course of operation, our43 avoid a large number of roundtrips. In the normal course of operation, our
41 Bazaar transport translates virtual paths to real paths on disk using this44 Bazaar transport translates virtual paths to real paths on disk using this
42 client. It does this many, many times for a single Bazaar operation, so we45 client. It does this many, many times for a single Bazaar operation, so we
43 cache the results here.46 cache the results here.
44 """47 """
4548
46 def __init__(self, branchfs_endpoint, user_id, expiry_time=None,49 def __init__(self, codehosting_endpoint, user_id, expiry_time=None,
47 seen_new_branch_hook=None, _now=time.time):50 seen_new_branch_hook=None, _now=time.time):
48 """Construct a caching branchfs_endpoint.51 """Construct a caching codehosting_endpoint.
4952
50 :param branchfs_endpoint: An XML-RPC proxy that implements callRemote.53 :param codehosting_endpoint: An XML-RPC proxy that implements callRemote.
51 :param user_id: The database ID of the user who will be making these54 :param user_id: The database ID of the user who will be making these
52 requests. An integer.55 requests. An integer.
53 :param expiry_time: If supplied, only cache the results of56 :param expiry_time: If supplied, only cache the results of
@@ -56,7 +59,7 @@
56 :param seen_new_branch_hook: A callable that will be called with the59 :param seen_new_branch_hook: A callable that will be called with the
57 unique_name of each new branch that is accessed.60 unique_name of each new branch that is accessed.
58 """61 """
59 self._branchfs_endpoint = branchfs_endpoint62 self._codehosting_endpoint = codehosting_endpoint
60 self._cache = {}63 self._cache = {}
61 self._user_id = user_id64 self._user_id = user_id
62 self.expiry_time = expiry_time65 self.expiry_time = expiry_time
@@ -104,16 +107,16 @@
104 def createBranch(self, branch_path):107 def createBranch(self, branch_path):
105 """Create a Launchpad `IBranch` in the database.108 """Create a Launchpad `IBranch` in the database.
106109
107 This raises any Faults that might be raised by the branchfs_endpoint's110 This raises any Faults that might be raised by the
108 `createBranch` method, so for more information see111 codehosting_endpoint's `createBranch` method, so for more information
109 `IBranchFileSystem.createBranch`.112 see `IBranchFileSystem.createBranch`.
110113
111 :param branch_path: The path to the branch to create.114 :param branch_path: The path to the branch to create.
112 :return: A `Deferred` that fires the ID of the created branch.115 :return: A `Deferred` that fires the ID of the created branch.
113 """116 """
114 return defer.maybeDeferred(117 return defer.maybeDeferred(
115 self._branchfs_endpoint.callRemote, 'createBranch', self._user_id,118 self._codehosting_endpoint.callRemote, 'createBranch',
116 branch_path)119 self._user_id, branch_path)
117120
118 def branchChanged(self, branch_id, stacked_on_url, last_revision_id,121 def branchChanged(self, branch_id, stacked_on_url, last_revision_id,
119 control_string, branch_string, repository_string):122 control_string, branch_string, repository_string):
@@ -122,7 +125,7 @@
122 :param branch_id: The database ID of the branch.125 :param branch_id: The database ID of the branch.
123 """126 """
124 return defer.maybeDeferred(127 return defer.maybeDeferred(
125 self._branchfs_endpoint.callRemote,128 self._codehosting_endpoint.callRemote,
126 'branchChanged', branch_id, stacked_on_url, last_revision_id,129 'branchChanged', branch_id, stacked_on_url, last_revision_id,
127 control_string, branch_string, repository_string)130 control_string, branch_string, repository_string)
128131
@@ -132,7 +135,7 @@
132 return defer.succeed(self._getFromCache(path))135 return defer.succeed(self._getFromCache(path))
133 except NotInCache:136 except NotInCache:
134 deferred = defer.maybeDeferred(137 deferred = defer.maybeDeferred(
135 self._branchfs_endpoint.callRemote,138 self._codehosting_endpoint.callRemote,
136 'translatePath', self._user_id, path)139 'translatePath', self._user_id, path)
137 deferred.addCallback(self._addToCache, path)140 deferred.addCallback(self._addToCache, path)
138 return deferred141 return deferred
139142
=== modified file 'lib/lp/codehosting/vfs/tests/test_branchfs.py'
--- lib/lp/codehosting/vfs/tests/test_branchfs.py 2010-04-27 02:11:16 +0000
+++ lib/lp/codehosting/vfs/tests/test_branchfs.py 2010-04-27 02:11:35 +0000
@@ -176,13 +176,13 @@
176176
177 def setUp(self):177 def setUp(self):
178 frontend = InMemoryFrontend()178 frontend = InMemoryFrontend()
179 self.authserver = frontend.getFilesystemEndpoint()179 self.codehosting_api = frontend.getCodehostingEndpoint()
180 self.factory = frontend.getLaunchpadObjectFactory()180 self.factory = frontend.getLaunchpadObjectFactory()
181 self.requester = self.factory.makePerson()181 self.requester = self.factory.makePerson()
182 self.server = self.getLaunchpadServer(182 self.server = self.getLaunchpadServer(
183 self.authserver, self.requester.id)183 self.codehosting_api, self.requester.id)
184184
185 def getLaunchpadServer(self, authserver, user_id):185 def getLaunchpadServer(self, codehosting_api, user_id):
186 raise NotImplementedError(186 raise NotImplementedError(
187 "Override this with a Launchpad server factory.")187 "Override this with a Launchpad server factory.")
188188
@@ -213,9 +213,9 @@
213 BzrTestCase.setUp(self)213 BzrTestCase.setUp(self)
214 MixinBaseLaunchpadServerTests.setUp(self)214 MixinBaseLaunchpadServerTests.setUp(self)
215215
216 def getLaunchpadServer(self, authserver, user_id):216 def getLaunchpadServer(self, codehosting_api, user_id):
217 return LaunchpadServer(217 return LaunchpadServer(
218 XMLRPCWrapper(authserver), user_id, MemoryTransport())218 XMLRPCWrapper(codehosting_api), user_id, MemoryTransport())
219219
220 def test_translateControlPath(self):220 def test_translateControlPath(self):
221 branch = self.factory.makeProductBranch(owner=self.requester)221 branch = self.factory.makeProductBranch(owner=self.requester)
@@ -342,9 +342,9 @@
342 self.disable_directory_isolation()342 self.disable_directory_isolation()
343 MixinBaseLaunchpadServerTests.setUp(self)343 MixinBaseLaunchpadServerTests.setUp(self)
344344
345 def getLaunchpadServer(self, authserver, user_id):345 def getLaunchpadServer(self, codehosting_api, user_id):
346 return LaunchpadInternalServer(346 return LaunchpadInternalServer(
347 'lp-test:///', XMLRPCWrapper(authserver), MemoryTransport())347 'lp-test:///', XMLRPCWrapper(codehosting_api), MemoryTransport())
348348
349349
350class TestDirectDatabaseLaunchpadServer(TestCaseWithFactory, TrialTestCase,350class TestDirectDatabaseLaunchpadServer(TestCaseWithFactory, TrialTestCase,
@@ -472,11 +472,11 @@
472 def setUp(self):472 def setUp(self):
473 frontend = InMemoryFrontend()473 frontend = InMemoryFrontend()
474 self.factory = frontend.getLaunchpadObjectFactory()474 self.factory = frontend.getLaunchpadObjectFactory()
475 authserver = frontend.getFilesystemEndpoint()475 codehosting_api = frontend.getCodehostingEndpoint()
476 self.requester = self.factory.makePerson()476 self.requester = self.factory.makePerson()
477 self.backing_transport = MemoryTransport()477 self.backing_transport = MemoryTransport()
478 self.server = self.getServer(478 self.server = self.getServer(
479 authserver, self.requester.id, self.backing_transport)479 codehosting_api, self.requester.id, self.backing_transport)
480 self.server.start_server()480 self.server.start_server()
481 self.addCleanup(self.server.stop_server)481 self.addCleanup(self.server.stop_server)
482482
@@ -507,9 +507,9 @@
507 """Call `function` and return an appropriate Deferred."""507 """Call `function` and return an appropriate Deferred."""
508 raise NotImplementedError508 raise NotImplementedError
509509
510 def getServer(self, authserver, user_id, backing_transport):510 def getServer(self, codehosting_api, user_id, backing_transport):
511 return LaunchpadServer(511 return LaunchpadServer(
512 XMLRPCWrapper(authserver), user_id, backing_transport)512 XMLRPCWrapper(codehosting_api), user_id, backing_transport)
513513
514 def getTransport(self):514 def getTransport(self):
515 """Return the transport to be tested."""515 """Return the transport to be tested."""
@@ -820,8 +820,8 @@
820 self._branch_changed_log = []820 self._branch_changed_log = []
821 frontend = InMemoryFrontend()821 frontend = InMemoryFrontend()
822 self.factory = frontend.getLaunchpadObjectFactory()822 self.factory = frontend.getLaunchpadObjectFactory()
823 self.authserver = frontend.getFilesystemEndpoint()823 self.codehosting_api = frontend.getCodehostingEndpoint()
824 self.authserver.branchChanged = self._replacement_branchChanged824 self.codehosting_api.branchChanged = self._replacement_branchChanged
825 self.requester = self.factory.makePerson()825 self.requester = self.factory.makePerson()
826 self.backing_transport = MemoryTransport()826 self.backing_transport = MemoryTransport()
827 self.disable_directory_isolation()827 self.disable_directory_isolation()
@@ -835,7 +835,7 @@
835 def get_server(self):835 def get_server(self):
836 if self._server is None:836 if self._server is None:
837 self._server = LaunchpadServer(837 self._server = LaunchpadServer(
838 XMLRPCWrapper(self.authserver), self.requester.id,838 XMLRPCWrapper(self.codehosting_api), self.requester.id,
839 self.backing_transport)839 self.backing_transport)
840 self._server.start_server()840 self._server.start_server()
841 self.addCleanup(self._server.stop_server)841 self.addCleanup(self._server.stop_server)
@@ -987,7 +987,7 @@
987 self._frontend = InMemoryFrontend()987 self._frontend = InMemoryFrontend()
988 self.factory = self._frontend.getLaunchpadObjectFactory()988 self.factory = self._frontend.getLaunchpadObjectFactory()
989989
990 authserver = self._frontend.getFilesystemEndpoint()990 codehosting_api = self._frontend.getCodehostingEndpoint()
991 self.requester = self.factory.makePerson()991 self.requester = self.factory.makePerson()
992992
993 self.writable_branch = self.factory.makeAnyBranch(993 self.writable_branch = self.factory.makeAnyBranch(
@@ -997,7 +997,7 @@
997 branch_type=BranchType.HOSTED).unique_name997 branch_type=BranchType.HOSTED).unique_name
998998
999 self.lp_server = self._setUpLaunchpadServer(999 self.lp_server = self._setUpLaunchpadServer(
1000 self.requester.id, authserver, backing_transport)1000 self.requester.id, codehosting_api, backing_transport)
1001 self.lp_transport = get_transport(self.lp_server.get_url())1001 self.lp_transport = get_transport(self.lp_server.get_url())
1002 self.lp_transport.mkdir(os.path.dirname(self.writable_file))1002 self.lp_transport.mkdir(os.path.dirname(self.writable_file))
1003 self.lp_transport.put_bytes(self.writable_file, 'Hello World!')1003 self.lp_transport.put_bytes(self.writable_file, 'Hello World!')
@@ -1008,9 +1008,9 @@
1008 self.addCleanup(memory_server.stop_server)1008 self.addCleanup(memory_server.stop_server)
1009 return memory_server1009 return memory_server
10101010
1011 def _setUpLaunchpadServer(self, user_id, authserver, backing_transport):1011 def _setUpLaunchpadServer(self, user_id, codehosting_api, backing_transport):
1012 server = LaunchpadServer(1012 server = LaunchpadServer(
1013 XMLRPCWrapper(authserver), user_id, backing_transport)1013 XMLRPCWrapper(codehosting_api), user_id, backing_transport)
1014 server.start_server()1014 server.start_server()
1015 self.addCleanup(server.stop_server)1015 self.addCleanup(server.stop_server)
1016 return server1016 return server
10171017
=== modified file 'lib/lp/codehosting/vfs/tests/test_branchfsclient.py'
--- lib/lp/codehosting/vfs/tests/test_branchfsclient.py 2010-04-09 12:39:23 +0000
+++ lib/lp/codehosting/vfs/tests/test_branchfsclient.py 2010-04-27 02:11:35 +0000
@@ -25,7 +25,7 @@
25 frontend = InMemoryFrontend()25 frontend = InMemoryFrontend()
26 self.factory = frontend.getLaunchpadObjectFactory()26 self.factory = frontend.getLaunchpadObjectFactory()
27 self.user = self.factory.makePerson()27 self.user = self.factory.makePerson()
28 self._xmlrpc_client = XMLRPCWrapper(frontend.getFilesystemEndpoint())28 self._xmlrpc_client = XMLRPCWrapper(frontend.getCodehostingEndpoint())
29 self.fake_time = FakeTime(12345)29 self.fake_time = FakeTime(12345)
3030
31 def advanceTime(self, amount):31 def advanceTime(self, amount):
3232
=== modified file 'lib/lp/codehosting/vfs/tests/test_filesystem.py'
--- lib/lp/codehosting/vfs/tests/test_filesystem.py 2010-04-27 02:11:16 +0000
+++ lib/lp/codehosting/vfs/tests/test_filesystem.py 2010-04-27 02:11:35 +0000
@@ -30,7 +30,7 @@
30 self.disable_directory_isolation()30 self.disable_directory_isolation()
31 frontend = InMemoryFrontend()31 frontend = InMemoryFrontend()
32 self.factory = frontend.getLaunchpadObjectFactory()32 self.factory = frontend.getLaunchpadObjectFactory()
33 endpoint = XMLRPCWrapper(frontend.getFilesystemEndpoint())33 endpoint = XMLRPCWrapper(frontend.getCodehostingEndpoint())
34 self.requester = self.factory.makePerson()34 self.requester = self.factory.makePerson()
35 self._server = LaunchpadServer(35 self._server = LaunchpadServer(
36 endpoint, self.requester.id, MemoryTransport())36 endpoint, self.requester.id, MemoryTransport())
3737
=== modified file 'lib/lp/codehosting/vfs/tests/test_transport.py'
--- lib/lp/codehosting/vfs/tests/test_transport.py 2010-01-20 02:00:32 +0000
+++ lib/lp/codehosting/vfs/tests/test_transport.py 2010-04-27 02:11:35 +0000
@@ -32,7 +32,7 @@
32 an in-memory XML-RPC client and backed onto a LocalTransport.32 an in-memory XML-RPC client and backed onto a LocalTransport.
33 """33 """
34 frontend = InMemoryFrontend()34 frontend = InMemoryFrontend()
35 branchfs = frontend.getFilesystemEndpoint()35 branchfs = frontend.getCodehostingEndpoint()
36 branch = frontend.getLaunchpadObjectFactory().makeAnyBranch()36 branch = frontend.getLaunchpadObjectFactory().makeAnyBranch()
37 self._branch_path = branch.unique_name37 self._branch_path = branch.unique_name
38 # XXX: JonathanLange bug=276972 2008-10-07: This should back on to a38 # XXX: JonathanLange bug=276972 2008-10-07: This should back on to a
3939
=== modified file 'scripts/update-stacked-on.py'
--- scripts/update-stacked-on.py 2010-02-16 15:25:52 +0000
+++ scripts/update-stacked-on.py 2010-04-27 02:11:35 +0000
@@ -39,7 +39,7 @@
3939
40def get_server(read_only):40def get_server(read_only):
41 """Get a server that can write to both hosted and mirrored areas."""41 """Get a server that can write to both hosted and mirrored areas."""
42 proxy = xmlrpclib.ServerProxy(config.codehosting.branchfs_endpoint)42 proxy = xmlrpclib.ServerProxy(config.codehosting.codehosting_endpoint)
43 authserver = BlockingProxy(proxy)43 authserver = BlockingProxy(proxy)
44 hosted_transport = get_chrooted_transport(44 hosted_transport = get_chrooted_transport(
45 config.codehosting.hosted_branches_root)45 config.codehosting.hosted_branches_root)