~lifeless/bzr/index.range_map

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Robert Collins
  • Date: 2008-06-19 01:17:19 UTC
  • mfrom: (3218.1.277 +trunk)
  • Revision ID: robertc@robertcollins.net-20080619011719-1c4g4uxzzhdls2wf
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
96
96
    return tree, new_list
97
97
 
98
98
 
99
 
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
100
 
def get_format_type(typestring):
101
 
    """Parse and return a format specifier."""
102
 
    # Have to use BzrDirMetaFormat1 directly, so that
103
 
    # RepositoryFormat.set_default_format works
104
 
    if typestring == "default":
105
 
        return bzrdir.BzrDirMetaFormat1()
106
 
    try:
107
 
        return bzrdir.format_registry.make_bzrdir(typestring)
108
 
    except KeyError:
109
 
        msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
110
 
        raise errors.BzrCommandError(msg)
111
 
 
112
 
 
113
99
# TODO: Make sure no commands unconditionally use the working directory as a
114
100
# branch.  If a filename argument is used, the first of them should be used to
115
101
# specify the branch.  (Perhaps this can be factored out into some kind of
166
152
                     Option('short', help='Use short status indicators.',
167
153
                            short_name='S'),
168
154
                     Option('versioned', help='Only show versioned files.',
169
 
                            short_name='V')
 
155
                            short_name='V'),
 
156
                     Option('no-pending', help='Don\'t show pending merges.',
 
157
                           ),
170
158
                     ]
171
159
    aliases = ['st', 'stat']
172
160
 
175
163
    
176
164
    @display_command
177
165
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
178
 
            versioned=False):
 
166
            versioned=False, no_pending=False):
179
167
        from bzrlib.status import show_tree_status
180
168
 
181
169
        if revision and len(revision) > 2:
186
174
            
187
175
        show_tree_status(tree, show_ids=show_ids,
188
176
                         specific_files=file_list, revision=revision,
189
 
                         to_file=self.outf, short=short, versioned=versioned)
 
177
                         to_file=self.outf, short=short, versioned=versioned,
 
178
                         show_pending=not no_pending)
190
179
 
191
180
 
192
181
class cmd_cat_revision(Command):
221
210
                if rev is None:
222
211
                    raise errors.BzrCommandError('You cannot specify a NULL'
223
212
                                                 ' revision.')
224
 
                revno, rev_id = rev.in_history(b)
 
213
                rev_id = rev.as_revision_id(b)
225
214
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
226
215
    
227
216
 
295
284
            revs.append(RevisionSpec.from_string('-1'))
296
285
 
297
286
        for rev in revs:
298
 
            revinfo = rev.in_history(b)
299
 
            if revinfo.revno is None:
 
287
            revision_id = rev.as_revision_id(b)
 
288
            try:
 
289
                revno = '%4d' % (b.revision_id_to_revno(revision_id))
 
290
            except errors.NoSuchRevision:
300
291
                dotted_map = b.get_revision_id_to_revno_map()
301
 
                revno = '.'.join(str(i) for i in dotted_map[revinfo.rev_id])
302
 
                print '%s %s' % (revno, revinfo.rev_id)
303
 
            else:
304
 
                print '%4d %s' % (revinfo.revno, revinfo.rev_id)
 
292
                revno = '.'.join(str(i) for i in dotted_map[revision_id])
 
293
            print '%s %s' % (revno, revision_id)
305
294
 
306
295
    
307
296
class cmd_add(Command):
466
455
                    raise errors.BzrCommandError(
467
456
                        'bzr inventory --revision takes exactly one revision'
468
457
                        ' identifier')
469
 
                revision_id = revision[0].in_history(work_tree.branch).rev_id
 
458
                revision_id = revision[0].as_revision_id(work_tree.branch)
470
459
                tree = work_tree.branch.repository.revision_tree(revision_id)
471
460
 
472
461
                extra_trees = [work_tree]
534
523
        if len(names_list) < 2:
535
524
            raise errors.BzrCommandError("missing file argument")
536
525
        tree, rel_names = tree_files(names_list)
537
 
        
538
 
        if os.path.isdir(names_list[-1]):
 
526
        tree.lock_write()
 
527
        try:
 
528
            self._run(tree, names_list, rel_names, after)
 
529
        finally:
 
530
            tree.unlock()
 
531
 
 
532
    def _run(self, tree, names_list, rel_names, after):
 
533
        into_existing = osutils.isdir(names_list[-1])
 
534
        if into_existing and len(names_list) == 2:
 
535
            # special cases:
 
536
            # a. case-insensitive filesystem and change case of dir
 
537
            # b. move directory after the fact (if the source used to be
 
538
            #    a directory, but now doesn't exist in the working tree
 
539
            #    and the target is an existing directory, just rename it)
 
540
            if (not tree.case_sensitive
 
541
                and rel_names[0].lower() == rel_names[1].lower()):
 
542
                into_existing = False
 
543
            else:
 
544
                inv = tree.inventory
 
545
                from_id = tree.path2id(rel_names[0])
 
546
                if (not osutils.lexists(names_list[0]) and
 
547
                    from_id and inv.get_file_kind(from_id) == "directory"):
 
548
                    into_existing = False
 
549
        # move/rename
 
550
        if into_existing:
539
551
            # move into existing directory
540
552
            for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
541
553
                self.outf.write("%s => %s\n" % pair)
546
558
                                             ' directory')
547
559
            tree.rename_one(rel_names[0], rel_names[1], after=after)
548
560
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
549
 
            
550
 
    
 
561
 
 
562
 
551
563
class cmd_pull(Command):
552
564
    """Turn this branch into a mirror of another branch.
553
565
 
566
578
    that, you can omit the location to use the default.  To change the
567
579
    default, use --remember. The value will only be saved if the remote
568
580
    location can be accessed.
 
581
 
 
582
    Note: The location can be specified either in the form of a branch,
 
583
    or in the form of a path to a file containing a merge directive generated
 
584
    with bzr send.
569
585
    """
570
586
 
571
587
    _see_also = ['push', 'update', 'status-flags']
599
615
 
600
616
        possible_transports = []
601
617
        if location is not None:
602
 
            mergeable, location_transport = _get_mergeable_helper(location)
603
 
            possible_transports.append(location_transport)
 
618
            try:
 
619
                mergeable = bundle.read_mergeable_from_url(location,
 
620
                    possible_transports=possible_transports)
 
621
            except errors.NotABundle:
 
622
                mergeable = None
604
623
 
605
624
        stored_loc = branch_to.get_parent()
606
625
        if location is None:
613
632
                if not is_quiet():
614
633
                    self.outf.write("Using saved location: %s\n" % display_url)
615
634
                location = stored_loc
616
 
                location_transport = transport.get_transport(
617
 
                    location, possible_transports=possible_transports)
618
635
 
619
636
        if mergeable is not None:
620
637
            if revision is not None:
625
642
                mergeable.get_merge_request(branch_to.repository)
626
643
            branch_from = branch_to
627
644
        else:
628
 
            branch_from = Branch.open_from_transport(location_transport)
 
645
            branch_from = Branch.open(location,
 
646
                possible_transports=possible_transports)
629
647
 
630
648
            if branch_to.get_parent() is None or remember:
631
649
                branch_to.set_parent(branch_from.base)
632
650
 
633
651
        if revision is not None:
634
652
            if len(revision) == 1:
635
 
                revision_id = revision[0].in_history(branch_from).rev_id
 
653
                revision_id = revision[0].as_revision_id(branch_from)
636
654
            else:
637
655
                raise errors.BzrCommandError(
638
656
                    'bzr pull --revision takes one value.')
639
657
 
640
 
        if verbose:
641
 
            old_rh = branch_to.revision_history()
642
 
        if tree_to is not None:
643
 
            change_reporter = delta._ChangeReporter(
644
 
                unversioned_filter=tree_to.is_ignored)
645
 
            result = tree_to.pull(branch_from, overwrite, revision_id,
646
 
                                  change_reporter,
647
 
                                  possible_transports=possible_transports)
648
 
        else:
649
 
            result = branch_to.pull(branch_from, overwrite, revision_id)
 
658
        branch_to.lock_write()
 
659
        try:
 
660
            if tree_to is not None:
 
661
                change_reporter = delta._ChangeReporter(
 
662
                    unversioned_filter=tree_to.is_ignored)
 
663
                result = tree_to.pull(branch_from, overwrite, revision_id,
 
664
                                      change_reporter,
 
665
                                      possible_transports=possible_transports)
 
666
            else:
 
667
                result = branch_to.pull(branch_from, overwrite, revision_id)
650
668
 
651
 
        result.report(self.outf)
652
 
        if verbose:
653
 
            new_rh = branch_to.revision_history()
654
 
            log.show_changed_revisions(branch_to, old_rh, new_rh,
655
 
                                       to_file=self.outf)
 
669
            result.report(self.outf)
 
670
            if verbose and result.old_revid != result.new_revid:
 
671
                old_rh = list(
 
672
                    branch_to.repository.iter_reverse_revision_history(
 
673
                    result.old_revid))
 
674
                old_rh.reverse()
 
675
                new_rh = branch_to.revision_history()
 
676
                log.show_changed_revisions(branch_to, old_rh, new_rh,
 
677
                                           to_file=self.outf)
 
678
        finally:
 
679
            branch_to.unlock()
656
680
 
657
681
 
658
682
class cmd_push(Command):
682
706
    """
683
707
 
684
708
    _see_also = ['pull', 'update', 'working-trees']
685
 
    takes_options = ['remember', 'overwrite', 'verbose',
 
709
    takes_options = ['remember', 'overwrite', 'verbose', 'revision',
686
710
        Option('create-prefix',
687
711
               help='Create the path leading up to the branch '
688
712
                    'if it does not already exist.'),
702
726
    encoding_type = 'replace'
703
727
 
704
728
    def run(self, location=None, remember=False, overwrite=False,
705
 
            create_prefix=False, verbose=False,
 
729
            create_prefix=False, verbose=False, revision=None,
706
730
            use_existing_dir=False,
707
731
            directory=None):
708
732
        # FIXME: Way too big!  Put this into a function called from the
741
765
            else:
742
766
                # Found a branch, so we must have found a repository
743
767
                repository_to = br_to.repository
 
768
 
 
769
        if revision is not None:
 
770
            if len(revision) == 1:
 
771
                revision_id = revision[0].in_history(br_from).rev_id
 
772
            else:
 
773
                raise errors.BzrCommandError(
 
774
                    'bzr push --revision takes one value.')
 
775
        else:
 
776
            revision_id = br_from.last_revision()
 
777
 
744
778
        push_result = None
745
779
        if verbose:
746
780
            old_rh = []
781
815
            # directory. So we need to create it, along with any work to create
782
816
            # all of the dependent branches, etc.
783
817
            dir_to = br_from.bzrdir.clone_on_transport(to_transport,
784
 
                revision_id=br_from.last_revision())
 
818
                                                       revision_id=revision_id)
785
819
            br_to = dir_to.open_branch()
786
820
            # TODO: Some more useful message about what was copied
787
821
            note('Created new branch.')
799
833
        elif br_to is None:
800
834
            # We have a repository but no branch, copy the revisions, and then
801
835
            # create a branch.
802
 
            last_revision_id = br_from.last_revision()
803
 
            repository_to.fetch(br_from.repository,
804
 
                                revision_id=last_revision_id)
805
 
            br_to = br_from.clone(dir_to, revision_id=last_revision_id)
 
836
            repository_to.fetch(br_from.repository, revision_id=revision_id)
 
837
            br_to = br_from.clone(dir_to, revision_id=revision_id)
806
838
            note('Created new branch.')
807
839
            if br_from.get_push_location() is None or remember:
808
840
                br_from.set_push_location(br_to.base)
820
852
                    warning("This transport does not update the working " 
821
853
                            "tree of: %s. See 'bzr help working-trees' for "
822
854
                            "more information." % br_to.base)
823
 
                    push_result = br_from.push(br_to, overwrite)
 
855
                    push_result = br_from.push(br_to, overwrite,
 
856
                                               stop_revision=revision_id)
824
857
                except errors.NoWorkingTree:
825
 
                    push_result = br_from.push(br_to, overwrite)
 
858
                    push_result = br_from.push(br_to, overwrite,
 
859
                                               stop_revision=revision_id)
826
860
                else:
827
861
                    tree_to.lock_write()
828
862
                    try:
829
 
                        push_result = br_from.push(tree_to.branch, overwrite)
 
863
                        push_result = br_from.push(tree_to.branch, overwrite,
 
864
                                                   stop_revision=revision_id)
830
865
                        tree_to.update()
831
866
                    finally:
832
867
                        tree_to.unlock()
864
899
 
865
900
    _see_also = ['checkout']
866
901
    takes_args = ['from_location', 'to_location?']
867
 
    takes_options = ['revision']
 
902
    takes_options = ['revision', Option('hardlink',
 
903
        help='Hard-link working tree files where possible.')]
868
904
    aliases = ['get', 'clone']
869
905
 
870
 
    def run(self, from_location, to_location=None, revision=None):
 
906
    def run(self, from_location, to_location=None, revision=None,
 
907
            hardlink=False):
871
908
        from bzrlib.tag import _merge_tags_if_possible
872
909
        if revision is None:
873
910
            revision = [None]
880
917
        br_from.lock_read()
881
918
        try:
882
919
            if len(revision) == 1 and revision[0] is not None:
883
 
                revision_id = revision[0].in_history(br_from)[1]
 
920
                revision_id = revision[0].as_revision_id(br_from)
884
921
            else:
885
922
                # FIXME - wt.last_revision, fallback to branch, fall back to
886
923
                # None or perhaps NULL_REVISION to mean copy nothing
888
925
                revision_id = br_from.last_revision()
889
926
            if to_location is None:
890
927
                to_location = urlutils.derive_to_location(from_location)
891
 
                name = None
892
 
            else:
893
 
                name = os.path.basename(to_location) + '\n'
894
 
 
895
928
            to_transport = transport.get_transport(to_location)
896
929
            try:
897
930
                to_transport.mkdir('.')
905
938
                # preserve whatever source format we have.
906
939
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
907
940
                                            possible_transports=[to_transport],
908
 
                                            accelerator_tree=accelerator_tree)
 
941
                                            accelerator_tree=accelerator_tree,
 
942
                                            hardlink=hardlink)
909
943
                branch = dir.open_branch()
910
944
            except errors.NoSuchRevision:
911
945
                to_transport.delete_tree('.')
912
946
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
913
947
                raise errors.BzrCommandError(msg)
914
 
            if name:
915
 
                branch.control_files.put_utf8('branch-name', name)
916
948
            _merge_tags_if_possible(br_from, branch)
917
949
            note('Branched %d revision(s).' % branch.revno())
918
950
        finally:
950
982
                                 "common operations like diff and status without "
951
983
                                 "such access, and also support local commits."
952
984
                            ),
953
 
                     Option('files-from',
954
 
                            help="Get file contents from this tree.", type=str)
 
985
                     Option('files-from', type=str,
 
986
                            help="Get file contents from this tree."),
 
987
                     Option('hardlink',
 
988
                            help='Hard-link working tree files where possible.'
 
989
                            ),
955
990
                     ]
956
991
    aliases = ['co']
957
992
 
958
993
    def run(self, branch_location=None, to_location=None, revision=None,
959
 
            lightweight=False, files_from=None):
 
994
            lightweight=False, files_from=None, hardlink=False):
960
995
        if revision is None:
961
996
            revision = [None]
962
997
        elif len(revision) > 1:
970
1005
        if files_from is not None:
971
1006
            accelerator_tree = WorkingTree.open(files_from)
972
1007
        if len(revision) == 1 and revision[0] is not None:
973
 
            revision_id = _mod_revision.ensure_null(
974
 
                revision[0].in_history(source)[1])
 
1008
            revision_id = revision[0].as_revision_id(source)
975
1009
        else:
976
1010
            revision_id = None
977
1011
        if to_location is None:
987
1021
                source.bzrdir.create_workingtree(revision_id)
988
1022
                return
989
1023
        source.create_checkout(to_location, revision_id, lightweight,
990
 
                               accelerator_tree)
 
1024
                               accelerator_tree, hardlink)
991
1025
 
992
1026
 
993
1027
class cmd_renames(Command):
1250
1284
            last_revision = wt.last_revision()
1251
1285
 
1252
1286
        revision_ids = b.repository.get_ancestry(last_revision)
1253
 
        assert revision_ids[0] is None
1254
1287
        revision_ids.pop(0)
1255
1288
        for revision_id in revision_ids:
1256
1289
            self.outf.write(revision_id + '\n')
1552
1585
 
1553
1586
    hidden = True
1554
1587
    _see_also = ['status', 'ls']
 
1588
    takes_options = [
 
1589
            Option('null',
 
1590
                   help='Write an ascii NUL (\\0) separator '
 
1591
                   'between files rather than a newline.')
 
1592
            ]
1555
1593
 
1556
1594
    @display_command
1557
 
    def run(self):
 
1595
    def run(self, null=False):
1558
1596
        tree = WorkingTree.open_containing(u'.')[0]
1559
1597
        td = tree.changes_from(tree.basis_tree())
1560
1598
        for path, id, kind, text_modified, meta_modified in td.modified:
1561
 
            self.outf.write(path + '\n')
 
1599
            if null:
 
1600
                self.outf.write(path + '\0')
 
1601
            else:
 
1602
                self.outf.write(osutils.quotefn(path) + '\n')
1562
1603
 
1563
1604
 
1564
1605
class cmd_added(Command):
1567
1608
 
1568
1609
    hidden = True
1569
1610
    _see_also = ['status', 'ls']
 
1611
    takes_options = [
 
1612
            Option('null',
 
1613
                   help='Write an ascii NUL (\\0) separator '
 
1614
                   'between files rather than a newline.')
 
1615
            ]
1570
1616
 
1571
1617
    @display_command
1572
 
    def run(self):
 
1618
    def run(self, null=False):
1573
1619
        wt = WorkingTree.open_containing(u'.')[0]
1574
1620
        wt.lock_read()
1575
1621
        try:
1586
1632
                    path = inv.id2path(file_id)
1587
1633
                    if not os.access(osutils.abspath(path), os.F_OK):
1588
1634
                        continue
1589
 
                    self.outf.write(path + '\n')
 
1635
                    if null:
 
1636
                        self.outf.write(path + '\0')
 
1637
                    else:
 
1638
                        self.outf.write(osutils.quotefn(path) + '\n')
1590
1639
            finally:
1591
1640
                basis.unlock()
1592
1641
        finally:
1675
1724
            message=None,
1676
1725
            limit=None):
1677
1726
        from bzrlib.log import show_log
1678
 
        assert message is None or isinstance(message, basestring), \
1679
 
            "invalid message argument %r" % message
1680
1727
        direction = (forward and 'forward') or 'reverse'
1681
1728
        
1682
1729
        # log everything
1789
1836
            Option('from-root',
1790
1837
                   help='Print paths relative to the root of the branch.'),
1791
1838
            Option('unknown', help='Print unknown files.'),
1792
 
            Option('versioned', help='Print versioned files.'),
 
1839
            Option('versioned', help='Print versioned files.',
 
1840
                   short_name='V'),
1793
1841
            Option('ignored', help='Print ignored files.'),
1794
1842
            Option('null',
1795
1843
                   help='Write an ascii NUL (\\0) separator '
1831
1879
            relpath += '/'
1832
1880
        if revision is not None:
1833
1881
            tree = branch.repository.revision_tree(
1834
 
                revision[0].in_history(branch).rev_id)
 
1882
                revision[0].as_revision_id(branch))
1835
1883
        elif tree is None:
1836
1884
            tree = branch.basis_tree()
1837
1885
 
1929
1977
        Ignore .o files under the lib directory::
1930
1978
 
1931
1979
            bzr ignore "RE:lib/.*\.o"
 
1980
 
 
1981
        Ignore everything but the "debian" toplevel directory::
 
1982
 
 
1983
            bzr ignore "RE:(?!debian/).*"
1932
1984
    """
1933
1985
 
1934
1986
    _see_also = ['status', 'ignored']
2092
2144
        else:
2093
2145
            if len(revision) != 1:
2094
2146
                raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
2095
 
            rev_id = revision[0].in_history(b).rev_id
 
2147
            rev_id = revision[0].as_revision_id(b)
2096
2148
        t = b.repository.revision_tree(rev_id)
2097
2149
        try:
2098
2150
            export(t, dest, format, root)
2137
2189
        if revision is None:
2138
2190
            revision_id = b.last_revision()
2139
2191
        else:
2140
 
            revision_id = revision[0].in_history(b).rev_id
 
2192
            revision_id = revision[0].as_revision_id(b)
2141
2193
 
2142
2194
        cur_file_id = tree.path2id(relpath)
2143
2195
        rev_tree = b.repository.revision_tree(revision_id)
2398
2450
                try:
2399
2451
                    repo_basis = tree.branch.repository.revision_tree(
2400
2452
                        tree.last_revision())
2401
 
                    if len(list(repo_basis._iter_changes(tree_basis))):
 
2453
                    if len(list(repo_basis.iter_changes(tree_basis))):
2402
2454
                        raise errors.BzrCheckError(
2403
2455
                            "Mismatched basis inventory content.")
2404
2456
                    tree._validate()
2505
2557
        print branch.nick
2506
2558
 
2507
2559
 
 
2560
class cmd_alias(Command):
 
2561
    """Set/unset and display aliases.
 
2562
 
 
2563
    :Examples:
 
2564
        Show the current aliases::
 
2565
 
 
2566
            bzr alias
 
2567
 
 
2568
        Show the alias specified for 'll'::
 
2569
 
 
2570
            bzr alias ll
 
2571
 
 
2572
        Set an alias for 'll'::
 
2573
 
 
2574
            bzr alias ll="log --line -r-10..-1"
 
2575
 
 
2576
        To remove an alias for 'll'::
 
2577
 
 
2578
            bzr alias --remove ll
 
2579
 
 
2580
    """
 
2581
    takes_args = ['name?']
 
2582
    takes_options = [
 
2583
        Option('remove', help='Remove the alias.'),
 
2584
        ]
 
2585
 
 
2586
    def run(self, name=None, remove=False):
 
2587
        if remove:
 
2588
            self.remove_alias(name)
 
2589
        elif name is None:
 
2590
            self.print_aliases()
 
2591
        else:
 
2592
            equal_pos = name.find('=')
 
2593
            if equal_pos == -1:
 
2594
                self.print_alias(name)
 
2595
            else:
 
2596
                self.set_alias(name[:equal_pos], name[equal_pos+1:])
 
2597
 
 
2598
    def remove_alias(self, alias_name):
 
2599
        if alias_name is None:
 
2600
            raise errors.BzrCommandError(
 
2601
                'bzr alias --remove expects an alias to remove.')
 
2602
        # If alias is not found, print something like:
 
2603
        # unalias: foo: not found
 
2604
        c = config.GlobalConfig()
 
2605
        c.unset_alias(alias_name)
 
2606
 
 
2607
    @display_command
 
2608
    def print_aliases(self):
 
2609
        """Print out the defined aliases in a similar format to bash."""
 
2610
        aliases = config.GlobalConfig().get_aliases()
 
2611
        for key, value in sorted(aliases.iteritems()):
 
2612
            self.outf.write('bzr alias %s="%s"\n' % (key, value))
 
2613
 
 
2614
    @display_command
 
2615
    def print_alias(self, alias_name):
 
2616
        from bzrlib.commands import get_alias
 
2617
        alias = get_alias(alias_name)
 
2618
        if alias is None:
 
2619
            self.outf.write("bzr alias: %s: not found\n" % alias_name)
 
2620
        else:
 
2621
            self.outf.write(
 
2622
                'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
 
2623
 
 
2624
    def set_alias(self, alias_name, alias_command):
 
2625
        """Save the alias in the global config."""
 
2626
        c = config.GlobalConfig()
 
2627
        c.set_alias(alias_name, alias_command)
 
2628
 
 
2629
 
2508
2630
class cmd_selftest(Command):
2509
2631
    """Run internal test suite.
2510
2632
    
2601
2723
                            'known failures.'),
2602
2724
                     Option('load-list', type=str, argname='TESTLISTFILE',
2603
2725
                            help='Load a test id list from a text file.'),
 
2726
                     ListOption('debugflag', type=str, short_name='E',
 
2727
                                help='Turn on a selftest debug flag.'),
 
2728
                     Option('starting-with', type=str, argname='TESTID',
 
2729
                            short_name='s',
 
2730
                            help='Load only the tests starting with TESTID.'),
2604
2731
                     ]
2605
2732
    encoding_type = 'replace'
2606
2733
 
2609
2736
            lsprof_timed=None, cache_dir=None,
2610
2737
            first=False, list_only=False,
2611
2738
            randomize=None, exclude=None, strict=False,
2612
 
            load_list=None):
 
2739
            load_list=None, debugflag=None, starting_with=None):
2613
2740
        import bzrlib.ui
2614
2741
        from bzrlib.tests import selftest
2615
2742
        import bzrlib.benchmarks as benchmarks
2616
2743
        from bzrlib.benchmarks import tree_creator
2617
2744
 
 
2745
        # Make deprecation warnings visible, unless -Werror is set
 
2746
        symbol_versioning.activate_deprecation_warnings(override=False)
 
2747
 
2618
2748
        if cache_dir is not None:
2619
2749
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2620
2750
        if not list_only:
2622
2752
            print '   %s (%s python%s)' % (
2623
2753
                    bzrlib.__path__[0],
2624
2754
                    bzrlib.version_string,
2625
 
                    '.'.join(map(str, sys.version_info)),
 
2755
                    bzrlib._format_version_tuple(sys.version_info),
2626
2756
                    )
2627
2757
        print
2628
2758
        if testspecs_list is not None:
2652
2782
                              exclude_pattern=exclude,
2653
2783
                              strict=strict,
2654
2784
                              load_list=load_list,
 
2785
                              debug_flags=debugflag,
 
2786
                              starting_with=starting_with,
2655
2787
                              )
2656
2788
        finally:
2657
2789
            if benchfile is not None:
2658
2790
                benchfile.close()
2659
2791
        if result:
2660
 
            info('tests passed')
 
2792
            note('tests passed')
2661
2793
        else:
2662
 
            info('tests failed')
 
2794
            note('tests failed')
2663
2795
        return int(not result)
2664
2796
 
2665
2797
 
2667
2799
    """Show version of bzr."""
2668
2800
 
2669
2801
    encoding_type = 'replace'
 
2802
    takes_options = [
 
2803
        Option("short", help="Print just the version number."),
 
2804
        ]
2670
2805
 
2671
2806
    @display_command
2672
 
    def run(self):
 
2807
    def run(self, short=False):
2673
2808
        from bzrlib.version import show_version
2674
 
        show_version(to_file=self.outf)
 
2809
        if short:
 
2810
            self.outf.write(bzrlib.version_string + '\n')
 
2811
        else:
 
2812
            show_version(to_file=self.outf)
2675
2813
 
2676
2814
 
2677
2815
class cmd_rocks(Command):
2717
2855
class cmd_merge(Command):
2718
2856
    """Perform a three-way merge.
2719
2857
    
2720
 
    The branch is the branch you will merge from.  By default, it will merge
2721
 
    the latest revision.  If you specify a revision, that revision will be
2722
 
    merged.  If you specify two revisions, the first will be used as a BASE,
2723
 
    and the second one as OTHER.  Revision numbers are always relative to the
2724
 
    specified branch.
 
2858
    The source of the merge can be specified either in the form of a branch,
 
2859
    or in the form of a path to a file containing a merge directive generated
 
2860
    with bzr send. If neither is specified, the default is the upstream branch
 
2861
    or the branch most recently merged using --remember.
 
2862
 
 
2863
    When merging a branch, by default the tip will be merged. To pick a different
 
2864
    revision, pass --revision. If you specify two values, the first will be used as
 
2865
    BASE and the second one as OTHER. Merging individual revisions, or a subset of
 
2866
    available revisions, like this is commonly referred to as "cherrypicking".
 
2867
 
 
2868
    Revision numbers are always relative to the branch being merged.
2725
2869
 
2726
2870
    By default, bzr will try to merge in all new work from the other
2727
2871
    branch, automatically determining an appropriate base.  If this
2758
2902
        To merge the changes introduced by 82, without previous changes::
2759
2903
 
2760
2904
            bzr merge -r 81..82 ../bzr.dev
 
2905
 
 
2906
        To apply a merge directive contained in in /tmp/merge:
 
2907
 
 
2908
            bzr merge /tmp/merge
2761
2909
    """
2762
2910
 
2763
2911
    encoding_type = 'exact'
2764
2912
    _see_also = ['update', 'remerge', 'status-flags']
2765
 
    takes_args = ['branch?']
 
2913
    takes_args = ['location?']
2766
2914
    takes_options = [
2767
2915
        'change',
2768
2916
        'revision',
2788
2936
        Option('preview', help='Instead of merging, show a diff of the merge.')
2789
2937
    ]
2790
2938
 
2791
 
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2792
 
            show_base=False, reprocess=False, remember=False,
 
2939
    def run(self, location=None, revision=None, force=False,
 
2940
            merge_type=None, show_base=False, reprocess=False, remember=False,
2793
2941
            uncommitted=False, pull=False,
2794
2942
            directory=None,
2795
2943
            preview=False,
2796
2944
            ):
2797
 
        # This is actually a branch (or merge-directive) *location*.
2798
 
        location = branch
2799
 
        del branch
2800
 
 
2801
2945
        if merge_type is None:
2802
2946
            merge_type = _mod_merge.Merge3Merger
2803
2947
 
2816
2960
            tree.lock_write()
2817
2961
            cleanups.append(tree.unlock)
2818
2962
            if location is not None:
2819
 
                mergeable, other_transport = _get_mergeable_helper(location)
2820
 
                if mergeable:
 
2963
                try:
 
2964
                    mergeable = bundle.read_mergeable_from_url(location,
 
2965
                        possible_transports=possible_transports)
 
2966
                except errors.NotABundle:
 
2967
                    mergeable = None
 
2968
                else:
2821
2969
                    if uncommitted:
2822
2970
                        raise errors.BzrCommandError('Cannot use --uncommitted'
2823
2971
                            ' with bundles or merge directives.')
2827
2975
                            'Cannot use -r with merge directives or bundles')
2828
2976
                    merger, verified = _mod_merge.Merger.from_mergeable(tree,
2829
2977
                       mergeable, pb)
2830
 
                possible_transports.append(other_transport)
2831
2978
 
2832
2979
            if merger is None and uncommitted:
2833
2980
                if revision is not None and len(revision) > 0:
2850
2997
            merger.show_base = show_base
2851
2998
            self.sanity_check_merger(merger)
2852
2999
            if (merger.base_rev_id == merger.other_rev_id and
2853
 
                merger.other_rev_id != None):
 
3000
                merger.other_rev_id is not None):
2854
3001
                note('Nothing to do.')
2855
3002
                return 0
2856
3003
            if pull:
2911
3058
                                possible_transports, pb):
2912
3059
        """Produce a merger from a location, assuming it refers to a branch."""
2913
3060
        from bzrlib.tag import _merge_tags_if_possible
2914
 
        assert revision is None or len(revision) < 3
2915
3061
        # find the branch locations
2916
3062
        other_loc, user_location = self._select_branch_location(tree, location,
2917
3063
            revision, -1)
2933
3079
            other_revision_id = _mod_revision.ensure_null(
2934
3080
                other_branch.last_revision())
2935
3081
        else:
2936
 
            other_revision_id = \
2937
 
                _mod_revision.ensure_null(
2938
 
                    revision[-1].in_history(other_branch).rev_id)
 
3082
            other_revision_id = revision[-1].as_revision_id(other_branch)
2939
3083
        if (revision is not None and len(revision) == 2
2940
3084
            and revision[0] is not None):
2941
 
            base_revision_id = \
2942
 
                _mod_revision.ensure_null(
2943
 
                    revision[0].in_history(base_branch).rev_id)
 
3085
            base_revision_id = revision[0].as_revision_id(base_branch)
2944
3086
        else:
2945
3087
            base_revision_id = None
2946
3088
        # Remember where we merge from
2997
3139
        mutter("%s", stored_location)
2998
3140
        if stored_location is None:
2999
3141
            raise errors.BzrCommandError("No location specified or remembered")
3000
 
        display_url = urlutils.unescape_for_display(stored_location,
3001
 
            self.outf.encoding)
3002
 
        self.outf.write("%s remembered location %s\n" % (verb_string,
3003
 
            display_url))
 
3142
        display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
 
3143
        note(u"%s remembered location %s", verb_string, display_url)
3004
3144
        return stored_location
3005
3145
 
3006
3146
 
3161
3301
        elif len(revision) != 1:
3162
3302
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
3163
3303
        else:
3164
 
            rev_id = revision[0].in_history(tree.branch).rev_id
 
3304
            rev_id = revision[0].as_revision_id(tree.branch)
3165
3305
        pb = ui.ui_factory.nested_progress_bar()
3166
3306
        try:
3167
3307
            tree.revert(file_list,
3258
3398
        from bzrlib.missing import find_unmerged, iter_log_revisions
3259
3399
 
3260
3400
        if this:
3261
 
          mine_only = this
 
3401
            mine_only = this
3262
3402
        if other:
3263
 
          theirs_only = other
 
3403
            theirs_only = other
 
3404
        # TODO: We should probably check that we don't have mine-only and
 
3405
        #       theirs-only set, but it gets complicated because we also have
 
3406
        #       this and other which could be used.
 
3407
        restrict = 'all'
 
3408
        if mine_only:
 
3409
            restrict = 'local'
 
3410
        elif theirs_only:
 
3411
            restrict = 'remote'
3264
3412
 
3265
3413
        local_branch = Branch.open_containing(u".")[0]
3266
3414
        parent = local_branch.get_parent()
3280
3428
        try:
3281
3429
            remote_branch.lock_read()
3282
3430
            try:
3283
 
                local_extra, remote_extra = find_unmerged(local_branch,
3284
 
                                                          remote_branch)
 
3431
                local_extra, remote_extra = find_unmerged(
 
3432
                    local_branch, remote_branch, restrict)
 
3433
 
3285
3434
                if log_format is None:
3286
3435
                    registry = log.log_formatter_registry
3287
3436
                    log_format = registry.get_default(local_branch)
3289
3438
                                show_ids=show_ids,
3290
3439
                                show_timezone='original')
3291
3440
                if reverse is False:
3292
 
                    local_extra.reverse()
3293
 
                    remote_extra.reverse()
 
3441
                    if local_extra is not None:
 
3442
                        local_extra.reverse()
 
3443
                    if remote_extra is not None:
 
3444
                        remote_extra.reverse()
 
3445
 
 
3446
                status_code = 0
3294
3447
                if local_extra and not theirs_only:
3295
3448
                    self.outf.write("You have %d extra revision(s):\n" %
3296
3449
                                    len(local_extra))
3299
3452
                                        verbose):
3300
3453
                        lf.log_revision(revision)
3301
3454
                    printed_local = True
 
3455
                    status_code = 1
3302
3456
                else:
3303
3457
                    printed_local = False
 
3458
 
3304
3459
                if remote_extra and not mine_only:
3305
3460
                    if printed_local is True:
3306
3461
                        self.outf.write("\n\n\n")
3310
3465
                                        remote_branch.repository,
3311
3466
                                        verbose):
3312
3467
                        lf.log_revision(revision)
3313
 
                if not remote_extra and not local_extra:
3314
 
                    status_code = 0
 
3468
                    status_code = 1
 
3469
 
 
3470
                if mine_only and not local_extra:
 
3471
                    # We checked local, and found nothing extra
 
3472
                    self.outf.write('This branch is up to date.\n')
 
3473
                elif theirs_only and not remote_extra:
 
3474
                    # We checked remote, and found nothing extra
 
3475
                    self.outf.write('Other branch is up to date.\n')
 
3476
                elif not (mine_only or theirs_only or local_extra or
 
3477
                          remote_extra):
 
3478
                    # We checked both branches, and neither one had extra
 
3479
                    # revisions
3315
3480
                    self.outf.write("Branches are up to date.\n")
3316
 
                else:
3317
 
                    status_code = 1
3318
3481
            finally:
3319
3482
                remote_branch.unlock()
3320
3483
        finally:
3412
3575
            if revision is None:
3413
3576
                rev_id = b.last_revision()
3414
3577
            else:
3415
 
                rev_id = revision[0].in_history(b).rev_id
 
3578
                rev_id = revision[0].as_revision_id(b)
3416
3579
            t = testament_class.from_revision(b.repository, rev_id)
3417
3580
            if long:
3418
3581
                sys.stdout.writelines(t.as_text_lines())
3459
3622
            elif len(revision) != 1:
3460
3623
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
3461
3624
            else:
3462
 
                revision_id = revision[0].in_history(branch).rev_id
 
3625
                revision_id = revision[0].as_revision_id(branch)
3463
3626
            tree = branch.repository.revision_tree(revision_id)
3464
3627
            if wt is not None:
3465
3628
                file_id = wt.path2id(relpath)
3604
3767
    specified revision.  For example, "bzr uncommit -r 15" will leave the
3605
3768
    branch at revision 15.
3606
3769
 
3607
 
    In the future, uncommit will create a revision bundle, which can then
3608
 
    be re-applied.
 
3770
    Uncommit leaves the working tree ready for a new commit.  The only change
 
3771
    it may make is to restore any pending merges that were present before
 
3772
    the commit.
3609
3773
    """
3610
3774
 
3611
3775
    # TODO: jam 20060108 Add an option to allow uncommit to remove
3615
3779
    _see_also = ['commit']
3616
3780
    takes_options = ['verbose', 'revision',
3617
3781
                    Option('dry-run', help='Don\'t actually make changes.'),
3618
 
                    Option('force', help='Say yes to all questions.')]
 
3782
                    Option('force', help='Say yes to all questions.'),
 
3783
                    Option('local',
 
3784
                           help="Only remove the commits from the local branch"
 
3785
                                " when in a checkout."
 
3786
                           ),
 
3787
                    ]
3619
3788
    takes_args = ['location?']
3620
3789
    aliases = []
3621
3790
    encoding_type = 'replace'
3622
3791
 
3623
3792
    def run(self, location=None,
3624
3793
            dry_run=False, verbose=False,
3625
 
            revision=None, force=False):
 
3794
            revision=None, force=False, local=False):
3626
3795
        if location is None:
3627
3796
            location = u'.'
3628
3797
        control, relpath = bzrdir.BzrDir.open_containing(location)
3638
3807
        else:
3639
3808
            b.lock_write()
3640
3809
        try:
3641
 
            return self._run(b, tree, dry_run, verbose, revision, force)
 
3810
            return self._run(b, tree, dry_run, verbose, revision, force,
 
3811
                             local=local)
3642
3812
        finally:
3643
3813
            if tree is not None:
3644
3814
                tree.unlock()
3645
3815
            else:
3646
3816
                b.unlock()
3647
3817
 
3648
 
    def _run(self, b, tree, dry_run, verbose, revision, force):
 
3818
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
3649
3819
        from bzrlib.log import log_formatter, show_log
3650
3820
        from bzrlib.uncommit import uncommit
3651
3821
 
3693
3863
                    return 0
3694
3864
 
3695
3865
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
3696
 
                 revno=revno)
 
