~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Sabin Iacob
  • Date: 2009-03-23 14:59:43 UTC
  • mto: (4189.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4193.
  • Revision ID: iacobs@m0n5t3r.info-20090323145943-3s3p1px5q1rkh2e5
update FSF mailing address

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
"""builtin bzr commands"""
18
18
 
19
19
import os
20
 
from StringIO import StringIO
21
20
 
22
21
from bzrlib.lazy_import import lazy_import
23
22
lazy_import(globals(), """
24
23
import codecs
 
24
import cStringIO
25
25
import sys
26
26
import time
27
27
 
29
29
from bzrlib import (
30
30
    bugtracker,
31
31
    bundle,
 
32
    btree_index,
32
33
    bzrdir,
33
34
    delta,
34
35
    config,
35
36
    errors,
36
37
    globbing,
37
 
    ignores,
 
38
    hooks,
38
39
    log,
39
40
    merge as _mod_merge,
40
41
    merge_directive,
46
47
    tree as _mod_tree,
47
48
    ui,
48
49
    urlutils,
 
50
    views,
49
51
    )
50
52
from bzrlib.branch import Branch
51
53
from bzrlib.conflicts import ConflictList
52
 
from bzrlib.revisionspec import RevisionSpec
 
54
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
53
55
from bzrlib.smtp_connection import SMTPConnection
54
56
from bzrlib.workingtree import WorkingTree
55
57
""")
56
58
 
57
59
from bzrlib.commands import Command, display_command
58
 
from bzrlib.option import ListOption, Option, RegistryOption, custom_help
59
 
from bzrlib.trace import mutter, note, warning, is_quiet, info
60
 
 
61
 
 
62
 
def tree_files(file_list, default_branch=u'.'):
 
60
from bzrlib.option import (
 
61
    ListOption,
 
62
    Option,
 
63
    RegistryOption,
 
64
    custom_help,
 
65
    _parse_revision_str,
 
66
    )
 
67
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
 
68
 
 
69
 
 
70
def tree_files(file_list, default_branch=u'.', canonicalize=True,
 
71
    apply_view=True):
63
72
    try:
64
 
        return internal_tree_files(file_list, default_branch)
 
73
        return internal_tree_files(file_list, default_branch, canonicalize,
 
74
            apply_view)
65
75
    except errors.FileInWrongBranch, e:
66
76
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
67
77
                                     (e.path, file_list[0]))
68
78
 
69
79
 
 
80
def tree_files_for_add(file_list):
 
81
    """Add handles files a bit differently so it a custom implementation."""
 
82
    if file_list:
 
83
        tree = WorkingTree.open_containing(file_list[0])[0]
 
84
        if tree.supports_views():
 
85
            view_files = tree.views.lookup_view()
 
86
            if view_files:
 
87
                for filename in file_list:
 
88
                    if not osutils.is_inside_any(view_files, filename):
 
89
                        raise errors.FileOutsideView(filename, view_files)
 
90
    else:
 
91
        tree = WorkingTree.open_containing(u'.')[0]
 
92
        if tree.supports_views():
 
93
            view_files = tree.views.lookup_view()
 
94
            if view_files:
 
95
                file_list = view_files
 
96
                view_str = views.view_display_str(view_files)
 
97
                note("ignoring files outside view: %s" % view_str)
 
98
    return tree, file_list
 
99
 
 
100
 
 
101
def _get_one_revision(command_name, revisions):
 
102
    if revisions is None:
 
103
        return None
 
104
    if len(revisions) != 1:
 
105
        raise errors.BzrCommandError(
 
106
            'bzr %s --revision takes exactly one revision identifier' % (
 
107
                command_name,))
 
108
    return revisions[0]
 
109
 
 
110
 
 
111
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
 
112
    if branch is None:
 
113
        branch = tree.branch
 
114
    if revisions is None:
 
115
        if tree is not None:
 
116
            rev_tree = tree.basis_tree()
 
117
        else:
 
118
            rev_tree = branch.basis_tree()
 
119
    else:
 
120
        revision = _get_one_revision(command_name, revisions)
 
121
        rev_tree = revision.as_tree(branch)
 
122
    return rev_tree
 
123
 
 
124
 
70
125
# XXX: Bad function name; should possibly also be a class method of
71
126
# WorkingTree rather than a function.
72
 
def internal_tree_files(file_list, default_branch=u'.'):
 
127
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
 
128
    apply_view=True):
73
129
    """Convert command-line paths to a WorkingTree and relative paths.
74
130
 
75
131
    This is typically used for command-line processors that take one or
77
133
 
78
134
    The filenames given are not required to exist.
79
135
 
80
 
    :param file_list: Filenames to convert.  
 
136
    :param file_list: Filenames to convert.
81
137
 
82
138
    :param default_branch: Fallback tree path to use if file_list is empty or
83
139
        None.
84
140
 
 
141
    :param apply_view: if True and a view is set, apply it or check that
 
142
        specified files are within it
 
143
 
85
144
    :return: workingtree, [relative_paths]
86
145
    """
87
146
    if file_list is None or len(file_list) == 0:
88
 
        return WorkingTree.open_containing(default_branch)[0], file_list
 
147
        tree = WorkingTree.open_containing(default_branch)[0]
 
148
        if tree.supports_views() and apply_view:
 
149
            view_files = tree.views.lookup_view()
 
150
            if view_files:
 
151
                file_list = view_files
 
152
                view_str = views.view_display_str(view_files)
 
153
                note("ignoring files outside view: %s" % view_str)
 
154
        return tree, file_list
89
155
    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
 
156
    return tree, safe_relpath_files(tree, file_list, canonicalize,
 
157
        apply_view=apply_view)
 
158
 
 
159
 
 
160
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
 
161
    """Convert file_list into a list of relpaths in tree.
 
162
 
 
163
    :param tree: A tree to operate on.
 
164
    :param file_list: A list of user provided paths or None.
 
165
    :param apply_view: if True and a view is set, apply it or check that
 
166
        specified files are within it
 
167
    :return: A list of relative paths.
 
168
    :raises errors.PathNotChild: When a provided path is in a different tree
 
169
        than tree.
 
170
    """
 
171
    if file_list is None:
 
172
        return None
 
173
    if tree.supports_views() and apply_view:
 
174
        view_files = tree.views.lookup_view()
 
175
    else:
 
176
        view_files = []
90
177
    new_list = []
 
178
    # tree.relpath exists as a "thunk" to osutils, but canonical_relpath
 
179
    # doesn't - fix that up here before we enter the loop.
 
180
    if canonicalize:
 
181
        fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
 
182
    else:
 
183
        fixer = tree.relpath
91
184
    for filename in file_list:
92
185
        try:
93
 
            new_list.append(tree.relpath(osutils.dereference_path(filename)))
 
186
            relpath = fixer(osutils.dereference_path(filename))
 
187
            if  view_files and not osutils.is_inside_any(view_files, relpath):
 
188
                raise errors.FileOutsideView(filename, view_files)
 
189
            new_list.append(relpath)
94
190
        except errors.PathNotChild:
95
191
            raise errors.FileInWrongBranch(tree.branch, filename)
96
 
    return tree, new_list
97
 
 
98
 
 
99
 
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
100
 
def get_format_type(typestring):
101
 
    """Parse and return a format specifier."""
102
 
    # Have to use BzrDirMetaFormat1 directly, so that
103
 
    # RepositoryFormat.set_default_format works
104
 
    if typestring == "default":
105
 
        return bzrdir.BzrDirMetaFormat1()
 
192
    return new_list
 
193
 
 
194
 
 
195
def _get_view_info_for_change_reporter(tree):
 
196
    """Get the view information from a tree for change reporting."""
 
197
    view_info = None
106
198
    try:
107
 
        return bzrdir.format_registry.make_bzrdir(typestring)
108
 
    except KeyError:
109
 
        msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
110
 
        raise errors.BzrCommandError(msg)
 
199
        current_view = tree.views.get_view_info()[0]
 
200
        if current_view is not None:
 
201
            view_info = (current_view, tree.views.lookup_view())
 
202
    except errors.ViewsNotSupported:
 
203
        pass
 
204
    return view_info
111
205
 
112
206
 
113
207
# TODO: Make sure no commands unconditionally use the working directory as a
145
239
 
146
240
    To see ignored files use 'bzr ignored'.  For details on the
147
241
    changes to file texts, use 'bzr diff'.
148
 
    
 
242
 
149
243
    Note that --short or -S gives status flags for each item, similar
150
244
    to Subversion's status command. To get output similar to svn -q,
151
 
    use bzr -SV.
 
245
    use bzr status -SV.
152
246
 
153
247
    If no arguments are specified, the status of the entire working
154
248
    directory is shown.  Otherwise, only the status of the specified
155
249
    files or directories is reported.  If a directory is given, status
156
250
    is reported for everything inside that directory.
157
251
 
 
252
    Before merges are committed, the pending merge tip revisions are
 
253
    shown. To see all pending merge revisions, use the -v option.
 
254
    To skip the display of pending merge information altogether, use
 
255
    the no-pending option or specify a file/directory.
 
256
 
158
257
    If a revision argument is given, the status is calculated against
159
258
    that revision, or between two revisions if two are provided.
160
259
    """
161
 
    
 
260
 
162
261
    # TODO: --no-recurse, --recurse options
163
 
    
 
262
 
164
263
    takes_args = ['file*']
165
 
    takes_options = ['show-ids', 'revision', 'change',
 
264
    takes_options = ['show-ids', 'revision', 'change', 'verbose',
166
265
                     Option('short', help='Use short status indicators.',
167
266
                            short_name='S'),
168
267
                     Option('versioned', help='Only show versioned files.',
169
 
                            short_name='V')
 
268
                            short_name='V'),
 
269
                     Option('no-pending', help='Don\'t show pending merges.',
 
270
                           ),
170
271
                     ]
171
272
    aliases = ['st', 'stat']
172
273
 
173
274
    encoding_type = 'replace'
174
275
    _see_also = ['diff', 'revert', 'status-flags']
175
 
    
 
276
 
176
277
    @display_command
177
278
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
178
 
            versioned=False):
 
279
            versioned=False, no_pending=False, verbose=False):
179
280
        from bzrlib.status import show_tree_status
180
281
 
181
282
        if revision and len(revision) > 2:
182
283
            raise errors.BzrCommandError('bzr status --revision takes exactly'
183
284
                                         ' one or two revision specifiers')
184
285
 
185
 
        tree, file_list = tree_files(file_list)
186
 
            
 
286
        tree, relfile_list = tree_files(file_list)
 
287
        # Avoid asking for specific files when that is not needed.
 
288
        if relfile_list == ['']:
 
289
            relfile_list = None
 
290
            # Don't disable pending merges for full trees other than '.'.
 
291
            if file_list == ['.']:
 
292
                no_pending = True
 
293
        # A specific path within a tree was given.
 
294
        elif relfile_list is not None:
 
295
            no_pending = True
187
296
        show_tree_status(tree, show_ids=show_ids,
188
 
                         specific_files=file_list, revision=revision,
189
 
                         to_file=self.outf, short=short, versioned=versioned)
 
297
                         specific_files=relfile_list, revision=revision,
 
298
                         to_file=self.outf, short=short, versioned=versioned,
 
299
                         show_pending=(not no_pending), verbose=verbose)
190
300
 
191
301
 
192
302
class cmd_cat_revision(Command):
193
303
    """Write out metadata for a revision.
194
 
    
 
304
 
195
305
    The revision to print can either be specified by a specific
196
306
    revision identifier, or you can use --revision.
197
307
    """
201
311
    takes_options = ['revision']
202
312
    # cat-revision is more for frontends so should be exact
203
313
    encoding = 'strict'
204
 
    
 
314
 
205
315
    @display_command
206
316
    def run(self, revision_id=None, revision=None):
207
317
        if revision_id is not None and revision is not None:
215
325
        # TODO: jam 20060112 should cat-revision always output utf-8?
216
326
        if revision_id is not None:
217
327
            revision_id = osutils.safe_revision_id(revision_id, warn=False)
218
 
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
 
328
            try:
 
329
                self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
 
330
            except errors.NoSuchRevision:
 
331
                msg = "The repository %s contains no revision %s." % (b.repository.base,
 
332
                    revision_id)
 
333
                raise errors.BzrCommandError(msg)
219
334
        elif revision is not None:
220
335
            for rev in revision:
221
336
                if rev is None:
222
337
                    raise errors.BzrCommandError('You cannot specify a NULL'
223
338
                                                 ' revision.')
224
 
                revno, rev_id = rev.in_history(b)
 
339
                rev_id = rev.as_revision_id(b)
225
340
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
226
 
    
 
341
 
 
342
 
 
343
class cmd_dump_btree(Command):
 
344
    """Dump the contents of a btree index file to stdout.
 
345
 
 
346
    PATH is a btree index file, it can be any URL. This includes things like
 
347
    .bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
 
348
 
 
349
    By default, the tuples stored in the index file will be displayed. With
 
350
    --raw, we will uncompress the pages, but otherwise display the raw bytes
 
351
    stored in the index.
 
352
    """
 
353
 
 
354
    # TODO: Do we want to dump the internal nodes as well?
 
355
    # TODO: It would be nice to be able to dump the un-parsed information,
 
356
    #       rather than only going through iter_all_entries. However, this is
 
357
    #       good enough for a start
 
358
    hidden = True
 
359
    encoding_type = 'exact'
 
360
    takes_args = ['path']
 
361
    takes_options = [Option('raw', help='Write the uncompressed bytes out,'
 
362
                                        ' rather than the parsed tuples.'),
 
363
                    ]
 
364
 
 
365
    def run(self, path, raw=False):
 
366
        dirname, basename = osutils.split(path)
 
367
        t = transport.get_transport(dirname)
 
368
        if raw:
 
369
            self._dump_raw_bytes(t, basename)
 
370
        else:
 
371
            self._dump_entries(t, basename)
 
372
 
 
373
    def _get_index_and_bytes(self, trans, basename):
 
374
        """Create a BTreeGraphIndex and raw bytes."""
 
375
        bt = btree_index.BTreeGraphIndex(trans, basename, None)
 
376
        bytes = trans.get_bytes(basename)
 
377
        bt._file = cStringIO.StringIO(bytes)
 
378
        bt._size = len(bytes)
 
379
        return bt, bytes
 
380
 
 
381
    def _dump_raw_bytes(self, trans, basename):
 
382
        import zlib
 
383
 
 
384
        # We need to parse at least the root node.
 
385
        # This is because the first page of every row starts with an
 
386
        # uncompressed header.
 
387
        bt, bytes = self._get_index_and_bytes(trans, basename)
 
388
        for page_idx, page_start in enumerate(xrange(0, len(bytes),
 
389
                                                     btree_index._PAGE_SIZE)):
 
390
            page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
 
391
            page_bytes = bytes[page_start:page_end]
 
392
            if page_idx == 0:
 
393
                self.outf.write('Root node:\n')
 
394
                header_end, data = bt._parse_header_from_bytes(page_bytes)
 
395
                self.outf.write(page_bytes[:header_end])
 
396
                page_bytes = data
 
397
            self.outf.write('\nPage %d\n' % (page_idx,))
 
398
            decomp_bytes = zlib.decompress(page_bytes)
 
399
            self.outf.write(decomp_bytes)
 
400
            self.outf.write('\n')
 
401
 
 
402
    def _dump_entries(self, trans, basename):
 
403
        try:
 
404
            st = trans.stat(basename)
 
405
        except errors.TransportNotPossible:
 
406
            # We can't stat, so we'll fake it because we have to do the 'get()'
 
407
            # anyway.
 
408
            bt, _ = self._get_index_and_bytes(trans, basename)
 
409
        else:
 
410
            bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
 
411
        for node in bt.iter_all_entries():
 
412
            # Node is made up of:
 
413
            # (index, key, value, [references])
 
414
            self.outf.write('%s\n' % (node[1:],))
 
415
 
227
416
 
228
417
class cmd_remove_tree(Command):
229
418
    """Remove the working tree from a given branch/checkout.
234
423
    To re-create the working tree, use "bzr checkout".
235
424
    """
236
425
    _see_also = ['checkout', 'working-trees']
237
 
 
238
426
    takes_args = ['location?']
 
427
    takes_options = [
 
428
        Option('force',
 
429
               help='Remove the working tree even if it has '
 
430
                    'uncommitted changes.'),
 
431
        ]
239
432
 
240
 
    def run(self, location='.'):
 
433
    def run(self, location='.', force=False):
241
434
        d = bzrdir.BzrDir.open(location)
242
 
        
 
435
 
243
436
        try:
244
437
            working = d.open_workingtree()
245
438
        except errors.NoWorkingTree:
247
440
        except errors.NotLocalUrl:
248
441
            raise errors.BzrCommandError("You cannot remove the working tree of a "
249
442
                                         "remote path")
250
 
        
 
443
        if not force:
 
444
            changes = working.changes_from(working.basis_tree())
 
445
            if changes.has_changed():
 
446
                raise errors.UncommittedChanges(working)
 
447
 
251
448
        working_path = working.bzrdir.root_transport.base
252
449
        branch_path = working.branch.bzrdir.root_transport.base
253
450
        if working_path != branch_path:
254
451
            raise errors.BzrCommandError("You cannot remove the working tree from "
255
452
                                         "a lightweight checkout")
256
 
        
 
453
 
257
454
        d.destroy_workingtree()
258
 
        
 
455
 
259
456
 
260
457
class cmd_revno(Command):
261
458
    """Show current revision number.
277
474
    """
278
475
    hidden = True
279
476
    takes_args = ['revision_info*']
280
 
    takes_options = ['revision']
 
477
    takes_options = [
 
478
        'revision',
 
479
        Option('directory',
 
480
            help='Branch to examine, '
 
481
                 'rather than the one containing the working directory.',
 
482
            short_name='d',
 
483
            type=unicode,
 
484
            ),
 
485
        ]
281
486
 
282
487
    @display_command
283
 
    def run(self, revision=None, revision_info_list=[]):
 
488
    def run(self, revision=None, directory=u'.', revision_info_list=[]):
284
489
 
285
490
        revs = []
286
491
        if revision is not None:
289
494
            for rev in revision_info_list:
290
495
                revs.append(RevisionSpec.from_string(rev))
291
496
 
292
 
        b = Branch.open_containing(u'.')[0]
 
497
        b = Branch.open_containing(directory)[0]
293
498
 
294
499
        if len(revs) == 0:
295
500
            revs.append(RevisionSpec.from_string('-1'))
296
501
 
297
502
        for rev in revs:
298
 
            revinfo = rev.in_history(b)
299
 
            if revinfo.revno is None:
 
503
            revision_id = rev.as_revision_id(b)
 
504
            try:
 
505
                revno = '%4d' % (b.revision_id_to_revno(revision_id))
 
506
            except errors.NoSuchRevision:
300
507
                dotted_map = b.get_revision_id_to_revno_map()
301
 
                revno = '.'.join(str(i) for i in dotted_map[revinfo.rev_id])
302
 
                print '%s %s' % (revno, revinfo.rev_id)
303
 
            else:
304
 
                print '%4d %s' % (revinfo.revno, revinfo.rev_id)
305
 
 
306
 
    
 
508
                revno = '.'.join(str(i) for i in dotted_map[revision_id])
 
509
            print '%s %s' % (revno, revision_id)
 
510
 
 
511
 
307
512
class cmd_add(Command):
308
513
    """Add specified files or directories.
309
514
 
327
532
    you should never need to explicitly add a directory, they'll just
328
533
    get added when you add a file in the directory.
329
534
 
330
 
    --dry-run will show which files would be added, but not actually 
 
535
    --dry-run will show which files would be added, but not actually
331
536
    add them.
332
537
 
333
538
    --file-ids-from will try to use the file ids from the supplied path.
376
581
            base_tree.lock_read()
377
582
        try:
378
583
            file_list = self._maybe_expand_globs(file_list)
379
 
            if file_list:
380
 
                tree = WorkingTree.open_containing(file_list[0])[0]
381
 
            else:
382
 
                tree = WorkingTree.open_containing(u'.')[0]
 
584
            tree, file_list = tree_files_for_add(file_list)
383
585
            added, ignored = tree.smart_add(file_list, not
384
586
                no_recurse, action=action, save=not dry_run)
385
587
        finally:
389
591
            if verbose:
390
592
                for glob in sorted(ignored.keys()):
391
593
                    for path in ignored[glob]:
