~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-03-16 14:01:20 UTC
  • mfrom: (3280.2.5 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20080316140120-i3yq8yr1l66m11h7
Start 1.4 development

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006, 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""builtin bzr commands"""
18
18
 
19
19
import os
 
20
from StringIO import StringIO
20
21
 
21
22
from bzrlib.lazy_import import lazy_import
22
23
lazy_import(globals(), """
23
24
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,
33
32
    bzrdir,
34
33
    delta,
35
34
    config,
36
35
    errors,
37
36
    globbing,
38
 
    hooks,
 
37
    ignores,
39
38
    log,
40
39
    merge as _mod_merge,
41
40
    merge_directive,
42
41
    osutils,
43
42
    reconfigure,
44
 
    rename_map,
45
43
    revision as _mod_revision,
46
44
    symbol_versioning,
47
45
    transport,
48
46
    tree as _mod_tree,
49
47
    ui,
50
48
    urlutils,
51
 
    views,
52
49
    )
53
50
from bzrlib.branch import Branch
54
51
from bzrlib.conflicts import ConflictList
55
 
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
 
52
from bzrlib.revisionspec import RevisionSpec
56
53
from bzrlib.smtp_connection import SMTPConnection
57
54
from bzrlib.workingtree import WorkingTree
58
55
""")
59
56
 
60
57
from bzrlib.commands import Command, display_command
61
 
from bzrlib.option import (
62
 
    ListOption,
63
 
    Option,
64
 
    RegistryOption,
65
 
    custom_help,
66
 
    _parse_revision_str,
67
 
    )
68
 
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
69
 
 
70
 
 
71
 
def tree_files(file_list, default_branch=u'.', canonicalize=True,
72
 
    apply_view=True):
 
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'.'):
73
63
    try:
74
 
        return internal_tree_files(file_list, default_branch, canonicalize,
75
 
            apply_view)
 
64
        return internal_tree_files(file_list, default_branch)
76
65
    except errors.FileInWrongBranch, e:
77
66
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
78
67
                                     (e.path, file_list[0]))
79
68
 
80
69
 
81
 
def tree_files_for_add(file_list):
82
 
    """
83
 
    Return a tree and list of absolute paths from a file list.
84
 
 
85
 
    Similar to tree_files, but add handles files a bit differently, so it a
86
 
    custom implementation.  In particular, MutableTreeTree.smart_add expects
87
 
    absolute paths, which it immediately converts to relative paths.
88
 
    """
89
 
    # FIXME Would be nice to just return the relative paths like
90
 
    # internal_tree_files does, but there are a large number of unit tests
91
 
    # that assume the current interface to mutabletree.smart_add
92
 
    if file_list:
93
 
        tree, relpath = WorkingTree.open_containing(file_list[0])
94
 
        if tree.supports_views():
95
 
            view_files = tree.views.lookup_view()
96
 
            if view_files:
97
 
                for filename in file_list:
98
 
                    if not osutils.is_inside_any(view_files, filename):
99
 
                        raise errors.FileOutsideView(filename, view_files)
100
 
        file_list = file_list[:]
101
 
        file_list[0] = tree.abspath(relpath)
102
 
    else:
103
 
        tree = WorkingTree.open_containing(u'.')[0]
104
 
        if tree.supports_views():
105
 
            view_files = tree.views.lookup_view()
106
 
            if view_files:
107
 
                file_list = view_files
108
 
                view_str = views.view_display_str(view_files)
109
 
                note("Ignoring files outside view. View is %s" % view_str)
110
 
    return tree, file_list
111
 
 
112
 
 
113
 
def _get_one_revision(command_name, revisions):
114
 
    if revisions is None:
115
 
        return None
116
 
    if len(revisions) != 1:
117
 
        raise errors.BzrCommandError(
118
 
            'bzr %s --revision takes exactly one revision identifier' % (
119
 
                command_name,))
120
 
    return revisions[0]
121
 
 
122
 
 
123
 
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
124
 
    if branch is None:
125
 
        branch = tree.branch
126
 
    if revisions is None:
127
 
        if tree is not None:
128
 
            rev_tree = tree.basis_tree()
129
 
        else:
130
 
            rev_tree = branch.basis_tree()
131
 
    else:
132
 
        revision = _get_one_revision(command_name, revisions)
133
 
        rev_tree = revision.as_tree(branch)
134
 
    return rev_tree
135
 
 
136
 
 
137
70
# XXX: Bad function name; should possibly also be a class method of
138
71
# WorkingTree rather than a function.
139
 
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
140
 
    apply_view=True):
 
72
def internal_tree_files(file_list, default_branch=u'.'):
141
73
    """Convert command-line paths to a WorkingTree and relative paths.
142
74
 
143
75
    This is typically used for command-line processors that take one or
145
77
 
146
78
    The filenames given are not required to exist.
147
79
 
148
 
    :param file_list: Filenames to convert.
 
80
    :param file_list: Filenames to convert.  
149
81
 
150
82
    :param default_branch: Fallback tree path to use if file_list is empty or
151
83
        None.
152
84
 
153
 
    :param apply_view: if True and a view is set, apply it or check that
154
 
        specified files are within it
155
 
 
156
85
    :return: workingtree, [relative_paths]
157
86
    """
158
87
    if file_list is None or len(file_list) == 0:
159
 
        tree = WorkingTree.open_containing(default_branch)[0]
160
 
        if tree.supports_views() and apply_view:
161
 
            view_files = tree.views.lookup_view()
162
 
            if view_files:
163
 
                file_list = view_files
164
 
                view_str = views.view_display_str(view_files)
165
 
                note("Ignoring files outside view. View is %s" % view_str)
166
 
        return tree, file_list
 
88
        return WorkingTree.open_containing(default_branch)[0], file_list
167
89
    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
168
 
    return tree, safe_relpath_files(tree, file_list, canonicalize,
169
 
        apply_view=apply_view)
170
 
 
171
 
 
172
 
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
173
 
    """Convert file_list into a list of relpaths in tree.
174
 
 
175
 
    :param tree: A tree to operate on.
176
 
    :param file_list: A list of user provided paths or None.
177
 
    :param apply_view: if True and a view is set, apply it or check that
178
 
        specified files are within it
179
 
    :return: A list of relative paths.
180
 
    :raises errors.PathNotChild: When a provided path is in a different tree
181
 
        than tree.
182
 
    """
183
 
    if file_list is None:
184
 
        return None
185
 
    if tree.supports_views() and apply_view:
186
 
        view_files = tree.views.lookup_view()
187
 
    else:
188
 
        view_files = []
189
90
    new_list = []
190
 
    # tree.relpath exists as a "thunk" to osutils, but canonical_relpath
191
 
    # doesn't - fix that up here before we enter the loop.
192
 
    if canonicalize:
193
 
        fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
194
 
    else:
195
 
        fixer = tree.relpath
196
91
    for filename in file_list:
197
92
        try:
198
 
            relpath = fixer(osutils.dereference_path(filename))
199
 
            if  view_files and not osutils.is_inside_any(view_files, relpath):
200
 
                raise errors.FileOutsideView(filename, view_files)
201
 
            new_list.append(relpath)
 
93
            new_list.append(tree.relpath(osutils.dereference_path(filename)))
202
94
        except errors.PathNotChild:
203
95
            raise errors.FileInWrongBranch(tree.branch, filename)
204
 
    return new_list
205
 
 
206
 
 
207
 
def _get_view_info_for_change_reporter(tree):
208
 
    """Get the view information from a tree for change reporting."""
209
 
    view_info = None
 
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()
210
106
    try:
211
 
        current_view = tree.views.get_view_info()[0]
212
 
        if current_view is not None:
213
 
            view_info = (current_view, tree.views.lookup_view())
214
 
    except errors.ViewsNotSupported:
215
 
        pass
216
 
    return view_info
 
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)
217
111
 
218
112
 
219
113
# TODO: Make sure no commands unconditionally use the working directory as a
251
145
 
252
146
    To see ignored files use 'bzr ignored'.  For details on the
253
147
    changes to file texts, use 'bzr diff'.
254
 
 
 
148
    
255
149
    Note that --short or -S gives status flags for each item, similar
256
150
    to Subversion's status command. To get output similar to svn -q,
257
 
    use bzr status -SV.
 
151
    use bzr -SV.
258
152
 
259
153
    If no arguments are specified, the status of the entire working
260
154
    directory is shown.  Otherwise, only the status of the specified
261
155
    files or directories is reported.  If a directory is given, status
262
156
    is reported for everything inside that directory.
263
157
 
264
 
    Before merges are committed, the pending merge tip revisions are
265
 
    shown. To see all pending merge revisions, use the -v option.
266
 
    To skip the display of pending merge information altogether, use
267
 
    the no-pending option or specify a file/directory.
268
 
 
269
158
    If a revision argument is given, the status is calculated against
270
159
    that revision, or between two revisions if two are provided.
271
160
    """
272
 
 
 
161
    
273
162
    # TODO: --no-recurse, --recurse options
274
 
 
 
163
    
275
164
    takes_args = ['file*']
276
 
    takes_options = ['show-ids', 'revision', 'change', 'verbose',
 
165
    takes_options = ['show-ids', 'revision', 'change',
277
166
                     Option('short', help='Use short status indicators.',
278
167
                            short_name='S'),
279
168
                     Option('versioned', help='Only show versioned files.',
280
 
                            short_name='V'),
281
 
                     Option('no-pending', help='Don\'t show pending merges.',
282
 
                           ),
 
169
                            short_name='V')
283
170
                     ]
284
171
    aliases = ['st', 'stat']
285
172
 
286
173
    encoding_type = 'replace'
287
174
    _see_also = ['diff', 'revert', 'status-flags']
288
 
 
 
175
    
289
176
    @display_command
290
177
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
291
 
            versioned=False, no_pending=False, verbose=False):
 
178
            versioned=False):
292
179
        from bzrlib.status import show_tree_status
293
180
 
294
181
        if revision and len(revision) > 2:
295
182
            raise errors.BzrCommandError('bzr status --revision takes exactly'
296
183
                                         ' one or two revision specifiers')
297
184
 
298
 
        tree, relfile_list = tree_files(file_list)
299
 
        # Avoid asking for specific files when that is not needed.
300
 
        if relfile_list == ['']:
301
 
            relfile_list = None
302
 
            # Don't disable pending merges for full trees other than '.'.
303
 
            if file_list == ['.']:
304
 
                no_pending = True
305
 
        # A specific path within a tree was given.
306
 
        elif relfile_list is not None:
307
 
            no_pending = True
 
185
        tree, file_list = tree_files(file_list)
 
186
            
308
187
        show_tree_status(tree, show_ids=show_ids,
309
 
                         specific_files=relfile_list, revision=revision,
310
 
                         to_file=self.outf, short=short, versioned=versioned,
311
 
                         show_pending=(not no_pending), verbose=verbose)
 
188
                         specific_files=file_list, revision=revision,
 
189
                         to_file=self.outf, short=short, versioned=versioned)
312
190
 
313
191
 
314
192
class cmd_cat_revision(Command):
315
193
    """Write out metadata for a revision.
316
 
 
 
194
    
317
195
    The revision to print can either be specified by a specific
318
196
    revision identifier, or you can use --revision.
319
197
    """
323
201
    takes_options = ['revision']
324
202
    # cat-revision is more for frontends so should be exact
325
203
    encoding = 'strict'
326
 
 
 
204
    
327
205
    @display_command
328
206
    def run(self, revision_id=None, revision=None):
329
207
        if revision_id is not None and revision is not None:
337
215
        # TODO: jam 20060112 should cat-revision always output utf-8?
338
216
        if revision_id is not None:
339
217
            revision_id = osutils.safe_revision_id(revision_id, warn=False)
340
 
            try:
341
 
                self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
342
 
            except errors.NoSuchRevision:
343
 
                msg = "The repository %s contains no revision %s." % (b.repository.base,
344
 
                    revision_id)
345
 
                raise errors.BzrCommandError(msg)
 
218
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
346
219
        elif revision is not None:
347
220
            for rev in revision:
348
221
                if rev is None:
349
222
                    raise errors.BzrCommandError('You cannot specify a NULL'
350
223
                                                 ' revision.')
351
 
                rev_id = rev.as_revision_id(b)
 
224
                revno, rev_id = rev.in_history(b)
352
225
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
353
 
 
354
 
 
355
 
class cmd_dump_btree(Command):
356
 
    """Dump the contents of a btree index file to stdout.
357
 
 
358
 
    PATH is a btree index file, it can be any URL. This includes things like
359
 
    .bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
360
 
 
361
 
    By default, the tuples stored in the index file will be displayed. With
362
 
    --raw, we will uncompress the pages, but otherwise display the raw bytes
363
 
    stored in the index.
364
 
    """
365
 
 
366
 
    # TODO: Do we want to dump the internal nodes as well?
367
 
    # TODO: It would be nice to be able to dump the un-parsed information,
368
 
    #       rather than only going through iter_all_entries. However, this is
369
 
    #       good enough for a start
370
 
    hidden = True
371
 
    encoding_type = 'exact'
372
 
    takes_args = ['path']
373
 
    takes_options = [Option('raw', help='Write the uncompressed bytes out,'
374
 
                                        ' rather than the parsed tuples.'),
375
 
                    ]
376
 
 
377
 
    def run(self, path, raw=False):
378
 
        dirname, basename = osutils.split(path)
379
 
        t = transport.get_transport(dirname)
380
 
        if raw:
381
 
            self._dump_raw_bytes(t, basename)
382
 
        else:
383
 
            self._dump_entries(t, basename)
384
 
 
385
 
    def _get_index_and_bytes(self, trans, basename):
386
 
        """Create a BTreeGraphIndex and raw bytes."""
387
 
        bt = btree_index.BTreeGraphIndex(trans, basename, None)
388
 
        bytes = trans.get_bytes(basename)
389
 
        bt._file = cStringIO.StringIO(bytes)
390
 
        bt._size = len(bytes)
391
 
        return bt, bytes
392
 
 
393
 
    def _dump_raw_bytes(self, trans, basename):
394
 
        import zlib
395
 
 
396
 
        # We need to parse at least the root node.
397
 
        # This is because the first page of every row starts with an
398
 
        # uncompressed header.
399
 
        bt, bytes = self._get_index_and_bytes(trans, basename)
400
 
        for page_idx, page_start in enumerate(xrange(0, len(bytes),
401
 
                                                     btree_index._PAGE_SIZE)):
402
 
            page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
403
 
            page_bytes = bytes[page_start:page_end]
404
 
            if page_idx == 0:
405
 
                self.outf.write('Root node:\n')
406
 
                header_end, data = bt._parse_header_from_bytes(page_bytes)
407
 
                self.outf.write(page_bytes[:header_end])
408
 
                page_bytes = data
409
 
            self.outf.write('\nPage %d\n' % (page_idx,))
410
 
            decomp_bytes = zlib.decompress(page_bytes)
411
 
            self.outf.write(decomp_bytes)
412
 
            self.outf.write('\n')
413
 
 
414
 
    def _dump_entries(self, trans, basename):
415
 
        try:
416
 
            st = trans.stat(basename)
417
 
        except errors.TransportNotPossible:
418
 
            # We can't stat, so we'll fake it because we have to do the 'get()'
419
 
            # anyway.
420
 
            bt, _ = self._get_index_and_bytes(trans, basename)
421
 
        else:
422
 
            bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
423
 
        for node in bt.iter_all_entries():
424
 
            # Node is made up of:
425
 
            # (index, key, value, [references])
426
 
            self.outf.write('%s\n' % (node[1:],))
427
 
 
 
226
    
428
227
 
429
228
class cmd_remove_tree(Command):
430
229
    """Remove the working tree from a given branch/checkout.
435
234
    To re-create the working tree, use "bzr checkout".
436
235
    """
437
236
    _see_also = ['checkout', 'working-trees']
 
237
 
438
238
    takes_args = ['location?']
439
 
    takes_options = [
440
 
        Option('force',
441
 
               help='Remove the working tree even if it has '
442
 
                    'uncommitted changes.'),
443
 
        ]
444
239
 
445
 
    def run(self, location='.', force=False):
 
240
    def run(self, location='.'):
446
241
        d = bzrdir.BzrDir.open(location)
447
 
 
 
242
        
448
243
        try:
449
244
            working = d.open_workingtree()
450
245
        except errors.NoWorkingTree:
452
247
        except errors.NotLocalUrl:
453
248
            raise errors.BzrCommandError("You cannot remove the working tree of a "
454
249
                                         "remote path")
455
 
        if not force:
456
 
            changes = working.changes_from(working.basis_tree())
457
 
            if changes.has_changed():
458
 
                raise errors.UncommittedChanges(working)
459
 
 
 
250
        
460
251
        working_path = working.bzrdir.root_transport.base
461
252
        branch_path = working.branch.bzrdir.root_transport.base
462
253
        if working_path != branch_path:
463
254
            raise errors.BzrCommandError("You cannot remove the working tree from "
464
255
                                         "a lightweight checkout")
465
 
 
 
256
        
466
257
        d.destroy_workingtree()
467
 
 
 
258
        
468
259
 
469
260
class cmd_revno(Command):
470
261
    """Show current revision number.
486
277
    """
487
278
    hidden = True
488
279
    takes_args = ['revision_info*']
489
 
    takes_options = [
490
 
        'revision',
491
 
        Option('directory',
492
 
            help='Branch to examine, '
493
 
                 'rather than the one containing the working directory.',
494
 
            short_name='d',
495
 
            type=unicode,
496
 
            ),
497
 
        ]
 
280
    takes_options = ['revision']
498
281
 
499
282
    @display_command
500
 
    def run(self, revision=None, directory=u'.', revision_info_list=[]):
 
283
    def run(self, revision=None, revision_info_list=[]):
501
284
 
502
285
        revs = []
503
286
        if revision is not None:
506
289
            for rev in revision_info_list:
507
290
                revs.append(RevisionSpec.from_string(rev))
508
291
 
509
 
        b = Branch.open_containing(directory)[0]
 
292
        b = Branch.open_containing(u'.')[0]
510
293
 
511
294
        if len(revs) == 0:
512
295
            revs.append(RevisionSpec.from_string('-1'))
513
296
 
514
297
        for rev in revs:
515
 
            revision_id = rev.as_revision_id(b)
516
 
            try:
517
 
                revno = '%4d' % (b.revision_id_to_revno(revision_id))
518
 
            except errors.NoSuchRevision:
 
298
            revinfo = rev.in_history(b)
 
299
            if revinfo.revno is None:
519
300
                dotted_map = b.get_revision_id_to_revno_map()
520
 
                revno = '.'.join(str(i) for i in dotted_map[revision_id])
521
 
            print '%s %s' % (revno, revision_id)
522
 
 
523
 
 
 
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
    
524
307
class cmd_add(Command):
525
308
    """Add specified files or directories.
526
309
 
544
327
    you should never need to explicitly add a directory, they'll just
545
328
    get added when you add a file in the directory.
546
329
 
547
 
    --dry-run will show which files would be added, but not actually
 
330
    --dry-run will show which files would be added, but not actually 
548
331
    add them.
549
332
 
550
333
    --file-ids-from will try to use the file ids from the supplied path.
593
376
            base_tree.lock_read()
594
377
        try:
595
378
            file_list = self._maybe_expand_globs(file_list)
596
 
            tree, file_list = tree_files_for_add(file_list)
 
379
            if file_list:
 
380
                tree = WorkingTree.open_containing(file_list[0])[0]
 
381
            else:
 
382
                tree = WorkingTree.open_containing(u'.')[0]
597
383
            added, ignored = tree.smart_add(file_list, not
598
384
                no_recurse, action=action, save=not dry_run)
599
385
        finally:
603
389
            if verbose:
604
390
                for glob in sorted(ignored.keys()):
605
391
                    for path in ignored[glob]:
606
 
                        self.outf.write("ignored %s matching \"%s\"\n"
 
392
                        self.outf.write("ignored %s matching \"%s\"\n" 
607
393
                                        % (path, glob))
608
394
            else:
609
395
                match_len = 0
610
396
                for glob, paths in ignored.items():
611
397
                    match_len += len(paths)
612
398
                self.outf.write("ignored %d file(s).\n" % match_len)
613
 
            self.outf.write("If you wish to add ignored files, "
614
 
                            "please add them explicitly by name. "
615
 
                            "(\"bzr ignored\" gives a list)\n")
 
399
            self.outf.write("If you wish to add some of these files,"
 
400
                            " please add them by name.\n")
616
401
 
617
402
 
618
403
class cmd_mkdir(Command):
637
422
 
638
423
    takes_args = ['filename']
639
424
    hidden = True
640
 
 
 
425
    
641
426
    @display_command
642
427
    def run(self, filename):
643
428
        # TODO: jam 20050106 Can relpath return a munged path if
673
458
        if kind and kind not in ['file', 'directory', 'symlink']:
674
459
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
675
460
 
676
 
        revision = _get_one_revision('inventory', revision)
677
461
        work_tree, file_list = tree_files(file_list)
678
462
        work_tree.lock_read()
679
463
        try:
680
464
            if revision is not None:
681
 
                tree = revision.as_tree(work_tree.branch)
 
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)
682
471
 
683
472
                extra_trees = [work_tree]
684
473
                tree.lock_read()
734
523
    takes_args = ['names*']
735
524
    takes_options = [Option("after", help="Move only the bzr identifier"
736
525
        " of the file, because the file has already been moved."),
737
 
        Option('auto', help='Automatically guess renames.'),
738
 
        Option('dry-run', help='Avoid making changes when guessing renames.'),
739
526
        ]
740
527
    aliases = ['move', 'rename']
741
528
    encoding_type = 'replace'
742
529
 
743
 
    def run(self, names_list, after=False, auto=False, dry_run=False):
744
 
        if auto:
745
 
            return self.run_auto(names_list, after, dry_run)
746
 
        elif dry_run:
747
 
            raise errors.BzrCommandError('--dry-run requires --auto.')
 
530
    def run(self, names_list, after=False):
748
531
        if names_list is None:
749
532
            names_list = []
 
533
 
750
534
        if len(names_list) < 2:
751
535
            raise errors.BzrCommandError("missing file argument")
752
 
        tree, rel_names = tree_files(names_list, canonicalize=False)
753
 
        tree.lock_write()
754
 
        try:
755
 
            self._run(tree, names_list, rel_names, after)
756
 
        finally:
757
 
            tree.unlock()
758
 
 
759
 
    def run_auto(self, names_list, after, dry_run):
760
 
        if names_list is not None and len(names_list) > 1:
761
 
            raise errors.BzrCommandError('Only one path may be specified to'
762
 
                                         ' --auto.')
763
 
        if after:
764
 
            raise errors.BzrCommandError('--after cannot be specified with'
765
 
                                         ' --auto.')
766
 
        work_tree, file_list = tree_files(names_list, default_branch='.')
767
 
        work_tree.lock_write()
768
 
        try:
769
 
            rename_map.RenameMap.guess_renames(work_tree, dry_run)
770
 
        finally:
771
 
            work_tree.unlock()
772
 
 
773
 
    def _run(self, tree, names_list, rel_names, after):
774
 
        into_existing = osutils.isdir(names_list[-1])
775
 
        if into_existing and len(names_list) == 2:
776
 
            # special cases:
777
 
            # a. case-insensitive filesystem and change case of dir
778
 
            # b. move directory after the fact (if the source used to be
779
 
            #    a directory, but now doesn't exist in the working tree
780
 
            #    and the target is an existing directory, just rename it)
781
 
            if (not tree.case_sensitive
782
 
                and rel_names[0].lower() == rel_names[1].lower()):
783
 
                into_existing = False
784
 
            else:
785
 
                inv = tree.inventory
786
 
                # 'fix' the case of a potential 'from'
787
 
                from_id = tree.path2id(
788
 
                            tree.get_canonical_inventory_path(rel_names[0]))
789
 
                if (not osutils.lexists(names_list[0]) and
790
 
                    from_id and inv.get_file_kind(from_id) == "directory"):
791
 
                    into_existing = False
792
 
        # move/rename
793
 
        if into_existing:
 
536
        tree, rel_names = tree_files(names_list)
 
537
 
 
538
        dest = names_list[-1]
 
539
        isdir = os.path.isdir(dest)
 
540
        if (isdir and not tree.case_sensitive and len(rel_names) == 2
 
541
            and rel_names[0].lower() == rel_names[1].lower()):
 
542
                isdir = False
 
543
        if isdir:
794
544
            # move into existing directory
795
 
            # All entries reference existing inventory items, so fix them up
796
 
            # for cicp file-systems.
797
 
            rel_names = tree.get_canonical_inventory_paths(rel_names)
798
545
            for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
799
546
                self.outf.write("%s => %s\n" % pair)
800
547
        else:
802
549
                raise errors.BzrCommandError('to mv multiple files the'
803
550
                                             ' destination must be a versioned'
804
551
                                             ' directory')
805
 
 
806
 
            # for cicp file-systems: the src references an existing inventory
807
 
            # item:
808
 
            src = tree.get_canonical_inventory_path(rel_names[0])
809
 
            # Find the canonical version of the destination:  In all cases, the
810
 
            # parent of the target must be in the inventory, so we fetch the
811
 
            # canonical version from there (we do not always *use* the
812
 
            # canonicalized tail portion - we may be attempting to rename the
813
 
            # case of the tail)
814
 
            canon_dest = tree.get_canonical_inventory_path(rel_names[1])
815
 
            dest_parent = osutils.dirname(canon_dest)
816
 
            spec_tail = osutils.basename(rel_names[1])
817
 
            # For a CICP file-system, we need to avoid creating 2 inventory
818
 
            # entries that differ only by case.  So regardless of the case
819
 
            # we *want* to use (ie, specified by the user or the file-system),
820
 
            # we must always choose to use the case of any existing inventory
821
 
            # items.  The only exception to this is when we are attempting a
822
 
            # case-only rename (ie, canonical versions of src and dest are
823
 
            # the same)
824
 
            dest_id = tree.path2id(canon_dest)
825
 
            if dest_id is None or tree.path2id(src) == dest_id:
826
 
                # No existing item we care about, so work out what case we
827
 
                # are actually going to use.
828
 
                if after:
829
 
                    # If 'after' is specified, the tail must refer to a file on disk.
830
 
                    if dest_parent:
831
 
                        dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
832
 
                    else:
833
 
                        # pathjoin with an empty tail adds a slash, which breaks
834
 
                        # relpath :(
835
 
                        dest_parent_fq = tree.basedir
836
 
 
837
 
                    dest_tail = osutils.canonical_relpath(
838
 
                                    dest_parent_fq,
839
 
                                    osutils.pathjoin(dest_parent_fq, spec_tail))
840
 
                else:
841
 
                    # not 'after', so case as specified is used
842
 
                    dest_tail = spec_tail
843
 
            else:
844
 
                # Use the existing item so 'mv' fails with AlreadyVersioned.
845
 
                dest_tail = os.path.basename(canon_dest)
846
 
            dest = osutils.pathjoin(dest_parent, dest_tail)
847
 
            mutter("attempting to move %s => %s", src, dest)
848
 
            tree.rename_one(src, dest, after=after)
849
 
            self.outf.write("%s => %s\n" % (src, dest))
 
552
            tree.rename_one(rel_names[0], rel_names[1], after=after)
 
553
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
850
554
 
851
555
 
852
556
class cmd_pull(Command):
867
571
    that, you can omit the location to use the default.  To change the
868
572
    default, use --remember. The value will only be saved if the remote
869
573
    location can be accessed.
870
 
 
871
 
    Note: The location can be specified either in the form of a branch,
872
 
    or in the form of a path to a file containing a merge directive generated
873
 
    with bzr send.
874
574
    """
875
575
 
876
 
    _see_also = ['push', 'update', 'status-flags', 'send']
 
576
    _see_also = ['push', 'update', 'status-flags']
877
577
    takes_options = ['remember', 'overwrite', 'revision',
878
578
        custom_help('verbose',
879
579
            help='Show logs of pulled revisions.'),
883
583
            short_name='d',
884
584
            type=unicode,
885
585
            ),
886
 
        Option('local',
887
 
            help="Perform a local pull in a bound "
888
 
                 "branch.  Local pulls are not applied to "
889
 
                 "the master branch."
890
 
            ),
891
586
        ]
892
587
    takes_args = ['location?']
893
588
    encoding_type = 'replace'
894
589
 
895
590
    def run(self, location=None, remember=False, overwrite=False,
896
591
            revision=None, verbose=False,
897
 
            directory=None, local=False):
 
592
            directory=None):
898
593
        # FIXME: too much stuff is in the command class
899
594
        revision_id = None
900
595
        mergeable = None
906
601
        except errors.NoWorkingTree:
907
602
            tree_to = None
908
603
            branch_to = Branch.open_containing(directory)[0]
909
 
        
910
 
        if local and not branch_to.get_bound_location():
911
 
            raise errors.LocalRequiresBoundBranch()
912
604
 
913
605
        possible_transports = []
914
606
        if location is not None:
915
 
            try:
916
 
                mergeable = bundle.read_mergeable_from_url(location,
917
 
                    possible_transports=possible_transports)
918
 
            except errors.NotABundle:
919
 
                mergeable = None
 
607
            mergeable, location_transport = _get_mergeable_helper(location)
 
608
            possible_transports.append(location_transport)
920
609
 
921
610
        stored_loc = branch_to.get_parent()
922
611
        if location is None:
927
616
                display_url = urlutils.unescape_for_display(stored_loc,
928
617
                        self.outf.encoding)
929
618
                if not is_quiet():
930
 
                    self.outf.write("Using saved parent location: %s\n" % display_url)
 
619
                    self.outf.write("Using saved location: %s\n" % display_url)
931
620
                location = stored_loc
 
621
                location_transport = transport.get_transport(
 
622
                    location, possible_transports=possible_transports)
932
623
 
933
 
        revision = _get_one_revision('pull', revision)
934
624
        if mergeable is not None:
935
625
            if revision is not None:
936
626
                raise errors.BzrCommandError(
940
630
                mergeable.get_merge_request(branch_to.repository)
941
631
            branch_from = branch_to
942
632
        else:
943
 
            branch_from = Branch.open(location,
944
 
                possible_transports=possible_transports)
 
633
            branch_from = Branch.open_from_transport(location_transport)
945
634
 
946
635
            if branch_to.get_parent() is None or remember:
947
636
                branch_to.set_parent(branch_from.base)
948
637
 
949
638
        if revision is not None:
950
 
            revision_id = revision.as_revision_id(branch_from)
951
 
 
952
 
        branch_to.lock_write()
953
 
        try:
954
 
            if tree_to is not None:
955
 
                view_info = _get_view_info_for_change_reporter(tree_to)
956
 
                change_reporter = delta._ChangeReporter(
957
 
                    unversioned_filter=tree_to.is_ignored, view_info=view_info)
958
 
                result = tree_to.pull(branch_from, overwrite, revision_id,
959
 
                                      change_reporter,
960
 
                                      possible_transports=possible_transports,
961
 
                                      local=local)
 
639
            if len(revision) == 1:
 
640
                revision_id = revision[0].in_history(branch_from).rev_id
962
641
            else:
963
 
                result = branch_to.pull(branch_from, overwrite, revision_id,
964
 
                                      local=local)
965
 
 
966
 
            result.report(self.outf)
967
 
            if verbose and result.old_revid != result.new_revid:
968
 
                log.show_branch_change(branch_to, self.outf, result.old_revno,
969
 
                                       result.old_revid)
970
 
        finally:
971
 
            branch_to.unlock()
 
642
                raise errors.BzrCommandError(
 
643
                    'bzr pull --revision takes one value.')
 
644
 
 
645
        if verbose:
 
646
            old_rh = branch_to.revision_history()
 
647
        if tree_to is not None:
 
648
            change_reporter = delta._ChangeReporter(
 
649
                unversioned_filter=tree_to.is_ignored)
 
650
            result = tree_to.pull(branch_from, overwrite, revision_id,
 
651
                                  change_reporter,
 
652
                                  possible_transports=possible_transports)
 
653
        else:
 
654
            result = branch_to.pull(branch_from, overwrite, revision_id)
 
655
 
 
656
        result.report(self.outf)
 
657
        if verbose:
 
658
            new_rh = branch_to.revision_history()
 
659
            log.show_changed_revisions(branch_to, old_rh, new_rh,
 
660
                                       to_file=self.outf)
972
661
 
973
662
 
974
663
class cmd_push(Command):
975
664
    """Update a mirror of this branch.
976
 
 
 
665
    
977
666
    The target branch will not have its working tree populated because this
978
667
    is both expensive, and is not supported on remote file systems.
979
 
 
 
668
    
980
669
    Some smart servers or protocols *may* put the working tree in place in
981
670
    the future.
982
671
 
986
675
 
987
676
    If branches have diverged, you can use 'bzr push --overwrite' to replace
988
677
    the other branch completely, discarding its unmerged changes.
989
 
 
 
678
    
990
679
    If you want to ensure you have the different changes in the other branch,
991
680
    do a merge (see bzr help merge) from the other branch, and commit that.
992
681
    After that you will be able to do a push without '--overwrite'.
1013
702
                    ' directory exists, but does not already'
1014
703
                    ' have a control directory.  This flag will'
1015
704
                    ' allow push to proceed.'),
1016
 
        Option('stacked',
1017
 
            help='Create a stacked branch that references the public location '
1018
 
                'of the parent branch.'),
1019
 
        Option('stacked-on',
1020
 
            help='Create a stacked branch that refers to another branch '
1021
 
                'for the commit history. Only the work not present in the '
1022
 
                'referenced branch is included in the branch created.',
1023
 
            type=unicode),
1024
705
        ]
1025
706
    takes_args = ['location?']
1026
707
    encoding_type = 'replace'
1027
708
 
1028
709
    def run(self, location=None, remember=False, overwrite=False,
1029
 
        create_prefix=False, verbose=False, revision=None,
1030
 
        use_existing_dir=False, directory=None, stacked_on=None,
1031
 
        stacked=False):
1032
 
        from bzrlib.push import _show_push_branch
1033
 
 
1034
 
        # Get the source branch and revision_id
 
710
            create_prefix=False, verbose=False, revision=None,
 
711
            use_existing_dir=False,
 
712
            directory=None):
 
713
        # FIXME: Way too big!  Put this into a function called from the
 
714
        # command.
1035
715
        if directory is None:
1036
716
            directory = '.'
1037
717
        br_from = Branch.open_containing(directory)[0]
1038
 
        revision = _get_one_revision('push', revision)
1039
 
        if revision is not None:
1040
 
            revision_id = revision.in_history(br_from).rev_id
1041
 
        else:
1042
 
            revision_id = None
1043
 
 
1044
 
        # Get the stacked_on branch, if any
1045
 
        if stacked_on is not None:
1046
 
            stacked_on = urlutils.normalize_url(stacked_on)
1047
 
        elif stacked:
1048
 
            parent_url = br_from.get_parent()
1049
 
            if parent_url:
1050
 
                parent = Branch.open(parent_url)
1051
 
                stacked_on = parent.get_public_branch()
1052
 
                if not stacked_on:
1053
 
                    # I considered excluding non-http url's here, thus forcing
1054
 
                    # 'public' branches only, but that only works for some
1055
 
                    # users, so it's best to just depend on the user spotting an
1056
 
                    # error by the feedback given to them. RBC 20080227.
1057
 
                    stacked_on = parent_url
1058
 
            if not stacked_on:
1059
 
                raise errors.BzrCommandError(
1060
 
                    "Could not determine branch to refer to.")
1061
 
 
1062
 
        # Get the destination location
 
718
        stored_loc = br_from.get_push_location()
1063
719
        if location is None:
1064
 
            stored_loc = br_from.get_push_location()
1065
720
            if stored_loc is None:
1066
 
                raise errors.BzrCommandError(
1067
 
                    "No push location known or specified.")
 
721
                raise errors.BzrCommandError("No push location known or specified.")
1068
722
            else:
1069
723
                display_url = urlutils.unescape_for_display(stored_loc,
1070
724
                        self.outf.encoding)
1071
 
                self.outf.write("Using saved push location: %s\n" % display_url)
 
725
                self.outf.write("Using saved location: %s\n" % display_url)
1072
726
                location = stored_loc
1073
727
 
1074
 
        _show_push_branch(br_from, revision_id, location, self.outf,
1075
 
            verbose=verbose, overwrite=overwrite, remember=remember,
1076
 
            stacked_on=stacked_on, create_prefix=create_prefix,
1077
 
            use_existing_dir=use_existing_dir)
 
728
        to_transport = transport.get_transport(location)
 
729
 
 
730
        br_to = repository_to = dir_to = None
 
731
        try:
 
732
            dir_to = bzrdir.BzrDir.open_from_transport(to_transport)
 
733
        except errors.NotBranchError:
 
734
            pass # Didn't find anything
 
735
        else:
 
736
            # If we can open a branch, use its direct repository, otherwise see
 
737
            # if there is a repository without a branch.
 
738
            try:
 
739
                br_to = dir_to.open_branch()
 
740
            except errors.NotBranchError:
 
741
                # Didn't find a branch, can we find a repository?
 
742
                try:
 
743
                    repository_to = dir_to.find_repository()
 
744
                except errors.NoRepositoryPresent:
 
745
                    pass
 
746
            else:
 
747
                # Found a branch, so we must have found a repository
 
748
                repository_to = br_to.repository
 
749
 
 
750
        if revision is not None:
 
751
            if len(revision) == 1:
 
752
                revision_id = revision[0].in_history(br_from).rev_id
 
753
            else:
 
754
                raise errors.BzrCommandError(
 
755
                    'bzr push --revision takes one value.')
 
756
        else:
 
757
            revision_id = br_from.last_revision()
 
758
 
 
759
        push_result = None
 
760
        if verbose:
 
761
            old_rh = []
 
762
        if dir_to is None:
 
763
            # The destination doesn't exist; create it.
 
764
            # XXX: Refactor the create_prefix/no_create_prefix code into a
 
765
            #      common helper function
 
766
 
 
767
            def make_directory(transport):
 
768
                transport.mkdir('.')
 
769
                return transport
 
770
 
 
771
            def redirected(redirected_transport, e, redirection_notice):
 
772
                return transport.get_transport(e.get_target_url())
 
773
 
 
774
            try:
 
775
                to_transport = transport.do_catching_redirections(
 
776
                    make_directory, to_transport, redirected)
 
777
            except errors.FileExists:
 
778
                if not use_existing_dir:
 
779
                    raise errors.BzrCommandError("Target directory %s"
 
780
                         " already exists, but does not have a valid .bzr"
 
781
                         " directory. Supply --use-existing-dir to push"
 
782
                         " there anyway." % location)
 
783
            except errors.NoSuchFile:
 
784
                if not create_prefix:
 
785
                    raise errors.BzrCommandError("Parent directory of %s"
 
786
                        " does not exist."
 
787
                        "\nYou may supply --create-prefix to create all"
 
788
                        " leading parent directories."
 
789
                        % location)
 
790
                _create_prefix(to_transport)
 
791
            except errors.TooManyRedirections:
 
792
                raise errors.BzrCommandError("Too many redirections trying "
 
793
                                             "to make %s." % location)
 
794
 
 
795
            # Now the target directory exists, but doesn't have a .bzr
 
796
            # directory. So we need to create it, along with any work to create
 
797
            # all of the dependent branches, etc.
 
798
            dir_to = br_from.bzrdir.clone_on_transport(to_transport,
 
799
                                                       revision_id=revision_id)
 
800
            br_to = dir_to.open_branch()
 
801
            # TODO: Some more useful message about what was copied
 
802
            note('Created new branch.')
 
803
            # We successfully created the target, remember it
 
804
            if br_from.get_push_location() is None or remember:
 
805
                br_from.set_push_location(br_to.base)
 
806
        elif repository_to is None:
 
807
            # we have a bzrdir but no branch or repository
 
808
            # XXX: Figure out what to do other than complain.
 
809
            raise errors.BzrCommandError("At %s you have a valid .bzr control"
 
810
                " directory, but not a branch or repository. This is an"
 
811
                " unsupported configuration. Please move the target directory"
 
812
                " out of the way and try again."
 
813
                % location)
 
814
        elif br_to is None:
 
815
            # We have a repository but no branch, copy the revisions, and then
 
816
            # create a branch.
 
817
            repository_to.fetch(br_from.repository, revision_id=revision_id)
 
818
            br_to = br_from.clone(dir_to, revision_id=revision_id)
 
819
            note('Created new branch.')
 
820
            if br_from.get_push_location() is None or remember:
 
821
                br_from.set_push_location(br_to.base)
 
822
        else: # We have a valid to branch
 
823
            # We were able to connect to the remote location, so remember it
 
824
            # we don't need to successfully push because of possible divergence.
 
825
            if br_from.get_push_location() is None or remember:
 
826
                br_from.set_push_location(br_to.base)
 
827
            if verbose:
 
828
                old_rh = br_to.revision_history()
 
829
            try:
 
830
                try:
 
831
                    tree_to = dir_to.open_workingtree()
 
832
                except errors.NotLocalUrl:
 
833
                    warning("This transport does not update the working " 
 
834
                            "tree of: %s. See 'bzr help working-trees' for "
 
835
                            "more information." % br_to.base)
 
836
                    push_result = br_from.push(br_to, overwrite,
 
837
                                               stop_revision=revision_id)
 
838
                except errors.NoWorkingTree:
 
839
                    push_result = br_from.push(br_to, overwrite,
 
840
                                               stop_revision=revision_id)
 
841
                else:
 
842
                    tree_to.lock_write()
 
843
                    try:
 
844
                        push_result = br_from.push(tree_to.branch, overwrite,
 
845
                                                   stop_revision=revision_id)
 
846
                        tree_to.update()
 
847
                    finally:
 
848
                        tree_to.unlock()
 
849
            except errors.DivergedBranches:
 
850
                raise errors.BzrCommandError('These branches have diverged.'
 
851
                                        '  Try using "merge" and then "push".')
 
852
        if push_result is not None:
 
853
            push_result.report(self.outf)
 
854
        elif verbose:
 
855
            new_rh = br_to.revision_history()
 
856
            if old_rh != new_rh:
 
857
                # Something changed
 
858
                from bzrlib.log import show_changed_revisions
 
859
                show_changed_revisions(br_to, old_rh, new_rh,
 
860
                                       to_file=self.outf)
 
861
        else:
 
862
            # we probably did a clone rather than a push, so a message was
 
863
            # emitted above
 
864
            pass
1078
865
 
1079
866
 
1080
867
class cmd_branch(Command):
1094
881
    _see_also = ['checkout']
1095
882
    takes_args = ['from_location', 'to_location?']
1096
883
    takes_options = ['revision', Option('hardlink',
1097
 
        help='Hard-link working tree files where possible.'),
1098
 
        Option('no-tree',
1099
 
            help="Create a branch without a working-tree."),
1100
 
        Option('stacked',
1101
 
            help='Create a stacked branch referring to the source branch. '
1102
 
                'The new branch will depend on the availability of the source '
1103
 
                'branch for all operations.'),
1104
 
        Option('standalone',
1105
 
               help='Do not use a shared repository, even if available.'),
1106
 
        ]
 
884
        help='Hard-link working tree files where possible.')]
1107
885
    aliases = ['get', 'clone']
1108
886
 
1109
887
    def run(self, from_location, to_location=None, revision=None,
1110
 
            hardlink=False, stacked=False, standalone=False, no_tree=False):
 
888
            hardlink=False):
1111
889
        from bzrlib.tag import _merge_tags_if_possible
 
890
        if revision is None:
 
891
            revision = [None]
 
892
        elif len(revision) > 1:
 
893
            raise errors.BzrCommandError(
 
894
                'bzr branch --revision takes exactly 1 revision value')
1112
895
 
1113
896
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1114
897
            from_location)
1115
 
        revision = _get_one_revision('branch', revision)
1116
898
        br_from.lock_read()
1117
899
        try:
1118
 
            if revision is not None:
1119
 
                revision_id = revision.as_revision_id(br_from)
 
900
            if len(revision) == 1 and revision[0] is not None:
 
901
                revision_id = revision[0].in_history(br_from)[1]
1120
902
            else:
1121
903
                # FIXME - wt.last_revision, fallback to branch, fall back to
1122
904
                # None or perhaps NULL_REVISION to mean copy nothing
1124
906
                revision_id = br_from.last_revision()
1125
907
            if to_location is None:
1126
908
                to_location = urlutils.derive_to_location(from_location)
 
909
                name = None
 
910
            else:
 
911
                name = os.path.basename(to_location) + '\n'
 
912
 
1127
913
            to_transport = transport.get_transport(to_location)
1128
914
            try:
1129
915
                to_transport.mkdir('.')
1138
924
                dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1139
925
                                            possible_transports=[to_transport],
1140
926
                                            accelerator_tree=accelerator_tree,
1141
 
                                            hardlink=hardlink, stacked=stacked,
1142
 
                                            force_new_repo=standalone,
1143
 
                                            create_tree_if_local=not no_tree,
1144
 
                                            source_branch=br_from)
 
927
                                            hardlink=hardlink)
1145
928
                branch = dir.open_branch()
1146
929
            except errors.NoSuchRevision:
1147
930
                to_transport.delete_tree('.')
1148
 
                msg = "The branch %s has no revision %s." % (from_location,
1149
 
                    revision)
 
931
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
1150
932
                raise errors.BzrCommandError(msg)
 
933
            if name:
 
934
                branch.control_files.put_utf8('branch-name', name)
1151
935
            _merge_tags_if_possible(br_from, branch)
1152
 
            # If the source branch is stacked, the new branch may
1153
 
            # be stacked whether we asked for that explicitly or not.
1154
 
            # We therefore need a try/except here and not just 'if stacked:'
1155
 
            try:
1156
 
                note('Created new stacked branch referring to %s.' %
1157
 
                    branch.get_stacked_on_url())
1158
 
            except (errors.NotStacked, errors.UnstackableBranchFormat,
1159
 
                errors.UnstackableRepositoryFormat), e:
1160
 
                note('Branched %d revision(s).' % branch.revno())
 
936
            note('Branched %d revision(s).' % branch.revno())
1161
937
        finally:
1162
938
            br_from.unlock()
1163
939
 
1169
945
    the branch found in '.'. This is useful if you have removed the working tree
1170
946
    or if it was never created - i.e. if you pushed the branch to its current
1171
947
    location using SFTP.
1172
 
 
 
948
    
1173
949
    If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
1174
950
    be used.  In other words, "checkout ../foo/bar" will attempt to create ./bar.
1175
951
    If the BRANCH_LOCATION has no / or path separator embedded, the TO_LOCATION
1203
979
 
1204
980
    def run(self, branch_location=None, to_location=None, revision=None,
1205
981
            lightweight=False, files_from=None, hardlink=False):
 
982
        if revision is None:
 
983
            revision = [None]
 
984
        elif len(revision) > 1:
 
985
            raise errors.BzrCommandError(
 
986
                'bzr checkout --revision takes exactly 1 revision value')
1206
987
        if branch_location is None:
1207
988
            branch_location = osutils.getcwd()
1208
989
            to_location = branch_location
1209
990
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1210
991
            branch_location)
1211
 
        revision = _get_one_revision('checkout', revision)
1212
992
        if files_from is not None:
1213
993
            accelerator_tree = WorkingTree.open(files_from)
1214
 
        if revision is not None:
1215
 
            revision_id = revision.as_revision_id(source)
 
994
        if len(revision) == 1 and revision[0] is not None:
 
995
            revision_id = _mod_revision.ensure_null(
 
996
                revision[0].in_history(source)[1])
1216
997
        else:
1217
998
            revision_id = None
1218
999
        if to_location is None:
1219
1000
            to_location = urlutils.derive_to_location(branch_location)
1220
 
        # if the source and to_location are the same,
 
1001
        # if the source and to_location are the same, 
1221
1002
        # and there is no working tree,
1222
1003
        # then reconstitute a branch
1223
1004
        if (osutils.abspath(to_location) ==
1250
1031
            old_tree.lock_read()
1251
1032
            try:
1252
1033
                old_inv = old_tree.inventory
1253
 
                renames = []
1254
 
                iterator = tree.iter_changes(old_tree, include_unchanged=True)
1255
 
                for f, paths, c, v, p, n, k, e in iterator:
1256
 
                    if paths[0] == paths[1]:
1257
 
                        continue
1258
 
                    if None in (paths):
1259
 
                        continue
1260
 
                    renames.append(paths)
 
1034
                renames = list(_mod_tree.find_renames(old_inv, new_inv))
1261
1035
                renames.sort()
1262
1036
                for old_name, new_name in renames:
1263
1037
                    self.outf.write("%s => %s\n" % (old_name, new_name))
1269
1043
 
1270
1044
class cmd_update(Command):
1271
1045
    """Update a tree to have the latest code committed to its branch.
1272
 
 
 
1046
    
1273
1047
    This will perform a merge into the working tree, and may generate
1274
 
    conflicts. If you have any local changes, you will still
 
1048
    conflicts. If you have any local changes, you will still 
1275
1049
    need to commit them after the update for the update to be complete.
1276
 
 
1277
 
    If you want to discard your local changes, you can just do a
 
1050
    
 
1051
    If you want to discard your local changes, you can just do a 
1278
1052
    'bzr revert' instead of 'bzr commit' after the update.
1279
1053
    """
1280
1054
 
1302
1076
                    revno = tree.branch.revision_id_to_revno(last_rev)
1303
1077
                    note("Tree is up to date at revision %d." % (revno,))
1304
1078
                    return 0
1305
 
            view_info = _get_view_info_for_change_reporter(tree)
1306
1079
            conflicts = tree.update(
1307
 
                delta._ChangeReporter(unversioned_filter=tree.is_ignored,
1308
 
                view_info=view_info), possible_transports=possible_transports)
 
1080
                delta._ChangeReporter(unversioned_filter=tree.is_ignored),
 
1081
                possible_transports=possible_transports)
1309
1082
            revno = tree.branch.revision_id_to_revno(
1310
1083
                _mod_revision.ensure_null(tree.last_revision()))
1311
1084
            note('Updated to revision %d.' % (revno,))
1324
1097
    """Show information about a working tree, branch or repository.
1325
1098
 
1326
1099
    This command will show all known locations and formats associated to the
1327
 
    tree, branch or repository.
1328
 
 
1329
 
    In verbose mode, statistical information is included with each report.
1330
 
    To see extended statistic information, use a verbosity level of 2 or
1331
 
    higher by specifying the verbose option multiple times, e.g. -vv.
 
1100
    tree, branch or repository.  Statistical information is included with
 
1101
    each report.
1332
1102
 
1333
1103
    Branches and working trees will also report any missing revisions.
1334
 
 
1335
 
    :Examples:
1336
 
 
1337
 
      Display information on the format and related locations:
1338
 
 
1339
 
        bzr info
1340
 
 
1341
 
      Display the above together with extended format information and
1342
 
      basic statistics (like the number of files in the working tree and
1343
 
      number of revisions in the branch and repository):
1344
 
 
1345
 
        bzr info -v
1346
 
 
1347
 
      Display the above together with number of committers to the branch:
1348
 
 
1349
 
        bzr info -vv
1350
1104
    """
1351
1105
    _see_also = ['revno', 'working-trees', 'repositories']
1352
1106
    takes_args = ['location?']
1356
1110
    @display_command
1357
1111
    def run(self, location=None, verbose=False):
1358
1112
        if verbose:
1359
 
            noise_level = get_verbosity_level()
 
1113
            noise_level = 2
1360
1114
        else:
1361
1115
            noise_level = 0
1362
1116
        from bzrlib.info import show_bzrdir_info
1367
1121
class cmd_remove(Command):
1368
1122
    """Remove files or directories.
1369
1123
 
1370
 
    This makes bzr stop tracking changes to the specified files. bzr will delete
1371
 
    them if they can easily be recovered using revert. If no options or
1372
 
    parameters are given bzr will scan for files that are being tracked by bzr
1373
 
    but missing in your tree and stop tracking them for you.
 
1124
    This makes bzr stop tracking changes to the specified files and
 
1125
    delete them if they can easily be recovered using revert.
 
1126
 
 
1127
    You can specify one or more files, and/or --new.  If you specify --new,
 
1128
    only 'added' files will be removed.  If you specify both, then new files
 
1129
    in the specified directories will be removed.  If the directories are
 
1130
    also new, they will also be removed.
1374
1131
    """
1375
1132
    takes_args = ['file*']
1376
1133
    takes_options = ['verbose',
1377
 
        Option('new', help='Only remove files that have never been committed.'),
 
1134
        Option('new', help='Remove newly-added files.'),
1378
1135
        RegistryOption.from_kwargs('file-deletion-strategy',
1379
1136
            'The file deletion mode to be used.',
1380
1137
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1383
1140
            keep="Don't delete any files.",
1384
1141
            force='Delete all the specified files, even if they can not be '
1385
1142
                'recovered and even if they are non-empty directories.')]
1386
 
    aliases = ['rm', 'del']
 
1143
    aliases = ['rm']
1387
1144
    encoding_type = 'replace'
1388
1145
 
1389
1146
    def run(self, file_list, verbose=False, new=False,
1392
1149
 
1393
1150
        if file_list is not None:
1394
1151
            file_list = [f for f in file_list]
 
1152
        elif not new:
 
1153
            raise errors.BzrCommandError('Specify one or more files to'
 
1154
            ' remove, or use --new.')
1395
1155
 
1396
 
        tree.lock_write()
1397
 
        try:
1398
 
            # Heuristics should probably all move into tree.remove_smart or
1399
 
            # some such?
1400
 
            if new:
1401
 
                added = tree.changes_from(tree.basis_tree(),
1402
 
                    specific_files=file_list).added
1403
 
                file_list = sorted([f[0] for f in added], reverse=True)
1404
 
                if len(file_list) == 0:
1405
 
                    raise errors.BzrCommandError('No matching files.')
1406
 
            elif file_list is None:
1407
 
                # missing files show up in iter_changes(basis) as
1408
 
                # versioned-with-no-kind.
1409
 
                missing = []
1410
 
                for change in tree.iter_changes(tree.basis_tree()):
1411
 
                    # Find paths in the working tree that have no kind:
1412
 
                    if change[1][1] is not None and change[6][1] is None:
1413
 
                        missing.append(change[1][1])
1414
 
                file_list = sorted(missing, reverse=True)
1415
 
                file_deletion_strategy = 'keep'
1416
 
            tree.remove(file_list, verbose=verbose, to_file=self.outf,
1417
 
                keep_files=file_deletion_strategy=='keep',
1418
 
                force=file_deletion_strategy=='force')
1419
 
        finally:
1420
 
            tree.unlock()
 
1156
        if new:
 
1157
            added = tree.changes_from(tree.basis_tree(),
 
1158
                specific_files=file_list).added
 
1159
            file_list = sorted([f[0] for f in added], reverse=True)
 
1160
            if len(file_list) == 0:
 
1161
                raise errors.BzrCommandError('No matching files.')
 
1162
        tree.remove(file_list, verbose=verbose, to_file=self.outf,
 
1163
            keep_files=file_deletion_strategy=='keep',
 
1164
            force=file_deletion_strategy=='force')
1421
1165
 
1422
1166
 
1423
1167
class cmd_file_id(Command):
1469
1213
 
1470
1214
    This can correct data mismatches that may have been caused by
1471
1215
    previous ghost operations or bzr upgrades. You should only
1472
 
    need to run this command if 'bzr check' or a bzr developer
 
1216
    need to run this command if 'bzr check' or a bzr developer 
1473
1217
    advises you to run it.
1474
1218
 
1475
1219
    If a second branch is provided, cross-branch reconciliation is
1477
1221
    id which was not present in very early bzr versions is represented
1478
1222
    correctly in both branches.
1479
1223
 
1480
 
    At the same time it is run it may recompress data resulting in
 
1224
    At the same time it is run it may recompress data resulting in 
1481
1225
    a potential saving in disk space or performance gain.
1482
1226
 
1483
1227
    The branch *MUST* be on a listable system such as local disk or sftp.
1528
1272
            last_revision = wt.last_revision()
1529
1273
 
1530
1274
        revision_ids = b.repository.get_ancestry(last_revision)
 
1275
        assert revision_ids[0] is None
1531
1276
        revision_ids.pop(0)
1532
1277
        for revision_id in revision_ids:
1533
1278
            self.outf.write(revision_id + '\n')
1539
1284
    Use this to create an empty branch, or before importing an
1540
1285
    existing project.
1541
1286
 
1542
 
    If there is a repository in a parent directory of the location, then
 
1287
    If there is a repository in a parent directory of the location, then 
1543
1288
    the history of the branch will be stored in the repository.  Otherwise
1544
1289
    init creates a standalone branch which carries its own history
1545
1290
    in the .bzr directory.
1565
1310
         RegistryOption('format',
1566
1311
                help='Specify a format for this branch. '
1567
1312
                'See "help formats".',
1568
 
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1569
 
                converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
1313
                registry=bzrdir.format_registry,
 
1314
                converter=bzrdir.format_registry.make_bzrdir,
1570
1315
                value_switches=True,
1571
1316
                title="Branch Format",
1572
1317
                ),
1597
1342
                    "\nYou may supply --create-prefix to create all"
1598
1343
                    " leading parent directories."
1599
1344
                    % location)
1600
 
            to_transport.create_prefix()
 
1345
            _create_prefix(to_transport)
1601
1346
 
1602
1347
        try:
1603
 
            a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
 
1348
            existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1604
1349
        except errors.NotBranchError:
1605
1350
            # really a NotBzrDir error...
1606
1351
            create_branch = bzrdir.BzrDir.create_branch_convenience
1607
1352
            branch = create_branch(to_transport.base, format=format,
1608
1353
                                   possible_transports=[to_transport])
1609
 
            a_bzrdir = branch.bzrdir
1610
1354
        else:
1611
1355
            from bzrlib.transport.local import LocalTransport
1612
 
            if a_bzrdir.has_branch():
 
1356
            if existing_bzrdir.has_branch():
1613
1357
                if (isinstance(to_transport, LocalTransport)
1614
 
                    and not a_bzrdir.has_workingtree()):
 
1358
                    and not existing_bzrdir.has_workingtree()):
1615
1359
                        raise errors.BranchExistsWithoutWorkingTree(location)
1616
1360
                raise errors.AlreadyBranchError(location)
1617
 
            branch = a_bzrdir.create_branch()
1618
 
            a_bzrdir.create_workingtree()
 
1361
            else:
 
1362
                branch = existing_bzrdir.create_branch()
 
1363
                existing_bzrdir.create_workingtree()
1619
1364
        if append_revisions_only:
1620
1365
            try:
1621
1366
                branch.set_append_revisions_only(True)
1622
1367
            except errors.UpgradeRequired:
1623
1368
                raise errors.BzrCommandError('This branch format cannot be set'
1624
1369
                    ' to append-revisions-only.  Try --experimental-branch6')
1625
 
        if not is_quiet():
1626
 
            from bzrlib.info import describe_layout, describe_format
1627
 
            try:
1628
 
                tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
1629
 
            except (errors.NoWorkingTree, errors.NotLocalUrl):
1630
 
                tree = None
1631
 
            repository = branch.repository
1632
 
            layout = describe_layout(repository, branch, tree).lower()
1633
 
            format = describe_format(a_bzrdir, repository, branch, tree)
1634
 
            self.outf.write("Created a %s (format: %s)\n" % (layout, format))
1635
 
            if repository.is_shared():
1636
 
                #XXX: maybe this can be refactored into transport.path_or_url()
1637
 
                url = repository.bzrdir.root_transport.external_url()
1638
 
                try:
1639
 
                    url = urlutils.local_path_from_url(url)
1640
 
                except errors.InvalidURL:
1641
 
                    pass
1642
 
                self.outf.write("Using shared repository: %s\n" % url)
1643
1370
 
1644
1371
 
1645
1372
class cmd_init_repository(Command):
1669
1396
    takes_options = [RegistryOption('format',
1670
1397
                            help='Specify a format for this repository. See'
1671
1398
                                 ' "bzr help formats" for details.',
1672
 
                            lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1673
 
                            converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
1399
                            registry=bzrdir.format_registry,
 
1400
                            converter=bzrdir.format_registry.make_bzrdir,
1674
1401
                            value_switches=True, title='Repository format'),
1675
1402
                     Option('no-trees',
1676
1403
                             help='Branches in the repository will default to'
1691
1418
        newdir = format.initialize_on_transport(to_transport)
1692
1419
        repo = newdir.create_repository(shared=True)
1693
1420
        repo.set_make_working_trees(not no_trees)
1694
 
        if not is_quiet():
1695
 
            from bzrlib.info import show_bzrdir_info
1696
 
            show_bzrdir_info(repo.bzrdir, verbose=0, outfile=self.outf)
1697
1421
 
1698
1422
 
1699
1423
class cmd_diff(Command):
1700
1424
    """Show differences in the working tree, between revisions or branches.
1701
 
 
 
1425
    
1702
1426
    If no arguments are given, all changes for the current tree are listed.
1703
1427
    If files are given, only the changes in those files are listed.
1704
1428
    Remote and multiple branches can be compared by using the --old and
1803
1527
                                         ' one or two revision specifiers')
