/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/builtins.py

  • Committer: Jelmer Vernooij
  • Date: 2019-05-29 03:22:34 UTC
  • mfrom: (7303 work)
  • mto: This revision was merged to the branch mainline in revision 7306.
  • Revision ID: jelmer@jelmer.uk-20190529032234-mt3fuws8gq03tapi
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
84
84
    RevisionInfo,
85
85
    )
86
86
from .sixish import (
87
 
    BytesIO,
88
87
    PY3,
89
88
    text_type,
90
89
    viewitems,
119
118
        and the full URL to the actual branch
120
119
    """
121
120
    # This path is meant to be relative to the existing branch
122
 
    this_url = _get_branch_location(control_dir,
123
 
        possible_transports=possible_transports)
 
121
    this_url = _get_branch_location(
 
122
        control_dir, possible_transports=possible_transports)
124
123
    # Perhaps the target control dir supports colocated branches?
125
124
    try:
126
 
        root = controldir.ControlDir.open(this_url,
127
 
            possible_transports=possible_transports)
 
125
        root = controldir.ControlDir.open(
 
126
            this_url, possible_transports=possible_transports)
128
127
    except errors.NotBranchError:
129
128
        return (False, this_url)
130
129
    else:
131
130
        try:
132
 
            wt = control_dir.open_workingtree()
 
131
            control_dir.open_workingtree()
133
132
        except (errors.NoWorkingTree, errors.NotLocalUrl):
134
133
            return (False, this_url)
135
134
        else:
151
150
        (colocated, this_url) = _is_colocated(control_dir, possible_transports)
152
151
 
153
152
        if colocated:
154
 
            return urlutils.join_segment_parameters(this_url,
155
 
                {"branch": urlutils.escape(location)})
 
153
            return urlutils.join_segment_parameters(
 
154
                this_url, {"branch": urlutils.escape(location)})
156
155
        else:
157
156
            return urlutils.join(this_url, '..', urlutils.escape(location))
158
157
    return location
168
167
    """
169
168
    try:
170
169
        # Perhaps it's a colocated branch?
171
 
        return control_dir.open_branch(location, 
172
 
            possible_transports=possible_transports)
 
170
        return control_dir.open_branch(
 
171
            location, possible_transports=possible_transports)
173
172
    except (errors.NotBranchError, errors.NoColocatedBranchSupport):
174
173
        this_url = _get_branch_location(control_dir)
175
174
        return Branch.open(
188
187
        if location is None:
189
188
            location = "."
190
189
        try:
191
 
            return Branch.open(location,
192
 
                possible_transports=possible_transports)
 
190
            return Branch.open(
 
191
                location, possible_transports=possible_transports)
193
192
        except errors.NotBranchError:
194
193
            near = "."
195
 
    cdir = controldir.ControlDir.open(near,
196
 
        possible_transports=possible_transports)
197
 
    return open_sibling_branch(cdir, location,
198
 
        possible_transports=possible_transports)
 
194
    cdir = controldir.ControlDir.open(
 
195
        near, possible_transports=possible_transports)
 
196
    return open_sibling_branch(
 
197
        cdir, location, possible_transports=possible_transports)
199
198
 
200
199
 
201
200
def iter_sibling_branches(control_dir, possible_transports=None):
204
203
    :param control_dir: Control directory for which to look up the siblings
205
204
    :return: Iterator over tuples with branch name and branch object
206
205
    """
207
 
    seen_urls = set()
208
206
    try:
209
207
        reference = control_dir.get_branch_reference()
210
208
    except errors.NotBranchError:
211
 
        # There is no active branch, just return the colocated branches.
212
 
        for name, branch in viewitems(control_dir.get_branches()):
213
 
            yield name, branch
214
 
        return
 
209
        reference = None
215
210
    if reference is not None:
216
 
        ref_branch = Branch.open(reference,
217
 
            possible_transports=possible_transports)
 
211
        try:
 
212
            ref_branch = Branch.open(
 
213
                reference, possible_transports=possible_transports)
 
214
        except errors.NotBranchError:
 
215
            ref_branch = None
218
216
    else:
219
217
        ref_branch = None
220
218
    if ref_branch is None or ref_branch.name:
225
223
    else:
226
224
        repo = ref_branch.controldir.find_repository()
227
225
        for branch in repo.find_branches(using=True):
228
 
            name = urlutils.relative_url(repo.user_url,
229
 
                branch.user_url).rstrip("/")
 
226
            name = urlutils.relative_url(
 
227
                repo.user_url, branch.user_url).rstrip("/")
230
228
            yield name, branch
231
229
 
232
230
 
258
256
            if view_files:
259
257
                file_list = view_files
260
258
                view_str = views.view_display_str(view_files)
261
 
                note(gettext("Ignoring files outside view. View is %s") % view_str)
 
259
                note(gettext("Ignoring files outside view. View is %s"),
 
260
                     view_str)
262
261
    return tree, file_list
263
262
 
264
263
 
274
273
 
275
274
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
276
275
    """Get a revision tree. Not suitable for commands that change the tree.
277
 
    
 
276
 
278
277
    Specifically, the basis tree in dirstate trees is coupled to the dirstate
279
278
    and doing a commit/uncommit/pull will at best fail due to changing the
280
279
    basis revision data.
349
348
        Not versioned and not matching an ignore pattern.
350
349
 
351
350
    Additionally for directories, symlinks and files with a changed
352
 
    executable bit, Bazaar indicates their type using a trailing
 
351
    executable bit, Breezy indicates their type using a trailing
353
352
    character: '/', '@' or '*' respectively. These decorations can be
354
353
    disabled using the '--no-classify' option.
355
354
 
386
385
                            short_name='S'),
387
386
                     Option('versioned', help='Only show versioned files.',
388
387
                            short_name='V'),
389
 
                     Option('no-pending', help='Don\'t show pending merges.',
390
 
                           ),
 
388
                     Option('no-pending', help='Don\'t show pending merges.'),
391
389
                     Option('no-classify',
392
 
                            help='Do not mark object type using indicator.',
393
 
                           ),
 
390
                            help='Do not mark object type using indicator.'),
394
391
                     ]
395
392
    aliases = ['st', 'stat']
396
393
 
404
401
        from .status import show_tree_status
405
402
 
406
403
        if revision and len(revision) > 2:
407
 
            raise errors.BzrCommandError(gettext('brz status --revision takes exactly'
408
 
                                         ' one or two revision specifiers'))
 
404
            raise errors.BzrCommandError(
 
405
                gettext('brz status --revision takes exactly'
 
406
                        ' one or two revision specifiers'))
409
407
 
410
408
        tree, relfile_list = WorkingTree.open_containing_paths(file_list)
411
409
        # Avoid asking for specific files when that is not needed.
449
447
    def run(self, revision_id=None, revision=None, directory=u'.'):
450
448
        if revision_id is not None and revision is not None:
451
449
            raise errors.BzrCommandError(gettext('You can only supply one of'
452
 
                                         ' revision_id or --revision'))
 
450
                                                 ' revision_id or --revision'))
453
451
        if revision_id is None and revision is None:
454
 
            raise errors.BzrCommandError(gettext('You must supply either'
455
 
                                         ' --revision or a revision_id'))
 
452
            raise errors.BzrCommandError(
 
453
                gettext('You must supply either --revision or a revision_id'))
456
454
 
457
455
        b = controldir.ControlDir.open_containing_tree_or_branch(directory)[1]
458
456
 
459
 
        revisions = b.repository.revisions
 
457
        revisions = getattr(b.repository, "revisions", None)
460
458
        if revisions is None:
461
 
            raise errors.BzrCommandError(gettext('Repository %r does not support '
462
 
                'access to raw revision texts'))
 
459
            raise errors.BzrCommandError(
 
460
                gettext('Repository %r does not support '
 
461
                        'access to raw revision texts') % b.repository)
463
462
 
464
463
        with b.repository.lock_read():
465
464
            # TODO: jam 20060112 should cat-revision always output utf-8?
468
467
                try:
469
468
                    self.print_revision(revisions, revision_id)
470
469
                except errors.NoSuchRevision:
471
 
                    msg = gettext("The repository {0} contains no revision {1}.").format(
472
 
                        b.repository.base, revision_id.decode('utf-8'))
 
470
                    msg = gettext(
 
471
                        "The repository {0} contains no revision {1}.").format(
 
472
                            b.repository.base, revision_id.decode('utf-8'))
473
473
                    raise errors.BzrCommandError(msg)
474
474
            elif revision is not None:
475
475
                for rev in revision:
498
498
 
499
499
    def run(self, location_list, force=False):
500
500
        if not location_list:
501
 
            location_list=['.']
 
501
            location_list = ['.']
502
502
 
503
503
        for location in location_list:
504
504
            d = controldir.ControlDir.open(location)
506
506
            try:
507
507
                working = d.open_workingtree()
508
508
            except errors.NoWorkingTree:
509
 
                raise errors.BzrCommandError(gettext("No working tree to remove"))
 
509
                raise errors.BzrCommandError(
 
510
                    gettext("No working tree to remove"))
510
511
            except errors.NotLocalUrl:
511
 
                raise errors.BzrCommandError(gettext("You cannot remove the working tree"
512
 
                                             " of a remote path"))
 
512
                raise errors.BzrCommandError(
 
513
                    gettext("You cannot remove the working tree"
 
514
                            " of a remote path"))
513
515
            if not force:
514
516
                if (working.has_changes()):
515
517
                    raise errors.UncommittedChanges(working)
517
519
                    raise errors.ShelvedChanges(working)
518
520
 
519
521
            if working.user_url != working.branch.user_url:
520
 
                raise errors.BzrCommandError(gettext("You cannot remove the working tree"
521
 
                                             " from a lightweight checkout"))
 
522
                raise errors.BzrCommandError(
 
523
                    gettext("You cannot remove the working tree"
 
524
                            " from a lightweight checkout"))
522
525
 
523
526
            d.destroy_workingtree()
524
527
 
539
542
    that, you can supply --revision to force the state of the tree.
540
543
    """
541
544
 
542
 
    takes_options = ['revision', 'directory',
 
545
    takes_options = [
 
546
        'revision', 'directory',
543
547
        Option('force',
544
548
               help='Reset the tree even if it doesn\'t appear to be'
545
549
                    ' corrupted.'),
553
557
            try:
554
558
                tree.check_state()
555
559
            except errors.BzrError:
556
 
                pass # There seems to be a real error here, so we'll reset
 
560
                pass  # There seems to be a real error here, so we'll reset
557
561
            else:
558
562
                # Refuse
559
563
                raise errors.BzrCommandError(gettext(
566
570
            revision_ids = [r.as_revision_id(tree.branch) for r in revision]
567
571
        try:
568
572
            tree.reset_state(revision_ids)
569
 
        except errors.BzrError as e:
 
573
        except errors.BzrError:
570
574
            if revision_ids is None:
571
 
                extra = (gettext(', the header appears corrupt, try passing -r -1'
572
 
                         ' to set the state to the last commit'))
 
575
                extra = gettext(', the header appears corrupt, try passing '
 
576
                                '-r -1 to set the state to the last commit')
573
577
            else:
574
578
                extra = ''
575
 
            raise errors.BzrCommandError(gettext('failed to reset the tree state{0}').format(extra))
 
579
            raise errors.BzrCommandError(
 
580
                gettext('failed to reset the tree state{0}').format(extra))
576
581
 
577
582
 
578
583
class cmd_revno(Command):
591
596
    @display_command
592
597
    def run(self, tree=False, location=u'.', revision=None):
593
598
        if revision is not None and tree:
594
 
            raise errors.BzrCommandError(gettext("--tree and --revision can "
595
 
                "not be used together"))
 
599
            raise errors.BzrCommandError(
 
600
                gettext("--tree and --revision can not be used together"))
596
601
 
597
602
        if tree:
598
603
            try:
615
620
                revid = b.last_revision()
616
621
        try:
617
622
            revno_t = b.revision_id_to_dotted_revno(revid)
618
 
        except errors.NoSuchRevision:
 
623
        except (errors.NoSuchRevision, errors.GhostRevisionsHaveNoRevno):
619
624
            revno_t = ('???',)
620
625
        revno = ".".join(str(n) for n in revno_t)
621
626
        self.cleanup_now()
629
634
    takes_args = ['revision_info*']
630
635
    takes_options = [
631
636
        'revision',
632
 
        custom_help('directory',
633
 
            help='Branch to examine, '
634
 
                 'rather than the one containing the working directory.'),
 
637
        custom_help('directory', help='Branch to examine, '
 
638
                    'rather than the one containing the working directory.'),
635
639
        Option('tree', help='Show revno of working tree.'),
636
640
        ]
637
641
 
676
680
 
677
681
        self.cleanup_now()
678
682
        for revno, revid in revinfos:
679
 
            self.outf.write('%*s %s\n' % (maxlen, revno, revid.decode('utf-8')))
 
683
            self.outf.write(
 
684
                '%*s %s\n' % (maxlen, revno, revid.decode('utf-8')))
680
685
 
681
686
 
682
687
class cmd_add(Command):
715
720
    branches that will be merged later (without showing the two different
716
721
    adds as a conflict). It is also useful when merging another project
717
722
    into a subdirectory of this one.
718
 
    
 
723
 
719
724
    Any files matching patterns in the ignore list will not be added
720
725
    unless they are explicitly mentioned.
721
 
    
722
 
    In recursive mode, files larger than the configuration option 
 
726
 
 
727
    In recursive mode, files larger than the configuration option
723
728
    add.maximum_file_size will be skipped. Named items are never skipped due
724
729
    to file size.
725
730
    """
729
734
               help="Don't recursively add the contents of directories.",
730
735
               short_name='N'),
731
736
        Option('dry-run',
732
 
               help="Show what would be done, but don't actually do anything."),
 
737
               help="Show what would be done, but don't actually do "
 
738
                    "anything."),
733
739
        'verbose',
734
740
        Option('file-ids-from',
735
741
               type=text_type,
746
752
        if file_ids_from is not None:
747
753
            try:
748
754
                base_tree, base_path = WorkingTree.open_containing(
749
 
                                            file_ids_from)
 
755
                    file_ids_from)
750
756
            except errors.NoWorkingTree:
751
757
                base_branch, base_path = Branch.open_containing(
752
 
                                            file_ids_from)
 
758
                    file_ids_from)
753
759
                base_tree = base_branch.basis_tree()
754
760
 
755
 
            action = breezy.add.AddFromBaseAction(base_tree, base_path,
756
 
                          to_file=self.outf, should_print=(not is_quiet()))
757
 
        else:
758
 
            action = breezy.add.AddWithSkipLargeAction(to_file=self.outf,
 
761
            action = breezy.add.AddFromBaseAction(
 
762
                base_tree, base_path, to_file=self.outf,
759
763
                should_print=(not is_quiet()))
 
764
        else:
 
765
            action = breezy.add.AddWithSkipLargeAction(
 
766
                to_file=self.outf, should_print=(not is_quiet()))
760
767
 
761
768
        if base_tree:
762
769
            self.add_cleanup(base_tree.lock_read().unlock)
763
770
        tree, file_list = tree_files_for_add(file_list)
764
 
        added, ignored = tree.smart_add(file_list, not
765
 
            no_recurse, action=action, save=not dry_run)
 
771
        added, ignored = tree.smart_add(
 
772
            file_list, not no_recurse, action=action, save=not dry_run)
766
773
        self.cleanup_now()
767
774
        if len(ignored) > 0:
768
775
            if verbose:
769
776
                for glob in sorted(ignored):
770
777
                    for path in ignored[glob]:
771
778
                        self.outf.write(
772
 
                         gettext("ignored {0} matching \"{1}\"\n").format(
773
 
                         path, glob))
 
779
                            gettext("ignored {0} matching \"{1}\"\n").format(
 
780
                                path, glob))
774
781
 
775
782
 
776
783
class cmd_mkdir(Command):
851
858
        'revision',
852
859
        'show-ids',
853
860
        Option('kind',
854
 
               help='List entries of a particular kind: file, directory, symlink.',
 
861
               help='List entries of a particular kind: file, directory, '
 
862
                    'symlink.',
855
863
               type=text_type),
856
864
        ]
857
865
    takes_args = ['file*']
859
867
    @display_command
860
868
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
861
869
        if kind and kind not in ['file', 'directory', 'symlink']:
862
 
            raise errors.BzrCommandError(gettext('invalid kind %r specified') % (kind,))
 
870
            raise errors.BzrCommandError(
 
871
                gettext('invalid kind %r specified') % (kind,))
863
872
 
864
873
        revision = _get_one_revision('inventory', revision)
865
874
        work_tree, file_list = WorkingTree.open_containing_paths(file_list)
876
885
        self.add_cleanup(tree.lock_read().unlock)
877
886
        if file_list is not None:
878
887
            paths = tree.find_related_paths_across_trees(
879
 
                    file_list, extra_trees, require_versioned=True)
 
888
                file_list, extra_trees, require_versioned=True)
880
889
            # find_ids_across_trees may include some paths that don't
881
890
            # exist in 'tree'.
882
891
            entries = tree.iter_entries_by_dir(specific_files=paths)
889
898
            if path == "":
890
899
                continue
891
900
            if show_ids:
892
 
                self.outf.write('%-50s %s\n' % (path, entry.file_id.decode('utf-8')))
 
901
                self.outf.write('%-50s %s\n' % (
 
902
                    path, entry.file_id.decode('utf-8')))
893
903
            else:
894
904
                self.outf.write(path)
895
905
                self.outf.write('\n')
917
927
    encoding_type = 'replace'
918
928
 
919
929
    def run(self, names_list):
920
 
        import shutil
921
930
        if names_list is None:
922
931
            names_list = []
923
932
        if len(names_list) < 2:
924
933
            raise errors.BzrCommandError(gettext("missing file argument"))
925
 
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
 
934
        tree, rel_names = WorkingTree.open_containing_paths(
 
935
            names_list, canonicalize=False)
926
936
        for file_name in rel_names[0:-1]:
927
937
            if file_name == '':
928
 
                raise errors.BzrCommandError(gettext("can not copy root of branch"))
 
938
                raise errors.BzrCommandError(
 
939
                    gettext("can not copy root of branch"))
929
940
        self.add_cleanup(tree.lock_tree_write().unlock)
930
941
        into_existing = osutils.isdir(names_list[-1])
931
942
        if not into_existing:
932
943
            try:
933
944
                (src, dst) = rel_names
934
945
            except IndexError:
935
 
                raise errors.BzrCommandError(gettext('to copy multiple files the'
936
 
                                                     ' destination must be a versioned'
937
 
                                                     ' directory'))
 
946
                raise errors.BzrCommandError(
 
947
                    gettext('to copy multiple files the'
 
948
                            ' destination must be a versioned'
 
949
                            ' directory'))
938
950
            pairs = [(src, dst)]
939
951
        else:
940
 
            pairs = [(n, osutils.joinpath([rel_names[-1], osutils.basename(n)]))
941
 
                     for n in rel_names[:-1]]
 
952
            pairs = [
 
953
                (n, osutils.joinpath([rel_names[-1], osutils.basename(n)]))
 
954
                for n in rel_names[:-1]]
942
955
 
943
956
        for src, dst in pairs:
944
957
            try:
945
958
                src_kind = tree.stored_kind(src)
946
959
            except errors.NoSuchFile:
947
960
                raise errors.BzrCommandError(
948
 
                        gettext('Could not copy %s => %s: %s is not versioned.')
949
 
                        % (src, dst, src))
 
961
                    gettext('Could not copy %s => %s: %s is not versioned.')
 
962
                    % (src, dst, src))
950
963
            if src_kind is None:
951
964
                raise errors.BzrCommandError(
952
965
                    gettext('Could not copy %s => %s . %s is not versioned\\.'
953
 
                        % (src, dst, src)))
 
966
                            % (src, dst, src)))
954
967
            if src_kind == 'directory':
955
968
                raise errors.BzrCommandError(
956
969
                    gettext('Could not copy %s => %s . %s is a directory.'
957
 
                        % (src, dst, src)))
 
970
                            % (src, dst, src)))
958
971
            dst_parent = osutils.split(dst)[0]
959
972
            if dst_parent != '':
960
973
                try:
961
974
                    dst_parent_kind = tree.stored_kind(dst_parent)
962
975
                except errors.NoSuchFile:
963
976
                    raise errors.BzrCommandError(
964
 
                            gettext('Could not copy %s => %s: %s is not versioned.')
965
 
                            % (src, dst, dst_parent))
 
977
                        gettext('Could not copy %s => %s: %s is not versioned.')
 
978
                        % (src, dst, dst_parent))
966
979
                if dst_parent_kind != 'directory':
967
980
                    raise errors.BzrCommandError(
968
 
                            gettext('Could not copy to %s: %s is not a directory.')
969
 
                            % (dst_parent, dst_parent))
 
981
                        gettext('Could not copy to %s: %s is not a directory.')
 
982
                        % (dst_parent, dst_parent))
970
983
 
971
984
            tree.copy_one(src, dst)
972
985
 
994
1007
 
995
1008
    takes_args = ['names*']
996
1009
    takes_options = [Option("after", help="Move only the brz identifier"
997
 
        " of the file, because the file has already been moved."),
998
 
        Option('auto', help='Automatically guess renames.'),
999
 
        Option('dry-run', help='Avoid making changes when guessing renames.'),
1000
 
        ]
 
1010
                            " of the file, because the file has already been moved."),
 
1011
                     Option('auto', help='Automatically guess renames.'),
 
1012
                     Option(
 
1013
                         'dry-run', help='Avoid making changes when guessing renames.'),
 
1014
                     ]
1001
1015
    aliases = ['move', 'rename']
1002
1016
    encoding_type = 'replace'
1003
1017
 
1010
1024
            names_list = []
1011
1025
        if len(names_list) < 2:
1012
1026
            raise errors.BzrCommandError(gettext("missing file argument"))
1013
 
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
 
1027
        tree, rel_names = WorkingTree.open_containing_paths(
 
1028
            names_list, canonicalize=False)
1014
1029
        for file_name in rel_names[0:-1]:
1015
1030
            if file_name == '':
1016
 
                raise errors.BzrCommandError(gettext("can not move root of branch"))
 
1031
                raise errors.BzrCommandError(
 
1032
                    gettext("can not move root of branch"))
1017
1033
        self.add_cleanup(tree.lock_tree_write().unlock)
1018
1034
        self._run(tree, names_list, rel_names, after)
1019
1035
 
1020
1036
    def run_auto(self, names_list, after, dry_run):
1021
1037
        if names_list is not None and len(names_list) > 1:
1022
 
            raise errors.BzrCommandError(gettext('Only one path may be specified to'
1023
 
                                         ' --auto.'))
 
1038
            raise errors.BzrCommandError(
 
1039
                gettext('Only one path may be specified to --auto.'))
1024
1040
        if after:
1025
 
            raise errors.BzrCommandError(gettext('--after cannot be specified with'
1026
 
                                         ' --auto.'))
 
1041
            raise errors.BzrCommandError(
 
1042
                gettext('--after cannot be specified with --auto.'))
1027
1043
        work_tree, file_list = WorkingTree.open_containing_paths(
1028
1044
            names_list, default_directory='.')
1029
1045
        self.add_cleanup(work_tree.lock_tree_write().unlock)
1030
1046
        rename_map.RenameMap.guess_renames(
1031
 
                work_tree.basis_tree(), work_tree, dry_run)
 
1047
            work_tree.basis_tree(), work_tree, dry_run)
1032
1048
 
1033
1049
    def _run(self, tree, names_list, rel_names, after):
1034
1050
        into_existing = osutils.isdir(names_list[-1])
1039
1055
            #    a directory, but now doesn't exist in the working tree
1040
1056
            #    and the target is an existing directory, just rename it)
1041
1057
            if (not tree.case_sensitive
1042
 
                and rel_names[0].lower() == rel_names[1].lower()):
 
1058
                    and rel_names[0].lower() == rel_names[1].lower()):
1043
1059
                into_existing = False
1044
1060
            else:
1045
1061
                # 'fix' the case of a potential 'from'
1046
1062
                from_path = tree.get_canonical_path(rel_names[0])
1047
1063
                if (not osutils.lexists(names_list[0]) and
1048
1064
                    tree.is_versioned(from_path) and
1049
 
                    tree.stored_kind(from_path) == "directory"):
 
1065
                        tree.stored_kind(from_path) == "directory"):
1050
1066
                    into_existing = False
1051
1067
        # move/rename
1052
1068
        if into_existing:
1060
1076
        else:
1061
1077
            if len(names_list) != 2:
1062
1078
                raise errors.BzrCommandError(gettext('to mv multiple files the'
1063
 
                                             ' destination must be a versioned'
1064
 
                                             ' directory'))
 
1079
                                                     ' destination must be a versioned'
 
1080
                                                     ' directory'))
1065
1081
 
1066
1082
            # for cicp file-systems: the src references an existing inventory
1067
1083
            # item:
1088
1104
                if after:
1089
1105
                    # If 'after' is specified, the tail must refer to a file on disk.
1090
1106
                    if dest_parent:
1091
 
                        dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
 
1107
                        dest_parent_fq = osutils.pathjoin(
 
1108
                            tree.basedir, dest_parent)
1092
1109
                    else:
1093
1110
                        # pathjoin with an empty tail adds a slash, which breaks
1094
1111
                        # relpath :(
1095
1112
                        dest_parent_fq = tree.basedir
1096
1113
 
1097
1114
                    dest_tail = osutils.canonical_relpath(
1098
 
                                    dest_parent_fq,
1099
 
                                    osutils.pathjoin(dest_parent_fq, spec_tail))
 
1115
                        dest_parent_fq,
 
1116
                        osutils.pathjoin(dest_parent_fq, spec_tail))
1100
1117
                else:
1101
1118
                    # not 'after', so case as specified is used
1102
1119
                    dest_tail = spec_tail
1114
1131
    __doc__ = """Turn this branch into a mirror of another branch.
1115
1132
 
1116
1133
    By default, this command only works on branches that have not diverged.
1117
 
    Branches are considered diverged if the destination branch's most recent 
1118
 
    commit is one that has not been merged (directly or indirectly) into the 
 
1134
    Branches are considered diverged if the destination branch's most recent
 
1135
    commit is one that has not been merged (directly or indirectly) into the
1119
1136
    parent.
1120
1137
 
1121
1138
    If branches have diverged, you can use 'brz merge' to integrate the changes
1142
1159
 
1143
1160
    _see_also = ['push', 'update', 'status-flags', 'send']
1144
1161
    takes_options = ['remember', 'overwrite', 'revision',
1145
 
        custom_help('verbose',
1146
 
            help='Show logs of pulled revisions.'),
1147
 
        custom_help('directory',
1148
 
            help='Branch to pull into, '
1149
 
                 'rather than the one containing the working directory.'),
1150
 
        Option('local',
1151
 
            help="Perform a local pull in a bound "
1152
 
                 "branch.  Local pulls are not applied to "
1153
 
                 "the master branch."
1154
 
            ),
1155
 
        Option('show-base',
1156
 
            help="Show base revision text in conflicts."),
1157
 
        Option('overwrite-tags',
1158
 
            help="Overwrite tags only."),
1159
 
        ]
 
1162
                     custom_help('verbose',
 
1163
                                 help='Show logs of pulled revisions.'),
 
1164
                     custom_help('directory',
 
1165
                                 help='Branch to pull into, '
 
1166
                                 'rather than the one containing the working directory.'),
 
1167
                     Option('local',
 
1168
                            help="Perform a local pull in a bound "
 
1169
                            "branch.  Local pulls are not applied to "
 
1170
                            "the master branch."
 
1171
                            ),
 
1172
                     Option('show-base',
 
1173
                            help="Show base revision text in conflicts."),
 
1174
                     Option('overwrite-tags',
 
1175
                            help="Overwrite tags only."),
 
1176
                     ]
1160
1177
    takes_args = ['location?']
1161
1178
    encoding_type = 'replace'
1162
1179
 
1194
1211
        if location is not None:
1195
1212
            try:
1196
1213
                mergeable = bundle.read_mergeable_from_url(location,
1197
 
                    possible_transports=possible_transports)
 
1214
                                                           possible_transports=possible_transports)
1198
1215
            except errors.NotABundle:
1199
1216
                mergeable = None
1200
1217
 
1202
1219
        if location is None:
1203
1220
            if stored_loc is None:
1204
1221
                raise errors.BzrCommandError(gettext("No pull location known or"
1205
 
                                             " specified."))
 
1222
                                                     " specified."))
1206
1223
            else:
1207
1224
                display_url = urlutils.unescape_for_display(stored_loc,
1208
 
                        self.outf.encoding)
 
1225
                                                            self.outf.encoding)
1209
1226
                if not is_quiet():
1210
 
                    self.outf.write(gettext("Using saved parent location: %s\n") % display_url)
 
1227
                    self.outf.write(
 
1228
                        gettext("Using saved parent location: %s\n") % display_url)
1211
1229
                location = stored_loc
1212
1230
 
1213
1231
        revision = _get_one_revision('pull', revision)
1221
1239
            branch_from = branch_to
1222
1240
        else:
1223
1241
            branch_from = Branch.open(location,
1224
 
                possible_transports=possible_transports)
 
1242
                                      possible_transports=possible_transports)
1225
1243
            self.add_cleanup(branch_from.lock_read().unlock)
1226
1244
            # Remembers if asked explicitly or no previous location is set
1227
1245
            if (remember
1228
 
                or (remember is None and branch_to.get_parent() is None)):
 
1246
                    or (remember is None and branch_to.get_parent() is None)):
1229
1247
                # FIXME: This shouldn't be done before the pull
1230
1248
                # succeeds... -- vila 2012-01-02
1231
1249
                branch_to.set_parent(branch_from.base)
1288
1306
 
1289
1307
    _see_also = ['pull', 'update', 'working-trees']
1290
1308
    takes_options = ['remember', 'overwrite', 'verbose', 'revision',
1291
 
        Option('create-prefix',
1292
 
               help='Create the path leading up to the branch '
1293
 
                    'if it does not already exist.'),
1294
 
        custom_help('directory',
1295
 
            help='Branch to push from, '
1296
 
                 'rather than the one containing the working directory.'),
1297
 
        Option('use-existing-dir',
1298
 
               help='By default push will fail if the target'
1299
 
                    ' directory exists, but does not already'
1300
 
                    ' have a control directory.  This flag will'
1301
 
                    ' allow push to proceed.'),
1302
 
        Option('stacked',
1303
 
            help='Create a stacked branch that references the public location '
1304
 
                'of the parent branch.'),
1305
 
        Option('stacked-on',
1306
 
            help='Create a stacked branch that refers to another branch '
1307
 
                'for the commit history. Only the work not present in the '
1308
 
                'referenced branch is included in the branch created.',
1309
 
            type=text_type),
1310
 
        Option('strict',
1311
 
               help='Refuse to push if there are uncommitted changes in'
1312
 
               ' the working tree, --no-strict disables the check.'),
1313
 
        Option('no-tree',
1314
 
               help="Don't populate the working tree, even for protocols"
1315
 
               " that support it."),
1316
 
        Option('overwrite-tags',
1317
 
              help="Overwrite tags only."),
1318
 
        Option('lossy', help="Allow lossy push, i.e. dropping metadata "
1319
 
                             "that can't be represented in the target.")
1320
 
        ]
 
1309
                     Option('create-prefix',
 
1310
                            help='Create the path leading up to the branch '
 
1311
                            'if it does not already exist.'),
 
1312
                     custom_help('directory',
 
1313
                                 help='Branch to push from, '
 
1314
                                 'rather than the one containing the working directory.'),
 
1315
                     Option('use-existing-dir',
 
1316
                            help='By default push will fail if the target'
 
1317
                            ' directory exists, but does not already'
 
1318
                            ' have a control directory.  This flag will'
 
1319
                            ' allow push to proceed.'),
 
1320
                     Option('stacked',
 
1321
                            help='Create a stacked branch that references the public location '
 
1322
                            'of the parent branch.'),
 
1323
                     Option('stacked-on',
 
1324
                            help='Create a stacked branch that refers to another branch '
 
1325
                            'for the commit history. Only the work not present in the '
 
1326
                            'referenced branch is included in the branch created.',
 
1327
                            type=text_type),
 
1328
                     Option('strict',
 
1329
                            help='Refuse to push if there are uncommitted changes in'
 
1330
                            ' the working tree, --no-strict disables the check.'),
 
1331
                     Option('no-tree',
 
1332
                            help="Don't populate the working tree, even for protocols"
 
1333
                            " that support it."),
 
1334
                     Option('overwrite-tags',
 
1335
                            help="Overwrite tags only."),
 
1336
                     Option('lossy', help="Allow lossy push, i.e. dropping metadata "
 
1337
                            "that can't be represented in the target.")
 
1338
                     ]
1321
1339
    takes_args = ['location?']
1322
1340
    encoding_type = 'replace'
1323
1341
 
1324
1342
    def run(self, location=None, remember=None, overwrite=False,
1325
 
        create_prefix=False, verbose=False, revision=None,
1326
 
        use_existing_dir=False, directory=None, stacked_on=None,
1327
 
        stacked=False, strict=None, no_tree=False,
1328
 
        overwrite_tags=False, lossy=False):
 
1343
            create_prefix=False, verbose=False, revision=None,
 
1344
            use_existing_dir=False, directory=None, stacked_on=None,
 
1345
            stacked=False, strict=None, no_tree=False,
 
1346
            overwrite_tags=False, lossy=False):
 
1347
        from .location import location_to_url
1329
1348
        from .push import _show_push_branch
1330
1349
 
1331
1350
        if overwrite:
1353
1372
                more_warning='Uncommitted changes will not be pushed.')
1354
1373
        # Get the stacked_on branch, if any
1355
1374
        if stacked_on is not None:
 
1375
            stacked_on = location_to_url(stacked_on, 'read')
1356
1376
            stacked_on = urlutils.normalize_url(stacked_on)
1357
1377
        elif stacked:
1358
1378
            parent_url = br_from.get_parent()
1379
1399
                        "No push location known or specified. To push to the "
1380
1400
                        "parent branch (at %s), use 'brz push :parent'." %
1381
1401
                        urlutils.unescape_for_display(parent_loc,
1382
 
                            self.outf.encoding)))
 
1402
                                                      self.outf.encoding)))
1383
1403
                else:
1384
1404
                    raise errors.BzrCommandError(gettext(
1385
1405
                        "No push location known or specified."))
1386
1406
            else:
1387
1407
                display_url = urlutils.unescape_for_display(stored_loc,
1388
 
                        self.outf.encoding)
 
1408
                                                            self.outf.encoding)
1389
1409
                note(gettext("Using saved push location: %s") % display_url)
1390
1410
                location = stored_loc
1391
1411
 
1392
1412
        _show_push_branch(br_from, revision_id, location, self.outf,
1393
 
            verbose=verbose, overwrite=overwrite, remember=remember,
1394
 
            stacked_on=stacked_on, create_prefix=create_prefix,
1395
 
            use_existing_dir=use_existing_dir, no_tree=no_tree,
1396
 
            lossy=lossy)
 
1413
                          verbose=verbose, overwrite=overwrite, remember=remember,
 
1414
                          stacked_on=stacked_on, create_prefix=create_prefix,
 
1415
                          use_existing_dir=use_existing_dir, no_tree=no_tree,
 
1416
                          lossy=lossy)
1397
1417
 
1398
1418
 
1399
1419
class cmd_branch(Command):
1413
1433
    _see_also = ['checkout']
1414
1434
    takes_args = ['from_location', 'to_location?']
1415
1435
    takes_options = ['revision',
1416
 
        Option('hardlink', help='Hard-link working tree files where possible.'),
1417
 
        Option('files-from', type=text_type,
1418
 
               help="Get file contents from this tree."),
1419
 
        Option('no-tree',
1420
 
            help="Create a branch without a working-tree."),
1421
 
        Option('switch',
1422
 
            help="Switch the checkout in the current directory "
1423
 
                 "to the new branch."),
1424
 
        Option('stacked',
1425
 
            help='Create a stacked branch referring to the source branch. '
1426
 
                'The new branch will depend on the availability of the source '
1427
 
                'branch for all operations.'),
1428
 
        Option('standalone',
1429
 
               help='Do not use a shared repository, even if available.'),
1430
 
        Option('use-existing-dir',
1431
 
               help='By default branch will fail if the target'
1432
 
                    ' directory exists, but does not already'
1433
 
                    ' have a control directory.  This flag will'
1434
 
                    ' allow branch to proceed.'),
1435
 
        Option('bind',
1436
 
            help="Bind new branch to from location."),
1437
 
        ]
 
1436
                     Option(
 
1437
                         'hardlink', help='Hard-link working tree files where possible.'),
 
1438
                     Option('files-from', type=text_type,
 
1439
                            help="Get file contents from this tree."),
 
1440
                     Option('no-tree',
 
1441
                            help="Create a branch without a working-tree."),
 
1442
                     Option('switch',
 
1443
                            help="Switch the checkout in the current directory "
 
1444
                            "to the new branch."),
 
1445
                     Option('stacked',
 
1446
                            help='Create a stacked branch referring to the source branch. '
 
1447
                            'The new branch will depend on the availability of the source '
 
1448
                            'branch for all operations.'),
 
1449
                     Option('standalone',
 
1450
                            help='Do not use a shared repository, even if available.'),
 
1451
                     Option('use-existing-dir',
 
1452
                            help='By default branch will fail if the target'
 
1453
                            ' directory exists, but does not already'
 
1454
                            ' have a control directory.  This flag will'
 
1455
                            ' allow branch to proceed.'),
 
1456
                     Option('bind',
 
1457
                            help="Bind new branch to from location."),
 
1458
                     ]
1438
1459
 
1439
1460
    def run(self, from_location, to_location=None, revision=None,
1440
1461
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1461
1482
            revision_id = br_from.last_revision()
1462
1483
        if to_location is None:
1463
1484
            to_location = urlutils.derive_to_location(from_location)
1464
 
        to_transport = transport.get_transport(to_location)
 
1485
        to_transport = transport.get_transport(to_location, purpose='write')
1465
1486
        try:
1466
1487
            to_transport.mkdir('.')
1467
1488
        except errors.FileExists:
1471
1492
            except errors.NotBranchError:
1472
1493
                if not use_existing_dir:
1473
1494
                    raise errors.BzrCommandError(gettext('Target directory "%s" '
1474
 
                        'already exists.') % to_location)
 
1495
                                                         'already exists.') % to_location)
1475
1496
                else:
1476
1497
                    to_dir = None
1477
1498
            else:
1517
1538
        # We therefore need a try/except here and not just 'if stacked:'
1518
1539
        try:
1519
1540
            note(gettext('Created new stacked branch referring to %s.') %
1520
 
                branch.get_stacked_on_url())
 
1541
                 branch.get_stacked_on_url())
1521
1542
        except (errors.NotStacked, _mod_branch.UnstackableBranchFormat,
1522
 
            errors.UnstackableRepositoryFormat) as e:
1523
 
            note(ngettext('Branched %d revision.', 'Branched %d revisions.', branch.revno()) % branch.revno())
 
1543
                errors.UnstackableRepositoryFormat) as e:
 
1544
            revno = branch.revno()
 
1545
            if revno is not None:
 
1546
                note(ngettext('Branched %d revision.',
 
1547
                              'Branched %d revisions.',
 
1548
                              branch.revno()) % revno)
 
1549
            else:
 
1550
                note(gettext('Created new branch.'))
1524
1551
        if bind:
1525
1552
            # Bind to the parent
1526
1553
            parent_branch = Branch.open(from_location)
1531
1558
            wt, _ = WorkingTree.open_containing('.')
1532
1559
            _mod_switch.switch(wt.controldir, branch)
1533
1560
            note(gettext('Switched to branch: %s'),
1534
 
                urlutils.unescape_for_display(branch.base, 'utf-8'))
 
1561
                 urlutils.unescape_for_display(branch.base, 'utf-8'))
1535
1562
 
1536
1563
 
1537
1564
class cmd_branches(Command):
1543
1570
 
1544
1571
    takes_args = ['location?']
1545
1572
    takes_options = [
1546
 
                  Option('recursive', short_name='R',
1547
 
                         help='Recursively scan for branches rather than '
1548
 
                              'just looking in the specified location.')]
 
1573
        Option('recursive', short_name='R',
 
1574
               help='Recursively scan for branches rather than '
 
1575
               'just looking in the specified location.')]
1549
1576
 
1550
1577
    def run(self, location=".", recursive=False):
1551
1578
        if recursive:
1552
 
            t = transport.get_transport(location)
 
1579
            t = transport.get_transport(location, purpose='read')
1553
1580
            if not t.listable():
1554
1581
                raise errors.BzrCommandError(
1555
1582
                    "Can't scan this type of location.")
1587
1614
class cmd_checkout(Command):
1588
1615
    __doc__ = """Create a new checkout of an existing branch.
1589
1616
 
1590
 
    If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
1591
 
    the branch found in '.'. This is useful if you have removed the working tree
1592
 
    or if it was never created - i.e. if you pushed the branch to its current
1593
 
    location using SFTP.
 
1617
    If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree
 
1618
    for the branch found in '.'. This is useful if you have removed the working
 
1619
    tree or if it was never created - i.e. if you pushed the branch to its
 
1620
    current location using SFTP.
1594
1621
 
1595
 
    If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
1596
 
    be used.  In other words, "checkout ../foo/bar" will attempt to create ./bar.
1597
 
    If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
1598
 
    is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
1599
 
    identifier, if any. For example, "checkout lp:foo-bar" will attempt to
1600
 
    create ./foo-bar.
 
1622
    If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION
 
1623
    will be used.  In other words, "checkout ../foo/bar" will attempt to create
 
1624
    ./bar.  If the BRANCH_LOCATION has no / or path separator embedded, the
 
1625
    TO_LOCATION is derived from the BRANCH_LOCATION by stripping a leading
 
1626
    scheme or drive identifier, if any. For example, "checkout lp:foo-bar" will
 
1627
    attempt to create ./foo-bar.
1601
1628
 
1602
1629
    To retrieve the branch as of a particular revision, supply the --revision
1603
 
    parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
1604
 
    out of date [so you cannot commit] but it may be useful (i.e. to examine old
1605
 
    code.)
 
1630
    parameter, as in "checkout foo/bar -r 5". Note that this will be
 
1631
    immediately out of date [so you cannot commit] but it may be useful (i.e.
 
1632
    to examine old code.)
1606
1633
    """
1607
1634
 
1608
1635
    _see_also = ['checkouts', 'branch', 'working-trees', 'remove-tree']
1647
1674
        # if the source and to_location are the same,
1648
1675
        # and there is no working tree,
1649
1676
        # then reconstitute a branch
1650
 
        if (osutils.abspath(to_location) ==
1651
 
            osutils.abspath(branch_location)):
 
1677
        if osutils.abspath(to_location) == osutils.abspath(branch_location):
1652
1678
            try:
1653
1679
                source.controldir.open_workingtree()
1654
1680
            except errors.NoWorkingTree:
1691
1717
 
1692
1718
    This will perform a merge of the destination revision (the tip of the
1693
1719
    branch, or the specified revision) into the working tree, and then make
1694
 
    that revision the basis revision for the working tree.  
 
1720
    that revision the basis revision for the working tree.
1695
1721
 
1696
1722
    You can use this to visit an older revision, or to update a working tree
1697
1723
    that is out of date from its branch.
1698
 
    
 
1724
 
1699
1725
    If there are any uncommitted changes in the tree, they will be carried
1700
1726
    across and remain as uncommitted changes after the update.  To discard
1701
1727
    these changes, use 'brz revert'.  The uncommitted changes may conflict
1704
1730
    If the tree's branch is bound to a master branch, brz will also update
1705
1731
    the branch from the master.
1706
1732
 
1707
 
    You cannot update just a single file or directory, because each Bazaar
 
1733
    You cannot update just a single file or directory, because each Breezy
1708
1734
    working tree has just a single basis revision.  If you want to restore a
1709
1735
    file that has been removed locally, use 'brz revert' instead of 'brz
1710
1736
    update'.  If you want to restore a file to its state in a previous
1712
1738
    out the old content of that file to a new location.
1713
1739
 
1714
1740
    The 'dir' argument, if given, must be the location of the root of a
1715
 
    working tree to update.  By default, the working tree that contains the 
 
1741
    working tree to update.  By default, the working tree that contains the
1716
1742
    current working directory is used.
1717
1743
    """
1718
1744
 
1767
1793
        if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1768
1794
            revno = branch.revision_id_to_dotted_revno(revision_id)
1769
1795
            note(gettext("Tree is up to date at revision {0} of branch {1}"
1770
 
                        ).format('.'.join(map(str, revno)), branch_location))
 
1796
                         ).format('.'.join(map(str, revno)), branch_location))
1771
1797
            return 0
1772
1798
        view_info = _get_view_info_for_change_reporter(tree)
1773
1799
        change_reporter = delta._ChangeReporter(
1782
1808
                show_base=show_base)
1783
1809
        except errors.NoSuchRevision as e:
1784
1810
            raise errors.BzrCommandError(gettext(
1785
 
                                  "branch has no revision %s\n"
1786
 
                                  "brz update --revision only works"
1787
 
                                  " for a revision in the branch history")
1788
 
                                  % (e.revision))
 
1811
                "branch has no revision %s\n"
 
1812
                "brz update --revision only works"
 
1813
                " for a revision in the branch history")
 
1814
                % (e.revision))
1789
1815
        revno = tree.branch.revision_id_to_dotted_revno(
1790
1816
            _mod_revision.ensure_null(tree.last_revision()))
1791
1817
        note(gettext('Updated to revision {0} of branch {1}').format(
1793
1819
        parent_ids = tree.get_parent_ids()
1794
1820
        if parent_ids[1:] and parent_ids[1:] != existing_pending_merges:
1795
1821
            note(gettext('Your local commits will now show as pending merges with '
1796
 
                 "'brz status', and can be committed with 'brz commit'."))
 
1822
                         "'brz status', and can be committed with 'brz commit'."))
1797
1823
        if conflicts != 0:
1798
1824
            return 1
1799
1825
        else:
1847
1873
class cmd_remove(Command):
1848
1874
    __doc__ = """Remove files or directories.
1849
1875
 
1850
 
    This makes Bazaar stop tracking changes to the specified files. Bazaar will
 
1876
    This makes Breezy stop tracking changes to the specified files. Breezy will
1851
1877
    delete them if they can easily be recovered using revert otherwise they
1852
1878
    will be backed up (adding an extension of the form .~#~). If no options or
1853
 
    parameters are given Bazaar will scan for files that are being tracked by
1854
 
    Bazaar but missing in your tree and stop tracking them for you.
 
1879
    parameters are given Breezy will scan for files that are being tracked by
 
1880
    Breezy but missing in your tree and stop tracking them for you.
1855
1881
    """
1856
1882
    takes_args = ['file*']
1857
1883
    takes_options = ['verbose',
1858
 
        Option('new', help='Only remove files that have never been committed.'),
1859
 
        RegistryOption.from_kwargs('file-deletion-strategy',
1860
 
            'The file deletion mode to be used.',
1861
 
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1862
 
            safe='Backup changed files (default).',
1863
 
            keep='Delete from brz but leave the working copy.',
1864
 
            no_backup='Don\'t backup changed files.'),
1865
 
        ]
 
1884
                     Option(
 
1885
                         'new', help='Only remove files that have never been committed.'),
 
1886
                     RegistryOption.from_kwargs('file-deletion-strategy',
 
1887
                                                'The file deletion mode to be used.',
 
1888
                                                title='Deletion Strategy', value_switches=True, enum_switch=False,
 
1889
                                                safe='Backup changed files (default).',
 
1890
                                                keep='Delete from brz but leave the working copy.',
 
1891
                                                no_backup='Don\'t backup changed files.'),
 
1892
                     ]
1866
1893
    aliases = ['rm', 'del']
1867
1894
    encoding_type = 'replace'
1868
1895
 
1869
1896
    def run(self, file_list, verbose=False, new=False,
1870
 
        file_deletion_strategy='safe'):
 
1897
            file_deletion_strategy='safe'):
1871
1898
 
1872
1899
        tree, file_list = WorkingTree.open_containing_paths(file_list)
1873
1900
 
1879
1906
        # some such?
1880
1907
        if new:
1881
1908
            added = tree.changes_from(tree.basis_tree(),
1882
 
                specific_files=file_list).added
 
1909
                                      specific_files=file_list).added
1883
1910
            file_list = sorted([f[0] for f in added], reverse=True)
1884
1911
            if len(file_list) == 0:
1885
1912
                raise errors.BzrCommandError(gettext('No matching files.'))
1894
1921
            file_list = sorted(missing, reverse=True)
1895
1922
            file_deletion_strategy = 'keep'
1896
1923
        tree.remove(file_list, verbose=verbose, to_file=self.outf,
1897
 
            keep_files=file_deletion_strategy=='keep',
1898
 
            force=(file_deletion_strategy=='no-backup'))
1899
 
 
1900
 
 
1901
 
class cmd_file_id(Command):
1902
 
    __doc__ = """Print file_id of a particular file or directory.
1903
 
 
1904
 
    The file_id is assigned when the file is first added and remains the
1905
 
    same through all revisions where the file exists, even when it is
1906
 
    moved or renamed.
1907
 
    """
1908
 
 
1909
 
    hidden = True
1910
 
    _see_also = ['inventory', 'ls']
1911
 
    takes_args = ['filename']
1912
 
 
1913
 
    @display_command
1914
 
    def run(self, filename):
1915
 
        tree, relpath = WorkingTree.open_containing(filename)
1916
 
        file_id = tree.path2id(relpath)
1917
 
        if file_id is None:
1918
 
            raise errors.NotVersionedError(filename)
1919
 
        else:
1920
 
            self.outf.write(file_id.decode('utf-8') + '\n')
1921
 
 
1922
 
 
1923
 
class cmd_file_path(Command):
1924
 
    __doc__ = """Print path of file_ids to a file or directory.
1925
 
 
1926
 
    This prints one line for each directory down to the target,
1927
 
    starting at the branch root.
1928
 
    """
1929
 
 
1930
 
    hidden = True
1931
 
    takes_args = ['filename']
1932
 
 
1933
 
    @display_command
1934
 
    def run(self, filename):
1935
 
        tree, relpath = WorkingTree.open_containing(filename)
1936
 
        fid = tree.path2id(relpath)
1937
 
        if fid is None:
1938
 
            raise errors.NotVersionedError(filename)
1939
 
        segments = osutils.splitpath(relpath)
1940
 
        for pos in range(1, len(segments) + 1):
1941
 
            path = osutils.joinpath(segments[:pos])
1942
 
            self.outf.write("%s\n" % tree.path2id(path))
 
1924
                    keep_files=file_deletion_strategy == 'keep',
 
1925
                    force=(file_deletion_strategy == 'no-backup'))
1943
1926
 
1944
1927
 
1945
1928
class cmd_reconcile(Command):
1990
1973
        self.add_cleanup(branch.lock_read().unlock)
1991
1974
        graph = branch.repository.get_graph()
1992
1975
        history = list(graph.iter_lefthand_ancestry(branch.last_revision(),
1993
 
            [_mod_revision.NULL_REVISION]))
 
1976
                                                    [_mod_revision.NULL_REVISION]))
1994
1977
        for revid in reversed(history):
1995
1978
            self.outf.write(revid)
1996
1979
            self.outf.write('\n')
2018
2001
        self.add_cleanup(b.repository.lock_read().unlock)
2019
2002
        graph = b.repository.get_graph()
2020
2003
        revisions = [revid for revid, parents in
2021
 
            graph.iter_ancestry([last_revision])]
 
2004
                     graph.iter_ancestry([last_revision])]
2022
2005
        for revision_id in reversed(revisions):
2023
2006
            if _mod_revision.is_null(revision_id):
2024
2007
                continue
2054
2037
        Option('create-prefix',
2055
2038
               help='Create the path leading up to the branch '
2056
2039
                    'if it does not already exist.'),
2057
 
         RegistryOption('format',
2058
 
                help='Specify a format for this branch. '
2059
 
                'See "help formats" for a full list.',
2060
 
                lazy_registry=('breezy.controldir', 'format_registry'),
2061
 
                converter=lambda name: controldir.format_registry.make_controldir(name),
2062
 
                value_switches=True,
2063
 
                title="Branch format",
2064
 
                ),
2065
 
         Option('append-revisions-only',
2066
 
                help='Never change revnos or the existing log.'
2067
 
                '  Append revisions to it only.'),
2068
 
         Option('no-tree',
2069
 
                'Create a branch without a working tree.')
2070
 
         ]
 
2040
        RegistryOption('format',
 
2041
                       help='Specify a format for this branch. '
 
2042
                       'See "help formats" for a full list.',
 
2043
                       lazy_registry=('breezy.controldir', 'format_registry'),
 
2044
                       converter=lambda name: controldir.format_registry.make_controldir(
 
2045
                            name),
 
2046
                       value_switches=True,
 
2047
                       title="Branch format",
 
2048
                       ),
 
2049
        Option('append-revisions-only',
 
2050
               help='Never change revnos or the existing log.'
 
2051
               '  Append revisions to it only.'),
 
2052
        Option('no-tree',
 
2053
               'Create a branch without a working tree.')
 
2054
        ]
 
2055
 
2071
2056
    def run(self, location=None, format=None, append_revisions_only=False,
2072
2057
            create_prefix=False, no_tree=False):
2073
2058
        if format is None:
2075
2060
        if location is None:
2076
2061
            location = u'.'
2077
2062
 
2078
 
        to_transport = transport.get_transport(location)
 
2063
        to_transport = transport.get_transport(location, purpose='write')
2079
2064
 
2080
2065
        # The path has to exist to initialize a
2081
2066
        # branch inside of it.
2087
2072
        except errors.NoSuchFile:
2088
2073
            if not create_prefix:
2089
2074
                raise errors.BzrCommandError(gettext("Parent directory of %s"
2090
 
                    " does not exist."
2091
 
                    "\nYou may supply --create-prefix to create all"
2092
 
                    " leading parent directories.")
2093
 
                    % location)
 
2075
                                                     " does not exist."
 
2076
                                                     "\nYou may supply --create-prefix to create all"
 
2077
                                                     " leading parent directories.")
 
2078
                                             % location)
2094
2079
            to_transport.create_prefix()
2095
2080
 
2096
2081
        try:
2097
 
            a_controldir = controldir.ControlDir.open_from_transport(to_transport)
 
2082
            a_controldir = controldir.ControlDir.open_from_transport(
 
2083
                to_transport)
2098
2084
        except errors.NotBranchError:
2099
2085
            # really a NotBzrDir error...
2100
2086
            create_branch = controldir.ControlDir.create_branch_convenience
2110
2096
            from .transport.local import LocalTransport
2111
2097
            if a_controldir.has_branch():
2112
2098
                if (isinstance(to_transport, LocalTransport)
2113
 
                    and not a_controldir.has_workingtree()):
2114
 
                        raise errors.BranchExistsWithoutWorkingTree(location)
 
2099
                        and not a_controldir.has_workingtree()):
 
2100
                    raise errors.BranchExistsWithoutWorkingTree(location)
2115
2101
                raise errors.AlreadyBranchError(location)
2116
2102
            branch = a_controldir.create_branch()
2117
2103
            if not no_tree and not a_controldir.has_workingtree():
2121
2107
                branch.set_append_revisions_only(True)
2122
2108
            except errors.UpgradeRequired:
2123
2109
                raise errors.BzrCommandError(gettext('This branch format cannot be set'
2124
 
                    ' to append-revisions-only.  Try --default.'))
 
2110
                                                     ' to append-revisions-only.  Try --default.'))
2125
2111
        if not is_quiet():
2126
2112
            from .info import describe_layout, describe_format
2127
2113
            try:
2132
2118
            layout = describe_layout(repository, branch, tree).lower()
2133
2119
            format = describe_format(a_controldir, repository, branch, tree)
2134
2120
            self.outf.write(gettext("Created a {0} (format: {1})\n").format(
2135
 
                  layout, format))
 
2121
                layout, format))
2136
2122
            if repository.is_shared():
2137
 
                #XXX: maybe this can be refactored into transport.path_or_url()
 
2123
                # XXX: maybe this can be refactored into transport.path_or_url()
2138
2124
                url = repository.controldir.root_transport.external_url()
2139
2125
                try:
2140
2126
                    url = urlutils.local_path_from_url(url)
2148
2134
 
2149
2135
    New branches created under the repository directory will store their
2150
2136
    revisions in the repository, not in the branch directory.  For branches
2151
 
    with shared history, this reduces the amount of storage needed and 
 
2137
    with shared history, this reduces the amount of storage needed and
2152
2138
    speeds up the creation of new branches.
2153
2139
 
2154
2140
    If the --no-trees option is given then the branches in the repository
2155
 
    will not have working trees by default.  They will still exist as 
2156
 
    directories on disk, but they will not have separate copies of the 
 
2141
    will not have working trees by default.  They will still exist as
 
2142
    directories on disk, but they will not have separate copies of the
2157
2143
    files at a certain revision.  This can be useful for repositories that
2158
2144
    store branches which are interacted with through checkouts or remote
2159
2145
    branches, such as on a server.
2174
2160
    _see_also = ['init', 'branch', 'checkout', 'repositories']
2175
2161
    takes_args = ["location"]
2176
2162
    takes_options = [RegistryOption('format',
2177
 
                            help='Specify a format for this repository. See'
2178
 
                                 ' "brz help formats" for details.',
2179
 
                            lazy_registry=('breezy.controldir', 'format_registry'),
2180
 
                            converter=lambda name: controldir.format_registry.make_controldir(name),
2181
 
                            value_switches=True, title='Repository format'),
 
2163
                                    help='Specify a format for this repository. See'
 
2164
                                    ' "brz help formats" for details.',
 
2165
                                    lazy_registry=(
 
2166
                                        'breezy.controldir', 'format_registry'),
 
2167
                                    converter=lambda name: controldir.format_registry.make_controldir(
 
2168
                                        name),
 
2169
                                    value_switches=True, title='Repository format'),
2182
2170
                     Option('no-trees',
2183
 
                             help='Branches in the repository will default to'
2184
 
                                  ' not having a working tree.'),
2185
 
                    ]
 
2171
                            help='Branches in the repository will default to'
 
2172
                            ' not having a working tree.'),
 
2173
                     ]
2186
2174
    aliases = ["init-repo"]
2187
2175
 
2188
2176
    def run(self, location, format=None, no_trees=False):
2192
2180
        if location is None:
2193
2181
            location = '.'
2194
2182
 
2195
 
        to_transport = transport.get_transport(location)
 
2183
        to_transport = transport.get_transport(location, purpose='write')
2196
2184
 
2197
2185
        if format.fixed_components:
2198
2186
            repo_format_name = None
2201
2189
 
2202
2190
        (repo, newdir, require_stacking, repository_policy) = (
2203
2191
            format.initialize_on_transport_ex(to_transport,
2204
 
            create_prefix=True, make_working_trees=not no_trees,
2205
 
            shared_repo=True, force_new_repo=True,
2206
 
            use_existing_dir=True,
2207
 
            repo_format_name=repo_format_name))
 
2192
                                              create_prefix=True, make_working_trees=not no_trees,
 
2193
                                              shared_repo=True, force_new_repo=True,
 
2194
                                              use_existing_dir=True,
 
2195
                                              repo_format_name=repo_format_name))
2208
2196
        if not is_quiet():
2209
2197
            from .info import show_bzrdir_info
2210
2198
            show_bzrdir_info(newdir, verbose=0, outfile=self.outf)
2225
2213
 
2226
2214
    Note that when using the -r argument with a range of revisions, the
2227
2215
    differences are computed between the two specified revisions.  That
2228
 
    is, the command does not show the changes introduced by the first 
2229
 
    revision in the range.  This differs from the interpretation of 
 
2216
    is, the command does not show the changes introduced by the first
 
2217
    revision in the range.  This differs from the interpretation of
2230
2218
    revision ranges used by "brz log" which includes the first revision
2231
2219
    in the range.
2232
2220
 
2258
2246
            brz diff -c2
2259
2247
 
2260
2248
        To see the changes introduced by revision X::
2261
 
        
 
2249
 
2262
2250
            brz diff -cX
2263
2251
 
2264
2252
        Note that in the case of a merge, the -c option shows the changes
2306
2294
               help='Set prefixes added to old and new filenames, as '
2307
2295
                    'two values separated by a colon. (eg "old/:new/").'),
2308
2296
        Option('old',
2309
 
            help='Branch/tree to compare from.',
2310
 
            type=text_type,
2311
 
            ),
 
2297
               help='Branch/tree to compare from.',
 
2298
               type=text_type,
 
2299
               ),
2312
2300
        Option('new',
2313
 
            help='Branch/tree to compare to.',
2314
 
            type=text_type,
2315
 
            ),
 
2301
               help='Branch/tree to compare to.',
 
2302
               type=text_type,
 
2303
               ),
2316
2304
        'revision',
2317
2305
        'change',
2318
2306
        Option('using',
2319
 
            help='Use this command to compare files.',
2320
 
            type=text_type,
2321
 
            ),
 
2307
               help='Use this command to compare files.',
 
2308
               type=text_type,
 
2309
               ),
2322
2310
        RegistryOption('format',
2323
 
            short_name='F',
2324
 
            help='Diff format to use.',
2325
 
            lazy_registry=('breezy.diff', 'format_registry'),
2326
 
            title='Diff format'),
 
2311
                       short_name='F',
 
2312
                       help='Diff format to use.',
 
2313
                       lazy_registry=('breezy.diff', 'format_registry'),
 
2314
                       title='Diff format'),
2327
2315
        Option('context',
2328
 
            help='How many lines of context to show.',
2329
 
            type=int,
2330
 
            ),
 
2316
               help='How many lines of context to show.',
 
2317
               type=int,
 
2318
               ),
2331
2319
        ]
2332
2320
    aliases = ['di', 'dif']
2333
2321
    encoding_type = 'exact'
2337
2325
            prefix=None, old=None, new=None, using=None, format=None,
2338
2326
            context=None):
2339
2327
        from .diff import (get_trees_and_branches_to_diff_locked,
2340
 
            show_diff_trees)
 
2328
                           show_diff_trees)
2341
2329
 
2342
2330
        if prefix == u'0':
2343
2331
            # diff -p0 format
2355
2343
 
2356
2344
        if revision and len(revision) > 2:
2357
2345
            raise errors.BzrCommandError(gettext('brz diff --revision takes exactly'
2358
 
                                         ' one or two revision specifiers'))
 
2346
                                                 ' one or two revision specifiers'))
2359
2347
 
2360
2348
        if using is not None and format is not None:
2361
2349
            raise errors.BzrCommandError(gettext(
2440
2428
        self.add_cleanup(wt.lock_read().unlock)
2441
2429
        basis = wt.basis_tree()
2442
2430
        self.add_cleanup(basis.lock_read().unlock)
2443
 
        root_id = wt.get_root_id()
2444
2431
        for path in wt.all_versioned_paths():
2445
2432
            if basis.has_filename(path):
2446
2433
                continue
2457
2444
class cmd_root(Command):
2458
2445
    __doc__ = """Show the tree root directory.
2459
2446
 
2460
 
    The root is the nearest enclosing directory with a .bzr control
 
2447
    The root is the nearest enclosing directory with a control
2461
2448
    directory."""
2462
2449
 
2463
2450
    takes_args = ['filename?']
 
2451
 
2464
2452
    @display_command
2465
2453
    def run(self, filename=None):
2466
2454
        """Print the branch root."""
2608
2596
      line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2609
2597
      bzr-explorer shell, or the Loggerhead web interface.  See the Bazaar
2610
2598
      Plugin Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2611
 
      <http://wiki.bazaar.canonical.com/IDEIntegration>.  
 
2599
      <http://wiki.bazaar.canonical.com/IDEIntegration>.
2612
2600
 
2613
2601
      You may find it useful to add the aliases below to ``breezy.conf``::
2614
2602
 
2642
2630
    takes_args = ['file*']
2643
2631
    _see_also = ['log-formats', 'revisionspec']
2644
2632
    takes_options = [
2645
 
            Option('forward',
2646
 
                   help='Show from oldest to newest.'),
2647
 
            'timezone',
2648
 
            custom_help('verbose',
2649
 
                   help='Show files changed in each revision.'),
2650
 
            'show-ids',
2651
 
            'revision',
2652
 
            Option('change',
2653
 
                   type=breezy.option._parse_revision_str,
2654
 
                   short_name='c',
2655
 
                   help='Show just the specified revision.'
2656
 
                   ' See also "help revisionspec".'),
2657
 
            'log-format',
2658
 
            RegistryOption('authors',
2659
 
                'What names to list as authors - first, all or committer.',
2660
 
                title='Authors',
2661
 
                lazy_registry=('breezy.log', 'author_list_registry'),
2662
 
            ),
2663
 
            Option('levels',
2664
 
                   short_name='n',
2665
 
                   help='Number of levels to display - 0 for all, 1 for flat.',
2666
 
                   argname='N',
2667
 
                   type=_parse_levels),
2668
 
            Option('message',
2669
 
                   help='Show revisions whose message matches this '
2670
 
                        'regular expression.',
2671
 
                   type=text_type,
2672
 
                   hidden=True),
2673
 
            Option('limit',
2674
 
                   short_name='l',
2675
 
                   help='Limit the output to the first N revisions.',
2676
 
                   argname='N',
2677
 
                   type=_parse_limit),
2678
 
            Option('show-diff',
2679
 
                   short_name='p',
2680
 
                   help='Show changes made in each revision as a patch.'),
2681
 
            Option('include-merged',
2682
 
                   help='Show merged revisions like --levels 0 does.'),
2683
 
            Option('include-merges', hidden=True,
2684
 
                   help='Historical alias for --include-merged.'),
2685
 
            Option('omit-merges',
2686
 
                   help='Do not report commits with more than one parent.'),
2687
 
            Option('exclude-common-ancestry',
2688
 
                   help='Display only the revisions that are not part'
2689
 
                   ' of both ancestries (require -rX..Y).'
2690
 
                   ),
2691
 
            Option('signatures',
2692
 
                   help='Show digital signature validity.'),
2693
 
            ListOption('match',
2694
 
                short_name='m',
2695
 
                help='Show revisions whose properties match this '
2696
 
                'expression.',
2697
 
                type=text_type),
2698
 
            ListOption('match-message',
2699
 
                   help='Show revisions whose message matches this '
2700
 
                   'expression.',
2701
 
                type=text_type),
2702
 
            ListOption('match-committer',
 
2633
        Option('forward',
 
2634
               help='Show from oldest to newest.'),
 
2635
        'timezone',
 
2636
        custom_help('verbose',
 
2637
                    help='Show files changed in each revision.'),
 
2638
        'show-ids',
 
2639
        'revision',
 
2640
        Option('change',
 
2641
               type=breezy.option._parse_revision_str,
 
2642
               short_name='c',
 
2643
               help='Show just the specified revision.'
 
2644
               ' See also "help revisionspec".'),
 
2645
        'log-format',
 
2646
        RegistryOption('authors',
 
2647
                       'What names to list as authors - first, all or committer.',
 
2648
                       title='Authors',
 
2649
                       lazy_registry=(
 
2650
                           'breezy.log', 'author_list_registry'),
 
2651
                       ),
 
2652
        Option('levels',
 
2653
               short_name='n',
 
2654
               help='Number of levels to display - 0 for all, 1 for flat.',
 
2655
               argname='N',
 
2656
               type=_parse_levels),
 
2657
        Option('message',
 
2658
               help='Show revisions whose message matches this '
 
2659
               'regular expression.',
 
2660
               type=text_type,
 
2661
               hidden=True),
 
2662
        Option('limit',
 
2663
               short_name='l',
 
2664
               help='Limit the output to the first N revisions.',
 
2665
               argname='N',
 
2666
               type=_parse_limit),
 
2667
        Option('show-diff',
 
2668
               short_name='p',
 
2669
               help='Show changes made in each revision as a patch.'),
 
2670
        Option('include-merged',
 
2671
               help='Show merged revisions like --levels 0 does.'),
 
2672
        Option('include-merges', hidden=True,
 
2673
               help='Historical alias for --include-merged.'),
 
2674
        Option('omit-merges',
 
2675
               help='Do not report commits with more than one parent.'),
 
2676
        Option('exclude-common-ancestry',
 
2677
               help='Display only the revisions that are not part'
 
2678
               ' of both ancestries (require -rX..Y).'
 
2679
               ),
 
2680
        Option('signatures',
 
2681
               help='Show digital signature validity.'),
 
2682
        ListOption('match',
 
2683
                   short_name='m',
 
2684
                   help='Show revisions whose properties match this '
 
2685
                   'expression.',
 
2686
                   type=text_type),
 
2687
        ListOption('match-message',
 
2688
                   help='Show revisions whose message matches this '
 
2689
                   'expression.',
 
2690
                   type=text_type),
 
2691
        ListOption('match-committer',
2703
2692
                   help='Show revisions whose committer matches this '
2704
2693
                   'expression.',
2705
 
                type=text_type),
2706
 
            ListOption('match-author',
 
2694
                   type=text_type),
 
2695
        ListOption('match-author',
2707
2696
                   help='Show revisions whose authors match this '
2708
2697
                   'expression.',
2709
 
                type=text_type),
2710
 
            ListOption('match-bugs',
 
2698
                   type=text_type),
 
2699
        ListOption('match-bugs',
2711
2700
                   help='Show revisions whose bugs match this '
2712
2701
                   'expression.',
2713
 
                type=text_type)
2714
 
            ]
 
2702
                   type=text_type)
 
2703
        ]
2715
2704
    encoding_type = 'replace'
2716
2705
 
2717
2706
    @display_command
2746
2735
        if include_merged is None:
2747
2736
            include_merged = False
2748
2737
        if (exclude_common_ancestry
2749
 
            and (revision is None or len(revision) != 2)):
 
2738
                and (revision is None or len(revision) != 2)):
2750
2739
            raise errors.BzrCommandError(gettext(
2751
2740
                '--exclude-common-ancestry requires -r with two revisions'))
2752
2741
        if include_merged:
2823
2812
        if log_format is None:
2824
2813
            log_format = log.log_formatter_registry.get_default(b)
2825
2814
        # Make a non-encoding output to include the diffs - bug 328007
2826
 
        unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
 
2815
        unencoded_output = ui.ui_factory.make_output_stream(
 
2816
            encoding_type='exact')
2827
2817
        lf = log_format(show_ids=show_ids, to_file=self.outf,
2828
2818
                        to_exact_file=unencoded_output,
2829
2819
                        show_timezone=timezone,
2846
2836
        # file that isn't a directory without showing a delta" case.
2847
2837
        partial_history = revision and b.repository._format.supports_chks
2848
2838
        match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2849
 
            or delta_type or partial_history)
 
2839
                              or delta_type or partial_history)
2850
2840
 
2851
2841
        match_dict = {}
2852
2842
        if match:
2922
2912
        rev_id2 = revision_range[1].rev_id
2923
2913
    return rev_id1, rev_id2
2924
2914
 
 
2915
 
2925
2916
def get_log_format(long=False, short=False, line=False, default='long'):
2926
2917
    log_format = default
2927
2918
    if long:
2947
2938
        tree, relpath = WorkingTree.open_containing(filename)
2948
2939
        with tree.lock_read():
2949
2940
            touching_revs = log.find_touching_revisions(
2950
 
                    tree.branch.repository, tree.branch.last_revision(), tree, relpath)
 
2941
                tree.branch.repository, tree.branch.last_revision(), tree, relpath)
2951
2942
            for revno, revision_id, what in reversed(list(touching_revs)):
2952
2943
                self.outf.write("%6d %s\n" % (revno, what))
2953
2944
 
2959
2950
    _see_also = ['status', 'cat']
2960
2951
    takes_args = ['path?']
2961
2952
    takes_options = [
2962
 
            'verbose',
2963
 
            'revision',
2964
 
            Option('recursive', short_name='R',
2965
 
                   help='Recurse into subdirectories.'),
2966
 
            Option('from-root',
2967
 
                   help='Print paths relative to the root of the branch.'),
2968
 
            Option('unknown', short_name='u',
2969
 
                help='Print unknown files.'),
2970
 
            Option('versioned', help='Print versioned files.',
2971
 
                   short_name='V'),
2972
 
            Option('ignored', short_name='i',
2973
 
                help='Print ignored files.'),
2974
 
            Option('kind', short_name='k',
2975
 
                   help=('List entries of a particular kind: file, '
2976
 
                         'directory, symlink, tree-reference.'),
2977
 
                   type=text_type),
2978
 
            'null',
2979
 
            'show-ids',
2980
 
            'directory',
2981
 
            ]
 
2953
        'verbose',
 
2954
        'revision',
 
2955
        Option('recursive', short_name='R',
 
2956
               help='Recurse into subdirectories.'),
 
2957
        Option('from-root',
 
2958
               help='Print paths relative to the root of the branch.'),
 
2959
        Option('unknown', short_name='u',
 
2960
               help='Print unknown files.'),
 
2961
        Option('versioned', help='Print versioned files.',
 
2962
               short_name='V'),
 
2963
        Option('ignored', short_name='i',
 
2964
               help='Print ignored files.'),
 
2965
        Option('kind', short_name='k',
 
2966
               help=('List entries of a particular kind: file, '
 
2967
                     'directory, symlink, tree-reference.'),
 
2968
               type=text_type),
 
2969
        'null',
 
2970
        'show-ids',
 
2971
        'directory',
 
2972
        ]
 
2973
 
2982
2974
    @display_command
2983
2975
    def run(self, revision=None, verbose=False,
2984
2976
            recursive=False, from_root=False,
2989
2981
            raise errors.BzrCommandError(gettext('invalid kind specified'))
2990
2982
 
2991
2983
        if verbose and null:
2992
 
            raise errors.BzrCommandError(gettext('Cannot set both --verbose and --null'))
 
2984
            raise errors.BzrCommandError(
 
2985
                gettext('Cannot set both --verbose and --null'))
2993
2986
        all = not (unknown or versioned or ignored)
2994
2987
 
2995
 
        selection = {'I':ignored, '?':unknown, 'V':versioned}
 
2988
        selection = {'I': ignored, '?': unknown, 'V': versioned}
2996
2989
 
2997
2990
        if path is None:
2998
2991
            fs_path = '.'
2999
2992
        else:
3000
2993
            if from_root:
3001
2994
                raise errors.BzrCommandError(gettext('cannot specify both --from-root'
3002
 
                                             ' and PATH'))
 
2995
                                                     ' and PATH'))
3003
2996
            fs_path = path
3004
2997
        tree, branch, relpath = \
3005
2998
            _open_directory_or_containing_tree_or_branch(fs_path, directory)
3024
3017
                note(gettext("Ignoring files outside view. View is %s") % view_str)
3025
3018
 
3026
3019
        self.add_cleanup(tree.lock_read().unlock)
3027
 
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
3028
 
            from_dir=relpath, recursive=recursive):
 
3020
        for fp, fc, fkind, entry in tree.list_files(
 
3021
                include_root=False, from_dir=relpath, recursive=recursive):
3029
3022
            # Apply additional masking
3030
3023
            if not all and not selection[fc]:
3031
3024
                continue
3049
3042
            ui.ui_factory.clear_term()
3050
3043
            if verbose:
3051
3044
                outstring = '%-8s %s' % (fc, outstring)
3052
 
                if show_ids and fid is not None:
3053
 
                    outstring = "%-50s %s" % (outstring, fid.decode('utf-8'))
 
3045
                if show_ids and getattr(entry, 'file_id', None) is not None:
 
3046
                    outstring = "%-50s %s" % (outstring, entry.file_id.decode('utf-8'))
3054
3047
                self.outf.write(outstring + '\n')
3055
3048
            elif null:
3056
3049
                self.outf.write(fp + '\0')
3057
3050
                if show_ids:
3058
 
                    if fid is not None:
3059
 
                        self.outf.write(fid.decode('utf-8'))
 
3051
                    if getattr(entry, 'file_id', None) is not None:
 
3052
                        self.outf.write(entry.file_id.decode('utf-8'))
3060
3053
                    self.outf.write('\0')
3061
3054
                self.outf.flush()
3062
3055
            else:
3063
3056
                if show_ids:
3064
 
                    if fid is not None:
3065
 
                        my_id = fid.decode('utf-8')
 
3057
                    if getattr(entry, 'file_id', None) is not None:
 
3058
                        my_id = entry.file_id.decode('utf-8')
3066
3059
                    else:
3067
3060
                        my_id = ''
3068
3061
                    self.outf.write('%-50s %s\n' % (outstring, my_id))
3091
3084
 
3092
3085
    If a .bzrignore file does not exist, the ignore command
3093
3086
    will create one and add the specified files or patterns to the newly
3094
 
    created file. The ignore command will also automatically add the 
 
3087
    created file. The ignore command will also automatically add the
3095
3088
    .bzrignore file to be versioned. Creating a .bzrignore file without
3096
3089
    the use of the ignore command will require an explicit add command.
3097
3090
 
3099
3092
    After adding, editing or deleting that file either indirectly by
3100
3093
    using this command or directly by using an editor, be sure to commit
3101
3094
    it.
3102
 
    
3103
 
    Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows
3104
 
    the global ignore file can be found in the application data directory as
3105
 
    C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore.
 
3095
 
 
3096
    Breezy also supports a global ignore file ~/.config/breezy/ignore. On
 
3097
    Windows the global ignore file can be found in the application data
 
3098
    directory as
 
3099
    C:\\Documents and Settings\\<user>\\Application Data\\Breezy\\3.0\\ignore.
3106
3100
    Global ignores are not touched by this command. The global ignore file
3107
3101
    can be edited directly using an editor.
3108
3102
 
3109
3103
    Patterns prefixed with '!' are exceptions to ignore patterns and take
3110
3104
    precedence over regular ignores.  Such exceptions are used to specify
3111
3105
    files that should be versioned which would otherwise be ignored.
3112
 
    
 
3106
 
3113
3107
    Patterns prefixed with '!!' act as regular ignore patterns, but have
3114
3108
    precedence over the '!' exception patterns.
3115
3109
 
3116
 
    :Notes: 
3117
 
        
 
3110
    :Notes:
 
3111
 
3118
3112
    * Ignore patterns containing shell wildcards must be quoted from
3119
3113
      the shell on Unix.
3120
3114
 
3149
3143
        Ignore everything but the "debian" toplevel directory::
3150
3144
 
3151
3145
            brz ignore "RE:(?!debian/).*"
3152
 
        
 
3146
 
3153
3147
        Ignore everything except the "local" toplevel directory,
3154
3148
        but always ignore autosave files ending in ~, even under local/::
3155
 
        
 
3149
 
3156
3150
            brz ignore "*"
3157
3151
            brz ignore "!./local"
3158
3152
            brz ignore "!!*~"
3161
3155
    _see_also = ['status', 'ignored', 'patterns']
3162
3156
    takes_args = ['name_pattern*']
3163
3157
    takes_options = ['directory',
3164
 
        Option('default-rules',
3165
 
               help='Display the default ignore rules that brz uses.')
3166
 
        ]
 
3158
                     Option('default-rules',
 
3159
                            help='Display the default ignore rules that brz uses.')
 
3160
                     ]
3167
3161
 
3168
3162
    def run(self, name_pattern_list=None, default_rules=None,
3169
3163
            directory=u'.'):
3175
3169
            return
3176
3170
        if not name_pattern_list:
3177
3171
            raise errors.BzrCommandError(gettext("ignore requires at least one "
3178
 
                "NAME_PATTERN or --default-rules."))
 
3172
                                                 "NAME_PATTERN or --default-rules."))
3179
3173
        name_pattern_list = [globbing.normalize_pattern(p)
3180
3174
                             for p in name_pattern_list]
3181
3175
        bad_patterns = ''
3185
3179
                bad_patterns_count += 1
3186
3180
                bad_patterns += ('\n  %s' % p)
3187
3181
        if bad_patterns:
3188
 
            msg = (ngettext('Invalid ignore pattern found. %s', 
 
3182
            msg = (ngettext('Invalid ignore pattern found. %s',
3189
3183
                            'Invalid ignore patterns found. %s',
3190
3184
                            bad_patterns_count) % bad_patterns)
3191
3185
            ui.ui_factory.show_error(msg)
3192
3186
            raise lazy_regex.InvalidPattern('')
3193
3187
        for name_pattern in name_pattern_list:
3194
3188
            if (name_pattern[0] == '/' or
3195
 
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
 
3189
                    (len(name_pattern) > 1 and name_pattern[1] == ':')):
3196
3190
                raise errors.BzrCommandError(gettext(
3197
3191
                    "NAME_PATTERN should not be an absolute path"))
3198
3192
        tree, relpath = WorkingTree.open_containing(directory)
3200
3194
        ignored = globbing.Globster(name_pattern_list)
3201
3195
        matches = []
3202
3196
        self.add_cleanup(tree.lock_read().unlock)
3203
 
        for entry in tree.list_files():
3204
 
            id = entry[3]
 
3197
        for filename, fc, fkind, entry in tree.list_files():
 
3198
            id = getattr(entry, 'file_id', None)
3205
3199
            if id is not None:
3206
 
                filename = entry[0]
3207
3200
                if ignored.match(filename):
3208
3201
                    matches.append(filename)
3209
3202
        if len(matches) > 0:
3210
3203
            self.outf.write(gettext("Warning: the following files are version "
3211
 
                  "controlled and match your ignore pattern:\n%s"
3212
 
                  "\nThese files will continue to be version controlled"
3213
 
                  " unless you 'brz remove' them.\n") % ("\n".join(matches),))
 
3204
                                    "controlled and match your ignore pattern:\n%s"
 
3205
                                    "\nThese files will continue to be version controlled"
 
3206
                                    " unless you 'brz remove' them.\n") % ("\n".join(matches),))
3214
3207
 
3215
3208
 
3216
3209
class cmd_ignored(Command):
3232
3225
    def run(self, directory=u'.'):
3233
3226
        tree = WorkingTree.open_containing(directory)[0]
3234
3227
        self.add_cleanup(tree.lock_read().unlock)
3235
 
        for path, file_class, kind, file_id, entry in tree.list_files():
 
3228
        for path, file_class, kind, entry in tree.list_files():
3236
3229
            if file_class != 'I':
3237
3230
                continue
3238
 
            ## XXX: Slightly inefficient since this was already calculated
 
3231
            # XXX: Slightly inefficient since this was already calculated
3239
3232
            pat = tree.is_ignored(path)
3240
3233
            self.outf.write('%-50s %s\n' % (path, pat))
3241
3234
 
3257
3250
        except ValueError:
3258
3251
            raise errors.BzrCommandError(gettext("not a valid revision-number: %r")
3259
3252
                                         % revno)
3260
 
        revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
 
3253
        revid = WorkingTree.open_containing(
 
3254
            directory)[0].branch.get_rev_id(revno)
3261
3255
        self.outf.write("%s\n" % revid.decode('utf-8'))
3262
3256
 
3263
3257
 
3293
3287
    encoding_type = 'exact'
3294
3288
    takes_args = ['dest', 'branch_or_subdir?']
3295
3289
    takes_options = ['directory',
3296
 
        Option('format',
3297
 
               help="Type of file to export to.",
3298
 
               type=text_type),
3299
 
        'revision',
3300
 
        Option('filters', help='Apply content filters to export the '
3301
 
                'convenient form.'),
3302
 
        Option('root',
3303
 
               type=text_type,
3304
 
               help="Name of the root directory inside the exported file."),
3305
 
        Option('per-file-timestamps',
3306
 
               help='Set modification time of files to that of the last '
3307
 
                    'revision in which it was changed.'),
3308
 
        Option('uncommitted',
3309
 
               help='Export the working tree contents rather than that of the '
3310
 
                    'last revision.'),
3311
 
        ]
 
3290
                     Option('format',
 
3291
                            help="Type of file to export to.",
 
3292
                            type=text_type),
 
3293
                     'revision',
 
3294
                     Option('filters', help='Apply content filters to export the '
 
3295
                            'convenient form.'),
 
3296
                     Option('root',
 
3297
                            type=text_type,
 
3298
                            help="Name of the root directory inside the exported file."),
 
3299
                     Option('per-file-timestamps',
 
3300
                            help='Set modification time of files to that of the last '
 
3301
                            'revision in which it was changed.'),
 
3302
                     Option('uncommitted',
 
3303
                            help='Export the working tree contents rather than that of the '
 
3304
                            'last revision.'),
 
3305
                     ]
 
3306
 
3312
3307
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
3313
 
        root=None, filters=False, per_file_timestamps=False, uncommitted=False,
3314
 
        directory=u'.'):
 
3308
            root=None, filters=False, per_file_timestamps=False, uncommitted=False,
 
3309
            directory=u'.'):
3315
3310
        from .export import export, guess_format, get_root_name
3316
3311
 
3317
3312
        if branch_or_subdir is None:
3329
3324
            export_tree = tree
3330
3325
        else:
3331
3326
            export_tree = _get_one_revision_tree(
3332
 
                    'export', revision, branch=b,
3333
 
                    tree=tree)
 
3327
                'export', revision, branch=b,
 
3328
                tree=tree)
3334
3329
 
3335
3330
        if format is None:
3336
3331
            format = guess_format(dest)
3346
3341
        if filters:
3347
3342
            from breezy.filter_tree import ContentFilterTree
3348
3343
            export_tree = ContentFilterTree(
3349
 
                    export_tree, export_tree._content_filter_stack)
 
3344
                export_tree, export_tree._content_filter_stack)
3350
3345
 
3351
3346
        try:
3352
3347
            export(export_tree, dest, format, root, subdir,
3367
3362
 
3368
3363
    _see_also = ['ls']
3369
3364
    takes_options = ['directory',
3370
 
        Option('name-from-revision', help='The path name in the old tree.'),
3371
 
        Option('filters', help='Apply content filters to display the '
3372
 
                'convenience form.'),
3373
 
        'revision',
3374
 
        ]
 
3365
                     Option('name-from-revision',
 
3366
                            help='The path name in the old tree.'),
 
3367
                     Option('filters', help='Apply content filters to display the '
 
3368
                            'convenience form.'),
 
3369
                     'revision',
 
3370
                     ]
3375
3371
    takes_args = ['filename']
3376
3372
    encoding_type = 'exact'
3377
3373
 
3380
3376
            filters=False, directory=None):
3381
3377
        if revision is not None and len(revision) != 1:
3382
3378
            raise errors.BzrCommandError(gettext("brz cat --revision takes exactly"
3383
 
                                         " one revision specifier"))
 
3379
                                                 " one revision specifier"))
3384
3380
        tree, branch, relpath = \
3385
3381
            _open_directory_or_containing_tree_or_branch(filename, directory)
3386
3382
        self.add_cleanup(branch.lock_read().unlock)
3388
3384
                         name_from_revision, filters)
3389
3385
 
3390
3386
    def _run(self, tree, b, relpath, filename, revision, name_from_revision,
3391
 
        filtered):
 
3387
             filtered):
3392
3388
        import shutil
3393
3389
        if tree is None:
3394
3390
            tree = b.basis_tree()
3395
3391
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3396
3392
        self.add_cleanup(rev_tree.lock_read().unlock)
3397
3393
 
3398
 
        old_file_id = rev_tree.path2id(relpath)
3399
 
 
3400
 
        # TODO: Split out this code to something that generically finds the
3401
 
        # best id for a path across one or more trees; it's like
3402
 
        # find_ids_across_trees but restricted to find just one. -- mbp
3403
 
        # 20110705.
3404
3394
        if name_from_revision:
3405
3395
            # Try in revision if requested
3406
 
            if old_file_id is None:
 
3396
            if not rev_tree.is_versioned(relpath):
3407
3397
                raise errors.BzrCommandError(gettext(
3408
3398
                    "{0!r} is not present in revision {1}").format(
3409
3399
                        filename, rev_tree.get_revision_id()))
3410
 
            else:
3411
 
                actual_file_id = old_file_id
 
3400
            rev_tree_path = relpath
3412
3401
        else:
3413
 
            cur_file_id = tree.path2id(relpath)
3414
 
            if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3415
 
                actual_file_id = cur_file_id
3416
 
            elif old_file_id is not None:
3417
 
                actual_file_id = old_file_id
3418
 
            else:
3419
 
                raise errors.BzrCommandError(gettext(
3420
 
                    "{0!r} is not present in revision {1}").format(
3421
 
                        filename, rev_tree.get_revision_id()))
3422
 
        relpath = rev_tree.id2path(actual_file_id)
 
3402
            try:
 
3403
                rev_tree_path = _mod_tree.find_previous_path(
 
3404
                    tree, rev_tree, relpath)
 
3405
            except errors.NoSuchFile:
 
3406
                rev_tree_path = None
 
3407
 
 
3408
            if rev_tree_path is None:
 
3409
                # Path didn't exist in working tree
 
3410
                if not rev_tree.is_versioned(relpath):
 
3411
                    raise errors.BzrCommandError(gettext(
 
3412
                        "{0!r} is not present in revision {1}").format(
 
3413
                            filename, rev_tree.get_revision_id()))
 
3414
                else:
 
3415
                    # Fall back to the same path in the basis tree, if present.
 
3416
                    rev_tree_path = relpath
 
3417
 
3423
3418
        if filtered:
3424
3419
            from .filter_tree import ContentFilterTree
3425
 
            filter_tree = ContentFilterTree(rev_tree,
3426
 
                rev_tree._content_filter_stack)
3427
 
            fileobj = filter_tree.get_file(relpath, actual_file_id)
 
3420
            filter_tree = ContentFilterTree(
 
3421
                rev_tree, rev_tree._content_filter_stack)
 
3422
            fileobj = filter_tree.get_file(rev_tree_path)
3428
3423
        else:
3429
 
            fileobj = rev_tree.get_file(relpath, actual_file_id)
 
3424
            fileobj = rev_tree.get_file(rev_tree_path)
3430
3425
        shutil.copyfileobj(fileobj, self.outf)
3431
3426
        self.cleanup_now()
3432
3427
 
3434
3429
class cmd_local_time_offset(Command):
3435
3430
    __doc__ = """Show the offset in seconds from GMT to local time."""
3436
3431
    hidden = True
 
3432
 
3437
3433
    @display_command
3438
3434
    def run(self):
3439
3435
        self.outf.write("%s\n" % osutils.local_time_offset())
3440
3436
 
3441
3437
 
3442
 
 
3443
3438
class cmd_commit(Command):
3444
3439
    __doc__ = """Commit changes into a new revision.
3445
3440
 
3459
3454
      If selected files are specified, only changes to those files are
3460
3455
      committed.  If a directory is specified then the directory and
3461
3456
      everything within it is committed.
3462
 
  
 
3457
 
3463
3458
      When excludes are given, they take precedence over selected files.
3464
3459
      For example, to commit only changes within foo, but not changes
3465
3460
      within foo/bar::
3466
 
  
 
3461
 
3467
3462
        brz commit foo -x foo/bar
3468
 
  
 
3463
 
3469
3464
      A selective commit after a merge is not yet supported.
3470
3465
 
3471
3466
    :Custom authors:
3476
3471
      "John Doe <jdoe@example.com>". If there is more than one author of
3477
3472
      the change you can specify the option multiple times, once for each
3478
3473
      author.
3479
 
  
 
3474
 
3480
3475
    :Checks:
3481
3476
 
3482
3477
      A common mistake is to forget to add a new file or directory before
3487
3482
 
3488
3483
    :Things to note:
3489
3484
 
3490
 
      If you accidentially commit the wrong changes or make a spelling
 
3485
      If you accidentally commit the wrong changes or make a spelling
3491
3486
      mistake in the commit message say, you can use the uncommit command
3492
3487
      to undo it. See ``brz help uncommit`` for details.
3493
3488
 
3500
3495
    _see_also = ['add', 'bugs', 'hooks', 'uncommit']
3501
3496
    takes_args = ['selected*']
3502
3497
    takes_options = [
3503
 
            ListOption('exclude', type=text_type, short_name='x',
3504
 
                help="Do not consider changes made to a given path."),
3505
 
            Option('message', type=text_type,
3506
 
                   short_name='m',
3507
 
                   help="Description of the new revision."),
3508
 
            'verbose',
3509
 
             Option('unchanged',
3510
 
                    help='Commit even if nothing has changed.'),
3511
 
             Option('file', type=text_type,
3512
 
                    short_name='F',
3513
 
                    argname='msgfile',
3514
 
                    help='Take commit message from this file.'),
3515
 
             Option('strict',
3516
 
                    help="Refuse to commit if there are unknown "
3517
 
                    "files in the working tree."),
3518
 
             Option('commit-time', type=text_type,
3519
 
                    help="Manually set a commit time using commit date "
3520
 
                    "format, e.g. '2009-10-10 08:00:00 +0100'."),
3521
 
             ListOption('fixes', type=text_type,
3522
 
                    help="Mark a bug as being fixed by this revision "
3523
 
                         "(see \"brz help bugs\")."),
3524
 
             ListOption('author', type=text_type,
3525
 
                    help="Set the author's name, if it's different "
3526
 
                         "from the committer."),
3527
 
             Option('local',
3528
 
                    help="Perform a local commit in a bound "
3529
 
                         "branch.  Local commits are not pushed to "
3530
 
                         "the master branch until a normal commit "
3531
 
                         "is performed."
3532
 
                    ),
3533
 
             Option('show-diff', short_name='p',
3534
 
                    help='When no message is supplied, show the diff along'
3535
 
                    ' with the status summary in the message editor.'),
3536
 
             Option('lossy', 
3537
 
                    help='When committing to a foreign version control '
3538
 
                    'system do not push data that can not be natively '
3539
 
                    'represented.'),
3540
 
             ]
 
3498
        ListOption(
 
3499
            'exclude', type=text_type, short_name='x',
 
3500
            help="Do not consider changes made to a given path."),
 
3501
        Option('message', type=text_type,
 
3502
               short_name='m',
 
3503
               help="Description of the new revision."),
 
3504
        'verbose',
 
3505
        Option('unchanged',
 
3506
               help='Commit even if nothing has changed.'),
 
3507
        Option('file', type=text_type,
 
3508
               short_name='F',
 
3509
               argname='msgfile',
 
3510
               help='Take commit message from this file.'),
 
3511
        Option('strict',
 
3512
               help="Refuse to commit if there are unknown "
 
3513
               "files in the working tree."),
 
3514
        Option('commit-time', type=text_type,
 
3515
               help="Manually set a commit time using commit date "
 
3516
               "format, e.g. '2009-10-10 08:00:00 +0100'."),
 
3517
        ListOption(
 
3518
            'bugs', type=text_type,
 
3519
            help="Link to a related bug. (see \"brz help bugs\")."),
 
3520
        ListOption(
 
3521
            'fixes', type=text_type,
 
3522
            help="Mark a bug as being fixed by this revision "
 
3523
                 "(see \"brz help bugs\")."),
 
3524
        ListOption(
 
3525
            'author', type=text_type,
 
3526
            help="Set the author's name, if it's different "
 
3527
                 "from the committer."),
 
3528
        Option('local',
 
3529
               help="Perform a local commit in a bound "
 
3530
                    "branch.  Local commits are not pushed to "
 
3531
                    "the master branch until a normal commit "
 
3532
                    "is performed."
 
3533
               ),
 
3534
        Option('show-diff', short_name='p',
 
3535
               help='When no message is supplied, show the diff along'
 
3536
               ' with the status summary in the message editor.'),
 
3537
        Option('lossy',
 
3538
               help='When committing to a foreign version control '
 
3539
               'system do not push data that can not be natively '
 
3540
               'represented.'), ]
3541
3541
    aliases = ['ci', 'checkin']
3542
3542
 
3543
 
    def _iter_bug_fix_urls(self, fixes, branch):
3544
 
        default_bugtracker  = None
 
3543
    def _iter_bug_urls(self, bugs, branch, status):
 
3544
        default_bugtracker = None
3545
3545
        # Configure the properties for bug fixing attributes.
3546
 
        for fixed_bug in fixes:
3547
 
            tokens = fixed_bug.split(':')
 
3546
        for bug in bugs:
 
3547
            tokens = bug.split(':')
3548
3548
            if len(tokens) == 1:
3549
3549
                if default_bugtracker is None:
3550
3550
                    branch_config = branch.get_config_stack()
3556
3556
                        "'tracker:id' or specify a default bug tracker "
3557
3557
                        "using the `bugtracker` option.\nSee "
3558
3558
                        "\"brz help bugs\" for more information on this "
3559
 
                        "feature. Commit refused.") % fixed_bug)
 
3559
                        "feature. Commit refused.") % bug)
3560
3560
                tag = default_bugtracker
3561
3561
                bug_id = tokens[0]
3562
3562
            elif len(tokens) != 2:
3563
3563
                raise errors.BzrCommandError(gettext(
3564
3564
                    "Invalid bug %s. Must be in the form of 'tracker:id'. "
3565
3565
                    "See \"brz help bugs\" for more information on this "
3566
 
                    "feature.\nCommit refused.") % fixed_bug)
 
3566
                    "feature.\nCommit refused.") % bug)
3567
3567
            else:
3568
3568
                tag, bug_id = tokens
3569
3569
            try:
3570
 
                yield bugtracker.get_bug_url(tag, branch, bug_id)
 
3570
                yield bugtracker.get_bug_url(tag, branch, bug_id), status
3571
3571
            except bugtracker.UnknownBugTrackerAbbreviation:
3572
3572
                raise errors.BzrCommandError(gettext(
3573
 
                    'Unrecognized bug %s. Commit refused.') % fixed_bug)
 
3573
                    'Unrecognized bug %s. Commit refused.') % bug)
3574
3574
            except bugtracker.MalformedBugIdentifier as e:
3575
3575
                raise errors.BzrCommandError(gettext(
3576
3576
                    u"%s\nCommit refused.") % (e,))
3577
3577
 
3578
3578
    def run(self, message=None, file=None, verbose=False, selected_list=None,
3579
 
            unchanged=False, strict=False, local=False, fixes=None,
 
3579
            unchanged=False, strict=False, local=False, fixes=None, bugs=None,
3580
3580
            author=None, show_diff=False, exclude=None, commit_time=None,
3581
3581
            lossy=False):
 
3582
        import itertools
3582
3583
        from .commit import (
3583
3584
            PointlessCommit,
3584
3585
            )
3612
3613
 
3613
3614
        if fixes is None:
3614
3615
            fixes = []
 
3616
        if bugs is None:
 
3617
            bugs = []
3615
3618
        bug_property = bugtracker.encode_fixes_bug_urls(
3616
 
            self._iter_bug_fix_urls(fixes, tree.branch))
 
3619
            itertools.chain(
 
3620
                self._iter_bug_urls(bugs, tree.branch, bugtracker.RELATED),
 
3621
                self._iter_bug_urls(fixes, tree.branch, bugtracker.FIXED)))
3617
3622
        if bug_property:
3618
3623
            properties[u'bugs'] = bug_property
3619
3624
 
3632
3637
                warning_msg = (
3633
3638
                    'The commit message is a file name: "%(f)s".\n'
3634
3639
                    '(use --file "%(f)s" to take commit message from that file)'
3635
 
                    % { 'f': message })
 
3640
                    % {'f': message})
3636
3641
                ui.ui_factory.show_warning(warning_msg)
3637
3642
            if '\r' in message:
3638
3643
                message = message.replace('\r\n', '\n')
3652
3657
                # No message supplied: make one up.
3653
3658
                # text is the status of the tree
3654
3659
                text = make_commit_message_template_encoded(tree,
3655
 
                        selected_list, diff=show_diff,
3656
 
                        output_encoding=osutils.get_user_encoding())
 
3660
                                                            selected_list, diff=show_diff,
 
3661
                                                            output_encoding=osutils.get_user_encoding())
3657
3662
                # start_message is the template generated from hooks
3658
3663
                # XXX: Warning - looks like hooks return unicode,
3659
3664
                # make_commit_message_template_encoded returns user encoding.
3661
3666
                # avoid this.
3662
3667
                my_message = set_commit_message(commit_obj)
3663
3668
                if my_message is None:
3664
 
                    start_message = generate_commit_message_template(commit_obj)
 
3669
                    start_message = generate_commit_message_template(
 
3670
                        commit_obj)
3665
3671
                    if start_message is not None:
3666
3672
                        start_message = start_message.encode(
3667
 
                                osutils.get_user_encoding())
 
3673
                            osutils.get_user_encoding())
3668
3674
                    my_message = edit_commit_message_encoded(text,
3669
 
                        start_message=start_message)
 
3675
                                                             start_message=start_message)
3670
3676
                if my_message is None:
3671
3677
                    raise errors.BzrCommandError(gettext("please specify a commit"
3672
 
                        " message with either --message or --file"))
 
3678
                                                         " message with either --message or --file"))
3673
3679
                if my_message == "":
3674
3680
                    raise errors.BzrCommandError(gettext("Empty commit message specified."
3675
 
                            " Please specify a commit message with either"
3676
 
                            " --message or --file or leave a blank message"
3677
 
                            " with --message \"\"."))
 
3681
                                                         " Please specify a commit message with either"
 
3682
                                                         " --message or --file or leave a blank message"
 
3683
                                                         " with --message \"\"."))
3678
3684
            return my_message
3679
3685
 
3680
3686
        # The API permits a commit with a filter of [] to mean 'select nothing'
3692
3698
                        lossy=lossy)
3693
3699
        except PointlessCommit:
3694
3700
            raise errors.BzrCommandError(gettext("No changes to commit."
3695
 
                " Please 'brz add' the files you want to commit, or use"
3696
 
                " --unchanged to force an empty commit."))
 
3701
                                                 " Please 'brz add' the files you want to commit, or use"
 
3702
                                                 " --unchanged to force an empty commit."))
3697
3703
        except ConflictsInTree:
3698
3704
            raise errors.BzrCommandError(gettext('Conflicts detected in working '
3699
 
                'tree.  Use "brz conflicts" to list, "brz resolve FILE" to'
3700
 
                ' resolve.'))
 
3705
                                                 'tree.  Use "brz conflicts" to list, "brz resolve FILE" to'
 
3706
                                                 ' resolve.'))
3701
3707
        except StrictCommitFailed:
3702
3708
            raise errors.BzrCommandError(gettext("Commit refused because there are"
3703
 
                              " unknown files in the working tree."))
 
3709
                                                 " unknown files in the working tree."))
3704
3710
        except errors.BoundBranchOutOfDate as e:
3705
3711
            e.extra_help = (gettext("\n"
3706
 
                'To commit to master branch, run update and then commit.\n'
3707
 
                'You can also pass --local to commit to continue working '
3708
 
                'disconnected.'))
 
3712
                                    'To commit to master branch, run update and then commit.\n'
 
3713
                                    'You can also pass --local to commit to continue working '
 
3714
                                    'disconnected.'))
3709
3715
            raise
3710
3716
 
3711
3717
 
3729
3735
    unreferenced ancestors
3730
3736
        Texts that are ancestors of other texts, but
3731
3737
        are not properly referenced by the revision ancestry.  This is a
3732
 
        subtle problem that Bazaar can work around.
 
3738
        subtle problem that Breezy can work around.
3733
3739
 
3734
3740
    unique file texts
3735
3741
        This is the total number of unique file contents
3741
3747
        entries are modified, but the file contents are not.  It does not
3742
3748
        indicate a problem.
3743
3749
 
3744
 
    If no restrictions are specified, all Bazaar data that is found at the given
 
3750
    If no restrictions are specified, all data that is found at the given
3745
3751
    location will be checked.
3746
3752
 
3747
3753
    :Examples:
3783
3789
    __doc__ = """Upgrade a repository, branch or working tree to a newer format.
3784
3790
 
3785
3791
    When the default format has changed after a major new release of
3786
 
    Bazaar, you may be informed during certain operations that you
 
3792
    Bazaar/Breezy, you may be informed during certain operations that you
3787
3793
    should upgrade. Upgrading to a newer format may improve performance
3788
3794
    or make new features available. It may however limit interoperability
3789
 
    with older repositories or with older versions of Bazaar.
 
3795
    with older repositories or with older versions of Bazaar or Breezy.
3790
3796
 
3791
3797
    If you wish to upgrade to a particular format rather than the
3792
3798
    current default, that can be specified using the --format option.
3808
3814
    If the conversion of a branch fails, remaining branches are still
3809
3815
    tried.
3810
3816
 
3811
 
    For more information on upgrades, see the Bazaar Upgrade Guide,
3812
 
    http://doc.bazaar.canonical.com/latest/en/upgrade-guide/.
 
3817
    For more information on upgrades, see the Breezy Upgrade Guide,
 
3818
    https://www.breezy-vcs.org/doc/en/upgrade-guide/.
3813
3819
    """
3814
3820
 
3815
3821
    _see_also = ['check', 'reconcile', 'formats']
3816
3822
    takes_args = ['url?']
3817
3823
    takes_options = [
3818
3824
        RegistryOption('format',
3819
 
            help='Upgrade to a specific format.  See "brz help'
3820
 
                 ' formats" for details.',
3821
 
            lazy_registry=('breezy.controldir', 'format_registry'),
3822
 
            converter=lambda name: controldir.format_registry.make_controldir(name),
3823
 
            value_switches=True, title='Branch format'),
 
3825
                       help='Upgrade to a specific format.  See "brz help'
 
3826
                       ' formats" for details.',
 
3827
                       lazy_registry=('breezy.controldir', 'format_registry'),
 
3828
                       converter=lambda name: controldir.format_registry.make_controldir(
 
3829
                           name),
 
3830
                       value_switches=True, title='Branch format'),
3824
3831
        Option('clean',
3825
 
            help='Remove the backup.bzr directory if successful.'),
 
3832
               help='Remove the backup.bzr directory if successful.'),
3826
3833
        Option('dry-run',
3827
 
            help="Show what would be done, but don't actually do anything."),
 
3834
               help="Show what would be done, but don't actually do anything."),
3828
3835
    ]
3829
3836
 
3830
3837
    def run(self, url='.', format=None, clean=False, dry_run=False):
3850
3857
 
3851
3858
            brz whoami "Frank Chu <fchu@example.com>"
3852
3859
    """
3853
 
    takes_options = [ 'directory',
3854
 
                      Option('email',
3855
 
                             help='Display email address only.'),
3856
 
                      Option('branch',
3857
 
                             help='Set identity for the current branch instead of '
3858
 
                                  'globally.'),
3859
 
                    ]
 
3860
    takes_options = ['directory',
 
3861
                     Option('email',
 
3862
                            help='Display email address only.'),
 
3863
                     Option('branch',
 
3864
                            help='Set identity for the current branch instead of '
 
3865
                            'globally.'),
 
3866
                     ]
3860
3867
    takes_args = ['name?']
3861
3868
    encoding_type = 'replace'
3862
3869
 
3881
3888
 
3882
3889
        if email:
3883
3890
            raise errors.BzrCommandError(gettext("--email can only be used to display existing "
3884
 
                                         "identity"))
 
3891
                                                 "identity"))
3885
3892
 
3886
3893
        # display a warning if an email address isn't included in the given name.
3887
3894
        try:
3888
3895
            _mod_config.extract_email_address(name)
3889
 
        except _mod_config.NoEmailInUsername as e:
 
3896
        except _mod_config.NoEmailInUsername:
3890
3897
            warning('"%s" does not seem to contain an email address.  '
3891
3898
                    'This is allowed, but not recommended.', name)
3892
3899
 
3917
3924
    _see_also = ['info']
3918
3925
    takes_args = ['nickname?']
3919
3926
    takes_options = ['directory']
 
3927
 
3920
3928
    def run(self, nickname=None, directory=u'.'):
3921
3929
        branch = Branch.open_containing(directory)[0]
3922
3930
        if nickname is None:
3965
3973
            if equal_pos == -1:
3966
3974
                self.print_alias(name)
3967
3975
            else:
3968
 
                self.set_alias(name[:equal_pos], name[equal_pos+1:])
 
3976
                self.set_alias(name[:equal_pos], name[equal_pos + 1:])
3969
3977
 
3970
3978
    def remove_alias(self, alias_name):
3971
3979
        if alias_name is None:
4050
4058
    """
4051
4059
    # NB: this is used from the class without creating an instance, which is
4052
4060
    # why it does not have a self parameter.
 
4061
 
4053
4062
    def get_transport_type(typestring):
4054
4063
        """Parse and return a transport specifier."""
4055
4064
        if typestring == "sftp":
4069
4078
    takes_args = ['testspecs*']
4070
4079
    takes_options = ['verbose',
4071
4080
                     Option('one',
4072
 
                             help='Stop when one test fails.',
4073
 
                             short_name='1',
4074
 
                             ),
 
4081
                            help='Stop when one test fails.',
 
4082
                            short_name='1',
 
4083
                            ),
4075
4084
                     Option('transport',
4076
4085
                            help='Use a different transport by default '
4077
4086
                                 'throughout the test suite.',
4091
4100
                     Option('list-only',
4092
4101
                            help='List the tests instead of running them.'),
4093
4102
                     RegistryOption('parallel',
4094
 
                        help="Run the test suite in parallel.",
4095
 
                        lazy_registry=('breezy.tests', 'parallel_registry'),
4096
 
                        value_switches=False,
4097
 
                        ),
 
4103
                                    help="Run the test suite in parallel.",
 
4104
                                    lazy_registry=(
 
4105
                                        'breezy.tests', 'parallel_registry'),
 
4106
                                    value_switches=False,
 
4107
                                    ),
4098
4108
                     Option('randomize', type=text_type, argname="SEED",
4099
4109
                            help='Randomize the order of tests using the given'
4100
4110
                                 ' seed or "now" for the current time.'),
4114
4124
                                help='Turn on a selftest debug flag.'),
4115
4125
                     ListOption('starting-with', type=text_type, argname='TESTID',
4116
4126
                                param_name='starting_with', short_name='s',
4117
 
                                help=
4118
 
                                'Load only the tests starting with TESTID.'),
 
4127
                                help='Load only the tests starting with TESTID.'),
4119
4128
                     Option('sync',
4120
4129
                            help="By default we disable fsync and fdatasync"
4121
4130
                                 " while running the test suite.")
4149
4158
            from . import tests
4150
4159
        except ImportError:
4151
4160
            raise errors.BzrCommandError("tests not available. Install the "
4152
 
                "breezy tests to run the breezy testsuite.")
 
4161
                                         "breezy tests to run the breezy testsuite.")
4153
4162
 
4154
4163
        if testspecs_list is not None:
4155
4164
            pattern = '|'.join(testspecs_list)
4164
4173
                    "to use --subunit."))
4165
4174
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunnerv1
4166
4175
            # On Windows, disable automatic conversion of '\n' to '\r\n' in
4167
 
            # stdout, which would corrupt the subunit stream. 
 
4176
            # stdout, which would corrupt the subunit stream.
4168
4177
            # FIXME: This has been fixed in subunit trunk (>0.0.5) so the
4169
4178
            # following code can be deleted when it's sufficiently deployed
4170
4179
            # -- vila/mgz 20100514
4171
4180
            if (sys.platform == "win32"
4172
 
                and getattr(sys.stdout, 'fileno', None) is not None):
 
4181
                    and getattr(sys.stdout, 'fileno', None) is not None):
4173
4182
                import msvcrt
4174
4183
                msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
4175
4184
        if subunit2:
4196
4205
        if not sync:
4197
4206
            self._disable_fsync()
4198
4207
        selftest_kwargs = {"verbose": verbose,
4199
 
                          "pattern": pattern,
4200
 
                          "stop_on_failure": one,
4201
 
                          "transport": transport,
4202
 
                          "test_suite_factory": test_suite_factory,
4203
 
                          "lsprof_timed": lsprof_timed,
4204
 
                          "lsprof_tests": lsprof_tests,
4205
 
                          "matching_tests_first": first,
4206
 
                          "list_only": list_only,
4207
 
                          "random_seed": randomize,
4208
 
                          "exclude_pattern": exclude_pattern,
4209
 
                          "strict": strict,
4210
 
                          "load_list": load_list,
4211
 
                          "debug_flags": debugflag,
4212
 
                          "starting_with": starting_with
4213
 
                          }
 
4208
                           "pattern": pattern,
 
4209
                           "stop_on_failure": one,
 
4210
                           "transport": transport,
 
4211
                           "test_suite_factory": test_suite_factory,
 
4212
                           "lsprof_timed": lsprof_timed,
 
4213
                           "lsprof_tests": lsprof_tests,
 
4214
                           "matching_tests_first": first,
 
4215
                           "list_only": list_only,
 
4216
                           "random_seed": randomize,
 
4217
                           "exclude_pattern": exclude_pattern,
 
4218
                           "strict": strict,
 
4219
                           "load_list": load_list,
 
4220
                           "debug_flags": debugflag,
 
4221
                           "starting_with": starting_with
 
4222
                           }
4214
4223
        selftest_kwargs.update(self.additional_selftest_args)
4215
4224
 
4216
4225
        # Make deprecation warnings visible, unless -Werror is set
4281
4290
        base_rev_id = graph.find_unique_lca(last1, last2)
4282
4291
 
4283
4292
        self.outf.write(gettext('merge base is revision %s\n') %
4284
 
                base_rev_id.decode('utf-8'))
 
4293
                        base_rev_id.decode('utf-8'))
4285
4294
 
4286
4295
 
4287
4296
class cmd_merge(Command):
4306
4315
    through OTHER, excluding BASE but including OTHER, will be merged.  If this
4307
4316
    causes some revisions to be skipped, i.e. if the destination branch does
4308
4317
    not already contain revision BASE, such a merge is commonly referred to as
4309
 
    a "cherrypick". Unlike a normal merge, Bazaar does not currently track
 
4318
    a "cherrypick". Unlike a normal merge, Breezy does not currently track
4310
4319
    cherrypicks. The changes look like a normal commit, and the history of the
4311
4320
    changes from the other branch is not stored in the commit.
4312
4321
 
4382
4391
        Option('uncommitted', help='Apply uncommitted changes'
4383
4392
               ' from a working copy, instead of branch changes.'),
4384
4393
        Option('pull', help='If the destination is already'
4385
 
                ' completely merged into the source, pull from the'
4386
 
                ' source rather than merging.  When this happens,'
4387
 
                ' you do not need to commit the result.'),
 
4394
               ' completely merged into the source, pull from the'
 
4395
               ' source rather than merging.  When this happens,'
 
4396
               ' you do not need to commit the result.'),
4388
4397
        custom_help('directory',
4389
 
               help='Branch to merge into, '
 
4398
                    help='Branch to merge into, '
4390
4399
                    'rather than the one containing the working directory.'),
4391
4400
        Option('preview', help='Instead of merging, show a diff of the'
4392
4401
               ' merge.'),
4393
4402
        Option('interactive', help='Select changes interactively.',
4394
 
            short_name='i')
 
4403
               short_name='i')
4395
4404
    ]
4396
4405
 
4397
4406
    def run(self, location=None, revision=None, force=False,
4404
4413
        if merge_type is None:
4405
4414
            merge_type = _mod_merge.Merge3Merger
4406
4415
 
4407
 
        if directory is None: directory = u'.'
 
4416
        if directory is None:
 
4417
            directory = u'.'
4408
4418
        possible_transports = []
4409
4419
        merger = None
4410
4420
        allow_pending = True
4411
4421
        verified = 'inapplicable'
4412
4422
 
4413
4423
        tree = WorkingTree.open_containing(directory)[0]
4414
 
        if tree.branch.revno() == 0:
 
4424
        if tree.branch.last_revision() == _mod_revision.NULL_REVISION:
4415
4425
            raise errors.BzrCommandError(gettext('Merging into empty branches not currently supported, '
4416
 
                                         'https://bugs.launchpad.net/bzr/+bug/308562'))
 
4426
                                                 'https://bugs.launchpad.net/bzr/+bug/308562'))
4417
4427
 
4418
4428
        # die as quickly as possible if there are uncommitted changes
4419
4429
        if not force:
4429
4439
        if location is not None:
4430
4440
            try:
4431
4441
                mergeable = bundle.read_mergeable_from_url(location,
4432
 
                    possible_transports=possible_transports)
 
4442
                                                           possible_transports=possible_transports)
4433
4443
            except errors.NotABundle:
4434
4444
                mergeable = None
4435
4445
            else:
4436
4446
                if uncommitted:
4437
4447
                    raise errors.BzrCommandError(gettext('Cannot use --uncommitted'
4438
 
                        ' with bundles or merge directives.'))
 
4448
                                                         ' with bundles or merge directives.'))
4439
4449
 
4440
4450
                if revision is not None:
4441
4451
                    raise errors.BzrCommandError(gettext(
4442
4452
                        'Cannot use -r with merge directives or bundles'))
4443
4453
                merger, verified = _mod_merge.Merger.from_mergeable(tree,
4444
 
                   mergeable)
 
4454
                                                                    mergeable)
4445
4455
 
4446
4456
        if merger is None and uncommitted:
4447
4457
            if revision is not None and len(revision) > 0:
4448
4458
                raise errors.BzrCommandError(gettext('Cannot use --uncommitted and'
4449
 
                    ' --revision at the same time.'))
 
4459
                                                     ' --revision at the same time.'))
4450
4460
            merger = self.get_merger_from_uncommitted(tree, location, None)
4451
4461
            allow_pending = False
4452
4462
 
4453
4463
        if merger is None:
4454
4464
            merger, allow_pending = self._get_merger_from_branch(tree,
4455
 
                location, revision, remember, possible_transports, None)
 
4465
                                                                 location, revision, remember, possible_transports, None)
4456
4466
 
4457
4467
        merger.merge_type = merge_type
4458
4468
        merger.reprocess = reprocess
4459
4469
        merger.show_base = show_base
4460
4470
        self.sanity_check_merger(merger)
4461
4471
        if (merger.base_rev_id == merger.other_rev_id and
4462
 
            merger.other_rev_id is not None):
 
4472
                merger.other_rev_id is not None):
4463
4473
            # check if location is a nonexistent file (and not a branch) to
4464
4474
            # disambiguate the 'Nothing to do'
4465
4475
            if merger.interesting_files:
4466
4476
                if not merger.other_tree.has_filename(
4467
 
                    merger.interesting_files[0]):
 
4477
                        merger.interesting_files[0]):
4468
4478
                    note(gettext("merger: ") + str(merger))
4469
4479
                    raise errors.PathsDoNotExist([location])
4470
4480
            note(gettext('Nothing to do.'))
4471
4481
            return 0
4472
4482
        if pull and not preview:
4473
4483
            if merger.interesting_files is not None:
4474
 
                raise errors.BzrCommandError(gettext('Cannot pull individual files'))
 
4484
                raise errors.BzrCommandError(
 
4485
                    gettext('Cannot pull individual files'))
4475
4486
            if (merger.base_rev_id == tree.last_revision()):
4476
4487
                result = tree.pull(merger.other_branch, False,
4477
4488
                                   merger.other_rev_id)
4536
4547
 
4537
4548
    def sanity_check_merger(self, merger):
4538
4549
        if (merger.show_base and
4539
 
            not merger.merge_type is _mod_merge.Merge3Merger):
 
4550
                merger.merge_type is not _mod_merge.Merge3Merger):
4540
4551
            raise errors.BzrCommandError(gettext("Show-base is not supported for this"
4541
 
                                         " merge type. %s") % merger.merge_type)
 
4552
                                                 " merge type. %s") % merger.merge_type)
4542
4553
        if merger.reprocess is None:
4543
4554
            if merger.show_base:
4544
4555
                merger.reprocess = False
4547
4558
                merger.reprocess = merger.merge_type.supports_reprocess
4548
4559
        if merger.reprocess and not merger.merge_type.supports_reprocess:
4549
4560
            raise errors.BzrCommandError(gettext("Conflict reduction is not supported"
4550
 
                                         " for merge type %s.") %
 
4561
                                                 " for merge type %s.") %
4551
4562
                                         merger.merge_type)
4552
4563
        if merger.reprocess and merger.show_base:
4553
4564
            raise errors.BzrCommandError(gettext("Cannot do conflict reduction and"
4554
 
                                         " show base."))
 
4565
                                                 " show base."))
4555
4566
 
4556
4567
        if (merger.merge_type.requires_file_merge_plan and
4557
4568
            (not getattr(merger.this_tree, 'plan_file_merge', None) or
4559
4570
             (merger.base_tree is not None and
4560
4571
                 not getattr(merger.base_tree, 'plan_file_merge', None)))):
4561
4572
            raise errors.BzrCommandError(
4562
 
                 gettext('Plan file merge unsupported: '
4563
 
                         'Merge type incompatible with tree formats.'))
 
4573
                gettext('Plan file merge unsupported: '
 
4574
                        'Merge type incompatible with tree formats.'))
4564
4575
 
4565
4576
    def _get_merger_from_branch(self, tree, location, revision, remember,
4566
4577
                                possible_transports, pb):
4567
4578
        """Produce a merger from a location, assuming it refers to a branch."""
4568
4579
        # find the branch locations
4569
4580
        other_loc, user_location = self._select_branch_location(tree, location,
4570
 
            revision, -1)
 
4581
                                                                revision, -1)
4571
4582
        if revision is not None and len(revision) == 2:
4572
4583
            base_loc, _unused = self._select_branch_location(tree,
4573
 
                location, revision, 0)
 
4584
                                                             location, revision, 0)
4574
4585
        else:
4575
4586
            base_loc = other_loc
4576
4587
        # Open the branches
4577
4588
        other_branch, other_path = Branch.open_containing(other_loc,
4578
 
            possible_transports)
 
4589
                                                          possible_transports)
4579
4590
        if base_loc == other_loc:
4580
4591
            base_branch = other_branch
4581
4592
        else:
4582
4593
            base_branch, base_path = Branch.open_containing(base_loc,
4583
 
                possible_transports)
 
4594
                                                            possible_transports)
4584
4595
        # Find the revision ids
4585
4596
        other_revision_id = None
4586
4597
        base_revision_id = None
4598
4609
        # - user ask to remember or there is no previous location set to merge
4599
4610
        #   from and user didn't ask to *not* remember
4600
4611
        if (user_location is not None
4601
 
            and ((remember
4602
 
                  or (remember is None
4603
 
                      and tree.branch.get_submit_branch() is None)))):
 
4612
            and ((remember or
 
4613
                 (remember is None and
 
4614
                  tree.branch.get_submit_branch() is None)))):
4604
4615
            tree.branch.set_submit_branch(other_branch.base)
4605
4616
        # Merge tags (but don't set them in the master branch yet, the user
4606
4617
        # might revert this merge).  Commit will propagate them.
4607
4618
        other_branch.tags.merge_to(tree.branch.tags, ignore_master=True)
4608
4619
        merger = _mod_merge.Merger.from_revision_ids(tree,
4609
 
            other_revision_id, base_revision_id, other_branch, base_branch)
 
4620
                                                     other_revision_id, base_revision_id, other_branch, base_branch)
4610
4621
        if other_path != '':
4611
4622
            allow_pending = False
4612
4623
            merger.interesting_files = [other_path]
4647
4658
            will be the user-entered location.
4648
4659
        """
4649
4660
        if (revision is not None and index is not None
4650
 
            and revision[index] is not None):
 
4661
                and revision[index] is not None):
4651
4662
            branch = revision[index].get_branch()
4652
4663
            if branch is not None:
4653
4664
                return branch, branch
4669
4680
            stored_location_type = "parent"
4670
4681
        mutter("%s", stored_location)
4671
4682
        if stored_location is None:
4672
 
            raise errors.BzrCommandError(gettext("No location specified or remembered"))
 
4683
            raise errors.BzrCommandError(
 
4684
                gettext("No location specified or remembered"))
4673
4685
        display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
4674
4686
        note(gettext("{0} remembered {1} location {2}").format(verb_string,
4675
 
                stored_location_type, display_url))
 
4687
                                                               stored_location_type, display_url))
4676
4688
        return stored_location
4677
4689
 
4678
4690
 
4700
4712
    """
4701
4713
    takes_args = ['file*']
4702
4714
    takes_options = [
4703
 
            'merge-type',
4704
 
            'reprocess',
4705
 
            Option('show-base',
4706
 
                   help="Show base revision text in conflicts."),
4707
 
            ]
 
4715
        'merge-type',
 
4716
        'reprocess',
 
4717
        Option('show-base',
 
4718
               help="Show base revision text in conflicts."),
 
4719
        ]
4708
4720
 
4709
4721
    def run(self, file_list=None, merge_type=None, show_base=False,
4710
4722
            reprocess=False):
4715
4727
        self.add_cleanup(tree.lock_write().unlock)
4716
4728
        parents = tree.get_parent_ids()
4717
4729
        if len(parents) != 2:
4718
 
            raise errors.BzrCommandError(gettext("Sorry, remerge only works after normal"
4719
 
                                         " merges.  Not cherrypicking or"
4720
 
                                         " multi-merges."))
4721
 
        repository = tree.branch.repository
 
4730
            raise errors.BzrCommandError(
 
4731
                gettext("Sorry, remerge only works after normal"
 
4732
                        " merges.  Not cherrypicking or multi-merges."))
4722
4733
        interesting_files = None
4723
4734
        new_conflicts = []
4724
4735
        conflicts = tree.conflicts()
4731
4742
                if tree.kind(filename) != "directory":
4732
4743
                    continue
4733
4744
 
4734
 
                for path, ie in tree.iter_entries_by_dir(specific_files=[filename]):
 
4745
                for path, ie in tree.iter_entries_by_dir(
 
4746
                        specific_files=[filename]):
4735
4747
                    interesting_files.add(path)
4736
4748
            new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4737
4749
        else:
4789
4801
    update command.
4790
4802
 
4791
4803
    Uncommitted changes to files that are reverted will be discarded.
4792
 
    Howver, by default, any files that have been manually changed will be
 
4804
    However, by default, any files that have been manually changed will be
4793
4805
    backed up first.  (Files changed only by merge are not backed up.)  Backup
4794
4806
    files have '.~#~' appended to their name, where # is a number.
4795
4807
 
4845
4857
    def _revert_tree_to_revision(tree, revision, file_list, no_backup):
4846
4858
        rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
4847
4859
        tree.revert(file_list, rev_tree, not no_backup, None,
4848
 
            report_changes=True)
 
4860
                    report_changes=True)
4849
4861
 
4850
4862
 
4851
4863
class cmd_assert_fail(Command):
4864
4876
 
4865
4877
    _see_also = ['topics']
4866
4878
    takes_options = [
4867
 
            Option('long', 'Show help on all commands.'),
4868
 
            ]
 
4879
        Option('long', 'Show help on all commands.'),
 
4880
        ]
4869
4881
    takes_args = ['topic?']
4870
4882
    aliases = ['?', '--help', '-?', '-h']
4871
4883
 
4900
4912
    To filter on a range of revisions, you can use the command -r begin..end
4901
4913
    -r revision requests a specific revision, -r ..end or -r begin.. are
4902
4914
    also valid.
4903
 
            
 
4915
 
4904
4916
    :Exit values:
4905
4917
        1 - some missing revisions
4906
4918
        0 - no missing revisions
4942
4954
        'show-ids',
4943
4955
        'verbose',
4944
4956
        custom_help('revision',
4945
 
             help='Filter on other branch revisions (inclusive). '
4946
 
                'See "help revisionspec" for details.'),
 
4957
                    help='Filter on other branch revisions (inclusive). '
 
4958
                    'See "help revisionspec" for details.'),
4947
4959
        Option('my-revision',
4948
 
            type=_parse_revision_str,
4949
 
            help='Filter on local branch revisions (inclusive). '
4950
 
                'See "help revisionspec" for details.'),
 
4960
               type=_parse_revision_str,
 
4961
               help='Filter on local branch revisions (inclusive). '
 
4962
               'See "help revisionspec" for details.'),
4951
4963
        Option('include-merged',
4952
4964
               'Show all revisions in addition to the mainline ones.'),
4953
4965
        Option('include-merges', hidden=True,
4963
4975
            include_merged=None, revision=None, my_revision=None,
4964
4976
            directory=u'.'):
4965
4977
        from breezy.missing import find_unmerged, iter_log_revisions
 
4978
 
4966
4979
        def message(s):
4967
4980
            if not is_quiet():
4968
4981
                self.outf.write(s)
4990
5003
            other_branch = parent
4991
5004
            if other_branch is None:
4992
5005
                raise errors.BzrCommandError(gettext("No peer location known"
4993
 
                                             " or specified."))
 
5006
                                                     " or specified."))
4994
5007
            display_url = urlutils.unescape_for_display(parent,
4995
5008
                                                        self.outf.encoding)
4996
5009
            message(gettext("Using saved parent location: {0}\n").format(
5004
5017
 
5005
5018
        local_revid_range = _revision_range_to_revid_range(
5006
5019
            _get_revision_range(my_revision, local_branch,
5007
 
                self.name()))
 
5020
                                self.name()))
5008
5021
 
5009
5022
        remote_revid_range = _revision_range_to_revid_range(
5010
5023
            _get_revision_range(revision,
5011
 
                remote_branch, self.name()))
 
5024
                                remote_branch, self.name()))
5012
5025
 
5013
5026
        local_extra, remote_extra = find_unmerged(
5014
5027
            local_branch, remote_branch, restrict,
5027
5040
        status_code = 0
5028
5041
        if local_extra and not theirs_only:
5029
5042
            message(ngettext("You have %d extra revision:\n",
5030
 
                             "You have %d extra revisions:\n", 
 
5043
                             "You have %d extra revisions:\n",
5031
5044
                             len(local_extra)) %
5032
 
                len(local_extra))
 
5045
                    len(local_extra))
5033
5046
            rev_tag_dict = {}
5034
5047
            if local_branch.supports_tags():
5035
5048
                rev_tag_dict = local_branch.tags.get_reverse_tag_dict()
5036
5049
            for revision in iter_log_revisions(local_extra,
5037
 
                                local_branch.repository,
5038
 
                                verbose,
5039
 
                                rev_tag_dict):
 
5050
                                               local_branch.repository,
 
5051
                                               verbose,
 
5052
                                               rev_tag_dict):
5040
5053
                lf.log_revision(revision)
5041
5054
            printed_local = True
5042
5055
            status_code = 1
5049
5062
            message(ngettext("You are missing %d revision:\n",
5050
5063
                             "You are missing %d revisions:\n",
5051
5064
                             len(remote_extra)) %
5052
 
                len(remote_extra))
 
5065
                    len(remote_extra))
5053
5066
            if remote_branch.supports_tags():
5054
5067
                rev_tag_dict = remote_branch.tags.get_reverse_tag_dict()
5055
5068
            for revision in iter_log_revisions(remote_extra,
5056
 
                                remote_branch.repository,
5057
 
                                verbose,
5058
 
                                rev_tag_dict):
 
5069
                                               remote_branch.repository,
 
5070
                                               verbose,
 
5071
                                               rev_tag_dict):
5059
5072
                lf.log_revision(revision)
5060
5073
            status_code = 1
5061
5074
 
5101
5114
    _see_also = ['repositories']
5102
5115
    takes_args = ['branch_or_repo?']
5103
5116
    takes_options = [
5104
 
        Option('clean-obsolete-packs', 'Delete obsolete packs to save disk space.'),
 
5117
        Option('clean-obsolete-packs',
 
5118
               'Delete obsolete packs to save disk space.'),
5105
5119
        ]
5106
5120
 
5107
5121
    def run(self, branch_or_repo='.', clean_obsolete_packs=False):
5122
5136
 
5123
5137
    --verbose shows the path where each plugin is located.
5124
5138
 
5125
 
    A plugin is an external component for Bazaar that extends the
5126
 
    revision control system, by adding or replacing code in Bazaar.
 
5139
    A plugin is an external component for Breezy that extends the
 
5140
    revision control system, by adding or replacing code in Breezy.
5127
5141
    Plugins can do a variety of things, including overriding commands,
5128
5142
    adding new commands, providing additional network transports and
5129
5143
    customizing log output.
5146
5160
class cmd_testament(Command):
5147
5161
    __doc__ = """Show testament (signing-form) of a revision."""
5148
5162
    takes_options = [
5149
 
            'revision',
5150
 
            Option('long', help='Produce long-format testament.'),
5151
 
            Option('strict',
5152
 
                   help='Produce a strict-format testament.')]
 
5163
        'revision',
 
5164
        Option('long', help='Produce long-format testament.'),
 
5165
        Option('strict',
 
5166
               help='Produce a strict-format testament.')]
5153
5167
    takes_args = ['branch?']
5154
5168
    encoding_type = 'exact'
 
5169
 
5155
5170
    @display_command
5156
5171
    def run(self, branch=u'.', revision=None, long=False, strict=False):
5157
 
        from .testament import Testament, StrictTestament
 
5172
        from .bzr.testament import Testament, StrictTestament
5158
5173
        if strict is True:
5159
5174
            testament_class = StrictTestament
5160
5175
        else:
5212
5227
        tree = _get_one_revision_tree('annotate', revision, branch=branch)
5213
5228
        self.add_cleanup(tree.lock_read().unlock)
5214
5229
        if wt is not None and revision is None:
5215
 
            file_id = wt.path2id(relpath)
5216
 
        else:
5217
 
            file_id = tree.path2id(relpath)
5218
 
        if file_id is None:
5219
 
            raise errors.NotVersionedError(filename)
5220
 
        if wt is not None and revision is None:
 
5230
            if not wt.is_versioned(relpath):
 
5231
                raise errors.NotVersionedError(relpath)
5221
5232
            # If there is a tree and we're not annotating historical
5222
5233
            # versions, annotate the working tree's content.
5223
5234
            annotate_file_tree(wt, relpath, self.outf, long, all,
5224
 
                show_ids=show_ids, file_id=file_id)
 
5235
                               show_ids=show_ids)
5225
5236
        else:
 
5237
            if not tree.is_versioned(relpath):
 
5238
                raise errors.NotVersionedError(relpath)
5226
5239
            annotate_file_tree(tree, relpath, self.outf, long, all,
5227
 
                show_ids=show_ids, branch=branch, file_id=file_id)
 
5240
                               show_ids=show_ids, branch=branch)
5228
5241
 
5229
5242
 
5230
5243
class cmd_re_sign(Command):
5231
5244
    __doc__ = """Create a digital signature for an existing revision."""
5232
5245
    # TODO be able to replace existing ones.
5233
5246
 
5234
 
    hidden = True # is this right ?
 
5247
    hidden = True  # is this right ?
5235
5248
    takes_args = ['revision_id*']
5236
5249
    takes_options = ['directory', 'revision']
5237
5250
 
5238
5251
    def run(self, revision_id_list=None, revision=None, directory=u'.'):
5239
5252
        if revision_id_list is not None and revision is not None:
5240
 
            raise errors.BzrCommandError(gettext('You can only supply one of revision_id or --revision'))
 
5253
            raise errors.BzrCommandError(
 
5254
                gettext('You can only supply one of revision_id or --revision'))
5241
5255
        if revision_id_list is None and revision is None:
5242
 
            raise errors.BzrCommandError(gettext('You must supply either --revision or a revision_id'))
 
5256
            raise errors.BzrCommandError(
 
5257
                gettext('You must supply either --revision or a revision_id'))
5243
5258
        b = WorkingTree.open_containing(directory)[0].branch
5244
5259
        self.add_cleanup(b.lock_write().unlock)
5245
5260
        return self._run(b, revision_id_list, revision)
5266
5281
                if to_revid is None:
5267
5282
                    to_revno = b.revno()
5268
5283
                if from_revno is None or to_revno is None:
5269
 
                    raise errors.BzrCommandError(gettext('Cannot sign a range of non-revision-history revisions'))
 
5284
                    raise errors.BzrCommandError(
 
5285
                        gettext('Cannot sign a range of non-revision-history revisions'))
5270
5286
                with WriteGroup(b.repository):
5271
5287
                    for revno in range(from_revno, to_revno + 1):
5272
5288
                        b.repository.sign_revision(b.get_rev_id(revno),
5273
5289
                                                   gpg_strategy)
5274
5290
            else:
5275
 
                raise errors.BzrCommandError(gettext('Please supply either one revision, or a range.'))
 
5291
                raise errors.BzrCommandError(
 
5292
                    gettext('Please supply either one revision, or a range.'))
5276
5293
 
5277
5294
 
5278
5295
class cmd_bind(Command):
5297
5314
            try:
5298
5315
                location = b.get_old_bound_location()
5299
5316
            except errors.UpgradeRequired:
5300
 
                raise errors.BzrCommandError(gettext('No location supplied.  '
5301
 
                    'This format does not remember old locations.'))
 
5317
                raise errors.BzrCommandError(
 
5318
                    gettext('No location supplied.  '
 
5319
                            'This format does not remember old locations.'))
5302
5320
            else:
5303
5321
                if location is None:
5304
5322
                    if b.get_bound_location() is not None:
5312
5330
        try:
5313
5331
            b.bind(b_other)
5314
5332
        except errors.DivergedBranches:
5315
 
            raise errors.BzrCommandError(gettext('These branches have diverged.'
5316
 
                                         ' Try merging, and then bind again.'))
 
5333
            raise errors.BzrCommandError(
 
5334
                gettext('These branches have diverged.'
 
5335
                        ' Try merging, and then bind again.'))
5317
5336
        if b.get_config().has_explicit_nickname():
5318
5337
            b.nick = b_other.nick
5319
5338
 
5357
5376
    # information in shared branches as well.
5358
5377
    _see_also = ['commit']
5359
5378
    takes_options = ['verbose', 'revision',
5360
 
                    Option('dry-run', help='Don\'t actually make changes.'),
5361
 
                    Option('force', help='Say yes to all questions.'),
5362
 
                    Option('keep-tags',
5363
 
                           help='Keep tags that point to removed revisions.'),
5364
 
                    Option('local',
5365
 
                           help="Only remove the commits from the local branch"
5366
 
                                " when in a checkout."
5367
 
                           ),
5368
 
                    ]
 
5379
                     Option('dry-run', help='Don\'t actually make changes.'),
 
5380
                     Option('force', help='Say yes to all questions.'),
 
5381
                     Option('keep-tags',
 
5382
                            help='Keep tags that point to removed revisions.'),
 
5383
                     Option('local',
 
5384
                            help="Only remove the commits from the local "
 
5385
                            "branch when in a checkout."
 
5386
                            ),
 
5387
                     ]
5369
5388
    takes_args = ['location?']
5370
5389
    aliases = []
5371
5390
    encoding_type = 'replace'
5387
5406
        else:
5388
5407
            self.add_cleanup(b.lock_write().unlock)
5389
5408
        return self._run(b, tree, dry_run, verbose, revision, force,
5390
 
                         local, keep_tags)
 
5409
                         local, keep_tags, location)
5391
5410
 
5392
5411
    def _run(self, b, tree, dry_run, verbose, revision, force, local,
5393
 
             keep_tags):
 
5412
             keep_tags, location):
5394
5413
        from .log import log_formatter, show_log
5395
5414
        from .uncommit import uncommit
5396
5415
 
5427
5446
 
5428
5447
        if dry_run:
5429
5448
            self.outf.write(gettext('Dry-run, pretending to remove'
5430
 
                            ' the above revisions.\n'))
 
5449
                                    ' the above revisions.\n'))
5431
5450
        else:
5432
 
            self.outf.write(gettext('The above revision(s) will be removed.\n'))
 
5451
            self.outf.write(
 
5452
                gettext('The above revision(s) will be removed.\n'))
5433
5453
 
5434
5454
        if not force:
5435
5455
            if not ui.ui_factory.confirm_action(
5443
5463
               last_rev_id, rev_id)
5444
5464
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
5445
5465
                 revno=revno, local=local, keep_tags=keep_tags)
5446
 
        self.outf.write(gettext('You can restore the old tip by running:\n'
5447
 
             '  brz pull . -r revid:%s\n') % last_rev_id.decode('utf-8'))
 
5466
        if location != '.':
 
5467
            self.outf.write(
 
5468
                gettext('You can restore the old tip by running:\n'
 
5469
                        '  brz pull -d %s %s -r revid:%s\n')
 
5470
                % (location, location, last_rev_id.decode('utf-8')))
 
5471
        else:
 
5472
            self.outf.write(
 
5473
                gettext('You can restore the old tip by running:\n'
 
5474
                        '  brz pull . -r revid:%s\n')
 
5475
                % last_rev_id.decode('utf-8'))
5448
5476
 
5449
5477
 
5450
5478
class cmd_break_lock(Command):
5462
5490
    :Examples:
5463
5491
        brz break-lock
5464
5492
        brz break-lock brz+ssh://example.com/brz/foo
5465
 
        brz break-lock --conf ~/.bazaar
 
5493
        brz break-lock --conf ~/.config/breezy
5466
5494
    """
