~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to baz_import.py

  • Committer: Aaron Bentley
  • Date: 2005-06-07 18:52:04 UTC
  • Revision ID: abentley@panoramicfeedback.com-20050607185204-5fc1f0e3d393b909
Added NEWS, obsoleted bzr-pull

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Aaron Bentley
2
 
 
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
 
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
 
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
from bzrlib.errors import NotBranchError
18
 
from bzrlib.branch import Branch, find_branch
19
 
from bzrlib.commands import Command
20
 
from errors import NoPyBaz
21
 
try:
22
 
    import pybaz
23
 
    import pybaz.errors
24
 
    from pybaz.backends.baz import null_cmd
25
 
except ImportError:
26
 
    raise NoPyBaz
27
 
import tempfile
28
 
import os
29
 
import os.path
30
 
import shutil
31
 
import bzrlib
32
 
from bzrlib.errors import BzrError
33
 
import bzrlib.trace
34
 
import bzrlib.merge
35
 
import bzrlib.inventory
36
 
import bzrlib.osutils
37
 
import sys
38
 
import email.Utils
39
 
from progress import *
40
 
 
41
 
def add_id(files, id=None):
42
 
    """Adds an explicit id to a list of files.
43
 
 
44
 
    :param files: the name of the file to add an id to
45
 
    :type files: list of str
46
 
    :param id: tag one file using the specified id, instead of generating id
47
 
    :type id: str
48
 
    """
49
 
    args = ["add-id"]
50
 
    if id is not None:
51
 
        args.extend(["--id", id])
52
 
    args.extend(files)
53
 
    return null_cmd(args)
54
 
 
55
 
saved_dir = None
56
 
 
57
 
def test_environ():
58
 
    """
59
 
    >>> q = test_environ()
60
 
    >>> os.path.exists(q)
61
 
    True
62
 
    >>> os.path.exists(os.path.join(q, "home", ".arch-params"))
63
 
    True
64
 
    >>> teardown_environ(q)
65
 
    >>> os.path.exists(q)
66
 
    False
67
 
    """
68
 
    global saved_dir
69
 
    saved_dir = os.getcwdu()
70
 
    tdir = tempfile.mkdtemp(prefix="testdir-")
71
 
    os.environ["HOME"] = os.path.join(tdir, "home")
72
 
    os.mkdir(os.environ["HOME"])
73
 
    arch_dir = os.path.join(tdir, "archive_dir")
74
 
    pybaz.make_archive("test@example.com", arch_dir)
75
 
    work_dir = os.path.join(tdir, "work_dir")
76
 
    os.mkdir(work_dir)
77
 
    os.chdir(work_dir)
78
 
    pybaz.init_tree(work_dir, "test@example.com/test--test--0")
79
 
    lib_dir = os.path.join(tdir, "lib_dir")
80
 
    os.mkdir(lib_dir)
81
 
    pybaz.register_revision_library(lib_dir)
82
 
    pybaz.set_my_id("Test User<test@example.org>")
83
 
    return tdir
84
 
 
85
 
def add_file(path, text, id):
86
 
    """
87
 
    >>> q = test_environ()
88
 
    >>> add_file("path with space", "text", "lalala")
89
 
    >>> tree = pybaz.tree_root(".")
90
 
    >>> inv = list(tree.iter_inventory_ids(source=True, both=True))
91
 
    >>> ("x_lalala", "path with space") in inv
92
 
    True
93
 
    >>> teardown_environ(q)
94
 
    """
95
 
    file(path, "wb").write(text)
96
 
    add_id([path], id)
97
 
 
98
 
 
99
 
def add_dir(path, id):
100
 
    """
101
 
    >>> q = test_environ()
102
 
    >>> add_dir("path with\(sp) space", "lalala")
103
 
    >>> tree = pybaz.tree_root(".")
104
 
    >>> inv = list(tree.iter_inventory_ids(source=True, both=True))
105
 
    >>> ("x_lalala", "path with\(sp) space") in inv
106
 
    True
107
 
    >>> teardown_environ(q)
108
 
    """
109
 
    os.mkdir(path)
110
 
    add_id([path], id)
111
 
 
112
 
def teardown_environ(tdir):
113
 
    os.chdir(saved_dir)
