~launchpad-pqm/launchpad/devel

8687.15.17 by Karl Fogel
Add the copyright header block to the rest of the files under lib/lp/.
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
5670.3.1 by jml at canonical
Just the BazaarBranchStore
3
4
"""The code import worker. This imports code from foreign repositories."""
5
6
__metaclass__ = type
5670.2.9 by jml at canonical
Add support for storing foreign branches.
7
__all__ = [
8
    'BazaarBranchStore',
7675.76.2 by Michael Hudson
small refactoring
9
    'BzrSvnImportWorker',
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
10
    'CSCVSImportWorker',
6055.1.3 by Michael Hudson
re-type what i had in my imploded loom :(
11
    'CodeImportSourceDetails',
10224.12.9 by Michael Hudson
self-review begins
12
    'CodeImportWorkerExitCode',
5670.2.29 by jml at canonical
ForeignBranchStore -> ForeignTreeStore
13
    'ForeignTreeStore',
7675.76.2 by Michael Hudson
small refactoring
14
    'GitImportWorker',
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
15
    'HgImportWorker',
5821.1.5 by Michael Hudson
a test. which does not work
16
    'ImportWorker',
5670.2.9 by jml at canonical
Add support for storing foreign branches.
17
    'get_default_bazaar_branch_store',
7675.76.2 by Michael Hudson
small refactoring
18
    ]
5670.3.1 by jml at canonical
Just the BazaarBranchStore
19
20
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
21
import os
22
import shutil
23
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
24
from bzrlib.branch import (
25
    Branch,
26
    InterBranch,
27
    )
28
from bzrlib.bzrdir import (
29
    BzrDir,
30
    BzrDirFormat,
31
    )
32
from bzrlib.errors import (
33
    NoSuchFile,
34
    NotBranchError,
35
    )
5670.3.1 by jml at canonical
Just the BazaarBranchStore
36
from bzrlib.transport import get_transport
8340.1.5 by Michael Hudson
* install LoggingUIFactory in worker
37
import bzrlib.ui
7873.1.2 by Paul Hummer
Fixed the test
38
from bzrlib.upgrade import upgrade
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
39
from bzrlib.urlutils import (
40
    join as urljoin,
41
    local_path_from_url,
42
    )
43
import cscvs
44
from cscvs.cmds import totla
45
import CVS
46
import SCM
5670.3.1 by jml at canonical
Just the BazaarBranchStore
47
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
48
from canonical.config import config
10224.12.9 by Michael Hudson
self-review begins
49
from lp.code.enums import RevisionControlSystems
8426.6.1 by Michael Hudson
bzr ls --versioned --recursive --kind=file | xargs sed -i -e 's,from canonical.codehosting,from lp.codehosting,'
50
from lp.codehosting.codeimport.foreigntree import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
51
    CVSWorkingTree,
52
    SubversionWorkingTree,
53
    )
8426.6.1 by Michael Hudson
bzr ls --versioned --recursive --kind=file | xargs sed -i -e 's,from canonical.codehosting,from lp.codehosting,'
54
from lp.codehosting.codeimport.tarball import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
55
    create_tarball,
56
    extract_tarball,
57
    )
8426.6.1 by Michael Hudson
bzr ls --versioned --recursive --kind=file | xargs sed -i -e 's,from canonical.codehosting,from lp.codehosting,'
58
from lp.codehosting.codeimport.uifactory import LoggingUIFactory
11382.6.34 by Gavin Panella
Reformat imports in all files touched so far.
59
from lp.services.propertycache import cachedproperty
5670.3.1 by jml at canonical
Just the BazaarBranchStore
60
61
10224.12.9 by Michael Hudson
self-review begins
62
class CodeImportWorkerExitCode:
63
    """Exit codes used by the code import worker script."""
64
65
    SUCCESS = 0
66
    FAILURE = 1
67
    SUCCESS_NOCHANGE = 2
10271.2.1 by Michael Hudson
well, this passes existing tests...
68
    SUCCESS_PARTIAL = 3
10224.12.9 by Michael Hudson
self-review begins
69
70
5670.3.1 by jml at canonical
Just the BazaarBranchStore
71
class BazaarBranchStore:
72
    """A place where Bazaar branches of code imports are kept."""
73
74
    def __init__(self, transport):
75
        """Construct a Bazaar branch store based at `transport`."""
76
        self.transport = transport
77
6015.2.1 by Michael Hudson
redo the branch store so it doesn't talk to the db
78
    def _getMirrorURL(self, db_branch_id):
5670.3.6 by jml at canonical
Rewrite gettarget in terms of the BazaarBranchStore.
79
        """Return the URL that `db_branch` is stored at."""
6015.2.1 by Michael Hudson
redo the branch store so it doesn't talk to the db
80
        return urljoin(self.transport.base, '%08x' % db_branch_id)
5670.3.1 by jml at canonical
Just the BazaarBranchStore
81
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
82
    def pull(self, db_branch_id, target_path, required_format,
83
             needs_tree=False):
84
        """Pull down the Bazaar branch of an import to `target_path`.
5670.3.1 by jml at canonical
Just the BazaarBranchStore
85
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
86
        :return: A Bazaar branch for the code import corresponding to the
87
            database branch with id `db_branch_id`.
5670.3.1 by jml at canonical
Just the BazaarBranchStore
88
        """
7873.1.6 by Michael Hudson
woo it works
89
        remote_url = self._getMirrorURL(db_branch_id)
5670.3.1 by jml at canonical
Just the BazaarBranchStore
90
        try:
10377.1.1 by Michael Hudson
this probably fixes the failure
91
            remote_bzr_dir = BzrDir.open(remote_url)
5670.3.1 by jml at canonical
Just the BazaarBranchStore
92
        except NotBranchError:
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
93
            local_branch = BzrDir.create_branch_and_repo(
94
                target_path, format=required_format)
95
            if needs_tree:
96
                local_branch.bzrdir.create_workingtree()
97
            return local_branch
9478.1.7 by Tim Penhey
Add bug number to XXX comment and add XXX to disabled tests too.
98
        # XXX Tim Penhey 2009-09-18 bug 432217 Automatic upgrade of import
9478.1.5 by Tim Penhey
Disable the automatic upgrades.
99
        # branches disabled.  Need an orderly upgrade process.
10377.1.1 by Michael Hudson
this probably fixes the failure
100
        if False and remote_bzr_dir.needs_format_conversion(
101
            format=required_format):
7873.1.6 by Michael Hudson
woo it works
102
            try:
10377.1.1 by Michael Hudson
this probably fixes the failure
103
                remote_bzr_dir.root_transport.delete_tree('backup.bzr')
7873.1.6 by Michael Hudson
woo it works
104
            except NoSuchFile:
105
                pass
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
106
            upgrade(remote_url, required_format)
10686.1.1 by Michael Hudson
be stupid and fast not smart and slow in BazaarBranchStore.pull
107
        # The proper thing to do here would be to call
108
        # "remote_bzr_dir.sprout()".  But 2a fetch slowly checks which
109
        # revisions are in the ancestry of the tip of the remote branch, which
110
        # we strictly don't care about, so we just copy the whole thing down
111
        # at the vfs level.
10792.1.2 by Michael Hudson
rob approved version
112
        control_dir = remote_bzr_dir.root_transport.relpath(
113
            remote_bzr_dir.transport.abspath('.'))
10686.1.1 by Michael Hudson
be stupid and fast not smart and slow in BazaarBranchStore.pull
114
        target = get_transport(target_path)
10792.1.2 by Michael Hudson
rob approved version
115
        target_control = target.clone(control_dir)
116
        target_control.create_prefix()
117
        remote_bzr_dir.transport.copy_tree_to_transport(target_control)
10686.1.1 by Michael Hudson
be stupid and fast not smart and slow in BazaarBranchStore.pull
118
        local_bzr_dir = BzrDir.open_from_transport(target)
119
        if needs_tree:
120
            local_bzr_dir.create_workingtree()
121
        return local_bzr_dir.open_branch()
5670.3.1 by jml at canonical
Just the BazaarBranchStore
122
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
123
    def push(self, db_branch_id, bzr_branch, required_format):
124
        """Push up `bzr_branch` as the Bazaar branch for `code_import`.
10224.12.11 by Michael Hudson
some restructuring
125
126
        :return: A boolean that is true if the push was non-trivial
127
            (i.e. actually transferred revisions).
128
        """
10081.1.3 by Michael Hudson
remove lp.codehosting.bzrutils.ensure_base
129
        self.transport.create_prefix()
6015.2.1 by Michael Hudson
redo the branch store so it doesn't talk to the db
130
        target_url = self._getMirrorURL(db_branch_id)
5670.3.1 by jml at canonical
Just the BazaarBranchStore
131
        try:
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
132
            remote_branch = Branch.open(target_url)
5670.3.1 by jml at canonical
Just the BazaarBranchStore
133
        except NotBranchError:
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
134
            remote_branch = BzrDir.create_branch_and_repo(
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
135
                target_url, format=required_format)
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
136
        pull_result = remote_branch.pull(bzr_branch, overwrite=True)
10377.1.1 by Michael Hudson
this probably fixes the failure
137
        # Because of the way we do incremental imports, there may be revisions
138
        # in the branch's repo that are not in the ancestry of the branch tip.
139
        # We need to transfer them too.
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
140
        remote_branch.repository.fetch(bzr_branch.repository)
10224.12.11 by Michael Hudson
some restructuring
141
        return pull_result.old_revid != pull_result.new_revid
5670.3.1 by jml at canonical
Just the BazaarBranchStore
142
143
144
def get_default_bazaar_branch_store():
145
    """Return the default `BazaarBranchStore`."""
146
    return BazaarBranchStore(
147
        get_transport(config.codeimport.bazaar_branch_store))
5670.2.9 by jml at canonical
Add support for storing foreign branches.
148
149
6015.2.4 by Michael Hudson
docstrings and some renaming
150
class CodeImportSourceDetails:
151
    """The information needed to process an import.
152
153
    As the worker doesn't talk to the database, we don't use
154
    `CodeImport` objects for this.
155
156
    The 'fromArguments' and 'asArguments' methods convert to and from a form
157
    of the information suitable for passing around on executables' command
158
    lines.
159
160
    :ivar branch_id: The id of the branch associated to this code import, used
161
        for locating the existing import and the foreign tree.
162
    :ivar rcstype: 'svn' or 'cvs' as appropriate.
10129.6.8 by Tim Penhey
More url cleanup.
163
    :ivar url: The branch URL if rcstype in ['svn', 'bzr-svn',
164
        'git'], None otherwise.
6015.2.4 by Michael Hudson
docstrings and some renaming
165
    :ivar cvs_root: The $CVSROOT if rcstype == 'cvs', None otherwise.
166
    :ivar cvs_module: The CVS module if rcstype == 'cvs', None otherwise.
10129.6.22 by Tim Penhey
Docstring fixes.
167
    """
6015.2.2 by Michael Hudson
move foreign tree away from database objects
168
10129.6.8 by Tim Penhey
More url cleanup.
169
    def __init__(self, branch_id, rcstype, url=None, cvs_root=None,
170
                 cvs_module=None):
6015.2.2 by Michael Hudson
move foreign tree away from database objects
171
        self.branch_id = branch_id
172
        self.rcstype = rcstype
10129.6.8 by Tim Penhey
More url cleanup.
173
        self.url = url
6015.2.2 by Michael Hudson
move foreign tree away from database objects
174
        self.cvs_root = cvs_root
175
        self.cvs_module = cvs_module
176
177
    @classmethod
178
    def fromArguments(cls, arguments):
