275
271
br_from.bzrdir.clone(to_location, revision_id)
276
272
except NoSuchRevision:
277
273
rmtree(to_location)
278
msg = "The branch %s has no revision %s." % (from_location,
274
msg = "The branch %s has no revision %s." % (from_location,
280
276
raise UserError(msg)
284
def get_remaining_revisions(output_dir, version, encoding,
285
reuse_history_from=[]):
280
def get_remaining_revisions(output_dir, version, reuse_history_from=[]):
286
281
last_patch = None
288
283
output_exists = os.path.exists(output_dir)
290
285
# We are starting from an existing directory, figure out what
291
286
# the current version is
292
287
branch = Branch.open(output_dir)
293
last_patch, last_encoding = get_last_revision(branch)
294
assert encoding == last_encoding
288
last_patch = get_last_revision(branch)
295
289
if last_patch is None:
296
290
if branch.last_revision() != None:
297
291
raise NotPreviousImport(branch.base)
310
304
# try to grab a copy of ancestor
311
305
# note that is not optimised: we could look for namespace
312
# transitions and only look for the past after the
306
# transitions and only look for the past after the
314
308
for history_root in reuse_history_from:
315
309
possible_source = os.path.join(history_root,
316
310
map_namespace(ancestor.version))
318
312
source = Branch.open(possible_source)
319
rev_id = revision_id(ancestor, encoding)
313
rev_id = revision_id(ancestor)
320
314
if rev_id in source.revision_history():
321
315
do_branch(source, output_dir, rev_id)
322
316
last_patch = ancestor
334
328
raise UserError("Directory \"%s\" already exists, and the last "
335
"revision (%s) is not in the ancestry of %s" %
329
"revision (%s) is not in the ancestry of %s" %
336
330
(output_dir, last_patch, version))
337
331
# Strip off all of the ancestors which are already present
338
332
# And get a directory starting with the latest ancestor
345
339
###class Importer(object):
346
340
### """An importer.
348
342
### Currently this is used as a parameter object, though more behaviour is
349
343
### possible later.
352
346
### def __init__(self, output_dir, version, fast=False,
353
### verbose=False, dry_run=False, max_count=None,
347
### verbose=False, dry_run=False, max_count=None,
354
348
### reuse_history_from=[]):
355
349
### self.output_dir = output_dir
356
350
### self.version = version
360
def import_version(output_dir, version, encoding, fast=False,
354
def import_version(output_dir, version, fast=False,
361
355
verbose=False, dry_run=False, max_count=None,
362
356
reuse_history_from=[], standalone=True):
364
358
>>> q = test_environ()
366
360
Progress bars output to stderr, but doctest does not capture that.
368
362
>>> old_stderr = sys.stderr
375
369
>>> bzrlib.ui.ui_factory = bzrlib.ui.text.TextUIFactory(
376
370
... bar_type=bzrlib.progress.DotsProgressBar)
378
>>> import_version('/', version, None, dry_run=True)
372
>>> import_version('/', version, dry_run=True)
379
373
Traceback (most recent call last):
380
374
NotPreviousImport: / is not the location of a previous import.
381
>>> import_version(result_path, version, None, dry_run=True)
375
>>> import_version(result_path, version, dry_run=True)
382
376
Traceback (most recent call last):
383
377
UserError: The version test@example.com/test--test--0.1 does not exist.
384
378
>>> version = pybaz.Version("test@example.com/test--test--0")
385
>>> import_version(result_path, version, None, dry_run=True) #doctest: +ELLIPSIS
379
>>> import_version(result_path, version, dry_run=True) #doctest: +ELLIPSIS
386
380
importing test@example.com/test--test--0 into ...
388
382
revisions: ..........................................
389
383
Dry run, not modifying output_dir
391
>>> import_version(result_path, version, None) #doctest: +ELLIPSIS
385
>>> import_version(result_path, version) #doctest: +ELLIPSIS
392
386
importing test@example.com/test--test--0 into ...
394
388
revisions: .....................................................................
397
>>> import_version(result_path, version, None) #doctest: +ELLIPSIS
391
>>> import_version(result_path, version) #doctest: +ELLIPSIS
398
392
Tree is up-to-date with test@example.com/test--test--0--patch-2
399
393
>>> commit_more_test_revisions()
400
>>> import_version(result_path, version, None) #doctest: +ELLIPSIS
394
>>> import_version(result_path, version) #doctest: +ELLIPSIS
401
395
importing test@example.com/test--test--0 into ...
402
396
revisions: ....................................................
418
411
progress_bar.note('Version %s has no revisions.' % version)
420
413
if len(ancestors) == 0:
421
last_revision, last_encoding = \
422
get_last_revision(Branch.open(output_dir))
414
last_revision = get_last_revision(Branch.open(output_dir))
423
415
progress_bar.note('Tree is up-to-date with %s' % last_revision)
426
418
progress_bar.note("importing %s into %s" % (version, output_dir))
428
420
tempdir = tempfile.mkdtemp(prefix="baz2bzr-",
429
421
dir=os.path.dirname(output_dir))
431
423
wt = WorkingTree.open(output_dir)
432
424
except (NotBranchError, NoWorkingTree):
427
old_basis = EmptyTree()
429
old_basis = wt.basis_tree()
435
431
for result in iter_import_version(output_dir, ancestors, tempdir,
436
pb=progress_bar, encoding=encoding, fast=fast,
437
verbose=verbose, dry_run=dry_run, max_count=max_count,
438
standalone=standalone):
433
fast=fast, verbose=verbose, dry_run=dry_run,
434
max_count=max_count, standalone=standalone):
439
435
show_progress(progress_bar, result)
441
437
progress_bar.note('Dry run, not modifying output_dir')
444
440
# Update the working tree of the branch
446
442
wt = WorkingTree.open(output_dir)
449
445
if wt is not None:
450
446
wt.set_last_revision(wt.branch.last_revision())
451
wt.set_root_id(BAZ_IMPORT_ROOT)
447
merge_inner(wt.branch, wt.basis_tree(), old_basis,
448
ignore_zero=True, this_tree=wt)
456
453
progress_bar.note('Cleaning up')
457
454
shutil.rmtree(tempdir)
458
455
progress_bar.note("Import complete.")
460
457
progress_bar.finished()
462
459
class UserError(BzrCommandError):
463
460
def __init__(self, message):
464
461
"""Exception to throw when a user makes an impossible request
482
479
:param arch_revision: The Arch revision to generate an ID for.
484
>>> revision_id(pybaz.Revision("you@example.com/cat--br--0--base-0"), None)
481
>>> revision_id(pybaz.Revision("you@example.com/cat--br--0--base-0"))
485
482
'Arch-1:you@example.com%cat--br--0--base-0'
486
>>> revision_id(pybaz.Revision("you@example.com/cat--br--0--base-0"), 'utf-8')
487
'Arch-1-utf-8:you@example.com%cat--br--0--base-0'
492
encoding = '-' + encoding
493
return "Arch-1%s:%s" % (encoding, str(arch_revision).replace('/', '%'))
484
return "Arch-1:%s" % str(arch_revision).replace('/', '%')
495
486
class NotArchRevision(Exception):
496
487
def __init__(self, revision_id):
506
497
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--base-5"))
507
498
Traceback (most recent call last):
508
499
NotArchRevision: The revision id Arch-1:jrandom@example.com%test--test--0--base-5 does not look like it came from Arch.
509
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--patch-5")[0])
510
'jrandom@example.com/test--test--0--patch-5'
511
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--patch-5")[0])
512
'jrandom@example.com/test--test--0--patch-5'
513
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--patch-5")[1])
515
>>> str(arch_revision("Arch-1-utf-8:jrandom@example.com%test--test--0--patch-5")[1])
500
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--patch-5"))
501
'jrandom@example.com/test--test--0--patch-5'
518
503
if revision_id is None:
520
if revision_id[:7] not in ('Arch-1:', 'Arch-1-'):
505
if revision_id[:7] != 'Arch-1:':
521
506
raise NotArchRevision(revision_id)
524
encoding, arch_name = revision_id[6:].split(':', 1)
525
arch_name = arch_name.replace('%', '/')
529
encoding = encoding[1:]
530
return pybaz.Revision(arch_name), encoding
509
return pybaz.Revision(revision_id[7:].replace('%', '/'))
531
510
except pybaz.errors.NamespaceError, e:
532
511
raise NotArchRevision(revision_id)
552
531
if revision_id is None:
553
532
revision_id = source.last_revision()
554
533
wt = create_checkout(source, to_location, NULL_REVISION)
557
wt.set_last_revision(revision_id)
559
if revision_id not in (NULL_REVISION, None):
560
basis = wt.basis_tree()
563
wt._write_inventory(basis.inventory)
534
wt.set_last_revision(revision_id)
535
wt._write_inventory(wt.basis_tree().inventory)
571
def iter_import_version(output_dir, ancestors, tempdir, pb, encoding,
572
fast=False, verbose=False, dry_run=False,
573
max_count=None, standalone=False):
539
def iter_import_version(output_dir, ancestors, tempdir, pb, fast=False,
540
verbose=False, dry_run=False, max_count=None,
575
log_encoding = 'ascii'
576
if encoding is not None:
577
log_encoding = encoding
579
544
# Uncomment this for testing, it basically just has baz2bzr only update
580
545
# 5 patches at a time
667
632
if missing_ancestor:
668
633
# if we want it to be in revision-history, do that here.
669
target_tree.set_parent_ids(
670
[revision_id(missing_ancestor, encoding)],
671
allow_leftmost_as_ghost=True)
634
target_tree.add_pending_merge(revision_id(missing_ancestor))
672
635
missing_ancestor = None
673
636
for merged_rev in direct_merges:
674
target_tree.add_pending_merge(revision_id(merged_rev,
676
target_tree.set_root_id(BAZ_IMPORT_ROOT)
637
target_tree.add_pending_merge(revision_id(merged_rev))
678
638
target_tree.set_inventory(baz_inv)
679
639
commitobj = Commit(reporter=ImportCommitReporter())
680
640
commitobj.commit(working_tree=target_tree,
681
message=log_message.decode(log_encoding, 'replace'),
682
verbose=False, committer=log_creator, timestamp=timestamp,
683
timezone=0, rev_id=rev_id, revprops={})
641
message=log_message.decode('ascii', 'replace'),
642
verbose=False, committer=log_creator,
643
timestamp=timestamp, timezone=0, rev_id=rev_id,
685
646
target_tree.unlock()
691
652
previous_version = revision.version
692
653
if pybaz.WorkingTree(revdir).tree_version != previous_version:
693
654
pybaz.WorkingTree(revdir).set_tree_version(previous_version)
694
log_path = "%s/{arch}/%s/%s/%s/%s/patch-log/%s" % (revdir,
695
revision.category.nonarch, revision.branch.nonarch,
655
log_path = "%s/{arch}/%s/%s/%s/%s/patch-log/%s" % (revdir,
656
revision.category.nonarch, revision.branch.nonarch,
696
657
revision.version.nonarch, revision.archive, revision.patchlevel)
697
658
temp_path = tempfile.mktemp(dir=os.path.dirname(revdir))
698
659
os.rename(log_path, temp_path)
718
679
tree = revision.get(revdir)
719
680
log = get_log(tree, revision)
721
return tree, bzr_inventory_data(tree), log
682
return tree, bzr_inventory_data(tree), log
722
683
except BadFileKind, e:
723
raise UserError("Cannot convert %s because %s is a %s" %
684
raise UserError("Cannot convert %s because %s is a %s" %
724
685
(revision,e.path, e.kind))
730
_global_option('max-count', type = int)
731
class cmd_baz_import_branch(Command):
732
"""Import an Arch or Baz branch into a bzr branch. <BZRTOOLS>"""
733
takes_args = ['to_location', 'from_branch?', 'reuse_history*']
734
takes_options = ['verbose', 'max-count']
770
def baz_import_branch(to_location, from_branch, fast, max_count, verbose,
771
encoding, dry_run, reuse_history_list):
772
to_location = os.path.realpath(str(to_location))
773
if from_branch is not None:
775
from_branch = pybaz.Version(from_branch)
776
except pybaz.errors.NamespaceError:
777
print "%s is not a valid Arch branch." % from_branch
779
if reuse_history_list is None:
780
reuse_history_list = []
781
import_version(to_location, from_branch, encoding, max_count=max_count,
782
reuse_history_from=reuse_history_list)
736
def run(self, to_location, from_branch=None, fast=False, max_count=None,
737
verbose=False, dry_run=False, reuse_history_list=[]):
738
to_location = os.path.realpath(str(to_location))
739
if from_branch is not None:
741
from_branch = pybaz.Version(from_branch)
742
except pybaz.errors.NamespaceError:
743
print "%s is not a valid Arch branch." % from_branch
745
if reuse_history_list is None:
746
reuse_history_list = []
747
import_version(to_location, from_branch,
749
reuse_history_from=reuse_history_list)
785
752
class NotInABranch(Exception):
792
def baz_import(to_root_dir, from_archive, encoding, verbose=False,
793
reuse_history_list=[], prefixes=None):
794
if reuse_history_list is None:
795
reuse_history_list = []
796
to_root = str(os.path.realpath(to_root_dir))
797
if not os.path.exists(to_root):
799
if prefixes is not None:
800
prefixes = prefixes.split(':')
801
import_archive(to_root, from_archive, verbose, encoding,
802
reuse_history_list, prefixes=prefixes)
758
class cmd_baz_import(Command):
759
"""Import an Arch or Baz archive into a bzr repository. <BZRTOOLS>
761
This command should be used on local archives (or mirrors) only. It is
762
quite slow on remote archives.
764
reuse_history allows you to specify any previous imports you
765
have done of different archives, which this archive has branches
766
tagged from. This will dramatically reduce the time to convert
767
the archive as it will not have to convert the history already
768
converted in that other branch.
770
If you specify prefixes, only branches whose names start with that prefix
771
will be imported. Skipped branches will be listed, so you can import any
772
branches you missed by accident. Here's an example of doing a partial
773
import from thelove@canonical.com:
774
bzr baz-import thelove thelove@canonical.com --prefixes dists:talloc-except
776
takes_args = ['to_root_dir', 'from_archive', 'reuse_history*']
777
takes_options = ['verbose', Option('prefixes', type=str,
778
help="Prefixes of branches to import, colon-separated")]
780
def run(self, to_root_dir, from_archive, verbose=False,
781
reuse_history_list=[], prefixes=None):
782
if reuse_history_list is None:
783
reuse_history_list = []
784
to_root = str(os.path.realpath(to_root_dir))
785
if not os.path.exists(to_root):
787
if prefixes is not None:
788
prefixes = prefixes.split(':')
789
import_archive(to_root, from_archive, verbose,
790
reuse_history_list, prefixes=prefixes)
805
793
def import_archive(to_root, from_archive, verbose,
806
encoding, reuse_history_from=[], standalone=False,
794
reuse_history_from=[], standalone=False,
808
796
def selected(version):
809
797
if prefixes is None:
835
823
if not os.path.exists(os.path.dirname(target)):
836
824
os.makedirs(os.path.dirname(target))
838
import_version(target, version, encoding,
839
reuse_history_from=reuse_history_from,
826
import_version(target, version,
827
reuse_history_from=reuse_history_from,
840
828
standalone=standalone)
841
829
except pybaz.errors.ExecProblem,e:
842
830
if str(e).find('The requested revision cannot be built.') != -1: