/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 bzrlib/builtins.py

  • Committer: Robert Collins
  • Date: 2006-06-09 09:04:53 UTC
  • mfrom: (1755.2.1 add)
  • mto: (1755.1.2 integration)
  • mto: This revision was merged to the branch mainline in revision 1757.
  • Revision ID: robertc@robertcollins.net-20060609090453-10e94172dc5f670b
MergeĀ currentĀ head.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""builtin bzr commands"""
18
18
 
19
19
 
 
20
import codecs
20
21
import errno
21
22
import os
 
23
from shutil import rmtree
22
24
import sys
23
25
 
24
26
import bzrlib
25
27
import bzrlib.branch
26
28
from bzrlib.branch import Branch
27
29
import bzrlib.bzrdir as bzrdir
 
30
from bzrlib.bundle.read_bundle import BundleReader
 
31
from bzrlib.bundle.apply_bundle import merge_bundle
28
32
from bzrlib.commands import Command, display_command
29
33
import bzrlib.errors as errors
30
34
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
31
35
                           NotBranchError, DivergedBranches, NotConflicted,
32
36
                           NoSuchFile, NoWorkingTree, FileInWrongBranch,
33
 
                           NotVersionedError)
 
37
                           NotVersionedError, NotABundle)
34
38
from bzrlib.log import show_one_log
35
39
from bzrlib.merge import Merge3Merger
36
40
from bzrlib.option import Option
 
41
import bzrlib.osutils
37
42
from bzrlib.progress import DummyProgress, ProgressPhase
38
43
from bzrlib.revision import common_ancestor
39
44
from bzrlib.revisionspec import RevisionSpec
41
46
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
42
47
from bzrlib.transport.local import LocalTransport
43
48
import bzrlib.ui
 
49
import bzrlib.urlutils as urlutils
44
50
from bzrlib.workingtree import WorkingTree
45
51
 
46
52
 
150
156
    takes_args = ['file*']
151
157
    takes_options = ['all', 'show-ids', 'revision']
152
158
    aliases = ['st', 'stat']
 
159
 
 
160
    encoding_type = 'replace'
153
161
    
154
162
    @display_command
155
163
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
156
 
        tree, file_list = tree_files(file_list)
157
 
            
158
164
        from bzrlib.status import show_tree_status
 
165
 
 
166
        tree, file_list = tree_files(file_list)
 
167
            
159
168
        show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
160
 
                         specific_files=file_list, revision=revision)
 
169
                         specific_files=file_list, revision=revision,
 
170
                         to_file=self.outf)
161
171
 
162
172
 
163
173
class cmd_cat_revision(Command):
170
180
    hidden = True
171
181
    takes_args = ['revision_id?']
172
182
    takes_options = ['revision']
 
183
    # cat-revision is more for frontends so should be exact
 
184
    encoding = 'strict'
173
185
    
174
186
    @display_command
175
187
    def run(self, revision_id=None, revision=None):
179
191
        if revision_id is None and revision is None:
180
192
            raise BzrCommandError('You must supply either --revision or a revision_id')
181
193
        b = WorkingTree.open_containing(u'.')[0].branch
 
194
 
 
195
        # TODO: jam 20060112 should cat-revision always output utf-8?
182
196
        if revision_id is not None:
183
 
            sys.stdout.write(b.repository.get_revision_xml(revision_id))
 
197
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
184
198
        elif revision is not None:
185
199
            for rev in revision:
186
200
                if rev is None:
187
201
                    raise BzrCommandError('You cannot specify a NULL revision.')
188
202
                revno, rev_id = rev.in_history(b)
189
 
                sys.stdout.write(b.repository.get_revision_xml(rev_id))
 
203
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
190
204
    
191
205
 
192
206
class cmd_revno(Command):
193
207
    """Show current revision number.
194
208
 
195
 
    This is equal to the number of revisions on this branch."""
 
209
    This is equal to the number of revisions on this branch.
 
210
    """
 
211
 
196
212
    takes_args = ['location?']
 
213
 
197
214
    @display_command
198
215
    def run(self, location=u'.'):
199
 
        print Branch.open_containing(location)[0].revno()
 
