1
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"""
21
from bzrlib.lazy_import import lazy_import
22
lazy_import(globals(), """
27
from bzrlib.branch import Branch, BranchReferenceFormat
28
from bzrlib import (bundle, branch, bzrdir, errors, osutils, ui, config,
30
from bzrlib.bundle import read_bundle_from_url
44
from bzrlib.branch import Branch
31
45
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
32
46
from bzrlib.conflicts import ConflictList
47
from bzrlib.revision import common_ancestor
48
from bzrlib.revisionspec import RevisionSpec
49
from bzrlib.workingtree import WorkingTree
33
52
from bzrlib.commands import Command, display_command
34
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError,
35
NotBranchError, DivergedBranches, NotConflicted,
36
NoSuchFile, NoWorkingTree, FileInWrongBranch,
37
NotVersionedError, NotABundle)
38
from bzrlib.merge import Merge3Merger
39
53
from bzrlib.option import Option
40
54
from bzrlib.progress import DummyProgress, ProgressPhase
41
from bzrlib.revision import common_ancestor
42
from bzrlib.revisionspec import RevisionSpec
43
55
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
44
from bzrlib.transport.local import LocalTransport
45
import bzrlib.urlutils as urlutils
46
from bzrlib.workingtree import WorkingTree
49
58
def tree_files(file_list, default_branch=u'.'):
51
60
return internal_tree_files(file_list, default_branch)
52
except FileInWrongBranch, e:
53
raise BzrCommandError("%s is not in the same branch as %s" %
54
(e.path, file_list[0]))
61
except errors.FileInWrongBranch, e:
62
raise errors.BzrCommandError("%s is not in the same branch as %s" %
63
(e.path, file_list[0]))
57
66
# XXX: Bad function name; should possibly also be a class method of
96
105
format = bzrdir.BzrDirMetaFormat1()
97
106
format.repository_format = repository.RepositoryFormatKnit1()
108
if typestring == "experimental-knit2":
109
format = bzrdir.BzrDirMetaFormat1()
110
format.repository_format = repository.RepositoryFormatKnit2()
99
112
msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
100
113
"metaweave and weave" % typestring
101
raise BzrCommandError(msg)
114
raise errors.BzrCommandError(msg)
104
117
# TODO: Make sure no commands unconditionally use the working directory as a
179
192
def run(self, revision_id=None, revision=None):
181
194
if revision_id is not None and revision is not None:
182
raise BzrCommandError('You can only supply one of revision_id or --revision')
195
raise errors.BzrCommandError('You can only supply one of'
196
' revision_id or --revision')
183
197
if revision_id is None and revision is None:
184
raise BzrCommandError('You must supply either --revision or a revision_id')
198
raise errors.BzrCommandError('You must supply either'
199
' --revision or a revision_id')
185
200
b = WorkingTree.open_containing(u'.')[0].branch
187
202
# TODO: jam 20060112 should cat-revision always output utf-8?
264
280
--dry-run will show which files would be added, but not actually
283
--file-ids-from will try to use the file ids from the supplied path.
284
It looks up ids trying to find a matching parent directory with the
285
same filename, and then by pure path.
267
287
takes_args = ['file*']
268
takes_options = ['no-recurse', 'dry-run', 'verbose']
288
takes_options = ['no-recurse', 'dry-run', 'verbose',
289
Option('file-ids-from', type=unicode,
290
help='Lookup file ids from here')]
269
291
encoding_type = 'replace'
271
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
293
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
272
295
import bzrlib.add
274
action = bzrlib.add.AddAction(to_file=self.outf,
275
should_print=(not is_quiet()))
277
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
297
if file_ids_from is not None:
299
base_tree, base_path = WorkingTree.open_containing(
301
except errors.NoWorkingTree:
302
base_branch, base_path = Branch.open_containing(
304
base_tree = base_branch.basis_tree()
306
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
307
to_file=self.outf, should_print=(not is_quiet()))
309
action = bzrlib.add.AddAction(to_file=self.outf,
310
should_print=(not is_quiet()))
312
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
278
313
action=action, save=not dry_run)
279
314
if len(ignored) > 0:
327
362
"""Show inventory of the current working copy or a revision.
329
364
It is possible to limit the output to a particular entry
330
type using the --kind option. For example; --kind file.
365
type using the --kind option. For example: --kind file.
367
It is also possible to restrict the list of files to a specific
368
set. For example: bzr inventory --show-ids this/file
333
371
takes_options = ['revision', 'show-ids', 'kind']
372
takes_args = ['file*']
336
def run(self, revision=None, show_ids=False, kind=None):
375
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
337
376
if kind and kind not in ['file', 'directory', 'symlink']:
338
raise BzrCommandError('invalid kind specified')
339
tree = WorkingTree.open_containing(u'.')[0]
341
inv = tree.read_working_inventory()
377
raise errors.BzrCommandError('invalid kind specified')
379
work_tree, file_list = tree_files(file_list)
381
if revision is not None:
343
382
if len(revision) > 1:
344
raise BzrCommandError('bzr inventory --revision takes'
345
' exactly one revision identifier')
346
inv = tree.branch.repository.get_revision_inventory(
347
revision[0].in_history(tree.branch).rev_id)
349
for path, entry in inv.entries():
383
raise errors.BzrCommandError('bzr inventory --revision takes'
384
' exactly one revision identifier')
385
revision_id = revision[0].in_history(work_tree.branch).rev_id
386
tree = work_tree.branch.repository.revision_tree(revision_id)
388
# We include work_tree as well as 'tree' here
389
# So that doing '-r 10 path/foo' will lookup whatever file
390
# exists now at 'path/foo' even if it has been renamed, as
391
# well as whatever files existed in revision 10 at path/foo
392
trees = [tree, work_tree]
397
if file_list is not None:
398
file_ids = _mod_tree.find_ids_across_trees(file_list, trees,
399
require_versioned=True)
400
# find_ids_across_trees may include some paths that don't
402
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
403
for file_id in file_ids if file_id in tree)
405
entries = tree.inventory.entries()
407
for path, entry in entries:
350
408
if kind and kind != entry.kind:
516
575
create_prefix=False, verbose=False):
517
576
# FIXME: Way too big! Put this into a function called from the
519
from bzrlib.transport import get_transport
521
579
br_from = Branch.open_containing('.')[0]
522
580
stored_loc = br_from.get_push_location()
523
581
if location is None:
524
582
if stored_loc is None:
525
raise BzrCommandError("No push location known or specified.")
583
raise errors.BzrCommandError("No push location known or specified.")
527
585
display_url = urlutils.unescape_for_display(stored_loc,
528
586
self.outf.encoding)
529
587
self.outf.write("Using saved location: %s\n" % display_url)
530
588
location = stored_loc
532
transport = get_transport(location)
533
location_url = transport.base
590
to_transport = transport.get_transport(location)
591
location_url = to_transport.base
537
595
dir_to = bzrdir.BzrDir.open(location_url)
538
596
br_to = dir_to.open_branch()
539
except NotBranchError:
597
except errors.NotBranchError:
540
598
# create a branch.
541
transport = transport.clone('..')
599
to_transport = to_transport.clone('..')
542
600
if not create_prefix:
544
relurl = transport.relpath(location_url)
602
relurl = to_transport.relpath(location_url)
545
603
mutter('creating directory %s => %s', location_url, relurl)
546
transport.mkdir(relurl)
548
raise BzrCommandError("Parent directory of %s "
549
"does not exist." % location)
604
to_transport.mkdir(relurl)
605
except errors.NoSuchFile:
606
raise errors.BzrCommandError("Parent directory of %s "
607
"does not exist." % location)
551
current = transport.base
552
needed = [(transport, transport.relpath(location_url))]
609
current = to_transport.base
610
needed = [(to_transport, to_transport.relpath(location_url))]
555
transport, relpath = needed[-1]
556
transport.mkdir(relpath)
613
to_transport, relpath = needed[-1]
614
to_transport.mkdir(relpath)
559
new_transport = transport.clone('..')
616
except errors.NoSuchFile:
617
new_transport = to_transport.clone('..')
560
618
needed.append((new_transport,
561
new_transport.relpath(transport.base)))
562
if new_transport.base == transport.base:
563
raise BzrCommandError("Could not create "
619
new_transport.relpath(to_transport.base)))
620
if new_transport.base == to_transport.base:
621
raise errors.BzrCommandError("Could not create "
565
623
dir_to = br_from.bzrdir.clone(location_url,
566
624
revision_id=br_from.last_revision())
567
625
br_to = dir_to.open_branch()
582
640
warning('This transport does not update the working '
583
641
'tree of: %s' % (br_to.base,))
584
642
count = br_to.pull(br_from, overwrite)
585
except NoWorkingTree:
643
except errors.NoWorkingTree:
586
644
count = br_to.pull(br_from, overwrite)
588
646
count = tree_to.pull(br_from, overwrite)
589
except DivergedBranches:
590
raise BzrCommandError("These branches have diverged."
591
" Try a merge then push with overwrite.")
647
except errors.DivergedBranches:
648
raise errors.BzrCommandError('These branches have diverged.'
649
' Try using "merge" and then "push".')
592
650
note('%d revision(s) pushed.' % (count,))
618
676
aliases = ['get', 'clone']
620
678
def run(self, from_location, to_location=None, revision=None, basis=None):
621
from bzrlib.transport import get_transport
622
679
if revision is None:
623
680
revision = [None]
624
681
elif len(revision) > 1:
625
raise BzrCommandError(
682
raise errors.BzrCommandError(
626
683
'bzr branch --revision takes exactly 1 revision value')
628
685
br_from = Branch.open(from_location)
629
686
except OSError, e:
630
687
if e.errno == errno.ENOENT:
631
raise BzrCommandError('Source location "%s" does not'
632
' exist.' % to_location)
688
raise errors.BzrCommandError('Source location "%s" does not'
689
' exist.' % to_location)
635
692
br_from.lock_read()
652
709
name = os.path.basename(to_location) + '\n'
654
to_transport = get_transport(to_location)
711
to_transport = transport.get_transport(to_location)
656
713
to_transport.mkdir('.')
657
714
except errors.FileExists:
658
raise BzrCommandError('Target directory "%s" already'
659
' exists.' % to_location)
715
raise errors.BzrCommandError('Target directory "%s" already'
716
' exists.' % to_location)
660
717
except errors.NoSuchFile:
661
raise BzrCommandError('Parent of "%s" does not exist.' %
718
raise errors.BzrCommandError('Parent of "%s" does not exist.'
664
721
# preserve whatever source format we have.
665
722
dir = br_from.bzrdir.sprout(to_transport.base,
668
725
except errors.NoSuchRevision:
669
726
to_transport.delete_tree('.')
670
727
msg = "The branch %s has no revision %s." % (from_location, revision[0])
671
raise BzrCommandError(msg)
728
raise errors.BzrCommandError(msg)
672
729
except errors.UnlistableBranch:
673
730
osutils.rmtree(to_location)
674
731
msg = "The branch %s cannot be used as a --basis" % (basis,)
675
raise BzrCommandError(msg)
732
raise errors.BzrCommandError(msg)
677
734
branch.control_files.put_utf8('branch-name', name)
678
735
note('Branched %d revision(s).' % branch.revno())
743
800
os.mkdir(to_location)
744
801
except OSError, e:
745
802
if e.errno == errno.EEXIST:
746
raise BzrCommandError('Target directory "%s" already'
747
' exists.' % to_location)
803
raise errors.BzrCommandError('Target directory "%s" already'
804
' exists.' % to_location)
748
805
if e.errno == errno.ENOENT:
749
raise BzrCommandError('Parent of "%s" does not exist.' %
806
raise errors.BzrCommandError('Parent of "%s" does not exist.'
753
810
old_format = bzrdir.BzrDirFormat.get_default_format()
754
811
bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
757
checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
758
branch.BranchReferenceFormat().initialize(checkout, source)
760
checkout_branch = bzrdir.BzrDir.create_branch_convenience(
761
to_location, force_new_tree=False)
762
checkout = checkout_branch.bzrdir
763
checkout_branch.bind(source)
764
if revision_id is not None:
765
rh = checkout_branch.revision_history()
766
checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
767
checkout.create_workingtree(revision_id)
813
source.create_checkout(to_location, revision_id, lightweight)
769
815
bzrdir.BzrDirFormat.set_default_format(old_format)
781
827
def run(self, dir=u'.'):
782
from bzrlib.tree import find_renames
783
828
tree = WorkingTree.open_containing(dir)[0]
784
829
old_inv = tree.basis_tree().inventory
785
830
new_inv = tree.read_working_inventory()
786
renames = list(find_renames(old_inv, new_inv))
831
renames = list(_mod_tree.find_renames(old_inv, new_inv))
788
833
for old_name, new_name in renames:
789
834
self.outf.write("%s => %s\n" % (old_name, new_name))
863
913
tree, file_list = tree_files(file_list)
865
915
if file_list is None:
866
raise BzrCommandError('Specify one or more files to remove, or'
916
raise errors.BzrCommandError('Specify one or more files to'
917
' remove, or use --new.')
869
from bzrlib.delta import compare_trees
870
added = [compare_trees(tree.basis_tree(), tree,
871
specific_files=file_list).added]
872
file_list = sorted([f[0] for f in added[0]], reverse=True)
919
added = tree.changes_from(tree.basis_tree(),
920
specific_files=file_list).added
921
file_list = sorted([f[0] for f in added], reverse=True)
873
922
if len(file_list) == 0:
874
raise BzrCommandError('No matching files.')
923
raise errors.BzrCommandError('No matching files.')
875
924
tree.remove(file_list, verbose=verbose, to_file=self.outf)
1016
1065
format = get_format_type('default')
1017
1066
if location is None:
1018
1067
location = u'.'
1020
# The path has to exist to initialize a
1021
# branch inside of it.
1022
# Just using os.mkdir, since I don't
1023
# believe that we want to create a bunch of
1024
# locations if the user supplies an extended path
1025
if not os.path.exists(location):
1069
to_transport = transport.get_transport(location)
1071
# The path has to exist to initialize a
1072
# branch inside of it.
1073
# Just using os.mkdir, since I don't
1074
# believe that we want to create a bunch of
1075
# locations if the user supplies an extended path
1076
# TODO: create-prefix
1078
to_transport.mkdir('.')
1079
except errors.FileExists:
1028
1083
existing_bzrdir = bzrdir.BzrDir.open(location)
1029
except NotBranchError:
1084
except errors.NotBranchError:
1030
1085
# really a NotBzrDir error...
1031
1086
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1088
from bzrlib.transport.local import LocalTransport
1033
1089
if existing_bzrdir.has_branch():
1034
if existing_bzrdir.has_workingtree():
1035
raise errors.AlreadyBranchError(location)
1037
raise errors.BranchExistsWithoutWorkingTree(location)
1090
if (isinstance(to_transport, LocalTransport)
1091
and not existing_bzrdir.has_workingtree()):
1092
raise errors.BranchExistsWithoutWorkingTree(location)
1093
raise errors.AlreadyBranchError(location)
1039
1095
existing_bzrdir.create_branch()
1040
1096
existing_bzrdir.create_workingtree()
1066
1122
' a working tree')]
1067
1123
aliases = ["init-repo"]
1068
1124
def run(self, location, format=None, trees=False):
1069
from bzrlib.transport import get_transport
1070
1125
if format is None:
1071
1126
format = get_format_type('default')
1072
transport = get_transport(location)
1073
if not transport.has('.'):
1075
newdir = format.initialize_on_transport(transport)
1128
if location is None:
1131
to_transport = transport.get_transport(location)
1133
to_transport.mkdir('.')
1134
except errors.FileExists:
1137
newdir = format.initialize_on_transport(to_transport)
1076
1138
repo = newdir.create_repository(shared=True)
1077
1139
repo.set_make_working_trees(trees)
1141
except FileInWrongBranch:
1204
except errors.FileInWrongBranch:
1142
1205
if len(file_list) != 2:
1143
raise BzrCommandError("Files are in different branches")
1206
raise errors.BzrCommandError("Files are in different branches")
1145
1208
tree1, file1 = WorkingTree.open_containing(file_list[0])
1146
1209
tree2, file2 = WorkingTree.open_containing(file_list[1])
1147
1210
if file1 != "" or file2 != "":
1148
1211
# FIXME diff those two files. rbc 20051123
1149
raise BzrCommandError("Files are in different branches")
1212
raise errors.BzrCommandError("Files are in different branches")
1150
1213
file_list = None
1151
except NotBranchError:
1152
# Don't raise an error when bzr diff is called from
1153
# outside a working tree.
1154
tree1, tree2 = None, None
1214
except errors.NotBranchError:
1215
if (revision is not None and len(revision) == 2
1216
and not revision[0].needs_branch()
1217
and not revision[1].needs_branch()):
1218
# If both revision specs include a branch, we can
1219
# diff them without needing a local working tree
1220
tree1, tree2 = None, None
1155
1223
if revision is not None:
1156
1224
if tree2 is not None:
1157
raise BzrCommandError("Can't specify -r with two branches")
1225
raise errors.BzrCommandError("Can't specify -r with two branches")
1158
1226
if (len(revision) == 1) or (revision[1].spec is None):
1159
1227
return diff_cmd_helper(tree1, file_list, diff_options,
1320
1391
elif len(revision) == 1:
1321
1392
rev1 = rev2 = revision[0].in_history(b).revno
1322
1393
elif len(revision) == 2:
1394
if revision[1].get_branch() != revision[0].get_branch():
1395
# b is taken from revision[0].get_branch(), and
1396
# show_log will use its revision_history. Having
1397
# different branches will lead to weird behaviors.
1398
raise errors.BzrCommandError(
1399
"Log doesn't accept two revisions in different branches.")
1323
1400
if revision[0].spec is None:
1324
1401
# missing begin-range means first revision
1585
1662
rev_id = b.last_revision()
1587
1664
if len(revision) != 1:
1588
raise BzrError('bzr export --revision takes exactly 1 argument')
1665
raise errors.BzrError('bzr export --revision takes exactly'
1589
1667
rev_id = revision[0].in_history(b).rev_id
1590
1668
t = b.repository.revision_tree(rev_id)
1592
1670
export(t, dest, format, root)
1593
1671
except errors.NoSuchExportFormat, e:
1594
raise BzrCommandError('Unsupported export format: %s' % e.format)
1672
raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1597
1675
class cmd_cat(Command):
1603
1681
@display_command
1604
1682
def run(self, filename, revision=None):
1605
1683
if revision is not None and len(revision) != 1:
1606
raise BzrCommandError("bzr cat --revision takes exactly one number")
1684
raise errors.BzrCommandError("bzr cat --revision takes exactly one number")
1609
1687
tree, relpath = WorkingTree.open_containing(filename)
1610
1688
b = tree.branch
1611
except NotBranchError:
1689
except errors.NotBranchError:
1614
1692
if tree is None:
1615
1693
b, relpath = Branch.open_containing(filename)
1694
if revision is not None and revision[0].get_branch() is not None:
1695
b = Branch.open(revision[0].get_branch())
1616
1696
if revision is None:
1617
1697
revision_id = b.last_revision()
1700
1780
template = make_commit_message_template(tree, selected_list)
1701
1781
message = edit_commit_message(template)
1702
1782
if message is None:
1703
raise BzrCommandError("please specify a commit message"
1704
" with either --message or --file")
1783
raise errors.BzrCommandError("please specify a commit message"
1784
" with either --message or --file")
1705
1785
elif message and file:
1706
raise BzrCommandError("please specify either --message or --file")
1786
raise errors.BzrCommandError("please specify either --message or --file")
1709
1789
message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1711
1791
if message == "":
1712
raise BzrCommandError("empty commit message specified")
1792
raise errors.BzrCommandError("empty commit message specified")
1715
1795
reporter = ReportCommitToLog()
1723
1803
except PointlessCommit:
1724
1804
# FIXME: This should really happen before the file is read in;
1725
1805
# perhaps prepare the commit; get the message; then actually commit
1726
raise BzrCommandError("no changes to commit."
1727
" use --unchanged to commit anyhow")
1806
raise errors.BzrCommandError("no changes to commit."
1807
" use --unchanged to commit anyhow")
1728
1808
except ConflictsInTree:
1729
raise BzrCommandError("Conflicts detected in working tree. "
1809
raise errors.BzrCommandError("Conflicts detected in working tree. "
1730
1810
'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1731
1811
except StrictCommitFailed:
1732
raise BzrCommandError("Commit refused because there are unknown "
1733
"files in the working tree.")
1812
raise errors.BzrCommandError("Commit refused because there are unknown "
1813
"files in the working tree.")
1734
1814
except errors.BoundBranchOutOfDate, e:
1735
raise BzrCommandError(str(e)
1736
+ ' Either unbind, update, or'
1737
' pass --local to commit.')
1815
raise errors.BzrCommandError(str(e) + "\n"
1816
'To commit to master branch, run update and then commit.\n'
1817
'You can also pass --local to commit to continue working '
1740
1820
class cmd_check(Command):
1741
1821
"""Validate consistency of branch history.
1917
1997
Option('lsprof-timed',
1918
1998
help='generate lsprof output for benchmarked'
1919
1999
' sections of code.'),
2000
Option('cache-dir', type=str,
2001
help='a directory to cache intermediate'
2002
' benchmark steps'),
1922
2005
def run(self, testspecs_list=None, verbose=None, one=False,
1923
2006
keep_output=False, transport=None, benchmark=None,
2007
lsprof_timed=None, cache_dir=None):
1925
2008
import bzrlib.ui
1926
2009
from bzrlib.tests import selftest
1927
2010
import bzrlib.benchmarks as benchmarks
2011
from bzrlib.benchmarks import tree_creator
2013
if cache_dir is not None:
2014
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
1928
2015
# we don't want progress meters from the tests to go to the
1929
2016
# real output; and we don't want log messages cluttering up
1930
2017
# the real logs.
1943
2030
test_suite_factory = benchmarks.test_suite
1944
2031
if verbose is None:
2033
# TODO: should possibly lock the history file...
2034
benchfile = open(".perf_history", "at")
1947
2036
test_suite_factory = None
1948
2037
if verbose is None:
1949
2038
verbose = False
1950
result = selftest(verbose=verbose,
1952
stop_on_failure=one,
1953
keep_output=keep_output,
1954
transport=transport,
1955
test_suite_factory=test_suite_factory,
1956
lsprof_timed=lsprof_timed)
2041
result = selftest(verbose=verbose,
2043
stop_on_failure=one,
2044
keep_output=keep_output,
2045
transport=transport,
2046
test_suite_factory=test_suite_factory,
2047
lsprof_timed=lsprof_timed,
2048
bench_history=benchfile)
2050
if benchfile is not None:
1958
2053
info('tests passed')
1963
2058
ui.ui_factory = save_ui
1966
def _get_bzr_branch():
1967
"""If bzr is run from a branch, return Branch or None"""
1968
from os.path import dirname
1971
branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
1973
except errors.BzrError:
1979
print "bzr (bazaar-ng) %s" % bzrlib.__version__
1980
# is bzrlib itself in a branch?
1981
branch = _get_bzr_branch()
1983
rh = branch.revision_history()
1985
print " bzr checkout, revision %d" % (revno,)
1986
print " nick: %s" % (branch.nick,)
1988
print " revid: %s" % (rh[-1],)
1989
print "Using python interpreter:", sys.executable
1991
print "Using python standard library:", os.path.dirname(site.__file__)
1992
print "Using bzrlib:",
1993
if len(bzrlib.__path__) > 1:
1994
# print repr, which is a good enough way of making it clear it's
1995
# more than one element (eg ['/foo/bar', '/foo/bzr'])
1996
print repr(bzrlib.__path__)
1998
print bzrlib.__path__[0]
2001
print bzrlib.__copyright__
2002
print "http://bazaar-vcs.org/"
2004
print "bzr comes with ABSOLUTELY NO WARRANTY. bzr is free software, and"
2005
print "you may use, modify and redistribute it under the terms of the GNU"
2006
print "General Public License version 2 or later."
2009
2061
class cmd_version(Command):
2010
2062
"""Show version of bzr."""
2011
2064
@display_command
2066
from bzrlib.version import show_version
2015
2070
class cmd_rocks(Command):
2016
2071
"""Statement of optimism."""
2018
2075
@display_command
2020
2077
print "it sure does!"
2023
2080
class cmd_find_merge_base(Command):
2024
"""Find and print a base revision for merging two branches.
2081
"""Find and print a base revision for merging two branches."""
2026
2082
# TODO: Options to specify revisions on either side, as if
2027
2083
# merging only part of the history.
2028
2084
takes_args = ['branch', 'other']
2093
2149
takes_args = ['branch?']
2094
2150
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2095
2151
Option('show-base', help="Show base revision text in "
2153
Option('uncommitted', help='Apply uncommitted changes'
2154
' from a working copy, instead of branch changes')]
2098
2156
def help(self):
2099
from merge import merge_type_help
2100
2157
from inspect import getdoc
2101
return getdoc(self) + '\n' + merge_type_help()
2158
return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2103
2160
def run(self, branch=None, revision=None, force=False, merge_type=None,
2104
show_base=False, reprocess=False, remember=False):
2161
show_base=False, reprocess=False, remember=False,
2105
2163
if merge_type is None:
2106
merge_type = Merge3Merger
2164
merge_type = _mod_merge.Merge3Merger
2108
2166
tree = WorkingTree.open_containing(u'.')[0]
2110
2168
if branch is not None:
2112
2170
reader = bundle.read_bundle_from_url(branch)
2171
except errors.NotABundle:
2114
2172
pass # Continue on considering this url a Branch
2116
2174
conflicts = merge_bundle(reader, tree, not force, merge_type,
2123
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2181
if revision is None \
2182
or len(revision) < 1 or revision[0].needs_branch():
2183
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2125
2185
if revision is None or len(revision) < 1:
2127
other = [branch, -1]
2188
other = [branch, None]
2191
other = [branch, -1]
2128
2192
other_branch, path = Branch.open_containing(branch)
2195
raise errors.BzrCommandError('Cannot use --uncommitted and'
2196
' --revision at the same time.')
2197
branch = revision[0].get_branch() or branch
2130
2198
if len(revision) == 1:
2131
2199
base = [None, None]
2132
2200
other_branch, path = Branch.open_containing(branch)
2136
2204
assert len(revision) == 2
2137
2205
if None in revision:
2138
raise BzrCommandError(
2139
"Merge doesn't permit that revision specifier.")
2140
other_branch, path = Branch.open_containing(branch)
2206
raise errors.BzrCommandError(
2207
"Merge doesn't permit empty revision specifier.")
2208
base_branch, path = Branch.open_containing(branch)
2209
branch1 = revision[1].get_branch() or branch
2210
other_branch, path1 = Branch.open_containing(branch1)
2211
if revision[0].get_branch() is not None:
2212
# then path was obtained from it, and is None.
2142
base = [branch, revision[0].in_history(other_branch).revno]
2143
other = [branch, revision[1].in_history(other_branch).revno]
2215
base = [branch, revision[0].in_history(base_branch).revno]
2216
other = [branch1, revision[1].in_history(other_branch).revno]
2145
2218
if tree.branch.get_parent() is None or remember:
2146
2219
tree.branch.set_parent(other_branch.base)
2218
2292
def help(self):
2219
from merge import merge_type_help
2220
2293
from inspect import getdoc
2221
return getdoc(self) + '\n' + merge_type_help()
2294
return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2223
2296
def run(self, file_list=None, merge_type=None, show_base=False,
2224
2297
reprocess=False):
2225
from bzrlib.merge import merge_inner, transform_tree
2226
2298
if merge_type is None:
2227
merge_type = Merge3Merger
2299
merge_type = _mod_merge.Merge3Merger
2228
2300
tree, file_list = tree_files(file_list)
2229
2301
tree.lock_write()
2231
pending_merges = tree.pending_merges()
2232
if len(pending_merges) != 1:
2233
raise BzrCommandError("Sorry, remerge only works after normal"
2234
" merges. Not cherrypicking or"
2303
parents = tree.get_parent_ids()
2304
if len(parents) != 2:
2305
raise errors.BzrCommandError("Sorry, remerge only works after normal"
2306
" merges. Not cherrypicking or"
2236
2308
repository = tree.branch.repository
2237
base_revision = common_ancestor(tree.branch.last_revision(),
2238
pending_merges[0], repository)
2309
base_revision = common_ancestor(parents[0],
2310
parents[1], repository)
2239
2311
base_tree = repository.revision_tree(base_revision)
2240
other_tree = repository.revision_tree(pending_merges[0])
2312
other_tree = repository.revision_tree(parents[1])
2241
2313
interesting_ids = None
2242
2314
new_conflicts = []
2243
2315
conflicts = tree.conflicts()
2254
2326
for name, ie in tree.inventory.iter_entries(file_id):
2255
2327
interesting_ids.add(ie.file_id)
2256
2328
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2257
transform_tree(tree, tree.basis_tree(), interesting_ids)
2329
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2258
2330
tree.set_conflicts(ConflictList(new_conflicts))
2259
2331
if file_list is None:
2260
2332
restore_files = list(tree.iter_conflicts())
2263
2335
for filename in restore_files:
2265
2337
restore(tree.abspath(filename))
2266
except NotConflicted:
2338
except errors.NotConflicted:
2268
conflicts = merge_inner(tree.branch, other_tree, base_tree,
2270
interesting_ids=interesting_ids,
2271
other_rev_id=pending_merges[0],
2272
merge_type=merge_type,
2273
show_base=show_base,
2274
reprocess=reprocess)
2340
conflicts = _mod_merge.merge_inner(
2341
tree.branch, other_tree, base_tree,
2343
interesting_ids=interesting_ids,
2344
other_rev_id=parents[1],
2345
merge_type=merge_type,
2346
show_base=show_base,
2347
reprocess=reprocess)
2277
2350
if conflicts > 0:
2282
2355
class cmd_revert(Command):
2283
"""Reverse all changes since the last commit.
2285
Only versioned files are affected. Specify filenames to revert only
2286
those files. By default, any files that are changed will be backed up
2287
first. Backup files have a '~' appended to their name.
2356
"""Revert files to a previous revision.
2358
Giving a list of files will revert only those files. Otherwise, all files
2359
will be reverted. If the revision is not specified with '--revision', the
2360
last committed revision is used.
2362
To remove only some changes, without reverting to a prior version, use
2363
merge instead. For example, "merge . --r-2..-3" will remove the changes
2364
introduced by -2, without affecting the changes introduced by -1. Or
2365
to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
2367
By default, any files that have been manually changed will be backed up
2368
first. (Files changed only by merge are not backed up.) Backup files have
2369
'.~#~' appended to their name, where # is a number.
2371
When you provide files, you can use their current pathname or the pathname
2372
from the target revision. So you can use revert to "undelete" a file by
2373
name. If you name a directory, all the contents of that directory will be
2289
2376
takes_options = ['revision', 'no-backup']
2290
2377
takes_args = ['file*']
2291
2378
aliases = ['merge-revert']
2293
2380
def run(self, revision=None, no_backup=False, file_list=None):
2294
from bzrlib.commands import parse_spec
2295
2381
if file_list is not None:
2296
2382
if len(file_list) == 0:
2297
raise BzrCommandError("No files specified")
2383
raise errors.BzrCommandError("No files specified")
2551
2638
def run(self, revision_id_list=None, revision=None):
2552
2639
import bzrlib.gpg as gpg
2553
2640
if revision_id_list is not None and revision is not None:
2554
raise BzrCommandError('You can only supply one of revision_id or --revision')
2641
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
2555
2642
if revision_id_list is None and revision is None:
2556
raise BzrCommandError('You must supply either --revision or a revision_id')
2643
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
2557
2644
b = WorkingTree.open_containing(u'.')[0].branch
2558
2645
gpg_strategy = gpg.GPGStrategy(b.get_config())
2559
2646
if revision_id_list is not None:
2811
class cmd_wait_until_signalled(Command):
2812
"""Test helper for test_start_and_stop_bzr_subprocess_send_signal.
2814
This just prints a line to signal when it is ready, then blocks on stdin.
2820
sys.stdout.write("running\n")
2822
sys.stdin.readline()
2825
class cmd_serve(Command):
2826
"""Run the bzr server."""
2828
aliases = ['server']
2832
help='serve on stdin/out for use from inetd or sshd'),
2834
help='listen for connections on nominated port of the form '
2835
'[hostname:]portnumber. Passing 0 as the port number will '
2836
'result in a dynamically allocated port.',
2839
help='serve contents of directory',
2841
Option('allow-writes',
2842
help='By default the server is a readonly server. Supplying '
2843
'--allow-writes enables write access to the contents of '
2844
'the served directory and below. '
2848
def run(self, port=None, inet=False, directory=None, allow_writes=False):
2849
from bzrlib.transport import smart
2850
from bzrlib.transport import get_transport
2851
if directory is None:
2852
directory = os.getcwd()
2853
url = urlutils.local_path_to_url(directory)
2854
if not allow_writes:
2855
url = 'readonly+' + url
2856
t = get_transport(url)
2858
server = smart.SmartStreamServer(sys.stdin, sys.stdout, t)
2859
elif port is not None:
2861
host, port = port.split(':')
2864
server = smart.SmartTCPServer(t, host=host, port=int(port))
2865
print 'listening on port: ', server.port
2868
raise errors.BzrCommandError("bzr serve requires one of --inet or --port")
2725
2872
# command-line interpretation helper for merge-related commands
2726
def merge(other_revision, base_revision,
2727
check_clean=True, ignore_zero=False,
2728
this_dir=None, backup_files=False, merge_type=Merge3Merger,
2729
file_list=None, show_base=False, reprocess=False,
2730
pb=DummyProgress()):
2873
def _merge_helper(other_revision, base_revision,
2874
check_clean=True, ignore_zero=False,
2875
this_dir=None, backup_files=False,
2877
file_list=None, show_base=False, reprocess=False,
2878
pb=DummyProgress()):
2731
2879
"""Merge changes into a tree.
2755
2903
clients might prefer to call merge.merge_inner(), which has less magic
2758
from bzrlib.merge import Merger
2906
# Loading it late, so that we don't always have to import bzrlib.merge
2907
if merge_type is None:
2908
merge_type = _mod_merge.Merge3Merger
2759
2909
if this_dir is None:
2760
2910
this_dir = u'.'
2761
2911
this_tree = WorkingTree.open_containing(this_dir)[0]
2762
if show_base and not merge_type is Merge3Merger:
2763
raise BzrCommandError("Show-base is not supported for this merge"
2764
" type. %s" % merge_type)
2912
if show_base and not merge_type is _mod_merge.Merge3Merger:
2913
raise errors.BzrCommandError("Show-base is not supported for this merge"
2914
" type. %s" % merge_type)
2765
2915
if reprocess and not merge_type.supports_reprocess:
2766
raise BzrCommandError("Conflict reduction is not supported for merge"
2767
" type %s." % merge_type)
2916
raise errors.BzrCommandError("Conflict reduction is not supported for merge"
2917
" type %s." % merge_type)
2768
2918
if reprocess and show_base:
2769
raise BzrCommandError("Cannot do conflict reduction and show base.")
2919
raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
2771
merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2921
merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
2772
2923
merger.pp = ProgressPhase("Merge phase", 5, pb)
2773
2924
merger.pp.next_phase()
2774
2925
merger.check_basis(check_clean)
2791
2942
return conflicts
2946
merge = _merge_helper
2794
2949
# these get imported and then picked up by the scan for cmd_*
2795
2950
# TODO: Some more consistent way to split command definitions across files;
2796
2951
# we do need to load at least some information about them to know of
2797
2952
# aliases. ideally we would avoid loading the implementation until the
2798
2953
# details were needed.
2954
from bzrlib.cmd_version_info import cmd_version_info
2799
2955
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2800
2956
from bzrlib.bundle.commands import cmd_bundle_revisions
2801
2957
from bzrlib.sign_my_commits import cmd_sign_my_commits