~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: mbp at sourcefrog
  • Date: 2005-04-07 02:40:18 UTC
  • Revision ID: mbp@sourcefrog.net-20050407024018-cf7130ea991f4ebc0c353ed2
more notes on svk

Show diffs side-by-side

added added

removed removed

Lines of Context:
62
62
 
63
63
 
64
64
 
65
 
import sys, os, random, time, sha, sets, types, re, shutil, tempfile
66
 
import traceback, socket, fnmatch, difflib
67
 
from os import path
 
65
import sys, os, time, types, shutil, tempfile, traceback, fnmatch, difflib, os.path
68
66
from sets import Set
69
67
from pprint import pprint
70
68
from stat import *
73
71
import bzrlib
74
72
from bzrlib.store import ImmutableStore
75
73
from bzrlib.trace import mutter, note, log_error
76
 
from bzrlib.errors import bailout, BzrError
 
74
from bzrlib.errors import bailout, BzrError, BzrCheckError
77
75
from bzrlib.osutils import quotefn, pumpfile, isdir, isfile
78
76
from bzrlib.tree import RevisionTree, EmptyTree, WorkingTree, Tree
79
77
from bzrlib.revision import Revision
180
178
    print Branch(filename).relpath(filename)
181
179
 
182
180
 
 
181
 
183
182
def cmd_inventory(revision=None):
184
183
    """Show inventory of the current working copy."""
185
184
    ## TODO: Also optionally show a previous inventory
195
194
 
196
195
 
197
196
 
 
197
# TODO: Maybe a 'mv' command that has the combined move/rename
 
198
# special behaviour of Unix?
 
199
 
 
200
def cmd_move(source_list, dest):
 
201
    b = Branch('.')
 
202
 
 
203
    b.move([b.relpath(s) for s in source_list], b.relpath(dest))
 
204
 
 
205
 
 
206
 
 
207
def cmd_rename(from_name, to_name):
 
208
    """Change the name of an entry.
 
209
 
 
210
usage: bzr rename FROM_NAME TO_NAME
 
211
 
 
212
examples:
 
213
  bzr rename frob.c frobber.c
 
214
  bzr rename src/frob.c lib/frob.c
 
215
 
 
216
It is an error if the destination name exists.
 
217
 
 
218
See also the 'move' command, which moves files into a different
 
219
directory without changing their name.
 
220
 
 
221
TODO: Some way to rename multiple files without invoking bzr for each
 
222
one?"""
 
223
    b = Branch('.')
 
224
    b.rename_one(b.relpath(from_name), b.relpath(to_name))
 
225
    
 
226
 
 
227
 
 
228
 
 
229
def cmd_renames(dir='.'):
 
230
    """Show list of renamed files.
 
231
 
 
232
usage: bzr renames [BRANCH]
 
233
 
 
234
TODO: Option to show renames between two historical versions.
 
235
 
 
236
TODO: Only show renames under dir, rather than in the whole branch.
 
237
"""
 
238
    b = Branch(dir)
 
239
    old_inv = b.basis_tree().inventory
 
240
    new_inv = b.read_working_inventory()
 
241
    
 
242
    renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
 
243
    renames.sort()
 
244
    for old_name, new_name in renames:
 
245
        print "%s => %s" % (old_name, new_name)        
 
246
 
 
247
 
 
248
 
198
249
def cmd_info():
199
250
    """info: Show statistical information for this branch
200
251
 
211
262
 
212
263
 
213
264
def cmd_file_id(filename):
 
265
    """Print file_id of a particular file or directory.
 
266
 
 
267
usage: bzr file-id FILE
 
268
 
 
269
The file_id is assigned when the file is first added and remains the
 
270
same through all revisions where the file exists, even when it is
 
271
moved or renamed.
 
272
"""
214
273
    b = Branch(filename)
215
274
    i = b.inventory.path2id(b.relpath(filename))
216
 
    if i is None:
217
 
        bailout("%s is not a versioned file" % filename)
 
275
    if i == None:
 
276
        bailout("%r is not a versioned file" % filename)
218
277
    else:
219
278
        print i
220
279
 
221
280
 
222
 
def cmd_find_filename(fileid):
223
 
    n = find_filename(fileid)
224
 
    if n is None:
225
 
        bailout("%s is not a live file id" % fileid)
226
 
    else:
227
 
        print n
 
281
def cmd_file_id_path(filename):
 
282
    """Print path of file_ids to a file or directory.
 
283
 
 
284
usage: bzr file-id-path FILE
 
285
 
 
286
This prints one line for each directory down to the target,
 
