1
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
1
# Copyright (C) 2004, 2005, 2006 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
47
revision as _mod_revision,
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
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,
36
from bzrlib.log import show_one_log
37
from bzrlib.merge import Merge3Merger
38
from bzrlib.option import Option
39
from bzrlib.progress import DummyProgress, ProgressPhase
58
40
from bzrlib.revisionspec import RevisionSpec
59
from bzrlib.smtp_connection import SMTPConnection
42
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
43
from bzrlib.transport.local import LocalTransport
60
45
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
48
def tree_files(file_list, default_branch=u'.'):
71
50
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.
51
except FileInWrongBranch, e:
52
raise BzrCommandError("%s is not in the same branch as %s" %
53
(e.path, file_list[0]))
79
55
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]
57
Return a branch and list of branch-relative paths.
58
If supplied file_list is empty or None, the branch default will be used,
59
and returned file_list will match the original.
94
61
if file_list is None or len(file_list) == 0:
95
62
return WorkingTree.open_containing(default_branch)[0], file_list
96
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
63
tree = WorkingTree.open_containing(file_list[0])[0]
98
65
for filename in file_list:
100
new_list.append(tree.relpath(osutils.dereference_path(filename)))
67
new_list.append(tree.relpath(filename))
101
68
except errors.PathNotChild:
102
raise errors.FileInWrongBranch(tree.branch, filename)
69
raise FileInWrongBranch(tree.branch, filename)
103
70
return tree, new_list
106
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
107
73
def get_format_type(typestring):
108
74
"""Parse and return a format specifier."""
109
# Have to use BzrDirMetaFormat1 directly, so that
110
# RepositoryFormat.set_default_format works
111
if typestring == "default":
75
if typestring == "metadir":
112
76
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)
77
if typestring == "knit":
78
format = bzrdir.BzrDirMetaFormat1()
79
format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
81
msg = "No known bzr-dir format %s. Supported types are: metadir\n" %\
83
raise BzrCommandError(msg)
120
86
# TODO: Make sure no commands unconditionally use the working directory as a
325
232
Adding a file whose parent directory is not versioned will
326
233
implicitly add the parent, and so on up to the root. This means
327
you should never need to explicitly add a directory, they'll just
234
you should never need to explictly add a directory, they'll just
328
235
get added when you add a file in the directory.
330
237
--dry-run will show which files would be added, but not actually
333
--file-ids-from will try to use the file ids from the supplied path.
334
It looks up ids trying to find a matching parent directory with the
335
same filename, and then by pure path. This option is rarely needed
336
but can be useful when adding the same logical file into two
337
branches that will be merged later (without showing the two different
338
adds as a conflict). It is also useful when merging another project
339
into a subdirectory of this one.
341
240
takes_args = ['file*']
344
help="Don't recursively add the contents of directories."),
346
help="Show what would be done, but don't actually do anything."),
348
Option('file-ids-from',
350
help='Lookup file ids from this tree.'),
352
encoding_type = 'replace'
353
_see_also = ['remove']
241
takes_options = ['no-recurse', 'dry-run', 'verbose']
355
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
243
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
357
244
import bzrlib.add
360
if file_ids_from is not None:
362
base_tree, base_path = WorkingTree.open_containing(
364
except errors.NoWorkingTree:
365
base_branch, base_path = Branch.open_containing(
367
base_tree = base_branch.basis_tree()
369
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
370
to_file=self.outf, should_print=(not is_quiet()))
248
# This is pointless, but I'd rather not raise an error
249
action = bzrlib.add.add_action_null
251
action = bzrlib.add.add_action_print
253
action = bzrlib.add.add_action_add
372
action = bzrlib.add.AddAction(to_file=self.outf,
373
should_print=(not is_quiet()))
255
action = bzrlib.add.add_action_add_and_print
376
base_tree.lock_read()
378
file_list = self._maybe_expand_globs(file_list)
380
tree = WorkingTree.open_containing(file_list[0])[0]
382
tree = WorkingTree.open_containing(u'.')[0]
383
added, ignored = tree.smart_add(file_list, not
384
no_recurse, action=action, save=not dry_run)
386
if base_tree is not None:
257
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
388
259
if len(ignored) > 0:
390
for glob in sorted(ignored.keys()):
260
for glob in sorted(ignored.keys()):
261
match_len = len(ignored[glob])
391
263
for path in ignored[glob]:
392
self.outf.write("ignored %s matching \"%s\"\n"
396
for glob, paths in ignored.items():
397
match_len += len(paths)
398
self.outf.write("ignored %d file(s).\n" % match_len)
399
self.outf.write("If you wish to add some of these files,"
400
" please add them by name.\n")
264
print "ignored %s matching \"%s\"" % (path, glob)
266
print "ignored %d file(s) matching \"%s\"" % (match_len,
268
print "If you wish to add some of these files, please add them"\
403
272
class cmd_mkdir(Command):
509
336
If the last argument is a versioned directory, all the other names
510
337
are moved into it. Otherwise, there must be exactly two arguments
511
and the file is changed to a new name.
513
If OLDNAME does not exist on the filesystem but is versioned and
514
NEWNAME does exist on the filesystem but is not versioned, mv
515
assumes that the file has been manually moved and only updates
516
its internal inventory to reflect that change.
517
The same is valid when moving many SOURCE files to a DESTINATION.
338
and the file is changed to a new name, which must not already exist.
519
340
Files cannot be moved between branches.
522
342
takes_args = ['names*']
523
takes_options = [Option("after", help="Move only the bzr identifier"
524
" of the file, because the file has already been moved."),
526
343
aliases = ['move', 'rename']
527
encoding_type = 'replace'
529
def run(self, names_list, after=False):
530
if names_list is None:
345
def run(self, names_list):
533
346
if len(names_list) < 2:
534
raise errors.BzrCommandError("missing file argument")
347
raise BzrCommandError("missing file argument")
535
348
tree, rel_names = tree_files(names_list)
537
350
if os.path.isdir(names_list[-1]):
538
351
# move into existing directory
539
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
540
self.outf.write("%s => %s\n" % pair)
352
for pair in tree.move(rel_names[:-1], rel_names[-1]):
353
print "%s => %s" % pair
542
355
if len(names_list) != 2:
543
raise errors.BzrCommandError('to mv multiple files the'
544
' destination must be a versioned'
546
tree.rename_one(rel_names[0], rel_names[1], after=after)
547
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
356
raise BzrCommandError('to mv multiple files the destination '
357
'must be a versioned directory')
358
tree.rename_one(rel_names[0], rel_names[1])
359
print "%s => %s" % (rel_names[0], rel_names[1])
550
362
class cmd_pull(Command):
551
"""Turn this branch into a mirror of another branch.
363
"""Pull any changes from another branch into the current one.
365
If there is no default location set, the first pull will set it. After
366
that, you can omit the location to use the default. To change the
367
default, use --remember.
553
369
This command only works on branches that have not diverged. Branches are
554
considered diverged if the destination branch's most recent commit is one
555
that has not been merged (directly or indirectly) into the parent.
370
considered diverged if both branches have had commits without first
371
pulling from the other.
557
If branches have diverged, you can use 'bzr merge' to integrate the changes
373
If branches have diverged, you can use 'bzr merge' to pull the text changes
558
374
from one into the other. Once one branch has merged, the other should
559
375
be able to pull it again.
561
377
If you want to forget your local changes and just update your branch to
562
match the remote one, use pull --overwrite.
564
If there is no default location set, the first pull will set it. After
565
that, you can omit the location to use the default. To change the
566
default, use --remember. The value will only be saved if the remote
567
location can be accessed.
378
match the remote one, use --overwrite.
570
_see_also = ['push', 'update', 'status-flags']
571
takes_options = ['remember', 'overwrite', 'revision', 'verbose',
573
help='Branch to pull into, '
574
'rather than the one containing the working directory.',
380
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
579
381
takes_args = ['location?']
580
encoding_type = 'replace'
582
def run(self, location=None, remember=False, overwrite=False,
583
revision=None, verbose=False,
585
from bzrlib.tag import _merge_tags_if_possible
383
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
586
384
# FIXME: too much stuff is in the command class
589
if directory is None:
592
tree_to = WorkingTree.open_containing(directory)[0]
386
tree_to = WorkingTree.open_containing(u'.')[0]
593
387
branch_to = tree_to.branch
594
except errors.NoWorkingTree:
388
except NoWorkingTree:
596
branch_to = Branch.open_containing(directory)[0]
599
# The user may provide a bundle or branch as 'location' We first try to
600
# identify a bundle, if it's not, we try to preserve connection used by
601
# the transport to access the branch.
602
if location is not None:
603
url = urlutils.normalize_url(location)
604
url, filename = urlutils.split(url, exclude_trailing_slash=False)
605
location_transport = transport.get_transport(url)
608
read_bundle = bundle.read_mergeable_from_transport
609
# There may be redirections but we ignore the intermediate
610
# and final transports used
611
mergeable, t = read_bundle(location_transport, filename)
612
except errors.NotABundle:
613
# Continue on considering this url a Branch but adjust the
615
location_transport = location_transport.clone(filename)
617
# A directory was provided, location_transport is correct
390
branch_to = Branch.open_containing(u'.')[0]
620
391
stored_loc = branch_to.get_parent()
621
392
if location is None:
622
393
if stored_loc is None:
623
raise errors.BzrCommandError("No pull location known or"
394
raise BzrCommandError("No pull location known or specified.")
626
display_url = urlutils.unescape_for_display(stored_loc,
628
self.outf.write("Using saved location: %s\n" % display_url)
396
print "Using saved location: %s" % stored_loc
629
397
location = stored_loc
630
location_transport = transport.get_transport(location)
632
if mergeable is not None:
633
if revision is not None:
634
raise errors.BzrCommandError(
635
'Cannot use -r with merge directives or bundles')
636
revision_id = mergeable.install_revisions(branch_to.repository)
637
branch_from = branch_to
399
br_from = Branch.open(location)
403
elif len(revision) == 1:
404
rev_id = revision[0].in_history(br_from).rev_id
639
branch_from = Branch.open_from_transport(location_transport)
641
if branch_to.get_parent() is None or remember:
642
branch_to.set_parent(branch_from.base)
644
if revision is not None:
645
if len(revision) == 1:
646
revision_id = revision[0].in_history(branch_from).rev_id
648
raise errors.BzrCommandError(
649
'bzr pull --revision takes one value.')
406
raise BzrCommandError('bzr pull --revision takes one value.')
651
408
old_rh = branch_to.revision_history()
652
409
if tree_to is not None:
653
result = tree_to.pull(branch_from, overwrite, revision_id,
654
delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
410
count = tree_to.pull(br_from, overwrite, rev_id)
656
result = branch_to.pull(branch_from, overwrite, revision_id)
658
result.report(self.outf)
412
count = branch_to.pull(br_from, overwrite, rev_id)
414
if branch_to.get_parent() is None or remember:
415
branch_to.set_parent(location)
416
note('%d revision(s) pulled.' % (count,))
660
from bzrlib.log import show_changed_revisions
661
419
new_rh = branch_to.revision_history()
662
show_changed_revisions(branch_to, old_rh, new_rh,
422
from bzrlib.log import show_changed_revisions
423
show_changed_revisions(branch_to, old_rh, new_rh)
666
426
class cmd_push(Command):
667
"""Update a mirror of this branch.
669
The target branch will not have its working tree populated because this
670
is both expensive, and is not supported on remote file systems.
672
Some smart servers or protocols *may* put the working tree in place in
427
"""Push this branch into another branch.
429
The remote branch will not have its working tree populated because this
430
is both expensive, and may not be supported on the remote file system.
432
Some smart servers or protocols *may* put the working tree in place.
434
If there is no default push location set, the first push will set it.
435
After that, you can omit the location to use the default. To change the
436
default, use --remember.
675
438
This command only works on branches that have not diverged. Branches are
676
considered diverged if the destination branch's most recent commit is one
677
that has not been merged (directly or indirectly) by the source branch.
439
considered diverged if the branch being pushed to is not an older version
679
442
If branches have diverged, you can use 'bzr push --overwrite' to replace
680
the other branch completely, discarding its unmerged changes.
443
the other branch completely.
682
445
If you want to ensure you have the different changes in the other branch,
683
do a merge (see bzr help merge) from the other branch, and commit that.
684
After that you will be able to do a push without '--overwrite'.
686
If there is no default push location set, the first push will set it.
687
After that, you can omit the location to use the default. To change the
688
default, use --remember. The value will only be saved if the remote
689
location can be accessed.
446
do a merge (see bzr help merge) from the other branch, and commit that
447
before doing a 'push --overwrite'.
692
_see_also = ['pull', 'update', 'working-trees']
693
takes_options = ['remember', 'overwrite', 'verbose',
694
Option('create-prefix',
695
help='Create the path leading up to the branch '
696
'if it does not already exist.'),
698
help='Branch to push from, '
699
'rather than the one containing the working directory.',
703
Option('use-existing-dir',
704
help='By default push will fail if the target'
705
' directory exists, but does not already'
706
' have a control directory. This flag will'
707
' allow push to proceed.'),
449
takes_options = ['remember', 'overwrite',
450
Option('create-prefix',
451
help='Create the path leading up to the branch '
452
'if it does not already exist')]
709
453
takes_args = ['location?']
710
encoding_type = 'replace'
712
455
def run(self, location=None, remember=False, overwrite=False,
713
create_prefix=False, verbose=False,
714
use_existing_dir=False,
456
create_prefix=False, verbose=False):
716
457
# FIXME: Way too big! Put this into a function called from the
718
if directory is None:
720
br_from = Branch.open_containing(directory)[0]
721
stored_loc = br_from.get_push_location()
459
from bzrlib.transport import get_transport
461
tree_from = WorkingTree.open_containing(u'.')[0]
462
br_from = tree_from.branch
463
stored_loc = tree_from.branch.get_push_location()
722
464
if location is None:
723
465
if stored_loc is None:
724
raise errors.BzrCommandError("No push location known or specified.")
466
raise BzrCommandError("No push location known or specified.")
726
display_url = urlutils.unescape_for_display(stored_loc,
728
self.outf.write("Using saved location: %s\n" % display_url)
468
print "Using saved location: %s" % stored_loc
729
469
location = stored_loc
731
to_transport = transport.get_transport(location)
733
br_to = repository_to = dir_to = None
735
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
736
except errors.NotBranchError:
737
pass # Didn't find anything
739
# If we can open a branch, use its direct repository, otherwise see
740
# if there is a repository without a branch.
742
br_to = dir_to.open_branch()
743
except errors.NotBranchError:
744
# Didn't find a branch, can we find a repository?
746
repository_to = dir_to.find_repository()
747
except errors.NoRepositoryPresent:
750
# Found a branch, so we must have found a repository
751
repository_to = br_to.repository
755
# The destination doesn't exist; create it.
756
# XXX: Refactor the create_prefix/no_create_prefix code into a
757
# common helper function
759
to_transport.mkdir('.')
760
except errors.FileExists:
761
if not use_existing_dir:
762
raise errors.BzrCommandError("Target directory %s"
763
" already exists, but does not have a valid .bzr"
764
" directory. Supply --use-existing-dir to push"
765
" there anyway." % location)
766
except errors.NoSuchFile:
767
if not create_prefix:
768
raise errors.BzrCommandError("Parent directory of %s"
770
"\nYou may supply --create-prefix to create all"
771
" leading parent directories."
773
_create_prefix(to_transport)
775
# Now the target directory exists, but doesn't have a .bzr
776
# directory. So we need to create it, along with any work to create
777
# all of the dependent branches, etc.
778
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
779
revision_id=br_from.last_revision())
471
dir_to = bzrlib.bzrdir.BzrDir.open(location)
780
472
br_to = dir_to.open_branch()
781
# TODO: Some more useful message about what was copied
782
note('Created new branch.')
783
# We successfully created the target, remember it
784
if br_from.get_push_location() is None or remember:
785
br_from.set_push_location(br_to.base)
786
elif repository_to is None:
787
# we have a bzrdir but no branch or repository
788
# XXX: Figure out what to do other than complain.
789
raise errors.BzrCommandError("At %s you have a valid .bzr control"
790
" directory, but not a branch or repository. This is an"
791
" unsupported configuration. Please move the target directory"
792
" out of the way and try again."
795
# We have a repository but no branch, copy the revisions, and then
473
except NotBranchError:
796
474
# create a branch.
797
last_revision_id = br_from.last_revision()
798
repository_to.fetch(br_from.repository,
799
revision_id=last_revision_id)
800
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
801
note('Created new branch.')
802
if br_from.get_push_location() is None or remember:
803
br_from.set_push_location(br_to.base)
804
else: # We have a valid to branch
805
# We were able to connect to the remote location, so remember it
806
# we don't need to successfully push because of possible divergence.
807
if br_from.get_push_location() is None or remember:
808
br_from.set_push_location(br_to.base)
809
old_rh = br_to.revision_history()
475
transport = get_transport(location).clone('..')
476
if not create_prefix:
812
tree_to = dir_to.open_workingtree()
813
except errors.NotLocalUrl:
814
warning("This transport does not update the working "
815
"tree of: %s. See 'bzr help working-trees' for "
816
"more information." % br_to.base)
817
push_result = br_from.push(br_to, overwrite)
818
except errors.NoWorkingTree:
819
push_result = br_from.push(br_to, overwrite)
478
transport.mkdir(transport.relpath(location))
480
raise BzrCommandError("Parent directory of %s "
481
"does not exist." % location)
483
current = transport.base
484
needed = [(transport, transport.relpath(location))]
823
push_result = br_from.push(tree_to.branch, overwrite)
827
except errors.DivergedBranches:
828
raise errors.BzrCommandError('These branches have diverged.'
829
' Try using "merge" and then "push".')
830
if push_result is not None:
831
push_result.report(self.outf)
487
transport, relpath = needed[-1]
488
transport.mkdir(relpath)
491
new_transport = transport.clone('..')
492
needed.append((new_transport,
493
new_transport.relpath(transport.base)))
494
if new_transport.base == transport.base:
495
raise BzrCommandError("Could not creeate "
497
dir_to = br_from.bzrdir.clone(location)
498
br_to = dir_to.open_branch()
499
old_rh = br_to.revision_history()
502
tree_to = dir_to.open_workingtree()
503
except errors.NotLocalUrl:
504
# TODO: This should be updated for branches which don't have a
505
# working tree, as opposed to ones where we just couldn't
507
warning('Unable to update the working tree of: %s' % (br_to.base,))
508
count = br_to.pull(br_from, overwrite)
509
except NoWorkingTree:
510
count = br_to.pull(br_from, overwrite)
512
count = tree_to.pull(br_from, overwrite)
513
except DivergedBranches:
514
raise BzrCommandError("These branches have diverged."
515
" Try a merge then push with overwrite.")
516
if br_from.get_push_location() is None or remember:
517
br_from.set_push_location(location)
518
note('%d revision(s) pushed.' % (count,))
833
521
new_rh = br_to.revision_history()
834
522
if old_rh != new_rh:
835
523
# Something changed
836
524
from bzrlib.log import show_changed_revisions
837
show_changed_revisions(br_to, old_rh, new_rh,
840
# we probably did a clone rather than a push, so a message was
525
show_changed_revisions(br_to, old_rh, new_rh)
845
528
class cmd_branch(Command):
914
608
class cmd_checkout(Command):
915
609
"""Create a new checkout of an existing branch.
917
If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
918
the branch found in '.'. This is useful if you have removed the working tree
919
or if it was never created - i.e. if you pushed the branch to its current
922
611
If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
923
612
be used. In other words, "checkout ../foo/bar" will attempt to create ./bar.
924
If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
925
is derived from the BRANCH_LOCATION by stripping a leading scheme or drive
926
identifier, if any. For example, "checkout lp:foo-bar" will attempt to
929
614
To retrieve the branch as of a particular revision, supply the --revision
930
615
parameter, as in "checkout foo/bar -r 5". Note that this will be immediately
931
616
out of date [so you cannot commit] but it may be useful (i.e. to examine old
619
--basis is to speed up checking out from remote branches. When specified, it
620
uses the inventory and file contents from the basis branch in preference to the
621
branch being checked out. [Not implemented yet.]
935
_see_also = ['checkouts', 'branch']
936
takes_args = ['branch_location?', 'to_location?']
937
takes_options = ['revision',
623
takes_args = ['branch_location', 'to_location?']
624
takes_options = ['revision', # , 'basis']
938
625
Option('lightweight',
939
help="Perform a lightweight checkout. Lightweight "
626
help="perform a lightweight checkout. Lightweight "
940
627
"checkouts depend on access to the branch for "
941
"every operation. Normal checkouts can perform "
628
"every operation. Normal checkouts can perform "
942
629
"common operations like diff and status without "
943
630
"such access, and also support local commits."
948
def run(self, branch_location=None, to_location=None, revision=None,
634
def run(self, branch_location, to_location=None, revision=None, basis=None,
949
635
lightweight=False):
950
636
if revision is None:
951
637
revision = [None]
952
638
elif len(revision) > 1:
953
raise errors.BzrCommandError(
639
raise BzrCommandError(
954
640
'bzr checkout --revision takes exactly 1 revision value')
955
if branch_location is None:
956
branch_location = osutils.getcwd()
957
to_location = branch_location
958
641
source = Branch.open(branch_location)
959
642
if len(revision) == 1 and revision[0] is not None:
960
643
revision_id = revision[0].in_history(source)[1]
962
645
revision_id = None
963
646
if to_location is None:
964
to_location = urlutils.derive_to_location(branch_location)
965
# if the source and to_location are the same,
966
# and there is no working tree,
967
# then reconstitute a branch
968
if (osutils.abspath(to_location) ==
969
osutils.abspath(branch_location)):
971
source.bzrdir.open_workingtree()
972
except errors.NoWorkingTree:
973
source.bzrdir.create_workingtree()
647
to_location = os.path.basename(branch_location.rstrip("/\\"))
976
649
os.mkdir(to_location)
977
650
except OSError, e:
978
651
if e.errno == errno.EEXIST:
979
raise errors.BzrCommandError('Target directory "%s" already'
980
' exists.' % to_location)
652
raise BzrCommandError('Target directory "%s" already'
653
' exists.' % to_location)
981
654
if e.errno == errno.ENOENT:
982
raise errors.BzrCommandError('Parent of "%s" does not exist.'
655
raise BzrCommandError('Parent of "%s" does not exist.' %
986
source.create_checkout(to_location, revision_id, lightweight)
659
old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
660
bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
663
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
664
bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
666
checkout_branch = bzrlib.bzrdir.BzrDir.create_branch_convenience(
667
to_location, force_new_tree=False)
668
checkout = checkout_branch.bzrdir
669
checkout_branch.bind(source)
670
if revision_id is not None:
671
rh = checkout_branch.revision_history()
672
checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
673
checkout.create_workingtree(revision_id)
675
bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
989
678
class cmd_renames(Command):
1068
731
class cmd_info(Command):
1069
"""Show information about a working tree, branch or repository.
1071
This command will show all known locations and formats associated to the
1072
tree, branch or repository. Statistical information is included with
1075
Branches and working trees will also report any missing revisions.
1077
_see_also = ['revno', 'working-trees', 'repositories']
1078
takes_args = ['location?']
1079
takes_options = ['verbose']
732
"""Show statistical information about a branch."""
733
takes_args = ['branch?']
1081
735
@display_command
1082
def run(self, location=None, verbose=0):
1083
from bzrlib.info import show_bzrdir_info
1084
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
736
def run(self, branch=None):
738
bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0])
1088
741
class cmd_remove(Command):
1089
"""Remove files or directories.
1091
This makes bzr stop tracking changes to the specified files and
1092
delete them if they can easily be recovered using revert.
1094
You can specify one or more files, and/or --new. If you specify --new,
1095
only 'added' files will be removed. If you specify both, then new files
1096
in the specified directories will be removed. If the directories are
1097
also new, they will also be removed.
742
"""Make a file unversioned.
744
This makes bzr stop tracking changes to a versioned file. It does
745
not delete the working copy.
1099
takes_args = ['file*']
1100
takes_options = ['verbose',
1101
Option('new', help='Remove newly-added files.'),
1102
RegistryOption.from_kwargs('file-deletion-strategy',
1103
'The file deletion mode to be used',
1104
title='Deletion Strategy', value_switches=True, enum_switch=False,
1105
safe='Only delete files if they can be'
1106
' safely recovered (default).',
1107
keep="Don't delete any files.",
1108
force='Delete all the specified files, even if they can not be '
1109
'recovered and even if they are non-empty directories.')]
747
takes_args = ['file+']
748
takes_options = ['verbose']
1110
749
aliases = ['rm']
1111
encoding_type = 'replace'
1113
def run(self, file_list, verbose=False, new=False,
1114
file_deletion_strategy='safe'):
751
def run(self, file_list, verbose=False):
1115
752
tree, file_list = tree_files(file_list)
1117
if file_list is not None:
1118
file_list = [f for f in file_list if f != '']
1120
raise errors.BzrCommandError('Specify one or more files to'
1121
' remove, or use --new.')
1124
added = tree.changes_from(tree.basis_tree(),
1125
specific_files=file_list).added
1126
file_list = sorted([f[0] for f in added], reverse=True)
1127
if len(file_list) == 0:
1128
raise errors.BzrCommandError('No matching files.')
1129
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1130
keep_files=file_deletion_strategy=='keep',
1131
force=file_deletion_strategy=='force')
753
tree.remove(file_list, verbose=verbose)
1134
756
class cmd_file_id(Command):
1267
852
bzr commit -m 'imported project'
1270
_see_also = ['init-repo', 'branch', 'checkout']
1271
854
takes_args = ['location?']
1272
855
takes_options = [
1273
Option('create-prefix',
1274
help='Create the path leading up to the branch '
1275
'if it does not already exist.'),
1276
RegistryOption('format',
1277
help='Specify a format for this branch. '
1278
'See "help formats".',
1279
registry=bzrdir.format_registry,
1280
converter=bzrdir.format_registry.make_bzrdir,
1281
value_switches=True,
1282
title="Branch Format",
1284
Option('append-revisions-only',
1285
help='Never change revnos or the existing log.'
1286
' Append revisions to it only.')
1288
def run(self, location=None, format=None, append_revisions_only=False,
1289
create_prefix=False):
1291
format = bzrdir.format_registry.make_bzrdir('default')
857
help='Create a specific format rather than the'
858
' current default format. Currently this '
859
' option only accepts =metadir',
860
type=get_format_type),
862
def run(self, location=None, format=None):
863
from bzrlib.branch import Branch
1292
864
if location is None:
1295
to_transport = transport.get_transport(location)
1297
# The path has to exist to initialize a
1298
# branch inside of it.
1299
# Just using os.mkdir, since I don't
1300
# believe that we want to create a bunch of
1301
# locations if the user supplies an extended path
1303
to_transport.ensure_base()
1304
except errors.NoSuchFile:
1305
if not create_prefix:
1306
raise errors.BzrCommandError("Parent directory of %s"
1308
"\nYou may supply --create-prefix to create all"
1309
" leading parent directories."
1311
_create_prefix(to_transport)
1314
existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1315
except errors.NotBranchError:
1316
# really a NotBzrDir error...
1317
create_branch = bzrdir.BzrDir.create_branch_convenience
1318
branch = create_branch(to_transport.base, format=format,
1319
possible_transports=[to_transport])
1321
from bzrlib.transport.local import LocalTransport
1322
if existing_bzrdir.has_branch():
1323
if (isinstance(to_transport, LocalTransport)
1324
and not existing_bzrdir.has_workingtree()):
1325
raise errors.BranchExistsWithoutWorkingTree(location)
1326
raise errors.AlreadyBranchError(location)
1328
branch = existing_bzrdir.create_branch()
1329
existing_bzrdir.create_workingtree()
1330
if append_revisions_only:
1332
branch.set_append_revisions_only(True)
1333
except errors.UpgradeRequired:
1334
raise errors.BzrCommandError('This branch format cannot be set'
1335
' to append-revisions-only. Try --experimental-branch6')
867
# The path has to exist to initialize a
868
# branch inside of it.
869
# Just using os.mkdir, since I don't
870
# believe that we want to create a bunch of
871
# locations if the user supplies an extended path
872
if not os.path.exists(location):
874
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1338
877
class cmd_init_repository(Command):
1339
"""Create a shared repository to hold branches.
1341
New branches created under the repository directory will store their
1342
revisions in the repository, not in the branch directory.
1344
If the --no-trees option is used then the branches in the repository
1345
will not have working trees by default.
1348
bzr init-repo --no-trees repo
1350
bzr checkout --lightweight repo/trunk trunk-checkout
1354
See 'bzr help repositories' for more information.
1357
_see_also = ['init', 'branch', 'checkout']
1358
takes_args = ["location"]
1359
takes_options = [RegistryOption('format',
1360
help='Specify a format for this repository. See'
1361
' "bzr help formats" for details.',
1362
registry=bzrdir.format_registry,
1363
converter=bzrdir.format_registry.make_bzrdir,
1364
value_switches=True, title='Repository format'),
1366
help='Branches in the repository will default to'
1367
' not having a working tree.'),
878
"""Create a shared repository to keep branches in."""
879
takes_args = ["location"]
880
takes_options = [Option('format',
881
help='Use a specific format rather than the'
882
' current default format. Currently this '
883
' option only accepts "metadir" and "knit"',
884
type=get_format_type)]
1369
885
aliases = ["init-repo"]
1371
def run(self, location, format=None, no_trees=False):
886
def run(self, location, format=None):
887
from bzrlib.bzrdir import BzrDirMetaFormat1
888
from bzrlib.transport import get_transport
1372
889
if format is None:
1373
format = bzrdir.format_registry.make_bzrdir('default')
1375
if location is None:
1378
to_transport = transport.get_transport(location)
1379
to_transport.ensure_base()
1381
newdir = format.initialize_on_transport(to_transport)
890
format = BzrDirMetaFormat1()
891
get_transport(location).mkdir('')
892
newdir = format.initialize(location)
1382
893
repo = newdir.create_repository(shared=True)
1383
repo.set_make_working_trees(not no_trees)
894
repo.set_make_working_trees(False)
1386
897
class cmd_diff(Command):
1387
"""Show differences in the working tree or between revisions.
898
"""Show differences in working tree.
1389
900
If files are listed, only the changes in those files are listed.
1390
901
Otherwise, all changes for the tree are listed.
1392
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1393
produces patches suitable for "patch -p1".
1397
Shows the difference in the working tree versus the last commit
1399
Difference between the working tree and revision 1
1401
Difference between revision 2 and revision 1
1402
bzr diff --prefix old/:new/
1403
Same as 'bzr diff' but prefix paths with old/ and new/
1404
bzr diff bzr.mine bzr.dev
1405
Show the differences between the two working trees
1407
Show just the differences for 'foo.c'
908
# TODO: Allow diff across branches.
1409
909
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1410
910
# or a graphical diff.
1412
912
# TODO: Python difflib is not exactly the same as unidiff; should
1413
913
# either fix it up or prefer to use an external diff.
915
# TODO: If a directory is given, diff everything under that.
1415
917
# TODO: Selected-file diff is inefficient and doesn't show you
1416
918
# deleted files.
1418
920
# TODO: This probably handles non-Unix newlines poorly.
1420
_see_also = ['status']
1421
922
takes_args = ['file*']
1423
Option('diff-options', type=str,
1424
help='Pass these options to the external diff program.'),
1425
Option('prefix', type=str,
1427
help='Set prefixes to added to old and new filenames, as '
1428
'two values separated by a colon. (eg "old/:new/").'),
923
takes_options = ['revision', 'diff-options']
1431
924
aliases = ['di', 'dif']
1432
encoding_type = 'exact'
1434
926
@display_command
1435
def run(self, revision=None, file_list=None, diff_options=None,
927
def run(self, revision=None, file_list=None, diff_options=None):
1437
928
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1439
if (prefix is None) or (prefix == '0'):
1447
old_label, new_label = prefix.split(":")
1449
raise errors.BzrCommandError(
1450
'--prefix expects two values separated by a colon'
1451
' (eg "old/:new/")')
1453
if revision and len(revision) > 2:
1454
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1455
' one or two revision specifiers')
1458
930
tree1, file_list = internal_tree_files(file_list)
1462
except errors.FileInWrongBranch:
934
except FileInWrongBranch:
1463
935
if len(file_list) != 2:
1464
raise errors.BzrCommandError("Files are in different branches")
936
raise BzrCommandError("Files are in different branches")
1466
938
tree1, file1 = WorkingTree.open_containing(file_list[0])
1467
939
tree2, file2 = WorkingTree.open_containing(file_list[1])
1468
940
if file1 != "" or file2 != "":
1469
941
# FIXME diff those two files. rbc 20051123
1470
raise errors.BzrCommandError("Files are in different branches")
942
raise BzrCommandError("Files are in different branches")
1471
943
file_list = None
1472
except errors.NotBranchError:
1473
if (revision is not None and len(revision) == 2
1474
and not revision[0].needs_branch()
1475
and not revision[1].needs_branch()):
1476
# If both revision specs include a branch, we can
1477
# diff them without needing a local working tree
1478
tree1, tree2 = None, None
1482
if tree2 is not None:
1483
if revision is not None:
1484
# FIXME: but there should be a clean way to diff between
1485
# non-default versions of two trees, it's not hard to do
1487
raise errors.BzrCommandError(
1488
"Sorry, diffing arbitrary revisions across branches "
1489
"is not implemented yet")
1490
return show_diff_trees(tree1, tree2, sys.stdout,
1491
specific_files=file_list,
1492
external_diff_options=diff_options,
1493
old_label=old_label, new_label=new_label)
1495
return diff_cmd_helper(tree1, file_list, diff_options,
1496
revision_specs=revision,
1497
old_label=old_label, new_label=new_label)
944
if revision is not None:
945
if tree2 is not None:
946
raise BzrCommandError("Can't specify -r with two branches")
947
if (len(revision) == 1) or (revision[1].spec is None):
948
return diff_cmd_helper(tree1, file_list, diff_options,
950
elif len(revision) == 2:
951
return diff_cmd_helper(tree1, file_list, diff_options,
952
revision[0], revision[1])
954
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
956
if tree2 is not None:
957
return show_diff_trees(tree1, tree2, sys.stdout,
958
specific_files=file_list,
959
external_diff_options=diff_options)
961
return diff_cmd_helper(tree1, file_list, diff_options)
1500
964
class cmd_deleted(Command):
1506
970
# directories with readdir, rather than stating each one. Same
1507
971
# level of effort but possibly much less IO. (Or possibly not,
1508
972
# if the directories are very large...)
1509
_see_also = ['status', 'ls']
1510
takes_options = ['show-ids']
1512
973
@display_command
1513
974
def run(self, show_ids=False):
1514
975
tree = WorkingTree.open_containing(u'.')[0]
1517
old = tree.basis_tree()
1520
for path, ie in old.inventory.iter_entries():
1521
if not tree.has_id(ie.file_id):
1522
self.outf.write(path)
1524
self.outf.write(' ')
1525
self.outf.write(ie.file_id)
1526
self.outf.write('\n')
976
old = tree.basis_tree()
977
for path, ie in old.inventory.iter_entries():
978
if not tree.has_id(ie.file_id):
980
print '%-50s %s' % (path, ie.file_id)
1533
985
class cmd_modified(Command):
1534
"""List files modified in working tree.
986
"""List files modified in working tree."""
1538
_see_also = ['status', 'ls']
1540
988
@display_command
990
from bzrlib.delta import compare_trees
1542
992
tree = WorkingTree.open_containing(u'.')[0]
1543
td = tree.changes_from(tree.basis_tree())
993
td = compare_trees(tree.basis_tree(), tree)
1544
995
for path, id, kind, text_modified, meta_modified in td.modified:
1545
self.outf.write(path + '\n')
1548
1000
class cmd_added(Command):
1549
"""List files added in working tree.
1001
"""List files added in working tree."""
1553
_see_also = ['status', 'ls']
1555
1003
@display_command
1557
1005
wt = WorkingTree.open_containing(u'.')[0]
1560
basis = wt.basis_tree()
1563
basis_inv = basis.inventory
1566
if file_id in basis_inv:
1568
if inv.is_root(file_id) and len(basis_inv) == 0:
1570
path = inv.id2path(file_id)
1571
if not os.access(osutils.abspath(path), os.F_OK):
1573
self.outf.write(path + '\n')
1006
basis_inv = wt.basis_tree().inventory
1009
if file_id in basis_inv:
1011
path = inv.id2path(file_id)
1012
if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
1580
1018
class cmd_root(Command):
1581
1019
"""Show the tree root directory.
1583
1021
The root is the nearest enclosing directory with a .bzr control
1586
1023
takes_args = ['filename?']
1587
1024
@display_command
1588
1025
def run(self, filename=None):
1589
1026
"""Print the branch root."""
1590
1027
tree = WorkingTree.open_containing(filename)[0]
1591
self.outf.write(tree.basedir + '\n')
1594
def _parse_limit(limitstring):
1596
return int(limitstring)
1598
msg = "The limit argument must be an integer."
1599
raise errors.BzrCommandError(msg)
1602
1031
class cmd_log(Command):
1603
"""Show log of a branch, file, or directory.
1605
By default show the log of the branch containing the working directory.
1032
"""Show log of this branch.
1607
1034
To request a range of logs, you can use the command -r begin..end
1608
1035
-r revision requests a specific revision, -r ..end or -r begin.. are
1614
bzr log -r -10.. http://server/branch
1617
1039
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1619
takes_args = ['location?']
1622
help='Show from oldest to newest.'),
1625
help='Display timezone as local, original, or utc.'),
1628
help='Show files changed in each revision.'),
1634
help='Show revisions whose message matches this '
1635
'regular expression.',
1638
help='Limit the output to the first N revisions.',
1642
encoding_type = 'replace'
1041
takes_args = ['filename?']
1042
takes_options = [Option('forward',
1043
help='show from oldest to newest'),
1044
'timezone', 'verbose',
1045
'show-ids', 'revision',
1049
help='show revisions whose message matches this regexp',
1644
1053
@display_command
1645
def run(self, location=None, timezone='original',
1054
def run(self, filename=None, timezone='original',
1647
1056
show_ids=False,
1650
1059
log_format=None,
1653
from bzrlib.log import show_log
1064
from bzrlib.log import log_formatter, show_log
1654
1066
assert message is None or isinstance(message, basestring), \
1655
1067
"invalid message argument %r" % message
1656
1068
direction = (forward and 'forward') or 'reverse'
1658
1070
# log everything
1661
1073
# find the file id to log:
1663
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1075
dir, fp = bzrdir.BzrDir.open_containing(filename)
1076
b = dir.open_branch()
1667
tree = b.basis_tree()
1668
file_id = tree.path2id(fp)
1670
raise errors.BzrCommandError(
1671
"Path does not have any revision history: %s" %
1080
inv = dir.open_workingtree().inventory
1081
except (errors.NotBranchError, errors.NotLocalUrl):
1082
# either no tree, or is remote.
1083
inv = b.basis_tree().inventory
1084
file_id = inv.path2id(fp)
1674
1086
# local dir only
1675
1087
# FIXME ? log the current subdir only RBC 20060203
1676
if revision is not None \
1677
and len(revision) > 0 and revision[0].get_branch():
1678
location = revision[0].get_branch()
1681
dir, relpath = bzrdir.BzrDir.open_containing(location)
1088
dir, relpath = bzrdir.BzrDir.open_containing('.')
1682
1089
b = dir.open_branch()
1686
if revision is None:
1689
elif len(revision) == 1:
1690
rev1 = rev2 = revision[0].in_history(b)
1691
elif len(revision) == 2:
1692
if revision[1].get_branch() != revision[0].get_branch():
1693
# b is taken from revision[0].get_branch(), and
1694
# show_log will use its revision_history. Having
1695
# different branches will lead to weird behaviors.
1696
raise errors.BzrCommandError(
1697
"Log doesn't accept two revisions in different"
1699
rev1 = revision[0].in_history(b)
1700
rev2 = revision[1].in_history(b)
1702
raise errors.BzrCommandError(
1703
'bzr log --revision takes one or two values.')
1705
if log_format is None:
1706
log_format = log.log_formatter_registry.get_default(b)
1708
lf = log_format(show_ids=show_ids, to_file=self.outf,
1709
show_timezone=timezone)
1715
direction=direction,
1716
start_revision=rev1,
1091
if revision is None:
1094
elif len(revision) == 1:
1095
rev1 = rev2 = revision[0].in_history(b).revno
1096
elif len(revision) == 2:
1097
if revision[0].spec is None:
1098
# missing begin-range means first revision
1101
rev1 = revision[0].in_history(b).revno
1103
if revision[1].spec is None:
1104
# missing end-range means last known revision
1107
rev2 = revision[1].in_history(b).revno
1109
raise BzrCommandError('bzr log --revision takes one or two values.')
1111
# By this point, the revision numbers are converted to the +ve
1112
# form if they were supplied in the -ve form, so we can do
1113
# this comparison in relative safety
1115
(rev2, rev1) = (rev1, rev2)
1117
mutter('encoding log as %r', bzrlib.user_encoding)
1119
# use 'replace' so that we don't abort if trying to write out
1120
# in e.g. the default C locale.
1121
outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
1123
if (log_format == None):
1124
default = bzrlib.config.BranchConfig(b).log_format()
1125
log_format = get_log_format(long=long, short=short, line=line, default=default)
1127
lf = log_formatter(log_format,
1130
show_timezone=timezone)
1136
direction=direction,
1137
start_revision=rev1,
1724
1142
def get_log_format(long=False, short=False, line=False, default='long'):
1735
1153
class cmd_touching_revisions(Command):
1736
1154
"""Return revision-ids which affected a particular file.
1738
A more user-friendly interface is "bzr log FILE".
1156
A more user-friendly interface is "bzr log FILE"."""
1742
1158
takes_args = ["filename"]
1744
1159
@display_command
1745
1160
def run(self, filename):
1746
1161
tree, relpath = WorkingTree.open_containing(filename)
1747
1162
b = tree.branch
1748
file_id = tree.path2id(relpath)
1749
for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1750
self.outf.write("%6d %s\n" % (revno, what))
1163
inv = tree.read_working_inventory()
1164
file_id = inv.path2id(relpath)
1165
for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
1166
print "%6d %s" % (revno, what)
1753
1169
class cmd_ls(Command):
1754
1170
"""List files in a tree.
1757
_see_also = ['status', 'cat']
1758
takes_args = ['path?']
1759
1172
# TODO: Take a revision or remote path and list that tree instead.
1763
Option('non-recursive',
1764
help='Don\'t recurse into subdirectories.'),
1766
help='Print paths relative to the root of the branch.'),
1767
Option('unknown', help='Print unknown files.'),
1768
Option('versioned', help='Print versioned files.'),
1769
Option('ignored', help='Print ignored files.'),
1771
help='Write an ascii NUL (\\0) separator '
1772
'between files rather than a newline.'),
1774
help='List entries of a particular kind: file, directory, symlink.',
1174
takes_options = ['verbose', 'revision',
1175
Option('non-recursive',
1176
help='don\'t recurse into sub-directories'),
1178
help='Print all paths from the root of the branch.'),
1179
Option('unknown', help='Print unknown files'),
1180
Option('versioned', help='Print versioned files'),
1181
Option('ignored', help='Print ignored files'),
1183
Option('null', help='Null separate the files'),
1778
1185
@display_command
1779
def run(self, revision=None, verbose=False,
1186
def run(self, revision=None, verbose=False,
1780
1187
non_recursive=False, from_root=False,
1781
1188
unknown=False, versioned=False, ignored=False,
1782
null=False, kind=None, show_ids=False, path=None):
1784
if kind and kind not in ('file', 'directory', 'symlink'):
1785
raise errors.BzrCommandError('invalid kind specified')
1787
1191
if verbose and null:
1788
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1192
raise BzrCommandError('Cannot set both --verbose and --null')
1789
1193
all = not (unknown or versioned or ignored)
1791
1195
selection = {'I':ignored, '?':unknown, 'V':versioned}
1798
raise errors.BzrCommandError('cannot specify both --from-root'
1802
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1197
tree, relpath = WorkingTree.open_containing(u'.')
1808
1202
if revision is not None:
1809
tree = branch.repository.revision_tree(
1810
revision[0].in_history(branch).rev_id)
1812
tree = branch.basis_tree()
1816
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1817
if fp.startswith(relpath):
1818
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1819
if non_recursive and '/' in fp:
1821
if not all and not selection[fc]:
1823
if kind is not None and fkind != kind:
1826
kindch = entry.kind_character()
1827
outstring = '%-8s %s%s' % (fc, fp, kindch)
1828
if show_ids and fid is not None:
1829
outstring = "%-50s %s" % (outstring, fid)
1830
self.outf.write(outstring + '\n')
1832
self.outf.write(fp + '\0')
1835
self.outf.write(fid)
1836
self.outf.write('\0')
1844
self.outf.write('%-50s %s\n' % (fp, my_id))
1846
self.outf.write(fp + '\n')
1203
tree = tree.branch.repository.revision_tree(
1204
revision[0].in_history(tree.branch).rev_id)
1205
for fp, fc, kind, fid, entry in tree.list_files():
1206
if fp.startswith(relpath):
1207
fp = fp[len(relpath):]
1208
if non_recursive and '/' in fp:
1210
if not all and not selection[fc]:
1213
kindch = entry.kind_character()
1214
print '%-8s %s%s' % (fc, fp, kindch)
1216
sys.stdout.write(fp)
1217
sys.stdout.write('\0')
1851
1223
class cmd_unknowns(Command):
1852
"""List unknown files.
1224
"""List unknown files."""
1858
1225
@display_command
1227
from bzrlib.osutils import quotefn
1860
1228
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1861
self.outf.write(osutils.quotefn(f) + '\n')
1864
1232
class cmd_ignore(Command):
1865
"""Ignore specified files or patterns.
1233
"""Ignore a command or pattern.
1867
1235
To remove patterns from the ignore list, edit the .bzrignore file.
1869
Trailing slashes on patterns are ignored.
1870
If the pattern contains a slash or is a regular expression, it is compared
1871
to the whole path from the branch root. Otherwise, it is compared to only
1872
the last component of the path. To match a file only in the root
1873
directory, prepend './'.
1875
Ignore patterns specifying absolute paths are not allowed.
1877
Ignore patterns may include globbing wildcards such as:
1878
? - Matches any single character except '/'
1879
* - Matches 0 or more characters except '/'
1880
/**/ - Matches 0 or more directories in a path
1881
[a-z] - Matches a single character from within a group of characters
1883
Ignore patterns may also be Python regular expressions.
1884
Regular expression ignore patterns are identified by a 'RE:' prefix
1885
followed by the regular expression. Regular expression ignore patterns
1886
may not include named or numbered groups.
1888
Note: ignore patterns containing shell wildcards must be quoted from
1237
If the pattern contains a slash, it is compared to the whole path
1238
from the branch root. Otherwise, it is compared to only the last
1239
component of the path. To match a file only in the root directory,
1242
Ignore patterns are case-insensitive on case-insensitive systems.
1244
Note: wildcards must be quoted from the shell on Unix.
1892
1247
bzr ignore ./Makefile
1893
1248
bzr ignore '*.class'
1894
bzr ignore 'lib/**/*.o'
1895
bzr ignore 'RE:lib/.*\.o'
1898
_see_also = ['status', 'ignored']
1899
takes_args = ['name_pattern*']
1901
Option('old-default-rules',
1902
help='Write out the ignore rules bzr < 0.9 always used.')
1250
# TODO: Complain if the filename is absolute
1251
takes_args = ['name_pattern']
1905
def run(self, name_pattern_list=None, old_default_rules=None):
1253
def run(self, name_pattern):
1906
1254
from bzrlib.atomicfile import AtomicFile
1907
if old_default_rules is not None:
1908
# dump the rules and exit
1909
for pattern in ignores.OLD_DEFAULTS:
1912
if not name_pattern_list:
1913
raise errors.BzrCommandError("ignore requires at least one "
1914
"NAME_PATTERN or --old-default-rules")
1915
name_pattern_list = [globbing.normalize_pattern(p)
1916
for p in name_pattern_list]
1917
for name_pattern in name_pattern_list:
1918
if (name_pattern[0] == '/' or
1919
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1920
raise errors.BzrCommandError(
1921
"NAME_PATTERN should not be an absolute path")
1922
1257
tree, relpath = WorkingTree.open_containing(u'.')
1923
1258
ifn = tree.abspath('.bzrignore')
1924
1260
if os.path.exists(ifn):
1925
1261
f = open(ifn, 'rt')
2152
1423
# XXX: verbose currently does nothing
2154
_see_also = ['bugs', 'uncommit']
2155
1425
takes_args = ['selected*']
2157
Option('message', type=unicode,
2159
help="Description of the new revision."),
2162
help='Commit even if nothing has changed.'),
2163
Option('file', type=str,
2166
help='Take commit message from this file.'),
2168
help="Refuse to commit if there are unknown "
2169
"files in the working tree."),
2170
ListOption('fixes', type=str,
2171
help="Mark a bug as being fixed by this revision."),
2173
help="Perform a local commit in a bound "
2174
"branch. Local commits are not pushed to "
2175
"the master branch until a normal commit "
1426
takes_options = ['message', 'verbose',
1428
help='commit even if nothing has changed'),
1429
Option('file', type=str,
1431
help='file containing commit message'),
1433
help="refuse to commit if there are unknown "
1434
"files in the working tree."),
1436
help="perform a local only commit in a bound "
1437
"branch. Such commits are not pushed to "
1438
"the master branch until a normal commit "
2179
1442
aliases = ['ci', 'checkin']
2181
def _get_bug_fix_properties(self, fixes, branch):
2183
# Configure the properties for bug fixing attributes.
2184
for fixed_bug in fixes:
2185
tokens = fixed_bug.split(':')
2186
if len(tokens) != 2:
2187
raise errors.BzrCommandError(
2188
"Invalid bug %s. Must be in the form of 'tag:id'. "
2189
"Commit refused." % fixed_bug)
2190
tag, bug_id = tokens
2192
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2193
except errors.UnknownBugTrackerAbbreviation:
2194
raise errors.BzrCommandError(
2195
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2196
except errors.MalformedBugIdentifier:
2197
raise errors.BzrCommandError(
2198
"Invalid bug identifier for %s. Commit refused."
2200
properties.append('%s fixed' % bug_url)
2201
return '\n'.join(properties)
2203
1444
def run(self, message=None, file=None, verbose=True, selected_list=None,
2204
unchanged=False, strict=False, local=False, fixes=None):
1445
unchanged=False, strict=False, local=False):
2205
1446
from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
2206
1447
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
2207
1448
StrictCommitFailed)
2208
1449
from bzrlib.msgeditor import edit_commit_message, \
2209
1450
make_commit_message_template
1451
from tempfile import TemporaryFile
2211
1454
# TODO: Need a blackbox test for invoking the external editor; may be
2212
1455
# slightly problematic to run this cross-platform.
2214
1457
# TODO: do more checks that the commit will succeed before
2215
1458
# spending the user's valuable time typing a commit message.
1460
# TODO: if the commit *does* happen to fail, then save the commit
1461
# message to a temporary file where it can be recovered
2219
1462
tree, selected_list = tree_files(selected_list)
2220
if selected_list == ['']:
2221
# workaround - commit of root of tree should be exactly the same
2222
# as just default commit in that tree, and succeed even though
2223
# selected-file merge commit is not done yet
2226
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2228
properties['bugs'] = bug_property
2230
1463
if local and not tree.branch.get_bound_location():
2231
1464
raise errors.LocalRequiresBoundBranch()
2233
def get_message(commit_obj):
2234
"""Callback to get commit message"""
2235
my_message = message
2236
if my_message is None and not file:
2237
template = make_commit_message_template(tree, selected_list)
2238
my_message = edit_commit_message(template)
2239
if my_message is None:
2240
raise errors.BzrCommandError("please specify a commit"
2241
" message with either --message or --file")
2242
elif my_message and file:
2243
raise errors.BzrCommandError(
2244
"please specify either --message or --file")
2246
my_message = codecs.open(file, 'rt',
2247
bzrlib.user_encoding).read()
2248
if my_message == "":
2249
raise errors.BzrCommandError("empty commit message specified")
1465
if message is None and not file:
1466
template = make_commit_message_template(tree, selected_list)
1467
message = edit_commit_message(template)
1469
raise BzrCommandError("please specify a commit message"
1470
" with either --message or --file")
1471
elif message and file:
1472
raise BzrCommandError("please specify either --message or --file")
1476
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1479
raise BzrCommandError("empty commit message specified")
2253
1482
reporter = ReportCommitToLog()
2255
1484
reporter = NullCommitReporter()
2258
tree.commit(message_callback=get_message,
2259
specific_files=selected_list,
1487
tree.commit(message, specific_files=selected_list,
2260
1488
allow_pointless=unchanged, strict=strict, local=local,
2261
reporter=reporter, revprops=properties)
2262
1490
except PointlessCommit:
2263
1491
# FIXME: This should really happen before the file is read in;
2264
1492
# perhaps prepare the commit; get the message; then actually commit
2265
raise errors.BzrCommandError("no changes to commit."
2266
" use --unchanged to commit anyhow")
1493
raise BzrCommandError("no changes to commit",
1494
["use --unchanged to commit anyhow"])
2267
1495
except ConflictsInTree:
2268
raise errors.BzrCommandError('Conflicts detected in working '
2269
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
1496
raise BzrCommandError("Conflicts detected in working tree. "
1497
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
2271
1498
except StrictCommitFailed:
2272
raise errors.BzrCommandError("Commit refused because there are"
2273
" unknown files in the working tree.")
1499
raise BzrCommandError("Commit refused because there are unknown "
1500
"files in the working tree.")
2274
1501
except errors.BoundBranchOutOfDate, e:
2275
raise errors.BzrCommandError(str(e) + "\n"
2276
'To commit to master branch, run update and then commit.\n'
2277
'You can also pass --local to commit to continue working '
1502
raise BzrCommandError(str(e)
1503
+ ' Either unbind, update, or'
1504
' pass --local to commit.')
2281
1507
class cmd_check(Command):
2441
1633
if typestring == "memory":
2442
1634
from bzrlib.transport.memory import MemoryServer
2443
1635
return MemoryServer
2444
if typestring == "fakenfs":
2445
from bzrlib.transport.fakenfs import FakeNFSServer
2446
return FakeNFSServer
2447
1636
msg = "No known transport type %s. Supported types are: sftp\n" %\
2449
raise errors.BzrCommandError(msg)
1638
raise BzrCommandError(msg)
2452
1641
takes_args = ['testspecs*']
2453
1642
takes_options = ['verbose',
2455
help='Stop when one test fails.',
1643
Option('one', help='stop when one test fails'),
1644
Option('keep-output',
1645
help='keep output directories when tests fail'),
2459
1647
help='Use a different transport by default '
2460
1648
'throughout the test suite.',
2461
1649
type=get_transport_type),
2463
help='Run the benchmarks rather than selftests.'),
2464
Option('lsprof-timed',
2465
help='Generate lsprof output for benchmarked'
2466
' sections of code.'),
2467
Option('cache-dir', type=str,
2468
help='Cache intermediate benchmark output in this '
2471
help='Run all tests, but run specified tests first.',
2475
help='List the tests instead of running them.'),
2476
Option('randomize', type=str, argname="SEED",
2477
help='Randomize the order of tests using the given'
2478
' seed or "now" for the current time.'),
2479
Option('exclude', type=str, argname="PATTERN",
2481
help='Exclude tests that match this regular'
2484
encoding_type = 'replace'
2486
def run(self, testspecs_list=None, verbose=None, one=False,
2487
transport=None, benchmark=None,
2488
lsprof_timed=None, cache_dir=None,
2489
first=False, list_only=False,
2490
randomize=None, exclude=None):
1652
def run(self, testspecs_list=None, verbose=False, one=False,
1653
keep_output=False, transport=None):
2491
1654
import bzrlib.ui
2492
1655
from bzrlib.tests import selftest
2493
import bzrlib.benchmarks as benchmarks
2494
from bzrlib.benchmarks import tree_creator
2495
from bzrlib.version import show_version
2497
if cache_dir is not None:
2498
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2500
show_version(show_config=False, show_copyright=False)
2502
if testspecs_list is not None:
2503
pattern = '|'.join(testspecs_list)
2507
test_suite_factory = benchmarks.test_suite
2510
# TODO: should possibly lock the history file...
2511
benchfile = open(".perf_history", "at", buffering=1)
2513
test_suite_factory = None
1656
# we don't want progress meters from the tests to go to the
1657
# real output; and we don't want log messages cluttering up
1659
save_ui = bzrlib.ui.ui_factory
1660
bzrlib.trace.info('running tests...')
2518
result = selftest(verbose=verbose,
1662
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1663
if testspecs_list is not None:
1664
pattern = '|'.join(testspecs_list)
1667
result = selftest(verbose=verbose,
2519
1668
pattern=pattern,
2520
stop_on_failure=one,
2521
transport=transport,
2522
test_suite_factory=test_suite_factory,
2523
lsprof_timed=lsprof_timed,
2524
bench_history=benchfile,
2525
matching_tests_first=first,
2526
list_only=list_only,
2527
random_seed=randomize,
2528
exclude_pattern=exclude
1669
stop_on_failure=one,
1670
keep_output=keep_output,
1671
transport=transport)
1673
bzrlib.trace.info('tests passed')
1675
bzrlib.trace.info('tests failed')
1676
return int(not result)
2531
if benchfile is not None:
2534
info('tests passed')
2536
info('tests failed')
2537
return int(not result)
1678
bzrlib.ui.ui_factory = save_ui
1681
def _get_bzr_branch():
1682
"""If bzr is run from a branch, return Branch or None"""
1683
import bzrlib.errors
1684
from bzrlib.branch import Branch
1685
from bzrlib.osutils import abspath
1686
from os.path import dirname
1689
branch = Branch.open(dirname(abspath(dirname(__file__))))
1691
except bzrlib.errors.BzrError:
1696
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1697
# is bzrlib itself in a branch?
1698
branch = _get_bzr_branch()
1700
rh = branch.revision_history()
1702
print " bzr checkout, revision %d" % (revno,)
1703
print " nick: %s" % (branch.nick,)
1705
print " revid: %s" % (rh[-1],)
1706
print bzrlib.__copyright__
1707
print "http://bazaar-ng.org/"
1709
print "bzr comes with ABSOLUTELY NO WARRANTY. bzr is free software, and"
1710
print "you may use, modify and redistribute it under the terms of the GNU"
1711
print "General Public License version 2 or later."
2540
1714
class cmd_version(Command):
2541
1715
"""Show version of bzr."""
2543
1716
@display_command
2545
from bzrlib.version import show_version
2549
1720
class cmd_rocks(Command):
2550
1721
"""Statement of optimism."""
2554
1723
@display_command
2556
print "It sure does!"
1725
print "it sure does!"
2559
1728
class cmd_find_merge_base(Command):
2560
"""Find and print a base revision for merging two branches."""
1729
"""Find and print a base revision for merging two branches.
2561
1731
# TODO: Options to specify revisions on either side, as if
2562
1732
# merging only part of the history.
2563
1733
takes_args = ['branch', 'other']
2600
1787
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
2602
If there is no default branch set, the first merge will set it. After
2603
that, you can omit the branch to use the default. To change the
2604
default, use --remember. The value will only be saved if the remote
2605
location can be accessed.
2607
The results of the merge are placed into the destination working
2608
directory, where they can be reviewed (with bzr diff), tested, and then
2609
committed to record the result of the merge.
2613
To merge the latest revision from bzr.dev:
2614
bzr merge ../bzr.dev
1791
To merge the latest revision from bzr.dev
1792
bzr merge ../bzr.dev
2616
To merge changes up to and including revision 82 from bzr.dev:
2617
bzr merge -r 82 ../bzr.dev
1794
To merge changes up to and including revision 82 from bzr.dev
1795
bzr merge -r 82 ../bzr.dev
2619
1797
To merge the changes introduced by 82, without previous changes:
2620
bzr merge -r 81..82 ../bzr.dev
1798
bzr merge -r 81..82 ../bzr.dev
2622
1800
merge refuses to run if there are any uncommitted changes, unless
2623
1801
--force is given.
2626
_see_also = ['update', 'remerge', 'status-flags']
2627
1803
takes_args = ['branch?']
2631
help='Merge even if the destination tree has uncommitted changes.'),
2635
Option('show-base', help="Show base revision text in "
2637
Option('uncommitted', help='Apply uncommitted changes'
2638
' from a working copy, instead of branch changes.'),
2639
Option('pull', help='If the destination is already'
2640
' completely merged into the source, pull from the'
2641
' source rather than merging. When this happens,'
2642
' you do not need to commit the result.'),
2644
help='Branch to merge into, '
2645
'rather than the one containing the working directory.',
1804
takes_options = ['revision', 'force', 'merge-type', 'reprocess',
1805
Option('show-base', help="Show base revision text in "
2651
1808
def run(self, branch=None, revision=None, force=False, merge_type=None,
2652
show_base=False, reprocess=False, remember=False,
2653
uncommitted=False, pull=False,
2656
from bzrlib.tag import _merge_tags_if_possible
1809
show_base=False, reprocess=False):
2657
1810
if merge_type is None:
2658
merge_type = _mod_merge.Merge3Merger
2660
if directory is None: directory = u'.'
2661
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2662
# inventory. Because merge is a mutating operation, it really
2663
# should be a lock_write() for the whole cmd_merge operation.
2664
# However, cmd_merge open's its own tree in _merge_helper, which
2665
# means if we lock here, the later lock_write() will always block.
2666
# Either the merge helper code should be updated to take a tree,
2667
# (What about tree.merge_from_branch?)
2668
tree = WorkingTree.open_containing(directory)[0]
2669
change_reporter = delta._ChangeReporter(
2670
unversioned_filter=tree.is_ignored)
2672
other_transport = None
2673
other_revision_id = None
2674
possible_transports = []
2675
# The user may provide a bundle or branch as 'branch' We first try to
2676
# identify a bundle, if it's not, we try to preserve connection used by
2677
# the transport to access the branch.
2678
if branch is not None:
2679
url = urlutils.normalize_url(branch)
2680
url, filename = urlutils.split(url, exclude_trailing_slash=False)
2681
other_transport = transport.get_transport(url)
2684
read_bundle = bundle.read_mergeable_from_transport
2685
# There may be redirections but we ignore the intermediate
2686
# and final transports used
2687
mergeable, t = read_bundle(other_transport, filename)
2688
except errors.NotABundle:
2689
# Continue on considering this url a Branch but adjust the
2691
other_transport = other_transport.clone(filename)
2693
if revision is not None:
2694
raise errors.BzrCommandError('Cannot use -r with merge'
2695
' directives or bundles')
2696
other_revision_id = mergeable.install_revisions(
2697
tree.branch.repository)
2698
revision = [RevisionSpec.from_string(
2699
'revid:' + other_revision_id)]
2700
possible_transports.append(other_transport)
2702
if revision is None \
2703
or len(revision) < 1 or revision[0].needs_branch():
2704
branch = self._get_remembered_parent(tree, branch, 'Merging from')
1811
merge_type = Merge3Merger
1813
branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
1815
raise BzrCommandError("No merge location known or specified.")
1817
print "Using saved location: %s" % branch
2706
1818
if revision is None or len(revision) < 1:
2709
other = [branch, None]
2712
other = [branch, -1]
2713
other_branch, path = Branch.open_containing(branch,
2714
possible_transports)
1820
other = [branch, -1]
2717
raise errors.BzrCommandError('Cannot use --uncommitted and'
2718
' --revision at the same time.')
2719
branch = revision[0].get_branch() or branch
2720
1822
if len(revision) == 1:
2721
1823
base = [None, None]
2722
if other_revision_id is not None:
2723
# We merge from a bundle
2728
other_branch, path = Branch.open_containing(
2729
branch, possible_transports)
2730
revno = revision[0].in_history(other_branch).revno
2731
other = [branch, revno]
1824
other_branch = Branch.open_containing(branch)[0]
1825
revno = revision[0].in_history(other_branch).revno
1826
other = [branch, revno]
2733
1828
assert len(revision) == 2
2734
1829
if None in revision:
2735
raise errors.BzrCommandError(
2736
"Merge doesn't permit empty revision specifier.")
2737
base_branch, path = Branch.open_containing(branch,
2738
possible_transports)
2739
branch1 = revision[1].get_branch() or branch
2740
other_branch, path1 = Branch.open_containing(
2741
branch1, possible_transports)
2742
if revision[0].get_branch() is not None:
2743
# then path was obtained from it, and is None.
2746
base = [branch, revision[0].in_history(base_branch).revno]
2747
other = [branch1, revision[1].in_history(other_branch).revno]
2749
# Remember where we merge from
2750
if ((tree.branch.get_parent() is None or remember) and
2751
other_branch is not None):
2752
tree.branch.set_parent(other_branch.base)
2754
# pull tags now... it's a bit inconsistent to do it ahead of copying
2755
# the history but that's done inside the merge code
2756
if other_branch is not None:
2757
_merge_tags_if_possible(other_branch, tree.branch)
2760
interesting_files = [path]
2762
interesting_files = None
2763
pb = ui.ui_factory.nested_progress_bar()
1830
raise BzrCommandError(
1831
"Merge doesn't permit that revision specifier.")
1832
b = Branch.open_containing(branch)[0]
1834
base = [branch, revision[0].in_history(b).revno]
1835
other = [branch, revision[1].in_history(b).revno]
1836
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2766
conflict_count = _merge_helper(
2767
other, base, possible_transports,
2768
other_rev_id=other_revision_id,
2769
check_clean=(not force),
2770
merge_type=merge_type,
2771
reprocess=reprocess,
2772
show_base=show_base,
2775
pb=pb, file_list=interesting_files,
2776
change_reporter=change_reporter)
1839
conflict_count = merge(other, base, check_clean=(not force),
1840
merge_type=merge_type,
1841
reprocess=reprocess,
1842
show_base=show_base,
2779
1846
if conflict_count != 0:
2783
except errors.AmbiguousBase, e:
1850
except bzrlib.errors.AmbiguousBase, e:
2784
1851
m = ("sorry, bzr can't determine the right merge base yet\n"
2785
1852
"candidates are:\n "
2786
1853
+ "\n ".join(e.bases)
2789
1856
"and (if you want) report this to the bzr developers\n")
2792
# TODO: move up to common parent; this isn't merge-specific anymore.
2793
def _get_remembered_parent(self, tree, supplied_location, verb_string):
2794
"""Use tree.branch's parent if none was supplied.
2796
Report if the remembered location was used.
2798
if supplied_location is not None:
2799
return supplied_location
2800
stored_location = tree.branch.get_parent()
2801
mutter("%s", stored_location)
2802
if stored_location is None:
2803
raise errors.BzrCommandError("No location specified or remembered")
2804
display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2805
self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2806
return stored_location
2809
1860
class cmd_remerge(Command):
2810
1861
"""Redo a merge.
2812
Use this if you want to try a different merge technique while resolving
2813
conflicts. Some merge techniques are better than others, and remerge
2814
lets you try different ones on different files.
2816
The options for remerge have the same meaning and defaults as the ones for
2817
merge. The difference is that remerge can (only) be run when there is a
2818
pending merge, and it lets you specify particular files.
2822
$ bzr remerge --show-base
2823
Re-do the merge of all conflicted files, and show the base text in
2824
conflict regions, in addition to the usual THIS and OTHER texts.
2826
$ bzr remerge --merge-type weave --reprocess foobar
2827
Re-do the merge of "foobar", using the weave merge algorithm, with
2828
additional processing to reduce the size of conflict regions.
2830
1863
takes_args = ['file*']
2835
help="Show base revision text in conflicts."),
1864
takes_options = ['merge-type', 'reprocess',
1865
Option('show-base', help="Show base revision text in "
2838
1868
def run(self, file_list=None, merge_type=None, show_base=False,
2839
1869
reprocess=False):
1870
from bzrlib.merge import merge_inner, transform_tree
2840
1871
if merge_type is None:
2841
merge_type = _mod_merge.Merge3Merger
1872
merge_type = Merge3Merger
2842
1873
tree, file_list = tree_files(file_list)
2843
1874
tree.lock_write()
2845
parents = tree.get_parent_ids()
2846
if len(parents) != 2:
2847
raise errors.BzrCommandError("Sorry, remerge only works after normal"
2848
" merges. Not cherrypicking or"
1876
pending_merges = tree.pending_merges()
1877
if len(pending_merges) != 1:
1878
raise BzrCommandError("Sorry, remerge only works after normal"
1879
+ " merges. Not cherrypicking or"
2850
1881
repository = tree.branch.repository
2851
graph = repository.get_graph()
2852
base_revision = graph.find_unique_lca(parents[0], parents[1])
1882
base_revision = common_ancestor(tree.branch.last_revision(),
1883
pending_merges[0], repository)
2853
1884
base_tree = repository.revision_tree(base_revision)
2854
other_tree = repository.revision_tree(parents[1])
1885
other_tree = repository.revision_tree(pending_merges[0])
2855
1886
interesting_ids = None
2857
conflicts = tree.conflicts()
2858
1887
if file_list is not None:
2859
1888
interesting_ids = set()
2860
1889
for filename in file_list:
2861
1890
file_id = tree.path2id(filename)
2862
1891
if file_id is None:
2863
raise errors.NotVersionedError(filename)
1892
raise NotVersionedError(filename)
2864
1893
interesting_ids.add(file_id)
2865
1894
if tree.kind(file_id) != "directory":
2868
1897
for name, ie in tree.inventory.iter_entries(file_id):
2869
1898
interesting_ids.add(ie.file_id)
2870
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
1899
transform_tree(tree, tree.basis_tree(), interesting_ids)
1900
if file_list is None:
1901
restore_files = list(tree.iter_conflicts())
2872
# Remerge only supports resolving contents conflicts
2873
allowed_conflicts = ('text conflict', 'contents conflict')
2874
restore_files = [c.path for c in conflicts
2875
if c.typestring in allowed_conflicts]
2876
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2877
tree.set_conflicts(ConflictList(new_conflicts))
2878
if file_list is not None:
2879
1903
restore_files = file_list
2880
1904
for filename in restore_files:
2882
1906
restore(tree.abspath(filename))
2883
except errors.NotConflicted:
1907
except NotConflicted:
2885
conflicts = _mod_merge.merge_inner(
2886
tree.branch, other_tree, base_tree,
2888
interesting_ids=interesting_ids,
2889
other_rev_id=parents[1],
2890
merge_type=merge_type,
2891
show_base=show_base,
2892
reprocess=reprocess)
1909
conflicts = merge_inner(tree.branch, other_tree, base_tree,
1911
interesting_ids = interesting_ids,
1912
other_rev_id=pending_merges[0],
1913
merge_type=merge_type,
1914
show_base=show_base,
1915
reprocess=reprocess)
2895
1918
if conflicts > 0:
3012
2010
class cmd_missing(Command):
3013
2011
"""Show unmerged/unpulled revisions between two branches.
3015
OTHER_BRANCH may be local or remote.
3018
_see_also = ['merge', 'pull']
2013
OTHER_BRANCH may be local or remote."""
3019
2014
takes_args = ['other_branch?']
3021
Option('reverse', 'Reverse the order of revisions.'),
3023
'Display changes in the local branch only.'),
3024
Option('this' , 'Same as --mine-only.'),
3025
Option('theirs-only',
3026
'Display changes in the remote branch only.'),
3027
Option('other', 'Same as --theirs-only.'),
3032
encoding_type = 'replace'
2015
takes_options = [Option('reverse', 'Reverse the order of revisions'),
2017
'Display changes in the local branch only'),
2018
Option('theirs-only',
2019
'Display changes in the remote branch only'),
3035
2028
def run(self, other_branch=None, reverse=False, mine_only=False,
3036
2029
theirs_only=False, log_format=None, long=False, short=False, line=False,
3037
show_ids=False, verbose=False, this=False, other=False):
3038
from bzrlib.missing import find_unmerged, iter_log_revisions
2030
show_ids=False, verbose=False):
2031
from bzrlib.missing import find_unmerged, iter_log_data
3039
2032
from bzrlib.log import log_formatter
3046
local_branch = Branch.open_containing(u".")[0]
2033
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
3047
2034
parent = local_branch.get_parent()
3048
2035
if other_branch is None:
3049
2036
other_branch = parent
3050
2037
if other_branch is None:
3051
raise errors.BzrCommandError("No peer location known"
3053
display_url = urlutils.unescape_for_display(parent,
3055
self.outf.write("Using last location: " + display_url + '\n')
3057
remote_branch = Branch.open(other_branch)
3058
if remote_branch.base == local_branch.base:
3059
remote_branch = local_branch
3060
local_branch.lock_read()
2038
raise BzrCommandError("No missing location known or specified.")
2039
print "Using last location: " + local_branch.get_parent()
2040
remote_branch = bzrlib.branch.Branch.open(other_branch)
2041
remote_branch.lock_read()
3062
remote_branch.lock_read()
2043
local_branch.lock_write()
3064
local_extra, remote_extra = find_unmerged(local_branch,
3066
if log_format is None:
3067
registry = log.log_formatter_registry
3068
log_format = registry.get_default(local_branch)
3069
lf = log_format(to_file=self.outf,
3071
show_timezone='original')
2045
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2046
if (log_format == None):
2047
default = bzrlib.config.BranchConfig(local_branch).log_format()
2048
log_format = get_log_format(long=long, short=short, line=line, default=default)
2049
lf = log_formatter(log_format, sys.stdout,
2051
show_timezone='original')
3072
2052
if reverse is False:
3073
2053
local_extra.reverse()
3074
2054
remote_extra.reverse()
3075
2055
if local_extra and not theirs_only:
3076
self.outf.write("You have %d extra revision(s):\n" %
3078
for revision in iter_log_revisions(local_extra,
3079
local_branch.repository,
3081
lf.log_revision(revision)
2056
print "You have %d extra revision(s):" % len(local_extra)
2057
for data in iter_log_data(local_extra, local_branch.repository,
3082
2060
printed_local = True
3084
2062
printed_local = False
3085
2063
if remote_extra and not mine_only:
3086
2064
if printed_local is True:
3087
self.outf.write("\n\n\n")
3088
self.outf.write("You are missing %d revision(s):\n" %
3090
for revision in iter_log_revisions(remote_extra,
3091
remote_branch.repository,
3093
lf.log_revision(revision)
2066
print "You are missing %d revision(s):" % len(remote_extra)
2067
for data in iter_log_data(remote_extra, remote_branch.repository,
3094
2070
if not remote_extra and not local_extra:
3095
2071
status_code = 0
3096
self.outf.write("Branches are up to date.\n")
2072
print "Branches are up to date."
3098
2074
status_code = 1
3100
remote_branch.unlock()
3102
local_branch.unlock()
3103
if not status_code and parent is None and other_branch is not None:
3104
local_branch.lock_write()
3106
# handle race conditions - a parent might be set while we run.
3107
if local_branch.get_parent() is None:
3108
local_branch.set_parent(remote_branch.base)
2075
if parent is None and other_branch is not None:
2076
local_branch.set_parent(other_branch)
3110
2079
local_branch.unlock()
3114
class cmd_pack(Command):
3115
"""Compress the data within a repository."""
3117
_see_also = ['repositories']
3118
takes_args = ['branch_or_repo?']
3120
def run(self, branch_or_repo='.'):
3121
dir = bzrdir.BzrDir.open_containing(branch_or_repo)[0]
3123
branch = dir.open_branch()
3124
repository = branch.repository
3125
except errors.NotBranchError:
3126
repository = dir.open_repository()
2081
remote_branch.unlock()
3130
2084
class cmd_plugins(Command):
3256
2191
if to_revid is None:
3257
2192
to_revno = b.revno()
3258
2193
if from_revno is None or to_revno is None:
3259
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2194
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
3260
2195
for revno in range(from_revno, to_revno + 1):
3261
2196
b.repository.sign_revision(b.get_rev_id(revno),
3264
raise errors.BzrCommandError('Please supply either one revision, or a range.')
2199
raise BzrCommandError('Please supply either one revision, or a range.')
3267
2202
class cmd_bind(Command):
3268
"""Convert the current branch into a checkout of the supplied branch.
2203
"""Bind the current branch to a master branch.
3270
Once converted into a checkout, commits must succeed on the master branch
3271
before they will be applied to the local branch.
2205
After binding, commits must succeed on the master branch
2206
before they are executed on the local one.
3274
_see_also = ['checkouts', 'unbind']
3275
takes_args = ['location?']
2209
takes_args = ['location']
3276
2210
takes_options = []
3278
2212
def run(self, location=None):
3279
2213
b, relpath = Branch.open_containing(u'.')
3280
if location is None:
3282
location = b.get_old_bound_location()
3283
except errors.UpgradeRequired:
3284
raise errors.BzrCommandError('No location supplied. '
3285
'This format does not remember old locations.')
3287
if location is None:
3288
raise errors.BzrCommandError('No location supplied and no '
3289
'previous location known')
3290
2214
b_other = Branch.open(location)
3292
2216
b.bind(b_other)
3293
except errors.DivergedBranches:
3294
raise errors.BzrCommandError('These branches have diverged.'
3295
' Try merging, and then bind again.')
2217
except DivergedBranches:
2218
raise BzrCommandError('These branches have diverged.'
2219
' Try merging, and then bind again.')
3298
2222
class cmd_unbind(Command):
3299
"""Convert the current checkout into a regular branch.
2223
"""Bind the current branch to its parent.
3301
After unbinding, the local branch is considered independent and subsequent
3302
commits will be local only.
2225
After unbinding, the local branch is considered independent.
3305
_see_also = ['checkouts', 'bind']
3306
2228
takes_args = []
3307
2229
takes_options = []
3310
2232
b, relpath = Branch.open_containing(u'.')
3311
2233
if not b.unbind():
3312
raise errors.BzrCommandError('Local branch is not bound')
3315
class cmd_uncommit(Command):
2234
raise BzrCommandError('Local branch is not bound')
2237
class cmd_uncommit(bzrlib.commands.Command):
3316
2238
"""Remove the last committed revision.
2240
By supplying the --all flag, it will not only remove the entry
2241
from revision_history, but also remove all of the entries in the
3318
2244
--verbose will print out what is being removed.
3319
2245
--dry-run will go through all the motions, but not actually
3320
2246
remove anything.
3322
In the future, uncommit will create a revision bundle, which can then
2248
In the future, uncommit will create a changeset, which can then
3326
2252
# TODO: jam 20060108 Add an option to allow uncommit to remove
3327
# unreferenced information in 'branch-as-repository' branches.
2253
# unreferenced information in 'branch-as-repostory' branches.
3328
2254
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
3329
2255
# information in shared branches as well.
3330
_see_also = ['commit']
3331
2256
takes_options = ['verbose', 'revision',
3332
Option('dry-run', help='Don\'t actually make changes.'),
2257
Option('dry-run', help='Don\'t actually make changes'),
3333
2258
Option('force', help='Say yes to all questions.')]
3334
2259
takes_args = ['location?']
3337
def run(self, location=None,
2262
def run(self, location=None,
3338
2263
dry_run=False, verbose=False,
3339
2264
revision=None, force=False):
3340
from bzrlib.log import log_formatter, show_log
2265
from bzrlib.branch import Branch
2266
from bzrlib.log import log_formatter
3342
2268
from bzrlib.uncommit import uncommit
3344
2270
if location is None:
3345
2271
location = u'.'
3346
2272
control, relpath = bzrdir.BzrDir.open_containing(location)
2273
b = control.open_branch()
3348
2275
tree = control.open_workingtree()
3350
2276
except (errors.NoWorkingTree, errors.NotLocalUrl):
3352
b = control.open_branch()
3355
2279
if revision is None:
3356
2280
revno = b.revno()
2281
rev_id = b.last_revision()
3358
# 'bzr uncommit -r 10' actually means uncommit
3359
# so that the final tree is at revno 10.
3360
# but bzrlib.uncommit.uncommit() actually uncommits
3361
# the revisions that are supplied.
3362
# So we need to offset it by one
3363
revno = revision[0].in_history(b).revno+1
3365
if revno <= b.revno():
3366
rev_id = b.get_rev_id(revno)
2283
revno, rev_id = revision[0].in_history(b)
3367
2284
if rev_id is None:
3368
self.outf.write('No revisions to uncommit.\n')
3371
lf = log_formatter('short',
3373
show_timezone='original')
3378
direction='forward',
3379
start_revision=revno,
3380
end_revision=b.revno())
2285
print 'No revisions to uncommit.'
2287
for r in range(revno, b.revno()+1):
2288
rev_id = b.get_rev_id(r)
2289
lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
2290
lf.show(r, b.repository.get_revision(rev_id), None)
3383
2293
print 'Dry-run, pretending to remove the above revisions.'
3401
2311
CAUTION: Locks should only be broken when you are sure that the process
3402
2312
holding the lock has been stopped.
3404
You can get information on what locks are open via the 'bzr info' command.
3409
takes_args = ['location?']
3411
def run(self, location=None, show=False):
3412
if location is None:
3414
control, relpath = bzrdir.BzrDir.open_containing(location)
3416
control.break_lock()
3417
except NotImplementedError:
3421
class cmd_wait_until_signalled(Command):
3422
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3424
This just prints a line to signal when it is ready, then blocks on stdin.
3430
sys.stdout.write("running\n")
3432
sys.stdin.readline()
3435
class cmd_serve(Command):
3436
"""Run the bzr server."""
3438
aliases = ['server']
3442
help='Serve on stdin/out for use from inetd or sshd.'),
3444
help='Listen for connections on nominated port of the form '
3445
'[hostname:]portnumber. Passing 0 as the port number will '
3446
'result in a dynamically allocated port. The default port is '
3450
help='Serve contents of this directory.',
3452
Option('allow-writes',
3453
help='By default the server is a readonly server. Supplying '
3454
'--allow-writes enables write access to the contents of '
3455
'the served directory and below.'
3459
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3460
from bzrlib.smart import medium, server
3461
from bzrlib.transport import get_transport
3462
from bzrlib.transport.chroot import ChrootServer
3463
from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3464
if directory is None:
3465
directory = os.getcwd()
3466
url = urlutils.local_path_to_url(directory)
3467
if not allow_writes:
3468
url = 'readonly+' + url
3469
chroot_server = ChrootServer(get_transport(url))
3470
chroot_server.setUp()
3471
t = get_transport(chroot_server.get_url())
3473
smart_server = medium.SmartServerPipeStreamMedium(
3474
sys.stdin, sys.stdout, t)
3476
host = BZR_DEFAULT_INTERFACE
3478
port = BZR_DEFAULT_PORT
3481
host, port = port.split(':')
3483
smart_server = server.SmartTCPServer(t, host=host, port=port)
3484
print 'listening on port: ', smart_server.port
3486
# for the duration of this server, no UI output is permitted.
3487
# note that this may cause problems with blackbox tests. This should
3488
# be changed with care though, as we dont want to use bandwidth sending
3489
# progress over stderr to smart server clients!
3490
old_factory = ui.ui_factory
3492
ui.ui_factory = ui.SilentUIFactory()
3493
smart_server.serve()
3495
ui.ui_factory = old_factory
3498
class cmd_join(Command):
3499
"""Combine a subtree into its containing tree.
3501
This command is for experimental use only. It requires the target tree
3502
to be in dirstate-with-subtree format, which cannot be converted into
3505
The TREE argument should be an independent tree, inside another tree, but
3506
not part of it. (Such trees can be produced by "bzr split", but also by
3507
running "bzr branch" with the target inside a tree.)
3509
The result is a combined tree, with the subtree no longer an independant
3510
part. This is marked as a merge of the subtree into the containing tree,
3511
and all history is preserved.
3513
If --reference is specified, the subtree retains its independence. It can
3514
be branched by itself, and can be part of multiple projects at the same
3515
time. But operations performed in the containing tree, such as commit
3516
and merge, will recurse into the subtree.
3519
_see_also = ['split']
3520
takes_args = ['tree']
3522
Option('reference', help='Join by reference.'),
3526
def run(self, tree, reference=False):
3527
sub_tree = WorkingTree.open(tree)
3528
parent_dir = osutils.dirname(sub_tree.basedir)
3529
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3530
repo = containing_tree.branch.repository
3531
if not repo.supports_rich_root():
3532
raise errors.BzrCommandError(
3533
"Can't join trees because %s doesn't support rich root data.\n"
3534
"You can use bzr upgrade on the repository."
3538
containing_tree.add_reference(sub_tree)
3539
except errors.BadReferenceTarget, e:
3540
# XXX: Would be better to just raise a nicely printable
3541
# exception from the real origin. Also below. mbp 20070306
3542
raise errors.BzrCommandError("Cannot join %s. %s" %
3546
containing_tree.subsume(sub_tree)
3547
except errors.BadSubsumeSource, e:
3548
raise errors.BzrCommandError("Cannot join %s. %s" %
3552
class cmd_split(Command):
3553
"""Split a tree into two trees.
3555
This command is for experimental use only. It requires the target tree
3556
to be in dirstate-with-subtree format, which cannot be converted into
3559
The TREE argument should be a subdirectory of a working tree. That
3560
subdirectory will be converted into an independent tree, with its own
3561
branch. Commits in the top-level tree will not apply to the new subtree.
3562
If you want that behavior, do "bzr join --reference TREE".
3565
_see_also = ['join']
3566
takes_args = ['tree']
3570
def run(self, tree):
3571
containing_tree, subdir = WorkingTree.open_containing(tree)
3572
sub_id = containing_tree.path2id(subdir)
3574
raise errors.NotVersionedError(subdir)
3576
containing_tree.extract(sub_id)
3577
except errors.RootNotRich:
3578
raise errors.UpgradeRequired(containing_tree.branch.base)
3582
class cmd_merge_directive(Command):
3583
"""Generate a merge directive for auto-merge tools.
3585
A directive requests a merge to be performed, and also provides all the
3586
information necessary to do so. This means it must either include a
3587
revision bundle, or the location of a branch containing the desired
3590
A submit branch (the location to merge into) must be supplied the first
3591
time the command is issued. After it has been supplied once, it will
3592
be remembered as the default.
3594
A public branch is optional if a revision bundle is supplied, but required
3595
if --diff or --plain is specified. It will be remembered as the default
3596
after the first use.
3599
takes_args = ['submit_branch?', 'public_branch?']
3602
RegistryOption.from_kwargs('patch-type',
3603
'The type of patch to include in the directive',
3605
value_switches=True,
3607
bundle='Bazaar revision bundle (default).',
3608
diff='Normal unified diff.',
3609
plain='No patch, just directive.'),
3610
Option('sign', help='GPG-sign the directive.'), 'revision',
3611
Option('mail-to', type=str,
3612
help='Instead of printing the directive, email to this address.'),
3613
Option('message', type=str, short_name='m',
3614
help='Message to use when committing this merge.')
3617
encoding_type = 'exact'
3619
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3620
sign=False, revision=None, mail_to=None, message=None):
3621
from bzrlib.revision import ensure_null, NULL_REVISION
3622
if patch_type == 'plain':
3624
branch = Branch.open('.')
3625
stored_submit_branch = branch.get_submit_branch()
3626
if submit_branch is None:
3627
submit_branch = stored_submit_branch
3629
if stored_submit_branch is None:
3630
branch.set_submit_branch(submit_branch)
3631
if submit_branch is None:
3632
submit_branch = branch.get_parent()
3633
if submit_branch is None:
3634
raise errors.BzrCommandError('No submit branch specified or known')
3636
stored_public_branch = branch.get_public_branch()
3637
if public_branch is None:
3638
public_branch = stored_public_branch
3639
elif stored_public_branch is None:
3640
branch.set_public_branch(public_branch)
3641
if patch_type != "bundle" and public_branch is None:
3642
raise errors.BzrCommandError('No public branch specified or'
3644
if revision is not None:
3645
if len(revision) != 1:
3646
raise errors.BzrCommandError('bzr merge-directive takes '
3647
'exactly one revision identifier')
3649
revision_id = revision[0].in_history(branch).rev_id
3651
revision_id = branch.last_revision()
3652
revision_id = ensure_null(revision_id)
3653
if revision_id == NULL_REVISION:
3654
raise errors.BzrCommandError('No revisions to bundle.')
3655
directive = merge_directive.MergeDirective.from_objects(
3656
branch.repository, revision_id, time.time(),
3657
osutils.local_time_offset(), submit_branch,
3658
public_branch=public_branch, patch_type=patch_type,
3662
self.outf.write(directive.to_signed(branch))
3664
self.outf.writelines(directive.to_lines())
3666
message = directive.to_email(mail_to, branch, sign)
3667
s = SMTPConnection(branch.get_config())
3668
s.send_email(message)
3671
class cmd_tag(Command):
3672
"""Create a tag naming a revision.
3674
Tags give human-meaningful names to revisions. Commands that take a -r
3675
(--revision) option can be given -rtag:X, where X is any previously
3678
Tags are stored in the branch. Tags are copied from one branch to another
3679
along when you branch, push, pull or merge.
3681
It is an error to give a tag name that already exists unless you pass
3682
--force, in which case the tag is moved to point to the new revision.
3685
_see_also = ['commit', 'tags']
3686
takes_args = ['tag_name']
3689
help='Delete this tag rather than placing it.',
3692
help='Branch in which to place the tag.',
3697
help='Replace existing tags.',
3702
def run(self, tag_name,
3708
branch, relpath = Branch.open_containing(directory)
3712
branch.tags.delete_tag(tag_name)
3713
self.outf.write('Deleted tag %s.\n' % tag_name)
3716
if len(revision) != 1:
3717
raise errors.BzrCommandError(
3718
"Tags can only be placed on a single revision, "
3720
revision_id = revision[0].in_history(branch).rev_id
3722
revision_id = branch.last_revision()
3723
if (not force) and branch.tags.has_tag(tag_name):
3724
raise errors.TagAlreadyExists(tag_name)
3725
branch.tags.set_tag(tag_name, revision_id)
3726
self.outf.write('Created tag %s.\n' % tag_name)
3731
class cmd_tags(Command):
3734
This tag shows a table of tag names and the revisions they reference.
3740
help='Branch whose tags should be displayed.',
3750
branch, relpath = Branch.open_containing(directory)
3751
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3752
self.outf.write('%-20s %s\n' % (tag_name, target))
2317
takes_args = ['location']
2318
takes_options = [Option('show',
2319
help="just show information on the lock, " \
2322
def run(self, location, show=False):
2323
d = bzrdir.BzrDir.open(location)
2324
repo = d.open_repository()
2325
if not repo.is_locked():
2326
raise errors.ObjectNotLocked(repo)
3755
2329
# command-line interpretation helper for merge-related commands
3756
def _merge_helper(other_revision, base_revision, possible_transports=None,
3757
check_clean=True, ignore_zero=False,
3758
this_dir=None, backup_files=False,
3760
file_list=None, show_base=False, reprocess=False,
3763
change_reporter=None,
2330
def merge(other_revision, base_revision,
2331
check_clean=True, ignore_zero=False,
2332
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2333
file_list=None, show_base=False, reprocess=False,
2334
pb=DummyProgress()):
3765
2335
"""Merge changes into a tree.
3789
2359
clients might prefer to call merge.merge_inner(), which has less magic
3792
# Loading it late, so that we don't always have to import bzrlib.merge
3793
if merge_type is None:
3794
merge_type = _mod_merge.Merge3Merger
2362
from bzrlib.merge import Merger
3795
2363
if this_dir is None:
3796
2364
this_dir = u'.'
3797
2365
this_tree = WorkingTree.open_containing(this_dir)[0]
3798
if show_base and not merge_type is _mod_merge.Merge3Merger:
3799
raise errors.BzrCommandError("Show-base is not supported for this merge"
3800
" type. %s" % merge_type)
3801
if reprocess and not merge_type.supports_reprocess:
3802
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3803
" type %s." % merge_type)
2366
if show_base and not merge_type is Merge3Merger:
2367
raise BzrCommandError("Show-base is not supported for this merge"
2368
" type. %s" % merge_type)
2369
if reprocess and not merge_type is Merge3Merger:
2370
raise BzrCommandError("Reprocess is not supported for this merge"
2371
" type. %s" % merge_type)
3804
2372
if reprocess and show_base:
3805
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3806
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3807
# only want to take out a lock_tree_write() if we don't have to pull
3808
# any ancestry. But merge might fetch ancestry in the middle, in
3809
# which case we would need a lock_write().
3810
# Because we cannot upgrade locks, for now we live with the fact that
3811
# the tree will be locked multiple times during a merge. (Maybe
3812
# read-only some of the time, but it means things will get read
2373
raise BzrCommandError("Cannot reprocess and show base.")
3815
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3816
pb=pb, change_reporter=change_reporter)
2375
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
3817
2376
merger.pp = ProgressPhase("Merge phase", 5, pb)
3818
2377
merger.pp.next_phase()
3819
2378
merger.check_basis(check_clean)
3820
if other_rev_id is not None:
3821
merger.set_other_revision(other_rev_id, this_tree.branch)
3823
merger.set_other(other_revision, possible_transports)
2379
merger.set_other(other_revision)
3824
2380
merger.pp.next_phase()
3825
2381
merger.set_base(base_revision)
3826
2382
if merger.base_rev_id == merger.other_rev_id:
3827
2383
note('Nothing to do.')
3829
if file_list is None:
3830
if pull and merger.base_rev_id == merger.this_rev_id:
3831
# FIXME: deduplicate with pull
3832
result = merger.this_tree.pull(merger.this_branch,
3833
False, merger.other_rev_id)
3834
if result.old_revid == result.new_revid:
3835
note('No revisions to pull.')
3837
note('Now on revision %d.' % result.new_revno)
3839
2385
merger.backup_files = backup_files
3840
2386
merger.merge_type = merge_type
3841
2387
merger.set_interesting_files(file_list)
3842
2388
merger.show_base = show_base
3843
2389
merger.reprocess = reprocess
3844
2390
conflicts = merger.do_merge()
3845
if file_list is None:
3846
merger.set_pending()
2391
merger.set_pending()
3849
2394
return conflicts
3852
def _create_prefix(cur_transport):
3853
needed = [cur_transport]
3854
# Recurse upwards until we can create a directory successfully
3856
new_transport = cur_transport.clone('..')
3857
if new_transport.base == cur_transport.base:
3858
raise errors.BzrCommandError(
3859
"Failed to create path prefix for %s."
3860
% cur_transport.base)
3862
new_transport.mkdir('.')
3863
except errors.NoSuchFile:
3864
needed.append(new_transport)
3865
cur_transport = new_transport
3868
# Now we only need to create child directories
3870
cur_transport = needed.pop()
3871
cur_transport.ensure_base()
3875
merge = _merge_helper
3878
2397
# these get imported and then picked up by the scan for cmd_*
3879
2398
# TODO: Some more consistent way to split command definitions across files;
3880
2399
# we do need to load at least some information about them to know of
3881
2400
# aliases. ideally we would avoid loading the implementation until the
3882
2401
# details were needed.
3883
from bzrlib.cmd_version_info import cmd_version_info
3884
2402
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
3885
from bzrlib.bundle.commands import cmd_bundle_revisions
3886
2403
from bzrlib.sign_my_commits import cmd_sign_my_commits
3887
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
3888
cmd_weave_plan_merge, cmd_weave_merge_text
2404
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join