86
86
def _get_branch_location(control_dir, possible_transports=None):
87
87
"""Return location of branch for this control dir."""
89
target = control_dir.get_branch_reference()
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
90
97
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
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
104
105
def _is_colocated(control_dir, possible_transports=None):
105
106
"""Check if the branch in control_dir is colocated.
107
108
: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
109
:return: Boolean indicating whether
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 to find sibling branches from
135
:param control_dir: Control directory relative to which to look up
136
137
:param location: Name of the new branch
137
138
:return: Full location to the new branch
151
def open_sibling_branch(control_dir, location, possible_transports=None):
152
"""Open a branch, possibly a sibling of another.
152
def lookup_sibling_branch(control_dir, location, possible_transports=None):
153
"""Lookup sibling branch.
154
155
:param control_dir: Control directory relative to which to lookup the
156
157
:param location: Location to look up
161
162
return control_dir.open_branch(location,
162
163
possible_transports=possible_transports)
163
164
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)
166
return Branch.open(location)
183
167
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("/")
168
this_url = _get_branch_location(control_dir)
171
this_url, '..', urlutils.escape(location)))
174
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
175
def tree_files(file_list, default_branch=u'.', canonicalize=True,
177
return internal_tree_files(file_list, default_branch, canonicalize,
223
181
def tree_files_for_add(file_list):
246
# XXX: Bad function name; should possibly also be a class method of
247
# WorkingTree rather than a function.
248
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
249
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
251
"""Convert command-line paths to a WorkingTree and relative paths.
253
Deprecated: use WorkingTree.open_containing_paths instead.
255
This is typically used for command-line processors that take one or
256
more filenames, and infer the workingtree that contains them.
258
The filenames given are not required to exist.
260
:param file_list: Filenames to convert.
262
:param default_branch: Fallback tree path to use if file_list is empty or
265
:param apply_view: if True and a view is set, apply it or check that
266
specified files are within it
268
:return: workingtree, [relative_paths]
270
return WorkingTree.open_containing_paths(
271
file_list, default_directory='.',
288
276
def _get_view_info_for_change_reporter(tree):
289
277
"""Get the view information from a tree for change reporting."""
953
self.add_cleanup(tree.lock_read().unlock)
954
940
if file_list is not None:
955
941
file_ids = tree.paths2ids(file_list, trees=extra_trees,
956
942
require_versioned=True)
957
943
# find_ids_across_trees may include some paths that don't
958
944
# exist in 'tree'.
959
entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
946
(tree.id2path(file_id), tree.inventory[file_id])
947
for file_id in file_ids if tree.has_id(file_id))
961
entries = tree.iter_entries_by_dir()
949
entries = tree.inventory.entries()
963
for path, entry in sorted(entries):
952
for path, entry in entries:
964
953
if kind and kind != entry.kind:
969
956
self.outf.write('%-50s %s\n' % (path, entry.file_id))
1163
1149
def run(self, location=None, remember=None, overwrite=False,
1164
1150
revision=None, verbose=False,
1165
1151
directory=None, local=False,
1166
show_base=False, overwrite_tags=False):
1169
overwrite = ["history", "tags"]
1170
elif overwrite_tags:
1171
overwrite = ["tags"]
1174
1153
# FIXME: too much stuff is in the command class
1175
1154
revision_id = None
1176
1155
mergeable = None
1323
1298
def run(self, location=None, remember=None, overwrite=False,
1324
1299
create_prefix=False, verbose=False, revision=None,
1325
1300
use_existing_dir=False, directory=None, stacked_on=None,
1326
stacked=False, strict=None, no_tree=False,
1327
overwrite_tags=False):
1301
stacked=False, strict=None, no_tree=False):
1328
1302
from bzrlib.push import _show_push_branch
1331
overwrite = ["history", "tags"]
1332
elif overwrite_tags:
1333
overwrite = ["tags"]
1337
1304
if directory is None:
1338
1305
directory = '.'
1339
1306
# Get the source branch
1681
1649
def run(self, dir=u'.'):
1682
1650
tree = WorkingTree.open_containing(dir)[0]
1683
1651
self.add_cleanup(tree.lock_read().unlock)
1652
new_inv = tree.inventory
1684
1653
old_tree = tree.basis_tree()
1685
1654
self.add_cleanup(old_tree.lock_read().unlock)
1655
old_inv = old_tree.inventory
1687
1657
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1688
1658
for f, paths, c, v, p, n, k, e in iterator:
2446
2416
self.add_cleanup(wt.lock_read().unlock)
2447
2417
basis = wt.basis_tree()
2448
2418
self.add_cleanup(basis.lock_read().unlock)
2449
root_id = wt.get_root_id()
2450
for file_id in wt.all_file_ids():
2451
if basis.has_id(file_id):
2453
if root_id == file_id:
2455
path = wt.id2path(file_id)
2419
basis_inv = basis.inventory
2422
if basis_inv.has_id(file_id):
2424
if inv.is_root(file_id) and len(basis_inv) == 0:
2426
path = inv.id2path(file_id)
2456
2427
if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
3546
3517
tokens = fixed_bug.split(':')
3547
3518
if len(tokens) == 1:
3548
3519
if default_bugtracker is None:
3549
branch_config = branch.get_config_stack()
3550
default_bugtracker = branch_config.get(
3520
branch_config = branch.get_config()
3521
default_bugtracker = branch_config.get_user_option(
3552
3523
if default_bugtracker is None:
3553
3524
raise errors.BzrCommandError(gettext(
4707
4676
if tree.kind(file_id) != "directory":
4710
# FIXME: Support nested trees
4711
for name, ie in tree.root_inventory.iter_entries(file_id):
4679
for name, ie in tree.inventory.iter_entries(file_id):
4712
4680
interesting_ids.add(ie.file_id)
4713
4681
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4749
4717
class cmd_revert(Command):
4751
Set files in the working tree back to the contents of a previous revision.
4718
__doc__ = """Revert files to a previous revision.
4753
4720
Giving a list of files will revert only those files. Otherwise, all files
4754
4721
will be reverted. If the revision is not specified with '--revision', the
4755
working tree basis revision is used. A revert operation affects only the
4756
working tree, not any revision history like the branch and repository or
4757
the working tree basis revision.
4722
last committed revision is used.
4759
4724
To remove only some changes, without reverting to a prior version, use
4760
4725
merge instead. For example, "merge . -r -2..-3" (don't forget the ".")
4761
4726
will remove the changes introduced by the second last commit (-2), without
4762
4727
affecting the changes introduced by the last commit (-1). To remove
4763
4728
certain changes on a hunk-by-hunk basis, see the shelve command.
4764
To update the branch to a specific revision or the latest revision and
4765
update the working tree accordingly while preserving local changes, see the
4768
Uncommitted changes to files that are reverted will be discarded.
4769
Howver, by default, any files that have been manually changed will be
4770
backed up first. (Files changed only by merge are not backed up.) Backup
4771
files have '.~#~' appended to their name, where # is a number.
4730
By default, any files that have been manually changed will be backed up
4731
first. (Files changed only by merge are not backed up.) Backup files have
4732
'.~#~' appended to their name, where # is a number.
4773
4734
When you provide files, you can use their current pathname or the pathname
4774
4735
from the target revision. So you can use revert to "undelete" a file by
5310
5264
if location is None:
5311
5265
if b.get_bound_location() is not None:
5312
raise errors.BzrCommandError(
5313
gettext('Branch is already bound'))
5266
raise errors.BzrCommandError(gettext('Branch is already bound'))
5315
raise errors.BzrCommandError(
5316
gettext('No location supplied'
5317
' and no previous location known'))
5268
raise errors.BzrCommandError(gettext('No location supplied '
5269
'and no previous location known'))
5318
5270
b_other = Branch.open(location)
5320
5272
b.bind(b_other)
5524
5476
help="Protocol to serve.",
5525
5477
lazy_registry=('bzrlib.transport', 'transport_server_registry'),
5526
5478
value_switches=True),
5528
help='Listen for connections on nominated address.', type=str),
5530
help='Listen for connections on nominated port. Passing 0 as '
5531
'the port number will result in a dynamically allocated '
5532
'port. The default port depends on the protocol.',
5480
help='Listen for connections on nominated port of the form '
5481
'[hostname:]portnumber. Passing 0 as the port number will '
5482
'result in a dynamically allocated port. The default port '
5483
'depends on the protocol.',
5534
5485
custom_help('directory',
5535
5486
help='Serve contents of this directory.'),
5536
5487
Option('allow-writes',
5546
5497
help='Override the default idle client timeout (5min).'),
5549
def run(self, listen=None, port=None, inet=False, directory=None,
5550
allow_writes=False, protocol=None, client_timeout=None):
5500
def get_host_and_port(self, port):
5501
"""Return the host and port to run the smart server on.
5503
If 'port' is None, None will be returned for the host and port.
5505
If 'port' has a colon in it, the string before the colon will be
5506
interpreted as the host.
5508
:param port: A string of the port to run the server on.
5509
:return: A tuple of (host, port), where 'host' is a host name or IP,
5510
and port is an integer TCP/IP port.
5513
if port is not None:
5515
host, port = port.split(':')
5519
def run(self, port=None, inet=False, directory=None, allow_writes=False,
5520
protocol=None, client_timeout=None):
5551
5521
from bzrlib import transport
5552
5522
if directory is None:
5553
5523
directory = os.getcwd()
5554
5524
if protocol is None:
5555
5525
protocol = transport.transport_server_registry.get()
5526
host, port = self.get_host_and_port(port)
5556
5527
url = transport.location_to_url(directory)
5557
5528
if not allow_writes:
5558
5529
url = 'readonly+' + url
5559
5530
t = transport.get_transport_from_url(url)
5560
protocol(t, listen, port, inet, client_timeout)
5532
protocol(t, host, port, inet, client_timeout)
5533
except TypeError, e:
5534
# We use symbol_versioning.deprecated_in just so that people
5535
# grepping can find it here.
5536
# symbol_versioning.deprecated_in((2, 5, 0))
5537
symbol_versioning.warn(
5538
'Got TypeError(%s)\ntrying to call protocol: %s.%s\n'
5539
'Most likely it needs to be updated to support a'
5540
' "timeout" parameter (added in bzr 2.5.0)'
5541
% (e, protocol.__module__, protocol),
5543
protocol(t, host, port, inet)
5563
5546
class cmd_join(Command):
6265
6247
possible_transports=possible_transports,
6266
6248
source_branch=branch).open_branch()
6269
to_branch = Branch.open(to_location,
6270
possible_transports=possible_transports)
6271
except errors.NotBranchError:
6272
to_branch = open_sibling_branch(control_dir, to_location,
6273
possible_transports=possible_transports)
6250
to_branch = lookup_sibling_branch(control_dir, to_location)
6274
6251
if revision is not None:
6275
6252
revision = revision.as_revision_id(to_branch)
6276
6253
switch.switch(control_dir, to_branch, force, revision_id=revision)
6474
6451
takes_args = ["location?"]
6476
takes_options = ['directory',
6477
Option('force', help='Remove branch even if it is the active branch.')]
6479
6453
aliases = ["rmbranch"]
6481
def run(self, directory=None, location=None, force=False):
6482
br = open_nearby_branch(near=directory, location=location)
6483
if not force and br.bzrdir.has_workingtree():
6485
active_branch = br.bzrdir.open_branch(name="")
6486
except errors.NotBranchError:
6487
active_branch = None
6488
if (active_branch is not None and
6489
br.control_url == active_branch.control_url):
6490
raise errors.BzrCommandError(
6491
gettext("Branch is active. Use --force to remove it."))
6492
br.bzrdir.destroy_branch(br.name)
6455
def run(self, location=None):
6456
if location is None:
6458
cdir = controldir.ControlDir.open_containing(location)[0]
6459
cdir.destroy_branch()
6495
6462
class cmd_shelve(Command):
6725
6692
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6726
6693
('cmd_conflicts', [], 'bzrlib.conflicts'),
6727
6694
('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6728
('cmd_verify_signatures', [], 'bzrlib.commit_signature_commands'),
6695
('cmd_verify_signatures', [],
6696
'bzrlib.commit_signature_commands'),
6729
6697
('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6731
6699
builtin_command_registry.register_lazy(name, aliases, module_name)