81
81
def tree_files_for_add(file_list):
82
"""Add handles files a bit differently so it a custom implementation."""
83
Return a tree and list of absolute paths from a file list.
85
Similar to tree_files, but add handles files a bit differently, so it a
86
custom implementation. In particular, MutableTreeTree.smart_add expects
87
absolute paths, which it immediately converts to relative paths.
89
# FIXME Would be nice to just return the relative paths like
90
# internal_tree_files does, but there are a large number of unit tests
91
# that assume the current interface to mutabletree.smart_add
84
tree = WorkingTree.open_containing(file_list[0])[0]
93
tree, relpath = WorkingTree.open_containing(file_list[0])
85
94
if tree.supports_views():
86
95
view_files = tree.views.lookup_view()
88
97
for filename in file_list:
89
98
if not osutils.is_inside_any(view_files, filename):
90
99
raise errors.FileOutsideView(filename, view_files)
100
file_list = file_list[:]
101
file_list[0] = tree.abspath(relpath)
92
103
tree = WorkingTree.open_containing(u'.')[0]
93
104
if tree.supports_views():
926
946
if branch_to.get_parent() is None or remember:
927
947
branch_to.set_parent(branch_from.base)
929
if revision is not None:
930
revision_id = revision.as_revision_id(branch_from)
932
branch_to.lock_write()
949
if branch_from is not branch_to:
950
branch_from.lock_read()
934
if tree_to is not None:
935
view_info = _get_view_info_for_change_reporter(tree_to)
936
change_reporter = delta._ChangeReporter(
937
unversioned_filter=tree_to.is_ignored, view_info=view_info)
938
result = tree_to.pull(branch_from, overwrite, revision_id,
940
possible_transports=possible_transports)
942
result = branch_to.pull(branch_from, overwrite, revision_id)
944
result.report(self.outf)
945
if verbose and result.old_revid != result.new_revid:
946
log.show_branch_change(branch_to, self.outf, result.old_revno,
952
if revision is not None:
953
revision_id = revision.as_revision_id(branch_from)
955
branch_to.lock_write()
957
if tree_to is not None:
958
view_info = _get_view_info_for_change_reporter(tree_to)
959
change_reporter = delta._ChangeReporter(
960
unversioned_filter=tree_to.is_ignored,
962
result = tree_to.pull(
963
branch_from, overwrite, revision_id, change_reporter,
964
possible_transports=possible_transports, local=local)
966
result = branch_to.pull(
967
branch_from, overwrite, revision_id, local=local)
969
result.report(self.outf)
970
if verbose and result.old_revid != result.new_revid:
971
log.show_branch_change(
972
branch_to, self.outf, result.old_revno,
977
if branch_from is not branch_to:
952
981
class cmd_push(Command):
2706
2739
class cmd_commit(Command):
2707
2740
"""Commit changes into a new revision.
2709
If no arguments are given, the entire tree is committed.
2711
If selected files are specified, only changes to those files are
2712
committed. If a directory is specified then the directory and everything
2713
within it is committed.
2715
When excludes are given, they take precedence over selected files.
2716
For example, too commit only changes within foo, but not changes within
2719
bzr commit foo -x foo/bar
2721
If author of the change is not the same person as the committer, you can
2722
specify the author's name using the --author option. The name should be
2723
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2724
If there is more than one author of the change you can specify the option
2725
multiple times, once for each author.
2727
A selected-file commit may fail in some cases where the committed
2728
tree would be invalid. Consider::
2733
bzr commit foo -m "committing foo"
2734
bzr mv foo/bar foo/baz
2737
bzr commit foo/bar -m "committing bar but not baz"
2739
In the example above, the last commit will fail by design. This gives
2740
the user the opportunity to decide whether they want to commit the
2741
rename at the same time, separately first, or not at all. (As a general
2742
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2744
Note: A selected-file commit after a merge is not yet supported.
2742
An explanatory message needs to be given for each commit. This is
2743
often done by using the --message option (getting the message from the
2744
command line) or by using the --file option (getting the message from
2745
a file). If neither of these options is given, an editor is opened for
2746
the user to enter the message. To see the changed files in the
2747
boilerplate text loaded into the editor, use the --show-diff option.
2749
By default, the entire tree is committed and the person doing the
2750
commit is assumed to be the author. These defaults can be overridden
2755
If selected files are specified, only changes to those files are
2756
committed. If a directory is specified then the directory and
2757
everything within it is committed.
2759
When excludes are given, they take precedence over selected files.
2760
For example, to commit only changes within foo, but not changes
2763
bzr commit foo -x foo/bar
2765
A selective commit after a merge is not yet supported.
2769
If the author of the change is not the same person as the committer,
2770
you can specify the author's name using the --author option. The
2771
name should be in the same format as a committer-id, e.g.
2772
"John Doe <jdoe@example.com>". If there is more than one author of
2773
the change you can specify the option multiple times, once for each
2778
A common mistake is to forget to add a new file or directory before
2779
running the commit command. The --strict option checks for unknown
2780
files and aborts the commit if any are found. More advanced pre-commit
2781
checks can be implemented by defining hooks. See ``bzr help hooks``
2786
If you accidentially commit the wrong changes or make a spelling
2787
mistake in the commit message say, you can use the uncommit command
2788
to undo it. See ``bzr help uncommit`` for details.
2790
Hooks can also be configured to run after a commit. This allows you
2791
to trigger updates to external systems like bug trackers. The --fixes
2792
option can be used to record the association between a revision and
2793
one or more bugs. See ``bzr help bugs`` for details.
2795
A selective commit may fail in some cases where the committed
2796
tree would be invalid. Consider::
2801
bzr commit foo -m "committing foo"
2802
bzr mv foo/bar foo/baz
2805
bzr commit foo/bar -m "committing bar but not baz"
2807
In the example above, the last commit will fail by design. This gives
2808
the user the opportunity to decide whether they want to commit the
2809
rename at the same time, separately first, or not at all. (As a general
2810
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2746
2812
# TODO: Run hooks on tree to-be-committed, and after commit.
4505
def run_smart_server(self, smart_server):
4506
"""Run 'smart_server' forever, with no UI output at all."""
4507
# For the duration of this server, no UI output is permitted. note
4508
# that this may cause problems with blackbox tests. This should be
4509
# changed with care though, as we dont want to use bandwidth sending
4510
# progress over stderr to smart server clients!
4511
from bzrlib import lockdir
4512
old_factory = ui.ui_factory
4513
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4515
ui.ui_factory = ui.SilentUIFactory()
4516
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4517
smart_server.serve()
4519
ui.ui_factory = old_factory
4520
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4522
4575
def get_host_and_port(self, port):
4523
4576
"""Return the host and port to run the smart server on.
4525
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4526
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4578
If 'port' is None, None will be returned for the host and port.
4528
4580
If 'port' has a colon in it, the string before the colon will be
4529
4581
interpreted as the host.
4532
4584
:return: A tuple of (host, port), where 'host' is a host name or IP,
4533
4585
and port is an integer TCP/IP port.
4535
from bzrlib.smart import medium
4536
host = medium.BZR_DEFAULT_INTERFACE
4538
port = medium.BZR_DEFAULT_PORT
4588
if port is not None:
4540
4589
if ':' in port:
4541
4590
host, port = port.split(':')
4542
4591
port = int(port)
4543
4592
return host, port
4545
def get_smart_server(self, transport, inet, port):
4546
"""Construct a smart server.
4548
:param transport: The base transport from which branches will be
4550
:param inet: If True, serve over stdin and stdout. Used for running
4552
:param port: The port to listen on. By default, it's `
4553
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4555
:return: A smart server.
4557
from bzrlib.smart import medium, server
4559
smart_server = medium.SmartServerPipeStreamMedium(
4560
sys.stdin, sys.stdout, transport)
4562
host, port = self.get_host_and_port(port)
4563
smart_server = server.SmartTCPServer(
4564
transport, host=host, port=port)
4565
note('listening on port: %s' % smart_server.port)
4568
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4569
from bzrlib.transport import get_transport
4570
from bzrlib.transport.chroot import ChrootServer
4594
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4596
from bzrlib.transport import get_transport, transport_server_registry
4571
4597
if directory is None:
4572
4598
directory = os.getcwd()
4599
if protocol is None:
4600
protocol = transport_server_registry.get()
4601
host, port = self.get_host_and_port(port)
4573
4602
url = urlutils.local_path_to_url(directory)
4574
4603
if not allow_writes:
4575
4604
url = 'readonly+' + url
4576
chroot_server = ChrootServer(get_transport(url))
4577
chroot_server.setUp()
4578
t = get_transport(chroot_server.get_url())
4579
smart_server = self.get_smart_server(t, inet, port)
4580
self.run_smart_server(smart_server)
4605
transport = get_transport(url)
4606
protocol(transport, host, port, inet)
4583
4609
class cmd_join(Command):
4831
4857
Option('body', help='Body for the email.', type=unicode),
4832
RegistryOption.from_kwargs('format',
4833
'Use the specified output format.',
4834
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4835
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4858
RegistryOption('format',
4859
help='Use the specified output format.',
4860
lazy_registry=('bzrlib.send', 'format_registry'))
4838
4863
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4839
4864
no_patch=False, revision=None, remember=False, output=None,
4840
format='4', mail_to=None, message=None, body=None, **kwargs):
4841
return self._run(submit_branch, revision, public_branch, remember,
4865
format=None, mail_to=None, message=None, body=None, **kwargs):
4866
from bzrlib.send import send
4867
return send(submit_branch, revision, public_branch, remember,
4842
4868
format, no_bundle, no_patch, output,
4843
kwargs.get('from', '.'), mail_to, message, body)
4845
def _run(self, submit_branch, revision, public_branch, remember, format,
4846
no_bundle, no_patch, output, from_, mail_to, message, body):
4847
from bzrlib.revision import NULL_REVISION
4848
branch = Branch.open_containing(from_)[0]
4850
outfile = cStringIO.StringIO()
4854
outfile = open(output, 'wb')
4855
# we may need to write data into branch's repository to calculate
4860
config = branch.get_config()
4862
mail_to = config.get_user_option('submit_to')
4863
mail_client = config.get_mail_client()
4864
if (not getattr(mail_client, 'supports_body', False)
4865
and body is not None):
4866
raise errors.BzrCommandError(
4867
'Mail client "%s" does not support specifying body' %
4868
mail_client.__class__.__name__)
4869
if remember and submit_branch is None:
4870
raise errors.BzrCommandError(
4871
'--remember requires a branch to be specified.')
4872
stored_submit_branch = branch.get_submit_branch()
4873
remembered_submit_branch = None
4874
if submit_branch is None:
4875
submit_branch = stored_submit_branch
4876
remembered_submit_branch = "submit"
4878
if stored_submit_branch is None or remember:
4879
branch.set_submit_branch(submit_branch)
4880
if submit_branch is None:
4881
submit_branch = branch.get_parent()
4882
remembered_submit_branch = "parent"
4883
if submit_branch is None:
4884
raise errors.BzrCommandError('No submit branch known or'
4886
if remembered_submit_branch is not None:
4887
note('Using saved %s location "%s" to determine what '
4888
'changes to submit.', remembered_submit_branch,
4892
submit_config = Branch.open(submit_branch).get_config()
4893
mail_to = submit_config.get_user_option("child_submit_to")
4895
stored_public_branch = branch.get_public_branch()
4896
if public_branch is None:
4897
public_branch = stored_public_branch
4898
elif stored_public_branch is None or remember:
4899
branch.set_public_branch(public_branch)
4900
if no_bundle and public_branch is None:
4901
raise errors.BzrCommandError('No public branch specified or'
4903
base_revision_id = None
4905
if revision is not None:
4906
if len(revision) > 2:
4907
raise errors.BzrCommandError('bzr send takes '
4908
'at most two one revision identifiers')
4909
revision_id = revision[-1].as_revision_id(branch)
4910
if len(revision) == 2:
4911
base_revision_id = revision[0].as_revision_id(branch)
4912
if revision_id is None:
4913
revision_id = branch.last_revision()
4914
if revision_id == NULL_REVISION:
4915
raise errors.BzrCommandError('No revisions to submit.')
4917
directive = merge_directive.MergeDirective2.from_objects(
4918
branch.repository, revision_id, time.time(),
4919
osutils.local_time_offset(), submit_branch,
4920
public_branch=public_branch, include_patch=not no_patch,
4921
include_bundle=not no_bundle, message=message,
4922
base_revision_id=base_revision_id)
4923
elif format == '0.9':
4926
patch_type = 'bundle'
4928
raise errors.BzrCommandError('Format 0.9 does not'
4929
' permit bundle with no patch')
4935
directive = merge_directive.MergeDirective.from_objects(
4936
branch.repository, revision_id, time.time(),
4937
osutils.local_time_offset(), submit_branch,
4938
public_branch=public_branch, patch_type=patch_type,
4941
outfile.writelines(directive.to_lines())
4943
subject = '[MERGE] '
4944
if message is not None:
4947
revision = branch.repository.get_revision(revision_id)
4948
subject += revision.get_summary()
4949
basename = directive.get_disk_name(branch)
4950
mail_client.compose_merge_request(mail_to, subject,
4869
kwargs.get('from', '.'), mail_to, message, body,
4959
4873
class cmd_bundle_revisions(cmd_send):
4961
4874
"""Create a merge-directive for submitting changes.
4963
4876
A merge directive provides many things needed for requesting merges:
5130
5044
graph = branch.repository.get_graph()
5131
5045
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5132
5046
revid1, revid2 = rev1.rev_id, rev2.rev_id
5133
5047
# only show revisions between revid1 and revid2 (inclusive)
5134
5048
tags = [(tag, revid) for tag, revid in tags if
5135
5049
graph.is_between(revid, revid1, revid2)]
5140
elif sort == 'time':
5142
for tag, revid in tags:
5144
revobj = branch.repository.get_revision(revid)
5145
except errors.NoSuchRevision:
5146
timestamp = sys.maxint # place them at the end
5148
timestamp = revobj.timestamp
5149
timestamps[revid] = timestamp
5150
tags.sort(key=lambda x: timestamps[x[1]])
5152
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5153
revno_map = branch.get_revision_id_to_revno_map()
5154
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
5155
for tag, revid in tags ]
5052
elif sort == 'time':
5054
for tag, revid in tags:
5056
revobj = branch.repository.get_revision(revid)
5057
except errors.NoSuchRevision:
5058
timestamp = sys.maxint # place them at the end
5060
timestamp = revobj.timestamp
5061
timestamps[revid] = timestamp
5062
tags.sort(key=lambda x: timestamps[x[1]])
5064
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5065
for index, (tag, revid) in enumerate(tags):
5067
revno = branch.revision_id_to_dotted_revno(revid)
5068
if isinstance(revno, tuple):
5069
revno = '.'.join(map(str, revno))
5070
except errors.NoSuchRevision:
5071
# Bad tag data/merges can lead to tagged revisions
5072
# which are not in this branch. Fail gracefully ...
5074
tags[index] = (tag, revno)
5156
5077
for tag, revspec in tags:
5157
5078
self.outf.write('%-20s %s\n' % (tag, revspec))
5257
5178
from bzrlib import switch
5258
5179
tree_location = '.'
5259
5180
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5260
branch = control_dir.open_branch()
5182
branch = control_dir.open_branch()
5183
had_explicit_nick = branch.get_config().has_explicit_nickname()
5184
except errors.NotBranchError:
5185
had_explicit_nick = False
5262
5187
to_branch = Branch.open(to_location)
5263
5188
except errors.NotBranchError:
5264
this_branch = control_dir.open_branch()
5265
# This may be a heavy checkout, where we want the master branch
5266
this_url = this_branch.get_bound_location()
5267
# If not, use a local sibling
5268
if this_url is None:
5269
this_url = this_branch.base
5189
this_url = self._get_branch_location(control_dir)
5270
5190
to_branch = Branch.open(
5271
5191
urlutils.join(this_url, '..', to_location))
5272
5192
switch.switch(control_dir, to_branch, force)
5273
if branch.get_config().has_explicit_nickname():
5193
if had_explicit_nick:
5274
5194
branch = control_dir.open_branch() #get the new branch!
5275
5195
branch.nick = to_branch.nick
5276
5196
note('Switched to branch: %s',
5277
5197
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5199
def _get_branch_location(self, control_dir):
5200
"""Return location of branch for this control dir."""
5202
this_branch = control_dir.open_branch()
5203
# This may be a heavy checkout, where we want the master branch
5204
master_location = this_branch.get_bound_location()
5205
if master_location is not None:
5206
return master_location
5207
# If not, use a local sibling
5208
return this_branch.base
5209
except errors.NotBranchError:
5210
format = control_dir.find_branch_format()
5211
if getattr(format, 'get_reference', None) is not None:
5212
return format.get_reference(control_dir)
5214
return control_dir.root_transport.base
5280
5217
class cmd_view(Command):
5281
5218
"""Manage filtered views.
5583
5520
dry_run=dry_run, no_prompt=force)
5586
def _create_prefix(cur_transport):
5587
needed = [cur_transport]
5588
# Recurse upwards until we can create a directory successfully
5590
new_transport = cur_transport.clone('..')
5591
if new_transport.base == cur_transport.base:
5592
raise errors.BzrCommandError(
5593
"Failed to create path prefix for %s."
5594
% cur_transport.base)
5596
new_transport.mkdir('.')
5597
except errors.NoSuchFile:
5598
needed.append(new_transport)
5599
cur_transport = new_transport
5523
class cmd_reference(Command):
5524
"""list, view and set branch locations for nested trees.
5526
If no arguments are provided, lists the branch locations for nested trees.
5527
If one argument is provided, display the branch location for that tree.
5528
If two arguments are provided, set the branch location for that tree.
5533
takes_args = ['path?', 'location?']
5535
def run(self, path=None, location=None):
5537
if path is not None:
5539
tree, branch, relpath =(
5540
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5541
if path is not None:
5544
tree = branch.basis_tree()
5546
info = branch._get_all_reference_info().iteritems()
5547
self._display_reference_info(tree, branch, info)
5602
# Now we only need to create child directories
5604
cur_transport = needed.pop()
5605
cur_transport.ensure_base()
5549
file_id = tree.path2id(path)
5551
raise errors.NotVersionedError(path)
5552
if location is None:
5553
info = [(file_id, branch.get_reference_info(file_id))]
5554
self._display_reference_info(tree, branch, info)
5556
branch.set_reference_info(file_id, path, location)
5558
def _display_reference_info(self, tree, branch, info):
5560
for file_id, (path, location) in info:
5562
path = tree.id2path(file_id)
5563
except errors.NoSuchId:
5565
ref_list.append((path, location))
5566
for path, location in sorted(ref_list):
5567
self.outf.write('%s %s\n' % (path, location))
5608
5570
# these get imported and then picked up by the scan for cmd_*