287
starting at the branch root."""
 
288
    b = Branch(filename)
 
289
    inv = b.inventory
 
290
    fid = inv.path2id(b.relpath(filename))
 
291
    if fid == None:
 
292
        bailout("%r is not a versioned file" % filename)
 
293
    for fip in inv.get_idpath(fid):
 
294
        print fip
228
295
 
229
296
 
230
297
def cmd_revision_history():
232
299
        print patchid
233
300
 
234
301
 
 
302
def cmd_directories():
 
303
    for name, ie in Branch('.').read_working_inventory().directories():
 
304
        if name == '':
 
305
            print '.'
 
306
        else:
 
307
            print name
 
308
 
 
309
 
 
310
def cmd_missing():
 
311
    for name, ie in Branch('.').working_tree().missing():
 
312
        print name
 
313
 
235
314
 
236
315
def cmd_init():
237
316
    # TODO: Check we're not already in a working directory?  At the
274
353
        old_tree = b.revision_tree(b.lookup_revision(revision))
275
354
        
276
355
    new_tree = b.working_tree()
277
 
    old_inv = old_tree.inventory
278
 
    new_inv = new_tree.inventory
279
356
 
280
357
    # TODO: Options to control putting on a prefix or suffix, perhaps as a format string
281
358
    old_label = ''
292
369
    # TODO: Better to return them in sorted order I think.
293
370
    
294
371
    for file_state, fid, old_name, new_name, kind in bzrlib.diff_trees(old_tree, new_tree):
295
 
        d = None
296
 
 
297
372
        # Don't show this by default; maybe do it if an option is passed
298
373
        # idlabel = '      {%s}' % fid
299
374
        idlabel = ''
301
376
        # FIXME: Something about the diff format makes patch unhappy
302
377
        # with newly-added files.
303
378
 
304
 
        def diffit(*a, **kw):
305
 
            sys.stdout.writelines(difflib.unified_diff(*a, **kw))
 
379
        def diffit(oldlines, newlines, **kw):
 
380
            # FIXME: difflib is wrong if there is no trailing newline.
 
381
 
 
382
            # Special workaround for Python2.3, where difflib fails if
 
383
            # both sequences are empty.
 
384
            if oldlines or newlines:
 
385
                sys.stdout.writelines(difflib.unified_diff(oldlines, newlines, **kw))
306
386
            print
307
387
        
308
388
        if file_state in ['.', '?', 'I']:
348
428
    old = b.basis_tree()
349
429
    new = b.working_tree()
350
430
 
 
431
    ## TODO: Much more efficient way to do this: read in new
 
432
    ## directories with readdir, rather than stating each one.  Same
 
433
    ## level of effort but possibly much less IO.  (Or possibly not,
 
434
    ## if the directories are very large...)
 
435
 
351
436
    for path, ie in old.inventory.iter_entries():
352
437
        if not new.has_id(ie.file_id):
353
438
            if show_ids:
354
439
                print '%-50s %s' % (path, ie.file_id)
355
440
            else:
356
441
                print path
357
 
                
358
 
    
359
 
 
 
442
 
 
443
 
 
444
 
 
445
def cmd_parse_inventory():
 
446
    import cElementTree
 
447
    
 
448
    cElementTree.ElementTree().parse(file('.bzr/inventory'))
 
449
 
 
450
 
 
451
 
 
452
def cmd_load_inventory():
 
453
    """Load inventory for timing purposes"""
 
454
    Branch('.').basis_tree().inventory
 
455
 
 
456
 
 
457
 
 
458
def cmd_dump_new_inventory():
 
459
    import bzrlib.newinventory
 
460
    inv = Branch('.').basis_tree().inventory
 
461
    bzrlib.newinventory.write_inventory(inv, sys.stdout)
 
462
 
 
463
 
 
464
def cmd_load_new_inventory():
 
465
    import bzrlib.newinventory
 
466
    bzrlib.newinventory.read_new_inventory(sys.stdin)
 
467
                
 
468
    
 
469
def cmd_dump_slacker_inventory():
 
470
    import bzrlib.newinventory
 
471
    inv = Branch('.').basis_tree().inventory
 
472
    bzrlib.newinventory.write_slacker_inventory(inv, sys.stdout)
 
473
                
 
474
    
360
475
 
361
476
def cmd_root(filename=None):
362
477
    """Print the branch root."""
404
519
 
405
520
 
406
521
 
407
 
def cmd_ignored(verbose=True):
 
522
def cmd_ignored():
408
523
    """List ignored files and the patterns that matched them.
