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
def lookup_sibling_branch(control_dir, location, possible_transports=None):
153
"""Lookup sibling branch.
151
def open_sibling_branch(control_dir, location, possible_transports=None):
152
"""Open a branch, possibly a sibling of another.
155
154
:param control_dir: Control directory relative to which to lookup the
157
156
:param location: Location to look up
162
161
return control_dir.open_branch(location,
163
162
possible_transports=possible_transports)
164
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
166
return Branch.open(location)
181
return Branch.open(location,
182
possible_transports=possible_transports)
167
183
except errors.NotBranchError:
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,
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("/")
181
223
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='.',
276
288
def _get_view_info_for_change_reporter(tree):
277
289
"""Get the view information from a tree for change reporting."""
953
self.add_cleanup(tree.lock_read().unlock)
940
954
if file_list is not None:
941
955
file_ids = tree.paths2ids(file_list, trees=extra_trees,
942
956
require_versioned=True)
943
957
# find_ids_across_trees may include some paths that don't
944
958
# exist in 'tree'.
946
(tree.id2path(file_id), tree.inventory[file_id])
947
for file_id in file_ids if tree.has_id(file_id))
959
entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
949
entries = tree.inventory.entries()
961
entries = tree.iter_entries_by_dir()
952
for path, entry in entries:
963
for path, entry in sorted(entries):
953
964
if kind and kind != entry.kind:
956
969
self.outf.write('%-50s %s\n' % (path, entry.file_id))
1668
1681
def run(self, dir=u'.'):
1669
1682
tree = WorkingTree.open_containing(dir)[0]
1670
1683
self.add_cleanup(tree.lock_read().unlock)
1671
new_inv = tree.inventory
1672
1684
old_tree = tree.basis_tree()
1673
1685
self.add_cleanup(old_tree.lock_read().unlock)
1674
old_inv = old_tree.inventory
1676
1687
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1677
1688
for f, paths, c, v, p, n, k, e in iterator:
2435
2446
self.add_cleanup(wt.lock_read().unlock)
2436
2447
basis = wt.basis_tree()
2437
2448
self.add_cleanup(basis.lock_read().unlock)
2438
basis_inv = basis.inventory
2441
if basis_inv.has_id(file_id):
2443
if inv.is_root(file_id) and len(basis_inv) == 0:
2445
path = inv.id2path(file_id)
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)
2446
2456
if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
3536
3546
tokens = fixed_bug.split(':')
3537
3547
if len(tokens) == 1:
3538
3548
if default_bugtracker is None:
3539
branch_config = branch.get_config()
3540
default_bugtracker = branch_config.get_user_option(
3549
branch_config = branch.get_config_stack()
3550
default_bugtracker = branch_config.get(
3542
3552
if default_bugtracker is None:
3543
3553
raise errors.BzrCommandError(gettext(
3891
3903
class cmd_nick(Command):
3892
3904
__doc__ = """Print or set the branch nickname.
3894
If unset, the tree root directory name is used as the nickname.
3895
To print the current nickname, execute with no argument.
3906
If unset, the colocated branch name is used for colocated branches, and
3907
the branch directory name is used for other branches. To print the
3908
current nickname, execute with no argument.
3897
3910
Bound branches use the nickname of its master branch unless it is set
4694
4707
if tree.kind(file_id) != "directory":
4697
for name, ie in tree.inventory.iter_entries(file_id):
4710
# FIXME: Support nested trees
4711
for name, ie in tree.root_inventory.iter_entries(file_id):
4698
4712
interesting_ids.add(ie.file_id)
4699
4713
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4735
4749
class cmd_revert(Command):
4736
__doc__ = """Revert files to a previous revision.
4751
Set files in the working tree back to the contents of a previous revision.
4738
4753
Giving a list of files will revert only those files. Otherwise, all files
4739
4754
will be reverted. If the revision is not specified with '--revision', the
4740
last committed revision is used.
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.
4742
4759
To remove only some changes, without reverting to a prior version, use
4743
4760
merge instead. For example, "merge . -r -2..-3" (don't forget the ".")
4744
4761
will remove the changes introduced by the second last commit (-2), without
4745
4762
affecting the changes introduced by the last commit (-1). To remove
4746
4763
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
4748
By default, any files that have been manually changed will be backed up
4749
first. (Files changed only by merge are not backed up.) Backup files have
4750
'.~#~' appended to their name, where # is a number.
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.
4752
4773
When you provide files, you can use their current pathname or the pathname
4753
4774
from the target revision. So you can use revert to "undelete" a file by
5282
5310
if location is None:
5283
5311
if b.get_bound_location() is not None:
5284
raise errors.BzrCommandError(gettext('Branch is already bound'))
5312
raise errors.BzrCommandError(
5313
gettext('Branch is already bound'))
5286
raise errors.BzrCommandError(gettext('No location supplied '
5287
'and no previous location known'))
5315
raise errors.BzrCommandError(
5316
gettext('No location supplied'
5317
' and no previous location known'))
5288
5318
b_other = Branch.open(location)
5290
5320
b.bind(b_other)
5494
5524
help="Protocol to serve.",
5495
5525
lazy_registry=('bzrlib.transport', 'transport_server_registry'),
5496
5526
value_switches=True),
5528
help='Listen for connections on nominated address.', type=str),
5498
help='Listen for connections on nominated port of the form '
5499
'[hostname:]portnumber. Passing 0 as the port number will '
5500
'result in a dynamically allocated port. The default port '
5501
'depends on the protocol.',
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.',
5503
5534
custom_help('directory',
5504
5535
help='Serve contents of this directory.'),
5505
5536
Option('allow-writes',
5515
5546
help='Override the default idle client timeout (5min).'),
5518
def get_host_and_port(self, port):
5519
"""Return the host and port to run the smart server on.
5521
If 'port' is None, None will be returned for the host and port.
5523
If 'port' has a colon in it, the string before the colon will be
5524
interpreted as the host.
5526
:param port: A string of the port to run the server on.
5527
:return: A tuple of (host, port), where 'host' is a host name or IP,
5528
and port is an integer TCP/IP port.
5531
if port is not None:
5533
host, port = port.split(':')
5537
def run(self, port=None, inet=False, directory=None, allow_writes=False,
5538
protocol=None, client_timeout=None):
5549
def run(self, listen=None, port=None, inet=False, directory=None,
5550
allow_writes=False, protocol=None, client_timeout=None):
5539
5551
from bzrlib import transport
5540
5552
if directory is None:
5541
5553
directory = os.getcwd()
5542
5554
if protocol is None:
5543
5555
protocol = transport.transport_server_registry.get()
5544
host, port = self.get_host_and_port(port)
5545
5556
url = transport.location_to_url(directory)
5546
5557
if not allow_writes:
5547
5558
url = 'readonly+' + url
5548
5559
t = transport.get_transport_from_url(url)
5550
protocol(t, host, port, inet, client_timeout)
5551
except TypeError, e:
5552
# We use symbol_versioning.deprecated_in just so that people
5553
# grepping can find it here.
5554
# symbol_versioning.deprecated_in((2, 5, 0))
5555
symbol_versioning.warn(
5556
'Got TypeError(%s)\ntrying to call protocol: %s.%s\n'
5557
'Most likely it needs to be updated to support a'
5558
' "timeout" parameter (added in bzr 2.5.0)'
5559
% (e, protocol.__module__, protocol),
5561
protocol(t, host, port, inet)
5560
protocol(t, listen, port, inet, client_timeout)
5564
5563
class cmd_join(Command):
6265
6265
possible_transports=possible_transports,
6266
6266
source_branch=branch).open_branch()
6268
to_branch = lookup_sibling_branch(control_dir, to_location)
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)
6269
6274
if revision is not None:
6270
6275
revision = revision.as_revision_id(to_branch)
6271
6276
switch.switch(control_dir, to_branch, force, revision_id=revision)
6469
6474
takes_args = ["location?"]
6476
takes_options = ['directory',
6477
Option('force', help='Remove branch even if it is the active branch.')]
6471
6479
aliases = ["rmbranch"]
6473
def run(self, location=None):
6474
if location is None:
6476
cdir = controldir.ControlDir.open_containing(location)[0]
6477
cdir.destroy_branch()
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)
6480
6495
class cmd_shelve(Command):
6710
6725
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6711
6726
('cmd_conflicts', [], 'bzrlib.conflicts'),
6712
6727
('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6713
('cmd_verify_signatures', [],
6714
'bzrlib.commit_signature_commands'),
6728
('cmd_verify_signatures', [], 'bzrlib.commit_signature_commands'),
6715
6729
('cmd_test_script', [], 'bzrlib.cmd_test_script'),
6717
6731
builtin_command_registry.register_lazy(name, aliases, module_name)