216
        self.outf.write(str(Branch.open_containing(location)[0].revno()))
 
217
        self.outf.write('\n')
200
218
 
201
219
 
202
220
class cmd_revision_info(Command):
205
223
    hidden = True
206
224
    takes_args = ['revision_info*']
207
225
    takes_options = ['revision']
 
226
 
208
227
    @display_command
209
228
    def run(self, revision=None, revision_info_list=[]):
210
229
 
255
274
    """
256
275
    takes_args = ['file*']
257
276
    takes_options = ['no-recurse', 'dry-run', 'verbose']
 
277
    encoding_type = 'replace'
258
278
 
259
279
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
260
280
        import bzrlib.add
261
281
 
262
 
        if dry_run:
263
 
            if is_quiet():
264
 
                # This is pointless, but I'd rather not raise an error
265
 
                action = bzrlib.add.add_action_null
266
 
            else:
267
 
                action = bzrlib.add.add_action_print
268
 
        elif is_quiet():
269
 
            action = bzrlib.add.add_action_add
270
 
        else:
271
 
            action = bzrlib.add.add_action_add_and_print
 
282
        action = bzrlib.add.AddAction(to_file=self.outf,
 
283
            should_add=(not dry_run), should_print=(not is_quiet()))
272
284
 
273
285
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse, 
274
 
                                              action)
 
286
                                              action=action)
275
287
        if len(ignored) > 0:
276
288
            if verbose:
277
289
                for glob in sorted(ignored.keys()):
278
290
                    for path in ignored[glob]:
279
 
                        print "ignored %s matching \"%s\"" % (path, glob)
 
291
                        self.outf.write("ignored %s matching \"%s\"\n" 
 
292
                                        % (path, glob))
280
293
            else:
281
294
                match_len = 0
282
295
                for glob, paths in ignored.items():
283
296
                    match_len += len(paths)
284
 
                print "ignored %d file(s)." % match_len
285
 
            print "If you wish to add some of these files, please add them"\
286
 
                " by name."
 
297
                self.outf.write("ignored %d file(s).\n" % match_len)
 
298
            self.outf.write("If you wish to add some of these files,"
 
299
                            " please add them by name.\n")
287
300
 
288
301
 
289
302
class cmd_mkdir(Command):
291
304
 
292
305
    This is equivalent to creating the directory and then adding it.
293
306
    """
 
307
 
294
308
    takes_args = ['dir+']
 
309
    encoding_type = 'replace'
295
310
 
296
311
    def run(self, dir_list):
297
312
        for d in dir_list:
298
313
            os.mkdir(d)
299
314
            wt, dd = WorkingTree.open_containing(d)
300
315
            wt.add([dd])
301
 
            print 'added', d
 
316
            self.outf.write('added %s\n' % d)
302
317
 
303
318
 
304
319
class cmd_relpath(Command):
305
320
    """Show path of a file relative to root"""
 
321
 
306
322
    takes_args = ['filename']
307
323
    hidden = True
308
324
    
309
325
    @display_command
310
326
    def run(self, filename):
 
327
        # TODO: jam 20050106 Can relpath return a munged path if
 
328
        #       sys.stdout encoding cannot represent it?
311
329
        tree, relpath = WorkingTree.open_containing(filename)
312
 
        print relpath
 
330
        self.outf.write(relpath)
 
331
        self.outf.write('\n')
313
332
 
314
333
 
315
334
class cmd_inventory(Command):
318
337
    It is possible to limit the output to a particular entry
319
338
    type using the --kind option.  For example; --kind file.
320
339
    """
 
340
 
321
341
    takes_options = ['revision', 'show-ids', 'kind']
322
342
    
323
343
    @display_command
338
358
            if kind and kind != entry.kind:
339
359
                continue
340
360
            if show_ids:
341
 
                print '%-50s %s' % (path, entry.file_id)
 
361
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
342
362
            else:
343
 
                print path
 
363
                self.outf.write(path)
 
364
                self.outf.write('\n')
344
365
 
345
366
 
346
367
class cmd_mv(Command):
356
377
 
357
378
    Files cannot be moved between branches.
358
379
    """
 
