~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: John Arbash Meinel
  • Date: 2006-08-16 22:00:19 UTC
  • mto: This revision was merged to the branch mainline in revision 1942.
  • Revision ID: john@arbash-meinel.com-20060816220019-541cb90093258ac3
Using real utf8 and cache_utf8 has similar performance, 272ms, and 363ms

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
24
24
import sys
25
25
 
26
26
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
    )
27
41
from bzrlib.branch import Branch, BranchReferenceFormat
28
 
from bzrlib import (bundle, branch, bzrdir, errors, osutils, ui, config,
29
 
    repository, log)
30
42
from bzrlib.bundle import read_bundle_from_url
31
43
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
32
44
from bzrlib.conflicts import ConflictList
42
54
from bzrlib.revisionspec import RevisionSpec
43
55
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
44
56
from bzrlib.transport.local import LocalTransport
45
 
import bzrlib.urlutils as urlutils
46
57
from bzrlib.workingtree import WorkingTree
47
58
 
48
59
 
263
274
 
264
275
    --dry-run will show which files would be added, but not actually 
265
276
    add them.
 
277
 
 
278
    --file-ids-from will try to use the file ids from the supplied path.
 
279
    It looks up ids trying to find a matching parent directory with the
 
280
    same filename, and then by pure path.
266
281
    """
267
282
    takes_args = ['file*']
268
 
    takes_options = ['no-recurse', 'dry-run', 'verbose']
 
283
    takes_options = ['no-recurse', 'dry-run', 'verbose',
 
284
                     Option('file-ids-from', type=unicode,
 
285
                            help='Lookup file ids from here')]
269
286
    encoding_type = 'replace'
270
287
 
271
 
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
 
288
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
 
289
            file_ids_from=None):
272
290
        import bzrlib.add
273
291
 
274
 
        action = bzrlib.add.AddAction(to_file=self.outf,
275
 
            should_print=(not is_quiet()))
276
 
 
277
 
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse, 
 
292
        if file_ids_from is not None:
 
293
            try:
 
294
                base_tree, base_path = WorkingTree.open_containing(
 
295
                                            file_ids_from)
 
296
            except errors.NoWorkingTree:
 
297
                base_branch, base_path = branch.Branch.open_containing(
 
298
                                            file_ids_from)
 
299
                base_tree = base_branch.basis_tree()
 
300
 
 
301
            action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
 
302
                          to_file=self.outf, should_print=(not is_quiet()))
 
303
        else:
 
304
            action = bzrlib.add.AddAction(to_file=self.outf,
 
305
                should_print=(not is_quiet()))
 
306
 
 
307
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
278
308
                                              action=action, save=not dry_run)
279
309
        if len(ignored) > 0:
280
310
            if verbose:
516
546
            create_prefix=False, verbose=False):
517
547
        # FIXME: Way too big!  Put this into a function called from the
518
548
        # command.
519
 
        from bzrlib.transport import get_transport
520
549
        
521
550
        br_from = Branch.open_containing('.')[0]
522
551
        stored_loc = br_from.get_push_location()
529
558
                self.outf.write("Using saved location: %s\n" % display_url)
530
559
                location = stored_loc
531
560
 
532
 
        transport = get_transport(location)
533
 
        location_url = transport.base
 
561
        to_transport = transport.get_transport(location)
 
562
        location_url = to_transport.base
534
563
 
535
564
        old_rh = []
536
565
        try:
538
567
            br_to = dir_to.open_branch()
539
568
        except NotBranchError:
540
569
            # create a branch.
541
 
            transport = transport.clone('..')
 
570
            to_transport = to_transport.clone('..')
542
571
            if not create_prefix:
543
572
                try:
544
 
                    relurl = transport.relpath(location_url)
 
573
                    relurl = to_transport.relpath(location_url)
545
574
                    mutter('creating directory %s => %s', location_url, relurl)
546
 
                    transport.mkdir(relurl)
 
575
                    to_transport.mkdir(relurl)
547
576
                except NoSuchFile:
548
577
                    raise BzrCommandError("Parent directory of %s "
549
578
                                          "does not exist." % location)
550
579
            else:
551
 
                current = transport.base
552
 
                needed = [(transport, transport.relpath(location_url))]
 
580
                current = to_transport.base
 
581
                needed = [(to_transport, to_transport.relpath(location_url))]
553
582
                while needed:
554
583
                    try:
555
 
                        transport, relpath = needed[-1]
556
 
                        transport.mkdir(relpath)
 
584
                        to_transport, relpath = needed[-1]
 
585
                        to_transport.mkdir(relpath)
557
586
                        needed.pop()
558
587
                    except NoSuchFile:
559
 
                        new_transport = transport.clone('..')
 
588
                        new_transport = to_transport.clone('..')
560
589
                        needed.append((new_transport,
561
 
                                       new_transport.relpath(transport.base)))
562
 
                        if new_transport.base == transport.base:
 
590
                                       new_transport.relpath(to_transport.base)))
 
591
                        if new_transport.base == to_transport.base:
563
592
                            raise BzrCommandError("Could not create "
564
593
                                                  "path prefix.")
565
594
            dir_to = br_from.bzrdir.clone(location_url,
618
647
    aliases = ['get', 'clone']
619
648
 
620
649
    def run(self, from_location, to_location=None, revision=None, basis=None):
621
 
        from bzrlib.transport import get_transport
622
650
        if revision is None:
623
651
            revision = [None]
624
652
        elif len(revision) > 1:
651
679
            else:
652
680
                name = os.path.basename(to_location) + '\n'
653
681
 
654
 
            to_transport = get_transport(to_location)
 
682
            to_transport = transport.get_transport(to_location)
655
683
            try:
656
684
                to_transport.mkdir('.')
657
685
            except errors.FileExists:
753
781
        old_format = bzrdir.BzrDirFormat.get_default_format()
754
782
        bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
755
783
        try:
756
 
            if lightweight:
757
 
                checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
758
 
                branch.BranchReferenceFormat().initialize(checkout, source)
759
 
            else:
760
 
                checkout_branch =  bzrdir.BzrDir.create_branch_convenience(
761
 
                    to_location, force_new_tree=False)
762
 
                checkout = checkout_branch.bzrdir
763
 
                checkout_branch.bind(source)
764
 
                if revision_id is not None:
765
 
                    rh = checkout_branch.revision_history()
766
 
                    checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
767
 
            checkout.create_workingtree(revision_id)
 
784
            source.create_checkout(to_location, revision_id, lightweight)
768
785
        finally:
769
786
            bzrdir.BzrDirFormat.set_default_format(old_format)
770
787
 
800
817
    'bzr revert' instead of 'bzr commit' after the update.
801
818
    """
802
819
    takes_args = ['dir?']
 
820
    aliases = ['up']
803
821
 
804
822
    def run(self, dir='.'):
805
823
        tree = WorkingTree.open_containing(dir)[0]
806
824
        tree.lock_write()
 
825
        existing_pending_merges = tree.pending_merges()
807
826
        try:
808
827
            last_rev = tree.last_revision() 
809
828
            if last_rev == tree.branch.last_revision():
816
835
            conflicts = tree.update()
817
836
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
818
837
            note('Updated to revision %d.' % (revno,))
 
838
            if tree.pending_merges() != existing_pending_merges:
 
839
                note('Your local commits will now show as pending merges with '
 
840
                     "'bzr status', and can be committed with 'bzr commit'.")
819
841
            if conflicts != 0:
820
842
                return 1
821
843
            else:
866
888
                raise BzrCommandError('Specify one or more files to remove, or'
867
889
                                      ' use --new.')
868
890
        else:
869
 
            from bzrlib.delta import compare_trees
870
 
            added = [compare_trees(tree.basis_tree(), tree,
871
 
                                   specific_files=file_list).added]
872
 
            file_list = sorted([f[0] for f in added[0]], reverse=True)
 
891
            added = tree.changes_from(tree.basis_tree(),
 
892
                specific_files=file_list).added
 
893
            file_list = sorted([f[0] for f in added], reverse=True)
873
894
            if len(file_list) == 0:
874
895
                raise BzrCommandError('No matching files.')
875
896
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
1016
1037
            format = get_format_type('default')
1017
1038
        if location is None:
1018
1039
            location = u'.'
1019
 
        else:
1020
 
            # The path has to exist to initialize a
1021
 
            # branch inside of it.
1022
 
            # Just using os.mkdir, since I don't
1023
 
            # believe that we want to create a bunch of
1024
 
            # locations if the user supplies an extended path
1025
 
            if not os.path.exists(location):
1026
 
                os.mkdir(location)
 
1040
 
 
1041
        to_transport = transport.get_transport(location)
 
1042
 
 
1043
        # The path has to exist to initialize a
 
1044
        # branch inside of it.
 
1045
        # Just using os.mkdir, since I don't
 
1046
        # believe that we want to create a bunch of
 
1047
        # locations if the user supplies an extended path
 
1048
        # TODO: create-prefix
 
1049
        try:
 
1050
            to_transport.mkdir('.')
 
1051
        except errors.FileExists:
 
1052
            pass
 
1053
                    
1027
1054
        try:
1028
1055
            existing_bzrdir = bzrdir.BzrDir.open(location)
1029
1056
        except NotBranchError:
1031
1058
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1032
1059
        else:
1033
1060
            if existing_bzrdir.has_branch():
1034
 
                if existing_bzrdir.has_workingtree():
1035
 
                    raise errors.AlreadyBranchError(location)
1036
 
                else:
1037
 
                    raise errors.BranchExistsWithoutWorkingTree(location)
 
1061
                if (isinstance(to_transport, LocalTransport)
 
1062
                    and not existing_bzrdir.has_workingtree()):
 
1063
                        raise errors.BranchExistsWithoutWorkingTree(location)
 
1064
                raise errors.AlreadyBranchError(location)
1038
1065
            else:
1039
1066
                existing_bzrdir.create_branch()
1040
1067
                existing_bzrdir.create_workingtree()
1066
1093
                             ' a working tree')]
1067
1094
    aliases = ["init-repo"]
1068
1095
    def run(self, location, format=None, trees=False):
1069
 
        from bzrlib.transport import get_transport
1070
1096
        if format is None:
1071
1097
            format = get_format_type('default')
1072
 
        transport = get_transport(location)
1073
 
        if not transport.has('.'):
1074
 
            transport.mkdir('')
1075
 
        newdir = format.initialize_on_transport(transport)
 
1098
 
 
1099
        if location is None:
 
1100
            location = '.'
 
1101
 
 
1102
        to_transport = transport.get_transport(location)
 
1103
        try:
 
1104
            to_transport.mkdir('.')
 
1105
        except errors.FileExists:
 
1106
            pass
 
1107
 
 
1108
        newdir = format.initialize_on_transport(to_transport)
1076
1109
        repo = newdir.create_repository(shared=True)
1077
1110
        repo.set_make_working_trees(trees)
1078
1111
 
1149
1182
                raise BzrCommandError("Files are in different branches")
1150
1183
            file_list = None
1151
1184
        except NotBranchError:
1152
 
            # Don't raise an error when bzr diff is called from
1153
 
            # outside a working tree.
1154
 
            tree1, tree2 = None, None
 
1185
            if (revision is not None and len(revision) == 2
 
1186
                and not revision[0].needs_branch()
 
1187
                and not revision[1].needs_branch()):
 
1188
                # If both revision specs include a branch, we can
 
1189
                # diff them without needing a local working tree
 
1190
                tree1, tree2 = None, None
 
1191
            else:
 
1192
                raise
1155
1193
        if revision is not None:
1156
1194
            if tree2 is not None:
1157
1195
                raise BzrCommandError("Can't specify -r with two branches")
1205
1243
    hidden = True
1206
1244
    @display_command
1207
1245
    def run(self):
1208
 
        from bzrlib.delta import compare_trees
1209
 
 
1210
1246
        tree = WorkingTree.open_containing(u'.')[0]
1211
 
        td = compare_trees(tree.basis_tree(), tree)
1212
 
 
 
1247
        td = tree.changes_from(tree.basis_tree())
1213
1248
        for path, id, kind, text_modified, meta_modified in td.modified:
1214
1249
            self.outf.write(path + '\n')
1215
1250
 
1480
1515
        from bzrlib.atomicfile import AtomicFile
1481
1516
        if old_default_rules is not None:
1482
1517
            # dump the rules and exit
1483
 
            for pattern in bzrlib.DEFAULT_IGNORE:
 
1518
            for pattern in ignores.OLD_DEFAULTS:
1484
1519
                print pattern
1485
1520
            return
1486
1521
        if name_pattern is None:
1732
1767
            raise BzrCommandError("Commit refused because there are unknown "
1733
1768
                                  "files in the working tree.")
1734
1769
        except errors.BoundBranchOutOfDate, e:
1735
 
            raise BzrCommandError(str(e)
1736
 
                                  + ' Either unbind, update, or'
1737
 
                                    ' pass --local to commit.')
1738
 
 
 
1770
            raise BzrCommandError(str(e) + "\n"
 
1771
                'To commit to master branch, run update and then commit.\n'
 
1772
                'You can also pass --local to commit to continue working '
 
1773
                'disconnected.')
1739
1774
 
1740
1775
class cmd_check(Command):
1741
1776
    """Validate consistency of branch history.
1917
1952
                     Option('lsprof-timed',
1918
1953
                            help='generate lsprof output for benchmarked'
1919
1954
                                 ' sections of code.'),
 
1955
                     Option('cache-dir', type=str,
 
1956
                            help='a directory to cache intermediate'
 
1957
                                 ' benchmark steps'),
1920
1958
                     ]
1921
1959
 
1922
1960
    def run(self, testspecs_list=None, verbose=None, one=False,
1923
1961
            keep_output=False, transport=None, benchmark=None,
1924
 
            lsprof_timed=None):
 
1962
            lsprof_timed=None, cache_dir=None):
1925
1963
        import bzrlib.ui
1926
1964
        from bzrlib.tests import selftest
1927
1965
        import bzrlib.benchmarks as benchmarks
 
1966
        from bzrlib.benchmarks import tree_creator
 
1967
 
 
1968
        if cache_dir is not None:
 
1969
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
1928
1970
        # we don't want progress meters from the tests to go to the
1929
1971
        # real output; and we don't want log messages cluttering up
1930
1972
        # the real logs.
1943
1985
                test_suite_factory = benchmarks.test_suite
1944
1986
                if verbose is None:
1945
1987
                    verbose = True
 
1988
                benchfile = open(".perf_history", "at")
1946
1989
            else:
1947
1990
                test_suite_factory = None
1948
1991
                if verbose is None:
1949
1992
                    verbose = False
1950
 
            result = selftest(verbose=verbose, 
1951
 
                              pattern=pattern,
1952
 
                              stop_on_failure=one, 
1953
 
                              keep_output=keep_output,
1954
 
                              transport=transport,
1955
 
                              test_suite_factory=test_suite_factory,
1956
 
                              lsprof_timed=lsprof_timed)
 
1993
                benchfile = None
 
1994
            try:
 
1995
                result = selftest(verbose=verbose, 
 
1996
                                  pattern=pattern,
 
1997
                                  stop_on_failure=one, 
 
1998
                                  keep_output=keep_output,
 
1999
                                  transport=transport,
 
2000
                                  test_suite_factory=test_suite_factory,
 
2001
                                  lsprof_timed=lsprof_timed,
 
2002
                                  bench_history=benchfile)
 
2003
            finally:
 
2004
                if benchfile is not None:
 
2005
                    benchfile.close()
1957
2006
            if result:
1958
2007
                info('tests passed')
1959
2008
            else:
1963
2012
            ui.ui_factory = save_ui
1964
2013
 
1965
2014
 
1966
 
def _get_bzr_branch():
1967
 
    """If bzr is run from a branch, return Branch or None"""
1968
 
    from os.path import dirname
1969
 
    
1970
 
    try:
1971
 
        branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
1972
 
        return branch
1973
 
    except errors.BzrError:
1974
 
        return None
1975
 
    
1976
 
 
1977
 
def show_version():
1978
 
    import bzrlib
1979
 
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
1980
 
    # is bzrlib itself in a branch?
1981
 
    branch = _get_bzr_branch()
1982
 
    if branch:
1983
 
        rh = branch.revision_history()
1984
 
        revno = len(rh)
1985
 
        print "  bzr checkout, revision %d" % (revno,)
1986
 
        print "  nick: %s" % (branch.nick,)
1987
 
        if rh:
1988
 
            print "  revid: %s" % (rh[-1],)
1989
 
    print "Using python interpreter:", sys.executable
1990
 
    import site
1991
 
    print "Using python standard library:", os.path.dirname(site.__file__)
1992
 
    print "Using bzrlib:",
1993
 
    if len(bzrlib.__path__) > 1:
1994
 
        # print repr, which is a good enough way of making it clear it's
1995
 
        # more than one element (eg ['/foo/bar', '/foo/bzr'])
1996
 
        print repr(bzrlib.__path__)
1997
 
    else:
1998
 
        print bzrlib.__path__[0]
1999
 
 
2000
 
    print
2001
 
    print bzrlib.__copyright__
2002
 
    print "http://bazaar-vcs.org/"
2003
 
    print
2004
 
    print "bzr comes with ABSOLUTELY NO WARRANTY.  bzr is free software, and"
2005
 
    print "you may use, modify and redistribute it under the terms of the GNU"
2006
 
    print "General Public License version 2 or later."
2007
 
 
2008
 
 
2009
2015
class cmd_version(Command):
2010
2016
    """Show version of bzr."""
 
2017
 
2011
2018
    @display_command
2012
2019
    def run(self):
 
2020
        from bzrlib.version import show_version
2013
2021
        show_version()
2014
2022
 
 
2023
 
2015
2024
class cmd_rocks(Command):
2016
2025
    """Statement of optimism."""
 
2026
 
2017
2027
    hidden = True
 
2028
 
2018
2029
    @display_command
2019
2030
    def run(self):
2020
2031
        print "it sure does!"
2021
2032
 
2022
2033
 
2023
2034
class cmd_find_merge_base(Command):
2024
 
    """Find and print a base revision for merging two branches.
2025
 
    """
 
2035
    """Find and print a base revision for merging two branches."""
2026
2036
    # TODO: Options to specify revisions on either side, as if
2027
2037
    #       merging only part of the history.
2028
2038
    takes_args = ['branch', 'other']
2093
2103
    takes_args = ['branch?']
2094
2104
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2095
2105
                     Option('show-base', help="Show base revision text in "
2096
 
                            "conflicts")]
 
2106
                            "conflicts"), 
 
2107
                     Option('uncommitted', help='Apply uncommitted changes'
 
2108
                            ' from a working copy, instead of branch changes')]
2097
2109
 
2098
2110
    def help(self):
2099
2111
        from merge import merge_type_help
2101
2113
        return getdoc(self) + '\n' + merge_type_help() 
2102
2114
 
2103
2115
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2104
 
            show_base=False, reprocess=False, remember=False):
 
2116
            show_base=False, reprocess=False, remember=False, 
 
2117
            uncommitted=False):
2105
2118
        if merge_type is None:
2106
2119
            merge_type = Merge3Merger
2107
2120
 
2123
2136
        branch = self._get_remembered_parent(tree, branch, 'Merging from')
2124
2137
 
2125
2138
        if revision is None or len(revision) < 1:
2126
 
            base = [None, None]
2127
 
            other = [branch, -1]
 
2139
            if uncommitted:
 
2140
                base = [branch, -1]
 
2141
                other = [branch, None]
 
2142
            else:
 
2143
                base = [None, None]
 
2144
                other = [branch, -1]
2128
2145
            other_branch, path = Branch.open_containing(branch)
2129
2146
        else:
 
2147
            if uncommitted:
 
2148
                raise BzrCommandError('Cannot use --uncommitted and --revision'
 
2149
                                      ' at the same time.')
2130
2150
            if len(revision) == 1:
2131
2151
                base = [None, None]
2132
2152
                other_branch, path = Branch.open_containing(branch)
2395
2415
        if other_branch is None:
2396
2416
            other_branch = parent
2397
2417
            if other_branch is None:
2398
 
                raise BzrCommandError("No missing location known or specified.")
 
2418
                raise BzrCommandError("No peer location known or specified.")
2399
2419
            print "Using last location: " + local_branch.get_parent()
2400
2420
        remote_branch = Branch.open(other_branch)
2401
2421
        if remote_branch.base == local_branch.base:
2473
2493
 
2474
2494
class cmd_testament(Command):
2475
2495
    """Show testament (signing-form) of a revision."""
2476
 
    takes_options = ['revision', 'long', 
 
2496
    takes_options = ['revision', 
 
2497
                     Option('long', help='Produce long-format testament'), 
2477
2498
                     Option('strict', help='Produce a strict-format'
2478
2499
                            ' testament')]
2479
2500
    takes_args = ['branch?']