6015.2.4 by Michael Hudson
docstrings and some renaming
179
        """Convert command line-style arguments to an instance."""
6305.1.1 by Michael Hudson
the required changes, probably, together with adaptations for existing tests.
180
        branch_id = int(arguments.pop(0))
181
        rcstype = arguments.pop(0)
10129.6.13 by Tim Penhey
Merge jelmer's hg-import branch and resolve conflicts.
182
        if rcstype in ['svn', 'bzr-svn', 'git', 'hg']:
10129.6.8 by Tim Penhey
More url cleanup.
183
            [url] = arguments
184
            cvs_root = cvs_module = None
6015.2.2 by Michael Hudson
move foreign tree away from database objects
185
        elif rcstype == 'cvs':
10129.6.8 by Tim Penhey
More url cleanup.
186
            url = None
6305.1.1 by Michael Hudson
the required changes, probably, together with adaptations for existing tests.
187
            [cvs_root, cvs_module] = arguments
6015.2.2 by Michael Hudson
move foreign tree away from database objects
188
        else:
6015.2.3 by Michael Hudson
move the rest of the worker gubbins over to the non-db style
189
            raise AssertionError("Unknown rcstype %r." % rcstype)
10129.6.8 by Tim Penhey
More url cleanup.
190
        return cls(branch_id, rcstype, url, cvs_root, cvs_module)
6015.2.2 by Michael Hudson
move foreign tree away from database objects
191
6055.1.2 by Michael Hudson
rescue stuff from my imploded loom
192
    @classmethod
193
    def fromCodeImport(cls, code_import):
194
        """Convert a `CodeImport` to an instance."""
10129.6.8 by Tim Penhey
More url cleanup.
195
        branch_id = code_import.branch.id
6055.1.2 by Michael Hudson
rescue stuff from my imploded loom
196
        if code_import.rcs_type == RevisionControlSystems.SVN:
10129.6.8 by Tim Penhey
More url cleanup.
197
            return cls(branch_id, 'svn', str(code_import.url))
9945.1.2 by Michael Hudson
worker monitor test for bzr-svn. depends on a hacked bzrlib
198
        elif code_import.rcs_type == RevisionControlSystems.BZR_SVN:
10129.6.8 by Tim Penhey
More url cleanup.
199
            return cls(branch_id, 'bzr-svn', str(code_import.url))
6055.1.2 by Michael Hudson
rescue stuff from my imploded loom
200
        elif code_import.rcs_type == RevisionControlSystems.CVS:
10129.6.8 by Tim Penhey
More url cleanup.
201
            return cls(
202
                branch_id, 'cvs',
203
                cvs_root=str(code_import.cvs_root),
204
                cvs_module=str(code_import.cvs_module))
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
205
        elif code_import.rcs_type == RevisionControlSystems.GIT:
10129.6.8 by Tim Penhey
More url cleanup.
206
            return cls(branch_id, 'git', str(code_import.url))
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
207
        elif code_import.rcs_type == RevisionControlSystems.HG:
10129.6.13 by Tim Penhey
Merge jelmer's hg-import branch and resolve conflicts.
208
            return cls(branch_id, 'hg', str(code_import.url))
6055.1.2 by Michael Hudson
rescue stuff from my imploded loom
209
        else:
9945.1.2 by Michael Hudson
worker monitor test for bzr-svn. depends on a hacked bzrlib
210
            raise AssertionError("Unknown rcstype %r." % code_import.rcs_type)
6055.1.2 by Michael Hudson
rescue stuff from my imploded loom
211
6015.2.3 by Michael Hudson
move the rest of the worker gubbins over to the non-db style
212
    def asArguments(self):
6015.2.4 by Michael Hudson
docstrings and some renaming
213
        """Return a list of arguments suitable for passing to a child process.
214
        """
7013.3.15 by Michael Hudson
assorting lingering stuffs
215
        result = [str(self.branch_id), self.rcstype]
10129.6.13 by Tim Penhey
Merge jelmer's hg-import branch and resolve conflicts.
216
        if self.rcstype in ['svn', 'bzr-svn', 'git', 'hg']:
10129.6.8 by Tim Penhey
More url cleanup.
217
            result.append(self.url)
6015.2.3 by Michael Hudson
move the rest of the worker gubbins over to the non-db style
218
        elif self.rcstype == 'cvs':
219
            result.append(self.cvs_root)
220
            result.append(self.cvs_module)
221
        else:
222
            raise AssertionError("Unknown rcstype %r." % self.rcstype)
223
        return result
224
6015.2.2 by Michael Hudson
move foreign tree away from database objects
225
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
226
class ImportDataStore:
8615.12.5 by Michael Hudson
tests for ImportDataSource
227
    """A store for data associated with an import.
228
229
    Import workers can store and retreive files into and from the store using
230
    `put()` and `fetch()`.
231
232
    So this store can find files stored by previous versions of this code, the
233
    files are stored at ``<BRANCH ID IN HEX>.<EXT>`` where BRANCH ID comes
234
    from the CodeImportSourceDetails used to construct the instance and EXT
235
    comes from the local name passed to `put` or `fetch`.
236
    """
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
237
238
    def __init__(self, transport, source_details):
239
        """Initialize an `ImportDataStore`.
240
241
        :param transport: The transport files will be stored on.
242
        :param source_details: The `CodeImportSourceDetails` object, used to
243
            know where to store files on the remote transport.
244
        """
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
245
        self.source_details = source_details
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
246
        self._transport = transport
247
        self._branch_id = source_details.branch_id
248
249
    def _getRemoteName(self, local_name):
250
        """Convert `local_name` to the name used to store a file.
251
252
        The algorithm is a little stupid for historical reasons: we chop off
253
        the extension and stick that on the end of the branch id from the
254
        source_details we were constructed with, in hex padded to 8
255
        characters.  For example 'tree.tar.gz' might become '0000a23d.tar.gz'
256
        or 'git.db' might become '00003e4.db'.
257
7675.76.8 by Michael Hudson
cleanups
258
        :param local_name: The local name of the file to be stored.
259
        :return: The name to store the file as on the remote transport.
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
260
        """
261
        if '/' in local_name:
262
            raise AssertionError("local_name must be a name, not a path")
263
        dot_index = local_name.index('.')
264
        if dot_index < 0:
265
            raise AssertionError("local_name must have an extension.")
266
        ext = local_name[dot_index:]
267
        return '%08x%s' % (self._branch_id, ext)
268
8615.12.14 by Michael Hudson
docstrings
269
    def fetch(self, filename, dest_transport=None):
270
        """Retrieve `filename` from the store.
271
272
        :param filename: The name of the file to retrieve (must be a filename,
273
            not a path).
8615.12.19 by Michael Hudson
review comments
274
        :param dest_transport: The transport to retrieve the file to,
8615.12.14 by Michael Hudson
docstrings
275
            defaulting to ``get_transport('.')``.
276
        :return: A boolean, true if the file was found and retrieved, false
277
            otherwise.
278
        """
8615.12.6 by Michael Hudson
acutally use ImportDataStore to store/retrieve git.db
279
        if dest_transport is None:
280
            dest_transport = get_transport('.')
8615.12.14 by Michael Hudson
docstrings
281
        remote_name = self._getRemoteName(filename)
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
282
        if self._transport.has(remote_name):
8615.12.18 by Michael Hudson
lint!
283
            dest_transport.put_file(
284
                filename, self._transport.get(remote_name))
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
285
            return True
286
        else:
287
            return False
288
8615.12.14 by Michael Hudson
docstrings
289
    def put(self, filename, source_transport=None):
290
        """Put `filename` into the store.
291
292
        :param filename: The name of the file to store (must be a filename,
293
            not a path).
294
        :param source_transport: The transport to look for the file on,
295
            defaulting to ``get_transport('.')``.
296
        """
8615.12.6 by Michael Hudson
acutally use ImportDataStore to store/retrieve git.db
297
        if source_transport is None:
298
            source_transport = get_transport('.')
8615.12.14 by Michael Hudson
docstrings
299
        remote_name = self._getRemoteName(filename)
300
        local_file = source_transport.get(filename)
10081.1.3 by Michael Hudson
remove lp.codehosting.bzrutils.ensure_base
301
        self._transport.create_prefix()
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
302
        try:
303
            self._transport.put_file(remote_name, local_file)
304
        finally:
305
            local_file.close()
306
307
5670.2.29 by jml at canonical
ForeignBranchStore -> ForeignTreeStore
308
class ForeignTreeStore:
5670.2.30 by jml at canonical
foreign_branch_store -> foreign_tree_store
309
    """Manages retrieving and storing foreign working trees.
5670.2.9 by jml at canonical
Add support for storing foreign branches.
310
5670.2.30 by jml at canonical
foreign_branch_store -> foreign_tree_store
311
    The code import system stores tarballs of CVS and SVN working trees on
312
    another system. The tarballs are kept in predictable locations based on
6015.2.4 by Michael Hudson
docstrings and some renaming
313
    the ID of the branch associated to the `CodeImport`.
5670.2.9 by jml at canonical
Add support for storing foreign branches.
314
315
    The tarballs are all kept in one directory. The filename of a tarball is
6015.2.4 by Michael Hudson
docstrings and some renaming
316
    XXXXXXXX.tar.gz, where 'XXXXXXXX' is the ID of the `CodeImport`'s branch
317
    in hex.
5670.2.9 by jml at canonical
Add support for storing foreign branches.
318
    """
319
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
320
    def __init__(self, import_data_store):
5670.2.29 by jml at canonical
ForeignBranchStore -> ForeignTreeStore
321
        """Construct a `ForeignTreeStore`.
5670.2.9 by jml at canonical
Add support for storing foreign branches.
322
323
        :param transport: A writable transport that points to the base
324
            directory where the tarballs are stored.
325
        :ptype transport: `bzrlib.transport.Transport`.
326
        """
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
327
        self.import_data_store = import_data_store
5670.2.9 by jml at canonical
Add support for storing foreign branches.
328
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
329
    def _getForeignTree(self, target_path):
330
        """Return a foreign tree object for `target_path`."""
331
        source_details = self.import_data_store.source_details
6015.2.2 by Michael Hudson
move foreign tree away from database objects
332
        if source_details.rcstype == 'svn':
5670.2.9 by jml at canonical
Add support for storing foreign branches.
333
            return SubversionWorkingTree(
10129.6.8 by Tim Penhey
More url cleanup.
334
                source_details.url, str(target_path))
6015.2.2 by Michael Hudson
move foreign tree away from database objects
335
        elif source_details.rcstype == 'cvs':
5670.2.9 by jml at canonical
Add support for storing foreign branches.
336
            return CVSWorkingTree(
6015.2.2 by Michael Hudson
move foreign tree away from database objects
337
                source_details.cvs_root, source_details.cvs_module,
5670.2.9 by jml at canonical
Add support for storing foreign branches.
338
                target_path)
339
        else:
340
            raise AssertionError(
6015.2.2 by Michael Hudson
move foreign tree away from database objects
341
                "unknown RCS type: %r" % source_details.rcstype)
5670.2.9 by jml at canonical
Add support for storing foreign branches.
342
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
343
    def archive(self, foreign_tree):
5670.2.31 by jml at canonical
Terminology change: foreign branch -> foreign tree.
344
        """Archive the foreign tree."""
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
345
        local_name = 'foreign_tree.tar.gz'
346
        create_tarball(foreign_tree.local_path, 'foreign_tree.tar.gz')
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
347
        self.import_data_store.put(local_name)