1804
1528
 
1805
1529
        old_tree, new_tree, specific_files, extra_trees = \
1806
 
                _get_trees_to_diff(file_list, revision, old, new,
1807
 
                apply_view=True)
1808
 
        return show_diff_trees(old_tree, new_tree, sys.stdout,
 
1530
                _get_trees_to_diff(file_list, revision, old, new)
 
1531
        return show_diff_trees(old_tree, new_tree, sys.stdout, 
1809
1532
                               specific_files=specific_files,
1810
1533
                               external_diff_options=diff_options,
1811
1534
                               old_label=old_label, new_label=new_label,
1851
1574
 
1852
1575
    hidden = True
1853
1576
    _see_also = ['status', 'ls']
1854
 
    takes_options = [
1855
 
            Option('null',
1856
 
                   help='Write an ascii NUL (\\0) separator '
1857
 
                   'between files rather than a newline.')
1858
 
            ]
1859
1577
 
1860
1578
    @display_command
1861
 
    def run(self, null=False):
 
1579
    def run(self):
1862
1580
        tree = WorkingTree.open_containing(u'.')[0]
1863
1581
        td = tree.changes_from(tree.basis_tree())
1864
1582
        for path, id, kind, text_modified, meta_modified in td.modified:
1865
 
            if null:
1866
 
                self.outf.write(path + '\0')
1867
 
            else:
1868
 
                self.outf.write(osutils.quotefn(path) + '\n')
 
1583
            self.outf.write(path + '\n')
1869
1584
 
1870
1585
 
1871
1586
class cmd_added(Command):
1874
1589
 
1875
1590
    hidden = True
1876
1591
    _see_also = ['status', 'ls']
1877
 
    takes_options = [
1878
 
            Option('null',
1879
 
                   help='Write an ascii NUL (\\0) separator '
1880
 
                   'between files rather than a newline.')
1881
 
            ]
1882
1592
 
1883
1593
    @display_command
1884
 
    def run(self, null=False):
 
1594
    def run(self):
1885
1595
        wt = WorkingTree.open_containing(u'.')[0]
1886
1596
        wt.lock_read()
1887
1597
        try:
1898
1608
                    path = inv.id2path(file_id)
1899
1609
                    if not os.access(osutils.abspath(path), os.F_OK):
1900
1610
                        continue
1901
 
                    if null:
1902
 
                        self.outf.write(path + '\0')
1903
 
                    else:
1904
 
                        self.outf.write(osutils.quotefn(path) + '\n')
 
1611
                    self.outf.write(path + '\n')
1905
1612
            finally:
1906
1613
                basis.unlock()
1907
1614
        finally:
1930
1637
        raise errors.BzrCommandError(msg)
1931
1638
 
1932
1639
 
1933
 
def _parse_levels(s):
1934
 
    try:
1935
 
        return int(s)
1936
 
    except ValueError:
1937
 
        msg = "The levels argument must be an integer."
1938
 
        raise errors.BzrCommandError(msg)
1939
 
 
1940
 
 
1941
1640
class cmd_log(Command):
1942
 
    """Show historical log for a branch or subset of a branch.
1943
 
 
1944
 
    log is bzr's default tool for exploring the history of a branch.
1945
 
    The branch to use is taken from the first parameter. If no parameters
1946
 
    are given, the branch containing the working directory is logged.
1947
 
    Here are some simple examples::
1948
 
 
1949
 
      bzr log                       log the current branch
1950
 
      bzr log foo.py                log a file in its branch
1951
 
      bzr log http://server/branch  log a branch on a server
1952
 
 
1953
 
    The filtering, ordering and information shown for each revision can
1954
 
    be controlled as explained below. By default, all revisions are
1955
 
    shown sorted (topologically) so that newer revisions appear before
1956
 
    older ones and descendants always appear before ancestors. If displayed,
1957
 
    merged revisions are shown indented under the revision in which they
1958
 
    were merged.
1959
 
 
1960
 
    :Output control:
1961
 
 
1962
 
      The log format controls how information about each revision is
1963
 
      displayed. The standard log formats are called ``long``, ``short``
1964
 
      and ``line``. The default is long. See ``bzr help log-formats``
1965
 
      for more details on log formats.
1966
 
 
1967
 
      The following options can be used to control what information is
1968
 
      displayed::
1969
 
 
1970
 
        -l N        display a maximum of N revisions
1971
 
        -n N        display N levels of revisions (0 for all, 1 for collapsed)
1972
 
        -v          display a status summary (delta) for each revision
1973
 
        -p          display a diff (patch) for each revision
1974
 
        --show-ids  display revision-ids (and file-ids), not just revnos
1975
 
 
1976
 
      Note that the default number of levels to display is a function of the
1977
 
      log format. If the -n option is not used, the standard log formats show
1978
 
      just the top level (mainline).
1979
 
 
1980
 
      Status summaries are shown using status flags like A, M, etc. To see
1981
 
      the changes explained using words like ``added`` and ``modified``
1982
 
      instead, use the -vv option.
1983
 
 
1984
 
    :Ordering control:
1985
 
 
1986
 
      To display revisions from oldest to newest, use the --forward option.
1987
 
      In most cases, using this option will have little impact on the total
1988
 
      time taken to produce a log, though --forward does not incrementally
1989
 
      display revisions like --reverse does when it can.
1990
 
 
1991
 
    :Revision filtering:
1992
 
 
1993
 
      The -r option can be used to specify what revision or range of revisions
1994
 
      to filter against. The various forms are shown below::
1995
 
 
1996
 
        -rX      display revision X
1997
 
        -rX..    display revision X and later
1998
 
        -r..Y    display up to and including revision Y
1999
 
        -rX..Y   display from X to Y inclusive
2000
 
 
2001
 
      See ``bzr help revisionspec`` for details on how to specify X and Y.
2002
 
      Some common examples are given below::
2003
 
 
2004
 
        -r-1                show just the tip
2005
 
        -r-10..             show the last 10 mainline revisions
2006
 
        -rsubmit:..         show what's new on this branch
2007
 
        -rancestor:path..   show changes since the common ancestor of this
2008
 
                            branch and the one at location path
2009
 
        -rdate:yesterday..  show changes since yesterday
2010
 
 
2011
 
      When logging a range of revisions using -rX..Y, log starts at
2012
 
      revision Y and searches back in history through the primary
2013
 
      ("left-hand") parents until it finds X. When logging just the
2014
 
      top level (using -n1), an error is reported if X is not found
2015
 
      along the way. If multi-level logging is used (-n0), X may be
2016
 
      a nested merge revision and the log will be truncated accordingly.
2017
 
 
2018
 
    :Path filtering:
2019
 
 
2020
 
      If parameters are given and the first one is not a branch, the log
2021
 
      will be filtered to show only those revisions that changed the
2022
 
      nominated files or directories.
2023
 
 
2024
 
      Filenames are interpreted within their historical context. To log a
2025
 
      deleted file, specify a revision range so that the file existed at
2026
 
      the end or start of the range.
2027
 
 
2028
 
      Historical context is also important when interpreting pathnames of
2029
 
      renamed files/directories. Consider the following example:
2030
 
 
2031
 
      * revision 1: add tutorial.txt
2032
 
      * revision 2: modify tutorial.txt
2033
 
      * revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2034
 
 
2035
 
      In this case:
2036
 
 
2037
 
      * ``bzr log guide.txt`` will log the file added in revision 1
2038
 
 
2039
 
      * ``bzr log tutorial.txt`` will log the new file added in revision 3
2040
 
 
2041
 
      * ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2042
 
        the original file in revision 2.
2043
 
 
2044
 
      * ``bzr log -r2 -p guide.txt`` will display an error message as there
2045
 
        was no file called guide.txt in revision 2.
2046
 
 
2047
 
      Renames are always followed by log. By design, there is no need to
2048
 
      explicitly ask for this (and no way to stop logging a file back
2049
 
      until it was last renamed).
2050
 
 
2051
 
    :Other filtering:
2052
 
 
2053
 
      The --message option can be used for finding revisions that match a
2054
 
      regular expression in a commit message.
2055
 
 
2056
 
    :Tips & tricks:
2057
 
 
2058
 
      GUI tools and IDEs are often better at exploring history than command
2059
 
      line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
2060
 
      respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
2061
 
      http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
2062
 
 
2063
 
      Web interfaces are often better at exploring history than command line
2064
 
      tools, particularly for branches on servers. You may prefer Loggerhead
2065
 
      or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2066
 
 
2067
 
      You may find it useful to add the aliases below to ``bazaar.conf``::
2068
 
 
2069
 
        [ALIASES]
2070
 
        tip = log -r-1
2071
 
        top = log -l10 --line
2072
 
        show = log -v -p
2073
 
 
2074
 
      ``bzr tip`` will then show the latest revision while ``bzr top``
2075
 
      will show the last 10 mainline revisions. To see the details of a
2076
 
      particular revision X,  ``bzr show -rX``.
2077
 
 
2078
 
      If you are interested in looking deeper into a particular merge X,
2079
 
      use ``bzr log -n0 -rX``.
2080
 
 
2081
 
      ``bzr log -v`` on a branch with lots of history is currently
2082
 
      very slow. A fix for this issue is currently under development.
2083
 
      With or without that fix, it is recommended that a revision range
2084
 
      be given when using the -v option.
2085
 
 
2086
 
      bzr has a generic full-text matching plugin, bzr-search, that can be
2087
 
      used to find revisions matching user names, commit messages, etc.
2088
 
      Among other features, this plugin can find all revisions containing
2089
 
      a list of words but not others.
2090
 
 
2091
 
      When exploring non-mainline history on large projects with deep
2092
 
      history, the performance of log can be greatly improved by installing
2093
 
      the historycache plugin. This plugin buffers historical information
2094
 
      trading disk space for faster speed.
 
1641
    """Show log of a branch, file, or directory.
 
1642
 
 
1643
    By default show the log of the branch containing the working directory.
 
1644
 
 
1645
    To request a range of logs, you can use the command -r begin..end
 
1646
    -r revision requests a specific revision, -r ..end or -r begin.. are
 
1647
    also valid.
 
1648
 
 
1649
    :Examples:
 
1650
        Log the current branch::
 
1651
 
 
1652
            bzr log
 
1653
 
 
1654
        Log a file::
 
1655
 
 
1656
            bzr log foo.c
 
1657
 
 
1658
        Log the last 10 revisions of a branch::
 
1659
 
 
1660
            bzr log -r -10.. http://server/branch
2095
1661
    """
2096
 
    takes_args = ['file*']
2097
 
    _see_also = ['log-formats', 'revisionspec']
 
1662
 
 
1663
    # TODO: Make --revision support uuid: and hash: [future tag:] notation.
 
1664
 
 
1665
    takes_args = ['location?']
2098
1666
    takes_options = [
2099
1667
            Option('forward',
2100
1668
                   help='Show from oldest to newest.'),
2101
 
            'timezone',
 
1669
            Option('timezone',
 
1670
                   type=str,
 
1671
                   help='Display timezone as local, original, or utc.'),
2102
1672
            custom_help('verbose',
2103
1673
                   help='Show files changed in each revision.'),
2104
1674
            'show-ids',
2105
1675
            'revision',
2106
 
            Option('change',
2107
 
                   type=bzrlib.option._parse_revision_str,
2108
 
                   short_name='c',
2109
 
                   help='Show just the specified revision.'
2110
 
                   ' See also "help revisionspec".'),
2111
1676
            'log-format',
2112
 
            Option('levels',
2113
 
                   short_name='n',
2114
 
                   help='Number of levels to display - 0 for all, 1 for flat.',
2115
 
                   argname='N',
2116
 
                   type=_parse_levels),
2117
1677
            Option('message',
2118
1678
                   short_name='m',
2119
1679
                   help='Show revisions whose message matches this '
2124
1684
                   help='Limit the output to the first N revisions.',
2125
1685
                   argname='N',
2126
1686
                   type=_parse_limit),
2127
 
            Option('show-diff',
2128
 
                   short_name='p',
2129
 
                   help='Show changes made in each revision as a patch.'),
2130
 
            Option('include-merges',
2131
 
                   help='Show merged revisions like --levels 0 does.'),
2132
1687
            ]
2133
1688
    encoding_type = 'replace'
2134
1689
 
2135
1690
    @display_command
2136
 
    def run(self, file_list=None, timezone='original',
 
1691
    def run(self, location=None, timezone='original',
2137
1692
            verbose=False,
2138
1693
            show_ids=False,
2139
1694
            forward=False,
2140
1695
            revision=None,
2141
 
            change=None,
2142
1696
            log_format=None,
2143
 
            levels=None,
2144
1697
            message=None,
2145
 
            limit=None,
2146
 
            show_diff=False,
2147
 
            include_merges=False):
2148
 
        from bzrlib.log import (
2149
 
            Logger,
2150
 
            make_log_request_dict,
2151
 
            _get_info_for_log_files,
2152
 
            )
 
1698
            limit=None):
 
1699
        from bzrlib.log import show_log
 
1700
        assert message is None or isinstance(message, basestring), \
 
1701
            "invalid message argument %r" % message
2153
1702
        direction = (forward and 'forward') or 'reverse'
2154
 
        if include_merges:
2155
 
            if levels is None:
2156
 
                levels = 0
2157
 
            else:
2158
 
                raise errors.BzrCommandError(
2159
 
                    '--levels and --include-merges are mutually exclusive')
2160
 
 
2161
 
        if change is not None:
2162
 
            if len(change) > 1:
2163
 
                raise errors.RangeInChangeOption()
2164
 
            if revision is not None:
2165
 
                raise errors.BzrCommandError(
2166
 
                    '--revision and --change are mutually exclusive')
2167
 
            else:
2168
 
                revision = change
2169
 
 
2170
 
        file_ids = []
2171
 
        filter_by_dir = False
2172
 
        if file_list:
2173
 
            # find the file ids to log and check for directory filtering
2174
 
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(revision,
2175
 
                file_list)
2176
 
            for relpath, file_id, kind in file_info_list:
 
1703
        
 
1704
        # log everything
 
1705
        file_id = None
 
1706
        if location:
 
1707
            # find the file id to log:
 
1708
 
 
1709
            tree, b, fp = bzrdir.BzrDir.open_containing_tree_or_branch(
 
1710
                location)
 
1711
            if fp != '':
 
1712
                if tree is None:
 
1713
                    tree = b.basis_tree()
 
1714
                file_id = tree.path2id(fp)
2177
1715
                if file_id is None:
2178
1716
                    raise errors.BzrCommandError(
2179
 
                        "Path unknown at end or start of revision range: %s" %
2180
 
                        relpath)
2181
 
                # If the relpath is the top of the tree, we log everything
2182
 
                if relpath == '':
2183
 
                    file_ids = []
2184
 
                    break
2185
 
                else:
2186
 
                    file_ids.append(file_id)
2187
 
                filter_by_dir = filter_by_dir or (
2188
 
                    kind in ['directory', 'tree-reference'])
 
1717
                        "Path does not have any revision history: %s" %
 
1718
                        location)
2189
1719
        else:
2190
 
            # log everything
2191
 
            # FIXME ? log the current subdir only RBC 20060203
 
1720
            # local dir only
 
1721
            # FIXME ? log the current subdir only RBC 20060203 
2192
1722
            if revision is not None \
2193
1723
                    and len(revision) > 0 and revision[0].get_branch():
2194
1724
                location = revision[0].get_branch()
2196
1726
                location = '.'
2197
1727
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2198
1728
            b = dir.open_branch()
2199
 
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2200
 
 
2201
 
        # Decide on the type of delta & diff filtering to use
2202
 
        # TODO: add an --all-files option to make this configurable & consistent
2203
 
        if not verbose:
2204
 
            delta_type = None
2205
 
        else:
2206
 
            delta_type = 'full'
2207
 
        if not show_diff:
2208
 
            diff_type = None
2209
 
        elif file_ids:
2210
 
            diff_type = 'partial'
2211
 
        else:
2212
 
            diff_type = 'full'
2213
1729
 
2214
1730
        b.lock_read()
2215
1731
        try:
2216
 
            # Build the log formatter
 
1732
            if revision is None:
 
1733
                rev1 = None
 
1734
                rev2 = None
 
1735
            elif len(revision) == 1:
 
1736
                rev1 = rev2 = revision[0].in_history(b)
 
1737
            elif len(revision) == 2:
 
1738
                if revision[1].get_branch() != revision[0].get_branch():
 
1739
                    # b is taken from revision[0].get_branch(), and
 
1740
                    # show_log will use its revision_history. Having
 
1741
                    # different branches will lead to weird behaviors.
 
1742
                    raise errors.BzrCommandError(
 
1743
                        "Log doesn't accept two revisions in different"
 
1744
                        " branches.")
 
1745
                rev1 = revision[0].in_history(b)
 
1746
                rev2 = revision[1].in_history(b)
 
1747
            else:
 
1748
                raise errors.BzrCommandError(
 
1749
                    'bzr log --revision takes one or two values.')
 
1750
 
2217
1751
            if log_format is None:
2218
1752
                log_format = log.log_formatter_registry.get_default(b)
 
1753
 
2219
1754
            lf = log_format(show_ids=show_ids, to_file=self.outf,
2220
 
                            show_timezone=timezone,
2221
 
                            delta_format=get_verbosity_level(),
2222
 
                            levels=levels,
2223
 
                            show_advice=levels is None)
2224
 
 
2225
 
            # Choose the algorithm for doing the logging. It's annoying
2226
 
            # having multiple code paths like this but necessary until
2227
 
            # the underlying repository format is faster at generating
2228
 
            # deltas or can provide everything we need from the indices.
2229
 
            # The default algorithm - match-using-deltas - works for
2230
 
            # multiple files and directories and is faster for small
2231
 
            # amounts of history (200 revisions say). However, it's too
2232
 
            # slow for logging a single file in a repository with deep
2233
 
            # history, i.e. > 10K revisions. In the spirit of "do no
2234
 
            # evil when adding features", we continue to use the
2235
 
            # original algorithm - per-file-graph - for the "single
2236
 
            # file that isn't a directory without showing a delta" case.
2237
 
            partial_history = revision and b.repository._format.supports_chks
2238
 
            match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2239
 
                or delta_type or partial_history)
2240
 
 
2241
 
            # Build the LogRequest and execute it
2242
 
            if len(file_ids) == 0:
2243
 
                file_ids = None
2244
 
            rqst = make_log_request_dict(
2245
 
                direction=direction, specific_fileids=file_ids,
2246
 
                start_revision=rev1, end_revision=rev2, limit=limit,
2247
 
                message_search=message, delta_type=delta_type,
2248
 
                diff_type=diff_type, _match_using_deltas=match_using_deltas)
2249
 
            Logger(b, rqst).show(lf)
 
1755
                            show_timezone=timezone)
 
1756
 
 
1757
            show_log(b,
 
1758
                     lf,
 
1759
                     file_id,
 
1760
                     verbose=verbose,
 
1761
                     direction=direction,
 
1762
                     start_revision=rev1,
 
1763
                     end_revision=rev2,
 
1764
                     search=message,
 
1765
                     limit=limit)
2250
1766
        finally:
2251
1767
            b.unlock()
2252
1768
 
2253
1769
 
2254
 
def _get_revision_range(revisionspec_list, branch, command_name):
2255
 
    """Take the input of a revision option and turn it into a revision range.
2256
 
 
2257
 
    It returns RevisionInfo objects which can be used to obtain the rev_id's
2258
 
    of the desired revisions. It does some user input validations.
2259
 
    """
2260
 
    if revisionspec_list is None:
2261
 
        rev1 = None
2262
 
        rev2 = None
2263
 
    elif len(revisionspec_list) == 1:
2264
 
        rev1 = rev2 = revisionspec_list[0].in_history(branch)
2265
 
    elif len(revisionspec_list) == 2:
2266
 
        start_spec = revisionspec_list[0]
2267
 
        end_spec = revisionspec_list[1]
2268
 
        if end_spec.get_branch() != start_spec.get_branch():
2269
 
            # b is taken from revision[0].get_branch(), and
2270
 
            # show_log will use its revision_history. Having
2271
 
            # different branches will lead to weird behaviors.
2272
 
            raise errors.BzrCommandError(
2273
 
                "bzr %s doesn't accept two revisions in different"
2274
 
                " branches." % command_name)
2275
 
        rev1 = start_spec.in_history(branch)
2276
 
        # Avoid loading all of history when we know a missing
2277
 
        # end of range means the last revision ...
2278
 
        if end_spec.spec is None:
2279
 
            last_revno, last_revision_id = branch.last_revision_info()
2280
 
            rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2281
 
        else:
2282
 
            rev2 = end_spec.in_history(branch)
2283
 
    else:
2284
 
        raise errors.BzrCommandError(
2285
 
            'bzr %s --revision takes one or two values.' % command_name)
2286
 
    return rev1, rev2
2287
 
 
2288
 
 
2289
 
def _revision_range_to_revid_range(revision_range):
2290
 
    rev_id1 = None
2291
 
    rev_id2 = None
2292
 
    if revision_range[0] is not None:
2293
 
        rev_id1 = revision_range[0].rev_id
2294
 
    if revision_range[1] is not None:
2295
 
        rev_id2 = revision_range[1].rev_id
2296
 
    return rev_id1, rev_id2
2297
 
 
2298
1770
def get_log_format(long=False, short=False, line=False, default='long'):
2299
1771
    log_format = default
2300
1772
    if long:
2330
1802
 
2331
1803
    _see_also = ['status', 'cat']
2332
1804
    takes_args = ['path?']
 
1805
    # TODO: Take a revision or remote path and list that tree instead.
2333
1806
    takes_options = [
2334
1807
            'verbose',
2335
1808
            'revision',
2336
 
            Option('recursive', short_name='R',
2337
 
                   help='Recurse into subdirectories.'),
 
1809
            Option('non-recursive',
 
1810
                   help='Don\'t recurse into subdirectories.'),
2338
1811
            Option('from-root',
2339
1812
                   help='Print paths relative to the root of the branch.'),
2340
1813
            Option('unknown', help='Print unknown files.'),
2341
 
            Option('versioned', help='Print versioned files.',
2342
 
                   short_name='V'),
 
1814
            Option('versioned', help='Print versioned files.'),
2343
1815
            Option('ignored', help='Print ignored files.'),
2344
1816
            Option('null',
2345
1817
                   help='Write an ascii NUL (\\0) separator '
2351
1823
            ]
2352
1824
    @display_command
2353
1825
    def run(self, revision=None, verbose=False,
2354
 
            recursive=False, from_root=False,
 
1826
            non_recursive=False, from_root=False,
2355
1827
            unknown=False, versioned=False, ignored=False,
2356
1828
            null=False, kind=None, show_ids=False, path=None):
2357
1829
 
2379
1851
            relpath = u''
2380
1852
        elif relpath:
2381
1853
            relpath += '/'
2382
 
        if revision is not None or tree is None:
2383
 
            tree = _get_one_revision_tree('ls', revision, branch=branch)
2384
 
 
2385
 
        apply_view = False
2386
 
        if isinstance(tree, WorkingTree) and tree.supports_views():
2387
 
            view_files = tree.views.lookup_view()
2388
 
            if view_files:
2389
 
                apply_view = True
2390
 
                view_str = views.view_display_str(view_files)
2391
 
                note("Ignoring files outside view. View is %s" % view_str)
 
1854
        if revision is not None:
 
1855
            tree = branch.repository.revision_tree(
 
1856
                revision[0].in_history(branch).rev_id)
 
1857
        elif tree is None:
 
1858
            tree = branch.basis_tree()
2392
1859
 
2393
1860
        tree.lock_read()
2394
1861
        try:
2395
1862
            for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2396
1863
                if fp.startswith(relpath):
2397
 
                    rp = fp[len(relpath):]
2398
 
                    fp = osutils.pathjoin(prefix, rp)
2399
 
                    if not recursive and '/' in rp:
 
1864
                    fp = osutils.pathjoin(prefix, fp[len(relpath):])
 
1865
                    if non_recursive and '/' in fp:
2400
1866
                        continue
2401
1867
                    if not all and not selection[fc]:
2402
1868
                        continue
2403
1869
                    if kind is not None and fkind != kind:
2404
1870
                        continue
2405
 
                    if apply_view:
2406
 
                        try:
2407
 
                            views.check_path_in_view(tree, fp)
2408
 
                        except errors.FileOutsideView:
2409
 
                            continue
2410
 
                    kindch = entry.kind_character()
2411
 
                    outstring = fp + kindch
2412
1871
                    if verbose:
2413
 
                        outstring = '%-8s %s' % (fc, outstring)
 
1872
                        kindch = entry.kind_character()
 
1873
                        outstring = '%-8s %s%s' % (fc, fp, kindch)
2414
1874
                        if show_ids and fid is not None:
2415
1875
                            outstring = "%-50s %s" % (outstring, fid)
2416
1876
                        self.outf.write(outstring + '\n')
2427
1887
                        else:
2428
1888
                            my_id = ''
2429
1889
                        if show_ids:
2430
 
                            self.outf.write('%-50s %s\n' % (outstring, my_id))
 
1890
                            self.outf.write('%-50s %s\n' % (fp, my_id))
2431
1891
                        else:
2432
 
                            self.outf.write(outstring + '\n')
 
1892
                            self.outf.write(fp + '\n')
2433
1893
        finally:
2434
1894
            tree.unlock()
2435
1895
 
2450
1910
class cmd_ignore(Command):
2451
1911
    """Ignore specified files or patterns.
2452
1912
 
2453
 
    See ``bzr help patterns`` for details on the syntax of patterns.
2454
 
 
2455
1913
    To remove patterns from the ignore list, edit the .bzrignore file.
2456
 
    After adding, editing or deleting that file either indirectly by
2457
 
    using this command or directly by using an editor, be sure to commit
2458
 
    it.
2459
 
 
2460
 
    Note: ignore patterns containing shell wildcards must be quoted from
 
1914
 
 
1915
    Trailing slashes on patterns are ignored. 
 
1916
    If the pattern contains a slash or is a regular expression, it is compared 
 
1917
    to the whole path from the branch root.  Otherwise, it is compared to only
 
1918
    the last component of the path.  To match a file only in the root 
 
1919
    directory, prepend './'.
 
1920
 
 
1921
    Ignore patterns specifying absolute paths are not allowed.
 
1922
 
 
1923
    Ignore patterns may include globbing wildcards such as::
 
1924
 
 
1925
      ? - Matches any single character except '/'
 
1926
      * - Matches 0 or more characters except '/'
 
1927
      /**/ - Matches 0 or more directories in a path
 
1928
      [a-z] - Matches a single character from within a group of characters
 
1929
 
 
1930
    Ignore patterns may also be Python regular expressions.  
 
1931
    Regular expression ignore patterns are identified by a 'RE:' prefix 
 
1932
    followed by the regular expression.  Regular expression ignore patterns
 
1933
    may not include named or numbered groups.
 
1934
 
 
1935
    Note: ignore patterns containing shell wildcards must be quoted from 
2461
1936
    the shell on Unix.
2462
1937
 
2463
1938
    :Examples:
2482
1957
            bzr ignore "RE:(?!debian/).*"
2483
1958
    """
2484
1959
 
2485
 
    _see_also = ['status', 'ignored', 'patterns']
 
1960
    _see_also = ['status', 'ignored']
2486
1961
    takes_args = ['name_pattern*']
2487
1962
    takes_options = [
2488
1963
        Option('old-default-rules',
2489
1964
               help='Write out the ignore rules bzr < 0.9 always used.')
2490
1965
        ]
2491
 
 
 
1966
    
2492
1967
    def run(self, name_pattern_list=None, old_default_rules=None):
2493
 
        from bzrlib import ignores
 
1968
        from bzrlib.atomicfile import AtomicFile
2494
1969
        if old_default_rules is not None:
2495
1970
            # dump the rules and exit
2496
1971
            for pattern in ignores.OLD_DEFAULTS:
2499
1974
        if not name_pattern_list:
2500
1975
            raise errors.BzrCommandError("ignore requires at least one "
2501
1976
                                  "NAME_PATTERN or --old-default-rules")
2502
 
        name_pattern_list = [globbing.normalize_pattern(p)
 
1977
        name_pattern_list = [globbing.normalize_pattern(p) 
2503
1978
                             for p in name_pattern_list]
2504
1979
        for name_pattern in name_pattern_list:
2505
 
            if (name_pattern[0] == '/' or
 
1980
            if (name_pattern[0] == '/' or 
2506
1981
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
2507
1982
                raise errors.BzrCommandError(
2508
1983
                    "NAME_PATTERN should not be an absolute path")
2509
1984
        tree, relpath = WorkingTree.open_containing(u'.')
2510
 
        ignores.tree_ignores_add_patterns(tree, name_pattern_list)
 
1985
        ifn = tree.abspath('.bzrignore')
 
1986
        if os.path.exists(ifn):
 
1987
            f = open(ifn, 'rt')
 
1988
            try:
 
1989
                igns = f.read().decode('utf-8')
 
1990
            finally:
 
1991
                f.close()
 
1992
        else:
 
1993
            igns = ''
 
1994
 
 
1995
        # TODO: If the file already uses crlf-style termination, maybe
 
1996
        # we should use that for the newly added lines?
 
1997
 
 
1998
        if igns and igns[-1] != '\n':
 
1999
            igns += '\n'
 
2000
        for name_pattern in name_pattern_list:
 
2001
            igns += name_pattern + '\n'
 
2002
 
 
2003
        f = AtomicFile(ifn, 'wb')
 
2004
        try:
 
2005
            f.write(igns.encode('utf-8'))
 
2006
            f.commit()
 
2007
        finally:
 
2008
            f.close()
 
2009
 
 
2010
        if not tree.path2id('.bzrignore'):
 
2011
            tree.add(['.bzrignore'])
 
2012
 
2511
2013
        ignored = globbing.Globster(name_pattern_list)
2512
2014
        matches = []
2513
2015
        tree.lock_read()
2520
2022
        tree.unlock()
2521
2023
        if len(matches) > 0:
2522
2024
            print "Warning: the following files are version controlled and" \
2523
 
                  " match your ignore pattern:\n%s" \
2524
 
                  "\nThese files will continue to be version controlled" \
2525
 
                  " unless you 'bzr remove' them." % ("\n".join(matches),)
2526
 
 
 
2025
                  " match your ignore pattern:\n%s" % ("\n".join(matches),)
2527
2026
 
2528
2027
class cmd_ignored(Command):
2529
2028
    """List ignored files and the patterns that matched them.
2530
 
 
2531
 
    List all the ignored files and the ignore pattern that caused the file to
2532
 
    be ignored.
2533
 
 
2534
 
    Alternatively, to list just the files::
2535
 
 
2536
 
        bzr ls --ignored
2537
2029
    """
2538
2030
 
2539
2031
    encoding_type = 'replace'
2540
 
    _see_also = ['ignore', 'ls']
 
2032
    _see_also = ['ignore']
2541
2033
 
2542
2034
    @display_command
2543
2035
    def run(self):
2562
2054
    """
2563
2055
    hidden = True
2564
2056
    takes_args = ['revno']
2565
 
 
 
2057
    
2566
2058
    @display_command
2567
2059
    def run(self, revno):
2568
2060
        try:
2601
2093
         zip                          .zip
2602
2094
      =================       =========================
2603
2095
    """
2604
 
    takes_args = ['dest', 'branch_or_subdir?']
 
2096
    takes_args = ['dest', 'branch?']
2605
2097
    takes_options = [
2606
2098
        Option('format',
2607
2099
               help="Type of file to export to.",
2608
2100
               type=unicode),
2609
2101
        'revision',
2610
 
        Option('filters', help='Apply content filters to export the '
2611
 
                'convenient form.'),
2612
2102
        Option('root',
2613
2103
               type=str,
2614
2104
               help="Name of the root directory inside the exported file."),
2615
2105
        ]
2616
 
    def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2617
 
        root=None, filters=False):
 
2106
    def run(self, dest, branch=None, revision=None, format=None, root=None):
2618
2107
        from bzrlib.export import export
2619
2108
 
2620
 
        if branch_or_subdir is None:
 
2109
        if branch is None:
2621
2110
            tree = WorkingTree.open_containing(u'.')[0]
2622
2111
            b = tree.branch
2623
 
            subdir = None
2624
 
        else:
2625
 
            b, subdir = Branch.open_containing(branch_or_subdir)
2626
 
            tree = None
2627
 
 
2628
 
        rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
 
2112
        else:
 
2113
            b = Branch.open(branch)
 
2114
            
 
2115
        if revision is None:
 
2116
            # should be tree.last_revision  FIXME
 
2117
            rev_id = b.last_revision()
 
2118
        else:
 
2119
            if len(revision) != 1:
 
2120
                raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
 
2121
            rev_id = revision[0].in_history(b).rev_id
 
2122
        t = b.repository.revision_tree(rev_id)
2629
2123
        try:
2630
 
            export(rev_tree, dest, format, root, subdir, filtered=filters)
 
2124
            export(t, dest, format, root)
2631
2125
        except errors.NoSuchExportFormat, e:
2632
2126
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
2633
2127
 
2638
2132
    If no revision is nominated, the last revision is used.
2639
2133
 
2640
2134
    Note: Take care to redirect standard output when using this command on a
2641
 
    binary file.
 
2135
    binary file. 
2642
2136
    """
2643
2137
 
2644
2138
    _see_also = ['ls']
2645
2139
    takes_options = [
2646
2140
        Option('name-from-revision', help='The path name in the old tree.'),
2647
 
        Option('filters', help='Apply content filters to display the '
2648
 
                'convenience form.'),
2649
2141
        'revision',
2650
2142
        ]
2651
2143
    takes_args = ['filename']
2652
2144
    encoding_type = 'exact'
2653
2145
 
2654
2146
    @display_command
2655
 
    def run(self, filename, revision=None, name_from_revision=False,
2656
 
            filters=False):
 
2147
    def run(self, filename, revision=None, name_from_revision=False):
2657
2148
        if revision is not None and len(revision) != 1:
2658
2149
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
2659
2150
                                         " one revision specifier")
2662
2153
        branch.lock_read()
2663
2154
        try:
2664
2155
            return self._run(tree, branch, relpath, filename, revision,
2665
 
                             name_from_revision, filters)
 
2156
                             name_from_revision)
2666
2157
        finally:
2667
2158
            branch.unlock()
2668
2159
 
2669
 
    def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2670
 
        filtered):
 
2160
    def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2671
2161
        if tree is None:
2672
2162
            tree = b.basis_tree()
2673
 
        rev_tree = _get_one_revision_tree('cat', revision, branch=b)
 
2163
        if revision is None:
 
2164
            revision_id = b.last_revision()
 
2165
        else:
 
2166
            revision_id = revision[0].in_history(b).rev_id
2674
2167
 
 
2168
        cur_file_id = tree.path2id(relpath)
 
2169
        rev_tree = b.repository.revision_tree(revision_id)
2675
2170
        old_file_id = rev_tree.path2id(relpath)
2676
 
 
 
2171
        
2677
2172
        if name_from_revision:
2678
 
            # Try in revision if requested
2679
2173
            if old_file_id is None:
2680
 
                raise errors.BzrCommandError(
2681
 
                    "%r is not present in revision %s" % (
2682
 
                        filename, rev_tree.get_revision_id()))
 
2174
                raise errors.BzrCommandError("%r is not present in revision %s"
 
2175
                                                % (filename, revision_id))
2683
2176
            else:
2684
 
                content = rev_tree.get_file_text(old_file_id)
2685
 
        else:
2686
 
            cur_file_id = tree.path2id(relpath)
2687
 
            found = False
2688
 
            if cur_file_id is not None:
2689
 
                # Then try with the actual file id
2690
 
                try:
2691
 
                    content = rev_tree.get_file_text(cur_file_id)
2692
 
                    found = True
2693
 
                except errors.NoSuchId:
2694
 
                    # The actual file id didn't exist at that time
2695
 
                    pass
2696
 
            if not found and old_file_id is not None:
2697
 
                # Finally try with the old file id
2698
 
                content = rev_tree.get_file_text(old_file_id)
2699
 
                found = True
2700
 
            if not found:
2701
 
                # Can't be found anywhere
2702
 
                raise errors.BzrCommandError(
2703
 
                    "%r is not present in revision %s" % (
2704
 
                        filename, rev_tree.get_revision_id()))
2705
 
        if filtered:
2706
 
            from bzrlib.filters import (
2707
 
                ContentFilterContext,
2708
 
                filtered_output_bytes,
2709
 
                )
2710
 
            filters = rev_tree._content_filter_stack(relpath)
2711
 
            chunks = content.splitlines(True)
2712
 
            content = filtered_output_bytes(chunks, filters,
2713
 
                ContentFilterContext(relpath, rev_tree))
2714
 
            self.outf.writelines(content)
2715
 
        else:
2716
 
            self.outf.write(content)
 
2177
                rev_tree.print_file(old_file_id)
 
2178
        elif cur_file_id is not None:
 
2179
            rev_tree.print_file(cur_file_id)
 
2180
        elif old_file_id is not None:
 
2181
            rev_tree.print_file(old_file_id)
 
2182
        else:
 
2183
            raise errors.BzrCommandError("%r is not present in revision %s" %
 
2184
                                         (filename, revision_id))
2717
2185
 
2718
2186
 
2719
2187
class cmd_local_time_offset(Command):
2720
2188
    """Show the offset in seconds from GMT to local time."""
2721
 
    hidden = True
 
2189
    hidden = True    
2722
2190
    @display_command
2723
2191
    def run(self):
2724
2192
        print osutils.local_time_offset()
2727
2195
 