380
 
359
381
    takes_args = ['names*']
360
382
    aliases = ['move', 'rename']
 
383
    encoding_type = 'replace'
361
384
 
362
385
    def run(self, names_list):
363
386
        if len(names_list) < 2:
367
390
        if os.path.isdir(names_list[-1]):
368
391
            # move into existing directory
369
392
            for pair in tree.move(rel_names[:-1], rel_names[-1]):
370
 
                print "%s => %s" % pair
 
393
                self.outf.write("%s => %s\n" % pair)
371
394
        else:
372
395
            if len(names_list) != 2:
373
396
                raise BzrCommandError('to mv multiple files the destination '
374
397
                                      'must be a versioned directory')
375
398
            tree.rename_one(rel_names[0], rel_names[1])
376
 
            print "%s => %s" % (rel_names[0], rel_names[1])
 
399
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
377
400
            
378
401
    
379
402
class cmd_pull(Command):
398
421
    that, you can omit the location to use the default.  To change the
399
422
    default, use --remember.
400
423
    """
 
424
 
401
425
    takes_options = ['remember', 'overwrite', 'revision', 'verbose']
402
426
    takes_args = ['location?']
 
427
    encoding_type = 'replace'
403
428
 
404
429
    def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
405
430
        # FIXME: too much stuff is in the command class
408
433
            branch_to = tree_to.branch
409
434
        except NoWorkingTree:
410
435
            tree_to = None
411
 
            branch_to = Branch.open_containing(u'.')[0] 
 
436
            branch_to = Branch.open_containing(u'.')[0]
412
437
        stored_loc = branch_to.get_parent()
413
438
        if location is None:
414
439
            if stored_loc is None:
415
440
                raise BzrCommandError("No pull location known or specified.")
416
441
            else:
417
 
                print "Using saved location: %s" % stored_loc
 
442
                display_url = urlutils.unescape_for_display(stored_loc,
 
443
                        self.outf.encoding)
 
444
                self.outf.write("Using saved location: %s\n" % display_url)
418
445
                location = stored_loc
419
446
 
 
447
        branch_from = Branch.open(location)
 
448
 
420
449
        if branch_to.get_parent() is None or remember:
421
 
            branch_to.set_parent(location)
422
 
 
423
 
        branch_from = Branch.open(location)
 
450
            branch_to.set_parent(branch_from.base)
424
451
 
425
452
        if revision is None:
426
453
            rev_id = None
441
468
            if old_rh != new_rh:
442
469
                # Something changed
443
470
                from bzrlib.log import show_changed_revisions
444
 
                show_changed_revisions(branch_to, old_rh, new_rh)
 
471
                show_changed_revisions(branch_to, old_rh, new_rh,
 
472
                                       to_file=self.outf)
445
473
 
446
474
 
447
475
class cmd_push(Command):
468
496
    After that, you can omit the location to use the default.  To change the
469
497
    default, use --remember.
470
498
    """