5670.2.9 by jml at canonical
Add support for storing foreign branches.
348
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
349
    def fetch(self, target_path):
6015.2.4 by Michael Hudson
docstrings and some renaming
350
        """Fetch the foreign branch for `source_details` to `target_path`.
5670.2.9 by jml at canonical
Add support for storing foreign branches.
351
6015.2.4 by Michael Hudson
docstrings and some renaming
352
        If there is no tarball archived for `source_details`, then try to
5670.2.31 by jml at canonical
Terminology change: foreign branch -> foreign tree.
353
        download (i.e. checkout) the foreign tree from its source repository,
354
        generally on a third party server.
5670.2.9 by jml at canonical
Add support for storing foreign branches.
355
        """
356
        try:
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
357
            return self.fetchFromArchive(target_path)
5670.2.9 by jml at canonical
Add support for storing foreign branches.
358
        except NoSuchFile:
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
359
            return self.fetchFromSource(target_path)
5670.2.9 by jml at canonical
Add support for storing foreign branches.
360
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
361
    def fetchFromSource(self, target_path):
6015.2.4 by Michael Hudson
docstrings and some renaming
362
        """Fetch the foreign tree for `source_details` to `target_path`."""
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
363
        branch = self._getForeignTree(target_path)
5670.2.9 by jml at canonical
Add support for storing foreign branches.
364
        branch.checkout()
365
        return branch
366
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
367
    def fetchFromArchive(self, target_path):
6015.2.4 by Michael Hudson
docstrings and some renaming
368
        """Fetch the foreign tree for `source_details` from the archive."""
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
369
        local_name = 'foreign_tree.tar.gz'
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
370
        if not self.import_data_store.fetch(local_name):
8615.12.4 by Michael Hudson
extract class that stores and retrieves branches from a transport from ForeignTreeStore
371
            raise NoSuchFile(local_name)
372
        extract_tarball(local_name, target_path)
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
373
        tree = self._getForeignTree(target_path)
5670.2.9 by jml at canonical
Add support for storing foreign branches.
374
        tree.update()
375
        return tree
376
377
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
378
class ImportWorker:
379
    """Oversees the actual work of a code import."""
380
381
    # Where the Bazaar working tree will be stored.
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
382
    BZR_BRANCH_PATH = 'bzr_branch'
383
384
    # Should `getBazaarBranch` create a working tree?
385
    needs_bzr_tree = True
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
386
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
387
    required_format = BzrDirFormat.get_default_format()
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
388
8615.12.7 by Michael Hudson
increase parameterization, fails in an interesting way though!
389
    def __init__(self, source_details, import_data_transport,
390
                 bazaar_branch_store, logger):
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
391
        """Construct an `ImportWorker`.
392
6015.2.4 by Michael Hudson
docstrings and some renaming
393
        :param source_details: A `CodeImportSourceDetails` object.
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
394
        :param bazaar_branch_store: A `BazaarBranchStore`. The import worker
395
            uses this to fetch and store the Bazaar branches that are created
396
            and updated during the import process.
5821.1.10 by Michael Hudson
comments from the review
397
        :param logger: A `Logger` to pass to cscvs.
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
398
        """
6015.2.3 by Michael Hudson
move the rest of the worker gubbins over to the non-db style
399
        self.source_details = source_details
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
400
        self.bazaar_branch_store = bazaar_branch_store
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
401
        self.import_data_store = ImportDataStore(
402
            import_data_transport, self.source_details)
5821.1.1 by Michael Hudson
make importworker logging less nuts
403
        self._logger = logger
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
404
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
405
    def getBazaarBranch(self):
406
        """Return the Bazaar `Branch` that we are importing into."""
407
        if os.path.isdir(self.BZR_BRANCH_PATH):
408
            shutil.rmtree(self.BZR_BRANCH_PATH)
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
409
        return self.bazaar_branch_store.pull(
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
410
            self.source_details.branch_id, self.BZR_BRANCH_PATH,
411
            self.required_format, self.needs_bzr_tree)
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
412
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
413
    def pushBazaarBranch(self, bazaar_branch):
414
        """Push the updated Bazaar branch to the server.
10224.12.11 by Michael Hudson
some restructuring
415
416
        :return: True if revisions were transferred.
417
        """
10224.12.7 by Michael Hudson
tests and ugly code for having the workers exit with the right code
418
        return self.bazaar_branch_store.push(
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
419
            self.source_details.branch_id, bazaar_branch,
420
            self.required_format)
8615.12.1 by Michael Hudson
basically noop changes that provide a place to hang the changes i want to make.
421
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
422
    def getWorkingDirectory(self):
423
        """The directory we should change to and store all scratch files in.
424
        """
425
        base = config.codeimportworker.working_directory_root
426
        dirname = 'worker-for-branch-%s' % self.source_details.branch_id
427
        return os.path.join(base, dirname)
428
429
    def run(self):
430
        """Run the code import job.
431
432
        This is the primary public interface to the `ImportWorker`. This
433
        method:
434
435
         1. Retrieves an up-to-date foreign tree to import.
436
         2. Gets the Bazaar branch to import into.
437
         3. Imports the foreign tree into the Bazaar branch. If we've
438
            already imported this before, we synchronize the imported Bazaar
439
            branch with the latest changes to the foreign tree.
440
         4. Publishes the newly-updated Bazaar branch, making it available to
441
            Launchpad users.
442
         5. Archives the foreign tree, so that we can update it quickly next
443
            time.
444
        """
445
        working_directory = self.getWorkingDirectory()
446
        if os.path.exists(working_directory):
447
            shutil.rmtree(working_directory)
448
        os.makedirs(working_directory)
7675.76.10 by Michael Hudson
clean up some old hacks. TestCVSImport.test_sync is broken though
449
        saved_pwd = os.getcwd()
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
450
        os.chdir(working_directory)
451
        try:
10271.2.1 by Michael Hudson
well, this passes existing tests...
452
            return self._doImport()
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
453
        finally:
454
            shutil.rmtree(working_directory)
7675.76.10 by Michael Hudson
clean up some old hacks. TestCVSImport.test_sync is broken though
455
            os.chdir(saved_pwd)
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
456
457
    def _doImport(self):
10224.12.11 by Michael Hudson
some restructuring
458
        """Perform the import.
459
460
        :return: True if the import actually imported some new revisions.
461
        """
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
462
        raise NotImplementedError()
463
464
465
class CSCVSImportWorker(ImportWorker):
466
    """An ImportWorker for imports that use CSCVS.
467
468
    As well as invoking cscvs to do the import, this class also needs to
469
    manage a foreign working tree.
470
    """
471
472
    # Where the foreign working tree will be stored.
473
    FOREIGN_WORKING_TREE_PATH = 'foreign_working_tree'
474
8615.12.20 by Michael Hudson
sneaky test fix
475
    @cachedproperty
8615.12.15 by Michael Hudson
docstrings, some more clarity
476
    def foreign_tree_store(self):
477
        return ForeignTreeStore(self.import_data_store)
7675.72.5 by Michael Hudson
begin moving code from ImportWorker into CSCVSImportWorker
478
5670.2.32 by jml at canonical
_getForeignBranch -> _getForeignTree.
479
    def getForeignTree(self):
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
480
        """Return the foreign branch object that we are importing from.
481
482
        :return: A `SubversionWorkingTree` or a `CVSWorkingTree`.
483
        """
6290.2.1 by Michael Hudson
this seems to be it?
484
        if os.path.isdir(self.FOREIGN_WORKING_TREE_PATH):
485
            shutil.rmtree(self.FOREIGN_WORKING_TREE_PATH)
486
        os.mkdir(self.FOREIGN_WORKING_TREE_PATH)
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
487
        return self.foreign_tree_store.fetch(self.FOREIGN_WORKING_TREE_PATH)
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
488
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
489
    def importToBazaar(self, foreign_tree, bazaar_branch):
490
        """Actually import `foreign_tree` into `bazaar_branch`.
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
491
5670.2.31 by jml at canonical
Terminology change: foreign branch -> foreign tree.
492
        :param foreign_tree: A `SubversionWorkingTree` or a `CVSWorkingTree`.
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
493
        :param bazaar_tree: A `bzrlib.branch.Branch`, which must have a
494
            colocated working tree.
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
495
        """
5670.2.31 by jml at canonical
Terminology change: foreign branch -> foreign tree.
496
        foreign_directory = foreign_tree.local_path
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
497
        bzr_directory = str(bazaar_branch.bzrdir.open_workingtree().basedir)
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
498
499
        scm_branch = SCM.branch(bzr_directory)
500
        last_commit = cscvs.findLastCscvsCommit(scm_branch)
501
502
        # If branch in `bazaar_tree` doesn't have any identifiable CSCVS
503
        # revisions, CSCVS "initialises" the branch.
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
504
        if last_commit is None:
505
            self._runToBaz(
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
506
                foreign_directory, "-SI", "MAIN.1", bzr_directory)
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
507
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
508
        # Now we synchronise the branch, that is, import all new revisions
509
        # from the foreign branch into the Bazaar branch. If we've just
510
        # initialized the Bazaar branch, then this means we import *all*
511
        # revisions.
512
        last_commit = cscvs.findLastCscvsCommit(scm_branch)
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
513
        self._runToBaz(
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
514
            foreign_directory, "-SC", "%s::" % last_commit, bzr_directory)
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
515
516
    def _runToBaz(self, source_dir, flags, revisions, bazpath):
5670.2.23 by jml at canonical
Mostly a bucket-load of docstrings. Also remove unused code.
517
        """Actually run the CSCVS utility that imports revisions.
518
519
        :param source_dir: The directory containing the foreign working tree
520
            that we are importing from.
521
        :param flags: Flags to pass to `totla.totla`.
522
        :param revisions: The revisions to import.
523
        :param bazpath: The directory containing the Bazaar working tree that
524
            we are importing into.
525
        """
526
        # XXX: JonathanLange 2008-02-08: We need better documentation for
527
        # `flags` and `revisions`.
5670.2.12 by jml at canonical
The worker itself! Finally. Still needs some cleanup.
528
        config = CVS.Config(source_dir)
529
        config.args = ["--strict", "-b", bazpath,
530
                       flags, revisions, bazpath]
531
        totla.totla(config, self._logger, config.args, SCM.tree(source_dir))
532
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
533
    def _doImport(self):
534
        foreign_tree = self.getForeignTree()
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
535
        bazaar_branch = self.getBazaarBranch()
536
        self.importToBazaar(foreign_tree, bazaar_branch)
537
        non_trivial = self.pushBazaarBranch(bazaar_branch)
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
538
        self.foreign_tree_store.archive(foreign_tree)
10271.2.1 by Michael Hudson
well, this passes existing tests...
539
        if non_trivial:
540
            return CodeImportWorkerExitCode.SUCCESS
541
        else:
542
            return CodeImportWorkerExitCode.SUCCESS_NOCHANGE
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
543
544
545
class PullingImportWorker(ImportWorker):
7675.76.2 by Michael Hudson
small refactoring
546
    """An import worker for imports that can be done by a bzr plugin.
547
13081.2.12 by Jelmer Vernooij
format_classes -> probers.
548
    Subclasses need to implement `probers`.
7675.76.2 by Michael Hudson
small refactoring
549
    """
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
550
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
551
    needs_bzr_tree = False
552
9949.2.4 by Michael Hudson
sort of works
553
    @property
13081.2.12 by Jelmer Vernooij
format_classes -> probers.
554
    def probers(self):
555
        """The probers that should be tried for this import."""
9949.2.4 by Michael Hudson
sort of works
556
        raise NotImplementedError
557
13081.2.13 by Jelmer Vernooij
Use new fetch(limit=) API.
558
    def getRevisionLimit(self):
559
        """Return maximum number of revisions to fetch (None for no limit).
10271.2.8 by Michael Hudson
docstring
560
        """
13081.2.13 by Jelmer Vernooij
Use new fetch(limit=) API.
561
        return None
10271.2.3 by Michael Hudson
finish off worker code, perhaps
562
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
563
    def _doImport(self):
10677.1.3 by Michael Hudson
more logging, delete commented out mystery line
564
        self._logger.info("Starting job.")
8340.1.5 by Michael Hudson
* install LoggingUIFactory in worker
565
        saved_factory = bzrlib.ui.ui_factory
566
        bzrlib.ui.ui_factory = LoggingUIFactory(
8340.1.9 by Michael Hudson
address most review comments
567
            writer=lambda m: self._logger.info('%s', m))
8340.1.5 by Michael Hudson
* install LoggingUIFactory in worker
568
        try:
10677.1.2 by Michael Hudson
add some logging statements
569
            self._logger.info(
570
                "Getting exising bzr branch from central store.")
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
571
            bazaar_branch = self.getBazaarBranch()
10129.7.1 by Tim Penhey
Minor tweaks mentioned in review.
572
            transport = get_transport(self.source_details.url)
13081.2.12 by Jelmer Vernooij
format_classes -> probers.
573
            for prober_kls in self.probers:
574
                prober = prober_kls()
9949.2.5 by Michael Hudson
support multiple formats to keep git testable
575
                try:
13081.2.12 by Jelmer Vernooij
format_classes -> probers.
576
                    format = prober.probe_transport(transport)
9949.2.10 by Michael Hudson
oops
577
                    break
9949.2.5 by Michael Hudson
support multiple formats to keep git testable
578
                except NotBranchError:
579
                    pass
580
            else:
10129.7.1 by Tim Penhey
Minor tweaks mentioned in review.
581
                raise NotBranchError(self.source_details.url)
13081.1.1 by Jelmer Vernooij
Rename foreign_branch to remote_branch.
582
            remote_branch = format.open(transport).open_branch()
583
            remote_branch_tip = remote_branch.last_revision()
584
            inter_branch = InterBranch.get(remote_branch, bazaar_branch)
585
            self._logger.info("Importing branch.")
13081.2.13 by Jelmer Vernooij
Use new fetch(limit=) API.
586
            inter_branch.fetch(limit=self.getRevisionLimit())
587
            if bazaar_branch.repository.has_revision(remote_branch_tip):
588
                pull_result = inter_branch.pull(overwrite=True)
589
                if pull_result.old_revid != pull_result.new_revid:
590
                    result = CodeImportWorkerExitCode.SUCCESS
591
                else:
592
                    result = CodeImportWorkerExitCode.SUCCESS_NOCHANGE
593
            else:
594
                result = CodeImportWorkerExitCode.SUCCESS_PARTIAL
13081.1.1 by Jelmer Vernooij
Rename foreign_branch to remote_branch.
595
            self._logger.info("Pushing local import branch to central store.")
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
596
            self.pushBazaarBranch(bazaar_branch)
10677.1.3 by Michael Hudson
more logging, delete commented out mystery line
597
            self._logger.info("Job complete.")
13081.2.13 by Jelmer Vernooij
Use new fetch(limit=) API.
598
            return result
8340.1.5 by Michael Hudson
* install LoggingUIFactory in worker
599
        finally:
600
            bzrlib.ui.ui_factory = saved_factory
7675.76.2 by Michael Hudson
small refactoring
601
602
603
class GitImportWorker(PullingImportWorker):
8615.12.15 by Michael Hudson
docstrings, some more clarity
604
    """An import worker for Git imports.
605
606
    The only behaviour we add is preserving the 'git.db' shamap between runs.
607
    """
8615.12.1 by Michael Hudson
basically noop changes that provide a place to hang the changes i want to make.
608
7675.76.4 by Michael Hudson
merge lots of trunk, fixing conflicts
609
    @property
13081.2.12 by Jelmer Vernooij
format_classes -> probers.
610
    def probers(self):
611
        """See `PullingImportWorker.probers`."""
9949.2.5 by Michael Hudson
support multiple formats to keep git testable
612
        from bzrlib.plugins.git import (
13081.2.12 by Jelmer Vernooij
format_classes -> probers.
613
            LocalGitProber, RemoteGitProber)
614
        return [LocalGitProber, RemoteGitProber]
9949.2.4 by Michael Hudson
sort of works
615
13081.2.13 by Jelmer Vernooij
Use new fetch(limit=) API.
616
    def getRevisionLimit(self):
617
        """See `PullingImportWorker.getRevisionLimit`."""
618
        return config.codeimport.git_revisions_import_limit
10271.2.3 by Michael Hudson
finish off worker code, perhaps
619
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
620
    def getBazaarBranch(self):
621
        """See `ImportWorker.getBazaarBranch`.
8615.12.15 by Michael Hudson
docstrings, some more clarity
622
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
623
        In addition to the superclass' behaviour, we retrieve bzr-git's
624
        caches, both legacy and modern, from the import data store and put
625
        them where bzr-git will find them in the Bazaar tree, that is at
626
        '.bzr/repository/git.db' and '.bzr/repository/git'.
8615.12.15 by Michael Hudson
docstrings, some more clarity
627
        """
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
628
        branch = PullingImportWorker.getBazaarBranch(self)
10651.1.4 by Michael Hudson
review comments
629
        # Fetch the legacy cache from the store, if present.
8615.12.11 by Michael Hudson
this interface finally makes sense, maybe
630
        self.import_data_store.fetch(
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
631
            'git.db', branch.repository._transport)
10651.1.4 by Michael Hudson
review comments
632
        # The cache dir from newer bzr-gits is stored as a tarball.
