55
60
Show summary of pending changes.
57
62
Make a file not versioned.
59
Show statistics about this branch.
65
import sys, os, time, types, shutil, tempfile, traceback, fnmatch, difflib, os.path
65
# not currently working:
67
# Show some information about this branch.
71
__copyright__ = "Copyright 2005 Canonical Development Ltd."
72
__author__ = "Martin Pool <mbp@canonical.com>"
73
__docformat__ = "restructuredtext en"
77
import sys, os, random, time, sha, sets, types, re, shutil, tempfile
78
import traceback, socket, fnmatch, difflib
66
80
from sets import Set
67
81
from pprint import pprint
72
86
from bzrlib.store import ImmutableStore
73
87
from bzrlib.trace import mutter, note, log_error
74
from bzrlib.errors import bailout, BzrError, BzrCheckError
88
from bzrlib.errors import bailout, BzrError
75
89
from bzrlib.osutils import quotefn, pumpfile, isdir, isfile
76
90
from bzrlib.tree import RevisionTree, EmptyTree, WorkingTree, Tree
77
91
from bzrlib.revision import Revision
170
184
Therefore simply saying 'bzr add .' will version all files that
171
185
are currently unknown.
173
bzrlib.add.smart_add(file_list, verbose)
188
bzrlib.add.smart_add(file_list, verbose)
192
b = Branch(file_list[0], find_root=True)
193
b.add([b.relpath(f) for f in file_list], verbose=verbose)
176
197
def cmd_relpath(filename):
177
"""Show path of file relative to root"""
178
198
print Branch(filename).relpath(filename)
182
201
def cmd_inventory(revision=None):
183
202
"""Show inventory of the current working copy."""
184
203
## TODO: Also optionally show a previous inventory
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)
250
"""info: Show statistical information for this branch
254
info.show_info(Branch('.'))
218
print 'branch format:', b.controlfile('branch-format', 'r').readline().rstrip('\n')
220
def plural(n, base='', pl=None):
228
count_version_dirs = 0
230
count_status = {'A': 0, 'D': 0, 'M': 0, 'R': 0, '?': 0, 'I': 0, '.': 0}
231
for st_tup in bzrlib.diff_trees(b.basis_tree(), b.working_tree()):
233
count_status[fs] += 1
234
if fs not in ['I', '?'] and st_tup[4] == 'directory':
235
count_version_dirs += 1
238
print 'in the working tree:'
239
for name, fs in (('unchanged', '.'),
240
('modified', 'M'), ('added', 'A'), ('removed', 'D'),
241
('renamed', 'R'), ('unknown', '?'), ('ignored', 'I'),
243
print ' %5d %s' % (count_status[fs], name)
244
print ' %5d versioned subdirector%s' % (count_version_dirs,
245
plural(count_version_dirs, 'y', 'ies'))
248
print 'branch history:'
249
history = b.revision_history()
251
print ' %5d revision%s' % (revno, plural(revno))
254
committers.add(b.get_revision(rev).committer)
255
print ' %5d committer%s' % (len(committers), plural(len(committers)))
257
firstrev = b.get_revision(history[0])
258
age = int((time.time() - firstrev.timestamp) / 3600 / 24)
259
print ' %5d day%s old' % (age, plural(age))
260
print ' first revision: %s' % format_date(firstrev.timestamp,
263
lastrev = b.get_revision(history[-1])
264
print ' latest revision: %s' % format_date(lastrev.timestamp,
264
276
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
273
277
b = Branch(filename)
274
278
i = b.inventory.path2id(b.relpath(filename))
276
bailout("%r is not a versioned file" % filename)
280
bailout("%s is not a versioned file" % filename)
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):
285
def cmd_find_filename(fileid):
286
n = find_filename(fileid)
288
bailout("%s is not a live file id" % fileid)
297
293
def cmd_revision_history():
325
309
Branch('.', init=True)
328
def cmd_diff(revision=None, file_list=None):
329
"""bzr diff: Show differences in working tree.
331
usage: bzr diff [-r REV] [FILE...]
334
Show changes since REV, rather than predecessor.
336
If files are listed, only the changes in those files are listed.
337
Otherwise, all changes for the tree are listed.
339
TODO: Given two revision arguments, show the difference between them.
341
TODO: Allow diff across branches.
343
TODO: Option to use external diff command; could be GNU diff, wdiff,
346
TODO: If a directory is given, diff everything under that.
348
TODO: Selected-file diff is inefficient and doesn't show you deleted files.
351
## TODO: Shouldn't be in the cmd function.
312
def cmd_diff(revision=None):
313
"""Show diff from basis to working copy.
315
:todo: Take one or two revision arguments, look up those trees,
318
:todo: Allow diff across branches.
320
:todo: Mangle filenames in diff to be more relevant.
322
:todo: Shouldn't be in the cmd function.
372
346
# be usefully made into a much faster special case.
374
348
# TODO: Better to return them in sorted order I think.
376
# FIXME: If given a file list, compare only those files rather
377
# than comparing everything and then throwing stuff away.
379
350
for file_state, fid, old_name, new_name, kind in bzrlib.diff_trees(old_tree, new_tree):
381
if file_list and new_name not in file_list:
384
353
# Don't show this by default; maybe do it if an option is passed
385
354
# idlabel = ' {%s}' % fid
388
357
# FIXME: Something about the diff format makes patch unhappy
389
358
# with newly-added files.
391
def diffit(oldlines, newlines, **kw):
392
# FIXME: difflib is wrong if there is no trailing newline.
394
# Special workaround for Python2.3, where difflib fails if
395
# both sequences are empty.
396
if oldlines or newlines:
397
sys.stdout.writelines(difflib.unified_diff(oldlines, newlines, **kw))
360
def diffit(*a, **kw):
361
sys.stdout.writelines(difflib.unified_diff(*a, **kw))
400
364
if file_state in ['.', '?', 'I']:
434
def cmd_deleted(show_ids=False):
435
"""List files deleted in the working tree.
437
TODO: Show files deleted since a previous revision, or between two revisions.
441
new = b.working_tree()
443
## TODO: Much more efficient way to do this: read in new
444
## directories with readdir, rather than stating each one. Same
445
## level of effort but possibly much less IO. (Or possibly not,
446
## if the directories are very large...)
448
for path, ie in old.inventory.iter_entries():
449
if not new.has_id(ie.file_id):
451
print '%-50s %s' % (path, ie.file_id)
457
def cmd_parse_inventory():
460
cElementTree.ElementTree().parse(file('.bzr/inventory'))
464
def cmd_load_inventory():
465
"""Load inventory for timing purposes"""
466
Branch('.').basis_tree().inventory
469
def cmd_dump_inventory():
470
Branch('.').read_working_inventory().write_xml(sys.stdout)
473
def cmd_dump_new_inventory():
474
import bzrlib.newinventory
475
inv = Branch('.').basis_tree().inventory
476
bzrlib.newinventory.write_inventory(inv, sys.stdout)
479
def cmd_load_new_inventory():
480
import bzrlib.newinventory
481
bzrlib.newinventory.read_new_inventory(sys.stdin)
484
def cmd_dump_slacker_inventory():
485
import bzrlib.newinventory
486
inv = Branch('.').basis_tree().inventory
487
bzrlib.newinventory.write_slacker_inventory(inv, sys.stdout)
491
398
def cmd_root(filename=None):
492
399
"""Print the branch root."""
493
400
print bzrlib.branch.find_branch_root(filename)
588
478
def cmd_commit(message=None, verbose=False):
589
"""Commit changes to a new revision.
592
Description of changes in this revision; free form text.
593
It is recommended that the first line be a single-sentence
596
Show status of changed files,
598
TODO: Commit only selected files.
600
TODO: Run hooks on tree to-be-committed, and after commit.
602
TODO: Strict commit that fails if there are unknown or deleted files.
606
480
bailout("please specify a commit message")
607
481
Branch('.').commit(message, verbose=verbose)
610
def cmd_check(dir='.'):
611
"""check: Consistency check of branch history.
613
usage: bzr check [-v] [BRANCH]
616
--verbose, -v Show progress of checking.
618
This command checks various invariants about the branch storage to
619
detect data corruption or bzr bugs.
622
bzrlib.check.check(Branch(dir, find_root=False))
485
"""Check consistency of the branch."""
625
489
def cmd_is(pred, *rest):
691
def cmd_help(topic=None):
696
# otherwise, maybe the name of a command?
698
cmdfn = globals()['cmd_' + topic.replace('-', '_')]
700
bailout("no help for %r" % topic)
704
bailout("sorry, no detailed help yet for %r" % topic)
557
# TODO: Specific help for particular commands
711
561
def cmd_version():
712
print "bzr (bazaar-ng) %s" % bzrlib.__version__
713
print bzrlib.__copyright__
562
print "bzr (bazaar-ng) %s" % __version__
714
564
print "http://bazaar-ng.org/"
770
618
'add': ['file+'],
774
'export': ['revno', 'dest'],
775
621
'file-id': ['filename'],
776
'file-id-path': ['filename'],
622
'root': ['filename?'],
623
'relpath': ['filename'],
777
624
'get-file-text': ['text_id'],
778
625
'get-inventory': ['inventory_id'],
779
626
'get-revision': ['revision_id'],
780
627
'get-revision-inventory': ['revision_id'],
784
629
'lookup-revision': ['revno'],
785
'move': ['source$', 'dest'],
786
'relpath': ['filename'],
630
'export': ['revno', 'dest'],
787
631
'remove': ['file+'],
788
'rename': ['from_name', 'to_name'],
790
'root': ['filename?'],
959
783
bailout("option %r is not allowed for command %r"
962
# TODO: give an error if there are any mandatory options which are
963
# not specified? Or maybe there shouldn't be any "mandatory
964
# options" (it is an oxymoron)
966
# mix arguments and options into one dictionary
967
786
cmdargs = _match_args(cmd, args)
968
for k, v in opts.items():
969
cmdargs[k.replace('-', '_')] = v
973
prof = hotshot.Profile('.bzr.profile')
974
ret = prof.runcall(cmd_handler, **cmdargs) or 0
978
stats = hotshot.stats.load('.bzr.profile')
980
stats.sort_stats('time')
981
stats.print_stats(20)
985
return cmd_handler(**cmdargs) or 0
789
ret = cmd_handler(**cmdargs) or 0
1003
807
if len(e.args) > 1:
1004
808
for h in e.args[1]:
1005
809
log_error(' ' + h + '\n')
1006
traceback.print_exc(None, bzrlib.trace._tracefile)
1007
log_error('(see $HOME/.bzr.log for debug information)\n')
1009
811
except Exception, e:
1010
812
log_error('bzr: exception: %s\n' % e)
1011
log_error('(see $HOME/.bzr.log for debug information)\n')
813
log_error(' see .bzr.log for details\n')
1012
814
traceback.print_exc(None, bzrlib.trace._tracefile)
1013
## traceback.print_exc(None, sys.stderr)
815
traceback.print_exc(None, sys.stderr)
1016
818
# TODO: Maybe nicer handling of IOError?