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
"""builtin bzr commands"""
19
# DO NOT change this to cStringIO - it results in control files
21
# FIXIT! (Only deal with byte streams OR unicode at any one layer.)
24
from StringIO import StringIO
29
22
from bzrlib import BZRDIR
30
from bzrlib.commands import Command, display_command
23
from bzrlib.commands import Command
31
24
from bzrlib.branch import Branch
32
from bzrlib.revision import common_ancestor
33
import bzrlib.errors as errors
34
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
35
NotBranchError, DivergedBranches, NotConflicted,
36
NoSuchFile, NoWorkingTree, FileInWrongBranch)
25
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
26
from bzrlib.errors import DivergedBranches
37
27
from bzrlib.option import Option
38
28
from bzrlib.revisionspec import RevisionSpec
39
29
import bzrlib.trace
40
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
30
from bzrlib.trace import mutter, note, log_error, warning
41
31
from bzrlib.workingtree import WorkingTree
42
from bzrlib.log import show_one_log
45
def tree_files(file_list, default_branch=u'.'):
47
return internal_tree_files(file_list, default_branch)
48
except FileInWrongBranch, e:
49
raise BzrCommandError("%s is not in the same branch as %s" %
50
(e.path, file_list[0]))
52
def internal_tree_files(file_list, default_branch=u'.'):
54
Return a branch and list of branch-relative paths.
55
If supplied file_list is empty or None, the branch default will be used,
56
and returned file_list will match the original.
58
if file_list is None or len(file_list) == 0:
59
return WorkingTree.open_containing(default_branch)[0], file_list
60
tree = WorkingTree.open_containing(file_list[0])[0]
62
for filename in file_list:
64
new_list.append(tree.relpath(filename))
65
except errors.PathNotChild:
66
raise FileInWrongBranch(tree.branch, filename)
70
# TODO: Make sure no commands unconditionally use the working directory as a
71
# branch. If a filename argument is used, the first of them should be used to
72
# specify the branch. (Perhaps this can be factored out into some kind of
73
# Argument class, representing a file in a branch, where the first occurrence
76
34
class cmd_status(Command):
77
35
"""Display status summary.
112
70
If a revision argument is given, the status is calculated against
113
71
that revision, or between two revisions if two are provided.
116
# TODO: --no-recurse, --recurse options
73
# XXX: FIXME: bzr status should accept a -r option to show changes
74
# relative to a revision, or between revisions
118
76
takes_args = ['file*']
119
takes_options = ['all', 'show-ids', 'revision']
77
takes_options = ['all', 'show-ids']
120
78
aliases = ['st', 'stat']
123
80
def run(self, all=False, show_ids=False, file_list=None, revision=None):
124
tree, file_list = tree_files(file_list)
82
b = Branch.open_containing(file_list[0])
83
tree = WorkingTree(b.base, b)
84
file_list = [tree.relpath(x) for x in file_list]
85
# special case: only one path was given and it's the root
90
b = Branch.open_containing('.')
126
92
from bzrlib.status import show_status
127
show_status(tree.branch, show_unchanged=all, show_ids=show_ids,
93
show_status(b, show_unchanged=all, show_ids=show_ids,
128
94
specific_files=file_list, revision=revision)
139
105
takes_args = ['revision_id?']
140
106
takes_options = ['revision']
143
108
def run(self, revision_id=None, revision=None):
145
110
if revision_id is not None and revision is not None:
146
111
raise BzrCommandError('You can only supply one of revision_id or --revision')
147
112
if revision_id is None and revision is None:
148
113
raise BzrCommandError('You must supply either --revision or a revision_id')
149
b = WorkingTree.open_containing(u'.')[0].branch
114
b = Branch.open_containing('.')
150
115
if revision_id is not None:
151
sys.stdout.write(b.get_revision_xml(revision_id))
116
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
152
117
elif revision is not None:
153
118
for rev in revision:
155
120
raise BzrCommandError('You cannot specify a NULL revision.')
156
121
revno, rev_id = rev.in_history(b)
157
sys.stdout.write(b.get_revision_xml(rev_id))
122
sys.stdout.write(b.get_revision_xml_file(rev_id).read())
160
125
class cmd_revno(Command):
161
126
"""Show current revision number.
163
128
This is equal to the number of revisions on this branch."""
164
takes_args = ['location?']
166
def run(self, location=u'.'):
167
print Branch.open_containing(location)[0].revno()
130
print Branch.open_containing('.').revno()
170
133
class cmd_revision_info(Command):
217
179
implicitly add the parent, and so on up to the root. This means
218
180
you should never need to explictly add a directory, they'll just
219
181
get added when you add a file in the directory.
221
--dry-run will show which files would be added, but not actually
224
183
takes_args = ['file*']
225
takes_options = ['no-recurse', 'dry-run', 'verbose']
227
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
232
# This is pointless, but I'd rather not raise an error
233
action = bzrlib.add.add_action_null
235
action = bzrlib.add.add_action_print
237
action = bzrlib.add.add_action_add
184
takes_options = ['no-recurse', 'quiet']
186
def run(self, file_list, no_recurse=False, quiet=False):
187
from bzrlib.add import smart_add, add_reporter_print, add_reporter_null
189
reporter = add_reporter_null
239
action = bzrlib.add.add_action_add_and_print
241
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
244
for glob in sorted(ignored.keys()):
245
match_len = len(ignored[glob])
247
for path in ignored[glob]:
248
print "ignored %s matching \"%s\"" % (path, glob)
250
print "ignored %d file(s) matching \"%s\"" % (match_len,
252
print "If you wish to add some of these files, please add them"\
191
reporter = add_reporter_print
192
smart_add(file_list, not no_recurse, reporter)
256
195
class cmd_mkdir(Command):
273
215
takes_args = ['filename']
277
218
def run(self, filename):
278
tree, relpath = WorkingTree.open_containing(filename)
219
branch = Branch.open_containing(filename)
220
print WorkingTree(branch.base, branch).relpath(filename)
282
223
class cmd_inventory(Command):
283
"""Show inventory of the current working copy or a revision.
285
It is possible to limit the output to a particular entry
286
type using the --kind option. For example; --kind file.
288
takes_options = ['revision', 'show-ids', 'kind']
224
"""Show inventory of the current working copy or a revision."""
225
takes_options = ['revision', 'show-ids']
291
def run(self, revision=None, show_ids=False, kind=None):
292
if kind and kind not in ['file', 'directory', 'symlink']:
293
raise BzrCommandError('invalid kind specified')
294
tree = WorkingTree.open_containing(u'.')[0]
227
def run(self, revision=None, show_ids=False):
228
b = Branch.open_containing('.')
295
229
if revision is None:
296
inv = tree.read_working_inventory()
230
inv = b.read_working_inventory()
298
232
if len(revision) > 1:
299
233
raise BzrCommandError('bzr inventory --revision takes'
300
234
' exactly one revision identifier')
301
inv = tree.branch.get_revision_inventory(
302
revision[0].in_history(tree.branch).rev_id)
235
inv = b.get_revision_inventory(revision[0].in_history(b).rev_id)
304
237
for path, entry in inv.entries():
305
if kind and kind != entry.kind:
308
239
print '%-50s %s' % (path, entry.file_id)
363
297
def run(self, names_list):
364
298
if len(names_list) < 2:
365
299
raise BzrCommandError("missing file argument")
366
tree, rel_names = tree_files(names_list)
300
b = Branch.open_containing(names_list[0])
301
tree = WorkingTree(b.base, b)
302
rel_names = [tree.relpath(x) for x in names_list]
368
304
if os.path.isdir(names_list[-1]):
369
305
# move into existing directory
370
for pair in tree.move(rel_names[:-1], rel_names[-1]):
306
for pair in b.move(rel_names[:-1], rel_names[-1]):
371
307
print "%s => %s" % pair
373
309
if len(names_list) != 2:
374
310
raise BzrCommandError('to mv multiple files the destination '
375
311
'must be a versioned directory')
376
tree.rename_one(rel_names[0], rel_names[1])
312
b.rename_one(rel_names[0], rel_names[1])
377
313
print "%s => %s" % (rel_names[0], rel_names[1])
380
318
class cmd_pull(Command):
381
319
"""Pull any changes from another branch into the current one.
383
If there is no default location set, the first pull will set it. After
384
that, you can omit the location to use the default. To change the
385
default, use --remember.
321
If the location is omitted, the last-used location will be used.
322
Both the revision history and the working directory will be
387
325
This command only works on branches that have not diverged. Branches are
388
326
considered diverged if both branches have had commits without first
389
327
pulling from the other.
391
329
If branches have diverged, you can use 'bzr merge' to pull the text changes
392
from one into the other. Once one branch has merged, the other should
393
be able to pull it again.
395
If you want to forget your local changes and just update your branch to
396
match the remote one, use --overwrite.
330
from one into the other.
398
takes_options = ['remember', 'overwrite', 'verbose']
332
takes_options = ['remember']
399
333
takes_args = ['location?']
401
def run(self, location=None, remember=False, overwrite=False, verbose=False):
335
def run(self, location=None, remember=False):
402
336
from bzrlib.merge import merge
403
338
from shutil import rmtree
405
# FIXME: too much stuff is in the command class
406
tree_to = WorkingTree.open_containing(u'.')[0]
407
stored_loc = tree_to.branch.get_parent()
341
br_to = Branch.open_containing('.')
342
stored_loc = br_to.get_parent()
408
343
if location is None:
409
344
if stored_loc is None:
410
345
raise BzrCommandError("No pull location known or specified.")
412
347
print "Using saved location: %s" % stored_loc
413
348
location = stored_loc
349
cache_root = tempfile.mkdtemp()
415
350
br_from = Branch.open(location)
416
br_to = tree_to.branch
418
old_rh = br_to.revision_history()
419
count = tree_to.pull(br_from, overwrite)
421
if br_to.get_parent() is None or remember:
422
br_to.set_parent(location)
423
note('%d revision(s) pulled.' % (count,))
426
new_rh = tree_to.branch.revision_history()
429
from bzrlib.log import show_changed_revisions
430
show_changed_revisions(tree_to.branch, old_rh, new_rh)
433
class cmd_push(Command):
434
"""Push this branch into another branch.
436
The remote branch will not have its working tree populated because this
437
is both expensive, and may not be supported on the remote file system.
439
Some smart servers or protocols *may* put the working tree in place.
441
If there is no default push location set, the first push will set it.
442
After that, you can omit the location to use the default. To change the
443
default, use --remember.
445
This command only works on branches that have not diverged. Branches are
446
considered diverged if the branch being pushed to is not an older version
449
If branches have diverged, you can use 'bzr push --overwrite' to replace
450
the other branch completely.
452
If you want to ensure you have the different changes in the other branch,
453
do a merge (see bzr help merge) from the other branch, and commit that
454
before doing a 'push --overwrite'.
456
takes_options = ['remember', 'overwrite',
457
Option('create-prefix',
458
help='Create the path leading up to the branch '
459
'if it does not already exist')]
460
takes_args = ['location?']
462
def run(self, location=None, remember=False, overwrite=False,
463
create_prefix=False, verbose=False):
464
# FIXME: Way too big! Put this into a function called from the
467
from shutil import rmtree
468
from bzrlib.transport import get_transport
470
tree_from = WorkingTree.open_containing(u'.')[0]
471
br_from = tree_from.branch
472
stored_loc = tree_from.branch.get_push_location()
474
if stored_loc is None:
475
raise BzrCommandError("No push location known or specified.")
477
print "Using saved location: %s" % stored_loc
478
location = stored_loc
480
br_to = Branch.open(location)
481
except NotBranchError:
483
transport = get_transport(location).clone('..')
484
if not create_prefix:
486
transport.mkdir(transport.relpath(location))
488
raise BzrCommandError("Parent directory of %s "
489
"does not exist." % location)
491
current = transport.base
492
needed = [(transport, transport.relpath(location))]
495
transport, relpath = needed[-1]
496
transport.mkdir(relpath)
499
new_transport = transport.clone('..')
500
needed.append((new_transport,
501
new_transport.relpath(transport.base)))
502
if new_transport.base == transport.base:
503
raise BzrCommandError("Could not creeate "
505
br_to = Branch.initialize(location)
506
old_rh = br_to.revision_history()
353
br_from.setup_caching(cache_root)
354
location = br_from.base
355
old_revno = br_to.revno()
356
old_revision_history = br_to.revision_history()
509
tree_to = br_to.working_tree()
510
except NoWorkingTree:
511
# TODO: This should be updated for branches which don't have a
512
# working tree, as opposed to ones where we just couldn't
514
warning('Unable to update the working tree of: %s' % (br_to.base,))
515
count = br_to.pull(br_from, overwrite)
517
count = tree_to.pull(br_from, overwrite)
518
except DivergedBranches:
519
raise BzrCommandError("These branches have diverged."
520
" Try a merge then push with overwrite.")
521
if br_from.get_push_location() is None or remember:
522
br_from.set_push_location(location)
523
note('%d revision(s) pushed.' % (count,))
358
br_to.update_revisions(br_from)
359
except DivergedBranches:
360
raise BzrCommandError("These branches have diverged."
362
new_revision_history = br_to.revision_history()
363
if new_revision_history != old_revision_history:
364
merge(('.', -1), ('.', old_revno), check_clean=False)
365
if stored_loc is None or remember:
366
br_to.set_parent(location)
526
new_rh = br_to.revision_history()
529
from bzrlib.log import show_changed_revisions
530
show_changed_revisions(br_to, old_rh, new_rh)
533
373
class cmd_branch(Command):
772
598
takes_options = ['revision', 'diff-options']
773
599
aliases = ['di', 'dif']
776
601
def run(self, revision=None, file_list=None, diff_options=None):
777
602
from bzrlib.diff import show_diff
779
tree, file_list = internal_tree_files(file_list)
782
except FileInWrongBranch:
783
if len(file_list) != 2:
784
raise BzrCommandError("Files are in different branches")
786
b, file1 = Branch.open_containing(file_list[0])
787
b2, file2 = Branch.open_containing(file_list[1])
788
if file1 != "" or file2 != "":
789
# FIXME diff those two files. rbc 20051123
790
raise BzrCommandError("Files are in different branches")
605
b = Branch.open_containing(file_list[0])
606
tree = WorkingTree(b.base, b)
607
file_list = [tree.relpath(f) for f in file_list]
608
if file_list == ['']:
609
# just pointing to top-of-tree
612
b = Branch.open_containing('.')
792
614
if revision is not None:
794
raise BzrCommandError("Can't specify -r with two branches")
795
615
if len(revision) == 1:
796
return show_diff(tree.branch, revision[0], specific_files=file_list,
797
external_diff_options=diff_options)
616
show_diff(b, revision[0], specific_files=file_list,
617
external_diff_options=diff_options)
798
618
elif len(revision) == 2:
799
return show_diff(tree.branch, revision[0], specific_files=file_list,
800
external_diff_options=diff_options,
801
revision2=revision[1])
619
show_diff(b, revision[0], specific_files=file_list,
620
external_diff_options=diff_options,
621
revision2=revision[1])
803
623
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
806
return show_diff(b, None, specific_files=file_list,
807
external_diff_options=diff_options, b2=b2)
809
return show_diff(tree.branch, None, specific_files=file_list,
810
external_diff_options=diff_options)
625
show_diff(b, None, specific_files=file_list,
626
external_diff_options=diff_options)
813
631
class cmd_deleted(Command):
1008
807
# TODO: Take a revision or remote path and list that tree instead.
1010
takes_options = ['verbose', 'revision',
1011
Option('non-recursive',
1012
help='don\'t recurse into sub-directories'),
1014
help='Print all paths from the root of the branch.'),
1015
Option('unknown', help='Print unknown files'),
1016
Option('versioned', help='Print versioned files'),
1017
Option('ignored', help='Print ignored files'),
1019
Option('null', help='Null separate the files'),
1022
def run(self, revision=None, verbose=False,
1023
non_recursive=False, from_root=False,
1024
unknown=False, versioned=False, ignored=False,
1027
if verbose and null:
1028
raise BzrCommandError('Cannot set both --verbose and --null')
1029
all = not (unknown or versioned or ignored)
1031
selection = {'I':ignored, '?':unknown, 'V':versioned}
1033
tree, relpath = WorkingTree.open_containing(u'.')
1038
if revision is not None:
1039
tree = tree.branch.revision_tree(
1040
revision[0].in_history(tree.branch).rev_id)
809
def run(self, revision=None, verbose=False):
810
b = Branch.open_containing('.')
812
tree = b.working_tree()
814
tree = b.revision_tree(revision.in_history(b).rev_id)
1041
815
for fp, fc, kind, fid, entry in tree.list_files():
1042
if fp.startswith(relpath):
1043
fp = fp[len(relpath):]
1044
if non_recursive and '/' in fp:
1046
if not all and not selection[fc]:
1049
kindch = entry.kind_character()
1050
print '%-8s %s%s' % (fc, fp, kindch)
1052
sys.stdout.write(fp)
1053
sys.stdout.write('\0')
817
kindch = entry.kind_character()
818
print '%-8s %s%s' % (fc, fp, kindch)
1059
824
class cmd_unknowns(Command):
1060
825
"""List unknown files."""
1063
827
from bzrlib.osutils import quotefn
1064
for f in WorkingTree.open_containing(u'.')[0].unknowns():
828
for f in Branch.open_containing('.').unknowns():
1065
829
print quotefn(f)
1068
833
class cmd_ignore(Command):
1069
834
"""Ignore a command or pattern.
1168
932
is found exports to a directory (equivalent to --format=dir).
1170
934
Root may be the top directory for tar, tgz and tbz2 formats. If none
1171
is given, the top directory will be the root name of the file.
1173
Note: export of tree with non-ascii filenames to zip is not supported.
1175
Supported formats Autodetected by extension
1176
----------------- -------------------------
1179
tbz2 .tar.bz2, .tbz2
935
is given, the top directory will be the root name of the file."""
936
# TODO: list known exporters
1183
937
takes_args = ['dest']
1184
938
takes_options = ['revision', 'format', 'root']
1185
939
def run(self, dest, revision=None, format=None, root=None):
1187
from bzrlib.export import export
1188
tree = WorkingTree.open_containing(u'.')[0]
941
b = Branch.open_containing('.')
1190
942
if revision is None:
1191
# should be tree.last_revision FIXME
1192
943
rev_id = b.last_revision()
1194
945
if len(revision) != 1:
1195
946
raise BzrError('bzr export --revision takes exactly 1 argument')
1196
947
rev_id = revision[0].in_history(b).rev_id
1197
948
t = b.revision_tree(rev_id)
1199
export(t, dest, format, root)
1200
except errors.NoSuchExportFormat, e:
1201
raise BzrCommandError('Unsupported export format: %s' % e.format)
949
arg_root, ext = os.path.splitext(os.path.basename(dest))
950
if ext in ('.gz', '.bz2'):
951
new_root, new_ext = os.path.splitext(arg_root)
952
if new_ext == '.tar':
960
elif ext in (".tar.gz", ".tgz"):
962
elif ext in (".tar.bz2", ".tbz2"):
966
t.export(dest, format, root)
1204
969
class cmd_cat(Command):
1265
1017
Option('file', type=str,
1266
1018
argname='msgfile',
1267
1019
help='file containing commit message'),
1269
help="refuse to commit if there are unknown "
1270
"files in the working tree."),
1272
1021
aliases = ['ci', 'checkin']
1274
1023
def run(self, message=None, file=None, verbose=True, selected_list=None,
1275
unchanged=False, strict=False):
1276
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1278
from bzrlib.msgeditor import edit_commit_message, \
1279
make_commit_message_template
1025
from bzrlib.errors import PointlessCommit, ConflictsInTree
1026
from bzrlib.msgeditor import edit_commit_message
1280
1027
from bzrlib.status import show_status
1281
from tempfile import TemporaryFile
1284
# TODO: Need a blackbox test for invoking the external editor; may be
1285
# slightly problematic to run this cross-platform.
1287
# TODO: do more checks that the commit will succeed before
1288
# spending the user's valuable time typing a commit message.
1290
# TODO: if the commit *does* happen to fail, then save the commit
1291
# message to a temporary file where it can be recovered
1292
tree, selected_list = tree_files(selected_list)
1028
from cStringIO import StringIO
1030
b = Branch.open_containing('.')
1031
tree = WorkingTree(b.base, b)
1033
selected_list = [tree.relpath(s) for s in selected_list]
1293
1034
if message is None and not file:
1294
template = make_commit_message_template(tree, selected_list)
1295
message = edit_commit_message(template)
1035
catcher = StringIO()
1036
show_status(b, specific_files=selected_list,
1038
message = edit_commit_message(catcher.getvalue())
1296
1040
if message is None:
1297
1041
raise BzrCommandError("please specify a commit message"
1298
1042
" with either --message or --file")
1613
class cmd_remerge(Command):
1616
takes_args = ['file*']
1617
takes_options = ['merge-type', 'reprocess',
1618
Option('show-base', help="Show base revision text in "
1621
def run(self, file_list=None, merge_type=None, show_base=False,
1623
from bzrlib.merge import merge_inner, transform_tree
1624
from bzrlib.merge_core import ApplyMerge3
1625
if merge_type is None:
1626
merge_type = ApplyMerge3
1627
tree, file_list = tree_files(file_list)
1630
pending_merges = tree.pending_merges()
1631
if len(pending_merges) != 1:
1632
raise BzrCommandError("Sorry, remerge only works after normal"
1633
+ " merges. Not cherrypicking or"
1635
base_revision = common_ancestor(tree.branch.last_revision(),
1636
pending_merges[0], tree.branch)
1637
base_tree = tree.branch.revision_tree(base_revision)
1638
other_tree = tree.branch.revision_tree(pending_merges[0])
1639
interesting_ids = None
1640
if file_list is not None:
1641
interesting_ids = set()
1642
for filename in file_list:
1643
file_id = tree.path2id(filename)
1644
interesting_ids.add(file_id)
1645
if tree.kind(file_id) != "directory":
1648
for name, ie in tree.inventory.iter_entries(file_id):
1649
interesting_ids.add(ie.file_id)
1650
transform_tree(tree, tree.branch.basis_tree(), interesting_ids)
1651
if file_list is None:
1652
restore_files = list(tree.iter_conflicts())
1654
restore_files = file_list
1655
for filename in restore_files:
1657
restore(tree.abspath(filename))
1658
except NotConflicted:
1660
conflicts = merge_inner(tree.branch, other_tree, base_tree,
1661
interesting_ids = interesting_ids,
1662
other_rev_id=pending_merges[0],
1663
merge_type=merge_type,
1664
show_base=show_base,
1665
reprocess=reprocess)
1673
1314
class cmd_revert(Command):
1674
1315
"""Reverse all changes since the last commit.
1749
1389
def run(self, from_branch, to_branch):
1750
1390
from bzrlib.fetch import Fetcher
1751
1391
from bzrlib.branch import Branch
1752
from_b = Branch.open(from_branch)
1753
to_b = Branch.open(to_branch)
1758
Fetcher(to_b, from_b)
1392
from_b = Branch(from_branch)
1393
to_b = Branch(to_branch)
1394
Fetcher(to_b, from_b)
1765
1398
class cmd_missing(Command):
1766
"""Show unmerged/unpulled revisions between two branches.
1768
OTHER_BRANCH may be local or remote."""
1769
takes_args = ['other_branch?']
1770
takes_options = [Option('reverse', 'Reverse the order of revisions'),
1772
'Display changes in the local branch only'),
1773
Option('theirs-only',
1774
'Display changes in the remote branch only'),
1782
def run(self, other_branch=None, reverse=False, mine_only=False,
1783
theirs_only=False, long=True, short=False, line=False,
1784
show_ids=False, verbose=False):
1785
from bzrlib.missing import find_unmerged, iter_log_data
1786
from bzrlib.log import log_formatter
1787
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
1788
parent = local_branch.get_parent()
1789
if other_branch is None:
1790
other_branch = parent
1791
if other_branch is None:
1399
"""What is missing in this branch relative to other branch.
1401
# TODO: rewrite this in terms of ancestry so that it shows only
1404
takes_args = ['remote?']
1405
aliases = ['mis', 'miss']
1406
# We don't have to add quiet to the list, because
1407
# unknown options are parsed as booleans
1408
takes_options = ['verbose', 'quiet']
1410
def run(self, remote=None, verbose=False, quiet=False):
1411
from bzrlib.errors import BzrCommandError
1412
from bzrlib.missing import show_missing
1414
if verbose and quiet:
1415
raise BzrCommandError('Cannot pass both quiet and verbose')
1417
b = Branch.open_containing('.')
1418
parent = b.get_parent()
1792
1421
raise BzrCommandError("No missing location known or specified.")
1793
print "Using last location: " + local_branch.get_parent()
1794
remote_branch = bzrlib.branch.Branch.open(other_branch)
1795
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
1796
log_format = get_log_format(long=long, short=short, line=line)
1797
lf = log_formatter(log_format, sys.stdout,
1799
show_timezone='original')
1800
if reverse is False:
1801
local_extra.reverse()
1802
remote_extra.reverse()
1803
if local_extra and not theirs_only:
1804
print "You have %d extra revision(s):" % len(local_extra)
1805
for data in iter_log_data(local_extra, local_branch, verbose):
1807
printed_local = True
1809
printed_local = False
1810
if remote_extra and not mine_only:
1811
if printed_local is True:
1813
print "You are missing %d revision(s):" % len(remote_extra)
1814
for data in iter_log_data(remote_extra, remote_branch, verbose):
1816
if not remote_extra and not local_extra:
1818
print "Branches are up to date."
1821
if parent is None and other_branch is not None:
1822
local_branch.set_parent(other_branch)
1424
print "Using last location: %s" % parent
1426
elif parent is None:
1427
# We only update parent if it did not exist, missing
1428
# should not change the parent
1429
b.set_parent(remote)
1430
br_remote = Branch.open_containing(remote)
1431
return show_missing(b, br_remote, verbose=verbose, quiet=quiet)
1826
1434
class cmd_plugins(Command):
1827
1435
"""List plugins"""
1831
1438
import bzrlib.plugin
1832
1439
from inspect import getdoc
1833
for name, plugin in bzrlib.plugin.all_plugins().items():
1440
for plugin in bzrlib.plugin.all_plugins:
1834
1441
if hasattr(plugin, '__path__'):
1835
1442
print plugin.__path__[0]
1836
1443
elif hasattr(plugin, '__file__'):
1915
1521
raise BzrCommandError('You can only supply one of revision_id or --revision')
1916
1522
if revision_id is None and revision is None:
1917
1523
raise BzrCommandError('You must supply either --revision or a revision_id')
1918
b = WorkingTree.open_containing(u'.')[0].branch
1524
b = Branch.open_containing('.')
1919
1525
gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
1920
1526
if revision_id is not None:
1921
1527
b.sign_revision(revision_id, gpg_strategy)
1922
1528
elif revision is not None:
1923
if len(revision) == 1:
1924
revno, rev_id = revision[0].in_history(b)
1529
for rev in revision:
1531
raise BzrCommandError('You cannot specify a NULL revision.')
1532
revno, rev_id = rev.in_history(b)
1925
1533
b.sign_revision(rev_id, gpg_strategy)
1926
elif len(revision) == 2:
1927
# are they both on rh- if so we can walk between them
1928
# might be nice to have a range helper for arbitrary
1929
# revision paths. hmm.
1930
from_revno, from_revid = revision[0].in_history(b)
1931
to_revno, to_revid = revision[1].in_history(b)
1932
if to_revid is None:
1933
to_revno = b.revno()
1934
if from_revno is None or to_revno is None:
1935
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
1936
for revno in range(from_revno, to_revno + 1):
1937
b.sign_revision(b.get_rev_id(revno), gpg_strategy)
1939
raise BzrCommandError('Please supply either one revision, or a range.')
1942
class cmd_uncommit(bzrlib.commands.Command):
1943
"""Remove the last committed revision.
1945
By supplying the --all flag, it will not only remove the entry
1946
from revision_history, but also remove all of the entries in the
1949
--verbose will print out what is being removed.
1950
--dry-run will go through all the motions, but not actually
1953
In the future, uncommit will create a changeset, which can then
1956
takes_options = ['all', 'verbose', 'revision',
1957
Option('dry-run', help='Don\'t actually make changes'),
1958
Option('force', help='Say yes to all questions.')]
1959
takes_args = ['location?']
1962
def run(self, location=None, all=False,
1963
dry_run=False, verbose=False,
1964
revision=None, force=False):
1965
from bzrlib.branch import Branch
1966
from bzrlib.log import log_formatter
1968
from bzrlib.uncommit import uncommit
1970
if location is None:
1972
b, relpath = Branch.open_containing(location)
1974
if revision is None:
1976
rev_id = b.last_revision()
1978
revno, rev_id = revision[0].in_history(b)
1980
print 'No revisions to uncommit.'
1982
for r in range(revno, b.revno()+1):
1983
rev_id = b.get_rev_id(r)
1984
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
1985
lf.show(r, b.get_revision(rev_id), None)
1988
print 'Dry-run, pretending to remove the above revisions.'
1990
val = raw_input('Press <enter> to continue')
1992
print 'The above revision(s) will be removed.'
1994
val = raw_input('Are you sure [y/N]? ')
1995
if val.lower() not in ('y', 'yes'):
1999
uncommit(b, remove_files=all,
2000
dry_run=dry_run, verbose=verbose,
2004
1536
# these get imported and then picked up by the scan for cmd_*
2005
1537
# TODO: Some more consistent way to split command definitions across files;
2006
1538
# we do need to load at least some information about them to know of
2008
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
1540
from bzrlib.conflicts import cmd_resolve, cmd_conflicts