~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: John Arbash Meinel
  • Date: 2008-07-08 14:55:19 UTC
  • mfrom: (3530 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3532.
  • Revision ID: john@arbash-meinel.com-20080708145519-paqg4kjwbpgs2xmq
Merge bzr.dev 3530

Show diffs side-by-side

added added

removed removed

Lines of Context:
96
96
    return tree, new_list
97
97
 
98
98
 
99
 
@symbol_versioning.deprecated_function(symbol_versioning.zero_fifteen)
100
 
def get_format_type(typestring):
101
 
    """Parse and return a format specifier."""
102
 
    # Have to use BzrDirMetaFormat1 directly, so that
103
 
    # RepositoryFormat.set_default_format works
104
 
    if typestring == "default":
105
 
        return bzrdir.BzrDirMetaFormat1()
106
 
    try:
107
 
        return bzrdir.format_registry.make_bzrdir(typestring)
108
 
    except KeyError:
109
 
        msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
110
 
        raise errors.BzrCommandError(msg)
111
 
 
112
 
 
113
99
# TODO: Make sure no commands unconditionally use the working directory as a
114
100
# branch.  If a filename argument is used, the first of them should be used to
115
101
# specify the branch.  (Perhaps this can be factored out into some kind of
148
134
    
149
135
    Note that --short or -S gives status flags for each item, similar
150
136
    to Subversion's status command. To get output similar to svn -q,
151
 
    use bzr -SV.
 
137
    use bzr status -SV.
152
138
 
153
139
    If no arguments are specified, the status of the entire working
154
140
    directory is shown.  Otherwise, only the status of the specified
166
152
                     Option('short', help='Use short status indicators.',
167
153
                            short_name='S'),
168
154
                     Option('versioned', help='Only show versioned files.',
169
 
                            short_name='V')
 
155
                            short_name='V'),
 
156
                     Option('no-pending', help='Don\'t show pending merges.',
 
157
                           ),
170
158
                     ]
171
159
    aliases = ['st', 'stat']
172
160
 
175
163
    
176
164
    @display_command
177
165
    def run(self, show_ids=False, file_list=None, revision=None, short=False,
178
 
            versioned=False):
 
166
            versioned=False, no_pending=False):
179
167
        from bzrlib.status import show_tree_status
180
168
 
181
169
        if revision and len(revision) > 2:
186
174
            
187
175
        show_tree_status(tree, show_ids=show_ids,
188
176
                         specific_files=file_list, revision=revision,
189
 
                         to_file=self.outf, short=short, versioned=versioned)
 
177
                         to_file=self.outf, short=short, versioned=versioned,
 
178
                         show_pending=not no_pending)
190
179
 
191
180
 
192
181
class cmd_cat_revision(Command):
221
210
                if rev is None:
222
211
                    raise errors.BzrCommandError('You cannot specify a NULL'
223
212
                                                 ' revision.')
224
 
                revno, rev_id = rev.in_history(b)
 
213
                rev_id = rev.as_revision_id(b)
225
214
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
226
215
    
227
216
 
295
284
            revs.append(RevisionSpec.from_string('-1'))
296
285
 
297
286
        for rev in revs:
298
 
            revinfo = rev.in_history(b)
299
 
            if revinfo.revno is None:
 
287
            revision_id = rev.as_revision_id(b)
 
288
            try:
 
289
                revno = '%4d' % (b.revision_id_to_revno(revision_id))
 
290
            except errors.NoSuchRevision:
300
291
                dotted_map = b.get_revision_id_to_revno_map()
301
 
                revno = '.'.join(str(i) for i in dotted_map[revinfo.rev_id])
302
 
                print '%s %s' % (revno, revinfo.rev_id)
303
 
            else:
304
 
                print '%4d %s' % (revinfo.revno, revinfo.rev_id)
 
292
                revno = '.'.join(str(i) for i in dotted_map[revision_id])
 
293
            print '%s %s' % (revno, revision_id)
305
294
 
306
295
    
307
296
class cmd_add(Command):
466
455
                    raise errors.BzrCommandError(
467
456
                        'bzr inventory --revision takes exactly one revision'
468
457
                        ' identifier')
469
 
                revision_id = revision[0].in_history(work_tree.branch).rev_id
 
458
                revision_id = revision[0].as_revision_id(work_tree.branch)
470
459
                tree = work_tree.branch.repository.revision_tree(revision_id)
471
460
 
472
461
                extra_trees = [work_tree]
534
523
        if len(names_list) < 2:
535
524
            raise errors.BzrCommandError("missing file argument")
536
525
        tree, rel_names = tree_files(names_list)
 
526
        tree.lock_write()
 
527
        try:
 
528
            self._run(tree, names_list, rel_names, after)
 
529
        finally:
 
530
            tree.unlock()
537
531
 
538
 
        dest = names_list[-1]
539
 
        isdir = os.path.isdir(dest)
540
 
        if (isdir and not tree.case_sensitive and len(rel_names) == 2
541
 
            and rel_names[0].lower() == rel_names[1].lower()):
542
 
                isdir = False
543
 
        if isdir:
 
532
    def _run(self, tree, names_list, rel_names, after):
 
533
        into_existing = osutils.isdir(names_list[-1])
 
534
        if into_existing and len(names_list) == 2:
 
535
            # special cases:
 
536
            # a. case-insensitive filesystem and change case of dir
 
537
            # b. move directory after the fact (if the source used to be
 
538
            #    a directory, but now doesn't exist in the working tree
 
539
            #    and the target is an existing directory, just rename it)
 
540
            if (not tree.case_sensitive
 
541
                and rel_names[0].lower() == rel_names[1].lower()):
 
542
                into_existing = False
 
543
            else:
 
544
                inv = tree.inventory
 
545
                from_id = tree.path2id(rel_names[0])
 
546
                if (not osutils.lexists(names_list[0]) and
 
547
                    from_id and inv.get_file_kind(from_id) == "directory"):
 
548
                    into_existing = False
 
549
        # move/rename
 
550
        if into_existing:
544
551
            # move into existing directory
545
552
            for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
546
553
                self.outf.write("%s => %s\n" % pair)
571
578
    that, you can omit the location to use the default.  To change the
572
579
    default, use --remember. The value will only be saved if the remote
573
580
    location can be accessed.
 
581
 
 
582
    Note: The location can be specified either in the form of a branch,
 
583
    or in the form of a path to a file containing a merge directive generated
 
584
    with bzr send.
574
585
    """
575
586
 
576
587
    _see_also = ['push', 'update', 'status-flags']
604
615
 
605
616
        possible_transports = []
606
617
        if location is not None:
607
 
            mergeable, location_transport = _get_mergeable_helper(location)
608
 
            possible_transports.append(location_transport)
 
618
            try:
 
619
                mergeable = bundle.read_mergeable_from_url(location,
 
620
                    possible_transports=possible_transports)
 
621
            except errors.NotABundle:
 
622
                mergeable = None
609
623
 
610
624
        stored_loc = branch_to.get_parent()
611
625
        if location is None:
618
632
                if not is_quiet():
619
633
                    self.outf.write("Using saved location: %s\n" % display_url)
620
634
                location = stored_loc
621
 
                location_transport = transport.get_transport(
622
 
                    location, possible_transports=possible_transports)
623
635
 
624
636
        if mergeable is not None:
625
637
            if revision is not None:
630
642
                mergeable.get_merge_request(branch_to.repository)
631
643
            branch_from = branch_to
632
644
        else:
633
 
            branch_from = Branch.open_from_transport(location_transport)
 
645
            branch_from = Branch.open(location,
 
646
                possible_transports=possible_transports)
634
647
 
635
648
            if branch_to.get_parent() is None or remember:
636
649
                branch_to.set_parent(branch_from.base)
637
650
 
638
651
        if revision is not None:
639
652
            if len(revision) == 1:
640
 
                revision_id = revision[0].in_history(branch_from).rev_id
 
653
                revision_id = revision[0].as_revision_id(branch_from)
641
654
            else:
642
655
                raise errors.BzrCommandError(
643
656
                    'bzr pull --revision takes one value.')
644
657
 
645
 
        if verbose:
646
 
            old_rh = branch_to.revision_history()
647
 
        if tree_to is not None:
648
 
            change_reporter = delta._ChangeReporter(
649
 
                unversioned_filter=tree_to.is_ignored)
650
 
            result = tree_to.pull(branch_from, overwrite, revision_id,
651
 
                                  change_reporter,
652
 
                                  possible_transports=possible_transports)
653
 
        else:
654
 
            result = branch_to.pull(branch_from, overwrite, revision_id)
 
658
        branch_to.lock_write()
 
659
        try:
 
660
            if tree_to is not None:
 
661
                change_reporter = delta._ChangeReporter(
 
662
                    unversioned_filter=tree_to.is_ignored)
 
663
                result = tree_to.pull(branch_from, overwrite, revision_id,
 
664
                                      change_reporter,
 
665
                                      possible_transports=possible_transports)
 
666
            else:
 
667
                result = branch_to.pull(branch_from, overwrite, revision_id)
655
668
 
656
 
        result.report(self.outf)
657
 
        if verbose:
658
 
            new_rh = branch_to.revision_history()
659
 
            log.show_changed_revisions(branch_to, old_rh, new_rh,
660
 
                                       to_file=self.outf)
 
669
            result.report(self.outf)
 
670
            if verbose and result.old_revid != result.new_revid:
 
671
                old_rh = list(
 
672
                    branch_to.repository.iter_reverse_revision_history(
 
673
                    result.old_revid))
 
674
                old_rh.reverse()
 
675
                new_rh = branch_to.revision_history()
 
676
                log.show_changed_revisions(branch_to, old_rh, new_rh,
 
677
                                           to_file=self.outf)
 
678
        finally:
 
679
            branch_to.unlock()
661
680
 
662
681
 
663
682
class cmd_push(Command):
898
917
        br_from.lock_read()
899
918
        try:
900
919
            if len(revision) == 1 and revision[0] is not None:
901
 
                revision_id = revision[0].in_history(br_from)[1]
 
920
                revision_id = revision[0].as_revision_id(br_from)
902
921
            else:
903
922
                # FIXME - wt.last_revision, fallback to branch, fall back to
904
923
                # None or perhaps NULL_REVISION to mean copy nothing
906
925
                revision_id = br_from.last_revision()
907
926
            if to_location is None:
908
927
                to_location = urlutils.derive_to_location(from_location)
909
 
                name = None
910
 
            else:
911
 
                name = os.path.basename(to_location) + '\n'
912
 
 
913
928
            to_transport = transport.get_transport(to_location)
914
929
            try:
915
930
                to_transport.mkdir('.')
930
945
                to_transport.delete_tree('.')
931
946
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
932
947
                raise errors.BzrCommandError(msg)
933
 
            if name:
934
 
                branch.control_files.put_utf8('branch-name', name)
935
948
            _merge_tags_if_possible(br_from, branch)
936
949
            note('Branched %d revision(s).' % branch.revno())
937
950
        finally:
992
1005
        if files_from is not None:
993
1006
            accelerator_tree = WorkingTree.open(files_from)
994
1007
        if len(revision) == 1 and revision[0] is not None:
995
 
            revision_id = _mod_revision.ensure_null(
996
 
                revision[0].in_history(source)[1])
 
1008
            revision_id = revision[0].as_revision_id(source)
997
1009
        else:
998
1010
            revision_id = None
999
1011
        if to_location is None:
1272
1284
            last_revision = wt.last_revision()
1273
1285
 
1274
1286
        revision_ids = b.repository.get_ancestry(last_revision)
1275
 
        assert revision_ids[0] is None
1276
1287
        revision_ids.pop(0)
1277
1288
        for revision_id in revision_ids:
1278
1289
            self.outf.write(revision_id + '\n')
1574
1585
 
1575
1586
    hidden = True
1576
1587
    _see_also = ['status', 'ls']
 
1588
    takes_options = [
 
1589
            Option('null',
 
1590
                   help='Write an ascii NUL (\\0) separator '
 
1591
                   'between files rather than a newline.')
 
1592
            ]
1577
1593
 
1578
1594
    @display_command
1579
 
    def run(self):
 
1595
    def run(self, null=False):
1580
1596
        tree = WorkingTree.open_containing(u'.')[0]
1581
1597
        td = tree.changes_from(tree.basis_tree())
1582
1598
        for path, id, kind, text_modified, meta_modified in td.modified:
1583
 
            self.outf.write(path + '\n')
 
1599
            if null:
 
1600
                self.outf.write(path + '\0')
 
1601
            else:
 
1602
                self.outf.write(osutils.quotefn(path) + '\n')
1584
1603
 
1585
1604
 
1586
1605
class cmd_added(Command):
1589
1608
 
1590
1609
    hidden = True
1591
1610
    _see_also = ['status', 'ls']
 
1611
    takes_options = [
 
1612
            Option('null',
 
1613
                   help='Write an ascii NUL (\\0) separator '
 
1614
                   'between files rather than a newline.')
 
1615
            ]
1592
1616
 
1593
1617
    @display_command
1594
 
    def run(self):
 
1618
    def run(self, null=False):
1595
1619
        wt = WorkingTree.open_containing(u'.')[0]
1596
1620
        wt.lock_read()
1597
1621
        try:
1608
1632
                    path = inv.id2path(file_id)
1609
1633
                    if not os.access(osutils.abspath(path), os.F_OK):
1610
1634
                        continue
1611
 
                    self.outf.write(path + '\n')
 
1635
                    if null:
 
1636
                        self.outf.write(path + '\0')
 
1637
                    else:
 
1638
                        self.outf.write(osutils.quotefn(path) + '\n')
1612
1639
            finally:
1613
1640
                basis.unlock()
1614
1641
        finally:
1697
1724
            message=None,
1698
1725
            limit=None):
1699
1726
        from bzrlib.log import show_log
1700
 
        assert message is None or isinstance(message, basestring), \
1701
 
            "invalid message argument %r" % message
1702
1727
        direction = (forward and 'forward') or 'reverse'
1703
1728
        
1704
1729
        # log everything
1811
1836
            Option('from-root',
1812
1837
                   help='Print paths relative to the root of the branch.'),
1813
1838
            Option('unknown', help='Print unknown files.'),
1814
 
            Option('versioned', help='Print versioned files.'),
 
1839
            Option('versioned', help='Print versioned files.',
 
1840
                   short_name='V'),
1815
1841
            Option('ignored', help='Print ignored files.'),
1816
1842
            Option('null',
1817
1843
                   help='Write an ascii NUL (\\0) separator '
1853
1879
            relpath += '/'
1854
1880
        if revision is not None:
1855
1881
            tree = branch.repository.revision_tree(
1856
 
                revision[0].in_history(branch).rev_id)
 
1882
                revision[0].as_revision_id(branch))
1857
1883
        elif tree is None:
1858
1884
            tree = branch.basis_tree()
1859
1885
 
1910
1936
class cmd_ignore(Command):
1911
1937
    """Ignore specified files or patterns.