114
 
    shutil.rmtree(tdir)
115
 
 
116
 
def timport(tree, summary):
117
 
    msg = tree.log_message()
118
 
    msg["summary"] = summary
119
 
    tree.import_(msg)
120
 
 
121
 
def commit(tree, summary):
122
 
    """
123
 
    >>> q = test_environ()
124
 
    >>> tree = pybaz.tree_root(".")
125
 
    >>> timport(tree, "import")
126
 
    >>> commit(tree, "commit")
127
 
    >>> logs = [str(l.revision) for l in tree.iter_logs()]
128
 
    >>> len(logs)
129
 
    2
130
 
    >>> logs[0]
131
 
    'test@example.com/test--test--0--base-0'
132
 
    >>> logs[1]
133
 
    'test@example.com/test--test--0--patch-1'
134
 
    >>> teardown_environ(q)
135
 
    """
136
 
    msg = tree.log_message()
137
 
    msg["summary"] = summary
138
 
    tree.commit(msg)
139
 
 
140
 
def commit_test_revisions():
141
 
    """
142
 
    >>> q = test_environ()
143
 
    >>> commit_test_revisions()
144
 
    >>> a = pybaz.Archive("test@example.com")
145
 
    >>> revisions = list(a.iter_revisions("test--test--0"))
146
 
    >>> len(revisions)
147
 
    3
148
 
    >>> str(revisions[2])
149
 
    'test@example.com/test--test--0--base-0'
150
 
    >>> str(revisions[1])
151
 
    'test@example.com/test--test--0--patch-1'
152
 
    >>> str(revisions[0])
153
 
    'test@example.com/test--test--0--patch-2'
154
 
    >>> teardown_environ(q)
155
 
    """
156
 
    tree = pybaz.tree_root(".")
157
 
    add_file("mainfile", "void main(void){}", "mainfile by aaron")
158
 
    timport(tree, "Created mainfile")
159
 
    file("mainfile", "wb").write("or something like that")
160
 
    commit(tree, "altered mainfile")
161
 
    add_file("ofile", "this is another file", "ofile by aaron")
162
 
    commit(tree, "altered mainfile")
163
 
 
164
 
 
165
 
def commit_more_test_revisions():
166
 
    """
167
 
    >>> q = test_environ()
168
 
    >>> commit_test_revisions()
169
 
    >>> commit_more_test_revisions()
170
 
    >>> a = pybaz.Archive("test@example.com")
171
 
    >>> revisions = list(a.iter_revisions("test--test--0"))
172
 
    >>> len(revisions)
173
 
    4
174
 
    >>> str(revisions[0])
175
 
    'test@example.com/test--test--0--patch-3'
176
 
    >>> teardown_environ(q)
177
 
    """
178
 
    tree = pybaz.tree_root(".")
179
 
    add_file("trainfile", "void train(void){}", "trainfile by aaron")
180
 
    commit(tree, "altered trainfile")
181
 
 
182
 
class NoSuchVersion(Exception):
183
 
    def __init__(self, version):
184
 
        Exception.__init__(self, "The version %s does not exist." % version)
185
 
        self.version = version
186
 
 
187
 
def version_ancestry(version):
188
 
    """
189
 
    >>> q = test_environ()
190
 
    >>> commit_test_revisions()
191
 
    >>> version = pybaz.Version("test@example.com/test--test--0")
192
 
    >>> ancestors = version_ancestry(version)
193
 
    >>> str(ancestors[0])
194
 
    'test@example.com/test--test--0--base-0'
195
 
    >>> str(ancestors[1])
196
 
    'test@example.com/test--test--0--patch-1'
197
 
    >>> version = pybaz.Version("test@example.com/test--test--0.5")
198
 
    >>> ancestors = version_ancestry(version)
199
 
    Traceback (most recent call last):
200
 
    NoSuchVersion: The version test@example.com/test--test--0.5 does not exist.
201
 
    >>> teardown_environ(q)
202
 
    """
203
 
    try:
204
 
        revision = version.iter_revisions(reverse=True).next()
205
 
    except:
206
 
        print version
207
 
        if not version.exists():
208
 
            raise NoSuchVersion(version)
209
 
        else:
210
 
            raise
