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
27
41
from bzrlib.branch import Branch, BranchReferenceFormat
28
from bzrlib import (bundle, branch, bzrdir, errors, osutils, ui, config,
30
42
from bzrlib.bundle import read_bundle_from_url
31
43
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
32
44
from bzrlib.conflicts import ConflictList
42
54
from bzrlib.revisionspec import RevisionSpec
43
55
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
44
56
from bzrlib.transport.local import LocalTransport
45
import bzrlib.urlutils as urlutils
46
57
from bzrlib.workingtree import WorkingTree
264
275
--dry-run will show which files would be added, but not actually
278
--file-ids-from will try to use the file ids from the supplied path.
279
It looks up ids trying to find a matching parent directory with the
280
same filename, and then by pure path.
267
282
takes_args = ['file*']
268
takes_options = ['no-recurse', 'dry-run', 'verbose']
283
takes_options = ['no-recurse', 'dry-run', 'verbose',
284
Option('file-ids-from', type=unicode,
285
help='Lookup file ids from here')]
269
286
encoding_type = 'replace'
271
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
288
def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
272
290
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,
292
if file_ids_from is not None:
294
base_tree, base_path = WorkingTree.open_containing(
296
except errors.NoWorkingTree:
297
base_branch, base_path = branch.Branch.open_containing(
299
base_tree = base_branch.basis_tree()
301
action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
302
to_file=self.outf, should_print=(not is_quiet()))
304
action = bzrlib.add.AddAction(to_file=self.outf,
305
should_print=(not is_quiet()))
307
added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
278
308
action=action, save=not dry_run)
279
309
if len(ignored) > 0:
516
546
create_prefix=False, verbose=False):
517
547
# FIXME: Way too big! Put this into a function called from the
519
from bzrlib.transport import get_transport
521
550
br_from = Branch.open_containing('.')[0]
522
551
stored_loc = br_from.get_push_location()
529
558
self.outf.write("Using saved location: %s\n" % display_url)
530
559
location = stored_loc
532
transport = get_transport(location)
533
location_url = transport.base
561
to_transport = transport.get_transport(location)
562
location_url = to_transport.base
538
567
br_to = dir_to.open_branch()
539
568
except NotBranchError:
540
569
# create a branch.
541
transport = transport.clone('..')
570
to_transport = to_transport.clone('..')
542
571
if not create_prefix:
544
relurl = transport.relpath(location_url)
573
relurl = to_transport.relpath(location_url)
545
574
mutter('creating directory %s => %s', location_url, relurl)
546
transport.mkdir(relurl)
575
to_transport.mkdir(relurl)
547
576
except NoSuchFile:
548
577
raise BzrCommandError("Parent directory of %s "
549
578
"does not exist." % location)
551
current = transport.base
552
needed = [(transport, transport.relpath(location_url))]
580
current = to_transport.base
581
needed = [(to_transport, to_transport.relpath(location_url))]
555
transport, relpath = needed[-1]
556
transport.mkdir(relpath)
584
to_transport, relpath = needed[-1]
585
to_transport.mkdir(relpath)
558
587
except NoSuchFile:
559
new_transport = transport.clone('..')
588
new_transport = to_transport.clone('..')
560
589
needed.append((new_transport,
561
new_transport.relpath(transport.base)))
562
if new_transport.base == transport.base:
590
new_transport.relpath(to_transport.base)))
591
if new_transport.base == to_transport.base:
563
592
raise BzrCommandError("Could not create "
565
594
dir_to = br_from.bzrdir.clone(location_url,
618
647
aliases = ['get', 'clone']
620
649
def run(self, from_location, to_location=None, revision=None, basis=None):
621
from bzrlib.transport import get_transport
622
650
if revision is None:
623
651
revision = [None]
624
652
elif len(revision) > 1:
753
781
old_format = bzrdir.BzrDirFormat.get_default_format()
754
782
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)
784
source.create_checkout(to_location, revision_id, lightweight)
769
786
bzrdir.BzrDirFormat.set_default_format(old_format)
800
817
'bzr revert' instead of 'bzr commit' after the update.
802
819
takes_args = ['dir?']
804
822
def run(self, dir='.'):
805
823
tree = WorkingTree.open_containing(dir)[0]
806
824
tree.lock_write()
825
existing_pending_merges = tree.pending_merges()
808
827
last_rev = tree.last_revision()
809
828
if last_rev == tree.branch.last_revision():
816
835
conflicts = tree.update()
817
836
revno = tree.branch.revision_id_to_revno(tree.last_revision())
818
837
note('Updated to revision %d.' % (revno,))
838
if tree.pending_merges() != existing_pending_merges:
839
note('Your local commits will now show as pending merges with '
840
"'bzr status', and can be committed with 'bzr commit'.")
819
841
if conflicts != 0:
866
888
raise BzrCommandError('Specify one or more files to remove, or'
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)
891
added = tree.changes_from(tree.basis_tree(),
892
specific_files=file_list).added
893
file_list = sorted([f[0] for f in added], reverse=True)
873
894
if len(file_list) == 0:
874
895
raise BzrCommandError('No matching files.')
875
896
tree.remove(file_list, verbose=verbose, to_file=self.outf)
1016
1037
format = get_format_type('default')
1017
1038
if location is None:
1018
1039
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):
1041
to_transport = transport.get_transport(location)
1043
# The path has to exist to initialize a
1044
# branch inside of it.
1045
# Just using os.mkdir, since I don't
1046
# believe that we want to create a bunch of
1047
# locations if the user supplies an extended path
1048
# TODO: create-prefix
1050
to_transport.mkdir('.')
1051
except errors.FileExists:
1028
1055
existing_bzrdir = bzrdir.BzrDir.open(location)
1029
1056
except NotBranchError:
1031
1058
bzrdir.BzrDir.create_branch_convenience(location, format=format)
1033
1060
if existing_bzrdir.has_branch():
1034
if existing_bzrdir.has_workingtree():
1035
raise errors.AlreadyBranchError(location)
1037
raise errors.BranchExistsWithoutWorkingTree(location)
1061
if (isinstance(to_transport, LocalTransport)
1062
and not existing_bzrdir.has_workingtree()):
1063
raise errors.BranchExistsWithoutWorkingTree(location)
1064
raise errors.AlreadyBranchError(location)
1039
1066
existing_bzrdir.create_branch()
1040
1067
existing_bzrdir.create_workingtree()
1066
1093
' a working tree')]
1067
1094
aliases = ["init-repo"]
1068
1095
def run(self, location, format=None, trees=False):
1069
from bzrlib.transport import get_transport
1070
1096
if format is None:
1071
1097
format = get_format_type('default')
1072
transport = get_transport(location)
1073
if not transport.has('.'):
1075
newdir = format.initialize_on_transport(transport)
1099
if location is None:
1102
to_transport = transport.get_transport(location)
1104
to_transport.mkdir('.')
1105
except errors.FileExists:
1108
newdir = format.initialize_on_transport(to_transport)
1076
1109
repo = newdir.create_repository(shared=True)
1077
1110
repo.set_make_working_trees(trees)
1149
1182
raise BzrCommandError("Files are in different branches")
1150
1183
file_list = None
1151
1184
except NotBranchError:
1152
# Don't raise an error when bzr diff is called from
1153
# outside a working tree.
1154
tree1, tree2 = None, None
1185
if (revision is not None and len(revision) == 2
1186
and not revision[0].needs_branch()
1187
and not revision[1].needs_branch()):
1188
# If both revision specs include a branch, we can
1189
# diff them without needing a local working tree
1190
tree1, tree2 = None, None
1155
1193
if revision is not None:
1156
1194
if tree2 is not None:
1157
1195
raise BzrCommandError("Can't specify -r with two branches")
1206
1244
@display_command
1208
from bzrlib.delta import compare_trees
1210
1246
tree = WorkingTree.open_containing(u'.')[0]
1211
td = compare_trees(tree.basis_tree(), tree)
1247
td = tree.changes_from(tree.basis_tree())
1213
1248
for path, id, kind, text_modified, meta_modified in td.modified:
1214
1249
self.outf.write(path + '\n')
1480
1515
from bzrlib.atomicfile import AtomicFile
1481
1516
if old_default_rules is not None:
1482
1517
# dump the rules and exit
1483
for pattern in bzrlib.DEFAULT_IGNORE:
1518
for pattern in ignores.OLD_DEFAULTS:
1486
1521
if name_pattern is None:
1732
1767
raise BzrCommandError("Commit refused because there are unknown "
1733
1768
"files in the working tree.")
1734
1769
except errors.BoundBranchOutOfDate, e:
1735
raise BzrCommandError(str(e)
1736
+ ' Either unbind, update, or'
1737
' pass --local to commit.')
1770
raise BzrCommandError(str(e) + "\n"
1771
'To commit to master branch, run update and then commit.\n'
1772
'You can also pass --local to commit to continue working '
1740
1775
class cmd_check(Command):
1741
1776
"""Validate consistency of branch history.
1917
1952
Option('lsprof-timed',
1918
1953
help='generate lsprof output for benchmarked'
1919
1954
' sections of code.'),
1955
Option('cache-dir', type=str,
1956
help='a directory to cache intermediate'
1957
' benchmark steps'),
1922
1960
def run(self, testspecs_list=None, verbose=None, one=False,
1923
1961
keep_output=False, transport=None, benchmark=None,
1962
lsprof_timed=None, cache_dir=None):
1925
1963
import bzrlib.ui
1926
1964
from bzrlib.tests import selftest
1927
1965
import bzrlib.benchmarks as benchmarks
1966
from bzrlib.benchmarks import tree_creator
1968
if cache_dir is not None:
1969
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
1928
1970
# we don't want progress meters from the tests to go to the
1929
1971
# real output; and we don't want log messages cluttering up
1930
1972
# the real logs.
1943
1985
test_suite_factory = benchmarks.test_suite
1944
1986
if verbose is None:
1988
benchfile = open(".perf_history", "at")
1947
1990
test_suite_factory = None
1948
1991
if verbose is None:
1949
1992
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)
1995
result = selftest(verbose=verbose,
1997
stop_on_failure=one,
1998
keep_output=keep_output,
1999
transport=transport,
2000
test_suite_factory=test_suite_factory,
2001
lsprof_timed=lsprof_timed,
2002
bench_history=benchfile)
2004
if benchfile is not None:
1958
2007
info('tests passed')
1963
2012
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
2015
class cmd_version(Command):
2010
2016
"""Show version of bzr."""
2011
2018
@display_command
2020
from bzrlib.version import show_version
2015
2024
class cmd_rocks(Command):
2016
2025
"""Statement of optimism."""
2018
2029
@display_command
2020
2031
print "it sure does!"
2023
2034
class cmd_find_merge_base(Command):
2024
"""Find and print a base revision for merging two branches.
2035
"""Find and print a base revision for merging two branches."""
2026
2036
# TODO: Options to specify revisions on either side, as if
2027
2037
# merging only part of the history.
2028
2038
takes_args = ['branch', 'other']
2093
2103
takes_args = ['branch?']
2094
2104
takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2095
2105
Option('show-base', help="Show base revision text in "
2107
Option('uncommitted', help='Apply uncommitted changes'
2108
' from a working copy, instead of branch changes')]
2098
2110
def help(self):
2099
2111
from merge import merge_type_help
2101
2113
return getdoc(self) + '\n' + merge_type_help()
2103
2115
def run(self, branch=None, revision=None, force=False, merge_type=None,
2104
show_base=False, reprocess=False, remember=False):
2116
show_base=False, reprocess=False, remember=False,
2105
2118
if merge_type is None:
2106
2119
merge_type = Merge3Merger
2123
2136
branch = self._get_remembered_parent(tree, branch, 'Merging from')
2125
2138
if revision is None or len(revision) < 1:
2127
other = [branch, -1]
2141
other = [branch, None]
2144
other = [branch, -1]
2128
2145
other_branch, path = Branch.open_containing(branch)
2148
raise BzrCommandError('Cannot use --uncommitted and --revision'
2149
' at the same time.')
2130
2150
if len(revision) == 1:
2131
2151
base = [None, None]
2132
2152
other_branch, path = Branch.open_containing(branch)
2395
2415
if other_branch is None:
2396
2416
other_branch = parent
2397
2417
if other_branch is None:
2398
raise BzrCommandError("No missing location known or specified.")
2418
raise BzrCommandError("No peer location known or specified.")
2399
2419
print "Using last location: " + local_branch.get_parent()
2400
2420
remote_branch = Branch.open(other_branch)
2401
2421
if remote_branch.base == local_branch.base:
2474
2494
class cmd_testament(Command):
2475
2495
"""Show testament (signing-form) of a revision."""
2476
takes_options = ['revision', 'long',
2496
takes_options = ['revision',
2497
Option('long', help='Produce long-format testament'),
2477
2498
Option('strict', help='Produce a strict-format'
2479
2500
takes_args = ['branch?']