~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Michael Ellerman
  • Date: 2006-02-28 14:45:51 UTC
  • mto: (1558.1.18 Aaron's integration)
  • mto: This revision was merged to the branch mainline in revision 1586.
  • Revision ID: michael@ellerman.id.au-20060228144551-3d9941ecde4a0b0a
Update contrib/pwk for -p1 diffs from bzr

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005, 2006 by Canonical Ltd
 
1
# Copyright (C) 2004, 2005 by 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
17
17
"""builtin bzr commands"""
18
18
 
19
19
 
20
 
import codecs
21
20
import errno
22
21
import os
23
 
import os.path
 
22
from shutil import rmtree
24
23
import sys
25
24
 
26
25
import bzrlib
27
 
from bzrlib.branch import Branch, BranchReferenceFormat
28
 
from bzrlib import (bundle, branch, bzrdir, errors, osutils, ui, config,
29
 
    repository, log)
30
 
from bzrlib.bundle import read_bundle_from_url
31
 
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
32
 
from bzrlib.conflicts import ConflictList
 
26
import bzrlib.branch
 
27
from bzrlib.branch import Branch
 
28
import bzrlib.bzrdir as bzrdir
33
29
from bzrlib.commands import Command, display_command
 
30
from bzrlib.revision import common_ancestor
 
31
import bzrlib.errors as errors
34
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
35
33
                           NotBranchError, DivergedBranches, NotConflicted,
36
 
                           NoSuchFile, NoWorkingTree, FileInWrongBranch,
37
 
                           NotVersionedError, NotABundle)
 
34
                           NoSuchFile, NoWorkingTree, FileInWrongBranch)
 
35
from bzrlib.log import show_one_log
38
36
from bzrlib.merge import Merge3Merger
39
37
from bzrlib.option import Option
40
 
from bzrlib.progress import DummyProgress, ProgressPhase
41
 
from bzrlib.revision import common_ancestor
 
38
from bzrlib.progress import DummyProgress
42
39
from bzrlib.revisionspec import RevisionSpec
43
 
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
 
40
import bzrlib.trace
 
41
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
44
42
from bzrlib.transport.local import LocalTransport
45
 
import bzrlib.urlutils as urlutils
 
43
import bzrlib.ui
46
44
from bzrlib.workingtree import WorkingTree
47
45
 
48
46
 
53
51
        raise BzrCommandError("%s is not in the same branch as %s" %
54
52
                             (e.path, file_list[0]))
55
53
 
56
 
 
57
 
# XXX: Bad function name; should possibly also be a class method of
58
 
# WorkingTree rather than a function.
59
54
def internal_tree_files(file_list, default_branch=u'.'):
60
 
    """Convert command-line paths to a WorkingTree and relative paths.
61
 
 
62
 
    This is typically used for command-line processors that take one or
63
 
    more filenames, and infer the workingtree that contains them.
64
 
 
65
 
    The filenames given are not required to exist.
66
 
 
67
 
    :param file_list: Filenames to convert.  
68
 
 
69
 
    :param default_branch: Fallback tree path to use if file_list is empty or None.
70
 
 
71
 
    :return: workingtree, [relative_paths]
 
55
    """\
 
56
    Return a branch and list of branch-relative paths.
 
57
    If supplied file_list is empty or None, the branch default will be used,
 
58
    and returned file_list will match the original.
72
59
    """
73
60
    if file_list is None or len(file_list) == 0:
74
61
        return WorkingTree.open_containing(default_branch)[0], file_list
82
69
    return tree, new_list
83
70
 
84
71
 
85
 
def get_format_type(typestring):
86
 
    """Parse and return a format specifier."""
87
 
    if typestring == "weave":
88
 
        return bzrdir.BzrDirFormat6()
89
 
    if typestring == "default":
90
 
        return bzrdir.BzrDirMetaFormat1()
91
 
    if typestring == "metaweave":
92
 
        format = bzrdir.BzrDirMetaFormat1()
93
 
        format.repository_format = repository.RepositoryFormat7()
94
 
        return format
95
 
    if typestring == "knit":
96
 
        format = bzrdir.BzrDirMetaFormat1()
97
 
        format.repository_format = repository.RepositoryFormatKnit1()
98
 
        return format
99
 
    msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
100
 
          "metaweave and weave" % typestring
101
 
    raise BzrCommandError(msg)
102
 
 
103
 
 
104
72
# TODO: Make sure no commands unconditionally use the working directory as a
105
73
# branch.  If a filename argument is used, the first of them should be used to
106
74
# specify the branch.  (Perhaps this can be factored out into some kind of
128
96
    modified
129
97
        Text has changed since the previous revision.
130
98
 
 
99
    unchanged
 
100
        Nothing about this file has changed since the previous revision.
 
101
        Only shown with --all.
 
102
 
131
103
    unknown
132
104
        Not versioned and not matching an ignore pattern.
133
105
 
146
118
    # TODO: --no-recurse, --recurse options
147
119
    
148
120
    takes_args = ['file*']
149
 
    takes_options = ['show-ids', 'revision']
 
121
    takes_options = ['all', 'show-ids', 'revision']
150
122
    aliases = ['st', 'stat']
151
 
 
152
 
    encoding_type = 'replace'
153
123
    
154
124
    @display_command
155
 
    def run(self, show_ids=False, file_list=None, revision=None):
 
125
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
 
126
        tree, file_list = tree_files(file_list)
 
127
            
156
128
        from bzrlib.status import show_tree_status
157
 
 
158
 
        tree, file_list = tree_files(file_list)
159
 
            
160
 
        show_tree_status(tree, show_ids=show_ids,
161
 
                         specific_files=file_list, revision=revision,
162
 
                         to_file=self.outf)
 
129
        show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
 
130
                         specific_files=file_list, revision=revision)
163
131
 
164
132
 
165
133
class cmd_cat_revision(Command):
172
140
    hidden = True
173
141
    takes_args = ['revision_id?']
174
142
    takes_options = ['revision']
175
 
    # cat-revision is more for frontends so should be exact
176
 
    encoding = 'strict'
177
143
    
178
144
    @display_command
179
145
    def run(self, revision_id=None, revision=None):
183
149
        if revision_id is None and revision is None:
184
150
            raise BzrCommandError('You must supply either --revision or a revision_id')
185
151
        b = WorkingTree.open_containing(u'.')[0].branch
186
 
 
187
 
        # TODO: jam 20060112 should cat-revision always output utf-8?
188
152
        if revision_id is not None:
189
 
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
 
153
            sys.stdout.write(b.repository.get_revision_xml(revision_id))
190
154
        elif revision is not None:
191
155
            for rev in revision:
192
156
                if rev is None:
193
157
                    raise BzrCommandError('You cannot specify a NULL revision.')
194
158
                revno, rev_id = rev.in_history(b)
195
 
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
 
159
                sys.stdout.write(b.repository.get_revision_xml(rev_id))
196
160
    
197
161
 
198
162
class cmd_revno(Command):
199
163
    """Show current revision number.
200
164
 
201
 
    This is equal to the number of revisions on this branch.
202
 
    """
203
 
 
 
165
    This is equal to the number of revisions on this branch."""
204
166
    takes_args = ['location?']
205
 
 
206
167
    @display_command
207
168
    def run(self, location=u'.'):
208
 
        self.outf.write(str(Branch.open_containing(location)[0].revno()))
209
 
        self.outf.write('\n')
 
169
        print Branch.open_containing(location)[0].revno()
210
170
 
211
171
 
212
172
class cmd_revision_info(Command):
215
175
    hidden = True
216
176
    takes_args = ['revision_info*']
217
177
    takes_options = ['revision']
218
 
 
219
178
    @display_command
220
179
    def run(self, revision=None, revision_info_list=[]):
221
180
 
258
217
 
259
218
    Adding a file whose parent directory is not versioned will
260
219
    implicitly add the parent, and so on up to the root. This means
261
 
    you should never need to explicitly add a directory, they'll just
 
220
    you should never need to explictly add a directory, they'll just
262
221
    get added when you add a file in the directory.
263
222
 
264
223
    --dry-run will show which files would be added, but not actually 
266
225
    """
267
226
    takes_args = ['file*']
268
227
    takes_options = ['no-recurse', 'dry-run', 'verbose']
269
 
    encoding_type = 'replace'
270
228
 
271
229
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
272
230
        import bzrlib.add
273
231
 
274
 
        action = bzrlib.add.AddAction(to_file=self.outf,
275
 
            should_print=(not is_quiet()))
 
232
        if dry_run:
 
233
            if is_quiet():
 
234
                # This is pointless, but I'd rather not raise an error
 
235
                action = bzrlib.add.add_action_null
 
236
            else:
 
237
                action = bzrlib.add.add_action_print
 
238
        elif is_quiet():
 
239
            action = bzrlib.add.add_action_add
 
240
        else:
 
241
            action = bzrlib.add.add_action_add_and_print
276
242
 
277
243
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse, 
278
 
                                              action=action, save=not dry_run)
 
244
                                              action)
279
245
        if len(ignored) > 0:
280
 
            if verbose:
281
 
                for glob in sorted(ignored.keys()):
 
246
            for glob in sorted(ignored.keys()):
 
247
                match_len = len(ignored[glob])
 
248
                if verbose:
282
249
                    for path in ignored[glob]:
283
 
                        self.outf.write("ignored %s matching \"%s\"\n" 
284
 
                                        % (path, glob))
285
 
            else:
286
 
                match_len = 0
287
 
                for glob, paths in ignored.items():
288
 
                    match_len += len(paths)
289
 
                self.outf.write("ignored %d file(s).\n" % match_len)
290
 
            self.outf.write("If you wish to add some of these files,"
291
 
                            " please add them by name.\n")
 
250
                        print "ignored %s matching \"%s\"" % (path, glob)
 
251
                else:
 
252
                    print "ignored %d file(s) matching \"%s\"" % (match_len,
 
253
                                                              glob)
 
254
            print "If you wish to add some of these files, please add them"\
 
255
                " by name."
292
256
 
293
257
 
294
258
class cmd_mkdir(Command):
296
260
 
297
261
    This is equivalent to creating the directory and then adding it.
298
262
    """
299
 
 
300
263
    takes_args = ['dir+']
301
 
    encoding_type = 'replace'
302
264
 
303
265
    def run(self, dir_list):
304
266
        for d in dir_list:
305
267
            os.mkdir(d)
306
268
            wt, dd = WorkingTree.open_containing(d)
307
269
            wt.add([dd])
308
 
            self.outf.write('added %s\n' % d)
 
270
            print 'added', d
309
271
 
310
272
 
311
273
class cmd_relpath(Command):
312
274
    """Show path of a file relative to root"""
313
 
 
314
275
    takes_args = ['filename']
315
276
    hidden = True
316
277
    
317
278
    @display_command
318
279
    def run(self, filename):
319
 
        # TODO: jam 20050106 Can relpath return a munged path if
320
 
        #       sys.stdout encoding cannot represent it?
321
280
        tree, relpath = WorkingTree.open_containing(filename)
322
 
        self.outf.write(relpath)
323
 
        self.outf.write('\n')
 
281
        print relpath
324
282
 
325
283
 
326
284
class cmd_inventory(Command):
329
287
    It is possible to limit the output to a particular entry
330
288
    type using the --kind option.  For example; --kind file.
331
289
    """
332
 
 
333
290
    takes_options = ['revision', 'show-ids', 'kind']
334
291
    
335
292
    @display_command
350
307
            if kind and kind != entry.kind:
351
308
                continue
352
309
            if show_ids:
353
 
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
 
310
                print '%-50s %s' % (path, entry.file_id)
354
311
            else:
355
 
                self.outf.write(path)
356
 
                self.outf.write('\n')
 
312
                print path
 
313
 
 
314
 
 
315
class cmd_move(Command):
 
316
    """Move files to a different directory.
 
317
 
 
318
    examples:
 
319
        bzr move *.txt doc
 
320
 
 
321
    The destination must be a versioned directory in the same branch.
 
322
    """
 
323
    takes_args = ['source$', 'dest']
 
324
    def run(self, source_list, dest):
 
325
        tree, source_list = tree_files(source_list)
 
326
        # TODO: glob expansion on windows?
 
327
        tree.move(source_list, tree.relpath(dest))
 
328
 
 
329
 
 
330
class cmd_rename(Command):
 
331
    """Change the name of an entry.
 
332
 
 
333
    examples:
 
334
      bzr rename frob.c frobber.c
 
335
      bzr rename src/frob.c lib/frob.c
 
336
 
 
337
    It is an error if the destination name exists.
 
338
 
 
339
    See also the 'move' command, which moves files into a different
 
340
    directory without changing their name.
 
341
    """
 
342
    # TODO: Some way to rename multiple files without invoking 
 
343
    # bzr for each one?"""
 
344
    takes_args = ['from_name', 'to_name']
 
345
    
 
346
    def run(self, from_name, to_name):
 
347
        tree, (from_name, to_name) = tree_files((from_name, to_name))
 
348
        tree.rename_one(from_name, to_name)