471
 
    takes_options = ['remember', 'overwrite', 
 
499
 
 
500
    takes_options = ['remember', 'overwrite', 'verbose',
472
501
                     Option('create-prefix', 
473
502
                            help='Create the path leading up to the branch '
474
503
                                 'if it does not already exist')]
475
504
    takes_args = ['location?']
 
505
    encoding_type = 'replace'
476
506
 
477
507
    def run(self, location=None, remember=False, overwrite=False,
478
508
            create_prefix=False, verbose=False):
486
516
            if stored_loc is None:
487
517
                raise BzrCommandError("No push location known or specified.")
488
518
            else:
489
 
                print "Using saved location: %s" % stored_loc
 
519
                display_url = urlutils.unescape_for_display(stored_loc,
 
520
                        self.outf.encoding)
 
521
                self.outf.write("Using saved location: %s" % display_url)
490
522
                location = stored_loc
 
523
 
 
524
        transport = get_transport(location)
 
525
        location_url = transport.base
491
526
        if br_from.get_push_location() is None or remember:
492
 
            br_from.set_push_location(location)
 
527
            br_from.set_push_location(location_url)
 
528
 
 
529
        old_rh = []
493
530
        try:
494
 
            dir_to = bzrlib.bzrdir.BzrDir.open(location)
 
531
            dir_to = bzrlib.bzrdir.BzrDir.open(location_url)
495
532
            br_to = dir_to.open_branch()
496
533
        except NotBranchError:
497
534
            # create a branch.
498
 
            transport = get_transport(location).clone('..')
 
535
            transport = transport.clone('..')
499
536
            if not create_prefix:
500
537
                try:
501
 
                    transport.mkdir(transport.relpath(location))
 
538
                    relurl = transport.relpath(location_url)
 
539
                    mutter('creating directory %s => %s', location_url, relurl)
 
540
                    transport.mkdir(relurl)
502
541
                except NoSuchFile:
503
542
                    raise BzrCommandError("Parent directory of %s "
504
543
                                          "does not exist." % location)
505
544
            else:
506
545
                current = transport.base
507
 
                needed = [(transport, transport.relpath(location))]
 
546
                needed = [(transport, transport.relpath(location_url))]
508
547
                while needed:
509
548
                    try:
510
549
                        transport, relpath = needed[-1]
517
556
                        if new_transport.base == transport.base:
518
557
                            raise BzrCommandError("Could not create "
519
558
                                                  "path prefix.")
520
 
            dir_to = br_from.bzrdir.clone(location,
 
559
            dir_to = br_from.bzrdir.clone(location_url,
521
560
                revision_id=br_from.last_revision())
522
561
            br_to = dir_to.open_branch()
523
562
            count = len(br_to.revision_history())
544
583
            if old_rh != new_rh:
545
584
                # Something changed
546
585
                from bzrlib.log import show_changed_revisions
547
 
                show_changed_revisions(br_to, old_rh, new_rh)
 
586
                show_changed_revisions(br_to, old_rh, new_rh,
 
587
                                       to_file=self.outf)
548
588
 
549
589
 
550
590
class cmd_branch(Command):
565
605
    aliases = ['get', 'clone']
566
606
 
567
607
    def run(self, from_location, to_location=None, revision=None, basis=None):
 
608
        from bzrlib.transport import get_transport
568
609
        from bzrlib.osutils import rmtree
569
610
        if revision is None:
570
611
            revision = [None]
597
638
                name = None
598
639
            else:
599
640
                name = os.path.basename(to_location) + '\n'
 
641
 
 
642
            to_transport = get_transport(to_location)
600
643
            try:
601
 
                os.mkdir(to_location)
602
 
            except OSError, e:
603
 
                if e.errno == errno.EEXIST:
604
 
                    raise BzrCommandError('Target directory "%s" already'
605
 
                                          ' exists.' % to_location)
606
 
                if e.errno == errno.ENOENT:
607
 
                    raise BzrCommandError('Parent of "%s" does not exist.' %
608
 
                                          to_location)
609
 
                else:
610
 
                    raise
 
644
                to_transport.mkdir('.')
 
645
            except bzrlib.errors.FileExists:
 
646
                raise BzrCommandError('Target directory "%s" already'
 
647
                                      ' exists.' % to_location)
 
648
            except bzrlib.errors.NoSuchFile:
 
649
                raise BzrCommandError('Parent of "%s" does not exist.' %
 
650
                                      to_location)
611
651
            try:
612
652
                # preserve whatever source format we have.
613
 
                dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
 
653
                dir = br_from.bzrdir.sprout(to_transport.base,
 
654
                        revision_id, basis_dir)
614
655
                branch = dir.open_branch()
615
656
            except bzrlib.errors.NoSuchRevision:
616
 
                rmtree(to_location)
 
657
                to_transport.delete_tree('.')
617
658
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
618
659
                raise BzrCommandError(msg)
619
660
            except bzrlib.errors.UnlistableBranch:
622
663
                raise BzrCommandError(msg)
623
664
            if name:
624
665
                branch.control_files.put_utf8('branch-name', name)
625
 
 
626
666
            note('Branched %d revision(s).' % branch.revno())
627
667
        finally:
628
668
            br_from.unlock()
733
773
        renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
734
774
        renames.sort()
735
775
        for old_name, new_name in renames:
736
 
            print "%s => %s" % (old_name, new_name)        
 
776
            self.outf.write("%s => %s\n" % (old_name, new_name))
737
777
 
738
778
 
739
779
class cmd_update(Command):
793
833
 
794
834
    This makes bzr stop tracking changes to a versioned file.  It does
795
835
    not delete the working copy.
 
836
 
 
837
    You can specify one or more files, and/or --new.  If you specify --new,
 
838
    only 'added' files will be removed.  If you specify both, then new files
 
839
    in the specified directories will be removed.  If the directories are
 
840
    also new, they will also be removed.
796
841
    """
797
 
    takes_args = ['file+']
798
 
    takes_options = ['verbose']
 
842
    takes_args = ['file*']
 
843
    takes_options = ['verbose', Option('new', help='remove newly-added files')]
799
844
    aliases = ['rm']
 
845
    encoding_type = 'replace'
800
846
    
801
 
    def run(self, file_list, verbose=False):
 
847
    def run(self, file_list, verbose=False, new=False):
802
848
        tree, file_list = tree_files(file_list)
803
 
        tree.remove(file_list, verbose=verbose)
 
849
        if new is False:
 
850
            if file_list is None:
 
851
                raise BzrCommandError('Specify one or more files to remove, or'
 
852
                                      ' use --new.')
 
853
        else:
 
854
            from bzrlib.delta import compare_trees
 
855
            added = [compare_trees(tree.basis_tree(), tree,
 
856
                                   specific_files=file_list).added]
 
857
            file_list = sorted([f[0] for f in added[0]], reverse=True)
 
858
            if len(file_list) == 0:
 
859
                raise BzrCommandError('No matching files.')
 
860
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
804
861
 
805
862
 
806
863
class cmd_file_id(Command):
810
867
    same through all revisions where the file exists, even when it is
811
868
    moved or renamed.
812
869
    """
 
870
 
813
871
    hidden = True
814
872
    takes_args = ['filename']
 
873
 
815
874
    @display_command
816
875
    def run(self, filename):
817
876
        tree, relpath = WorkingTree.open_containing(filename)
819
878
        if i == None:
820
879
            raise BzrError("%r is not a versioned file" % filename)
821
880
        else:
822
 
            print i
 
881
            self.outf.write(i + '\n')
823
882
 
824
883
 
825
884
class cmd_file_path(Command):
826
885
    """Print path of file_ids to a file or directory.
827
886
 
828
887
    This prints one line for each directory down to the target,
829
 
    starting at the branch root."""
 
888
    starting at the branch root.
 
889
    """
 
890
 
830
891
    hidden = True
831
892
    takes_args = ['filename']
 
893
 
832
894
    @display_command
833
895
    def run(self, filename):
834
896
        tree, relpath = WorkingTree.open_containing(filename)
837
899
        if fid == None:
838
900
            raise BzrError("%r is not a versioned file" % filename)
839
901
        for fip in inv.get_idpath(fid):
840
 
            print fip
 
902
            self.outf.write(fip + '\n')
841
903
 
842
904
 
843
905
class cmd_reconcile(Command):
869
931
class cmd_revision_history(Command):
870
932
    """Display list of revision ids on this branch."""
871
933
    hidden = True
 
934
 
872
935
    @display_command
873
936
    def run(self):
874
937
        branch = WorkingTree.open_containing(u'.')[0].branch
875
938
        for patchid in branch.revision_history():
876
 
            print patchid
 
939
            self.outf.write(patchid)
 
940
            self.outf.write('\n')
877
941
 
878
942
 
879
943
class cmd_ancestry(Command):
880
944
    """List all revisions merged into this branch."""
881
945
    hidden = True
 
946
 
882
947
    @display_command
883
948
    def run(self):
884
949
        tree = WorkingTree.open_containing(u'.')[0]
888
953
        assert revision_ids[0] == None
889
954
        revision_ids.pop(0)
890
955
        for revision_id in revision_ids:
891
 
            print revision_id
 
956
            self.outf.write(revision_id + '\n')
892
957
 
893
958
 
894
959
class cmd_init(Command):
1019
1084
    takes_args = ['file*']
1020
1085
    takes_options = ['revision', 'diff-options', 'prefix']
1021
1086
    aliases = ['di', 'dif']
 
1087
    encoding_type = 'exact'
1022
1088
 
1023
1089
    @display_command
1024
1090
    def run(self, revision=None, file_list=None, diff_options=None,
1085
1151
    # directories with readdir, rather than stating each one.  Same
1086
1152
    # level of effort but possibly much less IO.  (Or possibly not,
1087
1153
    # if the directories are very large...)
 
1154
    takes_options = ['show-ids']
 
1155
 
1088
1156
    @display_command
1089
1157
    def run(self, show_ids=False):
1090
1158
        tree = WorkingTree.open_containing(u'.')[0]
1091
1159
        old = tree.basis_tree()
1092
1160
        for path, ie in old.inventory.iter_entries():
1093
1161
            if not tree.has_id(ie.file_id):
 
1162
                self.outf.write(path)
1094
1163
                if show_ids:
1095
 
                    print '%-50s %s' % (path, ie.file_id)
1096
 
                else:
1097
 
                    print path
 
1164
                    self.outf.write(' ')
 
1165
                    self.outf.write(ie.file_id)
 
1166
                self.outf.write('\n')
1098
1167
 
1099
1168
 
1100
1169
class cmd_modified(Command):
1108
1177
        td = compare_trees(tree.basis_tree(), tree)
1109
1178
 
1110
1179
        for path, id, kind, text_modified, meta_modified in td.modified:
1111
 
            print path
1112
 
 
 
1180
            self.outf.write(path + '\n')
1113
1181
 
1114
1182
 
1115
1183
class cmd_added(Command):
1126
1194
            path = inv.id2path(file_id)
1127
1195
            if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
1128
1196
                continue
1129
 
            print path
1130
 
                
1131
 
        
 
1197
            self.outf.write(path + '\n')
 
1198
 
1132
1199
 
1133
1200
class cmd_root(Command):
1134
1201
    """Show the tree root directory.
1140
1207
    def run(self, filename=None):
1141
1208
        """Print the branch root."""
1142
1209
        tree = WorkingTree.open_containing(filename)[0]
1143
 
        print tree.basedir
 
1210
        self.outf.write(tree.basedir + '\n')
1144
1211
 
1145
1212
 
1146
1213
class cmd_log(Command):
1174
1241
                            type=str),
1175
1242
                     'short',
1176
1243
                     ]
 
