27
30
from bzrlib.commands import Command, display_command
28
31
from bzrlib.branch import Branch
29
32
from bzrlib.revision import common_ancestor
33
import bzrlib.errors as errors
30
34
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
31
35
NotBranchError, DivergedBranches, NotConflicted,
32
36
NoSuchFile, NoWorkingTree, FileInWrongBranch)
33
37
from bzrlib.option import Option
34
38
from bzrlib.revisionspec import RevisionSpec
35
39
import bzrlib.trace
36
from bzrlib.trace import mutter, note, log_error, warning
40
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
37
41
from bzrlib.workingtree import WorkingTree
40
def tree_files(file_list, default_branch='.'):
42
from bzrlib.log import show_one_log
45
def tree_files(file_list, default_branch=u'.'):
42
47
return internal_tree_files(file_list, default_branch)
43
48
except FileInWrongBranch, e:
44
49
raise BzrCommandError("%s is not in the same branch as %s" %
45
50
(e.path, file_list[0]))
47
def internal_tree_files(file_list, default_branch='.'):
52
def internal_tree_files(file_list, default_branch=u'.'):
49
54
Return a branch and list of branch-relative paths.
50
55
If supplied file_list is empty or None, the branch default will be used,
141
146
raise BzrCommandError('You can only supply one of revision_id or --revision')
142
147
if revision_id is None and revision is None:
143
148
raise BzrCommandError('You must supply either --revision or a revision_id')
144
b = WorkingTree.open_containing('.')[0].branch
149
b = WorkingTree.open_containing(u'.')[0].branch
145
150
if revision_id is not None:
146
sys.stdout.write(b.get_revision_xml_file(revision_id).read())
151
sys.stdout.write(b.get_revision_xml(revision_id))
147
152
elif revision is not None:
148
153
for rev in revision:
150
155
raise BzrCommandError('You cannot specify a NULL revision.')
151
156
revno, rev_id = rev.in_history(b)
152
sys.stdout.write(b.get_revision_xml_file(rev_id).read())
157
sys.stdout.write(b.get_revision_xml(rev_id))
155
160
class cmd_revno(Command):
156
161
"""Show current revision number.
158
163
This is equal to the number of revisions on this branch."""
164
takes_args = ['location?']
161
print Branch.open_containing('.')[0].revno()
166
def run(self, location=u'.'):
167
print Branch.open_containing(location)[0].revno()
164
170
class cmd_revision_info(Command):
211
217
implicitly add the parent, and so on up to the root. This means
212
218
you should never need to explictly add a directory, they'll just
213
219
get added when you add a file in the directory.
221
--dry-run will show which files would be added, but not actually
215
224
takes_args = ['file*']
216
takes_options = ['no-recurse', 'quiet']
218
def run(self, file_list, no_recurse=False, quiet=False):
219
from bzrlib.add import smart_add, add_reporter_print, add_reporter_null
221
reporter = add_reporter_null
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
223
reporter = add_reporter_print
224
smart_add(file_list, not no_recurse, reporter)
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"\
227
256
class cmd_mkdir(Command):
383
412
print "Using saved location: %s" % stored_loc
384
413
location = stored_loc
385
415
br_from = Branch.open(location)
387
old_rh = tree_to.branch.revision_history()
388
tree_to.pull(br_from, overwrite)
389
except DivergedBranches:
390
raise BzrCommandError("These branches have diverged."
392
if tree_to.branch.get_parent() is None or remember:
393
tree_to.branch.set_parent(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,))
396
426
new_rh = tree_to.branch.revision_history()
432
462
def run(self, location=None, remember=False, overwrite=False,
433
463
create_prefix=False, verbose=False):
464
# FIXME: Way too big! Put this into a function called from the
435
467
from shutil import rmtree
436
468
from bzrlib.transport import get_transport
438
tree_from = WorkingTree.open_containing('.')[0]
470
tree_from = WorkingTree.open_containing(u'.')[0]
471
br_from = tree_from.branch
439
472
stored_loc = tree_from.branch.get_push_location()
440
473
if location is None:
441
474
if stored_loc is None:
469
502
if new_transport.base == transport.base:
470
503
raise BzrCommandError("Could not creeate "
474
505
br_to = Branch.initialize(location)
506
old_rh = br_to.revision_history()
476
old_rh = br_to.revision_history()
477
br_to.pull(tree_from.branch, overwrite)
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)
478
518
except DivergedBranches:
479
519
raise BzrCommandError("These branches have diverged."
480
520
" Try a merge then push with overwrite.")
481
if tree_from.branch.get_push_location() is None or remember:
482
tree_from.branch.set_push_location(location)
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,))
485
526
new_rh = br_to.revision_history()
1122
1168
is found exports to a directory (equivalent to --format=dir).
1124
1170
Root may be the top directory for tar, tgz and tbz2 formats. If none
1125
is given, the top directory will be the root name of the file."""
1126
# TODO: list known exporters
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
1127
1183
takes_args = ['dest']
1128
1184
takes_options = ['revision', 'format', 'root']
1129
1185
def run(self, dest, revision=None, format=None, root=None):
1131
tree = WorkingTree.open_containing('.')[0]
1187
from bzrlib.export import export
1188
tree = WorkingTree.open_containing(u'.')[0]
1132
1189
b = tree.branch
1133
1190
if revision is None:
1134
1191
# should be tree.last_revision FIXME
1135
rev_id = tree.branch.last_revision()
1192
rev_id = b.last_revision()
1137
1194
if len(revision) != 1:
1138
1195
raise BzrError('bzr export --revision takes exactly 1 argument')
1139
1196
rev_id = revision[0].in_history(b).rev_id
1140
1197
t = b.revision_tree(rev_id)
1141
arg_root, ext = os.path.splitext(os.path.basename(dest))
1142
if ext in ('.gz', '.bz2'):
1143
new_root, new_ext = os.path.splitext(arg_root)
1144
if new_ext == '.tar':
1150
if ext in (".tar",):
1152
elif ext in (".tar.gz", ".tgz"):
1154
elif ext in (".tar.bz2", ".tbz2"):
1158
t.export(dest, format, root)
1199
export(t, dest, format, root)
1200
except errors.NoSuchExportFormat, e:
1201
raise BzrCommandError('Unsupported export format: %s' % e.format)
1161
1204
class cmd_cat(Command):
1229
1275
unchanged=False, strict=False):
1230
1276
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1231
1277
StrictCommitFailed)
1232
from bzrlib.msgeditor import edit_commit_message
1278
from bzrlib.msgeditor import edit_commit_message, \
1279
make_commit_message_template
1233
1280
from bzrlib.status import show_status
1234
from cStringIO import StringIO
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
1236
1292
tree, selected_list = tree_files(selected_list)
1237
1293
if message is None and not file:
1238
catcher = StringIO()
1239
show_status(tree.branch, specific_files=selected_list,
1241
message = edit_commit_message(catcher.getvalue())
1294
template = make_commit_message_template(tree, selected_list)
1295
message = edit_commit_message(template)
1243
1296
if message is None:
1244
1297
raise BzrCommandError("please specify a commit message"
1245
1298
" with either --message or --file")
1275
1329
This command checks various invariants about the branch storage to
1276
1330
detect data corruption or bzr bugs.
1278
takes_args = ['dir?']
1332
takes_args = ['branch?']
1279
1333
takes_options = ['verbose']
1281
def run(self, dir='.', verbose=False):
1335
def run(self, branch=None, verbose=False):
1282
1336
from bzrlib.check import check
1283
check(WorkingTree.open_containing(dir)[0].branch, verbose)
1338
tree = WorkingTree.open_containing()[0]
1339
branch = tree.branch
1341
branch = Branch.open(branch)
1342
check(branch, verbose)
1286
1345
class cmd_scan_cache(Command):
1402
1461
bzrlib.ui.ui_factory = save_ui
1464
def _get_bzr_branch():
1465
"""If bzr is run from a branch, return Branch or None"""
1466
import bzrlib.errors
1467
from bzrlib.branch import Branch
1468
from bzrlib.osutils import abspath
1469
from os.path import dirname
1472
branch = Branch.open(dirname(abspath(dirname(__file__))))
1474
except bzrlib.errors.BzrError:
1405
1478
def show_version():
1406
1479
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1407
1480
# is bzrlib itself in a branch?
1408
bzrrev = bzrlib.get_bzr_revision()
1410
print " (bzr checkout, revision %d {%s})" % bzrrev
1481
branch = _get_bzr_branch()
1483
rh = branch.revision_history()
1485
print " bzr checkout, revision %d" % (revno,)
1486
print " nick: %s" % (branch.nick,)
1488
print " revid: %s" % (rh[-1],)
1411
1489
print bzrlib.__copyright__
1412
1490
print "http://bazaar-ng.org/"
1706
1784
class cmd_missing(Command):
1707
"""What is missing in this branch relative to other branch.
1709
# TODO: rewrite this in terms of ancestry so that it shows only
1712
takes_args = ['remote?']
1713
aliases = ['mis', 'miss']
1714
# We don't have to add quiet to the list, because
1715
# unknown options are parsed as booleans
1716
takes_options = ['verbose', 'quiet']
1719
def run(self, remote=None, verbose=False, quiet=False):
1720
from bzrlib.errors import BzrCommandError
1721
from bzrlib.missing import show_missing
1723
if verbose and quiet:
1724
raise BzrCommandError('Cannot pass both quiet and verbose')
1726
tree = WorkingTree.open_containing('.')[0]
1727
parent = tree.branch.get_parent()
1785
"""Show unmerged/unpulled revisions between two branches.
1787
OTHER_BRANCH may be local or remote."""
1788
takes_args = ['other_branch?']
1789
takes_options = [Option('reverse', 'Reverse the order of revisions'),
1791
'Display changes in the local branch only'),
1792
Option('theirs-only',
1793
'Display changes in the remote branch only'),
1801
def run(self, other_branch=None, reverse=False, mine_only=False,
1802
theirs_only=False, long=True, short=False, line=False,
1803
show_ids=False, verbose=False):
1804
from bzrlib.missing import find_unmerged, iter_log_data
1805
from bzrlib.log import log_formatter
1806
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
1807
parent = local_branch.get_parent()
1808
if other_branch is None:
1809
other_branch = parent
1810
if other_branch is None:
1730
1811
raise BzrCommandError("No missing location known or specified.")
1733
print "Using last location: %s" % parent
1735
elif parent is None:
1736
# We only update parent if it did not exist, missing
1737
# should not change the parent
1738
tree.branch.set_parent(remote)
1739
br_remote = Branch.open_containing(remote)[0]
1740
return show_missing(tree.branch, br_remote, verbose=verbose, quiet=quiet)
1812
print "Using last location: " + local_branch.get_parent()
1813
remote_branch = bzrlib.branch.Branch.open(other_branch)
1814
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
1815
log_format = get_log_format(long=long, short=short, line=line)
1816
lf = log_formatter(log_format, sys.stdout,
1818
show_timezone='original')
1819
if reverse is False:
1820
local_extra.reverse()
1821
remote_extra.reverse()
1822
if local_extra and not theirs_only:
1823
print "You have %d extra revision(s):" % len(local_extra)
1824
for data in iter_log_data(local_extra, local_branch, verbose):
1826
printed_local = True
1828
printed_local = False
1829
if remote_extra and not mine_only:
1830
if printed_local is True:
1832
print "You are missing %d revision(s):" % len(remote_extra)
1833
for data in iter_log_data(remote_extra, remote_branch, verbose):
1835
if not remote_extra and not local_extra:
1837
print "Branches are up to date."
1840
if parent is None and other_branch is not None:
1841
local_branch.set_parent(other_branch)
1743
1845
class cmd_plugins(Command):
1856
1958
raise BzrCommandError('Please supply either one revision, or a range.')
1961
class cmd_uncommit(bzrlib.commands.Command):
1962
"""Remove the last committed revision.
1964
By supplying the --all flag, it will not only remove the entry
1965
from revision_history, but also remove all of the entries in the
1968
--verbose will print out what is being removed.
1969
--dry-run will go through all the motions, but not actually
1972
In the future, uncommit will create a changeset, which can then
1975
takes_options = ['all', 'verbose', 'revision',
1976
Option('dry-run', help='Don\'t actually make changes'),
1977
Option('force', help='Say yes to all questions.')]
1978
takes_args = ['location?']
1981
def run(self, location=None, all=False,
1982
dry_run=False, verbose=False,
1983
revision=None, force=False):
1984
from bzrlib.branch import Branch
1985
from bzrlib.log import log_formatter
1987
from bzrlib.uncommit import uncommit
1989
if location is None:
1991
b, relpath = Branch.open_containing(location)
1993
if revision is None:
1995
rev_id = b.last_revision()
1997
revno, rev_id = revision[0].in_history(b)
1999
print 'No revisions to uncommit.'
2001
for r in range(revno, b.revno()+1):
2002
rev_id = b.get_rev_id(r)
2003
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2004
lf.show(r, b.get_revision(rev_id), None)
2007
print 'Dry-run, pretending to remove the above revisions.'
2009
val = raw_input('Press <enter> to continue')
2011
print 'The above revision(s) will be removed.'
2013
val = raw_input('Are you sure [y/N]? ')
2014
if val.lower() not in ('y', 'yes'):
2018
uncommit(b, remove_files=all,
2019
dry_run=dry_run, verbose=verbose,
1859
2023
# these get imported and then picked up by the scan for cmd_*
1860
2024
# TODO: Some more consistent way to split command definitions across files;
1861
2025
# we do need to load at least some information about them to know of