211
 
    ancestors = list(revision.iter_ancestors(metoo=True))
212
 
    ancestors.reverse()
213
 
    return ancestors
214
 
 
215
 
def get_last_revision(branch):
216
 
    last_patch = branch.last_patch()
217
 
    try:
218
 
        return arch_revision(last_patch)
219
 
    except NotArchRevision:
220
 
        raise UserError(
221
 
            "Directory \"%s\" already exists, and the last revision is not"
222
 
            " an Arch revision (%s)" % (output_dir, last_patch))
223
 
 
224
 
 
225
 
def get_remaining_revisions(output_dir, version):
226
 
    last_patch = None
227
 
    old_revno = None
228
 
    if os.path.exists(output_dir):
229
 
        # We are starting from an existing directory, figure out what
230
 
        # the current version is
231
 
        branch = find_branch(output_dir, find_root=False)
232
 
        last_patch = get_last_revision(branch)
233
 
        if version is None:
234
 
            version = last_patch.version
235
 
    elif version is None:
236
 
        raise UserError("No version specified, and directory does not exist.")
237
 
 
238
 
    try:
239
 
        ancestors = version_ancestry(version)
240
 
    except NoSuchVersion, e:
241
 
        raise UserError(e)
242
 
 
243
 
    if last_patch:
244
 
        for i in range(len(ancestors)):
245
 
            if ancestors[i] == last_patch:
246
 
                break
247
 
        else:
248
 
            raise UserError("Directory \"%s\" already exists, and the last "
249
 
                "revision (%s) is not in the ancestry of %s" % 
250
 
                (output_dir, last_patch, version))
251
 
        # Strip off all of the ancestors which are already present
252
 
        # And get a directory starting with the latest ancestor
253
 
        latest_ancestor = ancestors[i]
254
 
        old_revno = find_branch(output_dir, find_root=False).revno()
255
 
        ancestors = ancestors[i+1:]
256
 
    return ancestors, old_revno
257
 
 
258
 
def import_version(output_dir, version, fancy=True, fast=False, verbose=False, 
259
 
                   dry_run=False, max_count=None):
260
 
    """
261
 
    >>> q = test_environ()
262
 
    >>> result_path = os.path.join(q, "result")
263
 
    >>> commit_test_revisions()
264
 
    >>> version = pybaz.Version("test@example.com/test--test--0.1")
265
 
    >>> import_version('/', version, fancy=False, dry_run=True)
266
 
    Traceback (most recent call last):
267
 
    UserError: / exists, but is not a bzr branch.
268
 
    >>> import_version(result_path, version, fancy=False, dry_run=True)
269
 
    Traceback (most recent call last):
270
 
    UserError: The version test@example.com/test--test--0.1 does not exist.
271
 
    >>> version = pybaz.Version("test@example.com/test--test--0")
272
 
    >>> import_version(result_path, version, fancy=False, dry_run=True)
273
 
    not fancy
274
 
    ....
275
 
    Dry run, not modifying output_dir
276
 
    Cleaning up
277
 
    >>> import_version(result_path, version, fancy=False)
278
 
    not fancy
279
 
    ....
280
 
    Cleaning up
281
 
    Import complete.
282
 
    >>> import_version(result_path, version, fancy=False)
283
 
    Tree is up-to-date with test@example.com/test--test--0--patch-2
284
 
    >>> commit_more_test_revisions()
285
 
    >>> import_version(result_path, version, fancy=False)
286
 
    not fancy
287
 
    ..
288
 
    Cleaning up
289
 
    Import complete.
290
 
    >>> teardown_environ(q)
291
 
    """
292
 
    try:
293
 
        ancestors, old_revno = get_remaining_revisions(output_dir, version)
294
 
    except NotBranchError, e:
295
 
        raise UserError("%s exists, but is not a bzr branch." % output_dir)
296
 
    if len(ancestors) == 0:
297
 
        last_revision = get_last_revision(find_branch(output_dir, find_root=False))
298
 
        print 'Tree is up-to-date with %s' % last_revision
299
 
        return
300
 
 
301
 
    progress_bar = ProgressBar()
302
 
    tempdir = tempfile.mkdtemp(prefix="baz2bzr-",
303
 
                               dir=os.path.dirname(output_dir))
304
 
    try:
