116
113
## TODO: Perhaps make UUIDs predictable in test mode to make it easier
117
114
## to compare output?
119
## TODO: Is ElementTree really all that much better for our purposes?
120
## Perhaps using the standard MiniDOM would be enough?
127
######################################################################
116
## TODO: Some kind of global code to generate the right Branch object
117
## to work on. Almost, but not quite all, commands need one, and it
118
## can be taken either from their parameters or their working
121
## TODO: rename command, needed soon: check destination doesn't exist
122
## either in working copy or tree; move working copy; update
123
## inventory; write out
125
## TODO: move command; check destination is a directory and will not
128
## TODO: command to show renames, one per line, as to->from
131
133
def cmd_status(all=False):
147
149
Branch('.').get_revision(revision_id).write_xml(sys.stdout)
150
def cmd_get_inventory(inventory_id):
151
"""Return inventory in XML by hash"""
152
Branch('.').get_inventory(inventory_hash).write_xml(sys.stdout)
155
def cmd_get_revision_inventory(revision_id):
156
"""Output inventory for a revision."""
158
b.get_revision_inventory(revision_id).write_xml(sys.stdout)
161
152
def cmd_get_file_text(text_id):
162
153
"""Get contents of a file by hash."""
163
154
sf = Branch('.').text_store[text_id]
202
193
print 'branch format:', b.controlfile('branch-format', 'r').readline().rstrip('\n')
203
print 'revision number:', b.revno()
204
print 'number of versioned files:', len(b.read_working_inventory())
195
def plural(n, base='', pl=None):
203
count_version_dirs = 0
205
count_status = {'A': 0, 'D': 0, 'M': 0, 'R': 0, '?': 0, 'I': 0, '.': 0}
206
for st_tup in bzrlib.diff_trees(b.basis_tree(), b.working_tree()):
208
count_status[fs] += 1
209
if fs not in ['I', '?'] and st_tup[4] == 'directory':
210
count_version_dirs += 1
213
print 'in the working tree:'
214
for name, fs in (('unchanged', '.'),
215
('modified', 'M'), ('added', 'A'), ('removed', 'D'),
216
('renamed', 'R'), ('unknown', '?'), ('ignored', 'I'),
218
print ' %5d %s' % (count_status[fs], name)
219
print ' %5d versioned subdirector%s' % (count_version_dirs,
220
plural(count_version_dirs, 'y', 'ies'))
223
print 'branch history:'
224
history = b.revision_history()
226
print ' %5d revision%s' % (revno, plural(revno))
229
committers.add(b.get_revision(rev).committer)
230
print ' %5d committer%s' % (len(committers), plural(len(committers)))
232
firstrev = b.get_revision(history[0])
233
age = int((time.time() - firstrev.timestamp) / 3600 / 24)
234
print ' %5d day%s old' % (age, plural(age))
235
print ' first revision: %s' % format_date(firstrev.timestamp,
238
lastrev = b.get_revision(history[-1])
239
print ' latest revision: %s' % format_date(lastrev.timestamp,
207
245
def cmd_remove(file_list, verbose=False):
371
def cmd_log(timezone='original'):
334
372
"""Show log of this branch.
336
374
:todo: Options for utc; to show ids; to limit range; etc.
338
Branch('.').write_log()
376
Branch('.').write_log(show_timezone=timezone)
341
379
def cmd_ls(revision=None, verbose=False):
445
488
## TODO: --verbose option
447
import bzr, doctest, bzrlib.store
490
import doctest, bzrlib.store
448
491
bzrlib.trace.verbose = False
450
492
doctest.testmod(bzrlib.store)
451
493
doctest.testmod(bzrlib.inventory)
452
494
doctest.testmod(bzrlib.branch)
514
557
'commit': ['message', 'verbose'],
515
558
'diff': ['revision'],
516
559
'inventory': ['revision'],
560
'log': ['show-ids', 'timezone'],
517
561
'ls': ['revision', 'verbose'],
562
'remove': ['verbose'],
518
563
'status': ['all'],
520
'remove': ['verbose'],
547
590
lookup table, something about the available options, what optargs
548
591
they take, and which commands will accept them.
550
>>> parse_args('bzr --help'.split())
593
>>> parse_args('--help'.split())
551
594
([], {'help': True})
552
>>> parse_args('bzr --version'.split())
595
>>> parse_args('--version'.split())
553
596
([], {'version': True})
554
>>> parse_args('bzr status --all'.split())
597
>>> parse_args('status --all'.split())
555
598
(['status'], {'all': True})
599
>>> parse_args('commit --message=biter'.split())
600
(['commit'], {'message': u'biter'})
560
605
# TODO: Maybe handle '--' to end options?
567
612
mutter(" got option %r" % a)
614
optname, optarg = a[2:].split('=', 1)
569
617
if optname not in OPTIONS:
570
618
bailout('unknown long option %r' % a)
577
625
if optname in opts:
578
626
# XXX: Do we ever want to support this, e.g. for -r?
579
627
bailout('repeated option %r' % a)
580
629
optargfn = OPTIONS[optname]
583
bailout('option %r needs an argument' % a)
584
opts[optname] = optargfn(it.next())
633
bailout('option %r needs an argument' % a)
636
opts[optname] = optargfn(optarg)
585
637
mutter(" option argument %r" % opts[optname])
587
# takes no option argument
640
bailout('option %r takes no argument' % optname)
588
641
opts[optname] = True
590
bailout('unknown short option %r' % a)
649
701
logging and error handling.
652
args, opts = parse_args(argv)
704
args, opts = parse_args(argv[1:])
653
705
if 'help' in opts:
654
706
# TODO: pass down other arguments in case they asked for
655
707
# help on a command name?
693
745
## than just a backtrace.
748
# TODO: Lift into separate function in trace.py
749
# TODO: Also show contents of /etc/lsb-release, if it can be parsed.
750
# Perhaps that should eventually go into the platform library?
751
# TODO: If the file doesn't exist, add a note describing it.
696
752
t = bzrlib.trace._tracefile
697
753
t.write('-' * 60 + '\n')
698
754
t.write('bzr invoked at %s\n' % format_date(time.time()))
699
t.write(' by %s on %s\n' % (bzrlib.osutils.username(), socket.gethostname()))
755
t.write(' by %s on %s\n' % (bzrlib.osutils.username(), socket.getfqdn()))
700
756
t.write(' arguments: %r\n' % argv)
702
758
starttime = os.times()[4]