1244
    encoding_type = 'replace'
 
1245
 
1177
1246
    @display_command
1178
1247
    def run(self, location=None, timezone='original',
1179
1248
            verbose=False,
1186
1255
            short=False,
1187
1256
            line=False):
1188
1257
        from bzrlib.log import log_formatter, show_log
1189
 
        import codecs
1190
1258
        assert message is None or isinstance(message, basestring), \
1191
1259
            "invalid message argument %r" % message
1192
1260
        direction = (forward and 'forward') or 'reverse'
1238
1306
        if rev1 > rev2:
1239
1307
            (rev2, rev1) = (rev1, rev2)
1240
1308
 
1241
 
        mutter('encoding log as %r', bzrlib.user_encoding)
1242
 
 
1243
 
        # use 'replace' so that we don't abort if trying to write out
1244
 
        # in e.g. the default C locale.
1245
 
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
1246
 
 
1247
1309
        if (log_format == None):
1248
1310
            default = bzrlib.config.BranchConfig(b).log_format()
1249
1311
            log_format = get_log_format(long=long, short=short, line=line, default=default)
1250
 
 
1251
1312
        lf = log_formatter(log_format,
1252
1313
                           show_ids=show_ids,
1253
 
                           to_file=outf,
 
1314
                           to_file=self.outf,
1254
1315
                           show_timezone=timezone)
