~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

[merge] aaron, various fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
from bzrlib import BZRDIR
27
27
from bzrlib.commands import Command, display_command
28
28
from bzrlib.branch import Branch
29
 
from bzrlib.errors import BzrError, BzrCheckError, BzrCommandError, NotBranchError
30
 
from bzrlib.errors import DivergedBranches, NoSuchFile, NoWorkingTree
 
29
from bzrlib.revision import common_ancestor
 
30
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
 
31
                           NotBranchError, DivergedBranches, NotConflicted,
 
32
                           NoSuchFile, NoWorkingTree)
31
33
from bzrlib.option import Option
32
34
from bzrlib.revisionspec import RevisionSpec
33
35
import bzrlib.trace
36
38
 
37
39
 
38
40
def branch_files(file_list, default_branch='.'):
 
41
    try:
 
42
        return inner_branch_files(file_list, default_branch)
 
43
    except NotBranchError:
 
44
        raise BzrCommandError("%s is not in the same branch as %s" %
 
45
                             (filename, file_list[0]))
 
46
 
 
47
def inner_branch_files(file_list, default_branch='.'):
39
48
    """\
40
49
    Return a branch and list of branch-relative paths.
41
50
    If supplied file_list is empty or None, the branch default will be used,
52
61
    tree = WorkingTree(b.base, b)
53
62
    new_list = []
54
63
    for filename in file_list:
55
 
        try:
56
 
            new_list.append(tree.relpath(filename))
57
 
        except NotBranchError:
58
 
            raise BzrCommandError("%s is not in the same branch as %s" % 
59
 
                                  (filename, file_list[0]))
 
64
        new_list.append(tree.relpath(filename))
60
65
    return b, new_list
61
66
 
62
67
 
604
609
    @display_command
605
610
    def run(self, filename):
606
611
        b, relpath = Branch.open_containing(filename)
607
 
        i = b.inventory.path2id(relpath)
 
612
        i = b.working_tree().inventory.path2id(relpath)
608
613
        if i == None:
609
614
            raise BzrError("%r is not a versioned file" % filename)
610
615
        else:
721
726
    @display_command
722
727
    def run(self, revision=None, file_list=None, diff_options=None):
723
728
        from bzrlib.diff import show_diff
724
 
        
725
 
        b, file_list = branch_files(file_list)
 
729
        try:
 
730
            b, file_list = inner_branch_files(file_list)
 
731
            b2 = None
 
732
        except NotBranchError:
 
733
            if len(file_list) != 2:
 
734
                raise BzrCommandError("Files are in different branches")
 
735
 
 
736
            b, file1 = Branch.open_containing(file_list[0])
 
737
            b2, file2 = Branch.open_containing(file_list[1])
 
738
            if file1 != "" or file2 != "":
 
739
                raise BzrCommandError("Files are in different branches")
 
740
            file_list = None
726
741
        if revision is not None:
 
742
            if b2 is not None:
 
743
                raise BzrCommandError("Can't specify -r with two branches")
727
744
            if len(revision) == 1:
728
745
                return show_diff(b, revision[0], specific_files=file_list,
729
746
                                 external_diff_options=diff_options)
735
752
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
736
753
        else:
737
754
            return show_diff(b, None, specific_files=file_list,
738
 
                             external_diff_options=diff_options)
 
755
                             external_diff_options=diff_options, b2=b2)
739
756
 
740
757
 
741
758
class cmd_deleted(Command):
1292
1309
        else:
1293
1310
            print config.username()
1294
1311
 
 
1312
class cmd_nick(Command):
 
1313
    """\
 
1314
    Print or set the branch nickname.  
 
1315
    If unset, the tree root directory name is used as the nickname
 
1316
    To print the current nickname, execute with no argument.  
 
1317
    """
 
1318
    takes_args = ['nickname?']
 
1319
    def run(self, nickname=None):
 
1320
        branch = Branch.open_containing('.')[0]
 
1321
        if nickname is None:
 
1322
            self.printme(branch)
 
1323
        else:
 
1324
            branch.nick = nickname
 
1325
 
 
1326
    @display_command
 
1327
    def printme(self, branch):
 
1328
        print branch.nick 
1295
1329
 
1296
1330
class cmd_selftest(Command):
1297
1331
    """Run internal test suite.
1299
1333
    This creates temporary test directories in the working directory,
1300
1334
    but not existing data is affected.  These directories are deleted
1301
1335
    if the tests pass, or left behind to help in debugging if they
1302
 
    fail.
 