357
349
 
358
350
 
359
351
class cmd_mv(Command):
369
361
 
370
362
    Files cannot be moved between branches.
371
363
    """
372
 
 
373
364
    takes_args = ['names*']
374
 
    aliases = ['move', 'rename']
375
 
    encoding_type = 'replace'
376
 
 
377
365
    def run(self, names_list):
378
 
        if names_list is None:
379
 
            names_list = []
380
 
 
381
366
        if len(names_list) < 2:
382
367
            raise BzrCommandError("missing file argument")
383
368
        tree, rel_names = tree_files(names_list)
385
370
        if os.path.isdir(names_list[-1]):
386
371
            # move into existing directory
387
372
            for pair in tree.move(rel_names[:-1], rel_names[-1]):
388
 
                self.outf.write("%s => %s\n" % pair)
 
373
                print "%s => %s" % pair
389
374
        else:
390
375
            if len(names_list) != 2:
391
376
                raise BzrCommandError('to mv multiple files the destination '
392
377
                                      'must be a versioned directory')
393
378
            tree.rename_one(rel_names[0], rel_names[1])
394
 
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
 
379
            print "%s => %s" % (rel_names[0], rel_names[1])
395
380
            
396
381
    
397
382
class cmd_pull(Command):
398
 
    """Turn this branch into a mirror of another branch.
 
383
    """Pull any changes from another branch into the current one.
 
384
 
 
385
    If there is no default location set, the first pull will set it.  After
 
386
    that, you can omit the location to use the default.  To change the
 
387
    default, use --remember.
399
388
 
400
389
    This command only works on branches that have not diverged.  Branches are
401
 
    considered diverged if the destination branch's most recent commit is one
402
 
    that has not been merged (directly or indirectly) into the parent.
 
390
    considered diverged if both branches have had commits without first
 
391
    pulling from the other.
403
392
 
404
 
    If branches have diverged, you can use 'bzr merge' to integrate the changes
 
393
    If branches have diverged, you can use 'bzr merge' to pull the text changes
405
394
    from one into the other.  Once one branch has merged, the other should
406
395
    be able to pull it again.
407
396
 
408
397
    If you want to forget your local changes and just update your branch to
409
 
    match the remote one, use pull --overwrite.
410
 
 
411
 
    If there is no default location set, the first pull will set it.  After
412
 
    that, you can omit the location to use the default.  To change the
413
 
    default, use --remember. The value will only be saved if the remote
414
 
    location can be accessed.
 
398
    match the remote one, use --overwrite.
415
399
    """
416
 
 
417
400
    takes_options = ['remember', 'overwrite', 'revision', 'verbose']
418
401
    takes_args = ['location?']
419
 
    encoding_type = 'replace'
420
402
 
421
403
    def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
422
 
        # FIXME: too much stuff is in the command class
423
 
        try:
424
 
            tree_to = WorkingTree.open_containing(u'.')[0]
425
 
            branch_to = tree_to.branch
426
 
        except NoWorkingTree:
427
 
            tree_to = None
428
 
            branch_to = Branch.open_containing(u'.')[0]
429
 
 
430
 
        reader = None
431
 
        if location is not None:
432
 
            try:
433
 
                reader = bundle.read_bundle_from_url(location)
434
 
            except NotABundle:
435
 
                pass # Continue on considering this url a Branch
436
 
 
437
 
        stored_loc = branch_to.get_parent()
 
404
        # FIXME: too much stuff is in the command class        
 
405
        tree_to = WorkingTree.open_containing(u'.')[0]
 
406
        stored_loc = tree_to.branch.get_parent()
438
407
        if location is None:
439
408
            if stored_loc is None:
440
409
                raise BzrCommandError("No pull location known or specified.")
441
410
            else:
442
 
                display_url = urlutils.unescape_for_display(stored_loc,
443
 
                        self.outf.encoding)
444
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
411
                print "Using saved location: %s" % stored_loc
445
412
                location = stored_loc
446
413
 
447
 
 
448
 
        if reader is not None:
449
 
            install_bundle(branch_to.repository, reader)
450
 
            branch_from = branch_to
451
 
        else:
452
 
            branch_from = Branch.open(location)
453
 
 
454
 
            if branch_to.get_parent() is None or remember:
455
 
                branch_to.set_parent(branch_from.base)
456
 
 
457
 
        rev_id = None
 
414
        br_from = Branch.open(location)
 
415
        br_to = tree_to.branch
 
416
 
458
417
        if revision is None:
459
 
            if reader is not None:
460
 
                rev_id = reader.target
 
418
            rev_id = None
461
419
        elif len(revision) == 1:
462
 
            rev_id = revision[0].in_history(branch_from).rev_id
 
420
            rev_id = revision[0].in_history(br_from).rev_id
463
421
        else:
464
422
            raise BzrCommandError('bzr pull --revision takes one value.')
465
423
 
466
 
        old_rh = branch_to.revision_history()
467
 
        if tree_to is not None:
468
 
            count = tree_to.pull(branch_from, overwrite, rev_id)
469
 
        else:
470
 
            count = branch_to.pull(branch_from, overwrite, rev_id)
 
424
        old_rh = br_to.revision_history()
 
425
        count = tree_to.pull(br_from, overwrite, rev_id)
 
426
 
 
427
        if br_to.get_parent() is None or remember:
 
428
            br_to.set_parent(location)
471
429
        note('%d revision(s) pulled.' % (count,))
472
430
 
473
431
        if verbose:
474
 
            new_rh = branch_to.revision_history()
 
432
            new_rh = tree_to.branch.revision_history()
475
433
            if old_rh != new_rh:
476
434
                # Something changed
477
435
                from bzrlib.log import show_changed_revisions
478
 
                show_changed_revisions(branch_to, old_rh, new_rh,
479
 
                                       to_file=self.outf)
 
436
                show_changed_revisions(tree_to.branch, old_rh, new_rh)
480
437
 
481
438
 
482
439
class cmd_push(Command):
483
 
    """Update a mirror of this branch.
484
 
    
485
 
    The target branch will not have its working tree populated because this
486
 
    is both expensive, and is not supported on remote file systems.
487
 
    
488
 
    Some smart servers or protocols *may* put the working tree in place in
489
 
    the future.
 
440
    """Push this branch into another branch.
 
441
    
 
442
    The remote branch will not have its working tree populated because this
 
443
    is both expensive, and may not be supported on the remote file system.
 
444
    
 
445
    Some smart servers or protocols *may* put the working tree in place.
 
446
 
 
447
    If there is no default push location set, the first push will set it.
 
448
    After that, you can omit the location to use the default.  To change the
 
449
    default, use --remember.
490
450
 
491
451
    This command only works on branches that have not diverged.  Branches are
492
 
    considered diverged if the destination branch's most recent commit is one
493
 
    that has not been merged (directly or indirectly) by the source branch.
 
452
    considered diverged if the branch being pushed to is not an older version
 
453
    of this branch.
494
454
 
495
455
    If branches have diverged, you can use 'bzr push --overwrite' to replace
496
 
    the other branch completely, discarding its unmerged changes.
 
456
    the other branch completely.
497
457
    
498
458
    If you want to ensure you have the different changes in the other branch,
499
 
    do a merge (see bzr help merge) from the other branch, and commit that.
500
 
    After that you will be able to do a push without '--overwrite'.
501
 
 
502
 
    If there is no default push location set, the first push will set it.
503
 
    After that, you can omit the location to use the default.  To change the
504
 
    default, use --remember. The value will only be saved if the remote
505
 
    location can be accessed.
 
459
    do a merge (see bzr help merge) from the other branch, and commit that
 
460
    before doing a 'push --overwrite'.
506
461
    """
507
 
 
508
 
    takes_options = ['remember', 'overwrite', 'verbose',
 
462
    takes_options = ['remember', 'overwrite', 
509
463
                     Option('create-prefix', 
510
464
                            help='Create the path leading up to the branch '
511
465
                                 'if it does not already exist')]
512
466
    takes_args = ['location?']
513
 
    encoding_type = 'replace'
514
467
 
515
468
    def run(self, location=None, remember=False, overwrite=False,
516
469
            create_prefix=False, verbose=False):
518
471
        # command.
519
472
        from bzrlib.transport import get_transport
520
473
        
521
 
        br_from = Branch.open_containing('.')[0]
522
 
        stored_loc = br_from.get_push_location()
 
474
        tree_from = WorkingTree.open_containing(u'.')[0]
 
475
        br_from = tree_from.branch
 
476
        stored_loc = tree_from.branch.get_push_location()
523
477
        if location is None:
524
478
            if stored_loc is None:
525
479
                raise BzrCommandError("No push location known or specified.")
526
480
            else:
527
 
                display_url = urlutils.unescape_for_display(stored_loc,
528
 
                        self.outf.encoding)
529
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
481
                print "Using saved location: %s" % stored_loc
530
482
                location = stored_loc
531
 
 
532
 
        transport = get_transport(location)
533
 
        location_url = transport.base
534
 
 
535
 
        old_rh = []
536
483
        try:
537
 
            dir_to = bzrdir.BzrDir.open(location_url)
538
 
            br_to = dir_to.open_branch()
 
484
            br_to = Branch.open(location)
539
485
        except NotBranchError:
540
486
            # create a branch.
541
 
            transport = transport.clone('..')
 
487
            transport = get_transport(location).clone('..')
542
488
            if not create_prefix:
543
489
                try:
544
 
                    relurl = transport.relpath(location_url)
545
 
                    mutter('creating directory %s => %s', location_url, relurl)
546
 
                    transport.mkdir(relurl)
 
490
                    transport.mkdir(transport.relpath(location))
547
491
                except NoSuchFile:
548
492
                    raise BzrCommandError("Parent directory of %s "
549
493
                                          "does not exist." % location)
550
494
            else:
551
495
                current = transport.base
552
 
                needed = [(transport, transport.relpath(location_url))]
 
496
                needed = [(transport, transport.relpath(location))]
553
497
                while needed:
554
498
                    try:
555
499
                        transport, relpath = needed[-1]
560
504
                        needed.append((new_transport,
561
505
                                       new_transport.relpath(transport.base)))
562
506
                        if new_transport.base == transport.base:
563
 
                            raise BzrCommandError("Could not create "
 
507
                            raise BzrCommandError("Could not creeate "
564
508
                                                  "path prefix.")
565
 
            dir_to = br_from.bzrdir.clone(location_url,
566
 
                revision_id=br_from.last_revision())
567
 
            br_to = dir_to.open_branch()
568
 
            count = len(br_to.revision_history())
569
 
            # We successfully created the target, remember it
570
 
            if br_from.get_push_location() is None or remember:
571
 
                br_from.set_push_location(br_to.base)
572
 
        else:
573
 
            # We were able to connect to the remote location, so remember it
574
 
            # we don't need to successfully push because of possible divergence.
575
 
            if br_from.get_push_location() is None or remember:
576
 
                br_from.set_push_location(br_to.base)
577
 
            old_rh = br_to.revision_history()
 
509
            br_to = bzrlib.bzrdir.BzrDir.create_branch_convenience(location)
 
510
        old_rh = br_to.revision_history()
 
511
        try:
578
512
            try:
579
 
                try:
580
 
                    tree_to = dir_to.open_workingtree()
581
 
                except errors.NotLocalUrl:
582
 
                    warning('This transport does not update the working '
583
 
                            'tree of: %s' % (br_to.base,))
584
 
                    count = br_to.pull(br_from, overwrite)
585
 
                except NoWorkingTree:
586
 
                    count = br_to.pull(br_from, overwrite)
587
 
                else:
588
 
                    count = tree_to.pull(br_from, overwrite)
589
 
            except DivergedBranches:
590
 
                raise BzrCommandError("These branches have diverged."
591
 
                                      "  Try a merge then push with overwrite.")
 
513
                tree_to = br_to.working_tree()
 
514
            except NoWorkingTree:
 
515
                # TODO: This should be updated for branches which don't have a
 
516
                # working tree, as opposed to ones where we just couldn't 
 
517
                # update the tree.
 
518
                warning('Unable to update the working tree of: %s' % (br_to.base,))
 
519
                count = br_to.pull(br_from, overwrite)
 
520
            else:
 
521
                count = tree_to.pull(br_from, overwrite)
 
522
        except DivergedBranches:
 
523
            raise BzrCommandError("These branches have diverged."
 
524
                                  "  Try a merge then push with overwrite.")
 
525
        if br_from.get_push_location() is None or remember:
 
526
            br_from.set_push_location(location)
592
527
        note('%d revision(s) pushed.' % (count,))
593
528
 
594
529
        if verbose:
596
531
            if old_rh != new_rh:
597
532
                # Something changed
598
533
                from bzrlib.log import show_changed_revisions
599
 
                show_changed_revisions(br_to, old_rh, new_rh,
600
 
                                       to_file=self.outf)
 
534
                show_changed_revisions(br_to, old_rh, new_rh)
601
535
 
602
536
 
603
537
class cmd_branch(Command):
618
552
    aliases = ['get', 'clone']
619
553
 
620
554
    def run(self, from_location, to_location=None, revision=None, basis=None):
621
 
        from bzrlib.transport import get_transport
622
555
        if revision is None:
623
556
            revision = [None]
624
557
        elif len(revision) > 1:
650
583
                name = None
651
584
            else:
652
585
                name = os.path.basename(to_location) + '\n'
653
 
 
654
 
            to_transport = get_transport(to_location)
655
 
            try:
656
 
                to_transport.mkdir('.')
657
 
            except errors.FileExists:
658
 
                raise BzrCommandError('Target directory "%s" already'
659
 
                                      ' exists.' % to_location)
660
 
            except errors.NoSuchFile:
661
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
662
 
                                      to_location)
663
 
            try:
664
 
                # preserve whatever source format we have.
665
 
                dir = br_from.bzrdir.sprout(to_transport.base,
666
 
                        revision_id, basis_dir)
 
586
            try:
 
587
                os.mkdir(to_location)
 
588
            except OSError, e:
 
589
                if e.errno == errno.EEXIST:
 
590
                    raise BzrCommandError('Target directory "%s" already'
 
591
                                          ' exists.' % to_location)
 
592
                if e.errno == errno.ENOENT:
 
593
                    raise BzrCommandError('Parent of "%s" does not exist.' %
 
594
                                          to_location)
 
595
                else:
 
596
                    raise
 
597
            try:
 
598
                dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
667
599
                branch = dir.open_branch()
668
 
            except errors.NoSuchRevision:
669
 
                to_transport.delete_tree('.')
 
600
            except bzrlib.errors.NoSuchRevision:
 
601
                rmtree(to_location)
670
602
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
671
603
                raise BzrCommandError(msg)
672
 
            except errors.UnlistableBranch:
673
 
                osutils.rmtree(to_location)
674
 
                msg = "The branch %s cannot be used as a --basis" % (basis,)
 
604
            except bzrlib.errors.UnlistableBranch:
 
605
                rmtree(to_location)
 
606
                msg = "The branch %s cannot be used as a --basis"
675
607
                raise BzrCommandError(msg)
676
608
            if name:
677
609
                branch.control_files.put_utf8('branch-name', name)
 
610
 
678
611
            note('Branched %d revision(s).' % branch.revno())
679
612
        finally:
680
613
            br_from.unlock()
683
616
class cmd_checkout(Command):
684
617
    """Create a new checkout of an existing branch.