1912
1938
 
 
1939
    See ``bzr help patterns`` for details on the syntax of patterns.
 
1940
 
1913
1941
    To remove patterns from the ignore list, edit the .bzrignore file.
1914
 
 
1915
 
    Trailing slashes on patterns are ignored. 
1916
 
    If the pattern contains a slash or is a regular expression, it is compared 
1917
 
    to the whole path from the branch root.  Otherwise, it is compared to only
1918
 
    the last component of the path.  To match a file only in the root 
1919
 
    directory, prepend './'.
1920
 
 
1921
 
    Ignore patterns specifying absolute paths are not allowed.
1922
 
 
1923
 
    Ignore patterns may include globbing wildcards such as::
1924
 
 
1925
 
      ? - Matches any single character except '/'
1926
 
      * - Matches 0 or more characters except '/'
1927
 
      /**/ - Matches 0 or more directories in a path
1928
 
      [a-z] - Matches a single character from within a group of characters
1929
 
 
1930
 
    Ignore patterns may also be Python regular expressions.  
1931
 
    Regular expression ignore patterns are identified by a 'RE:' prefix 
1932
 
    followed by the regular expression.  Regular expression ignore patterns
1933
 
    may not include named or numbered groups.
 
1942
    After adding, editing or deleting that file either indirectly by
 
1943
    using this command or directly by using an editor, be sure to commit
 
1944
    it.
1934
1945
 
1935
1946
    Note: ignore patterns containing shell wildcards must be quoted from 
1936
1947
    the shell on Unix.
1957
1968
            bzr ignore "RE:(?!debian/).*"