10651.1.1 by Michael Hudson
first attempt
633
        local_name = 'git-cache.tar.gz'
10651.1.2 by Michael Hudson
assorted fixes
634
        if self.import_data_store.fetch(local_name):
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
635
            repo_transport = branch.repository._transport
10651.1.2 by Michael Hudson
assorted fixes
636
            repo_transport.mkdir('git')
10651.1.1 by Michael Hudson
first attempt
637
            git_db_dir = os.path.join(
638
                local_path_from_url(repo_transport.base), 'git')
639
            extract_tarball(local_name, git_db_dir)
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
640
        return branch
641
642
    def pushBazaarBranch(self, bazaar_branch):
643
        """See `ImportWorker.pushBazaarBranch`.
644
645
        In addition to the superclass' behaviour, we store bzr-git's cache
646
        directory at .bzr/repository/git in the import data store.
8615.12.15 by Michael Hudson
docstrings, some more clarity
647
        """
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
648
        non_trivial = PullingImportWorker.pushBazaarBranch(
649
            self, bazaar_branch)
650
        repo_base = bazaar_branch.repository._transport.base
651
        git_db_dir = os.path.join(local_path_from_url(repo_base), 'git')
10651.1.1 by Michael Hudson
first attempt
652
        local_name = 'git-cache.tar.gz'
10651.1.2 by Michael Hudson
assorted fixes
653
        create_tarball(git_db_dir, local_name)
654
        self.import_data_store.put(local_name)
10224.12.12 by Michael Hudson
some renaming and a fix for hg
655
        return non_trivial
7675.76.2 by Michael Hudson
small refactoring
656
657
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
658
class HgImportWorker(PullingImportWorker):
659
    """An import worker for Mercurial imports.
660
10129.6.22 by Tim Penhey
Docstring fixes.
661
    The only behaviour we add is preserving the id-sha map between runs.
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
662
    """
663
664
    @property
13081.2.12 by Jelmer Vernooij
format_classes -> probers.
665
    def probers(self):
666
        """See `PullingImportWorker.probers`."""
667
        from bzrlib.plugins.hg import HgProber
668
        return [HgProber]
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
669
13081.2.13 by Jelmer Vernooij
Use new fetch(limit=) API.
670
    def getRevisionLimit(self):
671
        """See `PullingImportWorker.getRevisionLimit`."""
672
        return config.codeimport.hg_revisions_import_limit
673
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
674
    def getBazaarBranch(self):
675
        """See `ImportWorker.getBazaarBranch`.
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
676
11346.6.5 by Jelmer Vernooij
update docstrings.
677
        In addition to the superclass' behaviour, we retrieve the bzr-hg's
678
        caches, both legacy and current and put them where bzr-hg will find
679
        them in the Bazaar tree, that is at '.bzr/repository/hg-v2.db' and
680
        '.bzr/repository/hg'.
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
681
        """
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
682
        branch = PullingImportWorker.getBazaarBranch(self)
11346.6.1 by Jelmer Vernooij
Use newer version of bzr-hg, fix tests when tdb is installed.
683
        # Fetch the legacy cache from the store, if present.
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
684
        self.import_data_store.fetch(
11346.6.1 by Jelmer Vernooij
Use newer version of bzr-hg, fix tests when tdb is installed.
685
            'hg-v2.db', branch.repository._transport)
686
        # The cache dir from newer bzr-hgs is stored as a tarball.
687
        local_name = 'hg-cache.tar.gz'
688
        if self.import_data_store.fetch(local_name):
689
            repo_transport = branch.repository._transport
690
            repo_transport.mkdir('hg')
691
            hg_db_dir = os.path.join(
692
                local_path_from_url(repo_transport.base), 'hg')
693
            extract_tarball(local_name, hg_db_dir)
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
694
        return branch
695
696
    def pushBazaarBranch(self, bazaar_branch):
697
        """See `ImportWorker.pushBazaarBranch`.
698
11346.6.5 by Jelmer Vernooij
update docstrings.
699
        In addition to the superclass' behaviour, we store the hg cache
700
        that bzr-hg will have created at .bzr/repository/hg into
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
701
        the import data store.
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
702
        """
10677.1.1 by Michael Hudson
don't create a working tree for code imports if it's not needed
703
        non_trivial = PullingImportWorker.pushBazaarBranch(
704
            self, bazaar_branch)
11346.6.1 by Jelmer Vernooij
Use newer version of bzr-hg, fix tests when tdb is installed.
705
        repo_base = bazaar_branch.repository._transport.base
706
        hg_db_dir = os.path.join(local_path_from_url(repo_base), 'hg')
707
        local_name = 'hg-cache.tar.gz'
708
        create_tarball(hg_db_dir, local_name)
709
        self.import_data_store.put(local_name)
10224.12.12 by Michael Hudson
some renaming and a fix for hg
710
        return non_trivial
9905.7.3 by Jelmer Vernooij
Initial work on a HgImportWorker.
711
712
7675.76.2 by Michael Hudson
small refactoring
713
class BzrSvnImportWorker(PullingImportWorker):
7675.76.8 by Michael Hudson
cleanups
714
    """An import worker for importing Subversion via bzr-svn."""
7675.76.2 by Michael Hudson
small refactoring
715
13081.2.13 by Jelmer Vernooij
Use new fetch(limit=) API.
716
    def getRevisionLimit(self):
717
        """See `PullingImportWorker.getRevisionLimit`."""
718
        return config.codeimport.svn_revisions_import_limit
10490.1.2 by Michael Hudson
this is it
719
7675.76.4 by Michael Hudson
merge lots of trunk, fixing conflicts
720
    @property
13081.2.12 by Jelmer Vernooij
format_classes -> probers.
721
    def probers(self):
722
        """See `PullingImportWorker.probers`."""
723
        from bzrlib.plugins.svn import SvnRemoteProber
724
        return [SvnRemoteProber]