409
524
      """
410
525
    tree = Branch('.').working_tree()
411
 
    for path, file_class, kind, id in tree.list_files():
 
526
    for path, file_class, kind, file_id in tree.list_files():
412
527
        if file_class != 'I':
413
528
            continue
414
529
        ## XXX: Slightly inefficient since this was already calculated
415
530
        pat = tree.is_ignored(path)
416
531
        print '%-50s %s' % (path, pat)
417
 
    
418
532
 
419
533
 
420
534
def cmd_lookup_revision(revno):
435
549
    t = b.revision_tree(rh)
436
550
    t.export(dest)
437
551
 
 
552
def cmd_cat(revision, filename):
 
553
    """Print file to stdout."""
 
554
    b = Branch('.')
 
555
    b.print_file(b.relpath(filename), int(revision))
438
556
 
439
557
 
440
558
######################################################################
513
631
 
514
632
 
515
633
def cmd_gen_revision_id():
516
 
    import time
517
634
    print bzrlib.branch._gen_revision_id(time.time())
518
635
 
519
636
 
520
 
def cmd_selftest(verbose=False):
 
637
def cmd_selftest():
521
638
    """Run internal test suite"""
522
639
    ## -v, if present, is seen by doctest; the argument is just here
523
640
    ## so our parser doesn't complain
622
739
# listed take none.
623
740
cmd_options = {
624
741
    'add':                    ['verbose'],
 
742
    'cat':                    ['revision'],
625
743
    'commit':                 ['message', 'verbose'],
626
744
    'deleted':                ['show-ids'],
627
745
    'diff':                   ['revision'],
635
753
 
636
754
cmd_args = {
637
755
    'add':                    ['file+'],
 
756
    'cat':                    ['filename'],
638
757
    'commit':                 [],
639
758
    'diff':                   [],
640
759
    'export':                 ['revno', 'dest'],
641
760
    'file-id':                ['filename'],
 
761
    'file-id-path':           ['filename'],
642
762
    'get-file-text':          ['text_id'],
643
763
    'get-inventory':          ['inventory_id'],
644
764
    'get-revision':           ['revision_id'],
647
767
    'init':                   [],
648
768
    'log':                    [],
649
769
    'lookup-revision':        ['revno'],
 
770
    'move':                   ['source$', 'dest'],
650
771
    'relpath':                ['filename'],
651
772
    'remove':                 ['file+'],
 
773
    'rename':                 ['from_name', 'to_name'],
 
774
    'renames':                ['dir?'],
652
775
    'root':                   ['filename?'],
653
776
    'status':                 [],
654
777
    }
742
865
            if args:
743
866
                argdict[argname] = args.pop(0)
744
867
        elif ap[-1] == '*':
745
 
            assert 0
 
868
            raise BzrError("arg form %r not implemented yet" % ap)
746
869
        elif ap[-1] == '+':
747
870
            if not args:
748
871
                bailout("command %r needs one or more %s"
750
873
            else:
751
874
                argdict[argname + '_list'] = args[:]
752
875
                args = []
 
876
        elif ap[-1] == '$': # all but one
 
877
            if len(args) < 2:
 
878
                bailout("command %r needs one or more %s"
 
879
                        % (cmd, argname.upper()))
 
880
            argdict[argname + '_list'] = args[:-1]
 
881
            args[:-1] = []                
753
882
        else:
754
883
            # just a plain arg
755
884
            argname = ap
778
907
        if 'help' in opts:
779
908
            # TODO: pass down other arguments in case they asked for
780
909
            # help on a command name?
781
 
            cmd_help()
 
910
            if args:
 
911
                cmd_help(args[0])
 
912
            else:
 
913
                cmd_help()
782
914
            return 0
783
915
        elif 'version' in opts:
784
916
            cmd_version()
808
940
            bailout("option %r is not allowed for command %r"
809
941
                    % (oname, cmd))
810
942
 
 
943
    # TODO: give an error if there are any mandatory options which are
 
944
    # not specified?  Or maybe there shouldn't be any "mandatory
 
945
    # options" (it is an oxymoron)
 
946
 
811
947
    # mix arguments and options into one dictionary
812
948
    cmdargs = _match_args(cmd, args)
813
949
    for k, v in opts.items():
822
958
        import hotshot.stats
823
959
        stats = hotshot.stats.load('.bzr.profile')
824
960
        #stats.strip_dirs()
825
 
        stats.sort_stats('cumulative', 'calls')
 
961
        stats.sort_stats('time')
826
962
        stats.print_stats(20)
 
963
 
 
964
        return ret
827
965
    else:
828
966
        return cmd_handler(**cmdargs) or 0
829
967
 
846
984
        if len(e.args) > 1:
847
985
            for h in e.args[1]:
848
986
                log_error('  ' + h + '\n')
 
987
        traceback.print_exc(None, bzrlib.trace._tracefile)
 
988
        log_error('(see $HOME/.bzr.log for debug information)\n')
849
989
        return 1
850
990
    except Exception, e:
851
991
        log_error('bzr: exception: %s\n' % e)
852
 
        log_error('    see .bzr.log for details\n')
 
992
        log_error('(see $HOME/.bzr.log for debug information)\n')
853
993
        traceback.print_exc(None, bzrlib.trace._tracefile)
854
 
        traceback.print_exc(None, sys.stderr)
 
994
        ## traceback.print_exc(None, sys.stderr)
855
995
        return 1
856
996
 
857
997
    # TODO: Maybe nicer handling of IOError?