1255
1316
 
1256
1317
        show_log(b,
1277
1338
class cmd_touching_revisions(Command):
1278
1339
    """Return revision-ids which affected a particular file.
1279
1340
 
1280
 
    A more user-friendly interface is "bzr log FILE"."""
 
1341
    A more user-friendly interface is "bzr log FILE".
 
1342
    """
 
1343
 
1281
1344
    hidden = True
1282
1345
    takes_args = ["filename"]
 
1346
 
1283
1347
    @display_command
1284
1348
    def run(self, filename):
1285
1349
        tree, relpath = WorkingTree.open_containing(filename)
1287
1351
        inv = tree.read_working_inventory()
1288
1352
        file_id = inv.path2id(relpath)
1289
1353
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
1290
 
            print "%6d %s" % (revno, what)
 
1354
            self.outf.write("%6d %s\n" % (revno, what))
1291
1355
 
1292
1356
 
1293
1357
class cmd_ls(Command):
1326
1390
        if revision is not None:
1327
1391
            tree = tree.branch.repository.revision_tree(
1328
1392
                revision[0].in_history(tree.branch).rev_id)
 
1393
 
1329
1394
        for fp, fc, kind, fid, entry in tree.list_files():
1330
1395
            if fp.startswith(relpath):
1331
1396
                fp = fp[len(relpath):]
1335
1400
                    continue
1336
1401
                if verbose:
1337
1402
                    kindch = entry.kind_character()
1338
 
                    print '%-8s %s%s' % (fc, fp, kindch)
 
1403
                    self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
1339
1404
                elif null:
1340
 
                    sys.stdout.write(fp)
1341
 
                    sys.stdout.write('\0')
1342
 
                    sys.stdout.flush()
 
1405
                    self.outf.write(fp + '\0')
 
1406
                    self.outf.flush()
1343
1407
                else:
1344
 
                    print fp
 
1408
                    self.outf.write(fp + '\n')
1345
1409
 
1346
1410
 
1347
1411
class cmd_unknowns(Command):
1350
1414
    def run(self):
1351
1415
        from bzrlib.osutils import quotefn
1352
1416
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
1353
 
            print quotefn(f)
 
1417
            self.outf.write(quotefn(f) + '\n')
1354
1418
 
1355
1419
 
1356
1420
class cmd_ignore(Command):
1573
1637
        from bzrlib.msgeditor import edit_commit_message, \
1574
1638
                make_commit_message_template
1575
1639
        from tempfile import TemporaryFile
1576
 
        import codecs
1577
1640
 
1578
1641
        # TODO: Need a blackbox test for invoking the external editor; may be
1579
1642
        # slightly problematic to run this cross-platform.
1602
1665
            raise BzrCommandError("please specify either --message or --file")
1603
1666
        
1604
1667
        if file:
1605
 
            import codecs
1606
1668
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1607
1669
 
1608
1670
        if message == "":
1858
1920
        print "  nick: %s" % (branch.nick,)
1859
1921
        if rh:
1860
1922
            print "  revid: %s" % (rh[-1],)
 
1923
    print "Using python interpreter:", sys.executable
 
1924
    import site
 
1925
    print "Using python standard library:", os.path.dirname(site.__file__)
 
1926
    print "Using bzrlib:",
 
1927
    if len(bzrlib.__path__) > 1:
 
1928
        # print repr, which is a good enough way of making it clear it's
 
1929
        # more than one element (eg ['/foo/bar', '/foo/bzr'])
 
1930
        print repr(bzrlib.__path__)
 
1931
    else:
 
1932
        print bzrlib.__path__[0]
 
1933
 
 
1934
    print
1861
1935
    print bzrlib.__copyright__
1862
1936
    print "http://bazaar-vcs.org/"
1863
1937
    print
1977
2051
            merge_type = Merge3Merger
1978
2052
 
1979
2053
        tree = WorkingTree.open_containing(u'.')[0]
1980
 
        stored_loc = tree.branch.get_parent()
1981
 
        if branch is None:
1982
 
            if stored_loc is None:
1983
 
                raise BzrCommandError("No merge branch known or specified.")
1984
 
            else:
1985
 
                print "Using saved branch: %s" % stored_loc
1986
 
                branch = stored_loc
1987
 
 
1988
 
        if tree.branch.get_parent() is None or remember:
1989
 
            tree.branch.set_parent(branch)
 
2054
 
 
2055
        try:
 
2056
            if branch is not None:
 
2057
                reader = BundleReader(file(branch, 'rb'))
 
2058
            else:
 
2059
                reader = None
 
2060
        except IOError, e:
 
2061
            if e.errno not in (errno.ENOENT, errno.EISDIR):
 
2062
                raise
 
2063
            reader = None
 
2064
        except NotABundle:
 
2065
            reader = None
 
2066
        if reader is not None:
 
2067
            conflicts = merge_bundle(reader, tree, not force, merge_type,
 
2068
                                        reprocess, show_base)
 
2069
            if conflicts == 0:
 
2070
                return 0
 
2071
            else:
 
2072
                return 1
 
2073
 
 
2074
        branch = self._get_remembered_parent(tree, branch, 'Merging from')
1990
2075
 
1991
2076
        if revision is None or len(revision) < 1:
1992
2077
            base = [None, None]
2003
2088
                if None in revision:
2004
2089
                    raise BzrCommandError(
2005
2090
                        "Merge doesn't permit that revision specifier.")
2006
 
                b, path = Branch.open_containing(branch)
2007
 
 
2008
 
                base = [branch, revision[0].in_history(b).revno]
2009
 
                other = [branch, revision[1].in_history(b).revno]
 
2091
                other_branch, path = Branch.open_containing(branch)
 
2092
 
 
2093
                base = [branch, revision[0].in_history(other_branch).revno]
 
2094
                other = [branch, revision[1].in_history(other_branch).revno]
 
2095
 
 
2096
        if tree.branch.get_parent() is None or remember:
 
2097
            tree.branch.set_parent(other_branch.base)
 
2098
 
2010
2099
        if path != "":
2011
2100
            interesting_files = [path]
2012
2101
        else:
2015
2104
        try:
2016
2105
            try:
2017
2106
                conflict_count = merge(other, base, check_clean=(not force),
2018
 
                                       merge_type=merge_type, 
 
2107
                                       merge_type=merge_type,
2019
2108
                                       reprocess=reprocess,
2020
 
                                       show_base=show_base, 
 
2109
                                       show_base=show_base,
2021
2110
                                       pb=pb, file_list=interesting_files)
2022
2111
            finally:
2023
2112
                pb.finished()
2034
2123
                 "and (if you want) report this to the bzr developers\n")
2035
2124
            log_error(m)
2036
2125
 
 
2126
    # TODO: move up to common parent; this isn't merge-specific anymore. 
 
2127
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
 
2128
        """Use tree.branch's parent if none was supplied.
 
2129
 
 
2130
        Report if the remembered location was used.
 
2131
        """
 
2132
        if supplied_location is not None:
 
2133
            return supplied_location
 
2134
        stored_location = tree.branch.get_parent()
 
2135
        mutter("%s", stored_location)
 
2136
        if stored_location is None:
 
2137
            raise BzrCommandError("No location specified or remembered")
 
2138
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
 
2139
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
 
2140
        return stored_location
 
2141
 
2037
2142
 
2038
2143
class cmd_remerge(Command):
2039
2144
    """Redo a merge.
2284
2389
            try:
2285
2390
                # handle race conditions - a parent might be set while we run.
2286
2391
                if local_branch.get_parent() is None:
2287
 
                    local_branch.set_parent(other_branch)
 
2392
                    local_branch.set_parent(remote_branch.base)
2288
2393
            finally:
2289
2394
                local_branch.unlock()
2290
2395
        return status_code
2457
2562
    --dry-run will go through all the motions, but not actually
2458
2563
    remove anything.
2459
2564
    
2460
 
    In the future, uncommit will create a changeset, which can then
 
2565
    In the future, uncommit will create a revision bundle, which can then
2461
2566
    be re-applied.
2462
2567
    """
2463
2568
 
2617
2722
# aliases.  ideally we would avoid loading the implementation until the
2618
2723
# details were needed.
2619
2724
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
 
2725
from bzrlib.bundle.commands import cmd_bundle_revisions
2620
2726
from bzrlib.sign_my_commits import cmd_sign_my_commits
2621
2727
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
2622
2728
        cmd_weave_plan_merge, cmd_weave_merge_text