685
618
 
686
 
    If BRANCH_LOCATION is omitted, checkout will reconstitute a working tree for
687
 
    the branch found in '.'. This is useful if you have removed the working tree
688
 
    or if it was never created - i.e. if you pushed the branch to its current
689
 
    location using SFTP.
690
 
    
691
619
    If the TO_LOCATION is omitted, the last component of the BRANCH_LOCATION will
692
620
    be used.  In other words, "checkout ../foo/bar" will attempt to create ./bar.
693
621
 
698
626
 
699
627
    --basis is to speed up checking out from remote branches.  When specified, it
700
628
    uses the inventory and file contents from the basis branch in preference to the
701
 
    branch being checked out.
 
629
    branch being checked out. [Not implemented yet.]
702
630
    """
703
 
    takes_args = ['branch_location?', 'to_location?']
704
 
    takes_options = ['revision', # , 'basis']
705
 
                     Option('lightweight',
706
 
                            help="perform a lightweight checkout. Lightweight "
707
 
                                 "checkouts depend on access to the branch for "
708
 
                                 "every operation. Normal checkouts can perform "
709
 
                                 "common operations like diff and status without "
710
 
                                 "such access, and also support local commits."
711
 
                            ),
712
 
                     ]
713
 
    aliases = ['co']
 
631
    takes_args = ['branch_location', 'to_location?']
 
632
    takes_options = ['revision'] # , 'basis']
714
633
 
715
 
    def run(self, branch_location=None, to_location=None, revision=None, basis=None,
716
 
            lightweight=False):
 
634
    def run(self, branch_location, to_location=None, revision=None, basis=None):
717
635
        if revision is None:
718
636
            revision = [None]
719
637
        elif len(revision) > 1:
720
638
            raise BzrCommandError(
721
639
                'bzr checkout --revision takes exactly 1 revision value')
722
 
        if branch_location is None:
723
 
            branch_location = osutils.getcwd()
724
 
            to_location = branch_location
725
640
        source = Branch.open(branch_location)
726
641
        if len(revision) == 1 and revision[0] is not None:
727
642
            revision_id = revision[0].in_history(source)[1]
729
644
            revision_id = None
730
645
        if to_location is None:
731
646
            to_location = os.path.basename(branch_location.rstrip("/\\"))
732
 
        # if the source and to_location are the same, 
733
 
        # and there is no working tree,
734
 
        # then reconstitute a branch
735
 
        if (osutils.abspath(to_location) == 
736
 
            osutils.abspath(branch_location)):
737
 
            try:
738
 
                source.bzrdir.open_workingtree()
739
 
            except errors.NoWorkingTree:
740
 
                source.bzrdir.create_workingtree()
741
 
                return
742
647
        try:
743
648
            os.mkdir(to_location)
744
649
        except OSError, e:
750
655
                                      to_location)
751
656
            else:
752
657
                raise
753
 
        old_format = bzrdir.BzrDirFormat.get_default_format()
754
 
        bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
755
 
        try:
756
 
            if lightweight:
757
 
                checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
758
 
                branch.BranchReferenceFormat().initialize(checkout, source)
759
 
            else:
760
 
                checkout_branch =  bzrdir.BzrDir.create_branch_convenience(
761
 
                    to_location, force_new_tree=False)
762
 
                checkout = checkout_branch.bzrdir
763
 
                checkout_branch.bind(source)
764
 
                if revision_id is not None:
765
 
                    rh = checkout_branch.revision_history()
766
 
                    checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
767
 
            checkout.create_workingtree(revision_id)
768
 
        finally:
769
 
            bzrdir.BzrDirFormat.set_default_format(old_format)
 
658
        checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
 
659
        bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
 
660
        checkout.create_workingtree(revision_id)
770
661
 
771
662
 
772
663
class cmd_renames(Command):
779
670
 
780
671
    @display_command
781
672
    def run(self, dir=u'.'):
782
 
        from bzrlib.tree import find_renames
783
673
        tree = WorkingTree.open_containing(dir)[0]
784
674
        old_inv = tree.basis_tree().inventory
785
675
        new_inv = tree.read_working_inventory()
786
 
        renames = list(find_renames(old_inv, new_inv))
 
676
 
 
677
        renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
787
678
        renames.sort()
788
679
        for old_name, new_name in renames:
789
 
            self.outf.write("%s => %s\n" % (old_name, new_name))
 
680
            print "%s => %s" % (old_name, new_name)        
790
681
 
791
682
 
792
683
class cmd_update(Command):
793
684
    """Update a tree to have the latest code committed to its branch.
794
685
    
795
686
    This will perform a merge into the working tree, and may generate
796
 
    conflicts. If you have any local changes, you will still 
797
 
    need to commit them after the update for the update to be complete.
798
 
    
799
 
    If you want to discard your local changes, you can just do a 
800
 
    'bzr revert' instead of 'bzr commit' after the update.
 
687
    conflicts. If you have any uncommitted changes, you will still 
 
688
    need to commit them after the update.
801
689
    """
802
690
    takes_args = ['dir?']
803
691
 
805
693
        tree = WorkingTree.open_containing(dir)[0]
806
694
        tree.lock_write()
807
695
        try:
808
 
            last_rev = tree.last_revision() 
809
 
            if last_rev == tree.branch.last_revision():
810
 
                # may be up to date, check master too.
811
 
                master = tree.branch.get_master_branch()
812
 
                if master is None or last_rev == master.last_revision():
813
 
                    revno = tree.branch.revision_id_to_revno(last_rev)
814
 
                    note("Tree is up to date at revision %d." % (revno,))
815
 
                    return 0
 
696
            if tree.last_revision() == tree.branch.last_revision():
 
697
                note("Tree is up to date.")
 
698
                return
816
699
            conflicts = tree.update()
817
 
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
818
 
            note('Updated to revision %d.' % (revno,))
 
700
            note('Updated to revision %d.' %
 
701
                 (tree.branch.revision_id_to_revno(tree.last_revision()),))
819
702
            if conflicts != 0:
820
703
                return 1
821
704
            else:
825
708
 
826
709
 
827
710
class cmd_info(Command):
828
 
    """Show information about a working tree, branch or repository.
829
 
 
830
 
    This command will show all known locations and formats associated to the
831
 
    tree, branch or repository.  Statistical information is included with
832
 
    each report.
833
 
 
834
 
    Branches and working trees will also report any missing revisions.
835
 
    """
836
 
    takes_args = ['location?']
837
 
    takes_options = ['verbose']
838
 
 
 
711
    """Show statistical information about a branch."""
 
712
    takes_args = ['branch?']
 
713
    
839
714
    @display_command
840
 
    def run(self, location=None, verbose=False):
841
 
        from bzrlib.info import show_bzrdir_info
842
 
        show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
843
 
                         verbose=verbose)
 
715
    def run(self, branch=None):
 
716
        import bzrlib.info
 
717
        bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0])
844
718
 
845
719
 
846
720
class cmd_remove(Command):
848
722
 
849
723
    This makes bzr stop tracking changes to a versioned file.  It does
850
724
    not delete the working copy.
851
 
 
852
 
    You can specify one or more files, and/or --new.  If you specify --new,
853
 
    only 'added' files will be removed.  If you specify both, then new files
854
 
    in the specified directories will be removed.  If the directories are
855
 
    also new, they will also be removed.
856
725
    """
857
 
    takes_args = ['file*']
858
 
    takes_options = ['verbose', Option('new', help='remove newly-added files')]
 
726
    takes_args = ['file+']
 
727
    takes_options = ['verbose']
859
728
    aliases = ['rm']
860
 
    encoding_type = 'replace'
861
729
    
862
 
    def run(self, file_list, verbose=False, new=False):
 
730
    def run(self, file_list, verbose=False):
863
731
        tree, file_list = tree_files(file_list)
864
 
        if new is False:
865
 
            if file_list is None:
866
 
                raise BzrCommandError('Specify one or more files to remove, or'
867
 
                                      ' use --new.')
868
 
        else:
869
 
            from bzrlib.delta import compare_trees
870
 
            added = [compare_trees(tree.basis_tree(), tree,
871
 
                                   specific_files=file_list).added]
872
 
            file_list = sorted([f[0] for f in added[0]], reverse=True)
873
 
            if len(file_list) == 0:
874
 
                raise BzrCommandError('No matching files.')
875
 
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
 
732
        tree.remove(file_list, verbose=verbose)
876
733
 
877
734
 
878
735
class cmd_file_id(Command):
882
739
    same through all revisions where the file exists, even when it is
883
740
    moved or renamed.
884
741
    """
885
 
 
886
742
    hidden = True
887
743
    takes_args = ['filename']
888
 
 
889
744
    @display_command
890
745
    def run(self, filename):
891
746
        tree, relpath = WorkingTree.open_containing(filename)
893
748
        if i == None:
894
749
            raise BzrError("%r is not a versioned file" % filename)
895
750
        else:
896
 
            self.outf.write(i + '\n')
 
751
            print i
897
752
 
898
753
 
899
754
class cmd_file_path(Command):
900
755
    """Print path of file_ids to a file or directory.
901
756
 
902
757
    This prints one line for each directory down to the target,
903
 
    starting at the branch root.
904
 
    """
905
 
 
 
758
    starting at the branch root."""
906
759
    hidden = True
907
760
    takes_args = ['filename']
908
 
 
909
761
    @display_command
910
762
    def run(self, filename):
911
763
        tree, relpath = WorkingTree.open_containing(filename)
914
766
        if fid == None:
915
767
            raise BzrError("%r is not a versioned file" % filename)
916
768
        for fip in inv.get_idpath(fid):
917
 
            self.outf.write(fip + '\n')
918
 
 
919
 
 
920
 
class cmd_reconcile(Command):
921
 
    """Reconcile bzr metadata in a branch.
922
 
 
923
 
    This can correct data mismatches that may have been caused by
924
 
    previous ghost operations or bzr upgrades. You should only
925
 
    need to run this command if 'bzr check' or a bzr developer 
926
 
    advises you to run it.
927
 
 
928
 
    If a second branch is provided, cross-branch reconciliation is
929
 
    also attempted, which will check that data like the tree root
930
 
    id which was not present in very early bzr versions is represented
931
 
    correctly in both branches.
932
 
 
933
 
    At the same time it is run it may recompress data resulting in 
934
 
    a potential saving in disk space or performance gain.
935
 
 
936
 
    The branch *MUST* be on a listable system such as local disk or sftp.
937
 
    """
938
 
    takes_args = ['branch?']
939
 
 
940
 
    def run(self, branch="."):
941
 
        from bzrlib.reconcile import reconcile
942
 
        dir = bzrdir.BzrDir.open(branch)
943
 
        reconcile(dir)
 