2728
2196
class cmd_commit(Command):
2729
2197
    """Commit changes into a new revision.
2730
 
 
2731
 
    An explanatory message needs to be given for each commit. This is
2732
 
    often done by using the --message option (getting the message from the
2733
 
    command line) or by using the --file option (getting the message from
2734
 
    a file). If neither of these options is given, an editor is opened for
2735
 
    the user to enter the message. To see the changed files in the
2736
 
    boilerplate text loaded into the editor, use the --show-diff option.
2737
 
 
2738
 
    By default, the entire tree is committed and the person doing the
2739
 
    commit is assumed to be the author. These defaults can be overridden
2740
 
    as explained below.
2741
 
 
2742
 
    :Selective commits:
2743
 
 
2744
 
      If selected files are specified, only changes to those files are
2745
 
      committed.  If a directory is specified then the directory and
2746
 
      everything within it is committed.
2747
 
  
2748
 
      When excludes are given, they take precedence over selected files.
2749
 
      For example, to commit only changes within foo, but not changes
2750
 
      within foo/bar::
2751
 
  
2752
 
        bzr commit foo -x foo/bar
2753
 
  
2754
 
      A selective commit after a merge is not yet supported.
2755
 
 
2756
 
    :Custom authors:
2757
 
 
2758
 
      If the author of the change is not the same person as the committer,
2759
 
      you can specify the author's name using the --author option. The
2760
 
      name should be in the same format as a committer-id, e.g.
2761
 
      "John Doe <jdoe@example.com>". If there is more than one author of
2762
 
      the change you can specify the option multiple times, once for each
2763
 
      author.
2764
 
  
2765
 
    :Checks:
2766
 
 
2767
 
      A common mistake is to forget to add a new file or directory before
2768
 
      running the commit command. The --strict option checks for unknown
2769
 
      files and aborts the commit if any are found. More advanced pre-commit
2770
 
      checks can be implemented by defining hooks. See ``bzr help hooks``
2771
 
      for details.
2772
 
 
2773
 
    :Things to note:
2774
 
 
2775
 
      If you accidentially commit the wrong changes or make a spelling
2776
 
      mistake in the commit message say, you can use the uncommit command
2777
 
      to undo it. See ``bzr help uncommit`` for details.
2778
 
 
2779
 
      Hooks can also be configured to run after a commit. This allows you
2780
 
      to trigger updates to external systems like bug trackers. The --fixes
2781
 
      option can be used to record the association between a revision and
2782
 
      one or more bugs. See ``bzr help bugs`` for details.
2783
 
 
2784
 
      A selective commit may fail in some cases where the committed
2785
 
      tree would be invalid. Consider::
2786
 
  
2787
 
        bzr init foo
2788
 
        mkdir foo/bar
2789
 
        bzr add foo/bar
2790
 
        bzr commit foo -m "committing foo"
2791
 
        bzr mv foo/bar foo/baz
2792
 
        mkdir foo/bar
2793
 
        bzr add foo/bar
2794
 
        bzr commit foo/bar -m "committing bar but not baz"
2795
 
  
2796
 
      In the example above, the last commit will fail by design. This gives
2797
 
      the user the opportunity to decide whether they want to commit the
2798
 
      rename at the same time, separately first, or not at all. (As a general
2799
 
      rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
 
2198
    
 
2199
    If no arguments are given, the entire tree is committed.
 
2200
 
 
2201
    If selected files are specified, only changes to those files are
 
2202
    committed.  If a directory is specified then the directory and everything 
 
2203
    within it is committed.
 
2204
 
 
2205
    If author of the change is not the same person as the committer, you can
 
2206
    specify the author's name using the --author option. The name should be
 
2207
    in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
 
2208
 
 
2209
    A selected-file commit may fail in some cases where the committed
 
2210
    tree would be invalid. Consider::
 
2211
 
 
2212
      bzr init foo
 
2213
      mkdir foo/bar
 
2214
      bzr add foo/bar
 
2215
      bzr commit foo -m "committing foo"
 
2216
      bzr mv foo/bar foo/baz
 
2217
      mkdir foo/bar
 
2218
      bzr add foo/bar
 
2219
      bzr commit foo/bar -m "committing bar but not baz"
 
2220
 
 
2221
    In the example above, the last commit will fail by design. This gives
 
2222
    the user the opportunity to decide whether they want to commit the
 
2223
    rename at the same time, separately first, or not at all. (As a general
 
2224
    rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
 
2225
 
 
2226
    Note: A selected-file commit after a merge is not yet supported.
2800
2227
    """
2801
2228
    # TODO: Run hooks on tree to-be-committed, and after commit.
2802
2229
 
2807
2234
 
2808
2235
    # XXX: verbose currently does nothing
2809
2236
 
2810
 
    _see_also = ['add', 'bugs', 'hooks', 'uncommit']
 
2237
    _see_also = ['bugs', 'uncommit']
2811
2238
    takes_args = ['selected*']
2812
2239
    takes_options = [
2813
 
            ListOption('exclude', type=str, short_name='x',
2814
 
                help="Do not consider changes made to a given path."),
2815
2240
            Option('message', type=unicode,
2816
2241
                   short_name='m',
2817
2242
                   help="Description of the new revision."),
2826
2251
                    help="Refuse to commit if there are unknown "
2827
2252
                    "files in the working tree."),
2828
2253
             ListOption('fixes', type=str,
2829
 
                    help="Mark a bug as being fixed by this revision "
2830
 
                         "(see \"bzr help bugs\")."),
2831
 
             ListOption('author', type=unicode,
 
2254
                    help="Mark a bug as being fixed by this revision."),
 
2255
             Option('author', type=unicode,
2832
2256
                    help="Set the author's name, if it's different "
2833
2257
                         "from the committer."),
2834
2258
             Option('local',
2843
2267
             ]
2844
2268
    aliases = ['ci', 'checkin']
2845
2269
 
2846
 
    def _iter_bug_fix_urls(self, fixes, branch):
 
2270
    def _get_bug_fix_properties(self, fixes, branch):
 
2271
        properties = []
2847
2272
        # Configure the properties for bug fixing attributes.
2848
2273
        for fixed_bug in fixes:
2849
2274
            tokens = fixed_bug.split(':')
2850
2275
            if len(tokens) != 2:
2851
2276
                raise errors.BzrCommandError(
2852
 
                    "Invalid bug %s. Must be in the form of 'tracker:id'. "
2853
 
                    "See \"bzr help bugs\" for more information on this "
2854
 
                    "feature.\nCommit refused." % fixed_bug)
 
2277
                    "Invalid bug %s. Must be in the form of 'tag:id'. "
 
2278
                    "Commit refused." % fixed_bug)
2855
2279
            tag, bug_id = tokens
2856
2280
            try:
2857
 
                yield bugtracker.get_bug_url(tag, branch, bug_id)
 
2281
                bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
2858
2282
            except errors.UnknownBugTrackerAbbreviation:
2859
2283
                raise errors.BzrCommandError(
2860
2284
                    'Unrecognized bug %s. Commit refused.' % fixed_bug)
2861
 
            except errors.MalformedBugIdentifier, e:
 
2285
            except errors.MalformedBugIdentifier:
2862
2286
                raise errors.BzrCommandError(
2863
 
                    "%s\nCommit refused." % (str(e),))
 
2287
                    "Invalid bug identifier for %s. Commit refused."
 
2288
                    % fixed_bug)
 
2289
            properties.append('%s fixed' % bug_url)
 
2290
        return '\n'.join(properties)
2864
2291
 
2865
2292
    def run(self, message=None, file=None, verbose=False, selected_list=None,
2866
2293
            unchanged=False, strict=False, local=False, fixes=None,
2867
 
            author=None, show_diff=False, exclude=None):
 
2294
            author=None, show_diff=False):
2868
2295
        from bzrlib.errors import (
2869
2296
            PointlessCommit,
2870
2297
            ConflictsInTree,
2872
2299
        )
2873
2300
        from bzrlib.msgeditor import (
2874
2301
            edit_commit_message_encoded,
2875
 
            generate_commit_message_template,
2876
2302
            make_commit_message_template_encoded
2877
2303
        )
2878
2304
 
2879
2305
        # TODO: Need a blackbox test for invoking the external editor; may be
2880
2306
        # slightly problematic to run this cross-platform.
2881
2307
 
2882
 
        # TODO: do more checks that the commit will succeed before
 
2308
        # TODO: do more checks that the commit will succeed before 
2883
2309
        # spending the user's valuable time typing a commit message.
2884
2310
 
2885
2311
        properties = {}
2893
2319
 
2894
2320
        if fixes is None:
2895
2321
            fixes = []
2896
 
        bug_property = bugtracker.encode_fixes_bug_urls(
2897
 
            self._iter_bug_fix_urls(fixes, tree.branch))
 
2322
        bug_property = self._get_bug_fix_properties(fixes, tree.branch)
2898
2323
        if bug_property:
2899
2324
            properties['bugs'] = bug_property
2900
2325
 
2907
2332
            if my_message is None and not file:
2908
2333
                t = make_commit_message_template_encoded(tree,
2909
2334
                        selected_list, diff=show_diff,
2910
 
                        output_encoding=osutils.get_user_encoding())
2911
 
                start_message = generate_commit_message_template(commit_obj)
2912
 
                my_message = edit_commit_message_encoded(t,
2913
 
                    start_message=start_message)
 
2335
                        output_encoding=bzrlib.user_encoding)
 
2336
                my_message = edit_commit_message_encoded(t)
2914
2337
                if my_message is None:
2915
2338
                    raise errors.BzrCommandError("please specify a commit"
2916
2339
                        " message with either --message or --file")
2918
2341
                raise errors.BzrCommandError(
2919
2342
                    "please specify either --message or --file")
2920
2343
            if file:
2921
 
                my_message = codecs.open(file, 'rt',
2922
 
                                         osutils.get_user_encoding()).read()
 
2344
                my_message = codecs.open(file, 'rt', 
 
2345
                                         bzrlib.user_encoding).read()
2923
2346
            if my_message == "":
2924
2347
                raise errors.BzrCommandError("empty commit message specified")
2925
2348
            return my_message
2929
2352
                        specific_files=selected_list,
2930
2353
                        allow_pointless=unchanged, strict=strict, local=local,
2931
2354
                        reporter=None, verbose=verbose, revprops=properties,
2932
 
                        authors=author,
2933
 
                        exclude=safe_relpath_files(tree, exclude))
 
2355
                        author=author)
2934
2356
        except PointlessCommit:
2935
2357
            # FIXME: This should really happen before the file is read in;
2936
2358
            # perhaps prepare the commit; get the message; then actually commit
2937
 
            raise errors.BzrCommandError("No changes to commit."
2938
 
                              " Use --unchanged to commit anyhow.")
 
2359
            raise errors.BzrCommandError("no changes to commit."
 
2360
                              " use --unchanged to commit anyhow")
2939
2361
        except ConflictsInTree:
2940
2362
            raise errors.BzrCommandError('Conflicts detected in working '
2941
2363
                'tree.  Use "bzr conflicts" to list, "bzr resolve FILE" to'
2951
2373
 
2952
2374
 
2953
2375
class cmd_check(Command):
2954
 
    """Validate working tree structure, branch consistency and repository history.
2955
 
 
2956
 
    This command checks various invariants about branch and repository storage
2957
 
    to detect data corruption or bzr bugs.
2958
 
 
2959
 
    The working tree and branch checks will only give output if a problem is
2960
 
    detected. The output fields of the repository check are:
 
2376
    """Validate consistency of branch history.
 
2377
 
 
2378
    This command checks various invariants about the branch storage to
 
2379
    detect data corruption or bzr bugs.
 
2380
 
 
2381
    Output fields:
2961
2382
 
2962
2383
        revisions: This is just the number of revisions checked.  It doesn't
2963
2384
            indicate a problem.
2972
2393
            in the checked revisions.  Texts can be repeated when their file
2973
2394
            entries are modified, but the file contents are not.  It does not
2974
2395
            indicate a problem.
2975
 
 
2976
 
    If no restrictions are specified, all Bazaar data that is found at the given
2977
 
    location will be checked.
2978
 
 
2979
 
    :Examples:
2980
 
 
2981
 
        Check the tree and branch at 'foo'::
2982
 
 
2983
 
            bzr check --tree --branch foo
2984
 
 
2985
 
        Check only the repository at 'bar'::
2986
 
 
2987
 
            bzr check --repo bar
2988
 
 
2989
 
        Check everything at 'baz'::
2990
 
 
2991
 
            bzr check baz
2992
2396
    """
2993
2397
 
2994
2398
    _see_also = ['reconcile']
2995
 
    takes_args = ['path?']
2996
 
    takes_options = ['verbose',
2997
 
                     Option('branch', help="Check the branch related to the"
2998
 
                                           " current directory."),
2999
 
                     Option('repo', help="Check the repository related to the"
3000
 
                                         " current directory."),
3001
 
                     Option('tree', help="Check the working tree related to"
3002
 
                                         " the current directory.")]
 
2399
    takes_args = ['branch?']
 
2400
    takes_options = ['verbose']
3003
2401
 
3004
 
    def run(self, path=None, verbose=False, branch=False, repo=False,
3005
 
            tree=False):
3006
 
        from bzrlib.check import check_dwim
3007
 
        if path is None:
3008
 
            path = '.'
3009
 
        if not branch and not repo and not tree:
3010
 
            branch = repo = tree = True
3011
 
        check_dwim(path, verbose, do_branch=branch, do_repo=repo, do_tree=tree)
 
2402
    def run(self, branch=None, verbose=False):
 
2403
        from bzrlib.check import check
 
2404
        if branch is None:
 
2405
            branch_obj = Branch.open_containing('.')[0]
 
2406
        else:
 
2407
            branch_obj = Branch.open(branch)
 
2408
        check(branch_obj, verbose)
 
2409
        # bit hacky, check the tree parent is accurate
 
2410
        try:
 
2411
            if branch is None:
 
2412
                tree = WorkingTree.open_containing('.')[0]
 
2413
            else:
 
2414
                tree = WorkingTree.open(branch)
 
2415
        except (errors.NoWorkingTree, errors.NotLocalUrl):
 
2416
            pass
 
2417
        else:
 
2418
            # This is a primitive 'check' for tree state. Currently this is not
 
2419
            # integrated into the main check logic as yet.
 
2420
            tree.lock_read()
 
2421
            try:
 
2422
                tree_basis = tree.basis_tree()
 
2423
                tree_basis.lock_read()
 
2424
                try:
 
2425
                    repo_basis = tree.branch.repository.revision_tree(
 
2426
                        tree.last_revision())
 
2427
                    if len(list(repo_basis.iter_changes(tree_basis))):
 
2428
                        raise errors.BzrCheckError(
 
2429
                            "Mismatched basis inventory content.")
 
2430
                    tree._validate()
 
2431
                finally:
 
2432
                    tree_basis.unlock()
 
2433
            finally:
 
2434
                tree.unlock()
3012
2435
 
3013
2436
 
3014
2437
class cmd_upgrade(Command):
3025
2448
                    RegistryOption('format',
3026
2449
                        help='Upgrade to a specific format.  See "bzr help'
3027
2450
                             ' formats" for details.',
3028
 
                        lazy_registry=('bzrlib.bzrdir', 'format_registry'),
3029
 
                        converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
 
2451
                        registry=bzrdir.format_registry,
 
2452
                        converter=bzrdir.format_registry.make_bzrdir,
3030
2453
                        value_switches=True, title='Branch format'),
3031
2454
                    ]
3032
2455
 
3033
2456
    def run(self, url='.', format=None):
3034
2457
        from bzrlib.upgrade import upgrade
 
2458
        if format is None:
 
2459
            format = bzrdir.format_registry.make_bzrdir('default')
3035
2460
        upgrade(url, format)
3036
2461
 
3037
2462
 
3038
2463
class cmd_whoami(Command):
3039
2464
    """Show or set bzr user id.
3040
 
 
 
2465
    
3041
2466
    :Examples:
3042
2467
        Show the email of the current user::
3043
2468
 
3055
2480
                    ]
3056
2481
    takes_args = ['name?']
3057
2482
    encoding_type = 'replace'
3058
 
 
 
2483
    
3059
2484
    @display_command
3060
2485
    def run(self, email=False, branch=False, name=None):
3061
2486
        if name is None:
3076
2501
        except errors.NoEmailInUsername, e:
3077
2502
            warning('"%s" does not seem to contain an email address.  '
3078
2503
                    'This is allowed, but not recommended.', name)
3079
 
 
 
2504
        
3080
2505
        # use global config unless --branch given
3081
2506
        if branch:
3082
2507
            c = Branch.open_containing('.')[0].get_config()
3086
2511
 
3087
2512
 
3088
2513
class cmd_nick(Command):
3089
 
    """Print or set the branch nickname.
3090
 
 
3091
 
    If unset, the tree root directory name is used as the nickname.
3092
 
    To print the current nickname, execute with no argument.
3093
 
 
3094
 
    Bound branches use the nickname of its master branch unless it is set
3095
 
    locally.
 
2514
    """Print or set the branch nickname.  
 
2515
 
 
2516
    If unset, the tree root directory name is used as the nickname
 
2517
    To print the current nickname, execute with no argument.  
3096
2518
    """
3097
2519
 
3098
2520
    _see_also = ['info']
3109
2531
        print branch.nick
3110
2532
 
3111
2533
 
3112
 
class cmd_alias(Command):
3113
 
    """Set/unset and display aliases.
3114
 
 
3115
 
    :Examples:
3116
 
        Show the current aliases::
3117
 
 
3118
 
            bzr alias
3119
 
 
3120
 
        Show the alias specified for 'll'::
3121
 
 
3122
 
            bzr alias ll
3123
 
 
3124
 
        Set an alias for 'll'::
3125
 
 
3126
 
            bzr alias ll="log --line -r-10..-1"
3127
 
 
3128
 
        To remove an alias for 'll'::
3129
 
 
3130
 
            bzr alias --remove ll
3131
 
 
3132
 
    """
3133
 
    takes_args = ['name?']
3134
 
    takes_options = [
3135
 
        Option('remove', help='Remove the alias.'),
3136
 
        ]
3137
 
 
3138
 
    def run(self, name=None, remove=False):
3139
 
        if remove:
3140
 
            self.remove_alias(name)
3141
 
        elif name is None:
3142
 
            self.print_aliases()
3143
 
        else:
3144
 
            equal_pos = name.find('=')
3145
 
            if equal_pos == -1:
3146
 
                self.print_alias(name)
3147
 
            else:
3148
 
                self.set_alias(name[:equal_pos], name[equal_pos+1:])
3149
 
 
3150
 
    def remove_alias(self, alias_name):
3151
 
        if alias_name is None:
3152
 
            raise errors.BzrCommandError(
3153
 
                'bzr alias --remove expects an alias to remove.')
3154
 
        # If alias is not found, print something like:
3155
 
        # unalias: foo: not found
3156
 
        c = config.GlobalConfig()
3157
 
        c.unset_alias(alias_name)
3158
 
 
3159
 
    @display_command
3160
 
    def print_aliases(self):
3161
 
        """Print out the defined aliases in a similar format to bash."""
3162
 
        aliases = config.GlobalConfig().get_aliases()
3163
 
        for key, value in sorted(aliases.iteritems()):
3164
 
            self.outf.write('bzr alias %s="%s"\n' % (key, value))
3165
 
 
3166
 
    @display_command
3167
 
    def print_alias(self, alias_name):
3168
 
        from bzrlib.commands import get_alias
3169
 
        alias = get_alias(alias_name)
3170
 
        if alias is None:
3171
 
            self.outf.write("bzr alias: %s: not found\n" % alias_name)
3172
 
        else:
3173
 
            self.outf.write(
3174
 
                'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
3175
 
 
3176
 
    def set_alias(self, alias_name, alias_command):
3177
 
        """Save the alias in the global config."""
3178
 
        c = config.GlobalConfig()
3179
 
        c.set_alias(alias_name, alias_command)
3180
 
 
3181
 
 
3182
2534
class cmd_selftest(Command):
3183
2535
    """Run internal test suite.
3184
 
 
 
2536
    
3185
2537
    If arguments are given, they are regular expressions that say which tests
3186
2538
    should run.  Tests matching any expression are run, and other tests are
3187
2539
    not run.
3210
2562
    modified by plugins will not be tested, and tests provided by plugins will
3211
2563
    not be run.
3212
2564
 
3213
 
    Tests that need working space on disk use a common temporary directory,
 
2565
    Tests that need working space on disk use a common temporary directory, 
3214
2566
    typically inside $TMPDIR or /tmp.
3215
2567
 
3216
2568
    :Examples:
3264
2616
                            ),
3265
2617
                     Option('list-only',
3266
2618
                            help='List the tests instead of running them.'),
3267
 
                     RegistryOption('parallel',
3268
 
                        help="Run the test suite in parallel.",
3269
 
                        lazy_registry=('bzrlib.tests', 'parallel_registry'),
3270
 
                        value_switches=False,
3271
 
                        ),
3272
2619
                     Option('randomize', type=str, argname="SEED",
3273
2620
                            help='Randomize the order of tests using the given'
3274
2621
                                 ' seed or "now" for the current time.'),
3276
2623
                            short_name='x',
3277
2624
                            help='Exclude tests that match this regular'
3278
2625
                                 ' expression.'),
3279
 
                     Option('subunit',
3280
 
                        help='Output test progress via subunit.'),
3281
2626
                     Option('strict', help='Fail on missing dependencies or '
3282
2627
                            'known failures.'),
3283
2628
                     Option('load-list', type=str, argname='TESTLISTFILE',
3284
2629
                            help='Load a test id list from a text file.'),
3285
 
                     ListOption('debugflag', type=str, short_name='E',
3286
 
                                help='Turn on a selftest debug flag.'),
3287
 
                     ListOption('starting-with', type=str, argname='TESTID',
3288
 
                                param_name='starting_with', short_name='s',
3289
 
                                help=
3290
 
                                'Load only the tests starting with TESTID.'),
3291
2630
                     ]
3292
2631
    encoding_type = 'replace'
3293
2632
 
3294
 
    def __init__(self):
3295
 
        Command.__init__(self)
3296
 
        self.additional_selftest_args = {}
3297
 
 
3298
2633
    def run(self, testspecs_list=None, verbose=False, one=False,
3299
2634
            transport=None, benchmark=None,
3300
2635
            lsprof_timed=None, cache_dir=None,
3301
2636
            first=False, list_only=False,
3302
2637
            randomize=None, exclude=None, strict=False,
3303
 
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3304
 
            parallel=None):
 
2638
            load_list=None):
 
2639
        import bzrlib.ui
3305
2640
        from bzrlib.tests import selftest
3306
2641
        import bzrlib.benchmarks as benchmarks
3307
2642
        from bzrlib.benchmarks import tree_creator
3308
2643
 
3309
 
        # Make deprecation warnings visible, unless -Werror is set
3310
 
        symbol_versioning.activate_deprecation_warnings(override=False)
3311
 
 
3312
2644
        if cache_dir is not None:
3313
2645
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
 
2646
        if not list_only:
 
2647
            print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
 
2648
            print '   %s (%s python%s)' % (
 
2649
                    bzrlib.__path__[0],
 
2650
                    bzrlib.version_string,
 
2651
                    '.'.join(map(str, sys.version_info)),
 
2652
                    )
 
2653
        print
3314
2654
        if testspecs_list is not None:
3315
2655
            pattern = '|'.join(testspecs_list)
3316
2656
        else:
3317
2657
            pattern = ".*"
3318
 
        if subunit:
3319
 
            try:
3320
 
                from bzrlib.tests import SubUnitBzrRunner
3321
 
            except ImportError:
3322
 
                raise errors.BzrCommandError("subunit not available. subunit "
3323
 
                    "needs to be installed to use --subunit.")
3324
 
            self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3325
 
        if parallel:
3326
 
            self.additional_selftest_args.setdefault(
3327
 
                'suite_decorators', []).append(parallel)
3328
2658
        if benchmark:
3329
2659
            test_suite_factory = benchmarks.test_suite
3330
2660
            # Unless user explicitly asks for quiet, be verbose in benchmarks
3335
2665
            test_suite_factory = None
3336
2666
            benchfile = None
3337
2667
        try:
3338
 
            selftest_kwargs = {"verbose": verbose,
3339
 
                              "pattern": pattern,
3340
 
                              "stop_on_failure": one,
3341
 
                              "transport": transport,
3342
 
                              "test_suite_factory": test_suite_factory,
3343
 
                              "lsprof_timed": lsprof_timed,
3344
 
                              "bench_history": benchfile,
3345
 
                              "matching_tests_first": first,
3346
 
                              "list_only": list_only,
3347
 
                              "random_seed": randomize,
3348
 
                              "exclude_pattern": exclude,
3349
 
                              "strict": strict,
3350
 
                              "load_list": load_list,
3351
 
                              "debug_flags": debugflag,
3352
 
                              "starting_with": starting_with
3353
 
                              }
3354
 
            selftest_kwargs.update(self.additional_selftest_args)
3355
 
            result = selftest(**selftest_kwargs)
 
2668
            result = selftest(verbose=verbose,
 
2669
                              pattern=pattern,
 
2670
                              stop_on_failure=one,
 
2671
                              transport=transport,
 
2672
                              test_suite_factory=test_suite_factory,
 
2673
                              lsprof_timed=lsprof_timed,
 
2674
                              bench_history=benchfile,
 
2675
                              matching_tests_first=first,
 
2676
                              list_only=list_only,
 
2677
                              random_seed=randomize,
 
2678
                              exclude_pattern=exclude,
 
2679
                              strict=strict,
 
2680
                              load_list=load_list,
 
2681
                              )
3356
2682
        finally:
3357
2683
            if benchfile is not None:
3358
2684
                benchfile.close()
 
2685
        if result:
 
2686
            note('tests passed')
 
2687
        else:
 
2688
            note('tests failed')
3359
2689
        return int(not result)
3360
2690
 
3361
2691
 
3363
2693
    """Show version of bzr."""
3364
2694
 
3365
2695
    encoding_type = 'replace'
3366
 
    takes_options = [
3367
 
        Option("short", help="Print just the version number."),
3368
 
        ]
3369
2696
 
3370
2697
    @display_command
3371
 
    def run(self, short=False):
 
2698
    def run(self):
3372
2699
        from bzrlib.version import show_version
