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"""
20
from StringIO import StringIO
22
from bzrlib.lazy_import import lazy_import
23
lazy_import(globals(), """
22
from shutil import rmtree
55
27
from bzrlib.branch import Branch
56
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
57
from bzrlib.conflicts import ConflictList
28
import bzrlib.bzrdir as bzrdir
29
from bzrlib.commands import Command, display_command
58
30
from bzrlib.revision import common_ancestor
31
import bzrlib.errors as errors
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
33
NotBranchError, DivergedBranches, NotConflicted,
34
NoSuchFile, NoWorkingTree, FileInWrongBranch)
35
from bzrlib.log import show_one_log
36
from bzrlib.merge import Merge3Merger
37
from bzrlib.option import Option
59
38
from bzrlib.revisionspec import RevisionSpec
40
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
41
from bzrlib.transport.local import LocalTransport
60
42
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
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
342
216
Adding a file whose parent directory is not versioned will
343
217
implicitly add the parent, and so on up to the root. This means
344
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
345
219
get added when you add a file in the directory.
347
221
--dry-run will show which files would be added, but not actually
350
--file-ids-from will try to use the file ids from the supplied path.
351
It looks up ids trying to find a matching parent directory with the
352
same filename, and then by pure path. This option is rarely needed
353
but can be useful when adding the same logical file into two
354
branches that will be merged later (without showing the two different
355
adds as a conflict). It is also useful when merging another project
356
into a subdirectory of this one.
358
224
takes_args = ['file*']
359
takes_options = ['no-recurse', 'dry-run', 'verbose',
360
Option('file-ids-from', type=unicode,
361
help='Lookup file ids from here')]
362
encoding_type = 'replace'
363
_see_also = ['remove']
225
takes_options = ['no-recurse', 'dry-run', 'verbose']
365
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):
367
228
import bzrlib.add
370
if file_ids_from is not None:
372
base_tree, base_path = WorkingTree.open_containing(
374
except errors.NoWorkingTree:
375
base_branch, base_path = Branch.open_containing(
377
base_tree = base_branch.basis_tree()
379
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
380
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
382
action = bzrlib.add.AddAction(to_file=self.outf,
383
should_print=(not is_quiet()))
239
action = bzrlib.add.add_action_add_and_print
386
base_tree.lock_read()
388
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
389
action=action, save=not dry_run)
391
if base_tree is not None:
241
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
393
243
if len(ignored) > 0:
395
for glob in sorted(ignored.keys()):
244
for glob in sorted(ignored.keys()):
245
match_len = len(ignored[glob])
396
247
for path in ignored[glob]:
397
self.outf.write("ignored %s matching \"%s\"\n"
401
for glob, paths in ignored.items():
402
match_len += len(paths)
403
self.outf.write("ignored %d file(s).\n" % match_len)
404
self.outf.write("If you wish to add some of these files,"
405
" 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"\
408
256
class cmd_mkdir(Command):
411
259
This is equivalent to creating the directory and then adding it.
414
261
takes_args = ['dir+']
415
encoding_type = 'replace'
417
263
def run(self, dir_list):
418
264
for d in dir_list:
420
266
wt, dd = WorkingTree.open_containing(d)
422
self.outf.write('added %s\n' % d)
425
271
class cmd_relpath(Command):
426
272
"""Show path of a file relative to root"""
428
273
takes_args = ['filename']
432
277
def run(self, filename):
433
# TODO: jam 20050106 Can relpath return a munged path if
434
# sys.stdout encoding cannot represent it?
435
278
tree, relpath = WorkingTree.open_containing(filename)
436
self.outf.write(relpath)
437
self.outf.write('\n')
440
282
class cmd_inventory(Command):
441
283
"""Show inventory of the current working copy or a revision.
443
285
It is possible to limit the output to a particular entry
444
type using the --kind option. For example: --kind file.
446
It is also possible to restrict the list of files to a specific
447
set. For example: bzr inventory --show-ids this/file
286
type using the --kind option. For example; --kind file.
452
288
takes_options = ['revision', 'show-ids', 'kind']
453
takes_args = ['file*']
456
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
291
def run(self, revision=None, show_ids=False, kind=None):
457
292
if kind and kind not in ['file', 'directory', 'symlink']:
458
raise errors.BzrCommandError('invalid kind specified')
460
work_tree, file_list = tree_files(file_list)
461
work_tree.lock_read()
463
if revision is not None:
464
if len(revision) > 1:
465
raise errors.BzrCommandError(
466
'bzr inventory --revision takes exactly one revision'
468
revision_id = revision[0].in_history(work_tree.branch).rev_id
469
tree = work_tree.branch.repository.revision_tree(revision_id)
471
extra_trees = [work_tree]
477
if file_list is not None:
478
file_ids = tree.paths2ids(file_list, trees=extra_trees,
479
require_versioned=True)
480
# find_ids_across_trees may include some paths that don't
482
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
483
for file_id in file_ids if file_id in tree)
485
entries = tree.inventory.entries()
488
if tree is not work_tree:
491
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.repository.get_revision_inventory(
302
revision[0].in_history(tree.branch).rev_id)
304
for path, entry in inv.entries():
492
305
if kind and kind != entry.kind:
495
self.outf.write('%-50s %s\n' % (path, entry.file_id))
308
print '%-50s %s' % (path, entry.file_id)
497
self.outf.write(path)
498
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)
501
349
class cmd_mv(Command):
508
356
If the last argument is a versioned directory, all the other names
509
357
are moved into it. Otherwise, there must be exactly two arguments
510
and the file is changed to a new name.
512
If OLDNAME does not exist on the filesystem but is versioned and
513
NEWNAME does exist on the filesystem but is not versioned, mv
514
assumes that the file has been manually moved and only updates
515
its internal inventory to reflect that change.
516
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.
518
360
Files cannot be moved between branches.
521
362
takes_args = ['names*']
522
takes_options = [Option("after", help="move only the bzr identifier"
523
" of the file (file has already been moved). Use this flag if"
524
" bzr is not able to detect this itself.")]
525
aliases = ['move', 'rename']
526
encoding_type = 'replace'
528
def run(self, names_list, after=False):
529
if names_list is None:
363
def run(self, names_list):
532
364
if len(names_list) < 2:
533
raise errors.BzrCommandError("missing file argument")
365
raise BzrCommandError("missing file argument")
534
366
tree, rel_names = tree_files(names_list)
536
368
if os.path.isdir(names_list[-1]):
537
369
# move into existing directory
538
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
539
self.outf.write("%s => %s\n" % pair)
370
for pair in tree.move(rel_names[:-1], rel_names[-1]):
371
print "%s => %s" % pair
541
373
if len(names_list) != 2:
542
raise errors.BzrCommandError('to mv multiple files the'
543
' destination must be a versioned'
545
tree.rename_one(rel_names[0], rel_names[1], after=after)
546
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])
549
380
class cmd_pull(Command):
550
"""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.
552
387
This command only works on branches that have not diverged. Branches are
553
considered diverged if the destination branch's most recent commit is one
554
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.
556
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
557
392
from one into the other. Once one branch has merged, the other should
558
393
be able to pull it again.
560
395
If you want to forget your local changes and just update your branch to
561
match the remote one, use pull --overwrite.
563
If there is no default location set, the first pull will set it. After
564
that, you can omit the location to use the default. To change the
565
default, use --remember. The value will only be saved if the remote
566
location can be accessed.
396
match the remote one, use --overwrite.
569
_see_also = ['push', 'update']
570
takes_options = ['remember', 'overwrite', 'revision', 'verbose',
572
help='branch to pull into, '
573
'rather than the one containing the working directory',
398
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
578
399
takes_args = ['location?']
579
encoding_type = 'replace'
581
def run(self, location=None, remember=False, overwrite=False,
582
revision=None, verbose=False,
584
from bzrlib.tag import _merge_tags_if_possible
585
# FIXME: too much stuff is in the command class
588
if directory is None:
591
tree_to = WorkingTree.open_containing(directory)[0]
592
branch_to = tree_to.branch
593
except errors.NoWorkingTree:
595
branch_to = Branch.open_containing(directory)[0]
598
if location is not None:
600
mergeable = bundle.read_mergeable_from_url(
602
except errors.NotABundle:
603
pass # Continue on considering this url a Branch
605
stored_loc = branch_to.get_parent()
401
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
402
# FIXME: too much stuff is in the command class
403
tree_to = WorkingTree.open_containing(u'.')[0]
404
stored_loc = tree_to.branch.get_parent()
606
405
if location is None:
607
406
if stored_loc is None:
608
raise errors.BzrCommandError("No pull location known or"
407
raise BzrCommandError("No pull location known or specified.")
611
display_url = urlutils.unescape_for_display(stored_loc,
613
self.outf.write("Using saved location: %s\n" % display_url)
409
print "Using saved location: %s" % stored_loc
614
410
location = stored_loc
616
if mergeable is not None:
617
if revision is not None:
618
raise errors.BzrCommandError(
619
'Cannot use -r with merge directives or bundles')
620
revision_id = mergeable.install_revisions(branch_to.repository)
621
branch_from = branch_to
623
branch_from = Branch.open(location)
625
if branch_to.get_parent() is None or remember:
626
branch_to.set_parent(branch_from.base)
628
if revision is not None:
629
if len(revision) == 1:
630
revision_id = revision[0].in_history(branch_from).rev_id
632
raise errors.BzrCommandError(
633
'bzr pull --revision takes one value.')
635
old_rh = branch_to.revision_history()
636
if tree_to is not None:
637
result = tree_to.pull(branch_from, overwrite, revision_id,
638
delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
640
result = branch_to.pull(branch_from, overwrite, revision_id)
642
result.report(self.outf)
412
br_from = Branch.open(location)
413
br_to = tree_to.branch
417
elif len(revision) == 1:
418
rev_id = revision[0].in_history(br_from).rev_id
420
raise BzrCommandError('bzr pull --revision takes one value.')
422
old_rh = br_to.revision_history()
423
count = tree_to.pull(br_from, overwrite, rev_id)
425
if br_to.get_parent() is None or remember:
426
br_to.set_parent(location)
427
note('%d revision(s) pulled.' % (count,))
644
from bzrlib.log import show_changed_revisions
645
new_rh = branch_to.revision_history()
646
show_changed_revisions(branch_to, old_rh, new_rh,
430
new_rh = tree_to.branch.revision_history()
433
from bzrlib.log import show_changed_revisions
434
show_changed_revisions(tree_to.branch, old_rh, new_rh)
650
437
class cmd_push(Command):
651
"""Update a mirror of this branch.
653
The target branch will not have its working tree populated because this
654
is both expensive, and is not supported on remote file systems.
656
Some smart servers or protocols *may* put the working tree in place in
438
"""Push this branch into another branch.
440
The remote branch will not have its working tree populated because this
441
is both expensive, and may not be supported on the remote file system.
443
Some smart servers or protocols *may* put the working tree in place.
445
If there is no default push location set, the first push will set it.
446
After that, you can omit the location to use the default. To change the
447
default, use --remember.
659
449
This command only works on branches that have not diverged. Branches are
660
considered diverged if the destination branch's most recent commit is one
661
that has not been merged (directly or indirectly) by the source branch.
450
considered diverged if the branch being pushed to is not an older version
663
453
If branches have diverged, you can use 'bzr push --overwrite' to replace
664
the other branch completely, discarding its unmerged changes.
454
the other branch completely.
666
456
If you want to ensure you have the different changes in the other branch,
667
do a merge (see bzr help merge) from the other branch, and commit that.
668
After that you will be able to do a push without '--overwrite'.
670
If there is no default push location set, the first push will set it.
671
After that, you can omit the location to use the default. To change the
672
default, use --remember. The value will only be saved if the remote
673
location can be accessed.
457
do a merge (see bzr help merge) from the other branch, and commit that
458
before doing a 'push --overwrite'.
676
_see_also = ['pull', 'update', 'working-trees']
677
takes_options = ['remember', 'overwrite', 'verbose',
678
Option('create-prefix',
679
help='Create the path leading up to the branch '
680
'if it does not already exist'),
682
help='branch to push from, '
683
'rather than the one containing the working directory',
687
Option('use-existing-dir',
688
help='By default push will fail if the target'
689
' directory exists, but does not already'
690
' have a control directory. This flag will'
691
' allow push to proceed.'),
460
takes_options = ['remember', 'overwrite',
461
Option('create-prefix',
462
help='Create the path leading up to the branch '
463
'if it does not already exist')]
693
464
takes_args = ['location?']
694
encoding_type = 'replace'
696
466
def run(self, location=None, remember=False, overwrite=False,
697
create_prefix=False, verbose=False,
698
use_existing_dir=False,
467
create_prefix=False, verbose=False):
700
468
# FIXME: Way too big! Put this into a function called from the
702
if directory is None:
704
br_from = Branch.open_containing(directory)[0]
705
stored_loc = br_from.get_push_location()
470
from bzrlib.transport import get_transport
472
tree_from = WorkingTree.open_containing(u'.')[0]
473
br_from = tree_from.branch
474
stored_loc = tree_from.branch.get_push_location()
706
475
if location is None:
707
476
if stored_loc is None:
708
raise errors.BzrCommandError("No push location known or specified.")
477
raise BzrCommandError("No push location known or specified.")
710
display_url = urlutils.unescape_for_display(stored_loc,
712
self.outf.write("Using saved location: %s\n" % display_url)
479
print "Using saved location: %s" % stored_loc
713
480
location = stored_loc
715
to_transport = transport.get_transport(location)
717
br_to = repository_to = dir_to = None
719
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
720
except errors.NotBranchError:
721
pass # Didn't find anything
723
# If we can open a branch, use its direct repository, otherwise see
724
# if there is a repository without a branch.
726
br_to = dir_to.open_branch()
727
except errors.NotBranchError:
728
# Didn't find a branch, can we find a repository?
730
repository_to = dir_to.find_repository()
731
except errors.NoRepositoryPresent:
734
# Found a branch, so we must have found a repository
735
repository_to = br_to.repository
739
# The destination doesn't exist; create it.
740
# XXX: Refactor the create_prefix/no_create_prefix code into a
741
# common helper function
743
to_transport.mkdir('.')
744
except errors.FileExists:
745
if not use_existing_dir:
746
raise errors.BzrCommandError("Target directory %s"
747
" already exists, but does not have a valid .bzr"
748
" directory. Supply --use-existing-dir to push"
749
" there anyway." % location)
750
except errors.NoSuchFile:
751
if not create_prefix:
752
raise errors.BzrCommandError("Parent directory of %s"
754
"\nYou may supply --create-prefix to create all"
755
" leading parent directories."
758
_create_prefix(to_transport)
760
# Now the target directory exists, but doesn't have a .bzr
761
# directory. So we need to create it, along with any work to create
762
# all of the dependent branches, etc.
763
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
764
revision_id=br_from.last_revision())
765
br_to = dir_to.open_branch()
766
# TODO: Some more useful message about what was copied
767
note('Created new branch.')
768
# We successfully created the target, remember it
769
if br_from.get_push_location() is None or remember:
770
br_from.set_push_location(br_to.base)
771
elif repository_to is None:
772
# we have a bzrdir but no branch or repository
773
# XXX: Figure out what to do other than complain.
774
raise errors.BzrCommandError("At %s you have a valid .bzr control"
775
" directory, but not a branch or repository. This is an"
776
" unsupported configuration. Please move the target directory"
777
" out of the way and try again."
780
# We have a repository but no branch, copy the revisions, and then
482
br_to = Branch.open(location)
483
except NotBranchError:
781
484
# create a branch.
782
last_revision_id = br_from.last_revision()
783
repository_to.fetch(br_from.repository,
784
revision_id=last_revision_id)
785
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
786
note('Created new branch.')
787
if br_from.get_push_location() is None or remember:
788
br_from.set_push_location(br_to.base)
789
else: # We have a valid to branch
790
# We were able to connect to the remote location, so remember it
791
# we don't need to successfully push because of possible divergence.
792
if br_from.get_push_location() is None or remember:
793
br_from.set_push_location(br_to.base)
794
old_rh = br_to.revision_history()
485
transport = get_transport(location).clone('..')
486
if not create_prefix:
797
tree_to = dir_to.open_workingtree()
798
except errors.NotLocalUrl:
799
warning("This transport does not update the working "
800
"tree of: %s. See 'bzr help working-trees' for "
801
"more information." % br_to.base)
802
push_result = br_from.push(br_to, overwrite)
803
except errors.NoWorkingTree:
804
push_result = br_from.push(br_to, overwrite)
488
transport.mkdir(transport.relpath(location))
490
raise BzrCommandError("Parent directory of %s "
491
"does not exist." % location)
493
current = transport.base
494
needed = [(transport, transport.relpath(location))]
808
push_result = br_from.push(tree_to.branch, overwrite)
812
except errors.DivergedBranches:
813
raise errors.BzrCommandError('These branches have diverged.'
814
' Try using "merge" and then "push".')
815
if push_result is not None:
816
push_result.report(self.outf)
497
transport, relpath = needed[-1]
498
transport.mkdir(relpath)
501
new_transport = transport.clone('..')
502
needed.append((new_transport,
503
new_transport.relpath(transport.base)))
504
if new_transport.base == transport.base:
505
raise BzrCommandError("Could not creeate "
507
if isinstance(transport, LocalTransport):
508
br_to = WorkingTree.create_standalone(location).branch
510
br_to = Branch.create(location)
511
old_rh = br_to.revision_history()
514
tree_to = br_to.working_tree()
515
except NoWorkingTree:
516
# TODO: This should be updated for branches which don't have a
517
# working tree, as opposed to ones where we just couldn't
519
warning('Unable to update the working tree of: %s' % (br_to.base,))
520
count = br_to.pull(br_from, overwrite)
522
count = tree_to.pull(br_from, overwrite)
523
except DivergedBranches:
524
raise BzrCommandError("These branches have diverged."
525
" Try a merge then push with overwrite.")
526
if br_from.get_push_location() is None or remember:
527
br_from.set_push_location(location)
528
note('%d revision(s) pushed.' % (count,))
818
531
new_rh = br_to.revision_history()
819
532
if old_rh != new_rh:
820
533
# Something changed
821
534
from bzrlib.log import show_changed_revisions
822
show_changed_revisions(br_to, old_rh, new_rh,
825
# we probably did a clone rather than a push, so a message was
535
show_changed_revisions(br_to, old_rh, new_rh)
830
538
class cmd_branch(Command):
898
617
class cmd_checkout(Command):
899
618
"""Create a new checkout of an existing branch.
901
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
902
the branch found in '.'. This is useful if you have removed the working tree
903
or if it was never created - i.e. if you pushed the branch to its current
906
620
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
907
621
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
908
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
909
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
910
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
913
623
To retrieve the branch as of a particular revision, supply the --revision
914
624
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
915
625
out of date [so you cannot commit] but it may be useful (i.e. to examine old
628
--basis is to speed up checking out from remote branches. When specified, it
629
uses the inventory and file contents from the basis branch in preference to the
630
branch being checked out. [Not implemented yet.]
919
_see_also = ['checkouts', 'branch']
920
takes_args = ['branch_location?', 'to_location?']
921
takes_options = ['revision',
922
Option('lightweight',
923
help="perform a lightweight checkout. Lightweight "
924
"checkouts depend on access to the branch for "
925
"every operation. Normal checkouts can perform "
926
"common operations like diff and status without "
927
"such access, and also support local commits."
932
def run(self, branch_location=None, to_location=None, revision=None,
632
takes_args = ['branch_location', 'to_location?']
633
takes_options = ['revision'] # , 'basis']
635
def run(self, branch_location, to_location=None, revision=None, basis=None):
934
636
if revision is None:
935
637
revision = [None]
936
638
elif len(revision) > 1:
937
raise errors.BzrCommandError(
639
raise BzrCommandError(
938
640
'bzr checkout --revision takes exactly 1 revision value')
939
if branch_location is None:
940
branch_location = osutils.getcwd()
941
to_location = branch_location
942
641
source = Branch.open(branch_location)
943
642
if len(revision) == 1 and revision[0] is not None:
944
643
revision_id = revision[0].in_history(source)[1]
946
645
revision_id = None
947
646
if to_location is None:
948
to_location = urlutils.derive_to_location(branch_location)
949
# if the source and to_location are the same,
950
# and there is no working tree,
951
# then reconstitute a branch
952
if (osutils.abspath(to_location) ==
953
osutils.abspath(branch_location)):
955
source.bzrdir.open_workingtree()
956
except errors.NoWorkingTree:
957
source.bzrdir.create_workingtree()
647
to_location = os.path.basename(branch_location.rstrip("/\\"))
960
649
os.mkdir(to_location)
961
650
except OSError, e:
962
651
if e.errno == errno.EEXIST:
963
raise errors.BzrCommandError('Target directory "%s" already'
964
' exists.' % to_location)
652
raise BzrCommandError('Target directory "%s" already'
653
' exists.' % to_location)
965
654
if e.errno == errno.ENOENT:
966
raise errors.BzrCommandError('Parent of "%s" does not exist.'
655
raise BzrCommandError('Parent of "%s" does not exist.' %
970
source.create_checkout(to_location, revision_id, lightweight)
659
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
660
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
661
checkout.create_workingtree(revision_id)
973
664
class cmd_renames(Command):
1048
711
class cmd_info(Command):
1049
"""Show information about a working tree, branch or repository.
1051
This command will show all known locations and formats associated to the
1052
tree, branch or repository. Statistical information is included with
1055
Branches and working trees will also report any missing revisions.
1057
_see_also = ['revno', 'working-trees', 'repositories']
1058
takes_args = ['location?']
1059
takes_options = ['verbose']
712
"""Show statistical information about a branch."""
713
takes_args = ['branch?']
1061
715
@display_command
1062
def run(self, location=None, verbose=0):
1063
from bzrlib.info import show_bzrdir_info
1064
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
716
def run(self, branch=None):
718
bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0])
1068
721
class cmd_remove(Command):
1069
"""Remove files or directories.
1071
This makes bzr stop tracking changes to the specified files and
1072
delete them if they can easily be recovered using revert.
1074
You can specify one or more files, and/or --new. If you specify --new,
1075
only 'added' files will be removed. If you specify both, then new files
1076
in the specified directories will be removed. If the directories are
1077
also new, they will also be removed.
722
"""Make a file unversioned.
724
This makes bzr stop tracking changes to a versioned file. It does
725
not delete the working copy.
1079
takes_args = ['file*']
1080
takes_options = ['verbose',
1081
Option('new', help='remove newly-added files'),
1082
RegistryOption.from_kwargs('file-deletion-strategy',
1083
'The file deletion mode to be used',
1084
title='Deletion Strategy', value_switches=True, enum_switch=False,
1085
safe='Only delete files if they can be'
1086
' safely recovered (default).',
1087
keep="Don't delete any files.",
1088
force='Delete all the specified files, even if they can not be '
1089
'recovered and even if they are non-empty directories.')]
727
takes_args = ['file+']
728
takes_options = ['verbose']
1090
729
aliases = ['rm']
1091
encoding_type = 'replace'
1093
def run(self, file_list, verbose=False, new=False,
1094
file_deletion_strategy='safe'):
731
def run(self, file_list, verbose=False):
1095
732
tree, file_list = tree_files(file_list)
1097
if file_list is not None:
1098
file_list = [f for f in file_list if f != '']
1100
raise errors.BzrCommandError('Specify one or more files to'
1101
' remove, or use --new.')
1104
added = tree.changes_from(tree.basis_tree(),
1105
specific_files=file_list).added
1106
file_list = sorted([f[0] for f in added], reverse=True)
1107
if len(file_list) == 0:
1108
raise errors.BzrCommandError('No matching files.')
1109
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1110
keep_files=file_deletion_strategy=='keep',
1111
force=file_deletion_strategy=='force')
733
tree.remove(file_list, verbose=verbose)
1114
736
class cmd_file_id(Command):
1118
740
same through all revisions where the file exists, even when it is
1119
741
moved or renamed.
1123
_see_also = ['inventory', 'ls']
1124
744
takes_args = ['filename']
1126
745
@display_command
1127
746
def run(self, filename):
1128
747
tree, relpath = WorkingTree.open_containing(filename)
1129
i = tree.path2id(relpath)
1131
raise errors.NotVersionedError(filename)
748
i = tree.inventory.path2id(relpath)
750
raise BzrError("%r is not a versioned file" % filename)
1133
self.outf.write(i + '\n')
1136
755
class cmd_file_path(Command):
1137
756
"""Print path of file_ids to a file or directory.
1139
758
This prints one line for each directory down to the target,
1140
starting at the branch root.
759
starting at the branch root."""
1144
761
takes_args = ['filename']
1146
762
@display_command
1147
763
def run(self, filename):
1148
764
tree, relpath = WorkingTree.open_containing(filename)
1149
fid = tree.path2id(relpath)
1151
raise errors.NotVersionedError(filename)
1152
segments = osutils.splitpath(relpath)
1153
for pos in range(1, len(segments) + 1):
1154
path = osutils.joinpath(segments[:pos])
1155
self.outf.write("%s\n" % tree.path2id(path))
1158
class cmd_reconcile(Command):
1159
"""Reconcile bzr metadata in a branch.
1161
This can correct data mismatches that may have been caused by
1162
previous ghost operations or bzr upgrades. You should only
1163
need to run this command if 'bzr check' or a bzr developer
1164
advises you to run it.
1166
If a second branch is provided, cross-branch reconciliation is
1167
also attempted, which will check that data like the tree root
1168
id which was not present in very early bzr versions is represented
1169
correctly in both branches.
1171
At the same time it is run it may recompress data resulting in
1172
a potential saving in disk space or performance gain.
1174
The branch *MUST* be on a listable system such as local disk or sftp.
1177
_see_also = ['check']
1178
takes_args = ['branch?']
1180
def run(self, branch="."):
1181
from bzrlib.reconcile import reconcile
1182
dir = bzrdir.BzrDir.open(branch)
766
fid = inv.path2id(relpath)
768
raise BzrError("%r is not a versioned file" % filename)
769
for fip in inv.get_idpath(fid):
1186
773
class cmd_revision_history(Command):
1187
"""Display the list of revision ids on a branch."""
1190
takes_args = ['location?']
774
"""Display list of revision ids on this branch."""
1194
776
@display_command
1195
def run(self, location="."):
1196
branch = Branch.open_containing(location)[0]
1197
for revid in branch.revision_history():
1198
self.outf.write(revid)
1199
self.outf.write('\n')
778
branch = WorkingTree.open_containing(u'.')[0].branch
779
for patchid in branch.revision_history():
1202
783
class cmd_ancestry(Command):
1203
784
"""List all revisions merged into this branch."""
1205
_see_also = ['log', 'revision-history']
1206
takes_args = ['location?']
1210
786
@display_command
1211
def run(self, location="."):
1213
wt = WorkingTree.open_containing(location)[0]
1214
except errors.NoWorkingTree:
1215
b = Branch.open(location)
1216
last_revision = b.last_revision()
1219
last_revision = wt.last_revision()
1221
revision_ids = b.repository.get_ancestry(last_revision)
1222
assert revision_ids[0] is None
1224
for revision_id in revision_ids:
1225
self.outf.write(revision_id + '\n')
788
tree = WorkingTree.open_containing(u'.')[0]
790
# FIXME. should be tree.last_revision
791
for revision_id in b.repository.get_ancestry(b.last_revision()):
1228
795
class cmd_init(Command):
1247
806
bzr commit -m 'imported project'
1250
_see_also = ['init-repo', 'branch', 'checkout']
1251
808
takes_args = ['location?']
1253
Option('create-prefix',
1254
help='Create the path leading up to the branch '
1255
'if it does not already exist'),
1256
RegistryOption('format',
1257
help='Specify a format for this branch. '
1258
'See "help formats".',
1259
registry=bzrdir.format_registry,
1260
converter=bzrdir.format_registry.make_bzrdir,
1261
value_switches=True,
1262
title="Branch Format",
1264
Option('append-revisions-only',
1265
help='Never change revnos or the existing log.'
1266
' Append revisions to it only.')
1268
def run(self, location=None, format=None, append_revisions_only=False,
1269
create_prefix=False):
1271
format = bzrdir.format_registry.make_bzrdir('default')
809
def run(self, location=None):
810
from bzrlib.branch import Branch
1272
811
if location is None:
1275
to_transport = transport.get_transport(location)
1277
# The path has to exist to initialize a
1278
# branch inside of it.
1279
# Just using os.mkdir, since I don't
1280
# believe that we want to create a bunch of
1281
# locations if the user supplies an extended path
1283
to_transport.ensure_base()
1284
except errors.NoSuchFile:
1285
if not create_prefix:
1286
raise errors.BzrCommandError("Parent directory of %s"
1288
"\nYou may supply --create-prefix to create all"
1289
" leading parent directories."
1291
_create_prefix(to_transport)
1294
existing_bzrdir = bzrdir.BzrDir.open(location)
1295
except errors.NotBranchError:
1296
# really a NotBzrDir error...
1297
branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
1300
from bzrlib.transport.local import LocalTransport
1301
if existing_bzrdir.has_branch():
1302
if (isinstance(to_transport, LocalTransport)
1303
and not existing_bzrdir.has_workingtree()):
1304
raise errors.BranchExistsWithoutWorkingTree(location)
1305
raise errors.AlreadyBranchError(location)
1307
branch = existing_bzrdir.create_branch()
1308
existing_bzrdir.create_workingtree()
1309
if append_revisions_only:
1311
branch.set_append_revisions_only(True)
1312
except errors.UpgradeRequired:
1313
raise errors.BzrCommandError('This branch format cannot be set'
1314
' to append-revisions-only. Try --experimental-branch6')
1317
class cmd_init_repository(Command):
1318
"""Create a shared repository to hold branches.
1320
New branches created under the repository directory will store their
1321
revisions in the repository, not in the branch directory.
1323
If the --no-trees option is used then the branches in the repository
1324
will not have working trees by default.
1327
bzr init-repo --no-trees repo
1329
bzr checkout --lightweight repo/trunk trunk-checkout
1333
See 'bzr help repositories' for more information.
1336
_see_also = ['init', 'branch', 'checkout']
1337
takes_args = ["location"]
1338
takes_options = [RegistryOption('format',
1339
help='Specify a format for this repository. See'
1340
' "bzr help formats" for details',
1341
registry=bzrdir.format_registry,
1342
converter=bzrdir.format_registry.make_bzrdir,
1343
value_switches=True, title='Repository format'),
1345
help='Branches in the repository will default to'
1346
' not having a working tree'),
1348
aliases = ["init-repo"]
1350
def run(self, location, format=None, no_trees=False):
1352
format = bzrdir.format_registry.make_bzrdir('default')
1354
if location is None:
1357
to_transport = transport.get_transport(location)
1358
to_transport.ensure_base()
1360
newdir = format.initialize_on_transport(to_transport)
1361
repo = newdir.create_repository(shared=True)
1362
repo.set_make_working_trees(not no_trees)
814
# The path has to exist to initialize a
815
# branch inside of it.
816
# Just using os.mkdir, since I don't
817
# believe that we want to create a bunch of
818
# locations if the user supplies an extended path
819
if not os.path.exists(location):
821
bzrdir.BzrDir.create_standalone_workingtree(location)
1365
824
class cmd_diff(Command):
1366
"""Show differences in the working tree or between revisions.
825
"""Show differences in working tree.
1368
827
If files are listed, only the changes in those files are listed.
1369
828
Otherwise, all changes for the tree are listed.
1371
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1372
produces patches suitable for "patch -p1".
1376
Shows the difference in the working tree versus the last commit
1378
Difference between the working tree and revision 1
1380
Difference between revision 2 and revision 1
1381
bzr diff --prefix old/:new/
1382
Same as 'bzr diff' but prefix paths with old/ and new/
1383
bzr diff bzr.mine bzr.dev
1384
Show the differences between the two working trees
1386
Show just the differences for 'foo.c'
835
# TODO: Allow diff across branches.
1388
836
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1389
837
# or a graphical diff.
1391
839
# TODO: Python difflib is not exactly the same as unidiff; should
1392
840
# either fix it up or prefer to use an external diff.
842
# TODO: If a directory is given, diff everything under that.
1394
844
# TODO: Selected-file diff is inefficient and doesn't show you
1395
845
# deleted files.
1397
847
# TODO: This probably handles non-Unix newlines poorly.
1399
_see_also = ['status']
1400
849
takes_args = ['file*']
1401
takes_options = ['revision', 'diff-options',
1402
Option('prefix', type=str,
1404
help='Set prefixes to added to old and new filenames, as '
1405
'two values separated by a colon. (eg "old/:new/")'),
850
takes_options = ['revision', 'diff-options']
1407
851
aliases = ['di', 'dif']
1408
encoding_type = 'exact'
1410
853
@display_command
1411
def run(self, revision=None, file_list=None, diff_options=None,
1413
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1415
if (prefix is None) or (prefix == '0'):
1423
old_label, new_label = prefix.split(":")
1425
raise errors.BzrCommandError(
1426
'--prefix expects two values separated by a colon'
1427
' (eg "old/:new/")')
1429
if revision and len(revision) > 2:
1430
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1431
' one or two revision specifiers')
854
def run(self, revision=None, file_list=None, diff_options=None):
855
from bzrlib.diff import show_diff
1434
tree1, file_list = internal_tree_files(file_list)
857
tree, file_list = internal_tree_files(file_list)
1438
except errors.FileInWrongBranch:
860
except FileInWrongBranch:
1439
861
if len(file_list) != 2:
1440
raise errors.BzrCommandError("Files are in different branches")
862
raise BzrCommandError("Files are in different branches")
1442
tree1, file1 = WorkingTree.open_containing(file_list[0])
1443
tree2, file2 = WorkingTree.open_containing(file_list[1])
864
b, file1 = Branch.open_containing(file_list[0])
865
b2, file2 = Branch.open_containing(file_list[1])
1444
866
if file1 != "" or file2 != "":
1445
867
# FIXME diff those two files. rbc 20051123
1446
raise errors.BzrCommandError("Files are in different branches")
868
raise BzrCommandError("Files are in different branches")
1447
869
file_list = None
1448
except errors.NotBranchError:
1449
if (revision is not None and len(revision) == 2
1450
and not revision[0].needs_branch()
1451
and not revision[1].needs_branch()):
1452
# If both revision specs include a branch, we can
1453
# diff them without needing a local working tree
1454
tree1, tree2 = None, None
1458
if tree2 is not None:
1459
if revision is not None:
1460
# FIXME: but there should be a clean way to diff between
1461
# non-default versions of two trees, it's not hard to do
1463
raise errors.BzrCommandError(
1464
"Sorry, diffing arbitrary revisions across branches "
1465
"is not implemented yet")
1466
return show_diff_trees(tree1, tree2, sys.stdout,
1467
specific_files=file_list,
1468
external_diff_options=diff_options,
1469
old_label=old_label, new_label=new_label)
1471
return diff_cmd_helper(tree1, file_list, diff_options,
1472
revision_specs=revision,
1473
old_label=old_label, new_label=new_label)
870
if revision is not None:
872
raise BzrCommandError("Can't specify -r with two branches")
873
if (len(revision) == 1) or (revision[1].spec is None):
874
return show_diff(tree.branch, revision[0], specific_files=file_list,
875
external_diff_options=diff_options)
876
elif len(revision) == 2:
877
return show_diff(tree.branch, revision[0], specific_files=file_list,
878
external_diff_options=diff_options,
879
revision2=revision[1])
881
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
884
return show_diff(b, None, specific_files=file_list,
885
external_diff_options=diff_options, b2=b2)
887
return show_diff(tree.branch, None, specific_files=file_list,
888
external_diff_options=diff_options)
1476
891
class cmd_deleted(Command):
1482
897
# directories with readdir, rather than stating each one. Same
1483
898
# level of effort but possibly much less IO. (Or possibly not,
1484
899
# if the directories are very large...)
1485
_see_also = ['status', 'ls']
1486
takes_options = ['show-ids']
1488
900
@display_command
1489
901
def run(self, show_ids=False):
1490
902
tree = WorkingTree.open_containing(u'.')[0]
1493
old = tree.basis_tree()
1496
for path, ie in old.inventory.iter_entries():
1497
if not tree.has_id(ie.file_id):
1498
self.outf.write(path)
1500
self.outf.write(' ')
1501
self.outf.write(ie.file_id)
1502
self.outf.write('\n')
903
old = tree.basis_tree()
904
for path, ie in old.inventory.iter_entries():
905
if not tree.has_id(ie.file_id):
907
print '%-50s %s' % (path, ie.file_id)
1509
912
class cmd_modified(Command):
1510
"""List files modified in working tree.
913
"""List files modified in working tree."""
1514
_see_also = ['status', 'ls']
1516
915
@display_command
917
from bzrlib.delta import compare_trees
1518
919
tree = WorkingTree.open_containing(u'.')[0]
1519
td = tree.changes_from(tree.basis_tree())
920
td = compare_trees(tree.basis_tree(), tree)
1520
922
for path, id, kind, text_modified, meta_modified in td.modified:
1521
self.outf.write(path + '\n')
1524
927
class cmd_added(Command):
1525
"""List files added in working tree.
928
"""List files added in working tree."""
1529
_see_also = ['status', 'ls']
1531
930
@display_command
1533
932
wt = WorkingTree.open_containing(u'.')[0]
1536
basis = wt.basis_tree()
1539
basis_inv = basis.inventory
1542
if file_id in basis_inv:
1544
if inv.is_root(file_id) and len(basis_inv) == 0:
1546
path = inv.id2path(file_id)
1547
if not os.access(osutils.abspath(path), os.F_OK):
1549
self.outf.write(path + '\n')
933
basis_inv = wt.basis_tree().inventory
936
if file_id in basis_inv:
938
path = inv.id2path(file_id)
939
if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
1556
945
class cmd_root(Command):
1557
946
"""Show the tree root directory.
1559
948
The root is the nearest enclosing directory with a .bzr control
1562
950
takes_args = ['filename?']
1563
951
@display_command
1564
952
def run(self, filename=None):
1565
953
"""Print the branch root."""
1566
954
tree = WorkingTree.open_containing(filename)[0]
1567
self.outf.write(tree.basedir + '\n')
1570
def _parse_limit(limitstring):
1572
return int(limitstring)
1574
msg = "The limit argument must be an integer."
1575
raise errors.BzrCommandError(msg)
1578
958
class cmd_log(Command):
1579
"""Show log of a branch, file, or directory.
1581
By default show the log of the branch containing the working directory.
959
"""Show log of this branch.
1583
961
To request a range of logs, you can use the command -r begin..end
1584
962
-r revision requests a specific revision, -r ..end or -r begin.. are
1590
bzr log -r -10.. http://server/branch
1593
966
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1595
takes_args = ['location?']
968
takes_args = ['filename?']
1596
969
takes_options = [Option('forward',
1597
970
help='show from oldest to newest'),
1601
help='show files changed in each revision'),
971
'timezone', 'verbose',
1602
972
'show-ids', 'revision',
1604
975
Option('message',
1606
976
help='show revisions whose message matches this regexp',
1609
help='limit the output to the first N revisions',
1612
encoding_type = 'replace'
1614
980
@display_command
1615
def run(self, location=None, timezone='original',
981
def run(self, filename=None, timezone='original',
1620
986
log_format=None,
1623
from bzrlib.log import show_log
991
from bzrlib.log import log_formatter, show_log
1624
993
assert message is None or isinstance(message, basestring), \
1625
994
"invalid message argument %r" % message
1626
995
direction = (forward and 'forward') or 'reverse'
1628
997
# log everything
1631
1000
# find the file id to log:
1633
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1002
dir, fp = bzrdir.BzrDir.open_containing(filename)
1003
b = dir.open_branch()
1637
tree = b.basis_tree()
1638
file_id = tree.path2id(fp)
1640
raise errors.BzrCommandError(
1641
"Path does not have any revision history: %s" %
1007
inv = dir.open_workingtree().inventory
1008
except (errors.NotBranchError, errors.NotLocalUrl):
1009
# either no tree, or is remote.
1010
inv = b.basis_tree().inventory
1011
file_id = inv.path2id(fp)
1644
1013
# local dir only
1645
1014
# FIXME ? log the current subdir only RBC 20060203
1646
if revision is not None \
1647
and len(revision) > 0 and revision[0].get_branch():
1648
location = revision[0].get_branch()
1651
dir, relpath = bzrdir.BzrDir.open_containing(location)
1015
dir, relpath = bzrdir.BzrDir.open_containing('.')
1652
1016
b = dir.open_branch()
1656
if revision is None:
1659
elif len(revision) == 1:
1660
rev1 = rev2 = revision[0].in_history(b).revno
1661
elif len(revision) == 2:
1662
if revision[1].get_branch() != revision[0].get_branch():
1663
# b is taken from revision[0].get_branch(), and
1664
# show_log will use its revision_history. Having
1665
# different branches will lead to weird behaviors.
1666
raise errors.BzrCommandError(
1667
"Log doesn't accept two revisions in different"
1669
if revision[0].spec is None:
1670
# missing begin-range means first revision
1673
rev1 = revision[0].in_history(b).revno
1675
if revision[1].spec is None:
1676
# missing end-range means last known revision
1679
rev2 = revision[1].in_history(b).revno
1681
raise errors.BzrCommandError(
1682
'bzr log --revision takes one or two values.')
1684
# By this point, the revision numbers are converted to the +ve
1685
# form if they were supplied in the -ve form, so we can do
1686
# this comparison in relative safety
1688
(rev2, rev1) = (rev1, rev2)
1690
if log_format is None:
1691
log_format = log.log_formatter_registry.get_default(b)
1693
lf = log_format(show_ids=show_ids, to_file=self.outf,
1694
show_timezone=timezone)
1700
direction=direction,
1701
start_revision=rev1,
1018
if revision is None:
1021
elif len(revision) == 1:
1022
rev1 = rev2 = revision[0].in_history(b).revno
1023
elif len(revision) == 2:
1024
if revision[0].spec is None:
1025
# missing begin-range means first revision
1028
rev1 = revision[0].in_history(b).revno
1030
if revision[1].spec is None:
1031
# missing end-range means last known revision
1034
rev2 = revision[1].in_history(b).revno
1036
raise BzrCommandError('bzr log --revision takes one or two values.')
1038
# By this point, the revision numbers are converted to the +ve
1039
# form if they were supplied in the -ve form, so we can do
1040
# this comparison in relative safety
1042
(rev2, rev1) = (rev1, rev2)
1044
mutter('encoding log as %r', bzrlib.user_encoding)
1046
# use 'replace' so that we don't abort if trying to write out
1047
# in e.g. the default C locale.
1048
outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
1050
if (log_format == None):
1051
default = bzrlib.config.BranchConfig(b).log_format()
1052
log_format = get_log_format(long=long, short=short, line=line, default=default)
1054
lf = log_formatter(log_format,
1057
show_timezone=timezone)
1063
direction=direction,
1064
start_revision=rev1,
1709
1069
def get_log_format(long=False, short=False, line=False, default='long'):
1752
1108
Option('ignored', help='Print ignored files'),
1754
1110
Option('null', help='Null separate the files'),
1757
1112
@display_command
1758
1113
def run(self, revision=None, verbose=False,
1759
1114
non_recursive=False, from_root=False,
1760
1115
unknown=False, versioned=False, ignored=False,
1761
null=False, kind=None, show_ids=False, path=None):
1763
if kind and kind not in ('file', 'directory', 'symlink'):
1764
raise errors.BzrCommandError('invalid kind specified')
1766
1118
if verbose and null:
1767
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1119
raise BzrCommandError('Cannot set both --verbose and --null')
1768
1120
all = not (unknown or versioned or ignored)
1770
1122
selection = {'I':ignored, '?':unknown, 'V':versioned}
1777
raise errors.BzrCommandError('cannot specify both --from-root'
1781
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1124
tree, relpath = WorkingTree.open_containing(u'.')
1787
1129
if revision is not None:
1788
tree = branch.repository.revision_tree(
1789
revision[0].in_history(branch).rev_id)
1791
tree = branch.basis_tree()
1795
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1796
if fp.startswith(relpath):
1797
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1798
if non_recursive and '/' in fp:
1800
if not all and not selection[fc]:
1802
if kind is not None and fkind != kind:
1805
kindch = entry.kind_character()
1806
outstring = '%-8s %s%s' % (fc, fp, kindch)
1807
if show_ids and fid is not None:
1808
outstring = "%-50s %s" % (outstring, fid)
1809
self.outf.write(outstring + '\n')
1811
self.outf.write(fp + '\0')
1814
self.outf.write(fid)
1815
self.outf.write('\0')
1823
self.outf.write('%-50s %s\n' % (fp, my_id))
1825
self.outf.write(fp + '\n')
1130
tree = tree.branch.repository.revision_tree(
1131
revision[0].in_history(tree.branch).rev_id)
1132
for fp, fc, kind, fid, entry in tree.list_files():
1133
if fp.startswith(relpath):
1134
fp = fp[len(relpath):]
1135
if non_recursive and '/' in fp:
1137
if not all and not selection[fc]:
1140
kindch = entry.kind_character()
1141
print '%-8s %s%s' % (fc, fp, kindch)
1143
sys.stdout.write(fp)
1144
sys.stdout.write('\0')
1830
1150
class cmd_unknowns(Command):
1831
"""List unknown files.
1151
"""List unknown files."""
1837
1152
@display_command
1154
from bzrlib.osutils import quotefn
1839
1155
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1840
self.outf.write(osutils.quotefn(f) + '\n')
1843
1159
class cmd_ignore(Command):
1844
"""Ignore specified files or patterns.
1160
"""Ignore a command or pattern.
1846
1162
To remove patterns from the ignore list, edit the .bzrignore file.
1848
Trailing slashes on patterns are ignored.
1849
If the pattern contains a slash or is a regular expression, it is compared
1850
to the whole path from the branch root. Otherwise, it is compared to only
1851
the last component of the path. To match a file only in the root
1852
directory, prepend './'.
1854
Ignore patterns specifying absolute paths are not allowed.
1856
Ignore patterns may include globbing wildcards such as:
1857
? - Matches any single character except '/'
1858
* - Matches 0 or more characters except '/'
1859
/**/ - Matches 0 or more directories in a path
1860
[a-z] - Matches a single character from within a group of characters
1862
Ignore patterns may also be Python regular expressions.
1863
Regular expression ignore patterns are identified by a 'RE:' prefix
1864
followed by the regular expression. Regular expression ignore patterns
1865
may not include named or numbered groups.
1867
Note: ignore patterns containing shell wildcards must be quoted from
1164
If the pattern contains a slash, it is compared to the whole path
1165
from the branch root. Otherwise, it is compared to only the last
1166
component of the path. To match a file only in the root directory,
1169
Ignore patterns are case-insensitive on case-insensitive systems.
1171
Note: wildcards must be quoted from the shell on Unix.
1871
1174
bzr ignore ./Makefile
1872
1175
bzr ignore '*.class'
1873
bzr ignore 'lib/**/*.o'
1874
bzr ignore 'RE:lib/.*\.o'
1877
_see_also = ['status', 'ignored']
1878
takes_args = ['name_pattern*']
1880
Option('old-default-rules',
1881
help='Out the ignore rules bzr < 0.9 always used.')
1177
# TODO: Complain if the filename is absolute
1178
takes_args = ['name_pattern']
1884
def run(self, name_pattern_list=None, old_default_rules=None):
1180
def run(self, name_pattern):
1885
1181
from bzrlib.atomicfile import AtomicFile
1886
if old_default_rules is not None:
1887
# dump the rules and exit
1888
for pattern in ignores.OLD_DEFAULTS:
1891
if not name_pattern_list:
1892
raise errors.BzrCommandError("ignore requires at least one "
1893
"NAME_PATTERN or --old-default-rules")
1894
name_pattern_list = [globbing.normalize_pattern(p)
1895
for p in name_pattern_list]
1896
for name_pattern in name_pattern_list:
1897
if (name_pattern[0] == '/' or
1898
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1899
raise errors.BzrCommandError(
1900
"NAME_PATTERN should not be an absolute path")
1901
1184
tree, relpath = WorkingTree.open_containing(u'.')
1902
1185
ifn = tree.abspath('.bzrignore')
1903
1187
if os.path.exists(ifn):
1904
1188
f = open(ifn, 'rt')
2120
1350
# XXX: verbose currently does nothing
2122
_see_also = ['bugs', 'uncommit']
2123
1352
takes_args = ['selected*']
2124
1353
takes_options = ['message', 'verbose',
2125
1354
Option('unchanged',
2126
1355
help='commit even if nothing has changed'),
2127
1356
Option('file', type=str,
2129
1357
argname='msgfile',
2130
1358
help='file containing commit message'),
2131
1359
Option('strict',
2132
1360
help="refuse to commit if there are unknown "
2133
1361
"files in the working tree."),
2134
ListOption('fixes', type=str,
2135
help="mark a bug as being fixed by this "
2138
help="perform a local only commit in a bound "
2139
"branch. Such commits are not pushed to "
2140
"the master branch until a normal commit "
2144
1363
aliases = ['ci', 'checkin']
2146
def _get_bug_fix_properties(self, fixes, branch):
2148
# Configure the properties for bug fixing attributes.
2149
for fixed_bug in fixes:
2150
tokens = fixed_bug.split(':')
2151
if len(tokens) != 2:
2152
raise errors.BzrCommandError(
2153
"Invalid bug %s. Must be in the form of 'tag:id'. "
2154
"Commit refused." % fixed_bug)
2155
tag, bug_id = tokens
2157
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2158
except errors.UnknownBugTrackerAbbreviation:
2159
raise errors.BzrCommandError(
2160
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2161
except errors.MalformedBugIdentifier:
2162
raise errors.BzrCommandError(
2163
"Invalid bug identifier for %s. Commit refused."
2165
properties.append('%s fixed' % bug_url)
2166
return '\n'.join(properties)
2168
1365
def run(self, message=None, file=None, verbose=True, selected_list=None,
2169
unchanged=False, strict=False, local=False, fixes=None):
2170
from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
1366
unchanged=False, strict=False):
2171
1367
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
2172
1368
StrictCommitFailed)
2173
1369
from bzrlib.msgeditor import edit_commit_message, \
2174
1370
make_commit_message_template
1371
from bzrlib.status import show_status
1372
from tempfile import TemporaryFile
2176
1375
# TODO: Need a blackbox test for invoking the external editor; may be
2177
1376
# slightly problematic to run this cross-platform.
2179
1378
# TODO: do more checks that the commit will succeed before
2180
1379
# spending the user's valuable time typing a commit message.
1381
# TODO: if the commit *does* happen to fail, then save the commit
1382
# message to a temporary file where it can be recovered
2184
1383
tree, selected_list = tree_files(selected_list)
2185
if selected_list == ['']:
2186
# workaround - commit of root of tree should be exactly the same
2187
# as just default commit in that tree, and succeed even though
2188
# selected-file merge commit is not done yet
2191
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2193
properties['bugs'] = bug_property
2195
if local and not tree.branch.get_bound_location():
2196
raise errors.LocalRequiresBoundBranch()
2198
def get_message(commit_obj):
2199
"""Callback to get commit message"""
2200
my_message = message
2201
if my_message is None and not file:
2202
template = make_commit_message_template(tree, selected_list)
2203
my_message = edit_commit_message(template)
2204
if my_message is None:
2205
raise errors.BzrCommandError("please specify a commit"
2206
" message with either --message or --file")
2207
elif my_message and file:
2208
raise errors.BzrCommandError(
2209
"please specify either --message or --file")
2211
my_message = codecs.open(file, 'rt',
2212
bzrlib.user_encoding).read()
2213
if my_message == "":
2214
raise errors.BzrCommandError("empty commit message specified")
2218
reporter = ReportCommitToLog()
2220
reporter = NullCommitReporter()
1384
if message is None and not file:
1385
template = make_commit_message_template(tree, selected_list)
1386
message = edit_commit_message(template)
1388
raise BzrCommandError("please specify a commit message"
1389
" with either --message or --file")
1390
elif message and file:
1391
raise BzrCommandError("please specify either --message or --file")
1395
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1398
raise BzrCommandError("empty commit message specified")
2223
tree.commit(message_callback=get_message,
2224
specific_files=selected_list,
2225
allow_pointless=unchanged, strict=strict, local=local,
2226
reporter=reporter, revprops=properties)
1401
tree.commit(message, specific_files=selected_list,
1402
allow_pointless=unchanged, strict=strict)
2227
1403
except PointlessCommit:
2228
1404
# FIXME: This should really happen before the file is read in;
2229
1405
# perhaps prepare the commit; get the message; then actually commit
2230
raise errors.BzrCommandError("no changes to commit."
2231
" use --unchanged to commit anyhow")
1406
raise BzrCommandError("no changes to commit",
1407
["use --unchanged to commit anyhow"])
2232
1408
except ConflictsInTree:
2233
raise errors.BzrCommandError('Conflicts detected in working '
2234
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
1409
raise BzrCommandError("Conflicts detected in working tree. "
1410
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
2236
1411
except StrictCommitFailed:
2237
raise errors.BzrCommandError("Commit refused because there are"
2238
" unknown files in the working tree.")
2239
except errors.BoundBranchOutOfDate, e:
2240
raise errors.BzrCommandError(str(e) + "\n"
2241
'To commit to master branch, run update and then commit.\n'
2242
'You can also pass --local to commit to continue working '
1412
raise BzrCommandError("Commit refused because there are unknown "
1413
"files in the working tree.")
1414
note('Committed revision %d.' % (tree.branch.revno(),))
2246
1417
class cmd_check(Command):
2410
1552
if typestring == "memory":
2411
1553
from bzrlib.transport.memory import MemoryServer
2412
1554
return MemoryServer
2413
if typestring == "fakenfs":
2414
from bzrlib.transport.fakenfs import FakeNFSServer
2415
return FakeNFSServer
2416
1555
msg = "No known transport type %s. Supported types are: sftp\n" %\
2418
raise errors.BzrCommandError(msg)
1557
raise BzrCommandError(msg)
2421
1560
takes_args = ['testspecs*']
2422
1561
takes_options = ['verbose',
2424
help='stop when one test fails',
2427
Option('keep-output',
1562
Option('one', help='stop when one test fails'),
1563
Option('keep-output',
2428
1564
help='keep output directories when tests fail'),
2430
1566
help='Use a different transport by default '
2431
1567
'throughout the test suite.',
2432
1568
type=get_transport_type),
2433
Option('benchmark', help='run the bzr benchmarks.'),
2434
Option('lsprof-timed',
2435
help='generate lsprof output for benchmarked'
2436
' sections of code.'),
2437
Option('cache-dir', type=str,
2438
help='a directory to cache intermediate'
2439
' benchmark steps'),
2440
Option('clean-output',
2441
help='clean temporary tests directories'
2442
' without running tests'),
2444
help='run all tests, but run specified tests first',
2447
Option('numbered-dirs',
2448
help='use numbered dirs for TestCaseInTempDir'),
2450
help='list the tests instead of running them'),
2451
Option('randomize', type=str, argname="SEED",
2452
help='randomize the order of tests using the given'
2453
' seed or "now" for the current time'),
2454
Option('exclude', type=str, argname="PATTERN",
2456
help='exclude tests that match this regular'
2459
encoding_type = 'replace'
2461
def run(self, testspecs_list=None, verbose=None, one=False,
2462
keep_output=False, transport=None, benchmark=None,
2463
lsprof_timed=None, cache_dir=None, clean_output=False,
2464
first=False, numbered_dirs=None, list_only=False,
2465
randomize=None, exclude=None):
1571
def run(self, testspecs_list=None, verbose=False, one=False,
1572
keep_output=False, transport=None):
2466
1573
import bzrlib.ui
2467
1574
from bzrlib.tests import selftest
2468
import bzrlib.benchmarks as benchmarks
2469
from bzrlib.benchmarks import tree_creator
2472
from bzrlib.tests import clean_selftest_output
2473
clean_selftest_output()
2476
trace.warning("notice: selftest --keep-output "
2477
"is no longer supported; "
2478
"test output is always removed")
2480
if numbered_dirs is None and sys.platform == 'win32':
2481
numbered_dirs = True
2483
if cache_dir is not None:
2484
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2485
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2486
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2488
if testspecs_list is not None:
2489
pattern = '|'.join(testspecs_list)
2493
test_suite_factory = benchmarks.test_suite
2496
# TODO: should possibly lock the history file...
2497
benchfile = open(".perf_history", "at", buffering=1)
2499
test_suite_factory = None
1575
# we don't want progress meters from the tests to go to the
1576
# real output; and we don't want log messages cluttering up
1578
save_ui = bzrlib.ui.ui_factory
1579
bzrlib.trace.info('running tests...')
1581
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1582
if testspecs_list is not None:
1583
pattern = '|'.join(testspecs_list)
2504
1586
result = selftest(verbose=verbose,
2505
1587
pattern=pattern,
2506
1588
stop_on_failure=one,
2507
transport=transport,
2508
test_suite_factory=test_suite_factory,
2509
lsprof_timed=lsprof_timed,
2510
bench_history=benchfile,
2511
matching_tests_first=first,
2512
numbered_dirs=numbered_dirs,
2513
list_only=list_only,
2514
random_seed=randomize,
2515
exclude_pattern=exclude
1589
keep_output=keep_output,
1590
transport=transport)
1592
bzrlib.trace.info('tests passed')
1594
bzrlib.trace.info('tests failed')
1595
return int(not result)
2518
if benchfile is not None:
2521
info('tests passed')
2523
info('tests failed')
2524
return int(not result)
1597
bzrlib.ui.ui_factory = save_ui
1600
def _get_bzr_branch():
1601
"""If bzr is run from a branch, return Branch or None"""
1602
import bzrlib.errors
1603
from bzrlib.branch import Branch
1604
from bzrlib.osutils import abspath
1605
from os.path import dirname
1608
branch = Branch.open(dirname(abspath(dirname(__file__))))
1610
except bzrlib.errors.BzrError:
1615
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1616
# is bzrlib itself in a branch?
1617
branch = _get_bzr_branch()
1619
rh = branch.revision_history()
1621
print " bzr checkout, revision %d" % (revno,)
1622
print " nick: %s" % (branch.nick,)
1624
print " revid: %s" % (rh[-1],)
1625
print bzrlib.__copyright__
1626
print "http://bazaar-ng.org/"
1628
print "bzr comes with ABSOLUTELY NO WARRANTY. bzr is free software, and"
1629
print "you may use, modify and redistribute it under the terms of the GNU"
1630
print "General Public License version 2 or later."
2527
1633
class cmd_version(Command):
2528
1634
"""Show version of bzr."""
2530
1635
@display_command
2532
from bzrlib.version import show_version
2536
1639
class cmd_rocks(Command):
2537
1640
"""Statement of optimism."""
2541
1642
@display_command
2543
print "It sure does!"
1644
print "it sure does!"
2546
1647
class cmd_find_merge_base(Command):
2547
"""Find and print a base revision for merging two branches."""
1648
"""Find and print a base revision for merging two branches.
2548
1650
# TODO: Options to specify revisions on either side, as if
2549
1651
# merging only part of the history.
2550
1652
takes_args = ['branch', 'other']
2566
1671
base_rev_id = common_ancestor(last1, last2, source)
2568
1673
print 'merge base is revision %s' % base_rev_id
1677
if base_revno is None:
1678
raise bzrlib.errors.UnrelatedBranches()
1680
print ' r%-6d in %s' % (base_revno, branch)
1682
other_revno = branch2.revision_id_to_revno(base_revid)
1684
print ' r%-6d in %s' % (other_revno, other)
2571
1688
class cmd_merge(Command):
2572
1689
"""Perform a three-way merge.
2574
The branch is the branch you will merge from. By default, it will merge
2575
the latest revision. If you specify a revision, that revision will be
2576
merged. If you specify two revisions, the first will be used as a BASE,
2577
and the second one as OTHER. Revision numbers are always relative to the
1691
The branch is the branch you will merge from. By default, it will
1692
merge the latest revision. If you specify a revision, that
1693
revision will be merged. If you specify two revisions, the first
1694
will be used as a BASE, and the second one as OTHER. Revision
1695
numbers are always relative to the specified branch.
2580
By default, bzr will try to merge in all new work from the other
1697
By default bzr will try to merge in all new work from the other
2581
1698
branch, automatically determining an appropriate base. If this
2582
1699
fails, you may need to give an explicit base.
2584
Merge will do its best to combine the changes in two branches, but there
2585
are some kinds of problems only a human can fix. When it encounters those,
2586
it will mark a conflict. A conflict means that you need to fix something,
2587
before you should commit.
2589
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
2591
If there is no default branch set, the first merge will set it. After
2592
that, you can omit the branch to use the default. To change the
2593
default, use --remember. The value will only be saved if the remote
2594
location can be accessed.
2596
The results of the merge are placed into the destination working
2597
directory, where they can be reviewed (with bzr diff), tested, and then
2598
committed to record the result of the merge.
2602
To merge the latest revision from bzr.dev:
2603
bzr merge ../bzr.dev
1703
To merge the latest revision from bzr.dev
1704
bzr merge ../bzr.dev
2605
To merge changes up to and including revision 82 from bzr.dev:
2606
bzr merge -r 82 ../bzr.dev
1706
To merge changes up to and including revision 82 from bzr.dev
1707
bzr merge -r 82 ../bzr.dev
2608
1709
To merge the changes introduced by 82, without previous changes:
2609
bzr merge -r 81..82 ../bzr.dev
1710
bzr merge -r 81..82 ../bzr.dev
2611
1712
merge refuses to run if there are any uncommitted changes, unless
2612
1713
--force is given.
2615
_see_also = ['update', 'remerge']
2616
1715
takes_args = ['branch?']
2617
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2618
Option('show-base', help="Show base revision text in "
2620
Option('uncommitted', help='Apply uncommitted changes'
2621
' from a working copy, instead of branch changes'),
2622
Option('pull', help='If the destination is already'
2623
' completely merged into the source, pull from the'
2624
' source rather than merging. When this happens,'
2625
' you do not need to commit the result.'),
2627
help='Branch to merge into, '
2628
'rather than the one containing the working directory',
1716
takes_options = ['revision', 'force', 'merge-type', 'reprocess',
1717
Option('show-base', help="Show base revision text in "
2634
1720
def run(self, branch=None, revision=None, force=False, merge_type=None,
2635
show_base=False, reprocess=False, remember=False,
2636
uncommitted=False, pull=False,
2639
from bzrlib.tag import _merge_tags_if_possible
2640
other_revision_id = None
1721
show_base=False, reprocess=False):
2641
1722
if merge_type is None:
2642
merge_type = _mod_merge.Merge3Merger
2644
if directory is None: directory = u'.'
2645
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2646
# inventory. Because merge is a mutating operation, it really
2647
# should be a lock_write() for the whole cmd_merge operation.
2648
# However, cmd_merge open's its own tree in _merge_helper, which
2649
# means if we lock here, the later lock_write() will always block.
2650
# Either the merge helper code should be updated to take a tree,
2651
# (What about tree.merge_from_branch?)
2652
tree = WorkingTree.open_containing(directory)[0]
2653
change_reporter = delta._ChangeReporter(
2654
unversioned_filter=tree.is_ignored)
2656
if branch is not None:
2658
mergeable = bundle.read_mergeable_from_url(
2660
except errors.NotABundle:
2661
pass # Continue on considering this url a Branch
1723
merge_type = Merge3Merger
1725
branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
1727
raise BzrCommandError("No merge location known or specified.")
2663
if revision is not None:
2664
raise errors.BzrCommandError(
2665
'Cannot use -r with merge directives or bundles')
2666
other_revision_id = mergeable.install_revisions(
2667
tree.branch.repository)
2668
revision = [RevisionSpec.from_string(
2669
'revid:' + other_revision_id)]
2671
if revision is None \
2672
or len(revision) < 1 or revision[0].needs_branch():
2673
branch = self._get_remembered_parent(tree, branch, 'Merging from')
1729
print "Using saved location: %s" % branch
2675
1730
if revision is None or len(revision) < 1:
2678
other = [branch, None]
2681
other = [branch, -1]
2682
other_branch, path = Branch.open_containing(branch)
1732
other = [branch, -1]
2685
raise errors.BzrCommandError('Cannot use --uncommitted and'
2686
' --revision at the same time.')
2687
branch = revision[0].get_branch() or branch
2688
1734
if len(revision) == 1:
2689
1735
base = [None, None]
2690
if other_revision_id is not None:
2695
other_branch, path = Branch.open_containing(branch)
2696
revno = revision[0].in_history(other_branch).revno
2697
other = [branch, revno]
1736
other_branch = Branch.open_containing(branch)[0]
1737
revno = revision[0].in_history(other_branch).revno
1738
other = [branch, revno]
2699
1740
assert len(revision) == 2
2700
1741
if None in revision:
2701
raise errors.BzrCommandError(
2702
"Merge doesn't permit empty revision specifier.")
2703
base_branch, path = Branch.open_containing(branch)
2704
branch1 = revision[1].get_branch() or branch
2705
other_branch, path1 = Branch.open_containing(branch1)
2706
if revision[0].get_branch() is not None:
2707
# then path was obtained from it, and is None.
2710
base = [branch, revision[0].in_history(base_branch).revno]
2711
other = [branch1, revision[1].in_history(other_branch).revno]
2713
if ((tree.branch.get_parent() is None or remember) and
2714
other_branch is not None):
2715
tree.branch.set_parent(other_branch.base)
2717
# pull tags now... it's a bit inconsistent to do it ahead of copying
2718
# the history but that's done inside the merge code
2719
if other_branch is not None:
2720
_merge_tags_if_possible(other_branch, tree.branch)
2723
interesting_files = [path]
2725
interesting_files = None
2726
pb = ui.ui_factory.nested_progress_bar()
1742
raise BzrCommandError(
1743
"Merge doesn't permit that revision specifier.")
1744
b = Branch.open_containing(branch)[0]
1746
base = [branch, revision[0].in_history(b).revno]
1747
other = [branch, revision[1].in_history(b).revno]
2729
conflict_count = _merge_helper(
2730
other, base, other_rev_id=other_revision_id,
2731
check_clean=(not force),
2732
merge_type=merge_type,
2733
reprocess=reprocess,
2734
show_base=show_base,
2737
pb=pb, file_list=interesting_files,
2738
change_reporter=change_reporter)
1750
conflict_count = merge(other, base, check_clean=(not force),
1751
merge_type=merge_type, reprocess=reprocess,
1752
show_base=show_base)
2741
1753
if conflict_count != 0:
2745
except errors.AmbiguousBase, e:
1757
except bzrlib.errors.AmbiguousBase, e:
2746
1758
m = ("sorry, bzr can't determine the right merge base yet\n"
2747
1759
"candidates are:\n "
2748
1760
+ "\n ".join(e.bases)
2860
1827
class cmd_revert(Command):
2861
"""Revert files to a previous revision.
2863
Giving a list of files will revert only those files. Otherwise, all files
2864
will be reverted. If the revision is not specified with '--revision', the
2865
last committed revision is used.
2867
To remove only some changes, without reverting to a prior version, use
2868
merge instead. For example, "merge . --r-2..-3" will remove the changes
2869
introduced by -2, without affecting the changes introduced by -1. Or
2870
to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
2872
By default, any files that have been manually changed will be backed up
2873
first. (Files changed only by merge are not backed up.) Backup files have
2874
'.~#~' appended to their name, where # is a number.
2876
When you provide files, you can use their current pathname or the pathname
2877
from the target revision. So you can use revert to "undelete" a file by
2878
name. If you name a directory, all the contents of that directory will be
1828
"""Reverse all changes since the last commit.
1830
Only versioned files are affected. Specify filenames to revert only
1831
those files. By default, any files that are changed will be backed up
1832
first. Backup files have a '~' appended to their name.
2882
_see_also = ['cat', 'export']
2883
1834
takes_options = ['revision', 'no-backup']
2884
1835
takes_args = ['file*']
1836
aliases = ['merge-revert']
2886
1838
def run(self, revision=None, no_backup=False, file_list=None):
1839
from bzrlib.commands import parse_spec
2887
1840
if file_list is not None:
2888
1841
if len(file_list) == 0:
2889
raise errors.BzrCommandError("No files specified")
1842
raise BzrCommandError("No files specified")
2893
1846
tree, file_list = tree_files(file_list)
2894
1847
if revision is None:
2895
1848
# FIXME should be tree.last_revision
2896
rev_id = tree.last_revision()
1849
rev_id = tree.branch.last_revision()
2897
1850
elif len(revision) != 1:
2898
raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
1851
raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
2900
1853
rev_id = revision[0].in_history(tree.branch).rev_id
2901
pb = ui.ui_factory.nested_progress_bar()
2903
tree.revert(file_list,
2904
tree.branch.repository.revision_tree(rev_id),
2905
not no_backup, pb, report_changes=True)
1854
tree.revert(file_list, tree.branch.repository.revision_tree(rev_id),
2910
1858
class cmd_assert_fail(Command):
2911
1859
"""Test reporting of assertion failures"""
2912
# intended just for use in testing
2917
raise AssertionError("always fails")
1862
assert False, "always fails"
2920
1865
class cmd_help(Command):
2921
1866
"""Show help on a command or other topic.
2924
_see_also = ['topics']
1868
For a list of all available commands, say 'bzr help commands'."""
2925
1869
takes_options = [Option('long', 'show help on all commands')]
2926
1870
takes_args = ['topic?']
2927
aliases = ['?', '--help', '-?', '-h']
2929
1873
@display_command
2930
1874
def run(self, topic=None, long=False):
2932
1876
if topic is None and long:
2933
1877
topic = "commands"
2934
bzrlib.help.help(topic)
2937
1881
class cmd_shell_complete(Command):
2938
1882
"""Show appropriate completions for context.
2940
For a list of all available commands, say 'bzr shell-complete'.
1884
For a list of all available commands, say 'bzr shell-complete'."""
2942
1885
takes_args = ['context?']
2943
1886
aliases = ['s-c']
2966
1909
class cmd_missing(Command):
2967
1910
"""Show unmerged/unpulled revisions between two branches.
2969
OTHER_BRANCH may be local or remote.
2972
_see_also = ['merge', 'pull']
1912
OTHER_BRANCH may be local or remote."""
2973
1913
takes_args = ['other_branch?']
2974
1914
takes_options = [Option('reverse', 'Reverse the order of revisions'),
2975
1915
Option('mine-only',
2976
1916
'Display changes in the local branch only'),
2977
Option('this' , 'same as --mine-only'),
2978
1917
Option('theirs-only',
2979
'Display changes in the remote branch only'),
2980
Option('other', 'same as --theirs-only'),
1918
'Display changes in the remote branch only'),
2985
encoding_type = 'replace'
2988
1927
def run(self, other_branch=None, reverse=False, mine_only=False,
2989
1928
theirs_only=False, log_format=None, long=False, short=False, line=False,
2990
show_ids=False, verbose=False, this=False, other=False):
2991
from bzrlib.missing import find_unmerged, iter_log_revisions
1929
show_ids=False, verbose=False):
1930
from bzrlib.missing import find_unmerged, iter_log_data
2992
1931
from bzrlib.log import log_formatter
2999
local_branch = Branch.open_containing(u".")[0]
1932
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
3000
1933
parent = local_branch.get_parent()
3001
1934
if other_branch is None:
3002
1935
other_branch = parent
3003
1936
if other_branch is None:
3004
raise errors.BzrCommandError("No peer location known or specified.")
3005
display_url = urlutils.unescape_for_display(parent,
3007
print "Using last location: " + display_url
3009
remote_branch = Branch.open(other_branch)
3010
if remote_branch.base == local_branch.base:
3011
remote_branch = local_branch
3012
local_branch.lock_read()
3014
remote_branch.lock_read()
3016
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
3017
if (log_format is None):
3018
log_format = log.log_formatter_registry.get_default(
3020
lf = log_format(to_file=self.outf,
3022
show_timezone='original')
3023
if reverse is False:
3024
local_extra.reverse()
3025
remote_extra.reverse()
3026
if local_extra and not theirs_only:
3027
print "You have %d extra revision(s):" % len(local_extra)
3028
for revision in iter_log_revisions(local_extra,
3029
local_branch.repository,
3031
lf.log_revision(revision)
3032
printed_local = True
3034
printed_local = False
3035
if remote_extra and not mine_only:
3036
if printed_local is True:
3038
print "You are missing %d revision(s):" % len(remote_extra)
3039
for revision in iter_log_revisions(remote_extra,
3040
remote_branch.repository,
3042
lf.log_revision(revision)
3043
if not remote_extra and not local_extra:
3045
print "Branches are up to date."
3049
remote_branch.unlock()
3051
local_branch.unlock()
3052
if not status_code and parent is None and other_branch is not None:
3053
local_branch.lock_write()
3055
# handle race conditions - a parent might be set while we run.
3056
if local_branch.get_parent() is None:
3057
local_branch.set_parent(remote_branch.base)
3059
local_branch.unlock()
1937
raise BzrCommandError("No missing location known or specified.")
1938
print "Using last location: " + local_branch.get_parent()
1939
remote_branch = bzrlib.branch.Branch.open(other_branch)
1940
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
1941
if (log_format == None):
1942
default = bzrlib.config.BranchConfig(local_branch).log_format()
1943
log_format = get_log_format(long=long, short=short, line=line, default=default)
1944
lf = log_formatter(log_format, sys.stdout,
1946
show_timezone='original')
1947
if reverse is False:
1948
local_extra.reverse()
1949
remote_extra.reverse()
1950
if local_extra and not theirs_only:
1951
print "You have %d extra revision(s):" % len(local_extra)
1952
for data in iter_log_data(local_extra, local_branch.repository,
1955
printed_local = True
1957
printed_local = False
1958
if remote_extra and not mine_only:
1959
if printed_local is True:
1961
print "You are missing %d revision(s):" % len(remote_extra)
1962
for data in iter_log_data(remote_extra, remote_branch.repository,
1965
if not remote_extra and not local_extra:
1967
print "Branches are up to date."
1970
if parent is None and other_branch is not None:
1971
local_branch.set_parent(other_branch)
3060
1972
return status_code
3185
2082
if to_revid is None:
3186
2083
to_revno = b.revno()
3187
2084
if from_revno is None or to_revno is None:
3188
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2085
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
3189
2086
for revno in range(from_revno, to_revno + 1):
3190
2087
b.repository.sign_revision(b.get_rev_id(revno),
3193
raise errors.BzrCommandError('Please supply either one revision, or a range.')
3196
class cmd_bind(Command):
3197
"""Convert the current branch into a checkout of the supplied branch.
3199
Once converted into a checkout, commits must succeed on the master branch
3200
before they will be applied to the local branch.
3203
_see_also = ['checkouts', 'unbind']
3204
takes_args = ['location?']
3207
def run(self, location=None):
3208
b, relpath = Branch.open_containing(u'.')
3209
if location is None:
3211
location = b.get_old_bound_location()
3212
except errors.UpgradeRequired:
3213
raise errors.BzrCommandError('No location supplied. '
3214
'This format does not remember old locations.')
3216
if location is None:
3217
raise errors.BzrCommandError('No location supplied and no '
3218
'previous location known')
3219
b_other = Branch.open(location)
3222
except errors.DivergedBranches:
3223
raise errors.BzrCommandError('These branches have diverged.'
3224
' Try merging, and then bind again.')
3227
class cmd_unbind(Command):
3228
"""Convert the current checkout into a regular branch.
3230
After unbinding, the local branch is considered independent and subsequent
3231
commits will be local only.
3234
_see_also = ['checkouts', 'bind']
3239
b, relpath = Branch.open_containing(u'.')
3241
raise errors.BzrCommandError('Local branch is not bound')
3244
class cmd_uncommit(Command):
2090
raise BzrCommandError('Please supply either one revision, or a range.')
2093
class cmd_uncommit(bzrlib.commands.Command):
3245
2094
"""Remove the last committed revision.
2096
By supplying the --all flag, it will not only remove the entry
2097
from revision_history, but also remove all of the entries in the
3247
2100
--verbose will print out what is being removed.
3248
2101
--dry-run will go through all the motions, but not actually
3249
2102
remove anything.
3251
In the future, uncommit will create a revision bundle, which can then
2104
In the future, uncommit will create a changeset, which can then
2107
TODO: jam 20060108 Add an option to allow uncommit to remove unreferenced
2108
information in 'branch-as-repostory' branches.
2109
TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2110
information in shared branches as well.
3255
# TODO: jam 20060108 Add an option to allow uncommit to remove
3256
# unreferenced information in 'branch-as-repository' branches.
3257
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
3258
# information in shared branches as well.
3259
_see_also = ['commit']
3260
2112
takes_options = ['verbose', 'revision',
3261
2113
Option('dry-run', help='Don\'t actually make changes'),
3262
2114
Option('force', help='Say yes to all questions.')]
3263
2115
takes_args = ['location?']
3266
def run(self, location=None,
2118
def run(self, location=None,
3267
2119
dry_run=False, verbose=False,
3268
2120
revision=None, force=False):
3269
from bzrlib.log import log_formatter, show_log
2121
from bzrlib.branch import Branch
2122
from bzrlib.log import log_formatter
3271
2124
from bzrlib.uncommit import uncommit
3273
2126
if location is None:
3274
2127
location = u'.'
3275
control, relpath = bzrdir.BzrDir.open_containing(location)
3277
tree = control.open_workingtree()
3279
except (errors.NoWorkingTree, errors.NotLocalUrl):
3281
b = control.open_branch()
2128
b, relpath = Branch.open_containing(location)
3284
2130
if revision is None:
3285
2131
revno = b.revno()
2132
rev_id = b.last_revision()
3287
# 'bzr uncommit -r 10' actually means uncommit
3288
# so that the final tree is at revno 10.
3289
# but bzrlib.uncommit.uncommit() actually uncommits
3290
# the revisions that are supplied.
3291
# So we need to offset it by one
3292
revno = revision[0].in_history(b).revno+1
3294
if revno <= b.revno():
3295
rev_id = b.get_rev_id(revno)
2134
revno, rev_id = revision[0].in_history(b)
3296
2135
if rev_id is None:
3297
self.outf.write('No revisions to uncommit.\n')
3300
lf = log_formatter('short',
3302
show_timezone='original')
3307
direction='forward',
3308
start_revision=revno,
3309
end_revision=b.revno())
2136
print 'No revisions to uncommit.'
2138
for r in range(revno, b.revno()+1):
2139
rev_id = b.get_rev_id(r)
2140
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2141
lf.show(r, b.repository.get_revision(rev_id), None)
3312
2144
print 'Dry-run, pretending to remove the above revisions.'
3320
2152
print 'Canceled'
3323
uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
2155
uncommit(b, dry_run=dry_run, verbose=verbose,
3327
class cmd_break_lock(Command):
3328
"""Break a dead lock on a repository, branch or working directory.
3330
CAUTION: Locks should only be broken when you are sure that the process
3331
holding the lock has been stopped.
3333
You can get information on what locks are open via the 'bzr info' command.
3338
takes_args = ['location?']
3340
def run(self, location=None, show=False):
3341
if location is None:
3343
control, relpath = bzrdir.BzrDir.open_containing(location)
3345
control.break_lock()
3346
except NotImplementedError:
3350
class cmd_wait_until_signalled(Command):
3351
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3353
This just prints a line to signal when it is ready, then blocks on stdin.
3359
sys.stdout.write("running\n")
3361
sys.stdin.readline()
3364
class cmd_serve(Command):
3365
"""Run the bzr server."""
3367
aliases = ['server']
3371
help='serve on stdin/out for use from inetd or sshd'),
3373
help='listen for connections on nominated port of the form '
3374
'[hostname:]portnumber. Passing 0 as the port number will '
3375
'result in a dynamically allocated port. Default port is '
3379
help='serve contents of directory',
3381
Option('allow-writes',
3382
help='By default the server is a readonly server. Supplying '
3383
'--allow-writes enables write access to the contents of '
3384
'the served directory and below. '
3388
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3389
from bzrlib.smart import medium, server
3390
from bzrlib.transport import get_transport
3391
from bzrlib.transport.chroot import ChrootServer
3392
from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3393
if directory is None:
3394
directory = os.getcwd()
3395
url = urlutils.local_path_to_url(directory)
3396
if not allow_writes:
3397
url = 'readonly+' + url
3398
chroot_server = ChrootServer(get_transport(url))
3399
chroot_server.setUp()
3400
t = get_transport(chroot_server.get_url())
3402
smart_server = medium.SmartServerPipeStreamMedium(
3403
sys.stdin, sys.stdout, t)
3405
host = BZR_DEFAULT_INTERFACE
3407
port = BZR_DEFAULT_PORT
3410
host, port = port.split(':')
3412
smart_server = server.SmartTCPServer(t, host=host, port=port)
3413
print 'listening on port: ', smart_server.port
3415
# for the duration of this server, no UI output is permitted.
3416
# note that this may cause problems with blackbox tests. This should
3417
# be changed with care though, as we dont want to use bandwidth sending
3418
# progress over stderr to smart server clients!
3419
old_factory = ui.ui_factory
3421
ui.ui_factory = ui.SilentUIFactory()
3422
smart_server.serve()
3424
ui.ui_factory = old_factory
3427
class cmd_join(Command):
3428
"""Combine a subtree into its containing tree.
3430
This command is for experimental use only. It requires the target tree
3431
to be in dirstate-with-subtree format, which cannot be converted into
3434
The TREE argument should be an independent tree, inside another tree, but
3435
not part of it. (Such trees can be produced by "bzr split", but also by
3436
running "bzr branch" with the target inside a tree.)
3438
The result is a combined tree, with the subtree no longer an independant
3439
part. This is marked as a merge of the subtree into the containing tree,
3440
and all history is preserved.
3442
If --reference is specified, the subtree retains its independence. It can
3443
be branched by itself, and can be part of multiple projects at the same
3444
time. But operations performed in the containing tree, such as commit
3445
and merge, will recurse into the subtree.
3448
_see_also = ['split']
3449
takes_args = ['tree']
3450
takes_options = [Option('reference', 'join by reference')]
3453
def run(self, tree, reference=False):
3454
sub_tree = WorkingTree.open(tree)
3455
parent_dir = osutils.dirname(sub_tree.basedir)
3456
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3457
repo = containing_tree.branch.repository
3458
if not repo.supports_rich_root():
3459
raise errors.BzrCommandError(
3460
"Can't join trees because %s doesn't support rich root data.\n"
3461
"You can use bzr upgrade on the repository."
3465
containing_tree.add_reference(sub_tree)
3466
except errors.BadReferenceTarget, e:
3467
# XXX: Would be better to just raise a nicely printable
3468
# exception from the real origin. Also below. mbp 20070306
3469
raise errors.BzrCommandError("Cannot join %s. %s" %
3473
containing_tree.subsume(sub_tree)
3474
except errors.BadSubsumeSource, e:
3475
raise errors.BzrCommandError("Cannot join %s. %s" %
3479
class cmd_split(Command):
3480
"""Split a tree into two trees.
3482
This command is for experimental use only. It requires the target tree
3483
to be in dirstate-with-subtree format, which cannot be converted into
3486
The TREE argument should be a subdirectory of a working tree. That
3487
subdirectory will be converted into an independent tree, with its own
3488
branch. Commits in the top-level tree will not apply to the new subtree.
3489
If you want that behavior, do "bzr join --reference TREE".
3492
_see_also = ['join']
3493
takes_args = ['tree']
3497
def run(self, tree):
3498
containing_tree, subdir = WorkingTree.open_containing(tree)
3499
sub_id = containing_tree.path2id(subdir)
3501
raise errors.NotVersionedError(subdir)
3503
containing_tree.extract(sub_id)
3504
except errors.RootNotRich:
3505
raise errors.UpgradeRequired(containing_tree.branch.base)
3509
class cmd_merge_directive(Command):
3510
"""Generate a merge directive for auto-merge tools.
3512
A directive requests a merge to be performed, and also provides all the
3513
information necessary to do so. This means it must either include a
3514
revision bundle, or the location of a branch containing the desired
3517
A submit branch (the location to merge into) must be supplied the first
3518
time the command is issued. After it has been supplied once, it will
3519
be remembered as the default.
3521
A public branch is optional if a revision bundle is supplied, but required
3522
if --diff or --plain is specified. It will be remembered as the default
3523
after the first use.
3526
takes_args = ['submit_branch?', 'public_branch?']
3529
RegistryOption.from_kwargs('patch-type',
3530
'The type of patch to include in the directive',
3531
title='Patch type', value_switches=True, enum_switch=False,
3532
bundle='Bazaar revision bundle (default)',
3533
diff='Normal unified diff',
3534
plain='No patch, just directive'),
3535
Option('sign', help='GPG-sign the directive'), 'revision',
3536
Option('mail-to', type=str,
3537
help='Instead of printing the directive, email to this address'),
3538
Option('message', type=str, short_name='m',
3539
help='Message to use when committing this merge')
3542
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3543
sign=False, revision=None, mail_to=None, message=None):
3544
if patch_type == 'plain':
3546
branch = Branch.open('.')
3547
stored_submit_branch = branch.get_submit_branch()
3548
if submit_branch is None:
3549
submit_branch = stored_submit_branch
3551
if stored_submit_branch is None:
3552
branch.set_submit_branch(submit_branch)
3553
if submit_branch is None:
3554
submit_branch = branch.get_parent()
3555
if submit_branch is None:
3556
raise errors.BzrCommandError('No submit branch specified or known')
3558
stored_public_branch = branch.get_public_branch()
3559
if public_branch is None:
3560
public_branch = stored_public_branch
3561
elif stored_public_branch is None:
3562
branch.set_public_branch(public_branch)
3563
if patch_type != "bundle" and public_branch is None:
3564
raise errors.BzrCommandError('No public branch specified or'
3566
if revision is not None:
3567
if len(revision) != 1:
3568
raise errors.BzrCommandError('bzr merge-directive takes '
3569
'exactly one revision identifier')
3571
revision_id = revision[0].in_history(branch).rev_id
3573
revision_id = branch.last_revision()
3574
directive = merge_directive.MergeDirective.from_objects(
3575
branch.repository, revision_id, time.time(),
3576
osutils.local_time_offset(), submit_branch,
3577
public_branch=public_branch, patch_type=patch_type,
3581
self.outf.write(directive.to_signed(branch))
3583
self.outf.writelines(directive.to_lines())
3585
message = directive.to_email(mail_to, branch, sign)
3587
server = branch.get_config().get_user_option('smtp_server')
3589
server = 'localhost'
3591
s.sendmail(message['From'], message['To'], message.as_string())
3594
class cmd_tag(Command):
3595
"""Create a tag naming a revision.
3597
Tags give human-meaningful names to revisions. Commands that take a -r
3598
(--revision) option can be given -rtag:X, where X is any previously
3601
Tags are stored in the branch. Tags are copied from one branch to another
3602
along when you branch, push, pull or merge.
3604
It is an error to give a tag name that already exists unless you pass
3605
--force, in which case the tag is moved to point to the new revision.
3608
_see_also = ['commit', 'tags']
3609
takes_args = ['tag_name']
3612
help='Delete this tag rather than placing it.',
3615
help='Branch in which to place the tag.',
3620
help='Replace existing tags',
3625
def run(self, tag_name,
3631
branch, relpath = Branch.open_containing(directory)
3635
branch.tags.delete_tag(tag_name)
3636
self.outf.write('Deleted tag %s.\n' % tag_name)
3639
if len(revision) != 1:
3640
raise errors.BzrCommandError(
3641
"Tags can only be placed on a single revision, "
3643
revision_id = revision[0].in_history(branch).rev_id
3645
revision_id = branch.last_revision()
3646
if (not force) and branch.tags.has_tag(tag_name):
3647
raise errors.TagAlreadyExists(tag_name)
3648
branch.tags.set_tag(tag_name, revision_id)
3649
self.outf.write('Created tag %s.\n' % tag_name)
3654
class cmd_tags(Command):
3657
This tag shows a table of tag names and the revisions they reference.
3663
help='Branch whose tags should be displayed',
3673
branch, relpath = Branch.open_containing(directory)
3674
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3675
self.outf.write('%-20s %s\n' % (tag_name, target))
3678
# command-line interpretation helper for merge-related commands
3679
def _merge_helper(other_revision, base_revision,
3680
check_clean=True, ignore_zero=False,
3681
this_dir=None, backup_files=False,
3683
file_list=None, show_base=False, reprocess=False,
3686
change_reporter=None,
2159
def merge(other_revision, base_revision,
2160
check_clean=True, ignore_zero=False,
2161
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2162
file_list=None, show_base=False, reprocess=False):
3688
2163
"""Merge changes into a tree.
3712
2187
clients might prefer to call merge.merge_inner(), which has less magic
3715
# Loading it late, so that we don't always have to import bzrlib.merge
3716
if merge_type is None:
3717
merge_type = _mod_merge.Merge3Merger
2190
from bzrlib.merge import Merger
3718
2191
if this_dir is None:
3719
2192
this_dir = u'.'
3720
2193
this_tree = WorkingTree.open_containing(this_dir)[0]
3721
if show_base and not merge_type is _mod_merge.Merge3Merger:
3722
raise errors.BzrCommandError("Show-base is not supported for this merge"
3723
" type. %s" % merge_type)
3724
if reprocess and not merge_type.supports_reprocess:
3725
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3726
" type %s." % merge_type)
2194
if show_base and not merge_type is Merge3Merger:
2195
raise BzrCommandError("Show-base is not supported for this merge"
2196
" type. %s" % merge_type)
2197
if reprocess and not merge_type is Merge3Merger:
2198
raise BzrCommandError("Reprocess is not supported for this merge"
2199
" type. %s" % merge_type)
3727
2200
if reprocess and show_base:
3728
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3729
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3730
# only want to take out a lock_tree_write() if we don't have to pull
3731
# any ancestry. But merge might fetch ancestry in the middle, in
3732
# which case we would need a lock_write().
3733
# Because we cannot upgrade locks, for now we live with the fact that
3734
# the tree will be locked multiple times during a merge. (Maybe
3735
# read-only some of the time, but it means things will get read
3738
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3739
pb=pb, change_reporter=change_reporter)
3740
merger.pp = ProgressPhase("Merge phase", 5, pb)
3741
merger.pp.next_phase()
3742
merger.check_basis(check_clean)
3743
if other_rev_id is not None:
3744
merger.set_other_revision(other_rev_id, this_tree.branch)
3746
merger.set_other(other_revision)
3747
merger.pp.next_phase()
3748
merger.set_base(base_revision)
3749
if merger.base_rev_id == merger.other_rev_id:
3750
note('Nothing to do.')
3752
if file_list is None:
3753
if pull and merger.base_rev_id == merger.this_rev_id:
3754
# FIXME: deduplicate with pull
3755
result = merger.this_tree.pull(merger.this_branch,
3756
False, merger.other_rev_id)
3757
if result.old_revid == result.new_revid:
3758
note('No revisions to pull.')
3760
note('Now on revision %d.' % result.new_revno)
3762
merger.backup_files = backup_files
3763
merger.merge_type = merge_type
3764
merger.set_interesting_files(file_list)
3765
merger.show_base = show_base
3766
merger.reprocess = reprocess
3767
conflicts = merger.do_merge()
3768
if file_list is None:
3769
merger.set_pending()
2201
raise BzrCommandError("Cannot reprocess and show base.")
2202
merger = Merger(this_tree.branch, this_tree=this_tree)
2203
merger.check_basis(check_clean)
2204
merger.set_other(other_revision)
2205
merger.set_base(base_revision)
2206
if merger.base_rev_id == merger.other_rev_id:
2207
note('Nothing to do.')
2209
merger.backup_files = backup_files
2210
merger.merge_type = merge_type
2211
merger.set_interesting_files(file_list)
2212
merger.show_base = show_base
2213
merger.reprocess = reprocess
2214
conflicts = merger.do_merge()
2215
merger.set_pending()
3772
2216
return conflicts
3775
def _create_prefix(cur_transport):
3776
needed = [cur_transport]
3777
# Recurse upwards until we can create a directory successfully
3779
new_transport = cur_transport.clone('..')
3780
if new_transport.base == cur_transport.base:
3781
raise errors.BzrCommandError("Failed to create path"
3785
new_transport.mkdir('.')
3786
except errors.NoSuchFile:
3787
needed.append(new_transport)
3788
cur_transport = new_transport
3792
# Now we only need to create child directories
3794
cur_transport = needed.pop()
3795
cur_transport.ensure_base()
3798
merge = _merge_helper
3801
2219
# these get imported and then picked up by the scan for cmd_*
3802
2220
# TODO: Some more consistent way to split command definitions across files;
3803
2221
# we do need to load at least some information about them to know of
3804
# aliases. ideally we would avoid loading the implementation until the
3805
# details were needed.
3806
from bzrlib.cmd_version_info import cmd_version_info
3807
2223
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
3808
from bzrlib.bundle.commands import cmd_bundle_revisions
3809
2224
from bzrlib.sign_my_commits import cmd_sign_my_commits
3810
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
3811
cmd_weave_plan_merge, cmd_weave_merge_text