769
            print fip
944
770
 
945
771
 
946
772
class cmd_revision_history(Command):
947
 
    """Display the list of revision ids on a branch."""
948
 
    takes_args = ['location?']
949
 
 
 
773
    """Display list of revision ids on this branch."""
950
774
    hidden = True
951
 
 
952
775
    @display_command
953
 
    def run(self, location="."):
954
 
        branch = Branch.open_containing(location)[0]
955
 
        for revid in branch.revision_history():
956
 
            self.outf.write(revid)
957
 
            self.outf.write('\n')
 
776
    def run(self):
 
777
        branch = WorkingTree.open_containing(u'.')[0].branch
 
778
        for patchid in branch.revision_history():
 
779
            print patchid
958
780
 
959
781
 
960
782
class cmd_ancestry(Command):
961
783
    """List all revisions merged into this branch."""
962
 
    takes_args = ['location?']
963
 
 
964
784
    hidden = True
965
 
 
966
785
    @display_command
967
 
    def run(self, location="."):
968
 
        try:
969
 
            wt = WorkingTree.open_containing(location)[0]
970
 
        except errors.NoWorkingTree:
971
 
            b = Branch.open(location)
972
 
            last_revision = b.last_revision()
973
 
        else:
974
 
            b = wt.branch
975
 
            last_revision = wt.last_revision()
976
 
 
977
 
        revision_ids = b.repository.get_ancestry(last_revision)
978
 
        assert revision_ids[0] == None
979
 
        revision_ids.pop(0)
980
 
        for revision_id in revision_ids:
981
 
            self.outf.write(revision_id + '\n')
 
786
    def run(self):
 
787
        tree = WorkingTree.open_containing(u'.')[0]
 
788
        b = tree.branch
 
789
        # FIXME. should be tree.last_revision
 
790
        for revision_id in b.repository.get_ancestry(b.last_revision()):
 
791
            print revision_id
982
792
 
983
793
 
984
794
class cmd_init(Command):
987
797
    Use this to create an empty branch, or before importing an
988
798
    existing project.
989
799
 
990
 
    If there is a repository in a parent directory of the location, then 
991
 
    the history of the branch will be stored in the repository.  Otherwise
992
 
    init creates a standalone branch which carries its own history in 
993
 
    .bzr.
994
 
 
995
 
    If there is already a branch at the location but it has no working tree,
996
 
    the tree can be populated with 'bzr checkout'.
997
 
 
998
800
    Recipe for importing a tree of files:
999
801
        cd ~/project
1000
802
        bzr init
1003
805
        bzr commit -m 'imported project'
1004
806
    """
1005
807
    takes_args = ['location?']
1006
 
    takes_options = [
1007
 
                     Option('format', 
1008
 
                            help='Specify a format for this branch. Current'
1009
 
                                 ' formats are: default, knit, metaweave and'
1010
 
                                 ' weave. Default is knit; metaweave and'
1011
 
                                 ' weave are deprecated',
1012
 
                            type=get_format_type),
1013
 
                     ]
1014
 
    def run(self, location=None, format=None):
1015
 
        if format is None:
1016
 
            format = get_format_type('default')
 
808
    def run(self, location=None):
 
809
        from bzrlib.branch import Branch
1017
810
        if location is None:
1018
811
            location = u'.'
1019
812
        else:
1024
817
            # locations if the user supplies an extended path
1025
818
            if not os.path.exists(location):
1026
819
                os.mkdir(location)
1027
 
        try:
1028
 
            existing_bzrdir = bzrdir.BzrDir.open(location)
1029
 
        except NotBranchError:
1030
 
            # really a NotBzrDir error...
1031
 
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1032
 
        else:
1033
 
            if existing_bzrdir.has_branch():
1034
 
                if existing_bzrdir.has_workingtree():
1035
 
                    raise errors.AlreadyBranchError(location)
1036
 
                else:
1037
 
                    raise errors.BranchExistsWithoutWorkingTree(location)
1038
 
            else:
1039
 
                existing_bzrdir.create_branch()
1040
 
                existing_bzrdir.create_workingtree()
1041
 
 
1042
 
 
1043
 
class cmd_init_repository(Command):
1044
 
    """Create a shared repository to hold branches.
1045
 
 
1046
 
    New branches created under the repository directory will store their revisions
1047
 
    in the repository, not in the branch directory, if the branch format supports
1048
 
    shared storage.
1049
 
 
1050
 
    example:
1051
 
        bzr init-repo repo
1052
 
        bzr init repo/trunk
1053
 
        bzr checkout --lightweight repo/trunk trunk-checkout
1054
 
        cd trunk-checkout
1055
 
        (add files here)
1056
 
    """
1057
 
    takes_args = ["location"] 
1058
 
    takes_options = [Option('format', 
1059
 
                            help='Specify a format for this repository.'
1060
 
                                 ' Current formats are: default, knit,'
1061
 
                                 ' metaweave and weave. Default is knit;'
1062
 
                                 ' metaweave and weave are deprecated',
1063
 
                            type=get_format_type),
1064
 
                     Option('trees',
1065
 
                             help='Allows branches in repository to have'
1066
 
                             ' a working tree')]
1067
 
    aliases = ["init-repo"]
1068
 
    def run(self, location, format=None, trees=False):
1069
 
        from bzrlib.transport import get_transport
1070
 
        if format is None:
1071
 
            format = get_format_type('default')
1072
 
        transport = get_transport(location)
1073
 
        if not transport.has('.'):
1074
 
            transport.mkdir('')
1075
 
        newdir = format.initialize_on_transport(transport)
1076
 
        repo = newdir.create_repository(shared=True)
1077
 
        repo.set_make_working_trees(trees)
 
820
        bzrdir.BzrDir.create_standalone_workingtree(location)
1078
821
 
1079
822
 
1080
823
class cmd_diff(Command):
1081
 
    """Show differences in the working tree or between revisions.
 
824
    """Show differences in working tree.
1082
825
    
1083
826
    If files are listed, only the changes in those files are listed.
1084
827
    Otherwise, all changes for the tree are listed.
1085
828
 
1086
 
    "bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1087
 
    produces patches suitable for "patch -p1".
1088
 
 
1089
829
    examples:
1090
830
        bzr diff
1091
 
            Shows the difference in the working tree versus the last commit
1092
831
        bzr diff -r1
1093
 
            Difference between the working tree and revision 1
1094
832
        bzr diff -r1..2
1095
 
            Difference between revision 2 and revision 1
1096
 
        bzr diff --diff-prefix old/:new/
1097
 
            Same as 'bzr diff' but prefix paths with old/ and new/
1098
 
        bzr diff bzr.mine bzr.dev
1099
 
            Show the differences between the two working trees
1100
 
        bzr diff foo.c
1101
 
            Show just the differences for 'foo.c'
1102
833
    """
 
834
    # TODO: Allow diff across branches.
1103
835
    # TODO: Option to use external diff command; could be GNU diff, wdiff,
1104
836
    #       or a graphical diff.
1105
837
 
1106
838
    # TODO: Python difflib is not exactly the same as unidiff; should
1107
839
    #       either fix it up or prefer to use an external diff.
1108
840
 
 
841
    # TODO: If a directory is given, diff everything under that.
 
842
 
1109
843
    # TODO: Selected-file diff is inefficient and doesn't show you
1110
844
    #       deleted files.
1111
845
 
1112
846
    # TODO: This probably handles non-Unix newlines poorly.
1113
847
    
1114
848
    takes_args = ['file*']
1115
 
    takes_options = ['revision', 'diff-options', 'prefix']
 
849
    takes_options = ['revision', 'diff-options']
1116
850
    aliases = ['di', 'dif']
1117
 
    encoding_type = 'exact'
1118
851
 
1119
852
    @display_command
1120
 
    def run(self, revision=None, file_list=None, diff_options=None,
1121
 
            prefix=None):
 
853
    def run(self, revision=None, file_list=None, diff_options=None):
1122
854
        from bzrlib.diff import diff_cmd_helper, show_diff_trees
1123
 
 
1124
 
        if (prefix is None) or (prefix == '0'):
1125
 
            # diff -p0 format
1126
 
            old_label = ''
1127
 
            new_label = ''
1128
 
        elif prefix == '1':
1129
 
            old_label = 'old/'
1130
 
            new_label = 'new/'
1131
 
        else:
1132
 
            if not ':' in prefix:
1133
 
                 raise BzrError("--diff-prefix expects two values separated by a colon")
1134
 
            old_label, new_label = prefix.split(":")
1135
 
        
1136
855
        try:
1137
856
            tree1, file_list = internal_tree_files(file_list)
1138
857
            tree2 = None
1148
867
                # FIXME diff those two files. rbc 20051123
1149
868
                raise BzrCommandError("Files are in different branches")
1150
869
            file_list = None
1151
 
        except NotBranchError:
1152
 
            # Don't raise an error when bzr diff is called from
1153
 
            # outside a working tree.
1154
 
            tree1, tree2 = None, None
1155
870
        if revision is not None:
1156
871
            if tree2 is not None:
1157
872
                raise BzrCommandError("Can't specify -r with two branches")
1158
873
            if (len(revision) == 1) or (revision[1].spec is None):
1159
874
                return diff_cmd_helper(tree1, file_list, diff_options,
1160
 
                                       revision[0], 
1161
 
                                       old_label=old_label, new_label=new_label)
 
875
                                       revision[0])
1162
876
            elif len(revision) == 2:
1163
877
                return diff_cmd_helper(tree1, file_list, diff_options,
1164
 
                                       revision[0], revision[1],
1165
 
                                       old_label=old_label, new_label=new_label)
 
878
                                       revision[0], revision[1])
1166
879
            else:
1167
880
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1168
881
        else:
1169
882
            if tree2 is not None:
1170
883
                return show_diff_trees(tree1, tree2, sys.stdout, 
1171
884
                                       specific_files=file_list,
1172
 
                                       external_diff_options=diff_options,
1173
 
                                       old_label=old_label, new_label=new_label)
 
885
                                       external_diff_options=diff_options)
1174
886
            else:
1175
 
                return diff_cmd_helper(tree1, file_list, diff_options,
1176
 
                                       old_label=old_label, new_label=new_label)
 
887
                return diff_cmd_helper(tree1, file_list, diff_options)
1177
888
 
1178
889
 
1179
890
class cmd_deleted(Command):
1185
896
    # directories with readdir, rather than stating each one.  Same
1186
897
    # level of effort but possibly much less IO.  (Or possibly not,
1187
898
    # if the directories are very large...)
1188
 
    takes_options = ['show-ids']
1189
 
 
1190
899
    @display_command
1191
900
    def run(self, show_ids=False):
1192
901
        tree = WorkingTree.open_containing(u'.')[0]
1193
902
        old = tree.basis_tree()
1194
903
        for path, ie in old.inventory.iter_entries():
1195
904
            if not tree.has_id(ie.file_id):
1196
 
                self.outf.write(path)
1197
905
                if show_ids:
1198
 
                    self.outf.write(' ')
1199
 
                    self.outf.write(ie.file_id)
1200
 
                self.outf.write('\n')
 
906
                    print '%-50s %s' % (path, ie.file_id)
 
907
                else:
 
908
                    print path
1201
909
 
1202
910
 
1203
911
class cmd_modified(Command):
1211
919
        td = compare_trees(tree.basis_tree(), tree)
1212
920
 
1213
921
        for path, id, kind, text_modified, meta_modified in td.modified:
1214
 
            self.outf.write(path + '\n')
 
922
            print path
 
923
 
1215
924
 
1216
925
 
1217
926
class cmd_added(Command):
1226
935
            if file_id in basis_inv:
1227
936
                continue
1228
937
            path = inv.id2path(file_id)
1229
 
            if not os.access(osutils.abspath(path), os.F_OK):
 
938
            if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
1230
939
                continue
1231
 
            self.outf.write(path + '\n')
1232
 
 
 
940
            print path
 
941
                
 
942
        
1233
943
 
1234
944
class cmd_root(Command):
1235
945
    """Show the tree root directory.
1241
951
    def run(self, filename=None):
1242
952
        """Print the branch root."""
1243
953
        tree = WorkingTree.open_containing(filename)[0]
1244
 
        self.outf.write(tree.basedir + '\n')
 
954
        print tree.basedir
1245
955
 
1246
956
 
1247
957
class cmd_log(Command):
1248
 
    """Show log of a branch, file, or directory.
1249
 
 
1250
 
    By default show the log of the branch containing the working directory.
 
958
    """Show log of this branch.
1251
959
 
1252
960
    To request a range of logs, you can use the command -r begin..end
1253
961
    -r revision requests a specific revision, -r ..end or -r begin.. are
1254
962
    also valid.
1255
 
 
1256
 
    examples:
1257
 
        bzr log
1258
 
        bzr log foo.c
1259
 
        bzr log -r -10.. http://server/branch
1260
963
    """
1261
964
 
1262
965
    # TODO: Make --revision support uuid: and hash: [future tag:] notation.
1263
966
 
1264
 
    takes_args = ['location?']
 
967
    takes_args = ['filename?']
1265
968
    takes_options = [Option('forward', 
1266
969
                            help='show from oldest to newest'),
1267
 
                     'timezone', 
1268
 
                     Option('verbose', 
1269
 
                             help='show files changed in each revision'),
 
970
                     'timezone', 'verbose', 
1270
971
                     'show-ids', 'revision',
1271
972
                     'log-format',
1272
973
                     'line', 'long', 
1275
976
                            type=str),
1276
977
                     'short',
1277
978
                     ]
1278
 
    encoding_type = 'replace'
1279
 
 
1280
979
    @display_command
1281
 
    def run(self, location=None, timezone='original',
 
980
    def run(self, filename=None, timezone='original',
1282
981
            verbose=False,
1283
982
            show_ids=False,
1284
983
            forward=False,
1289
988
            short=False,
1290
989
            line=False):
1291
990
        from bzrlib.log import log_formatter, show_log
 
991
        import codecs
1292
992
        assert message is None or isinstance(message, basestring), \
1293
993
            "invalid message argument %r" % message
1294
994
        direction = (forward and 'forward') or 'reverse'
1295
995
        
1296
996
        # log everything
1297
997
        file_id = None
1298
 
        if location:
 
998
        if filename:
1299
999
            # find the file id to log:
1300
1000
 
1301
 
            dir, fp = bzrdir.BzrDir.open_containing(location)
 
1001
            dir, fp = bzrdir.BzrDir.open_containing(filename)
1302
1002
            b = dir.open_branch()
1303
1003
            if fp != '':
1304
1004
                try:
1340
1040
        if rev1 > rev2:
1341
1041
            (rev2, rev1) = (rev1, rev2)
1342
1042
 
 
1043
        mutter('encoding log as %r', bzrlib.user_encoding)
 
1044
 
 
1045
        # use 'replace' so that we don't abort if trying to write out
 
1046
        # in e.g. the default C locale.
 
1047
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
 
1048
 
1343
1049
        if (log_format == None):
1344
 
            default = b.get_config().log_format()
1345
 
            log_format = get_log_format(long=long, short=short, line=line, 
1346
 
                                        default=default)
 
1050
            default = bzrlib.config.BranchConfig(b).log_format()
 
1051
            log_format = get_log_format(long=long, short=short, line=line, default=default)
 
1052
 
1347
1053
        lf = log_formatter(log_format,
1348
1054
                           show_ids=show_ids,
1349
 
                           to_file=self.outf,
 
1055
                           to_file=outf,
1350
1056
                           show_timezone=timezone)
1351
1057
 
1352
1058
        show_log(b,
1373
1079
class cmd_touching_revisions(Command):
1374
1080
    """Return revision-ids which affected a particular file.
1375
1081
 
1376
 
    A more user-friendly interface is "bzr log FILE".
1377
 
    """
1378
 
 
 
1082
    A more user-friendly interface is "bzr log FILE"."""
1379
1083
    hidden = True
1380
1084
    takes_args = ["filename"]
1381
 
 
1382
1085
    @display_command
1383
1086
    def run(self, filename):
1384
1087
        tree, relpath = WorkingTree.open_containing(filename)
1385
1088
        b = tree.branch
1386
1089
        inv = tree.read_working_inventory()
1387
1090
        file_id = inv.path2id(relpath)
1388
 
        for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1389
 
            self.outf.write("%6d %s\n" % (revno, what))
 
1091
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
 
1092
            print "%6d %s" % (revno, what)
1390
1093
 
1391
1094
 
1392
1095
class cmd_ls(Command):
1425
1128
        if revision is not None:
1426
1129
            tree = tree.branch.repository.revision_tree(
1427
1130
                revision[0].in_history(tree.branch).rev_id)
1428
 
 
1429
1131
        for fp, fc, kind, fid, entry in tree.list_files():
1430
1132
            if fp.startswith(relpath):
1431
1133
                fp = fp[len(relpath):]
1435
1137
                    continue
1436
1138
                if verbose:
1437
1139
                    kindch = entry.kind_character()
1438
 
                    self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
 
1140
                    print '%-8s %s%s' % (fc, fp, kindch)
1439
1141
                elif null:
1440
 
                    self.outf.write(fp + '\0')
1441
 
                    self.outf.flush()
 
1142
                    sys.stdout.write(fp)
 
1143
                    sys.stdout.write('\0')
 
1144
                    sys.stdout.flush()
1442
1145
                else:
1443
 
                    self.outf.write(fp + '\n')
 
1146
                    print fp
1444
1147
 
1445
1148
 
1446
1149
class cmd_unknowns(Command):
1447
1150
    """List unknown files."""
1448
1151
    @display_command
1449
1152
    def run(self):
 
1153
        from bzrlib.osutils import quotefn
1450
1154
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
1451
 
            self.outf.write(osutils.quotefn(f) + '\n')
 
1155
            print quotefn(f)
1452
1156
 
1453
1157
 
1454
1158
class cmd_ignore(Command):
1470
1174
        bzr ignore '*.class'
1471
1175
    """
1472
1176
    # TODO: Complain if the filename is absolute
1473
 
    takes_args = ['name_pattern?']
1474
 
    takes_options = [
1475
 
                     Option('old-default-rules',
1476
 
                            help='Out the ignore rules bzr < 0.9 always used.')
1477
 
                     ]
 
1177
    takes_args = ['name_pattern']
1478
1178
    
1479
 
    def run(self, name_pattern=None, old_default_rules=None):
 
1179
    def run(self, name_pattern):
1480
1180
        from bzrlib.atomicfile import AtomicFile
1481
 
        if old_default_rules is not None:
1482
 
            # dump the rules and exit
1483
 
            for pattern in bzrlib.DEFAULT_IGNORE:
1484
 
                print pattern
1485
 
            return
1486
 
        if name_pattern is None:
1487
 
            raise BzrCommandError("ignore requires a NAME_PATTERN")
 
1181
        import os.path
 
1182
 
1488
1183
        tree, relpath = WorkingTree.open_containing(u'.')
1489
1184
        ifn = tree.abspath('.bzrignore')
 
1185
 
1490
1186
        if os.path.exists(ifn):
1491
1187
            f = open(ifn, 'rt')
1492
1188
            try:
1503
1199
            igns += '\n'
1504
1200
        igns += name_pattern + '\n'
1505
1201
 
1506
 
        f = AtomicFile(ifn, 'wt')
1507
1202
        try:
 
1203
            f = AtomicFile(ifn, 'wt')
1508
1204
            f.write(igns.encode('utf-8'))
1509
1205
            f.commit()
1510
1206
        finally:
1577
1273
    takes_args = ['dest']
1578
1274
    takes_options = ['revision', 'format', 'root']
1579
1275
    def run(self, dest, revision=None, format=None, root=None):
 
1276
        import os.path
1580
1277
        from bzrlib.export import export
1581
1278
        tree = WorkingTree.open_containing(u'.')[0]
1582
1279
        b = tree.branch
1625
1322
    hidden = True    
1626
1323
    @display_command
1627
1324
    def run(self):
1628
 
        print osutils.local_time_offset()
 
1325
        print bzrlib.osutils.local_time_offset()
1629
1326
 
1630
1327
 
1631
1328
 
1661
1358
                     Option('strict',
1662
1359
                            help="refuse to commit if there are unknown "
1663
1360
                            "files in the working tree."),
1664
 
                     Option('local',
1665
 
                            help="perform a local only commit in a bound "
1666
 
                                 "branch. Such commits are not pushed to "
1667
 
                                 "the master branch until a normal commit "
1668
 
                                 "is performed."
1669
 
                            ),
1670
1361
                     ]
1671
1362
    aliases = ['ci', 'checkin']
1672
1363
 
1673
1364
    def run(self, message=None, file=None, verbose=True, selected_list=None,
1674
 
            unchanged=False, strict=False, local=False):
1675
 
        from bzrlib.commit import (NullCommitReporter, ReportCommitToLog)
 
1365
            unchanged=False, strict=False):
1676
1366
        from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1677
1367
                StrictCommitFailed)
1678
1368
        from bzrlib.msgeditor import edit_commit_message, \
1679
1369
                make_commit_message_template
1680
1370
        from tempfile import TemporaryFile
 
1371
        import codecs
1681
1372
 
1682
1373
        # TODO: Need a blackbox test for invoking the external editor; may be
1683
1374
        # slightly problematic to run this cross-platform.
1688
1379
        # TODO: if the commit *does* happen to fail, then save the commit 
1689
1380
        # message to a temporary file where it can be recovered
1690
1381
        tree, selected_list = tree_files(selected_list)
1691
 
        if selected_list == ['']:
1692
 
            # workaround - commit of root of tree should be exactly the same
1693
 
            # as just default commit in that tree, and succeed even though
1694
 
            # selected-file merge commit is not done yet
1695
 
            selected_list = []
1696
 
 
1697
 
        if local and not tree.branch.get_bound_location():
1698
 
            raise errors.LocalRequiresBoundBranch()
1699
1382
        if message is None and not file:
1700
1383
            template = make_commit_message_template(tree, selected_list)
1701
1384
            message = edit_commit_message(template)
1706
1389
            raise BzrCommandError("please specify either --message or --file")
1707
1390
        
1708
1391
        if file:
 
1392
            import codecs
1709
1393
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1710
1394
 
1711
1395
        if message == "":
1712
 
            raise BzrCommandError("empty commit message specified")
1713
 
        
1714
 
        if verbose:
1715
 
            reporter = ReportCommitToLog()
1716
 
        else:
1717
 
            reporter = NullCommitReporter()
1718
 
        
 
1396
                raise BzrCommandError("empty commit message specified")
 
1397
            
1719
1398
        try:
1720
1399
            tree.commit(message, specific_files=selected_list,
1721
 
                        allow_pointless=unchanged, strict=strict, local=local,
1722
 
                        reporter=reporter)
 
1400
                        allow_pointless=unchanged, strict=strict)
1723
1401
        except PointlessCommit:
1724
1402
            # FIXME: This should really happen before the file is read in;
1725
1403
            # perhaps prepare the commit; get the message; then actually commit
1726
 
            raise BzrCommandError("no changes to commit."
1727
 
                                  " use --unchanged to commit anyhow")
 
1404
            raise BzrCommandError("no changes to commit",
 
1405
                                  ["use --unchanged to commit anyhow"])
1728
1406
        except ConflictsInTree:
1729
1407
            raise BzrCommandError("Conflicts detected in working tree.  "
1730
1408
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1731
1409
        except StrictCommitFailed:
1732
1410
            raise BzrCommandError("Commit refused because there are unknown "
1733
1411
                                  "files in the working tree.")
1734
 
        except errors.BoundBranchOutOfDate, e:
1735
 
            raise BzrCommandError(str(e)
1736
 
                                  + ' Either unbind, update, or'
1737
 
                                    ' pass --local to commit.')
 
1412
        note('Committed revision %d.' % (tree.branch.revno(),))
1738
1413
 
1739
1414
 
1740
1415
class cmd_check(Command):
1775
1450
            c.write()
1776
1451
 
1777
1452
 
 
1453
def get_format_type(typestring):
 
1454
    """Parse and return a format specifier."""
 
1455
    if typestring == "metadir":
 
1456
        return bzrdir.BzrDirMetaFormat1()
 
1457
    if typestring == "knit":
 
1458
        format = bzrdir.BzrDirMetaFormat1()
 
1459
        format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
 
1460
        return format
 
1461
    msg = "No known bzr-dir format %s. Supported types are: metadir\n" %\
 
1462
        (typestring)
 
1463
    raise BzrCommandError(msg)
 
1464
 
 
1465
 
1778
1466
class cmd_upgrade(Command):
1779
1467
    """Upgrade branch storage to current format.
1780
1468
 
1785
1473
    takes_args = ['url?']
1786
1474
    takes_options = [
1787
1475
                     Option('format', 
1788
 
                            help='Upgrade to a specific format. Current formats'
1789
 
                                 ' are: default, knit, metaweave and weave.'
1790
 
                                 ' Default is knit; metaweave and weave are'
1791
 
                                 ' deprecated',
 
1476
                            help='Upgrade to a specific format rather than the'
 
1477
                                 ' current default format. Currently this '
 
1478
                                 ' option only accepts =metadir',
1792
1479
                            type=get_format_type),
1793
1480
                    ]
1794
1481
 
1795
1482
 
1796
1483
    def run(self, url='.', format=None):
1797
1484
        from bzrlib.upgrade import upgrade
1798
 
        if format is None:
1799
 
            format = get_format_type('default')
1800
1485
        upgrade(url, format)
1801
1486
 
1802
1487
 
1803
1488
class cmd_whoami(Command):
1804
 
    """Show or set bzr user id.
1805
 
    
1806
 
    examples:
1807
 
        bzr whoami --email
1808
 
        bzr whoami 'Frank Chu <fchu@example.com>'
1809
 
    """
1810
 
    takes_options = [ Option('email',
1811
 
                             help='display email address only'),
1812
 
                      Option('branch',
1813
 
                             help='set identity for the current branch instead of '
1814
 
                                  'globally'),
1815
 
                    ]
1816
 
    takes_args = ['name?']
1817
 
    encoding_type = 'replace'
 
1489
    """Show bzr user id."""
 
1490
    takes_options = ['email']
1818
1491
    
1819
1492
    @display_command
1820
 
    def run(self, email=False, branch=False, name=None):
1821
 
        if name is None:
1822
 
            # use branch if we're inside one; otherwise global config
1823
 
            try:
1824
 
                c = Branch.open_containing('.')[0].get_config()
1825
 
            except NotBranchError:
1826
 
                c = config.GlobalConfig()
1827
 
            if email:
1828
 
                self.outf.write(c.user_email() + '\n')
1829
 
            else:
1830
 
                self.outf.write(c.username() + '\n')
1831
 
            return
1832
 
 
1833
 
        # display a warning if an email address isn't included in the given name.
 
1493
    def run(self, email=False):
1834
1494
        try:
1835
 
            config.extract_email_address(name)
1836
 
        except BzrError, e:
1837
 
            warning('"%s" does not seem to contain an email address.  '
1838
 
                    'This is allowed, but not recommended.', name)
 
1495
            b = WorkingTree.open_containing(u'.')[0].branch
 
1496
            config = bzrlib.config.BranchConfig(b)
 
1497
        except NotBranchError:
 
1498
            config = bzrlib.config.GlobalConfig()
1839
1499
        
1840
 
        # use global config unless --branch given
1841
 
        if branch:
1842
 
            c = Branch.open_containing('.')[0].get_config()
 
1500
        if email:
 
1501
            print config.user_email()
1843
1502
        else:
1844
 
            c = config.GlobalConfig()
1845
 
        c.set_user_option('email', name)
 
1503
            print config.username()
1846
1504
 
1847
1505
 
1848
1506
class cmd_nick(Command):
1896
1554
        if typestring == "memory":
1897
1555
            from bzrlib.transport.memory import MemoryServer
1898
1556
            return MemoryServer
1899
 
        if typestring == "fakenfs":
1900
 
            from bzrlib.transport.fakenfs import FakeNFSServer
1901
 
            return FakeNFSServer
1902
1557
        msg = "No known transport type %s. Supported types are: sftp\n" %\
1903
1558
            (typestring)
1904
1559
        raise BzrCommandError(msg)
1913
1568
                            help='Use a different transport by default '
1914
1569
                                 'throughout the test suite.',
1915
1570
                            type=get_transport_type),
1916
 
                     Option('benchmark', help='run the bzr bencharks.'),
1917
 
                     Option('lsprof-timed',
1918
 
                            help='generate lsprof output for benchmarked'
1919
 
                                 ' sections of code.'),
1920
 
                     ]
 
1571
                    ]
1921
1572
 
1922
 
    def run(self, testspecs_list=None, verbose=None, one=False,
1923
 
            keep_output=False, transport=None, benchmark=None,
1924
 
            lsprof_timed=None):
 
1573
    def run(self, testspecs_list=None, verbose=False, one=False,
 
1574
            keep_output=False, transport=None):
1925
1575
        import bzrlib.ui
1926
1576
        from bzrlib.tests import selftest
1927
 
        import bzrlib.benchmarks as benchmarks
1928
1577
        # we don't want progress meters from the tests to go to the
1929
1578
        # real output; and we don't want log messages cluttering up
1930
1579
        # the real logs.
1931
 
        save_ui = ui.ui_factory
1932
 
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1933
 
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1934
 
        print
1935
 
        info('running tests...')
 
1580
        save_ui = bzrlib.ui.ui_factory
 
1581
        bzrlib.trace.info('running tests...')
1936
1582
        try:
1937
 
            ui.ui_factory = ui.SilentUIFactory()
 
1583
            bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1938
1584
            if testspecs_list is not None:
1939
1585
                pattern = '|'.join(testspecs_list)
1940
1586
            else:
1941
1587
                pattern = ".*"
1942
 
            if benchmark:
1943
 
                test_suite_factory = benchmarks.test_suite
1944
 
                if verbose is None:
1945
 
                    verbose = True
1946
 
            else:
1947
 
                test_suite_factory = None
1948
 
                if verbose is None:
1949
 
                    verbose = False
1950
1588
            result = selftest(verbose=verbose, 
1951
1589
                              pattern=pattern,
1952
1590
                              stop_on_failure=one, 
1953
1591
                              keep_output=keep_output,
1954
 
                              transport=transport,
1955
 
                              test_suite_factory=test_suite_factory,
1956
 
                              lsprof_timed=lsprof_timed)
 
1592
                              transport=transport)
1957
1593
            if result:
1958
 
                info('tests passed')
 
1594
                bzrlib.trace.info('tests passed')
1959
1595
            else:
1960
 
                info('tests failed')
 
1596
                bzrlib.trace.info('tests failed')
1961
1597
            return int(not result)
1962
1598
        finally:
1963
 
            ui.ui_factory = save_ui
 
1599
            bzrlib.ui.ui_factory = save_ui
1964
1600
 
1965
1601
 
1966
1602
def _get_bzr_branch():
1967
1603
    """If bzr is run from a branch, return Branch or None"""
 
1604
    import bzrlib.errors
 
1605
    from bzrlib.branch import Branch
 
1606
    from bzrlib.osutils import abspath
1968
1607
    from os.path import dirname
1969
1608
    
1970
1609
    try:
1971
 
        branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
 
1610
        branch = Branch.open(dirname(abspath(dirname(__file__))))
1972
1611
        return branch
1973
 
    except errors.BzrError:
 
1612
    except bzrlib.errors.BzrError:
1974
1613
        return None
1975
1614
    
1976
1615
 
1977
1616
def show_version():
1978
 
    import bzrlib
1979
1617
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
1980
1618
    # is bzrlib itself in a branch?
1981
1619
    branch = _get_bzr_branch()
1986
1624
        print "  nick: %s" % (branch.nick,)
1987
1625
        if rh:
1988
1626
            print "  revid: %s" % (rh[-1],)
1989
 
    print "Using python interpreter:", sys.executable
1990
 
    import site
1991
 
    print "Using python standard library:", os.path.dirname(site.__file__)
1992
 
    print "Using bzrlib:",
1993
 
    if len(bzrlib.__path__) > 1:
1994
 
        # print repr, which is a good enough way of making it clear it's
1995
 
        # more than one element (eg ['/foo/bar', '/foo/bzr'])
1996
 
        print repr(bzrlib.__path__)
1997
 
    else:
1998
 
        print bzrlib.__path__[0]
1999
 
 
2000
 
    print
2001
1627
    print bzrlib.__copyright__
2002
 
    print "http://bazaar-vcs.org/"
 
1628
    print "http://bazaar-ng.org/"
2003
1629
    print
2004
1630
    print "bzr comes with ABSOLUTELY NO WARRANTY.  bzr is free software, and"
2005
1631
    print "you may use, modify and redistribute it under the terms of the GNU"
2047
1673
        base_rev_id = common_ancestor(last1, last2, source)
2048
1674
 
2049
1675
        print 'merge base is revision %s' % base_rev_id
 
1676
        
 
1677
        return
 
1678
 
 
1679
        if base_revno is None:
 
1680
            raise bzrlib.errors.UnrelatedBranches()
 
1681
 
 
1682
        print ' r%-6d in %s' % (base_revno, branch)
 
1683
 
 
1684
        other_revno = branch2.revision_id_to_revno(base_revid)
 
1685
        
 
1686
        print ' r%-6d in %s' % (other_revno, other)
 
1687
 
2050
1688
 
2051
1689
 
2052
1690
class cmd_merge(Command):
2053
1691
    """Perform a three-way merge.
2054
1692
    
2055
 
    The branch is the branch you will merge from.  By default, it will merge
2056
 
    the latest revision.  If you specify a revision, that revision will be
2057
 
    merged.  If you specify two revisions, the first will be used as a BASE,
2058
 
    and the second one as OTHER.  Revision numbers are always relative to the
2059
 
    specified branch.
 
1693
    The branch is the branch you will merge from.  By default, it will
 
1694
    merge the latest revision.  If you specify a revision, that
 
1695
    revision will be merged.  If you specify two revisions, the first
 
1696
    will be used as a BASE, and the second one as OTHER.  Revision
 
1697
    numbers are always relative to the specified branch.
2060
1698
 
2061
 
    By default, bzr will try to merge in all new work from the other
 
1699
    By default bzr will try to merge in all new work from the other
2062
1700
    branch, automatically determining an appropriate base.  If this
2063
1701
    fails, you may need to give an explicit base.
2064
1702
    
2065
 
    Merge will do its best to combine the changes in two branches, but there
2066
 
    are some kinds of problems only a human can fix.  When it encounters those,
2067
 
    it will mark a conflict.  A conflict means that you need to fix something,
2068
 
    before you should commit.
2069
 
 
2070
 
    Use bzr resolve when you have fixed a problem.  See also bzr conflicts.
2071
 
 
2072
 
    If there is no default branch set, the first merge will set it. After
2073
 
    that, you can omit the branch to use the default.  To change the
2074
 
    default, use --remember. The value will only be saved if the remote
2075
 
    location can be accessed.
2076
 
 
2077
1703
    Examples:
2078
1704
 
2079
1705
    To merge the latest revision from bzr.dev
2087
1713
    
2088
1714
    merge refuses to run if there are any uncommitted changes, unless
2089
1715
    --force is given.
2090
 
 
2091
 
    The following merge types are available:
2092
1716
    """
2093
1717
    takes_args = ['branch?']
2094
 
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
 
1718
    takes_options = ['revision', 'force', 'merge-type', 'reprocess',
2095
1719
                     Option('show-base', help="Show base revision text in "
2096
1720
                            "conflicts")]
2097
1721
 
2098
 
    def help(self):
2099
 
        from merge import merge_type_help
2100
 
        from inspect import getdoc
2101
 
        return getdoc(self) + '\n' + merge_type_help() 
2102
 
 
2103
1722
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2104
 
            show_base=False, reprocess=False, remember=False):
 
1723
            show_base=False, reprocess=False):
2105
1724
        if merge_type is None:
2106
1725
            merge_type = Merge3Merger
2107
 
 
2108
 
        tree = WorkingTree.open_containing(u'.')[0]
2109
 
 
2110
 
        if branch is not None:
2111
 
            try:
2112
 
                reader = bundle.read_bundle_from_url(branch)
2113
 
            except NotABundle:
2114
 
                pass # Continue on considering this url a Branch
 
1726
        if branch is None:
 
1727
            branch = WorkingTree.open_containing(u'.')[0].branch.get_parent()
 
1728
            if branch is None:
 
1729
                raise BzrCommandError("No merge location known or specified.")
2115
1730
            else:
2116
 
                conflicts = merge_bundle(reader, tree, not force, merge_type,
2117
 
                                            reprocess, show_base)
2118
 
                if conflicts == 0:
2119
 
                    return 0
2120
 
                else:
2121
 
                    return 1
2122
 
 
2123
 
        branch = self._get_remembered_parent(tree, branch, 'Merging from')
2124
 
 
 
1731
                print "Using saved location: %s" % branch 
2125
1732
        if revision is None or len(revision) < 1:
2126
1733
            base = [None, None]
2127
1734
            other = [branch, -1]
2128
 
            other_branch, path = Branch.open_containing(branch)
2129
1735
        else:
2130
1736
            if len(revision) == 1:
2131
1737
                base = [None, None]
2132
 
                other_branch, path = Branch.open_containing(branch)
 
1738
                other_branch = Branch.open_containing(branch)[0]
2133
1739
                revno = revision[0].in_history(other_branch).revno
2134
1740
                other = [branch, revno]
2135
1741
            else:
2137
1743
                if None in revision:
2138
1744
                    raise BzrCommandError(
2139
1745
                        "Merge doesn't permit that revision specifier.")
2140
 
                other_branch, path = Branch.open_containing(branch)
2141
 
 
2142
 
                base = [branch, revision[0].in_history(other_branch).revno]
2143
 
                other = [branch, revision[1].in_history(other_branch).revno]
2144
 
 
2145
 
        if tree.branch.get_parent() is None or remember:
2146
 
            tree.branch.set_parent(other_branch.base)
2147
 
 
2148
 
        if path != "":
2149
 
            interesting_files = [path]
2150
 
        else:
2151
 
            interesting_files = None
2152
 
        pb = ui.ui_factory.nested_progress_bar()
 
1746
                b = Branch.open_containing(branch)[0]
 
1747
 
 
1748
                base = [branch, revision[0].in_history(b).revno]
 
1749
                other = [branch, revision[1].in_history(b).revno]
 
1750
 
2153
1751
        try:
2154
 
            try:
2155
 
                conflict_count = merge(other, base, check_clean=(not force),
2156
 
                                       merge_type=merge_type,
2157
 
                                       reprocess=reprocess,
2158
 
                                       show_base=show_base,
2159
 
                                       pb=pb, file_list=interesting_files)
2160
 
            finally:
2161
 
                pb.finished()
 
1752
            conflict_count = merge(other, base, check_clean=(not force),
 
1753
                                   merge_type=merge_type, reprocess=reprocess,
 
1754
                                   show_base=show_base, 
 
1755
                                   pb=bzrlib.ui.ui_factory.progress_bar())
2162
1756
            if conflict_count != 0:
2163
1757
                return 1
2164
1758
            else:
2165
1759
                return 0
2166
 
        except errors.AmbiguousBase, e:
 
1760
        except bzrlib.errors.AmbiguousBase, e:
2167
1761
            m = ("sorry, bzr can't determine the right merge base yet\n"
2168
1762
                 "candidates are:\n  "
2169
1763
                 + "\n  ".join(e.bases)
2172
1766
                 "and (if you want) report this to the bzr developers\n")
2173
1767
            log_error(m)
2174
1768
 
2175
 
    # TODO: move up to common parent; this isn't merge-specific anymore. 
2176
 
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
2177
 
        """Use tree.branch's parent if none was supplied.
2178
 
 
2179
 
        Report if the remembered location was used.
2180
 
        """
2181
 
        if supplied_location is not None:
2182
 
            return supplied_location
2183
 
        stored_location = tree.branch.get_parent()
2184
 
        mutter("%s", stored_location)
2185
 
        if stored_location is None:
2186
 
            raise BzrCommandError("No location specified or remembered")
2187
 
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2188
 
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2189
 
        return stored_location
2190
 
 
2191
1769
 
2192
1770
class cmd_remerge(Command):
2193
1771
    """Redo a merge.
2194
 
 
2195
 
    Use this if you want to try a different merge technique while resolving
2196
 
    conflicts.  Some merge techniques are better than others, and remerge 
2197
 
    lets you try different ones on different files.
2198
 
 
2199
 
    The options for remerge have the same meaning and defaults as the ones for
2200
 
    merge.  The difference is that remerge can (only) be run when there is a
2201
 
    pending merge, and it lets you specify particular files.
2202
 
 
2203
 
    Examples:
2204
 
    $ bzr remerge --show-base
2205
 
        Re-do the merge of all conflicted files, and show the base text in
2206
 
        conflict regions, in addition to the usual THIS and OTHER texts.
2207
 
 
2208
 
    $ bzr remerge --merge-type weave --reprocess foobar
2209
 
        Re-do the merge of "foobar", using the weave merge algorithm, with
2210
 
        additional processing to reduce the size of conflict regions.
2211
 
    
2212
 
    The following merge types are available:"""
 
1772
    """
2213
1773
    takes_args = ['file*']
2214
1774
    takes_options = ['merge-type', 'reprocess',
2215
1775
                     Option('show-base', help="Show base revision text in "
2216
1776
                            "conflicts")]
2217
1777
 
2218
 
    def help(self):
2219
 
        from merge import merge_type_help
2220
 
        from inspect import getdoc
2221
 
        return getdoc(self) + '\n' + merge_type_help() 
2222
 
 
2223
1778
    def run(self, file_list=None, merge_type=None, show_base=False,
2224
1779
            reprocess=False):
2225
1780
        from bzrlib.merge import merge_inner, transform_tree
2231
1786
            pending_merges = tree.pending_merges() 
2232
1787
            if len(pending_merges) != 1:
2233
1788
                raise BzrCommandError("Sorry, remerge only works after normal"
2234
 
                                      " merges.  Not cherrypicking or"
2235
 
                                      " multi-merges.")
 
1789
                                      + " merges.  Not cherrypicking or"
 
1790
                                      + "multi-merges.")