392
 
                        self.outf.write("ignored %s matching \"%s\"\n" 
 
594
                        self.outf.write("ignored %s matching \"%s\"\n"
393
595
                                        % (path, glob))
394
596
            else:
395
597
                match_len = 0
422
624
 
423
625
    takes_args = ['filename']
424
626
    hidden = True
425
 
    
 
627
 
426
628
    @display_command
427
629
    def run(self, filename):
428
630
        # TODO: jam 20050106 Can relpath return a munged path if
458
660
        if kind and kind not in ['file', 'directory', 'symlink']:
459
661
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
460
662
 
 
663
        revision = _get_one_revision('inventory', revision)
461
664
        work_tree, file_list = tree_files(file_list)
462
665
        work_tree.lock_read()
463
666
        try:
464
667
            if revision is not None:
465
 
                if len(revision) > 1:
466
 
                    raise errors.BzrCommandError(
467
 
                        'bzr inventory --revision takes exactly one revision'
468
 
                        ' identifier')
469
 
                revision_id = revision[0].in_history(work_tree.branch).rev_id
470
 
                tree = work_tree.branch.repository.revision_tree(revision_id)
 
668
                tree = revision.as_tree(work_tree.branch)
471
669
 
472
670
                extra_trees = [work_tree]
473
671
                tree.lock_read()
533
731
 
534
732
        if len(names_list) < 2:
535
733
            raise errors.BzrCommandError("missing file argument")
536
 
        tree, rel_names = tree_files(names_list)
537
 
        
538
 
        if os.path.isdir(names_list[-1]):
 
734
        tree, rel_names = tree_files(names_list, canonicalize=False)
 
735
        tree.lock_write()
 
736
        try:
 
737
            self._run(tree, names_list, rel_names, after)
 
738
        finally:
 
739
            tree.unlock()
 
740
 
 
741
    def _run(self, tree, names_list, rel_names, after):
 
742
        into_existing = osutils.isdir(names_list[-1])
 
743
        if into_existing and len(names_list) == 2:
 
744
            # special cases:
 
745
            # a. case-insensitive filesystem and change case of dir
 
746
            # b. move directory after the fact (if the source used to be
 
747
            #    a directory, but now doesn't exist in the working tree
 
748
            #    and the target is an existing directory, just rename it)
 
749
            if (not tree.case_sensitive
 
750
                and rel_names[0].lower() == rel_names[1].lower()):
 
751
                into_existing = False
 
752
            else:
 
753
                inv = tree.inventory
 
754
                # 'fix' the case of a potential 'from'
 
755
                from_id = tree.path2id(
 
756
                            tree.get_canonical_inventory_path(rel_names[0]))
 
757
                if (not osutils.lexists(names_list[0]) and
 
758
                    from_id and inv.get_file_kind(from_id) == "directory"):
 
759
                    into_existing = False
 
760
        # move/rename
 
761
        if into_existing:
539
762
            # move into existing directory
 
763
            # All entries reference existing inventory items, so fix them up
 
764
            # for cicp file-systems.
 
765
            rel_names = tree.get_canonical_inventory_paths(rel_names)
540
766
            for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
541
767
                self.outf.write("%s => %s\n" % pair)
542
768
        else:
544
770
                raise errors.BzrCommandError('to mv multiple files the'
545
771
                                             ' destination must be a versioned'
546
772
                                             ' directory')
547
 
            tree.rename_one(rel_names[0], rel_names[1], after=after)
548
 
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
549
 
            
550
 
    
 
773
 
 
774
            # for cicp file-systems: the src references an existing inventory
 
775
            # item:
 
776
            src = tree.get_canonical_inventory_path(rel_names[0])
 
777
            # Find the canonical version of the destination:  In all cases, the
 
778
            # parent of the target must be in the inventory, so we fetch the
 
779
            # canonical version from there (we do not always *use* the
 
780
            # canonicalized tail portion - we may be attempting to rename the
 
781
            # case of the tail)
 
782
            canon_dest = tree.get_canonical_inventory_path(rel_names[1])
 
783
            dest_parent = osutils.dirname(canon_dest)
 
784
            spec_tail = osutils.basename(rel_names[1])
 
785
            # For a CICP file-system, we need to avoid creating 2 inventory
 
786
            # entries that differ only by case.  So regardless of the case
 
787
            # we *want* to use (ie, specified by the user or the file-system),
 
788
            # we must always choose to use the case of any existing inventory
 
789
            # items.  The only exception to this is when we are attempting a
 
790
            # case-only rename (ie, canonical versions of src and dest are
 
791
            # the same)
 
792
            dest_id = tree.path2id(canon_dest)
 
793
            if dest_id is None or tree.path2id(src) == dest_id:
 
794
                # No existing item we care about, so work out what case we
 
795
                # are actually going to use.
 
796
                if after:
 
797
                    # If 'after' is specified, the tail must refer to a file on disk.
 
798
                    if dest_parent:
 
799
                        dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
 
800
                    else:
 
801
                        # pathjoin with an empty tail adds a slash, which breaks
 
802
                        # relpath :(
 
803
                        dest_parent_fq = tree.basedir
 
804
 
 
805
                    dest_tail = osutils.canonical_relpath(
 
806
                                    dest_parent_fq,
 
807
                                    osutils.pathjoin(dest_parent_fq, spec_tail))
 
808
                else:
 
809
                    # not 'after', so case as specified is used
 
810
                    dest_tail = spec_tail
 
811
            else:
 
812
                # Use the existing item so 'mv' fails with AlreadyVersioned.
 
813
                dest_tail = os.path.basename(canon_dest)
 
814
            dest = osutils.pathjoin(dest_parent, dest_tail)
 
815
            mutter("attempting to move %s => %s", src, dest)
 
816
            tree.rename_one(src, dest, after=after)
 
817
            self.outf.write("%s => %s\n" % (src, dest))
 
818
 
 
819
 
551
820
class cmd_pull(Command):
552
821
    """Turn this branch into a mirror of another branch.
553
822
 
566
835
    that, you can omit the location to use the default.  To change the
567
836
    default, use --remember. The value will only be saved if the remote
568
837
    location can be accessed.
 
838
 
 
839
    Note: The location can be specified either in the form of a branch,
 
840
    or in the form of a path to a file containing a merge directive generated
 
841
    with bzr send.
569
842
    """
570
843
 
571
 
    _see_also = ['push', 'update', 'status-flags']
 
844
    _see_also = ['push', 'update', 'status-flags', 'send']
572
845
    takes_options = ['remember', 'overwrite', 'revision',
573
846
        custom_help('verbose',
574
847
            help='Show logs of pulled revisions.'),
599
872
 
600
873
        possible_transports = []
601
874
        if location is not None:
602
 
            mergeable, location_transport = _get_mergeable_helper(location)
603
 
            possible_transports.append(location_transport)
 
875
            try:
 
876
                mergeable = bundle.read_mergeable_from_url(location,
 
877
                    possible_transports=possible_transports)
 
878
            except errors.NotABundle:
 
879
                mergeable = None
604
880
 
605
881
        stored_loc = branch_to.get_parent()
606
882
        if location is None:
610
886
            else:
611
887
                display_url = urlutils.unescape_for_display(stored_loc,
612
888
                        self.outf.encoding)
613
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
889
                if not is_quiet():
 
890
                    self.outf.write("Using saved parent location: %s\n" % display_url)
614
891
                location = stored_loc
615
 
                location_transport = transport.get_transport(
616
 
                    location, possible_transports=possible_transports)
617
892
 
 
893
        revision = _get_one_revision('pull', revision)
618
894
        if mergeable is not None:
619
895
            if revision is not None:
620
896
                raise errors.BzrCommandError(
624
900
                mergeable.get_merge_request(branch_to.repository)
625
901
            branch_from = branch_to
626
902
        else:
627
 
            branch_from = Branch.open_from_transport(location_transport)
 
903
            branch_from = Branch.open(location,
 
904
                possible_transports=possible_transports)
628
905
 
629
906
            if branch_to.get_parent() is None or remember:
630
907
                branch_to.set_parent(branch_from.base)
631
908
 
632
909
        if revision is not None:
633
 
            if len(revision) == 1:
634
 
                revision_id = revision[0].in_history(branch_from).rev_id
 
910
            revision_id = revision.as_revision_id(branch_from)
 
911
 
 
912
        branch_to.lock_write()
 
913
        try:
 
914
            if tree_to is not None:
 
915
                view_info = _get_view_info_for_change_reporter(tree_to)
 
916
                change_reporter = delta._ChangeReporter(
 
917
                    unversioned_filter=tree_to.is_ignored, view_info=view_info)
 
918
                result = tree_to.pull(branch_from, overwrite, revision_id,
 
919
                                      change_reporter,
 
920
                                      possible_transports=possible_transports)
635
921
            else:
636
 
                raise errors.BzrCommandError(
637
 
                    'bzr pull --revision takes one value.')
638
 
 
639
 
        if verbose:
640
 
            old_rh = branch_to.revision_history()
641
 
        if tree_to is not None:
642
 
            change_reporter = delta._ChangeReporter(
643
 
                unversioned_filter=tree_to.is_ignored)
644
 
            result = tree_to.pull(branch_from, overwrite, revision_id,
645
 
                                  change_reporter,
646
 
                                  possible_transports=possible_transports)
647
 
        else:
648
 
            result = branch_to.pull(branch_from, overwrite, revision_id)
649
 
 
650
 
        result.report(self.outf)
651
 
        if verbose:
652
 
            new_rh = branch_to.revision_history()
653
 
            log.show_changed_revisions(branch_to, old_rh, new_rh,
654
 
                                       to_file=self.outf)
 
922
                result = branch_to.pull(branch_from, overwrite, revision_id)
 
923
 
 
924
            result.report(self.outf)
 
925
            if verbose and result.old_revid != result.new_revid:
 
926
                log.show_branch_change(branch_to, self.outf, result.old_revno,
 
927
                                       result.old_revid)
 
928
        finally:
 
929
            branch_to.unlock()
655
930
 
656
931
 
657
932
class cmd_push(Command):
658
933
    """Update a mirror of this branch.
659
 
    
 
934
 
660
935
    The target branch will not have its working tree populated because this
661
936
    is both expensive, and is not supported on remote file systems.
662
 
    
 
937
 
663
938
    Some smart servers or protocols *may* put the working tree in place in
664
939
    the future.
665
940
 
669
944
 
670
945
    If branches have diverged, you can use 'bzr push --overwrite' to replace
671
946
    the other branch completely, discarding its unmerged changes.
672
 
    
 
947
 
673
948
    If you want to ensure you have the different changes in the other branch,
674
949
    do a merge (see bzr help merge) from the other branch, and commit that.
675
950
    After that you will be able to do a push without '--overwrite'.
681
956
    """
682
957
 
683
958
    _see_also = ['pull', 'update', 'working-trees']
684
 
    takes_options = ['remember', 'overwrite', 'verbose',
 
959
    takes_options = ['remember', 'overwrite', 'verbose', 'revision',
685
960
        Option('create-prefix',
686
961
               help='Create the path leading up to the branch '
687
962
                    'if it does not already exist.'),
696
971
                    ' directory exists, but does not already'
697
972
                    ' have a control directory.  This flag will'
698
973
                    ' allow push to proceed.'),
 
974
        Option('stacked',
 
975
            help='Create a stacked branch that references the public location '
 
976
                'of the parent branch.'),
 
977
        Option('stacked-on',
 
978
            help='Create a stacked branch that refers to another branch '
 
979
                'for the commit history. Only the work not present in the '
 
980
                'referenced branch is included in the branch created.',
 
981
            type=unicode),
699
982
        ]
700
983
    takes_args = ['location?']
701
984
    encoding_type = 'replace'
702
985
 
703
986
    def run(self, location=None, remember=False, overwrite=False,
704
 
            create_prefix=False, verbose=False,
705
 
            use_existing_dir=False,
706
 
            directory=None):
707
 
        # FIXME: Way too big!  Put this into a function called from the
708
 
        # command.
 
987
        create_prefix=False, verbose=False, revision=None,
 
988
        use_existing_dir=False, directory=None, stacked_on=None,
 
989
        stacked=False):
 
990
        from bzrlib.push import _show_push_branch
 
991
 
 
992
        # Get the source branch and revision_id
709
993
        if directory is None:
710
994
            directory = '.'
711
995
        br_from = Branch.open_containing(directory)[0]
712
 
        stored_loc = br_from.get_push_location()
 
996
        revision = _get_one_revision('push', revision)
 
997
        if revision is not None:
 
998
            revision_id = revision.in_history(br_from).rev_id
 
999
        else:
 
1000
            revision_id = br_from.last_revision()
 
1001
 
 
1002
        # Get the stacked_on branch, if any
 
1003
        if stacked_on is not None:
 
1004
            stacked_on = urlutils.normalize_url(stacked_on)
 
1005
        elif stacked:
 
1006
            parent_url = br_from.get_parent()
 
1007
            if parent_url:
 
1008
                parent = Branch.open(parent_url)
 
1009
                stacked_on = parent.get_public_branch()
 
1010
                if not stacked_on:
 
1011
                    # I considered excluding non-http url's here, thus forcing
 
1012
                    # 'public' branches only, but that only works for some
 
1013
                    # users, so it's best to just depend on the user spotting an
 
1014
                    # error by the feedback given to them. RBC 20080227.
 
1015
                    stacked_on = parent_url
 
1016
            if not stacked_on:
 
1017
                raise errors.BzrCommandError(
 
1018
                    "Could not determine branch to refer to.")
 
1019
 
 
1020
        # Get the destination location
713
1021
        if location is None:
 
1022
            stored_loc = br_from.get_push_location()
714
1023
            if stored_loc is None:
715
 
                raise errors.BzrCommandError("No push location known or specified.")
 
1024
                raise errors.BzrCommandError(
 
1025
                    "No push location known or specified.")
716
1026
            else:
717
1027
                display_url = urlutils.unescape_for_display(stored_loc,
718
1028
                        self.outf.encoding)
719
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
1029
                self.outf.write("Using saved push location: %s\n" % display_url)
720
1030
                location = stored_loc
721
1031
 
722
 
        to_transport = transport.get_transport(location)
723
 
 
724
 
        br_to = repository_to = dir_to = None
725
 
        try:
726
 
            dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
727
 
        except errors.NotBranchError:
728
 
            pass # Didn't find anything
729
 
        else:
730
 
            # If we can open a branch, use its direct repository, otherwise see
731
 
            # if there is a repository without a branch.
732
 
            try:
733
 
                br_to = dir_to.open_branch()
734
 
            except errors.NotBranchError:
735
 
                # Didn't find a branch, can we find a repository?
736
 
                try:
737
 
                    repository_to = dir_to.find_repository()
738
 
                except errors.NoRepositoryPresent:
739
 
                    pass
740
 
            else:
741
 
                # Found a branch, so we must have found a repository
742
 
                repository_to = br_to.repository
743
 
        push_result = None
744
 
        if verbose:
745
 
            old_rh = []
746
 
        if dir_to is None:
747
 
            # The destination doesn't exist; create it.
748
 
            # XXX: Refactor the create_prefix/no_create_prefix code into a
749
 
            #      common helper function
750
 
 
751
 
            def make_directory(transport):
752
 
                transport.mkdir('.')
753
 
                return transport
754
 
 
755
 
            def redirected(redirected_transport, e, redirection_notice):
756
 
                return transport.get_transport(e.get_target_url())
757
 
 
758
 
            try:
759
 
                to_transport = transport.do_catching_redirections(
760
 
                    make_directory, to_transport, redirected)
761
 
            except errors.FileExists:
762
 
                if not use_existing_dir:
763
 
                    raise errors.BzrCommandError("Target directory %s"
764
 
                         " already exists, but does not have a valid .bzr"
765
 
                         " directory. Supply --use-existing-dir to push"
766
 
                         " there anyway." % location)
767
 
            except errors.NoSuchFile:
768
 
                if not create_prefix:
769
 
                    raise errors.BzrCommandError("Parent directory of %s"
770
 
                        " does not exist."
771
 
                        "\nYou may supply --create-prefix to create all"
772
 
                        " leading parent directories."
773
 
                        % location)
774
 
                _create_prefix(to_transport)
775
 
            except errors.TooManyRedirections:
776
 
                raise errors.BzrCommandError("Too many redirections trying "
777
 
                                             "to make %s." % location)
778
 
 
779
 
            # Now the target directory exists, but doesn't have a .bzr
780
 
            # directory. So we need to create it, along with any work to create
781
 
            # all of the dependent branches, etc.
782
 
            dir_to = br_from.bzrdir.clone_on_transport(to_transport,
783
 
                revision_id=br_from.last_revision())
784
 
            br_to = dir_to.open_branch()
785
 
            # TODO: Some more useful message about what was copied
786
 
            note('Created new branch.')
787
 
            # We successfully created the target, remember it
788
 
            if br_from.get_push_location() is None or remember:
789
 
                br_from.set_push_location(br_to.base)
790
 
        elif repository_to is None:
791
 
            # we have a bzrdir but no branch or repository
792
 
            # XXX: Figure out what to do other than complain.
793
 
            raise errors.BzrCommandError("At %s you have a valid .bzr control"
794
 
                " directory, but not a branch or repository. This is an"
795
 
                " unsupported configuration. Please move the target directory"
796
 
                " out of the way and try again."
797
 
                % location)
798
 
        elif br_to is None:
799
 
            # We have a repository but no branch, copy the revisions, and then
800
 
            # create a branch.
801
 
            last_revision_id = br_from.last_revision()
802
 
            repository_to.fetch(br_from.repository,
803
 
                                revision_id=last_revision_id)
804
 
            br_to = br_from.clone(dir_to, revision_id=last_revision_id)
805
 
            note('Created new branch.')
806
 
            if br_from.get_push_location() is None or remember:
807
 
                br_from.set_push_location(br_to.base)
808
 
        else: # We have a valid to branch
809
 
            # We were able to connect to the remote location, so remember it
810
 
            # we don't need to successfully push because of possible divergence.
811
 
            if br_from.get_push_location() is None or remember:
812
 
                br_from.set_push_location(br_to.base)
813
 
            if verbose:
814
 
                old_rh = br_to.revision_history()
815
 
            try:
816
 
                try:
817
 
                    tree_to = dir_to.open_workingtree()
818
 
                except errors.NotLocalUrl:
819
 
                    warning("This transport does not update the working " 
820
 
                            "tree of: %s. See 'bzr help working-trees' for "
821
 
                            "more information." % br_to.base)
822
 
                    push_result = br_from.push(br_to, overwrite)
823
 
                except errors.NoWorkingTree:
824
 
                    push_result = br_from.push(br_to, overwrite)
825
 
                else:
826
 
                    tree_to.lock_write()
827
 
                    try:
828
 
                        push_result = br_from.push(tree_to.branch, overwrite)
829
 
                        tree_to.update()
830
 
                    finally:
831
 
                        tree_to.unlock()
832
 
            except errors.DivergedBranches:
833
 
                raise errors.BzrCommandError('These branches have diverged.'
834
 
                                        '  Try using "merge" and then "push".')
835
 
        if push_result is not None:
836
 
            push_result.report(self.outf)
837
 
        elif verbose:
838
 
            new_rh = br_to.revision_history()
839
 
            if old_rh != new_rh:
840
 
                # Something changed
841
 
                from bzrlib.log import show_changed_revisions
842
 
                show_changed_revisions(br_to, old_rh, new_rh,
843
 
                                       to_file=self.outf)
844
 
        else:
845
 
            # we probably did a clone rather than a push, so a message was
846
 
            # emitted above
847
 
            pass
 
1032
        _show_push_branch(br_from, revision_id, location, self.outf,
 
1033
            verbose=verbose, overwrite=overwrite, remember=remember,
 
1034
            stacked_on=stacked_on, create_prefix=create_prefix,
 
1035
            use_existing_dir=use_existing_dir)
848
1036
 
849
1037
 
850
1038
class cmd_branch(Command):
863
1051
 
864
1052
    _see_also = ['checkout']
865
1053
    takes_args = ['from_location', 'to_location?']
866
 
    takes_options = ['revision']
 
1054
    takes_options = ['revision', Option('hardlink',
 
1055
        help='Hard-link working tree files where possible.'),
 
1056
        Option('no-tree',
 
1057
            help="Create a branch without a working-tree."),
 
1058
        Option('stacked',
 
1059
            help='Create a stacked branch referring to the source branch. '
 
1060
                'The new branch will depend on the availability of the source '
 
1061
                'branch for all operations.'),
 
1062
        Option('standalone',
 
1063
               help='Do not use a shared repository, even if available.'),
 
1064
        ]
867
1065
    aliases = ['get', 'clone']
868
1066
 
869
 
    def run(self, from_location, to_location=None, revision=None):
 
1067
    def run(self, from_location, to_location=None, revision=None,
 
1068
            hardlink=False, stacked=False, standalone=False, no_tree=False):
870
1069
        from bzrlib.tag import _merge_tags_if_possible
871
 
        if revision is None:
872
 
            revision = [None]
873
 
        elif len(revision) > 1:
874
 
            raise errors.BzrCommandError(
875
 
                'bzr branch --revision takes exactly 1 revision value')
876
1070
 
877
1071
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
878
1072
            from_location)
 
1073
        revision = _get_one_revision('branch', revision)
879
1074
        br_from.lock_read()
880
1075
        try:
881
 
            if len(revision) == 1 and revision[0] is not None:
882
 
                revision_id = revision[0].in_history(br_from)[1]
 
1076
            if revision is not None:
 
1077
                revision_id = revision.as_revision_id(br_from)
883
1078
            else:
884
1079
                # FIXME - wt.last_revision, fallback to branch, fall back to
885
1080
                # None or perhaps NULL_REVISION to mean copy nothing
887
1082
                revision_id = br_from.last_revision()
888
1083
            if to_location is None:
889
1084
                to_location = urlutils.derive_to_location(from_location)
890
 
                name = None
891
 
            else:
892
 
                name = os.path.basename(to_location) + '\n'
893
 
 
894
1085
            to_transport = transport.get_transport(to_location)
895
1086
            try:
896
1087
                to_transport.mkdir('.')
904
1095
                # preserve whatever source format we have.
905
1096
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
906
1097
                                            possible_transports=[to_transport],
907
 
                                            accelerator_tree=accelerator_tree)
 
1098
                                            accelerator_tree=accelerator_tree,
 
1099
                                            hardlink=hardlink, stacked=stacked,
 
1100
                                            force_new_repo=standalone,
 
1101
                                            create_tree_if_local=not no_tree,
 
1102
                                            source_branch=br_from)
908
1103
                branch = dir.open_branch()
909
1104
            except errors.NoSuchRevision:
910
1105
                to_transport.delete_tree('.')
911
 
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
 
1106
                msg = "The branch %s has no revision %s." % (from_location,
 
1107
                    revision)
912
1108
                raise errors.BzrCommandError(msg)
913
 
            if name:
914
 
                branch.control_files.put_utf8('branch-name', name)
915
1109
            _merge_tags_if_possible(br_from, branch)
916
 
            note('Branched %d revision(s).' % branch.revno())
 
1110
            # If the source branch is stacked, the new branch may
 
1111
            # be stacked whether we asked for that explicitly or not.
 
1112
            # We therefore need a try/except here and not just 'if stacked:'
 
1113
            try:
 
1114
                note('Created new stacked branch referring to %s.' %
 
1115
                    branch.get_stacked_on_url())
 
1116
            except (errors.NotStacked, errors.UnstackableBranchFormat,
 
1117
                errors.UnstackableRepositoryFormat), e:
 
1118
                note('Branched %d revision(s).' % branch.revno())
917
1119
        finally:
918
1120
            br_from.unlock()
919
1121
 
925
1127
    the branch found in '.'. This is useful if you have removed the working tree
926
1128
    or if it was never created - i.e. if you pushed the branch to its current
927
1129
    location using SFTP.
928
 
    
 
1130
 
929
1131
    If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
930
1132
    be used.  In other words, "checkout ../foo/bar" will attempt to create ./bar.
931
1133
    If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
949
1151
                                 "common operations like diff and status without "
950
1152
                                 "such access, and also support local commits."
951
1153
                            ),
952
 
                     Option('files-from',
953
 
                            help="Get file contents from this tree.", type=str)
 
1154
                     Option('files-from', type=str,
 
1155
                            help="Get file contents from this tree."),
 
1156
                     Option('hardlink',
 
1157
                            help='Hard-link working tree files where possible.'
 
1158
                            ),
954
1159
                     ]
955
1160
    aliases = ['co']
956
1161
 
957
1162
    def run(self, branch_location=None, to_location=None, revision=None,
958
 
            lightweight=False, files_from=None):
959
 
        if revision is None:
960
 
            revision = [None]
961
 
        elif len(revision) > 1:
962
 
            raise errors.BzrCommandError(
963
 
                'bzr checkout --revision takes exactly 1 revision value')
 
1163
            lightweight=False, files_from=None, hardlink=False):
964
1164
        if branch_location is None:
965
1165
            branch_location = osutils.getcwd()
966
1166
            to_location = branch_location
967
1167
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
968
1168
            branch_location)
 
1169
        revision = _get_one_revision('checkout', revision)
969
1170
        if files_from is not None:
970
1171
            accelerator_tree = WorkingTree.open(files_from)
971
 
        if len(revision) == 1 and revision[0] is not None:
972
 
            revision_id = _mod_revision.ensure_null(
973
 
                revision[0].in_history(source)[1])
 
1172
        if revision is not None:
 
1173
            revision_id = revision.as_revision_id(source)
974
1174
        else:
975
1175
            revision_id = None
976
1176
        if to_location is None:
977
1177
            to_location = urlutils.derive_to_location(branch_location)
978
 
        # if the source and to_location are the same, 
 
1178
        # if the source and to_location are the same,
979
1179
        # and there is no working tree,
980
1180
        # then reconstitute a branch
981
1181
        if (osutils.abspath(to_location) ==
986
1186
                source.bzrdir.create_workingtree(revision_id)
987
1187
                return
988
1188
        source.create_checkout(to_location, revision_id, lightweight,
989
 
                               accelerator_tree)
 
1189
                               accelerator_tree, hardlink)
990
1190
 
991
1191
 
992
1192
class cmd_renames(Command):
1008
1208
            old_tree.lock_read()
1009
1209
            try:
1010
1210
                old_inv = old_tree.inventory
1011
 
                renames = list(_mod_tree.find_renames(old_inv, new_inv))
 
1211
                renames = []
 
1212
                iterator = tree.iter_changes(old_tree, include_unchanged=True)
 
1213
                for f, paths, c, v, p, n, k, e in iterator:
 
1214
                    if paths[0] == paths[1]:
 
1215
                        continue
 
1216
                    if None in (paths):
 
1217
                        continue
 
1218
                    renames.append(paths)
1012
1219
                renames.sort()
1013
1220
                for old_name, new_name in renames:
1014
1221
                    self.outf.write("%s => %s\n" % (old_name, new_name))
1020
1227
 
1021
1228
class cmd_update(Command):
1022
1229
    """Update a tree to have the latest code committed to its branch.
1023
 
    
 
1230
 
1024
1231
    This will perform a merge into the working tree, and may generate
1025
 
    conflicts. If you have any local changes, you will still 
 
1232
    conflicts. If you have any local changes, you will still
1026
1233
    need to commit them after the update for the update to be complete.
1027
 
    
1028
 
    If you want to discard your local changes, you can just do a 
 
1234
 
 
1235
    If you want to discard your local changes, you can just do a
1029
1236
    'bzr revert' instead of 'bzr commit' after the update.
1030
1237
    """
1031
1238
 
1053
1260
                    revno = tree.branch.revision_id_to_revno(last_rev)
1054
1261
                    note("Tree is up to date at revision %d." % (revno,))
1055
1262
                    return 0
 
1263
            view_info = _get_view_info_for_change_reporter(tree)
1056
1264
            conflicts = tree.update(
1057
 
                delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1058
 
                possible_transports=possible_transports)
 
1265
                delta._ChangeReporter(unversioned_filter=tree.is_ignored,
 
1266
                view_info=view_info), possible_transports=possible_transports)
1059
1267
            revno = tree.branch.revision_id_to_revno(
1060
1268
                _mod_revision.ensure_null(tree.last_revision()))
1061
1269
            note('Updated to revision %d.' % (revno,))
1074
1282
    """Show information about a working tree, branch or repository.
1075
1283
 
1076
1284
    This command will show all known locations and formats associated to the
1077
 
    tree, branch or repository.  Statistical information is included with
1078
 
    each report.
 
1285
    tree, branch or repository.
 
1286
 
 
1287
    In verbose mode, statistical information is included with each report.
 
1288
    To see extended statistic information, use a verbosity level of 2 or
 
1289
    higher by specifying the verbose option multiple times, e.g. -vv.
1079
1290
 
1080
1291
    Branches and working trees will also report any missing revisions.
 
1292
 
 
1293
    :Examples:
 
1294
 
 
1295
      Display information on the format and related locations:
 
1296
 
 
1297
        bzr info
 
1298
 
 
1299
      Display the above together with extended format information and
 
1300
      basic statistics (like the number of files in the working tree and
 
1301
      number of revisions in the branch and repository):
 
1302
 
 
1303
        bzr -v info
 
1304
 
 
1305
      Display the above together with number of committers to the branch:
 
1306
 
 
1307
        bzr -vv info
1081
1308
    """
1082
1309
    _see_also = ['revno', 'working-trees', 'repositories']
1083
1310
    takes_args = ['location?']
1087
1314
    @display_command
1088
1315
    def run(self, location=None, verbose=False):
1089
1316
        if verbose:
1090
 
            noise_level = 2
 
1317
            noise_level = get_verbosity_level()
1091
1318
        else:
1092
1319
            noise_level = 0
1093
1320
        from bzrlib.info import show_bzrdir_info
1098
1325
class cmd_remove(Command):
1099
1326
    """Remove files or directories.
1100
1327
 
1101
 
    This makes bzr stop tracking changes to the specified files and
1102
 
    delete them if they can easily be recovered using revert.
1103
 
 
1104
 
    You can specify one or more files, and/or --new.  If you specify --new,
1105
 
    only 'added' files will be removed.  If you specify both, then new files
1106
 
    in the specified directories will be removed.  If the directories are
1107
 
    also new, they will also be removed.
 
1328
    This makes bzr stop tracking changes to the specified files. bzr will delete
 
1329
    them if they can easily be recovered using revert. If no options or
 
1330
    parameters are given bzr will scan for files that are being tracked by bzr
 
1331
    but missing in your tree and stop tracking them for you.
1108
1332
    """
1109
1333
    takes_args = ['file*']
1110
1334
    takes_options = ['verbose',
1111
 
        Option('new', help='Remove newly-added files.'),
 
1335
        Option('new', help='Only remove files that have never been committed.'),
1112
1336
        RegistryOption.from_kwargs('file-deletion-strategy',
1113
1337
            'The file deletion mode to be used.',
1114
1338
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1117
1341
            keep="Don't delete any files.",
1118
1342
            force='Delete all the specified files, even if they can not be '
1119
1343
                'recovered and even if they are non-empty directories.')]
1120
 
    aliases = ['rm']
 
1344
    aliases = ['rm', 'del']
1121
1345
    encoding_type = 'replace'
1122
1346
 
1123
1347
    def run(self, file_list, verbose=False, new=False,
1126
1350
 
1127
1351
        if file_list is not None:
1128
1352
            file_list = [f for f in file_list]
1129
 
        elif not new:
1130
 
            raise errors.BzrCommandError('Specify one or more files to'
1131
 
            ' remove, or use --new.')
1132
1353
 
1133
 
        if new:
1134
 
            added = tree.changes_from(tree.basis_tree(),
1135
 
                specific_files=file_list).added
1136
 
            file_list = sorted([f[0] for f in added], reverse=True)
1137
 
            if len(file_list) == 0:
1138
 
                raise errors.BzrCommandError('No matching files.')
1139
 
        tree.remove(file_list, verbose=verbose, to_file=self.outf,
1140
 
            keep_files=file_deletion_strategy=='keep',
1141
 
            force=file_deletion_strategy=='force')
 
1354
        tree.lock_write()
 
1355
        try:
 
1356
            # Heuristics should probably all move into tree.remove_smart or
 
1357
            # some such?
 
1358
            if new:
 
1359
                added = tree.changes_from(tree.basis_tree(),
 
1360
                    specific_files=file_list).added
 
1361
                file_list = sorted([f[0] for f in added], reverse=True)
 
1362
                if len(file_list) == 0:
 
1363
                    raise errors.BzrCommandError('No matching files.')
 
1364
            elif file_list is None:
 
1365
                # missing files show up in iter_changes(basis) as
 
1366
                # versioned-with-no-kind.
 
1367
                missing = []
 
1368
                for change in tree.iter_changes(tree.basis_tree()):
 
1369
                    # Find paths in the working tree that have no kind:
 
1370
                    if change[1][1] is not None and change[6][1] is None:
 
1371
                        missing.append(change[1][1])
 
1372
                file_list = sorted(missing, reverse=True)
 
1373
                file_deletion_strategy = 'keep'
 
1374
            tree.remove(file_list, verbose=verbose, to_file=self.outf,
 
1375
                keep_files=file_deletion_strategy=='keep',
 
1376
                force=file_deletion_strategy=='force')
 
1377
        finally:
 
1378
            tree.unlock()
1142
1379
 
1143
1380
 
1144
1381
class cmd_file_id(Command):
1190
1427
 
1191
1428
    This can correct data mismatches that may have been caused by
1192
1429
    previous ghost operations or bzr upgrades. You should only
1193
 
    need to run this command if 'bzr check' or a bzr developer 
 
1430
    need to run this command if 'bzr check' or a bzr developer
1194
1431
    advises you to run it.
1195
1432
 
1196
1433
    If a second branch is provided, cross-branch reconciliation is
1198
1435
    id which was not present in very early bzr versions is represented
1199
1436
    correctly in both branches.
1200
1437
 
1201
 
    At the same time it is run it may recompress data resulting in 
 
1438
    At the same time it is run it may recompress data resulting in
1202
1439
    a potential saving in disk space or performance gain.
1203
1440
 
1204
1441
    The branch *MUST* be on a listable system such as local disk or sftp.
1249
1486
            last_revision = wt.last_revision()
1250
1487
 
1251
1488
        revision_ids = b.repository.get_ancestry(last_revision)
1252
 
        assert revision_ids[0] is None
1253
1489
        revision_ids.pop(0)
1254
1490
        for revision_id in revision_ids:
1255
1491
            self.outf.write(revision_id + '\n')
1261
1497
    Use this to create an empty branch, or before importing an
1262
1498
    existing project.
1263
1499
 
1264
 
    If there is a repository in a parent directory of the location, then 
 
1500
    If there is a repository in a parent directory of the location, then
1265
1501
    the history of the branch will be stored in the repository.  Otherwise
1266
1502
    init creates a standalone branch which carries its own history
1267
1503
    in the .bzr directory.
1287
1523
         RegistryOption('format',
1288
1524
                help='Specify a format for this branch. '
1289
1525
                'See "help formats".',
1290
 
                registry=bzrdir.format_registry,
1291
 
                converter=bzrdir.format_registry.make_bzrdir,
 
1526
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
 
1527
                converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1292
1528
                value_switches=True,
1293
1529
                title="Branch Format",
1294
1530
                ),
1322
1558
            _create_prefix(to_transport)
1323
1559
 
1324
1560
        try:
1325
 
            existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
 
1561
            a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1326
1562
        except errors.NotBranchError:
1327
1563
            # really a NotBzrDir error...
1328
1564
            create_branch = bzrdir.BzrDir.create_branch_convenience
1329
1565
            branch = create_branch(to_transport.base, format=format,
1330
1566
                                   possible_transports=[to_transport])
 
1567
            a_bzrdir = branch.bzrdir
1331
1568
        else:
1332
1569
            from bzrlib.transport.local import LocalTransport
1333
 
            if existing_bzrdir.has_branch():
 
1570
            if a_bzrdir.has_branch():
1334
1571
                if (isinstance(to_transport, LocalTransport)
1335
 
                    and not existing_bzrdir.has_workingtree()):
 
1572
                    and not a_bzrdir.has_workingtree()):
1336
1573
                        raise errors.BranchExistsWithoutWorkingTree(location)
1337
1574
                raise errors.AlreadyBranchError(location)
1338
 
            else:
1339
 
                branch = existing_bzrdir.create_branch()
1340
 
                existing_bzrdir.create_workingtree()
 
1575
            branch = a_bzrdir.create_branch()
 
1576
            a_bzrdir.create_workingtree()
1341
1577
        if append_revisions_only:
1342
1578
            try:
1343
1579
                branch.set_append_revisions_only(True)
1344
1580
            except errors.UpgradeRequired:
1345
1581
                raise errors.BzrCommandError('This branch format cannot be set'
1346
1582
                    ' to append-revisions-only.  Try --experimental-branch6')
 
1583
        if not is_quiet():
 
1584
            from bzrlib.info import describe_layout, describe_format
 
1585
            try:
 
1586
                tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
 
1587
            except (errors.NoWorkingTree, errors.NotLocalUrl):
 
1588
                tree = None
 
1589
            repository = branch.repository
 
1590
            layout = describe_layout(repository, branch, tree).lower()
 
1591
            format = describe_format(a_bzrdir, repository, branch, tree)
 
1592
            self.outf.write("Created a %s (format: %s)\n" % (layout, format))
 
1593
            if repository.is_shared():
 
1594
                #XXX: maybe this can be refactored into transport.path_or_url()
 
1595
                url = repository.bzrdir.root_transport.external_url()
 
1596
                try:
 
1597
                    url = urlutils.local_path_from_url(url)
 
1598
                except errors.InvalidURL:
 
1599
                    pass
 
1600
                self.outf.write("Using shared repository: %s\n" % url)
1347
1601
 
1348
1602
 
1349
1603
class cmd_init_repository(Command):
1373
1627
    takes_options = [RegistryOption('format',
1374
1628
                            help='Specify a format for this repository. See'
1375
1629
                                 ' "bzr help formats" for details.',
1376
 
                            registry=bzrdir.format_registry,
1377
 
                            converter=bzrdir.format_registry.make_bzrdir,
 
1630
                            lazy_registry=('bzrlib.bzrdir', 'format_registry'),
 
1631
                            converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1378
1632
                            value_switches=True, title='Repository format'),
1379
1633
                     Option('no-trees',
1380
1634
                             help='Branches in the repository will default to'
1395
1649
        newdir = format.initialize_on_transport(to_transport)
1396
1650
        repo = newdir.create_repository(shared=True)
1397
1651
        repo.set_make_working_trees(not no_trees)
 
1652
        if not is_quiet():
 
1653
            from bzrlib.info import show_bzrdir_info
 
1654
            show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
1398
1655
 
1399
1656
 
1400
1657
class cmd_diff(Command):
1401
1658
    """Show differences in the working tree, between revisions or branches.
1402
 
    
 
1659
 
1403
1660
    If no arguments are given, all changes for the current tree are listed.
1404
1661
    If files are given, only the changes in those files are listed.
1405
1662
    Remote and multiple branches can be compared by using the --old and
1504
1761
                                         ' one or two revision specifiers')
1505
1762
 
1506
1763
        old_tree, new_tree, specific_files, extra_trees = \
1507
 
                _get_trees_to_diff(file_list, revision, old, new)
1508
 
        return show_diff_trees(old_tree, new_tree, sys.stdout, 
 
1764
                _get_trees_to_diff(file_list, revision, old, new,
 
1765
                apply_view=True)
 
1766
        return show_diff_trees(old_tree, new_tree, sys.stdout,
1509
1767
                               specific_files=specific_files,
1510
1768
                               external_diff_options=diff_options,
1511
1769
                               old_label=old_label, new_label=new_label,
1551
1809
 
1552
1810
    hidden = True
1553
1811
    _see_also = ['status', 'ls']
 
1812
    takes_options = [
 
1813
            Option('null',
 
1814
                   help='Write an ascii NUL (\\0) separator '
 
1815
                   'between files rather than a newline.')
 
1816
            ]
1554
1817
 
1555
1818
    @display_command
1556
 
    def run(self):
 
1819
    def run(self, null=False):
1557
1820
        tree = WorkingTree.open_containing(u'.')[0]
1558
1821
        td = tree.changes_from(tree.basis_tree())
1559
1822
        for path, id, kind, text_modified, meta_modified in td.modified:
1560
 
            self.outf.write(path + '\n')
 
1823
            if null:
 
1824
                self.outf.write(path + '\0')
 
1825
            else:
 
1826
                self.outf.write(osutils.quotefn(path) + '\n')
1561
1827
 
1562
1828
 
1563
1829
class cmd_added(Command):
1566
1832
 
1567
1833
    hidden = True
1568
1834
    _see_also = ['status', 'ls']
 
1835
    takes_options = [
 
1836
            Option('null',
 
1837
                   help='Write an ascii NUL (\\0) separator '
 
1838
                   'between files rather than a newline.')
 
1839
            ]
1569
1840
 
1570
1841
    @display_command
1571
 
    def run(self):
 
1842
    def run(self, null=False):
1572
1843
        wt = WorkingTree.open_containing(u'.')[0]
1573
1844
        wt.lock_read()
1574
1845
        try:
1585
1856
                    path = inv.id2path(file_id)
1586
1857
                    if not os.access(osutils.abspath(path), os.F_OK):
1587
1858
                        continue
1588
 
                    self.outf.write(path + '\n')
 
1859
                    if null:
 
1860
                        self.outf.write(path + '\0')
 
1861
                    else:
 
1862
                        self.outf.write(osutils.quotefn(path) + '\n')
1589
1863
            finally:
1590
1864
                basis.unlock()
1591
1865
        finally:
1614
1888
        raise errors.BzrCommandError(msg)
1615
1889
 
1616
1890
 
 
1891
def _parse_levels(s):
 
1892
    try:
 
1893
        return int(s)
 
1894
    except ValueError:
 
1895
        msg = "The levels argument must be an integer."
 
1896
        raise errors.BzrCommandError(msg)
 
1897
 
 
1898
 
1617
1899
class cmd_log(Command):
1618
 
    """Show log of a branch, file, or directory.
1619
 
 
1620
 
    By default show the log of the branch containing the working directory.
1621
 
 
1622
 
    To request a range of logs, you can use the command -r begin..end
1623
 
    -r revision requests a specific revision, -r ..end or -r begin.. are
1624
 
    also valid.
1625
 
 
1626
 
    :Examples:
1627
 
        Log the current branch::
1628
 
 
1629
 
            bzr log
1630
 
 
1631
 
        Log a file::
1632
 
 
1633
 
            bzr log foo.c
1634
 
 
1635
 
        Log the last 10 revisions of a branch::
1636
 
 
1637
 
            bzr log -r -10.. http://server/branch
 
1900
    """Show historical log for a branch or subset of a branch.
 
1901
 
 
1902
    log is bzr's default tool for exploring the history of a branch.
 
1903
    The branch to use is taken from the first parameter. If no parameters
 
1904
    are given, the branch containing the working directory is logged.
 
1905
    Here are some simple examples::
 
1906
 
 
1907
      bzr log                       log the current branch
 
1908
      bzr log foo.py                log a file in its branch
 
1909
      bzr log http://server/branch  log a branch on a server
 
1910
 
 
1911
    The filtering, ordering and information shown for each revision can
 
1912
    be controlled as explained below. By default, all revisions are
 
1913
    shown sorted (topologically) so that newer revisions appear before
 
1914
    older ones and descendants always appear before ancestors. If displayed,
 
1915
    merged revisions are shown indented under the revision in which they
 
1916
    were merged.
 
1917
 
 
1918
    :Output control:
 
1919
 
 
1920
      The log format controls how information about each revision is
 
1921
      displayed. The standard log formats are called ``long``, ``short``
 
1922
      and ``line``. The default is long. See ``bzr help log-formats``
 
1923
      for more details on log formats.
 
1924
 
 
1925
      The following options can be used to control what information is
 
1926
      displayed::
 
1927
 
 
1928
        -l N        display a maximum of N revisions
 
1929
        -n N        display N levels of revisions (0 for all, 1 for collapsed)
 
1930
        -v          display a status summary (delta) for each revision
 
1931
        -p          display a diff (patch) for each revision
 
1932
        --show-ids  display revision-ids (and file-ids), not just revnos
 
1933
 
 
1934
      Note that the default number of levels to display is a function of the
 
1935
      log format. If the -n option is not used, ``short`` and ``line`` show
 
1936
      just the top level (mainline) while ``long`` shows all levels of merged
 
1937
      revisions.
 
1938
 
 
1939
      Status summaries are shown using status flags like A, M, etc. To see
 
1940
      the changes explained using words like ``added`` and ``modified``
 
1941
      instead, use the -vv option.
 
1942
 
 
1943
    :Ordering control:
 
1944
 
 
1945
      To display revisions from oldest to newest, use the --forward option.
 
1946
      In most cases, using this option will have little impact on the total
 
1947
      time taken to produce a log, though --forward does not incrementally
 
1948
      display revisions like --reverse does when it can.
 
1949
 
 
1950
    :Revision filtering:
 
1951
 
 
1952
      The -r option can be used to specify what revision or range of revisions
 
1953
      to filter against. The various forms are shown below::
 
1954
 
 
1955
        -rX      display revision X
 
1956
        -rX..    display revision X and later
 
1957
        -r..Y    display up to and including revision Y
 
1958
        -rX..Y   display from X to Y inclusive
 
1959
 
 
1960
      See ``bzr help revisionspec`` for details on how to specify X and Y.
 
1961
      Some common examples are given below::
 
1962
 
 
1963
        -r-1                show just the tip
 
1964
        -r-10..             show the last 10 mainline revisions
 
1965
        -rsubmit:..         show what's new on this branch
 
1966
        -rancestor:path..   show changes since the common ancestor of this
 
1967
                            branch and the one at location path
 
1968
        -rdate:yesterday..  show changes since yesterday
 
1969
 
 
1970
      When logging a range of revisions using -rX..Y, log starts at
 
1971
      revision Y and searches back in history through the primary
 
1972
      ("left-hand") parents until it finds X. When logging just the
 
1973
      top level (using -n1), an error is reported if X is not found
 
1974
      along the way. If multi-level logging is used (-n0), X may be
 
1975
      a nested merge revision and the log will be truncated accordingly.
 
1976
 
 
1977
    :Path filtering:
 
1978
 
 
1979
      If a parameter is given and it's not a branch, the log will be filtered
 
1980
      to show only those revisions that changed the nominated file or
 
1981
      directory.
 
1982
 
 
1983
      Filenames are interpreted within their historical context. To log a
 
1984
      deleted file, specify a revision range so that the file existed at
 
1985
      the end or start of the range.
 
1986
 
 
1987
      Historical context is also important when interpreting pathnames of
 
1988
      renamed files/directories. Consider the following example:
 
1989
 
 
1990
      * revision 1: add tutorial.txt
 
1991
      * revision 2: modify tutorial.txt
 
1992
      * revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
 
1993
 
 
1994
      In this case:
 
1995
 
 
1996
      * ``bzr log guide.txt`` will log the file added in revision 1
 
1997
 
 
1998
      * ``bzr log tutorial.txt`` will log the new file added in revision 3
 
1999
 
 
2000
      * ``bzr log -r2 -p tutorial.txt`` will show the changes made to
 
2001
        the original file in revision 2.
 
2002
 
 
2003
      * ``bzr log -r2 -p guide.txt`` will display an error message as there
 
2004
        was no file called guide.txt in revision 2.
 
2005
 
 
2006
      Renames are always followed by log. By design, there is no need to
 
2007
      explicitly ask for this (and no way to stop logging a file back
 
2008
      until it was last renamed).
 
2009
 
 
2010
      Note: If the path is a directory, only revisions that directly changed
 
2011
      that directory object are currently shown. This is considered a bug.
 
2012
      (Support for filtering against multiple files and for files within a
 
2013
      directory is under development.)
 
2014
 
 
2015
    :Other filtering:
 
2016
 
 
2017
      The --message option can be used for finding revisions that match a
 
2018
      regular expression in a commit message.
 
2019
 
 
2020
    :Tips & tricks:
 
2021
 
 
2022
      GUI tools and IDEs are often better at exploring history than command
 
2023
      line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
 
2024
      respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
 
2025
      http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
 
2026
 
 
2027
      Web interfaces are often better at exploring history than command line
 
2028
      tools, particularly for branches on servers. You may prefer Loggerhead
 
2029
      or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
 
2030
 
 
2031
      You may find it useful to add the aliases below to ``bazaar.conf``::
 
2032
 
 
2033
        [ALIASES]
 
2034
        tip = log -r-1 -n1
 
2035
        top = log -r-10.. --short --forward
 
2036
        show = log -v -p -n1 --long
 
2037
 
 
2038
      ``bzr tip`` will then show the latest revision while ``bzr top``
 
2039
      will show the last 10 mainline revisions. To see the details of a
 
2040
      particular revision X,  ``bzr show -rX``.
 
2041
 
 
2042
      As many GUI tools and Web interfaces do, you may prefer viewing
 
2043
      history collapsed initially. If you are interested in looking deeper
 
2044
      into a particular merge X, use ``bzr log -n0 -rX``. If you like
 
2045
      working this way, you may wish to either:
 
2046
 
 
2047
      * change your default log format to short (or line)
 
2048
      * add this alias: log = log -n1
 
2049
 
 
2050
      ``bzr log -v`` on a branch with lots of history is currently
 
2051
      very slow. A fix for this issue is currently under development.
 
2052
      With or without that fix, it is recommended that a revision range
 
2053
      be given when using the -v option.
 
2054
 
 
2055
      bzr has a generic full-text matching plugin, bzr-search, that can be
 
2056
      used to find revisions matching user names, commit messages, etc.
 
2057
      Among other features, this plugin can find all revisions containing
 
2058
      a list of words but not others.
 
2059
 
 
2060
      When exploring non-mainline history on large projects with deep
 
2061
      history, the performance of log can be greatly improved by installing
 
2062
      the revnocache plugin. This plugin buffers historical information
 
2063
      trading disk space for faster speed.
1638
2064
    """
1639
 
 
1640
 
    # TODO: Make --revision support uuid: and hash: [future tag:] notation.
1641
 
 
1642
2065
    takes_args = ['location?']
 
2066
    _see_also = ['log-formats', 'revisionspec']
1643
2067
    takes_options = [
1644
2068
            Option('forward',
1645
2069
                   help='Show from oldest to newest.'),
1646
 
            Option('timezone',
1647
 
                   type=str,
1648
 
                   help='Display timezone as local, original, or utc.'),
 
2070
            'timezone',
1649
2071
            custom_help('verbose',
1650
2072
                   help='Show files changed in each revision.'),
1651
2073
            'show-ids',
1652
2074
            'revision',
 
2075
            Option('change',
 
2076
                   type=bzrlib.option._parse_revision_str,
 
2077
                   short_name='c',
 
2078
                   help='Show just the specified revision.'
 
2079
                   ' See also "help revisionspec".'),
1653
2080
            'log-format',
 
2081
            Option('levels',
 
2082
                   short_name='n',
 
2083
                   help='Number of levels to display - 0 for all, 1 for flat.',
 
2084
                   argname='N',
 
2085
                   type=_parse_levels),
1654
2086
            Option('message',
1655
2087
                   short_name='m',
1656
2088
                   help='Show revisions whose message matches this '
1661
2093
                   help='Limit the output to the first N revisions.',
1662
2094
                   argname='N',
1663
2095
                   type=_parse_limit),
 
2096
            Option('show-diff',
 
2097
                   short_name='p',
 
2098
                   help='Show changes made in each revision as a patch.'),
1664
2099
            ]
1665
2100
    encoding_type = 'replace'
1666
2101
 
1670
2105
            show_ids=False,
1671
2106
            forward=False,
1672
2107
            revision=None,
 
2108
            change=None,
1673
2109
            log_format=None,
 
2110
            levels=None,
1674
2111
            message=None,
1675
 
            limit=None):
1676
 
        from bzrlib.log import show_log
1677
 
        assert message is None or isinstance(message, basestring), \
1678
 
            "invalid message argument %r" % message
 
2112
            limit=None,
 
2113
            show_diff=False):
 
2114
        from bzrlib.log import show_log, _get_fileid_to_log
1679
2115
        direction = (forward and 'forward') or 'reverse'
1680
 
        
 
2116
 
 
2117
        if change is not None:
 
2118
            if len(change) > 1:
 
2119
                raise errors.RangeInChangeOption()
 
2120
            if revision is not None:
 
2121
                raise errors.BzrCommandError(
 
2122
                    '--revision and --change are mutually exclusive')
 
2123
            else:
 
2124
                revision = change
 
2125
 
1681
2126
        # log everything
1682
2127
        file_id = None
1683
2128
        if location:
1686
2131
            tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
1687
2132
                location)
1688
2133
            if fp != '':
1689
 
                if tree is None:
1690
 
                    tree = b.basis_tree()
1691
 
                file_id = tree.path2id(fp)
 
2134
                file_id = _get_fileid_to_log(revision, tree, b, fp)
1692
2135
                if file_id is None:
1693
2136
                    raise errors.BzrCommandError(
1694
 
                        "Path does not have any revision history: %s" %
 
2137
                        "Path unknown at end or start of revision range: %s" %
1695
2138
                        location)
1696
2139
        else:
1697
2140
            # local dir only
1698
 
            # FIXME ? log the current subdir only RBC 20060203 
 
2141
            # FIXME ? log the current subdir only RBC 20060203
1699
2142
            if revision is not None \
1700
2143
                    and len(revision) > 0 and revision[0].get_branch():
1701
2144
                location = revision[0].get_branch()
1706
2149
 
1707
2150
        b.lock_read()
1708
2151
        try:
1709
 
            if revision is None:
1710
 
                rev1 = None
1711
 
                rev2 = None
1712
 
            elif len(revision) == 1:
1713
 
                rev1 = rev2 = revision[0].in_history(b)
1714
 
            elif len(revision) == 2:
1715
 
                if revision[1].get_branch() != revision[0].get_branch():
1716
 
                    # b is taken from revision[0].get_branch(), and
1717
 
                    # show_log will use its revision_history. Having
1718
 
                    # different branches will lead to weird behaviors.
1719
 
                    raise errors.BzrCommandError(
1720
 
                        "Log doesn't accept two revisions in different"
1721
 
                        " branches.")
1722
 
                rev1 = revision[0].in_history(b)
1723
 
                rev2 = revision[1].in_history(b)
1724
 
            else:
1725
 
                raise errors.BzrCommandError(
1726
 
                    'bzr log --revision takes one or two values.')
1727
 
 
 
2152
            rev1, rev2 = _get_revision_range(revision, b, self.name())
1728
2153
            if log_format is None:
1729
2154
                log_format = log.log_formatter_registry.get_default(b)
1730
2155
 
1731
2156
            lf = log_format(show_ids=show_ids, to_file=self.outf,
1732
 
                            show_timezone=timezone)
 
2157
                            show_timezone=timezone,
 
2158
                            delta_format=get_verbosity_level(),
 
2159
                            levels=levels)
1733
2160
 
1734
2161
            show_log(b,
1735
2162
                     lf,
1739
2166
                     start_revision=rev1,
1740
2167
                     end_revision=rev2,
1741
2168
                     search=message,
1742
 
                     limit=limit)
 
2169
                     limit=limit,
 
2170
                     show_diff=show_diff)
1743
2171
        finally:
1744
2172
            b.unlock()
1745
2173
 
1746
2174
 
 
2175
def _get_revision_range(revisionspec_list, branch, command_name):
 
2176
    """Take the input of a revision option and turn it into a revision range.
 
2177
 
 
2178
    It returns RevisionInfo objects which can be used to obtain the rev_id's
 
2179
    of the desired revisons. It does some user input validations.
 
2180
    """
 
2181
    if revisionspec_list is None:
 
2182
        rev1 = None
 
2183
        rev2 = None
 
2184
    elif len(revisionspec_list) == 1:
 
2185
        rev1 = rev2 = revisionspec_list[0].in_history(branch)
 
2186
    elif len(revisionspec_list) == 2:
 
2187
        start_spec = revisionspec_list[0]
 
2188
        end_spec = revisionspec_list[1]
 
2189
        if end_spec.get_branch() != start_spec.get_branch():
 
2190
            # b is taken from revision[0].get_branch(), and
 
2191
            # show_log will use its revision_history. Having
 
2192
            # different branches will lead to weird behaviors.
 
2193
            raise errors.BzrCommandError(
 
2194
                "bzr %s doesn't accept two revisions in different"
 
2195
                " branches." % command_name)
 
2196
        rev1 = start_spec.in_history(branch)
 
2197
        # Avoid loading all of history when we know a missing
 
2198
        # end of range means the last revision ...
 
2199
        if end_spec.spec is None:
 
2200
            last_revno, last_revision_id = branch.last_revision_info()
 
2201
            rev2 = RevisionInfo(branch, last_revno, last_revision_id)
 
2202
        else:
 
2203
            rev2 = end_spec.in_history(branch)
 
2204
    else:
 
2205
        raise errors.BzrCommandError(
 
2206
            'bzr %s --revision takes one or two values.' % command_name)
 
2207
    return rev1, rev2
 
2208
 
 
2209
 
 
2210
def _revision_range_to_revid_range(revision_range):
 
2211
    rev_id1 = None
 
2212
    rev_id2 = None
 
2213
    if revision_range[0] is not None:
 
2214
        rev_id1 = revision_range[0].rev_id
 
2215
    if revision_range[1] is not None:
 
2216
        rev_id2 = revision_range[1].rev_id
 
2217
    return rev_id1, rev_id2
 
2218
 
1747
2219
def get_log_format(long=False, short=False, line=False, default='long'):
1748
2220
    log_format = default
1749
2221
    if long:
1788
2260
            Option('from-root',
1789
2261
                   help='Print paths relative to the root of the branch.'),
1790
2262
            Option('unknown', help='Print unknown files.'),
1791
 
            Option('versioned', help='Print versioned files.'),
 
2263
            Option('versioned', help='Print versioned files.',
 
2264
                   short_name='V'),
1792
2265
            Option('ignored', help='Print ignored files.'),
1793
2266
            Option('null',
1794
2267
                   help='Write an ascii NUL (\\0) separator '
1828
2301
            relpath = u''
1829
2302
        elif relpath:
1830
2303
            relpath += '/'
1831
 
        if revision is not None:
1832
 
            tree = branch.repository.revision_tree(
1833
 
                revision[0].in_history(branch).rev_id)
1834
 
        elif tree is None:
1835
 
            tree = branch.basis_tree()
 
2304
        if revision is not None or tree is None:
 
2305
            tree = _get_one_revision_tree('ls', revision, branch=branch)
 
2306
 
 
2307
        apply_view = False
 
2308
        if isinstance(tree, WorkingTree) and tree.supports_views():
 
2309
            view_files = tree.views.lookup_view()
 
2310
            if view_files:
 
2311
                apply_view = True
 
2312
                view_str = views.view_display_str(view_files)
 
2313
                note("ignoring files outside view: %s" % view_str)
1836
2314
 
1837
2315
        tree.lock_read()
1838
2316
        try:
1845
2323
                        continue
1846
2324
                    if kind is not None and fkind != kind:
1847
2325
                        continue
 
2326
                    if apply_view:
 
2327
                        try:
 
2328
                            views.check_path_in_view(tree, fp)
 
2329
                        except errors.FileOutsideView:
 
2330
                            continue
 
2331
                    kindch = entry.kind_character()
 
2332
                    outstring = fp + kindch
1848
2333
                    if verbose:
1849
 
                        kindch = entry.kind_character()
1850
 
                        outstring = '%-8s %s%s' % (fc, fp, kindch)
 
2334
                        outstring = '%-8s %s' % (fc, outstring)
1851
2335
                        if show_ids and fid is not None:
1852
2336
                            outstring = "%-50s %s" % (outstring, fid)
1853
2337
                        self.outf.write(outstring + '\n')
1864
2348
                        else:
1865
2349
                            my_id = ''
1866
2350
                        if show_ids:
1867
 
                            self.outf.write('%-50s %s\n' % (fp, my_id))
 
2351
                            self.outf.write('%-50s %s\n' % (outstring, my_id))
1868
2352
                        else:
1869
 
                            self.outf.write(fp + '\n')
 
2353
                            self.outf.write(outstring + '\n')
1870
2354
        finally:
1871
2355
            tree.unlock()
1872
2356
 
1887
2371
class cmd_ignore(Command):
1888
2372
    """Ignore specified files or patterns.
1889
2373
 
 
2374
    See ``bzr help patterns`` for details on the syntax of patterns.
 
2375
 
1890
2376
    To remove patterns from the ignore list, edit the .bzrignore file.
1891
 
 
1892
 
    Trailing slashes on patterns are ignored. 
1893
 
    If the pattern contains a slash or is a regular expression, it is compared 
1894
 
    to the whole path from the branch root.  Otherwise, it is compared to only
1895
 
    the last component of the path.  To match a file only in the root 
1896
 
    directory, prepend './'.
1897
 
 
1898
 
    Ignore patterns specifying absolute paths are not allowed.
1899
 
 
1900
 
    Ignore patterns may include globbing wildcards such as::
1901
 
 
1902
 
      ? - Matches any single character except '/'
1903
 
      * - Matches 0 or more characters except '/'
1904
 
      /**/ - Matches 0 or more directories in a path
1905
 
      [a-z] - Matches a single character from within a group of characters
1906
 
 
1907
 
    Ignore patterns may also be Python regular expressions.  
1908
 
    Regular expression ignore patterns are identified by a 'RE:' prefix 
1909
 
    followed by the regular expression.  Regular expression ignore patterns
1910
 
    may not include named or numbered groups.
1911
 
 
1912
 
    Note: ignore patterns containing shell wildcards must be quoted from 
 
2377
    After adding, editing or deleting that file either indirectly by
 
2378
    using this command or directly by using an editor, be sure to commit
 
2379
    it.
 
2380
 
 
2381
    Note: ignore patterns containing shell wildcards must be quoted from
1913
2382
    the shell on Unix.
1914
2383
 
1915
2384
    :Examples:
1928
2397
        Ignore .o files under the lib directory::
1929
2398
 
1930
2399
            bzr ignore "RE:lib/.*\.o"
 
2400
 
 
2401
        Ignore everything but the "debian" toplevel directory::
 
2402
 
 
2403
            bzr ignore "RE:(?!debian/).*"
1931
2404
    """
1932
2405
 
1933
 
    _see_also = ['status', 'ignored']
 
2406
    _see_also = ['status', 'ignored', 'patterns']
1934
2407
    takes_args = ['name_pattern*']
1935
2408
    takes_options = [
1936
2409
        Option('old-default-rules',
1937
2410
               help='Write out the ignore rules bzr < 0.9 always used.')
1938
2411
        ]
1939
 
    
 
2412
 
1940
2413
    def run(self, name_pattern_list=None, old_default_rules=None):
1941
 
        from bzrlib.atomicfile import AtomicFile
 
2414
        from bzrlib import ignores
1942
2415
        if old_default_rules is not None:
1943
2416
            # dump the rules and exit
1944
2417
            for pattern in ignores.OLD_DEFAULTS:
1947
2420
        if not name_pattern_list:
1948
2421
            raise errors.BzrCommandError("ignore requires at least one "
1949
2422
                                  "NAME_PATTERN or --old-default-rules")
1950
 
        name_pattern_list = [globbing.normalize_pattern(p) 
 
2423
        name_pattern_list = [globbing.normalize_pattern(p)
1951
2424
                             for p in name_pattern_list]
1952
2425
        for name_pattern in name_pattern_list:
1953
 
            if (name_pattern[0] == '/' or 
 
2426
            if (name_pattern[0] == '/' or
1954
2427
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
1955
2428
                raise errors.BzrCommandError(
1956
2429
                    "NAME_PATTERN should not be an absolute path")
1957
2430
        tree, relpath = WorkingTree.open_containing(u'.')
1958
 
        ifn = tree.abspath('.bzrignore')
1959
 
        if os.path.exists(ifn):
1960
 
            f = open(ifn, 'rt')
1961
 
            try:
1962
 
                igns = f.read().decode('utf-8')
1963
 
            finally:
1964
 
                f.close()
1965
 
        else:
1966
 
            igns = ''
1967
 
 
1968
 
        # TODO: If the file already uses crlf-style termination, maybe
1969
 
        # we should use that for the newly added lines?
1970
 
 
1971
 
        if igns and igns[-1] != '\n':
1972
 
            igns += '\n'
1973
 
        for name_pattern in name_pattern_list:
1974
 
            igns += name_pattern + '\n'
1975
 
 
1976
 
        f = AtomicFile(ifn, 'wb')
1977
 
        try:
1978
 
            f.write(igns.encode('utf-8'))
1979
 
            f.commit()
1980
 
        finally:
1981
 
            f.close()
1982
 
 
1983
 
        if not tree.path2id('.bzrignore'):
1984
 
            tree.add(['.bzrignore'])
1985
 
 
 
2431
        ignores.tree_ignores_add_patterns(tree, name_pattern_list)
1986
2432
        ignored = globbing.Globster(name_pattern_list)
1987
2433
        matches = []
1988
2434
        tree.lock_read()
1995
2441
        tree.unlock()
1996
2442
        if len(matches) > 0:
1997
2443
            print "Warning: the following files are version controlled and" \
1998
 
                  " match your ignore pattern:\n%s" % ("\n".join(matches),)
 
2444
                  " match your ignore pattern:\n%s" \
 
2445
                  "\nThese files will continue to be version controlled" \
 
2446
                  " unless you 'bzr remove' them." % ("\n".join(matches),)
 
2447
 
1999
2448
 
2000
2449
class cmd_ignored(Command):
2001
2450
    """List ignored files and the patterns that matched them.
 
2451
 
 
2452
    List all the ignored files and the ignore pattern that caused the file to
 
2453
    be ignored.
 
2454
 
 
2455
    Alternatively, to list just the files::
 
2456
 
 
2457
        bzr ls --ignored
2002
2458
    """
2003
2459
 
2004
2460
    encoding_type = 'replace'
2005
 
    _see_also = ['ignore']
 
2461
    _see_also = ['ignore', 'ls']
2006
2462
 
2007
2463
    @display_command
2008
2464
    def run(self):
2027
2483
    """
2028
2484
    hidden = True
2029
2485
    takes_args = ['revno']
2030
 
    
 
2486
 
2031
2487
    @display_command
2032
2488
    def run(self, revno):
2033
2489
        try:
2066
2522
         zip                          .zip
2067
2523
      =================       =========================
2068
2524
    """
2069
 
    takes_args = ['dest', 'branch?']
 
2525
    takes_args = ['dest', 'branch_or_subdir?']
2070
2526
    takes_options = [
2071
2527
        Option('format',
2072
2528
               help="Type of file to export to.",
2073
2529
               type=unicode),
2074
2530
        'revision',
 
2531
        Option('filters', help='Apply content filters to export the '
 
2532
                'convenient form.'),
2075
2533
        Option('root',
2076
2534
               type=str,
2077
2535
               help="Name of the root directory inside the exported file."),
2078
2536
        ]
2079
 
    def run(self, dest, branch=None, revision=None, format=None, root=None):
 
2537
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
 
2538
        root=None, filters=False):
2080
2539
        from bzrlib.export import export
2081
2540
 
2082
 
        if branch is None:
 
2541
        if branch_or_subdir is None:
2083
2542
            tree = WorkingTree.open_containing(u'.')[0]
2084
2543
            b = tree.branch
2085
 
        else:
2086
 
            b = Branch.open(branch)
2087
 
            
2088
 
        if revision is None:
2089
 
            # should be tree.last_revision  FIXME
2090
 
            rev_id = b.last_revision()
2091
 
        else:
2092
 
            if len(revision) != 1:
2093
 
                raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
2094
 
            rev_id = revision[0].in_history(b).rev_id
2095
 
        t = b.repository.revision_tree(rev_id)
 
2544
            subdir = None
 
2545
        else:
 
2546
            b, subdir = Branch.open_containing(branch_or_subdir)
 
2547
            tree = None
 
2548
 
 
2549
        rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
2096
2550
        try:
2097
 
            export(t, dest, format, root)
 
2551
            export(rev_tree, dest, format, root, subdir, filtered=filters)
2098
2552
        except errors.NoSuchExportFormat, e:
2099
2553
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2100
2554
 
2105
2559
    If no revision is nominated, the last revision is used.
2106
2560
 
2107
2561
    Note: Take care to redirect standard output when using this command on a
2108
 
    binary file. 
 
2562
    binary file.
2109
2563
    """
2110
2564
 
2111
2565
    _see_also = ['ls']
2112
2566
    takes_options = [
2113
2567
        Option('name-from-revision', help='The path name in the old tree.'),
 
2568
        Option('filters', help='Apply content filters to display the '
 
2569
                'convenience form.'),
2114
2570
        'revision',
2115
2571
        ]
2116
2572
    takes_args = ['filename']
2117
2573
    encoding_type = 'exact'
2118
2574
 
2119
2575
    @display_command
2120
 
    def run(self, filename, revision=None, name_from_revision=False):
 
2576
    def run(self, filename, revision=None, name_from_revision=False,
 
2577
            filters=False):
2121
2578
        if revision is not None and len(revision) != 1:
2122
2579
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
2123
2580
                                         " one revision specifier")
2126
2583
        branch.lock_read()
2127
2584
        try:
2128
2585
            return self._run(tree, branch, relpath, filename, revision,
2129
 
                             name_from_revision)
 
2586
                             name_from_revision, filters)
2130
2587
        finally:
2131
2588
            branch.unlock()
2132
2589
 
2133
 
    def _run(self, tree, b, relpath, filename, revision, name_from_revision):
 
2590
    def _run(self, tree, b, relpath, filename, revision, name_from_revision,
 
2591
        filtered):
2134
2592
        if tree is None:
2135
2593
            tree = b.basis_tree()
2136
 
        if revision is None:
2137
 
            revision_id = b.last_revision()
2138
 
        else:
2139
 
            revision_id = revision[0].in_history(b).rev_id
 
2594
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2140
2595
 
2141
 
        cur_file_id = tree.path2id(relpath)
2142
 
        rev_tree = b.repository.revision_tree(revision_id)
2143
2596
        old_file_id = rev_tree.path2id(relpath)
2144
 
        
 
2597
 
2145
2598
        if name_from_revision:
 
2599
            # Try in revision if requested
2146
2600
            if old_file_id is None:
2147
 
                raise errors.BzrCommandError("%r is not present in revision %s"
2148
 
                                                % (filename, revision_id))
 
2601
                raise errors.BzrCommandError(
 
2602
                    "%r is not present in revision %s" % (
 
2603
                        filename, rev_tree.get_revision_id()))
2149
2604
            else:
2150
 
                rev_tree.print_file(old_file_id)
2151
 
        elif cur_file_id is not None:
2152
 
            rev_tree.print_file(cur_file_id)
2153
 
        elif old_file_id is not None:
2154
 
            rev_tree.print_file(old_file_id)
2155
 
        else:
2156
 
            raise errors.BzrCommandError("%r is not present in revision %s" %
2157
 
                                         (filename, revision_id))
 
2605
                content = rev_tree.get_file_text(old_file_id)
 
2606
        else:
 
2607
            cur_file_id = tree.path2id(relpath)
 
2608
            found = False
 
2609
            if cur_file_id is not None:
 
2610
                # Then try with the actual file id
 
2611
                try:
 
2612
                    content = rev_tree.get_file_text(cur_file_id)
 
2613
                    found = True
 
2614
                except errors.NoSuchId:
 
2615
                    # The actual file id didn't exist at that time
 
2616
                    pass
 
2617
            if not found and old_file_id is not None:
 
2618
                # Finally try with the old file id
 
2619
                content = rev_tree.get_file_text(old_file_id)
 
2620
                found = True
 
2621
            if not found:
 
2622
                # Can't be found anywhere
 
2623
                raise errors.BzrCommandError(
 
2624
                    "%r is not present in revision %s" % (
 
2625
                        filename, rev_tree.get_revision_id()))
 
2626
        if filtered:
 
2627
            from bzrlib.filters import (
 
2628
                ContentFilterContext,
 
2629
                filtered_output_bytes,
 
2630
                )
 
2631
            filters = rev_tree._content_filter_stack(relpath)
 
2632
            chunks = content.splitlines(True)
 
2633
            content = filtered_output_bytes(chunks, filters,
 
2634
                ContentFilterContext(relpath, rev_tree))
 
2635
            self.outf.writelines(content)
 
2636
        else:
 
2637
            self.outf.write(content)
2158
2638
 
2159
2639
 
2160
2640
class cmd_local_time_offset(Command):
2161
2641
    """Show the offset in seconds from GMT to local time."""
2162
 
    hidden = True    
 
2642
    hidden = True
2163
2643
    @display_command
2164
2644
    def run(self):
2165
2645
        print osutils.local_time_offset()
2168
2648
 
2169
2649
class cmd_commit(Command):
2170
2650
    """Commit changes into a new revision.
2171
 
    
 
2651
 
2172
2652
    If no arguments are given, the entire tree is committed.
2173
2653
 
2174
2654
    If selected files are specified, only changes to those files are
2175
 
    committed.  If a directory is specified then the directory and everything 
 
2655
    committed.  If a directory is specified then the directory and everything
2176
2656
    within it is committed.
2177
2657
 
 
2658
    When excludes are given, they take precedence over selected files.
 
2659
    For example, too commit only changes within foo, but not changes within
 
2660
    foo/bar::
 
2661
 
 
2662
      bzr commit foo -x foo/bar
 
2663
 
2178
2664
    If author of the change is not the same person as the committer, you can
2179
2665
    specify the author's name using the --author option. The name should be
2180
2666
    in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
 
2667
    If there is more than one author of the change you can specify the option
 
2668
    multiple times, once for each author.
2181
2669
 
2182
2670
    A selected-file commit may fail in some cases where the committed
2183
2671
    tree would be invalid. Consider::
2210
2698
    _see_also = ['bugs', 'uncommit']
2211
2699
    takes_args = ['selected*']
2212
2700
    takes_options = [
 
2701
            ListOption('exclude', type=str, short_name='x',
 
2702
                help="Do not consider changes made to a given path."),
2213
2703
            Option('message', type=unicode,
2214
2704
                   short_name='m',
2215
2705
                   help="Description of the new revision."),
2224
2714
                    help="Refuse to commit if there are unknown "
2225
2715
                    "files in the working tree."),
2226
2716
             ListOption('fixes', type=str,
2227
 
                    help="Mark a bug as being fixed by this revision."),
2228
 
             Option('author', type=unicode,
 
2717
                    help="Mark a bug as being fixed by this revision "
 
2718
                         "(see \"bzr help bugs\")."),
 
2719
             ListOption('author', type=unicode,
2229
2720
                    help="Set the author's name, if it's different "
2230
2721
                         "from the committer."),
2231
2722
             Option('local',
2240
2731
             ]
2241
2732
    aliases = ['ci', 'checkin']
2242
2733
 
2243
 
    def _get_bug_fix_properties(self, fixes, branch):
2244
 
        properties = []
 
2734
    def _iter_bug_fix_urls(self, fixes, branch):
2245
2735
        # Configure the properties for bug fixing attributes.
2246
2736
        for fixed_bug in fixes:
2247
2737
            tokens = fixed_bug.split(':')
2248
2738
            if len(tokens) != 2:
2249
2739
                raise errors.BzrCommandError(
2250
 
                    "Invalid bug %s. Must be in the form of 'tag:id'. "
2251
 
                    "Commit refused." % fixed_bug)
 
2740
                    "Invalid bug %s. Must be in the form of 'tracker:id'. "
 
2741
                    "See \"bzr help bugs\" for more information on this "
 
2742
                    "feature.\nCommit refused." % fixed_bug)
2252
2743
            tag, bug_id = tokens
2253
2744
            try:
2254
 
                bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
 
2745
                yield bugtracker.get_bug_url(tag, branch, bug_id)
2255
2746
            except errors.UnknownBugTrackerAbbreviation:
2256
2747
                raise errors.BzrCommandError(
2257
2748
                    'Unrecognized bug %s. Commit refused.' % fixed_bug)
2258
 
            except errors.MalformedBugIdentifier:
 
2749
            except errors.MalformedBugIdentifier, e:
2259
2750
                raise errors.BzrCommandError(
2260
 
                    "Invalid bug identifier for %s. Commit refused."
2261
 
                    % fixed_bug)
2262
 
            properties.append('%s fixed' % bug_url)
2263
 
        return '\n'.join(properties)
 
2751
                    "%s\nCommit refused." % (str(e),))
2264
2752
 
2265
2753
    def run(self, message=None, file=None, verbose=False, selected_list=None,
2266
2754
            unchanged=False, strict=False, local=False, fixes=None,
2267
 
            author=None, show_diff=False):
 
2755
            author=None, show_diff=False, exclude=None):
2268
2756
        from bzrlib.errors import (
2269
2757
            PointlessCommit,
2270
2758
            ConflictsInTree,
2272
2760
        )
2273
2761
        from bzrlib.msgeditor import (
2274
2762
            edit_commit_message_encoded,
 
2763
            generate_commit_message_template,
2275
2764
            make_commit_message_template_encoded
2276
2765
        )
2277
2766
 
2278
2767
        # TODO: Need a blackbox test for invoking the external editor; may be
2279
2768
        # slightly problematic to run this cross-platform.
2280
2769
 
2281
 
        # TODO: do more checks that the commit will succeed before 
 
2770
        # TODO: do more checks that the commit will succeed before
2282
2771
        # spending the user's valuable time typing a commit message.
2283
2772
 
2284
2773
        properties = {}
2292
2781
 
2293
2782
        if fixes is None:
2294
2783
            fixes = []
2295
 
        bug_property = self._get_bug_fix_properties(fixes, tree.branch)
 
2784
        bug_property = bugtracker.encode_fixes_bug_urls(
 
2785
            self._iter_bug_fix_urls(fixes, tree.branch))
2296
2786
        if bug_property:
2297
2787
            properties['bugs'] = bug_property
2298
2788
 
2305
2795
            if my_message is None and not file:
2306
2796
                t = make_commit_message_template_encoded(tree,
2307
2797
                        selected_list, diff=show_diff,
2308
 
                        output_encoding=bzrlib.user_encoding)
2309
 
                my_message = edit_commit_message_encoded(t)
 
2798
                        output_encoding=osutils.get_user_encoding())
 
2799
                start_message = generate_commit_message_template(commit_obj)
 
2800
                my_message = edit_commit_message_encoded(t,
 
2801
                    start_message=start_message)
2310
2802
                if my_message is None:
2311
2803
                    raise errors.BzrCommandError("please specify a commit"
2312
2804
                        " message with either --message or --file")
2314
2806
                raise errors.BzrCommandError(
2315
2807
                    "please specify either --message or --file")
2316
2808
            if file:
2317
 
                my_message = codecs.open(file, 'rt', 
2318
 
                                         bzrlib.user_encoding).read()
 
2809
                my_message = codecs.open(file, 'rt',
 
2810
                                         osutils.get_user_encoding()).read()
2319
2811
            if my_message == "":
2320
2812
                raise errors.BzrCommandError("empty commit message specified")
2321
2813
            return my_message
2325
2817
                        specific_files=selected_list,
2326
2818
                        allow_pointless=unchanged, strict=strict, local=local,
2327
2819
                        reporter=None, verbose=verbose, revprops=properties,
2328
 
                        author=author)
 
2820
                        authors=author,
 
2821
                        exclude=safe_relpath_files(tree, exclude))
2329
2822
        except PointlessCommit:
2330
2823
            # FIXME: This should really happen before the file is read in;
2331
2824
            # perhaps prepare the commit; get the message; then actually commit
2346
2839
 
2347
2840
 
2348
2841
class cmd_check(Command):
2349
 
    """Validate consistency of branch history.
2350
 
 
2351
 
    This command checks various invariants about the branch storage to
2352
 
    detect data corruption or bzr bugs.
2353
 
 
2354
 
    Output fields:
 
2842
    """Validate working tree structure, branch consistency and repository history.
 
2843
 
 
2844
    This command checks various invariants about branch and repository storage
 
2845
    to detect data corruption or bzr bugs.
 
2846
 
 
2847
    The working tree and branch checks will only give output if a problem is
 
2848
    detected. The output fields of the repository check are:
2355
2849
 
2356
2850
        revisions: This is just the number of revisions checked.  It doesn't
2357
2851
            indicate a problem.
2366
2860
            in the checked revisions.  Texts can be repeated when their file
2367
2861
            entries are modified, but the file contents are not.  It does not
2368
2862
            indicate a problem.
 
2863
 
 
2864
    If no restrictions are specified, all Bazaar data that is found at the given
 
2865
    location will be checked.
 
2866
 
 
2867
    :Examples:
 
2868
 
 
2869
        Check the tree and branch at 'foo'::
 
2870
 
 
2871
            bzr check --tree --branch foo
 
2872
 
 
2873
        Check only the repository at 'bar'::
 
2874
 
 
2875
            bzr check --repo bar
 
2876
 
 
2877
        Check everything at 'baz'::
 
2878
 
 
2879
            bzr check baz
2369
2880
    """
2370
2881
 
2371
2882
    _see_also = ['reconcile']
2372
 
    takes_args = ['branch?']
2373
 
    takes_options = ['verbose']
 
2883
    takes_args = ['path?']
 
2884
    takes_options = ['verbose',
 
2885
                     Option('branch', help="Check the branch related to the"
 
2886
                                           " current directory."),
 
2887
                     Option('repo', help="Check the repository related to the"
 
2888
                                         " current directory."),
 
2889
                     Option('tree', help="Check the working tree related to"
 
2890
                                         " the current directory.")]
2374
2891
 
2375
 
    def run(self, branch=None, verbose=False):
2376
 
        from bzrlib.check import check
2377
 
        if branch is None:
2378
 
            branch_obj = Branch.open_containing('.')[0]
2379
 
        else:
2380
 
            branch_obj = Branch.open(branch)
2381
 
        check(branch_obj, verbose)
2382
 
        # bit hacky, check the tree parent is accurate
2383
 
        try:
2384
 
            if branch is None:
2385
 
                tree = WorkingTree.open_containing('.')[0]
2386
 
            else:
2387
 
                tree = WorkingTree.open(branch)
2388
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
2389
 
            pass
2390
 
        else:
2391
 
            # This is a primitive 'check' for tree state. Currently this is not
2392
 
            # integrated into the main check logic as yet.
2393
 
            tree.lock_read()
2394
 
            try:
2395
 
                tree_basis = tree.basis_tree()
2396
 
                tree_basis.lock_read()
2397
 
                try:
2398
 
                    repo_basis = tree.branch.repository.revision_tree(
2399
 
                        tree.last_revision())
2400
 
                    if len(list(repo_basis._iter_changes(tree_basis))):
2401
 
                        raise errors.BzrCheckError(
2402
 
                            "Mismatched basis inventory content.")
2403
 
                    tree._validate()
2404
 
                finally:
2405
 
                    tree_basis.unlock()
2406
 
            finally:
2407
 
                tree.unlock()
 
2892
    def run(self, path=None, verbose=False, branch=False, repo=False,
 
2893
            tree=False):
 
2894
        from bzrlib.check import check_dwim
 
2895
        if path is None:
 
2896
            path = '.'
 
2897
        if not branch and not repo and not tree:
 
2898
            branch = repo = tree = True
 
2899
        check_dwim(path, verbose, do_branch=branch, do_repo=repo, do_tree=tree)
2408
2900
 
2409
2901
 
2410
2902
class cmd_upgrade(Command):
2421
2913
                    RegistryOption('format',
2422
2914
                        help='Upgrade to a specific format.  See "bzr help'
2423
2915
                             ' formats" for details.',
2424
 
                        registry=bzrdir.format_registry,
2425
 
                        converter=bzrdir.format_registry.make_bzrdir,
 
2916
                        lazy_registry=('bzrlib.bzrdir', 'format_registry'),
 
2917
                        converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
2426
2918
                        value_switches=True, title='Branch format'),
2427
2919
                    ]
2428
2920
 
2435
2927
 
2436
2928
class cmd_whoami(Command):
2437
2929
    """Show or set bzr user id.
2438
 
    
 
2930
 
2439
2931
    :Examples:
2440
2932
        Show the email of the current user::
2441
2933
 
2453
2945
                    ]
2454
2946
    takes_args = ['name?']
2455
2947
    encoding_type = 'replace'
2456
 
    
 
2948
 
2457
2949
    @display_command
2458
2950
    def run(self, email=False, branch=False, name=None):
2459
2951
        if name is None:
2474
2966
        except errors.NoEmailInUsername, e:
2475
2967
            warning('"%s" does not seem to contain an email address.  '
2476
2968
                    'This is allowed, but not recommended.', name)
2477
 
        
 
2969
 
2478
2970
        # use global config unless --branch given
2479
2971
        if branch:
2480
2972
            c = Branch.open_containing('.')[0].get_config()
2484
2976
 
2485
2977
 
2486
2978
class cmd_nick(Command):
2487
 
    """Print or set the branch nickname.  
2488
 
 
2489
 
    If unset, the tree root directory name is used as the nickname
2490
 
    To print the current nickname, execute with no argument.  
 
2979
    """Print or set the branch nickname.
 
2980
 
 
2981
    If unset, the tree root directory name is used as the nickname.
 
2982
    To print the current nickname, execute with no argument.
 
2983
 
 
2984
    Bound branches use the nickname of its master branch unless it is set
 
2985
    locally.
2491
2986
    """
2492
2987
 
2493
2988
    _see_also = ['info']
2504
2999
        print branch.nick
2505
3000
 
2506
3001
 
 
3002
class cmd_alias(Command):
 
3003
    """Set/unset and display aliases.
 
3004
 
 
3005
    :Examples:
 
3006
        Show the current aliases::
 
3007
 
 
3008
            bzr alias
 
3009
 
 
3010
        Show the alias specified for 'll'::
 
3011
 
 
3012
            bzr alias ll
 
3013
 
 
3014
        Set an alias for 'll'::
 
3015
 
 
3016
            bzr alias ll="log --line -r-10..-1"
 
3017
 
 
3018
        To remove an alias for 'll'::
 
3019
 
 
3020
            bzr alias --remove ll
 
3021
 
 
3022
    """
 
3023
    takes_args = ['name?']
 
3024
    takes_options = [
 
3025
        Option('remove', help='Remove the alias.'),
 
3026
        ]
 
3027
 
 
3028
    def run(self, name=None, remove=False):
 
3029
        if remove:
 
3030
            self.remove_alias(name)
 
3031
        elif name is None:
 
3032
            self.print_aliases()
 
3033
        else:
 
3034
            equal_pos = name.find('=')
 
3035
            if equal_pos == -1:
 
3036
                self.print_alias(name)
 
3037
            else:
 
3038
                self.set_alias(name[:equal_pos], name[equal_pos+1:])
 
3039
 
 
3040
    def remove_alias(self, alias_name):
 
3041
        if alias_name is None:
 
3042
            raise errors.BzrCommandError(
 
3043
                'bzr alias --remove expects an alias to remove.')
 
3044
        # If alias is not found, print something like:
 
3045
        # unalias: foo: not found
 
3046
        c = config.GlobalConfig()
 
3047
        c.unset_alias(alias_name)
 
3048
 
 
3049
    @display_command
 
3050
    def print_aliases(self):
 
3051
        """Print out the defined aliases in a similar format to bash."""
 
3052
        aliases = config.GlobalConfig().get_aliases()
 
3053
        for key, value in sorted(aliases.iteritems()):
 
3054
            self.outf.write('bzr alias %s="%s"\n' % (key, value))
 
3055
 
 
3056
    @display_command
 
3057
    def print_alias(self, alias_name):
 
3058
        from bzrlib.commands import get_alias
 
3059
        alias = get_alias(alias_name)
 
3060
        if alias is None:
 
3061
            self.outf.write("bzr alias: %s: not found\n" % alias_name)
 
3062
        else:
 
3063
            self.outf.write(
 
3064
                'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
 
3065
 
 
3066
    def set_alias(self, alias_name, alias_command):
 
3067
        """Save the alias in the global config."""
 
3068
        c = config.GlobalConfig()
 
3069
        c.set_alias(alias_name, alias_command)
 
3070
 
 
3071
 
2507
3072
class cmd_selftest(Command):
2508
3073
    """Run internal test suite.
2509
 
    
 
3074
 
2510
3075
    If arguments are given, they are regular expressions that say which tests
2511
3076
    should run.  Tests matching any expression are run, and other tests are
2512
3077
    not run.
2535
3100
    modified by plugins will not be tested, and tests provided by plugins will
2536
3101
    not be run.
2537
3102
 
2538
 
    Tests that need working space on disk use a common temporary directory, 
 
3103
    Tests that need working space on disk use a common temporary directory,
2539
3104
    typically inside $TMPDIR or /tmp.
2540
3105
 
2541
3106
    :Examples:
2596
3161
                            short_name='x',
2597
3162
                            help='Exclude tests that match this regular'
2598
3163
                                 ' expression.'),
 
3164
                     Option('subunit',
 
3165
                        help='Output test progress via subunit.'),
2599
3166
                     Option('strict', help='Fail on missing dependencies or '
2600
3167
                            'known failures.'),
2601
 
                     Option('coverage', type=str, argname="DIRECTORY",
2602
 
                            help='Generate line coverage report in this '
2603
 
                                 'directory.'),
 
3168
                     Option('load-list', type=str, argname='TESTLISTFILE',
 
3169
                            help='Load a test id list from a text file.'),
 
3170
                     ListOption('debugflag', type=str, short_name='E',
 
3171
                                help='Turn on a selftest debug flag.'),
 
3172
                     ListOption('starting-with', type=str, argname='TESTID',
 
3173
                                param_name='starting_with', short_name='s',
 
3174
                                help=
 
3175
                                'Load only the tests starting with TESTID.'),
2604
3176
                     ]
2605
3177
    encoding_type = 'replace'
2606
3178
 
 
3179
    def __init__(self):
 
3180
        Command.__init__(self)
 
3181
        self.additional_selftest_args = {}
 
3182
 
2607
3183
    def run(self, testspecs_list=None, verbose=False, one=False,
2608
3184
            transport=None, benchmark=None,
2609
3185
            lsprof_timed=None, cache_dir=None,
2610
3186
            first=False, list_only=False,
2611
 
            randomize=None, exclude=None, strict=False, coverage=None):
2612
 
        import bzrlib.ui
 
3187
            randomize=None, exclude=None, strict=False,
 
3188
            load_list=None, debugflag=None, starting_with=None, subunit=False):
2613
3189
        from bzrlib.tests import selftest
2614
3190
        import bzrlib.benchmarks as benchmarks
2615
3191
        from bzrlib.benchmarks import tree_creator
2616
3192
 
 
3193
        # Make deprecation warnings visible, unless -Werror is set
 
3194
        symbol_versioning.activate_deprecation_warnings(override=False)
 
3195
 
2617
3196
        if cache_dir is not None:
2618
3197
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2619
3198
        if not list_only:
2621
3200
            print '   %s (%s python%s)' % (
2622
3201
                    bzrlib.__path__[0],
2623
3202
                    bzrlib.version_string,
2624
 
                    '.'.join(map(str, sys.version_info)),
 
3203
                    bzrlib._format_version_tuple(sys.version_info),
2625
3204
                    )
2626
3205
        print
2627
3206
        if testspecs_list is not None:
2628
3207
            pattern = '|'.join(testspecs_list)
2629
3208
        else:
2630
3209
            pattern = ".*"
 
3210
        if subunit:
 
3211
            try:
 
3212
                from bzrlib.tests import SubUnitBzrRunner
 
3213
            except ImportError:
 
3214
                raise errors.BzrCommandError("subunit not available. subunit "
 
3215
                    "needs to be installed to use --subunit.")
 
3216
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
2631
3217
        if benchmark:
2632
3218
            test_suite_factory = benchmarks.test_suite
2633
3219
            # Unless user explicitly asks for quiet, be verbose in benchmarks
2638
3224
            test_suite_factory = None
2639
3225
            benchfile = None
2640
3226
        try:
2641
 
            result = selftest(verbose=verbose,
2642
 
                              pattern=pattern,
2643
 
                              stop_on_failure=one,
2644
 
                              transport=transport,
2645
 
                              test_suite_factory=test_suite_factory,
2646
 
                              lsprof_timed=lsprof_timed,
2647
 
                              bench_history=benchfile,
2648
 
                              matching_tests_first=first,
2649
 
                              list_only=list_only,
2650
 
                              random_seed=randomize,
2651
 
                              exclude_pattern=exclude,
2652
 
                              strict=strict,
2653
 
                              coverage_dir=coverage,
2654
 
                              )
 
3227
            selftest_kwargs = {"verbose": verbose,
 
3228
                              "pattern": pattern,
 
3229
                              "stop_on_failure": one,
 
3230
                              "transport": transport,
 
3231
                              "test_suite_factory": test_suite_factory,
 
3232
                              "lsprof_timed": lsprof_timed,
 
3233
                              "bench_history": benchfile,
 
3234
                              "matching_tests_first": first,
 
3235
                              "list_only": list_only,
 
3236
                              "random_seed": randomize,
 
3237
                              "exclude_pattern": exclude,
 
3238
                              "strict": strict,
 
3239
                              "load_list": load_list,
 
3240
                              "debug_flags": debugflag,
 
3241
                              "starting_with": starting_with
 
3242
                              }
 
3243
            selftest_kwargs.update(self.additional_selftest_args)
 
3244
            result = selftest(**selftest_kwargs)
2655
3245
        finally:
2656
3246
            if benchfile is not None:
2657
3247
                benchfile.close()
2658
3248
        if result:
2659
 
            info('tests passed')
 
3249
            note('tests passed')
2660
3250
        else:
2661
 
            info('tests failed')
 
3251
            note('tests failed')
2662
3252
        return int(not result)
2663
3253
 
2664
3254
 
2666
3256
    """Show version of bzr."""
2667
3257
 
2668
3258
    encoding_type = 'replace'
 
3259
    takes_options = [
 
3260
        Option("short", help="Print just the version number."),
 
3261
        ]
2669
3262
 
2670
3263
    @display_command
2671
 
    def run(self):
 
3264
    def run(self, short=False):
2672
3265
        from bzrlib.version import show_version
2673
 
        show_version(to_file=self.outf)
 
3266
        if short:
 
3267
            self.outf.write(bzrlib.version_string + '\n')
 
3268
        else:
 
3269
            show_version(to_file=self.outf)
2674
3270
 
2675
3271
 
2676
3272
class cmd_rocks(Command):
2689
3285
    #       merging only part of the history.
2690
3286
    takes_args = ['branch', 'other']
2691
3287
    hidden = True
2692
 
    
 
3288
 
2693
3289
    @display_command
2694
3290
    def run(self, branch, other):
2695
3291
        from bzrlib.revision import ensure_null
2696
 
        
 
3292
 
2697
3293
        branch1 = Branch.open_containing(branch)[0]
2698
3294
        branch2 = Branch.open_containing(other)[0]
2699
3295
        branch1.lock_read()
2715
3311
 
2716
3312
class cmd_merge(Command):
2717
3313
    """Perform a three-way merge.
2718
 
    
2719
 
    The branch is the branch you will merge from.  By default, it will merge
2720
 
    the latest revision.  If you specify a revision, that revision will be
2721
 
    merged.  If you specify two revisions, the first will be used as a BASE,
2722
 
    and the second one as OTHER.  Revision numbers are always relative to the
2723
 
    specified branch.
 
3314
 
 
3315
    The source of the merge can be specified either in the form of a branch,
 
3316
    or in the form of a path to a file containing a merge directive generated
 
3317
    with bzr send. If neither is specified, the default is the upstream branch
 
3318
    or the branch most recently merged using --remember.
 
3319
 
 
3320
    When merging a branch, by default the tip will be merged. To pick a different
 
3321
    revision, pass --revision. If you specify two values, the first will be used as
 
3322
    BASE and the second one as OTHER. Merging individual revisions, or a subset of
 
3323
    available revisions, like this is commonly referred to as "cherrypicking".
 
3324
 
 
3325
    Revision numbers are always relative to the branch being merged.
2724
3326
 
2725
3327
    By default, bzr will try to merge in all new work from the other
2726
3328
    branch, automatically determining an appropriate base.  If this
2727
3329
    fails, you may need to give an explicit base.
2728
 
    
 
3330
 
2729
3331
    Merge will do its best to combine the changes in two branches, but there
2730
3332
    are some kinds of problems only a human can fix.  When it encounters those,
2731
3333
    it will mark a conflict.  A conflict means that you need to fix something,
2741
3343
    The results of the merge are placed into the destination working
2742
3344
    directory, where they can be reviewed (with bzr diff), tested, and then
2743
3345
    committed to record the result of the merge.
2744
 
    
 
3346
 
2745
3347
    merge refuses to run if there are any uncommitted changes, unless
2746
3348
    --force is given.
2747
3349
 
2757
3359
        To merge the changes introduced by 82, without previous changes::
2758
3360
 
2759
3361
            bzr merge -r 81..82 ../bzr.dev
 
3362
 
 
3363
        To apply a merge directive contained in in /tmp/merge:
 
3364
 
 
3365
            bzr merge /tmp/merge
2760
3366
    """
2761
3367
 
2762
 
    _see_also = ['update', 'remerge', 'status-flags']
2763
 
    takes_args = ['branch?']
 
3368
    encoding_type = 'exact'
 
3369
    _see_also = ['update', 'remerge', 'status-flags', 'send']
 
3370
    takes_args = ['location?']
2764
3371
    takes_options = [
2765
3372
        'change',
2766
3373
        'revision',
2783
3390
               short_name='d',
2784
3391
               type=unicode,
2785
3392
               ),
 
3393
        Option('preview', help='Instead of merging, show a diff of the merge.')
2786
3394
    ]
2787
3395
 
2788
 
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2789
 
            show_base=False, reprocess=False, remember=False,
 
3396
    def run(self, location=None, revision=None, force=False,
 
3397
            merge_type=None, show_base=False, reprocess=None, remember=False,
2790
3398
            uncommitted=False, pull=False,
2791
3399
            directory=None,
 
3400
            preview=False,
2792
3401
            ):
2793
 
        # This is actually a branch (or merge-directive) *location*.
2794
 
        location = branch
2795
 
        del branch
2796
 
 
2797
3402
        if merge_type is None:
2798
3403
            merge_type = _mod_merge.Merge3Merger
2799
3404
 
2803
3408
        allow_pending = True
2804
3409
        verified = 'inapplicable'
2805
3410
        tree = WorkingTree.open_containing(directory)[0]
 
3411
 
 
3412
        # die as quickly as possible if there are uncommitted changes
 
3413
        try:
 
3414
            basis_tree = tree.revision_tree(tree.last_revision())
 
3415
        except errors.NoSuchRevision:
 
3416
            basis_tree = tree.basis_tree()
 
3417
        if not force:
 
3418
            changes = tree.changes_from(basis_tree)
 
3419
            if changes.has_changed():
 
3420
                raise errors.UncommittedChanges(tree)
 
3421
 
 
3422
        view_info = _get_view_info_for_change_reporter(tree)
2806
3423
        change_reporter = delta._ChangeReporter(
2807
 
            unversioned_filter=tree.is_ignored)
 
3424
            unversioned_filter=tree.is_ignored, view_info=view_info)
2808
3425
        cleanups = []
2809
3426
        try:
2810
3427
            pb = ui.ui_factory.nested_progress_bar()
2812
3429
            tree.lock_write()
2813
3430
            cleanups.append(tree.unlock)
2814
3431
            if location is not None:
2815
 
                mergeable, other_transport = _get_mergeable_helper(location)
2816
 
                if mergeable:
 
3432
                try:
 
3433
                    mergeable = bundle.read_mergeable_from_url(location,
 
3434
                        possible_transports=possible_transports)
 
3435
                except errors.NotABundle:
 
3436
                    mergeable = None
 
3437
                else:
2817
3438
                    if uncommitted:
2818
3439
                        raise errors.BzrCommandError('Cannot use --uncommitted'
2819
3440
                            ' with bundles or merge directives.')
2823
3444
                            'Cannot use -r with merge directives or bundles')
2824
3445
                    merger, verified = _mod_merge.Merger.from_mergeable(tree,
2825
3446
                       mergeable, pb)
2826
 
                possible_transports.append(other_transport)
2827
3447
 
2828
3448
            if merger is None and uncommitted:
2829
3449
                if revision is not None and len(revision) > 0:
2844
3464
            merger.merge_type = merge_type
2845
3465
            merger.reprocess = reprocess
2846
3466
            merger.show_base = show_base
2847
 
            merger.change_reporter = change_reporter
2848
3467
            self.sanity_check_merger(merger)
2849
3468
            if (merger.base_rev_id == merger.other_rev_id and
2850
 
                merger.other_rev_id != None):
 
3469
                merger.other_rev_id is not None):
2851
3470
                note('Nothing to do.')
2852
3471
                return 0
2853
3472
            if pull:
2858
3477
                                       merger.other_rev_id)
2859
3478
                    result.report(self.outf)
2860
3479
                    return 0
2861
 
            merger.check_basis(not force)
2862
 
            conflict_count = merger.do_merge()
2863
 
            if allow_pending:
2864
 
                merger.set_pending()
2865
 
            if verified == 'failed':
2866
 
                warning('Preview patch does not match changes')
2867
 
            if conflict_count != 0:
2868
 
                return 1
 
3480
            merger.check_basis(False)
 
3481
            if preview:
 
3482
                return self._do_preview(merger)
2869
3483
            else:
2870
 
                return 0
 
3484
                return self._do_merge(merger, change_reporter, allow_pending,
 
3485
                                      verified)
2871
3486
        finally:
2872
3487
            for cleanup in reversed(cleanups):
2873
3488
                cleanup()
2874
3489
 
 
3490
    def _do_preview(self, merger):
 
3491
        from bzrlib.diff import show_diff_trees
 
3492
        tree_merger = merger.make_merger()
 
3493
        tt = tree_merger.make_preview_transform()
 
3494
        try:
 
3495
            result_tree = tt.get_preview_tree()
 
3496
            show_diff_trees(merger.this_tree, result_tree, self.outf,
 
3497
                            old_label='', new_label='')
 
3498
        finally:
 
3499
            tt.finalize()
 
3500
 
 
3501
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
 
3502
        merger.change_reporter = change_reporter
 
3503
        conflict_count = merger.do_merge()
 
3504
        if allow_pending:
 
3505
            merger.set_pending()
 
3506
        if verified == 'failed':
 
3507
            warning('Preview patch does not match changes')
 
3508
        if conflict_count != 0:
 
3509
            return 1
 
3510
        else:
 
3511
            return 0
 
3512
 
2875
3513
    def sanity_check_merger(self, merger):
2876
3514
        if (merger.show_base and
2877
3515
            not merger.merge_type is _mod_merge.Merge3Merger):
2878
3516
            raise errors.BzrCommandError("Show-base is not supported for this"
2879
3517
                                         " merge type. %s" % merger.merge_type)
 
3518
        if merger.reprocess is None:
 
3519
            if merger.show_base:
 
3520
                merger.reprocess = False
 
3521
            else:
 
3522
                # Use reprocess if the merger supports it
 
3523
                merger.reprocess = merger.merge_type.supports_reprocess
2880
3524
        if merger.reprocess and not merger.merge_type.supports_reprocess:
2881
3525
            raise errors.BzrCommandError("Conflict reduction is not supported"
2882
3526
                                         " for merge type %s." %
2889
3533
                                possible_transports, pb):
2890
3534
        """Produce a merger from a location, assuming it refers to a branch."""
2891
3535
        from bzrlib.tag import _merge_tags_if_possible
2892
 
        assert revision is None or len(revision) < 3
2893
3536
        # find the branch locations
2894
 
        other_loc, location = self._select_branch_location(tree, location,
 
3537
        other_loc, user_location = self._select_branch_location(tree, location,
2895
3538
            revision, -1)
2896
3539
        if revision is not None and len(revision) == 2:
2897
 
            base_loc, location = self._select_branch_location(tree, location,
2898
 
                                                              revision, 0)
 
3540
            base_loc, _unused = self._select_branch_location(tree,
 
3541
                location, revision, 0)
2899
3542
        else:
2900
3543
            base_loc = other_loc
2901
3544
        # Open the branches
2911
3554
            other_revision_id = _mod_revision.ensure_null(
2912
3555
                other_branch.last_revision())
2913
3556
        else:
2914
 
            other_revision_id = \
2915
 
                _mod_revision.ensure_null(
2916
 
                    revision[-1].in_history(other_branch).rev_id)
 
3557
            other_revision_id = revision[-1].as_revision_id(other_branch)
2917
3558
        if (revision is not None and len(revision) == 2
2918
3559
            and revision[0] is not None):
2919
 
            base_revision_id = \
2920
 
                _mod_revision.ensure_null(
2921
 
                    revision[0].in_history(base_branch).rev_id)
 
3560
            base_revision_id = revision[0].as_revision_id(base_branch)
2922
3561
        else:
2923
3562
            base_revision_id = None
2924
3563
        # Remember where we merge from
2925
 
        if ((tree.branch.get_parent() is None or remember) and
2926
 
            other_branch is not None):
2927
 
            tree.branch.set_parent(other_branch.base)
 
3564
        if ((remember or tree.branch.get_submit_branch() is None) and
 
3565
             user_location is not None):
 
3566
            tree.branch.set_submit_branch(other_branch.base)
2928
3567
        _merge_tags_if_possible(other_branch, tree.branch)
2929
3568
        merger = _mod_merge.Merger.from_revision_ids(pb, tree,
2930
3569
            other_revision_id, base_revision_id, other_branch, base_branch)
2935
3574
            allow_pending = True
2936
3575
        return merger, allow_pending
2937
3576
 
2938
 
    def _select_branch_location(self, tree, location, revision=None,
 
3577
    def _select_branch_location(self, tree, user_location, revision=None,
2939
3578
                                index=None):
2940
3579
        """Select a branch location, according to possible inputs.
2941
3580
 
2943
3582
        ``revision`` and ``index`` must be supplied.)
2944
3583
 
2945
3584
        Otherwise, the ``location`` parameter is used.  If it is None, then the
2946
 
        ``parent`` location is used, and a note is printed.
 
3585
        ``submit`` or ``parent`` location is used, and a note is printed.
2947
3586
 
2948
3587
        :param tree: The working tree to select a branch for merging into
2949
3588
        :param location: The location entered by the user
2950
3589
        :param revision: The revision parameter to the command
2951
3590
        :param index: The index to use for the revision parameter.  Negative
2952
3591
            indices are permitted.
2953
 
        :return: (selected_location, default_location).  The default location
2954
 
            will be the user-entered location, if any, or else the remembered
2955
 
            location.
 
3592
        :return: (selected_location, user_location).  The default location
 
3593
            will be the user-entered location.
2956
3594
        """
2957
3595
        if (revision is not None and index is not None
2958
3596
            and revision[index] is not None):
2959
3597
            branch = revision[index].get_branch()
2960
3598
            if branch is not None:
2961
 
                return branch, location
2962
 
        location = self._get_remembered_parent(tree, location, 'Merging from')
2963
 
        return location, location
 
3599
                return branch, branch
 
3600
        if user_location is None:
 
3601
            location = self._get_remembered(tree, 'Merging from')
 
3602
        else:
 
3603
            location = user_location
 
3604
        return location, user_location
2964
3605
 
2965
 
    # TODO: move up to common parent; this isn't merge-specific anymore. 
2966
 
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
 
3606
    def _get_remembered(self, tree, verb_string):
2967
3607
        """Use tree.branch's parent if none was supplied.
2968
3608
 
2969
3609
        Report if the remembered location was used.
2970
3610
        """
2971
 
        if supplied_location is not None:
2972
 
            return supplied_location
2973
 
        stored_location = tree.branch.get_parent()
 
3611
        stored_location = tree.branch.get_submit_branch()
 
3612
        stored_location_type = "submit"
 
3613
        if stored_location is None:
 
3614
            stored_location = tree.branch.get_parent()
 
3615
            stored_location_type = "parent"
2974
3616
        mutter("%s", stored_location)
2975
3617
        if stored_location is None:
2976
3618
            raise errors.BzrCommandError("No location specified or remembered")
2977
 
        display_url = urlutils.unescape_for_display(stored_location,
2978
 
            self.outf.encoding)
2979
 
        self.outf.write("%s remembered location %s\n" % (verb_string,
2980
 
            display_url))
 
3619
        display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
 
3620
        note(u"%s remembered %s location %s", verb_string,
 
3621
                stored_location_type, display_url)
2981
3622
        return stored_location
2982
3623
 
2983
3624
 
2985
3626
    """Redo a merge.
2986
3627
 
2987
3628
    Use this if you want to try a different merge technique while resolving
2988
 
    conflicts.  Some merge techniques are better than others, and remerge 
 
3629
    conflicts.  Some merge techniques are better than others, and remerge
2989
3630
    lets you try different ones on different files.
2990
3631
 
2991
3632
    The options for remerge have the same meaning and defaults as the ones for
2995
3636
    :Examples:
2996
3637
        Re-do the merge of all conflicted files, and show the base text in
2997
3638
        conflict regions, in addition to the usual THIS and OTHER texts::
2998
 
      
 
3639
 
2999
3640
            bzr remerge --show-base
3000
3641
 
3001
3642
        Re-do the merge of "foobar", using the weave merge algorithm, with
3002
3643
        additional processing to reduce the size of conflict regions::
3003
 
      
 
3644
 
3004
3645
            bzr remerge --merge-type weave --reprocess foobar
3005
3646
    """
3006
3647
    takes_args = ['file*']
3036
3677
                    interesting_ids.add(file_id)
3037
3678
                    if tree.kind(file_id) != "directory":
3038
3679
                        continue
3039
 
                    
 
3680
 
3040
3681
                    for name, ie in tree.inventory.iter_entries(file_id):
3041
3682
                        interesting_ids.add(ie.file_id)
3042
3683
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3091
3732
    merge instead.  For example, "merge . --revision -2..-3" will remove the
3092
3733
    changes introduced by -2, without affecting the changes introduced by -1.
3093
3734
    Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
3094
 
    
 
3735
 
3095
3736
    By default, any files that have been manually changed will be backed up
3096
3737
    first.  (Files changed only by merge are not backed up.)  Backup files have
3097
3738
    '.~#~' appended to their name, where # is a number.
3126
3767
    def run(self, revision=None, no_backup=False, file_list=None,
3127
3768
            forget_merges=None):
3128
3769
        tree, file_list = tree_files(file_list)
3129
 
        if forget_merges:
3130
 
            tree.set_parent_ids(tree.get_parent_ids()[:1])
3131
 
        else:
3132
 
            self._revert_tree_to_revision(tree, revision, file_list, no_backup)
 
3770
        tree.lock_write()
 
3771
        try:
 
3772
            if forget_merges:
 
3773
                tree.set_parent_ids(tree.get_parent_ids()[:1])
 
3774
            else:
 
3775
                self._revert_tree_to_revision(tree, revision, file_list, no_backup)
 
3776
        finally:
 
3777
            tree.unlock()
3133
3778
 
3134
3779
    @staticmethod
3135
3780
    def _revert_tree_to_revision(tree, revision, file_list, no_backup):
3136
 
        if revision is None:
3137
 
            rev_id = tree.last_revision()
3138
 
        elif len(revision) != 1:
3139
 
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
3140
 
        else:
3141
 
            rev_id = revision[0].in_history(tree.branch).rev_id
 
3781
        rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
3142
3782
        pb = ui.ui_factory.nested_progress_bar()
3143
3783
        try:
3144
 
            tree.revert(file_list,
3145
 
                        tree.branch.repository.revision_tree(rev_id),
3146
 
                        not no_backup, pb, report_changes=True)
 
3784
            tree.revert(file_list, rev_tree, not no_backup, pb,
 
3785
                report_changes=True)
3147
3786
        finally:
3148
3787
            pb.finished()
3149
3788
 
3168
3807
            ]
3169
3808
    takes_args = ['topic?']
3170
3809
    aliases = ['?', '--help', '-?', '-h']
3171
 
    
 
3810
 
3172
3811
    @display_command
3173
3812
    def run(self, topic=None, long=False):
3174
3813
        import bzrlib.help
3185
3824
    takes_args = ['context?']
3186
3825
    aliases = ['s-c']
3187
3826
    hidden = True
3188
 
    
 
3827
 
3189
3828
    @display_command
3190
3829
    def run(self, context=None):
3191
3830
        import shellcomplete
3192
3831
        shellcomplete.shellcomplete(context)
3193
3832
 
3194
3833
 
3195
 
class cmd_fetch(Command):
3196
 
    """Copy in history from another branch but don't merge it.
3197
 
 
3198
 
    This is an internal method used for pull and merge.
3199
 
    """
3200
 
    hidden = True
3201
 
    takes_args = ['from_branch', 'to_branch']
3202
 
    def run(self, from_branch, to_branch):
3203
 
        from bzrlib.fetch import Fetcher
3204
 
        from_b = Branch.open(from_branch)
3205
 
        to_b = Branch.open(to_branch)
3206
 
        Fetcher(to_b, from_b)
3207
 
 
3208
 
 
3209
3834
class cmd_missing(Command):
3210
3835
    """Show unmerged/unpulled revisions between two branches.
3211
 
    
 
3836
 
3212
3837
    OTHER_BRANCH may be local or remote.
 
3838
 
 
3839
    To filter on a range of revisions, you can use the command -r begin..end
 
3840
    -r revision requests a specific revision, -r ..end or -r begin.. are
 
3841
    also valid.
 
3842
 
 
3843
    :Examples:
 
3844
 
 
3845
        Determine the missing revisions between this and the branch at the
 
3846
        remembered pull location::
 
3847
 
 
3848
            bzr missing
 
3849
 
 
3850
        Determine the missing revisions between this and another branch::
 
3851
 
 
3852
            bzr missing http://server/branch
 
3853
 
 
3854
        Determine the missing revisions up to a specific revision on the other
 
3855
        branch::
 
3856
 
 
3857
            bzr missing -r ..-10
 
3858
 
 
3859
        Determine the missing revisions up to a specific revision on this
 
3860
        branch::
 
3861
 
 
3862
            bzr missing --my-revision ..-10
3213
3863
    """
3214
3864
 
3215
3865
    _see_also = ['merge', 'pull']
3216
3866
    takes_args = ['other_branch?']
3217
3867
    takes_options = [
3218
 
            Option('reverse', 'Reverse the order of revisions.'),
3219
 
            Option('mine-only',
3220
 
                   'Display changes in the local branch only.'),
3221
 
            Option('this' , 'Same as --mine-only.'),
3222
 
            Option('theirs-only',
3223
 
                   'Display changes in the remote branch only.'),
3224
 
            Option('other', 'Same as --theirs-only.'),
3225
 
            'log-format',
3226
 
            'show-ids',
3227
 
            'verbose'
3228
 
            ]
 
3868
        Option('reverse', 'Reverse the order of revisions.'),
 
3869
        Option('mine-only',
 
3870
               'Display changes in the local branch only.'),
 
3871
        Option('this' , 'Same as --mine-only.'),
 
3872
        Option('theirs-only',
 
3873
               'Display changes in the remote branch only.'),
 
3874
        Option('other', 'Same as --theirs-only.'),
 
3875
        'log-format',
 
3876
        'show-ids',
 
3877
        'verbose',
 
3878
        custom_help('revision',
 
3879
             help='Filter on other branch revisions (inclusive). '
 
3880
                'See "help revisionspec" for details.'),
 
3881
        Option('my-revision',
 
3882
            type=_parse_revision_str,
 
3883
            help='Filter on local branch revisions (inclusive). '
 
3884
                'See "help revisionspec" for details.'),
 
3885
        Option('include-merges', 'Show merged revisions.'),
 
3886
        ]
3229
3887
    encoding_type = 'replace'
3230
3888
 
3231
3889
    @display_command
3232
3890
    def run(self, other_branch=None, reverse=False, mine_only=False,
3233
 
            theirs_only=False, log_format=None, long=False, short=False, line=False, 
3234
 
            show_ids=False, verbose=False, this=False, other=False):
 
3891
            theirs_only=False,
 
3892
            log_format=None, long=False, short=False, line=False,
 
3893
            show_ids=False, verbose=False, this=False, other=False,
 
3894
            include_merges=False, revision=None, my_revision=None):
3235
3895
        from bzrlib.missing import find_unmerged, iter_log_revisions
 
3896
        def message(s):
 
3897
            if not is_quiet():
 
3898
                self.outf.write(s)
3236
3899
 
3237
3900
        if this:
3238
 
          mine_only = this
 
3901
            mine_only = this
3239
3902
        if other:
3240
 
          theirs_only = other
 
3903
            theirs_only = other
 
3904
        # TODO: We should probably check that we don't have mine-only and
 
3905
        #       theirs-only set, but it gets complicated because we also have
 
3906
        #       this and other which could be used.
 
3907
        restrict = 'all'
 
3908
        if mine_only:
 
3909
            restrict = 'local'
 
3910
        elif theirs_only:
 
3911
            restrict = 'remote'
3241
3912
 
3242
3913
        local_branch = Branch.open_containing(u".")[0]
3243
3914
        parent = local_branch.get_parent()
3248
3919
                                             " or specified.")
3249
3920
            display_url = urlutils.unescape_for_display(parent,
3250
3921
                                                        self.outf.encoding)
3251
 
            self.outf.write("Using last location: " + display_url + "\n")
 
3922
            message("Using saved parent location: "
 
3923
                    + display_url + "\n")
3252
3924
 
3253
3925
        remote_branch = Branch.open(other_branch)
3254
3926
        if remote_branch.base == local_branch.base:
3255
3927
            remote_branch = local_branch
 
3928
 
 
3929
        local_revid_range = _revision_range_to_revid_range(
 
3930
            _get_revision_range(my_revision, local_branch,
 
3931
                self.name()))
 
3932
 
 
3933
        remote_revid_range = _revision_range_to_revid_range(
 
3934
            _get_revision_range(revision,
 
3935
                remote_branch, self.name()))
 
3936
 
3256
3937
        local_branch.lock_read()
3257
3938
        try:
3258
3939
            remote_branch.lock_read()
3259
3940
            try:
3260
 
                local_extra, remote_extra = find_unmerged(local_branch,
3261
 
                                                          remote_branch)
 
3941
                local_extra, remote_extra = find_unmerged(
 
3942
                    local_branch, remote_branch, restrict,
 
3943
                    backward=not reverse,
 
3944
                    include_merges=include_merges,
 
3945
                    local_revid_range=local_revid_range,
 
3946
                    remote_revid_range=remote_revid_range)
 
3947
 
3262
3948
                if log_format is None:
3263
3949
                    registry = log.log_formatter_registry
3264
3950
                    log_format = registry.get_default(local_branch)
3265
3951
                lf = log_format(to_file=self.outf,
3266
3952
                                show_ids=show_ids,
3267
3953
                                show_timezone='original')
3268
 
                if reverse is False:
3269
 
                    local_extra.reverse()
3270
 
                    remote_extra.reverse()
 
3954
 
 
3955
                status_code = 0
3271
3956
                if local_extra and not theirs_only:
3272
 
                    self.outf.write("You have %d extra revision(s):\n" %
3273
 
                                    len(local_extra))
 
3957
                    message("You have %d extra revision(s):\n" %
 
3958
                        len(local_extra))
3274
3959
                    for revision in iter_log_revisions(local_extra,
3275
3960
                                        local_branch.repository,
3276
3961
                                        verbose):
3277
3962
                        lf.log_revision(revision)
3278
3963
                    printed_local = True
 
3964
                    status_code = 1
3279
3965
                else:
3280
3966
                    printed_local = False
 
3967
 
3281
3968
                if remote_extra and not mine_only:
3282
3969
                    if printed_local is True:
3283
 
                        self.outf.write("\n\n\n")
3284
 
                    self.outf.write("You are missing %d revision(s):\n" %
3285
 
                                    len(remote_extra))
 
3970
                        message("\n\n\n")
 
3971
                    message("You are missing %d revision(s):\n" %
 
3972
                        len(remote_extra))
3286
3973
                    for revision in iter_log_revisions(remote_extra,
3287
3974
                                        remote_branch.repository,
3288
3975
                                        verbose):
3289
3976
                        lf.log_revision(revision)
3290
 
                if not remote_extra and not local_extra:
3291
 
                    status_code = 0
3292
 
                    self.outf.write("Branches are up to date.\n")
3293
 
                else:
3294
3977
                    status_code = 1
 
3978
 
 
3979
                if mine_only and not local_extra:
 
3980
                    # We checked local, and found nothing extra
 
3981
                    message('This branch is up to date.\n')
 
3982
                elif theirs_only and not remote_extra:
 
3983
                    # We checked remote, and found nothing extra
 
3984
                    message('Other branch is up to date.\n')
 
3985
                elif not (mine_only or theirs_only or local_extra or
 
3986
                          remote_extra):
 
3987
                    # We checked both branches, and neither one had extra
 
3988
                    # revisions
 
3989
                    message("Branches are up to date.\n")
3295
3990
            finally:
3296
3991
                remote_branch.unlock()
3297
3992
        finally:
3325
4020
 
3326
4021
class cmd_plugins(Command):
3327
4022
    """List the installed plugins.
3328
 
    
3329
 
    This command displays the list of installed plugins including the
3330
 
    path where each one is located and a short description of each.
 
4023
 
 
4024
    This command displays the list of installed plugins including
 
4025
    version of plugin and a short description of each.
 
4026
 
 
4027
    --verbose shows the path where each plugin is located.
3331
4028
 
3332
4029
    A plugin is an external component for Bazaar that extends the
3333
4030
    revision control system, by adding or replacing code in Bazaar.
3340
4037
    install them. Instructions are also provided there on how to
3341
4038
    write new plugins using the Python programming language.
3342
4039
    """
 
4040
    takes_options = ['verbose']
3343
4041
 
3344
4042
    @display_command
3345
 
    def run(self):
 
4043
    def run(self, verbose=False):
3346
4044
        import bzrlib.plugin
3347
4045
        from inspect import getdoc
 
4046
        result = []
3348
4047
        for name, plugin in bzrlib.plugin.plugins().items():
3349
 
            print plugin.path(), "[%s]" % plugin.__version__
 
4048
            version = plugin.__version__
 
4049
            if version == 'unknown':
 
4050
                version = ''
 
4051
            name_ver = '%s %s' % (name, version)
3350
4052
            d = getdoc(plugin.module)
3351
4053
            if d:
3352
 
                print '\t', d.split('\n')[0]
 
4054
                doc = d.split('\n')[0]
 
4055
            else:
 
4056
                doc = '(no description)'
 
4057
            result.append((name_ver, doc, plugin.path()))
 
4058
        for name_ver, doc, path in sorted(result):
 
4059
            print name_ver
 
4060
            print '   ', doc
 
4061
            if verbose:
 
4062
                print '   ', path
 
4063
            print
3353
4064
 
3354
4065
 
3355
4066
class cmd_testament(Command):
3367
4078
            testament_class = StrictTestament
3368
4079
        else:
3369
4080
            testament_class = Testament
3370
 
        b = WorkingTree.open_containing(branch)[0].branch
 
4081
        if branch == '.':
 
4082
            b = Branch.open_containing(branch)[0]
 
4083
        else:
 
4084
            b = Branch.open(branch)
3371
4085
        b.lock_read()
3372
4086
        try:
3373
4087
            if revision is None:
3374
4088
                rev_id = b.last_revision()
3375
4089
            else:
3376
 
                rev_id = revision[0].in_history(b).rev_id
 
4090
                rev_id = revision[0].as_revision_id(b)
3377
4091
            t = testament_class.from_revision(b.repository, rev_id)
3378
4092
            if long:
3379
4093
                sys.stdout.writelines(t.as_text_lines())
3389
4103
    This prints out the given file with an annotation on the left side
3390
4104
    indicating which revision, author and date introduced the change.
3391
4105
 
3392
 
    If the origin is the same for a run of consecutive lines, it is 
 
4106
    If the origin is the same for a run of consecutive lines, it is
3393
4107
    shown only at the top, unless the --all option is given.
3394
4108
    """
3395
4109
    # TODO: annotate directories; showing when each file was last changed
3396
 
    # TODO: if the working copy is modified, show annotations on that 
 
4110
    # TODO: if the working copy is modified, show annotations on that
3397
4111
    #       with new uncommitted lines marked
3398
4112
    aliases = ['ann', 'blame', 'praise']
3399
4113
    takes_args = ['filename']
3407
4121
    @display_command
3408
4122
    def run(self, filename, all=False, long=False, revision=None,
3409
4123
            show_ids=False):
3410
 
        from bzrlib.annotate import annotate_file
3411
 
        tree, relpath = WorkingTree.open_containing(filename)
3412
 
        branch = tree.branch
3413
 
        branch.lock_read()
 
4124
        from bzrlib.annotate import annotate_file, annotate_file_tree
 
4125
        wt, branch, relpath = \
 
4126
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
 
4127
        if wt is not None:
 
4128
            wt.lock_read()
 
4129
        else:
 
4130
            branch.lock_read()
3414
4131
        try:
3415
 
            if revision is None:
3416
 
                revision_id = branch.last_revision()
3417
 
            elif len(revision) != 1:
3418
 
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
 
4132
            tree = _get_one_revision_tree('annotate', revision, branch=branch)
 
4133
            if wt is not None:
 
4134
                file_id = wt.path2id(relpath)
3419
4135
            else:
3420
 
                revision_id = revision[0].in_history(branch).rev_id
3421
 
            file_id = tree.path2id(relpath)
 
4136
                file_id = tree.path2id(relpath)
3422
4137
            if file_id is None:
3423
4138
                raise errors.NotVersionedError(filename)
3424
 
            tree = branch.repository.revision_tree(revision_id)
3425
4139
            file_version = tree.inventory[file_id].revision
3426
 
            annotate_file(branch, file_version, file_id, long, all, self.outf,
3427
 
                          show_ids=show_ids)
 
4140
            if wt is not None and revision is None:
 
4141
                # If there is a tree and we're not annotating historical
 
4142
                # versions, annotate the working tree's content.
 
4143
                annotate_file_tree(wt, file_id, self.outf, long, all,
 
4144
                    show_ids=show_ids)
 
4145
            else:
 
4146
                annotate_file(branch, file_version, file_id, long, all, self.outf,
 
4147
                              show_ids=show_ids)
3428
4148
        finally:
3429
 
            branch.unlock()
 
4149
            if wt is not None:
 
4150
                wt.unlock()
 
4151
            else:
 
4152
                branch.unlock()
3430
4153
 
3431
4154
 
3432
4155
class cmd_re_sign(Command):
3436
4159
    hidden = True # is this right ?
3437
4160
    takes_args = ['revision_id*']
3438
4161
    takes_options = ['revision']
3439
 
    
 
4162
 
3440
4163
    def run(self, revision_id_list=None, revision=None):
3441
4164
        if revision_id_list is not None and revision is not None:
3442
4165
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
3502
4225
 
3503
4226
    Once converted into a checkout, commits must succeed on the master branch
3504
4227
    before they will be applied to the local branch.
 
4228
 
 
4229
    Bound branches use the nickname of its master branch unless it is set
 
4230
    locally, in which case binding will update the the local nickname to be
 
4231
    that of the master.
3505
4232
    """
3506
4233
 
3507
4234
    _see_also = ['checkouts', 'unbind']
3526
4253
        except errors.DivergedBranches:
3527
4254
            raise errors.BzrCommandError('These branches have diverged.'
3528
4255
                                         ' Try merging, and then bind again.')
 
4256
        if b.get_config().has_explicit_nickname():
 
4257
            b.nick = b_other.nick
3529
4258
 
3530
4259
 
3531
4260
class cmd_unbind(Command):
3556
4285
    specified revision.  For example, "bzr uncommit -r 15" will leave the
3557
4286
    branch at revision 15.
3558
4287
 
3559
 
    In the future, uncommit will create a revision bundle, which can then
3560
 
    be re-applied.
 
4288
    Uncommit leaves the working tree ready for a new commit.  The only change
 
4289
    it may make is to restore any pending merges that were present before
 
4290
    the commit.
3561
4291
    """
3562
4292
 
3563
4293
    # TODO: jam 20060108 Add an option to allow uncommit to remove
3567
4297
    _see_also = ['commit']
3568
4298
    takes_options = ['verbose', 'revision',
3569
4299
                    Option('dry-run', help='Don\'t actually make changes.'),
3570
 
                    Option('force', help='Say yes to all questions.')]
 
4300
                    Option('force', help='Say yes to all questions.'),
 
4301
                    Option('local',
 
4302
                           help="Only remove the commits from the local branch"
 
4303
                                " when in a checkout."
 
4304
                           ),
 
4305
                    ]
3571
4306
    takes_args = ['location?']
3572
4307
    aliases = []
3573
4308
    encoding_type = 'replace'
3574
4309
 
3575
4310
    def run(self, location=None,
3576
4311
            dry_run=False, verbose=False,
3577
 
            revision=None, force=False):
 
4312
            revision=None, force=False, local=False):
3578
4313
        if location is None:
3579
4314
            location = u'.'
3580
4315
        control, relpath = bzrdir.BzrDir.open_containing(location)
3590
4325
        else:
3591
4326
            b.lock_write()
3592
4327
        try:
3593
 
            return self._run(b, tree, dry_run, verbose, revision, force)
 
4328
            return self._run(b, tree, dry_run, verbose, revision, force,
 
4329
                             local=local)
3594
4330
        finally:
3595
4331
            if tree is not None:
3596
4332
                tree.unlock()
3597
4333
            else:
3598
4334
                b.unlock()
3599
4335
 
3600
 
    def _run(self, b, tree, dry_run, verbose, revision, force):
 
4336
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
3601
4337
        from bzrlib.log import log_formatter, show_log
3602
4338
        from bzrlib.uncommit import uncommit
3603
4339
 
3644
4380
                    print 'Canceled'
3645
4381
                    return 0
3646
4382
 
 
4383
        mutter('Uncommitting from {%s} to {%s}',
 
4384
               last_rev_id, rev_id)
3647
4385
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
3648
 
                 revno=revno)
 
4386
                 revno=revno, local=local)
 
4387
        note('You can restore the old tip by running:\n'
 
4388
             '  bzr pull . -r revid:%s', last_rev_id)
3649
4389
 
3650
4390
 
3651
4391
class cmd_break_lock(Command):
3655
4395
    holding the lock has been stopped.
3656
4396
 
3657
4397
    You can get information on what locks are open via the 'bzr info' command.
3658
 
    
 
4398
 
3659
4399
    :Examples:
3660
4400
        bzr break-lock
3661
4401
    """
3669
4409
            control.break_lock()
3670
4410
        except NotImplementedError:
3671
4411
            pass
3672
 
        
 
4412
 
3673
4413
 
3674
4414
class cmd_wait_until_signalled(Command):
3675
4415
    """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
3709
4449
                ),
3710
4450
        ]
3711
4451
 
3712
 
    def run(self, port=None, inet=False, directory=None, allow_writes=False):
 
4452
    def run_smart_server(self, smart_server):
 
4453
        """Run 'smart_server' forever, with no UI output at all."""
 
4454
        # For the duration of this server, no UI output is permitted. note
 
4455
        # that this may cause problems with blackbox tests. This should be
 
4456
        # changed with care though, as we dont want to use bandwidth sending
 
4457
        # progress over stderr to smart server clients!
3713
4458
        from bzrlib import lockdir
 
4459
        old_factory = ui.ui_factory
 
4460
        old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
 
4461
        try:
 
4462
            ui.ui_factory = ui.SilentUIFactory()
 
4463
            lockdir._DEFAULT_TIMEOUT_SECONDS = 0
 
4464
            smart_server.serve()
 
4465
        finally:
 
4466
            ui.ui_factory = old_factory
 
4467
            lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
 
4468
 
 
4469
    def get_host_and_port(self, port):
 
4470
        """Return the host and port to run the smart server on.
 
4471
 
 
4472
        If 'port' is None, the default host (`medium.BZR_DEFAULT_INTERFACE`)
 
4473
        and port (`medium.BZR_DEFAULT_PORT`) will be used.
 
4474
 
 
4475
        If 'port' has a colon in it, the string before the colon will be
 
4476
        interpreted as the host.
 
4477
 
 
4478
        :param port: A string of the port to run the server on.
 
4479
        :return: A tuple of (host, port), where 'host' is a host name or IP,
 
4480
            and port is an integer TCP/IP port.
 
4481
        """
 
4482
        from bzrlib.smart import medium
 
4483
        host = medium.BZR_DEFAULT_INTERFACE
 
4484
        if port is None:
 
4485
            port = medium.BZR_DEFAULT_PORT
 
4486
        else:
 
4487
            if ':' in port:
 
4488
                host, port = port.split(':')
 
4489
            port = int(port)
 
4490
        return host, port
 
4491
 
 
4492
    def get_smart_server(self, transport, inet, port):
 
4493
        """Construct a smart server.
 
4494
 
 
4495
        :param transport: The base transport from which branches will be
 
4496
            served.
 
4497
        :param inet: If True, serve over stdin and stdout. Used for running
 
4498
            from inet.
 
4499
        :param port: The port to listen on. By default, it's `
 
4500
            medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
 
4501
            information.
 
4502
        :return: A smart server.
 
4503
        """
3714
4504
        from bzrlib.smart import medium, server
 
4505
        if inet:
 
4506
            smart_server = medium.SmartServerPipeStreamMedium(
 
4507
                sys.stdin, sys.stdout, transport)
 
4508
        else:
 
4509
            host, port = self.get_host_and_port(port)
 
4510
            smart_server = server.SmartTCPServer(
 
4511
                transport, host=host, port=port)
 
4512
            note('listening on port: %s' % smart_server.port)
 
4513
        return smart_server
 
4514
 
 
4515
    def run(self, port=None, inet=False, directory=None, allow_writes=False):
3715
4516
        from bzrlib.transport import get_transport
3716
4517
        from bzrlib.transport.chroot import ChrootServer
3717
4518
        if directory is None:
3722
4523
        chroot_server = ChrootServer(get_transport(url))
3723
4524
        chroot_server.setUp()
3724
4525
        t = get_transport(chroot_server.get_url())
3725
 
        if inet:
3726
 
            smart_server = medium.SmartServerPipeStreamMedium(
3727
 
                sys.stdin, sys.stdout, t)
3728
 
        else:
3729
 
            host = medium.BZR_DEFAULT_INTERFACE
3730
 
            if port is None:
3731
 
                port = medium.BZR_DEFAULT_PORT
3732
 
            else:
3733
 
                if ':' in port:
3734
 
                    host, port = port.split(':')
3735
 
                port = int(port)
3736
 
            smart_server = server.SmartTCPServer(t, host=host, port=port)
3737
 
            print 'listening on port: ', smart_server.port
3738
 
            sys.stdout.flush()
3739
 
        # for the duration of this server, no UI output is permitted.
3740
 
        # note that this may cause problems with blackbox tests. This should
3741
 
        # be changed with care though, as we dont want to use bandwidth sending
3742
 
        # progress over stderr to smart server clients!
3743
 
        old_factory = ui.ui_factory
3744
 
        old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
3745
 
        try:
3746
 
            ui.ui_factory = ui.SilentUIFactory()
3747
 
            lockdir._DEFAULT_TIMEOUT_SECONDS = 0
3748
 
            smart_server.serve()
3749
 
        finally:
3750
 
            ui.ui_factory = old_factory
3751
 
            lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
 
4526
        smart_server = self.get_smart_server(t, inet, port)
 
4527
        self.run_smart_server(smart_server)
3752
4528
 
3753
4529
 
3754
4530
class cmd_join(Command):
3755
4531
    """Combine a subtree into its containing tree.
3756
 
    
 
4532
 
3757
4533
    This command is for experimental use only.  It requires the target tree
3758
4534
    to be in dirstate-with-subtree format, which cannot be converted into
3759
4535
    earlier formats.
3801
4577
            try:
3802
4578
                containing_tree.subsume(sub_tree)
3803
4579
            except errors.BadSubsumeSource, e:
3804
 
                raise errors.BzrCommandError("Cannot join %s.  %s" % 
 
4580
                raise errors.BzrCommandError("Cannot join %s.  %s" %
3805
4581
                                             (tree, e.reason))
3806
4582
 
3807
4583
 
3906
4682
            if len(revision) > 2:
3907
4683
                raise errors.BzrCommandError('bzr merge-directive takes '
3908
4684
                    'at most two one revision identifiers')
3909
 
            revision_id = revision[-1].in_history(branch).rev_id
 
4685
            revision_id = revision[-1].as_revision_id(branch)
3910
4686
            if len(revision) == 2:
3911
 
                base_revision_id = revision[0].in_history(branch).rev_id
3912
 
                base_revision_id = ensure_null(base_revision_id)
 
4687
                base_revision_id = revision[0].as_revision_id(branch)
3913
4688
        else:
3914
4689
            revision_id = branch.last_revision()
3915
4690
        revision_id = ensure_null(revision_id)
3933
4708
 
3934
4709
 
3935
4710
class cmd_send(Command):
3936
 
    """Mail or create a merge-directive for submiting changes.
 
4711
    """Mail or create a merge-directive for submitting changes.
3937
4712
 
3938
4713
    A merge directive provides many things needed for requesting merges:
3939
4714
 
3961
4736
    Mail is sent using your preferred mail program.  This should be transparent
3962
4737
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
3963
4738
    If the preferred client can't be found (or used), your editor will be used.
3964
 
    
 
4739
 
3965
4740
    To use a specific mail program, set the mail_client configuration option.
3966
4741
    (For Thunderbird 1.5, this works around some bugs.)  Supported values for
3967
 
    specific clients are "evolution", "kmail", "mutt", and "thunderbird";
3968
 
    generic options are "default", "editor", "mapi", and "xdg-email".
 
4742
    specific clients are "claws", "evolution", "kmail", "mutt", and
 
4743
    "thunderbird"; generic options are "default", "editor", "emacsclient",
 
4744
    "mapi", and "xdg-email".  Plugins may also add supported clients.
3969
4745
 
3970
4746
    If mail is being sent, a to address is required.  This can be supplied
3971
 
    either on the commandline, or by setting the submit_to configuration
3972
 
    option.
 
4747
    either on the commandline, by setting the submit_to configuration
 
4748
    option in the branch itself or the child_submit_to configuration option
 
4749
    in the submit branch.
3973
4750
 
3974
4751
    Two formats are currently supported: "4" uses revision bundle format 4 and
3975
4752
    merge directive format 2.  It is significantly faster and smaller than
3976
4753
    older formats.  It is compatible with Bazaar 0.19 and later.  It is the
3977
4754
    default.  "0.9" uses revision bundle format 0.9 and merge directive
3978
4755
    format 1.  It is compatible with Bazaar 0.12 - 0.18.
 
4756
 
 
4757
    The merge directives created by bzr send may be applied using bzr merge or
 
4758
    bzr pull by specifying a file containing a merge directive as the location.
3979
4759
    """
3980
4760
 
3981
4761
    encoding_type = 'exact'
3982
4762
 
3983
 
    _see_also = ['merge']
 
4763
    _see_also = ['merge', 'pull']
3984
4764
 
3985
4765
    takes_args = ['submit_branch?', 'public_branch?']
3986
4766
 
3996
4776
               'rather than the one containing the working directory.',
3997
4777
               short_name='f',
3998
4778
               type=unicode),
3999
 
        Option('output', short_name='o', help='Write directive to this file.',
 
4779
        Option('output', short_name='o',
 
4780
               help='Write merge directive to this file; '
 
4781
                    'use - for stdout.',
4000
4782
               type=unicode),
4001
4783
        Option('mail-to', help='Mail the request to this address.',
4002
4784
               type=unicode),
4003
4785
        'revision',
4004
4786
        'message',
 
4787
        Option('body', help='Body for the email.', type=unicode),
4005
4788
        RegistryOption.from_kwargs('format',
4006
4789
        'Use the specified output format.',
4007
4790
        **{'4': 'Bundle format 4, Merge Directive 2 (default)',
4010
4793
 
4011
4794
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4012
4795
            no_patch=False, revision=None, remember=False, output=None,
4013
 
            format='4', mail_to=None, message=None, **kwargs):
 
4796
            format='4', mail_to=None, message=None, body=None, **kwargs):
4014
4797
        return self._run(submit_branch, revision, public_branch, remember,
4015
4798
                         format, no_bundle, no_patch, output,
4016
 
                         kwargs.get('from', '.'), mail_to, message)
 
4799
                         kwargs.get('from', '.'), mail_to, message, body)
4017
4800
 
4018
4801
    def _run(self, submit_branch, revision, public_branch, remember, format,
4019
 
             no_bundle, no_patch, output, from_, mail_to, message):
 
4802
             no_bundle, no_patch, output, from_, mail_to, message, body):
4020
4803
        from bzrlib.revision import NULL_REVISION
4021
4804
        branch = Branch.open_containing(from_)[0]
4022
4805
        if output is None:
4023
 
            outfile = StringIO()
 
4806
            outfile = cStringIO.StringIO()
4024
4807
        elif output == '-':
4025
4808
            outfile = self.outf
4026
4809
        else:
4034
4817
                if mail_to is None:
4035
4818
                    mail_to = config.get_user_option('submit_to')
4036
4819
                mail_client = config.get_mail_client()
 
4820
                if (not getattr(mail_client, 'supports_body', False)
 
4821
                    and body is not None):
 
4822
                    raise errors.BzrCommandError(
 
4823
                        'Mail client "%s" does not support specifying body' %
 
4824
                        mail_client.__class__.__name__)
4037
4825
            if remember and submit_branch is None:
4038
4826
                raise errors.BzrCommandError(
4039
4827
                    '--remember requires a branch to be specified.')
4040
4828
            stored_submit_branch = branch.get_submit_branch()
4041
 
            remembered_submit_branch = False
 
4829
            remembered_submit_branch = None
4042
4830
            if submit_branch is None:
4043
4831
                submit_branch = stored_submit_branch
4044
 
                remembered_submit_branch = True
 
4832
                remembered_submit_branch = "submit"
4045
4833
            else:
4046
4834
                if stored_submit_branch is None or remember:
4047
4835
                    branch.set_submit_branch(submit_branch)
4048
4836
            if submit_branch is None:
4049
4837
                submit_branch = branch.get_parent()
4050
 
                remembered_submit_branch = True
 
4838
                remembered_submit_branch = "parent"
4051
4839
            if submit_branch is None:
4052
4840
                raise errors.BzrCommandError('No submit branch known or'
4053
4841
                                             ' specified')
4054
 
            if remembered_submit_branch:
4055
 
                note('Using saved location: %s', submit_branch)
 
4842
            if remembered_submit_branch is not None:
 
4843
                note('Using saved %s location "%s" to determine what '
 
4844
                        'changes to submit.', remembered_submit_branch,
 
4845
                        submit_branch)
 
4846
 
 
4847
            if mail_to is None:
 
4848
                submit_config = Branch.open(submit_branch).get_config()
 
4849
                mail_to = submit_config.get_user_option("child_submit_to")
4056
4850
 
4057
4851
            stored_public_branch = branch.get_public_branch()
4058
4852
            if public_branch is None:
4068
4862
                if len(revision) > 2:
4069
4863
                    raise errors.BzrCommandError('bzr send takes '
4070
4864
                        'at most two one revision identifiers')
4071
 
                revision_id = revision[-1].in_history(branch).rev_id
 
4865
                revision_id = revision[-1].as_revision_id(branch)
4072
4866
                if len(revision) == 2:
4073
 
                    base_revision_id = revision[0].in_history(branch).rev_id
 
4867
                    base_revision_id = revision[0].as_revision_id(branch)
4074
4868
            if revision_id is None:
4075
4869
                revision_id = branch.last_revision()
4076
4870
            if revision_id == NULL_REVISION:
4108
4902
                else:
4109
4903
                    revision = branch.repository.get_revision(revision_id)
4110
4904
                    subject += revision.get_summary()
 
4905
                basename = directive.get_disk_name(branch)
4111
4906
                mail_client.compose_merge_request(mail_to, subject,
4112
 
                                                  outfile.getvalue())
 
4907
                                                  outfile.getvalue(),
 
4908
                                                  basename, body)
4113
4909
        finally:
4114
4910
            if output != '-':
4115
4911
                outfile.close()
4118
4914
 
4119
4915
class cmd_bundle_revisions(cmd_send):
4120
4916
 
4121
 
    """Create a merge-directive for submiting changes.
 
4917
    """Create a merge-directive for submitting changes.
4122
4918
 
4123
4919
    A merge directive provides many things needed for requesting merges:
4124
4920
 
4183
4979
            output = '-'
4184
4980
        return self._run(submit_branch, revision, public_branch, remember,
4185
4981
                         format, no_bundle, no_patch, output,
4186
 
                         kwargs.get('from', '.'), None, None)
 
4982
                         kwargs.get('from', '.'), None, None, None)
4187
4983
 
4188
4984
 
4189
4985
class cmd_tag(Command):
4190
4986
    """Create, remove or modify a tag naming a revision.
4191
 
    
 
4987
 
4192
4988
    Tags give human-meaningful names to revisions.  Commands that take a -r
4193
4989
    (--revision) option can be given -rtag:X, where X is any previously
4194
4990
    created tag.
4196
4992
    Tags are stored in the branch.  Tags are copied from one branch to another
4197
4993
    along when you branch, push, pull or merge.
4198
4994
 
4199
 
    It is an error to give a tag name that already exists unless you pass 
 
4995
    It is an error to give a tag name that already exists unless you pass
4200
4996
    --force, in which case the tag is moved to point to the new revision.
 
4997
 
 
4998
    To rename a tag (change the name but keep it on the same revsion), run ``bzr
 
4999
    tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
4201
5000
    """
4202
5001
 
4203
5002
    _see_also = ['commit', 'tags']
4235
5034
                        raise errors.BzrCommandError(
4236
5035
                            "Tags can only be placed on a single revision, "
4237
5036
                            "not on a range")
4238
 
                    revision_id = revision[0].in_history(branch).rev_id
 
5037
                    revision_id = revision[0].as_revision_id(branch)
4239
5038
                else:
4240
5039
                    revision_id = branch.last_revision()
4241
5040
                if (not force) and branch.tags.has_tag(tag_name):
4265
5064
            time='Sort tags chronologically.',
4266
5065
            ),
4267
5066
        'show-ids',
 
5067
        'revision',
4268
5068
    ]
4269
5069
 
4270
5070
    @display_command
4272
5072
            directory='.',
4273
5073
            sort='alpha',
4274
5074
            show_ids=False,
 
5075
            revision=None,
4275
5076
            ):
4276
5077
        branch, relpath = Branch.open_containing(directory)
 
5078
 
4277
5079
        tags = branch.tags.get_tag_dict().items()
 
5080
        if not tags:
 
5081
            return
 
5082
 
 
5083
        if revision:
 
5084
            branch.lock_read()
 
5085
            try:
 
5086
                graph = branch.repository.get_graph()
 
5087
                rev1, rev2 = _get_revision_range(revision, branch, self.name())
 
5088
                revid1, revid2 = rev1.rev_id, rev2.rev_id
 
5089
                # only show revisions between revid1 and revid2 (inclusive)
 
5090
                tags = [(tag, revid) for tag, revid in tags if
 
5091
                    graph.is_between(revid, revid1, revid2)]
 
5092
            finally:
 
5093
                branch.unlock()
4278
5094
        if sort == 'alpha':
4279
5095
            tags.sort()
4280
5096
        elif sort == 'time':
4311
5127
    If none of these is available, --bind-to must be specified.
4312
5128
    """
4313
5129
 
 
5130
    _see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
4314
5131
    takes_args = ['location?']
4315
 
    takes_options = [RegistryOption.from_kwargs('target_type',
4316
 
                     title='Target type',
4317
 
                     help='The type to reconfigure the directory to.',
4318
 
                     value_switches=True, enum_switch=False,
4319
 
                     branch='Reconfigure to a branch.',
4320
 
                     tree='Reconfigure to a tree.',
4321
 
                     checkout='Reconfigure to a checkout.',
4322
 
                     lightweight_checkout='Reconfigure to a lightweight'
4323
 
                     ' checkout.'),
4324
 
                     Option('bind-to', help='Branch to bind checkout to.',
4325
 
                            type=str),
4326
 
                     Option('force',
4327
 
                        help='Perform reconfiguration even if local changes'
4328
 
                        ' will be lost.')
4329
 
                     ]
 
5132
    takes_options = [
 
5133
        RegistryOption.from_kwargs(
 
5134
            'target_type',
 
5135
            title='Target type',
 
5136
            help='The type to reconfigure the directory to.',
 
5137
            value_switches=True, enum_switch=False,
 
5138
            branch='Reconfigure to be an unbound branch with no working tree.',
 
5139
            tree='Reconfigure to be an unbound branch with a working tree.',
 
5140
            checkout='Reconfigure to be a bound branch with a working tree.',
 
5141
            lightweight_checkout='Reconfigure to be a lightweight'
 
5142
                ' checkout (with no local history).',
 
5143
            standalone='Reconfigure to be a standalone branch '
 
5144
                '(i.e. stop using shared repository).',
 
5145
            use_shared='Reconfigure to use a shared repository.',
 
5146
            with_trees='Reconfigure repository to create '
 
5147
                'working trees on branches by default.',
 
5148
            with_no_trees='Reconfigure repository to not create '
 
5149
                'working trees on branches by default.'
 
5150
            ),
 
5151
        Option('bind-to', help='Branch to bind checkout to.', type=str),
 
5152
        Option('force',
 
5153
               help='Perform reconfiguration even if local changes'
 
5154
               ' will be lost.')
 
5155
        ]
4330
5156
 
4331
5157
    def run(self, location=None, target_type=None, bind_to=None, force=False):
4332
5158
        directory = bzrdir.BzrDir.open(location)
4337
5163
        elif target_type == 'tree':
4338
5164
            reconfiguration = reconfigure.Reconfigure.to_tree(directory)
4339
5165
        elif target_type == 'checkout':
4340
 
            reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
4341
 
                                                                  bind_to)
 
5166
            reconfiguration = reconfigure.Reconfigure.to_checkout(
 
5167
                directory, bind_to)
4342
5168
        elif target_type == 'lightweight-checkout':
4343
5169
            reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4344
5170
                directory, bind_to)
 
5171
        elif target_type == 'use-shared':
 
5172
            reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
 
5173
        elif target_type == 'standalone':
 
5174
            reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
 
5175
        elif target_type == 'with-trees':
 
5176
            reconfiguration = reconfigure.Reconfigure.set_repository_trees(
 
5177
                directory, True)
 
5178
        elif target_type == 'with-no-trees':
 
5179
            reconfiguration = reconfigure.Reconfigure.set_repository_trees(
 
5180
                directory, False)
4345
5181
        reconfiguration.apply(force)
4346
5182
 
4347
5183
 
4348
5184
class cmd_switch(Command):
4349
5185
    """Set the branch of a checkout and update.
4350
 
    
 
5186
 
4351
5187
    For lightweight checkouts, this changes the branch being referenced.
4352
5188
    For heavyweight checkouts, this checks that there are no local commits
4353
5189
    versus the current bound branch, then it makes the local branch a mirror
4354
5190
    of the new location and binds to it.
4355
 
    
 
5191
 
4356
5192
    In both cases, the working tree is updated and uncommitted changes
4357
5193
    are merged. The user can commit or revert these as they desire.
4358
5194
 
4359
5195
    Pending merges need to be committed or reverted before using switch.
 
5196
 
 
5197
    The path to the branch to switch to can be specified relative to the parent
 
5198
    directory of the current branch. For example, if you are currently in a
 
5199
    checkout of /path/to/branch, specifying 'newbranch' will find a branch at
 
5200
    /path/to/newbranch.
 
5201
 
 
5202
    Bound branches use the nickname of its master branch unless it is set
 
5203
    locally, in which case switching will update the the local nickname to be
 
5204
    that of the master.
4360
5205
    """
4361
5206
 
4362
5207
    takes_args = ['to_location']
4366
5211
 
4367
5212
    def run(self, to_location, force=False):
4368
5213
        from bzrlib import switch
4369
 
        to_branch = Branch.open(to_location)
4370
5214
        tree_location = '.'
4371
5215
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
 
5216
        branch = control_dir.open_branch()
 
5217
        try:
 
5218
            to_branch = Branch.open(to_location)
 
5219
        except errors.NotBranchError:
 
5220
            this_branch = control_dir.open_branch()
 
5221
            # This may be a heavy checkout, where we want the master branch
 
5222
            this_url = this_branch.get_bound_location()
 
5223
            # If not, use a local sibling
 
5224
            if this_url is None:
 
5225
                this_url = this_branch.base
 
5226
            to_branch = Branch.open(
 
5227
                urlutils.join(this_url, '..', to_location))
4372
5228
        switch.switch(control_dir, to_branch, force)
 
5229
        if branch.get_config().has_explicit_nickname():
 
5230
            branch = control_dir.open_branch() #get the new branch!
 
5231
            branch.nick = to_branch.nick
4373
5232
        note('Switched to branch: %s',
4374
5233
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
4375
5234
 
4376
5235
 
 
5236
class cmd_view(Command):
 
5237
    """Manage filtered views.
 
5238
 
 
5239
    Views provide a mask over the tree so that users can focus on
 
5240
    a subset of a tree when doing their work. After creating a view,
 
5241
    commands that support a list of files - status, diff, commit, etc -
 
5242
    effectively have that list of files implicitly given each time.
 
5243
    An explicit list of files can still be given but those files
 
5244
    must be within the current view.
 
5245
 
 
5246
    In most cases, a view has a short life-span: it is created to make
 
5247
    a selected change and is deleted once that change is committed.
 
5248
    At other times, you may wish to create one or more named views
 
5249
    and switch between them.
 
5250
 
 
5251
    To disable the current view without deleting it, you can switch to
 
5252
    the pseudo view called ``off``. This can be useful when you need
 
5253
    to see the whole tree for an operation or two (e.g. merge) but
 
5254
    want to switch back to your view after that.
 
5255
 
 
5256
    :Examples:
 
5257
      To define the current view::
 
5258
 
 
5259
        bzr view file1 dir1 ...
 
5260
 
 
5261
      To list the current view::
 
5262
 
 
5263
        bzr view
 
5264
 
 
5265
      To delete the current view::
 
5266
 
 
5267
        bzr view --delete
 
5268
 
 
5269
      To disable the current view without deleting it::
 
5270
 
 
5271
        bzr view --switch off
 
5272
 
 
5273
      To define a named view and switch to it::
 
5274
 
 
5275
        bzr view --name view-name file1 dir1 ...
 
5276
 
 
5277
      To list a named view::
 
5278
 
 
5279
        bzr view --name view-name
 
5280
 
 
5281
      To delete a named view::
 
5282
 
 
5283
        bzr view --name view-name --delete
 
5284
 
 
5285
      To switch to a named view::
 
5286
 
 
5287
        bzr view --switch view-name
 
5288
 
 
5289
      To list all views defined::
 
5290
 
 
5291
        bzr view --all
 
5292
 
 
5293
      To delete all views::
 
5294
 
 
5295
        bzr view --delete --all
 
5296
    """
 
5297
 
 
5298
    _see_also = []
 
5299
    takes_args = ['file*']
 
5300
    takes_options = [
 
5301
        Option('all',
 
5302
            help='Apply list or delete action to all views.',
 
5303
            ),
 
5304
        Option('delete',
 
5305
            help='Delete the view.',
 
5306
            ),
 
5307
        Option('name',
 
5308
            help='Name of the view to define, list or delete.',
 
5309
            type=unicode,
 
5310
            ),
 
5311
        Option('switch',
 
5312
            help='Name of the view to switch to.',
 
5313
            type=unicode,
 
5314
            ),
 
5315
        ]
 
5316
 
 
5317
    def run(self, file_list,
 
5318
            all=False,
 
5319
            delete=False,
 
5320
            name=None,
 
5321
            switch=None,
 
5322
            ):
 
5323
        tree, file_list = tree_files(file_list, apply_view=False)
 
5324
        current_view, view_dict = tree.views.get_view_info()
 
5325
        if name is None:
 
5326
            name = current_view
 
5327
        if delete:
 
5328
            if file_list:
 
5329
                raise errors.BzrCommandError(
 
5330
                    "Both --delete and a file list specified")
 
5331
            elif switch:
 
5332
                raise errors.BzrCommandError(
 
5333
                    "Both --delete and --switch specified")
 
5334
            elif all:
 
5335
                tree.views.set_view_info(None, {})
 
5336
                self.outf.write("Deleted all views.\n")
 
5337
            elif name is None:
 
5338
                raise errors.BzrCommandError("No current view to delete")
 
5339
            else:
 
5340
                tree.views.delete_view(name)
 
5341
                self.outf.write("Deleted '%s' view.\n" % name)
 
5342
        elif switch:
 
5343
            if file_list:
 
5344
                raise errors.BzrCommandError(
 
5345
                    "Both --switch and a file list specified")
 
5346
            elif all:
 
5347
                raise errors.BzrCommandError(
 
5348
                    "Both --switch and --all specified")
 
5349
            elif switch == 'off':
 
5350
                if current_view is None:
 
5351
                    raise errors.BzrCommandError("No current view to disable")
 
5352
                tree.views.set_view_info(None, view_dict)
 
5353
                self.outf.write("Disabled '%s' view.\n" % (current_view))
 
5354
            else:
 
5355
                tree.views.set_view_info(switch, view_dict)
 
5356
                view_str = views.view_display_str(tree.views.lookup_view())
 
5357
                self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
 
5358
        elif all:
 
5359
            if view_dict:
 
5360
                self.outf.write('Views defined:\n')
 
5361
                for view in sorted(view_dict):
 
5362
                    if view == current_view:
 
5363
                        active = "=>"
 
5364
                    else:
 
5365
                        active = "  "
 
5366
                    view_str = views.view_display_str(view_dict[view])
 
5367
                    self.outf.write('%s %-20s %s\n' % (active, view, view_str))
 
5368
            else:
 
5369
                self.outf.write('No views defined.\n')
 
5370
        elif file_list:
 
5371
            if name is None:
 
5372
                # No name given and no current view set
 
5373
                name = 'my'
 
5374
            elif name == 'off':
 
5375
                raise errors.BzrCommandError(
 
5376
                    "Cannot change the 'off' pseudo view")
 
5377
            tree.views.set_view(name, sorted(file_list))
 
5378
            view_str = views.view_display_str(tree.views.lookup_view())
 
5379
            self.outf.write("Using '%s' view: %s\n" % (name, view_str))
 
5380
        else:
 
5381
            # list the files
 
5382
            if name is None:
 
5383
                # No name given and no current view set
 
5384
                self.outf.write('No current view.\n')
 
5385
            else:
 
5386
                view_str = views.view_display_str(tree.views.lookup_view(name))
 
5387
                self.outf.write("'%s' view is: %s\n" % (name, view_str))
 
5388
 
 
5389
 
 
5390
class cmd_hooks(Command):
 
5391
    """Show hooks."""
 
5392
 
 
5393
    hidden = True
 
5394
 
 
5395
    def run(self):
 
5396
        for hook_key in sorted(hooks.known_hooks.keys()):
 
5397
            some_hooks = hooks.known_hooks_key_to_object(hook_key)
 
5398
            self.outf.write("%s:\n" % type(some_hooks).__name__)
 
5399
            for hook_name, hook_point in sorted(some_hooks.items()):
 
5400
                self.outf.write("  %s:\n" % (hook_name,))
 
5401
                found_hooks = list(hook_point)
 
5402
                if found_hooks:
 
5403
                    for hook in found_hooks:
 
5404
                        self.outf.write("    %s\n" %
 
5405
                                        (some_hooks.get_hook_name(hook),))
 
5406
                else:
 
5407
                    self.outf.write("    <no hooks installed>\n")
 
5408
 
 
5409
 
 
5410
class cmd_shelve(Command):
 
5411
    """Temporarily set aside some changes from the current tree.
 
5412
 
 
5413
    Shelve allows you to temporarily put changes you've made "on the shelf",
 
5414
    ie. out of the way, until a later time when you can bring them back from
 
5415
    the shelf with the 'unshelve' command.  The changes are stored alongside
 
5416
    your working tree, and so they aren't propagated along with your branch nor
 
5417
    will they survive its deletion.
 
5418
 
 
5419
    If shelve --list is specified, previously-shelved changes are listed.
 
5420
 
 
5421
    Shelve is intended to help separate several sets of changes that have
 
5422
    been inappropriately mingled.  If you just want to get rid of all changes
 
5423
    and you don't need to restore them later, use revert.  If you want to
 
5424
    shelve all text changes at once, use shelve --all.
 
5425
 
 
5426
    If filenames are specified, only the changes to those files will be
 
5427
    shelved. Other files will be left untouched.
 
5428
 
 
5429
    If a revision is specified, changes since that revision will be shelved.
 
5430
 
 
5431
    You can put multiple items on the shelf, and by default, 'unshelve' will
 
5432
    restore the most recently shelved changes.
 
5433
    """
 
5434
 
 
5435
    takes_args = ['file*']
 
5436
 
 
5437
    takes_options = [
 
5438
        'revision',
 
5439
        Option('all', help='Shelve all changes.'),
 
5440
        'message',
 
5441
        RegistryOption('writer', 'Method to use for writing diffs.',
 
5442
                       bzrlib.option.diff_writer_registry,
 
5443
                       value_switches=True, enum_switch=False),
 
5444
 
 
5445
        Option('list', help='List shelved changes.'),
 
5446
        Option('destroy',
 
5447
               help='Destroy removed changes instead of shelving them.'),
 
5448
    ]
 
5449
    _see_also = ['unshelve']
 
5450
 
 
5451
    def run(self, revision=None, all=False, file_list=None, message=None,
 
5452
            writer=None, list=False, destroy=False):
 
5453
        if list:
 
5454
            return self.run_for_list()
 
5455
        from bzrlib.shelf_ui import Shelver
 
5456
        if writer is None:
 
5457
            writer = bzrlib.option.diff_writer_registry.get()
 
5458
        try:
 
5459
            Shelver.from_args(writer(sys.stdout), revision, all, file_list,
 
5460
                              message, destroy=destroy).run()
 
5461
        except errors.UserAbort:
 
5462
            return 0
 
5463
 
 
5464
    def run_for_list(self):
 
5465
        tree = WorkingTree.open_containing('.')[0]
 
5466
        tree.lock_read()
 
5467
        try:
 
5468
            manager = tree.get_shelf_manager()
 
5469
            shelves = manager.active_shelves()
 
5470
            if len(shelves) == 0:
 
5471
                note('No shelved changes.')
 
5472
                return 0
 
5473
            for shelf_id in reversed(shelves):
 
5474
                message = manager.get_metadata(shelf_id).get('message')
 
5475
                if message is None:
 
5476
                    message = '<no message>'
 
5477
                self.outf.write('%3d: %s\n' % (shelf_id, message))
 
5478
            return 1
 
5479
        finally:
 
5480
            tree.unlock()
 
5481
 
 
5482
 
 
5483
class cmd_unshelve(Command):
 
5484
    """Restore shelved changes.
 
5485
 
 
5486
    By default, the most recently shelved changes are restored. However if you
 
5487
    specify a shelf by id those changes will be restored instead.  This works
 
5488
    best when the changes don't depend on each other.
 
5489
    """
 
5490
 
 
5491
    takes_args = ['shelf_id?']
 
5492
    takes_options = [
 
5493
        RegistryOption.from_kwargs(
 
5494
            'action', help="The action to perform.",
 
5495
            enum_switch=False, value_switches=True,
 
5496
            apply="Apply changes and remove from the shelf.",
 
5497
            dry_run="Show changes, but do not apply or remove them.",
 
5498
            delete_only="Delete changes without applying them."
 
5499
        )
 
5500
    ]
 
5501
    _see_also = ['shelve']
 
5502
 
 
5503
    def run(self, shelf_id=None, action='apply'):
 
5504
        from bzrlib.shelf_ui import Unshelver
 
5505
        Unshelver.from_args(shelf_id, action).run()
 
5506
 
 
5507
 
 
5508
class cmd_clean_tree(Command):
 
5509
    """Remove unwanted files from working tree.
 
5510
 
 
5511
    By default, only unknown files, not ignored files, are deleted.  Versioned
 
5512
    files are never deleted.
 
5513
 
 
5514
    Another class is 'detritus', which includes files emitted by bzr during
 
5515
    normal operations and selftests.  (The value of these files decreases with
 
5516
    time.)
 
5517
 
 
5518
    If no options are specified, unknown files are deleted.  Otherwise, option
 
5519
    flags are respected, and may be combined.
 
5520
 
 
5521
    To check what clean-tree will do, use --dry-run.
 
5522
    """
 
5523
    takes_options = [Option('ignored', help='Delete all ignored files.'),
 
5524
                     Option('detritus', help='Delete conflict files, merge'
 
5525
                            ' backups, and failed selftest dirs.'),
 
5526
                     Option('unknown',
 
5527
                            help='Delete files unknown to bzr (default).'),
 
5528
                     Option('dry-run', help='Show files to delete instead of'
 
5529
                            ' deleting them.'),
 
5530
                     Option('force', help='Do not prompt before deleting.')]
 
5531
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
 
5532
            force=False):
 
5533
        from bzrlib.clean_tree import clean_tree
 
5534
        if not (unknown or ignored or detritus):
 
5535
            unknown = True
 
5536
        if dry_run:
 
5537
            force = True
 
5538
        clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
 
5539
                   dry_run=dry_run, no_prompt=force)
 
5540
 
 
5541
 
4377
5542
def _create_prefix(cur_transport):
4378
5543
    needed = [cur_transport]
4379
5544
    # Recurse upwards until we can create a directory successfully
4396
5561
        cur_transport.ensure_base()
4397
5562
 
4398
5563
 
4399
 
def _get_mergeable_helper(location):
4400
 
    """Get a merge directive or bundle if 'location' points to one.
4401
 
 
4402
 
    Try try to identify a bundle and returns its mergeable form. If it's not,
4403
 
    we return the tried transport anyway so that it can reused to access the
4404
 
    branch
4405
 
 
4406
 
    :param location: can point to a bundle or a branch.
4407
 
 
4408
 
    :return: mergeable, transport
4409
 
    """
4410
 
    mergeable = None
4411
 
    url = urlutils.normalize_url(location)
4412
 
    url, filename = urlutils.split(url, exclude_trailing_slash=False)
4413
 
    location_transport = transport.get_transport(url)
4414
 
    if filename:
4415
 
        try:
4416
 
            # There may be redirections but we ignore the intermediate
4417
 
            # and final transports used
4418
 
            read = bundle.read_mergeable_from_transport
4419
 
            mergeable, t = read(location_transport, filename)
4420
 
        except errors.NotABundle:
4421
 
            # Continue on considering this url a Branch but adjust the
4422
 
            # location_transport
4423
 
            location_transport = location_transport.clone(filename)
4424
 
    return mergeable, location_transport
4425
 
 
4426
 
 
4427
5564
# these get imported and then picked up by the scan for cmd_*
4428
5565
# TODO: Some more consistent way to split command definitions across files;
4429
 
# we do need to load at least some information about them to know of 
 
5566
# we do need to load at least some information about them to know of
4430
5567
# aliases.  ideally we would avoid loading the implementation until the
4431
5568
# details were needed.
4432
5569
from bzrlib.cmd_version_info import cmd_version_info
4435
5572
    cmd_bundle_info,
4436
5573
    )
4437
5574
from bzrlib.sign_my_commits import cmd_sign_my_commits
4438
 
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
 
5575
from bzrlib.weave_commands import cmd_versionedfile_list, \
4439
5576
        cmd_weave_plan_merge, cmd_weave_merge_text