1
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
1
# Copyright (C) 2004, 2005 by Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
11
# GNU General Public License for more details.
13
13
# You should have received a copy of the GNU General Public License
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
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.)
20
24
from StringIO import StringIO
22
from bzrlib.lazy_import import lazy_import
23
lazy_import(globals(), """
47
revision as _mod_revision,
29
from bzrlib import BZRDIR
30
from bzrlib.commands import Command, display_command
55
31
from bzrlib.branch import Branch
56
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
57
from bzrlib.conflicts import ConflictList
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)
37
from bzrlib.option import Option
58
38
from bzrlib.revisionspec import RevisionSpec
59
from bzrlib.smtp_connection import SMTPConnection
40
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
60
41
from bzrlib.workingtree import WorkingTree
63
from bzrlib.commands import Command, display_command
64
from bzrlib.option import ListOption, Option, RegistryOption
65
from bzrlib.progress import DummyProgress, ProgressPhase
66
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
42
from bzrlib.log import show_one_log
69
45
def tree_files(file_list, default_branch=u'.'):
71
47
return internal_tree_files(file_list, default_branch)
72
except errors.FileInWrongBranch, e:
73
raise errors.BzrCommandError("%s is not in the same branch as %s" %
74
(e.path, file_list[0]))
77
# XXX: Bad function name; should possibly also be a class method of
78
# WorkingTree rather than a function.
48
except FileInWrongBranch, e:
49
raise BzrCommandError("%s is not in the same branch as %s" %
50
(e.path, file_list[0]))
79
52
def internal_tree_files(file_list, default_branch=u'.'):
80
"""Convert command-line paths to a WorkingTree and relative paths.
82
This is typically used for command-line processors that take one or
83
more filenames, and infer the workingtree that contains them.
85
The filenames given are not required to exist.
87
:param file_list: Filenames to convert.
89
:param default_branch: Fallback tree path to use if file_list is empty or
92
:return: workingtree, [relative_paths]
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.
94
58
if file_list is None or len(file_list) == 0:
95
59
return WorkingTree.open_containing(default_branch)[0], file_list
96
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
60
tree = WorkingTree.open_containing(file_list[0])[0]
98
62
for filename in file_list:
100
new_list.append(tree.relpath(osutils.dereference_path(filename)))
64
new_list.append(tree.relpath(filename))
101
65
except errors.PathNotChild:
102
raise errors.FileInWrongBranch(tree.branch, filename)
66
raise FileInWrongBranch(tree.branch, filename)
103
67
return tree, new_list
106
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
107
def get_format_type(typestring):
108
"""Parse and return a format specifier."""
109
# Have to use BzrDirMetaFormat1 directly, so that
110
# RepositoryFormat.set_default_format works
111
if typestring == "default":
112
return bzrdir.BzrDirMetaFormat1()
114
return bzrdir.format_registry.make_bzrdir(typestring)
116
msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
117
raise errors.BzrCommandError(msg)
120
70
# TODO: Make sure no commands unconditionally use the working directory as a
121
71
# branch. If a filename argument is used, the first of them should be used to
122
72
# specify the branch. (Perhaps this can be factored out into some kind of
325
216
Adding a file whose parent directory is not versioned will
326
217
implicitly add the parent, and so on up to the root. This means
327
you should never need to explicitly add a directory, they'll just
218
you should never need to explictly add a directory, they'll just
328
219
get added when you add a file in the directory.
330
221
--dry-run will show which files would be added, but not actually
333
--file-ids-from will try to use the file ids from the supplied path.
334
It looks up ids trying to find a matching parent directory with the
335
same filename, and then by pure path. This option is rarely needed
336
but can be useful when adding the same logical file into two
337
branches that will be merged later (without showing the two different
338
adds as a conflict). It is also useful when merging another project
339
into a subdirectory of this one.
341
224
takes_args = ['file*']
344
help="Don't recursively add the contents of directories."),
346
help="Show what would be done, but don't actually do anything."),
348
Option('file-ids-from',
350
help='Lookup file ids from this tree.'),
352
encoding_type = 'replace'
353
_see_also = ['remove']
225
takes_options = ['no-recurse', 'dry-run', 'verbose']
355
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
227
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
357
228
import bzrlib.add
360
if file_ids_from is not None:
362
base_tree, base_path = WorkingTree.open_containing(
364
except errors.NoWorkingTree:
365
base_branch, base_path = Branch.open_containing(
367
base_tree = base_branch.basis_tree()
369
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
370
to_file=self.outf, should_print=(not is_quiet()))
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
372
action = bzrlib.add.AddAction(to_file=self.outf,
373
should_print=(not is_quiet()))
239
action = bzrlib.add.add_action_add_and_print
376
base_tree.lock_read()
378
file_list = self._maybe_expand_globs(file_list)
380
tree = WorkingTree.open_containing(file_list[0])[0]
382
tree = WorkingTree.open_containing(u'.')[0]
383
added, ignored = tree.smart_add(file_list, not
384
no_recurse, action=action, save=not dry_run)
386
if base_tree is not None:
241
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
388
243
if len(ignored) > 0:
390
for glob in sorted(ignored.keys()):
244
for glob in sorted(ignored.keys()):
245
match_len = len(ignored[glob])
391
247
for path in ignored[glob]:
392
self.outf.write("ignored %s matching \"%s\"\n"
396
for glob, paths in ignored.items():
397
match_len += len(paths)
398
self.outf.write("ignored %d file(s).\n" % match_len)
399
self.outf.write("If you wish to add some of these files,"
400
" please add them by name.\n")
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"\
403
256
class cmd_mkdir(Command):
406
259
This is equivalent to creating the directory and then adding it.
409
261
takes_args = ['dir+']
410
encoding_type = 'replace'
412
263
def run(self, dir_list):
413
264
for d in dir_list:
415
266
wt, dd = WorkingTree.open_containing(d)
417
self.outf.write('added %s\n' % d)
420
271
class cmd_relpath(Command):
421
272
"""Show path of a file relative to root"""
423
273
takes_args = ['filename']
427
277
def run(self, filename):
428
# TODO: jam 20050106 Can relpath return a munged path if
429
# sys.stdout encoding cannot represent it?
430
278
tree, relpath = WorkingTree.open_containing(filename)
431
self.outf.write(relpath)
432
self.outf.write('\n')
435
282
class cmd_inventory(Command):
436
283
"""Show inventory of the current working copy or a revision.
438
285
It is possible to limit the output to a particular entry
439
type using the --kind option. For example: --kind file.
441
It is also possible to restrict the list of files to a specific
442
set. For example: bzr inventory --show-ids this/file
286
type using the --kind option. For example; --kind file.
451
help='List entries of a particular kind: file, directory, symlink.',
454
takes_args = ['file*']
288
takes_options = ['revision', 'show-ids', 'kind']
457
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
291
def run(self, revision=None, show_ids=False, kind=None):
458
292
if kind and kind not in ['file', 'directory', 'symlink']:
459
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
461
work_tree, file_list = tree_files(file_list)
462
work_tree.lock_read()
464
if revision is not None:
465
if len(revision) > 1:
466
raise errors.BzrCommandError(
467
'bzr inventory --revision takes exactly one revision'
469
revision_id = revision[0].in_history(work_tree.branch).rev_id
470
tree = work_tree.branch.repository.revision_tree(revision_id)
472
extra_trees = [work_tree]
478
if file_list is not None:
479
file_ids = tree.paths2ids(file_list, trees=extra_trees,
480
require_versioned=True)
481
# find_ids_across_trees may include some paths that don't
483
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
484
for file_id in file_ids if file_id in tree)
486
entries = tree.inventory.entries()
489
if tree is not work_tree:
492
for path, entry in entries:
293
raise BzrCommandError('invalid kind specified')
294
tree = WorkingTree.open_containing(u'.')[0]
296
inv = tree.read_working_inventory()
298
if len(revision) > 1:
299
raise BzrCommandError('bzr inventory --revision takes'
300
' exactly one revision identifier')
301
inv = tree.branch.get_revision_inventory(
302
revision[0].in_history(tree.branch).rev_id)
304
for path, entry in inv.entries():
493
305
if kind and kind != entry.kind:
496
self.outf.write('%-50s %s\n' % (path, entry.file_id))
308
print '%-50s %s' % (path, entry.file_id)
498
self.outf.write(path)
499
self.outf.write('\n')
313
class cmd_move(Command):
314
"""Move files to a different directory.
319
The destination must be a versioned directory in the same branch.
321
takes_args = ['source$', 'dest']
322
def run(self, source_list, dest):
323
tree, source_list = tree_files(source_list)
324
# TODO: glob expansion on windows?
325
tree.move(source_list, tree.relpath(dest))
328
class cmd_rename(Command):
329
"""Change the name of an entry.
332
bzr rename frob.c frobber.c
333
bzr rename src/frob.c lib/frob.c
335
It is an error if the destination name exists.
337
See also the 'move' command, which moves files into a different
338
directory without changing their name.
340
# TODO: Some way to rename multiple files without invoking
341
# bzr for each one?"""
342
takes_args = ['from_name', 'to_name']
344
def run(self, from_name, to_name):
345
tree, (from_name, to_name) = tree_files((from_name, to_name))
346
tree.rename_one(from_name, to_name)
502
349
class cmd_mv(Command):
509
356
If the last argument is a versioned directory, all the other names
510
357
are moved into it. Otherwise, there must be exactly two arguments
511
and the file is changed to a new name.
513
If OLDNAME does not exist on the filesystem but is versioned and
514
NEWNAME does exist on the filesystem but is not versioned, mv
515
assumes that the file has been manually moved and only updates
516
its internal inventory to reflect that change.
517
The same is valid when moving many SOURCE files to a DESTINATION.
358
and the file is changed to a new name, which must not already exist.
519
360
Files cannot be moved between branches.
522
362
takes_args = ['names*']
523
takes_options = [Option("after", help="Move only the bzr identifier"
524
" of the file, because the file has already been moved."),
526
aliases = ['move', 'rename']
527
encoding_type = 'replace'
529
def run(self, names_list, after=False):
530
if names_list is None:
363
def run(self, names_list):
533
364
if len(names_list) < 2:
534
raise errors.BzrCommandError("missing file argument")
365
raise BzrCommandError("missing file argument")
535
366
tree, rel_names = tree_files(names_list)
537
368
if os.path.isdir(names_list[-1]):
538
369
# move into existing directory
539
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
540
self.outf.write("%s => %s\n" % pair)
370
for pair in tree.move(rel_names[:-1], rel_names[-1]):
371
print "%s => %s" % pair
542
373
if len(names_list) != 2:
543
raise errors.BzrCommandError('to mv multiple files the'
544
' destination must be a versioned'
546
tree.rename_one(rel_names[0], rel_names[1], after=after)
547
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
374
raise BzrCommandError('to mv multiple files the destination '
375
'must be a versioned directory')
376
tree.rename_one(rel_names[0], rel_names[1])
377
print "%s => %s" % (rel_names[0], rel_names[1])
550
380
class cmd_pull(Command):
551
"""Turn this branch into a mirror of another branch.
381
"""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.
553
387
This command only works on branches that have not diverged. Branches are
554
considered diverged if the destination branch's most recent commit is one
555
that has not been merged (directly or indirectly) into the parent.
388
considered diverged if both branches have had commits without first
389
pulling from the other.
557
If branches have diverged, you can use 'bzr merge' to integrate the changes
391
If branches have diverged, you can use 'bzr merge' to pull the text changes
558
392
from one into the other. Once one branch has merged, the other should
559
393
be able to pull it again.
561
395
If you want to forget your local changes and just update your branch to
562
match the remote one, use pull --overwrite.
564
If there is no default location set, the first pull will set it. After
565
that, you can omit the location to use the default. To change the
566
default, use --remember. The value will only be saved if the remote
567
location can be accessed.
396
match the remote one, use --overwrite.
570
_see_also = ['push', 'update', 'status-flags']
571
takes_options = ['remember', 'overwrite', 'revision', 'verbose',
573
help='Branch to pull into, '
574
'rather than the one containing the working directory.',
398
takes_options = ['remember', 'overwrite', 'verbose']
579
399
takes_args = ['location?']
580
encoding_type = 'replace'
582
def run(self, location=None, remember=False, overwrite=False,
583
revision=None, verbose=False,
585
from bzrlib.tag import _merge_tags_if_possible
586
# FIXME: too much stuff is in the command class
589
if directory is None:
592
tree_to = WorkingTree.open_containing(directory)[0]
593
branch_to = tree_to.branch
594
except errors.NoWorkingTree:
596
branch_to = Branch.open_containing(directory)[0]
599
# The user may provide a bundle or branch as 'location' We first try to
600
# identify a bundle, if it's not, we try to preserve connection used by
601
# the transport to access the branch.
602
if location is not None:
603
url = urlutils.normalize_url(location)
604
url, filename = urlutils.split(url, exclude_trailing_slash=False)
605
location_transport = transport.get_transport(url)
608
read_bundle = bundle.read_mergeable_from_transport
609
# There may be redirections but we ignore the intermediate
610
# and final transports used
611
mergeable, t = read_bundle(location_transport, filename)
612
except errors.NotABundle:
613
# Continue on considering this url a Branch but adjust the
615
location_transport = location_transport.clone(filename)
617
# A directory was provided, location_transport is correct
620
stored_loc = branch_to.get_parent()
401
def run(self, location=None, remember=False, overwrite=False, verbose=False):
402
from bzrlib.merge import merge
403
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()
621
408
if location is None:
622
409
if stored_loc is None:
623
raise errors.BzrCommandError("No pull location known or"
410
raise BzrCommandError("No pull location known or specified.")
626
display_url = urlutils.unescape_for_display(stored_loc,
628
self.outf.write("Using saved location: %s\n" % display_url)
412
print "Using saved location: %s" % stored_loc
629
413
location = stored_loc
630
location_transport = transport.get_transport(location)
632
if mergeable is not None:
633
if revision is not None:
634
raise errors.BzrCommandError(
635
'Cannot use -r with merge directives or bundles')
636
revision_id = mergeable.install_revisions(branch_to.repository)
637
branch_from = branch_to
639
branch_from = Branch.open_from_transport(location_transport)
641
if branch_to.get_parent() is None or remember:
642
branch_to.set_parent(branch_from.base)
644
if revision is not None:
645
if len(revision) == 1:
646
revision_id = revision[0].in_history(branch_from).rev_id
648
raise errors.BzrCommandError(
649
'bzr pull --revision takes one value.')
651
old_rh = branch_to.revision_history()
652
if tree_to is not None:
653
result = tree_to.pull(branch_from, overwrite, revision_id,
654
delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
656
result = branch_to.pull(branch_from, overwrite, revision_id)
658
result.report(self.outf)
415
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,))
660
from bzrlib.log import show_changed_revisions
661
new_rh = branch_to.revision_history()
662
show_changed_revisions(branch_to, old_rh, new_rh,
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)
666
433
class cmd_push(Command):
667
"""Update a mirror of this branch.
669
The target branch will not have its working tree populated because this
670
is both expensive, and is not supported on remote file systems.
672
Some smart servers or protocols *may* put the working tree in place in
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.
675
445
This command only works on branches that have not diverged. Branches are
676
considered diverged if the destination branch's most recent commit is one
677
that has not been merged (directly or indirectly) by the source branch.
446
considered diverged if the branch being pushed to is not an older version
679
449
If branches have diverged, you can use 'bzr push --overwrite' to replace
680
the other branch completely, discarding its unmerged changes.
450
the other branch completely.
682
452
If you want to ensure you have the different changes in the other branch,
683
do a merge (see bzr help merge) from the other branch, and commit that.
684
After that you will be able to do a push without '--overwrite'.
686
If there is no default push location set, the first push will set it.
687
After that, you can omit the location to use the default. To change the
688
default, use --remember. The value will only be saved if the remote
689
location can be accessed.
453
do a merge (see bzr help merge) from the other branch, and commit that
454
before doing a 'push --overwrite'.
692
_see_also = ['pull', 'update', 'working-trees']
693
takes_options = ['remember', 'overwrite', 'verbose',
694
Option('create-prefix',
695
help='Create the path leading up to the branch '
696
'if it does not already exist.'),
698
help='Branch to push from, '
699
'rather than the one containing the working directory.',
703
Option('use-existing-dir',
704
help='By default push will fail if the target'
705
' directory exists, but does not already'
706
' have a control directory. This flag will'
707
' allow push to proceed.'),
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')]
709
460
takes_args = ['location?']
710
encoding_type = 'replace'
712
462
def run(self, location=None, remember=False, overwrite=False,
713
create_prefix=False, verbose=False,
714
use_existing_dir=False,
463
create_prefix=False, verbose=False):
716
464
# FIXME: Way too big! Put this into a function called from the
718
if directory is None:
720
br_from = Branch.open_containing(directory)[0]
721
stored_loc = br_from.get_push_location()
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()
722
473
if location is None:
723
474
if stored_loc is None:
724
raise errors.BzrCommandError("No push location known or specified.")
475
raise BzrCommandError("No push location known or specified.")
726
display_url = urlutils.unescape_for_display(stored_loc,
728
self.outf.write("Using saved location: %s\n" % display_url)
477
print "Using saved location: %s" % stored_loc
729
478
location = stored_loc
731
to_transport = transport.get_transport(location)
733
br_to = repository_to = dir_to = None
735
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
736
except errors.NotBranchError:
737
pass # Didn't find anything
739
# If we can open a branch, use its direct repository, otherwise see
740
# if there is a repository without a branch.
742
br_to = dir_to.open_branch()
743
except errors.NotBranchError:
744
# Didn't find a branch, can we find a repository?
746
repository_to = dir_to.find_repository()
747
except errors.NoRepositoryPresent:
750
# Found a branch, so we must have found a repository
751
repository_to = br_to.repository
755
# The destination doesn't exist; create it.
756
# XXX: Refactor the create_prefix/no_create_prefix code into a
757
# common helper function
759
to_transport.mkdir('.')
760
except errors.FileExists:
761
if not use_existing_dir:
762
raise errors.BzrCommandError("Target directory %s"
763
" already exists, but does not have a valid .bzr"
764
" directory. Supply --use-existing-dir to push"
765
" there anyway." % location)
766
except errors.NoSuchFile:
767
if not create_prefix:
768
raise errors.BzrCommandError("Parent directory of %s"
770
"\nYou may supply --create-prefix to create all"
771
" leading parent directories."
773
_create_prefix(to_transport)
775
# Now the target directory exists, but doesn't have a .bzr
776
# directory. So we need to create it, along with any work to create
777
# all of the dependent branches, etc.
778
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
779
revision_id=br_from.last_revision())
780
br_to = dir_to.open_branch()
781
# TODO: Some more useful message about what was copied
782
note('Created new branch.')
783
# We successfully created the target, remember it
784
if br_from.get_push_location() is None or remember:
785
br_from.set_push_location(br_to.base)
786
elif repository_to is None:
787
# we have a bzrdir but no branch or repository
788
# XXX: Figure out what to do other than complain.
789
raise errors.BzrCommandError("At %s you have a valid .bzr control"
790
" directory, but not a branch or repository. This is an"
791
" unsupported configuration. Please move the target directory"
792
" out of the way and try again."
795
# We have a repository but no branch, copy the revisions, and then
480
br_to = Branch.open(location)
481
except NotBranchError:
796
482
# create a branch.
797
last_revision_id = br_from.last_revision()
798
repository_to.fetch(br_from.repository,
799
revision_id=last_revision_id)
800
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
801
note('Created new branch.')
802
if br_from.get_push_location() is None or remember:
803
br_from.set_push_location(br_to.base)
804
else: # We have a valid to branch
805
# We were able to connect to the remote location, so remember it
806
# we don't need to successfully push because of possible divergence.
807
if br_from.get_push_location() is None or remember:
808
br_from.set_push_location(br_to.base)
809
old_rh = br_to.revision_history()
483
transport = get_transport(location).clone('..')
484
if not create_prefix:
812
tree_to = dir_to.open_workingtree()
813
except errors.NotLocalUrl:
814
warning("This transport does not update the working "
815
"tree of: %s. See 'bzr help working-trees' for "
816
"more information." % br_to.base)
817
push_result = br_from.push(br_to, overwrite)
818
except errors.NoWorkingTree:
819
push_result = br_from.push(br_to, overwrite)
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))]
823
push_result = br_from.push(tree_to.branch, overwrite)
827
except errors.DivergedBranches:
828
raise errors.BzrCommandError('These branches have diverged.'
829
' Try using "merge" and then "push".')
830
if push_result is not None:
831
push_result.report(self.outf)
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()
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,))
833
526
new_rh = br_to.revision_history()
834
527
if old_rh != new_rh:
835
528
# Something changed
836
529
from bzrlib.log import show_changed_revisions
837
show_changed_revisions(br_to, old_rh, new_rh,
840
# we probably did a clone rather than a push, so a message was
530
show_changed_revisions(br_to, old_rh, new_rh)
845
533
class cmd_branch(Command):
848
536
If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
849
537
be used. In other words, "branch ../foo/bar" will attempt to create ./bar.
850
If the FROM_LOCATION has no / or path separator embedded, the TO_LOCATION
851
is derived from the FROM_LOCATION by stripping a leading scheme or drive
852
identifier, if any. For example, "branch lp:foo-bar" will attempt to
855
539
To retrieve the branch as of a particular revision, supply the --revision
856
540
parameter, as in "branch foo/bar -r 5".
542
--basis is to speed up branching from remote branches. When specified, it
543
copies all the file-contents, inventory and revision data from the basis
544
branch before copying anything from the remote branch.
859
_see_also = ['checkout']
860
546
takes_args = ['from_location', 'to_location?']
861
takes_options = ['revision']
547
takes_options = ['revision', 'basis']
862
548
aliases = ['get', 'clone']
864
def run(self, from_location, to_location=None, revision=None):
865
from bzrlib.tag import _merge_tags_if_possible
550
def run(self, from_location, to_location=None, revision=None, basis=None):
551
from bzrlib.clone import copy_branch
553
from shutil import rmtree
866
554
if revision is None:
867
555
revision = [None]
868
556
elif len(revision) > 1:
869
raise errors.BzrCommandError(
557
raise BzrCommandError(
870
558
'bzr branch --revision takes exactly 1 revision value')
872
br_from = Branch.open(from_location)
560
br_from = Branch.open(from_location)
562
if e.errno == errno.ENOENT:
563
raise BzrCommandError('Source location "%s" does not'
564
' exist.' % to_location)
873
567
br_from.lock_read()
569
if basis is not None:
570
basis_branch = WorkingTree.open_containing(basis)[0].branch
875
573
if len(revision) == 1 and revision[0] is not None:
876
574
revision_id = revision[0].in_history(br_from)[1]
878
# FIXME - wt.last_revision, fallback to branch, fall back to
879
# None or perhaps NULL_REVISION to mean copy nothing
881
revision_id = br_from.last_revision()
882
577
if to_location is None:
883
to_location = urlutils.derive_to_location(from_location)
578
to_location = os.path.basename(from_location.rstrip("/\\"))
886
581
name = os.path.basename(to_location) + '\n'
888
to_transport = transport.get_transport(to_location)
890
to_transport.mkdir('.')
891
except errors.FileExists:
892
raise errors.BzrCommandError('Target directory "%s" already'
893
' exists.' % to_location)
894
except errors.NoSuchFile:
895
raise errors.BzrCommandError('Parent of "%s" does not exist.'
898
# preserve whatever source format we have.
899
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
900
possible_transports=[to_transport])
901
branch = dir.open_branch()
902
except errors.NoSuchRevision:
903
to_transport.delete_tree('.')
583
os.mkdir(to_location)
585
if e.errno == errno.EEXIST:
586
raise BzrCommandError('Target directory "%s" already'
587
' exists.' % to_location)
588
if e.errno == errno.ENOENT:
589
raise BzrCommandError('Parent of "%s" does not exist.' %
594
copy_branch(br_from, to_location, revision_id, basis_branch)
595
except bzrlib.errors.NoSuchRevision:
904
597
msg = "The branch %s has no revision %s." % (from_location, revision[0])
905
raise errors.BzrCommandError(msg)
598
raise BzrCommandError(msg)
599
except bzrlib.errors.UnlistableBranch:
601
msg = "The branch %s cannot be used as a --basis"
602
raise BzrCommandError(msg)
603
branch = Branch.open(to_location)
907
branch.control_files.put_utf8('branch-name', name)
908
_merge_tags_if_possible(br_from, branch)
605
name = StringIO(name)
606
branch.put_controlfile('branch-name', name)
909
607
note('Branched %d revision(s).' % branch.revno())
914
class cmd_checkout(Command):
915
"""Create a new checkout of an existing branch.
917
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
918
the branch found in '.'. This is useful if you have removed the working tree
919
or if it was never created - i.e. if you pushed the branch to its current
922
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
923
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
924
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
925
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
926
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
929
To retrieve the branch as of a particular revision, supply the --revision
930
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
931
out of date [so you cannot commit] but it may be useful (i.e. to examine old
935
_see_also = ['checkouts', 'branch']
936
takes_args = ['branch_location?', 'to_location?']
937
takes_options = ['revision',
938
Option('lightweight',
939
help="Perform a lightweight checkout. Lightweight "
940
"checkouts depend on access to the branch for "
941
"every operation. Normal checkouts can perform "
942
"common operations like diff and status without "
943
"such access, and also support local commits."
948
def run(self, branch_location=None, to_location=None, revision=None,
952
elif len(revision) > 1:
953
raise errors.BzrCommandError(
954
'bzr checkout --revision takes exactly 1 revision value')
955
if branch_location is None:
956
branch_location = osutils.getcwd()
957
to_location = branch_location
958
source = Branch.open(branch_location)
959
if len(revision) == 1 and revision[0] is not None:
960
revision_id = revision[0].in_history(source)[1]
963
if to_location is None:
964
to_location = urlutils.derive_to_location(branch_location)
965
# if the source and to_location are the same,
966
# and there is no working tree,
967
# then reconstitute a branch
968
if (osutils.abspath(to_location) ==
969
osutils.abspath(branch_location)):
971
source.bzrdir.open_workingtree()
972
except errors.NoWorkingTree:
973
source.bzrdir.create_workingtree()
976
os.mkdir(to_location)
978
if e.errno == errno.EEXIST:
979
raise errors.BzrCommandError('Target directory "%s" already'
980
' exists.' % to_location)
981
if e.errno == errno.ENOENT:
982
raise errors.BzrCommandError('Parent of "%s" does not exist.'
986
source.create_checkout(to_location, revision_id, lightweight)
989
612
class cmd_renames(Command):
990
613
"""Show list of renamed files.
992
615
# TODO: Option to show renames between two historical versions.
994
617
# TODO: Only show renames under dir, rather than in the whole branch.
995
_see_also = ['status']
996
618
takes_args = ['dir?']
999
621
def run(self, dir=u'.'):
1000
622
tree = WorkingTree.open_containing(dir)[0]
1003
new_inv = tree.inventory
1004
old_tree = tree.basis_tree()
1005
old_tree.lock_read()
1007
old_inv = old_tree.inventory
1008
renames = list(_mod_tree.find_renames(old_inv, new_inv))
1010
for old_name, new_name in renames:
1011
self.outf.write("%s => %s\n" % (old_name, new_name))
1018
class cmd_update(Command):
1019
"""Update a tree to have the latest code committed to its branch.
1021
This will perform a merge into the working tree, and may generate
1022
conflicts. If you have any local changes, you will still
1023
need to commit them after the update for the update to be complete.
1025
If you want to discard your local changes, you can just do a
1026
'bzr revert' instead of 'bzr commit' after the update.
1029
_see_also = ['pull', 'working-trees']
1030
takes_args = ['dir?']
1033
def run(self, dir='.'):
1034
tree = WorkingTree.open_containing(dir)[0]
1035
master = tree.branch.get_master_branch()
1036
if master is not None:
1039
tree.lock_tree_write()
1041
existing_pending_merges = tree.get_parent_ids()[1:]
1042
last_rev = _mod_revision.ensure_null(tree.last_revision())
1043
if last_rev == _mod_revision.ensure_null(
1044
tree.branch.last_revision()):
1045
# may be up to date, check master too.
1046
master = tree.branch.get_master_branch()
1047
if master is None or last_rev == _mod_revision.ensure_null(
1048
master.last_revision()):
1049
revno = tree.branch.revision_id_to_revno(last_rev)
1050
note("Tree is up to date at revision %d." % (revno,))
1052
conflicts = tree.update(delta._ChangeReporter(
1053
unversioned_filter=tree.is_ignored))
1054
revno = tree.branch.revision_id_to_revno(
1055
_mod_revision.ensure_null(tree.last_revision()))
1056
note('Updated to revision %d.' % (revno,))
1057
if tree.get_parent_ids()[1:] != existing_pending_merges:
1058
note('Your local commits will now show as pending merges with '
1059
"'bzr status', and can be committed with 'bzr commit'.")
623
old_inv = tree.branch.basis_tree().inventory
624
new_inv = tree.read_working_inventory()
626
renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
628
for old_name, new_name in renames:
629
print "%s => %s" % (old_name, new_name)
1068
632
class cmd_info(Command):
1069
"""Show information about a working tree, branch or repository.
1071
This command will show all known locations and formats associated to the
1072
tree, branch or repository. Statistical information is included with
1075
Branches and working trees will also report any missing revisions.
1077
_see_also = ['revno', 'working-trees', 'repositories']
1078
takes_args = ['location?']
1079
takes_options = ['verbose']
633
"""Show statistical information about a branch."""
634
takes_args = ['branch?']
1081
636
@display_command
1082
def run(self, location=None, verbose=0):
1083
from bzrlib.info import show_bzrdir_info
1084
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
637
def run(self, branch=None):
639
b = WorkingTree.open_containing(branch)[0].branch
1088
643
class cmd_remove(Command):
1089
"""Remove files or directories.
1091
This makes bzr stop tracking changes to the specified files and
1092
delete them if they can easily be recovered using revert.
1094
You can specify one or more files, and/or --new. If you specify --new,
1095
only 'added' files will be removed. If you specify both, then new files
1096
in the specified directories will be removed. If the directories are
1097
also new, they will also be removed.
644
"""Make a file unversioned.
646
This makes bzr stop tracking changes to a versioned file. It does
647
not delete the working copy.
1099
takes_args = ['file*']
1100
takes_options = ['verbose',
1101
Option('new', help='Remove newly-added files.'),
1102
RegistryOption.from_kwargs('file-deletion-strategy',
1103
'The file deletion mode to be used',
1104
title='Deletion Strategy', value_switches=True, enum_switch=False,
1105
safe='Only delete files if they can be'
1106
' safely recovered (default).',
1107
keep="Don't delete any files.",
1108
force='Delete all the specified files, even if they can not be '
1109
'recovered and even if they are non-empty directories.')]
649
takes_args = ['file+']
650
takes_options = ['verbose']
1110
651
aliases = ['rm']
1111
encoding_type = 'replace'
1113
def run(self, file_list, verbose=False, new=False,
1114
file_deletion_strategy='safe'):
653
def run(self, file_list, verbose=False):
1115
654
tree, file_list = tree_files(file_list)
1117
if file_list is not None:
1118
file_list = [f for f in file_list if f != '']
1120
raise errors.BzrCommandError('Specify one or more files to'
1121
' remove, or use --new.')
1124
added = tree.changes_from(tree.basis_tree(),
1125
specific_files=file_list).added
1126
file_list = sorted([f[0] for f in added], reverse=True)
1127
if len(file_list) == 0:
1128
raise errors.BzrCommandError('No matching files.')
1129
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1130
keep_files=file_deletion_strategy=='keep',
1131
force=file_deletion_strategy=='force')
655
tree.remove(file_list, verbose=verbose)
1134
658
class cmd_file_id(Command):
1138
662
same through all revisions where the file exists, even when it is
1139
663
moved or renamed.
1143
_see_also = ['inventory', 'ls']
1144
666
takes_args = ['filename']
1146
667
@display_command
1147
668
def run(self, filename):
1148
669
tree, relpath = WorkingTree.open_containing(filename)
1149
i = tree.path2id(relpath)
1151
raise errors.NotVersionedError(filename)
670
i = tree.inventory.path2id(relpath)
672
raise BzrError("%r is not a versioned file" % filename)
1153
self.outf.write(i + '\n')
1156
677
class cmd_file_path(Command):
1157
678
"""Print path of file_ids to a file or directory.
1159
680
This prints one line for each directory down to the target,
1160
starting at the branch root.
681
starting at the branch root."""
1164
683
takes_args = ['filename']
1166
684
@display_command
1167
685
def run(self, filename):
1168
686
tree, relpath = WorkingTree.open_containing(filename)
1169
fid = tree.path2id(relpath)
1171
raise errors.NotVersionedError(filename)
1172
segments = osutils.splitpath(relpath)
1173
for pos in range(1, len(segments) + 1):
1174
path = osutils.joinpath(segments[:pos])
1175
self.outf.write("%s\n" % tree.path2id(path))
1178
class cmd_reconcile(Command):
1179
"""Reconcile bzr metadata in a branch.
1181
This can correct data mismatches that may have been caused by
1182
previous ghost operations or bzr upgrades. You should only
1183
need to run this command if 'bzr check' or a bzr developer
1184
advises you to run it.
1186
If a second branch is provided, cross-branch reconciliation is
1187
also attempted, which will check that data like the tree root
1188
id which was not present in very early bzr versions is represented
1189
correctly in both branches.
1191
At the same time it is run it may recompress data resulting in
1192
a potential saving in disk space or performance gain.
1194
The branch *MUST* be on a listable system such as local disk or sftp.
1197
_see_also = ['check']
1198
takes_args = ['branch?']
1200
def run(self, branch="."):
1201
from bzrlib.reconcile import reconcile
1202
dir = bzrdir.BzrDir.open(branch)
688
fid = inv.path2id(relpath)
690
raise BzrError("%r is not a versioned file" % filename)
691
for fip in inv.get_idpath(fid):
1206
695
class cmd_revision_history(Command):
1207
"""Display the list of revision ids on a branch."""
1210
takes_args = ['location?']
696
"""Display list of revision ids on this branch."""
1214
698
@display_command
1215
def run(self, location="."):
1216
branch = Branch.open_containing(location)[0]
1217
for revid in branch.revision_history():
1218
self.outf.write(revid)
1219
self.outf.write('\n')
700
branch = WorkingTree.open_containing(u'.')[0].branch
701
for patchid in branch.revision_history():
1222
705
class cmd_ancestry(Command):
1223
706
"""List all revisions merged into this branch."""
1225
_see_also = ['log', 'revision-history']
1226
takes_args = ['location?']
1230
708
@display_command
1231
def run(self, location="."):
1233
wt = WorkingTree.open_containing(location)[0]
1234
except errors.NoWorkingTree:
1235
b = Branch.open(location)
1236
last_revision = b.last_revision()
1239
last_revision = wt.last_revision()
1241
revision_ids = b.repository.get_ancestry(last_revision)
1242
assert revision_ids[0] is None
1244
for revision_id in revision_ids:
1245
self.outf.write(revision_id + '\n')
710
tree = WorkingTree.open_containing(u'.')[0]
712
# FIXME. should be tree.last_revision
713
for revision_id in b.get_ancestry(b.last_revision()):
1248
717
class cmd_init(Command):
1267
728
bzr commit -m 'imported project'
1270
_see_also = ['init-repo', 'branch', 'checkout']
1271
730
takes_args = ['location?']
1273
Option('create-prefix',
1274
help='Create the path leading up to the branch '
1275
'if it does not already exist.'),
1276
RegistryOption('format',
1277
help='Specify a format for this branch. '
1278
'See "help formats".',
1279
registry=bzrdir.format_registry,
1280
converter=bzrdir.format_registry.make_bzrdir,
1281
value_switches=True,
1282
title="Branch Format",
1284
Option('append-revisions-only',
1285
help='Never change revnos or the existing log.'
1286
' Append revisions to it only.')
1288
def run(self, location=None, format=None, append_revisions_only=False,
1289
create_prefix=False):
1291
format = bzrdir.format_registry.make_bzrdir('default')
731
def run(self, location=None):
732
from bzrlib.branch import Branch
1292
733
if location is None:
1295
to_transport = transport.get_transport(location)
1297
# The path has to exist to initialize a
1298
# branch inside of it.
1299
# Just using os.mkdir, since I don't
1300
# believe that we want to create a bunch of
1301
# locations if the user supplies an extended path
1303
to_transport.ensure_base()
1304
except errors.NoSuchFile:
1305
if not create_prefix:
1306
raise errors.BzrCommandError("Parent directory of %s"
1308
"\nYou may supply --create-prefix to create all"
1309
" leading parent directories."
1311
_create_prefix(to_transport)
1314
existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1315
except errors.NotBranchError:
1316
# really a NotBzrDir error...
1317
create_branch = bzrdir.BzrDir.create_branch_convenience
1318
branch = create_branch(to_transport.base, format=format,
1319
possible_transports=[to_transport])
1321
from bzrlib.transport.local import LocalTransport
1322
if existing_bzrdir.has_branch():
1323
if (isinstance(to_transport, LocalTransport)
1324
and not existing_bzrdir.has_workingtree()):
1325
raise errors.BranchExistsWithoutWorkingTree(location)
1326
raise errors.AlreadyBranchError(location)
1328
branch = existing_bzrdir.create_branch()
1329
existing_bzrdir.create_workingtree()
1330
if append_revisions_only:
1332
branch.set_append_revisions_only(True)
1333
except errors.UpgradeRequired:
1334
raise errors.BzrCommandError('This branch format cannot be set'
1335
' to append-revisions-only. Try --experimental-branch6')
1338
class cmd_init_repository(Command):
1339
"""Create a shared repository to hold branches.
1341
New branches created under the repository directory will store their
1342
revisions in the repository, not in the branch directory.
1344
If the --no-trees option is used then the branches in the repository
1345
will not have working trees by default.
1348
bzr init-repo --no-trees repo
1350
bzr checkout --lightweight repo/trunk trunk-checkout
1354
See 'bzr help repositories' for more information.
1357
_see_also = ['init', 'branch', 'checkout']
1358
takes_args = ["location"]
1359
takes_options = [RegistryOption('format',
1360
help='Specify a format for this repository. See'
1361
' "bzr help formats" for details.',
1362
registry=bzrdir.format_registry,
1363
converter=bzrdir.format_registry.make_bzrdir,
1364
value_switches=True, title='Repository format'),
1366
help='Branches in the repository will default to'
1367
' not having a working tree.'),
1369
aliases = ["init-repo"]
1371
def run(self, location, format=None, no_trees=False):
1373
format = bzrdir.format_registry.make_bzrdir('default')
1375
if location is None:
1378
to_transport = transport.get_transport(location)
1379
to_transport.ensure_base()
1381
newdir = format.initialize_on_transport(to_transport)
1382
repo = newdir.create_repository(shared=True)
1383
repo.set_make_working_trees(not no_trees)
736
# The path has to exist to initialize a
737
# branch inside of it.
738
# Just using os.mkdir, since I don't
739
# believe that we want to create a bunch of
740
# locations if the user supplies an extended path
741
if not os.path.exists(location):
743
Branch.initialize(location)
1386
746
class cmd_diff(Command):
1387
"""Show differences in the working tree or between revisions.
747
"""Show differences in working tree.
1389
749
If files are listed, only the changes in those files are listed.
1390
750
Otherwise, all changes for the tree are listed.
1392
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1393
produces patches suitable for "patch -p1".
1397
Shows the difference in the working tree versus the last commit
1399
Difference between the working tree and revision 1
1401
Difference between revision 2 and revision 1
1402
bzr diff --prefix old/:new/
1403
Same as 'bzr diff' but prefix paths with old/ and new/
1404
bzr diff bzr.mine bzr.dev
1405
Show the differences between the two working trees
1407
Show just the differences for 'foo.c'
757
# TODO: Allow diff across branches.
1409
758
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1410
759
# or a graphical diff.
1412
761
# TODO: Python difflib is not exactly the same as unidiff; should
1413
762
# either fix it up or prefer to use an external diff.
764
# TODO: If a directory is given, diff everything under that.
1415
766
# TODO: Selected-file diff is inefficient and doesn't show you
1416
767
# deleted files.
1418
769
# TODO: This probably handles non-Unix newlines poorly.
1420
_see_also = ['status']
1421
771
takes_args = ['file*']
1423
Option('diff-options', type=str,
1424
help='Pass these options to the external diff program.'),
1425
Option('prefix', type=str,
1427
help='Set prefixes to added to old and new filenames, as '
1428
'two values separated by a colon. (eg "old/:new/").'),
772
takes_options = ['revision', 'diff-options']
1431
773
aliases = ['di', 'dif']
1432
encoding_type = 'exact'
1434
775
@display_command
1435
def run(self, revision=None, file_list=None, diff_options=None,
1437
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1439
if (prefix is None) or (prefix == '0'):
1447
old_label, new_label = prefix.split(":")
1449
raise errors.BzrCommandError(
1450
'--prefix expects two values separated by a colon'
1451
' (eg "old/:new/")')
1453
if revision and len(revision) > 2:
1454
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1455
' one or two revision specifiers')
776
def run(self, revision=None, file_list=None, diff_options=None):
777
from bzrlib.diff import show_diff
1458
tree1, file_list = internal_tree_files(file_list)
779
tree, file_list = internal_tree_files(file_list)
1462
except errors.FileInWrongBranch:
782
except FileInWrongBranch:
1463
783
if len(file_list) != 2:
1464
raise errors.BzrCommandError("Files are in different branches")
784
raise BzrCommandError("Files are in different branches")
1466
tree1, file1 = WorkingTree.open_containing(file_list[0])
1467
tree2, file2 = WorkingTree.open_containing(file_list[1])
786
b, file1 = Branch.open_containing(file_list[0])
787
b2, file2 = Branch.open_containing(file_list[1])
1468
788
if file1 != "" or file2 != "":
1469
789
# FIXME diff those two files. rbc 20051123
1470
raise errors.BzrCommandError("Files are in different branches")
790
raise BzrCommandError("Files are in different branches")
1471
791
file_list = None
1472
except errors.NotBranchError:
1473
if (revision is not None and len(revision) == 2
1474
and not revision[0].needs_branch()
1475
and not revision[1].needs_branch()):
1476
# If both revision specs include a branch, we can
1477
# diff them without needing a local working tree
1478
tree1, tree2 = None, None
1482
if tree2 is not None:
1483
if revision is not None:
1484
# FIXME: but there should be a clean way to diff between
1485
# non-default versions of two trees, it's not hard to do
1487
raise errors.BzrCommandError(
1488
"Sorry, diffing arbitrary revisions across branches "
1489
"is not implemented yet")
1490
return show_diff_trees(tree1, tree2, sys.stdout,
1491
specific_files=file_list,
1492
external_diff_options=diff_options,
1493
old_label=old_label, new_label=new_label)
1495
return diff_cmd_helper(tree1, file_list, diff_options,
1496
revision_specs=revision,
1497
old_label=old_label, new_label=new_label)
792
if revision is not None:
794
raise BzrCommandError("Can't specify -r with two branches")
795
if len(revision) == 1:
796
return show_diff(tree.branch, revision[0], specific_files=file_list,
797
external_diff_options=diff_options)
798
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])
803
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)
1500
813
class cmd_deleted(Command):
1506
819
# directories with readdir, rather than stating each one. Same
1507
820
# level of effort but possibly much less IO. (Or possibly not,
1508
821
# if the directories are very large...)
1509
_see_also = ['status', 'ls']
1510
takes_options = ['show-ids']
1512
822
@display_command
1513
823
def run(self, show_ids=False):
1514
824
tree = WorkingTree.open_containing(u'.')[0]
1517
old = tree.basis_tree()
1520
for path, ie in old.inventory.iter_entries():
1521
if not tree.has_id(ie.file_id):
1522
self.outf.write(path)
1524
self.outf.write(' ')
1525
self.outf.write(ie.file_id)
1526
self.outf.write('\n')
825
old = tree.branch.basis_tree()
826
for path, ie in old.inventory.iter_entries():
827
if not tree.has_id(ie.file_id):
829
print '%-50s %s' % (path, ie.file_id)
1533
834
class cmd_modified(Command):
1534
"""List files modified in working tree.
835
"""List files modified in working tree."""
1538
_see_also = ['status', 'ls']
1540
837
@display_command
839
from bzrlib.delta import compare_trees
1542
841
tree = WorkingTree.open_containing(u'.')[0]
1543
td = tree.changes_from(tree.basis_tree())
842
td = compare_trees(tree.branch.basis_tree(), tree)
1544
844
for path, id, kind, text_modified, meta_modified in td.modified:
1545
self.outf.write(path + '\n')
1548
849
class cmd_added(Command):
1549
"""List files added in working tree.
850
"""List files added in working tree."""
1553
_see_also = ['status', 'ls']
1555
852
@display_command
1557
854
wt = WorkingTree.open_containing(u'.')[0]
1560
basis = wt.basis_tree()
1563
basis_inv = basis.inventory
1566
if file_id in basis_inv:
1568
if inv.is_root(file_id) and len(basis_inv) == 0:
1570
path = inv.id2path(file_id)
1571
if not os.access(osutils.abspath(path), os.F_OK):
1573
self.outf.write(path + '\n')
855
basis_inv = wt.branch.basis_tree().inventory
858
if file_id in basis_inv:
860
path = inv.id2path(file_id)
861
if not os.access(b.abspath(path), os.F_OK):
1580
867
class cmd_root(Command):
1581
868
"""Show the tree root directory.
1583
870
The root is the nearest enclosing directory with a .bzr control
1586
872
takes_args = ['filename?']
1587
873
@display_command
1588
874
def run(self, filename=None):
1589
875
"""Print the branch root."""
1590
876
tree = WorkingTree.open_containing(filename)[0]
1591
self.outf.write(tree.basedir + '\n')
1594
def _parse_limit(limitstring):
1596
return int(limitstring)
1598
msg = "The limit argument must be an integer."
1599
raise errors.BzrCommandError(msg)
1602
880
class cmd_log(Command):
1603
"""Show log of a branch, file, or directory.
1605
By default show the log of the branch containing the working directory.
881
"""Show log of this branch.
1607
883
To request a range of logs, you can use the command -r begin..end
1608
884
-r revision requests a specific revision, -r ..end or -r begin.. are
1614
bzr log -r -10.. http://server/branch
1617
888
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1619
takes_args = ['location?']
1622
help='Show from oldest to newest.'),
1625
help='Display timezone as local, original, or utc.'),
1628
help='Show files changed in each revision.'),
1634
help='Show revisions whose message matches this '
1635
'regular expression.',
1638
help='Limit the output to the first N revisions.',
1642
encoding_type = 'replace'
890
takes_args = ['filename?']
891
takes_options = [Option('forward',
892
help='show from oldest to newest'),
893
'timezone', 'verbose',
894
'show-ids', 'revision',
897
help='show revisions whose message matches this regexp',
1644
901
@display_command
1645
def run(self, location=None, timezone='original',
902
def run(self, filename=None, timezone='original',
1653
from bzrlib.log import show_log
911
from bzrlib.log import log_formatter, show_log
1654
913
assert message is None or isinstance(message, basestring), \
1655
914
"invalid message argument %r" % message
1656
915
direction = (forward and 'forward') or 'reverse'
1661
# find the file id to log:
1663
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
921
tree, fp = WorkingTree.open_containing(filename)
924
inv = tree.read_working_inventory()
925
except NotBranchError:
928
b, fp = Branch.open_containing(filename)
930
inv = b.get_inventory(b.last_revision())
1667
tree = b.basis_tree()
1668
file_id = tree.path2id(fp)
1670
raise errors.BzrCommandError(
1671
"Path does not have any revision history: %s" %
1675
# FIXME ? log the current subdir only RBC 20060203
1676
if revision is not None \
1677
and len(revision) > 0 and revision[0].get_branch():
1678
location = revision[0].get_branch()
1681
dir, relpath = bzrdir.BzrDir.open_containing(location)
1682
b = dir.open_branch()
1686
if revision is None:
1689
elif len(revision) == 1:
1690
rev1 = rev2 = revision[0].in_history(b)
1691
elif len(revision) == 2:
1692
if revision[1].get_branch() != revision[0].get_branch():
1693
# b is taken from revision[0].get_branch(), and
1694
# show_log will use its revision_history. Having
1695
# different branches will lead to weird behaviors.
1696
raise errors.BzrCommandError(
1697
"Log doesn't accept two revisions in different"
1699
rev1 = revision[0].in_history(b)
1700
rev2 = revision[1].in_history(b)
1702
raise errors.BzrCommandError(
1703
'bzr log --revision takes one or two values.')
1705
if log_format is None:
1706
log_format = log.log_formatter_registry.get_default(b)
1708
lf = log_format(show_ids=show_ids, to_file=self.outf,
1709
show_timezone=timezone)
1715
direction=direction,
1716
start_revision=rev1,
932
file_id = inv.path2id(fp)
934
file_id = None # points to branch root
936
tree, relpath = WorkingTree.open_containing(u'.')
943
elif len(revision) == 1:
944
rev1 = rev2 = revision[0].in_history(b).revno
945
elif len(revision) == 2:
946
rev1 = revision[0].in_history(b).revno
947
rev2 = revision[1].in_history(b).revno
949
raise BzrCommandError('bzr log --revision takes one or two values.')
951
# By this point, the revision numbers are converted to the +ve
952
# form if they were supplied in the -ve form, so we can do
953
# this comparison in relative safety
955
(rev2, rev1) = (rev1, rev2)
957
mutter('encoding log as %r', bzrlib.user_encoding)
959
# use 'replace' so that we don't abort if trying to write out
960
# in e.g. the default C locale.
961
outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
963
log_format = get_log_format(long=long, short=short, line=line)
964
lf = log_formatter(log_format,
967
show_timezone=timezone)
1724
978
def get_log_format(long=False, short=False, line=False, default='long'):
1725
979
log_format = default
1735
989
class cmd_touching_revisions(Command):
1736
990
"""Return revision-ids which affected a particular file.
1738
A more user-friendly interface is "bzr log FILE".
992
A more user-friendly interface is "bzr log FILE"."""
1742
994
takes_args = ["filename"]
1744
995
@display_command
1745
996
def run(self, filename):
1746
997
tree, relpath = WorkingTree.open_containing(filename)
1748
file_id = tree.path2id(relpath)
1749
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1750
self.outf.write("%6d %s\n" % (revno, what))
999
inv = tree.read_working_inventory()
1000
file_id = inv.path2id(relpath)
1001
for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
1002
print "%6d %s" % (revno, what)
1753
1005
class cmd_ls(Command):
1754
1006
"""List files in a tree.
1757
_see_also = ['status', 'cat']
1758
takes_args = ['path?']
1759
1008
# TODO: Take a revision or remote path and list that tree instead.
1763
Option('non-recursive',
1764
help='Don\'t recurse into subdirectories.'),
1766
help='Print paths relative to the root of the branch.'),
1767
Option('unknown', help='Print unknown files.'),
1768
Option('versioned', help='Print versioned files.'),
1769
Option('ignored', help='Print ignored files.'),
1771
help='Write an ascii NUL (\\0) separator '
1772
'between files rather than a newline.'),
1774
help='List entries of a particular kind: file, directory, symlink.',
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'),
1778
1021
@display_command
1779
def run(self, revision=None, verbose=False,
1022
def run(self, revision=None, verbose=False,
1780
1023
non_recursive=False, from_root=False,
1781
1024
unknown=False, versioned=False, ignored=False,
1782
null=False, kind=None, show_ids=False, path=None):
1784
if kind and kind not in ('file', 'directory', 'symlink'):
1785
raise errors.BzrCommandError('invalid kind specified')
1787
1027
if verbose and null:
1788
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1028
raise BzrCommandError('Cannot set both --verbose and --null')
1789
1029
all = not (unknown or versioned or ignored)
1791
1031
selection = {'I':ignored, '?':unknown, 'V':versioned}
1798
raise errors.BzrCommandError('cannot specify both --from-root'
1802
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1033
tree, relpath = WorkingTree.open_containing(u'.')
1808
1038
if revision is not None:
1809
tree = branch.repository.revision_tree(
1810
revision[0].in_history(branch).rev_id)
1812
tree = branch.basis_tree()
1816
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1817
if fp.startswith(relpath):
1818
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1819
if non_recursive and '/' in fp:
1821
if not all and not selection[fc]:
1823
if kind is not None and fkind != kind:
1826
kindch = entry.kind_character()
1827
outstring = '%-8s %s%s' % (fc, fp, kindch)
1828
if show_ids and fid is not None:
1829
outstring = "%-50s %s" % (outstring, fid)
1830
self.outf.write(outstring + '\n')
1832
self.outf.write(fp + '\0')
1835
self.outf.write(fid)
1836
self.outf.write('\0')
1844
self.outf.write('%-50s %s\n' % (fp, my_id))
1846
self.outf.write(fp + '\n')
1039
tree = tree.branch.revision_tree(
1040
revision[0].in_history(tree.branch).rev_id)
1041
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')
1851
1059
class cmd_unknowns(Command):
1852
"""List unknown files.
1060
"""List unknown files."""
1858
1061
@display_command
1063
from bzrlib.osutils import quotefn
1860
1064
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1861
self.outf.write(osutils.quotefn(f) + '\n')
1864
1068
class cmd_ignore(Command):
1865
"""Ignore specified files or patterns.
1069
"""Ignore a command or pattern.
1867
1071
To remove patterns from the ignore list, edit the .bzrignore file.
1869
Trailing slashes on patterns are ignored.
1870
If the pattern contains a slash or is a regular expression, it is compared
1871
to the whole path from the branch root. Otherwise, it is compared to only
1872
the last component of the path. To match a file only in the root
1873
directory, prepend './'.
1875
Ignore patterns specifying absolute paths are not allowed.
1877
Ignore patterns may include globbing wildcards such as:
1878
? - Matches any single character except '/'
1879
* - Matches 0 or more characters except '/'
1880
/**/ - Matches 0 or more directories in a path
1881
[a-z] - Matches a single character from within a group of characters
1883
Ignore patterns may also be Python regular expressions.
1884
Regular expression ignore patterns are identified by a 'RE:' prefix
1885
followed by the regular expression. Regular expression ignore patterns
1886
may not include named or numbered groups.
1888
Note: ignore patterns containing shell wildcards must be quoted from
1073
If the pattern contains a slash, it is compared to the whole path
1074
from the branch root. Otherwise, it is compared to only the last
1075
component of the path. To match a file only in the root directory,
1078
Ignore patterns are case-insensitive on case-insensitive systems.
1080
Note: wildcards must be quoted from the shell on Unix.
1892
1083
bzr ignore ./Makefile
1893
1084
bzr ignore '*.class'
1894
bzr ignore 'lib/**/*.o'
1895
bzr ignore 'RE:lib/.*\.o'
1898
_see_also = ['status', 'ignored']
1899
takes_args = ['name_pattern*']
1901
Option('old-default-rules',
1902
help='Write out the ignore rules bzr < 0.9 always used.')
1086
# TODO: Complain if the filename is absolute
1087
takes_args = ['name_pattern']
1905
def run(self, name_pattern_list=None, old_default_rules=None):
1089
def run(self, name_pattern):
1906
1090
from bzrlib.atomicfile import AtomicFile
1907
if old_default_rules is not None:
1908
# dump the rules and exit
1909
for pattern in ignores.OLD_DEFAULTS:
1912
if not name_pattern_list:
1913
raise errors.BzrCommandError("ignore requires at least one "
1914
"NAME_PATTERN or --old-default-rules")
1915
name_pattern_list = [globbing.normalize_pattern(p)
1916
for p in name_pattern_list]
1917
for name_pattern in name_pattern_list:
1918
if (name_pattern[0] == '/' or
1919
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1920
raise errors.BzrCommandError(
1921
"NAME_PATTERN should not be an absolute path")
1922
1093
tree, relpath = WorkingTree.open_containing(u'.')
1923
1094
ifn = tree.abspath('.bzrignore')
1924
1096
if os.path.exists(ifn):
1925
1097
f = open(ifn, 'rt')
1997
1167
given, try to find the format with the extension. If no extension
1998
1168
is found exports to a directory (equivalent to --format=dir).
2000
If root is supplied, it will be used as the root directory inside
2001
container formats (tar, zip, etc). If it is not supplied it will default
2002
to the exported filename. The root option has no effect for 'dir' format.
2004
If branch is omitted then the branch containing the current working
2005
directory will be used.
2007
Note: Export of tree with non-ASCII filenames to zip is not supported.
2009
Supported formats Autodetected by extension
2010
----------------- -------------------------
1170
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
----------------- -------------------------
2013
1179
tbz2 .tar.bz2, .tbz2
2014
1180
tgz .tar.gz, .tgz
2017
takes_args = ['dest', 'branch?']
2020
help="Type of file to export to.",
2025
help="Name of the root directory inside the exported file."),
2027
def run(self, dest, branch=None, revision=None, format=None, root=None):
1183
takes_args = ['dest']
1184
takes_options = ['revision', 'format', 'root']
1185
def run(self, dest, revision=None, format=None, root=None):
2028
1187
from bzrlib.export import export
2031
tree = WorkingTree.open_containing(u'.')[0]
2034
b = Branch.open(branch)
1188
tree = WorkingTree.open_containing(u'.')[0]
2036
1190
if revision is None:
2037
1191
# should be tree.last_revision FIXME
2038
1192
rev_id = b.last_revision()
2040
1194
if len(revision) != 1:
2041
raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
1195
raise BzrError('bzr export --revision takes exactly 1 argument')
2042
1196
rev_id = revision[0].in_history(b).rev_id
2043
t = b.repository.revision_tree(rev_id)
1197
t = b.revision_tree(rev_id)
2045
1199
export(t, dest, format, root)
2046
1200
except errors.NoSuchExportFormat, e:
2047
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1201
raise BzrCommandError('Unsupported export format: %s' % e.format)
2050
1204
class cmd_cat(Command):
2051
"""Write the contents of a file as of a given revision to standard output.
2053
If no revision is nominated, the last revision is used.
2055
Note: Take care to redirect standard output when using this command on a
2061
Option('name-from-revision', help='The path name in the old tree.'),
1205
"""Write a file's text from a previous revision."""
1207
takes_options = ['revision']
2064
1208
takes_args = ['filename']
2065
encoding_type = 'exact'
2067
1210
@display_command
2068
def run(self, filename, revision=None, name_from_revision=False):
1211
def run(self, filename, revision=None):
2069
1212
if revision is not None and len(revision) != 1:
2070
raise errors.BzrCommandError("bzr cat --revision takes exactly"
1213
raise BzrCommandError("bzr cat --revision takes exactly one number")
2075
tree, b, relpath = \
2076
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2077
except errors.NotBranchError:
1216
tree, relpath = WorkingTree.open_containing(filename)
1218
except NotBranchError:
2080
if revision is not None and revision[0].get_branch() is not None:
2081
b = Branch.open(revision[0].get_branch())
2082
1221
if tree is None:
2083
tree = b.basis_tree()
1222
b, relpath = Branch.open_containing(filename)
2084
1223
if revision is None:
2085
1224
revision_id = b.last_revision()
2087
1226
revision_id = revision[0].in_history(b).rev_id
2089
cur_file_id = tree.path2id(relpath)
2090
rev_tree = b.repository.revision_tree(revision_id)
2091
old_file_id = rev_tree.path2id(relpath)
2093
if name_from_revision:
2094
if old_file_id is None:
2095
raise errors.BzrCommandError("%r is not present in revision %s"
2096
% (filename, revision_id))
2098
rev_tree.print_file(old_file_id)
2099
elif cur_file_id is not None:
2100
rev_tree.print_file(cur_file_id)
2101
elif old_file_id is not None:
2102
rev_tree.print_file(old_file_id)
2104
raise errors.BzrCommandError("%r is not present in revision %s" %
2105
(filename, revision_id))
1227
b.print_file(relpath, revision_id)
2108
1230
class cmd_local_time_offset(Command):
2152
1259
# XXX: verbose currently does nothing
2154
_see_also = ['bugs', 'uncommit']
2155
1261
takes_args = ['selected*']
2157
Option('message', type=unicode,
2159
help="Description of the new revision."),
2162
help='Commit even if nothing has changed.'),
2163
Option('file', type=str,
2166
help='Take commit message from this file.'),
2168
help="Refuse to commit if there are unknown "
2169
"files in the working tree."),
2170
ListOption('fixes', type=str,
2171
help="Mark a bug as being fixed by this revision."),
2173
help="Perform a local commit in a bound "
2174
"branch. Local commits are not pushed to "
2175
"the master branch until a normal commit "
1262
takes_options = ['message', 'verbose',
1264
help='commit even if nothing has changed'),
1265
Option('file', type=str,
1267
help='file containing commit message'),
1269
help="refuse to commit if there are unknown "
1270
"files in the working tree."),
2179
1272
aliases = ['ci', 'checkin']
2181
def _get_bug_fix_properties(self, fixes, branch):
2183
# Configure the properties for bug fixing attributes.
2184
for fixed_bug in fixes:
2185
tokens = fixed_bug.split(':')
2186
if len(tokens) != 2:
2187
raise errors.BzrCommandError(
2188
"Invalid bug %s. Must be in the form of 'tag:id'. "
2189
"Commit refused." % fixed_bug)
2190
tag, bug_id = tokens
2192
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2193
except errors.UnknownBugTrackerAbbreviation:
2194
raise errors.BzrCommandError(
2195
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2196
except errors.MalformedBugIdentifier:
2197
raise errors.BzrCommandError(
2198
"Invalid bug identifier for %s. Commit refused."
2200
properties.append('%s fixed' % bug_url)
2201
return '\n'.join(properties)
2203
1274
def run(self, message=None, file=None, verbose=True, selected_list=None,
2204
unchanged=False, strict=False, local=False, fixes=None):
2205
from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
1275
unchanged=False, strict=False):
2206
1276
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
2207
1277
StrictCommitFailed)
2208
1278
from bzrlib.msgeditor import edit_commit_message, \
2209
1279
make_commit_message_template
1280
from bzrlib.status import show_status
1281
from tempfile import TemporaryFile
2211
1284
# TODO: Need a blackbox test for invoking the external editor; may be
2212
1285
# slightly problematic to run this cross-platform.
2214
1287
# TODO: do more checks that the commit will succeed before
2215
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
2219
1292
tree, selected_list = tree_files(selected_list)
2220
if selected_list == ['']:
2221
# workaround - commit of root of tree should be exactly the same
2222
# as just default commit in that tree, and succeed even though
2223
# selected-file merge commit is not done yet
2226
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2228
properties['bugs'] = bug_property
2230
if local and not tree.branch.get_bound_location():
2231
raise errors.LocalRequiresBoundBranch()
2233
def get_message(commit_obj):
2234
"""Callback to get commit message"""
2235
my_message = message
2236
if my_message is None and not file:
2237
template = make_commit_message_template(tree, selected_list)
2238
my_message = edit_commit_message(template)
2239
if my_message is None:
2240
raise errors.BzrCommandError("please specify a commit"
2241
" message with either --message or --file")
2242
elif my_message and file:
2243
raise errors.BzrCommandError(
2244
"please specify either --message or --file")
2246
my_message = codecs.open(file, 'rt',
2247
bzrlib.user_encoding).read()
2248
if my_message == "":
2249
raise errors.BzrCommandError("empty commit message specified")
2253
reporter = ReportCommitToLog()
2255
reporter = NullCommitReporter()
1293
if message is None and not file:
1294
template = make_commit_message_template(tree, selected_list)
1295
message = edit_commit_message(template)
1297
raise BzrCommandError("please specify a commit message"
1298
" with either --message or --file")
1299
elif message and file:
1300
raise BzrCommandError("please specify either --message or --file")
1304
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1307
raise BzrCommandError("empty commit message specified")
2258
tree.commit(message_callback=get_message,
2259
specific_files=selected_list,
2260
allow_pointless=unchanged, strict=strict, local=local,
2261
reporter=reporter, revprops=properties)
1310
tree.commit(message, specific_files=selected_list,
1311
allow_pointless=unchanged, strict=strict)
2262
1312
except PointlessCommit:
2263
1313
# FIXME: This should really happen before the file is read in;
2264
1314
# perhaps prepare the commit; get the message; then actually commit
2265
raise errors.BzrCommandError("no changes to commit."
2266
" use --unchanged to commit anyhow")
1315
raise BzrCommandError("no changes to commit",
1316
["use --unchanged to commit anyhow"])
2267
1317
except ConflictsInTree:
2268
raise errors.BzrCommandError('Conflicts detected in working '
2269
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
1318
raise BzrCommandError("Conflicts detected in working tree. "
1319
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
2271
1320
except StrictCommitFailed:
2272
raise errors.BzrCommandError("Commit refused because there are"
2273
" unknown files in the working tree.")
2274
except errors.BoundBranchOutOfDate, e:
2275
raise errors.BzrCommandError(str(e) + "\n"
2276
'To commit to master branch, run update and then commit.\n'
2277
'You can also pass --local to commit to continue working '
1321
raise BzrCommandError("Commit refused because there are unknown "
1322
"files in the working tree.")
1323
note('Committed revision %d.' % (tree.branch.revno(),))
2281
1326
class cmd_check(Command):
2299
1342
check(branch, verbose)
1345
class cmd_scan_cache(Command):
1348
from bzrlib.hashcache import HashCache
1354
print '%6d stats' % c.stat_count
1355
print '%6d in hashcache' % len(c._cache)
1356
print '%6d files removed from cache' % c.removed_count
1357
print '%6d hashes updated' % c.update_count
1358
print '%6d files changed too recently to cache' % c.danger_count
2302
1365
class cmd_upgrade(Command):
2303
1366
"""Upgrade branch storage to current format.
2305
1368
The check command or bzr developers may sometimes advise you to run
2306
this command. When the default format has changed you may also be warned
2307
during other operations to upgrade.
1371
This version of this command upgrades from the full-text storage
1372
used by bzr 0.0.8 and earlier to the weave format (v5).
2310
_see_also = ['check']
2311
takes_args = ['url?']
2313
RegistryOption('format',
2314
help='Upgrade to a specific format. See "bzr help'
2315
' formats" for details.',
2316
registry=bzrdir.format_registry,
2317
converter=bzrdir.format_registry.make_bzrdir,
2318
value_switches=True, title='Branch format'),
2321
def run(self, url='.', format=None):
1374
takes_args = ['dir?']
1376
def run(self, dir=u'.'):
2322
1377
from bzrlib.upgrade import upgrade
2324
format = bzrdir.format_registry.make_bzrdir('default')
2325
upgrade(url, format)
2328
1381
class cmd_whoami(Command):
2329
"""Show or set bzr user id.
2333
bzr whoami 'Frank Chu <fchu@example.com>'
2335
takes_options = [ Option('email',
2336
help='Display email address only.'),
2338
help='Set identity for the current branch instead of '
2341
takes_args = ['name?']
2342
encoding_type = 'replace'
1382
"""Show bzr user id."""
1383
takes_options = ['email']
2344
1385
@display_command
2345
def run(self, email=False, branch=False, name=None):
2347
# use branch if we're inside one; otherwise global config
2349
c = Branch.open_containing('.')[0].get_config()
2350
except errors.NotBranchError:
2351
c = config.GlobalConfig()
2353
self.outf.write(c.user_email() + '\n')
2355
self.outf.write(c.username() + '\n')
2358
# display a warning if an email address isn't included in the given name.
1386
def run(self, email=False):
2360
config.extract_email_address(name)
2361
except errors.NoEmailInUsername, e:
2362
warning('"%s" does not seem to contain an email address. '
2363
'This is allowed, but not recommended.', name)
1388
b = WorkingTree.open_containing(u'.')[0].branch
1389
config = bzrlib.config.BranchConfig(b)
1390
except NotBranchError:
1391
config = bzrlib.config.GlobalConfig()
2365
# use global config unless --branch given
2367
c = Branch.open_containing('.')[0].get_config()
1394
print config.user_email()
2369
c = config.GlobalConfig()
2370
c.set_user_option('email', name)
1396
print config.username()
2373
1398
class cmd_nick(Command):
2374
"""Print or set the branch nickname.
1400
Print or set the branch nickname.
2376
1401
If unset, the tree root directory name is used as the nickname
2377
1402
To print the current nickname, execute with no argument.
2380
_see_also = ['info']
2381
1404
takes_args = ['nickname?']
2382
1405
def run(self, nickname=None):
2383
1406
branch = Branch.open_containing(u'.')[0]
2389
1412
@display_command
2390
1413
def printme(self, branch):
2394
1416
class cmd_selftest(Command):
2395
1417
"""Run internal test suite.
2397
If arguments are given, they are regular expressions that say which tests
2398
should run. Tests matching any expression are run, and other tests are
2401
Alternatively if --first is given, matching tests are run first and then
2402
all other tests are run. This is useful if you have been working in a
2403
particular area, but want to make sure nothing else was broken.
2405
If --exclude is given, tests that match that regular expression are
2406
excluded, regardless of whether they match --first or not.
2408
To help catch accidential dependencies between tests, the --randomize
2409
option is useful. In most cases, the argument used is the word 'now'.
2410
Note that the seed used for the random number generator is displayed
2411
when this option is used. The seed can be explicitly passed as the
2412
argument to this option if required. This enables reproduction of the
2413
actual ordering used if and when an order sensitive problem is encountered.
2415
If --list-only is given, the tests that would be run are listed. This is
2416
useful when combined with --first, --exclude and/or --randomize to
2417
understand their impact. The test harness reports "Listed nn tests in ..."
2418
instead of "Ran nn tests in ..." when list mode is enabled.
2420
If the global option '--no-plugins' is given, plugins are not loaded
2421
before running the selftests. This has two effects: features provided or
2422
modified by plugins will not be tested, and tests provided by plugins will
2425
Tests that need working space on disk use a common temporary directory,
2426
typically inside $TMPDIR or /tmp.
2430
run only tests relating to 'ignore'
2431
bzr --no-plugins selftest -v
2432
disable plugins and list tests as they're run
1419
This creates temporary test directories in the working directory,
1420
but not existing data is affected. These directories are deleted
1421
if the tests pass, or left behind to help in debugging if they
1422
fail and --keep-output is specified.
1424
If arguments are given, they are regular expressions that say
1425
which tests should run.
2434
# NB: this is used from the class without creating an instance, which is
2435
# why it does not have a self parameter.
2436
def get_transport_type(typestring):
2437
"""Parse and return a transport specifier."""
2438
if typestring == "sftp":
2439
from bzrlib.transport.sftp import SFTPAbsoluteServer
2440
return SFTPAbsoluteServer
2441
if typestring == "memory":
2442
from bzrlib.transport.memory import MemoryServer
2444
if typestring == "fakenfs":
2445
from bzrlib.transport.fakenfs import FakeNFSServer
2446
return FakeNFSServer
2447
msg = "No known transport type %s. Supported types are: sftp\n" %\
2449
raise errors.BzrCommandError(msg)
1427
# TODO: --list should give a list of all available tests
2452
1429
takes_args = ['testspecs*']
2453
takes_options = ['verbose',
2455
help='Stop when one test fails.',
2459
help='Use a different transport by default '
2460
'throughout the test suite.',
2461
type=get_transport_type),
2463
help='Run the benchmarks rather than selftests.'),
2464
Option('lsprof-timed',
2465
help='Generate lsprof output for benchmarked'
2466
' sections of code.'),
2467
Option('cache-dir', type=str,
2468
help='Cache intermediate benchmark output in this '
2471
help='Run all tests, but run specified tests first.',
2475
help='List the tests instead of running them.'),
2476
Option('randomize', type=str, argname="SEED",
2477
help='Randomize the order of tests using the given'
2478
' seed or "now" for the current time.'),
2479
Option('exclude', type=str, argname="PATTERN",
2481
help='Exclude tests that match this regular'
2484
encoding_type = 'replace'
1430
takes_options = ['verbose',
1431
Option('one', help='stop when one test fails'),
1432
Option('keep-output',
1433
help='keep output directories when tests fail')
2486
def run(self, testspecs_list=None, verbose=None, one=False,
2487
transport=None, benchmark=None,
2488
lsprof_timed=None, cache_dir=None,
2489
first=False, list_only=False,
2490
randomize=None, exclude=None):
1436
def run(self, testspecs_list=None, verbose=False, one=False,
2491
1438
import bzrlib.ui
2492
1439
from bzrlib.tests import selftest
2493
import bzrlib.benchmarks as benchmarks
2494
from bzrlib.benchmarks import tree_creator
2495
from bzrlib.version import show_version
2497
if cache_dir is not None:
2498
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2500
show_version(show_config=False, show_copyright=False)
2502
if testspecs_list is not None:
2503
pattern = '|'.join(testspecs_list)
2507
test_suite_factory = benchmarks.test_suite
2510
# TODO: should possibly lock the history file...
2511
benchfile = open(".perf_history", "at", buffering=1)
2513
test_suite_factory = None
1440
# we don't want progress meters from the tests to go to the
1441
# real output; and we don't want log messages cluttering up
1443
save_ui = bzrlib.ui.ui_factory
1444
bzrlib.trace.info('running tests...')
2518
result = selftest(verbose=verbose,
1446
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1447
if testspecs_list is not None:
1448
pattern = '|'.join(testspecs_list)
1451
result = selftest(verbose=verbose,
2519
1452
pattern=pattern,
2520
stop_on_failure=one,
2521
transport=transport,
2522
test_suite_factory=test_suite_factory,
2523
lsprof_timed=lsprof_timed,
2524
bench_history=benchfile,
2525
matching_tests_first=first,
2526
list_only=list_only,
2527
random_seed=randomize,
2528
exclude_pattern=exclude
1453
stop_on_failure=one,
1454
keep_output=keep_output)
1456
bzrlib.trace.info('tests passed')
1458
bzrlib.trace.info('tests failed')
1459
return int(not result)
2531
if benchfile is not None:
2534
info('tests passed')
2536
info('tests failed')
2537
return int(not result)
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:
1479
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1480
# is bzrlib itself in a branch?
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],)
1489
print bzrlib.__copyright__
1490
print "http://bazaar-ng.org/"
1492
print "bzr comes with ABSOLUTELY NO WARRANTY. bzr is free software, and"
1493
print "you may use, modify and redistribute it under the terms of the GNU"
1494
print "General Public License version 2 or later."
2540
1497
class cmd_version(Command):
2541
1498
"""Show version of bzr."""
2543
1499
@display_command
2545
from bzrlib.version import show_version
2549
1503
class cmd_rocks(Command):
2550
1504
"""Statement of optimism."""
2554
1506
@display_command
2556
print "It sure does!"
1508
print "it sure does!"
2559
1511
class cmd_find_merge_base(Command):
2560
"""Find and print a base revision for merging two branches."""
1512
"""Find and print a base revision for merging two branches.
2561
1514
# TODO: Options to specify revisions on either side, as if
2562
1515
# merging only part of the history.
2563
1516
takes_args = ['branch', 'other']
2566
1519
@display_command
2567
1520
def run(self, branch, other):
2568
from bzrlib.revision import ensure_null, MultipleRevisionSources
1521
from bzrlib.revision import common_ancestor, MultipleRevisionSources
2570
1523
branch1 = Branch.open_containing(branch)[0]
2571
1524
branch2 = Branch.open_containing(other)[0]
2573
last1 = ensure_null(branch1.last_revision())
2574
last2 = ensure_null(branch2.last_revision())
2576
graph = branch1.repository.get_graph(branch2.repository)
2577
base_rev_id = graph.find_unique_lca(last1, last2)
1526
history_1 = branch1.revision_history()
1527
history_2 = branch2.revision_history()
1529
last1 = branch1.last_revision()
1530
last2 = branch2.last_revision()
1532
source = MultipleRevisionSources(branch1, branch2)
1534
base_rev_id = common_ancestor(last1, last2, source)
2579
1536
print 'merge base is revision %s' % base_rev_id
1540
if base_revno is None:
1541
raise bzrlib.errors.UnrelatedBranches()
1543
print ' r%-6d in %s' % (base_revno, branch)
1545
other_revno = branch2.revision_id_to_revno(base_revid)
1547
print ' r%-6d in %s' % (other_revno, other)
2582
1551
class cmd_merge(Command):
2583
1552
"""Perform a three-way merge.
2585
The branch is the branch you will merge from. By default, it will merge
2586
the latest revision. If you specify a revision, that revision will be
2587
merged. If you specify two revisions, the first will be used as a BASE,
2588
and the second one as OTHER. Revision numbers are always relative to the
1554
The branch is the branch you will merge from. By default, it will
1555
merge the latest revision. If you specify a revision, that
1556
revision will be merged. If you specify two revisions, the first
1557
will be used as a BASE, and the second one as OTHER. Revision
1558
numbers are always relative to the specified branch.
2591
By default, bzr will try to merge in all new work from the other
1560
By default bzr will try to merge in all new work from the other
2592
1561
branch, automatically determining an appropriate base. If this
2593
1562
fails, you may need to give an explicit base.
2595
Merge will do its best to combine the changes in two branches, but there
2596
are some kinds of problems only a human can fix. When it encounters those,
2597
it will mark a conflict. A conflict means that you need to fix something,
2598
before you should commit.
2600
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
2602
If there is no default branch set, the first merge will set it. After
2603
that, you can omit the branch to use the default. To change the
2604
default, use --remember. The value will only be saved if the remote
2605
location can be accessed.
2607
The results of the merge are placed into the destination working
2608
directory, where they can be reviewed (with bzr diff), tested, and then
2609
committed to record the result of the merge.
2613
To merge the latest revision from bzr.dev:
2614
bzr merge ../bzr.dev
1566
To merge the latest revision from bzr.dev
1567
bzr merge ../bzr.dev
2616
To merge changes up to and including revision 82 from bzr.dev:
2617
bzr merge -r 82 ../bzr.dev
1569
To merge changes up to and including revision 82 from bzr.dev
1570
bzr merge -r 82 ../bzr.dev
2619
1572
To merge the changes introduced by 82, without previous changes:
2620
bzr merge -r 81..82 ../bzr.dev
1573
bzr merge -r 81..82 ../bzr.dev
2622
1575
merge refuses to run if there are any uncommitted changes, unless
2623
1576
--force is given.
2626
_see_also = ['update', 'remerge', 'status-flags']
2627
1578
takes_args = ['branch?']
2631
help='Merge even if the destination tree has uncommitted changes.'),
2635
Option('show-base', help="Show base revision text in "
2637
Option('uncommitted', help='Apply uncommitted changes'
2638
' from a working copy, instead of branch changes.'),
2639
Option('pull', help='If the destination is already'
2640
' completely merged into the source, pull from the'
2641
' source rather than merging. When this happens,'
2642
' you do not need to commit the result.'),
2644
help='Branch to merge into, '
2645
'rather than the one containing the working directory.',
1579
takes_options = ['revision', 'force', 'merge-type', 'reprocess',
1580
Option('show-base', help="Show base revision text in "
2651
1583
def run(self, branch=None, revision=None, force=False, merge_type=None,
2652
show_base=False, reprocess=False, remember=False,
2653
uncommitted=False, pull=False,
2656
from bzrlib.tag import _merge_tags_if_possible
1584
show_base=False, reprocess=False):
1585
from bzrlib.merge import merge
1586
from bzrlib.merge_core import ApplyMerge3
2657
1587
if merge_type is None:
2658
merge_type = _mod_merge.Merge3Merger
2660
if directory is None: directory = u'.'
2661
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2662
# inventory. Because merge is a mutating operation, it really
2663
# should be a lock_write() for the whole cmd_merge operation.
2664
# However, cmd_merge open's its own tree in _merge_helper, which
2665
# means if we lock here, the later lock_write() will always block.
2666
# Either the merge helper code should be updated to take a tree,
2667
# (What about tree.merge_from_branch?)
2668
tree = WorkingTree.open_containing(directory)[0]
2669
change_reporter = delta._ChangeReporter(
2670
unversioned_filter=tree.is_ignored)
2672
other_transport = None
2673
other_revision_id = None
2674
possible_transports = []
2675
# The user may provide a bundle or branch as 'branch' We first try to
2676
# identify a bundle, if it's not, we try to preserve connection used by
2677
# the transport to access the branch.
2678
if branch is not None:
2679
url = urlutils.normalize_url(branch)
2680
url, filename = urlutils.split(url, exclude_trailing_slash=False)
2681
other_transport = transport.get_transport(url)
2684
read_bundle = bundle.read_mergeable_from_transport
2685
# There may be redirections but we ignore the intermediate
2686
# and final transports used
2687
mergeable, t = read_bundle(other_transport, filename)
2688
except errors.NotABundle:
2689
# Continue on considering this url a Branch but adjust the
2691
other_transport = other_transport.clone(filename)
2693
if revision is not None:
2694
raise errors.BzrCommandError('Cannot use -r with merge'
2695
' directives or bundles')
2696
other_revision_id = mergeable.install_revisions(
2697
tree.branch.repository)
2698
revision = [RevisionSpec.from_string(
2699
'revid:' + other_revision_id)]
2700
possible_transports.append(other_transport)
2702
if revision is None \
2703
or len(revision) < 1 or revision[0].needs_branch():
2704
branch = self._get_remembered_parent(tree, branch, 'Merging from')
1588
merge_type = ApplyMerge3
1590
branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
1592
raise BzrCommandError("No merge location known or specified.")
1594
print "Using saved location: %s" % branch
2706
1595
if revision is None or len(revision) < 1:
2709
other = [branch, None]
2712
other = [branch, -1]
2713
other_branch, path = Branch.open_containing(branch,
2714
possible_transports)
1597
other = [branch, -1]
2717
raise errors.BzrCommandError('Cannot use --uncommitted and'
2718
' --revision at the same time.')
2719
branch = revision[0].get_branch() or branch
2720
1599
if len(revision) == 1:
2721
1600
base = [None, None]
2722
if other_revision_id is not None:
2723
# We merge from a bundle
2728
other_branch, path = Branch.open_containing(
2729
branch, possible_transports)
2730
revno = revision[0].in_history(other_branch).revno
2731
other = [branch, revno]
1601
other_branch = Branch.open_containing(branch)[0]
1602
revno = revision[0].in_history(other_branch).revno
1603
other = [branch, revno]
2733
1605
assert len(revision) == 2
2734
1606
if None in revision:
2735
raise errors.BzrCommandError(
2736
"Merge doesn't permit empty revision specifier.")
2737
base_branch, path = Branch.open_containing(branch,
2738
possible_transports)
2739
branch1 = revision[1].get_branch() or branch
2740
other_branch, path1 = Branch.open_containing(
2741
branch1, possible_transports)
2742
if revision[0].get_branch() is not None:
2743
# then path was obtained from it, and is None.
2746
base = [branch, revision[0].in_history(base_branch).revno]
2747
other = [branch1, revision[1].in_history(other_branch).revno]
2749
# Remember where we merge from
2750
if ((tree.branch.get_parent() is None or remember) and
2751
other_branch is not None):
2752
tree.branch.set_parent(other_branch.base)
2754
# pull tags now... it's a bit inconsistent to do it ahead of copying
2755
# the history but that's done inside the merge code
2756
if other_branch is not None:
2757
_merge_tags_if_possible(other_branch, tree.branch)
2760
interesting_files = [path]
2762
interesting_files = None
2763
pb = ui.ui_factory.nested_progress_bar()
1607
raise BzrCommandError(
1608
"Merge doesn't permit that revision specifier.")
1609
b = Branch.open_containing(branch)[0]
1611
base = [branch, revision[0].in_history(b).revno]
1612
other = [branch, revision[1].in_history(b).revno]
2766
conflict_count = _merge_helper(
2767
other, base, possible_transports,
2768
other_rev_id=other_revision_id,
2769
check_clean=(not force),
2770
merge_type=merge_type,
2771
reprocess=reprocess,
2772
show_base=show_base,
2775
pb=pb, file_list=interesting_files,
2776
change_reporter=change_reporter)
1615
conflict_count = merge(other, base, check_clean=(not force),
1616
merge_type=merge_type, reprocess=reprocess,
1617
show_base=show_base)
2779
1618
if conflict_count != 0:
2783
except errors.AmbiguousBase, e:
1622
except bzrlib.errors.AmbiguousBase, e:
2784
1623
m = ("sorry, bzr can't determine the right merge base yet\n"
2785
1624
"candidates are:\n "
2786
1625
+ "\n ".join(e.bases)
2789
1628
"and (if you want) report this to the bzr developers\n")
2792
# TODO: move up to common parent; this isn't merge-specific anymore.
2793
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2794
"""Use tree.branch's parent if none was supplied.
2796
Report if the remembered location was used.
2798
if supplied_location is not None:
2799
return supplied_location
2800
stored_location = tree.branch.get_parent()
2801
mutter("%s", stored_location)
2802
if stored_location is None:
2803
raise errors.BzrCommandError("No location specified or remembered")
2804
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2805
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2806
return stored_location
2809
1632
class cmd_remerge(Command):
2810
1633
"""Redo a merge.
2812
Use this if you want to try a different merge technique while resolving
2813
conflicts. Some merge techniques are better than others, and remerge
2814
lets you try different ones on different files.
2816
The options for remerge have the same meaning and defaults as the ones for
2817
merge. The difference is that remerge can (only) be run when there is a
2818
pending merge, and it lets you specify particular files.
2822
$ bzr remerge --show-base
2823
Re-do the merge of all conflicted files, and show the base text in
2824
conflict regions, in addition to the usual THIS and OTHER texts.
2826
$ bzr remerge --merge-type weave --reprocess foobar
2827
Re-do the merge of "foobar", using the weave merge algorithm, with
2828
additional processing to reduce the size of conflict regions.
2830
1635
takes_args = ['file*']
2835
help="Show base revision text in conflicts."),
1636
takes_options = ['merge-type', 'reprocess',
1637
Option('show-base', help="Show base revision text in "
2838
1640
def run(self, file_list=None, merge_type=None, show_base=False,
2839
1641
reprocess=False):
1642
from bzrlib.merge import merge_inner, transform_tree
1643
from bzrlib.merge_core import ApplyMerge3
2840
1644
if merge_type is None:
2841
merge_type = _mod_merge.Merge3Merger
1645
merge_type = ApplyMerge3
2842
1646
tree, file_list = tree_files(file_list)
2843
1647
tree.lock_write()
2845
parents = tree.get_parent_ids()
2846
if len(parents) != 2:
2847
raise errors.BzrCommandError("Sorry, remerge only works after normal"
2848
" merges. Not cherrypicking or"
2850
repository = tree.branch.repository
2851
graph = repository.get_graph()
2852
base_revision = graph.find_unique_lca(parents[0], parents[1])
2853
base_tree = repository.revision_tree(base_revision)
2854
other_tree = repository.revision_tree(parents[1])
1649
pending_merges = tree.pending_merges()
1650
if len(pending_merges) != 1:
1651
raise BzrCommandError("Sorry, remerge only works after normal"
1652
+ " merges. Not cherrypicking or"
1654
base_revision = common_ancestor(tree.branch.last_revision(),
1655
pending_merges[0], tree.branch)
1656
base_tree = tree.branch.revision_tree(base_revision)
1657
other_tree = tree.branch.revision_tree(pending_merges[0])
2855
1658
interesting_ids = None
2857
conflicts = tree.conflicts()
2858
1659
if file_list is not None:
2859
1660
interesting_ids = set()
2860
1661
for filename in file_list:
2861
1662
file_id = tree.path2id(filename)
2863
raise errors.NotVersionedError(filename)
2864
1663
interesting_ids.add(file_id)
2865
1664
if tree.kind(file_id) != "directory":
2868
1667
for name, ie in tree.inventory.iter_entries(file_id):
2869
1668
interesting_ids.add(ie.file_id)
2870
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
1669
transform_tree(tree, tree.branch.basis_tree(), interesting_ids)
1670
if file_list is None:
1671
restore_files = list(tree.iter_conflicts())
2872
# Remerge only supports resolving contents conflicts
2873
allowed_conflicts = ('text conflict', 'contents conflict')
2874
restore_files = [c.path for c in conflicts
2875
if c.typestring in allowed_conflicts]
2876
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2877
tree.set_conflicts(ConflictList(new_conflicts))
2878
if file_list is not None:
2879
1673
restore_files = file_list
2880
1674
for filename in restore_files:
2882
1676
restore(tree.abspath(filename))
2883
except errors.NotConflicted:
1677
except NotConflicted:
2885
conflicts = _mod_merge.merge_inner(
2886
tree.branch, other_tree, base_tree,
2888
interesting_ids=interesting_ids,
2889
other_rev_id=parents[1],
2890
merge_type=merge_type,
2891
show_base=show_base,
2892
reprocess=reprocess)
1679
conflicts = merge_inner(tree.branch, other_tree, base_tree,
1680
interesting_ids = interesting_ids,
1681
other_rev_id=pending_merges[0],
1682
merge_type=merge_type,
1683
show_base=show_base,
1684
reprocess=reprocess)
2895
1687
if conflicts > 0:
2901
1692
class cmd_revert(Command):
2902
"""Revert files to a previous revision.
2904
Giving a list of files will revert only those files. Otherwise, all files
2905
will be reverted. If the revision is not specified with '--revision', the
2906
last committed revision is used.
2908
To remove only some changes, without reverting to a prior version, use
2909
merge instead. For example, "merge . --r-2..-3" will remove the changes
2910
introduced by -2, without affecting the changes introduced by -1. Or
2911
to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
2913
By default, any files that have been manually changed will be backed up
2914
first. (Files changed only by merge are not backed up.) Backup files have
2915
'.~#~' appended to their name, where # is a number.
2917
When you provide files, you can use their current pathname or the pathname
2918
from the target revision. So you can use revert to "undelete" a file by
2919
name. If you name a directory, all the contents of that directory will be
1693
"""Reverse all changes since the last commit.
1695
Only versioned files are affected. Specify filenames to revert only
1696
those files. By default, any files that are changed will be backed up
1697
first. Backup files have a '~' appended to their name.
2923
_see_also = ['cat', 'export']
2926
Option('no-backup', "Do not save backups of reverted files."),
1699
takes_options = ['revision', 'no-backup']
2928
1700
takes_args = ['file*']
1701
aliases = ['merge-revert']
2930
1703
def run(self, revision=None, no_backup=False, file_list=None):
1704
from bzrlib.merge import merge_inner
1705
from bzrlib.commands import parse_spec
2931
1706
if file_list is not None:
2932
1707
if len(file_list) == 0:
2933
raise errors.BzrCommandError("No files specified")
1708
raise BzrCommandError("No files specified")
2937
tree, file_list = tree_files(file_list)
2938
1711
if revision is None:
1713
tree = WorkingTree.open_containing(u'.')[0]
2939
1714
# FIXME should be tree.last_revision
2940
rev_id = tree.last_revision()
1715
rev_id = tree.branch.last_revision()
2941
1716
elif len(revision) != 1:
2942
raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
1717
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
1719
tree, file_list = tree_files(file_list)
2944
1720
rev_id = revision[0].in_history(tree.branch).rev_id
2945
pb = ui.ui_factory.nested_progress_bar()
2947
tree.revert(file_list,
2948
tree.branch.repository.revision_tree(rev_id),
2949
not no_backup, pb, report_changes=True)
1721
tree.revert(file_list, tree.branch.revision_tree(rev_id),
2954
1725
class cmd_assert_fail(Command):
2955
1726
"""Test reporting of assertion failures"""
2956
# intended just for use in testing
2961
raise AssertionError("always fails")
1729
assert False, "always fails"
2964
1732
class cmd_help(Command):
2965
1733
"""Show help on a command or other topic.
2968
_see_also = ['topics']
2970
Option('long', 'Show help on all commands.'),
1735
For a list of all available commands, say 'bzr help commands'."""
1736
takes_options = ['long']
2972
1737
takes_args = ['topic?']
2973
aliases = ['?', '--help', '-?', '-h']
2975
1740
@display_command
2976
1741
def run(self, topic=None, long=False):
2978
1743
if topic is None and long:
2979
1744
topic = "commands"
2980
bzrlib.help.help(topic)
2983
1748
class cmd_shell_complete(Command):
2984
1749
"""Show appropriate completions for context.
2986
For a list of all available commands, say 'bzr shell-complete'.
1751
For a list of all available commands, say 'bzr shell-complete'."""
2988
1752
takes_args = ['context?']
2989
1753
aliases = ['s-c']
2998
1762
class cmd_fetch(Command):
2999
1763
"""Copy in history from another branch but don't merge it.
3001
This is an internal method used for pull and merge.
1765
This is an internal method used for pull and merge."""
3004
1767
takes_args = ['from_branch', 'to_branch']
3005
1768
def run(self, from_branch, to_branch):
3006
1769
from bzrlib.fetch import Fetcher
1770
from bzrlib.branch import Branch
3007
1771
from_b = Branch.open(from_branch)
3008
1772
to_b = Branch.open(to_branch)
3009
Fetcher(to_b, from_b)
1777
Fetcher(to_b, from_b)
3012
1784
class cmd_missing(Command):
3013
1785
"""Show unmerged/unpulled revisions between two branches.
3015
OTHER_BRANCH may be local or remote.
3018
_see_also = ['merge', 'pull']
1787
OTHER_BRANCH may be local or remote."""
3019
1788
takes_args = ['other_branch?']
3021
Option('reverse', 'Reverse the order of revisions.'),
3023
'Display changes in the local branch only.'),
3024
Option('this' , 'Same as --mine-only.'),
3025
Option('theirs-only',
3026
'Display changes in the remote branch only.'),
3027
Option('other', 'Same as --theirs-only.'),
3032
encoding_type = 'replace'
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'),
3035
1801
def run(self, other_branch=None, reverse=False, mine_only=False,
3036
theirs_only=False, log_format=None, long=False, short=False, line=False,
3037
show_ids=False, verbose=False, this=False, other=False):
3038
from bzrlib.missing import find_unmerged, iter_log_revisions
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
3039
1805
from bzrlib.log import log_formatter
3046
local_branch = Branch.open_containing(u".")[0]
1806
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
3047
1807
parent = local_branch.get_parent()
3048
1808
if other_branch is None:
3049
1809
other_branch = parent
3050
1810
if other_branch is None:
3051
raise errors.BzrCommandError("No peer location known"
3053
display_url = urlutils.unescape_for_display(parent,
3055
self.outf.write("Using last location: " + display_url + '\n')
3057
remote_branch = Branch.open(other_branch)
3058
if remote_branch.base == local_branch.base:
3059
remote_branch = local_branch
3060
local_branch.lock_read()
3062
remote_branch.lock_read()
3064
local_extra, remote_extra = find_unmerged(local_branch,
3066
if log_format is None:
3067
registry = log.log_formatter_registry
3068
log_format = registry.get_default(local_branch)
3069
lf = log_format(to_file=self.outf,
3071
show_timezone='original')
3072
if reverse is False:
3073
local_extra.reverse()
3074
remote_extra.reverse()
3075
if local_extra and not theirs_only:
3076
self.outf.write("You have %d extra revision(s):\n" %
3078
for revision in iter_log_revisions(local_extra,
3079
local_branch.repository,
3081
lf.log_revision(revision)
3082
printed_local = True
3084
printed_local = False
3085
if remote_extra and not mine_only:
3086
if printed_local is True:
3087
self.outf.write("\n\n\n")
3088
self.outf.write("You are missing %d revision(s):\n" %
3090
for revision in iter_log_revisions(remote_extra,
3091
remote_branch.repository,
3093
lf.log_revision(revision)
3094
if not remote_extra and not local_extra:
3096
self.outf.write("Branches are up to date.\n")
3100
remote_branch.unlock()
3102
local_branch.unlock()
3103
if not status_code and parent is None and other_branch is not None:
3104
local_branch.lock_write()
3106
# handle race conditions - a parent might be set while we run.
3107
if local_branch.get_parent() is None:
3108
local_branch.set_parent(remote_branch.base)
3110
local_branch.unlock()
1811
raise BzrCommandError("No missing location known or specified.")
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)
3111
1842
return status_code
3114
class cmd_pack(Command):
3115
"""Compress the data within a repository."""
3117
_see_also = ['repositories']
3118
takes_args = ['branch_or_repo?']
3120
def run(self, branch_or_repo='.'):
3121
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3123
branch = dir.open_branch()
3124
repository = branch.repository
3125
except errors.NotBranchError:
3126
repository = dir.open_repository()
3130
1845
class cmd_plugins(Command):
3131
1846
"""List plugins"""
3256
1951
if to_revid is None:
3257
1952
to_revno = b.revno()
3258
1953
if from_revno is None or to_revno is None:
3259
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
1954
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
3260
1955
for revno in range(from_revno, to_revno + 1):
3261
b.repository.sign_revision(b.get_rev_id(revno),
3264
raise errors.BzrCommandError('Please supply either one revision, or a range.')
3267
class cmd_bind(Command):
3268
"""Convert the current branch into a checkout of the supplied branch.
3270
Once converted into a checkout, commits must succeed on the master branch
3271
before they will be applied to the local branch.
3274
_see_also = ['checkouts', 'unbind']
3275
takes_args = ['location?']
3278
def run(self, location=None):
3279
b, relpath = Branch.open_containing(u'.')
3280
if location is None:
3282
location = b.get_old_bound_location()
3283
except errors.UpgradeRequired:
3284
raise errors.BzrCommandError('No location supplied. '
3285
'This format does not remember old locations.')
3287
if location is None:
3288
raise errors.BzrCommandError('No location supplied and no '
3289
'previous location known')
3290
b_other = Branch.open(location)
3293
except errors.DivergedBranches:
3294
raise errors.BzrCommandError('These branches have diverged.'
3295
' Try merging, and then bind again.')
3298
class cmd_unbind(Command):
3299
"""Convert the current checkout into a regular branch.
3301
After unbinding, the local branch is considered independent and subsequent
3302
commits will be local only.
3305
_see_also = ['checkouts', 'bind']
3310
b, relpath = Branch.open_containing(u'.')
3312
raise errors.BzrCommandError('Local branch is not bound')
3315
class cmd_uncommit(Command):
1956
b.sign_revision(b.get_rev_id(revno), gpg_strategy)
1958
raise BzrCommandError('Please supply either one revision, or a range.')
1961
class cmd_uncommit(bzrlib.commands.Command):
3316
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
3318
1968
--verbose will print out what is being removed.
3319
1969
--dry-run will go through all the motions, but not actually
3320
1970
remove anything.
3322
In the future, uncommit will create a revision bundle, which can then
1972
In the future, uncommit will create a changeset, which can then
3326
# TODO: jam 20060108 Add an option to allow uncommit to remove
3327
# unreferenced information in 'branch-as-repository' branches.
3328
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
3329
# information in shared branches as well.
3330
_see_also = ['commit']
3331
takes_options = ['verbose', 'revision',
3332
Option('dry-run', help='Don\'t actually make changes.'),
1975
takes_options = ['all', 'verbose', 'revision',
1976
Option('dry-run', help='Don\'t actually make changes'),
3333
1977
Option('force', help='Say yes to all questions.')]
3334
1978
takes_args = ['location?']
3337
def run(self, location=None,
1981
def run(self, location=None, all=False,
3338
1982
dry_run=False, verbose=False,
3339
1983
revision=None, force=False):
3340
from bzrlib.log import log_formatter, show_log
1984
from bzrlib.branch import Branch
1985
from bzrlib.log import log_formatter
3342
1987
from bzrlib.uncommit import uncommit
3344
1989
if location is None:
3345
1990
location = u'.'
3346
control, relpath = bzrdir.BzrDir.open_containing(location)
3348
tree = control.open_workingtree()
3350
except (errors.NoWorkingTree, errors.NotLocalUrl):
3352
b = control.open_branch()
1991
b, relpath = Branch.open_containing(location)
3355
1993
if revision is None:
3356
1994
revno = b.revno()
1995
rev_id = b.last_revision()
3358
# 'bzr uncommit -r 10' actually means uncommit
3359
# so that the final tree is at revno 10.
3360
# but bzrlib.uncommit.uncommit() actually uncommits
3361
# the revisions that are supplied.
3362
# So we need to offset it by one
3363
revno = revision[0].in_history(b).revno+1
3365
if revno <= b.revno():
3366
rev_id = b.get_rev_id(revno)
1997
revno, rev_id = revision[0].in_history(b)
3367
1998
if rev_id is None:
3368
self.outf.write('No revisions to uncommit.\n')
3371
lf = log_formatter('short',
3373
show_timezone='original')
3378
direction='forward',
3379
start_revision=revno,
3380
end_revision=b.revno())
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)
3383
2007
print 'Dry-run, pretending to remove the above revisions.'
3391
2015
print 'Canceled'
3394
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
2018
uncommit(b, remove_files=all,
2019
dry_run=dry_run, verbose=verbose,
3398
class cmd_break_lock(Command):
3399
"""Break a dead lock on a repository, branch or working directory.
3401
CAUTION: Locks should only be broken when you are sure that the process
3402
holding the lock has been stopped.
3404
You can get information on what locks are open via the 'bzr info' command.
3409
takes_args = ['location?']
3411
def run(self, location=None, show=False):
3412
if location is None:
3414
control, relpath = bzrdir.BzrDir.open_containing(location)
3416
control.break_lock()
3417
except NotImplementedError:
3421
class cmd_wait_until_signalled(Command):
3422
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3424
This just prints a line to signal when it is ready, then blocks on stdin.
3430
sys.stdout.write("running\n")
3432
sys.stdin.readline()
3435
class cmd_serve(Command):
3436
"""Run the bzr server."""
3438
aliases = ['server']
3442
help='Serve on stdin/out for use from inetd or sshd.'),
3444
help='Listen for connections on nominated port of the form '
3445
'[hostname:]portnumber. Passing 0 as the port number will '
3446
'result in a dynamically allocated port. The default port is '
3450
help='Serve contents of this directory.',
3452
Option('allow-writes',
3453
help='By default the server is a readonly server. Supplying '
3454
'--allow-writes enables write access to the contents of '
3455
'the served directory and below.'
3459
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3460
from bzrlib.smart import medium, server
3461
from bzrlib.transport import get_transport
3462
from bzrlib.transport.chroot import ChrootServer
3463
from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3464
if directory is None:
3465
directory = os.getcwd()
3466
url = urlutils.local_path_to_url(directory)
3467
if not allow_writes:
3468
url = 'readonly+' + url
3469
chroot_server = ChrootServer(get_transport(url))
3470
chroot_server.setUp()
3471
t = get_transport(chroot_server.get_url())
3473
smart_server = medium.SmartServerPipeStreamMedium(
3474
sys.stdin, sys.stdout, t)
3476
host = BZR_DEFAULT_INTERFACE
3478
port = BZR_DEFAULT_PORT
3481
host, port = port.split(':')
3483
smart_server = server.SmartTCPServer(t, host=host, port=port)
3484
print 'listening on port: ', smart_server.port
3486
# for the duration of this server, no UI output is permitted.
3487
# note that this may cause problems with blackbox tests. This should
3488
# be changed with care though, as we dont want to use bandwidth sending
3489
# progress over stderr to smart server clients!
3490
old_factory = ui.ui_factory
3492
ui.ui_factory = ui.SilentUIFactory()
3493
smart_server.serve()
3495
ui.ui_factory = old_factory
3498
class cmd_join(Command):
3499
"""Combine a subtree into its containing tree.
3501
This command is for experimental use only. It requires the target tree
3502
to be in dirstate-with-subtree format, which cannot be converted into
3505
The TREE argument should be an independent tree, inside another tree, but
3506
not part of it. (Such trees can be produced by "bzr split", but also by
3507
running "bzr branch" with the target inside a tree.)
3509
The result is a combined tree, with the subtree no longer an independant
3510
part. This is marked as a merge of the subtree into the containing tree,
3511
and all history is preserved.
3513
If --reference is specified, the subtree retains its independence. It can
3514
be branched by itself, and can be part of multiple projects at the same
3515
time. But operations performed in the containing tree, such as commit
3516
and merge, will recurse into the subtree.
3519
_see_also = ['split']
3520
takes_args = ['tree']
3522
Option('reference', help='Join by reference.'),
3526
def run(self, tree, reference=False):
3527
sub_tree = WorkingTree.open(tree)
3528
parent_dir = osutils.dirname(sub_tree.basedir)
3529
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3530
repo = containing_tree.branch.repository
3531
if not repo.supports_rich_root():
3532
raise errors.BzrCommandError(
3533
"Can't join trees because %s doesn't support rich root data.\n"
3534
"You can use bzr upgrade on the repository."
3538
containing_tree.add_reference(sub_tree)
3539
except errors.BadReferenceTarget, e:
3540
# XXX: Would be better to just raise a nicely printable
3541
# exception from the real origin. Also below. mbp 20070306
3542
raise errors.BzrCommandError("Cannot join %s. %s" %
3546
containing_tree.subsume(sub_tree)
3547
except errors.BadSubsumeSource, e:
3548
raise errors.BzrCommandError("Cannot join %s. %s" %
3552
class cmd_split(Command):
3553
"""Split a tree into two trees.
3555
This command is for experimental use only. It requires the target tree
3556
to be in dirstate-with-subtree format, which cannot be converted into
3559
The TREE argument should be a subdirectory of a working tree. That
3560
subdirectory will be converted into an independent tree, with its own
3561
branch. Commits in the top-level tree will not apply to the new subtree.
3562
If you want that behavior, do "bzr join --reference TREE".
3565
_see_also = ['join']
3566
takes_args = ['tree']
3570
def run(self, tree):
3571
containing_tree, subdir = WorkingTree.open_containing(tree)
3572
sub_id = containing_tree.path2id(subdir)
3574
raise errors.NotVersionedError(subdir)
3576
containing_tree.extract(sub_id)
3577
except errors.RootNotRich:
3578
raise errors.UpgradeRequired(containing_tree.branch.base)
3582
class cmd_merge_directive(Command):
3583
"""Generate a merge directive for auto-merge tools.
3585
A directive requests a merge to be performed, and also provides all the
3586
information necessary to do so. This means it must either include a
3587
revision bundle, or the location of a branch containing the desired
3590
A submit branch (the location to merge into) must be supplied the first
3591
time the command is issued. After it has been supplied once, it will
3592
be remembered as the default.
3594
A public branch is optional if a revision bundle is supplied, but required
3595
if --diff or --plain is specified. It will be remembered as the default
3596
after the first use.
3599
takes_args = ['submit_branch?', 'public_branch?']
3602
RegistryOption.from_kwargs('patch-type',
3603
'The type of patch to include in the directive',
3605
value_switches=True,
3607
bundle='Bazaar revision bundle (default).',
3608
diff='Normal unified diff.',
3609
plain='No patch, just directive.'),
3610
Option('sign', help='GPG-sign the directive.'), 'revision',
3611
Option('mail-to', type=str,
3612
help='Instead of printing the directive, email to this address.'),
3613
Option('message', type=str, short_name='m',
3614
help='Message to use when committing this merge.')
3617
encoding_type = 'exact'
3619
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3620
sign=False, revision=None, mail_to=None, message=None):
3621
from bzrlib.revision import ensure_null, NULL_REVISION
3622
if patch_type == 'plain':
3624
branch = Branch.open('.')
3625
stored_submit_branch = branch.get_submit_branch()
3626
if submit_branch is None:
3627
submit_branch = stored_submit_branch
3629
if stored_submit_branch is None:
3630
branch.set_submit_branch(submit_branch)
3631
if submit_branch is None:
3632
submit_branch = branch.get_parent()
3633
if submit_branch is None:
3634
raise errors.BzrCommandError('No submit branch specified or known')
3636
stored_public_branch = branch.get_public_branch()
3637
if public_branch is None:
3638
public_branch = stored_public_branch
3639
elif stored_public_branch is None:
3640
branch.set_public_branch(public_branch)
3641
if patch_type != "bundle" and public_branch is None:
3642
raise errors.BzrCommandError('No public branch specified or'
3644
if revision is not None:
3645
if len(revision) != 1:
3646
raise errors.BzrCommandError('bzr merge-directive takes '
3647
'exactly one revision identifier')
3649
revision_id = revision[0].in_history(branch).rev_id
3651
revision_id = branch.last_revision()
3652
revision_id = ensure_null(revision_id)
3653
if revision_id == NULL_REVISION:
3654
raise errors.BzrCommandError('No revisions to bundle.')
3655
directive = merge_directive.MergeDirective.from_objects(
3656
branch.repository, revision_id, time.time(),
3657
osutils.local_time_offset(), submit_branch,
3658
public_branch=public_branch, patch_type=patch_type,
3662
self.outf.write(directive.to_signed(branch))
3664
self.outf.writelines(directive.to_lines())
3666
message = directive.to_email(mail_to, branch, sign)
3667
s = SMTPConnection(branch.get_config())
3668
s.send_email(message)
3671
class cmd_tag(Command):
3672
"""Create a tag naming a revision.
3674
Tags give human-meaningful names to revisions. Commands that take a -r
3675
(--revision) option can be given -rtag:X, where X is any previously
3678
Tags are stored in the branch. Tags are copied from one branch to another
3679
along when you branch, push, pull or merge.
3681
It is an error to give a tag name that already exists unless you pass
3682
--force, in which case the tag is moved to point to the new revision.
3685
_see_also = ['commit', 'tags']
3686
takes_args = ['tag_name']
3689
help='Delete this tag rather than placing it.',
3692
help='Branch in which to place the tag.',
3697
help='Replace existing tags.',
3702
def run(self, tag_name,
3708
branch, relpath = Branch.open_containing(directory)
3712
branch.tags.delete_tag(tag_name)
3713
self.outf.write('Deleted tag %s.\n' % tag_name)
3716
if len(revision) != 1:
3717
raise errors.BzrCommandError(
3718
"Tags can only be placed on a single revision, "
3720
revision_id = revision[0].in_history(branch).rev_id
3722
revision_id = branch.last_revision()
3723
if (not force) and branch.tags.has_tag(tag_name):
3724
raise errors.TagAlreadyExists(tag_name)
3725
branch.tags.set_tag(tag_name, revision_id)
3726
self.outf.write('Created tag %s.\n' % tag_name)
3731
class cmd_tags(Command):
3734
This tag shows a table of tag names and the revisions they reference.
3740
help='Branch whose tags should be displayed.',
3750
branch, relpath = Branch.open_containing(directory)
3751
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3752
self.outf.write('%-20s %s\n' % (tag_name, target))
3755
# command-line interpretation helper for merge-related commands
3756
def _merge_helper(other_revision, base_revision, possible_transports=None,
3757
check_clean=True, ignore_zero=False,
3758
this_dir=None, backup_files=False,
3760
file_list=None, show_base=False, reprocess=False,
3763
change_reporter=None,
3765
"""Merge changes into a tree.
3768
list(path, revno) Base for three-way merge.
3769
If [None, None] then a base will be automatically determined.
3771
list(path, revno) Other revision for three-way merge.
3773
Directory to merge changes into; '.' by default.
3775
If true, this_dir must have no uncommitted changes before the
3777
ignore_zero - If true, suppress the "zero conflicts" message when
3778
there are no conflicts; should be set when doing something we expect
3779
to complete perfectly.
3780
file_list - If supplied, merge only changes to selected files.
3782
All available ancestors of other_revision and base_revision are
3783
automatically pulled into the branch.
3785
The revno may be -1 to indicate the last revision on the branch, which is
3788
This function is intended for use from the command line; programmatic
3789
clients might prefer to call merge.merge_inner(), which has less magic
3792
# Loading it late, so that we don't always have to import bzrlib.merge
3793
if merge_type is None:
3794
merge_type = _mod_merge.Merge3Merger
3795
if this_dir is None:
3797
this_tree = WorkingTree.open_containing(this_dir)[0]
3798
if show_base and not merge_type is _mod_merge.Merge3Merger:
3799
raise errors.BzrCommandError("Show-base is not supported for this merge"
3800
" type. %s" % merge_type)
3801
if reprocess and not merge_type.supports_reprocess:
3802
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3803
" type %s." % merge_type)
3804
if reprocess and show_base:
3805
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3806
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3807
# only want to take out a lock_tree_write() if we don't have to pull
3808
# any ancestry. But merge might fetch ancestry in the middle, in
3809
# which case we would need a lock_write().
3810
# Because we cannot upgrade locks, for now we live with the fact that
3811
# the tree will be locked multiple times during a merge. (Maybe
3812
# read-only some of the time, but it means things will get read
3815
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3816
pb=pb, change_reporter=change_reporter)
3817
merger.pp = ProgressPhase("Merge phase", 5, pb)
3818
merger.pp.next_phase()
3819
merger.check_basis(check_clean)
3820
if other_rev_id is not None:
3821
merger.set_other_revision(other_rev_id, this_tree.branch)
3823
merger.set_other(other_revision, possible_transports)
3824
merger.pp.next_phase()
3825
merger.set_base(base_revision)
3826
if merger.base_rev_id == merger.other_rev_id:
3827
note('Nothing to do.')
3829
if file_list is None:
3830
if pull and merger.base_rev_id == merger.this_rev_id:
3831
# FIXME: deduplicate with pull
3832
result = merger.this_tree.pull(merger.this_branch,
3833
False, merger.other_rev_id)
3834
if result.old_revid == result.new_revid:
3835
note('No revisions to pull.')
3837
note('Now on revision %d.' % result.new_revno)
3839
merger.backup_files = backup_files
3840
merger.merge_type = merge_type
3841
merger.set_interesting_files(file_list)
3842
merger.show_base = show_base
3843
merger.reprocess = reprocess
3844
conflicts = merger.do_merge()
3845
if file_list is None:
3846
merger.set_pending()
3852
def _create_prefix(cur_transport):
3853
needed = [cur_transport]
3854
# Recurse upwards until we can create a directory successfully
3856
new_transport = cur_transport.clone('..')
3857
if new_transport.base == cur_transport.base:
3858
raise errors.BzrCommandError(
3859
"Failed to create path prefix for %s."
3860
% cur_transport.base)
3862
new_transport.mkdir('.')
3863
except errors.NoSuchFile:
3864
needed.append(new_transport)
3865
cur_transport = new_transport
3868
# Now we only need to create child directories
3870
cur_transport = needed.pop()
3871
cur_transport.ensure_base()
3875
merge = _merge_helper
3878
2023
# these get imported and then picked up by the scan for cmd_*
3879
2024
# TODO: Some more consistent way to split command definitions across files;
3880
2025
# we do need to load at least some information about them to know of
3881
# aliases. ideally we would avoid loading the implementation until the
3882
# details were needed.
3883
from bzrlib.cmd_version_info import cmd_version_info
3884
2027
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
3885
from bzrlib.bundle.commands import cmd_bundle_revisions
3886
from bzrlib.sign_my_commits import cmd_sign_my_commits
3887
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
3888
cmd_weave_plan_merge, cmd_weave_merge_text