2236
1791
            repository = tree.branch.repository
2237
1792
            base_revision = common_ancestor(tree.branch.last_revision(), 
2238
1793
                                            pending_merges[0], repository)
2239
1794
            base_tree = repository.revision_tree(base_revision)
2240
1795
            other_tree = repository.revision_tree(pending_merges[0])
2241
1796
            interesting_ids = None
2242
 
            new_conflicts = []
2243
 
            conflicts = tree.conflicts()
2244
1797
            if file_list is not None:
2245
1798
                interesting_ids = set()
2246
1799
                for filename in file_list:
2247
1800
                    file_id = tree.path2id(filename)
2248
 
                    if file_id is None:
2249
 
                        raise NotVersionedError(filename)
2250
1801
                    interesting_ids.add(file_id)
2251
1802
                    if tree.kind(file_id) != "directory":
2252
1803
                        continue
2253
1804
                    
2254
1805
                    for name, ie in tree.inventory.iter_entries(file_id):
2255
1806
                        interesting_ids.add(ie.file_id)
2256
 
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2257
1807
            transform_tree(tree, tree.basis_tree(), interesting_ids)
2258
 
            tree.set_conflicts(ConflictList(new_conflicts))
2259
1808
            if file_list is None:
2260
1809
                restore_files = list(tree.iter_conflicts())
2261
1810
            else:
2265
1814
                    restore(tree.abspath(filename))
2266
1815
                except NotConflicted:
2267
1816
                    pass
2268
 
            conflicts = merge_inner(tree.branch, other_tree, base_tree,
2269
 
                                    this_tree=tree,
2270
 
                                    interesting_ids=interesting_ids, 
2271
 
                                    other_rev_id=pending_merges[0], 
2272
 
                                    merge_type=merge_type, 
2273
 
                                    show_base=show_base,
2274
 
                                    reprocess=reprocess)
 
1817
            conflicts =  merge_inner(tree.branch, other_tree, base_tree, 
 
1818
                                     interesting_ids = interesting_ids, 
 
1819
                                     other_rev_id=pending_merges[0], 
 
1820
                                     merge_type=merge_type, 
 
1821
                                     show_base=show_base,
 
1822
                                     reprocess=reprocess)
2275
1823
        finally:
2276
1824
            tree.unlock()
2277
1825
        if conflicts > 0:
2301
1849
        tree, file_list = tree_files(file_list)
2302
1850
        if revision is None:
2303
1851
            # FIXME should be tree.last_revision
2304
 
            rev_id = tree.last_revision()
 
1852
            rev_id = tree.branch.last_revision()
2305
1853
        elif len(revision) != 1:
2306
1854
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
2307
1855
        else:
2308
1856
            rev_id = revision[0].in_history(tree.branch).rev_id
2309
 
        pb = ui.ui_factory.nested_progress_bar()
2310
 
        try:
2311
 
            tree.revert(file_list, 
2312
 
                        tree.branch.repository.revision_tree(rev_id),
2313
 
                        not no_backup, pb)
2314
 
        finally:
2315
 
            pb.finished()
 
1857
        tree.revert(file_list, tree.branch.repository.revision_tree(rev_id),
 
1858
                    not no_backup, bzrlib.ui.ui_factory.progress_bar())
2316
1859
 
2317
1860
 
2318
1861
class cmd_assert_fail(Command):
2328
1871
    For a list of all available commands, say 'bzr help commands'."""
2329
1872
    takes_options = [Option('long', 'show help on all commands')]
2330
1873
    takes_args = ['topic?']
2331
 
    aliases = ['?', '--help', '-?', '-h']
 
1874
    aliases = ['?']
2332
1875
    
2333
1876
    @display_command
2334
1877
    def run(self, topic=None, long=False):
2360
1903
    takes_args = ['from_branch', 'to_branch']
2361
1904
    def run(self, from_branch, to_branch):
2362
1905
        from bzrlib.fetch import Fetcher
 
1906
        from bzrlib.branch import Branch
2363
1907
        from_b = Branch.open(from_branch)
2364
1908
        to_b = Branch.open(to_branch)
2365
1909
        Fetcher(to_b, from_b)
2382
1926
                     'show-ids',
2383
1927
                     'verbose'
2384
1928
                     ]
2385
 
    encoding_type = 'replace'
2386
1929
 
2387
 
    @display_command
2388
1930
    def run(self, other_branch=None, reverse=False, mine_only=False,
2389
1931
            theirs_only=False, log_format=None, long=False, short=False, line=False, 
2390
1932
            show_ids=False, verbose=False):
2391
1933
        from bzrlib.missing import find_unmerged, iter_log_data
2392
1934
        from bzrlib.log import log_formatter
2393
 
        local_branch = Branch.open_containing(u".")[0]
 
1935
        local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2394
1936
        parent = local_branch.get_parent()
2395
1937
        if other_branch is None:
2396
1938
            other_branch = parent
2397
1939
            if other_branch is None:
2398
1940
                raise BzrCommandError("No missing location known or specified.")
2399
1941
            print "Using last location: " + local_branch.get_parent()
2400
 
        remote_branch = Branch.open(other_branch)
2401
 
        if remote_branch.base == local_branch.base:
2402
 
            remote_branch = local_branch
2403
 
        local_branch.lock_read()
2404
 
        try:
2405
 
            remote_branch.lock_read()
2406
 
            try:
2407
 
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2408
 
                if (log_format == None):
2409
 
                    default = local_branch.get_config().log_format()
2410
 
                    log_format = get_log_format(long=long, short=short, 
2411
 
                                                line=line, default=default)
2412
 
                lf = log_formatter(log_format,
2413
 
                                   to_file=self.outf,
2414
 
                                   show_ids=show_ids,
2415
 
                                   show_timezone='original')
2416
 
                if reverse is False:
2417
 
                    local_extra.reverse()
2418
 
                    remote_extra.reverse()
2419
 
                if local_extra and not theirs_only:
2420
 
                    print "You have %d extra revision(s):" % len(local_extra)
2421
 
                    for data in iter_log_data(local_extra, local_branch.repository,
2422
 
                                              verbose):
2423
 
                        lf.show(*data)
2424
 
                    printed_local = True
2425
 
                else:
2426
 
                    printed_local = False
2427
 
                if remote_extra and not mine_only:
2428
 
                    if printed_local is True:
2429
 
                        print "\n\n"
2430
 
                    print "You are missing %d revision(s):" % len(remote_extra)
2431
 
                    for data in iter_log_data(remote_extra, remote_branch.repository, 
2432
 
                                              verbose):
2433
 
                        lf.show(*data)
2434
 
                if not remote_extra and not local_extra:
2435
 
                    status_code = 0
2436
 
                    print "Branches are up to date."
2437
 
                else:
2438
 
                    status_code = 1
2439
 
            finally:
2440
 
                remote_branch.unlock()
2441
 
        finally:
2442
 
            local_branch.unlock()
2443
 
        if not status_code and parent is None and other_branch is not None:
2444
 
            local_branch.lock_write()
2445
 
            try:
2446
 
                # handle race conditions - a parent might be set while we run.
2447
 
                if local_branch.get_parent() is None:
2448
 
                    local_branch.set_parent(remote_branch.base)
2449
 
            finally:
2450
 
                local_branch.unlock()
 
1942
        remote_branch = bzrlib.branch.Branch.open(other_branch)
 
1943
        local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
 
1944
        if (log_format == None):
 
1945
            default = bzrlib.config.BranchConfig(local_branch).log_format()
 
1946
            log_format = get_log_format(long=long, short=short, line=line, default=default)
 
1947
        lf = log_formatter(log_format, sys.stdout,
 
1948
                           show_ids=show_ids,
 
1949
                           show_timezone='original')
 
1950
        if reverse is False:
 
1951
            local_extra.reverse()
 
1952
            remote_extra.reverse()
 
1953
        if local_extra and not theirs_only:
 
1954
            print "You have %d extra revision(s):" % len(local_extra)
 
1955
            for data in iter_log_data(local_extra, local_branch.repository,
 
1956
                                      verbose):
 
1957
                lf.show(*data)
 
1958
            printed_local = True
 
1959
        else:
 
1960
            printed_local = False
 
1961
        if remote_extra and not mine_only:
 
1962
            if printed_local is True:
 
1963
                print "\n\n"
 
1964
            print "You are missing %d revision(s):" % len(remote_extra)
 
1965
            for data in iter_log_data(remote_extra, remote_branch.repository, 
 
1966
                                      verbose):
 
1967
                lf.show(*data)
 
1968
        if not remote_extra and not local_extra:
 
1969
            status_code = 0
 
1970
            print "Branches are up to date."
 
1971
        else:
 
1972
            status_code = 1
 
1973
        if parent is None and other_branch is not None:
 
1974
            local_branch.set_parent(other_branch)
2451
1975
        return status_code
2452
1976
 
2453
1977
 
2473
1997
 
2474
1998
class cmd_testament(Command):
2475
1999
    """Show testament (signing-form) of a revision."""
2476
 
    takes_options = ['revision', 'long', 
2477
 
                     Option('strict', help='Produce a strict-format'
2478
 
                            ' testament')]
 
2000
    takes_options = ['revision', 'long']
2479
2001
    takes_args = ['branch?']
2480
2002
    @display_command
2481
 
    def run(self, branch=u'.', revision=None, long=False, strict=False):
2482
 
        from bzrlib.testament import Testament, StrictTestament
2483
 
        if strict is True:
2484
 
            testament_class = StrictTestament
2485
 
        else:
2486
 
            testament_class = Testament
 
2003
    def run(self, branch=u'.', revision=None, long=False):
 
2004
        from bzrlib.testament import Testament
2487
2005
        b = WorkingTree.open_containing(branch)[0].branch
2488
2006
        b.lock_read()
2489
2007
        try:
2491
2009
                rev_id = b.last_revision()
2492
2010
            else:
2493
2011
                rev_id = revision[0].in_history(b).rev_id
2494
 
            t = testament_class.from_revision(b.repository, rev_id)
 
2012
            t = Testament.from_revision(b.repository, rev_id)
2495
2013
            if long:
2496
2014
                sys.stdout.writelines(t.as_text_lines())
2497
2015
            else:
2510
2028
    shown only at the top, unless the --all option is given.
2511
2029
    """
