14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Bazaar-NG -- a free distributed version-control tool
20
**WARNING: THIS IS AN UNSTABLE DEVELOPMENT VERSION**
22
* Metadata format is not stable yet -- you may need to
23
discard history in the future.
25
* Many commands unimplemented or partially implemented.
27
* Space-inefficient storage.
29
* No merge operators yet.
36
Show software version/licence/non-warranty.
38
Start versioning the current directory
42
Show revision history.
45
bzr move FROM... DESTDIR
46
Move one or more files to a different directory.
48
Show changes from last revision to working copy.
49
bzr commit -m 'MESSAGE'
50
Store current state as new revision.
51
bzr export [-r REVNO] DESTINATION
52
Export the branch state at a previous version.
54
Show summary of pending changes.
56
Make a file not versioned.
58
Show statistics about this branch.
60
Verify history is stored safely.
61
(for more type 'bzr help commands')
67
import sys, os, time, types, shutil, tempfile, fnmatch, difflib, os.path
19
import sys, os, time, os.path
68
20
from sets import Set
69
from pprint import pprint
74
from bzrlib.store import ImmutableStore
75
23
from bzrlib.trace import mutter, note, log_error
76
24
from bzrlib.errors import bailout, BzrError, BzrCheckError, BzrCommandError
77
25
from bzrlib.osutils import quotefn, pumpfile, isdir, isfile
80
28
from bzrlib import Branch, Inventory, InventoryEntry, ScratchBranch, BZRDIR, \
83
BZR_DIFF_FORMAT = "## Bazaar-NG diff, format 0 ##\n"
84
BZR_PATCHNAME_FORMAT = 'cset:sha1:%s'
86
## standard representation
87
NONE_STRING = '(none)'
32
def _squish_command_name(cmd):
33
return 'cmd_' + cmd.replace('-', '_')
36
def _unsquish_command_name(cmd):
37
assert cmd.startswith("cmd_")
38
return cmd[4:].replace('_','-')
41
"""Return canonical name and class for all registered commands."""
42
for k, v in globals().iteritems():
43
if k.startswith("cmd_"):
44
yield _unsquish_command_name(k), v
101
46
def get_cmd_class(cmd):
104
cmd = CMD_ALIASES.get(cmd, cmd)
47
"""Return the canonical name and command class for a command.
49
cmd = str(cmd) # not unicode
51
# first look up this command under the specified name
107
cmd_class = globals()['cmd_' + cmd.replace('-', '_')]
53
return cmd, globals()[_squish_command_name(cmd)]
109
raise BzrError("unknown command %r" % cmd)
111
return cmd, cmd_class
57
# look for any command which claims this as an alias
58
for cmdname, cmdclass in get_all_cmds():
59
if cmd in cmdclass.aliases:
60
return cmdname, cmdclass
62
raise BzrCommandError("unknown command %r" % cmd)
222
174
bzrlib.add.smart_add(file_list, verbose)
225
def Relpath(Command):
177
class cmd_relpath(Command):
226
178
"""Show path of a file relative to root"""
227
takes_args = ('filename')
179
takes_args = ['filename']
230
print Branch(self.args['filename']).relpath(filename)
181
def run(self, filename):
182
print Branch(filename).relpath(filename)
463
416
class cmd_log(Command):
464
417
"""Show log of this branch.
466
TODO: Options to show ids; to limit range; etc.
419
TODO: Option to limit range.
421
TODO: Perhaps show most-recent first with an option for last.
468
takes_options = ['timezone', 'verbose']
469
def run(self, timezone='original', verbose=False):
470
Branch('.').write_log(show_timezone=timezone, verbose=verbose)
423
takes_args = ['filename?']
424
takes_options = ['timezone', 'verbose', 'show-ids']
425
def run(self, filename=None, timezone='original', verbose=False, show_ids=False):
426
b = Branch((filename or '.'), lock_mode='r')
428
filename = b.relpath(filename)
429
bzrlib.show_log(b, filename,
430
show_timezone=timezone,
436
class cmd_touching_revisions(Command):
437
"""Return revision-ids which affected a particular file."""
439
takes_args = ["filename"]
440
def run(self, filename):
441
b = Branch(filename, lock_mode='r')
442
inv = b.read_working_inventory()
443
file_id = inv.path2id(b.relpath(filename))
444
for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
445
print "%6d %s" % (revno, what)
473
448
class cmd_ls(Command):
546
521
bzr lookup-revision 33
524
takes_args = ['revno']
549
526
def run(self, revno):
551
528
revno = int(revno)
552
529
except ValueError:
553
raise BzrError("not a valid revision-number: %r" % revno)
555
print Branch('.').lookup_revision(revno) or NONE_STRING
530
raise BzrCommandError("not a valid revision-number: %r" % revno)
532
print Branch('.').lookup_revision(revno)
559
535
class cmd_export(Command):
562
538
If no revision is specified this exports the last committed revision."""
563
539
takes_args = ['dest']
564
540
takes_options = ['revision']
565
def run(self, dest, revno=None):
541
def run(self, dest, revision=None):
568
rh = b.revision_history[-1]
544
rh = b.revision_history()[-1]
570
rh = b.lookup_revision(int(revno))
546
rh = b.lookup_revision(int(revision))
571
547
t = b.revision_tree(rh)
603
579
TODO: Strict commit that fails if there are unknown or deleted files.
605
takes_options = ['message', 'verbose']
607
def run(self, message=None, verbose=False):
609
raise BzrCommandError("please specify a commit message")
581
takes_options = ['message', 'file', 'verbose']
582
aliases = ['ci', 'checkin']
584
def run(self, message=None, file=None, verbose=False):
585
## Warning: shadows builtin file()
586
if not message and not file:
587
raise BzrCommandError("please specify a commit message",
588
["use either --message or --file"])
589
elif message and file:
590
raise BzrCommandError("please specify either --message or --file")
594
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
610
596
Branch('.').commit(message, verbose=verbose)
697
683
For a list of all available commands, say 'bzr help commands'."""
698
684
takes_args = ['topic?']
700
687
def run(self, topic=None):
704
def help(topic=None):
707
elif topic == 'commands':
710
help_on_command(topic)
713
def help_on_command(cmdname):
714
cmdname = str(cmdname)
716
from inspect import getdoc
717
topic, cmdclass = get_cmd_class(cmdname)
719
doc = getdoc(cmdclass)
721
raise NotImplementedError("sorry, no detailed help yet for %r" % cmdname)
724
short, rest = doc.split('\n', 1)
729
print 'usage: bzr ' + topic,
730
for aname in cmdclass.takes_args:
731
aname = aname.upper()
732
if aname[-1] in ['$', '+']:
733
aname = aname[:-1] + '...'
734
elif aname[-1] == '?':
735
aname = '[' + aname[:-1] + ']'
736
elif aname[-1] == '*':
737
aname = '[' + aname[:-1] + '...]'
744
help_on_option(cmdclass.takes_options)
747
def help_on_option(options):
755
for shortname, longname in SHORT_OPTIONS.items():
757
l += ', -' + shortname
763
"""List all commands"""
767
for k, v in globals().items():
768
if k.startswith('cmd_'):
769
accu.append((k[4:].replace('_','-'), v))
771
for cmdname, cmdclass in accu:
775
help = inspect.getdoc(cmdclass)
777
print " " + help.split('\n', 1)[0]
780
692
######################################################################
921
835
This is similar to main(), but without all the trappings for
922
836
logging and error handling.
925
838
argv = [a.decode(bzrlib.user_encoding) for a in argv]
928
841
args, opts = parse_args(argv[1:])
929
842
if 'help' in opts:
935
849
elif 'version' in opts:
938
852
cmd = str(args.pop(0))
939
853
except IndexError:
979
893
## print_stats seems hardcoded to stdout
980
894
stats.print_stats(20)
985
899
os.close(pffileno)
986
900
os.remove(pfname)
988
cmdobj = cmd_class(cmdopts, cmdargs) or 0
992
def _report_exception(e, summary, quiet=False):
902
cmdobj = cmd_class(cmdopts, cmdargs).status
905
def _report_exception(summary, quiet=False):
994
907
log_error('bzr: ' + summary)
995
bzrlib.trace.log_exception(e)
908
bzrlib.trace.log_exception()
998
911
tb = sys.exc_info()[2]
1009
bzrlib.trace.create_tracefile(argv)
922
bzrlib.open_tracefile(argv)
1014
# do this here to catch EPIPE
929
# do this here inside the exception wrappers to catch EPIPE
1017
931
except BzrError, e:
1018
932
quiet = isinstance(e, (BzrCommandError))
1019
_report_exception(e, 'error: ' + e.args[0], quiet=quiet)
933
_report_exception('error: ' + e.args[0], quiet=quiet)
1020
934
if len(e.args) > 1:
1021
935
for h in e.args[1]:
1022
936
# some explanation or hints
1026
940
msg = 'assertion failed'
1028
942
msg += ': ' + str(e)
1029
_report_exception(e, msg)
943
_report_exception(msg)
1031
945
except KeyboardInterrupt, e:
1032
_report_exception(e, 'interrupted', quiet=True)
946
_report_exception('interrupted', quiet=True)
1034
948
except Exception, e:
1038
952
msg = 'broken pipe'
1040
954
msg = str(e).rstrip('\n')
1041
_report_exception(e, msg, quiet)
955
_report_exception(msg, quiet)
1044
958
bzrlib.trace.close_trace()