~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to baz_import.py

  • Committer: Aaron Bentley
  • Date: 2006-03-25 06:08:01 UTC
  • Revision ID: aaron.bentley@utoronto.ca-20060325060801-eb4909f92e6e9adc
Tweakage of the apache scraper

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
from bzrlib.option import _global_option, Option
32
32
from bzrlib.merge import merge_inner
33
33
from bzrlib.revision import NULL_REVISION
 
34
from bzrlib.tree import EmptyTree
34
35
import bzrlib.ui
35
 
import bzrlib.ui.text
36
36
from bzrlib.workingtree import WorkingTree
37
37
from errors import NoPyBaz
38
38
try:
57
57
from progress import *
58
58
 
59
59
class ImportCommitReporter(NullCommitReporter):
 
60
    def __init__(self, pb):
 
61
        self.pb = pb
60
62
 
61
63
    def escaped(self, escape_count, message):
 
64
        self.pb.clear()
62
65
        bzrlib.trace.warning("replaced %d control characters in message" %
63
66
                             escape_count)
64
67
 
287
290
        branch = Branch.open(output_dir)
288
291
        last_patch = get_last_revision(branch)
289
292
        if last_patch is None:
290
 
            if branch.last_revision() != None:
291
 
                raise NotPreviousImport(branch.base)
292
 
        elif version is None:
 
293
            raise NotPreviousImport(branch.base)
 
294
        if version is None:
293
295
            version = last_patch.version
294
296
    elif version is None:
295
297
        raise UserError("No version specified, and directory does not exist.")
343
345
###    possible later.
344
346
###    """
345
347
###
346
 
###    def __init__(self, output_dir, version, fast=False,
 
348
###    def __init__(self, output_dir, version, printer, fancy=True, fast=False,
347
349
###                 verbose=False, dry_run=False, max_count=None, 
348
350
###                   reuse_history_from=[]):
349
351
###        self.output_dir = output_dir
351
353
###        self.
352
354
 
353
355
 
354
 