305
 
        if not fancy:
306
 
            print "not fancy"
307
 
        try:
308
 
            for result in iter_import_version(output_dir, ancestors, tempdir,
309
 
                    fast=fast, verbose=verbose, dry_run=dry_run, 
310
 
                    max_count=max_count):
311
 
                if fancy:
312
 
                    show_progress(progress_bar, result)
313
 
                else:
314
 
                    sys.stdout.write('.')
315
 
        finally:
316
 
            if fancy:
317
 
                progress_bar.clear()
318
 
            else:
319
 
                sys.stdout.write('\n')
320
 
 
321
 
        if dry_run:
322
 
            print 'Dry run, not modifying output_dir'
323
 
            return
324
 
        if os.path.exists(output_dir):
325
 
            # Move the bzr control directory back, and update the working tree
326
 
            tmp_bzr_dir = os.path.join(tempdir, '.bzr')
327
 
            
328
 
            bzr_dir = os.path.join(output_dir, '.bzr')
329
 
            new_bzr_dir = os.path.join(tempdir, "rd", '.bzr')
330
 
 
331
 
            os.rename(bzr_dir, tmp_bzr_dir) # Move the original bzr out of the way
332
 
            os.rename(new_bzr_dir, bzr_dir)
333
 
            try:
334
 
                bzrlib.merge.merge((output_dir, -1), (output_dir, old_revno), 
335
 
                                   check_clean=False, this_dir=output_dir, 
336
 
                                   ignore_zero=True)
337
 
            except:
338
 
                # If something failed, move back the original bzr directory
339
 
                os.rename(bzr_dir, new_bzr_dir)
340
 
                os.rename(tmp_bzr_dir, bzr_dir)
341
 
                raise
342
 
        else:
343
 
            revdir = os.path.join(tempdir, "rd")
344
 
            os.rename(revdir, output_dir)
345
 
 
346
 
    finally:
347
 
        print 'Cleaning up'
348
 
        shutil.rmtree(tempdir)
349
 
    print "Import complete."
350
 
            
351
 
class UserError(Exception):
352
 
    def __init__(self, message):
353
 
        """Exception to throw when a user makes an impossible request
354
 
        :param message: The message to emit when printing this exception
355
 
        :type message: string
356
 
        """
357
 
        Exception.__init__(self, message)
358
 
 
359
 
def revision_id(arch_revision):
360
 
    """
361
 
    Generate a Bzr revision id from an Arch revision id.  'x' in the id
362
 
    designates a revision imported with an experimental algorithm.  A number
363
 
    would indicate a particular standardized version.
364
 
 
365
 
    :param arch_revision: The Arch revision to generate an ID for.
366
 
 
367
 
    >>> revision_id(pybaz.Revision("you@example.com/cat--br--0--base-0"))
368
 
    'Arch-1:you@example.com%cat--br--0--base-0'
369
 
    """
370
 
    return "Arch-1:%s" % str(arch_revision).replace('/', '%')
371
 
 
372
 
class NotArchRevision(Exception):
373
 
    def __init__(self, revision_id):
374
 
        msg = "The revision id %s does not look like it came from Arch."\
375
 
            % revision_id
376
 
        Exception.__init__(self, msg)
377
 
 
378
 
def arch_revision(revision_id):
379
 
    """
380
 
    >>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0"))
381
 
    Traceback (most recent call last):
382
 
    NotArchRevision: The revision id Arch-1:jrandom@example.com%test--test--0 does not look like it came from Arch.
383
 
    >>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--base-5"))
384
 
    Traceback (most recent call last):
385
 
    NotArchRevision: The revision id Arch-1:jrandom@example.com%test--test--0--base-5 does not look like it came from Arch.
386
 
    >>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--patch-5"))
387
 
    'jrandom@example.com/test--test--0--patch-5'
388
 
    """
389
 
    if revision_id is None:
390
 
        return None
391
 
    if revision_id[:7] != 'Arch-1:':
392
 
        raise NotArchRevision(revision_id)
393
 
    else:
394
 
        try:
395
 
            return pybaz.Revision(revision_id[7:].replace('%', '/'))
396
 
        except pybaz.errors.NamespaceError, e:
397
 
            raise NotArchRevision(revision_id)
398
 
            
399
 
def iter_import_version(output_dir, ancestors, tempdir, fast=False,
400
 
                        verbose=False, dry_run=False, max_count=None):
401
 
    revdir = None
402
 
 
403
 
    # Uncomment this for testing, it basically just has baz2bzr only update
404
 
    # 5 patches at a time
405
 
    if max_count:
406
 
        ancestors = ancestors[:max_count]
407
 
 
408
 
    # Not sure if I want this output. basically it tells you ahead of time
409
 
    # what it is going to do, but then later it tells you as it is doing it.
410
 
    # what probably would be best would be to collapse it into ranges, so that
411
 
    # this gives the simple view, and then later it gives the blow by blow.
412
 
    #if verbose:
413
 
    #    print 'Adding the following revisions:'
414
 
    #    for a in ancestors:
415
 
    #        print '\t%s' % a
416
 
 
417
 
    previous_version=None
418
 
 
419
 
    for i in range(len(ancestors)):
420
 
        revision = ancestors[i]
421
 
        direct_merges = []
422
 
        if verbose:
423
 
            version = str(revision.version)
424
 
            if version != previous_version:
425
 
                clear_progress_bar()
426
 
                print '\rOn version: %s' % version
427
 
            yield Progress(str(revision.patchlevel), i, len(ancestors))
428
 
            previous_version = version
429
 
        else:
430
 
            yield Progress("revisions", i, len(ancestors))
431
 
        if revdir is None:
432
 
            revdir = os.path.join(tempdir, "rd")
433
 
            baz_inv, log = get_revision(revdir, revision)
434
 
            # cached so we can delete the log
435
 
            log_date = log.date
436
 
            log_summary = log.summary
437
 
            log_creator = log.creator
438
 
            if os.path.exists(output_dir):
439
 
                bzr_dir = os.path.join(output_dir, '.bzr')
440
 
                new_bzr_dir = os.path.join(tempdir, "rd", '.bzr')
441
 
                # This would be much faster with a simple os.rename(), but if
442
 
                # we fail, we have corrupted the original .bzr directory.  Is
443
 
                # that a big problem, as we can just back out the last
444
 
                # revisions in .bzr/revision_history I don't really know
445
 
                shutil.copytree(bzr_dir, new_bzr_dir)
446
 
                # Now revdir should have a tree with the latest .bzr, and the
447
 
                # next revision of the baz tree
448
 
                branch = find_branch(revdir, find_root=False)
449
 
            else:
450
 
                branch = Branch(revdir, init=True)
451
 
        else:
452
 
            old = os.path.join(revdir, ".bzr")
453
 
            new = os.path.join(tempdir, ".bzr")
454
 
            os.rename(old, new)
455
 
            baz_inv, log = apply_revision(revdir, revision)
456
 
            log_date = log.date
457
 
            log_summary = log.summary
458
 
            log_creator = log.creator
459
 
            direct_merges = get_direct_merges(revdir, revision)
460
 
            os.rename(new, old)
461
 
            branch = find_branch(revdir, find_root=False)
462
 
        timestamp = email.Utils.mktime_tz(log_date + (0,))
463
 
        rev_id = revision_id(revision)
464
 
        branch.lock_write()
465
 
        try:
466
 
            for merge in direct_merges:
467
 
                branch.add_pending_merge(revision_id(merge.revision))
468
 
            branch.set_inventory(baz_inv)
469
 
            bzrlib.trace.silent = True
470
 
            branch.commit(log_summary, verbose=False, committer=log_creator,
471
 
                          timestamp=timestamp, timezone=0, rev_id=rev_id)
472
 
        finally:
473
 
            bzrlib.trace.silent = False   
474
 
            branch.unlock()
475
 
    yield Progress("revisions", len(ancestors), len(ancestors))
476
 
    unlink_unversioned(branch, revdir)
477
 
 
478
 
def get_direct_merges(revdir, revision):
479
 
    from fai.cmdutil import pylon, direct_merges
480
 
    if pybaz.WorkingTree(revdir).tree_version != revision.version:
481
 
        pybaz.WorkingTree(revdir).set_tree_version(revision.version)
