4559
def run_smart_server(self, smart_server):
4560
"""Run 'smart_server' forever, with no UI output at all."""
4561
# For the duration of this server, no UI output is permitted. note
4562
# that this may cause problems with blackbox tests. This should be
4563
# changed with care though, as we dont want to use bandwidth sending
4564
# progress over stderr to smart server clients!
4565
from bzrlib import lockdir
4566
old_factory = ui.ui_factory
4567
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
4569
ui.ui_factory = ui.SilentUIFactory()
4570
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4571
smart_server.serve()
4573
ui.ui_factory = old_factory
4574
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4576
4565
def get_host_and_port(self, port):
4577
4566
"""Return the host and port to run the smart server on.
4579
If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4580
and port (`medium.BZR_DEFAULT_PORT`) will be used.
4568
If 'port' is None, None will be returned for the host and port.
4582
4570
If 'port' has a colon in it, the string before the colon will be
4583
4571
interpreted as the host.
4586
4574
:return: A tuple of (host, port), where 'host' is a host name or IP,
4587
4575
and port is an integer TCP/IP port.
4589
from bzrlib.smart import medium
4590
host = medium.BZR_DEFAULT_INTERFACE
4592
port = medium.BZR_DEFAULT_PORT
4578
if port is not None:
4594
4579
if ':' in port:
4595
4580
host, port = port.split(':')
4596
4581
port = int(port)
4597
4582
return host, port
4599
def get_smart_server(self, transport, inet, port):
4600
"""Construct a smart server.
4602
:param transport: The base transport from which branches will be
4604
:param inet: If True, serve over stdin and stdout. Used for running
4606
:param port: The port to listen on. By default, it's `
4607
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4609
:return: A smart server.
4611
from bzrlib.smart import medium, server
4613
smart_server = medium.SmartServerPipeStreamMedium(
4614
sys.stdin, sys.stdout, transport)
4616
host, port = self.get_host_and_port(port)
4617
smart_server = server.SmartTCPServer(
4618
transport, host=host, port=port)
4619
note('listening on port: %s' % smart_server.port)
4622
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4623
from bzrlib.transport import get_transport
4624
from bzrlib.transport.chroot import ChrootServer
4584
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4586
from bzrlib.transport import get_transport, transport_server_registry
4625
4587
if directory is None:
4626
4588
directory = os.getcwd()
4589
if protocol is None:
4590
protocol = transport_server_registry.get()
4591
host, port = self.get_host_and_port(port)
4627
4592
url = urlutils.local_path_to_url(directory)
4628
4593
if not allow_writes:
4629
4594
url = 'readonly+' + url
4630
chroot_server = ChrootServer(get_transport(url))
4631
chroot_server.setUp()
4632
t = get_transport(chroot_server.get_url())
4633
smart_server = self.get_smart_server(t, inet, port)
4634
self.run_smart_server(smart_server)
4595
transport = get_transport(url)
4596
protocol(transport, host, port, inet)
4637
4599
class cmd_join(Command):
4885
4847
Option('body', help='Body for the email.', type=unicode),
4886
RegistryOption.from_kwargs('format',
4887
'Use the specified output format.',
4888
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4889
'0.9': 'Bundle format 0.9, Merge Directive 1',})
4848
RegistryOption('format',
4849
help='Use the specified output format.',
4850
lazy_registry=('bzrlib.send', 'format_registry'))
4892
4853
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4893
4854
no_patch=False, revision=None, remember=False, output=None,
4894
format='4', mail_to=None, message=None, body=None, **kwargs):
4895
return self._run(submit_branch, revision, public_branch, remember,
4855
format=None, mail_to=None, message=None, body=None, **kwargs):
4856
from bzrlib.send import send
4857
return send(submit_branch, revision, public_branch, remember,
4896
4858
format, no_bundle, no_patch, output,
4897
kwargs.get('from', '.'), mail_to, message, body)
4899
def _run(self, submit_branch, revision, public_branch, remember, format,
4900
no_bundle, no_patch, output, from_, mail_to, message, body):
4901
from bzrlib.revision import NULL_REVISION
4902
tree, branch = bzrdir.BzrDir.open_containing_tree_or_branch(from_)[:2]
4903
# we may need to write data into branch's repository to calculate
4908
config = branch.get_config()
4910
mail_to = config.get_user_option('submit_to')
4911
mail_client = config.get_mail_client()
4912
if (not getattr(mail_client, 'supports_body', False)
4913
and body is not None):
4914
raise errors.BzrCommandError(
4915
'Mail client "%s" does not support specifying body' %
4916
mail_client.__class__.__name__)
4917
if remember and submit_branch is None:
4918
raise errors.BzrCommandError(
4919
'--remember requires a branch to be specified.')
4920
stored_submit_branch = branch.get_submit_branch()
4921
remembered_submit_branch = None
4922
if submit_branch is None:
4923
submit_branch = stored_submit_branch
4924
remembered_submit_branch = "submit"
4926
if stored_submit_branch is None or remember:
4927
branch.set_submit_branch(submit_branch)
4928
if submit_branch is None:
4929
submit_branch = branch.get_parent()
4930
remembered_submit_branch = "parent"
4931
if submit_branch is None:
4932
raise errors.BzrCommandError('No submit branch known or'
4934
if remembered_submit_branch is not None:
4935
note('Using saved %s location "%s" to determine what '
4936
'changes to submit.', remembered_submit_branch,
4940
submit_config = Branch.open(submit_branch).get_config()
4941
mail_to = submit_config.get_user_option("child_submit_to")
4943
stored_public_branch = branch.get_public_branch()
4944
if public_branch is None:
4945
public_branch = stored_public_branch
4946
elif stored_public_branch is None or remember:
4947
branch.set_public_branch(public_branch)
4948
if no_bundle and public_branch is None:
4949
raise errors.BzrCommandError('No public branch specified or'
4951
base_revision_id = None
4953
if revision is not None:
4954
if len(revision) > 2:
4955
raise errors.BzrCommandError('bzr send takes '
4956
'at most two one revision identifiers')
4957
revision_id = revision[-1].as_revision_id(branch)
4958
if len(revision) == 2:
4959
base_revision_id = revision[0].as_revision_id(branch)
4960
if revision_id is None:
4961
revision_id = branch.last_revision()
4962
if revision_id == NULL_REVISION:
4963
raise errors.BzrCommandError('No revisions to submit.')
4965
directive = merge_directive.MergeDirective2.from_objects(
4966
branch.repository, revision_id, time.time(),
4967
osutils.local_time_offset(), submit_branch,
4968
public_branch=public_branch, include_patch=not no_patch,
4969
include_bundle=not no_bundle, message=message,
4970
base_revision_id=base_revision_id)
4971
elif format == '0.9':
4974
patch_type = 'bundle'
4976
raise errors.BzrCommandError('Format 0.9 does not'
4977
' permit bundle with no patch')
4983
directive = merge_directive.MergeDirective.from_objects(
4984
branch.repository, revision_id, time.time(),
4985
osutils.local_time_offset(), submit_branch,
4986
public_branch=public_branch, patch_type=patch_type,
4990
directive.compose_merge_request(mail_client, mail_to, body,
4996
outfile = open(output, 'wb')
4998
outfile.writelines(directive.to_lines())
5000
if outfile is not self.outf:
4859
kwargs.get('from', '.'), mail_to, message, body,
5006
4863
class cmd_bundle_revisions(cmd_send):
5008
4864
"""Create a merge-directive for submitting changes.
5010
4866
A merge directive provides many things needed for requesting merges:
5177
5034
graph = branch.repository.get_graph()
5178
5035
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5179
5036
revid1, revid2 = rev1.rev_id, rev2.rev_id
5180
5037
# only show revisions between revid1 and revid2 (inclusive)
5181
5038
tags = [(tag, revid) for tag, revid in tags if
5182
5039
graph.is_between(revid, revid1, revid2)]
5187
elif sort == 'time':
5189
for tag, revid in tags:
5191
revobj = branch.repository.get_revision(revid)
5192
except errors.NoSuchRevision:
5193
timestamp = sys.maxint # place them at the end
5195
timestamp = revobj.timestamp
5196
timestamps[revid] = timestamp
5197
tags.sort(key=lambda x: timestamps[x[1]])
5199
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5200
revno_map = branch.get_revision_id_to_revno_map()
5201
tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
5202
for tag, revid in tags ]
5042
elif sort == 'time':
5044
for tag, revid in tags:
5046
revobj = branch.repository.get_revision(revid)
5047
except errors.NoSuchRevision:
5048
timestamp = sys.maxint # place them at the end
5050
timestamp = revobj.timestamp
5051
timestamps[revid] = timestamp
5052
tags.sort(key=lambda x: timestamps[x[1]])
5054
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5055
for index, (tag, revid) in enumerate(tags):
5057
revno = branch.revision_id_to_dotted_revno(revid)
5058
if isinstance(revno, tuple):
5059
revno = '.'.join(map(str, revno))
5060
except errors.NoSuchRevision:
5061
# Bad tag data/merges can lead to tagged revisions
5062
# which are not in this branch. Fail gracefully ...
5064
tags[index] = (tag, revno)
5203
5067
for tag, revspec in tags:
5204
5068
self.outf.write('%-20s %s\n' % (tag, revspec))
5304
5168
from bzrlib import switch
5305
5169
tree_location = '.'
5306
5170
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5307
branch = control_dir.open_branch()
5172
branch = control_dir.open_branch()
5173
had_explicit_nick = branch.get_config().has_explicit_nickname()
5174
except errors.NotBranchError:
5175
had_explicit_nick = False
5309
5177
to_branch = Branch.open(to_location)
5310
5178
except errors.NotBranchError:
5311
this_branch = control_dir.open_branch()
5312
# This may be a heavy checkout, where we want the master branch
5313
this_url = this_branch.get_bound_location()
5314
# If not, use a local sibling
5315
if this_url is None:
5316
this_url = this_branch.base
5179
this_url = self._get_branch_location(control_dir)
5317
5180
to_branch = Branch.open(
5318
5181
urlutils.join(this_url, '..', to_location))
5319
5182
switch.switch(control_dir, to_branch, force)
5320
if branch.get_config().has_explicit_nickname():
5183
if had_explicit_nick:
5321
5184
branch = control_dir.open_branch() #get the new branch!
5322
5185
branch.nick = to_branch.nick
5323
5186
note('Switched to branch: %s',
5324
5187
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5189
def _get_branch_location(self, control_dir):
5190
"""Return location of branch for this control dir."""
5192
this_branch = control_dir.open_branch()
5193
# This may be a heavy checkout, where we want the master branch
5194
master_location = this_branch.get_bound_location()
5195
if master_location is not None:
5196
return master_location
5197
# If not, use a local sibling
5198
return this_branch.base
5199
except errors.NotBranchError:
5200
format = control_dir.find_branch_format()
5201
if getattr(format, 'get_reference', None) is not None:
5202
return format.get_reference(control_dir)
5204
return control_dir.root_transport.base
5327
5207
class cmd_view(Command):
5328
5208
"""Manage filtered views.