1336
    fail and --keep-output is specified.
1303
1337
    
1304
1338
    If arguments are given, they are regular expressions that say
1305
1339
    which tests should run.
1309
1343
    takes_args = ['testspecs*']
1310
1344
    takes_options = ['verbose', 
1311
1345
                     Option('one', help='stop when one test fails'),
 
1346
                     Option('keep-output', 
 
1347
                            help='keep output directories when tests fail')
1312
1348
                    ]
1313
1349
 
1314
 
    def run(self, testspecs_list=None, verbose=False, one=False):
 
1350
    def run(self, testspecs_list=None, verbose=False, one=False,
 
1351
            keep_output=False):
1315
1352
        import bzrlib.ui
1316
1353
        from bzrlib.selftest import selftest
1317
1354
        # we don't want progress meters from the tests to go to the
1327
1364
                pattern = ".*"
1328
1365
            result = selftest(verbose=verbose, 
1329
1366
                              pattern=pattern,
1330
 
                              stop_on_failure=one)
 
1367
                              stop_on_failure=one, 
 
1368
                              keep_output=keep_output)
1331
1369
            if result:
1332
1370
                bzrlib.trace.info('tests passed')
1333
1371
            else:
1486
1524
            log_error(m)
1487
1525
 
1488
1526
 
 
1527
class cmd_remerge(Command):
 
1528
    """Redo a merge.
 
1529
    """
 
1530
    takes_args = ['file*']
 
1531
    takes_options = ['merge-type', 'reprocess',
 
1532
                     Option('show-base', help="Show base revision text in "
 
1533
                            "conflicts")]
 
1534
 
 
1535
    def run(self, file_list=None, merge_type=None, show_base=False,
 
1536
            reprocess=False):
 
1537
        from bzrlib.merge import merge_inner, transform_tree
 
1538
        from bzrlib.merge_core import ApplyMerge3
 
1539
        if merge_type is None:
 
1540
            merge_type = ApplyMerge3
 
1541
        b, file_list = branch_files(file_list)
 
1542
        b.lock_write()
 
1543
        try:
 
1544
            pending_merges = b.pending_merges() 
 
1545
            if len(pending_merges) != 1:
 
1546
                raise BzrCommandError("Sorry, remerge only works after normal"
 
1547
                                      + " merges.  Not cherrypicking or"
 
1548
                                      + "multi-merges.")
 
1549
            this_tree = b.working_tree()
 
1550
            base_revision = common_ancestor(b.last_revision(), 
 
1551
                                            pending_merges[0], b)
 
1552
            base_tree = b.revision_tree(base_revision)
 
1553
            other_tree = b.revision_tree(pending_merges[0])
 
1554
            interesting_ids = None
 
1555
            if file_list is not None:
 
1556
                interesting_ids = set()
 
1557
                for filename in file_list:
 
1558
                    file_id = this_tree.path2id(filename)
 
1559
                    interesting_ids.add(file_id)
 
1560
                    if this_tree.kind(file_id) != "directory":
 
1561
                        continue
 
1562
                    
 
1563
                    for name, ie in this_tree.inventory.iter_entries(file_id):
 
1564
                        interesting_ids.add(ie.file_id)
 
1565
            transform_tree(this_tree, b.basis_tree(), interesting_ids)
 
1566
            if file_list is None:
 
1567
                restore_files = list(this_tree.iter_conflicts())
 
1568
            else:
 
1569
                restore_files = file_list
 
1570
            for filename in restore_files:
 
1571
                try:
 
1572
                    restore(this_tree.abspath(filename))
 
1573
                except NotConflicted:
 
1574
                    pass
 
1575
            conflicts =  merge_inner(b, other_tree, base_tree, 
 
1576
                                     interesting_ids = interesting_ids, 
 
1577
                                     other_rev_id=pending_merges[0], 
 
1578
                                     merge_type=merge_type, 
 
1579
                                     show_base=show_base,
 
1580
                                     reprocess=reprocess)
 
1581
        finally:
 
1582
            b.unlock()
 
1583
        if conflicts > 0:
 
1584
            return 1
 
1585
        else:
 
1586
            return 0
 
1587
 
1489
1588
class cmd_revert(Command):
1490
1589
    """Reverse all changes since the last commit.
1491
1590
 
1736
1835
# TODO: Some more consistent way to split command definitions across files;
1737
1836
# we do need to load at least some information about them to know of 
1738
1837
# aliases.
1739
 
from bzrlib.conflicts import cmd_resolve, cmd_conflicts
 
1838
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore