~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Andrew Bennetts
  • Date: 2009-06-09 03:14:05 UTC
  • mfrom: (4416 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4420.
  • Revision ID: andrew.bennetts@canonical.com-20090609031405-wak9yogzzpx9o172
Merge bzr.dev, resolving NEWS conflict.

Show diffs side-by-side

added added

removed removed

Lines of Context:
610
610
                for glob, paths in ignored.items():
611
611
                    match_len += len(paths)
612
612
                self.outf.write("ignored %d file(s).\n" % match_len)
613
 
            self.outf.write("If you wish to add some of these files,"
614
 
                            " please add them by name.\n")
 
613
            self.outf.write("If you wish to add ignored files, "
 
614
                            "please add them explicitly by name. "
 
615
                            "(\"bzr ignored\" gives a list)\n")
615
616
 
616
617
 
617
618
class cmd_mkdir(Command):
2408
2409
                            continue
2409
2410
                    kindch = entry.kind_character()
2410
2411
                    outstring = fp + kindch
 
2412
                    ui.ui_factory.clear_term()
2411
2413
                    if verbose:
2412
2414
                        outstring = '%-8s %s' % (fc, outstring)
2413
2415
                        if show_ids and fid is not None:
4540
4542
    takes_options = [
4541
4543
        Option('inet',
4542
4544
               help='Serve on stdin/out for use from inetd or sshd.'),
 
4545
        RegistryOption('protocol', 
 
4546
               help="Protocol to serve.", 
 
4547
               lazy_registry=('bzrlib.transport', 'transport_server_registry'),
 
4548
               value_switches=True),
4543
4549
        Option('port',
4544
4550
               help='Listen for connections on nominated port of the form '
4545
4551
                    '[hostname:]portnumber.  Passing 0 as the port number will '
4546
 
                    'result in a dynamically allocated port.  The default port is '
4547
 
                    '4155.',
 
4552
                    'result in a dynamically allocated port.  The default port '
 
4553
                    'depends on the protocol.',
4548
4554
               type=str),
4549
4555
        Option('directory',
4550
4556
               help='Serve contents of this directory.',
4556
4562
                ),
4557
4563
        ]
4558
4564
 
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
4568
 
        try:
4569
 
            ui.ui_factory = ui.SilentUIFactory()
4570
 
            lockdir._DEFAULT_TIMEOUT_SECONDS = 0
4571
 
            smart_server.serve()
4572
 
        finally:
4573
 
            ui.ui_factory = old_factory
4574
 
            lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4575
 
 
4576
4565
    def get_host_and_port(self, port):
4577
4566
        """Return the host and port to run the smart server on.
4578
4567
 
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.
4581
4569
 
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.
4588
4576
        """
4589
 
        from bzrlib.smart import medium
4590
 
        host = medium.BZR_DEFAULT_INTERFACE
4591
 
        if port is None:
4592
 
            port = medium.BZR_DEFAULT_PORT
4593
 
        else:
 
4577
        host = None
 
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
4598
4583
 
4599
 
    def get_smart_server(self, transport, inet, port):
4600
 
        """Construct a smart server.
4601
 
 
4602
 
        :param transport: The base transport from which branches will be
4603
 
            served.
4604
 
        :param inet: If True, serve over stdin and stdout. Used for running
4605
 
            from inet.
4606
 
        :param port: The port to listen on. By default, it's `
4607
 
            medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4608
 
            information.
4609
 
        :return: A smart server.
4610
 
        """
4611
 
        from bzrlib.smart import medium, server
4612
 
        if inet:
4613
 
            smart_server = medium.SmartServerPipeStreamMedium(
4614
 
                sys.stdin, sys.stdout, transport)
4615
 
        else:
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)
4620
 
        return smart_server
4621
 
 
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,
 
4585
            protocol=None):
 
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)
4635
4597
 
4636
4598
 
4637
4599
class cmd_join(Command):
4883
4845
        'revision',
4884
4846
        'message',
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'))
4890
4851
        ]
4891
4852
 
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
4855
            format=None, mail_to=None, message=None, body=None, **kwargs):
4895
 
        return self._run(submit_branch, revision, public_branch, remember,
 
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)
4898
 
 
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
4904
 
        # the data to send.
4905
 
        branch.lock_write()
4906
 
        try:
4907
 
            if output is None:
4908
 
                config = branch.get_config()
4909
 
                if mail_to is None:
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"
4925
 
            else:
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'
4933
 
                                             ' specified')
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,
4937
 
                        submit_branch)
4938
 
 
4939
 
            if mail_to is None or format is None:
4940
 
                submit_config = Branch.open(submit_branch).get_config()
4941
 
                if mail_to is None:
4942
 
                    mail_to = submit_config.get_user_option("child_submit_to")
4943
 
                if format is None:
4944
 
                    format = submit_config.get_user_option("child_submit_format")
4945
 
 
4946
 
            stored_public_branch = branch.get_public_branch()
4947
 
            if public_branch is None:
4948
 
                public_branch = stored_public_branch
4949
 
            elif stored_public_branch is None or remember:
4950
 
                branch.set_public_branch(public_branch)
4951
 
            if no_bundle and public_branch is None:
4952
 
                raise errors.BzrCommandError('No public branch specified or'
4953
 
                                             ' known')
4954
 
            base_revision_id = None
4955
 
            revision_id = None
4956
 
            if revision is not None:
4957
 
                if len(revision) > 2:
4958
 
                    raise errors.BzrCommandError('bzr send takes '
4959
 
                        'at most two one revision identifiers')
4960
 
                revision_id = revision[-1].as_revision_id(branch)
4961
 
                if len(revision) == 2:
4962
 
                    base_revision_id = revision[0].as_revision_id(branch)
4963
 
            if revision_id is None:
4964
 
                revision_id = branch.last_revision()
4965
 
            if revision_id == NULL_REVISION:
4966
 
                raise errors.BzrCommandError('No revisions to submit.')
4967
 
            if format is None:
4968
 
                format = '4'
4969
 
            if format == '4':
4970
 
                directive = merge_directive.MergeDirective2.from_objects(
4971
 
                    branch.repository, revision_id, time.time(),
4972
 
                    osutils.local_time_offset(), submit_branch,
4973
 
                    public_branch=public_branch, include_patch=not no_patch,
4974
 
                    include_bundle=not no_bundle, message=message,
4975
 
                    base_revision_id=base_revision_id)
4976
 
            elif format == '0.9':
4977
 
                if not no_bundle:
4978
 
                    if not no_patch:
4979
 
                        patch_type = 'bundle'
4980
 
                    else:
4981
 
                        raise errors.BzrCommandError('Format 0.9 does not'
4982
 
                            ' permit bundle with no patch')
4983
 
                else:
4984
 
                    if not no_patch:
4985
 
                        patch_type = 'diff'
4986
 
                    else:
4987
 
                        patch_type = None
4988
 
                directive = merge_directive.MergeDirective.from_objects(
4989
 
                    branch.repository, revision_id, time.time(),
4990
 
                    osutils.local_time_offset(), submit_branch,
4991
 
                    public_branch=public_branch, patch_type=patch_type,
4992
 
                    message=message)
4993
 
            else:
4994
 
                raise errors.BzrCommandError("No such send format '%s'." % 
4995
 
                                             format)
4996
 
 
4997
 
            if output is None:
4998
 
                directive.compose_merge_request(mail_client, mail_to, body,
4999
 
                                                branch, tree)
5000
 
            else:
5001
 
                if output == '-':
5002
 
                    outfile = self.outf
5003
 
                else:
5004
 
                    outfile = open(output, 'wb')
5005
 
                try:
5006
 
                    outfile.writelines(directive.to_lines())
5007
 
                finally:
5008
 
                    if outfile is not self.outf:
5009
 
                        outfile.close()
5010
 
        finally:
5011
 
            branch.unlock()
 
4859
                         kwargs.get('from', '.'), mail_to, message, body,
 
4860
                         self.outf)
5012
4861
 
5013
4862
 
5014
4863
class cmd_bundle_revisions(cmd_send):
5015
 
 
5016
4864
    """Create a merge-directive for submitting changes.
5017
4865
 
5018
4866
    A merge directive provides many things needed for requesting merges:
5060
4908
        Option('output', short_name='o', help='Write directive to this file.',
5061
4909
               type=unicode),
5062
4910
        'revision',
5063
 
        RegistryOption.from_kwargs('format',
5064
 
        'Use the specified output format.',
5065
 
        **{'4': 'Bundle format 4, Merge Directive 2 (default)',
5066
 
           '0.9': 'Bundle format 0.9, Merge Directive 1',})
 
4911
        RegistryOption('format',
 
4912
                       help='Use the specified output format.',
 
4913
                       lazy_registry=('bzrlib.send', 'format_registry')),
5067
4914
        ]
5068
4915
    aliases = ['bundle']
5069
4916
 
5076
4923
            format=None, **kwargs):
5077
4924
        if output is None:
5078
4925
            output = '-'
5079
 
        return self._run(submit_branch, revision, public_branch, remember,
 
4926
        from bzrlib.send import send
 
4927
        return send(submit_branch, revision, public_branch, remember,
5080
4928
                         format, no_bundle, no_patch, output,
5081
 
                         kwargs.get('from', '.'), None, None, None)
 
4929
                         kwargs.get('from', '.'), None, None, None,
 
4930
                         self.outf)
5082
4931
 
5083
4932
 
5084
4933
class cmd_tag(Command):
5179
5028
        if not tags:
5180
5029
            return
5181
5030
 
5182
 
        if revision:
5183
 
            branch.lock_read()
5184
 
            try:
 
5031
        branch.lock_read()
 
5032
        try:
 
5033
            if revision:
5185
5034
                graph = branch.repository.get_graph()
5186
5035
                rev1, rev2 = _get_revision_range(revision, branch, self.name())
5187
5036
                revid1, revid2 = rev1.rev_id, rev2.rev_id
5188
5037
                # only show revisions between revid1 and revid2 (inclusive)
5189
5038
                tags = [(tag, revid) for tag, revid in tags if
5190
5039
                    graph.is_between(revid, revid1, revid2)]
5191
 
            finally:
5192
 
                branch.unlock()
5193
 
        if sort == 'alpha':
5194
 
            tags.sort()
5195
 
        elif sort == 'time':
5196
 
            timestamps = {}
5197
 
            for tag, revid in tags:
5198
 
                try:
5199
 
                    revobj = branch.repository.get_revision(revid)
5200
 
                except errors.NoSuchRevision:
5201
 
                    timestamp = sys.maxint # place them at the end
5202
 
                else:
5203
 
                    timestamp = revobj.timestamp
5204
 
                timestamps[revid] = timestamp
5205
 
            tags.sort(key=lambda x: timestamps[x[1]])
5206
 
        if not show_ids:
5207
 
            # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5208
 
            revno_map = branch.get_revision_id_to_revno_map()
5209
 
            tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
5210
 
                        for tag, revid in tags ]
 
5040
            if sort == 'alpha':
 
5041
                tags.sort()
 
5042
            elif sort == 'time':
 
5043
                timestamps = {}
 
5044
                for tag, revid in tags:
 
5045
                    try:
 
5046
                        revobj = branch.repository.get_revision(revid)
 
5047
                    except errors.NoSuchRevision:
 
5048
                        timestamp = sys.maxint # place them at the end
 
5049
                    else:
 
5050
                        timestamp = revobj.timestamp
 
5051
                    timestamps[revid] = timestamp
 
5052
                tags.sort(key=lambda x: timestamps[x[1]])
 
5053
            if not show_ids:
 
5054
                # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
 
5055
                for index, (tag, revid) in enumerate(tags):
 
5056
                    try:
 
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 ...
 
5063
                        revno = '?'
 
5064
                    tags[index] = (tag, revno)
 
5065
        finally:
 
5066
            branch.unlock()
5211
5067
        for tag, revspec in tags:
5212
5068
            self.outf.write('%-20s %s\n' % (tag, revspec))
5213
5069