3866
                 revno=revno, local=local)
3697
3867
 
3698
3868
 
3699
3869
class cmd_break_lock(Command):
3954
4124
            if len(revision) > 2:
3955
4125
                raise errors.BzrCommandError('bzr merge-directive takes '
3956
4126
                    'at most two one revision identifiers')
3957
 
            revision_id = revision[-1].in_history(branch).rev_id
 
4127
            revision_id = revision[-1].as_revision_id(branch)
3958
4128
            if len(revision) == 2:
3959
 
                base_revision_id = revision[0].in_history(branch).rev_id
3960
 
                base_revision_id = ensure_null(base_revision_id)
 
4129
                base_revision_id = revision[0].as_revision_id(branch)
3961
4130
        else:
3962
4131
            revision_id = branch.last_revision()
3963
4132
        revision_id = ensure_null(revision_id)
4016
4185
    generic options are "default", "editor", "mapi", and "xdg-email".
4017
4186
 
4018
4187
    If mail is being sent, a to address is required.  This can be supplied
4019
 
    either on the commandline, or by setting the submit_to configuration
4020
 
    option.
 
4188
    either on the commandline, by setting the submit_to configuration
 
4189
    option in the branch itself or the child_submit_to configuration option 
 
4190
    in the submit branch.
4021
4191
 
4022
4192
    Two formats are currently supported: "4" uses revision bundle format 4 and
4023
4193
    merge directive format 2.  It is significantly faster and smaller than
4024
4194
    older formats.  It is compatible with Bazaar 0.19 and later.  It is the
4025
4195
    default.  "0.9" uses revision bundle format 0.9 and merge directive
4026
4196
    format 1.  It is compatible with Bazaar 0.12 - 0.18.
 
4197
    
 
4198
    Merge directives are applied using the merge command or the pull command.
4027
4199
    """
4028
4200
 
4029
4201
    encoding_type = 'exact'
4030
4202
 
4031
 
    _see_also = ['merge']
 
4203
    _see_also = ['merge', 'pull']
4032
4204
 
4033
4205
    takes_args = ['submit_branch?', 'public_branch?']
4034
4206
 
4044
4216
               'rather than the one containing the working directory.',
4045
4217
               short_name='f',
4046
4218
               type=unicode),
4047
 
        Option('output', short_name='o', help='Write directive to this file.',
 
4219
        Option('output', short_name='o',
 
4220
               help='Write merge directive to this file; '
 
4221
                    'use - for stdout.',
4048
4222
               type=unicode),
4049
4223
        Option('mail-to', help='Mail the request to this address.',
4050
4224
               type=unicode),
4102
4276
            if remembered_submit_branch:
4103
4277
                note('Using saved location: %s', submit_branch)
4104
4278
 
 
4279
            if mail_to is None:
 
4280
                submit_config = Branch.open(submit_branch).get_config()
 
4281
                mail_to = submit_config.get_user_option("child_submit_to")
 
4282
 
4105
4283
            stored_public_branch = branch.get_public_branch()
4106
4284
            if public_branch is None:
4107
4285
                public_branch = stored_public_branch
4116
4294
                if len(revision) > 2:
4117
4295
                    raise errors.BzrCommandError('bzr send takes '
4118
4296
                        'at most two one revision identifiers')
4119
 
                revision_id = revision[-1].in_history(branch).rev_id
 
4297
                revision_id = revision[-1].as_revision_id(branch)
4120
4298
                if len(revision) == 2:
4121
 
                    base_revision_id = revision[0].in_history(branch).rev_id
 
4299
                    base_revision_id = revision[0].as_revision_id(branch)
4122
4300
            if revision_id is None:
4123
4301
                revision_id = branch.last_revision()
4124
4302
            if revision_id == NULL_REVISION:
4156
4334
                else:
4157
4335
                    revision = branch.repository.get_revision(revision_id)
4158
4336
                    subject += revision.get_summary()
 
4337
                basename = directive.get_disk_name(branch)
4159
4338
                mail_client.compose_merge_request(mail_to, subject,
4160
 
                                                  outfile.getvalue())
 
4339
                                                  outfile.getvalue(), basename)
4161
4340
        finally:
4162
4341
            if output != '-':
4163
4342
                outfile.close()
4283
4462
                        raise errors.BzrCommandError(
4284
4463
                            "Tags can only be placed on a single revision, "
4285
4464
                            "not on a range")
4286
 
                    revision_id = revision[0].in_history(branch).rev_id
 
4465
                    revision_id = revision[0].as_revision_id(branch)
4287
4466
                else:
4288
4467
                    revision_id = branch.last_revision()
4289
4468
                if (not force) and branch.tags.has_tag(tag_name):
4368
4547
                     tree='Reconfigure to a tree.',
4369
4548
                     checkout='Reconfigure to a checkout.',
4370
4549
                     lightweight_checkout='Reconfigure to a lightweight'
4371
 
                     ' checkout.'),
 
4550
                     ' checkout.',
 
4551
                     standalone='Reconfigure to be standalone.',
 
4552
                     use_shared='Reconfigure to use a shared repository.'),
4372
4553
                     Option('bind-to', help='Branch to bind checkout to.',
4373
4554
                            type=str),
4374
4555
                     Option('force',
4390
4571
        elif target_type == 'lightweight-checkout':
4391
4572
            reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4392
4573
                directory, bind_to)
 
4574
        elif target_type == 'use-shared':
 
4575
            reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
 
4576
        elif target_type == 'standalone':
 
4577
            reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
4393
4578
        reconfiguration.apply(force)
4394
4579
 
4395
4580
 
4405
4590
    are merged. The user can commit or revert these as they desire.
4406
4591
 
4407
4592
    Pending merges need to be committed or reverted before using switch.
 
4593
 
 
4594
    The path to the branch to switch to can be specified relative to the parent
 
4595
    directory of the current branch. For example, if you are currently in a
 
4596
    checkout of /path/to/branch, specifying 'newbranch' will find a branch at
 
4597
    /path/to/newbranch.
4408
4598
    """
4409
4599
 
4410
4600
    takes_args = ['to_location']
4414
4604
 
4415
4605
    def run(self, to_location, force=False):
4416
4606
        from bzrlib import switch
4417
 
        to_branch = Branch.open(to_location)
4418
4607
        tree_location = '.'
4419
4608
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
 
4609
        try:
 
4610
            to_branch = Branch.open(to_location)
 
4611
        except errors.NotBranchError:
 
4612
            to_branch = Branch.open(
 
4613
                control_dir.open_branch().base + '../' + to_location)
4420
4614
        switch.switch(control_dir, to_branch, force)
4421
4615
        note('Switched to branch: %s',
4422
4616
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
4423
4617
 
4424
4618
 
 
4619
class cmd_hooks(Command):
 
4620
    """Show a branch's currently registered hooks.
 
4621
    """
 
4622
 
 
4623
    hidden = True
 
4624
    takes_args = ['path?']
 
4625
 
 
4626
    def run(self, path=None):
 
4627
        if path is None:
 
4628
            path = '.'
 
4629
        branch_hooks = Branch.open(path).hooks
 
4630
        for hook_type in branch_hooks:
 
4631
            hooks = branch_hooks[hook_type]
 
4632
            self.outf.write("%s:\n" % (hook_type,))
 
4633
            if hooks:
 
4634
                for hook in hooks:
 
4635
                    self.outf.write("  %s\n" %
 
4636
                                    (branch_hooks.get_hook_name(hook),))
 
4637
            else:
 
4638
                self.outf.write("  <no hooks installed>\n")
 
4639
 
 
4640
 
4425
4641
def _create_prefix(cur_transport):
4426
4642
    needed = [cur_transport]
4427
4643
    # Recurse upwards until we can create a directory successfully
4444
4660
        cur_transport.ensure_base()
4445
4661
 
4446
4662
 
4447
 
def _get_mergeable_helper(location):
4448
 
    """Get a merge directive or bundle if 'location' points to one.
4449
 
 
4450
 
    Try try to identify a bundle and returns its mergeable form. If it's not,
4451
 
    we return the tried transport anyway so that it can reused to access the
4452
 
    branch
4453
 
 
4454
 
    :param location: can point to a bundle or a branch.
4455
 
 
4456
 
    :return: mergeable, transport
4457
 
    """
4458
 
    mergeable = None
4459
 
    url = urlutils.normalize_url(location)
4460
 
    url, filename = urlutils.split(url, exclude_trailing_slash=False)
4461
 
    location_transport = transport.get_transport(url)
4462
 
    if filename:
4463
 
        try:
4464
 
            # There may be redirections but we ignore the intermediate
4465
 
            # and final transports used
4466
 
            read = bundle.read_mergeable_from_transport
4467
 
            mergeable, t = read(location_transport, filename)
4468
 
        except errors.NotABundle:
4469
 
            # Continue on considering this url a Branch but adjust the
4470
 
            # location_transport
4471
 
            location_transport = location_transport.clone(filename)
4472
 
    return mergeable, location_transport
4473
 
 
4474
 
 
4475
4663
# these get imported and then picked up by the scan for cmd_*
4476
4664
# TODO: Some more consistent way to split command definitions across files;
4477
4665
# we do need to load at least some information about them to know of