1958
1969
    """
1959
1970
 
1960
 
    _see_also = ['status', 'ignored']
 
1971
    _see_also = ['status', 'ignored', 'patterns']
1961
1972
    takes_args = ['name_pattern*']
1962
1973
    takes_options = [
1963
1974
        Option('old-default-rules',
2118
2129
        else:
2119
2130
            if len(revision) != 1:
2120
2131
                raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
2121
 
            rev_id = revision[0].in_history(b).rev_id
 
2132
            rev_id = revision[0].as_revision_id(b)
2122
2133
        t = b.repository.revision_tree(rev_id)
2123
2134
        try:
2124
2135
            export(t, dest, format, root)
2163
2174
        if revision is None:
2164
2175
            revision_id = b.last_revision()
2165
2176
        else:
2166
 
            revision_id = revision[0].in_history(b).rev_id
 
2177
            revision_id = revision[0].as_revision_id(b)
2167
2178
 
2168
2179
        cur_file_id = tree.path2id(relpath)
2169
2180
        rev_tree = b.repository.revision_tree(revision_id)
2174
2185
                raise errors.BzrCommandError("%r is not present in revision %s"
2175
2186
                                                % (filename, revision_id))
2176
2187
            else:
2177
 
                rev_tree.print_file(old_file_id)
 
2188
                content = rev_tree.get_file_text(old_file_id)
2178
2189
        elif cur_file_id is not None:
2179
 
            rev_tree.print_file(cur_file_id)
 
2190
            content = rev_tree.get_file_text(cur_file_id)
2180
2191
        elif old_file_id is not None:
2181
 
            rev_tree.print_file(old_file_id)
 
2192
            content = rev_tree.get_file_text(old_file_id)
2182
2193
        else:
2183
2194
            raise errors.BzrCommandError("%r is not present in revision %s" %
2184
2195
                                         (filename, revision_id))
 
2196
        self.outf.write(content)
2185
2197
 
2186
2198
 
2187
2199
class cmd_local_time_offset(Command):
2373
2385
 
2374
2386
 
2375
2387
class cmd_check(Command):
2376
 
    """Validate consistency of branch history.
2377
 
 
2378
 
    This command checks various invariants about the branch storage to
2379
 
    detect data corruption or bzr bugs.
2380
 
 
2381
 
    Output fields:
 
2388
    """Validate working tree structure, branch consistency and repository
 
2389
    history.
 
2390
 
 
2391
    This command checks various invariants about branch and repository storage
 
2392
    to detect data corruption or bzr bugs.
 
2393
 
 
2394
    The working tree and branch checks will only give output if a problem is
 
2395
    detected. The output fields of the repository check are:
2382
2396
 
2383
2397
        revisions: This is just the number of revisions checked.  It doesn't
2384
2398
            indicate a problem.
2396
2410
    """
2397
2411
 
2398
2412
    _see_also = ['reconcile']
2399
 
    takes_args = ['branch?']
 
2413
    takes_args = ['path?']
2400
2414
    takes_options = ['verbose']
2401
2415
 
2402
 
    def run(self, branch=None, verbose=False):
2403
 
        from bzrlib.check import check
2404
 
        if branch is None:
2405
 
            branch_obj = Branch.open_containing('.')[0]
2406
 
        else:
2407
 
            branch_obj = Branch.open(branch)
2408
 
        check(branch_obj, verbose)
2409
 
        # bit hacky, check the tree parent is accurate
2410
 
        try:
2411
 
            if branch is None:
2412
 
                tree = WorkingTree.open_containing('.')[0]
2413
 
            else:
2414
 
                tree = WorkingTree.open(branch)
2415
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
2416
 
            pass
2417
 
        else:
2418
 
            # This is a primitive 'check' for tree state. Currently this is not
2419
 
            # integrated into the main check logic as yet.
2420
 
            tree.lock_read()
2421
 
            try:
2422
 
                tree_basis = tree.basis_tree()
2423
 
                tree_basis.lock_read()
2424
 
                try:
2425
 
                    repo_basis = tree.branch.repository.revision_tree(
2426
 
                        tree.last_revision())
2427
 
                    if len(list(repo_basis.iter_changes(tree_basis))):
2428
 
                        raise errors.BzrCheckError(
2429
 
                            "Mismatched basis inventory content.")
2430
 
                    tree._validate()
2431
 
                finally:
2432
 
                    tree_basis.unlock()
2433
 
            finally:
2434
 
                tree.unlock()
 
2416
    def run(self, path=None, verbose=False):
 
2417
        from bzrlib.check import check_dwim
 
2418
        if path is None:
 
2419
            path = '.'
 
2420
        check_dwim(path, verbose)
2435
2421
 
2436
2422
 
2437
2423
class cmd_upgrade(Command):
2531
2517
        print branch.nick
2532
2518
 
2533
2519
 
 
2520
class cmd_alias(Command):
 
2521
    """Set/unset and display aliases.
 
2522
 
 
2523
    :Examples:
 
2524
        Show the current aliases::
 
2525
 
 
2526
            bzr alias
 
2527
 
 
2528
        Show the alias specified for 'll'::
 
2529
 
 
2530
            bzr alias ll
 
2531
 
 
2532
        Set an alias for 'll'::
 
2533
 
 
2534
            bzr alias ll="log --line -r-10..-1"
 
2535
 
 
2536
        To remove an alias for 'll'::
 
2537
 
 
2538
            bzr alias --remove ll
 
2539
 
 
2540
    """
 
2541
    takes_args = ['name?']
 
2542
    takes_options = [
 
2543
        Option('remove', help='Remove the alias.'),
 
2544
        ]
 
2545
 
 
2546
    def run(self, name=None, remove=False):
 
2547
        if remove:
 
2548
            self.remove_alias(name)
 
2549
        elif name is None:
 
2550
            self.print_aliases()
 
2551
        else:
 
2552
            equal_pos = name.find('=')
 
2553
            if equal_pos == -1:
 
2554
                self.print_alias(name)
 
2555
            else:
 
2556
                self.set_alias(name[:equal_pos], name[equal_pos+1:])
 
2557
 
 
2558
    def remove_alias(self, alias_name):
 
2559
        if alias_name is None:
 
2560
            raise errors.BzrCommandError(
 
2561
                'bzr alias --remove expects an alias to remove.')
 
2562
        # If alias is not found, print something like:
 
2563
        # unalias: foo: not found
 
2564
        c = config.GlobalConfig()
 
2565
        c.unset_alias(alias_name)
 
2566
 
 
2567
    @display_command
 
2568
    def print_aliases(self):
 
2569
        """Print out the defined aliases in a similar format to bash."""
 
2570
        aliases = config.GlobalConfig().get_aliases()
 
2571
        for key, value in sorted(aliases.iteritems()):
 
2572
            self.outf.write('bzr alias %s="%s"\n' % (key, value))
 
2573
 
 
2574
    @display_command
 
2575
    def print_alias(self, alias_name):
 
