~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-04-27 01:14:33 UTC
  • mfrom: (1686.1.1 integration)
  • Revision ID: pqm@pqm.ubuntu.com-20060427011433-95634ee1da8a2049
Merge in faster joins from weave to knit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2004, 2005, 2006 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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
#
 
7
 
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
#
 
12
 
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 import (
28
 
    branch,
29
 
    bundle,
30
 
    bzrdir,
31
 
    config,
32
 
    errors,
33
 
    ignores,
34
 
    log,
35
 
    osutils,
36
 
    repository,
37
 
    transport,
38
 
    ui,
39
 
    urlutils,
40
 
    )
41
 
from bzrlib.branch import Branch, BranchReferenceFormat
42
 
from bzrlib.bundle import read_bundle_from_url
43
 
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
44
 
from bzrlib.conflicts import ConflictList
 
26
import bzrlib.branch
 
27
from bzrlib.branch import Branch
 
28
import bzrlib.bzrdir as bzrdir
45
29
from bzrlib.commands import Command, display_command
 
30
from bzrlib.revision import common_ancestor
 
31
import bzrlib.errors as errors
46
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
47
33
                           NotBranchError, DivergedBranches, NotConflicted,
48
34
                           NoSuchFile, NoWorkingTree, FileInWrongBranch,
49
 
                           NotVersionedError, NotABundle)
 
35
                           NotVersionedError)
 
36
from bzrlib.log import show_one_log
50
37
from bzrlib.merge import Merge3Merger
51
38
from bzrlib.option import Option
52
39
from bzrlib.progress import DummyProgress, ProgressPhase
53
 
from bzrlib.revision import common_ancestor
54
40
from bzrlib.revisionspec import RevisionSpec
55
 
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
 
41
import bzrlib.trace
 
42
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
56
43
from bzrlib.transport.local import LocalTransport
 
44
import bzrlib.ui
57
45
from bzrlib.workingtree import WorkingTree
58
46
 
59
47
 
97
85
    """Parse and return a format specifier."""
98
86
    if typestring == "weave":
99
87
        return bzrdir.BzrDirFormat6()
100
 
    if typestring == "default":
 
88
    if typestring == "metadir":
101
89
        return bzrdir.BzrDirMetaFormat1()
102
 
    if typestring == "metaweave":
103
 
        format = bzrdir.BzrDirMetaFormat1()
104
 
        format.repository_format = repository.RepositoryFormat7()
105
 
        return format
106
90
    if typestring == "knit":
107
91
        format = bzrdir.BzrDirMetaFormat1()
108
 
        format.repository_format = repository.RepositoryFormatKnit1()
 
92
        format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
109
93
        return format
110
 
    msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
111
 
          "metaweave and weave" % typestring
 
94
    msg = "No known bzr-dir format %s. Supported types are: weave, metadir\n" %\
 
95
        (typestring)
112
96
    raise BzrCommandError(msg)
113
97
 
114
98
 
139
123
    modified
140
124
        Text has changed since the previous revision.
141
125
 
 
126
    unchanged
 
127
        Nothing about this file has changed since the previous revision.
 
128
        Only shown with --all.
 
129
 
142
130
    unknown
143
131
        Not versioned and not matching an ignore pattern.
144
132
 
157
145
    # TODO: --no-recurse, --recurse options
158
146
    
159
147
    takes_args = ['file*']
160
 
    takes_options = ['show-ids', 'revision']
 
148
    takes_options = ['all', 'show-ids', 'revision']
161
149
    aliases = ['st', 'stat']
162
 
 
163
 
    encoding_type = 'replace'
164
150
    
165
151
    @display_command
166
 
    def run(self, show_ids=False, file_list=None, revision=None):
 
152
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
 
153
        tree, file_list = tree_files(file_list)
 
154
            
167
155
        from bzrlib.status import show_tree_status
168
 
 
169
 
        tree, file_list = tree_files(file_list)
170
 
            
171
 
        show_tree_status(tree, show_ids=show_ids,
172
 
                         specific_files=file_list, revision=revision,
173
 
                         to_file=self.outf)
 
156
        show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
 
157
                         specific_files=file_list, revision=revision)
174
158
 
175
159
 
176
160
class cmd_cat_revision(Command):
183
167
    hidden = True
184
168
    takes_args = ['revision_id?']
185
169
    takes_options = ['revision']
186
 
    # cat-revision is more for frontends so should be exact
187
 
    encoding = 'strict'
188
170
    
189
171
    @display_command
190
172
    def run(self, revision_id=None, revision=None):
194
176
        if revision_id is None and revision is None:
195
177
            raise BzrCommandError('You must supply either --revision or a revision_id')
196
178
        b = WorkingTree.open_containing(u'.')[0].branch
197
 
 
198
 
        # TODO: jam 20060112 should cat-revision always output utf-8?
199
179
        if revision_id is not None:
200
 
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
 
180
            sys.stdout.write(b.repository.get_revision_xml(revision_id))
201
181
        elif revision is not None:
202
182
            for rev in revision:
203
183
                if rev is None:
204
184
                    raise BzrCommandError('You cannot specify a NULL revision.')
205
185
                revno, rev_id = rev.in_history(b)
206
 
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
 
186
                sys.stdout.write(b.repository.get_revision_xml(rev_id))
207
187
    
208
188
 
209
189
class cmd_revno(Command):
210
190
    """Show current revision number.
211
191
 
212
 
    This is equal to the number of revisions on this branch.
213
 
    """
214
 
 
 
192
    This is equal to the number of revisions on this branch."""
215
193
    takes_args = ['location?']
216
 
 
217
194
    @display_command
218
195
    def run(self, location=u'.'):
219
 
        self.outf.write(str(Branch.open_containing(location)[0].revno()))
220
 
        self.outf.write('\n')
 
196
        print Branch.open_containing(location)[0].revno()
221
197
 
222
198
 
223
199
class cmd_revision_info(Command):
226
202
    hidden = True
227
203
    takes_args = ['revision_info*']
228
204
    takes_options = ['revision']
229
 
 
230
205
    @display_command
231
206
    def run(self, revision=None, revision_info_list=[]):
232
207
 
269
244
 
270
245
    Adding a file whose parent directory is not versioned will
271
246
    implicitly add the parent, and so on up to the root. This means
272
 
    you should never need to explicitly add a directory, they'll just
 
247
    you should never need to explictly add a directory, they'll just
273
248
    get added when you add a file in the directory.
274
249
 
275
250
    --dry-run will show which files would be added, but not actually 
277
252
    """
278
253
    takes_args = ['file*']
279
254
    takes_options = ['no-recurse', 'dry-run', 'verbose']
280
 
    encoding_type = 'replace'
281
255
 
282
256
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
283
257
        import bzrlib.add
284
258
 
285
 
        action = bzrlib.add.AddAction(to_file=self.outf,
286
 
            should_print=(not is_quiet()))
 
259
        if dry_run:
 
260
            if is_quiet():
 
261
                # This is pointless, but I'd rather not raise an error
 
262
                action = bzrlib.add.add_action_null
 
263
            else:
 
264
                action = bzrlib.add.add_action_print
 
265
        elif is_quiet():
 
266
            action = bzrlib.add.add_action_add
 
267
        else:
 
268
            action = bzrlib.add.add_action_add_and_print
287
269
 
288
270
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse, 
289
 
                                              action=action, save=not dry_run)
 
271
                                              action)
290
272
        if len(ignored) > 0:
291
 
            if verbose:
292
 
                for glob in sorted(ignored.keys()):
 
273
            for glob in sorted(ignored.keys()):
 
274
                match_len = len(ignored[glob])
 
275
                if verbose:
293
276
                    for path in ignored[glob]:
294
 
                        self.outf.write("ignored %s matching \"%s\"\n" 
295
 
                                        % (path, glob))
296
 
            else:
297
 
                match_len = 0
298
 
                for glob, paths in ignored.items():
299
 
                    match_len += len(paths)
300
 
                self.outf.write("ignored %d file(s).\n" % match_len)
301
 
            self.outf.write("If you wish to add some of these files,"
302
 
                            " please add them by name.\n")
 
277
                        print "ignored %s matching \"%s\"" % (path, glob)
 
278
                else:
 
279
                    print "ignored %d file(s) matching \"%s\"" % (match_len,
 
280
                                                              glob)
 
281
            print "If you wish to add some of these files, please add them"\
 
282
                " by name."
303
283
 
304
284
 
305
285
class cmd_mkdir(Command):
307
287
 
308
288
    This is equivalent to creating the directory and then adding it.
309
289
    """
310
 
 
311
290
    takes_args = ['dir+']
312
 
    encoding_type = 'replace'
313
291
 
314
292
    def run(self, dir_list):
315
293
        for d in dir_list:
316
294
            os.mkdir(d)
317
295
            wt, dd = WorkingTree.open_containing(d)
318
296
            wt.add([dd])
319
 
            self.outf.write('added %s\n' % d)
 
297
            print 'added', d
320
298
 
321
299
 
322
300
class cmd_relpath(Command):
323
301
    """Show path of a file relative to root"""
324
 
 
325
302
    takes_args = ['filename']
326
303
    hidden = True
327
304
    
328
305
    @display_command
329
306
    def run(self, filename):
330
 
        # TODO: jam 20050106 Can relpath return a munged path if
331
 
        #       sys.stdout encoding cannot represent it?
332
307
        tree, relpath = WorkingTree.open_containing(filename)
333
 
        self.outf.write(relpath)
334
 
        self.outf.write('\n')
 
308
        print relpath
335
309
 
336
310
 
337
311
class cmd_inventory(Command):
340
314
    It is possible to limit the output to a particular entry
341
315
    type using the --kind option.  For example; --kind file.
342
316
    """
343
 
 
344
317
    takes_options = ['revision', 'show-ids', 'kind']
345
318
    
346
319
    @display_command
361
334
            if kind and kind != entry.kind:
362
335
                continue
363
336
            if show_ids:
364
 
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
 
337
                print '%-50s %s' % (path, entry.file_id)
365
338
            else:
366
 
                self.outf.write(path)
367
 
                self.outf.write('\n')
 
339
                print path
368
340
 
369
341
 
370
342
class cmd_mv(Command):
380
352
 
381
353
    Files cannot be moved between branches.
382
354
    """
383
 
 
384
355
    takes_args = ['names*']
385
356
    aliases = ['move', 'rename']
386
 
    encoding_type = 'replace'
387
357
 
388
358
    def run(self, names_list):
389
 
        if names_list is None:
390
 
            names_list = []
391
 
 
392
359
        if len(names_list) < 2:
393
360
            raise BzrCommandError("missing file argument")
394
361
        tree, rel_names = tree_files(names_list)
396
363
        if os.path.isdir(names_list[-1]):
397
364
            # move into existing directory
398
365
            for pair in tree.move(rel_names[:-1], rel_names[-1]):
399
 
                self.outf.write("%s => %s\n" % pair)
 
366
                print "%s => %s" % pair
400
367
        else:
401
368
            if len(names_list) != 2:
402
369
                raise BzrCommandError('to mv multiple files the destination '
403
370
                                      'must be a versioned directory')
404
371
            tree.rename_one(rel_names[0], rel_names[1])
405
 
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
 
372
            print "%s => %s" % (rel_names[0], rel_names[1])
406
373
            
407
374
    
408
375
class cmd_pull(Command):
416
383
    from one into the other.  Once one branch has merged, the other should
417
384
    be able to pull it again.
418
385
 
 
386
    If branches have diverged, you can use 'bzr merge' to pull the text changes
 
387
    from one into the other.  Once one branch has merged, the other should
 
388
    be able to pull it again.
 
389
 
419
390
    If you want to forget your local changes and just update your branch to
420
391
    match the remote one, use pull --overwrite.
421
392
 
422
393
    If there is no default location set, the first pull will set it.  After
423
394
    that, you can omit the location to use the default.  To change the
424
 
    default, use --remember. The value will only be saved if the remote
425
 
    location can be accessed.
 
395
    default, use --remember.
426
396
    """
427
 
 
428
397
    takes_options = ['remember', 'overwrite', 'revision', 'verbose']
429
398
    takes_args = ['location?']
430
 
    encoding_type = 'replace'
431
399
 
432
400
    def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
433
401
        # FIXME: too much stuff is in the command class
436
404
            branch_to = tree_to.branch
437
405
        except NoWorkingTree:
438
406
            tree_to = None
439
 
            branch_to = Branch.open_containing(u'.')[0]
440
 
 
441
 
        reader = None
442
 
        if location is not None:
443
 
            try:
444
 
                reader = bundle.read_bundle_from_url(location)
445
 
            except NotABundle:
446
 
                pass # Continue on considering this url a Branch
447
 
 
 
407
            branch_to = Branch.open_containing(u'.')[0] 
448
408
        stored_loc = branch_to.get_parent()
449
409
        if location is None:
450
410
            if stored_loc is None:
451
411
                raise BzrCommandError("No pull location known or specified.")
452
412
            else:
453
 
                display_url = urlutils.unescape_for_display(stored_loc,
454
 
                        self.outf.encoding)
455
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
413
                print "Using saved location: %s" % stored_loc
456
414
                location = stored_loc
457
415
 
458
 
 
459
 
        if reader is not None:
460
 
            install_bundle(branch_to.repository, reader)
461
 
            branch_from = branch_to
462
 
        else:
463
 
            branch_from = Branch.open(location)
464
 
 
465
 
            if branch_to.get_parent() is None or remember:
466
 
                branch_to.set_parent(branch_from.base)
467
 
 
468
 
        rev_id = None
 
416
        if branch_to.get_parent() is None or remember:
 
417
            branch_to.set_parent(location)
 
418
 
 
419
        branch_from = Branch.open(location)
 
420
 
469
421
        if revision is None:
470
 
            if reader is not None:
471
 
                rev_id = reader.target
 
422
            rev_id = None
472
423
        elif len(revision) == 1:
473
424
            rev_id = revision[0].in_history(branch_from).rev_id
474
425
        else:
486
437
            if old_rh != new_rh:
487
438
                # Something changed
488
439
                from bzrlib.log import show_changed_revisions
489
 
                show_changed_revisions(branch_to, old_rh, new_rh,
490
 
                                       to_file=self.outf)
 
440
                show_changed_revisions(branch_to, old_rh, new_rh)
491
441
 
492
442
 
493
443
class cmd_push(Command):
512
462
 
513
463
    If there is no default push location set, the first push will set it.
514
464
    After that, you can omit the location to use the default.  To change the
515
 
    default, use --remember. The value will only be saved if the remote
516
 
    location can be accessed.
 
465
    default, use --remember.
517
466
    """
518
 
 
519
 
    takes_options = ['remember', 'overwrite', 'verbose',
 
467
    takes_options = ['remember', 'overwrite', 
520
468
                     Option('create-prefix', 
521
469
                            help='Create the path leading up to the branch '
522
470
                                 'if it does not already exist')]
523
471
    takes_args = ['location?']
524
 
    encoding_type = 'replace'
525
472
 
526
473
    def run(self, location=None, remember=False, overwrite=False,
527
474
            create_prefix=False, verbose=False):
528
475
        # FIXME: Way too big!  Put this into a function called from the
529
476
        # command.
 
477
        from bzrlib.transport import get_transport
530
478
        
531
 
        br_from = Branch.open_containing('.')[0]
532
 
        stored_loc = br_from.get_push_location()
 
479
        tree_from = WorkingTree.open_containing(u'.')[0]
 
480
        br_from = tree_from.branch
 
481
        stored_loc = tree_from.branch.get_push_location()
533
482
        if location is None:
534
483
            if stored_loc is None:
535
484
                raise BzrCommandError("No push location known or specified.")
536
485
            else:
537
 
                display_url = urlutils.unescape_for_display(stored_loc,
538
 
                        self.outf.encoding)
539
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
486
                print "Using saved location: %s" % stored_loc
540
487
                location = stored_loc
541
 
 
542
 
        to_transport = transport.get_transport(location)
543
 
        location_url = to_transport.base
544
 
 
545
 
        old_rh = []
 
488
        if br_from.get_push_location() is None or remember:
 
489
            br_from.set_push_location(location)
546
490
        try:
547
 
            dir_to = bzrdir.BzrDir.open(location_url)
 
491
            dir_to = bzrlib.bzrdir.BzrDir.open(location)
548
492
            br_to = dir_to.open_branch()
549
493
        except NotBranchError:
550
494
            # create a branch.
551
 
            to_transport = to_transport.clone('..')
 
495
            transport = get_transport(location).clone('..')
552
496
            if not create_prefix:
553
497
                try:
554
 
                    relurl = to_transport.relpath(location_url)
555
 
                    mutter('creating directory %s => %s', location_url, relurl)
556
 
                    to_transport.mkdir(relurl)
 
498
                    transport.mkdir(transport.relpath(location))
557
499
                except NoSuchFile:
558
500
                    raise BzrCommandError("Parent directory of %s "
559
501
                                          "does not exist." % location)
560
502
            else:
561
 
                current = to_transport.base
562
 
                needed = [(to_transport, to_transport.relpath(location_url))]
 
503
                current = transport.base
 
504
                needed = [(transport, transport.relpath(location))]
563
505
                while needed:
564
506
                    try:
565
 
                        to_transport, relpath = needed[-1]
566
 
                        to_transport.mkdir(relpath)
 
507
                        transport, relpath = needed[-1]
 
508
                        transport.mkdir(relpath)
567
509
                        needed.pop()
568
510
                    except NoSuchFile:
569
 
                        new_transport = to_transport.clone('..')
 
511
                        new_transport = transport.clone('..')
570
512
                        needed.append((new_transport,
571
 
                                       new_transport.relpath(to_transport.base)))
572
 
                        if new_transport.base == to_transport.base:
 
513
                                       new_transport.relpath(transport.base)))
 
514
                        if new_transport.base == transport.base:
573
515
                            raise BzrCommandError("Could not create "
574
516
                                                  "path prefix.")
575
 
            dir_to = br_from.bzrdir.clone(location_url,
576
 
                revision_id=br_from.last_revision())
 
517
            dir_to = br_from.bzrdir.clone(location)
577
518
            br_to = dir_to.open_branch()
578
 
            count = len(br_to.revision_history())
579
 
            # We successfully created the target, remember it
580
 
            if br_from.get_push_location() is None or remember:
581
 
                br_from.set_push_location(br_to.base)
582
 
        else:
583
 
            # We were able to connect to the remote location, so remember it
584
 
            # we don't need to successfully push because of possible divergence.
585
 
            if br_from.get_push_location() is None or remember:
586
 
                br_from.set_push_location(br_to.base)
587
 
            old_rh = br_to.revision_history()
 
519
        old_rh = br_to.revision_history()
 
520
        try:
588
521
            try:
589
 
                try:
590
 
                    tree_to = dir_to.open_workingtree()
591
 
                except errors.NotLocalUrl:
592
 
                    warning('This transport does not update the working '
593
 
                            'tree of: %s' % (br_to.base,))
594
 
                    count = br_to.pull(br_from, overwrite)
595
 
                except NoWorkingTree:
596
 
                    count = br_to.pull(br_from, overwrite)
597
 
                else:
598
 
                    count = tree_to.pull(br_from, overwrite)
599
 
            except DivergedBranches:
600
 
                raise BzrCommandError("These branches have diverged."
601
 
                                      "  Try a merge then push with overwrite.")
 
522
                tree_to = dir_to.open_workingtree()
 
523
            except errors.NotLocalUrl:
 
524
                # TODO: This should be updated for branches which don't have a
 
525
                # working tree, as opposed to ones where we just couldn't 
 
526
                # update the tree.
 
527
                warning('This transport does not update the working '
 
528
                        'tree of: %s' % (br_to.base,))
 
529
                count = br_to.pull(br_from, overwrite)
 
530
            except NoWorkingTree:
 
531
                count = br_to.pull(br_from, overwrite)
 
532
            else:
 
533
                count = tree_to.pull(br_from, overwrite)
 
534
        except DivergedBranches:
 
535
            raise BzrCommandError("These branches have diverged."
 
536
                                  "  Try a merge then push with overwrite.")
602
537
        note('%d revision(s) pushed.' % (count,))
603
538
 
604
539
        if verbose:
606
541
            if old_rh != new_rh:
607
542
                # Something changed
608
543
                from bzrlib.log import show_changed_revisions
609
 
                show_changed_revisions(br_to, old_rh, new_rh,
610
 
                                       to_file=self.outf)
 
544
                show_changed_revisions(br_to, old_rh, new_rh)
611
545
 
612
546
 
613
547
class cmd_branch(Command):
659
593
                name = None
660
594
            else:
661
595
                name = os.path.basename(to_location) + '\n'
662
 
 
663
 
            to_transport = transport.get_transport(to_location)
664
596
            try:
665
 
                to_transport.mkdir('.')
666
 
            except errors.FileExists:
667
 
                raise BzrCommandError('Target directory "%s" already'
668
 
                                      ' exists.' % to_location)
669
 
            except errors.NoSuchFile:
670
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
671
 
                                      to_location)
 
597
                os.mkdir(to_location)
 
598
            except OSError, e:
 
599
                if e.errno == errno.EEXIST:
 
600
                    raise BzrCommandError('Target directory "%s" already'
 
601
                                          ' exists.' % to_location)
 
602
                if e.errno == errno.ENOENT:
 
603
                    raise BzrCommandError('Parent of "%s" does not exist.' %
 
604
                                          to_location)
 
605
                else:
 
606
                    raise
672
607
            try:
673
608
                # preserve whatever source format we have.
674
 
                dir = br_from.bzrdir.sprout(to_transport.base,
675
 
                        revision_id, basis_dir)
 
609
                dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
676
610
                branch = dir.open_branch()
677
 
            except errors.NoSuchRevision:
678
 
                to_transport.delete_tree('.')
 
611
            except bzrlib.errors.NoSuchRevision:
 
612
                rmtree(to_location)
679
613
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
680
614
                raise BzrCommandError(msg)
681
 
            except errors.UnlistableBranch:
682
 
                osutils.rmtree(to_location)
 
615
            except bzrlib.errors.UnlistableBranch:
 
616
                rmtree(to_location)
683
617
                msg = "The branch %s cannot be used as a --basis" % (basis,)
684
618
                raise BzrCommandError(msg)
685
619
            if name:
686
620
                branch.control_files.put_utf8('branch-name', name)
 
621
 
687
622
            note('Branched %d revision(s).' % branch.revno())
688
623
        finally:
689
624
            br_from.unlock()
707
642
 
708
643
    --basis is to speed up checking out from remote branches.  When specified, it
709
644
    uses the inventory and file contents from the basis branch in preference to the
710
 
    branch being checked out.
 
645
    branch being checked out. [Not implemented yet.]
711
646
    """
712
647
    takes_args = ['branch_location?', 'to_location?']
713
648
    takes_options = ['revision', # , 'basis']
719
654
                                 "such access, and also support local commits."
720
655
                            ),
721
656
                     ]
722
 
    aliases = ['co']
723
657
 
724
658
    def run(self, branch_location=None, to_location=None, revision=None, basis=None,
725
659
            lightweight=False):
729
663
            raise BzrCommandError(
730
664
                'bzr checkout --revision takes exactly 1 revision value')
731
665
        if branch_location is None:
732
 
            branch_location = osutils.getcwd()
 
666
            branch_location = bzrlib.osutils.getcwd()
733
667
            to_location = branch_location
734
668
        source = Branch.open(branch_location)
735
669
        if len(revision) == 1 and revision[0] is not None:
741
675
        # if the source and to_location are the same, 
742
676
        # and there is no working tree,
743
677
        # then reconstitute a branch
744
 
        if (osutils.abspath(to_location) == 
745
 
            osutils.abspath(branch_location)):
 
678
        if (bzrlib.osutils.abspath(to_location) == 
 
679
            bzrlib.osutils.abspath(branch_location)):
746
680
            try:
747
681
                source.bzrdir.open_workingtree()
748
682
            except errors.NoWorkingTree:
759
693
                                      to_location)
760
694
            else:
761
695
                raise
762
 
        old_format = bzrdir.BzrDirFormat.get_default_format()
763
 
        bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
 
696
        old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
697
        bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
764
698
        try:
765
699
            if lightweight:
766
700
                checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
767
 
                branch.BranchReferenceFormat().initialize(checkout, source)
 
701
                bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
768
702
            else:
769
 
                checkout_branch =  bzrdir.BzrDir.create_branch_convenience(
 
703
                checkout_branch =  bzrlib.bzrdir.BzrDir.create_branch_convenience(
770
704
                    to_location, force_new_tree=False)
771
705
                checkout = checkout_branch.bzrdir
772
706
                checkout_branch.bind(source)
775
709
                    checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
776
710
            checkout.create_workingtree(revision_id)
777
711
        finally:
778
 
            bzrdir.BzrDirFormat.set_default_format(old_format)
 
712
            bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
779
713
 
780
714
 
781
715
class cmd_renames(Command):
788
722
 
789
723
    @display_command
790
724
    def run(self, dir=u'.'):
791
 
        from bzrlib.tree import find_renames
792
725
        tree = WorkingTree.open_containing(dir)[0]
793
726
        old_inv = tree.basis_tree().inventory
794
727
        new_inv = tree.read_working_inventory()
795
 
        renames = list(find_renames(old_inv, new_inv))
 
728
 
 
729
        renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
796
730
        renames.sort()
797
731
        for old_name, new_name in renames:
798
 
            self.outf.write("%s => %s\n" % (old_name, new_name))
 
732
            print "%s => %s" % (old_name, new_name)        
799
733
 
800
734
 
801
735
class cmd_update(Command):
809
743
    'bzr revert' instead of 'bzr commit' after the update.
810
744
    """
811
745
    takes_args = ['dir?']
812
 
    aliases = ['up']
813
746
 
814
747
    def run(self, dir='.'):
815
748
        tree = WorkingTree.open_containing(dir)[0]
816
749
        tree.lock_write()
817
750
        try:
818
 
            last_rev = tree.last_revision() 
819
 
            if last_rev == tree.branch.last_revision():
 
751
            if tree.last_revision() == tree.branch.last_revision():
820
752
                # may be up to date, check master too.
821
753
                master = tree.branch.get_master_branch()
822
 
                if master is None or last_rev == master.last_revision():
823
 
                    revno = tree.branch.revision_id_to_revno(last_rev)
824
 
                    note("Tree is up to date at revision %d." % (revno,))
825
 
                    return 0
 
754
                if master is None or master.last_revision == tree.last_revision():
 
755
                    note("Tree is up to date.")
 
756
                    return
826
757
            conflicts = tree.update()
827
 
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
828
 
            note('Updated to revision %d.' % (revno,))
 
758
            note('Updated to revision %d.' %
 
759
                 (tree.branch.revision_id_to_revno(tree.last_revision()),))
829
760
            if conflicts != 0:
830
761
                return 1
831
762
            else:
835
766
 
836
767
 
837
768
class cmd_info(Command):
838
 
    """Show information about a working tree, branch or repository.
839
 
 
840
 
    This command will show all known locations and formats associated to the
841
 
    tree, branch or repository.  Statistical information is included with
842
 
    each report.
843
 
 
844
 
    Branches and working trees will also report any missing revisions.
845
 
    """
846
 
    takes_args = ['location?']
 
769
    """Show statistical information about a branch."""
 
770
    takes_args = ['branch?']
847
771
    takes_options = ['verbose']
848
 
 
 
772
    
849
773
    @display_command
850
 
    def run(self, location=None, verbose=False):
851
 
        from bzrlib.info import show_bzrdir_info
852
 
        show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
853
 
                         verbose=verbose)
 
774
    def run(self, branch=None, verbose=False):
 
775
        import bzrlib.info
 
776
        bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0],
 
777
                                     verbose=verbose)
854
778
 
855
779
 
856
780
class cmd_remove(Command):
858
782
 
859
783
    This makes bzr stop tracking changes to a versioned file.  It does
860
784
    not delete the working copy.
861
 
 
862
 
    You can specify one or more files, and/or --new.  If you specify --new,
863
 
    only 'added' files will be removed.  If you specify both, then new files
864
 
    in the specified directories will be removed.  If the directories are
865
 
    also new, they will also be removed.
866
785
    """
867
 
    takes_args = ['file*']
868
 
    takes_options = ['verbose', Option('new', help='remove newly-added files')]
 
786
    takes_args = ['file+']
 
787
    takes_options = ['verbose']
869
788
    aliases = ['rm']
870
 
    encoding_type = 'replace'
871
789
    
872
 
    def run(self, file_list, verbose=False, new=False):
 
790
    def run(self, file_list, verbose=False):
873
791
        tree, file_list = tree_files(file_list)
874
 
        if new is False:
875
 
            if file_list is None:
876
 
                raise BzrCommandError('Specify one or more files to remove, or'
877
 
                                      ' use --new.')
878
 
        else:
879
 
            added = tree.changes_from(tree.basis_tree(),
880
 
                specific_files=file_list).added
881
 
            file_list = sorted([f[0] for f in added], reverse=True)
882
 
            if len(file_list) == 0:
883
 
                raise BzrCommandError('No matching files.')
884
 
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
 
792
        tree.remove(file_list, verbose=verbose)
885
793
 
886
794
 
887
795
class cmd_file_id(Command):
891
799
    same through all revisions where the file exists, even when it is
892
800
    moved or renamed.
893
801
    """
894
 
 
895
802
    hidden = True
896
803
    takes_args = ['filename']
897
 
 
898
804
    @display_command
899
805
    def run(self, filename):
900
806
        tree, relpath = WorkingTree.open_containing(filename)
902
808
        if i == None:
903
809
            raise BzrError("%r is not a versioned file" % filename)
904
810
        else:
905
 
            self.outf.write(i + '\n')
 
811
            print i
906
812
 
907
813
 
908
814
class cmd_file_path(Command):
909
815
    """Print path of file_ids to a file or directory.
910
816
 
911
817
    This prints one line for each directory down to the target,
912
 
    starting at the branch root.
913
 
    """
914
 
 
 
818
    starting at the branch root."""
915
819
    hidden = True
916
820
    takes_args = ['filename']
917
 
 
918
821
    @display_command
919
822
    def run(self, filename):
920
823
        tree, relpath = WorkingTree.open_containing(filename)
923
826
        if fid == None:
924
827
            raise BzrError("%r is not a versioned file" % filename)
925
828
        for fip in inv.get_idpath(fid):
926
 
            self.outf.write(fip + '\n')
 
829
            print fip
927
830
 
928
831
 
929
832
class cmd_reconcile(Command):
948
851
 
949
852
    def run(self, branch="."):
950
853
        from bzrlib.reconcile import reconcile
951
 
        dir = bzrdir.BzrDir.open(branch)
 
854
        dir = bzrlib.bzrdir.BzrDir.open(branch)
952
855
        reconcile(dir)
953
856
 
954
857
 
955
858
class cmd_revision_history(Command):
956
 
    """Display the list of revision ids on a branch."""
957
 
    takes_args = ['location?']
958
 
 
 
859
    """Display list of revision ids on this branch."""
959
860
    hidden = True
960
 
 
961
861
    @display_command
962
 
    def run(self, location="."):
963
 
        branch = Branch.open_containing(location)[0]
964
 
        for revid in branch.revision_history():
965
 
            self.outf.write(revid)
966
 
            self.outf.write('\n')
 
862
    def run(self):
 
863
        branch = WorkingTree.open_containing(u'.')[0].branch
 
864
        for patchid in branch.revision_history():
 
865
            print patchid
967
866
 
968
867
 
969
868
class cmd_ancestry(Command):
970
869
    """List all revisions merged into this branch."""
971
 
    takes_args = ['location?']
972
 
 
973
870
    hidden = True
974
 
 
975
871
    @display_command
976
 
    def run(self, location="."):
977
 
        try:
978
 
            wt = WorkingTree.open_containing(location)[0]
979
 
        except errors.NoWorkingTree:
980
 
            b = Branch.open(location)
981
 
            last_revision = b.last_revision()
982
 
        else:
983
 
            b = wt.branch
984
 
            last_revision = wt.last_revision()
985
 
 
986
 
        revision_ids = b.repository.get_ancestry(last_revision)
987
 
        assert revision_ids[0] == None
988
 
        revision_ids.pop(0)
989
 
        for revision_id in revision_ids:
990
 
            self.outf.write(revision_id + '\n')
 
872
    def run(self):
 
873
        tree = WorkingTree.open_containing(u'.')[0]
 
874
        b = tree.branch
 
875
        # FIXME. should be tree.last_revision
 
876
        for revision_id in b.repository.get_ancestry(b.last_revision()):
 
877
            print revision_id
991
878
 
992
879
 
993
880
class cmd_init(Command):
1014
901
    takes_args = ['location?']
1015
902
    takes_options = [
1016
903
                     Option('format', 
1017
 
                            help='Specify a format for this branch. Current'
1018
 
                                 ' formats are: default, knit, metaweave and'
1019
 
                                 ' weave. Default is knit; metaweave and'
1020
 
                                 ' weave are deprecated',
 
904
                            help='Create a specific format rather than the'
 
905
                                 ' current default format. Currently this '
 
906
                                 ' option only accepts "metadir"',
1021
907
                            type=get_format_type),
1022
908
                     ]
1023
909
    def run(self, location=None, format=None):
1024
 
        if format is None:
1025
 
            format = get_format_type('default')
 
910
        from bzrlib.branch import Branch
1026
911
        if location is None:
1027
912
            location = u'.'
1028
 
 
1029
 
        to_transport = transport.get_transport(location)
1030
 
 
1031
 
        # The path has to exist to initialize a
1032
 
        # branch inside of it.
1033
 
        # Just using os.mkdir, since I don't
1034
 
        # believe that we want to create a bunch of
1035
 
        # locations if the user supplies an extended path
1036
 
        # TODO: create-prefix
1037
 
        try:
1038
 
            to_transport.mkdir('.')
1039
 
        except errors.FileExists:
1040
 
            pass
1041
 
                    
 
913
        else:
 
914
            # The path has to exist to initialize a
 
915
            # branch inside of it.
 
916
            # Just using os.mkdir, since I don't
 
917
            # believe that we want to create a bunch of
 
918
            # locations if the user supplies an extended path
 
919
            if not os.path.exists(location):
 
920
                os.mkdir(location)
1042
921
        try:
1043
922
            existing_bzrdir = bzrdir.BzrDir.open(location)
1044
923
        except NotBranchError:
1046
925
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1047
926
        else:
1048
927
            if existing_bzrdir.has_branch():
1049
 
                if (isinstance(to_transport, LocalTransport)
1050
 
                    and not existing_bzrdir.has_workingtree()):
1051
 
                        raise errors.BranchExistsWithoutWorkingTree(location)
1052
 
                raise errors.AlreadyBranchError(location)
 
928
                if existing_bzrdir.has_workingtree():
 
929
                    raise errors.AlreadyBranchError(location)
 
930
                else:
 
931
                    raise errors.BranchExistsWithoutWorkingTree(location)
1053
932
            else:
1054
933
                existing_bzrdir.create_branch()
1055
934
                existing_bzrdir.create_workingtree()
1071
950
    """
1072
951
    takes_args = ["location"] 
1073
952
    takes_options = [Option('format', 
1074
 
                            help='Specify a format for this repository.'
1075
 
                                 ' Current formats are: default, knit,'
1076
 
                                 ' metaweave and weave. Default is knit;'
1077
 
                                 ' metaweave and weave are deprecated',
 
953
                            help='Use a specific format rather than the'
 
954
                            ' current default format. Currently this'
 
955
                            ' option accepts "weave", "metadir" and "knit"',
1078
956
                            type=get_format_type),
1079
957
                     Option('trees',
1080
958
                             help='Allows branches in repository to have'
1081
959
                             ' a working tree')]
1082
960
    aliases = ["init-repo"]
1083
961
    def run(self, location, format=None, trees=False):
 
962
        from bzrlib.bzrdir import BzrDirMetaFormat1
 
963
        from bzrlib.transport import get_transport
1084
964
        if format is None:
1085
 
            format = get_format_type('default')
1086
 
 
1087
 
        if location is None:
1088
 
            location = '.'
1089
 
 
1090
 
        to_transport = transport.get_transport(location)
1091
 
        try:
1092
 
            to_transport.mkdir('.')
1093
 
        except errors.FileExists:
1094
 
            pass
1095
 
 
1096
 
        newdir = format.initialize_on_transport(to_transport)
 
965
            format = BzrDirMetaFormat1()
 
966
        transport = get_transport(location)
 
967
        if not transport.has('.'):
 
968
            transport.mkdir('')
 
969
        newdir = format.initialize_on_transport(transport)
1097
970
        repo = newdir.create_repository(shared=True)
1098
971
        repo.set_make_working_trees(trees)
1099
972
 
1100
973
 
1101
974
class cmd_diff(Command):
1102
 
    """Show differences in the working tree or between revisions.
 
975
    """Show differences in working tree.
1103
976
    
1104
977
    If files are listed, only the changes in those files are listed.
1105
978
    Otherwise, all changes for the tree are listed.
1106
979
 
1107
 
    "bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1108
 
    produces patches suitable for "patch -p1".
1109
 
 
1110
980
    examples:
1111
981
        bzr diff
1112
 
            Shows the difference in the working tree versus the last commit
1113
982
        bzr diff -r1
1114
 
            Difference between the working tree and revision 1
1115
983
        bzr diff -r1..2
1116
 
            Difference between revision 2 and revision 1
1117
 
        bzr diff --diff-prefix old/:new/
1118
 
            Same as 'bzr diff' but prefix paths with old/ and new/
1119
 
        bzr diff bzr.mine bzr.dev
1120
 
            Show the differences between the two working trees
1121
 
        bzr diff foo.c
1122
 
            Show just the differences for 'foo.c'
1123
984
    """
 
985
    # TODO: Allow diff across branches.
1124
986
    # TODO: Option to use external diff command; could be GNU diff, wdiff,
1125
987
    #       or a graphical diff.
1126
988
 
1127
989
    # TODO: Python difflib is not exactly the same as unidiff; should
1128
990
    #       either fix it up or prefer to use an external diff.
1129
991
 
 
992
    # TODO: If a directory is given, diff everything under that.
 
993
 
1130
994
    # TODO: Selected-file diff is inefficient and doesn't show you
1131
995
    #       deleted files.
1132
996
 
1133
997
    # TODO: This probably handles non-Unix newlines poorly.
1134
998
    
1135
999
    takes_args = ['file*']
1136
 
    takes_options = ['revision', 'diff-options', 'prefix']
 
1000
    takes_options = ['revision', 'diff-options']
1137
1001
    aliases = ['di', 'dif']
1138
 
    encoding_type = 'exact'
1139
1002
 
1140
1003
    @display_command
1141
 
    def run(self, revision=None, file_list=None, diff_options=None,
1142
 
            prefix=None):
 
1004
    def run(self, revision=None, file_list=None, diff_options=None):
1143
1005
        from bzrlib.diff import diff_cmd_helper, show_diff_trees
1144
 
 
1145
 
        if (prefix is None) or (prefix == '0'):
1146
 
            # diff -p0 format
1147
 
            old_label = ''
1148
 
            new_label = ''
1149
 
        elif prefix == '1':
1150
 
            old_label = 'old/'
1151
 
            new_label = 'new/'
1152
 
        else:
1153
 
            if not ':' in prefix:
1154
 
                 raise BzrError("--diff-prefix expects two values separated by a colon")
1155
 
            old_label, new_label = prefix.split(":")
1156
 
        
1157
1006
        try:
1158
1007
            tree1, file_list = internal_tree_files(file_list)
1159
1008
            tree2 = None
1169
1018
                # FIXME diff those two files. rbc 20051123
1170
1019
                raise BzrCommandError("Files are in different branches")
1171
1020
            file_list = None
1172
 
        except NotBranchError:
1173
 
            if (revision is not None and len(revision) == 2
1174
 
                and not revision[0].needs_branch()
1175
 
                and not revision[1].needs_branch()):
1176
 
                # If both revision specs include a branch, we can
1177
 
                # diff them without needing a local working tree
1178
 
                tree1, tree2 = None, None
1179
 
            else:
1180
 
                raise
1181
1021
        if revision is not None:
1182
1022
            if tree2 is not None:
1183
1023
                raise BzrCommandError("Can't specify -r with two branches")
1184
1024
            if (len(revision) == 1) or (revision[1].spec is None):
1185
1025
                return diff_cmd_helper(tree1, file_list, diff_options,
1186
 
                                       revision[0], 
1187
 
                                       old_label=old_label, new_label=new_label)
 
1026
                                       revision[0])
1188
1027
            elif len(revision) == 2:
1189
1028
                return diff_cmd_helper(tree1, file_list, diff_options,
1190
 
                                       revision[0], revision[1],
1191
 
                                       old_label=old_label, new_label=new_label)
 
1029
                                       revision[0], revision[1])
1192
1030
            else:
1193
1031
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1194
1032
        else:
1195
1033
            if tree2 is not None:
1196
1034
                return show_diff_trees(tree1, tree2, sys.stdout, 
1197
1035
                                       specific_files=file_list,
1198
 
                                       external_diff_options=diff_options,
1199
 
                                       old_label=old_label, new_label=new_label)
 
1036
                                       external_diff_options=diff_options)
1200
1037
            else:
1201
 
                return diff_cmd_helper(tree1, file_list, diff_options,
1202
 
                                       old_label=old_label, new_label=new_label)
 
1038
                return diff_cmd_helper(tree1, file_list, diff_options)
1203
1039
 
1204
1040
 
1205
1041
class cmd_deleted(Command):
1211
1047
    # directories with readdir, rather than stating each one.  Same
1212
1048
    # level of effort but possibly much less IO.  (Or possibly not,
1213
1049
    # if the directories are very large...)
1214
 
    takes_options = ['show-ids']
1215
 
 
1216
1050
    @display_command
1217
1051
    def run(self, show_ids=False):
1218
1052
        tree = WorkingTree.open_containing(u'.')[0]
1219
1053
        old = tree.basis_tree()
1220
1054
        for path, ie in old.inventory.iter_entries():
1221
1055
            if not tree.has_id(ie.file_id):
1222
 
                self.outf.write(path)
1223
1056
                if show_ids:
1224
 
                    self.outf.write(' ')
1225
 
                    self.outf.write(ie.file_id)
1226
 
                self.outf.write('\n')
 
1057
                    print '%-50s %s' % (path, ie.file_id)
 
1058
                else:
 
1059
                    print path
1227
1060
 
1228
1061
 
1229
1062
class cmd_modified(Command):
1231
1064
    hidden = True
1232
1065
    @display_command
1233
1066
    def run(self):
 
1067
        from bzrlib.delta import compare_trees
 
1068
 
1234
1069
        tree = WorkingTree.open_containing(u'.')[0]
1235
 
        td = tree.changes_from(tree.basis_tree())
 
1070
        td = compare_trees(tree.basis_tree(), tree)
 
1071
 
1236
1072
        for path, id, kind, text_modified, meta_modified in td.modified:
1237
 
            self.outf.write(path + '\n')
 
1073
            print path
 
1074
 
1238
1075
 
1239
1076
 
1240
1077
class cmd_added(Command):
1249
1086
            if file_id in basis_inv:
1250
1087
                continue
1251
1088
            path = inv.id2path(file_id)
1252
 
            if not os.access(osutils.abspath(path), os.F_OK):
 
1089
            if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
1253
1090
                continue
1254
 
            self.outf.write(path + '\n')
1255
 
 
 
1091
            print path
 
1092
                
 
1093
        
1256
1094
 
1257
1095
class cmd_root(Command):
1258
1096
    """Show the tree root directory.
1264
1102
    def run(self, filename=None):
1265
1103
        """Print the branch root."""
1266
1104
        tree = WorkingTree.open_containing(filename)[0]
1267
 
        self.outf.write(tree.basedir + '\n')
 
1105
        print tree.basedir
1268
1106
 
1269
1107
 
1270
1108
class cmd_log(Command):
1298
1136
                            type=str),
1299
1137
                     'short',
1300
1138
                     ]
1301
 
    encoding_type = 'replace'
1302
 
 
1303
1139
    @display_command
1304
1140
    def run(self, location=None, timezone='original',
1305
1141
            verbose=False,
1312
1148
            short=False,
1313
1149
            line=False):
1314
1150
        from bzrlib.log import log_formatter, show_log
 
1151
        import codecs
1315
1152
        assert message is None or isinstance(message, basestring), \
1316
1153
            "invalid message argument %r" % message
1317
1154
        direction = (forward and 'forward') or 'reverse'
1363
1200
        if rev1 > rev2:
1364
1201
            (rev2, rev1) = (rev1, rev2)
1365
1202
 
 
1203
        mutter('encoding log as %r', bzrlib.user_encoding)
 
1204
 
 
1205
        # use 'replace' so that we don't abort if trying to write out
 
1206
        # in e.g. the default C locale.
 
1207
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
 
1208
 
1366
1209
        if (log_format == None):
1367
 
            default = b.get_config().log_format()
1368
 
            log_format = get_log_format(long=long, short=short, line=line, 
1369
 
                                        default=default)
 
1210
            default = bzrlib.config.BranchConfig(b).log_format()
 
1211
            log_format = get_log_format(long=long, short=short, line=line, default=default)
 
1212
 
1370
1213
        lf = log_formatter(log_format,
1371
1214
                           show_ids=show_ids,
1372
 
                           to_file=self.outf,
 
1215
                           to_file=outf,
1373
1216
                           show_timezone=timezone)
1374
1217
 
1375
1218
        show_log(b,
1396
1239
class cmd_touching_revisions(Command):
1397
1240
    """Return revision-ids which affected a particular file.
1398
1241
 
1399
 
    A more user-friendly interface is "bzr log FILE".
1400
 
    """
1401
 
 
 
1242
    A more user-friendly interface is "bzr log FILE"."""
1402
1243
    hidden = True
1403
1244
    takes_args = ["filename"]
1404
 
 
1405
1245
    @display_command
1406
1246
    def run(self, filename):
1407
1247
        tree, relpath = WorkingTree.open_containing(filename)
1408
1248
        b = tree.branch
1409
1249
        inv = tree.read_working_inventory()
1410
1250
        file_id = inv.path2id(relpath)
1411
 
        for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1412
 
            self.outf.write("%6d %s\n" % (revno, what))
 
1251
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
 
1252
            print "%6d %s" % (revno, what)
1413
1253
 
1414
1254
 
1415
1255
class cmd_ls(Command):
1448
1288
        if revision is not None:
1449
1289
            tree = tree.branch.repository.revision_tree(
1450
1290
                revision[0].in_history(tree.branch).rev_id)
1451
 
 
1452
1291
        for fp, fc, kind, fid, entry in tree.list_files():
1453
1292
            if fp.startswith(relpath):
1454
1293
                fp = fp[len(relpath):]
1458
1297
                    continue
1459
1298
                if verbose:
1460
1299
                    kindch = entry.kind_character()
1461
 
                    self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
 
1300
                    print '%-8s %s%s' % (fc, fp, kindch)
1462
1301
                elif null:
1463
 
                    self.outf.write(fp + '\0')
1464
 
                    self.outf.flush()
 
1302
                    sys.stdout.write(fp)
 
1303
                    sys.stdout.write('\0')
 
1304
                    sys.stdout.flush()
1465
1305
                else:
1466
 
                    self.outf.write(fp + '\n')
 
1306
                    print fp
1467
1307
 
1468
1308
 
1469
1309
class cmd_unknowns(Command):
1470
1310
    """List unknown files."""
1471
1311
    @display_command
1472
1312
    def run(self):
 
1313
        from bzrlib.osutils import quotefn
1473
1314
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
1474
 
            self.outf.write(osutils.quotefn(f) + '\n')
 
1315
            print quotefn(f)
1475
1316
 
1476
1317
 
1477
1318
class cmd_ignore(Command):
1493
1334
        bzr ignore '*.class'
1494
1335
    """
1495
1336
    # TODO: Complain if the filename is absolute
1496
 
    takes_args = ['name_pattern?']
1497
 
    takes_options = [
1498
 
                     Option('old-default-rules',
1499
 
                            help='Out the ignore rules bzr < 0.9 always used.')
1500
 
                     ]
 
1337
    takes_args = ['name_pattern']
1501
1338
    
1502
 
    def run(self, name_pattern=None, old_default_rules=None):
 
1339
    def run(self, name_pattern):
1503
1340
        from bzrlib.atomicfile import AtomicFile
1504
 
        if old_default_rules is not None:
1505
 
            # dump the rules and exit
1506
 
            for pattern in ignores.OLD_DEFAULTS:
1507
 
                print pattern
1508
 
            return
1509
 
        if name_pattern is None:
1510
 
            raise BzrCommandError("ignore requires a NAME_PATTERN")
 
1341
        import os.path
 
1342
 
1511
1343
        tree, relpath = WorkingTree.open_containing(u'.')
1512
1344
        ifn = tree.abspath('.bzrignore')
 
1345
 
1513
1346
        if os.path.exists(ifn):
1514
1347
            f = open(ifn, 'rt')
1515
1348
            try:
1526
1359
            igns += '\n'
1527
1360
        igns += name_pattern + '\n'
1528
1361
 
1529
 
        f = AtomicFile(ifn, 'wt')
1530
1362
        try:
 
1363
            f = AtomicFile(ifn, 'wt')
1531
1364
            f.write(igns.encode('utf-8'))
1532
1365
            f.commit()
1533
1366
        finally:
1600
1433
    takes_args = ['dest']
1601
1434
    takes_options = ['revision', 'format', 'root']
1602
1435
    def run(self, dest, revision=None, format=None, root=None):
 
1436
        import os.path
1603
1437
        from bzrlib.export import export
1604
1438
        tree = WorkingTree.open_containing(u'.')[0]
1605
1439
        b = tree.branch
1648
1482
    hidden = True    
1649
1483
    @display_command
1650
1484
    def run(self):
1651
 
        print osutils.local_time_offset()
 
1485
        print bzrlib.osutils.local_time_offset()
1652
1486
 
1653
1487
 
1654
1488
 
1701
1535
        from bzrlib.msgeditor import edit_commit_message, \
1702
1536
                make_commit_message_template
1703
1537
        from tempfile import TemporaryFile
 
1538
        import codecs
1704
1539
 
1705
1540
        # TODO: Need a blackbox test for invoking the external editor; may be
1706
1541
        # slightly problematic to run this cross-platform.
1711
1546
        # TODO: if the commit *does* happen to fail, then save the commit 
1712
1547
        # message to a temporary file where it can be recovered
1713
1548
        tree, selected_list = tree_files(selected_list)
1714
 
        if selected_list == ['']:
1715
 
            # workaround - commit of root of tree should be exactly the same
1716
 
            # as just default commit in that tree, and succeed even though
1717
 
            # selected-file merge commit is not done yet
1718
 
            selected_list = []
1719
 
 
1720
1549
        if local and not tree.branch.get_bound_location():
1721
1550
            raise errors.LocalRequiresBoundBranch()
1722
1551
        if message is None and not file:
1729
1558
            raise BzrCommandError("please specify either --message or --file")
1730
1559
        
1731
1560
        if file:
 
1561
            import codecs
1732
1562
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1733
1563
 
1734
1564
        if message == "":
1735
 
            raise BzrCommandError("empty commit message specified")
 
1565
                raise BzrCommandError("empty commit message specified")
1736
1566
        
1737
1567
        if verbose:
1738
1568
            reporter = ReportCommitToLog()
1746
1576
        except PointlessCommit:
1747
1577
            # FIXME: This should really happen before the file is read in;
1748
1578
            # perhaps prepare the commit; get the message; then actually commit
1749
 
            raise BzrCommandError("no changes to commit."
1750
 
                                  " use --unchanged to commit anyhow")
 
1579
            raise BzrCommandError("no changes to commit",
 
1580
                                  ["use --unchanged to commit anyhow"])
1751
1581
        except ConflictsInTree:
1752
1582
            raise BzrCommandError("Conflicts detected in working tree.  "
1753
1583
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1808
1638
    takes_args = ['url?']
1809
1639
    takes_options = [
1810
1640
                     Option('format', 
1811
 
                            help='Upgrade to a specific format. Current formats'
1812
 
                                 ' are: default, knit, metaweave and weave.'
1813
 
                                 ' Default is knit; metaweave and weave are'
1814
 
                                 ' deprecated',
 
1641
                            help='Upgrade to a specific format rather than the'
 
1642
                                 ' current default format. Currently this'
 
1643
                                 ' option accepts "weave", "metadir" and'
 
1644
                                 ' "knit".',
1815
1645
                            type=get_format_type),
1816
1646
                    ]
1817
1647
 
1818
1648
 
1819
1649
    def run(self, url='.', format=None):
1820
1650
        from bzrlib.upgrade import upgrade
1821
 
        if format is None:
1822
 
            format = get_format_type('default')
1823
1651
        upgrade(url, format)
1824
1652
 
1825
1653
 
1826
1654
class cmd_whoami(Command):
1827
 
    """Show or set bzr user id.
1828
 
    
1829
 
    examples:
1830
 
        bzr whoami --email
1831
 
        bzr whoami 'Frank Chu <fchu@example.com>'
1832
 
    """
1833
 
    takes_options = [ Option('email',
1834
 
                             help='display email address only'),
1835
 
                      Option('branch',
1836
 
                             help='set identity for the current branch instead of '
1837
 
                                  'globally'),
1838
 
                    ]
1839
 
    takes_args = ['name?']
1840
 
    encoding_type = 'replace'
 
1655
    """Show bzr user id."""
 
1656
    takes_options = ['email']
1841
1657
    
1842
1658
    @display_command
1843
 
    def run(self, email=False, branch=False, name=None):
1844
 
        if name is None:
1845
 
            # use branch if we're inside one; otherwise global config
1846
 
            try:
1847
 
                c = Branch.open_containing('.')[0].get_config()
1848
 
            except NotBranchError:
1849
 
                c = config.GlobalConfig()
1850
 
            if email:
1851
 
                self.outf.write(c.user_email() + '\n')
1852
 
            else:
1853
 
                self.outf.write(c.username() + '\n')
1854
 
            return
1855
 
 
1856
 
        # display a warning if an email address isn't included in the given name.
 
1659
    def run(self, email=False):
1857
1660
        try:
1858
 
            config.extract_email_address(name)
1859
 
        except BzrError, e:
1860
 
            warning('"%s" does not seem to contain an email address.  '
1861
 
                    'This is allowed, but not recommended.', name)
 
1661
            b = WorkingTree.open_containing(u'.')[0].branch
 
1662
            config = bzrlib.config.BranchConfig(b)
 
1663
        except NotBranchError:
 
1664
            config = bzrlib.config.GlobalConfig()
1862
1665
        
1863
 
        # use global config unless --branch given
1864
 
        if branch:
1865
 
            c = Branch.open_containing('.')[0].get_config()
 
1666
        if email:
 
1667
            print config.user_email()
1866
1668
        else:
1867
 
            c = config.GlobalConfig()
1868
 
        c.set_user_option('email', name)
 
1669
            print config.username()
1869
1670
 
1870
1671
 
1871
1672
class cmd_nick(Command):
1936
1737
                            help='Use a different transport by default '
1937
1738
                                 'throughout the test suite.',
1938
1739
                            type=get_transport_type),
1939
 
                     Option('benchmark', help='run the bzr bencharks.'),
1940
 
                     Option('lsprof-timed',
1941
 
                            help='generate lsprof output for benchmarked'
1942
 
                                 ' sections of code.'),
1943
 
                     ]
 
1740
                    ]
1944
1741
 
1945
 
    def run(self, testspecs_list=None, verbose=None, one=False,
1946
 
            keep_output=False, transport=None, benchmark=None,
1947
 
            lsprof_timed=None):
 
1742
    def run(self, testspecs_list=None, verbose=False, one=False,
 
1743
            keep_output=False, transport=None):
1948
1744
        import bzrlib.ui
1949
1745
        from bzrlib.tests import selftest
1950
 
        import bzrlib.benchmarks as benchmarks
1951
1746
        # we don't want progress meters from the tests to go to the
1952
1747
        # real output; and we don't want log messages cluttering up
1953
1748
        # the real logs.
1954
 
        save_ui = ui.ui_factory
1955
 
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1956
 
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1957
 
        print
1958
 
        info('running tests...')
 
1749
        save_ui = bzrlib.ui.ui_factory
 
1750
        bzrlib.trace.info('running tests...')
1959
1751
        try:
1960
 
            ui.ui_factory = ui.SilentUIFactory()
 
1752
            bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1961
1753
            if testspecs_list is not None:
1962
1754
                pattern = '|'.join(testspecs_list)
1963
1755
            else:
1964
1756
                pattern = ".*"
1965
 
            if benchmark:
1966
 
                test_suite_factory = benchmarks.test_suite
1967
 
                if verbose is None:
1968
 
                    verbose = True
1969
 
            else:
1970
 
                test_suite_factory = None
1971
 
                if verbose is None:
1972
 
                    verbose = False
1973
1757
            result = selftest(verbose=verbose, 
1974
1758
                              pattern=pattern,
1975
1759
                              stop_on_failure=one, 
1976
1760
                              keep_output=keep_output,
1977
 
                              transport=transport,
1978
 
                              test_suite_factory=test_suite_factory,
1979
 
                              lsprof_timed=lsprof_timed)
 
1761
                              transport=transport)
1980
1762
            if result:
1981
 
                info('tests passed')
 
1763
                bzrlib.trace.info('tests passed')
1982
1764
            else:
1983
 
                info('tests failed')
 
1765
                bzrlib.trace.info('tests failed')
1984
1766
            return int(not result)
1985
1767
        finally:
1986
 
            ui.ui_factory = save_ui
 
1768
            bzrlib.ui.ui_factory = save_ui
1987
1769
 
1988
1770
 
1989
1771
def _get_bzr_branch():
1990
1772
    """If bzr is run from a branch, return Branch or None"""
 
1773
    import bzrlib.errors
 
1774
    from bzrlib.branch import Branch
 
1775
    from bzrlib.osutils import abspath
1991
1776
    from os.path import dirname
1992
1777
    
1993
1778
    try:
1994
 
        branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
 
1779
        branch = Branch.open(dirname(abspath(dirname(__file__))))
1995
1780
        return branch
1996
 
    except errors.BzrError:
 
1781
    except bzrlib.errors.BzrError:
1997
1782
        return None
1998
1783
    
1999
1784
 
2000
1785
def show_version():
2001
 
    import bzrlib
2002
 
    print "Bazaar (bzr) %s" % bzrlib.__version__
 
1786
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
2003
1787
    # is bzrlib itself in a branch?
2004
1788
    branch = _get_bzr_branch()
2005
1789
    if branch:
2009
1793
        print "  nick: %s" % (branch.nick,)
2010
1794
        if rh:
2011
1795
            print "  revid: %s" % (rh[-1],)
2012
 
    print "Using python interpreter:", sys.executable
2013
 
    import site
2014
 
    print "Using python standard library:", os.path.dirname(site.__file__)
2015
 
    print "Using bzrlib:",
2016
 
    if len(bzrlib.__path__) > 1:
2017
 
        # print repr, which is a good enough way of making it clear it's
2018
 
        # more than one element (eg ['/foo/bar', '/foo/bzr'])
2019
 
        print repr(bzrlib.__path__)
2020
 
    else:
2021
 
        print bzrlib.__path__[0]
2022
 
 
2023
 
    print
2024
1796
    print bzrlib.__copyright__
2025
 
    print "http://bazaar-vcs.org/"
 
1797
    print "http://bazaar-ng.org/"
2026
1798
    print
2027
1799
    print "bzr comes with ABSOLUTELY NO WARRANTY.  bzr is free software, and"
2028
1800
    print "you may use, modify and redistribute it under the terms of the GNU"
2031
1803
 
2032
1804
class cmd_version(Command):
2033
1805
    """Show version of bzr."""
2034
 
 
2035
1806
    @display_command
2036
1807
    def run(self):
2037
1808
        show_version()
2038
1809
 
2039
 
 
2040
1810
class cmd_rocks(Command):
2041
1811
    """Statement of optimism."""
2042
 
 
2043
1812
    hidden = True
2044
 
 
2045
1813
    @display_command
2046
1814
    def run(self):
2047
1815
        print "it sure does!"
2048
1816
 
2049
1817
 
2050
1818
class cmd_find_merge_base(Command):
2051
 
    """Find and print a base revision for merging two branches."""
 
1819
    """Find and print a base revision for merging two branches.
 
1820
    """
2052
1821
    # TODO: Options to specify revisions on either side, as if
2053
1822
    #       merging only part of the history.
2054
1823
    takes_args = ['branch', 'other']
2073
1842
        base_rev_id = common_ancestor(last1, last2, source)
2074
1843
 
2075
1844
        print 'merge base is revision %s' % base_rev_id
 
1845
        
 
1846
        return
 
1847
 
 
1848
        if base_revno is None:
 
1849
            raise bzrlib.errors.UnrelatedBranches()
 
1850
 
 
1851
        print ' r%-6d in %s' % (base_revno, branch)
 
1852
 
 
1853
        other_revno = branch2.revision_id_to_revno(base_revid)
 
1854
        
 
1855
        print ' r%-6d in %s' % (other_revno, other)
 
1856
 
2076
1857
 
2077
1858
 
2078
1859
class cmd_merge(Command):
2079
1860
    """Perform a three-way merge.
2080
1861
    
2081
 
    The branch is the branch you will merge from.  By default, it will merge
2082
 
    the latest revision.  If you specify a revision, that revision will be
2083
 
    merged.  If you specify two revisions, the first will be used as a BASE,
2084
 
    and the second one as OTHER.  Revision numbers are always relative to the
2085
 
    specified branch.
 
1862
    The branch is the branch you will merge from.  By default, it will
 
1863
    merge the latest revision.  If you specify a revision, that
 
1864
    revision will be merged.  If you specify two revisions, the first
 
1865
    will be used as a BASE, and the second one as OTHER.  Revision
 
1866
    numbers are always relative to the specified branch.
2086
1867
 
2087
1868
    By default, bzr will try to merge in all new work from the other
2088
1869
    branch, automatically determining an appropriate base.  If this
2097
1878
 
2098
1879
    If there is no default branch set, the first merge will set it. After
2099
1880
    that, you can omit the branch to use the default.  To change the
2100
 
    default, use --remember. The value will only be saved if the remote
2101
 
    location can be accessed.
 
1881
    default, use --remember.
2102
1882
 
2103
1883
    Examples:
2104
1884
 
2113
1893
    
2114
1894
    merge refuses to run if there are any uncommitted changes, unless
2115
1895
    --force is given.
2116
 
 
2117
 
    The following merge types are available:
2118
1896
    """
2119
1897
    takes_args = ['branch?']
2120
1898
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2121
1899
                     Option('show-base', help="Show base revision text in "
2122
1900
                            "conflicts")]
2123
1901
 
2124
 
    def help(self):
2125
 
        from merge import merge_type_help
2126
 
        from inspect import getdoc
2127
 
        return getdoc(self) + '\n' + merge_type_help() 
2128
 
 
2129
1902
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2130
1903
            show_base=False, reprocess=False, remember=False):
2131
1904
        if merge_type is None:
2132
1905
            merge_type = Merge3Merger
2133
1906
 
2134
1907
        tree = WorkingTree.open_containing(u'.')[0]
2135
 
 
2136
 
        if branch is not None:
2137
 
            try:
2138
 
                reader = bundle.read_bundle_from_url(branch)
2139
 
            except NotABundle:
2140
 
                pass # Continue on considering this url a Branch
 
1908
        stored_loc = tree.branch.get_parent()
 
1909
        if branch is None:
 
1910
            if stored_loc is None:
 
1911
                raise BzrCommandError("No merge branch known or specified.")
2141
1912
            else:
2142
 
                conflicts = merge_bundle(reader, tree, not force, merge_type,
2143
 
                                            reprocess, show_base)
2144
 
                if conflicts == 0:
2145
 
                    return 0
2146
 
                else:
2147
 
                    return 1
 
1913
                print "Using saved branch: %s" % stored_loc
 
1914
                branch = stored_loc
2148
1915
 
2149
 
        branch = self._get_remembered_parent(tree, branch, 'Merging from')
 
1916
        if tree.branch.get_parent() is None or remember:
 
1917
            tree.branch.set_parent(branch)
2150
1918
 
2151
1919
        if revision is None or len(revision) < 1:
2152
1920
            base = [None, None]
2163
1931
                if None in revision:
2164
1932
                    raise BzrCommandError(
2165
1933
                        "Merge doesn't permit that revision specifier.")
2166
 
                other_branch, path = Branch.open_containing(branch)
2167
 
 
2168
 
                base = [branch, revision[0].in_history(other_branch).revno]
2169
 
                other = [branch, revision[1].in_history(other_branch).revno]
2170
 
 
2171
 
        if tree.branch.get_parent() is None or remember:
2172
 
            tree.branch.set_parent(other_branch.base)
2173
 
 
 
1934
                b, path = Branch.open_containing(branch)
 
1935
 
 
1936
                base = [branch, revision[0].in_history(b).revno]
 
1937
                other = [branch, revision[1].in_history(b).revno]
2174
1938
        if path != "":
2175
1939
            interesting_files = [path]
2176
1940
        else:
2177
1941
            interesting_files = None
2178
 
        pb = ui.ui_factory.nested_progress_bar()
 
1942
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
2179
1943
        try:
2180
1944
            try:
2181
1945
                conflict_count = merge(other, base, check_clean=(not force),
2182
 
                                       merge_type=merge_type,
 
1946
                                       merge_type=merge_type, 
2183
1947
                                       reprocess=reprocess,
2184
 
                                       show_base=show_base,
 
1948
                                       show_base=show_base, 
2185
1949
                                       pb=pb, file_list=interesting_files)
2186
1950
            finally:
2187
1951
                pb.finished()
2189
1953
                return 1
2190
1954
            else:
2191
1955
                return 0
2192
 
        except errors.AmbiguousBase, e:
 
1956
        except bzrlib.errors.AmbiguousBase, e:
2193
1957
            m = ("sorry, bzr can't determine the right merge base yet\n"
2194
1958
                 "candidates are:\n  "
2195
1959
                 + "\n  ".join(e.bases)
2198
1962
                 "and (if you want) report this to the bzr developers\n")
2199
1963
            log_error(m)
2200
1964
 
2201
 
    # TODO: move up to common parent; this isn't merge-specific anymore. 
2202
 
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
2203
 
        """Use tree.branch's parent if none was supplied.
2204
 
 
2205
 
        Report if the remembered location was used.
2206
 
        """
2207
 
        if supplied_location is not None:
2208
 
            return supplied_location
2209
 
        stored_location = tree.branch.get_parent()
2210
 
        mutter("%s", stored_location)
2211
 
        if stored_location is None:
2212
 
            raise BzrCommandError("No location specified or remembered")
2213
 
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2214
 
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2215
 
        return stored_location
2216
 
 
2217
1965
 
2218
1966
class cmd_remerge(Command):
2219
1967
    """Redo a merge.
2220
 
 
2221
 
    Use this if you want to try a different merge technique while resolving
2222
 
    conflicts.  Some merge techniques are better than others, and remerge 
2223
 
    lets you try different ones on different files.
2224
 
 
2225
 
    The options for remerge have the same meaning and defaults as the ones for
2226
 
    merge.  The difference is that remerge can (only) be run when there is a
2227
 
    pending merge, and it lets you specify particular files.
2228
 
 
2229
 
    Examples:
2230
 
    $ bzr remerge --show-base
2231
 
        Re-do the merge of all conflicted files, and show the base text in
2232
 
        conflict regions, in addition to the usual THIS and OTHER texts.
2233
 
 
2234
 
    $ bzr remerge --merge-type weave --reprocess foobar
2235
 
        Re-do the merge of "foobar", using the weave merge algorithm, with
2236
 
        additional processing to reduce the size of conflict regions.
2237
 
    
2238
 
    The following merge types are available:"""
 
1968
    """
2239
1969
    takes_args = ['file*']
2240
1970
    takes_options = ['merge-type', 'reprocess',
2241
1971
                     Option('show-base', help="Show base revision text in "
2242
1972
                            "conflicts")]
2243
1973
 
2244
 
    def help(self):
2245
 
        from merge import merge_type_help
2246
 
        from inspect import getdoc
2247
 
        return getdoc(self) + '\n' + merge_type_help() 
2248
 
 
2249
1974
    def run(self, file_list=None, merge_type=None, show_base=False,
2250
1975
            reprocess=False):
2251
1976
        from bzrlib.merge import merge_inner, transform_tree
2257
1982
            pending_merges = tree.pending_merges() 
2258
1983
            if len(pending_merges) != 1:
2259
1984
                raise BzrCommandError("Sorry, remerge only works after normal"
2260
 
                                      " merges.  Not cherrypicking or"
2261
 
                                      " multi-merges.")
 
1985
                                      + " merges.  Not cherrypicking or"
 
1986
                                      + "multi-merges.")
2262
1987
            repository = tree.branch.repository
2263
1988
            base_revision = common_ancestor(tree.branch.last_revision(), 
2264
1989
                                            pending_merges[0], repository)
2265
1990
            base_tree = repository.revision_tree(base_revision)
2266
1991
            other_tree = repository.revision_tree(pending_merges[0])
2267
1992
            interesting_ids = None
2268
 
            new_conflicts = []
2269
 
            conflicts = tree.conflicts()
2270
1993
            if file_list is not None:
2271
1994
                interesting_ids = set()
2272
1995
                for filename in file_list:
2279
2002
                    
2280
2003
                    for name, ie in tree.inventory.iter_entries(file_id):
2281
2004
                        interesting_ids.add(ie.file_id)
2282
 
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2283
2005
            transform_tree(tree, tree.basis_tree(), interesting_ids)
2284
 
            tree.set_conflicts(ConflictList(new_conflicts))
2285
2006
            if file_list is None:
2286
2007
                restore_files = list(tree.iter_conflicts())
2287
2008
            else:
2291
2012
                    restore(tree.abspath(filename))
2292
2013
                except NotConflicted:
2293
2014
                    pass
2294
 
            conflicts = merge_inner(tree.branch, other_tree, base_tree,
2295
 
                                    this_tree=tree,
2296
 
                                    interesting_ids=interesting_ids, 
2297
 
                                    other_rev_id=pending_merges[0], 
2298
 
                                    merge_type=merge_type, 
2299
 
                                    show_base=show_base,
2300
 
                                    reprocess=reprocess)
 
2015
            conflicts =  merge_inner(tree.branch, other_tree, base_tree,
 
2016
                                     this_tree=tree,
 
2017
                                     interesting_ids = interesting_ids, 
 
2018
                                     other_rev_id=pending_merges[0], 
 
2019
                                     merge_type=merge_type, 
 
2020
                                     show_base=show_base,
 
2021
                                     reprocess=reprocess)
2301
2022
        finally:
2302
2023
            tree.unlock()
2303
2024
        if conflicts > 0:
2332
2053
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
2333
2054
        else:
2334
2055
            rev_id = revision[0].in_history(tree.branch).rev_id
2335
 
        pb = ui.ui_factory.nested_progress_bar()
 
2056
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
2336
2057
        try:
2337
2058
            tree.revert(file_list, 
2338
2059
                        tree.branch.repository.revision_tree(rev_id),
2386
2107
    takes_args = ['from_branch', 'to_branch']
2387
2108
    def run(self, from_branch, to_branch):
2388
2109
        from bzrlib.fetch import Fetcher
 
2110
        from bzrlib.branch import Branch
2389
2111
        from_b = Branch.open(from_branch)
2390
2112
        to_b = Branch.open(to_branch)
2391
2113
        Fetcher(to_b, from_b)
2408
2130
                     'show-ids',
2409
2131
                     'verbose'
2410
2132
                     ]
2411
 
    encoding_type = 'replace'
2412
2133
 
2413
 
    @display_command
2414
2134
    def run(self, other_branch=None, reverse=False, mine_only=False,
2415
2135
            theirs_only=False, log_format=None, long=False, short=False, line=False, 
2416
2136
            show_ids=False, verbose=False):
2417
2137
        from bzrlib.missing import find_unmerged, iter_log_data
2418
2138
        from bzrlib.log import log_formatter
2419
 
        local_branch = Branch.open_containing(u".")[0]
 
2139
        local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2420
2140
        parent = local_branch.get_parent()
2421
2141
        if other_branch is None:
2422
2142
            other_branch = parent
2423
2143
            if other_branch is None:
2424
 
                raise BzrCommandError("No peer location known or specified.")
 
2144
                raise BzrCommandError("No missing location known or specified.")
2425
2145
            print "Using last location: " + local_branch.get_parent()
2426
 
        remote_branch = Branch.open(other_branch)
 
2146
        remote_branch = bzrlib.branch.Branch.open(other_branch)
2427
2147
        if remote_branch.base == local_branch.base:
2428
2148
            remote_branch = local_branch
2429
2149
        local_branch.lock_read()
2432
2152
            try:
2433
2153
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2434
2154
                if (log_format == None):
2435
 
                    default = local_branch.get_config().log_format()
2436
 
                    log_format = get_log_format(long=long, short=short, 
2437
 
                                                line=line, default=default)
2438
 
                lf = log_formatter(log_format,
2439
 
                                   to_file=self.outf,
 
2155
                    default = bzrlib.config.BranchConfig(local_branch).log_format()
 
2156
                    log_format = get_log_format(long=long, short=short, line=line, default=default)
 
2157
                lf = log_formatter(log_format, sys.stdout,
2440
2158
                                   show_ids=show_ids,
2441
2159
                                   show_timezone='original')
2442
2160
                if reverse is False:
2471
2189
            try:
2472
2190
                # handle race conditions - a parent might be set while we run.
2473
2191
                if local_branch.get_parent() is None:
2474
 
                    local_branch.set_parent(remote_branch.base)
 
2192
                    local_branch.set_parent(other_branch)
2475
2193
            finally:
2476
2194
                local_branch.unlock()
2477
2195
        return status_code
2499
2217
 
2500
2218
class cmd_testament(Command):
2501
2219
    """Show testament (signing-form) of a revision."""
2502
 
    takes_options = ['revision', 'long', 
2503
 
                     Option('strict', help='Produce a strict-format'
2504
 
                            ' testament')]
 
2220
    takes_options = ['revision', 'long']
2505
2221
    takes_args = ['branch?']
2506
2222
    @display_command
2507
 
    def run(self, branch=u'.', revision=None, long=False, strict=False):
2508
 
        from bzrlib.testament import Testament, StrictTestament
2509
 
        if strict is True:
2510
 
            testament_class = StrictTestament
2511
 
        else:
2512
 
            testament_class = Testament
 
2223
    def run(self, branch=u'.', revision=None, long=False):
 
2224
        from bzrlib.testament import Testament
2513
2225
        b = WorkingTree.open_containing(branch)[0].branch
2514
2226
        b.lock_read()
2515
2227
        try:
2517
2229
                rev_id = b.last_revision()
2518
2230
            else:
2519
2231
                rev_id = revision[0].in_history(b).rev_id
2520
 
            t = testament_class.from_revision(b.repository, rev_id)
 
2232
            t = Testament.from_revision(b.repository, rev_id)
2521
2233
            if long:
2522
2234
                sys.stdout.writelines(t.as_text_lines())
2523
2235
            else:
2536
2248
    shown only at the top, unless the --all option is given.
2537
2249
    """
2538
2250
    # TODO: annotate directories; showing when each file was last changed
 
2251
    # TODO: annotate a previous version of a file
2539
2252
    # TODO: if the working copy is modified, show annotations on that 
2540
2253
    #       with new uncommitted lines marked
2541
 
    aliases = ['ann', 'blame', 'praise']
 
2254
    aliases = ['blame', 'praise']
2542
2255
    takes_args = ['filename']
2543
2256
    takes_options = [Option('all', help='show annotations on all lines'),
2544
2257
                     Option('long', help='show date in annotations'),
2545
 
                     'revision'
2546
2258
                     ]
2547
2259
 
2548
2260
    @display_command
2549
 
    def run(self, filename, all=False, long=False, revision=None):
 
2261
    def run(self, filename, all=False, long=False):
2550
2262
        from bzrlib.annotate import annotate_file
2551
2263
        tree, relpath = WorkingTree.open_containing(filename)
2552
2264
        branch = tree.branch
2553
2265
        branch.lock_read()
2554
2266
        try:
2555
 
            if revision is None:
2556
 
                revision_id = branch.last_revision()
2557
 
            elif len(revision) != 1:
2558
 
                raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2559
 
            else:
2560
 
                revision_id = revision[0].in_history(branch).rev_id
2561
2267
            file_id = tree.inventory.path2id(relpath)
2562
 
            tree = branch.repository.revision_tree(revision_id)
 
2268
            tree = branch.repository.revision_tree(branch.last_revision())
2563
2269
            file_version = tree.inventory[file_id].revision
2564
2270
            annotate_file(branch, file_version, file_id, long, all, sys.stdout)
2565
2271
        finally:
2575
2281
    takes_options = ['revision']
2576
2282
    
2577
2283
    def run(self, revision_id_list=None, revision=None):
 
2284
        import bzrlib.config as config
2578
2285
        import bzrlib.gpg as gpg
2579
2286
        if revision_id_list is not None and revision is not None:
2580
2287
            raise BzrCommandError('You can only supply one of revision_id or --revision')
2581
2288
        if revision_id_list is None and revision is None:
2582
2289
            raise BzrCommandError('You must supply either --revision or a revision_id')
2583
2290
        b = WorkingTree.open_containing(u'.')[0].branch
2584
 
        gpg_strategy = gpg.GPGStrategy(b.get_config())
 
2291
        gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
2585
2292
        if revision_id_list is not None:
2586
2293
            for revision_id in revision_id_list:
2587
2294
                b.repository.sign_revision(revision_id, gpg_strategy)
2627
2334
 
2628
2335
 
2629
2336
class cmd_unbind(Command):
2630
 
    """Unbind the current branch from its master branch.
 
2337
    """Bind the current branch to its parent.
2631
2338
 
2632
2339
    After unbinding, the local branch is considered independent.
2633
 
    All subsequent commits will be local.
2634
2340
    """
2635
2341
 
2636
2342
    takes_args = []
2642
2348
            raise BzrCommandError('Local branch is not bound')
2643
2349
 
2644
2350
 
2645
 
class cmd_uncommit(Command):
 
2351
class cmd_uncommit(bzrlib.commands.Command):
2646
2352
    """Remove the last committed revision.
2647
2353
 
 
2354
    By supplying the --all flag, it will not only remove the entry 
 
2355
    from revision_history, but also remove all of the entries in the
 
2356
    stores.
 
2357
 
2648
2358
    --verbose will print out what is being removed.
2649
2359
    --dry-run will go through all the motions, but not actually
2650
2360
    remove anything.
2651
2361
    
2652
 
    In the future, uncommit will create a revision bundle, which can then
 
2362
    In the future, uncommit will create a changeset, which can then
2653
2363
    be re-applied.
2654
2364
    """
2655
2365
 
2656
2366
    # TODO: jam 20060108 Add an option to allow uncommit to remove
2657
 
    # unreferenced information in 'branch-as-repository' branches.
 
2367
    # unreferenced information in 'branch-as-repostory' branches.
2658
2368
    # TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2659
2369
    # information in shared branches as well.
2660
2370
    takes_options = ['verbose', 'revision',
2663
2373
    takes_args = ['location?']
2664
2374
    aliases = []
2665
2375
 
2666
 
    def run(self, location=None,
 
2376
    def run(self, location=None, 
2667
2377
            dry_run=False, verbose=False,
2668
2378
            revision=None, force=False):
2669
 
        from bzrlib.log import log_formatter, show_log
 
2379
        from bzrlib.branch import Branch
 
2380
        from bzrlib.log import log_formatter
2670
2381
        import sys
2671
2382
        from bzrlib.uncommit import uncommit
2672
2383
 
2680
2391
            tree = None
2681
2392
            b = control.open_branch()
2682
2393
 
2683
 
        rev_id = None
2684
2394
        if revision is None:
2685
2395
            revno = b.revno()
 
2396
            rev_id = b.last_revision()
2686
2397
        else:
2687
 
            # 'bzr uncommit -r 10' actually means uncommit
2688
 
            # so that the final tree is at revno 10.
2689
 
            # but bzrlib.uncommit.uncommit() actually uncommits
2690
 
            # the revisions that are supplied.
2691
 
            # So we need to offset it by one
2692
 
            revno = revision[0].in_history(b).revno+1
2693
 
 
2694
 
        if revno <= b.revno():
2695
 
            rev_id = b.get_rev_id(revno)
 
2398
            revno, rev_id = revision[0].in_history(b)
2696
2399
        if rev_id is None:
2697
 
            self.outf.write('No revisions to uncommit.\n')
2698
 
            return 1
2699
 
 
2700
 
        lf = log_formatter('short',
2701
 
                           to_file=self.outf,
2702
 
                           show_timezone='original')
2703
 
 
2704
 
        show_log(b,
2705
 
                 lf,
2706
 
                 verbose=False,
2707
 
                 direction='forward',
2708
 
                 start_revision=revno,
2709
 
                 end_revision=b.revno())
 
2400
            print 'No revisions to uncommit.'
 
2401
 
 
2402
        for r in range(revno, b.revno()+1):
 
2403
            rev_id = b.get_rev_id(r)
 
2404
            lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
 
2405
            lf.show(r, b.repository.get_revision(rev_id), None)
2710
2406
 
2711
2407
        if dry_run:
2712
2408
            print 'Dry-run, pretending to remove the above revisions.'
2729
2425
 
2730
2426
    CAUTION: Locks should only be broken when you are sure that the process
2731
2427
    holding the lock has been stopped.
2732
 
 
2733
 
    You can get information on what locks are open via the 'bzr info' command.
2734
2428
    
2735
2429
    example:
2736
 
        bzr break-lock
 
2430
        bzr break-lock .
2737
2431
    """
2738
 
    takes_args = ['location?']
2739
 
 
2740
 
    def run(self, location=None, show=False):
2741
 
        if location is None:
2742
 
            location = u'.'
2743
 
        control, relpath = bzrdir.BzrDir.open_containing(location)
2744
 
        try:
2745
 
            control.break_lock()
2746
 
        except NotImplementedError:
2747
 
            pass
2748
 
        
 
2432
    takes_args = ['location']
 
2433
    takes_options = [Option('show',
 
2434
                            help="just show information on the lock, " \
 
2435
                                 "don't break it"),
 
2436
                    ]
 
2437
    def run(self, location, show=False):
 
2438
        raise NotImplementedError("sorry, break-lock is not complete yet; "
 
2439
                "you can remove the 'held' directory manually to break the lock")
2749
2440
 
2750
2441
 
2751
2442
# command-line interpretation helper for merge-related commands
2823
2514
# aliases.  ideally we would avoid loading the implementation until the
2824
2515
# details were needed.
2825
2516
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2826
 
from bzrlib.bundle.commands import cmd_bundle_revisions
2827
2517
from bzrlib.sign_my_commits import cmd_sign_my_commits
2828
2518
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
2829
2519
        cmd_weave_plan_merge, cmd_weave_merge_text