345
325
###class Importer(object):
346
326
### """An importer.
348
328
### Currently this is used as a parameter object, though more behaviour is
349
329
### possible later.
352
### def __init__(self, output_dir, version, fast=False,
353
### verbose=False, dry_run=False, max_count=None,
332
### def __init__(self, output_dir, version, printer, fancy=True, fast=False,
333
### verbose=False, dry_run=False, max_count=None,
354
334
### reuse_history_from=[]):
355
335
### self.output_dir = output_dir
356
336
### self.version = version
360
def import_version(output_dir, version, encoding, fast=False,
340
def import_version(output_dir, version, printer, fancy=True, fast=False,
361
341
verbose=False, dry_run=False, max_count=None,
362
reuse_history_from=[], standalone=True):
342
reuse_history_from=[]):
364
344
>>> q = test_environ()
366
Progress bars output to stderr, but doctest does not capture that.
368
>>> old_stderr = sys.stderr
369
>>> sys.stderr = sys.stdout
371
345
>>> result_path = os.path.join(q, "result")
372
346
>>> commit_test_revisions()
373
347
>>> version = pybaz.Version("test@example.com/test--test--0.1")
374
>>> old_ui = bzrlib.ui.ui_factory
375
>>> bzrlib.ui.ui_factory = bzrlib.ui.text.TextUIFactory(
376
... bar_type=bzrlib.progress.DotsProgressBar)
378
>>> import_version('/', version, None, dry_run=True)
348
>>> def printer(message): print message
349
>>> import_version('/', version, printer, fancy=False, dry_run=True)
379
350
Traceback (most recent call last):
380
351
NotPreviousImport: / is not the location of a previous import.
381
>>> import_version(result_path, version, None, dry_run=True)
352
>>> import_version(result_path, version, printer, fancy=False, dry_run=True)
382
353
Traceback (most recent call last):
383
354
UserError: The version test@example.com/test--test--0.1 does not exist.
384
355
>>> version = pybaz.Version("test@example.com/test--test--0")
385
>>> import_version(result_path, version, None, dry_run=True) #doctest: +ELLIPSIS
386
importing test@example.com/test--test--0 into ...
388
revisions: ..........................................
356
>>> import_version(result_path, version, printer, fancy=False, dry_run=True)
389
359
Dry run, not modifying output_dir
391
>>> import_version(result_path, version, None) #doctest: +ELLIPSIS
392
importing test@example.com/test--test--0 into ...
394
revisions: .....................................................................
361
>>> import_version(result_path, version, printer, fancy=False)
397
>>> import_version(result_path, version, None) #doctest: +ELLIPSIS
366
>>> import_version(result_path, version, printer, fancy=False)
398
367
Tree is up-to-date with test@example.com/test--test--0--patch-2
399
368
>>> commit_more_test_revisions()
400
>>> import_version(result_path, version, None) #doctest: +ELLIPSIS
401
importing test@example.com/test--test--0 into ...
402
revisions: ....................................................
369
>>> import_version(result_path, version, printer, fancy=False)
405
>>> bzrlib.ui.ui_factory = old_ui
406
>>> sys.stderr = old_stderr
407
374
>>> teardown_environ(q)
409
progress_bar = bzrlib.ui.ui_factory.nested_progress_bar()
412
ancestors, old_revno = get_remaining_revisions(output_dir, version,
415
except NotBranchError, e:
416
raise NotPreviousImport(e.path)
417
if old_revno is None and len(ancestors) == 0:
418
progress_bar.note('Version %s has no revisions.' % version)
420
if len(ancestors) == 0:
421
last_revision, last_encoding = \
422
get_last_revision(Branch.open(output_dir))
423
progress_bar.note('Tree is up-to-date with %s' % last_revision)
426
progress_bar.note("importing %s into %s" % (version, output_dir))
428
tempdir = tempfile.mkdtemp(prefix="baz2bzr-",
429
dir=os.path.dirname(output_dir))
431
wt = WorkingTree.open(output_dir)
432
except (NotBranchError, NoWorkingTree):
377
ancestors, old_revno = get_remaining_revisions(output_dir, version,
379
except NotBranchError, e:
380
raise NotPreviousImport(e.path)
381
if old_revno is None and len(ancestors) == 0:
382
print 'Version %s has no revisions.' % version
384
if len(ancestors) == 0:
385
last_revision = get_last_revision(Branch.open(output_dir))
386
print 'Tree is up-to-date with %s' % last_revision
389
progress_bar = ProgressBar()
390
tempdir = tempfile.mkdtemp(prefix="baz2bzr-",
391
dir=os.path.dirname(output_dir))
435
396
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):
439
show_progress(progress_bar, result)
441
progress_bar.note('Dry run, not modifying output_dir')
444
# Update the working tree of the branch
446
wt = WorkingTree.open(output_dir)
447
except NoWorkingTree:
450
wt.set_last_revision(wt.branch.last_revision())
451
wt.set_root_id(BAZ_IMPORT_ROOT)
397
progress_bar, fast=fast, verbose=verbose, dry_run=dry_run,
398
max_count=max_count):
400
show_progress(progress_bar, result)
402
sys.stdout.write('.')
456
progress_bar.note('Cleaning up')
457
shutil.rmtree(tempdir)
458
progress_bar.note("Import complete.")
407
sys.stdout.write('\n')
410
print 'Dry run, not modifying output_dir'
412
if os.path.exists(output_dir):
413
# Move the bzr control directory back, and update the working tree
414
revdir = os.path.join(tempdir, "rd")
415
if os.path.exists(revdir):
416
# actual imports were done
417
tmp_bzr_dir = os.path.join(tempdir, '.bzr')
419
bzr_dir = os.path.join(output_dir, '.bzr')
420
new_bzr_dir = os.path.join(tempdir, "rd", '.bzr')
422
os.rename(bzr_dir, tmp_bzr_dir) # Move the original bzr out of the way
423
os.rename(new_bzr_dir, bzr_dir)
425
bzrlib.merge.merge((output_dir, -1), (output_dir, None), # old_revno),
426
check_clean=False, this_dir=output_dir,
429
# If something failed, move back the original bzr directory
430
os.rename(bzr_dir, new_bzr_dir)
431
os.rename(tmp_bzr_dir, bzr_dir)
434
# no imports - perhaps just append_revisions
436
bzrlib.merge.merge((output_dir, -1), (output_dir, None), # old_revno),
437
check_clean=False, this_dir=output_dir,
440
revdir = os.path.join(tempdir, "rd")
441
os.rename(revdir, output_dir)
460
progress_bar.finished()
444
printer('Cleaning up')
445
shutil.rmtree(tempdir)
446
printer("Import complete.")
462
448
class UserError(BzrCommandError):
463
449
def __init__(self, message):
464
450
"""Exception to throw when a user makes an impossible request
506
486
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--base-5"))
507
487
Traceback (most recent call last):
508
488
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])
489
>>> str(arch_revision("Arch-1:jrandom@example.com%test--test--0--patch-5"))
490
'jrandom@example.com/test--test--0--patch-5'
518
492
if revision_id is None:
520
if revision_id[:7] not in ('Arch-1:', 'Arch-1-'):
494
if revision_id[:7] != 'Arch-1:':
521
495
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
498
return pybaz.Revision(revision_id[7:].replace('%', '/'))
531
499
except pybaz.errors.NamespaceError, e:
532
500
raise NotArchRevision(revision_id)
535
def create_shared_repository(output_dir):
536
bd = bzrdir.BzrDirMetaFormat1().initialize(output_dir)
537
bd.create_repository(shared=True)
539
def create_branch(output_dir):
541
bd = bzrdir.BzrDirMetaFormat1().initialize(output_dir)
542
return bd.create_branch()
545
def create_checkout(source, to_location, revision_id=None):
546
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
547
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
548
return checkout.create_workingtree(revision_id)
551
def create_checkout_metadata(source, to_location, revision_id=None):
552
if revision_id is None:
553
revision_id = source.last_revision()
554
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)
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):
502
def iter_import_version(output_dir, ancestors, tempdir, pb, fast=False,
503
verbose=False, dry_run=False, max_count=None):
575
log_encoding = 'ascii'
576
if encoding is not None:
577
log_encoding = encoding
579
506
# Uncomment this for testing, it basically just has baz2bzr only update
580
507
# 5 patches at a time
633
549
missing_ancestor = revision
635
pb.note("unable to access ancestor %s, making into a merge."
551
print ("unable to access ancestor %s, making into a merge."
636
552
% missing_ancestor)
638
target_tree = create_checkout_metadata(target_branch, revdir)
639
branch = target_tree.branch
554
if os.path.exists(output_dir):
555
bzr_dir = os.path.join(output_dir, '.bzr')
556
new_bzr_dir = os.path.join(tempdir, "rd", '.bzr')
557
# This would be much faster with a simple os.rename(), but if
558
# we fail, we have corrupted the original .bzr directory. Is
559
# that a big problem, as we can just back out the last
560
# revisions in .bzr/revision_history I don't really know
561
# RBC20051024 - yes, it would be a problem as we could not then
562
# apply the corrupted revision.
563
shutil.copytree(bzr_dir, new_bzr_dir)
564
# Now revdir should have a tree with the latest .bzr, and the
565
# next revision of the baz tree
566
branch = Branch.open(revdir)
568
branch = Branch.initialize(revdir)
641
570
old = os.path.join(revdir, ".bzr")
642
571
new = os.path.join(tempdir, ".bzr")
643
572
os.rename(old, new)
644
573
baz_inv, log = apply_revision(tree, revision)
645
574
os.rename(new, old)
646
target_tree = WorkingTree.open(revdir)
647
branch = target_tree.branch
575
branch = Branch.open(revdir)
648
576
# cached so we can delete the log
649
577
log_date = log.date
650
578
log_summary = log.summary
661
589
log_message = "\n".join((log_summary, log_description))
663
591
log_message = log_summary
593
target_tree = WorkingTree(revdir ,branch=branch)
664
594
target_tree.lock_write()
667
596
if missing_ancestor:
668
597
# 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)
598
target_tree.add_pending_merge(revision_id(missing_ancestor))
672
599
missing_ancestor = None
673
600
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)
601
target_tree.add_pending_merge(revision_id(merged_rev))
678
602
target_tree.set_inventory(baz_inv)
679
commitobj = Commit(reporter=ImportCommitReporter())
680
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={})
603
commitobj = Commit(reporter=ImportCommitReporter(pb))
604
commitobj.commit(branch, log_message.decode('ascii', 'replace'),
605
verbose=False, committer=log_creator,
606
timestamp=timestamp, timezone=0, rev_id=rev_id)
685
608
target_tree.unlock()
687
610
yield Progress("revisions", len(ancestors), len(ancestors))
611
unlink_unversioned(branch, revdir)
689
613
def get_direct_merges(revdir, revision, log):
690
614
continuation = log.continuation_of
691
615
previous_version = revision.version
692
616
if pybaz.WorkingTree(revdir).tree_version != previous_version:
693
617
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,
618
log_path = "%s/{arch}/%s/%s/%s/%s/patch-log/%s" % (revdir,
619
revision.category.nonarch, revision.branch.nonarch,
696
620
revision.version.nonarch, revision.archive, revision.patchlevel)
697
621
temp_path = tempfile.mktemp(dir=os.path.dirname(revdir))
698
622
os.rename(log_path, temp_path)
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)
691
_global_option('max-count', type = int)
692
class cmd_baz_import_branch(Command):
693
"""Import an Arch or Baz branch into a bzr branch"""
694
takes_args = ['to_location', 'from_branch?', 'reuse_history*']
695
takes_options = ['verbose', 'max-count']
697
def printer(self, name):
700
def run(self, to_location, from_branch=None, fast=False, max_count=None,
701
verbose=False, dry_run=False, reuse_history_list=[]):
702
to_location = os.path.realpath(str(to_location))
703
if from_branch is not None:
705
from_branch = pybaz.Version(from_branch)
706
except pybaz.errors.NamespaceError:
707
print "%s is not a valid Arch branch." % from_branch
709
if reuse_history_list is None:
710
reuse_history_list = []
711
import_version(to_location, from_branch, self.printer,
713
reuse_history_from=reuse_history_list)
785
716
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)
805
def import_archive(to_root, from_archive, verbose,
806
encoding, reuse_history_from=[], standalone=False,
808
def selected(version):
812
for prefix in prefixes:
813
if version.nonarch.startswith(prefix):
722
class cmd_baz_import(Command):
723
"""Import an Arch or Baz archive into bzr branches.
725
reuse_history allows you to specify any previous imports you
726
have done of different archives, which this archive has branches
727
tagged from. This will dramatically reduce the time to convert
728
the archive as it will not have to convert the history already
729
converted in that other branch.
731
takes_args = ['to_root_dir', 'from_archive', 'reuse_history*']
732
takes_options = ['verbose']
734
def printer(self, name):
737
def run(self, to_root_dir, from_archive, verbose=False,
738
reuse_history_list=[]):
739
if reuse_history_list is None:
740
reuse_history_list = []
741
to_root = str(os.path.realpath(to_root_dir))
742
if not os.path.exists(to_root):
744
import_archive(to_root, from_archive, verbose, self.printer,
748
def import_archive(to_root, from_archive, verbose, printer,
749
reuse_history_from=[]):
816
750
real_to = os.path.realpath(to_root)
817
751
history_locations = [real_to] + reuse_history_from
818
if standalone is False:
752
for version in pybaz.Archive(str(from_archive)).iter_versions():
753
target = os.path.join(to_root, map_namespace(version))
754
printer("importing %s into %s" % (version, target))
755
if not os.path.exists(os.path.dirname(target)):
756
os.makedirs(os.path.dirname(target))
820
bd = BzrDir.open(to_root)
822
except NotBranchError:
823
create_shared_repository(to_root)
824
except NoRepositoryPresent:
825
raise BzrCommandError("Can't create repository at existing branch.")
826
versions = list(pybaz.Archive(str(from_archive)).iter_versions())
827
progress_bar = bzrlib.ui.ui_factory.nested_progress_bar()
829
for num, version in enumerate(versions):
830
progress_bar.update("Branch", num, len(versions))
831
if not selected(version):
832
print "Skipping %s" % version
834
target = os.path.join(to_root, map_namespace(version))
835
if not os.path.exists(os.path.dirname(target)):
836
os.makedirs(os.path.dirname(target))
838
import_version(target, version, encoding,
839
reuse_history_from=reuse_history_from,
840
standalone=standalone)
841
except pybaz.errors.ExecProblem,e:
842
if str(e).find('The requested revision cannot be built.') != -1:
844
"Skipping version %s as it cannot be built due"
758
import_version(target, version, printer,
759
reuse_history_from=reuse_history_from)
760
except pybaz.errors.ExecProblem,e:
761
if str(e).find('The requested revision cannot be built.') != -1:
762
printer("Skipping version %s as it cannot be built due"
845
763
" to a missing parent archive." % version)
849
if str(e).find('already exists, and the last revision ') != -1:
851
"Skipping version %s as it has had commits made"
767
if str(e).find('already exists, and the last revision ') != -1:
768
printer("Skipping version %s as it has had commits made"
852
769
" since it was converted to bzr." % version)
856
progress_bar.finished()
859
774
def map_namespace(a_version):