86
def _get_branch_location(control_dir, possible_transports=None):
87
"""Return location of branch for this control dir."""
89
target = control_dir.get_branch_reference()
90
except errors.NotBranchError:
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
104
def _is_colocated(control_dir, possible_transports=None):
105
"""Check if the branch in control_dir is colocated.
107
:param control_dir: Control directory
108
:return: Tuple with boolean indicating whether the branch is colocated
109
and the full URL to the actual branch
111
# This path is meant to be relative to the existing branch
112
this_url = _get_branch_location(control_dir,
113
possible_transports=possible_transports)
114
# Perhaps the target control dir supports colocated branches?
116
root = controldir.ControlDir.open(this_url,
117
possible_transports=possible_transports)
118
except errors.NotBranchError:
119
return (False, this_url)
122
wt = control_dir.open_workingtree()
123
except (errors.NoWorkingTree, errors.NotLocalUrl):
124
return (False, this_url)
127
root._format.colocated_branches and
128
control_dir.control_url == root.control_url,
132
def lookup_new_sibling_branch(control_dir, location, possible_transports=None):
133
"""Lookup the location for a new sibling branch.
135
:param control_dir: Control directory to find sibling branches from
136
:param location: Name of the new branch
137
:return: Full location to the new branch
139
location = directory_service.directories.dereference(location)
140
if '/' not in location and '\\' not in location:
141
(colocated, this_url) = _is_colocated(control_dir, possible_transports)
144
return urlutils.join_segment_parameters(this_url,
145
{"branch": urlutils.escape(location)})
147
return urlutils.join(this_url, '..', urlutils.escape(location))
151
def open_sibling_branch(control_dir, location, possible_transports=None):
152
"""Open a branch, possibly a sibling of another.
154
:param control_dir: Control directory relative to which to lookup the
156
:param location: Location to look up
157
:return: branch to open
160
# Perhaps it's a colocated branch?
161
return control_dir.open_branch(location,
162
possible_transports=possible_transports)
163
except (errors.NotBranchError, errors.NoColocatedBranchSupport):
164
this_url = _get_branch_location(control_dir)
167
this_url, '..', urlutils.escape(location)))
170
def open_nearby_branch(near=None, location=None, possible_transports=None):
171
"""Open a nearby branch.
173
:param near: Optional location of container from which to open branch
174
:param location: Location of the branch
175
:return: Branch instance
181
return Branch.open(location,
182
possible_transports=possible_transports)
183
except errors.NotBranchError:
185
cdir = controldir.ControlDir.open(near,
186
possible_transports=possible_transports)
187
return open_sibling_branch(cdir, location,
188
possible_transports=possible_transports)
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("/")
86
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
87
def tree_files(file_list, default_branch=u'.', canonicalize=True,
89
return internal_tree_files(file_list, default_branch, canonicalize,
223
93
def tree_files_for_add(file_list):
158
# XXX: Bad function name; should possibly also be a class method of
159
# WorkingTree rather than a function.
160
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
161
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
163
"""Convert command-line paths to a WorkingTree and relative paths.
165
Deprecated: use WorkingTree.open_containing_paths instead.
167
This is typically used for command-line processors that take one or
168
more filenames, and infer the workingtree that contains them.
170
The filenames given are not required to exist.
172
:param file_list: Filenames to convert.
174
:param default_branch: Fallback tree path to use if file_list is empty or
177
:param apply_view: if True and a view is set, apply it or check that
178
specified files are within it
180
:return: workingtree, [relative_paths]
182
return WorkingTree.open_containing_paths(
183
file_list, default_directory='.',
288
188
def _get_view_info_for_change_reporter(tree):
289
189
"""Get the view information from a tree for change reporting."""
1870
1750
title='Deletion Strategy', value_switches=True, enum_switch=False,
1871
1751
safe='Backup changed files (default).',
1872
1752
keep='Delete from bzr but leave the working copy.',
1873
no_backup='Don\'t backup changed files.'),
1753
no_backup='Don\'t backup changed files.',
1754
force='Delete all the specified files, even if they can not be '
1755
'recovered and even if they are non-empty directories. '
1756
'(deprecated, use no-backup)')]
1875
1757
aliases = ['rm', 'del']
1876
1758
encoding_type = 'replace'
1878
1760
def run(self, file_list, verbose=False, new=False,
1879
1761
file_deletion_strategy='safe'):
1762
if file_deletion_strategy == 'force':
1763
note(gettext("(The --force option is deprecated, rather use --no-backup "
1765
file_deletion_strategy = 'no-backup'
1881
1767
tree, file_list = WorkingTree.open_containing_paths(file_list)
4747
4627
class cmd_revert(Command):
4749
Set files in the working tree back to the contents of a previous revision.
4628
__doc__ = """Revert files to a previous revision.
4751
4630
Giving a list of files will revert only those files. Otherwise, all files
4752
4631
will be reverted. If the revision is not specified with '--revision', the
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.
4632
last committed revision is used.
4757
4634
To remove only some changes, without reverting to a prior version, use
4758
4635
merge instead. For example, "merge . -r -2..-3" (don't forget the ".")
4759
4636
will remove the changes introduced by the second last commit (-2), without
4760
4637
affecting the changes introduced by the last commit (-1). To remove
4761
4638
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
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.
4640
By default, any files that have been manually changed will be backed up
4641
first. (Files changed only by merge are not backed up.) Backup files have
4642
'.~#~' appended to their name, where # is a number.
4771
4644
When you provide files, you can use their current pathname or the pathname
4772
4645
from the target revision. So you can use revert to "undelete" a file by
5545
5409
help='Override the default idle client timeout (5min).'),
5548
def run(self, listen=None, port=None, inet=False, directory=None,
5549
allow_writes=False, protocol=None, client_timeout=None):
5412
def get_host_and_port(self, port):
5413
"""Return the host and port to run the smart server on.
5415
If 'port' is None, None will be returned for the host and port.
5417
If 'port' has a colon in it, the string before the colon will be
5418
interpreted as the host.
5420
:param port: A string of the port to run the server on.
5421
:return: A tuple of (host, port), where 'host' is a host name or IP,
5422
and port is an integer TCP/IP port.
5425
if port is not None:
5427
host, port = port.split(':')
5431
def run(self, port=None, inet=False, directory=None, allow_writes=False,
5432
protocol=None, client_timeout=None):
5550
5433
from bzrlib import transport
5551
5434
if directory is None:
5552
5435
directory = os.getcwd()
5553
5436
if protocol is None:
5554
5437
protocol = transport.transport_server_registry.get()
5438
host, port = self.get_host_and_port(port)
5555
5439
url = transport.location_to_url(directory)
5556
5440
if not allow_writes:
5557
5441
url = 'readonly+' + url
5558
5442
t = transport.get_transport_from_url(url)
5559
protocol(t, listen, port, inet, client_timeout)
5444
protocol(t, host, port, inet, client_timeout)
5445
except TypeError, e:
5446
# We use symbol_versioning.deprecated_in just so that people
5447
# grepping can find it here.
5448
# symbol_versioning.deprecated_in((2, 5, 0))
5449
symbol_versioning.warn(
5450
'Got TypeError(%s)\ntrying to call protocol: %s.%s\n'
5451
'Most likely it needs to be updated to support a'
5452
' "timeout" parameter (added in bzr 2.5.0)'
5453
% (e, protocol.__module__, protocol),
5455
protocol(t, host, port, inet)
5562
5458
class cmd_join(Command):
6232
6128
Option('create-branch', short_name='b',
6233
6129
help='Create the target branch from this one before'
6234
6130
' switching to it.'),
6236
help='Store and restore uncommitted changes in the'
6240
6133
def run(self, to_location=None, force=False, create_branch=False,
6241
revision=None, directory=u'.', store=False):
6134
revision=None, directory=u'.'):
6242
6135
from bzrlib import switch
6243
6136
tree_location = directory
6244
6137
revision = _get_one_revision('switch', revision)
6245
possible_transports = []
6246
control_dir = controldir.ControlDir.open_containing(tree_location,
6247
possible_transports=possible_transports)[0]
6138
control_dir = controldir.ControlDir.open_containing(tree_location)[0]
6248
6139
if to_location is None:
6249
6140
if revision is None:
6250
6141
raise errors.BzrCommandError(gettext('You must supply either a'
6251
6142
' revision or a location'))
6252
6143
to_location = tree_location
6254
branch = control_dir.open_branch(
6255
possible_transports=possible_transports)
6145
branch = control_dir.open_branch()
6256
6146
had_explicit_nick = branch.get_config().has_explicit_nickname()
6257
6147
except errors.NotBranchError:
6259
6149
had_explicit_nick = False
6260
6150
if create_branch:
6261
6151
if branch is None:
6262
raise errors.BzrCommandError(
6263
gettext('cannot create branch without source branch'))
6264
to_location = lookup_new_sibling_branch(control_dir, to_location,
6265
possible_transports=possible_transports)
6152
raise errors.BzrCommandError(gettext('cannot create branch without'
6154
to_location = directory_service.directories.dereference(
6156
if '/' not in to_location and '\\' not in to_location:
6157
# This path is meant to be relative to the existing branch
6158
this_url = self._get_branch_location(control_dir)
6159
# Perhaps the target control dir supports colocated branches?
6161
root = controldir.ControlDir.open(this_url,
6162
possible_transports=[control_dir.user_transport])
6163
except errors.NotBranchError:
6166
colocated = root._format.colocated_branches
6168
to_location = urlutils.join_segment_parameters(this_url,
6169
{"branch": urlutils.escape(to_location)})
6171
to_location = urlutils.join(
6172
this_url, '..', urlutils.escape(to_location))
6266
6173
to_branch = branch.bzrdir.sprout(to_location,
6267
possible_transports=possible_transports,
6268
source_branch=branch).open_branch()
6174
possible_transports=[branch.bzrdir.root_transport],
6175
source_branch=branch).open_branch()
6177
# Perhaps it's a colocated branch?
6271
to_branch = Branch.open(to_location,
6272
possible_transports=possible_transports)
6273
except errors.NotBranchError:
6274
to_branch = open_sibling_branch(control_dir, to_location,
6275
possible_transports=possible_transports)
6179
to_branch = control_dir.open_branch(to_location)
6180
except (errors.NotBranchError, errors.NoColocatedBranchSupport):
6182
to_branch = Branch.open(to_location)
6183
except errors.NotBranchError:
6184
this_url = self._get_branch_location(control_dir)
6185
to_branch = Branch.open(
6187
this_url, '..', urlutils.escape(to_location)))
6276
6188
if revision is not None:
6277
6189
revision = revision.as_revision_id(to_branch)
6278
switch.switch(control_dir, to_branch, force, revision_id=revision,
6279
store_uncommitted=store)
6190
switch.switch(control_dir, to_branch, force, revision_id=revision)
6280
6191
if had_explicit_nick:
6281
6192
branch = control_dir.open_branch() #get the new branch!
6282
6193
branch.nick = to_branch.nick
6283
6194
note(gettext('Switched to branch: %s'),
6284
6195
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6197
def _get_branch_location(self, control_dir):
6198
"""Return location of branch for this control dir."""
6200
this_branch = control_dir.open_branch()
6201
# This may be a heavy checkout, where we want the master branch
6202
master_location = this_branch.get_bound_location()
6203
if master_location is not None:
6204
return master_location
6205
# If not, use a local sibling
6206
return this_branch.base
6207
except errors.NotBranchError:
6208
format = control_dir.find_branch_format()
6209
if getattr(format, 'get_reference', None) is not None:
6210
return format.get_reference(control_dir)
6212
return control_dir.root_transport.base
6288
6215
class cmd_view(Command):
6477
6404
takes_args = ["location?"]
6479
takes_options = ['directory',
6480
Option('force', help='Remove branch even if it is the active branch.')]
6482
6406
aliases = ["rmbranch"]
6484
def run(self, directory=None, location=None, force=False):
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."))
6495
br.bzrdir.destroy_branch(br.name)
6408
def run(self, location=None):
6409
if location is None:
6411
branch = Branch.open_containing(location)[0]
6412
branch.bzrdir.destroy_branch()
6498
6415
class cmd_shelve(Command):
6727
6644
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6728
6645
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6729
6646
('cmd_conflicts', [], 'bzrlib.conflicts'),
6730
('cmd_ping', [], 'bzrlib.smart.ping'),
6731
6647
('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6732
('cmd_verify_signatures', [], 'bzrlib.commit_signature_commands'),
6648
('cmd_verify_signatures', [],
6649
'bzrlib.commit_signature_commands'),
6733
6650
('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6735
6652
builtin_command_registry.register_lazy(name, aliases, module_name)