def import_version(output_dir, version, fast=False,
 
356
def import_version(output_dir, version, printer, fancy=True, fast=False,
355
357
                   verbose=False, dry_run=False, max_count=None,
356
358
                   reuse_history_from=[], standalone=True):
357
359
    """
358
360
    >>> q = test_environ()
359
 
    
360
 
    Progress bars output to stderr, but doctest does not capture that.
361
 
 
362
 
    >>> old_stderr = sys.stderr
363
 
    >>> sys.stderr = sys.stdout
364
 
 
365
361
    >>> result_path = os.path.join(q, "result")
366
362
    >>> commit_test_revisions()
367
363
    >>> version = pybaz.Version("test@example.com/test--test--0.1")
368
 
    >>> old_ui = bzrlib.ui.ui_factory
369
 
    >>> bzrlib.ui.ui_factory = bzrlib.ui.text.TextUIFactory(
370
 
    ...     bar_type=bzrlib.progress.DotsProgressBar)
371
 
 
372
 
    >>> import_version('/', version, dry_run=True)
 
364
    >>> def printer(message): print message
 
365
    >>> import_version('/', version, printer, fancy=False, dry_run=True)
373
366
    Traceback (most recent call last):
374
367
    NotPreviousImport: / is not the location of a previous import.
375
 
    >>> import_version(result_path, version, dry_run=True)
 
368
    >>> import_version(result_path, version, printer, fancy=False, dry_run=True)
376
369
    Traceback (most recent call last):
377
370
    UserError: The version test@example.com/test--test--0.1 does not exist.
378
371
    >>> version = pybaz.Version("test@example.com/test--test--0")
379
 
    >>> import_version(result_path, version, dry_run=True) #doctest: +ELLIPSIS
380
 
    importing test@example.com/test--test--0 into ...
381
 
    ...
382
 
    revisions: ..........................................
 
372
    >>> import_version(result_path, version, printer, fancy=False, dry_run=True)
 
373
    not fancy
 
374
    ....
383
375
    Dry run, not modifying output_dir
384
376
    Cleaning up
385
 
    >>> import_version(result_path, version) #doctest: +ELLIPSIS
386
 
    importing test@example.com/test--test--0 into ...
387
 
    ...
388
 
    revisions: .....................................................................
 
377
    >>> import_version(result_path, version, printer, fancy=False)
 
378
    not fancy
 
379
    ....
389
380
    Cleaning up
390
381
    Import complete.
391
 
    >>> import_version(result_path, version) #doctest: +ELLIPSIS
 
382
    >>> import_version(result_path, version, printer, fancy=False)
392
383
    Tree is up-to-date with test@example.com/test--test--0--patch-2
393
384
    >>> commit_more_test_revisions()
394
 
    >>> import_version(result_path, version) #doctest: +ELLIPSIS
395
 
    importing test@example.com/test--test--0 into ...
396
 
    revisions: ....................................................
 
385
    >>> import_version(result_path, version, printer, fancy=False)
 
386
    not fancy
 
387
    ..
397
388
    Cleaning up
398
389
    Import complete.
399
 
    >>> bzrlib.ui.ui_factory = old_ui
400
 
    >>> sys.stderr = old_stderr
401
390
    >>> teardown_environ(q)
402
391
    """
 
392
    try:
 
393
        ancestors, old_revno = get_remaining_revisions(output_dir, version,
 
394
                                                       reuse_history_from)
 
395
    except NotBranchError, e:
 
396
        raise NotPreviousImport(e.path)
 
397
    if old_revno is None and len(ancestors) == 0:
 
398
        print 'Version %s has no revisions.' % version
 
399
        return
 
400
    if len(ancestors) == 0:
 
401
        last_revision = get_last_revision(Branch.open(output_dir))
 
402
        print 'Tree is up-to-date with %s' % last_revision
 
403
        return
 
404
 
403
405
    progress_bar = bzrlib.ui.ui_factory.nested_progress_bar()
404
 
    try:
 
406
    tempdir = tempfile.mkdtemp(prefix="baz2bzr-",
 
407
                               dir=os.path.dirname(output_dir))
 
408
    try:
 
409
        wt = WorkingTree.open(output_dir)
 
410
    except (NotBranchError, NoWorkingTree):
 
411
        wt = None
 
412
    if wt is None:
 
413
        old_basis = EmptyTree()
 
414
    else:
 
415
        old_basis = wt.basis_tree()
 
416
    try:
 
417
        if not fancy:
 
418
            print "not fancy"
405
419
        try:
406
 
            ancestors, old_revno = get_remaining_revisions(output_dir, version,
407
 
                                                           reuse_history_from)
408
 
        except NotBranchError, e:
409
 
            raise NotPreviousImport(e.path)
410
 
        if old_revno is None and len(ancestors) == 0:
411
 
            progress_bar.note('Version %s has no revisions.' % version)
412
 
            return
413
 
        if len(ancestors) == 0:
414
 
            last_revision = get_last_revision(Branch.open(output_dir))
415
 
            progress_bar.note('Tree is up-to-date with %s' % last_revision)
416
 
            return
417
 
 
418
 
        progress_bar.note("importing %s into %s" % (version, output_dir))
419
 
    
420
 
        tempdir = tempfile.mkdtemp(prefix="baz2bzr-",
421
 
                                   dir=os.path.dirname(output_dir))
 
420
            for result in iter_import_version(output_dir, ancestors, tempdir,
 
421
                    progress_bar, fast=fast, verbose=verbose, dry_run=dry_run,
 
422
                    max_count=max_count, standalone=standalone):
 
423
                if fancy:
 
424
                    show_progress(progress_bar, result)
 
425
                else:
 
426
                    sys.stdout.write('.')
 
427
        finally:
 
428
            if fancy:
 
429
                progress_bar.finished()
 
430
            else:
 
431
                sys.stdout.write('\n')
 
432
 
 
433
        if dry_run:
 
434
            print 'Dry run, not modifying output_dir'
 
435
            return
 
436
 
 
437
        # Update the working tree of the branch
422
438
        try:
423
439
            wt = WorkingTree.open(output_dir)
424
 
        except (NotBranchError, NoWorkingTree):
 
440
        except NoWorkingTree:
425
441
            wt = None
426
 
        try:
427
 
            for result in iter_import_version(output_dir, ancestors, tempdir,
428
 
                    pb=progress_bar,
429
 
                    fast=fast, verbose=verbose, dry_run=dry_run,
430
 
                    max_count=max_count, standalone=standalone):
431
 
                show_progress(progress_bar, result)
432
 
            if dry_run:
433
 
                progress_bar.note('Dry run, not modifying output_dir')
434
 
                return
435
 
    
436
 
            # Update the working tree of the branch
437
 
            try:
438
 
                wt = WorkingTree.open(output_dir)
439
 
            except NoWorkingTree:
440
 
                wt = None
441
 
            if wt is not None:
442
 
                wt.set_last_revision(wt.branch.last_revision())
443
 
                wt.revert([])
444
 
    
445
 
        finally:
446
 
            
447
 
            progress_bar.note('Cleaning up')
448
 
            shutil.rmtree(tempdir)
449
 
        progress_bar.note("Import complete.")
 
442
        if wt is not None:
 
443
            wt.set_last_revision(wt.branch.last_revision())
 
444
            merge_inner(wt.branch, wt.basis_tree(), old_basis, 
 
445
                        ignore_zero=True, this_tree=wt)
 
446
            wt.revert([])
 
447
 
450
448
    finally:
451
 
        progress_bar.finished()
 
449
        printer('Cleaning up')
 
450
        shutil.rmtree(tempdir)
 
451
    printer("Import complete.")
452
452
            
453
453
class UserError(BzrCommandError):
454
454
    def __init__(self, message):
573
573
        if verbose:
574
574
            version = str(revision.version)
575
575
            if version != previous_version:
576
 
                pb.note('On version: %s' % version)
 
576
                clear_progress_bar()
 
577
                print '\rOn version: %s' % version
577
578
            yield Progress(str(revision.patchlevel), i, len(ancestors))
578
579
            previous_version = version
579
580
        else:
591
592
                    raise
592
593
                missing_ancestor = revision
593
594
                revdir = None
594
 
                pb.note("unable to access ancestor %s, making into a merge."
 
595
                print ("unable to access ancestor %s, making into a merge."
595
596
                       % missing_ancestor)
596
597
                continue
597
598
            target_tree = create_checkout_metadata(target_branch, revdir)
630
631
            for merged_rev in direct_merges:
631
632
                target_tree.add_pending_merge(revision_id(merged_rev))
632
633
            target_tree.set_inventory(baz_inv)
633
 
            commitobj = Commit(reporter=ImportCommitReporter())
 
634
            commitobj = Commit(reporter=ImportCommitReporter(pb))
634
635
            commitobj.commit(working_tree=target_tree,
635
636
                             message=log_message.decode('ascii', 'replace'), 
636
637
                             verbose=False, committer=log_creator,
721
722
    bzr_inv.sort()
722
723
    return bzr_inv
723
724
 
724
 
 
725
 
def baz_import_branch(to_location, from_branch, fast, max_count, verbose, 
726
 
                      dry_run, reuse_history_list):
727
 
    to_location = os.path.realpath(str(to_location))
728
 
    if from_branch is not None:
729
 
        try:
730
 
            from_branch = pybaz.Version(from_branch)
731
 
        except pybaz.errors.NamespaceError:
732
 
            print "%s is not a valid Arch branch." % from_branch
733
 
            return 1
734
 
    if reuse_history_list is None:
735
 
        reuse_history_list = []
736
 
    import_version(to_location, from_branch, 
737
 
                   max_count=max_count, 
738
 
                   reuse_history_from=reuse_history_list)
 
725
_global_option('max-count', type = int)
 
726
class cmd_baz_import_branch(Command):
 
727
    """Import an Arch or Baz branch into a bzr branch.  <BZRTOOLS>"""
 
728
    takes_args = ['to_location', 'from_branch?', 'reuse_history*']
 
729
    takes_options = ['verbose', 'max-count']
 
730
 
 
731
    def printer(self, name):
 
732
        print name
 
733
 
 
734
    def run(self, to_location, from_branch=None, fast=False, max_count=None,
 
735
            verbose=False, dry_run=False, reuse_history_list=[]):
 
736
        to_location = os.path.realpath(str(to_location))
 
737
        if from_branch is not None:
 
738
            try:
 
739
                from_branch = pybaz.Version(from_branch)
 
740
            except pybaz.errors.NamespaceError:
 
741
                print "%s is not a valid Arch branch." % from_branch
 
742
                return 1
 
743
        if reuse_history_list is None:
 
744
            reuse_history_list = []
 
745
        import_version(to_location, from_branch, self.printer, 
 
746
                       max_count=max_count, 
 
747
                       reuse_history_from=reuse_history_list)
739
748
 
740
749
 
741
750
class NotInABranch(Exception):
744
753
        self.path = path
745
754
 
746
755
 
747
 
 
748
 
def baz_import(to_root_dir, from_archive, verbose=False, reuse_history_list=[],
749
 
               prefixes=None):
750
 
    if reuse_history_list is None:
751
 
        reuse_history_list = []
752
 
    to_root = str(os.path.realpath(to_root_dir))
753
 
    if not os.path.exists(to_root):
754
 
        os.mkdir(to_root)
755
 
    if prefixes is not None:
756
 
        prefixes = prefixes.split(':')
757
 
    import_archive(to_root, from_archive, verbose,
758
 
                   reuse_history_list, prefixes=prefixes)
759
 
 
760
 
 
761
 
def import_archive(to_root, from_archive, verbose,
 
756
class cmd_baz_import(Command):
 
757
    """Import an Arch or Baz archive into bzr branches.  <BZRTOOLS>
 
758
 
 
759
    This command should be used on local archives (or mirrors) only.  It is
 
760
    quite slow on remote archives.
 
761
    
 
762
    reuse_history allows you to specify any previous imports you 
 
763
    have done of different archives, which this archive has branches
 
764
    tagged from. This will dramatically reduce the time to convert 
 
765
    the archive as it will not have to convert the history already
 
766
    converted in that other branch.
 
767
 
 
768
    If you specify prefixes, only branches whose names start with that prefix
 
769
    will be imported.  Skipped branches will be listed, so you can import any
 
770
    branches you missed by accident.  Here's an example of doing a partial
 
771
    import from thelove@canonical.com:
 
772
    bzr baz-import thelove thelove@canonical.com --prefixes dists:talloc-except
 
773
    """
 
774
    takes_args = ['to_root_dir', 'from_archive', 'reuse_history*']
 
775
    takes_options = ['verbose', Option('prefixes', type=str,
 
776
                     help="Prefixes of branches to import, colon-separated")]
 
777
 
 
778
    def printer(self, name):
 
779
        print name
 
780
 
 
781
    def run(self, to_root_dir, from_archive, verbose=False,
 
782
            reuse_history_list=[], prefixes=None):
 
783
        if reuse_history_list is None:
 
784
            reuse_history_list = []
 
785
        to_root = str(os.path.realpath(to_root_dir))
 
786
        if not os.path.exists(to_root):
 
787
            os.mkdir(to_root)
 
788
        if prefixes is not None:
 
789
            prefixes = prefixes.split(':')
 
790
        import_archive(to_root, from_archive, verbose, self.printer, 
 
791
                       reuse_history_list, prefixes=prefixes)
 
792
 
 
793
 
 
794
def import_archive(to_root, from_archive, verbose, printer,
762
795
                   reuse_history_from=[], standalone=False,
763
796
                   prefixes=None):
764
797
    def selected(version):
780
813
        except NoRepositoryPresent:
781
814
            raise BzrCommandError("Can't create repository at existing branch.")
782
815
    versions = list(pybaz.Archive(str(from_archive)).iter_versions())
783
 
    progress_bar = bzrlib.ui.ui_factory.nested_progress_bar()
 
816
#    progress_bar = bzrlib.ui.ui_factory.nested_progress_bar()
784
817
    try:
785
818
        for num, version in enumerate(versions):
786
 
            progress_bar.update("Branch", num, len(versions))
 
819
#            progress_bar.update("Branch", num, len(versions))
787
820
            if not selected(version):
788
821
                print "Skipping %s" % version
789
822
                continue
790
823
            target = os.path.join(to_root, map_namespace(version))
 
824
            printer("importing %s into %s" % (version, target))
791
825
            if not os.path.exists(os.path.dirname(target)):
792
826
                os.makedirs(os.path.dirname(target))
793
827
            try:
794
 
                import_version(target, version,
 
828
                import_version(target, version, printer,
795
829
                               reuse_history_from=reuse_history_from, 
796
830
                               standalone=standalone)
797
831
            except pybaz.errors.ExecProblem,e:
798
832
                if str(e).find('The requested revision cannot be built.') != -1:
799
 
                    progress_bar.note(
800
 
                        "Skipping version %s as it cannot be built due"
801
 
                        " to a missing parent archive." % version)
 
833
                    printer("Skipping version %s as it cannot be built due"
 
834
                            " to a missing parent archive." % version)
802
835
                else:
803
836
                    raise
804
837
            except UserError, e:
805
838
                if str(e).find('already exists, and the last revision ') != -1:
806
 
                    progress_bar.note(
807
 
                        "Skipping version %s as it has had commits made"
808
 
                        " since it was converted to bzr." % version)
 
839
                    printer("Skipping version %s as it has had commits made"
 
840
                            " since it was converted to bzr." % version)
809
841
                else:
810
842
                    raise
811
843
    finally:
812
 
        progress_bar.finished()
813
 
 
 
844
        pass
 
845
#        progress_bar.finished()
814
846
 
815
847
def map_namespace(a_version):
816
848
    a_version = pybaz.Version("%s" % a_version)
824
856
        return "%s/%s" % (category, branch)
825
857
    return "%s/%s/%s" % (category, version, branch)
826
858
 
827
 
 
828
859
def map_file_id(file_id):
829
860
    """Convert a baz file id to a bzr one."""
830
861
    return file_id.replace('%', '%25').replace('/', '%2f')