~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Vincent Ladeuil
  • Date: 2009-06-02 09:21:20 UTC
  • mfrom: (4396 +trunk)
  • mto: (4396.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4397.
  • Revision ID: v.ladeuil+lp@free.fr-20090602092120-xs1ikguqckiu820o
Merge bzr.dev

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):
4540
4541
    takes_options = [
4541
4542
        Option('inet',
4542
4543
               help='Serve on stdin/out for use from inetd or sshd.'),
 
4544
        RegistryOption('protocol', 
 
4545
               help="Protocol to serve.", 
 
4546
               lazy_registry=('bzrlib.transport', 'transport_server_registry'),
 
4547
               value_switches=True),
4543
4548
        Option('port',
4544
4549
               help='Listen for connections on nominated port of the form '
4545
4550
                    '[hostname:]portnumber.  Passing 0 as the port number will '
4546
 
                    'result in a dynamically allocated port.  The default port is '
4547
 
                    '4155.',
 
4551
                    'result in a dynamically allocated port.  The default port '
 
4552
                    'depends on the protocol.',
4548
4553
               type=str),
4549
4554
        Option('directory',
4550
4555
               help='Serve contents of this directory.',
4556
4561
                ),
4557
4562
        ]
4558
4563
 
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
4564
    def get_host_and_port(self, port):
4577
4565
        """Return the host and port to run the smart server on.
4578
4566
 
4579
 
        If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
4580
 
        and port (`medium.BZR_DEFAULT_PORT`) will be used.
 
4567
        If 'port' is None, None will be returned for the host and port.
4581
4568
 
4582
4569
        If 'port' has a colon in it, the string before the colon will be
4583
4570
        interpreted as the host.
4586
4573
        :return: A tuple of (host, port), where 'host' is a host name or IP,
4587
4574
            and port is an integer TCP/IP port.
4588
4575
        """
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:
 
4576
        host = None
 
4577
        if port is not None:
4594
4578
            if ':' in port:
4595
4579
                host, port = port.split(':')
4596
4580
            port = int(port)
4597
4581
        return host, port
4598
4582
 
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
 
4583
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
 
4584
            protocol=None):
 
4585
        from bzrlib.transport import get_transport, transport_server_registry
4625
4586
        if directory is None:
4626
4587
            directory = os.getcwd()
 
4588
        if protocol is None:
 
4589
            protocol = transport_server_registry.get()
 
4590
        host, port = self.get_host_and_port(port)
4627
4591
        url = urlutils.local_path_to_url(directory)
4628
4592
        if not allow_writes:
4629
4593
            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)
 
4594
        transport = get_transport(url)
 
4595
        protocol(transport, host, port, inet)
4635
4596
 
4636
4597
 
4637
4598
class cmd_join(Command):
4883
4844
        'revision',
4884
4845
        'message',
4885
4846
        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',})
 
4847
        RegistryOption('format',
 
4848
                       help='Use the specified output format.', 
 
4849
                       lazy_registry=('bzrlib.send', 'format_registry'))
4890
4850
        ]
4891
4851
 
4892
4852
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4893
4853
            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,
 
4854
            format=None, mail_to=None, message=None, body=None, **kwargs):
 
4855
        from bzrlib.send import send
 
4856
        return send(submit_branch, revision, public_branch, remember,
4896
4857
                         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:
4940
 
                submit_config = Branch.open(submit_branch).get_config()
4941
 
                mail_to = submit_config.get_user_option("child_submit_to")
4942
 
 
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'
4950
 
                                             ' known')
4951
 
            base_revision_id = None
4952
 
            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.')
4964
 
            if format == '4':
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':
4972
 
                if not no_bundle:
4973
 
                    if not no_patch:
4974
 
                        patch_type = 'bundle'
4975
 
                    else:
4976
 
                        raise errors.BzrCommandError('Format 0.9 does not'
4977
 
                            ' permit bundle with no patch')
4978
 
                else:
4979
 
                    if not no_patch:
4980
 
                        patch_type = 'diff'
4981
 
                    else:
4982
 
                        patch_type = None
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,
4987
 
                    message=message)
4988
 
 
4989
 
            if output is None:
4990
 
                directive.compose_merge_request(mail_client, mail_to, body,
4991
 
                                                branch, tree)
4992
 
            else:
4993
 
                if output == '-':
4994
 
                    outfile = self.outf
4995
 
                else:
4996
 
                    outfile = open(output, 'wb')
4997
 
                try:
4998
 
                    outfile.writelines(directive.to_lines())
4999
 
                finally:
5000
 
                    if outfile is not self.outf:
5001
 
                        outfile.close()
5002
 
        finally:
5003
 
            branch.unlock()
 
4858
                         kwargs.get('from', '.'), mail_to, message, body,
 
4859
                         self.outf)
5004
4860
 
5005
4861
 
5006
4862
class cmd_bundle_revisions(cmd_send):
5007
 
 
5008
4863
    """Create a merge-directive for submitting changes.
5009
4864
 
5010
4865
    A merge directive provides many things needed for requesting merges:
5052
4907
        Option('output', short_name='o', help='Write directive to this file.',
5053
4908
               type=unicode),
5054
4909
        'revision',
5055
 
        RegistryOption.from_kwargs('format',
5056
 
        'Use the specified output format.',
5057
 
        **{'4': 'Bundle format 4, Merge Directive 2 (default)',
5058
 
           '0.9': 'Bundle format 0.9, Merge Directive 1',})
 
4910
        RegistryOption('format',
 
4911
                       help='Use the specified output format.',
 
4912
                       lazy_registry=('bzrlib.send', 'format_registry')),
5059
4913
        ]
5060
4914
    aliases = ['bundle']
5061
4915
 
5065
4919
 
5066
4920
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5067
4921
            no_patch=False, revision=None, remember=False, output=None,
5068
 
            format='4', **kwargs):
 
4922
            format=None, **kwargs):
5069
4923
        if output is None:
5070
4924
            output = '-'
5071
 
        return self._run(submit_branch, revision, public_branch, remember,
 
4925
        from bzrlib.send import send
 
4926
        return send(submit_branch, revision, public_branch, remember,
5072
4927
                         format, no_bundle, no_patch, output,
5073
 
                         kwargs.get('from', '.'), None, None, None)
 
4928
                         kwargs.get('from', '.'), None, None, None,
 
4929
                         self.outf)
5074
4930
 
5075
4931
 
5076
4932
class cmd_tag(Command):
5171
5027
        if not tags:
5172
5028
            return
5173
5029
 
5174
 
        if revision:
5175
 
            branch.lock_read()
5176
 
            try:
 
5030
        branch.lock_read()
 
5031
        try:
 
5032
            if revision:
5177
5033
                graph = branch.repository.get_graph()
5178
5034
                rev1, rev2 = _get_revision_range(revision, branch, self.name())
5179
5035
                revid1, revid2 = rev1.rev_id, rev2.rev_id
5180
5036
                # only show revisions between revid1 and revid2 (inclusive)
5181
5037
                tags = [(tag, revid) for tag, revid in tags if
5182
5038
                    graph.is_between(revid, revid1, revid2)]
5183
 
            finally:
5184
 
                branch.unlock()
5185
 
        if sort == 'alpha':
5186
 
            tags.sort()
5187
 
        elif sort == 'time':
5188
 
            timestamps = {}
5189
 
            for tag, revid in tags:
5190
 
                try:
5191
 
                    revobj = branch.repository.get_revision(revid)
5192
 
                except errors.NoSuchRevision:
5193
 
                    timestamp = sys.maxint # place them at the end
5194
 
                else:
5195
 
                    timestamp = revobj.timestamp
5196
 
                timestamps[revid] = timestamp
5197
 
            tags.sort(key=lambda x: timestamps[x[1]])
5198
 
        if not show_ids:
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 ]
 
5039
            if sort == 'alpha':
 
5040
                tags.sort()
 
5041
            elif sort == 'time':
 
5042
                timestamps = {}
 
5043
                for tag, revid in tags:
 
5044
                    try:
 
5045
                        revobj = branch.repository.get_revision(revid)
 
5046
                    except errors.NoSuchRevision:
 
5047
                        timestamp = sys.maxint # place them at the end
 
5048
                    else:
 
5049
                        timestamp = revobj.timestamp
 
5050
                    timestamps[revid] = timestamp
 
5051
                tags.sort(key=lambda x: timestamps[x[1]])
 
5052
            if not show_ids:
 
5053
                # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
 
5054
                for index, (tag, revid) in enumerate(tags):
 
5055
                    try:
 
5056
                        revno = branch.revision_id_to_dotted_revno(revid)
 
5057
                        if isinstance(revno, tuple):
 
5058
                            revno = '.'.join(map(str, revno))
 
5059
                    except errors.NoSuchRevision:
 
5060
                        # Bad tag data/merges can lead to tagged revisions
 
5061
                        # which are not in this branch. Fail gracefully ...
 
5062
                        revno = '?'
 
5063
                    tags[index] = (tag, revno)
 
5064
        finally:
 
5065
            branch.unlock()
5203
5066
        for tag, revspec in tags:
5204
5067
            self.outf.write('%-20s %s\n' % (tag, revspec))
5205
5068