2576
        from bzrlib.commands import get_alias
 
2577
        alias = get_alias(alias_name)
 
2578
        if alias is None:
 
2579
            self.outf.write("bzr alias: %s: not found\n" % alias_name)
 
2580
        else:
 
2581
            self.outf.write(
 
2582
                'bzr alias %s="%s"\n' % (alias_name, ' '.join(alias)))
 
2583
 
 
2584
    def set_alias(self, alias_name, alias_command):
 
2585
        """Save the alias in the global config."""
 
2586
        c = config.GlobalConfig()
 
2587
        c.set_alias(alias_name, alias_command)
 
2588
 
 
2589
 
2534
2590
class cmd_selftest(Command):
2535
2591
    """Run internal test suite.
2536
2592
    
2627
2683
                            'known failures.'),
2628
2684
                     Option('load-list', type=str, argname='TESTLISTFILE',
2629
2685
                            help='Load a test id list from a text file.'),
 
2686
                     ListOption('debugflag', type=str, short_name='E',
 
2687
                                help='Turn on a selftest debug flag.'),
 
2688
                     Option('starting-with', type=str, argname='TESTID',
 
2689
                            short_name='s',
 
2690
                            help='Load only the tests starting with TESTID.'),
2630
2691
                     ]
2631
2692
    encoding_type = 'replace'
2632
2693
 
2635
2696
            lsprof_timed=None, cache_dir=None,
2636
2697
            first=False, list_only=False,
2637
2698
            randomize=None, exclude=None, strict=False,
2638
 
            load_list=None):
 
2699
            load_list=None, debugflag=None, starting_with=None):
2639
2700
        import bzrlib.ui
2640
2701
        from bzrlib.tests import selftest
2641
2702
        import bzrlib.benchmarks as benchmarks
2642
2703
        from bzrlib.benchmarks import tree_creator
2643
2704
 
 
2705
        # Make deprecation warnings visible, unless -Werror is set
 
2706
        symbol_versioning.activate_deprecation_warnings(override=False)
 
2707
 
2644
2708
        if cache_dir is not None:
2645
2709
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2646
2710
        if not list_only:
2648
2712
            print '   %s (%s python%s)' % (
2649
2713
                    bzrlib.__path__[0],
2650
2714
                    bzrlib.version_string,
2651
 
                    '.'.join(map(str, sys.version_info)),
 
2715
                    bzrlib._format_version_tuple(sys.version_info),
2652
2716
                    )
2653
2717
        print
2654
2718
        if testspecs_list is not None:
2678
2742
                              exclude_pattern=exclude,
2679
2743
                              strict=strict,
2680
2744
                              load_list=load_list,
 
2745
                              debug_flags=debugflag,
 
2746
                              starting_with=starting_with,
2681
2747
                              )
2682
2748
        finally:
2683
2749
            if benchfile is not None:
2693
2759
    """Show version of bzr."""
2694
2760
 
2695
2761
    encoding_type = 'replace'
 
2762
    takes_options = [
 
2763
        Option("short", help="Print just the version number."),
 
2764
        ]
2696
2765
 
2697
2766
    @display_command
2698
 
    def run(self):
 
2767
    def run(self, short=False):
2699
2768
        from bzrlib.version import show_version
2700
 
        show_version(to_file=self.outf)
 
2769
        if short:
 
2770
            self.outf.write(bzrlib.version_string + '\n')
 
2771
        else:
 
2772
            show_version(to_file=self.outf)
2701
2773
 
2702
2774
 
2703
2775
class cmd_rocks(Command):
2743
2815
class cmd_merge(Command):
2744
2816
    """Perform a three-way merge.
2745
2817
    
2746
 
    The branch is the branch you will merge from.  By default, it will merge
2747
 
    the latest revision.  If you specify a revision, that revision will be
2748
 
    merged.  If you specify two revisions, the first will be used as a BASE,
2749
 
    and the second one as OTHER.  Revision numbers are always relative to the
2750
 
    specified branch.
 
2818
    The source of the merge can be specified either in the form of a branch,
 
2819
    or in the form of a path to a file containing a merge directive generated
 
2820
    with bzr send. If neither is specified, the default is the upstream branch
 
2821
    or the branch most recently merged using --remember.
 
2822
 
 
2823
    When merging a branch, by default the tip will be merged. To pick a different
 
2824
    revision, pass --revision. If you specify two values, the first will be used as
 
2825
    BASE and the second one as OTHER. Merging individual revisions, or a subset of
 
2826
    available revisions, like this is commonly referred to as "cherrypicking".
 
2827
 
 
2828
    Revision numbers are always relative to the branch being merged.
2751
2829
 
2752
2830
    By default, bzr will try to merge in all new work from the other
2753
2831
    branch, automatically determining an appropriate base.  If this
2784
2862
        To merge the changes introduced by 82, without previous changes::
2785
2863
 
2786
2864
            bzr merge -r 81..82 ../bzr.dev
 
2865
 
 
2866
        To apply a merge directive contained in in /tmp/merge:
 
2867
 
 
2868
            bzr merge /tmp/merge
2787
2869
    """
2788
2870
 
2789
2871
    encoding_type = 'exact'
2790
2872
    _see_also = ['update', 'remerge', 'status-flags']
2791
 
    takes_args = ['branch?']
 
2873
    takes_args = ['location?']
2792
2874
    takes_options = [
2793
2875
        'change',
2794
2876
        'revision',
2814
2896
        Option('preview', help='Instead of merging, show a diff of the merge.')
2815
2897
    ]
2816
2898
 
2817
 
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2818
 
            show_base=False, reprocess=False, remember=False,
 
2899
    def run(self, location=None, revision=None, force=False,
 
2900
            merge_type=None, show_base=False, reprocess=False, remember=False,
2819
2901
            uncommitted=False, pull=False,
2820
2902
            directory=None,
2821
2903
            preview=False,
2822
2904
            ):
2823
 
        # This is actually a branch (or merge-directive) *location*.
2824
 
        location = branch
2825
 
        del branch
2826
 
 
2827
2905
        if merge_type is None:
2828
2906
            merge_type = _mod_merge.Merge3Merger
2829
2907
 
2842
2920
            tree.lock_write()
2843
2921
            cleanups.append(tree.unlock)
2844
2922
            if location is not None:
2845
 
                mergeable, other_transport = _get_mergeable_helper(location)
2846
 
                if mergeable:
 
2923
                try:
 
2924
                    mergeable = bundle.read_mergeable_from_url(location,
 
2925
                        possible_transports=possible_transports)
 
2926
                except errors.NotABundle:
 
2927
                    mergeable = None
 
2928
                else:
2847
2929
                    if uncommitted:
2848
2930
                        raise errors.BzrCommandError('Cannot use --uncommitted'
2849
2931
                            ' with bundles or merge directives.')
2853
2935
                            'Cannot use -r with merge directives or bundles')
2854
2936
                    merger, verified = _mod_merge.Merger.from_mergeable(tree,
2855
2937
                       mergeable, pb)
2856
 
                possible_transports.append(other_transport)
2857
2938
 
2858
2939
            if merger is None and uncommitted:
2859
2940
                if revision is not None and len(revision) > 0:
2876
2957
            merger.show_base = show_base
2877
2958
            self.sanity_check_merger(merger)
2878
2959
            if (merger.base_rev_id == merger.other_rev_id and
2879
 
                merger.other_rev_id != None):
 
2960
                merger.other_rev_id is not None):
2880
2961
                note('Nothing to do.')
2881
2962
                return 0
2882
2963
            if pull:
2937
3018
                                possible_transports, pb):
2938
3019
        """Produce a merger from a location, assuming it refers to a branch."""
2939
3020
        from bzrlib.tag import _merge_tags_if_possible
2940
 
        assert revision is None or len(revision) < 3
2941
3021
        # find the branch locations
2942
3022
        other_loc, user_location = self._select_branch_location(tree, location,
2943
3023
            revision, -1)
2959
3039
            other_revision_id = _mod_revision.ensure_null(
2960
3040
                other_branch.last_revision())
2961
3041
        else:
2962
 
            other_revision_id = \
2963
 
                _mod_revision.ensure_null(
2964
 
                    revision[-1].in_history(other_branch).rev_id)
 
3042
            other_revision_id = revision[-1].as_revision_id(other_branch)
2965
3043
        if (revision is not None and len(revision) == 2
2966
3044
            and revision[0] is not None):
2967
 
            base_revision_id = \
2968
 
                _mod_revision.ensure_null(
2969
 
                    revision[0].in_history(base_branch).rev_id)
 
3045
            base_revision_id = revision[0].as_revision_id(base_branch)
2970
3046
        else:
2971
3047
            base_revision_id = None
2972
3048
        # Remember where we merge from
3185
3261
        elif len(revision) != 1:
3186
3262
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
3187
3263
        else:
3188
 
            rev_id = revision[0].in_history(tree.branch).rev_id
 
3264
            rev_id = revision[0].as_revision_id(tree.branch)
3189
3265
        pb = ui.ui_factory.nested_progress_bar()
3190
3266
        try:
3191
3267
            tree.revert(file_list,
3239
3315
        shellcomplete.shellcomplete(context)
3240
3316
 
3241
3317
 
3242
 
class cmd_fetch(Command):
3243
 
    """Copy in history from another branch but don't merge it.
3244
 
 
3245
 
    This is an internal method used for pull and merge.
3246
 
    """
3247
 
    hidden = True
3248
 
    takes_args = ['from_branch', 'to_branch']
3249
 
    def run(self, from_branch, to_branch):
3250
 
        from bzrlib.fetch import Fetcher
3251
 
        from_b = Branch.open(from_branch)
3252
 
        to_b = Branch.open(to_branch)
3253
 
        Fetcher(to_b, from_b)
3254
 
 
3255
 
 
3256
3318
class cmd_missing(Command):
3257
3319
    """Show unmerged/unpulled revisions between two branches.
3258
3320
    
3282
3344
        from bzrlib.missing import find_unmerged, iter_log_revisions
3283
3345
 
3284
3346
        if this:
3285
 
          mine_only = this
 
3347
            mine_only = this
3286
3348
        if other:
3287
 
          theirs_only = other
 
3349
            theirs_only = other
 
3350
        # TODO: We should probably check that we don't have mine-only and
 
3351
        #       theirs-only set, but it gets complicated because we also have
 
3352
        #       this and other which could be used.
 
3353
        restrict = 'all'
 
3354
        if mine_only:
 
3355
            restrict = 'local'
 
3356
        elif theirs_only:
 
3357
            restrict = 'remote'
3288
3358
 
3289
3359
        local_branch = Branch.open_containing(u".")[0]
3290
3360
        parent = local_branch.get_parent()
3304
3374
        try:
3305
3375
            remote_branch.lock_read()
3306
3376
            try:
3307
 
                local_extra, remote_extra = find_unmerged(local_branch,
3308
 
                                                          remote_branch)
 
3377
                local_extra, remote_extra = find_unmerged(
 
3378
                    local_branch, remote_branch, restrict)
 
3379
 
3309
3380
                if log_format is None:
3310
3381
                    registry = log.log_formatter_registry
3311
3382
                    log_format = registry.get_default(local_branch)
3313
3384
                                show_ids=show_ids,
3314
3385
                                show_timezone='original')
3315
3386
                if reverse is False:
3316
 
                    local_extra.reverse()
3317
 
                    remote_extra.reverse()
 
3387
                    if local_extra is not None:
 
3388
                        local_extra.reverse()
 
3389
                    if remote_extra is not None:
 
3390
                        remote_extra.reverse()
 
3391
 
 
3392
                status_code = 0
3318
3393
                if local_extra and not theirs_only:
3319
3394
                    self.outf.write("You have %d extra revision(s):\n" %
3320
3395
                                    len(local_extra))
3323
3398
                                        verbose):
3324
3399
                        lf.log_revision(revision)
3325
3400
                    printed_local = True
 
3401
                    status_code = 1
3326
3402
                else:
3327
3403
                    printed_local = False
 
3404
 
3328
3405
                if remote_extra and not mine_only:
3329
3406
                    if printed_local is True:
3330
3407
                        self.outf.write("\n\n\n")
3334
3411
                                        remote_branch.repository,
3335
3412
                                        verbose):
3336
3413
                        lf.log_revision(revision)
3337
 
                if not remote_extra and not local_extra:
3338
 
                    status_code = 0
 
3414
                    status_code = 1
 
3415
 
 
3416
                if mine_only and not local_extra:
 
3417
                    # We checked local, and found nothing extra
 
3418
                    self.outf.write('This branch is up to date.\n')
 
3419
                elif theirs_only and not remote_extra:
 
3420
                    # We checked remote, and found nothing extra
 
3421
                    self.outf.write('Other branch is up to date.\n')
 
3422
                elif not (mine_only or theirs_only or local_extra or
 
3423
                          remote_extra):
 
3424
                    # We checked both branches, and neither one had extra
 
3425
                    # revisions
3339
3426
                    self.outf.write("Branches are up to date.\n")
3340
 
                else:
3341
 
                    status_code = 1
3342
3427
            finally:
3343
3428
                remote_branch.unlock()
3344
3429
        finally:
3436
3521
            if revision is None:
3437
3522
                rev_id = b.last_revision()
3438
3523
            else:
3439
 
                rev_id = revision[0].in_history(b).rev_id
 
3524
                rev_id = revision[0].as_revision_id(b)
3440
3525
            t = testament_class.from_revision(b.repository, rev_id)
3441
3526
            if long:
3442
3527
                sys.stdout.writelines(t.as_text_lines())
3483
3568
            elif len(revision) != 1:
3484
3569
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
3485
3570
            else:
3486
 
                revision_id = revision[0].in_history(branch).rev_id
 
3571
                revision_id = revision[0].as_revision_id(branch)
3487
3572
            tree = branch.repository.revision_tree(revision_id)
3488
3573
            if wt is not None:
3489
3574
                file_id = wt.path2id(relpath)
3628
3713
    specified revision.  For example, "bzr uncommit -r 15" will leave the
3629
3714
    branch at revision 15.
3630
3715
 
3631
 
    In the future, uncommit will create a revision bundle, which can then
3632
 
    be re-applied.
 
3716
    Uncommit leaves the working tree ready for a new commit.  The only change
 
3717
    it may make is to restore any pending merges that were present before
 
3718
    the commit.
3633
3719
    """
3634
3720
 
3635
3721
    # TODO: jam 20060108 Add an option to allow uncommit to remove
3639
3725
    _see_also = ['commit']
3640
3726
    takes_options = ['verbose', 'revision',
3641
3727
                    Option('dry-run', help='Don\'t actually make changes.'),
3642
 
                    Option('force', help='Say yes to all questions.')]
 
3728
                    Option('force', help='Say yes to all questions.'),
 
3729
                    Option('local',
 
3730
                           help="Only remove the commits from the local branch"
 
3731
                                " when in a checkout."
 
3732
                           ),
 
3733
                    ]
3643
3734
    takes_args = ['location?']
3644
3735
    aliases = []
3645
3736
    encoding_type = 'replace'
3646
3737
 
3647
3738
    def run(self, location=None,
3648
3739
            dry_run=False, verbose=False,
3649
 
            revision=None, force=False):
 
3740
            revision=None, force=False, local=False):
3650
3741
        if location is None:
3651
3742
            location = u'.'
3652
3743
        control, relpath = bzrdir.BzrDir.open_containing(location)
3662
3753
        else:
3663
3754
            b.lock_write()
3664
3755
        try:
3665
 
            return self._run(b, tree, dry_run, verbose, revision, force)
 
3756
            return self._run(b, tree, dry_run, verbose, revision, force,
 
3757
                             local=local)
3666
3758
        finally:
3667
3759
            if tree is not None:
3668
3760
                tree.unlock()
3669
3761
            else:
3670
3762
                b.unlock()
3671
3763
 
3672
 
    def _run(self, b, tree, dry_run, verbose, revision, force):
 
3764
    def _run(self, b, tree, dry_run, verbose, revision, force, local=False):
3673
3765
        from bzrlib.log import log_formatter, show_log
3674
3766
        from bzrlib.uncommit import uncommit
3675
3767
 
3717
3809
                    return 0
3718
3810
 
3719
3811
        uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
3720
 
                 revno=revno)
 
3812
                 revno=revno, local=local)
3721
3813
 
3722
3814
 
3723
3815
class cmd_break_lock(Command):
3978
4070
            if len(revision) > 2:
3979
4071
                raise errors.BzrCommandError('bzr merge-directive takes '
3980
4072
                    'at most two one revision identifiers')
3981
 
            revision_id = revision[-1].in_history(branch).rev_id
 
4073
            revision_id = revision[-1].as_revision_id(branch)
3982
4074
            if len(revision) == 2:
3983
 
                base_revision_id = revision[0].in_history(branch).rev_id
3984
 
                base_revision_id = ensure_null(base_revision_id)
 
4075
                base_revision_id = revision[0].as_revision_id(branch)
3985
4076
        else:
3986
4077
            revision_id = branch.last_revision()
3987
4078
        revision_id = ensure_null(revision_id)
4049
4140
    older formats.  It is compatible with Bazaar 0.19 and later.  It is the
4050
4141
    default.  "0.9" uses revision bundle format 0.9 and merge directive
4051
4142
    format 1.  It is compatible with Bazaar 0.12 - 0.18.
 
4143
    
 
4144
    Merge directives are applied using the merge command or the pull command.
4052
4145
    """
4053
4146
 
4054
4147
    encoding_type = 'exact'
4055
4148
 
4056
 
    _see_also = ['merge']
 
4149
    _see_also = ['merge', 'pull']
4057
4150
 
4058
4151
    takes_args = ['submit_branch?', 'public_branch?']
4059
4152
 
4069
4162
               'rather than the one containing the working directory.',
4070
4163
               short_name='f',
4071
4164
               type=unicode),
4072
 
        Option('output', short_name='o', help='Write directive to this file.',
 
4165
        Option('output', short_name='o',
 
4166
               help='Write merge directive to this file; '
 
4167
                    'use - for stdout.',
4073
4168
               type=unicode),
4074
4169
        Option('mail-to', help='Mail the request to this address.',
4075
4170
               type=unicode),
4145
4240
                if len(revision) > 2:
4146
4241
                    raise errors.BzrCommandError('bzr send takes '
4147
4242
                        'at most two one revision identifiers')
4148
 
                revision_id = revision[-1].in_history(branch).rev_id
 
4243
                revision_id = revision[-1].as_revision_id(branch)
4149
4244
                if len(revision) == 2:
4150
 
                    base_revision_id = revision[0].in_history(branch).rev_id
 
4245
                    base_revision_id = revision[0].as_revision_id(branch)
4151
4246
            if revision_id is None:
4152
4247
                revision_id = branch.last_revision()
4153
4248
            if revision_id == NULL_REVISION:
4313
4408
                        raise errors.BzrCommandError(
4314
4409
                            "Tags can only be placed on a single revision, "
4315
4410
                            "not on a range")
4316
 
                    revision_id = revision[0].in_history(branch).rev_id
 
4411
                    revision_id = revision[0].as_revision_id(branch)
4317
4412
                else:
4318
4413
                    revision_id = branch.last_revision()
4319
4414
                if (not force) and branch.tags.has_tag(tag_name):
4398
4493
                     tree='Reconfigure to a tree.',
4399
4494
                     checkout='Reconfigure to a checkout.',
4400
4495
                     lightweight_checkout='Reconfigure to a lightweight'
4401
 
                     ' checkout.'),
 
4496
                     ' checkout.',
 
4497
                     standalone='Reconfigure to be standalone.',
 
4498
                     use_shared='Reconfigure to use a shared repository.'),
4402
4499
                     Option('bind-to', help='Branch to bind checkout to.',
4403
4500
                            type=str),
4404
4501
                     Option('force',
4420
4517
        elif target_type == 'lightweight-checkout':
4421
4518
            reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4422
4519
                directory, bind_to)
 
4520
        elif target_type == 'use-shared':
 
4521
            reconfiguration = reconfigure.Reconfigure.to_use_shared(directory)
 
4522
        elif target_type == 'standalone':
 
4523
            reconfiguration = reconfigure.Reconfigure.to_standalone(directory)
4423
4524
        reconfiguration.apply(force)
4424
4525
 
4425
4526
 
4435
4536
    are merged. The user can commit or revert these as they desire.
4436
4537
 
4437
4538
    Pending merges need to be committed or reverted before using switch.
 
4539
 
 
4540
    The path to the branch to switch to can be specified relative to the parent
 
4541
    directory of the current branch. For example, if you are currently in a
 
4542
    checkout of /path/to/branch, specifying 'newbranch' will find a branch at
 
4543
    /path/to/newbranch.
4438
4544
    """
4439
4545
 
4440
4546
    takes_args = ['to_location']
4444
4550
 
4445
4551
    def run(self, to_location, force=False):
4446
4552
        from bzrlib import switch
4447
 
        to_branch = Branch.open(to_location)
4448
4553
        tree_location = '.'
4449
4554
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
 
4555
        try:
 
4556
            to_branch = Branch.open(to_location)
 
4557
        except errors.NotBranchError:
 
4558
            to_branch = Branch.open(
 
4559
                control_dir.open_branch().base + '../' + to_location)
4450
4560
        switch.switch(control_dir, to_branch, force)
4451
4561
        note('Switched to branch: %s',
4452
4562
            urlutils.unescape_for_display(to_branch.base, 'utf-8'))
4496
4606
        cur_transport.ensure_base()
4497
4607
 
4498
4608
 
4499
 
def _get_mergeable_helper(location):
4500
 
    """Get a merge directive or bundle if 'location' points to one.
4501
 
 
4502
 
    Try try to identify a bundle and returns its mergeable form. If it's not,
4503
 
    we return the tried transport anyway so that it can reused to access the
4504
 
    branch
4505
 
 
4506
 
    :param location: can point to a bundle or a branch.
4507
 
 
4508
 
    :return: mergeable, transport
4509
 
    """
4510
 
    mergeable = None
4511
 
    url = urlutils.normalize_url(location)
4512
 
    url, filename = urlutils.split(url, exclude_trailing_slash=False)
4513
 
    location_transport = transport.get_transport(url)
4514
 
    if filename:
4515
 
        try:
4516
 
            # There may be redirections but we ignore the intermediate
4517
 
            # and final transports used
4518
 
            read = bundle.read_mergeable_from_transport
4519
 
            mergeable, t = read(location_transport, filename)
4520
 
        except errors.NotABundle:
4521
 
            # Continue on considering this url a Branch but adjust the
4522
 
            # location_transport
4523
 
            location_transport = location_transport.clone(filename)
4524
 
    return mergeable, location_transport
4525
 
 
4526
 
 
4527
4609
# these get imported and then picked up by the scan for cmd_*
4528
4610
# TODO: Some more consistent way to split command definitions across files;
4529
4611
# we do need to load at least some information about them to know of 
4535
4617
    cmd_bundle_info,
4536
4618
    )
4537
4619
from bzrlib.sign_my_commits import cmd_sign_my_commits
4538
 
from bzrlib.weave_commands import cmd_versionedfile_list, cmd_weave_join, \
 
4620
from bzrlib.weave_commands import cmd_versionedfile_list, \
4539
4621
        cmd_weave_plan_merge, cmd_weave_merge_text