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
54
27
from bzrlib.branch import Branch
55
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
56
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
57
40
from bzrlib.revisionspec import RevisionSpec
58
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
59
45
from bzrlib.workingtree import WorkingTree
62
from bzrlib.commands import Command, display_command
63
from bzrlib.option import ListOption, Option, RegistryOption
64
from bzrlib.progress import DummyProgress, ProgressPhase
65
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
68
48
def tree_files(file_list, default_branch=u'.'):
70
50
return internal_tree_files(file_list, default_branch)
71
except errors.FileInWrongBranch, e:
72
raise errors.BzrCommandError("%s is not in the same branch as %s" %
73
(e.path, file_list[0]))
76
# XXX: Bad function name; should possibly also be a class method of
77
# 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]))
78
55
def internal_tree_files(file_list, default_branch=u'.'):
79
"""Convert command-line paths to a WorkingTree and relative paths.
81
This is typically used for command-line processors that take one or
82
more filenames, and infer the workingtree that contains them.
84
The filenames given are not required to exist.
86
:param file_list: Filenames to convert.
88
:param default_branch: Fallback tree path to use if file_list is empty or
91
: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.
93
61
if file_list is None or len(file_list) == 0:
94
62
return WorkingTree.open_containing(default_branch)[0], file_list
95
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
63
tree = WorkingTree.open_containing(file_list[0])[0]
97
65
for filename in file_list:
99
new_list.append(tree.relpath(osutils.dereference_path(filename)))
67
new_list.append(tree.relpath(filename))
100
68
except errors.PathNotChild:
101
raise errors.FileInWrongBranch(tree.branch, filename)
69
raise FileInWrongBranch(tree.branch, filename)
102
70
return tree, new_list
105
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
106
73
def get_format_type(typestring):
107
74
"""Parse and return a format specifier."""
108
# Have to use BzrDirMetaFormat1 directly, so that
109
# RepositoryFormat.set_default_format works
110
if typestring == "default":
75
if typestring == "metadir":
111
76
return bzrdir.BzrDirMetaFormat1()
113
return bzrdir.format_registry.make_bzrdir(typestring)
115
msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
116
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)
119
86
# TODO: Make sure no commands unconditionally use the working directory as a
341
232
Adding a file whose parent directory is not versioned will
342
233
implicitly add the parent, and so on up to the root. This means
343
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
344
235
get added when you add a file in the directory.
346
237
--dry-run will show which files would be added, but not actually
349
--file-ids-from will try to use the file ids from the supplied path.
350
It looks up ids trying to find a matching parent directory with the
351
same filename, and then by pure path. This option is rarely needed
352
but can be useful when adding the same logical file into two
353
branches that will be merged later (without showing the two different
354
adds as a conflict). It is also useful when merging another project
355
into a subdirectory of this one.
357
240
takes_args = ['file*']
358
takes_options = ['no-recurse', 'dry-run', 'verbose',
359
Option('file-ids-from', type=unicode,
360
help='Lookup file ids from here')]
361
encoding_type = 'replace'
362
_see_also = ['remove']
241
takes_options = ['no-recurse', 'dry-run', 'verbose']
364
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):
366
244
import bzrlib.add
369
if file_ids_from is not None:
371
base_tree, base_path = WorkingTree.open_containing(
373
except errors.NoWorkingTree:
374
base_branch, base_path = Branch.open_containing(
376
base_tree = base_branch.basis_tree()
378
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
379
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
381
action = bzrlib.add.AddAction(to_file=self.outf,
382
should_print=(not is_quiet()))
255
action = bzrlib.add.add_action_add_and_print
385
base_tree.lock_read()
387
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
388
action=action, save=not dry_run)
390
if base_tree is not None:
257
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
392
259
if len(ignored) > 0:
394
for glob in sorted(ignored.keys()):
260
for glob in sorted(ignored.keys()):
261
match_len = len(ignored[glob])
395
263
for path in ignored[glob]:
396
self.outf.write("ignored %s matching \"%s\"\n"
400
for glob, paths in ignored.items():
401
match_len += len(paths)
402
self.outf.write("ignored %d file(s).\n" % match_len)
403
self.outf.write("If you wish to add some of these files,"
404
" 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"\
407
272
class cmd_mkdir(Command):
507
336
If the last argument is a versioned directory, all the other names
508
337
are moved into it. Otherwise, there must be exactly two arguments
509
and the file is changed to a new name.
511
If OLDNAME does not exist on the filesystem but is versioned and
512
NEWNAME does exist on the filesystem but is not versioned, mv
513
assumes that the file has been manually moved and only updates
514
its internal inventory to reflect that change.
515
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.
517
340
Files cannot be moved between branches.
520
342
takes_args = ['names*']
521
takes_options = [Option("after", help="move only the bzr identifier"
522
" of the file (file has already been moved). Use this flag if"
523
" bzr is not able to detect this itself.")]
524
343
aliases = ['move', 'rename']
525
encoding_type = 'replace'
527
def run(self, names_list, after=False):
528
if names_list is None:
345
def run(self, names_list):
531
346
if len(names_list) < 2:
532
raise errors.BzrCommandError("missing file argument")
347
raise BzrCommandError("missing file argument")
533
348
tree, rel_names = tree_files(names_list)
535
350
if os.path.isdir(names_list[-1]):
536
351
# move into existing directory
537
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
538
self.outf.write("%s => %s\n" % pair)
352
for pair in tree.move(rel_names[:-1], rel_names[-1]):
353
print "%s => %s" % pair
540
355
if len(names_list) != 2:
541
raise errors.BzrCommandError('to mv multiple files the'
542
' destination must be a versioned'
544
tree.rename_one(rel_names[0], rel_names[1], after=after)
545
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])
548
362
class cmd_pull(Command):
549
"""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.
551
369
This command only works on branches that have not diverged. Branches are
552
considered diverged if the destination branch's most recent commit is one
553
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.
555
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
556
374
from one into the other. Once one branch has merged, the other should
557
375
be able to pull it again.
559
377
If you want to forget your local changes and just update your branch to
560
match the remote one, use pull --overwrite.
562
If there is no default location set, the first pull will set it. After
563
that, you can omit the location to use the default. To change the
564
default, use --remember. The value will only be saved if the remote
565
location can be accessed.
378
match the remote one, use --overwrite.
568
_see_also = ['push', 'update']
569
takes_options = ['remember', 'overwrite', 'revision', 'verbose',
571
help='branch to pull into, '
572
'rather than the one containing the working directory',
380
takes_options = ['remember', 'overwrite', 'revision', 'verbose']
577
381
takes_args = ['location?']
578
encoding_type = 'replace'
580
def run(self, location=None, remember=False, overwrite=False,
581
revision=None, verbose=False,
583
from bzrlib.tag import _merge_tags_if_possible
383
def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
584
384
# FIXME: too much stuff is in the command class
587
if directory is None:
590
tree_to = WorkingTree.open_containing(directory)[0]
386
tree_to = WorkingTree.open_containing(u'.')[0]
591
387
branch_to = tree_to.branch
592
except errors.NoWorkingTree:
388
except NoWorkingTree:
594
branch_to = Branch.open_containing(directory)[0]
597
if location is not None:
599
mergeable = bundle.read_mergeable_from_url(
601
except errors.NotABundle:
602
pass # Continue on considering this url a Branch
390
branch_to = Branch.open_containing(u'.')[0]
604
391
stored_loc = branch_to.get_parent()
605
392
if location is None:
606
393
if stored_loc is None:
607
raise errors.BzrCommandError("No pull location known or"
394
raise BzrCommandError("No pull location known or specified.")
610
display_url = urlutils.unescape_for_display(stored_loc,
612
self.outf.write("Using saved location: %s\n" % display_url)
396
print "Using saved location: %s" % stored_loc
613
397
location = stored_loc
615
if mergeable is not None:
616
if revision is not None:
617
raise errors.BzrCommandError(
618
'Cannot use -r with merge directives or bundles')
619
revision_id = mergeable.install_revisions(branch_to.repository)
620
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
622
branch_from = Branch.open(location)
624
if branch_to.get_parent() is None or remember:
625
branch_to.set_parent(branch_from.base)
627
if revision is not None:
628
if len(revision) == 1:
629
revision_id = revision[0].in_history(branch_from).rev_id
631
raise errors.BzrCommandError(
632
'bzr pull --revision takes one value.')
406
raise BzrCommandError('bzr pull --revision takes one value.')
634
408
old_rh = branch_to.revision_history()
635
409
if tree_to is not None:
636
result = tree_to.pull(branch_from, overwrite, revision_id,
637
delta._ChangeReporter(unversioned_filter=tree_to.is_ignored))
410
count = tree_to.pull(br_from, overwrite, rev_id)
639
result = branch_to.pull(branch_from, overwrite, revision_id)
641
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,))
643
from bzrlib.log import show_changed_revisions
644
419
new_rh = branch_to.revision_history()
645
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)
649
426
class cmd_push(Command):
650
"""Update a mirror of this branch.
652
The target branch will not have its working tree populated because this
653
is both expensive, and is not supported on remote file systems.
655
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.
658
438
This command only works on branches that have not diverged. Branches are
659
considered diverged if the destination branch's most recent commit is one
660
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
662
442
If branches have diverged, you can use 'bzr push --overwrite' to replace
663
the other branch completely, discarding its unmerged changes.
443
the other branch completely.
665
445
If you want to ensure you have the different changes in the other branch,
666
do a merge (see bzr help merge) from the other branch, and commit that.
667
After that you will be able to do a push without '--overwrite'.
669
If there is no default push location set, the first push will set it.
670
After that, you can omit the location to use the default. To change the
671
default, use --remember. The value will only be saved if the remote
672
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'.
675
_see_also = ['pull', 'update', 'working-trees']
676
takes_options = ['remember', 'overwrite', 'verbose',
677
Option('create-prefix',
678
help='Create the path leading up to the branch '
679
'if it does not already exist'),
681
help='branch to push from, '
682
'rather than the one containing the working directory',
686
Option('use-existing-dir',
687
help='By default push will fail if the target'
688
' directory exists, but does not already'
689
' have a control directory. This flag will'
690
' 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')]
692
453
takes_args = ['location?']
693
encoding_type = 'replace'
695
455
def run(self, location=None, remember=False, overwrite=False,
696
create_prefix=False, verbose=False,
697
use_existing_dir=False,
456
create_prefix=False, verbose=False):
699
457
# FIXME: Way too big! Put this into a function called from the
701
if directory is None:
703
br_from = Branch.open_containing(directory)[0]
704
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()
705
464
if location is None:
706
465
if stored_loc is None:
707
raise errors.BzrCommandError("No push location known or specified.")
466
raise BzrCommandError("No push location known or specified.")
709
display_url = urlutils.unescape_for_display(stored_loc,
711
self.outf.write("Using saved location: %s\n" % display_url)
468
print "Using saved location: %s" % stored_loc
712
469
location = stored_loc
714
to_transport = transport.get_transport(location)
716
br_to = repository_to = dir_to = None
718
dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
719
except errors.NotBranchError:
720
pass # Didn't find anything
722
# If we can open a branch, use its direct repository, otherwise see
723
# if there is a repository without a branch.
725
br_to = dir_to.open_branch()
726
except errors.NotBranchError:
727
# Didn't find a branch, can we find a repository?
729
repository_to = dir_to.find_repository()
730
except errors.NoRepositoryPresent:
733
# Found a branch, so we must have found a repository
734
repository_to = br_to.repository
738
# The destination doesn't exist; create it.
739
# XXX: Refactor the create_prefix/no_create_prefix code into a
740
# common helper function
742
to_transport.mkdir('.')
743
except errors.FileExists:
744
if not use_existing_dir:
745
raise errors.BzrCommandError("Target directory %s"
746
" already exists, but does not have a valid .bzr"
747
" directory. Supply --use-existing-dir to push"
748
" there anyway." % location)
749
except errors.NoSuchFile:
750
if not create_prefix:
751
raise errors.BzrCommandError("Parent directory of %s"
753
"\nYou may supply --create-prefix to create all"
754
" leading parent directories."
757
_create_prefix(to_transport)
759
# Now the target directory exists, but doesn't have a .bzr
760
# directory. So we need to create it, along with any work to create
761
# all of the dependent branches, etc.
762
dir_to = br_from.bzrdir.clone_on_transport(to_transport,
763
revision_id=br_from.last_revision())
471
dir_to = bzrlib.bzrdir.BzrDir.open(location)
764
472
br_to = dir_to.open_branch()
765
# TODO: Some more useful message about what was copied
766
note('Created new branch.')
767
# We successfully created the target, remember it
768
if br_from.get_push_location() is None or remember:
769
br_from.set_push_location(br_to.base)
770
elif repository_to is None:
771
# we have a bzrdir but no branch or repository
772
# XXX: Figure out what to do other than complain.
773
raise errors.BzrCommandError("At %s you have a valid .bzr control"
774
" directory, but not a branch or repository. This is an"
775
" unsupported configuration. Please move the target directory"
776
" out of the way and try again."
779
# We have a repository but no branch, copy the revisions, and then
473
except NotBranchError:
780
474
# create a branch.
781
last_revision_id = br_from.last_revision()
782
repository_to.fetch(br_from.repository,
783
revision_id=last_revision_id)
784
br_to = br_from.clone(dir_to, revision_id=last_revision_id)
785
note('Created new branch.')
786
if br_from.get_push_location() is None or remember:
787
br_from.set_push_location(br_to.base)
788
else: # We have a valid to branch
789
# We were able to connect to the remote location, so remember it
790
# we don't need to successfully push because of possible divergence.
791
if br_from.get_push_location() is None or remember:
792
br_from.set_push_location(br_to.base)
793
old_rh = br_to.revision_history()
475
transport = get_transport(location).clone('..')
476
if not create_prefix:
796
tree_to = dir_to.open_workingtree()
797
except errors.NotLocalUrl:
798
warning("This transport does not update the working "
799
"tree of: %s. See 'bzr help working-trees' for "
800
"more information." % br_to.base)
801
push_result = br_from.push(br_to, overwrite)
802
except errors.NoWorkingTree:
803
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))]
807
push_result = br_from.push(tree_to.branch, overwrite)
811
except errors.DivergedBranches:
812
raise errors.BzrCommandError('These branches have diverged.'
813
' Try using "merge" and then "push".')
814
if push_result is not None:
815
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 create "
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('This transport does not update the working '
508
'tree of: %s' % (br_to.base,))
509
count = br_to.pull(br_from, overwrite)
510
except NoWorkingTree:
511
count = br_to.pull(br_from, overwrite)
513
count = tree_to.pull(br_from, overwrite)
514
except DivergedBranches:
515
raise BzrCommandError("These branches have diverged."
516
" Try a merge then push with overwrite.")
517
if br_from.get_push_location() is None or remember:
518
br_from.set_push_location(location)
519
note('%d revision(s) pushed.' % (count,))
817
522
new_rh = br_to.revision_history()
818
523
if old_rh != new_rh:
819
524
# Something changed
820
525
from bzrlib.log import show_changed_revisions
821
show_changed_revisions(br_to, old_rh, new_rh,
824
# we probably did a clone rather than a push, so a message was
526
show_changed_revisions(br_to, old_rh, new_rh)
829
529
class cmd_branch(Command):
1047
750
class cmd_info(Command):
1048
"""Show information about a working tree, branch or repository.
1050
This command will show all known locations and formats associated to the
1051
tree, branch or repository. Statistical information is included with
1054
Branches and working trees will also report any missing revisions.
1056
_see_also = ['revno', 'working-trees', 'repositories']
1057
takes_args = ['location?']
1058
takes_options = ['verbose']
751
"""Show statistical information about a branch."""
752
takes_args = ['branch?']
1060
754
@display_command
1061
def run(self, location=None, verbose=0):
1062
from bzrlib.info import show_bzrdir_info
1063
show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
755
def run(self, branch=None):
757
bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0])
1067
760
class cmd_remove(Command):
1068
"""Remove files or directories.
1070
This makes bzr stop tracking changes to the specified files and
1071
delete them if they can easily be recovered using revert.
1073
You can specify one or more files, and/or --new. If you specify --new,
1074
only 'added' files will be removed. If you specify both, then new files
1075
in the specified directories will be removed. If the directories are
1076
also new, they will also be removed.
761
"""Make a file unversioned.
763
This makes bzr stop tracking changes to a versioned file. It does
764
not delete the working copy.
1078
takes_args = ['file*']
1079
takes_options = ['verbose',
1080
Option('new', help='remove newly-added files'),
1081
RegistryOption.from_kwargs('file-deletion-strategy',
1082
'The file deletion mode to be used',
1083
title='Deletion Strategy', value_switches=True, enum_switch=False,
1084
safe='Only delete files if they can be'
1085
' safely recovered (default).',
1086
keep="Don't delete any files.",
1087
force='Delete all the specified files, even if they can not be '
1088
'recovered and even if they are non-empty directories.')]
766
takes_args = ['file+']
767
takes_options = ['verbose']
1089
768
aliases = ['rm']
1090
encoding_type = 'replace'
1092
def run(self, file_list, verbose=False, new=False,
1093
file_deletion_strategy='safe'):
770
def run(self, file_list, verbose=False):
1094
771
tree, file_list = tree_files(file_list)
1096
if file_list is not None:
1097
file_list = [f for f in file_list if f != '']
1099
raise errors.BzrCommandError('Specify one or more files to'
1100
' remove, or use --new.')
1103
added = tree.changes_from(tree.basis_tree(),
1104
specific_files=file_list).added
1105
file_list = sorted([f[0] for f in added], reverse=True)
1106
if len(file_list) == 0:
1107
raise errors.BzrCommandError('No matching files.')
1108
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1109
keep_files=file_deletion_strategy=='keep',
1110
force=file_deletion_strategy=='force')
772
tree.remove(file_list, verbose=verbose)
1113
775
class cmd_file_id(Command):
1246
871
bzr commit -m 'imported project'
1249
_see_also = ['init-repo', 'branch', 'checkout']
1250
873
takes_args = ['location?']
1251
874
takes_options = [
1252
Option('create-prefix',
1253
help='Create the path leading up to the branch '
1254
'if it does not already exist'),
1255
RegistryOption('format',
1256
help='Specify a format for this branch. '
1257
'See "help formats".',
1258
registry=bzrdir.format_registry,
1259
converter=bzrdir.format_registry.make_bzrdir,
1260
value_switches=True,
1261
title="Branch Format",
1263
Option('append-revisions-only',
1264
help='Never change revnos or the existing log.'
1265
' Append revisions to it only.')
1267
def run(self, location=None, format=None, append_revisions_only=False,
1268
create_prefix=False):
1270
format = bzrdir.format_registry.make_bzrdir('default')
876
help='Create a specific format rather than the'
877
' current default format. Currently this '
878
' option only accepts =metadir',
879
type=get_format_type),
881
def run(self, location=None, format=None):
882
from bzrlib.branch import Branch
1271
883
if location is None:
1274
to_transport = transport.get_transport(location)
1276
# The path has to exist to initialize a
1277
# branch inside of it.
1278
# Just using os.mkdir, since I don't
1279
# believe that we want to create a bunch of
1280
# locations if the user supplies an extended path
1282
to_transport.ensure_base()
1283
except errors.NoSuchFile:
1284
if not create_prefix:
1285
raise errors.BzrCommandError("Parent directory of %s"
1287
"\nYou may supply --create-prefix to create all"
1288
" leading parent directories."
1290
_create_prefix(to_transport)
1293
existing_bzrdir = bzrdir.BzrDir.open(location)
1294
except errors.NotBranchError:
1295
# really a NotBzrDir error...
1296
branch = bzrdir.BzrDir.create_branch_convenience(to_transport.base,
1299
from bzrlib.transport.local import LocalTransport
1300
if existing_bzrdir.has_branch():
1301
if (isinstance(to_transport, LocalTransport)
1302
and not existing_bzrdir.has_workingtree()):
1303
raise errors.BranchExistsWithoutWorkingTree(location)
1304
raise errors.AlreadyBranchError(location)
1306
branch = existing_bzrdir.create_branch()
1307
existing_bzrdir.create_workingtree()
1308
if append_revisions_only:
1310
branch.set_append_revisions_only(True)
1311
except errors.UpgradeRequired:
1312
raise errors.BzrCommandError('This branch format cannot be set'
1313
' to append-revisions-only. Try --experimental-branch6')
886
# The path has to exist to initialize a
887
# branch inside of it.
888
# Just using os.mkdir, since I don't
889
# believe that we want to create a bunch of
890
# locations if the user supplies an extended path
891
if not os.path.exists(location):
893
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1316
896
class cmd_init_repository(Command):
1317
"""Create a shared repository to hold branches.
1319
New branches created under the repository directory will store their
1320
revisions in the repository, not in the branch directory.
1322
If the --no-trees option is used then the branches in the repository
1323
will not have working trees by default.
1326
bzr init-repo --no-trees repo
1328
bzr checkout --lightweight repo/trunk trunk-checkout
1332
See 'bzr help repositories' for more information.
1335
_see_also = ['init', 'branch', 'checkout']
1336
takes_args = ["location"]
1337
takes_options = [RegistryOption('format',
1338
help='Specify a format for this repository. See'
1339
' "bzr help formats" for details',
1340
registry=bzrdir.format_registry,
1341
converter=bzrdir.format_registry.make_bzrdir,
1342
value_switches=True, title='Repository format'),
1344
help='Branches in the repository will default to'
1345
' not having a working tree'),
897
"""Create a shared repository to keep branches in."""
898
takes_args = ["location"]
899
takes_options = [Option('format',
900
help='Use a specific format rather than the'
901
' current default format. Currently this'
902
' option only accepts "metadir" and "knit"'
903
' WARNING: the knit format is currently unstable'
904
' and only for experimental use.',
905
type=get_format_type),
907
help='Allows branches in repository to have'
1347
909
aliases = ["init-repo"]
1349
def run(self, location, format=None, no_trees=False):
910
def run(self, location, format=None, trees=False):
911
from bzrlib.bzrdir import BzrDirMetaFormat1
912
from bzrlib.transport import get_transport
1350
913
if format is None:
1351
format = bzrdir.format_registry.make_bzrdir('default')
1353
if location is None:
1356
to_transport = transport.get_transport(location)
1357
to_transport.ensure_base()
1359
newdir = format.initialize_on_transport(to_transport)
914
format = BzrDirMetaFormat1()
915
get_transport(location).mkdir('')
916
newdir = format.initialize(location)
1360
917
repo = newdir.create_repository(shared=True)
1361
repo.set_make_working_trees(not no_trees)
918
repo.set_make_working_trees(trees)
1364
921
class cmd_diff(Command):
1365
"""Show differences in the working tree or between revisions.
922
"""Show differences in working tree.
1367
924
If files are listed, only the changes in those files are listed.
1368
925
Otherwise, all changes for the tree are listed.
1370
"bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1371
produces patches suitable for "patch -p1".
1375
Shows the difference in the working tree versus the last commit
1377
Difference between the working tree and revision 1
1379
Difference between revision 2 and revision 1
1380
bzr diff --prefix old/:new/
1381
Same as 'bzr diff' but prefix paths with old/ and new/
1382
bzr diff bzr.mine bzr.dev
1383
Show the differences between the two working trees
1385
Show just the differences for 'foo.c'
932
# TODO: Allow diff across branches.
1387
933
# TODO: Option to use external diff command; could be GNU diff, wdiff,
1388
934
# or a graphical diff.
1390
936
# TODO: Python difflib is not exactly the same as unidiff; should
1391
937
# either fix it up or prefer to use an external diff.
939
# TODO: If a directory is given, diff everything under that.
1393
941
# TODO: Selected-file diff is inefficient and doesn't show you
1394
942
# deleted files.
1396
944
# TODO: This probably handles non-Unix newlines poorly.
1398
_see_also = ['status']
1399
946
takes_args = ['file*']
1400
takes_options = ['revision', 'diff-options',
1401
Option('prefix', type=str,
1403
help='Set prefixes to added to old and new filenames, as '
1404
'two values separated by a colon. (eg "old/:new/")'),
947
takes_options = ['revision', 'diff-options']
1406
948
aliases = ['di', 'dif']
1407
encoding_type = 'exact'
1409
950
@display_command
1410
def run(self, revision=None, file_list=None, diff_options=None,
951
def run(self, revision=None, file_list=None, diff_options=None):
1412
952
from bzrlib.diff import diff_cmd_helper, show_diff_trees
1414
if (prefix is None) or (prefix == '0'):
1422
old_label, new_label = prefix.split(":")
1424
raise errors.BzrCommandError(
1425
'--prefix expects two values separated by a colon'
1426
' (eg "old/:new/")')
1428
if revision and len(revision) > 2:
1429
raise errors.BzrCommandError('bzr diff --revision takes exactly'
1430
' one or two revision specifiers')
1433
954
tree1, file_list = internal_tree_files(file_list)
1437
except errors.FileInWrongBranch:
958
except FileInWrongBranch:
1438
959
if len(file_list) != 2:
1439
raise errors.BzrCommandError("Files are in different branches")
960
raise BzrCommandError("Files are in different branches")
1441
962
tree1, file1 = WorkingTree.open_containing(file_list[0])
1442
963
tree2, file2 = WorkingTree.open_containing(file_list[1])
1443
964
if file1 != "" or file2 != "":
1444
965
# FIXME diff those two files. rbc 20051123
1445
raise errors.BzrCommandError("Files are in different branches")
966
raise BzrCommandError("Files are in different branches")
1446
967
file_list = None
1447
except errors.NotBranchError:
1448
if (revision is not None and len(revision) == 2
1449
and not revision[0].needs_branch()
1450
and not revision[1].needs_branch()):
1451
# If both revision specs include a branch, we can
1452
# diff them without needing a local working tree
1453
tree1, tree2 = None, None
1457
if tree2 is not None:
1458
if revision is not None:
1459
# FIXME: but there should be a clean way to diff between
1460
# non-default versions of two trees, it's not hard to do
1462
raise errors.BzrCommandError(
1463
"Sorry, diffing arbitrary revisions across branches "
1464
"is not implemented yet")
1465
return show_diff_trees(tree1, tree2, sys.stdout,
1466
specific_files=file_list,
1467
external_diff_options=diff_options,
1468
old_label=old_label, new_label=new_label)
1470
return diff_cmd_helper(tree1, file_list, diff_options,
1471
revision_specs=revision,
1472
old_label=old_label, new_label=new_label)
968
if revision is not None:
969
if tree2 is not None:
970
raise BzrCommandError("Can't specify -r with two branches")
971
if (len(revision) == 1) or (revision[1].spec is None):
972
return diff_cmd_helper(tree1, file_list, diff_options,
974
elif len(revision) == 2:
975
return diff_cmd_helper(tree1, file_list, diff_options,
976
revision[0], revision[1])
978
raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
980
if tree2 is not None:
981
return show_diff_trees(tree1, tree2, sys.stdout,
982
specific_files=file_list,
983
external_diff_options=diff_options)
985
return diff_cmd_helper(tree1, file_list, diff_options)
1475
988
class cmd_deleted(Command):
1630
1106
# find the file id to log:
1632
tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1108
dir, fp = bzrdir.BzrDir.open_containing(location)
1109
b = dir.open_branch()
1636
tree = b.basis_tree()
1637
file_id = tree.path2id(fp)
1639
raise errors.BzrCommandError(
1640
"Path does not have any revision history: %s" %
1113
inv = dir.open_workingtree().inventory
1114
except (errors.NotBranchError, errors.NotLocalUrl):
1115
# either no tree, or is remote.
1116
inv = b.basis_tree().inventory
1117
file_id = inv.path2id(fp)
1643
1119
# local dir only
1644
1120
# FIXME ? log the current subdir only RBC 20060203
1645
if revision is not None \
1646
and len(revision) > 0 and revision[0].get_branch():
1647
location = revision[0].get_branch()
1650
dir, relpath = bzrdir.BzrDir.open_containing(location)
1121
dir, relpath = bzrdir.BzrDir.open_containing('.')
1651
1122
b = dir.open_branch()
1655
if revision is None:
1658
elif len(revision) == 1:
1659
rev1 = rev2 = revision[0].in_history(b).revno
1660
elif len(revision) == 2:
1661
if revision[1].get_branch() != revision[0].get_branch():
1662
# b is taken from revision[0].get_branch(), and
1663
# show_log will use its revision_history. Having
1664
# different branches will lead to weird behaviors.
1665
raise errors.BzrCommandError(
1666
"Log doesn't accept two revisions in different"
1668
if revision[0].spec is None:
1669
# missing begin-range means first revision
1672
rev1 = revision[0].in_history(b).revno
1674
if revision[1].spec is None:
1675
# missing end-range means last known revision
1678
rev2 = revision[1].in_history(b).revno
1680
raise errors.BzrCommandError(
1681
'bzr log --revision takes one or two values.')
1683
# By this point, the revision numbers are converted to the +ve
1684
# form if they were supplied in the -ve form, so we can do
1685
# this comparison in relative safety
1687
(rev2, rev1) = (rev1, rev2)
1689
if log_format is None:
1690
log_format = log.log_formatter_registry.get_default(b)
1692
lf = log_format(show_ids=show_ids, to_file=self.outf,
1693
show_timezone=timezone)
1699
direction=direction,
1700
start_revision=rev1,
1124
if revision is None:
1127
elif len(revision) == 1:
1128
rev1 = rev2 = revision[0].in_history(b).revno
1129
elif len(revision) == 2:
1130
if revision[0].spec is None:
1131
# missing begin-range means first revision
1134
rev1 = revision[0].in_history(b).revno
1136
if revision[1].spec is None:
1137
# missing end-range means last known revision
1140
rev2 = revision[1].in_history(b).revno
1142
raise BzrCommandError('bzr log --revision takes one or two values.')
1144
# By this point, the revision numbers are converted to the +ve
1145
# form if they were supplied in the -ve form, so we can do
1146
# this comparison in relative safety
1148
(rev2, rev1) = (rev1, rev2)
1150
mutter('encoding log as %r', bzrlib.user_encoding)
1152
# use 'replace' so that we don't abort if trying to write out
1153
# in e.g. the default C locale.
1154
outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
1156
if (log_format == None):
1157
default = bzrlib.config.BranchConfig(b).log_format()
1158
log_format = get_log_format(long=long, short=short, line=line, default=default)
1160
lf = log_formatter(log_format,
1163
show_timezone=timezone)
1169
direction=direction,
1170
start_revision=rev1,
1708
1175
def get_log_format(long=False, short=False, line=False, default='long'):
1751
1214
Option('ignored', help='Print ignored files'),
1753
1216
Option('null', help='Null separate the files'),
1756
1218
@display_command
1757
1219
def run(self, revision=None, verbose=False,
1758
1220
non_recursive=False, from_root=False,
1759
1221
unknown=False, versioned=False, ignored=False,
1760
null=False, kind=None, show_ids=False, path=None):
1762
if kind and kind not in ('file', 'directory', 'symlink'):
1763
raise errors.BzrCommandError('invalid kind specified')
1765
1224
if verbose and null:
1766
raise errors.BzrCommandError('Cannot set both --verbose and --null')
1225
raise BzrCommandError('Cannot set both --verbose and --null')
1767
1226
all = not (unknown or versioned or ignored)
1769
1228
selection = {'I':ignored, '?':unknown, 'V':versioned}
1776
raise errors.BzrCommandError('cannot specify both --from-root'
1780
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
1230
tree, relpath = WorkingTree.open_containing(u'.')
1786
1235
if revision is not None:
1787
tree = branch.repository.revision_tree(
1788
revision[0].in_history(branch).rev_id)
1790
tree = branch.basis_tree()
1794
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1795
if fp.startswith(relpath):
1796
fp = osutils.pathjoin(prefix, fp[len(relpath):])
1797
if non_recursive and '/' in fp:
1799
if not all and not selection[fc]:
1801
if kind is not None and fkind != kind:
1804
kindch = entry.kind_character()
1805
outstring = '%-8s %s%s' % (fc, fp, kindch)
1806
if show_ids and fid is not None:
1807
outstring = "%-50s %s" % (outstring, fid)
1808
self.outf.write(outstring + '\n')
1810
self.outf.write(fp + '\0')
1813
self.outf.write(fid)
1814
self.outf.write('\0')
1822
self.outf.write('%-50s %s\n' % (fp, my_id))
1824
self.outf.write(fp + '\n')
1236
tree = tree.branch.repository.revision_tree(
1237
revision[0].in_history(tree.branch).rev_id)
1238
for fp, fc, kind, fid, entry in tree.list_files():
1239
if fp.startswith(relpath):
1240
fp = fp[len(relpath):]
1241
if non_recursive and '/' in fp:
1243
if not all and not selection[fc]:
1246
kindch = entry.kind_character()
1247
print '%-8s %s%s' % (fc, fp, kindch)
1249
sys.stdout.write(fp)
1250
sys.stdout.write('\0')
1829
1256
class cmd_unknowns(Command):
1830
"""List unknown files.
1257
"""List unknown files."""
1836
1258
@display_command
1260
from bzrlib.osutils import quotefn
1838
1261
for f in WorkingTree.open_containing(u'.')[0].unknowns():
1839
self.outf.write(osutils.quotefn(f) + '\n')
1842
1265
class cmd_ignore(Command):
1843
"""Ignore specified files or patterns.
1266
"""Ignore a command or pattern.
1845
1268
To remove patterns from the ignore list, edit the .bzrignore file.
1847
Trailing slashes on patterns are ignored.
1848
If the pattern contains a slash or is a regular expression, it is compared
1849
to the whole path from the branch root. Otherwise, it is compared to only
1850
the last component of the path. To match a file only in the root
1851
directory, prepend './'.
1853
Ignore patterns specifying absolute paths are not allowed.
1855
Ignore patterns may include globbing wildcards such as:
1856
? - Matches any single character except '/'
1857
* - Matches 0 or more characters except '/'
1858
/**/ - Matches 0 or more directories in a path
1859
[a-z] - Matches a single character from within a group of characters
1861
Ignore patterns may also be Python regular expressions.
1862
Regular expression ignore patterns are identified by a 'RE:' prefix
1863
followed by the regular expression. Regular expression ignore patterns
1864
may not include named or numbered groups.
1866
Note: ignore patterns containing shell wildcards must be quoted from
1270
If the pattern contains a slash, it is compared to the whole path
1271
from the branch root. Otherwise, it is compared to only the last
1272
component of the path. To match a file only in the root directory,
1275
Ignore patterns are case-insensitive on case-insensitive systems.
1277
Note: wildcards must be quoted from the shell on Unix.
1870
1280
bzr ignore ./Makefile
1871
1281
bzr ignore '*.class'
1872
bzr ignore 'lib/**/*.o'
1873
bzr ignore 'RE:lib/.*\.o'
1876
_see_also = ['status', 'ignored']
1877
takes_args = ['name_pattern*']
1879
Option('old-default-rules',
1880
help='Out the ignore rules bzr < 0.9 always used.')
1283
# TODO: Complain if the filename is absolute
1284
takes_args = ['name_pattern']
1883
def run(self, name_pattern_list=None, old_default_rules=None):
1286
def run(self, name_pattern):
1884
1287
from bzrlib.atomicfile import AtomicFile
1885
if old_default_rules is not None:
1886
# dump the rules and exit
1887
for pattern in ignores.OLD_DEFAULTS:
1890
if not name_pattern_list:
1891
raise errors.BzrCommandError("ignore requires at least one "
1892
"NAME_PATTERN or --old-default-rules")
1893
name_pattern_list = [globbing.normalize_pattern(p)
1894
for p in name_pattern_list]
1895
for name_pattern in name_pattern_list:
1896
if (name_pattern[0] == '/' or
1897
(len(name_pattern) > 1 and name_pattern[1] == ':')):
1898
raise errors.BzrCommandError(
1899
"NAME_PATTERN should not be an absolute path")
1900
1290
tree, relpath = WorkingTree.open_containing(u'.')
1901
1291
ifn = tree.abspath('.bzrignore')
1902
1293
if os.path.exists(ifn):
1903
1294
f = open(ifn, 'rt')
2143
1475
aliases = ['ci', 'checkin']
2145
def _get_bug_fix_properties(self, fixes, branch):
2147
# Configure the properties for bug fixing attributes.
2148
for fixed_bug in fixes:
2149
tokens = fixed_bug.split(':')
2150
if len(tokens) != 2:
2151
raise errors.BzrCommandError(
2152
"Invalid bug %s. Must be in the form of 'tag:id'. "
2153
"Commit refused." % fixed_bug)
2154
tag, bug_id = tokens
2156
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2157
except errors.UnknownBugTrackerAbbreviation:
2158
raise errors.BzrCommandError(
2159
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2160
except errors.MalformedBugIdentifier:
2161
raise errors.BzrCommandError(
2162
"Invalid bug identifier for %s. Commit refused."
2164
properties.append('%s fixed' % bug_url)
2165
return '\n'.join(properties)
2167
1477
def run(self, message=None, file=None, verbose=True, selected_list=None,
2168
unchanged=False, strict=False, local=False, fixes=None):
1478
unchanged=False, strict=False, local=False):
2169
1479
from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
2170
1480
from bzrlib.errors import (PointlessCommit, ConflictsInTree,
2171
1481
StrictCommitFailed)
2172
1482
from bzrlib.msgeditor import edit_commit_message, \
2173
1483
make_commit_message_template
1484
from tempfile import TemporaryFile
2175
1487
# TODO: Need a blackbox test for invoking the external editor; may be
2176
1488
# slightly problematic to run this cross-platform.
2178
1490
# TODO: do more checks that the commit will succeed before
2179
1491
# spending the user's valuable time typing a commit message.
1493
# TODO: if the commit *does* happen to fail, then save the commit
1494
# message to a temporary file where it can be recovered
2183
1495
tree, selected_list = tree_files(selected_list)
2184
if selected_list == ['']:
2185
# workaround - commit of root of tree should be exactly the same
2186
# as just default commit in that tree, and succeed even though
2187
# selected-file merge commit is not done yet
2190
bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2192
properties['bugs'] = bug_property
2194
1496
if local and not tree.branch.get_bound_location():
2195
1497
raise errors.LocalRequiresBoundBranch()
2197
def get_message(commit_obj):
2198
"""Callback to get commit message"""
2199
my_message = message
2200
if my_message is None and not file:
2201
template = make_commit_message_template(tree, selected_list)
2202
my_message = edit_commit_message(template)
2203
if my_message is None:
2204
raise errors.BzrCommandError("please specify a commit"
2205
" message with either --message or --file")
2206
elif my_message and file:
2207
raise errors.BzrCommandError(
2208
"please specify either --message or --file")
2210
my_message = codecs.open(file, 'rt',
2211
bzrlib.user_encoding).read()
2212
if my_message == "":
2213
raise errors.BzrCommandError("empty commit message specified")
1498
if message is None and not file:
1499
template = make_commit_message_template(tree, selected_list)
1500
message = edit_commit_message(template)
1502
raise BzrCommandError("please specify a commit message"
1503
" with either --message or --file")
1504
elif message and file:
1505
raise BzrCommandError("please specify either --message or --file")
1509
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1512
raise BzrCommandError("empty commit message specified")
2217
1515
reporter = ReportCommitToLog()
2219
1517
reporter = NullCommitReporter()
2222
tree.commit(message_callback=get_message,
2223
specific_files=selected_list,
1520
tree.commit(message, specific_files=selected_list,
2224
1521
allow_pointless=unchanged, strict=strict, local=local,
2225
reporter=reporter, revprops=properties)
2226
1523
except PointlessCommit:
2227
1524
# FIXME: This should really happen before the file is read in;
2228
1525
# perhaps prepare the commit; get the message; then actually commit
2229
raise errors.BzrCommandError("no changes to commit."
2230
" use --unchanged to commit anyhow")
1526
raise BzrCommandError("no changes to commit",
1527
["use --unchanged to commit anyhow"])
2231
1528
except ConflictsInTree:
2232
raise errors.BzrCommandError('Conflicts detected in working '
2233
'tree. Use "bzr conflicts" to list, "bzr resolve FILE" to'
1529
raise BzrCommandError("Conflicts detected in working tree. "
1530
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
2235
1531
except StrictCommitFailed:
2236
raise errors.BzrCommandError("Commit refused because there are"
2237
" unknown files in the working tree.")
1532
raise BzrCommandError("Commit refused because there are unknown "
1533
"files in the working tree.")
2238
1534
except errors.BoundBranchOutOfDate, e:
2239
raise errors.BzrCommandError(str(e) + "\n"
2240
'To commit to master branch, run update and then commit.\n'
2241
'You can also pass --local to commit to continue working '
1535
raise BzrCommandError(str(e)
1536
+ ' Either unbind, update, or'
1537
' pass --local to commit.')
2245
1540
class cmd_check(Command):
2414
1673
return FakeNFSServer
2415
1674
msg = "No known transport type %s. Supported types are: sftp\n" %\
2417
raise errors.BzrCommandError(msg)
1676
raise BzrCommandError(msg)
2420
1679
takes_args = ['testspecs*']
2421
1680
takes_options = ['verbose',
2423
help='stop when one test fails',
2426
Option('keep-output',
1681
Option('one', help='stop when one test fails'),
1682
Option('keep-output',
2427
1683
help='keep output directories when tests fail'),
2429
1685
help='Use a different transport by default '
2430
1686
'throughout the test suite.',
2431
1687
type=get_transport_type),
2432
Option('benchmark', help='run the bzr benchmarks.'),
2433
Option('lsprof-timed',
2434
help='generate lsprof output for benchmarked'
2435
' sections of code.'),
2436
Option('cache-dir', type=str,
2437
help='a directory to cache intermediate'
2438
' benchmark steps'),
2439
Option('clean-output',
2440
help='clean temporary tests directories'
2441
' without running tests'),
2443
help='run all tests, but run specified tests first',
2446
Option('numbered-dirs',
2447
help='use numbered dirs for TestCaseInTempDir'),
2449
help='list the tests instead of running them'),
2450
Option('randomize', type=str, argname="SEED",
2451
help='randomize the order of tests using the given'
2452
' seed or "now" for the current time'),
2453
Option('exclude', type=str, argname="PATTERN",
2455
help='exclude tests that match this regular'
2458
encoding_type = 'replace'
2460
def run(self, testspecs_list=None, verbose=None, one=False,
2461
keep_output=False, transport=None, benchmark=None,
2462
lsprof_timed=None, cache_dir=None, clean_output=False,
2463
first=False, numbered_dirs=None, list_only=False,
2464
randomize=None, exclude=None):
1690
def run(self, testspecs_list=None, verbose=False, one=False,
1691
keep_output=False, transport=None):
2465
1692
import bzrlib.ui
2466
1693
from bzrlib.tests import selftest
2467
import bzrlib.benchmarks as benchmarks
2468
from bzrlib.benchmarks import tree_creator
2471
from bzrlib.tests import clean_selftest_output
2472
clean_selftest_output()
2475
warning("notice: selftest --keep-output "
2476
"is no longer supported; "
2477
"test output is always removed")
2479
if numbered_dirs is None and sys.platform == 'win32':
2480
numbered_dirs = True
2482
if cache_dir is not None:
2483
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2484
print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2485
print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2487
if testspecs_list is not None:
2488
pattern = '|'.join(testspecs_list)
2492
test_suite_factory = benchmarks.test_suite
2495
# TODO: should possibly lock the history file...
2496
benchfile = open(".perf_history", "at", buffering=1)
2498
test_suite_factory = None
1694
# we don't want progress meters from the tests to go to the
1695
# real output; and we don't want log messages cluttering up
1697
save_ui = bzrlib.ui.ui_factory
1698
bzrlib.trace.info('running tests...')
1700
bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1701
if testspecs_list is not None:
1702
pattern = '|'.join(testspecs_list)
2503
1705
result = selftest(verbose=verbose,
2504
1706
pattern=pattern,
2505
1707
stop_on_failure=one,
2506
transport=transport,
2507
test_suite_factory=test_suite_factory,
2508
lsprof_timed=lsprof_timed,
2509
bench_history=benchfile,
2510
matching_tests_first=first,
2511
numbered_dirs=numbered_dirs,
2512
list_only=list_only,
2513
random_seed=randomize,
2514
exclude_pattern=exclude
1708
keep_output=keep_output,
1709
transport=transport)
1711
bzrlib.trace.info('tests passed')
1713
bzrlib.trace.info('tests failed')
1714
return int(not result)
2517
if benchfile is not None:
2520
info('tests passed')
2522
info('tests failed')
2523
return int(not result)
1716
bzrlib.ui.ui_factory = save_ui
1719
def _get_bzr_branch():
1720
"""If bzr is run from a branch, return Branch or None"""
1721
import bzrlib.errors
1722
from bzrlib.branch import Branch
1723
from bzrlib.osutils import abspath
1724
from os.path import dirname
1727
branch = Branch.open(dirname(abspath(dirname(__file__))))
1729
except bzrlib.errors.BzrError:
1734
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1735
# is bzrlib itself in a branch?
1736
branch = _get_bzr_branch()
1738
rh = branch.revision_history()
1740
print " bzr checkout, revision %d" % (revno,)
1741
print " nick: %s" % (branch.nick,)
1743
print " revid: %s" % (rh[-1],)
1744
print bzrlib.__copyright__
1745
print "http://bazaar-ng.org/"
1747
print "bzr comes with ABSOLUTELY NO WARRANTY. bzr is free software, and"
1748
print "you may use, modify and redistribute it under the terms of the GNU"
1749
print "General Public License version 2 or later."
2526
1752
class cmd_version(Command):
2527
1753
"""Show version of bzr."""
2529
1754
@display_command
2531
from bzrlib.version import show_version
2535
1758
class cmd_rocks(Command):
2536
1759
"""Statement of optimism."""
2540
1761
@display_command
2542
print "It sure does!"
1763
print "it sure does!"
2545
1766
class cmd_find_merge_base(Command):
2546
"""Find and print a base revision for merging two branches."""
1767
"""Find and print a base revision for merging two branches.
2547
1769
# TODO: Options to specify revisions on either side, as if
2548
1770
# merging only part of the history.
2549
1771
takes_args = ['branch', 'other']
2586
1825
Use bzr resolve when you have fixed a problem. See also bzr conflicts.
2588
If there is no default branch set, the first merge will set it. After
2589
that, you can omit the branch to use the default. To change the
2590
default, use --remember. The value will only be saved if the remote
2591
location can be accessed.
2593
The results of the merge are placed into the destination working
2594
directory, where they can be reviewed (with bzr diff), tested, and then
2595
committed to record the result of the merge.
2599
To merge the latest revision from bzr.dev:
2600
bzr merge ../bzr.dev
1829
To merge the latest revision from bzr.dev
1830
bzr merge ../bzr.dev
2602
To merge changes up to and including revision 82 from bzr.dev:
2603
bzr merge -r 82 ../bzr.dev
1832
To merge changes up to and including revision 82 from bzr.dev
1833
bzr merge -r 82 ../bzr.dev
2605
1835
To merge the changes introduced by 82, without previous changes:
2606
bzr merge -r 81..82 ../bzr.dev
1836
bzr merge -r 81..82 ../bzr.dev
2608
1838
merge refuses to run if there are any uncommitted changes, unless
2609
1839
--force is given.
2612
_see_also = ['update', 'remerge']
2613
1841
takes_args = ['branch?']
2614
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2615
Option('show-base', help="Show base revision text in "
2617
Option('uncommitted', help='Apply uncommitted changes'
2618
' from a working copy, instead of branch changes'),
2619
Option('pull', help='If the destination is already'
2620
' completely merged into the source, pull from the'
2621
' source rather than merging. When this happens,'
2622
' you do not need to commit the result.'),
2624
help='Branch to merge into, '
2625
'rather than the one containing the working directory',
1842
takes_options = ['revision', 'force', 'merge-type', 'reprocess',
1843
Option('show-base', help="Show base revision text in "
2631
1846
def run(self, branch=None, revision=None, force=False, merge_type=None,
2632
show_base=False, reprocess=False, remember=False,
2633
uncommitted=False, pull=False,
2636
from bzrlib.tag import _merge_tags_if_possible
2637
other_revision_id = None
1847
show_base=False, reprocess=False):
2638
1848
if merge_type is None:
2639
merge_type = _mod_merge.Merge3Merger
2641
if directory is None: directory = u'.'
2642
# XXX: jam 20070225 WorkingTree should be locked before you extract its
2643
# inventory. Because merge is a mutating operation, it really
2644
# should be a lock_write() for the whole cmd_merge operation.
2645
# However, cmd_merge open's its own tree in _merge_helper, which
2646
# means if we lock here, the later lock_write() will always block.
2647
# Either the merge helper code should be updated to take a tree,
2648
# (What about tree.merge_from_branch?)
2649
tree = WorkingTree.open_containing(directory)[0]
2650
change_reporter = delta._ChangeReporter(
2651
unversioned_filter=tree.is_ignored)
2653
if branch is not None:
2655
mergeable = bundle.read_mergeable_from_url(
2657
except errors.NotABundle:
2658
pass # Continue on considering this url a Branch
1849
merge_type = Merge3Merger
1851
branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
1853
raise BzrCommandError("No merge location known or specified.")
2660
if revision is not None:
2661
raise errors.BzrCommandError(
2662
'Cannot use -r with merge directives or bundles')
2663
other_revision_id = mergeable.install_revisions(
2664
tree.branch.repository)
2665
revision = [RevisionSpec.from_string(
2666
'revid:' + other_revision_id)]
2668
if revision is None \
2669
or len(revision) < 1 or revision[0].needs_branch():
2670
branch = self._get_remembered_parent(tree, branch, 'Merging from')
1855
print "Using saved location: %s" % branch
2672
1856
if revision is None or len(revision) < 1:
2675
other = [branch, None]
2678
other = [branch, -1]
2679
other_branch, path = Branch.open_containing(branch)
1858
other = [branch, -1]
2682
raise errors.BzrCommandError('Cannot use --uncommitted and'
2683
' --revision at the same time.')
2684
branch = revision[0].get_branch() or branch
2685
1860
if len(revision) == 1:
2686
1861
base = [None, None]
2687
if other_revision_id is not None:
2692
other_branch, path = Branch.open_containing(branch)
2693
revno = revision[0].in_history(other_branch).revno
2694
other = [branch, revno]
1862
other_branch = Branch.open_containing(branch)[0]
1863
revno = revision[0].in_history(other_branch).revno
1864
other = [branch, revno]
2696
1866
assert len(revision) == 2
2697
1867
if None in revision:
2698
raise errors.BzrCommandError(
2699
"Merge doesn't permit empty revision specifier.")
2700
base_branch, path = Branch.open_containing(branch)
2701
branch1 = revision[1].get_branch() or branch
2702
other_branch, path1 = Branch.open_containing(branch1)
2703
if revision[0].get_branch() is not None:
2704
# then path was obtained from it, and is None.
2707
base = [branch, revision[0].in_history(base_branch).revno]
2708
other = [branch1, revision[1].in_history(other_branch).revno]
2710
if ((tree.branch.get_parent() is None or remember) and
2711
other_branch is not None):
2712
tree.branch.set_parent(other_branch.base)
2714
# pull tags now... it's a bit inconsistent to do it ahead of copying
2715
# the history but that's done inside the merge code
2716
if other_branch is not None:
2717
_merge_tags_if_possible(other_branch, tree.branch)
2720
interesting_files = [path]
2722
interesting_files = None
2723
pb = ui.ui_factory.nested_progress_bar()
1868
raise BzrCommandError(
1869
"Merge doesn't permit that revision specifier.")
1870
b = Branch.open_containing(branch)[0]
1872
base = [branch, revision[0].in_history(b).revno]
1873
other = [branch, revision[1].in_history(b).revno]
1874
pb = bzrlib.ui.ui_factory.nested_progress_bar()
2726
conflict_count = _merge_helper(
2727
other, base, other_rev_id=other_revision_id,
2728
check_clean=(not force),
2729
merge_type=merge_type,
2730
reprocess=reprocess,
2731
show_base=show_base,
2734
pb=pb, file_list=interesting_files,
2735
change_reporter=change_reporter)
1877
conflict_count = merge(other, base, check_clean=(not force),
1878
merge_type=merge_type,
1879
reprocess=reprocess,
1880
show_base=show_base,
2738
1884
if conflict_count != 0:
2742
except errors.AmbiguousBase, e:
1888
except bzrlib.errors.AmbiguousBase, e:
2743
1889
m = ("sorry, bzr can't determine the right merge base yet\n"
2744
1890
"candidates are:\n "
2745
1891
+ "\n ".join(e.bases)
2963
2048
class cmd_missing(Command):
2964
2049
"""Show unmerged/unpulled revisions between two branches.
2966
OTHER_BRANCH may be local or remote.
2969
_see_also = ['merge', 'pull']
2051
OTHER_BRANCH may be local or remote."""
2970
2052
takes_args = ['other_branch?']
2971
2053
takes_options = [Option('reverse', 'Reverse the order of revisions'),
2972
2054
Option('mine-only',
2973
2055
'Display changes in the local branch only'),
2974
Option('this' , 'same as --mine-only'),
2975
2056
Option('theirs-only',
2976
'Display changes in the remote branch only'),
2977
Option('other', 'same as --theirs-only'),
2057
'Display changes in the remote branch only'),
2982
encoding_type = 'replace'
2985
2066
def run(self, other_branch=None, reverse=False, mine_only=False,
2986
2067
theirs_only=False, log_format=None, long=False, short=False, line=False,
2987
show_ids=False, verbose=False, this=False, other=False):
2988
from bzrlib.missing import find_unmerged, iter_log_revisions
2068
show_ids=False, verbose=False):
2069
from bzrlib.missing import find_unmerged, iter_log_data
2989
2070
from bzrlib.log import log_formatter
2996
local_branch = Branch.open_containing(u".")[0]
2071
local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2997
2072
parent = local_branch.get_parent()
2998
2073
if other_branch is None:
2999
2074
other_branch = parent
3000
2075
if other_branch is None:
3001
raise errors.BzrCommandError("No peer location known or specified.")
3002
display_url = urlutils.unescape_for_display(parent,
3004
print "Using last location: " + display_url
3006
remote_branch = Branch.open(other_branch)
2076
raise BzrCommandError("No missing location known or specified.")
2077
print "Using last location: " + local_branch.get_parent()
2078
remote_branch = bzrlib.branch.Branch.open(other_branch)
2079
local_branch.lock_write()
3007
2080
if remote_branch.base == local_branch.base:
3008
2081
remote_branch = local_branch
3009
local_branch.lock_read()
3011
2083
remote_branch.lock_read()
3013
2085
local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
3014
if (log_format is None):
3015
log_format = log.log_formatter_registry.get_default(
3017
lf = log_format(to_file=self.outf,
3019
show_timezone='original')
2086
if (log_format == None):
2087
default = bzrlib.config.BranchConfig(local_branch).log_format()
2088
log_format = get_log_format(long=long, short=short, line=line, default=default)
2089
lf = log_formatter(log_format, sys.stdout,
2091
show_timezone='original')
3020
2092
if reverse is False:
3021
2093
local_extra.reverse()
3022
2094
remote_extra.reverse()
3023
2095
if local_extra and not theirs_only:
3024
2096
print "You have %d extra revision(s):" % len(local_extra)
3025
for revision in iter_log_revisions(local_extra,
3026
local_branch.repository,
3028
lf.log_revision(revision)
2097
for data in iter_log_data(local_extra, local_branch.repository,
3029
2100
printed_local = True
3031
2102
printed_local = False
3184
2231
if to_revid is None:
3185
2232
to_revno = b.revno()
3186
2233
if from_revno is None or to_revno is None:
3187
raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2234
raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
3188
2235
for revno in range(from_revno, to_revno + 1):
3189
2236
b.repository.sign_revision(b.get_rev_id(revno),
3192
raise errors.BzrCommandError('Please supply either one revision, or a range.')
2239
raise BzrCommandError('Please supply either one revision, or a range.')
3195
2242
class cmd_bind(Command):
3196
"""Convert the current branch into a checkout of the supplied branch.
2243
"""Bind the current branch to a master branch.
3198
Once converted into a checkout, commits must succeed on the master branch
3199
before they will be applied to the local branch.
2245
After binding, commits must succeed on the master branch
2246
before they are executed on the local one.
3202
_see_also = ['checkouts', 'unbind']
3203
takes_args = ['location?']
2249
takes_args = ['location']
3204
2250
takes_options = []
3206
2252
def run(self, location=None):
3207
2253
b, relpath = Branch.open_containing(u'.')
3208
if location is None:
3210
location = b.get_old_bound_location()
3211
except errors.UpgradeRequired:
3212
raise errors.BzrCommandError('No location supplied. '
3213
'This format does not remember old locations.')
3215
if location is None:
3216
raise errors.BzrCommandError('No location supplied and no '
3217
'previous location known')
3218
2254
b_other = Branch.open(location)
3220
2256
b.bind(b_other)
3221
except errors.DivergedBranches:
3222
raise errors.BzrCommandError('These branches have diverged.'
3223
' Try merging, and then bind again.')
2257
except DivergedBranches:
2258
raise BzrCommandError('These branches have diverged.'
2259
' Try merging, and then bind again.')
3226
2262
class cmd_unbind(Command):
3227
"""Convert the current checkout into a regular branch.
2263
"""Bind the current branch to its parent.
3229
After unbinding, the local branch is considered independent and subsequent
3230
commits will be local only.
2265
After unbinding, the local branch is considered independent.
3233
_see_also = ['checkouts', 'bind']
3234
2268
takes_args = []
3235
2269
takes_options = []
3238
2272
b, relpath = Branch.open_containing(u'.')
3239
2273
if not b.unbind():
3240
raise errors.BzrCommandError('Local branch is not bound')
3243
class cmd_uncommit(Command):
2274
raise BzrCommandError('Local branch is not bound')
2277
class cmd_uncommit(bzrlib.commands.Command):
3244
2278
"""Remove the last committed revision.
2280
By supplying the --all flag, it will not only remove the entry
2281
from revision_history, but also remove all of the entries in the
3246
2284
--verbose will print out what is being removed.
3247
2285
--dry-run will go through all the motions, but not actually
3248
2286
remove anything.
3250
In the future, uncommit will create a revision bundle, which can then
2288
In the future, uncommit will create a changeset, which can then
3254
2292
# TODO: jam 20060108 Add an option to allow uncommit to remove
3255
# unreferenced information in 'branch-as-repository' branches.
2293
# unreferenced information in 'branch-as-repostory' branches.
3256
2294
# TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
3257
2295
# information in shared branches as well.
3258
_see_also = ['commit']
3259
2296
takes_options = ['verbose', 'revision',
3260
2297
Option('dry-run', help='Don\'t actually make changes'),
3261
2298
Option('force', help='Say yes to all questions.')]
3262
2299
takes_args = ['location?']
3265
def run(self, location=None,
2302
def run(self, location=None,
3266
2303
dry_run=False, verbose=False,
3267
2304
revision=None, force=False):
3268
from bzrlib.log import log_formatter, show_log
2305
from bzrlib.branch import Branch
2306
from bzrlib.log import log_formatter
3270
2308
from bzrlib.uncommit import uncommit
3329
2352
CAUTION: Locks should only be broken when you are sure that the process
3330
2353
holding the lock has been stopped.
3332
You can get information on what locks are open via the 'bzr info' command.
3337
takes_args = ['location?']
3339
def run(self, location=None, show=False):
3340
if location is None:
3342
control, relpath = bzrdir.BzrDir.open_containing(location)
3344
control.break_lock()
3345
except NotImplementedError:
3349
class cmd_wait_until_signalled(Command):
3350
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3352
This just prints a line to signal when it is ready, then blocks on stdin.
3358
sys.stdout.write("running\n")
3360
sys.stdin.readline()
3363
class cmd_serve(Command):
3364
"""Run the bzr server."""
3366
aliases = ['server']
3370
help='serve on stdin/out for use from inetd or sshd'),
3372
help='listen for connections on nominated port of the form '
3373
'[hostname:]portnumber. Passing 0 as the port number will '
3374
'result in a dynamically allocated port. Default port is '
3378
help='serve contents of directory',
3380
Option('allow-writes',
3381
help='By default the server is a readonly server. Supplying '
3382
'--allow-writes enables write access to the contents of '
3383
'the served directory and below. '
3387
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3388
from bzrlib.smart import medium, server
3389
from bzrlib.transport import get_transport
3390
from bzrlib.transport.chroot import ChrootServer
3391
from bzrlib.transport.remote import BZR_DEFAULT_PORT, BZR_DEFAULT_INTERFACE
3392
if directory is None:
3393
directory = os.getcwd()
3394
url = urlutils.local_path_to_url(directory)
3395
if not allow_writes:
3396
url = 'readonly+' + url
3397
chroot_server = ChrootServer(get_transport(url))
3398
chroot_server.setUp()
3399
t = get_transport(chroot_server.get_url())
3401
smart_server = medium.SmartServerPipeStreamMedium(
3402
sys.stdin, sys.stdout, t)
3404
host = BZR_DEFAULT_INTERFACE
3406
port = BZR_DEFAULT_PORT
3409
host, port = port.split(':')
3411
smart_server = server.SmartTCPServer(t, host=host, port=port)
3412
print 'listening on port: ', smart_server.port
3414
# for the duration of this server, no UI output is permitted.
3415
# note that this may cause problems with blackbox tests. This should
3416
# be changed with care though, as we dont want to use bandwidth sending
3417
# progress over stderr to smart server clients!
3418
old_factory = ui.ui_factory
3420
ui.ui_factory = ui.SilentUIFactory()
3421
smart_server.serve()
3423
ui.ui_factory = old_factory
3426
class cmd_join(Command):
3427
"""Combine a subtree into its containing tree.
3429
This command is for experimental use only. It requires the target tree
3430
to be in dirstate-with-subtree format, which cannot be converted into
3433
The TREE argument should be an independent tree, inside another tree, but
3434
not part of it. (Such trees can be produced by "bzr split", but also by
3435
running "bzr branch" with the target inside a tree.)
3437
The result is a combined tree, with the subtree no longer an independant
3438
part. This is marked as a merge of the subtree into the containing tree,
3439
and all history is preserved.
3441
If --reference is specified, the subtree retains its independence. It can
3442
be branched by itself, and can be part of multiple projects at the same
3443
time. But operations performed in the containing tree, such as commit
3444
and merge, will recurse into the subtree.
3447
_see_also = ['split']
3448
takes_args = ['tree']
3449
takes_options = [Option('reference', 'join by reference')]
3452
def run(self, tree, reference=False):
3453
sub_tree = WorkingTree.open(tree)
3454
parent_dir = osutils.dirname(sub_tree.basedir)
3455
containing_tree = WorkingTree.open_containing(parent_dir)[0]
3456
repo = containing_tree.branch.repository
3457
if not repo.supports_rich_root():
3458
raise errors.BzrCommandError(
3459
"Can't join trees because %s doesn't support rich root data.\n"
3460
"You can use bzr upgrade on the repository."
3464
containing_tree.add_reference(sub_tree)
3465
except errors.BadReferenceTarget, e:
3466
# XXX: Would be better to just raise a nicely printable
3467
# exception from the real origin. Also below. mbp 20070306
3468
raise errors.BzrCommandError("Cannot join %s. %s" %
3472
containing_tree.subsume(sub_tree)
3473
except errors.BadSubsumeSource, e:
3474
raise errors.BzrCommandError("Cannot join %s. %s" %
3478
class cmd_split(Command):
3479
"""Split a tree into two trees.
3481
This command is for experimental use only. It requires the target tree
3482
to be in dirstate-with-subtree format, which cannot be converted into
3485
The TREE argument should be a subdirectory of a working tree. That
3486
subdirectory will be converted into an independent tree, with its own
3487
branch. Commits in the top-level tree will not apply to the new subtree.
3488
If you want that behavior, do "bzr join --reference TREE".
3491
_see_also = ['join']
3492
takes_args = ['tree']
3496
def run(self, tree):
3497
containing_tree, subdir = WorkingTree.open_containing(tree)
3498
sub_id = containing_tree.path2id(subdir)
3500
raise errors.NotVersionedError(subdir)
3502
containing_tree.extract(sub_id)
3503
except errors.RootNotRich:
3504
raise errors.UpgradeRequired(containing_tree.branch.base)
3508
class cmd_merge_directive(Command):
3509
"""Generate a merge directive for auto-merge tools.
3511
A directive requests a merge to be performed, and also provides all the
3512
information necessary to do so. This means it must either include a
3513
revision bundle, or the location of a branch containing the desired
3516
A submit branch (the location to merge into) must be supplied the first
3517
time the command is issued. After it has been supplied once, it will
3518
be remembered as the default.
3520
A public branch is optional if a revision bundle is supplied, but required
3521
if --diff or --plain is specified. It will be remembered as the default
3522
after the first use.
3525
takes_args = ['submit_branch?', 'public_branch?']
3528
RegistryOption.from_kwargs('patch-type',
3529
'The type of patch to include in the directive',
3530
title='Patch type', value_switches=True, enum_switch=False,
3531
bundle='Bazaar revision bundle (default)',
3532
diff='Normal unified diff',
3533
plain='No patch, just directive'),
3534
Option('sign', help='GPG-sign the directive'), 'revision',
3535
Option('mail-to', type=str,
3536
help='Instead of printing the directive, email to this address'),
3537
Option('message', type=str, short_name='m',
3538
help='Message to use when committing this merge')
3541
encoding_type = 'exact'
3543
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
3544
sign=False, revision=None, mail_to=None, message=None):
3545
from bzrlib.revision import ensure_null, NULL_REVISION
3546
if patch_type == 'plain':
3548
branch = Branch.open('.')
3549
stored_submit_branch = branch.get_submit_branch()
3550
if submit_branch is None:
3551
submit_branch = stored_submit_branch
3553
if stored_submit_branch is None:
3554
branch.set_submit_branch(submit_branch)
3555
if submit_branch is None:
3556
submit_branch = branch.get_parent()
3557
if submit_branch is None:
3558
raise errors.BzrCommandError('No submit branch specified or known')
3560
stored_public_branch = branch.get_public_branch()
3561
if public_branch is None:
3562
public_branch = stored_public_branch
3563
elif stored_public_branch is None:
3564
branch.set_public_branch(public_branch)
3565
if patch_type != "bundle" and public_branch is None:
3566
raise errors.BzrCommandError('No public branch specified or'
3568
if revision is not None:
3569
if len(revision) != 1:
3570
raise errors.BzrCommandError('bzr merge-directive takes '
3571
'exactly one revision identifier')
3573
revision_id = revision[0].in_history(branch).rev_id
3575
revision_id = branch.last_revision()
3576
revision_id = ensure_null(revision_id)
3577
if revision_id == NULL_REVISION:
3578
raise errors.BzrCommandError('No revisions to bundle.')
3579
directive = merge_directive.MergeDirective.from_objects(
3580
branch.repository, revision_id, time.time(),
3581
osutils.local_time_offset(), submit_branch,
3582
public_branch=public_branch, patch_type=patch_type,
3586
self.outf.write(directive.to_signed(branch))
3588
self.outf.writelines(directive.to_lines())
3590
message = directive.to_email(mail_to, branch, sign)
3591
s = SMTPConnection(branch.get_config())
3592
s.send_email(message)
3595
class cmd_tag(Command):
3596
"""Create a tag naming a revision.
3598
Tags give human-meaningful names to revisions. Commands that take a -r
3599
(--revision) option can be given -rtag:X, where X is any previously
3602
Tags are stored in the branch. Tags are copied from one branch to another
3603
along when you branch, push, pull or merge.
3605
It is an error to give a tag name that already exists unless you pass
3606
--force, in which case the tag is moved to point to the new revision.
3609
_see_also = ['commit', 'tags']
3610
takes_args = ['tag_name']
3613
help='Delete this tag rather than placing it.',
3616
help='Branch in which to place the tag.',
3621
help='Replace existing tags',
3626
def run(self, tag_name,
3632
branch, relpath = Branch.open_containing(directory)
3636
branch.tags.delete_tag(tag_name)
3637
self.outf.write('Deleted tag %s.\n' % tag_name)
3640
if len(revision) != 1:
3641
raise errors.BzrCommandError(
3642
"Tags can only be placed on a single revision, "
3644
revision_id = revision[0].in_history(branch).rev_id
3646
revision_id = branch.last_revision()
3647
if (not force) and branch.tags.has_tag(tag_name):
3648
raise errors.TagAlreadyExists(tag_name)
3649
branch.tags.set_tag(tag_name, revision_id)
3650
self.outf.write('Created tag %s.\n' % tag_name)
3655
class cmd_tags(Command):
3658
This tag shows a table of tag names and the revisions they reference.
3664
help='Branch whose tags should be displayed',
3674
branch, relpath = Branch.open_containing(directory)
3675
for tag_name, target in sorted(branch.tags.get_tag_dict().items()):
3676
self.outf.write('%-20s %s\n' % (tag_name, target))
2358
takes_args = ['location']
2359
takes_options = [Option('show',
2360
help="just show information on the lock, " \
2363
def run(self, location, show=False):
2364
raise NotImplementedError("sorry, break-lock is not complete yet; "
2365
"you can remove the 'held' directory manually to break the lock")
3679
2368
# command-line interpretation helper for merge-related commands
3680
def _merge_helper(other_revision, base_revision,
3681
check_clean=True, ignore_zero=False,
3682
this_dir=None, backup_files=False,
3684
file_list=None, show_base=False, reprocess=False,
3687
change_reporter=None,
2369
def merge(other_revision, base_revision,
2370
check_clean=True, ignore_zero=False,
2371
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2372
file_list=None, show_base=False, reprocess=False,
2373
pb=DummyProgress()):
3689
2374
"""Merge changes into a tree.
3713
2398
clients might prefer to call merge.merge_inner(), which has less magic
3716
# Loading it late, so that we don't always have to import bzrlib.merge
3717
if merge_type is None:
3718
merge_type = _mod_merge.Merge3Merger
2401
from bzrlib.merge import Merger
3719
2402
if this_dir is None:
3720
2403
this_dir = u'.'
3721
2404
this_tree = WorkingTree.open_containing(this_dir)[0]
3722
if show_base and not merge_type is _mod_merge.Merge3Merger:
3723
raise errors.BzrCommandError("Show-base is not supported for this merge"
3724
" type. %s" % merge_type)
2405
if show_base and not merge_type is Merge3Merger:
2406
raise BzrCommandError("Show-base is not supported for this merge"
2407
" type. %s" % merge_type)
3725
2408
if reprocess and not merge_type.supports_reprocess:
3726
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
3727
" type %s." % merge_type)
2409
raise BzrCommandError("Reprocess is not supported for this merge"
2410
" type. %s" % merge_type)
3728
2411
if reprocess and show_base:
3729
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
3730
# TODO: jam 20070226 We should really lock these trees earlier. However, we
3731
# only want to take out a lock_tree_write() if we don't have to pull
3732
# any ancestry. But merge might fetch ancestry in the middle, in
3733
# which case we would need a lock_write().
3734
# Because we cannot upgrade locks, for now we live with the fact that
3735
# the tree will be locked multiple times during a merge. (Maybe
3736
# read-only some of the time, but it means things will get read
2412
raise BzrCommandError("Cannot reprocess and show base.")
3739
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
3740
pb=pb, change_reporter=change_reporter)
2414
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
3741
2415
merger.pp = ProgressPhase("Merge phase", 5, pb)
3742
2416
merger.pp.next_phase()
3743
2417
merger.check_basis(check_clean)
3744
if other_rev_id is not None:
3745
merger.set_other_revision(other_rev_id, this_tree.branch)
3747
merger.set_other(other_revision)
2418
merger.set_other(other_revision)
3748
2419
merger.pp.next_phase()
3749
2420
merger.set_base(base_revision)
3750
2421
if merger.base_rev_id == merger.other_rev_id:
3751
2422
note('Nothing to do.')
3753
if file_list is None:
3754
if pull and merger.base_rev_id == merger.this_rev_id:
3755
# FIXME: deduplicate with pull
3756
result = merger.this_tree.pull(merger.this_branch,
3757
False, merger.other_rev_id)
3758
if result.old_revid == result.new_revid:
3759
note('No revisions to pull.')
3761
note('Now on revision %d.' % result.new_revno)
3763
2424
merger.backup_files = backup_files
3764
2425
merger.merge_type = merge_type
3765
2426
merger.set_interesting_files(file_list)
3766
2427
merger.show_base = show_base
3767
2428
merger.reprocess = reprocess
3768
2429
conflicts = merger.do_merge()
3769
if file_list is None:
3770
merger.set_pending()
2430
merger.set_pending()
3773
2433
return conflicts
3776
def _create_prefix(cur_transport):
3777
needed = [cur_transport]
3778
# Recurse upwards until we can create a directory successfully
3780
new_transport = cur_transport.clone('..')
3781
if new_transport.base == cur_transport.base:
3782
raise errors.BzrCommandError("Failed to create path"
3786
new_transport.mkdir('.')
3787
except errors.NoSuchFile:
3788
needed.append(new_transport)
3789
cur_transport = new_transport
3793
# Now we only need to create child directories
3795
cur_transport = needed.pop()
3796
cur_transport.ensure_base()
3799
merge = _merge_helper
3802
2436
# these get imported and then picked up by the scan for cmd_*
3803
2437
# TODO: Some more consistent way to split command definitions across files;
3804
2438
# we do need to load at least some information about them to know of
3805
2439
# aliases. ideally we would avoid loading the implementation until the
3806
2440
# details were needed.
3807
from bzrlib.cmd_version_info import cmd_version_info
3808
2441
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
3809
from bzrlib.bundle.commands import cmd_bundle_revisions
3810
2442
from bzrlib.sign_my_commits import cmd_sign_my_commits
3811
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
2443
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
3812
2444
cmd_weave_plan_merge, cmd_weave_merge_text