86
86
def _get_branch_location(control_dir, possible_transports=None):
87
87
"""Return location of branch for this control dir."""
89
this_branch = control_dir.open_branch(
90
possible_transports=possible_transports)
91
# This may be a heavy checkout, where we want the master branch
92
master_location = this_branch.get_bound_location()
93
if master_location is not None:
94
return master_location
95
# If not, use a local sibling
96
return this_branch.base
89
target = control_dir.get_branch_reference()
97
90
except errors.NotBranchError:
98
format = control_dir.find_branch_format()
99
if getattr(format, 'get_reference', None) is not None:
100
return format.get_reference(control_dir)
102
return control_dir.root_transport.base
91
return control_dir.root_transport.base
92
if target is not None:
94
this_branch = control_dir.open_branch(
95
possible_transports=possible_transports)
96
# This may be a heavy checkout, where we want the master branch
97
master_location = this_branch.get_bound_location()
98
if master_location is not None:
99
return master_location
100
# If not, use a local sibling
101
return this_branch.base
105
104
def _is_colocated(control_dir, possible_transports=None):
106
105
"""Check if the branch in control_dir is colocated.
108
107
:param control_dir: Control directory
109
:return: Boolean indicating whether
108
:return: Tuple with boolean indicating whether the branch is colocated
109
and the full URL to the actual branch
111
111
# This path is meant to be relative to the existing branch
112
112
this_url = _get_branch_location(control_dir,
132
132
def lookup_new_sibling_branch(control_dir, location, possible_transports=None):
133
133
"""Lookup the location for a new sibling branch.
135
:param control_dir: Control directory relative to which to look up
135
:param control_dir: Control directory to find sibling branches from
137
136
:param location: Name of the new branch
138
137
:return: Full location to the new branch
152
151
def open_sibling_branch(control_dir, location, possible_transports=None):
153
"""Open a branch, possibly a sibling.
152
"""Open a branch, possibly a sibling of another.
155
154
:param control_dir: Control directory relative to which to lookup the
189
188
possible_transports=possible_transports)
192
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
193
def tree_files(file_list, default_branch=u'.', canonicalize=True,
195
return internal_tree_files(file_list, default_branch, canonicalize,
191
def iter_sibling_branches(control_dir, possible_transports=None):
192
"""Iterate over the siblings of a branch.
194
:param control_dir: Control directory for which to look up the siblings
195
:return: Iterator over tuples with branch name and branch object
199
reference = control_dir.get_branch_reference()
200
except errors.NotBranchError:
201
# There is no active branch, just return the colocated branches.
202
for name, branch in control_dir.get_branches().iteritems():
205
if reference is not None:
206
ref_branch = Branch.open(reference,
207
possible_transports=possible_transports)
210
if ref_branch is None or ref_branch.name:
211
if ref_branch is not None:
212
control_dir = ref_branch.bzrdir
213
for name, branch in control_dir.get_branches().iteritems():
216
repo = ref_branch.bzrdir.find_repository()
217
for branch in repo.find_branches(using=True):
218
name = urlutils.relative_url(repo.user_url,
219
branch.user_url).rstrip("/")
199
223
def tree_files_for_add(file_list):
264
# XXX: Bad function name; should possibly also be a class method of
265
# WorkingTree rather than a function.
266
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
267
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
269
"""Convert command-line paths to a WorkingTree and relative paths.
271
Deprecated: use WorkingTree.open_containing_paths instead.
273
This is typically used for command-line processors that take one or
274
more filenames, and infer the workingtree that contains them.
276
The filenames given are not required to exist.
278
:param file_list: Filenames to convert.
280
:param default_branch: Fallback tree path to use if file_list is empty or
283
:param apply_view: if True and a view is set, apply it or check that
284
specified files are within it
286
:return: workingtree, [relative_paths]
288
return WorkingTree.open_containing_paths(
289
file_list, default_directory='.',
294
288
def _get_view_info_for_change_reporter(tree):
295
289
"""Get the view information from a tree for change reporting."""
374
368
This will produce the same results as calling 'bzr diff --summarize'.
377
# TODO: --no-recurse, --recurse options
371
# TODO: --no-recurse/-N, --recurse options
379
373
takes_args = ['file*']
380
374
takes_options = ['show-ids', 'revision', 'change', 'verbose',
692
686
if len(revision) != 1:
693
687
raise errors.BzrCommandError(gettext(
694
"Tags can only be placed on a single revision, "
688
"Revision numbers only make sense for single "
689
"revisions, not ranges"))
696
690
revid = revision[0].as_revision_id(b)
698
692
revid = b.last_revision()
1158
1153
"the master branch."
1160
1155
Option('show-base',
1161
help="Show base revision text in conflicts.")
1156
help="Show base revision text in conflicts."),
1157
Option('overwrite-tags',
1158
help="Overwrite tags only."),
1163
1160
takes_args = ['location?']
1164
1161
encoding_type = 'replace'
1166
1163
def run(self, location=None, remember=None, overwrite=False,
1167
1164
revision=None, verbose=False,
1168
1165
directory=None, local=False,
1166
show_base=False, overwrite_tags=False):
1169
overwrite = ["history", "tags"]
1170
elif overwrite_tags:
1171
overwrite = ["tags"]
1170
1174
# FIXME: too much stuff is in the command class
1171
1175
revision_id = None
1172
1176
mergeable = None
1181
1185
branch_to = Branch.open_containing(directory)[0]
1182
1186
self.add_cleanup(branch_to.lock_write().unlock)
1184
if tree_to is None and show_base:
1185
raise errors.BzrCommandError(gettext("Need working tree for --show-base."))
1188
warning(gettext("No working tree, ignoring --show-base"))
1187
1190
if local and not branch_to.get_bound_location():
1188
1191
raise errors.LocalRequiresBoundBranch()
1317
1322
def run(self, location=None, remember=None, overwrite=False,
1318
1323
create_prefix=False, verbose=False, revision=None,
1319
1324
use_existing_dir=False, directory=None, stacked_on=None,
1320
stacked=False, strict=None, no_tree=False):
1325
stacked=False, strict=None, no_tree=False,
1326
overwrite_tags=False):
1321
1327
from bzrlib.push import _show_push_branch
1330
overwrite = ["history", "tags"]
1331
elif overwrite_tags:
1332
overwrite = ["tags"]
1323
1336
if directory is None:
1324
1337
directory = '.'
1325
1338
# Get the source branch
1559
1572
active_branch = dir.open_branch(name="")
1560
1573
except errors.NotBranchError:
1561
1574
active_branch = None
1562
branches = dir.get_branches()
1564
for name, branch in branches.iteritems():
1576
for name, branch in iter_sibling_branches(dir):
1567
1579
active = (active_branch is not None and
1605
_see_also = ['checkouts', 'branch']
1617
_see_also = ['checkouts', 'branch', 'working-trees', 'remove-tree']
1606
1618
takes_args = ['branch_location?', 'to_location?']
1607
1619
takes_options = ['revision',
1608
1620
Option('lightweight',
1847
1859
This makes Bazaar stop tracking changes to the specified files. Bazaar will
1848
1860
delete them if they can easily be recovered using revert otherwise they
1849
will be backed up (adding an extention of the form .~#~). If no options or
1861
will be backed up (adding an extension of the form .~#~). If no options or
1850
1862
parameters are given Bazaar will scan for files that are being tracked by
1851
1863
Bazaar but missing in your tree and stop tracking them for you.
1858
1870
title='Deletion Strategy', value_switches=True, enum_switch=False,
1859
1871
safe='Backup changed files (default).',
1860
1872
keep='Delete from bzr but leave the working copy.',
1861
no_backup='Don\'t backup changed files.',
1862
force='Delete all the specified files, even if they can not be '
1863
'recovered and even if they are non-empty directories. '
1864
'(deprecated, use no-backup)')]
1873
no_backup='Don\'t backup changed files.'),
1865
1875
aliases = ['rm', 'del']
1866
1876
encoding_type = 'replace'
1868
1878
def run(self, file_list, verbose=False, new=False,
1869
1879
file_deletion_strategy='safe'):
1870
if file_deletion_strategy == 'force':
1871
note(gettext("(The --force option is deprecated, rather use --no-backup "
1873
file_deletion_strategy = 'no-backup'
1875
1881
tree, file_list = WorkingTree.open_containing_paths(file_list)
2060
2066
RegistryOption('format',
2061
2067
help='Specify a format for this branch. '
2062
2068
'See "help formats".',
2063
lazy_registry=('bzrlib.bzrdir', 'format_registry'),
2069
lazy_registry=('bzrlib.controldir', 'format_registry'),
2064
2070
converter=lambda name: controldir.format_registry.make_bzrdir(name),
2065
2071
value_switches=True,
2066
2072
title="Branch format",
2322
2328
help='Diff format to use.',
2323
2329
lazy_registry=('bzrlib.diff', 'format_registry'),
2324
2330
title='Diff format'),
2332
help='How many lines of context to show.',
2326
2336
aliases = ['di', 'dif']
2327
2337
encoding_type = 'exact'
2329
2339
@display_command
2330
2340
def run(self, revision=None, file_list=None, diff_options=None,
2331
prefix=None, old=None, new=None, using=None, format=None):
2341
prefix=None, old=None, new=None, using=None, format=None,
2332
2343
from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
2333
2344
show_diff_trees)
4736
4747
class cmd_revert(Command):
4737
__doc__ = """Revert files to a previous revision.
4749
Set files in the working tree back to the contents of a previous revision.
4739
4751
Giving a list of files will revert only those files. Otherwise, all files
4740
4752
will be reverted. If the revision is not specified with '--revision', the
4741
last committed revision is used.
4753
working tree basis revision is used. A revert operation affects only the
4754
working tree, not any revision history like the branch and repository or
4755
the working tree basis revision.
4743
4757
To remove only some changes, without reverting to a prior version, use
4744
4758
merge instead. For example, "merge . -r -2..-3" (don't forget the ".")
4745
4759
will remove the changes introduced by the second last commit (-2), without
4746
4760
affecting the changes introduced by the last commit (-1). To remove
4747
4761
certain changes on a hunk-by-hunk basis, see the shelve command.
4762
To update the branch to a specific revision or the latest revision and
4763
update the working tree accordingly while preserving local changes, see the
4749
By default, any files that have been manually changed will be backed up
4750
first. (Files changed only by merge are not backed up.) Backup files have
4751
'.~#~' appended to their name, where # is a number.
4766
Uncommitted changes to files that are reverted will be discarded.
4767
Howver, by default, any files that have been manually changed will be
4768
backed up first. (Files changed only by merge are not backed up.) Backup
4769
files have '.~#~' appended to their name, where # is a number.
4753
4771
When you provide files, you can use their current pathname or the pathname
4754
4772
from the target revision. So you can use revert to "undelete" a file by
5001
5019
"You have %d extra revisions:\n",
5002
5020
len(local_extra)) %
5003
5021
len(local_extra))
5023
if local_branch.supports_tags():
5024
rev_tag_dict = local_branch.tags.get_reverse_tag_dict()
5004
5025
for revision in iter_log_revisions(local_extra,
5005
5026
local_branch.repository,
5007
5029
lf.log_revision(revision)
5008
5030
printed_local = True
5009
5031
status_code = 1
5017
5039
"You are missing %d revisions:\n",
5018
5040
len(remote_extra)) %
5019
5041
len(remote_extra))
5042
if remote_branch.supports_tags():
5043
rev_tag_dict = remote_branch.tags.get_reverse_tag_dict()
5020
5044
for revision in iter_log_revisions(remote_extra,
5021
5045
remote_branch.repository,
5023
5048
lf.log_revision(revision)
5024
5049
status_code = 1
5133
5159
rev_id = revision[0].as_revision_id(b)
5134
5160
t = testament_class.from_revision(b.repository, rev_id)
5136
sys.stdout.writelines(t.as_text_lines())
5162
self.outf.writelines(t.as_text_lines())
5138
sys.stdout.write(t.as_short_text())
5164
self.outf.write(t.as_short_text())
5141
5167
class cmd_annotate(Command):
5497
5523
help="Protocol to serve.",
5498
5524
lazy_registry=('bzrlib.transport', 'transport_server_registry'),
5499
5525
value_switches=True),
5527
help='Listen for connections on nominated address.', type=str),
5501
help='Listen for connections on nominated port of the form '
5502
'[hostname:]portnumber. Passing 0 as the port number will '
5503
'result in a dynamically allocated port. The default port '
5504
'depends on the protocol.',
5529
help='Listen for connections on nominated port. Passing 0 as '
5530
'the port number will result in a dynamically allocated '
5531
'port. The default port depends on the protocol.',
5506
5533
custom_help('directory',
5507
5534
help='Serve contents of this directory.'),
5508
5535
Option('allow-writes',
5518
5545
help='Override the default idle client timeout (5min).'),
5521
def get_host_and_port(self, port):
5522
"""Return the host and port to run the smart server on.
5524
If 'port' is None, None will be returned for the host and port.
5526
If 'port' has a colon in it, the string before the colon will be
5527
interpreted as the host.
5529
:param port: A string of the port to run the server on.
5530
:return: A tuple of (host, port), where 'host' is a host name or IP,
5531
and port is an integer TCP/IP port.
5534
if port is not None:
5536
host, port = port.split(':')
5540
def run(self, port=None, inet=False, directory=None, allow_writes=False,
5541
protocol=None, client_timeout=None):
5548
def run(self, listen=None, port=None, inet=False, directory=None,
5549
allow_writes=False, protocol=None, client_timeout=None):
5542
5550
from bzrlib import transport
5543
5551
if directory is None:
5544
5552
directory = os.getcwd()
5545
5553
if protocol is None:
5546
5554
protocol = transport.transport_server_registry.get()
5547
host, port = self.get_host_and_port(port)
5548
5555
url = transport.location_to_url(directory)
5549
5556
if not allow_writes:
5550
5557
url = 'readonly+' + url
5551
5558
t = transport.get_transport_from_url(url)
5553
protocol(t, host, port, inet, client_timeout)
5554
except TypeError, e:
5555
# We use symbol_versioning.deprecated_in just so that people
5556
# grepping can find it here.
5557
# symbol_versioning.deprecated_in((2, 5, 0))
5558
symbol_versioning.warn(
5559
'Got TypeError(%s)\ntrying to call protocol: %s.%s\n'
5560
'Most likely it needs to be updated to support a'
5561
' "timeout" parameter (added in bzr 2.5.0)'
5562
% (e, protocol.__module__, protocol),
5564
protocol(t, host, port, inet)
5559
protocol(t, listen, port, inet, client_timeout)
5567
5562
class cmd_join(Command):
6237
6232
Option('create-branch', short_name='b',
6238
6233
help='Create the target branch from this one before'
6239
6234
' switching to it.'),
6236
help='Store and restore uncommitted changes in the'
6242
6240
def run(self, to_location=None, force=False, create_branch=False,
6243
revision=None, directory=u'.'):
6241
revision=None, directory=u'.', store=False):
6244
6242
from bzrlib import switch
6245
6243
tree_location = directory
6246
6244
revision = _get_one_revision('switch', revision)
6277
6275
possible_transports=possible_transports)
6278
6276
if revision is not None:
6279
6277
revision = revision.as_revision_id(to_branch)
6280
switch.switch(control_dir, to_branch, force, revision_id=revision)
6278
switch.switch(control_dir, to_branch, force, revision_id=revision,
6279
store_uncommitted=store)
6281
6280
if had_explicit_nick:
6282
6281
branch = control_dir.open_branch() #get the new branch!
6283
6282
branch.nick = to_branch.nick
6478
6477
takes_args = ["location?"]
6480
takes_options = ['directory']
6479
takes_options = ['directory',
6480
Option('force', help='Remove branch even if it is the active branch.')]
6482
6482
aliases = ["rmbranch"]
6484
def run(self, directory=None, location=None):
6484
def run(self, directory=None, location=None, force=False):
6485
6485
br = open_nearby_branch(near=directory, location=location)
6486
if not force and br.bzrdir.has_workingtree():
6488
active_branch = br.bzrdir.open_branch(name="")
6489
except errors.NotBranchError:
6490
active_branch = None
6491
if (active_branch is not None and
6492
br.control_url == active_branch.control_url):
6493
raise errors.BzrCommandError(
6494
gettext("Branch is active. Use --force to remove it."))
6486
6495
br.bzrdir.destroy_branch(br.name)
6718
6727
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6719
6728
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6720
6729
('cmd_conflicts', [], 'bzrlib.conflicts'),
6730
('cmd_ping', [], 'bzrlib.smart.ping'),
6721
6731
('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6722
('cmd_verify_signatures', [],
6723
'bzrlib.commit_signature_commands'),
6732
('cmd_verify_signatures', [], 'bzrlib.commit_signature_commands'),
6724
6733
('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6726
6735
builtin_command_registry.register_lazy(name, aliases, module_name)