3373
 
        if short:
3374
 
            self.outf.write(bzrlib.version_string + '\n')
3375
 
        else:
3376
 
            show_version(to_file=self.outf)
 
2700
        show_version(to_file=self.outf)
3377
2701
 
3378
2702
 
3379
2703
class cmd_rocks(Command):
3392
2716
    #       merging only part of the history.
3393
2717
    takes_args = ['branch', 'other']
3394
2718
    hidden = True
3395
 
 
 
2719
    
3396
2720
    @display_command
3397
2721
    def run(self, branch, other):
3398
2722
        from bzrlib.revision import ensure_null
3399
 
 
 
2723
        
3400
2724
        branch1 = Branch.open_containing(branch)[0]
3401
2725
        branch2 = Branch.open_containing(other)[0]
3402
2726
        branch1.lock_read()
3418
2742
 
3419
2743
class cmd_merge(Command):
3420
2744
    """Perform a three-way merge.
3421
 
 
3422
 
    The source of the merge can be specified either in the form of a branch,
3423
 
    or in the form of a path to a file containing a merge directive generated
3424
 
    with bzr send. If neither is specified, the default is the upstream branch
3425
 
    or the branch most recently merged using --remember.
3426
 
 
3427
 
    When merging a branch, by default the tip will be merged. To pick a different
3428
 
    revision, pass --revision. If you specify two values, the first will be used as
3429
 
    BASE and the second one as OTHER. Merging individual revisions, or a subset of
3430
 
    available revisions, like this is commonly referred to as "cherrypicking".
3431
 
 
3432
 
    Revision numbers are always relative to the branch being merged.
 
2745
    
 
2746
    The branch is the branch you will merge from.  By default, it will merge
 
2747
    the latest revision.  If you specify a revision, that revision will be
 
2748
    merged.  If you specify two revisions, the first will be used as a BASE,
 
2749
    and the second one as OTHER.  Revision numbers are always relative to the
 
2750
    specified branch.
3433
2751
 
3434
2752
    By default, bzr will try to merge in all new work from the other
3435
2753
    branch, automatically determining an appropriate base.  If this
3436
2754
    fails, you may need to give an explicit base.
3437
 
 
 
2755
    
3438
2756
    Merge will do its best to combine the changes in two branches, but there
3439
2757
    are some kinds of problems only a human can fix.  When it encounters those,
3440
2758
    it will mark a conflict.  A conflict means that you need to fix something,
3450
2768
    The results of the merge are placed into the destination working
3451
2769
    directory, where they can be reviewed (with bzr diff), tested, and then
3452
2770
    committed to record the result of the merge.
3453
 
 
 
2771
    
3454
2772
    merge refuses to run if there are any uncommitted changes, unless
3455
2773
    --force is given.
3456
2774
 
3466
2784
        To merge the changes introduced by 82, without previous changes::
3467
2785
 
3468
2786
            bzr merge -r 81..82 ../bzr.dev
3469
 
 
3470
 
        To apply a merge directive contained in /tmp/merge:
3471
 
 
3472
 
            bzr merge /tmp/merge
3473
2787
    """
3474
2788
 
3475
2789
    encoding_type = 'exact'
3476
 
    _see_also = ['update', 'remerge', 'status-flags', 'send']
3477
 
    takes_args = ['location?']
 
2790
    _see_also = ['update', 'remerge', 'status-flags']
 
2791
    takes_args = ['branch?']
3478
2792
    takes_options = [
3479
2793
        'change',
3480
2794
        'revision',
3500
2814
        Option('preview', help='Instead of merging, show a diff of the merge.')
3501
2815
    ]
3502
2816
 
3503
 
    def run(self, location=None, revision=None, force=False,
3504
 
            merge_type=None, show_base=False, reprocess=None, remember=False,
 
2817
    def run(self, branch=None, revision=None, force=False, merge_type=None,
 
2818
            show_base=False, reprocess=False, remember=False,
3505
2819
            uncommitted=False, pull=False,
3506
2820
            directory=None,
3507
2821
            preview=False,
3508
2822
            ):
 
2823
        # This is actually a branch (or merge-directive) *location*.
 
2824
        location = branch
 
2825
        del branch
 
2826
 
3509
2827
        if merge_type is None:
3510
2828
            merge_type = _mod_merge.Merge3Merger
3511
2829
 
3515
2833
        allow_pending = True
3516
2834
        verified = 'inapplicable'
3517
2835
        tree = WorkingTree.open_containing(directory)[0]
3518
 
 
3519
 
        # die as quickly as possible if there are uncommitted changes
3520
 
        try:
3521
 
            basis_tree = tree.revision_tree(tree.last_revision())
3522
 
        except errors.NoSuchRevision:
3523
 
            basis_tree = tree.basis_tree()
3524
 
        if not force:
3525
 
            changes = tree.changes_from(basis_tree)
3526
 
            if changes.has_changed():
3527
 
                raise errors.UncommittedChanges(tree)
3528
 
 
3529
 
        view_info = _get_view_info_for_change_reporter(tree)
3530
2836
        change_reporter = delta._ChangeReporter(
3531
 
            unversioned_filter=tree.is_ignored, view_info=view_info)
 
2837
            unversioned_filter=tree.is_ignored)
3532
2838
        cleanups = []
3533
2839
        try:
3534
2840
            pb = ui.ui_factory.nested_progress_bar()
3536
2842
            tree.lock_write()
3537
2843
            cleanups.append(tree.unlock)
3538
2844
            if location is not None:
3539
 
                try:
3540
 
                    mergeable = bundle.read_mergeable_from_url(location,
3541
 
                        possible_transports=possible_transports)
3542
 
                except errors.NotABundle:
3543
 
                    mergeable = None
3544
 
                else:
 
2845
                mergeable, other_transport = _get_mergeable_helper(location)
 
2846
                if mergeable:
3545
2847
                    if uncommitted:
3546
2848
                        raise errors.BzrCommandError('Cannot use --uncommitted'
3547
2849
                            ' with bundles or merge directives.')
3551
2853
                            'Cannot use -r with merge directives or bundles')
3552
2854
                    merger, verified = _mod_merge.Merger.from_mergeable(tree,
3553
2855
                       mergeable, pb)
 
2856
                possible_transports.append(other_transport)
3554
2857
 
3555
2858
            if merger is None and uncommitted:
3556
2859
                if revision is not None and len(revision) > 0:
3573
2876
            merger.show_base = show_base
3574
2877
            self.sanity_check_merger(merger)
3575
2878
            if (merger.base_rev_id == merger.other_rev_id and
3576
 
                merger.other_rev_id is not None):
 
2879
                merger.other_rev_id != None):
3577
2880
                note('Nothing to do.')
3578
2881
                return 0
3579
2882
            if pull:
3584
2887
                                       merger.other_rev_id)
3585
2888
                    result.report(self.outf)
3586
2889
                    return 0
3587
 
            merger.check_basis(False)
 
2890
            merger.check_basis(not force)
3588
2891
            if preview:
3589
2892
                return self._do_preview(merger)
3590
2893
            else:
3622
2925
            not merger.merge_type is _mod_merge.Merge3Merger):
3623
2926
            raise errors.BzrCommandError("Show-base is not supported for this"
3624
2927
                                         " merge type. %s" % merger.merge_type)
3625
 
        if merger.reprocess is None:
3626
 
            if merger.show_base:
3627
 
                merger.reprocess = False
3628
 
            else:
3629
 
                # Use reprocess if the merger supports it
3630
 
                merger.reprocess = merger.merge_type.supports_reprocess
3631
2928
        if merger.reprocess and not merger.merge_type.supports_reprocess:
3632
2929
            raise errors.BzrCommandError("Conflict reduction is not supported"
3633
2930
                                         " for merge type %s." %
3640
2937
                                possible_transports, pb):
3641
2938
        """Produce a merger from a location, assuming it refers to a branch."""
3642
2939
        from bzrlib.tag import _merge_tags_if_possible
 
2940
        assert revision is None or len(revision) < 3
3643
2941
        # find the branch locations
3644
2942
        other_loc, user_location = self._select_branch_location(tree, location,
3645
2943
            revision, -1)
3661
2959
            other_revision_id = _mod_revision.ensure_null(
3662
2960
                other_branch.last_revision())
3663
2961
        else:
3664
 
            other_revision_id = revision[-1].as_revision_id(other_branch)
 
2962
            other_revision_id = \
 
2963
                _mod_revision.ensure_null(
 
2964
                    revision[-1].in_history(other_branch).rev_id)
3665
2965
        if (revision is not None and len(revision) == 2
3666
2966
            and revision[0] is not None):
3667
 
            base_revision_id = revision[0].as_revision_id(base_branch)
 
2967
            base_revision_id = \
 
2968
                _mod_revision.ensure_null(
 
2969
                    revision[0].in_history(base_branch).rev_id)
3668
2970
        else:
3669
2971
            base_revision_id = None
3670
2972
        # Remember where we merge from
3716
3018
        Report if the remembered location was used.
3717
3019
        """
3718
3020
        stored_location = tree.branch.get_submit_branch()
3719
 
        stored_location_type = "submit"
3720
3021
        if stored_location is None:
3721
3022
            stored_location = tree.branch.get_parent()
3722
 
            stored_location_type = "parent"
3723
3023
        mutter("%s", stored_location)
3724
3024
        if stored_location is None:
3725
3025
            raise errors.BzrCommandError("No location specified or remembered")
3726
3026
        display_url = urlutils.unescape_for_display(stored_location, 'utf-8')
3727
 
        note(u"%s remembered %s location %s", verb_string,
3728
 
                stored_location_type, display_url)
 
3027
        note(u"%s remembered location %s", verb_string, display_url)
3729
3028
        return stored_location
3730
3029
 
3731
3030
 
3733
3032
    """Redo a merge.
3734
3033
 
3735
3034
    Use this if you want to try a different merge technique while resolving
3736
 
    conflicts.  Some merge techniques are better than others, and remerge
 
3035
    conflicts.  Some merge techniques are better than others, and remerge 
3737
3036
    lets you try different ones on different files.
3738
3037
 
3739
3038
    The options for remerge have the same meaning and defaults as the ones for
3743
3042
    :Examples:
3744
3043
        Re-do the merge of all conflicted files, and show the base text in
3745
3044
        conflict regions, in addition to the usual THIS and OTHER texts::
3746
 
 
 
3045
      
3747
3046
            bzr remerge --show-base
3748
3047
 
3749
3048
        Re-do the merge of "foobar", using the weave merge algorithm, with
3750
3049
        additional processing to reduce the size of conflict regions::
3751
 
 
 
3050
      
3752
3051
            bzr remerge --merge-type weave --reprocess foobar
3753
3052
    """
3754
3053
    takes_args = ['file*']
3784
3083
                    interesting_ids.add(file_id)
3785
3084
                    if tree.kind(file_id) != "directory":
3786
3085
                        continue
3787
 
 
 
3086
                    
3788
3087
                    for name, ie in tree.inventory.iter_entries(file_id):
3789
3088
                        interesting_ids.add(ie.file_id)
3790
3089
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3839
3138
    merge instead.  For example, "merge . --revision -2..-3" will remove the
3840
3139
    changes introduced by -2, without affecting the changes introduced by -1.
3841
3140
    Or to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
3842
 
 
 
3141
    
3843
3142
    By default, any files that have been manually changed will be backed up
3844
3143
    first.  (Files changed only by merge are not backed up.)  Backup files have
3845
3144
    '.~#~' appended to their name, where # is a number.
3874
3173
    def run(self, revision=None, no_backup=False, file_list=None,
3875
3174
            forget_merges=None):
3876
3175
        tree, file_list = tree_files(file_list)
3877
 
        tree.lock_write()
3878
 
        try:
3879
 
            if forget_merges:
3880
 
                tree.set_parent_ids(tree.get_parent_ids()[:1])
3881
 
            else:
3882
 
                self._revert_tree_to_revision(tree, revision, file_list, no_backup)
3883
 
        finally:
3884
 
            tree.unlock()
 
3176
        if forget_merges:
 
3177
            tree.set_parent_ids(tree.get_parent_ids()[:1])
 
3178
        else:
 
3179
            self._revert_tree_to_revision(tree, revision, file_list, no_backup)
3885
3180
 
3886
3181
    @staticmethod
3887
3182
    def _revert_tree_to_revision(tree, revision, file_list, no_backup):
3888
 
        rev_tree = _get_one_revision_tree('revert', revision, tree=tree)
 
3183
        if revision is None:
 
3184
            rev_id = tree.last_revision()
 
3185
        elif len(revision) != 1:
 
3186
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
 
3187
        else:
 
3188
            rev_id = revision[0].in_history(tree.branch).rev_id
3889
3189
        pb = ui.ui_factory.nested_progress_bar()
3890
3190
        try:
3891
 
            tree.revert(file_list, rev_tree, not no_backup, pb,
3892
 
                report_changes=True)
 
3191
            tree.revert(file_list,
 
3192
                        tree.branch.repository.revision_tree(rev_id),
 
3193
                        not no_backup, pb, report_changes=True)
3893
3194
        finally:
3894
3195
            pb.finished()
3895
3196
 
3914
3215
            ]
3915
3216
    takes_args = ['topic?']
3916
3217
    aliases = ['?', '--help', '-?', '-h']
3917
 
 
 
3218
    
3918
3219
    @display_command
3919
3220
    def run(self, topic=None, long=False):
3920
3221
        import bzrlib.help
3931
3232
    takes_args = ['context?']
3932
3233
    aliases = ['s-c']
3933
3234
    hidden = True
3934
 
 
 
3235
    
3935
3236
    @display_command
3936
3237
    def run(self, context=None):
3937
3238
        import shellcomplete
3938
3239
        shellcomplete.shellcomplete(context)
3939
3240
 
3940
3241
 
 
3242
class cmd_fetch(Command):
 
3243
    """Copy in history from another branch but don't merge it.
 
3244
 
 
3245
    This is an internal method used for pull and merge.
 
3246
    """
 
3247
    hidden = True
 
3248
    takes_args = ['from_branch', 'to_branch']
 
3249
    def run(self, from_branch, to_branch):
 
3250
        from bzrlib.fetch import Fetcher
 
3251
        from_b = Branch.open(from_branch)
 
3252
        to_b = Branch.open(to_branch)
 
3253
        Fetcher(to_b, from_b)
 
3254
 
 
3255
 
3941
3256
class cmd_missing(Command):
3942
3257
    """Show unmerged/unpulled revisions between two branches.
3943
 
 
 
3258
    
3944
3259
    OTHER_BRANCH may be local or remote.
3945
 
 
3946
 
    To filter on a range of revisions, you can use the command -r begin..end
3947
 
    -r revision requests a specific revision, -r ..end or -r begin.. are
3948
 
    also valid.
3949
 
 
3950
 
    :Examples:
3951
 
 
3952
 
        Determine the missing revisions between this and the branch at the
3953
 
        remembered pull location::
3954
 
 
3955
 
            bzr missing
3956
 
 
3957
 
        Determine the missing revisions between this and another branch::
3958
 
 
3959
 
            bzr missing http://server/branch
3960
 
 
3961
 
        Determine the missing revisions up to a specific revision on the other
3962
 
        branch::
3963
 
 
3964
 
            bzr missing -r ..-10
3965
 
 
3966
 
        Determine the missing revisions up to a specific revision on this
3967
 
        branch::
3968
 
 
3969
 
            bzr missing --my-revision ..-10
3970
3260
    """
3971
3261
 
3972
3262
    _see_also = ['merge', 'pull']
3973
3263
    takes_args = ['other_branch?']
3974
3264
    takes_options = [
3975
 
        Option('reverse', 'Reverse the order of revisions.'),
3976
 
        Option('mine-only',
3977
 
               'Display changes in the local branch only.'),
3978
 
        Option('this' , 'Same as --mine-only.'),
3979
 
        Option('theirs-only',
3980
 
               'Display changes in the remote branch only.'),
3981
 
        Option('other', 'Same as --theirs-only.'),
3982
 
        'log-format',
3983
 
        'show-ids',
3984
 
        'verbose',
3985
 
        custom_help('revision',
3986
 
             help='Filter on other branch revisions (inclusive). '
3987
 
                'See "help revisionspec" for details.'),
3988
 
        Option('my-revision',
3989
 
            type=_parse_revision_str,
3990
 
            help='Filter on local branch revisions (inclusive). '
3991
 
                'See "help revisionspec" for details.'),
3992
 
        Option('include-merges',
3993
 
               'Show all revisions in addition to the mainline ones.'),
3994
 
        ]
 
3265
            Option('reverse', 'Reverse the order of revisions.'),
 
3266
            Option('mine-only',
 
3267
                   'Display changes in the local branch only.'),
 
3268
            Option('this' , 'Same as --mine-only.'),
 
3269
            Option('theirs-only',
 
3270
                   'Display changes in the remote branch only.'),
 
3271
            Option('other', 'Same as --theirs-only.'),
 
3272
            'log-format',
 
3273
            'show-ids',
 
3274
            'verbose'
 
3275
            ]
3995
3276
    encoding_type = 'replace'
3996
3277
 
3997
3278
    @display_command
3998
3279
    def run(self, other_branch=None, reverse=False, mine_only=False,
3999
 
            theirs_only=False,
4000
 
            log_format=None, long=False, short=False, line=False,
4001
 
            show_ids=False, verbose=False, this=False, other=False,
4002
 
            include_merges=False, revision=None, my_revision=None):
 
3280
            theirs_only=False, log_format=None, long=False, short=False, line=False, 
 
3281
            show_ids=False, verbose=False, this=False, other=False):
4003
3282
        from bzrlib.missing import find_unmerged, iter_log_revisions
4004
 
        def message(s):
4005
 
            if not is_quiet():
4006
 
                self.outf.write(s)
4007
3283
 
4008
3284
        if this:
4009
 
            mine_only = this
 
3285
          mine_only = this
4010
3286
        if other:
4011
 
            theirs_only = other
4012
 
        # TODO: We should probably check that we don't have mine-only and
4013
 
        #       theirs-only set, but it gets complicated because we also have
4014
 
        #       this and other which could be used.
4015
 
        restrict = 'all'
4016
 
        if mine_only:
4017
 
            restrict = 'local'
4018
 
        elif theirs_only:
4019
 
            restrict = 'remote'
 
3287
          theirs_only = other
4020
3288
 
4021
3289
        local_branch = Branch.open_containing(u".")[0]
4022
3290
        parent = local_branch.get_parent()
4027
3295
                                             " or specified.")
4028
3296
            display_url = urlutils.unescape_for_display(parent,
4029
3297
                                                        self.outf.encoding)
4030
 
            message("Using saved parent location: "
4031
 
                    + display_url + "\n")
 
3298
            self.outf.write("Using last location: " + display_url + "\n")
4032
3299
 
4033
3300
        remote_branch = Branch.open(other_branch)
4034
3301
        if remote_branch.base == local_branch.base:
4035
3302
            remote_branch = local_branch
4036
 
 
4037
 
        local_revid_range = _revision_range_to_revid_range(
4038
 
            _get_revision_range(my_revision, local_branch,
4039
 
                self.name()))
4040
 
 
4041
 
        remote_revid_range = _revision_range_to_revid_range(
4042
 
            _get_revision_range(revision,
4043
 
                remote_branch, self.name()))
4044
 
 
4045
3303
        local_branch.lock_read()
4046
3304
        try:
4047
3305
            remote_branch.lock_read()
4048
3306
            try:
4049
 
                local_extra, remote_extra = find_unmerged(
4050
 
                    local_branch, remote_branch, restrict,
4051
 
                    backward=not reverse,
4052
 
                    include_merges=include_merges,
4053
 
                    local_revid_range=local_revid_range,
4054
 
                    remote_revid_range=remote_revid_range)
4055
 
 
 
3307
                local_extra, remote_extra = find_unmerged(local_branch,
 
3308
                                                          remote_branch)
4056
3309
                if log_format is None:
4057
3310
                    registry = log.log_formatter_registry
4058
3311
                    log_format = registry.get_default(local_branch)
4059
3312
                lf = log_format(to_file=self.outf,
4060
3313
                                show_ids=show_ids,
4061
3314
                                show_timezone='original')
4062
 
 
4063
 
                status_code = 0
 
3315
                if reverse is False:
 
3316
                    local_extra.reverse()
 
3317
                    remote_extra.reverse()
4064
3318
                if local_extra and not theirs_only:
4065
 
                    message("You have %d extra revision(s):\n" %
4066
 
                        len(local_extra))
 
3319
                    self.outf.write("You have %d extra revision(s):\n" %
 
3320
                                    len(local_extra))
4067
3321
                    for revision in iter_log_revisions(local_extra,
4068
3322
                                        local_branch.repository,
4069
3323
                                        verbose):
4070
3324
                        lf.log_revision(revision)
4071
3325
                    printed_local = True
4072
 
                    status_code = 1
4073
3326
                else:
4074
3327
                    printed_local = False
4075
 
 
4076
3328
                if remote_extra and not mine_only:
4077
3329
                    if printed_local is True:
4078
 
                        message("\n\n\n")
4079
 
                    message("You are missing %d revision(s):\n" %
4080
 
                        len(remote_extra))
 
3330
                        self.outf.write("\n\n\n")
 
3331
                    self.outf.write("You are missing %d revision(s):\n" %
 
3332
                                    len(remote_extra))
4081
3333
                    for revision in iter_log_revisions(remote_extra,
4082
3334
                                        remote_branch.repository,
4083
3335
                                        verbose):
4084
3336
                        lf.log_revision(revision)
 
3337
                if not remote_extra and not local_extra:
 
3338
                    status_code = 0
 
3339
                    self.outf.write("Branches are up to date.\n")
 
3340
                else:
4085
3341
                    status_code = 1
4086
 
 
4087
 
                if mine_only and not local_extra:
4088
 
                    # We checked local, and found nothing extra
4089
 
                    message('This branch is up to date.\n')
4090
 
                elif theirs_only and not remote_extra:
4091
 
                    # We checked remote, and found nothing extra
4092
 
                    message('Other branch is up to date.\n')
4093
 
                elif not (mine_only or theirs_only or local_extra or
4094
 
                          remote_extra):
4095
 
                    # We checked both branches, and neither one had extra
4096
 
                    # revisions
4097
 
                    message("Branches are up to date.\n")
4098
3342
            finally:
4099
3343
                remote_branch.unlock()
4100
3344
        finally:
4128
3372
 
4129
3373
class cmd_plugins(Command):
4130
3374
    """List the installed plugins.
4131
 
 
 
3375
    
4132
3376
    This command displays the list of installed plugins including
4133
3377
    version of plugin and a short description of each.
4134
3378
 
4186
3430
            testament_class = StrictTestament
4187
3431
        else:
4188
3432
            testament_class = Testament
4189
 
        if branch == '.':
4190
 
            b = Branch.open_containing(branch)[0]
4191
 
        else:
4192
 
            b = Branch.open(branch)
 
3433
        b = WorkingTree.open_containing(branch)[0].branch
4193
3434
        b.lock_read()
4194
3435
        try:
4195
3436
            if revision is None:
4196
3437
                rev_id = b.last_revision()
4197
3438
            else:
4198
 
                rev_id = revision[0].as_revision_id(b)
 
3439
                rev_id = revision[0].in_history(b).rev_id
4199
3440
            t = testament_class.from_revision(b.repository, rev_id)
4200
3441
            if long:
4201
3442
                sys.stdout.writelines(t.as_text_lines())
4211
3452
    This prints out the given file with an annotation on the left side
4212
3453
    indicating which revision, author and date introduced the change.
4213
3454
 
4214
 
    If the origin is the same for a run of consecutive lines, it is
 
3455
    If the origin is the same for a run of consecutive lines, it is 
4215
3456
    shown only at the top, unless the --all option is given.
4216
3457
    """
4217
3458
    # TODO: annotate directories; showing when each file was last changed
4218
 
    # TODO: if the working copy is modified, show annotations on that
 
3459
    # TODO: if the working copy is modified, show annotations on that 
4219
3460
    #       with new uncommitted lines marked
4220
3461
    aliases = ['ann', 'blame', 'praise']
4221
3462
    takes_args = ['filename']
4229
3470
    @display_command
4230
3471
    def run(self, filename, all=False, long=False, revision=None,
4231
3472
            show_ids=False):
4232
 
        from bzrlib.annotate import annotate_file, annotate_file_tree
 
3473
        from bzrlib.annotate import annotate_file
4233
3474
        wt, branch, relpath = \
4234
3475
            bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4235
3476
        if wt is not None:
4237
3478
        else:
4238
3479
            branch.lock_read()
4239
3480
        try:
4240
 
            tree = _get_one_revision_tree('annotate', revision, branch=branch)
 
3481
            if revision is None:
 
3482
                revision_id = branch.last_revision()
 
3483
            elif len(revision) != 1:
 
3484
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
 
3485
            else:
 
3486
                revision_id = revision[0].in_history(branch).rev_id
 
3487
            tree = branch.repository.revision_tree(revision_id)
4241
3488
            if wt is not None:
4242
3489
                file_id = wt.path2id(relpath)
4243
3490
            else:
4245
3492
            if file_id is None:
4246
3493
                raise errors.NotVersionedError(filename)
4247
3494
            file_version = tree.inventory[file_id].revision
4248
 
            if wt is not None and revision is None:
4249
 
                # If there is a tree and we're not annotating historical
4250
 
                # versions, annotate the working tree's content.
4251
 
                annotate_file_tree(wt, file_id, self.outf, long, all,
4252
 
                    show_ids=show_ids)
4253
 
            else:
4254
 
                annotate_file(branch, file_version, file_id, long, all, self.outf,
4255
 
                              show_ids=show_ids)
 
3495
            annotate_file(branch, file_version, file_id, long, all, self.outf,
 
3496
                          show_ids=show_ids)
4256
3497
        finally:
4257
3498
            if wt is not None:
4258
3499
                wt.unlock()
4267
3508
    hidden = True # is this right ?
4268
3509
    takes_args = ['revision_id*']
4269
3510
    takes_options = ['revision']
4270
 
 
 
3511
    
4271
3512
    def run(self, revision_id_list=None, revision=None):
4272
3513
        if revision_id_list is not None and revision is not None:
4273
3514
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4333
3574
 
4334
3575
    Once converted into a checkout, commits must succeed on the master branch
4335
3576
    before they will be applied to the local branch.
4336
 
 
4337
 
    Bound branches use the nickname of its master branch unless it is set
4338
 
    locally, in which case binding will update the the local nickname to be
4339
 
    that of the master.
4340
3577
    """
4341
3578
 
4342
3579
    _see_also = ['checkouts', 'unbind']
4361
3598
        except errors.DivergedBranches:
4362
3599
            raise errors.BzrCommandError('These branches have diverged.'
4363
3600
                                         ' Try merging, and then bind again.')
4364
 
        if b.get_config().has_explicit_nickname():
4365
 
            b.nick = b_other.nick
4366
3601
 
4367
3602
 
4368
3603
class cmd_unbind(Command):
4393
3628
    specified revision.  For example, "bzr uncommit -r 15" will leave the
4394
3629
    branch at revision 15.
4395
3630
 
4396
 
    Uncommit leaves the working tree ready for a new commit.  The only change
4397
 
    it may make is to restore any pending merges that were present before
4398
 
    the commit.
 
3631
    In the future, uncommit will create a revision bundle, which can then
 
3632
    be re-applied.
4399
3633
    """
4400
3634
 
4401
3635
    # TODO: jam 20060108 Add an option to allow uncommit to remove
4405
3639
    _see_also = ['commit']
4406
3640
    takes_options = ['verbose', 'revision',
4407
3641
                    Option('dry-run', help='Don\'t actually make changes.'),
4408
 
                    Option('force', help='Say yes to all questions.'),
4409
 
                    Option('local',
4410
 
                           help="Only remove the commits from the local branch"
4411
 
                                " when in a checkout."
4412
 
                           ),
4413
 
                    ]
 
3642
                    Option('force', help='Say yes to all questions.')]
4414
3643
    takes_args = ['location?']
4415
3644
    aliases = []
4416
3645
    encoding_type = 'replace'
4417
3646
 
4418
3647
    def run(self, location=None,
4419
3648
            dry_run=False, verbose=False,
4420
 
            revision=None, force=False, local=False):
 
3649
            revision=None, force=False):
4421
3650
        if location is None:
4422
3651
            location = u'.'
4423
3652
        control, relpath = bzrdir.BzrDir.open_containing(location)
4433
3662
        else:
4434
3663
            b.lock_write()
4435
3664
        try:
4436
 
            return self._run(b, tree, dry_run, verbose, revision, force,
4437
 
                             local=local)
 
3665
            return self._run(b, tree, dry_run, verbose, revision, force)
4438
3666
        finally:
4439
3667
            if tree is not None:
4440
3668
                tree.unlock()
4441
3669
            else:
4442
3670
                b.unlock()
4443
3671
 
4444
 
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
 
3672
    def _run(self, b, tree, dry_run, verbose, revision, force):
4445
3673
        from bzrlib.log import log_formatter, show_log
4446
3674
        from bzrlib.uncommit import uncommit
4447
3675
 
4488
3716
                    print 'Canceled'
4489
3717
                    return 0
4490
3718
 
4491
 
        mutter('Uncommitting from {%s} to {%s}',
4492
 
               last_rev_id, rev_id)
4493
3719
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
4494
 
                 revno=revno, local=local)
4495
 
        note('You can restore the old tip by running:\n'
4496
 
             '  bzr pull . -r revid:%s', last_rev_id)
 
3720
                 revno=revno)
4497
3721
 
4498
3722
 
4499
3723
class cmd_break_lock(Command):
4503
3727
    holding the lock has been stopped.
4504
3728
 
4505
3729
    You can get information on what locks are open via the 'bzr info' command.
4506
 
 
 
3730
    
4507
3731
    :Examples:
4508
3732
        bzr break-lock
4509
3733
    """
4517
3741
            control.break_lock()
4518
3742
        except NotImplementedError:
4519
3743
            pass
4520
 
 
 
3744
        
4521
3745
 
4522
3746
class cmd_wait_until_signalled(Command):
4523
3747
    """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
4541
3765
    takes_options = [
4542
3766
        Option('inet',
4543
3767
               help='Serve on stdin/out for use from inetd or sshd.'),
4544
 
        RegistryOption('protocol', 
4545
 
               help="Protocol to serve.", 
4546
 
               lazy_registry=('bzrlib.transport', 'transport_server_registry'),
4547
 
               value_switches=True),
4548
3768
        Option('port',
4549
3769
               help='Listen for connections on nominated port of the form '
4550
3770
                    '[hostname:]portnumber.  Passing 0 as the port number will '
4551
 
                    'result in a dynamically allocated port.  The default port '
4552
 
                    'depends on the protocol.',
 
3771
                    'result in a dynamically allocated port.  The default port is '
 
3772
                    '4155.',
4553
3773
               type=str),
4554
3774
        Option('directory',
4555
3775
               help='Serve contents of this directory.',
4561
3781
                ),
4562
3782
        ]
4563
3783
 
4564
 
    def get_host_and_port(self, port):
4565
 
        """Return the host and port to run the smart server on.
4566
 
 
4567
 
        If 'port' is None, None will be returned for the host and port.
4568
 
 
4569
 
        If 'port' has a colon in it, the string before the colon will be
4570
 
        interpreted as the host.
4571
 
 
4572
 
        :param port: A string of the port to run the server on.
4573
 
        :return: A tuple of (host, port), where 'host' is a host name or IP,
4574
 
            and port is an integer TCP/IP port.
4575
 
        """
4576
 
        host = None
4577
 
        if port is not None:
4578
 
            if ':' in port:
4579
 
                host, port = port.split(':')
4580
 
            port = int(port)
4581
 
        return host, port
4582
 
 
4583
 
    def run(self, port=None, inet=False, directory=None, allow_writes=False,
4584
 
            protocol=None):
4585
 
        from bzrlib.transport import get_transport, transport_server_registry
 
3784
    def run(self, port=None, inet=False, directory=None, allow_writes=False):
 
3785
        from bzrlib import lockdir
 
3786
        from bzrlib.smart import medium, server
 
3787
        from bzrlib.transport import get_transport
 
3788
        from bzrlib.transport.chroot import ChrootServer
4586
3789
        if directory is None:
4587
3790
            directory = os.getcwd()
4588
 
        if protocol is None:
4589
 
            protocol = transport_server_registry.get()
4590
 
        host, port = self.get_host_and_port(port)
4591
3791
        url = urlutils.local_path_to_url(directory)
4592
3792
        if not allow_writes:
4593
3793
            url = 'readonly+' + url
4594
 
        transport = get_transport(url)
4595
 
        protocol(transport, host, port, inet)
 
3794
        chroot_server = ChrootServer(get_transport(url))
 
3795
        chroot_server.setUp()
 
3796
        t = get_transport(chroot_server.get_url())
 
3797
        if inet:
 
3798
            smart_server = medium.SmartServerPipeStreamMedium(
 
3799
                sys.stdin, sys.stdout, t)
 
3800
        else:
 
3801
            host = medium.BZR_DEFAULT_INTERFACE
 
3802
            if port is None:
 
3803
                port = medium.BZR_DEFAULT_PORT
 
3804
            else:
 
3805
                if ':' in port:
 
3806
                    host, port = port.split(':')
 
3807
                port = int(port)
 
3808
            smart_server = server.SmartTCPServer(t, host=host, port=port)
 
3809
            print 'listening on port: ', smart_server.port
 
3810
            sys.stdout.flush()
 
3811
        # for the duration of this server, no UI output is permitted.
 
3812
        # note that this may cause problems with blackbox tests. This should
 
3813
        # be changed with care though, as we dont want to use bandwidth sending
 
3814
        # progress over stderr to smart server clients!
 
3815
        old_factory = ui.ui_factory
 
3816
        old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
 
3817
        try:
 
3818
            ui.ui_factory = ui.SilentUIFactory()
 
3819
            lockdir._DEFAULT_TIMEOUT_SECONDS = 0
 
3820
            smart_server.serve()
 
3821
        finally:
 
3822
            ui.ui_factory = old_factory
 
3823
            lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4596
3824
 
4597
3825
 
4598
3826
class cmd_join(Command):
4599
 
    """Combine a tree into its containing tree.
4600
 
 
4601
 
    This command requires the target tree to be in a rich-root format.
 
3827
    """Combine a subtree into its containing tree.
 
3828
    
 
3829
    This command is for experimental use only.  It requires the target tree
 
3830
    to be in dirstate-with-subtree format, which cannot be converted into
 
3831
    earlier formats.
4602
3832
 
4603
3833
    The TREE argument should be an independent tree, inside another tree, but
4604
3834
    not part of it.  (Such trees can be produced by "bzr split", but also by
4607
3837
    The result is a combined tree, with the subtree no longer an independant
4608
3838
    part.  This is marked as a merge of the subtree into the containing tree,
4609
3839
    and all history is preserved.
 
3840
 
 
3841
    If --reference is specified, the subtree retains its independence.  It can
 
3842
    be branched by itself, and can be part of multiple projects at the same
 
3843
    time.  But operations performed in the containing tree, such as commit
 
3844
    and merge, will recurse into the subtree.
4610
3845
    """
4611
3846
 
4612
3847
    _see_also = ['split']
4613
3848
    takes_args = ['tree']
4614
3849
    takes_options = [
4615
 
            Option('reference', help='Join by reference.', hidden=True),
 
3850
            Option('reference', help='Join by reference.'),
4616
3851
            ]
 
3852
    hidden = True
4617
3853
 
4618
3854
    def run(self, tree, reference=False):
4619
3855
        sub_tree = WorkingTree.open(tree)
4637
3873
            try:
4638
3874
                containing_tree.subsume(sub_tree)
4639
3875
            except errors.BadSubsumeSource, e:
4640
 
                raise errors.BzrCommandError("Cannot join %s.  %s" %
 
3876
                raise errors.BzrCommandError("Cannot join %s.  %s" % 
4641
3877
                                             (tree, e.reason))
4642
3878
 
4643
3879
 
4653
3889
    branch.  Commits in the top-level tree will not apply to the new subtree.
4654
3890
    """
4655
3891
 
4656
 
    _see_also = ['join']
 
3892
    # join is not un-hidden yet
 
3893
    #_see_also = ['join']
4657
3894
    takes_args = ['tree']
4658
3895
 
4659
3896
    def run(self, tree):
4741
3978
            if len(revision) > 2:
4742
3979
                raise errors.BzrCommandError('bzr merge-directive takes '
4743
3980
                    'at most two one revision identifiers')
4744
 
            revision_id = revision[-1].as_revision_id(branch)
 
3981
            revision_id = revision[-1].in_history(branch).rev_id
4745
3982
            if len(revision) == 2:
4746
 
                base_revision_id = revision[0].as_revision_id(branch)
 
3983
                base_revision_id = revision[0].in_history(branch).rev_id
 
3984
                base_revision_id = ensure_null(base_revision_id)
4747
3985
        else:
4748
3986
            revision_id = branch.last_revision()
4749
3987
        revision_id = ensure_null(revision_id)
4767
4005
 
4768
4006
 
4769
4007
class cmd_send(Command):
4770
 
    """Mail or create a merge-directive for submitting changes.
 
4008
    """Mail or create a merge-directive for submiting changes.
4771
4009
 
4772
4010
    A merge directive provides many things needed for requesting merges:
4773
4011
 
4795
4033
    Mail is sent using your preferred mail program.  This should be transparent
4796
4034
    on Windows (it uses MAPI).  On Linux, it requires the xdg-email utility.
4797
4035
    If the preferred client can't be found (or used), your editor will be used.
4798
 
 
 
4036
    
4799
4037
    To use a specific mail program, set the mail_client configuration option.
4800
4038
    (For Thunderbird 1.5, this works around some bugs.)  Supported values for
4801
 
    specific clients are "claws", "evolution", "kmail", "mutt", and
4802
 
    "thunderbird"; generic options are "default", "editor", "emacsclient",
4803
 
    "mapi", and "xdg-email".  Plugins may also add supported clients.
 
4039
    specific clients are "evolution", "kmail", "mutt", and "thunderbird";
 
4040
    generic options are "default", "editor", "mapi", and "xdg-email".
4804
4041
 
4805
4042
    If mail is being sent, a to address is required.  This can be supplied
4806
4043
    either on the commandline, by setting the submit_to configuration
4807
 
    option in the branch itself or the child_submit_to configuration option
 
4044
    option in the branch itself or the child_submit_to configuration option 
4808
4045
    in the submit branch.
4809
4046
 
4810
4047
    Two formats are currently supported: "4" uses revision bundle format 4 and
4812
4049
    older formats.  It is compatible with Bazaar 0.19 and later.  It is the
4813
4050
    default.  "0.9" uses revision bundle format 0.9 and merge directive
4814
4051
    format 1.  It is compatible with Bazaar 0.12 - 0.18.
4815
 
 
4816
 
    The merge directives created by bzr send may be applied using bzr merge or
4817
 
    bzr pull by specifying a file containing a merge directive as the location.
4818
4052
    """
4819
4053
 
4820
4054
    encoding_type = 'exact'
4821
4055
 
4822
 
    _see_also = ['merge', 'pull']
 
4056
    _see_also = ['merge']
4823
4057
 
4824
4058
    takes_args = ['submit_branch?', 'public_branch?']
4825
4059
 
4835
4069
               'rather than the one containing the working directory.',
4836
4070
               short_name='f',
4837
4071
               type=unicode),
4838
 
        Option('output', short_name='o',
4839
 
               help='Write merge directive to this file; '
4840
 
                    'use - for stdout.',
 
4072
        Option('output', short_name='o', help='Write directive to this file.',
4841
4073
               type=unicode),
4842
4074
        Option('mail-to', help='Mail the request to this address.',
4843
4075
               type=unicode),
4844
4076
        'revision',
4845
4077
        'message',
4846
 
        Option('body', help='Body for the email.', type=unicode),
4847
 
        RegistryOption('format',
4848
 
                       help='Use the specified output format.', 
4849
 
                       lazy_registry=('bzrlib.send', 'format_registry'))
 
4078
        RegistryOption.from_kwargs('format',
 
4079
        'Use the specified output format.',
 
4080
        **{'4': 'Bundle format 4, Merge Directive 2 (default)',
 
4081
           '0.9': 'Bundle format 0.9, Merge Directive 1',})
4850
4082
        ]
4851
4083
 
4852
4084
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4853
4085
            no_patch=False, revision=None, remember=False, output=None,
4854
 
            format=None, mail_to=None, message=None, body=None, **kwargs):
4855
 
        from bzrlib.send import send
4856
 
        return send(submit_branch, revision, public_branch, remember,
 
4086
            format='4', mail_to=None, message=None, **kwargs):
 
4087
        return self._run(submit_branch, revision, public_branch, remember,
4857
4088
                         format, no_bundle, no_patch, output,
4858
 
                         kwargs.get('from', '.'), mail_to, message, body,
4859
 
                         self.outf)
 
4089
                         kwargs.get('from', '.'), mail_to, message)
 
4090
 
 
4091
    def _run(self, submit_branch, revision, public_branch, remember, format,
 
4092
             no_bundle, no_patch, output, from_, mail_to, message):
 
4093
        from bzrlib.revision import NULL_REVISION
 
4094
        branch = Branch.open_containing(from_)[0]
 
4095
        if output is None:
 
4096
            outfile = StringIO()
 
4097
        elif output == '-':
 
4098
            outfile = self.outf
 
4099
        else:
 
4100
            outfile = open(output, 'wb')
 
4101
        # we may need to write data into branch's repository to calculate
 
4102
        # the data to send.
 
4103
        branch.lock_write()
 
4104
        try:
 
4105
            if output is None:
 
4106
                config = branch.get_config()
 
4107
                if mail_to is None:
 
4108
                    mail_to = config.get_user_option('submit_to')
 
4109
                mail_client = config.get_mail_client()
 
4110
            if remember and submit_branch is None:
 
4111
                raise errors.BzrCommandError(
 
4112
                    '--remember requires a branch to be specified.')
 
4113
            stored_submit_branch = branch.get_submit_branch()
 
4114
            remembered_submit_branch = False
 
4115
            if submit_branch is None:
 
4116
                submit_branch = stored_submit_branch
 
4117
                remembered_submit_branch = True
 
4118
            else:
 
4119
                if stored_submit_branch is None or remember:
 
4120
                    branch.set_submit_branch(submit_branch)
 
4121
            if submit_branch is None:
 
4122
                submit_branch = branch.get_parent()
 
4123
                remembered_submit_branch = True
 
4124
            if submit_branch is None:
 
4125
                raise errors.BzrCommandError('No submit branch known or'
 
4126
                                             ' specified')
 
4127
            if remembered_submit_branch:
 
4128
                note('Using saved location: %s', submit_branch)
 
4129
 
 
4130
            if mail_to is None:
 
4131
                submit_config = Branch.open(submit_branch).get_config()
 
4132
                mail_to = submit_config.get_user_option("child_submit_to")
 
4133
 
 
4134
            stored_public_branch = branch.get_public_branch()
 
4135
            if public_branch is None:
 
4136
                public_branch = stored_public_branch
 
4137
            elif stored_public_branch is None or remember:
 
4138
                branch.set_public_branch(public_branch)
 
4139
            if no_bundle and public_branch is None:
 
4140
                raise errors.BzrCommandError('No public branch specified or'
 
4141
                                             ' known')
 
4142
            base_revision_id = None
 
4143
            revision_id = None
 
4144
            if revision is not None:
 
4145
                if len(revision) > 2:
 
4146
                    raise errors.BzrCommandError('bzr send takes '
 
4147
                        'at most two one revision identifiers')
 
4148
                revision_id = revision[-1].in_history(branch).rev_id
 
4149
                if len(revision) == 2:
 
4150
                    base_revision_id = revision[0].in_history(branch).rev_id
 
4151
            if revision_id is None:
 
4152
                revision_id = branch.last_revision()
 
4153
            if revision_id == NULL_REVISION:
 
4154
                raise errors.BzrCommandError('No revisions to submit.')
 
4155
            if format == '4':
 
4156
                directive = merge_directive.MergeDirective2.from_objects(
 
4157
                    branch.repository, revision_id, time.time(),
 
4158
                    osutils.local_time_offset(), submit_branch,
 
4159
                    public_branch=public_branch, include_patch=not no_patch,
 
4160
                    include_bundle=not no_bundle, message=message,
 
4161
                    base_revision_id=base_revision_id)
 
4162
            elif format == '0.9':
 
4163
                if not no_bundle:
 
4164
                    if not no_patch:
 
4165
                        patch_type = 'bundle'
 
4166
                    else:
 
4167
                        raise errors.BzrCommandError('Format 0.9 does not'
 
4168
                            ' permit bundle with no patch')
 
4169
                else:
 
4170
                    if not no_patch:
 
4171
                        patch_type = 'diff'
 
4172
                    else:
 
4173
                        patch_type = None
 
4174
                directive = merge_directive.MergeDirective.from_objects(
 
4175
                    branch.repository, revision_id, time.time(),
 
4176
                    osutils.local_time_offset(), submit_branch,
 
4177
                    public_branch=public_branch, patch_type=patch_type,
 
4178
                    message=message)
 
4179
 
 
4180
            outfile.writelines(directive.to_lines())
 
4181
            if output is None:
 
4182
                subject = '[MERGE] '
 
4183
                if message is not None:
 
4184
                    subject += message
 
4185
                else:
 
4186
                    revision = branch.repository.get_revision(revision_id)
 
4187
                    subject += revision.get_summary()
 
4188
                basename = directive.get_disk_name(branch)
 
4189
                mail_client.compose_merge_request(mail_to, subject,
 
4190
                                                  outfile.getvalue(), basename)
 
4191
        finally:
 
4192
            if output != '-':
 
4193
                outfile.close()
 
4194
            branch.unlock()
4860
4195
 
4861
4196
 
4862
4197
class cmd_bundle_revisions(cmd_send):
4863
 
    """Create a merge-directive for submitting changes.
 
4198
 
 
4199
    """Create a merge-directive for submiting changes.
4864
4200
 
4865
4201
    A merge directive provides many things needed for requesting merges:
4866
4202
 
4907
4243
        Option('output', short_name='o', help='Write directive to this file.',
4908
4244
               type=unicode),
4909
4245
        'revision',
4910
 
        RegistryOption('format',
4911
 
                       help='Use the specified output format.',
4912
 
                       lazy_registry=('bzrlib.send', 'format_registry')),
 
4246
        RegistryOption.from_kwargs('format',
 
4247
        'Use the specified output format.',
 
4248
        **{'4': 'Bundle format 4, Merge Directive 2 (default)',
 
4249
           '0.9': 'Bundle format 0.9, Merge Directive 1',})
4913
4250
        ]
4914
4251
    aliases = ['bundle']
4915
4252
 
4919
4256
 
4920
4257
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4921
4258
            no_patch=False, revision=None, remember=False, output=None,
4922
 
            format=None, **kwargs):
 
4259
            format='4', **kwargs):
4923
4260
        if output is None:
4924
4261
            output = '-'
4925
 
        from bzrlib.send import send
4926
 
        return send(submit_branch, revision, public_branch, remember,
 
4262
        return self._run(submit_branch, revision, public_branch, remember,
4927
4263
                         format, no_bundle, no_patch, output,
4928
 
                         kwargs.get('from', '.'), None, None, None,
4929
 
                         self.outf)
 
4264
                         kwargs.get('from', '.'), None, None)
4930
4265
 
4931
4266
 
4932
4267
class cmd_tag(Command):
4933
4268
    """Create, remove or modify a tag naming a revision.
4934
 
 
 
4269
    
4935
4270
    Tags give human-meaningful names to revisions.  Commands that take a -r
4936
4271
    (--revision) option can be given -rtag:X, where X is any previously
4937
4272
    created tag.
4939
4274
    Tags are stored in the branch.  Tags are copied from one branch to another
4940
4275
    along when you branch, push, pull or merge.
4941
4276
 
4942
 
    It is an error to give a tag name that already exists unless you pass
 
4277
    It is an error to give a tag name that already exists unless you pass 
4943
4278
    --force, in which case the tag is moved to point to the new revision.
4944
 
 
4945
 
    To rename a tag (change the name but keep it on the same revsion), run ``bzr
4946
 
    tag new-name -r tag:old-name`` and then ``bzr tag --delete oldname``.
4947
4279
    """
4948
4280
 
4949
4281
    _see_also = ['commit', 'tags']
4981
4313
                        raise errors.BzrCommandError(
4982
4314
                            "Tags can only be placed on a single revision, "
4983
4315
                            "not on a range")
4984
 
                    revision_id = revision[0].as_revision_id(branch)
 
4316
                    revision_id = revision[0].in_history(branch).rev_id
4985
4317
                else:
4986
4318
                    revision_id = branch.last_revision()
4987
4319
                if (not force) and branch.tags.has_tag(tag_name):
5011
4343
            time='Sort tags chronologically.',
5012
4344
            ),
5013
4345
        'show-ids',
5014
 
        'revision',
5015
4346
    ]
5016
4347
 
5017
4348
    @display_command
5019
4350
            directory='.',
5020
4351
            sort='alpha',
5021
4352
            show_ids=False,
5022
 
            revision=None,
5023
4353
            ):
5024
4354
        branch, relpath = Branch.open_containing(directory)
5025
 
 
5026
4355
        tags = branch.tags.get_tag_dict().items()
5027
 
        if not tags:
5028
 
            return
5029
 
 
5030
 
        if revision:
5031
 
            branch.lock_read()
5032
 
            try:
5033
 
                graph = branch.repository.get_graph()
5034
 
                rev1, rev2 = _get_revision_range(revision, branch, self.name())
5035
 
                revid1, revid2 = rev1.rev_id, rev2.rev_id
5036
 
                # only show revisions between revid1 and revid2 (inclusive)
5037
 
                tags = [(tag, revid) for tag, revid in tags if
5038
 
                    graph.is_between(revid, revid1, revid2)]
5039
 
            finally:
5040
 
                branch.unlock()
5041
4356
        if sort == 'alpha':
5042
4357
            tags.sort()
5043
4358
        elif sort == 'time':
5053
4368
            tags.sort(key=lambda x: timestamps[x[1]])
5054
4369
        if not show_ids:
5055
4370
            # [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5056
 
            for index, (tag, revid) in enumerate(tags):
5057
 
                try:
5058
 
                    revno = branch.revision_id_to_dotted_revno(revid)
5059
 
                    if isinstance(revno, tuple):
5060
 
                        revno = '.'.join(map(str, revno))
5061
 
                except errors.NoSuchRevision:
5062
 
                    # Bad tag data/merges can lead to tagged revisions
5063
 
                    # which are not in this branch. Fail gracefully ...
5064
 
                    revno = '?'
5065
 
                tags[index] = (tag, revno)
 
4371
            revno_map = branch.get_revision_id_to_revno_map()
 
4372
            tags = [ (tag, '.'.join(map(str, revno_map.get(revid, ('?',)))))
 
4373
                        for tag, revid in tags ]
5066
4374
        for tag, revspec in tags:
5067
4375
            self.outf.write('%-20s %s\n' % (tag, revspec))
5068
4376
 
5081
4389
    If none of these is available, --bind-to must be specified.
5082
4390
    """
5083
4391
 
5084
 
    _see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
5085
4392
    takes_args = ['location?']
5086
 
    takes_options = [
5087
 
        RegistryOption.from_kwargs(
5088
 
            'target_type',
5089
 
            title='Target type',
5090
 
            help='The type to reconfigure the directory to.',
5091
 
            value_switches=True, enum_switch=False,
5092
 
            branch='Reconfigure to be an unbound branch with no working tree.',
5093
 
            tree='Reconfigure to be an unbound branch with a working tree.',
5094
 
            checkout='Reconfigure to be a bound branch with a working tree.',
5095
 
            lightweight_checkout='Reconfigure to be a lightweight'
5096
 
                ' checkout (with no local history).',
5097
 
            standalone='Reconfigure to be a standalone branch '
5098
 
                '(i.e. stop using shared repository).',
5099
 
            use_shared='Reconfigure to use a shared repository.',
5100
 
            with_trees='Reconfigure repository to create '
5101
 
                'working trees on branches by default.',
5102
 
            with_no_trees='Reconfigure repository to not create '
5103
 
                'working trees on branches by default.'
5104
 
            ),
5105
 
        Option('bind-to', help='Branch to bind checkout to.', type=str),
5106
 
        Option('force',
5107
 
               help='Perform reconfiguration even if local changes'
5108
 
               ' will be lost.')
5109
 
        ]
 
4393
    takes_options = [RegistryOption.from_kwargs('target_type',
 
4394
                     title='Target type',
 
4395
                     help='The type to reconfigure the directory to.',
 
4396
                     value_switches=True, enum_switch=False,
 
4397
                     branch='Reconfigure to a branch.',
 
4398
                     tree='Reconfigure to a tree.',
 
4399
                     checkout='Reconfigure to a checkout.',
 
4400
                     lightweight_checkout='Reconfigure to a lightweight'
 
4401
                     ' checkout.'),
 
4402
                     Option('bind-to', help='Branch to bind checkout to.',
 
4403
                            type=str),
 
4404
                     Option('force',
 
4405
                        help='Perform reconfiguration even if local changes'
 
4406
                        ' will be lost.')
 
4407
                     ]
5110
4408
 
5111
4409
    def run(self, location=None, target_type=None, bind_to=None, force=False):
5112
4410
        directory = bzrdir.BzrDir.open(location)
5117
4415
        elif target_type == 'tree':
5118
4416
            reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5119
4417
        elif target_type == 'checkout':
5120
 
            reconfiguration = reconfigure.Reconfigure.to_checkout(
5121
 
                directory, bind_to)
 
4418
            reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
 
4419
                                                                  bind_to)
5122
4420
        elif target_type == 'lightweight-checkout':
5123
4421
            reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5124
4422
                directory, bind_to)
5125
 
        elif target_type == 'use-shared':
5126
 
            reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
5127
 
        elif target_type == 'standalone':
5128
 
            reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
5129
 
        elif target_type == 'with-trees':
5130
 
            reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5131
 
                directory, True)
5132
 
        elif target_type == 'with-no-trees':
5133
 
            reconfiguration = reconfigure.Reconfigure.set_repository_trees(
5134
 
                directory, False)
5135
4423
        reconfiguration.apply(force)
5136
4424
 
5137
4425
 
5138
4426
class cmd_switch(Command):
5139
4427
    """Set the branch of a checkout and update.
5140
 
 
 
4428
    
5141
4429
    For lightweight checkouts, this changes the branch being referenced.
5142
4430
    For heavyweight checkouts, this checks that there are no local commits
5143
4431
    versus the current bound branch, then it makes the local branch a mirror
5144
4432
    of the new location and binds to it.
5145
 
 
 
4433
    
5146
4434
    In both cases, the working tree is updated and uncommitted changes
5147
4435
    are merged. The user can commit or revert these as they desire.
5148
4436
 
5149
4437
    Pending merges need to be committed or reverted before using switch.
5150
 
 
5151
 
    The path to the branch to switch to can be specified relative to the parent
5152
 
    directory of the current branch. For example, if you are currently in a
5153
 
    checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5154
 
    /path/to/newbranch.
5155
 
 
5156
 
    Bound branches use the nickname of its master branch unless it is set
5157
 
    locally, in which case switching will update the the local nickname to be
5158
 
    that of the master.
5159
4438
    """
5160
4439
 
5161
4440
    takes_args = ['to_location']
5165
4444
 
5166
4445
    def run(self, to_location, force=False):
5167
4446
        from bzrlib import switch
 
4447
        to_branch = Branch.open(to_location)
5168
4448
        tree_location = '.'
5169
4449
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5170
 
        try:
5171
 
            branch = control_dir.open_branch()
5172
 
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5173
 
        except errors.NotBranchError:
5174
 
            had_explicit_nick = False
5175
 
        try:
5176
 
            to_branch = Branch.open(to_location)
5177
 
        except errors.NotBranchError:
5178
 
            this_url = self._get_branch_location(control_dir)
5179
 
            to_branch = Branch.open(
5180
 
                urlutils.join(this_url, '..', to_location))
5181
4450
        switch.switch(control_dir, to_branch, force)
5182
 
        if had_explicit_nick:
5183
 
            branch = control_dir.open_branch() #get the new branch!
5184
 
            branch.nick = to_branch.nick
5185
4451
        note('Switched to branch: %s',
5186
4452
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5187
4453
 
5188
 
    def _get_branch_location(self, control_dir):
5189
 
        """Return location of branch for this control dir."""
5190
 
        try:
5191
 
            this_branch = control_dir.open_branch()
5192
 
            # This may be a heavy checkout, where we want the master branch
5193
 
            master_location = this_branch.get_bound_location()
5194
 
            if master_location is not None:
5195
 
                return master_location
5196
 
            # If not, use a local sibling
5197
 
            return this_branch.base
5198
 
        except errors.NotBranchError:
5199
 
            format = control_dir.find_branch_format()
5200
 
            if getattr(format, 'get_reference', None) is not None:
5201
 
                return format.get_reference(control_dir)
5202
 
            else:
5203
 
                return control_dir.root_transport.base
5204
 
 
5205
 
 
5206
 
class cmd_view(Command):
5207
 
    """Manage filtered views.
5208
 
 
5209
 
    Views provide a mask over the tree so that users can focus on
5210
 
    a subset of a tree when doing their work. After creating a view,
5211
 
    commands that support a list of files - status, diff, commit, etc -
5212
 
    effectively have that list of files implicitly given each time.
5213
 
    An explicit list of files can still be given but those files
5214
 
    must be within the current view.
5215
 
 
5216
 
    In most cases, a view has a short life-span: it is created to make
5217
 
    a selected change and is deleted once that change is committed.
5218
 
    At other times, you may wish to create one or more named views
5219
 
    and switch between them.
5220
 
 
5221
 
    To disable the current view without deleting it, you can switch to
5222
 
    the pseudo view called ``off``. This can be useful when you need
5223
 
    to see the whole tree for an operation or two (e.g. merge) but
5224
 
    want to switch back to your view after that.
5225
 
 
5226
 
    :Examples:
5227
 
      To define the current view::
5228
 
 
5229
 
        bzr view file1 dir1 ...
5230
 
 
5231
 
      To list the current view::
5232
 
 
5233
 
        bzr view
5234
 
 
5235
 
      To delete the current view::
5236
 
 
5237
 
        bzr view --delete
5238
 
 
5239
 
      To disable the current view without deleting it::
5240
 
 
5241
 
        bzr view --switch off
5242
 
 
5243
 
      To define a named view and switch to it::
5244
 
 
5245
 
        bzr view --name view-name file1 dir1 ...
5246
 
 
5247
 
      To list a named view::
5248
 
 
5249
 
        bzr view --name view-name
5250
 
 
5251
 
      To delete a named view::
5252
 
 
5253
 
        bzr view --name view-name --delete
5254
 
 
5255
 
      To switch to a named view::
5256
 
 
5257
 
        bzr view --switch view-name
5258
 
 
5259
 
      To list all views defined::
5260
 
 
5261
 
        bzr view --all
5262
 
 
5263
 
      To delete all views::
5264
 
 
5265
 
        bzr view --delete --all
5266
 
    """
5267
 
 
5268
 
    _see_also = []
5269
 
    takes_args = ['file*']
5270
 
    takes_options = [
5271
 
        Option('all',
5272
 
            help='Apply list or delete action to all views.',
5273
 
            ),
5274
 
        Option('delete',
5275
 
            help='Delete the view.',
5276
 
            ),
5277
 
        Option('name',
5278
 
            help='Name of the view to define, list or delete.',
5279
 
            type=unicode,
5280
 
            ),
5281
 
        Option('switch',
5282
 
            help='Name of the view to switch to.',
5283
 
            type=unicode,
5284
 
            ),
5285
 
        ]
5286
 
 
5287
 
    def run(self, file_list,
5288
 
            all=False,
5289
 
            delete=False,
5290
 
            name=None,
5291
 
            switch=None,
5292
 
            ):
5293
 
        tree, file_list = tree_files(file_list, apply_view=False)
5294
 
        current_view, view_dict = tree.views.get_view_info()
5295
 
        if name is None:
5296
 
            name = current_view
5297
 
        if delete:
5298
 
            if file_list:
5299
 
                raise errors.BzrCommandError(
5300
 
                    "Both --delete and a file list specified")
5301
 
            elif switch:
5302
 
                raise errors.BzrCommandError(
5303
 
                    "Both --delete and --switch specified")
5304
 
            elif all:
5305
 
                tree.views.set_view_info(None, {})
5306
 
                self.outf.write("Deleted all views.\n")
5307
 
            elif name is None:
5308
 
                raise errors.BzrCommandError("No current view to delete")
5309
 
            else:
5310
 
                tree.views.delete_view(name)
5311
 
                self.outf.write("Deleted '%s' view.\n" % name)
5312
 
        elif switch:
5313
 
            if file_list:
5314
 
                raise errors.BzrCommandError(
5315
 
                    "Both --switch and a file list specified")
5316
 
            elif all:
5317
 
                raise errors.BzrCommandError(
5318
 
                    "Both --switch and --all specified")
5319
 
            elif switch == 'off':
5320
 
                if current_view is None:
5321
 
                    raise errors.BzrCommandError("No current view to disable")
5322
 
                tree.views.set_view_info(None, view_dict)
5323
 
                self.outf.write("Disabled '%s' view.\n" % (current_view))
5324
 
            else:
5325
 
                tree.views.set_view_info(switch, view_dict)
5326
 
                view_str = views.view_display_str(tree.views.lookup_view())
5327
 
                self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5328
 
        elif all:
5329
 
            if view_dict:
5330
 
                self.outf.write('Views defined:\n')
5331
 
                for view in sorted(view_dict):
5332
 
                    if view == current_view:
5333
 
                        active = "=>"
5334
 
                    else:
5335
 
                        active = "  "
5336
 
                    view_str = views.view_display_str(view_dict[view])
5337
 
                    self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5338
 
            else:
5339
 
                self.outf.write('No views defined.\n')
5340
 
        elif file_list:
5341
 
            if name is None:
5342
 
                # No name given and no current view set
5343
 
                name = 'my'
5344
 
            elif name == 'off':
5345
 
                raise errors.BzrCommandError(
5346
 
                    "Cannot change the 'off' pseudo view")
5347
 
            tree.views.set_view(name, sorted(file_list))
5348
 
            view_str = views.view_display_str(tree.views.lookup_view())
5349
 
            self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5350
 
        else:
5351
 
            # list the files
5352
 
            if name is None:
5353
 
                # No name given and no current view set
5354
 
                self.outf.write('No current view.\n')
5355
 
            else:
5356
 
                view_str = views.view_display_str(tree.views.lookup_view(name))
5357
 
                self.outf.write("'%s' view is: %s\n" % (name, view_str))
5358
 
 
5359
4454
 
5360
4455
class cmd_hooks(Command):
5361
 
    """Show hooks."""
5362
 
 
5363
 
    hidden = True
5364
 
 
5365
 
    def run(self):
5366
 
        for hook_key in sorted(hooks.known_hooks.keys()):
5367
 
            some_hooks = hooks.known_hooks_key_to_object(hook_key)
5368
 
            self.outf.write("%s:\n" % type(some_hooks).__name__)
5369
 
            for hook_name, hook_point in sorted(some_hooks.items()):
5370
 
                self.outf.write("  %s:\n" % (hook_name,))
5371
 
                found_hooks = list(hook_point)
5372
 
                if found_hooks:
5373
 
                    for hook in found_hooks:
5374
 
                        self.outf.write("    %s\n" %
5375
 
                                        (some_hooks.get_hook_name(hook),))
5376
 
                else:
5377
 
                    self.outf.write("    <no hooks installed>\n")
5378
 
 
5379
 
 
5380
 
class cmd_shelve(Command):
5381
 
    """Temporarily set aside some changes from the current tree.
5382
 
 
5383
 
    Shelve allows you to temporarily put changes you've made "on the shelf",
5384
 
    ie. out of the way, until a later time when you can bring them back from
5385
 
    the shelf with the 'unshelve' command.  The changes are stored alongside
5386
 
    your working tree, and so they aren't propagated along with your branch nor
5387
 
    will they survive its deletion.
5388
 
 
5389
 
    If shelve --list is specified, previously-shelved changes are listed.
5390
 
 
5391
 
    Shelve is intended to help separate several sets of changes that have
5392
 
    been inappropriately mingled.  If you just want to get rid of all changes
5393
 
    and you don't need to restore them later, use revert.  If you want to
5394
 
    shelve all text changes at once, use shelve --all.
5395
 
 
5396
 
    If filenames are specified, only the changes to those files will be
5397
 
    shelved. Other files will be left untouched.
5398
 
 
5399
 
    If a revision is specified, changes since that revision will be shelved.
5400
 
 
5401
 
    You can put multiple items on the shelf, and by default, 'unshelve' will
5402
 
    restore the most recently shelved changes.
5403
 
    """
5404
 
 
5405
 
    takes_args = ['file*']
5406
 
 
5407
 
    takes_options = [
5408
 
        'revision',
5409
 
        Option('all', help='Shelve all changes.'),
5410
 
        'message',
5411
 
        RegistryOption('writer', 'Method to use for writing diffs.',
5412
 
                       bzrlib.option.diff_writer_registry,
5413
 
                       value_switches=True, enum_switch=False),
5414
 
 
5415
 
        Option('list', help='List shelved changes.'),
5416
 
        Option('destroy',
5417
 
               help='Destroy removed changes instead of shelving them.'),
5418
 
    ]
5419
 
    _see_also = ['unshelve']
5420
 
 
5421
 
    def run(self, revision=None, all=False, file_list=None, message=None,
5422
 
            writer=None, list=False, destroy=False):
5423
 
        if list:
5424
 
            return self.run_for_list()
5425
 
        from bzrlib.shelf_ui import Shelver
5426
 
        if writer is None:
5427
 
            writer = bzrlib.option.diff_writer_registry.get()
5428
 
        try:
5429
 
            Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5430
 
                              message, destroy=destroy).run()
5431
 
        except errors.UserAbort:
5432
 
            return 0
5433
 
 
5434
 
    def run_for_list(self):
5435
 
        tree = WorkingTree.open_containing('.')[0]
5436
 
        tree.lock_read()
5437
 
        try:
5438
 
            manager = tree.get_shelf_manager()
5439
 
            shelves = manager.active_shelves()
5440
 
            if len(shelves) == 0:
5441
 
                note('No shelved changes.')
5442
 
                return 0
5443
 
            for shelf_id in reversed(shelves):
5444
 
                message = manager.get_metadata(shelf_id).get('message')
5445
 
                if message is None:
5446
 
                    message = '<no message>'
5447
 
                self.outf.write('%3d: %s\n' % (shelf_id, message))
5448
 
            return 1
5449
 
        finally:
5450
 
            tree.unlock()
5451
 
 
5452
 
 
5453
 
class cmd_unshelve(Command):
5454
 
    """Restore shelved changes.
5455
 
 
5456
 
    By default, the most recently shelved changes are restored. However if you
5457
 
    specify a shelf by id those changes will be restored instead.  This works
5458
 
    best when the changes don't depend on each other.
5459
 
    """
5460
 
 
5461
 
    takes_args = ['shelf_id?']
5462
 
    takes_options = [
5463
 
        RegistryOption.from_kwargs(
5464
 
            'action', help="The action to perform.",
5465
 
            enum_switch=False, value_switches=True,
5466
 
            apply="Apply changes and remove from the shelf.",
5467
 
            dry_run="Show changes, but do not apply or remove them.",
5468
 
            delete_only="Delete changes without applying them."
5469
 
        )
5470
 
    ]
5471
 
    _see_also = ['shelve']
5472
 
 
5473
 
    def run(self, shelf_id=None, action='apply'):
5474
 
        from bzrlib.shelf_ui import Unshelver
5475
 
        Unshelver.from_args(shelf_id, action).run()
5476
 
 
5477
 
 
5478
 
class cmd_clean_tree(Command):
5479
 
    """Remove unwanted files from working tree.
5480
 
 
5481
 
    By default, only unknown files, not ignored files, are deleted.  Versioned
5482
 
    files are never deleted.
5483
 
 
5484
 
    Another class is 'detritus', which includes files emitted by bzr during
5485
 
    normal operations and selftests.  (The value of these files decreases with
5486
 
    time.)
5487
 
 
5488
 
    If no options are specified, unknown files are deleted.  Otherwise, option
5489
 
    flags are respected, and may be combined.
5490
 
 
5491
 
    To check what clean-tree will do, use --dry-run.
5492
 
    """
5493
 
    takes_options = [Option('ignored', help='Delete all ignored files.'),
5494
 
                     Option('detritus', help='Delete conflict files, merge'
5495
 
                            ' backups, and failed selftest dirs.'),
5496
 
                     Option('unknown',
5497
 
                            help='Delete files unknown to bzr (default).'),
5498
 
                     Option('dry-run', help='Show files to delete instead of'
5499
 
                            ' deleting them.'),
5500
 
                     Option('force', help='Do not prompt before deleting.')]
5501
 
    def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5502
 
            force=False):
5503
 
        from bzrlib.clean_tree import clean_tree
5504
 
        if not (unknown or ignored or detritus):
5505
 
            unknown = True
5506
 
        if dry_run:
5507
 
            force = True
5508
 
        clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5509
 
                   dry_run=dry_run, no_prompt=force)
5510
 
 
5511
 
 
5512
 
class cmd_reference(Command):
5513
 
    """list, view and set branch locations for nested trees.
5514
 
 
5515
 
    If no arguments are provided, lists the branch locations for nested trees.
5516
 
    If one argument is provided, display the branch location for that tree.
5517
 
    If two arguments are provided, set the branch location for that tree.
5518
 
    """
5519
 
 
5520
 
    hidden = True
5521
 
 
5522
 
    takes_args = ['path?', 'location?']
5523
 
 
5524
 
    def run(self, path=None, location=None):
5525
 
        branchdir = '.'
5526
 
        if path is not None:
5527
 
            branchdir = path
5528
 
        tree, branch, relpath =(
5529
 
            bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5530
 
        if path is not None:
5531
 
            path = relpath
5532
 
        if tree is None:
5533
 
            tree = branch.basis_tree()
 
4456
    """Show a branch's currently registered hooks.
 
4457
    """
 
4458
 
 
4459
    hidden = True
 
4460
    takes_args = ['path?']
 
4461
 
 
4462
    def run(self, path=None):
5534
4463
        if path is None:
5535
 
            info = branch._get_all_reference_info().iteritems()
5536
 
            self._display_reference_info(tree, branch, info)
 
4464
            path = '.'
 
4465
        branch_hooks = Branch.open(path).hooks
 
4466
        for hook_type in branch_hooks:
 
4467
            hooks = branch_hooks[hook_type]
 
4468
            self.outf.write("%s:\n" % (hook_type,))
 
4469
            if hooks:
 
4470
                for hook in hooks:
 
4471
                    self.outf.write("  %s\n" %
 
4472
                                    (branch_hooks.get_hook_name(hook),))
 
4473
            else:
 
4474
                self.outf.write("  <no hooks installed>\n")
 
4475
 
 
4476
 
 
4477
def _create_prefix(cur_transport):
 
4478
    needed = [cur_transport]
 
4479
    # Recurse upwards until we can create a directory successfully
 
4480
    while True:
 
4481
        new_transport = cur_transport.clone('..')
 
4482
        if new_transport.base == cur_transport.base:
 
4483
            raise errors.BzrCommandError(
 
4484
                "Failed to create path prefix for %s."
 
4485
                % cur_transport.base)
 
4486
        try:
 
4487
            new_transport.mkdir('.')
 
4488
        except errors.NoSuchFile:
 
4489
            needed.append(new_transport)
 
4490
            cur_transport = new_transport
5537
4491
        else:
5538
 
            file_id = tree.path2id(path)
5539
 
            if file_id is None:
5540
 
                raise errors.NotVersionedError(path)
5541
 
            if location is None:
5542
 
                info = [(file_id, branch.get_reference_info(file_id))]
5543
 
                self._display_reference_info(tree, branch, info)
5544
 
            else:
5545
 
                branch.set_reference_info(file_id, path, location)
5546
 
 
5547
 
    def _display_reference_info(self, tree, branch, info):
5548
 
        ref_list = []
5549
 
        for file_id, (path, location) in info:
5550
 
            try:
5551
 
                path = tree.id2path(file_id)
5552
 
            except errors.NoSuchId:
5553
 
                pass
5554
 
            ref_list.append((path, location))
5555
 
        for path, location in sorted(ref_list):
5556
 
            self.outf.write('%s %s\n' % (path, location))
 
4492
            break
 
4493
    # Now we only need to create child directories
 
4494
    while needed:
 
4495
        cur_transport = needed.pop()
 
4496
        cur_transport.ensure_base()
 
4497
 
 
4498
 
 
4499
def _get_mergeable_helper(location):
 
4500
    """Get a merge directive or bundle if 'location' points to one.
 
4501
 
 
4502
    Try try to identify a bundle and returns its mergeable form. If it's not,
 
4503
    we return the tried transport anyway so that it can reused to access the
 
4504
    branch
 
4505
 
 
4506
    :param location: can point to a bundle or a branch.
 
4507
 
 
4508
    :return: mergeable, transport
 
4509
    """
 
4510
    mergeable = None
 
4511
    url = urlutils.normalize_url(location)
 
4512
    url, filename = urlutils.split(url, exclude_trailing_slash=False)
 
4513
    location_transport = transport.get_transport(url)
 
4514
    if filename:
 
4515
        try:
 
4516
            # There may be redirections but we ignore the intermediate
 
4517
            # and final transports used
 
4518
            read = bundle.read_mergeable_from_transport
 
4519
            mergeable, t = read(location_transport, filename)
 
4520
        except errors.NotABundle:
 
4521
            # Continue on considering this url a Branch but adjust the
 
4522
            # location_transport
 
4523
            location_transport = location_transport.clone(filename)
 
4524
    return mergeable, location_transport
5557
4525
 
5558
4526
 
5559
4527
# these get imported and then picked up by the scan for cmd_*
5560
4528
# TODO: Some more consistent way to split command definitions across files;
5561
 
# we do need to load at least some information about them to know of
 
4529
# we do need to load at least some information about them to know of 
5562
4530
# aliases.  ideally we would avoid loading the implementation until the
5563
4531
# details were needed.
5564
4532
from bzrlib.cmd_version_info import cmd_version_info
5566
4534
from bzrlib.bundle.commands import (
5567
4535
    cmd_bundle_info,
5568
4536
    )
5569
 
from bzrlib.foreign import cmd_dpush
5570
4537
from bzrlib.sign_my_commits import cmd_sign_my_commits
5571
 
from bzrlib.weave_commands import cmd_versionedfile_list, \
 
4538
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
5572
4539
        cmd_weave_plan_merge, cmd_weave_merge_text