65
import sys, os, random, time, sha, sets, types, re, shutil, tempfile
66
import traceback, socket, fnmatch, difflib
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
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
197
# TODO: Maybe a 'mv' command that has the combined move/rename
198
# special behaviour of Unix?
200
def cmd_move(source_list, dest):
203
b.move([b.relpath(s) for s in source_list], b.relpath(dest))
207
def cmd_rename(from_name, to_name):
208
"""Change the name of an entry.
210
usage: bzr rename FROM_NAME TO_NAME
213
bzr rename frob.c frobber.c
214
bzr rename src/frob.c lib/frob.c
216
It is an error if the destination name exists.
218
See also the 'move' command, which moves files into a different
219
directory without changing their name.
221
TODO: Some way to rename multiple files without invoking bzr for each
224
b.rename_one(b.relpath(from_name), b.relpath(to_name))
229
def cmd_renames(dir='.'):
230
"""Show list of renamed files.
232
usage: bzr renames [BRANCH]
234
TODO: Option to show renames between two historical versions.
236
TODO: Only show renames under dir, rather than in the whole branch.
239
old_inv = b.basis_tree().inventory
240
new_inv = b.read_working_inventory()
242
renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
244
for old_name, new_name in renames:
245
print "%s => %s" % (old_name, new_name)
199
250
"""info: Show statistical information for this branch
213
264
def cmd_file_id(filename):
265
"""Print file_id of a particular file or directory.
267
usage: bzr file-id FILE
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
214
273
b = Branch(filename)
215
274
i = b.inventory.path2id(b.relpath(filename))
217
bailout("%s is not a versioned file" % filename)
276
bailout("%r is not a versioned file" % filename)
222
def cmd_find_filename(fileid):
223
n = find_filename(fileid)
225
bailout("%s is not a live file id" % fileid)
281
def cmd_file_id_path(filename):
282
"""Print path of file_ids to a file or directory.
284
usage: bzr file-id-path FILE
286
This prints one line for each directory down to the target,
287
starting at the branch root."""
290
fid = inv.path2id(b.relpath(filename))
292
bailout("%r is not a versioned file" % filename)
293
for fip in inv.get_idpath(fid):
230
297
def cmd_revision_history():
274
353
old_tree = b.revision_tree(b.lookup_revision(revision))
276
355
new_tree = b.working_tree()
277
old_inv = old_tree.inventory
278
new_inv = new_tree.inventory
280
357
# TODO: Options to control putting on a prefix or suffix, perhaps as a format string
292
369
# TODO: Better to return them in sorted order I think.
294
371
for file_state, fid, old_name, new_name, kind in bzrlib.diff_trees(old_tree, new_tree):
297
372
# Don't show this by default; maybe do it if an option is passed
298
373
# idlabel = ' {%s}' % fid
301
376
# FIXME: Something about the diff format makes patch unhappy
302
377
# with newly-added files.
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.
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))
308
388
if file_state in ['.', '?', 'I']:
348
428
old = b.basis_tree()
349
429
new = b.working_tree()
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...)
351
436
for path, ie in old.inventory.iter_entries():
352
437
if not new.has_id(ie.file_id):
354
439
print '%-50s %s' % (path, ie.file_id)
445
def cmd_parse_inventory():
448
cElementTree.ElementTree().parse(file('.bzr/inventory'))
452
def cmd_load_inventory():
453
"""Load inventory for timing purposes"""
454
Branch('.').basis_tree().inventory
458
def cmd_dump_new_inventory():
459
import bzrlib.newinventory
460
inv = Branch('.').basis_tree().inventory
461
bzrlib.newinventory.write_inventory(inv, sys.stdout)
464
def cmd_load_new_inventory():
465
import bzrlib.newinventory
466
bzrlib.newinventory.read_new_inventory(sys.stdin)
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)
361
476
def cmd_root(filename=None):
362
477
"""Print the branch root."""
407
def cmd_ignored(verbose=True):
408
523
"""List ignored files and the patterns that matched them.
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':
414
529
## XXX: Slightly inefficient since this was already calculated
415
530
pat = tree.is_ignored(path)
416
531
print '%-50s %s' % (path, pat)
420
534
def cmd_lookup_revision(revno):
435
549
t = b.revision_tree(rh)
552
def cmd_cat(revision, filename):
553
"""Print file to stdout."""
555
b.print_file(b.relpath(filename), int(revision))
440
558
######################################################################
515
633
def cmd_gen_revision_id():
517
634
print bzrlib.branch._gen_revision_id(time.time())
520
def cmd_selftest(verbose=False):
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
637
755
'add': ['file+'],
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'],
649
769
'lookup-revision': ['revno'],
770
'move': ['source$', 'dest'],
650
771
'relpath': ['filename'],
651
772
'remove': ['file+'],
773
'rename': ['from_name', 'to_name'],
652
775
'root': ['filename?'],
751
874
argdict[argname + '_list'] = args[:]
876
elif ap[-1] == '$': # all but one
878
bailout("command %r needs one or more %s"
879
% (cmd, argname.upper()))
880
argdict[argname + '_list'] = args[:-1]
754
883
# just a plain arg
808
940
bailout("option %r is not allowed for command %r"
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)
811
947
# mix arguments and options into one dictionary
812
948
cmdargs = _match_args(cmd, args)
813
949
for k, v in opts.items():
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')
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)
857
997
# TODO: Maybe nicer handling of IOError?