5467
5495
 
5468
5496
    takes_args = ['location?']
5470
5498
        Option('config',
5471
5499
               help='LOCATION is the directory where the config lock is.'),
5472
5500
        Option('force',
5473
 
            help='Do not ask for confirmation before breaking the lock.'),
 
5501
               help='Do not ask for confirmation before breaking the lock.'),
5474
5502
        ]
5475
5503
 
5476
5504
    def run(self, location=None, config=False, force=False):
5478
5506
            location = u'.'
5479
5507
        if force:
5480
5508
            ui.ui_factory = ui.ConfirmationUserInterfacePolicy(ui.ui_factory,
5481
 
                None,
5482
 
                {'breezy.lockdir.break': True})
 
5509
                                                               None,
 
5510
                                                               {'breezy.lockdir.break': True})
5483
5511
        if config:
5484
5512
            conf = _mod_config.LockableConfig(file_name=location)
5485
5513
            conf.break_lock()
5514
5542
        Option('inet',
5515
5543
               help='Serve on stdin/out for use from inetd or sshd.'),
5516
5544
        RegistryOption('protocol',
5517
 
               help="Protocol to serve.",
5518
 
               lazy_registry=('breezy.transport', 'transport_server_registry'),
5519
 
               value_switches=True),
 
5545
                       help="Protocol to serve.",
 
5546
                       lazy_registry=('breezy.transport',
 
5547
                                      'transport_server_registry'),
 
5548
                       value_switches=True),
5520
5549
        Option('listen',
5521
 
               help='Listen for connections on nominated address.', type=text_type),
 
5550
               help='Listen for connections on nominated address.',
 
5551
               type=text_type),
5522
5552
        Option('port',
5523
5553
               help='Listen for connections on nominated port.  Passing 0 as '
5524
5554
                    'the port number will result in a dynamically allocated '
5525
5555
                    'port.  The default port depends on the protocol.',
5526
5556
               type=int),
5527
5557
        custom_help('directory',
5528
 
               help='Serve contents of this directory.'),
 
5558
                    help='Serve contents of this directory.'),
5529
5559
        Option('allow-writes',
5530
5560
               help='By default the server is a readonly server.  Supplying '
5531
5561
                    '--allow-writes enables write access to the contents of '
5534
5564
                    'external authentication is arranged supplying this '
5535
5565
                    'option leads to global uncontrolled write access to your '
5536
5566
                    'file system.'
5537
 
                ),
 
5567
               ),
5538
5568
        Option('client-timeout', type=float,
5539
5569
               help='Override the default idle client timeout (5min).'),
5540
5570
        ]
5541
5571
 
5542
5572
    def run(self, listen=None, port=None, inet=False, directory=None,
5543
5573
            allow_writes=False, protocol=None, client_timeout=None):
5544
 
        from . import transport
 
5574
        from . import location, transport
5545
5575
        if directory is None:
5546
5576
            directory = osutils.getcwd()
5547
5577
        if protocol is None:
5548
5578
            protocol = transport.transport_server_registry.get()
5549
 
        url = transport.location_to_url(directory)
 
5579
        url = location.location_to_url(directory)
5550
5580
        if not allow_writes:
5551
5581
            url = 'readonly+' + url
5552
5582
        t = transport.get_transport_from_url(url)
5570
5600
    _see_also = ['split']
5571
5601
    takes_args = ['tree']
5572
5602
    takes_options = [
5573
 
            Option('reference', help='Join by reference.', hidden=True),
5574
 
            ]
 
5603
        Option('reference', help='Join by reference.', hidden=True),
 
5604
        ]
5575
5605
 
5576
5606
    def run(self, tree, reference=False):
5577
5607
        from breezy.mutabletree import BadReferenceTarget
5591
5621
                # XXX: Would be better to just raise a nicely printable
5592
5622
                # exception from the real origin.  Also below.  mbp 20070306
5593
5623
                raise errors.BzrCommandError(
5594
 
                       gettext("Cannot join {0}.  {1}").format(tree, e.reason))
 
5624
                    gettext("Cannot join {0}.  {1}").format(tree, e.reason))
5595
5625
        else:
5596
5626
            try:
5597
5627
                containing_tree.subsume(sub_tree)
5598
5628
            except errors.BadSubsumeSource as e:
5599
5629
                raise errors.BzrCommandError(
5600
 
                       gettext("Cannot join {0}.  {1}").format(tree, e.reason))
 
5630
                    gettext("Cannot join {0}.  {1}").format(tree, e.reason))
5601
5631
 
5602
5632
 
5603
5633
class cmd_split(Command):
5617
5647
 
5618
5648
    def run(self, tree):
5619
5649
        containing_tree, subdir = WorkingTree.open_containing(tree)
5620
 
        sub_id = containing_tree.path2id(subdir)
5621
 
        if sub_id is None:
 
5650
        if not containing_tree.is_versioned(subdir):
5622
5651
            raise errors.NotVersionedError(subdir)
5623
5652
        try:
5624
 
            containing_tree.extract(subdir, sub_id)
 
5653
            containing_tree.extract(subdir)
5625
5654
        except errors.RootNotRich:
5626
5655
            raise errors.RichRootUpgradeRequired(containing_tree.branch.base)
5627
5656
 
5651
5680
 
5652
5681
    takes_options = [
5653
5682
        'directory',
5654
 
        RegistryOption.from_kwargs('patch-type',
 
5683
        RegistryOption.from_kwargs(
 
5684
            'patch-type',
5655
5685
            'The type of patch to include in the directive.',
5656
5686
            title='Patch type',
5657
5687
            value_switches=True,
5661
5691
            plain='No patch, just directive.'),
5662
5692
        Option('sign', help='GPG-sign the directive.'), 'revision',
5663
5693
        Option('mail-to', type=text_type,
5664
 
            help='Instead of printing the directive, email to this address.'),
 
5694
               help='Instead of printing the directive, email to this '
 
5695
               'address.'),
5665
5696
        Option('message', type=text_type, short_name='m',
5666
 
            help='Message to use when committing this merge.')
 
5697
               help='Message to use when committing this merge.')
5667
5698
        ]
5668
5699
 
5669
5700
    encoding_type = 'exact'
5687
5718
        if submit_branch is None:
5688
5719
            submit_branch = branch.get_parent()
5689
5720
        if submit_branch is None:
5690
 
            raise errors.BzrCommandError(gettext('No submit branch specified or known'))
 
5721
            raise errors.BzrCommandError(
 
5722
                gettext('No submit branch specified or known'))
5691
5723
 
5692
5724
        stored_public_branch = branch.get_public_branch()
5693
5725
        if public_branch is None:
5696
5728
            # FIXME: Should be done only if we succeed ? -- vila 2012-01-03
5697
5729
            branch.set_public_branch(public_branch)
5698
5730
        if not include_bundle and public_branch is None:
5699
 
            raise errors.BzrCommandError(gettext('No public branch specified or'
5700
 
                                         ' known'))
 
5731
            raise errors.BzrCommandError(
 
5732
                gettext('No public branch specified or known'))
5701
5733
        base_revision_id = None
5702
5734
        if revision is not None:
5703
5735
            if len(revision) > 2:
5704
 
                raise errors.BzrCommandError(gettext('brz merge-directive takes '
5705
 
                    'at most two one revision identifiers'))
 
5736
                raise errors.BzrCommandError(
 
5737
                    gettext('brz merge-directive takes '
 
5738
                            'at most two one revision identifiers'))
5706
5739
            revision_id = revision[-1].as_revision_id(branch)
5707
5740
            if len(revision) == 2:
5708
5741
                base_revision_id = revision[0].as_revision_id(branch)
5742
5775
      branch.
5743
5776
 
5744
5777
    `brz send` creates a compact data set that, when applied using brz
5745
 
    merge, has the same effect as merging from the source branch.  
5746
 
    
 
5778
    merge, has the same effect as merging from the source branch.
 
5779
 
5747
5780
    By default the merge directive is self-contained and can be applied to any
5748
5781
    branch containing submit_branch in its ancestory without needing access to
5749
5782
    the source branch.
5750
 
    
5751
 
    If --no-bundle is specified, then Bazaar doesn't send the contents of the
 
5783
 
 
5784
    If --no-bundle is specified, then Breezy doesn't send the contents of the
5752
5785
    revisions, but only a structured request to merge from the
5753
5786
    public_location.  In that case the public_branch is needed and it must be
5754
5787
    up-to-date and accessible to the recipient.  The public_branch is always
5779
5812
    If the preferred client can't be found (or used), your editor will be used.
5780
5813
 
5781
5814
    To use a specific mail program, set the mail_client configuration option.
5782
 
    (For Thunderbird 1.5, this works around some bugs.)  Supported values for
5783
 
    specific clients are "claws", "evolution", "kmail", "mail.app" (MacOS X's
5784
 
    Mail.app), "mutt", and "thunderbird"; generic options are "default",
5785
 
    "editor", "emacsclient", "mapi", and "xdg-email".  Plugins may also add
5786
 
    supported clients.
 
5815
    Supported values for specific clients are "claws", "evolution", "kmail",
 
5816
    "mail.app" (MacOS X's Mail.app), "mutt", and "thunderbird"; generic options
 
5817
    are "default", "editor", "emacsclient", "mapi", and "xdg-email".  Plugins
 
5818
    may also add supported clients.
5787
5819
 
5788
5820
    If mail is being sent, a to address is required.  This can be supplied
5789
5821
    either on the commandline, by setting the submit_to configuration
5790
5822
    option in the branch itself or the child_submit_to configuration option
5791
5823
    in the submit branch.
5792
5824
 
5793
 
    Two formats are currently supported: "4" uses revision bundle format 4 and
5794
 
    merge directive format 2.  It is significantly faster and smaller than
5795
 
    older formats.  It is compatible with Bazaar 0.19 and later.  It is the
5796
 
    default.  "0.9" uses revision bundle format 0.9 and merge directive
5797
 
    format 1.  It is compatible with Bazaar 0.12 - 0.18.
5798
 
 
5799
5825
    The merge directives created by brz send may be applied using brz merge or
5800
5826
    brz pull by specifying a file containing a merge directive as the location.
5801
5827
 
5876
5902
    branch is used in the merge instructions.  This means that a local mirror
5877
5903
    can be used as your actual submit branch, once you have set public_branch
5878
5904
    for that mirror.
5879
 
 
5880
 
    Two formats are currently supported: "4" uses revision bundle format 4 and
5881
 
    merge directive format 2.  It is significantly faster and smaller than
5882
 
    older formats.  It is compatible with Bazaar 0.19 and later.  It is the
5883
 
    default.  "0.9" uses revision bundle format 0.9 and merge directive
5884
 
    format 1.  It is compatible with Bazaar 0.12 - 0.18.
5885
5905
    """
5886
5906
 
5887
5907
    takes_options = [
5919
5939
            output = '-'
5920
5940
        from .send import send
5921
5941
        return send(submit_branch, revision, public_branch, remember,
5922
 
                         format, no_bundle, no_patch, output,
5923
 
                         kwargs.get('from', '.'), None, None, None,
5924
 
                         self.outf, strict=strict)
 
5942
                    format, no_bundle, no_patch, output,
 
5943
                    kwargs.get('from', '.'), None, None, None,
 
5944
                    self.outf, strict=strict)
5925
5945
 
5926
5946
 
5927
5947
class cmd_tag(Command):
5940
5960
    To rename a tag (change the name but keep it on the same revsion), run ``brz
5941
5961
    tag new-name -r tag:old-name`` and then ``brz tag --delete oldname``.
5942
5962
 
5943
 
    If no tag name is specified it will be determined through the 
 
5963
    If no tag name is specified it will be determined through the
5944
5964
    'automatic_tag_name' hook. This can e.g. be used to automatically tag
5945
5965
    upstream releases by reading configure.ac. See ``brz help hooks`` for
5946
5966
    details.
5950
5970
    takes_args = ['tag_name?']
5951
5971
    takes_options = [
5952
5972
        Option('delete',
5953
 
            help='Delete this tag rather than placing it.',
5954
 
            ),
 
5973
               help='Delete this tag rather than placing it.',
 
5974
               ),
5955
5975
        custom_help('directory',
5956
 
            help='Branch in which to place the tag.'),
 
5976
                    help='Branch in which to place the tag.'),
5957
5977
        Option('force',
5958
 
            help='Replace existing tags.',
5959
 
            ),
 
5978
               help='Replace existing tags.',
 
5979
               ),
5960
5980
        'revision',
5961
5981
        ]
5962
5982
 
5970
5990
        self.add_cleanup(branch.lock_write().unlock)
5971
5991
        if delete:
5972
5992
            if tag_name is None:
5973
 
                raise errors.BzrCommandError(gettext("No tag specified to delete."))
 
5993
                raise errors.BzrCommandError(
 
5994
                    gettext("No tag specified to delete."))
5974
5995
            branch.tags.delete_tag(tag_name)
5975
5996
            note(gettext('Deleted tag %s.') % tag_name)
5976
5997
        else:
6012
6033
    _see_also = ['tag']
6013
6034
    takes_options = [
6014
6035
        custom_help('directory',
6015
 
            help='Branch whose tags should be displayed.'),
 
6036
                    help='Branch whose tags should be displayed.'),
6016
6037
        RegistryOption('sort',
6017
 
            'Sort tags by different criteria.', title='Sorting',
6018
 
            lazy_registry=('breezy.tag', 'tag_sort_methods')
6019
 
            ),
 
6038
                       'Sort tags by different criteria.', title='Sorting',
 
6039
                       lazy_registry=('breezy.tag', 'tag_sort_methods')
 
6040
                       ),
6020
6041
        'show-ids',
6021
6042
        'revision',
6022
6043
    ]
6058
6079
            self.outf.write('%-20s %s\n' % (tag, revspec))
6059
6080
 
6060
6081
    def _tags_for_range(self, branch, revision):
6061
 
        range_valid = True
6062
6082
        rev1, rev2 = _get_revision_range(revision, branch, self.name())
6063
6083
        revid1, revid2 = rev1.rev_id, rev2.rev_id
6064
6084
        # _get_revision_range will always set revid2 if it's not specified.
6076
6096
        tagged_revids = branch.tags.get_reverse_tag_dict()
6077
6097
        found = []
6078
6098
        for r in branch.iter_merge_sorted_revisions(
6079
 
            start_revision_id=revid2, stop_revision_id=revid1,
6080
 
            stop_rule='include'):
 
6099
                start_revision_id=revid2, stop_revision_id=revid1,
 
6100
                stop_rule='include'):
6081
6101
            revid_tags = tagged_revids.get(r[0], None)
6082
6102
            if revid_tags:
6083
6103
                found.extend([(tag, r[0]) for tag in revid_tags])
6110
6130
            tree='Reconfigure to be an unbound branch with a working tree.',
6111
6131
            checkout='Reconfigure to be a bound branch with a working tree.',
6112
6132
            lightweight_checkout='Reconfigure to be a lightweight'
6113
 
                ' checkout (with no local history).',
 
6133
            ' checkout (with no local history).',
6114
6134
            ),
6115
6135
        RegistryOption.from_kwargs(
6116
6136
            'repository_type',
6118
6138
            help='Location fo the repository.',
6119
6139
            value_switches=True, enum_switch=False,
6120
6140
            standalone='Reconfigure to be a standalone branch '
6121
 
                '(i.e. stop using shared repository).',
 
6141
            '(i.e. stop using shared repository).',
6122
6142
            use_shared='Reconfigure to use a shared repository.',
6123
6143
            ),
6124
6144
        RegistryOption.from_kwargs(
6127
6147
            help='Whether new branches in the repository have trees.',
6128
6148
            value_switches=True, enum_switch=False,
6129
6149
            with_trees='Reconfigure repository to create '
6130
 
                'working trees on branches by default.',
 
6150
            'working trees on branches by default.',
6131
6151
            with_no_trees='Reconfigure repository to not create '
6132
 
                'working trees on branches by default.'
 
6152
            'working trees on branches by default.'
6133
6153
            ),
6134
6154
        Option('bind-to', help='Branch to bind checkout to.', type=text_type),
6135
6155
        Option('force',
6136
 
            help='Perform reconfiguration even if local changes'
6137
 
            ' will be lost.'),
 
6156
               help='Perform reconfiguration even if local changes'
 
6157
               ' will be lost.'),
6138
6158
        Option('stacked-on',
6139
 
            help='Reconfigure a branch to be stacked on another branch.',
6140
 
            type=text_type,
6141
 
            ),
 
6159
               help='Reconfigure a branch to be stacked on another branch.',
 
6160
               type=text_type,
 
6161
               ),
6142
6162
        Option('unstacked',
6143
 
            help='Reconfigure a branch to be unstacked.  This '
6144
 
                'may require copying substantial data into it.',
6145
 
            ),
 
6163
               help='Reconfigure a branch to be unstacked.  This '
 
6164
               'may require copying substantial data into it.',
 
6165
               ),
6146
6166
        ]
6147
6167
 
6148
6168
    def run(self, location=None, bind_to=None, force=False,
6150
6170
            stacked_on=None, unstacked=None):
6151
6171
        directory = controldir.ControlDir.open(location)
6152
6172
        if stacked_on and unstacked:
6153
 
            raise errors.BzrCommandError(gettext("Can't use both --stacked-on and --unstacked"))
 
6173
            raise errors.BzrCommandError(
 
6174
                gettext("Can't use both --stacked-on and --unstacked"))
6154
6175
        elif stacked_on is not None:
6155
6176
            reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
6156
6177
        elif unstacked:
6160
6181
        # to ban it.
6161
6182
        if (tree_type is None and
6162
6183
            repository_type is None and
6163
 
            repository_trees is None):
 
6184
                repository_trees is None):
6164
6185
            if stacked_on or unstacked:
6165
6186
                return
6166
6187
            else:
6167
6188
                raise errors.BzrCommandError(gettext('No target configuration '
6168
 
                    'specified'))
 
6189
                                                     'specified'))
6169
6190
        reconfiguration = None
6170
6191
        if tree_type == 'branch':
6171
6192
            reconfiguration = reconfigure.Reconfigure.to_branch(directory)
6224
6245
    takes_args = ['to_location?']
6225
6246
    takes_options = ['directory',
6226
6247
                     Option('force',
6227
 
                        help='Switch even if local commits will be lost.'),
 
6248
                            help='Switch even if local commits will be lost.'),
6228
6249
                     'revision',
6229
6250
                     Option('create-branch', short_name='b',
6230
 
                        help='Create the target branch from this one before'
6231
 
                             ' switching to it.'),
 
6251
                            help='Create the target branch from this one before'
 
6252
                            ' switching to it.'),
6232
6253
                     Option('store',
6233
 
                        help='Store and restore uncommitted changes in the'
6234
 
                             ' branch.'),
6235
 
                    ]
 
6254
                            help='Store and restore uncommitted changes in the'
 
6255
                            ' branch.'),
 
6256
                     ]
6236
6257
 
6237
6258
    def run(self, to_location=None, force=False, create_branch=False,
6238
6259
            revision=None, directory=u'.', store=False):
6241
6262
        revision = _get_one_revision('switch', revision)
6242
6263
        possible_transports = []
6243
6264
        control_dir = controldir.ControlDir.open_containing(tree_location,
6244
 
            possible_transports=possible_transports)[0]
 
6265
                                                            possible_transports=possible_transports)[0]
6245
6266
        if to_location is None:
6246
6267
            if revision is None:
6247
6268
                raise errors.BzrCommandError(gettext('You must supply either a'
6248
 
                                             ' revision or a location'))
 
6269
                                                     ' revision or a location'))
6249
6270
            to_location = tree_location
6250
6271
        try:
6251
6272
            branch = control_dir.open_branch(
6258
6279
            if branch is None:
6259
6280
                raise errors.BzrCommandError(
6260
6281
                    gettext('cannot create branch without source branch'))
6261
 
            to_location = lookup_new_sibling_branch(control_dir, to_location,
6262
 
                 possible_transports=possible_transports)
6263
 
            to_branch = branch.controldir.sprout(to_location,
6264
 
                 possible_transports=possible_transports,
6265
 
                 source_branch=branch).open_branch()
 
6282
            to_location = lookup_new_sibling_branch(
 
6283
                control_dir, to_location,
 
6284
                possible_transports=possible_transports)
 
6285
            if revision is not None:
 
6286
                revision = revision.as_revision_id(branch)
 
6287
            to_branch = branch.controldir.sprout(
 
6288
                to_location,
 
6289
                possible_transports=possible_transports,
 
6290
                revision_id=revision,
 
6291
                source_branch=branch).open_branch()
6266
6292
        else:
6267
6293
            try:
6268
6294
                to_branch = Branch.open(to_location,
6269
 
                    possible_transports=possible_transports)
 
6295
                                        possible_transports=possible_transports)
6270
6296
            except errors.NotBranchError:
6271
 
                to_branch = open_sibling_branch(control_dir, to_location,
 
6297
                to_branch = open_sibling_branch(
 
6298
                    control_dir, to_location,
6272
6299
                    possible_transports=possible_transports)
6273
 
        if revision is not None:
6274
 
            revision = revision.as_revision_id(to_branch)
 
6300
            if revision is not None:
 
6301
                revision = revision.as_revision_id(to_branch)
6275
6302
        try:
6276
6303
            switch.switch(control_dir, to_branch, force, revision_id=revision,
6277
6304
                          store_uncommitted=store)
6278
6305
        except controldir.BranchReferenceLoop:
6279
6306
            raise errors.BzrCommandError(
6280
 
                    gettext('switching would create a branch reference loop. '
6281
 
                            'Use the "bzr up" command to switch to a '
6282
 
                            'different revision.'))
 
6307
                gettext('switching would create a branch reference loop. '
 
6308
                        'Use the "bzr up" command to switch to a '
 
6309
                        'different revision.'))
6283
6310
        if had_explicit_nick:
6284
 
            branch = control_dir.open_branch() #get the new branch!
 
6311
            branch = control_dir.open_branch()  # get the new branch!
6285
6312
            branch.nick = to_branch.nick
6286
 
        note(gettext('Switched to branch: %s'),
6287
 
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6288
 
 
 
6313
        if to_branch.name:
 
6314
            if to_branch.controldir.control_url != control_dir.control_url:
 
6315
                note(gettext('Switched to branch %s at %s'),
 
6316
                     to_branch.name, urlutils.unescape_for_display(to_branch.base, 'utf-8'))
 
6317
            else:
 
6318
                note(gettext('Switched to branch %s'), to_branch.name)
 
6319
        else:
 
6320
            note(gettext('Switched to branch at %s'),
 
6321
                 urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6289
6322
 
6290
6323
 
6291
6324
class cmd_view(Command):
6354
6387
    takes_args = ['file*']
6355
6388
    takes_options = [
6356
6389
        Option('all',
6357
 
            help='Apply list or delete action to all views.',
6358
 
            ),
 
6390
               help='Apply list or delete action to all views.',
 
6391
               ),
6359
6392
        Option('delete',
6360
 
            help='Delete the view.',
6361
 
            ),
 
6393
               help='Delete the view.',
 
6394
               ),
6362
6395
        Option('name',
6363
 
            help='Name of the view to define, list or delete.',
6364
 
            type=text_type,
6365
 
            ),
 
6396
               help='Name of the view to define, list or delete.',
 
6397
               type=text_type,
 
6398
               ),
6366
6399
        Option('switch',
6367
 
            help='Name of the view to switch to.',
6368
 
            type=text_type,
6369
 
            ),
 
6400
               help='Name of the view to switch to.',
 
6401
               type=text_type,
 
6402
               ),
6370
6403
        ]
6371
6404
 
6372
6405
    def run(self, file_list,
6376
6409
            switch=None,
6377
6410
            ):
6378
6411
        tree, file_list = WorkingTree.open_containing_paths(file_list,
6379
 
            apply_view=False)
 
6412
                                                            apply_view=False)
6380
6413
        current_view, view_dict = tree.views.get_view_info()
6381
6414
        if name is None:
6382
6415
            name = current_view
6391
6424
                tree.views.set_view_info(None, {})
6392
6425
                self.outf.write(gettext("Deleted all views.\n"))
6393
6426
            elif name is None:
6394
 
                raise errors.BzrCommandError(gettext("No current view to delete"))
 
6427
                raise errors.BzrCommandError(
 
6428
                    gettext("No current view to delete"))
6395
6429
            else:
6396
6430
                tree.views.delete_view(name)
6397
6431
                self.outf.write(gettext("Deleted '%s' view.\n") % name)
6404
6438
                    "Both --switch and --all specified"))
6405
6439
            elif switch == 'off':
6406
6440
                if current_view is None:
6407
 
                    raise errors.BzrCommandError(gettext("No current view to disable"))
 
6441
                    raise errors.BzrCommandError(
 
6442
                        gettext("No current view to disable"))
6408
6443
                tree.views.set_view_info(None, view_dict)
6409
 
                self.outf.write(gettext("Disabled '%s' view.\n") % (current_view))
 
6444
                self.outf.write(gettext("Disabled '%s' view.\n") %
 
6445
                                (current_view))
6410
6446
            else:
6411
6447
                tree.views.set_view_info(switch, view_dict)
6412
6448
                view_str = views.view_display_str(tree.views.lookup_view())
6413
 
                self.outf.write(gettext("Using '{0}' view: {1}\n").format(switch, view_str))
 
6449
                self.outf.write(
 
6450
                    gettext("Using '{0}' view: {1}\n").format(switch, view_str))
6414
6451
        elif all:
6415
6452
            if view_dict:
6416
6453
                self.outf.write(gettext('Views defined:\n'))
6432
6469
                    "Cannot change the 'off' pseudo view"))
6433
6470
            tree.views.set_view(name, sorted(file_list))
6434
6471
            view_str = views.view_display_str(tree.views.lookup_view())
6435
 
            self.outf.write(gettext("Using '{0}' view: {1}\n").format(name, view_str))
 
6472
            self.outf.write(
 
6473
                gettext("Using '{0}' view: {1}\n").format(name, view_str))
6436
6474
        else:
6437
6475
            # list the files
6438
6476
            if name is None:
6440
6478
                self.outf.write(gettext('No current view.\n'))
6441
6479
            else:
6442
6480
                view_str = views.view_display_str(tree.views.lookup_view(name))
6443
 
                self.outf.write(gettext("'{0}' view is: {1}\n").format(name, view_str))
 
6481
                self.outf.write(
 
6482
                    gettext("'{0}' view is: {1}\n").format(name, view_str))
6444
6483
 
6445
6484
 
6446
6485
class cmd_hooks(Command):
6466
6505
class cmd_remove_branch(Command):
6467
6506
    __doc__ = """Remove a branch.
6468
6507
 
6469
 
    This will remove the branch from the specified location but 
 
6508
    This will remove the branch from the specified location but
6470
6509
    will keep any working tree or repository in place.
6471
6510
 
6472
6511
    :Examples:
6480
6519
    takes_args = ["location?"]
6481
6520
 
6482
6521
    takes_options = ['directory',
6483
 
        Option('force', help='Remove branch even if it is the active branch.')]
 
6522
                     Option('force', help='Remove branch even if it is the active branch.')]
6484
6523
 
6485
6524
    aliases = ["rmbranch"]
6486
6525
 
6492
6531
            except errors.NotBranchError:
6493
6532
                active_branch = None
6494
6533
            if (active_branch is not None and
6495
 
                br.control_url == active_branch.control_url):
 
6534
                    br.control_url == active_branch.control_url):
6496
6535
                raise errors.BzrCommandError(
6497
6536
                    gettext("Branch is active. Use --force to remove it."))
6498
6537
        br.controldir.destroy_branch(br.name)
6528
6567
 
6529
6568
        change_editor = PROGRAM @new_path @old_path
6530
6569
 
6531
 
    where @new_path is replaced with the path of the new version of the 
6532
 
    file and @old_path is replaced with the path of the old version of 
6533
 
    the file.  The PROGRAM should save the new file with the desired 
 
6570
    where @new_path is replaced with the path of the new version of the
 
6571
    file and @old_path is replaced with the path of the old version of
 
6572
    the file.  The PROGRAM should save the new file with the desired
6534
6573
    contents of the file in the working tree.
6535
 
        
 
6574
 
6536
6575
    """
6537
6576
 
6538
6577
    takes_args = ['file*']
6561
6600
            writer = breezy.option.diff_writer_registry.get()
6562
6601
        try:
6563
6602
            shelver = Shelver.from_args(writer(self.outf), revision, all,
6564
 
                file_list, message, destroy=destroy, directory=directory)
 
6603
                                        file_list, message, destroy=destroy, directory=directory)
6565
6604
            try:
6566
6605
                shelver.run()
6567
6606
            finally:
6644
6683
                     Option('dry-run', help='Show files to delete instead of'
6645
6684
                            ' deleting them.'),
6646
6685
                     Option('force', help='Do not prompt before deleting.')]
 
6686
 
6647
6687
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
6648
6688
            force=False, directory=u'.'):
6649
6689
        from .clean_tree import clean_tree
6675
6715
        branchdir = '.'
6676
6716
        if path is not None:
6677
6717
            branchdir = path
6678
 
        tree, branch, relpath =(
 
6718
        tree, branch, relpath = (
6679
6719
            controldir.ControlDir.open_containing_tree_or_branch(branchdir))
6680
6720
        if path is not None:
6681
6721
            path = relpath
6707
6747
 
6708
6748
    hidden = True
6709
6749
    takes_options = [Option('plugin',
6710
 
                            help='Export help text from named command '\
 
6750
                            help='Export help text from named command '
6711
6751
                                 '(defaults to all built in commands).',
6712
6752
                            type=text_type),
6713
6753
                     Option('include-duplicates',
6714
6754
                            help='Output multiple copies of the same msgid '
6715
6755
                                 'string if it appears more than once.'),
6716
 
                            ]
 
6756
                     ]
6717
6757
 
6718
6758
    def run(self, plugin=None, include_duplicates=False):
6719
6759
        from .export_pot import export_pot
6783
6823
            cmd_reconcile().run(".")
6784
6824
 
6785
6825
 
 
6826
class cmd_grep(Command):
 
6827
    """Print lines matching PATTERN for specified files and revisions.
 
6828
 
 
6829
    This command searches the specified files and revisions for a given
 
6830
    pattern.  The pattern is specified as a Python regular expressions[1].
 
6831
 
 
6832
    If the file name is not specified, the revisions starting with the
 
6833
    current directory are searched recursively. If the revision number is
 
6834
    not specified, the working copy is searched. To search the last committed
 
6835
    revision, use the '-r -1' or '-r last:1' option.
 
6836
 
 
6837
    Unversioned files are not searched unless explicitly specified on the
 
6838
    command line. Unversioned directores are not searched.
 
6839
 
 
6840
    When searching a pattern, the output is shown in the 'filepath:string'
 
6841
    format. If a revision is explicitly searched, the output is shown as
 
6842
    'filepath~N:string', where N is the revision number.
 
6843
 
 
6844
    --include and --exclude options can be used to search only (or exclude
 
6845
    from search) files with base name matches the specified Unix style GLOB
 
6846
    pattern.  The GLOB pattern an use *, ?, and [...] as wildcards, and \\
 
6847
    to quote wildcard or backslash character literally. Note that the glob
 
6848
    pattern is not a regular expression.
 
6849
 
 
6850
    [1] http://docs.python.org/library/re.html#regular-expression-syntax
 
6851
    """
 
6852
 
 
6853
    encoding_type = 'replace'
 
6854
    takes_args = ['pattern', 'path*']
 
6855
    takes_options = [
 
6856
        'verbose',
 
6857
        'revision',
 
6858
        Option('color', type=text_type, argname='when',
 
6859
               help='Show match in color. WHEN is never, always or auto.'),
 
6860
        Option('diff', short_name='p',
 
6861
               help='Grep for pattern in changeset for each revision.'),
 
6862
        ListOption('exclude', type=text_type, argname='glob', short_name='X',
 
6863
                   help="Skip files whose base name matches GLOB."),
 
6864
        ListOption('include', type=text_type, argname='glob', short_name='I',
 
6865
                   help="Search only files whose base name matches GLOB."),
 
6866
        Option('files-with-matches', short_name='l',
 
6867
               help='Print only the name of each input file in '
 
6868
               'which PATTERN is found.'),
 
6869
        Option('files-without-match', short_name='L',
 
6870
               help='Print only the name of each input file in '
 
6871
               'which PATTERN is not found.'),
 
6872
        Option('fixed-string', short_name='F',
 
6873
               help='Interpret PATTERN is a single fixed string (not regex).'),
 
6874
        Option('from-root',
 
6875
               help='Search for pattern starting from the root of the branch. '
 
6876
               '(implies --recursive)'),
 
6877
        Option('ignore-case', short_name='i',
 
6878
               help='Ignore case distinctions while matching.'),
 
6879
        Option('levels',
 
6880
               help='Number of levels to display - 0 for all, 1 for collapsed '
 
6881
               '(1 is default).',
 
6882
               argname='N',
 
6883
               type=_parse_levels),
 
6884
        Option('line-number', short_name='n',
 
6885
               help='Show 1-based line number.'),
 
6886
        Option('no-recursive',
 
6887
               help="Don't recurse into subdirectories. (default is --recursive)"),
 
6888
        Option('null', short_name='Z',
 
6889
               help='Write an ASCII NUL (\\0) separator '
 
6890
               'between output lines rather than a newline.'),
 
6891
        ]
 
6892
 
 
6893
    @display_command
 
6894
    def run(self, verbose=False, ignore_case=False, no_recursive=False,
 
6895
            from_root=False, null=False, levels=None, line_number=False,
 
6896
            path_list=None, revision=None, pattern=None, include=None,
 
6897
            exclude=None, fixed_string=False, files_with_matches=False,
 
6898
            files_without_match=False, color=None, diff=False):
 
6899
        from breezy import _termcolor
 
6900
        from . import grep
 
6901
        import re
 
6902
        if path_list is None:
 
6903
            path_list = ['.']
 
6904
        else:
 
6905
            if from_root:
 
6906
                raise errors.BzrCommandError(
 
6907
                    'cannot specify both --from-root and PATH.')
 
6908
 
 
6909
        if files_with_matches and files_without_match:
 
6910
            raise errors.BzrCommandError(
 
6911
                'cannot specify both '
 
6912
                '-l/--files-with-matches and -L/--files-without-matches.')
 
6913
 
 
6914
        global_config = _mod_config.GlobalConfig()
 
6915
 
 
6916
        if color is None:
 
6917
            color = global_config.get_user_option('grep_color')
 
6918
 
 
6919
        if color is None:
 
6920
            color = 'never'
 
6921
 
 
6922
        if color not in ['always', 'never', 'auto']:
 
6923
            raise errors.BzrCommandError('Valid values for --color are '
 
6924
                                         '"always", "never" or "auto".')
 
6925
 
 
6926
        if levels is None:
 
6927
            levels = 1
 
6928
 
 
6929
        print_revno = False
 
6930
        if revision is not None or levels == 0:
 
6931
            # print revision numbers as we may be showing multiple revisions
 
6932
            print_revno = True
 
6933
 
 
6934
        eol_marker = '\n'
 
6935
        if null:
 
6936
            eol_marker = '\0'
 
6937
 
 
6938
        if not ignore_case and grep.is_fixed_string(pattern):
 
6939
            # if the pattern isalnum, implicitly use to -F for faster grep
 
6940
            fixed_string = True
 
6941
        elif ignore_case and fixed_string:
 
6942
            # GZ 2010-06-02: Fall back to regexp rather than lowercasing
 
6943
            #                pattern and text which will cause pain later
 
6944
            fixed_string = False
 
6945
            pattern = re.escape(pattern)
 
6946
 
 
6947
        patternc = None
 
6948
        re_flags = re.MULTILINE
 
6949
        if ignore_case:
 
6950
            re_flags |= re.IGNORECASE
 
6951
 
 
6952
        if not fixed_string:
 
6953
            patternc = grep.compile_pattern(
 
6954
                pattern.encode(grep._user_encoding), re_flags)
 
6955
 
 
6956
        if color == 'always':
 
6957
            show_color = True
 
6958
        elif color == 'never':
 
6959
            show_color = False
 
6960
        elif color == 'auto':
 
6961
            show_color = _termcolor.allow_color()
 
6962
 
 
6963
        opts = grep.GrepOptions()
 
6964
 
 
6965
        opts.verbose = verbose
 
6966
        opts.ignore_case = ignore_case
 
6967
        opts.no_recursive = no_recursive
 
6968
        opts.from_root = from_root
 
6969
        opts.null = null
 
6970
        opts.levels = levels
 
6971
        opts.line_number = line_number
 
6972
        opts.path_list = path_list
 
6973
        opts.revision = revision
 
6974
        opts.pattern = pattern
 
6975
        opts.include = include
 
6976
        opts.exclude = exclude
 
6977
        opts.fixed_string = fixed_string
 
6978
        opts.files_with_matches = files_with_matches
 
6979
        opts.files_without_match = files_without_match
 
6980
        opts.color = color
 
6981
        opts.diff = False
 
6982
 
 
6983
        opts.eol_marker = eol_marker
 
6984
        opts.print_revno = print_revno
 
6985
        opts.patternc = patternc
 
6986
        opts.recursive = not no_recursive
 
6987
        opts.fixed_string = fixed_string
 
6988
        opts.outf = self.outf
 
6989
        opts.show_color = show_color
 
6990
 
 
6991
        if diff:
 
6992
            # options not used:
 
6993
            # files_with_matches, files_without_match
 
6994
            # levels(?), line_number, from_root
 
6995
            # include, exclude
 
6996
            # These are silently ignored.
 
6997
            grep.grep_diff(opts)
 
6998
        elif revision is None:
 
6999
            grep.workingtree_grep(opts)
 
7000
        else:
 
7001
            grep.versioned_grep(opts)
 
7002
 
 
7003
 
 
7004
class cmd_resolve_location(Command):
 
7005
    __doc__ = """Expand a location to a full URL.
 
7006
 
 
7007
    :Examples:
 
7008
        Look up a Launchpad URL.
 
7009
 
 
7010
            brz resolve-location lp:brz
 
7011
    """
 
7012
    takes_args = ['location']
 
7013
    hidden = True
 
7014
 
 
7015
    def run(self, location):
 
7016
        from .location import location_to_url
 
7017
        url = location_to_url(location)
 
7018
        display_url = urlutils.unescape_for_display(url, self.outf.encoding)
 
7019
        self.outf.write('%s\n' % url)
 
7020
 
 
7021
 
6786
7022
def _register_lazy_builtins():
6787
7023
    # register lazy builtins from other modules; called at startup and should
6788
7024
    # be only called once.
6789
7025
    for (name, aliases, module_name) in [
6790
 
        ('cmd_bisect', [], 'breezy.bisect'),
6791
 
        ('cmd_bundle_info', [], 'breezy.bundle.commands'),
6792
 
        ('cmd_config', [], 'breezy.config'),
6793
 
        ('cmd_dump_btree', [], 'breezy.bzr.debug_commands'),
6794
 
        ('cmd_version_info', [], 'breezy.cmd_version_info'),
6795
 
        ('cmd_resolve', ['resolved'], 'breezy.conflicts'),
6796
 
        ('cmd_conflicts', [], 'breezy.conflicts'),
6797
 
        ('cmd_ping', [], 'breezy.bzr.smart.ping'),
6798
 
        ('cmd_sign_my_commits', [], 'breezy.commit_signature_commands'),
6799
 
        ('cmd_verify_signatures', [], 'breezy.commit_signature_commands'),
6800
 
        ('cmd_test_script', [], 'breezy.cmd_test_script'),
6801
 
        ]:
 
7026
            ('cmd_bisect', [], 'breezy.bisect'),
 
7027
            ('cmd_bundle_info', [], 'breezy.bundle.commands'),
 
7028
            ('cmd_config', [], 'breezy.config'),
 
7029
            ('cmd_dump_btree', [], 'breezy.bzr.debug_commands'),
 
7030
            ('cmd_file_id', [], 'breezy.bzr.debug_commands'),
 
7031
            ('cmd_file_path', [], 'breezy.bzr.debug_commands'),
 
7032
            ('cmd_version_info', [], 'breezy.cmd_version_info'),
 
7033
            ('cmd_resolve', ['resolved'], 'breezy.conflicts'),
 
7034
            ('cmd_conflicts', [], 'breezy.conflicts'),
 
7035
            ('cmd_ping', [], 'breezy.bzr.smart.ping'),
 
7036
            ('cmd_sign_my_commits', [], 'breezy.commit_signature_commands'),
 
7037
            ('cmd_verify_signatures', [], 'breezy.commit_signature_commands'),
 
7038
            ('cmd_test_script', [], 'breezy.cmd_test_script'),
 
7039
            ]:
6802
7040
        builtin_command_registry.register_lazy(name, aliases, module_name)