55
60
Show summary of pending changes.
57
62
Make a file not versioned.
59
Show statistics about this branch.
65
# not currently working:
67
# Run internal consistency checks.
69
# Show some information about this branch.
73
__copyright__ = "Copyright 2005 Canonical Development Ltd."
74
__author__ = "Martin Pool <mbp@canonical.com>"
75
__docformat__ = "restructuredtext en"
65
79
import sys, os, random, time, sha, sets, types, re, shutil, tempfile
101
115
## TODO: Perhaps make UUIDs predictable in test mode to make it easier
102
116
## to compare output?
104
## TODO: Some kind of global code to generate the right Branch object
105
## to work on. Almost, but not quite all, commands need one, and it
106
## can be taken either from their parameters or their working
109
## TODO: rename command, needed soon: check destination doesn't exist
110
## either in working copy or tree; move working copy; update
111
## inventory; write out
113
## TODO: move command; check destination is a directory and will not
116
## TODO: command to show renames, one per line, as to->from
121
######################################################################
121
125
def cmd_status(all=False):
137
141
Branch('.').get_revision(revision_id).write_xml(sys.stdout)
144
def cmd_get_inventory(inventory_id):
145
"""Return inventory in XML by hash"""
146
Branch('.').get_inventory(inventory_hash).write_xml(sys.stdout)
149
def cmd_get_revision_inventory(revision_id):
150
"""Output inventory for a revision."""
152
b.get_revision_inventory(revision_id).write_xml(sys.stdout)
140
155
def cmd_get_file_text(text_id):
141
156
"""Get contents of a file by hash."""
142
157
sf = Branch('.').text_store[text_id]
153
168
print Branch('.').revno()
157
171
def cmd_add(file_list, verbose=False):
158
"""Add specified files or directories.
160
In non-recursive mode, all the named items are added, regardless
161
of whether they were previously ignored. A warning is given if
162
any of the named files are already versioned.
164
In recursive mode (the default), files are treated the same way
165
but the behaviour for directories is different. Directories that
166
are already versioned do not give a warning. All directories,
167
whether already versioned or not, are searched for files or
168
subdirectories that are neither versioned or ignored, and these
169
are added. This search proceeds recursively into versioned
172
Therefore simply saying 'bzr add .' will version all files that
173
are currently unknown.
172
"""Add specified files.
174
Fails if the files are already added.
175
bzrlib.add.smart_add(file_list, verbose)
178
def cmd_relpath(filename):
179
"""Show path of file relative to root"""
180
print Branch(filename).relpath(filename)
176
Branch('.').add(file_list, verbose=verbose)
183
179
def cmd_inventory(revision=None):
199
"""info: Show statistical information for this branch
203
info.show_info(Branch('.'))
196
print 'branch format:', b.controlfile('branch-format', 'r').readline().rstrip('\n')
198
def plural(n, base='', pl=None):
206
count_version_dirs = 0
208
count_status = {'A': 0, 'D': 0, 'M': 0, 'R': 0, '?': 0, 'I': 0, '.': 0}
209
for st_tup in bzrlib.diff_trees(b.basis_tree(), b.working_tree()):
211
count_status[fs] += 1
212
if fs not in ['I', '?'] and st_tup[4] == 'directory':
213
count_version_dirs += 1
216
print 'in the working tree:'
217
for name, fs in (('unchanged', '.'),
218
('modified', 'M'), ('added', 'A'), ('removed', 'D'),
219
('renamed', 'R'), ('unknown', '?'), ('ignored', 'I'),
221
print ' %5d %s' % (count_status[fs], name)
222
print ' %5d versioned subdirector%s' % (count_version_dirs,
223
plural(count_version_dirs, 'y', 'ies'))
226
print 'branch history:'
227
history = b.revision_history()
229
print ' %5d revision%s' % (revno, plural(revno))
232
committers.add(b.get_revision(rev).committer)
233
print ' %5d committer%s' % (len(committers), plural(len(committers)))
235
firstrev = b.get_revision(history[0])
236
age = int((time.time() - firstrev.timestamp) / 3600 / 24)
237
print ' %5d day%s old' % (age, plural(age))
238
print ' first revision: %s' % format_date(firstrev.timestamp,
241
lastrev = b.get_revision(history[-1])
242
print ' latest revision: %s' % format_date(lastrev.timestamp,
207
248
def cmd_remove(file_list, verbose=False):
208
b = Branch(file_list[0])
209
b.remove([b.relpath(f) for f in file_list], verbose=verbose)
249
Branch('.').remove(file_list, verbose=verbose)
213
253
def cmd_file_id(filename):
215
i = b.inventory.path2id(b.relpath(filename))
254
i = Branch('.').read_working_inventory().path2id(filename)
217
256
bailout("%s is not a versioned file" % filename)
249
288
def cmd_diff(revision=None):
250
"""bzr diff: Show differences in working tree.
252
usage: bzr diff [-r REV]
255
Show changes since REV, rather than predecessor.
257
TODO: Given two revision arguments, show the difference between them.
259
TODO: Allow diff across branches.
261
TODO: Option to use external diff command; could be GNU diff, wdiff,
264
TODO: Diff selected files.
267
## TODO: Shouldn't be in the cmd function.
289
"""Show diff from basis to working copy.
291
:todo: Take one or two revision arguments, look up those trees,
294
:todo: Allow diff across branches.
296
:todo: Mangle filenames in diff to be more relevant.
298
:todo: Shouldn't be in the cmd function.
342
def cmd_deleted(show_ids=False):
343
"""List files deleted in the working tree.
345
TODO: Show files deleted since a previous revision, or between two revisions.
349
new = b.working_tree()
351
for path, ie in old.inventory.iter_entries():
352
if not new.has_id(ie.file_id):
354
print '%-50s %s' % (path, ie.file_id)
361
def cmd_root(filename=None):
362
"""Print the branch root."""
363
print bzrlib.branch.find_branch_root(filename)
366
374
def cmd_log(timezone='original'):
367
375
"""Show log of this branch.
407
def cmd_ignored(verbose=True):
408
"""List ignored files and the patterns that matched them.
410
tree = Branch('.').working_tree()
411
for path, file_class, kind, id in tree.list_files():
412
if file_class != 'I':
414
## XXX: Slightly inefficient since this was already calculated
415
pat = tree.is_ignored(path)
416
print '%-50s %s' % (path, pat)
420
414
def cmd_lookup_revision(revno):
422
416
revno = int(revno)
455
def cmd_commit(message=None, verbose=False):
456
"""Commit changes to a new revision.
459
Description of changes in this revision; free form text.
460
It is recommended that the first line be a single-sentence
463
Show status of changed files,
465
TODO: Commit only selected files.
467
TODO: Run hooks on tree to-be-committed, and after commit.
469
TODO: Strict commit that fails if there are unknown or deleted files.
473
bailout("please specify a commit message")
449
def cmd_commit(message, verbose=False):
474
450
Branch('.').commit(message, verbose=verbose)
477
def cmd_check(dir='.'):
478
"""check: Consistency check of branch history.
480
usage: bzr check [-v] [BRANCH]
483
--verbose, -v Show progress of checking.
485
This command checks various invariants about the branch storage to
486
detect data corruption or bzr bugs.
489
bzrlib.check.check(Branch(dir, find_root=False))
454
"""Check consistency of the branch."""
492
458
def cmd_is(pred, *rest):
517
483
print bzrlib.branch._gen_revision_id(time.time())
520
def cmd_selftest(verbose=False):
521
"""Run internal test suite"""
487
"""Run internal doctest suite"""
522
488
## -v, if present, is seen by doctest; the argument is just here
523
489
## so our parser doesn't complain
525
491
## TODO: --verbose option
527
failures, tests = 0, 0
529
import doctest, bzrlib.store, bzrlib.tests
493
import bzr, doctest, bzrlib.store
530
494
bzrlib.trace.verbose = False
532
for m in bzrlib.store, bzrlib.inventory, bzrlib.branch, bzrlib.osutils, \
533
bzrlib.tree, bzrlib.tests, bzrlib.commands, bzrlib.add:
534
mf, mt = doctest.testmod(m)
537
print '%-40s %3d tests' % (m.__name__, mt),
539
print '%3d FAILED!' % mf
543
print '%-40s %3d tests' % ('total', tests),
545
print '%3d FAILED!' % failures
552
cmd_doctest = cmd_selftest
496
doctest.testmod(bzrlib.store)
497
doctest.testmod(bzrlib.inventory)
498
doctest.testmod(bzrlib.branch)
499
doctest.testmod(bzrlib.osutils)
500
doctest.testmod(bzrlib.tree)
502
# more strenuous tests;
504
doctest.testmod(bzrlib.tests)
555
507
######################################################################
559
def cmd_help(topic=None):
564
# otherwise, maybe the name of a command?
566
cmdfn = globals()['cmd_' + topic.replace('-', '_')]
568
bailout("no help for %r" % topic)
572
bailout("sorry, no detailed help yet for %r" % topic)
512
# TODO: Specific help for particular commands
579
516
def cmd_version():
580
print "bzr (bazaar-ng) %s" % bzrlib.__version__
581
print bzrlib.__copyright__
517
print "bzr (bazaar-ng) %s" % __version__
582
519
print "http://bazaar-ng.org/"
624
560
'add': ['verbose'],
625
561
'commit': ['message', 'verbose'],
626
'deleted': ['show-ids'],
627
562
'diff': ['revision'],
628
563
'inventory': ['revision'],
564
'log': ['show-ids', 'timezone'],
630
565
'ls': ['revision', 'verbose'],
631
566
'remove': ['verbose'],
632
567
'status': ['all'],
637
573
'add': ['file+'],
640
'export': ['revno', 'dest'],
641
576
'file-id': ['filename'],
642
577
'get-file-text': ['text_id'],
643
578
'get-inventory': ['inventory_id'],
644
579
'get-revision': ['revision_id'],
645
580
'get-revision-inventory': ['revision_id'],
649
582
'lookup-revision': ['revno'],
650
'relpath': ['filename'],
583
'export': ['revno', 'dest'],
651
584
'remove': ['file+'],
652
'root': ['filename?'],
662
594
lookup table, something about the available options, what optargs
663
595
they take, and which commands will accept them.
665
>>> parse_args('--help'.split())
597
>>> parse_args('bzr --help'.split())
666
598
([], {'help': True})
667
>>> parse_args('--version'.split())
599
>>> parse_args('bzr --version'.split())
668
600
([], {'version': True})
669
>>> parse_args('status --all'.split())
601
>>> parse_args('bzr status --all'.split())
670
602
(['status'], {'all': True})
671
>>> parse_args('commit --message=biter'.split())
603
>>> parse_args('bzr commit --message=biter'.split())
672
604
(['commit'], {'message': u'biter'})
788
719
log_error('usage: bzr COMMAND\n')
789
720
log_error(' try "bzr help"\n')
793
724
cmd_handler = globals()['cmd_' + cmd.replace('-', '_')]
795
726
bailout("unknown command " + `cmd`)
798
if 'profile' in opts:
728
# TODO: special --profile option to turn on the Python profiler
804
730
# check options are reasonable
805
731
allowed = cmd_options.get(cmd, [])
808
734
bailout("option %r is not allowed for command %r"
811
# mix arguments and options into one dictionary
812
737
cmdargs = _match_args(cmd, args)
813
for k, v in opts.items():
814
cmdargs[k.replace('-', '_')] = v
818
prof = hotshot.Profile('.bzr.profile')
819
ret = prof.runcall(cmd_handler, **cmdargs) or 0
823
stats = hotshot.stats.load('.bzr.profile')
825
stats.sort_stats('cumulative', 'calls')
826
stats.print_stats(20)
828
return cmd_handler(**cmdargs) or 0
740
ret = cmd_handler(**cmdargs) or 0
836
748
## TODO: If the arguments are wrong, give a usage message rather
837
749
## than just a backtrace.
839
bzrlib.trace.create_tracefile(argv)
752
t = bzrlib.trace._tracefile
753
t.write('-' * 60 + '\n')
754
t.write('bzr invoked at %s\n' % format_date(time.time()))
755
t.write(' by %s on %s\n' % (bzrlib.osutils.username(), socket.gethostname()))
756
t.write(' arguments: %r\n' % argv)
758
starttime = os.times()[4]
761
t.write(' platform: %s\n' % platform.platform())
762
t.write(' python: %s\n' % platform.python_version())
842
764
ret = run_bzr(argv)
767
mutter("finished, %.3fu/%.3fs cpu, %.3fu/%.3fs cum"
769
mutter(" %.3f elapsed" % (times[4] - starttime))
844
772
except BzrError, e:
845
773
log_error('bzr: error: ' + e.args[0] + '\n')