482
 
    log_path = "%s/{arch}/%s/%s/%s/%s/patch-log/%s" % (revdir, 
483
 
        revision.category.nonarch, revision.branch.nonarch, 
484
 
        revision.version.nonarch, revision.archive, revision.patchlevel)
485
 
    temp_path = "templog"
486
 
    os.rename(log_path, temp_path)
487
 
    merges = list(pylon.iter_new_merges(revdir, revision.version))
488
 
    direct = direct_merges (merges)
489
 
    os.rename(temp_path, log_path)
490
 
    return direct
491
 
 
492
 
def unlink_unversioned(branch, revdir):
493
 
    for unversioned in branch.working_tree().extras():
494
 
        path = os.path.join(revdir, unversioned)
495
 
        if os.path.isdir(path):
496
 
            shutil.rmtree(path)
497
 
        else:
498
 
            os.unlink(path)
499
 
 
500
 
def get_log(tree, revision):
501
 
    log = tree.iter_logs(version=revision.version, reverse=True).next()
502
 
    assert str(log.revision) == str(revision), (log.revision, revision)
503
 
    return log
504
 
 
505
 
def get_revision(revdir, revision):
506
 
    revision.get(revdir)
507
 
    tree = pybaz.tree_root(revdir)
508
 
    log = get_log(tree, revision)
509
 
    try:
510
 
        return bzr_inventory_data(tree), log 
511
 
    except BadFileKind, e:
512
 
        raise UserError("Cannot convert %s because %s is a %s" % (revision,e.path, e.kind) )
513
 
 
514
 
 
515
 
def apply_revision(revdir, revision):
516
 
    tree = pybaz.tree_root(revdir)
517
 
    revision.apply(tree)
518
 
    log = get_log(tree, revision)
519
 
    try:
520
 
        return bzr_inventory_data(tree), log
521
 
    except BadFileKind, e:
522
 
        raise UserError("Cannot convert %s because %s is a %s" % (revision,e.path, e.kind) )
523
 
 
524
 
 
525
 
 
526
 
 
527
 
class BadFileKind(Exception):
528
 
    """The file kind is not permitted in bzr inventories"""
529
 
    def __init__(self, tree_root, path, kind):
530
 
        self.tree_root = tree_root
531
 
        self.path = path
532
 
        self.kind = kind
533
 
        Exception.__init__(self, "File %s is of forbidden type %s" %
534
 
                           (os.path.join(tree_root, path), kind))
535
 
 
536
 
def bzr_inventory_data(tree):
537
 
    inv_iter = tree.iter_inventory_ids(source=True, both=True)
538
 
    inv_map = {}
539
 
    for arch_id, path in inv_iter:
540
 
        bzr_file_id = arch_id.replace('%', '%25').replace('/', '%2f')
541
 
        inv_map[path] = bzr_file_id 
542
 
 
543
 
    bzr_inv = []
544
 
    for path, file_id in inv_map.iteritems():
545
 
        full_path = os.path.join(tree, path)
546
 
        kind = bzrlib.osutils.file_kind(full_path)
547
 
        if kind not in ("file", "directory", "symlink"):
548
 
            raise BadFileKind(tree, path, kind)
549
 
        parent_dir = os.path.dirname(path)
550
 
        if parent_dir != "":
551
 
            parent_id = inv_map[parent_dir]
552
 
        else:
553
 
            parent_id = bzrlib.inventory.ROOT_ID
554
 
        bzr_inv.append((path, file_id, parent_id, kind))
555
 
    bzr_inv.sort()
556
 
    return bzr_inv
557
 
 
558
 
 
559
 
class cmd_baz_import(Command):
560
 
    """Import an Arch or Baz branch into a bzr branch"""
561
 
    takes_args = ['to_location', 'from_branch?']
562
 
    takes_options = ['verbose']
563
 
 
564
 
    def run(self, to_location, from_branch=None, fast=False, max_count=None,
565
 
            verbose=False, dry_run=False):
566
 
        to_location = os.path.realpath(str(to_location))
567
 
        if from_branch is not None:
568
 
            try:
569
 
                from_branch = pybaz.Version(from_branch)
570
 
            except pybaz.errors.NamespaceError:
571
 
                print "%s is not a valid Arch branch." % from_branch
572
 
                return 1
573
 
        import_version(to_location, from_branch)