~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Robert J. Tanner
  • Date: 2009-06-10 03:56:49 UTC
  • mfrom: (4423 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4425.
  • Revision ID: tanner@real-time.com-20090610035649-7rfx4cls4550zc3c
Merge 1.15.1 back to trunk

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):
2089
2090
 
2090
2091
      When exploring non-mainline history on large projects with deep
2091
2092
      history, the performance of log can be greatly improved by installing
2092
 
      the revnocache plugin. This plugin buffers historical information
 
2093
      the historycache plugin. This plugin buffers historical information
2093
2094
      trading disk space for faster speed.
2094
2095
    """
2095
2096
    takes_args = ['file*']
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
 
            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)
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()
 
4859
                         kwargs.get('from', '.'), mail_to, message, body,
 
4860
                         self.outf)
5004
4861
 
5005
4862
 
5006
4863
class cmd_bundle_revisions(cmd_send):
5007
 
 
5008
4864
    """Create a merge-directive for submitting changes.
5009
4865
 
5010
4866
    A merge directive provides many things needed for requesting merges:
5052
4908
        Option('output', short_name='o', help='Write directive to this file.',
5053
4909
               type=unicode),
5054
4910
        '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',})
 
4911
        RegistryOption('format',
 
4912
                       help='Use the specified output format.',
 
4913
                       lazy_registry=('bzrlib.send', 'format_registry')),
5059
4914
        ]
5060
4915
    aliases = ['bundle']
5061
4916
 
5065
4920
 
5066
4921
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5067
4922
            no_patch=False, revision=None, remember=False, output=None,
5068
 
            format='4', **kwargs):
 
4923
            format=None, **kwargs):
5069
4924
        if output is None:
5070
4925
            output = '-'
5071
 
        return self._run(submit_branch, revision, public_branch, remember,
 
4926
        from bzrlib.send import send
 
4927
        return send(submit_branch, revision, public_branch, remember,
5072
4928
                         format, no_bundle, no_patch, output,
5073
 
                         kwargs.get('from', '.'), None, None, None)
 
4929
                         kwargs.get('from', '.'), None, None, None,
 
4930
                         self.outf)
5074
4931
 
5075
4932
 
5076
4933
class cmd_tag(Command):
5171
5028
        if not tags:
5172
5029
            return
5173
5030
 
5174
 
        if revision:
5175
 
            branch.lock_read()
5176
 
            try:
 
5031
        branch.lock_read()
 
5032
        try:
 
5033
            if revision:
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)]
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 ]
 
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()
5203
5067
        for tag, revspec in tags:
5204
5068
            self.outf.write('%-20s %s\n' % (tag, revspec))
5205
5069
 
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()
 
5171
        try:
 
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
5308
5176
        try:
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'))
5325
5188
 
 
5189
    def _get_branch_location(self, control_dir):
 
5190
        """Return location of branch for this control dir."""
 
5191
        try:
 
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)
 
5203
            else:
 
5204
                return control_dir.root_transport.base
 
5205
 
5326
5206
 
5327
5207
class cmd_view(Command):
5328
5208
    """Manage filtered views.