22
22
import bzrlib.trace
23
23
from bzrlib.trace import mutter, note, log_error, warning
24
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
25
from bzrlib.branch import Branch
24
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError
25
from bzrlib.branch import find_branch
26
26
from bzrlib import BZRDIR
27
27
from bzrlib.commands import Command
62
62
directory is shown. Otherwise, only the status of the specified
63
63
files or directories is reported. If a directory is given, status
64
64
is reported for everything inside that directory.
66
If a revision argument is given, the status is calculated against
67
that revision, or between two revisions if two are provided.
69
66
# XXX: FIXME: bzr status should accept a -r option to show changes
70
67
# relative to a revision, or between revisions
73
70
takes_options = ['all', 'show-ids']
74
71
aliases = ['st', 'stat']
76
def run(self, all=False, show_ids=False, file_list=None, revision=None):
73
def run(self, all=False, show_ids=False, file_list=None):
78
b = Branch.open_containing(file_list[0])
75
b = find_branch(file_list[0])
79
76
file_list = [b.relpath(x) for x in file_list]
80
77
# special case: only one path was given and it's the root
82
79
if file_list == ['']:
85
b = Branch.open_containing('.')
87
84
from bzrlib.status import show_status
88
85
show_status(b, show_unchanged=all, show_ids=show_ids,
89
specific_files=file_list, revision=revision)
86
specific_files=file_list)
92
89
class cmd_cat_revision(Command):
93
"""Write out metadata for a revision.
95
The revision to print can either be specified by a specific
96
revision identifier, or you can use --revision.
90
"""Write out metadata for a revision."""
100
takes_args = ['revision_id?']
101
takes_options = ['revision']
93
takes_args = ['revision_id']
103
def run(self, revision_id=None, revision=None):
104
from bzrlib.revisionspec import RevisionSpec
95
def run(self, revision_id):
97
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
106
if revision_id is not None and revision is not None:
107
raise BzrCommandError('You can only supply one of revision_id or --revision')
108
if revision_id is None and revision is None:
109
raise BzrCommandError('You must supply either --revision or a revision_id')
110
b = Branch.open_containing('.')
111
if revision_id is not None:
112
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
113
elif revision is not None:
116
raise BzrCommandError('You cannot specify a NULL revision.')
117
revno, rev_id = rev.in_history(b)
118
sys.stdout.write(b.get_revision_xml_file(rev_id).read())
121
100
class cmd_revno(Command):
122
101
"""Show current revision number.
124
103
This is equal to the number of revisions on this branch."""
126
print Branch.open_containing('.').revno()
105
print find_branch('.').revno()
129
108
class cmd_revision_info(Command):
133
112
takes_args = ['revision_info*']
134
113
takes_options = ['revision']
135
def run(self, revision=None, revision_info_list=[]):
136
from bzrlib.revisionspec import RevisionSpec
114
def run(self, revision=None, revision_info_list=None):
115
from bzrlib.branch import find_branch
139
118
if revision is not None:
140
119
revs.extend(revision)
141
120
if revision_info_list is not None:
142
for rev in revision_info_list:
143
revs.append(RevisionSpec(rev))
121
revs.extend(revision_info_list)
144
122
if len(revs) == 0:
145
123
raise BzrCommandError('You must supply a revision identifier')
147
b = Branch.open_containing('.')
150
revinfo = rev.in_history(b)
151
if revinfo.revno is None:
152
print ' %s' % revinfo.rev_id
154
print '%4d %s' % (revinfo.revno, revinfo.rev_id)
128
print '%4d %s' % b.get_revision_info(rev)
157
131
class cmd_add(Command):
220
194
takes_options = ['revision', 'show-ids']
222
196
def run(self, revision=None, show_ids=False):
223
b = Branch.open_containing('.')
225
199
inv = b.read_working_inventory()
227
201
if len(revision) > 1:
228
202
raise BzrCommandError('bzr inventory --revision takes'
229
203
' exactly one revision identifier')
230
inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
204
inv = b.get_revision_inventory(b.lookup_revision(revision[0]))
232
206
for path, entry in inv.entries():
247
221
takes_args = ['source$', 'dest']
248
222
def run(self, source_list, dest):
249
b = Branch.open_containing('.')
251
225
# TODO: glob expansion on windows?
252
226
b.move([b.relpath(s) for s in source_list], b.relpath(dest))
340
314
print "Using last location: %s" % stored_loc
341
315
location = stored_loc
342
316
cache_root = tempfile.mkdtemp()
343
from bzrlib.errors import DivergedBranches
344
br_from = Branch.open_containing(location)
317
from bzrlib.branch import DivergedBranches
318
br_from = find_branch(location)
345
319
location = br_from.base
346
320
old_revno = br_to.revno()
348
from bzrlib.errors import DivergedBranches
349
br_from = Branch.open(location)
350
br_from.setup_caching(cache_root)
322
from branch import find_cached_branch, DivergedBranches
323
br_from = find_cached_branch(location, cache_root)
351
324
location = br_from.base
352
325
old_revno = br_to.revno()
373
346
To retrieve the branch as of a particular revision, supply the --revision
374
347
parameter, as in "branch foo/bar -r 5".
376
--basis is to speed up branching from remote branches. When specified, it
377
copies all the file-contents, inventory and revision data from the basis
378
branch before copying anything from the remote branch.
380
349
takes_args = ['from_location', 'to_location?']
381
takes_options = ['revision', 'basis']
350
takes_options = ['revision']
382
351
aliases = ['get', 'clone']
384
def run(self, from_location, to_location=None, revision=None, basis=None):
385
from bzrlib.clone import copy_branch
353
def run(self, from_location, to_location=None, revision=None):
354
from bzrlib.branch import copy_branch, find_cached_branch
388
357
from shutil import rmtree
394
363
raise BzrCommandError(
395
364
'bzr branch --revision takes exactly 1 revision value')
397
br_from = Branch.open(from_location)
366
br_from = find_cached_branch(from_location, cache_root)
398
367
except OSError, e:
399
368
if e.errno == errno.ENOENT:
400
369
raise BzrCommandError('Source location "%s" does not'
401
370
' exist.' % to_location)
404
br_from.setup_caching(cache_root)
405
if basis is not None:
406
basis_branch = Branch.open_containing(basis)
409
if len(revision) == 1 and revision[0] is not None:
410
revision_id = revision[0].in_history(br_from)[1]
413
373
if to_location is None:
414
374
to_location = os.path.basename(from_location.rstrip("/\\"))
427
copy_branch(br_from, to_location, revision_id, basis_branch)
387
copy_branch(br_from, to_location, revision[0])
428
388
except bzrlib.errors.NoSuchRevision:
429
389
rmtree(to_location)
430
390
msg = "The branch %s has no revision %d." % (from_location, revision[0])
431
391
raise BzrCommandError(msg)
432
except bzrlib.errors.UnlistableBranch:
433
msg = "The branch %s cannot be used as a --basis"
435
393
rmtree(cache_root)
519
477
"""Display list of revision ids on this branch."""
522
for patchid in Branch.open_containing('.').revision_history():
480
for patchid in find_branch('.').revision_history():
526
class cmd_ancestry(Command):
527
"""List all revisions merged into this branch."""
531
for revision_id in b.get_ancestry(b.last_revision()):
535
484
class cmd_directories(Command):
536
485
"""Display list of versioned directories in this branch."""
538
for name, ie in Branch.open_containing('.').read_working_inventory().directories():
487
for name, ie in find_branch('.').read_working_inventory().directories():
649
599
from bzrlib.delta import compare_trees
651
b = Branch.open_containing('.')
652
602
td = compare_trees(b.basis_tree(), b.working_tree())
654
for path, id, kind, text_modified, meta_modified in td.modified:
604
for path, id, kind in td.modified:
696
646
--message allows you to give a regular expression, which will be evaluated
697
647
so that only matching entries will be displayed.
649
TODO: Make --revision support uuid: and hash: [future tag:] notation.
700
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
702
653
takes_args = ['filename?']
703
654
takes_options = ['forward', 'timezone', 'verbose', 'show-ids', 'revision',
704
655
'long', 'message', 'short',]
717
668
direction = (forward and 'forward') or 'reverse'
720
b = Branch.open_containing(filename)
671
b = find_branch(filename)
721
672
fp = b.relpath(filename)
723
674
file_id = b.read_working_inventory().path2id(fp)
725
676
file_id = None # points to branch root
727
b = Branch.open_containing('.')
730
681
if revision is None:
733
684
elif len(revision) == 1:
734
rev1 = rev2 = revision[0].in_history(b).revno
685
rev1 = rev2 = b.get_revision_info(revision[0])[0]
735
686
elif len(revision) == 2:
736
rev1 = revision[0].in_history(b).revno
737
rev2 = revision[1].in_history(b).revno
687
rev1 = b.get_revision_info(revision[0])[0]
688
rev2 = b.get_revision_info(revision[1])[0]
739
690
raise BzrCommandError('bzr log --revision takes one or two values.')
777
728
takes_args = ["filename"]
778
729
def run(self, filename):
779
b = Branch.open_containing(filename)
730
b = find_branch(filename)
780
731
inv = b.read_working_inventory()
781
732
file_id = inv.path2id(b.relpath(filename))
782
733
for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
792
743
def run(self, revision=None, verbose=False):
793
b = Branch.open_containing('.')
794
745
if revision == None:
795
746
tree = b.working_tree()
797
tree = b.revision_tree(revision.in_history(b).rev_id)
798
for fp, fc, kind, fid, entry in tree.list_files():
748
tree = b.revision_tree(b.lookup_revision(revision))
750
for fp, fc, kind, fid in tree.list_files():
800
kindch = entry.kind_character()
752
if kind == 'directory':
801
759
print '%-8s %s%s' % (fc, fp, kindch)
877
835
See also: bzr ignore"""
879
tree = Branch.open_containing('.').working_tree()
880
for path, file_class, kind, file_id, entry in tree.list_files():
837
tree = find_branch('.').working_tree()
838
for path, file_class, kind, file_id in tree.list_files():
881
839
if file_class != 'I':
883
841
## XXX: Slightly inefficient since this was already calculated
919
877
takes_options = ['revision', 'format', 'root']
920
878
def run(self, dest, revision=None, format=None, root=None):
922
b = Branch.open_containing('.')
923
881
if revision is None:
924
rev_id = b.last_revision()
882
rev_id = b.last_patch()
926
884
if len(revision) != 1:
927
885
raise BzrError('bzr export --revision takes exactly 1 argument')
928
rev_id = revision[0].in_history(b).rev_id
886
revno, rev_id = b.get_revision_info(revision[0])
929
887
t = b.revision_tree(rev_id)
930
arg_root, ext = os.path.splitext(os.path.basename(dest))
931
if ext in ('.gz', '.bz2'):
932
new_root, new_ext = os.path.splitext(arg_root)
933
if new_ext == '.tar':
888
root, ext = os.path.splitext(dest)
939
890
if ext in (".tar",):
941
elif ext in (".tar.gz", ".tgz"):
892
elif ext in (".gz", ".tgz"):
943
elif ext in (".tar.bz2", ".tbz2"):
894
elif ext in (".bz2", ".tbz2"):
954
905
takes_args = ['filename']
956
907
def run(self, filename, revision=None):
958
909
raise BzrCommandError("bzr cat requires a revision number")
959
910
elif len(revision) != 1:
960
911
raise BzrCommandError("bzr cat --revision takes exactly one number")
961
b = Branch.open_containing('.')
962
b.print_file(b.relpath(filename), revision[0].in_history(b).revno)
913
b.print_file(b.relpath(filename), revision[0])
965
916
class cmd_local_time_offset(Command):
992
943
aliases = ['ci', 'checkin']
994
945
# TODO: Give better message for -s, --summary, used by tla people
996
# XXX: verbose currently does nothing
998
947
def run(self, message=None, file=None, verbose=True, selected_list=None,
999
948
unchanged=False):
1002
951
from bzrlib.status import show_status
1003
952
from cStringIO import StringIO
1005
b = Branch.open_containing('.')
1006
955
if selected_list:
1007
956
selected_list = [b.relpath(s) for s in selected_list]
1009
if message is None and not file:
958
if not message and not file:
1010
959
catcher = StringIO()
1011
960
show_status(b, specific_files=selected_list,
1012
961
to_file=catcher)
1013
962
message = edit_commit_message(catcher.getvalue())
1015
964
if message is None:
1016
965
raise BzrCommandError("please specify a commit message"
1017
966
" with either --message or --file")
1023
972
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1026
raise BzrCommandError("empty commit message specified")
975
b.commit(message, verbose=verbose,
1030
976
specific_files=selected_list,
1031
977
allow_pointless=unchanged)
1032
978
except PointlessCommit:
1105
1049
class cmd_selftest(Command):
1106
"""Run internal test suite.
1108
This creates temporary test directories in the working directory,
1109
but not existing data is affected. These directories are deleted
1110
if the tests pass, or left behind to help in debugging if they
1113
If arguments are given, they are regular expressions that say
1114
which tests should run."""
1115
# TODO: --list should give a list of all available tests
1050
"""Run internal test suite"""
1117
takes_args = ['testnames*']
1118
1052
takes_options = ['verbose', 'pattern']
1119
def run(self, testnames_list=None, verbose=False, pattern=".*"):
1053
def run(self, verbose=False, pattern=".*"):
1120
1054
import bzrlib.ui
1121
1055
from bzrlib.selftest import selftest
1122
1056
# we don't want progress meters from the tests to go to the
1126
1060
bzrlib.trace.info('running tests...')
1128
1062
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1129
result = selftest(verbose=verbose,
1131
testnames=testnames_list)
1063
result = selftest(verbose=verbose, pattern=pattern)
1133
1065
bzrlib.trace.info('tests passed')
1176
1108
def run(self, branch, other):
1177
1109
from bzrlib.revision import common_ancestor, MultipleRevisionSources
1179
branch1 = Branch.open_containing(branch)
1180
branch2 = Branch.open_containing(other)
1111
branch1 = find_branch(branch)
1112
branch2 = find_branch(other)
1182
1114
history_1 = branch1.revision_history()
1183
1115
history_2 = branch2.revision_history()
1185
last1 = branch1.last_revision()
1186
last2 = branch2.last_revision()
1117
last1 = branch1.last_patch()
1118
last2 = branch2.last_patch()
1188
1120
source = MultipleRevisionSources(branch1, branch2)
1246
1178
other = [branch, -1]
1248
1180
if len(revision) == 1:
1181
other = [branch, revision[0]]
1249
1182
base = [None, None]
1250
other = [branch, revision[0].in_history(branch).revno]
1252
1184
assert len(revision) == 2
1253
1185
if None in revision:
1254
1186
raise BzrCommandError(
1255
1187
"Merge doesn't permit that revision specifier.")
1256
b = Branch.open(branch)
1258
base = [branch, revision[0].in_history(b).revno]
1259
other = [branch, revision[1].in_history(b).revno]
1188
base = [branch, revision[0]]
1189
other = [branch, revision[1]]
1262
1192
merge(other, base, check_clean=(not force), merge_type=merge_type)
1284
1214
def run(self, revision=None, no_backup=False, file_list=None):
1285
1215
from bzrlib.merge import merge
1216
from bzrlib.branch import Branch
1286
1217
from bzrlib.commands import parse_spec
1288
1219
if file_list is not None:
1289
1220
if len(file_list) == 0:
1290
1221
raise BzrCommandError("No files specified")
1291
1222
if revision is None:
1293
1224
elif len(revision) != 1:
1294
1225
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1296
b = Branch.open_containing('.')
1297
revno = revision[0].in_history(b).revno
1298
merge(('.', revno), parse_spec('.'),
1226
merge(('.', revision[0]), parse_spec('.'),
1299
1227
check_clean=False,
1300
1228
ignore_zero=True,
1301
1229
backup_files=not no_backup,
1302
1230
file_list=file_list)
1303
1231
if not file_list:
1304
Branch.open_containing('.').set_pending_merges([])
1232
Branch('.').set_pending_merges([])
1307
1235
class cmd_assert_fail(Command):
1339
1267
shellcomplete.shellcomplete(context)
1342
class cmd_fetch(Command):
1343
"""Copy in history from another branch but don't merge it.
1345
This is an internal method used for pull and merge."""
1347
takes_args = ['from_branch', 'to_branch']
1348
def run(self, from_branch, to_branch):
1349
from bzrlib.fetch import Fetcher
1350
from bzrlib.branch import Branch
1351
from_b = Branch(from_branch)
1352
to_b = Branch(to_branch)
1353
Fetcher(to_b, from_b)
1357
1270
class cmd_missing(Command):
1358
1271
"""What is missing in this branch relative to other branch.
1360
# TODO: rewrite this in terms of ancestry so that it shows only
1363
1273
takes_args = ['remote?']
1364
1274
aliases = ['mis', 'miss']
1365
1275
# We don't have to add quiet to the list, because
1383
1293
print "Using last location: %s" % parent
1384
1294
remote = parent
1385
1295
elif parent is None:
1386
# We only update parent if it did not exist, missing
1387
# should not change the parent
1296
# We only update parent if it did not exist, missing should not change the parent
1388
1297
b.set_parent(remote)
1389
br_remote = Branch.open_containing(remote)
1298
br_remote = find_branch(remote)
1390
1300
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1393
1304
class cmd_plugins(Command):
1394
1305
"""List plugins"""