2512
2030
    # TODO: annotate directories; showing when each file was last changed
 
2031
    # TODO: annotate a previous version of a file
2513
2032
    # TODO: if the working copy is modified, show annotations on that 
2514
2033
    #       with new uncommitted lines marked
2515
 
    aliases = ['ann', 'blame', 'praise']
 
2034
    aliases = ['blame', 'praise']
2516
2035
    takes_args = ['filename']
2517
2036
    takes_options = [Option('all', help='show annotations on all lines'),
2518
2037
                     Option('long', help='show date in annotations'),
2519
 
                     'revision'
2520
2038
                     ]
2521
2039
 
2522
2040
    @display_command
2523
 
    def run(self, filename, all=False, long=False, revision=None):
 
2041
    def run(self, filename, all=False, long=False):
2524
2042
        from bzrlib.annotate import annotate_file
2525
2043
        tree, relpath = WorkingTree.open_containing(filename)
2526
2044
        branch = tree.branch
2527
2045
        branch.lock_read()
2528
2046
        try:
2529
 
            if revision is None:
2530
 
                revision_id = branch.last_revision()
2531
 
            elif len(revision) != 1:
2532
 
                raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2533
 
            else:
2534
 
                revision_id = revision[0].in_history(branch).rev_id
2535
2047
            file_id = tree.inventory.path2id(relpath)
2536
 
            tree = branch.repository.revision_tree(revision_id)
 
2048
            tree = branch.repository.revision_tree(branch.last_revision())
2537
2049
            file_version = tree.inventory[file_id].revision
2538
2050
            annotate_file(branch, file_version, file_id, long, all, sys.stdout)
2539
2051
        finally:
2549
2061
    takes_options = ['revision']
2550
2062
    
2551
2063
    def run(self, revision_id_list=None, revision=None):
 
2064
        import bzrlib.config as config
2552
2065
        import bzrlib.gpg as gpg
2553
2066
        if revision_id_list is not None and revision is not None:
2554
2067
            raise BzrCommandError('You can only supply one of revision_id or --revision')
2555
2068
        if revision_id_list is None and revision is None:
2556
2069
            raise BzrCommandError('You must supply either --revision or a revision_id')
2557
2070
        b = WorkingTree.open_containing(u'.')[0].branch
2558
 
        gpg_strategy = gpg.GPGStrategy(b.get_config())
 
2071
        gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
2559
2072
        if revision_id_list is not None:
2560
2073
            for revision_id in revision_id_list:
2561
2074
                b.repository.sign_revision(revision_id, gpg_strategy)
2580
2093
                raise BzrCommandError('Please supply either one revision, or a range.')
2581
2094
 
2582
2095
 
2583
 
class cmd_bind(Command):
2584
 
    """Bind the current branch to a master branch.
2585
 
 
2586
 
    After binding, commits must succeed on the master branch
2587
 
    before they are executed on the local one.
2588
 
    """
2589
 
 
2590
 
    takes_args = ['location']
2591
 
    takes_options = []
2592
 
 
2593
 
    def run(self, location=None):
2594
 
        b, relpath = Branch.open_containing(u'.')
2595
 
        b_other = Branch.open(location)
2596
 
        try:
2597
 
            b.bind(b_other)
2598
 
        except DivergedBranches:
2599
 
            raise BzrCommandError('These branches have diverged.'
2600
 
                                  ' Try merging, and then bind again.')
2601
 
 
2602
 
 
2603
 
class cmd_unbind(Command):
2604
 
    """Unbind the current branch from its master branch.
2605
 
 
2606
 
    After unbinding, the local branch is considered independent.
2607
 
    All subsequent commits will be local.
2608
 
    """
2609
 
 
2610
 
    takes_args = []
2611
 
    takes_options = []
2612
 
 
2613
 
    def run(self):
2614
 
        b, relpath = Branch.open_containing(u'.')
2615
 
        if not b.unbind():
2616
 
            raise BzrCommandError('Local branch is not bound')
2617
 
 
2618
 
 
2619
 
class cmd_uncommit(Command):
 
2096
class cmd_uncommit(bzrlib.commands.Command):
2620
2097
    """Remove the last committed revision.
2621
2098
 
 
2099
    By supplying the --all flag, it will not only remove the entry 
 
2100
    from revision_history, but also remove all of the entries in the
 
2101
    stores.
 
2102
 
2622
2103
    --verbose will print out what is being removed.
2623
2104
    --dry-run will go through all the motions, but not actually
2624
2105
    remove anything.
2625
2106
    
2626
 
    In the future, uncommit will create a revision bundle, which can then
 
2107
    In the future, uncommit will create a changeset, which can then
2627
2108
    be re-applied.
 
2109
 
 
2110
    TODO: jam 20060108 Add an option to allow uncommit to remove unreferenced
 
2111
              information in 'branch-as-repostory' branches.
 
2112
    TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
 
2113
              information in shared branches as well.
2628
2114
    """
2629
 
 
2630
 
    # TODO: jam 20060108 Add an option to allow uncommit to remove
2631
 
    # unreferenced information in 'branch-as-repository' branches.
2632
 
    # TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2633
 
    # information in shared branches as well.
2634
2115
    takes_options = ['verbose', 'revision',
2635
2116
                    Option('dry-run', help='Don\'t actually make changes'),
2636
2117
                    Option('force', help='Say yes to all questions.')]
2637
2118
    takes_args = ['location?']
2638
2119
    aliases = []
2639
2120
 
2640
 
    def run(self, location=None,
 
2121
    def run(self, location=None, 
2641
2122
            dry_run=False, verbose=False,
2642
2123
            revision=None, force=False):
2643
 
        from bzrlib.log import log_formatter, show_log
 
2124
        from bzrlib.branch import Branch
 
2125
        from bzrlib.log import log_formatter
2644
2126
        import sys
2645
2127
        from bzrlib.uncommit import uncommit
2646
2128
 
2647
2129
        if location is None:
2648
2130
            location = u'.'
2649
2131
        control, relpath = bzrdir.BzrDir.open_containing(location)
 
2132
        b = control.open_branch()
2650
2133
        try:
2651
2134
            tree = control.open_workingtree()
2652
 
            b = tree.branch
2653
2135
        except (errors.NoWorkingTree, errors.NotLocalUrl):
2654
2136
            tree = None
2655
 
            b = control.open_branch()
2656
2137
 
2657
 
        rev_id = None
2658
2138
        if revision is None:
2659
2139
            revno = b.revno()
 
2140
            rev_id = b.last_revision()
2660
2141
        else:
2661
 
            # 'bzr uncommit -r 10' actually means uncommit
2662
 
            # so that the final tree is at revno 10.
2663
 
            # but bzrlib.uncommit.uncommit() actually uncommits
2664
 
            # the revisions that are supplied.
2665
 
            # So we need to offset it by one
2666
 
            revno = revision[0].in_history(b).revno+1
2667
 
 
2668
 
        if revno <= b.revno():
2669
 
            rev_id = b.get_rev_id(revno)
 
2142
            revno, rev_id = revision[0].in_history(b)
2670
2143
        if rev_id is None:
2671
 
            self.outf.write('No revisions to uncommit.\n')
2672
 
            return 1
2673
 
 
2674
 
        lf = log_formatter('short',
2675
 
                           to_file=self.outf,
2676
 
                           show_timezone='original')
2677
 
 
2678
 
        show_log(b,
2679
 
                 lf,
2680
 
                 verbose=False,
2681
 
                 direction='forward',
2682
 
                 start_revision=revno,
2683
 
                 end_revision=b.revno())
 
2144
            print 'No revisions to uncommit.'
 
2145
 
 
2146
        for r in range(revno, b.revno()+1):
 
2147
            rev_id = b.get_rev_id(r)
 
2148
            lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
 
2149
            lf.show(r, b.repository.get_revision(rev_id), None)
2684
2150
 
2685
2151
        if dry_run:
2686
2152
            print 'Dry-run, pretending to remove the above revisions.'
2698
2164
                revno=revno)
2699
2165
 
2700
2166
 
2701
 
class cmd_break_lock(Command):
2702
 
    """Break a dead lock on a repository, branch or working directory.
2703
 
 
2704
 
    CAUTION: Locks should only be broken when you are sure that the process
2705
 
    holding the lock has been stopped.
2706
 
 
2707
 
    You can get information on what locks are open via the 'bzr info' command.
2708
 
    
2709
 
    example:
2710
 
        bzr break-lock
2711
 
    """
2712
 
    takes_args = ['location?']
2713
 
 
2714
 
    def run(self, location=None, show=False):
2715
 
        if location is None:
2716
 
            location = u'.'
2717
 
        control, relpath = bzrdir.BzrDir.open_containing(location)
2718
 
        try:
2719
 
            control.break_lock()
2720
 
        except NotImplementedError:
2721
 
            pass
2722
 
        
2723
 
 
2724
 
 
2725
 
# command-line interpretation helper for merge-related commands
2726
2167
def merge(other_revision, base_revision,
2727
2168
          check_clean=True, ignore_zero=False,
2728
2169
          this_dir=None, backup_files=False, merge_type=Merge3Merger,
2729
 
          file_list=None, show_base=False, reprocess=False,
 
2170
          file_list=None, show_base=False, reprocess=False, 
2730
2171
          pb=DummyProgress()):
2731
2172
    """Merge changes into a tree.
2732
2173
 
2762
2203
    if show_base and not merge_type is Merge3Merger:
2763
2204
        raise BzrCommandError("Show-base is not supported for this merge"
2764
2205
                              " type. %s" % merge_type)
2765
 
    if reprocess and not merge_type.supports_reprocess:
2766
 
        raise BzrCommandError("Conflict reduction is not supported for merge"
2767
 
                              " type %s." % merge_type)
 
2206
    if reprocess and not merge_type is Merge3Merger:
 
2207
        raise BzrCommandError("Reprocess is not supported for this merge"
 
2208
                              " type. %s" % merge_type)
2768
2209
    if reprocess and show_base:
2769
 
        raise BzrCommandError("Cannot do conflict reduction and show base.")
2770
 
    try:
2771
 
        merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2772
 
        merger.pp = ProgressPhase("Merge phase", 5, pb)
2773
 
        merger.pp.next_phase()
2774
 
        merger.check_basis(check_clean)
2775
 
        merger.set_other(other_revision)
2776
 
        merger.pp.next_phase()
2777
 
        merger.set_base(base_revision)
2778
 
        if merger.base_rev_id == merger.other_rev_id:
2779
 
            note('Nothing to do.')
2780
 
            return 0
2781
 
        merger.backup_files = backup_files
2782
 
        merger.merge_type = merge_type 
2783
 
        merger.set_interesting_files(file_list)
2784
 
        merger.show_base = show_base 
2785
 
        merger.reprocess = reprocess
2786
 
        conflicts = merger.do_merge()
2787
 
        if file_list is None:
2788
 
            merger.set_pending()
2789
 
    finally:
2790
 
        pb.clear()
 
2210
        raise BzrCommandError("Cannot reprocess and show base.")
 
2211
    merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
 
2212
    merger.check_basis(check_clean)
 
2213
    merger.set_other(other_revision)
 
2214
    merger.set_base(base_revision)
 
2215
    if merger.base_rev_id == merger.other_rev_id:
 
2216
        note('Nothing to do.')
 
2217
        return 0
 
2218
    merger.backup_files = backup_files
 
2219
    merger.merge_type = merge_type 
 
2220
    merger.set_interesting_files(file_list)
 
2221
    merger.show_base = show_base 
 
2222
    merger.reprocess = reprocess
 
2223
    conflicts = merger.do_merge()
 
2224
    merger.set_pending()
2791
2225
    return conflicts
2792
2226
 
2793
2227
 
2794
2228
# these get imported and then picked up by the scan for cmd_*
2795
2229
# TODO: Some more consistent way to split command definitions across files;
2796
2230
# we do need to load at least some information about them to know of 
2797
 
# aliases.  ideally we would avoid loading the implementation until the
2798
 
# details were needed.
 
2231
# aliases.
2799
2232
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2800
 
from bzrlib.bundle.commands import cmd_bundle_revisions
2801
2233
from bzrlib.sign_my_commits import cmd_sign_my_commits
2802
 
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
2803
 
        cmd_weave_plan_merge, cmd_weave_merge_text