~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

Merge from mbp.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
16
16
 
 
17
"""builtin bzr commands"""
 
18
 
17
19
# DO NOT change this to cStringIO - it results in control files 
18
20
# written as UCS4
19
21
# FIXIT! (Only deal with byte streams OR unicode at any one layer.)
20
22
# RBC 20051018
 
23
 
21
24
from StringIO import StringIO
22
25
import sys
23
26
import os
36
39
import bzrlib.trace
37
40
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
38
41
from bzrlib.workingtree import WorkingTree
 
42
from bzrlib.log import show_one_log
39
43
 
40
44
 
41
45
def tree_files(file_list, default_branch=u'.'):
58
62
    for filename in file_list:
59
63
        try:
60
64
            new_list.append(tree.relpath(filename))
61
 
        except NotBranchError:
 
65
        except errors.PathNotChild:
62
66
            raise FileInWrongBranch(tree.branch, filename)
63
67
    return tree, new_list
64
68
 
157
161
    """Show current revision number.
158
162
 
159
163
    This is equal to the number of revisions on this branch."""
 
164
    takes_args = ['location?']
160
165
    @display_command
161
 
    def run(self):
162
 
        print Branch.open_containing(u'.')[0].revno()
 
166
    def run(self, location=u'.'):
 
167
        print Branch.open_containing(location)[0].revno()
163
168
 
164
169
 
165
170
class cmd_revision_info(Command):
212
217
    implicitly add the parent, and so on up to the root. This means
213
218
    you should never need to explictly add a directory, they'll just
214
219
    get added when you add a file in the directory.
 
220
 
 
221
    --dry-run will show which files would be added, but not actually 
 
222
    add them.
215
223
    """
216
224
    takes_args = ['file*']
217
 
    takes_options = ['no-recurse']
218
 
    
219
 
    def run(self, file_list, no_recurse=False):
220
 
        from bzrlib.add import smart_add, add_reporter_print, add_reporter_null
221
 
        if is_quiet():
222
 
            reporter = add_reporter_null
 
225
    takes_options = ['no-recurse', 'dry-run', 'verbose']
 
226
 
 
227
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
 
228
        import bzrlib.add
 
229
 
 
230
        if dry_run:
 
231
            if is_quiet():
 
232
                # This is pointless, but I'd rather not raise an error
 
233
                action = bzrlib.add.add_action_null
 
234
            else:
 
235
                action = bzrlib.add.add_action_print
 
236
        elif is_quiet():
 
237
            action = bzrlib.add.add_action_add
223
238
        else:
224
 
            reporter = add_reporter_print
225
 
        smart_add(file_list, not no_recurse, reporter)
 
239
            action = bzrlib.add.add_action_add_and_print
 
240
 
 
241
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse, 
 
242
                                              action)
 
243
        if len(ignored) > 0:
 
244
            for glob in sorted(ignored.keys()):
 
245
                match_len = len(ignored[glob])
 
246
                if verbose:
 
247
                    for path in ignored[glob]:
 
248
                        print "ignored %s matching \"%s\"" % (path, glob)
 
249
                else:
 
250
                    print "ignored %d file(s) matching \"%s\"" % (match_len,
 
251
                                                              glob)
 
252
            print "If you wish to add some of these files, please add them"\
 
253
                " by name."
226
254
 
227
255
 
228
256
class cmd_mkdir(Command):
383
411
            else:
384
412
                print "Using saved location: %s" % stored_loc
385
413
                location = stored_loc
 
414
 
386
415
        br_from = Branch.open(location)
387
416
        br_to = tree_to.branch
388
 
        try:
389
 
            old_rh = br_to.revision_history()
390
 
            count = tree_to.pull(br_from, overwrite)
391
 
        except DivergedBranches:
392
 
            # FIXME: Just make DivergedBranches display the right message
393
 
            # itself.
394
 
            raise BzrCommandError("These branches have diverged."
395
 
                                  "  Try merge.")
 
417
 
 
418
        old_rh = br_to.revision_history()
 
419
        count = tree_to.pull(br_from, overwrite)
 
420
 
396
421
        if br_to.get_parent() is None or remember:
397
422
            br_to.set_parent(location)
398
423
        note('%d revision(s) pulled.' % (count,))
478
503
                            raise BzrCommandError("Could not creeate "
479
504
                                                  "path prefix.")
480
505
            br_to = Branch.initialize(location)
 
506
        old_rh = br_to.revision_history()
481
507
        try:
482
 
            old_rh = br_to.revision_history()
483
 
            count = br_to.pull(br_from, overwrite)
 
508
            try:
 
509
                tree_to = br_to.working_tree()
 
510
            except NoWorkingTree:
 
511
                # TODO: This should be updated for branches which don't have a
 
512
                # working tree, as opposed to ones where we just couldn't 
 
513
                # update the tree.
 
514
                warning('Unable to update the working tree of: %s' % (br_to.base,))
 
515
                count = br_to.pull(br_from, overwrite)
 
516
            else:
 
517
                count = tree_to.pull(br_from, overwrite)
484
518
        except DivergedBranches:
485
519
            raise BzrCommandError("These branches have diverged."
486
520
                                  "  Try a merge then push with overwrite.")
858
892
                            help='show from oldest to newest'),
859
893
                     'timezone', 'verbose', 
860
894
                     'show-ids', 'revision',
861
 
                     Option('line', help='format with one line per revision'),
862
 
                     'long', 
 
895
                     'line', 'long', 
863
896
                     Option('message',
864
897
                            help='show revisions whose message matches this regexp',
865
898
                            type=str),
866
 
                     Option('short', help='use moderately short format'),
 
899
                     'short',
867
900
                     ]
868
901
    @display_command
869
902
    def run(self, filename=None, timezone='original',
927
960
        # in e.g. the default C locale.
928
961
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
929
962
 
930
 
        log_format = 'long'
931
 
        if short:
932
 
            log_format = 'short'
933
 
        if line:
934
 
            log_format = 'line'
 
963
        log_format = get_log_format(long=long, short=short, line=line)
935
964
        lf = log_formatter(log_format,
936
965
                           show_ids=show_ids,
937
966
                           to_file=outf,
946
975
                 end_revision=rev2,
947
976
                 search=message)
948
977
 
 
978
def get_log_format(long=False, short=False, line=False, default='long'):
 
979
    log_format = default
 
980
    if long:
 
981
        log_format = 'long'
 
982
    if short:
 
983
        log_format = 'short'
 
984
    if line:
 
985
        log_format = 'line'
 
986
    return log_format
949
987
 
950
988
 
951
989
class cmd_touching_revisions(Command):
1171
1209
 
1172
1210
    @display_command
1173
1211
    def run(self, filename, revision=None):
1174
 
        if revision is None:
1175
 
            raise BzrCommandError("bzr cat requires a revision number")
1176
 
        elif len(revision) != 1:
 
1212
        if revision is not None and len(revision) != 1:
1177
1213
            raise BzrCommandError("bzr cat --revision takes exactly one number")
1178
1214
        tree = None
1179
1215
        try:
1181
1217
            b = tree.branch
1182
1218
        except NotBranchError:
1183
1219
            pass
 
1220
 
1184
1221
        if tree is None:
1185
1222
            b, relpath = Branch.open_containing(filename)
1186
 
        b.print_file(relpath, revision[0].in_history(b).revno)
 
1223
        if revision is None:
 
1224
            revision_id = b.last_revision()
 
1225
        else:
 
1226
            revision_id = revision[0].in_history(b).rev_id
 
1227
        b.print_file(relpath, revision_id)
1187
1228
 
1188
1229
 
1189
1230
class cmd_local_time_offset(Command):
1234
1275
            unchanged=False, strict=False):
1235
1276
        from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1236
1277
                StrictCommitFailed)
1237
 
        from bzrlib.msgeditor import edit_commit_message
 
1278
        from bzrlib.msgeditor import edit_commit_message, \
 
1279
                make_commit_message_template
1238
1280
        from bzrlib.status import show_status
1239
1281
        from tempfile import TemporaryFile
1240
1282
        import codecs
1241
1283
 
 
1284
        # TODO: Need a blackbox test for invoking the external editor; may be
 
1285
        # slightly problematic to run this cross-platform.
 
1286
 
1242
1287
        # TODO: do more checks that the commit will succeed before 
1243
1288
        # spending the user's valuable time typing a commit message.
1244
1289
        #
1246
1291
        # message to a temporary file where it can be recovered
1247
1292
        tree, selected_list = tree_files(selected_list)
1248
1293
        if message is None and not file:
1249
 
            template = make_commit_message_template(tree)
 
1294
            template = make_commit_message_template(tree, selected_list)
1250
1295
            message = edit_commit_message(template)
1251
1296
            if message is None:
1252
1297
                raise BzrCommandError("please specify a commit message"
1718
1763
 
1719
1764
 
1720
1765
class cmd_missing(Command):
1721
 
    """What is missing in this branch relative to other branch.
1722
 
    """
1723
 
    # TODO: rewrite this in terms of ancestry so that it shows only
1724
 
    # unmerged things
1725
 
    
1726
 
    takes_args = ['remote?']
1727
 
    aliases = ['mis', 'miss']
1728
 
    takes_options = ['verbose']
1729
 
 
1730
 
    @display_command
1731
 
    def run(self, remote=None, verbose=False):
1732
 
        from bzrlib.errors import BzrCommandError
1733
 
        from bzrlib.missing import show_missing
1734
 
 
1735
 
        if verbose and is_quiet():
1736
 
            raise BzrCommandError('Cannot pass both quiet and verbose')
1737
 
 
1738
 
        tree = WorkingTree.open_containing(u'.')[0]
1739
 
        parent = tree.branch.get_parent()
1740
 
        if remote is None:
1741
 
            if parent is None:
 
1766
    """Show unmerged/unpulled revisions between two branches.
 
1767
 
 
1768
    OTHER_BRANCH may be local or remote."""
 
1769
    takes_args = ['other_branch?']
 
1770
    takes_options = [Option('reverse', 'Reverse the order of revisions'),
 
1771
                     Option('mine-only', 
 
1772
                            'Display changes in the local branch only'),
 
1773
                     Option('theirs-only', 
 
1774
                            'Display changes in the remote branch only'), 
 
1775
                     'line',
 
1776
                     'long', 
 
1777
                     'short',
 
1778
                     'show-ids',
 
1779
                     'verbose'
 
1780
                     ]
 
1781
 
 
1782
    def run(self, other_branch=None, reverse=False, mine_only=False,
 
1783
            theirs_only=False, long=True, short=False, line=False, 
 
1784
            show_ids=False, verbose=False):
 
1785
        from bzrlib.missing import find_unmerged, iter_log_data
 
1786
        from bzrlib.log import log_formatter
 
1787
        local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
 
1788
        parent = local_branch.get_parent()
 
1789
        if other_branch is None:
 
1790
            other_branch = parent
 
1791
            if other_branch is None:
1742
1792
                raise BzrCommandError("No missing location known or specified.")
1743
 
            else:
1744
 
                if not is_quiet():
1745
 
                    print "Using last location: %s" % parent
1746
 
                remote = parent
1747
 
        elif parent is None:
1748
 
            # We only update parent if it did not exist, missing
1749
 
            # should not change the parent
1750
 
            tree.branch.set_parent(remote)
1751
 
        br_remote = Branch.open_containing(remote)[0]
1752
 
        return show_missing(tree.branch, br_remote, verbose=verbose, 
1753
 
                            quiet=is_quiet())
 
1793
            print "Using last location: " + local_branch.get_parent()
 
1794
        remote_branch = bzrlib.branch.Branch.open(other_branch)
 
1795
        local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
 
1796
        log_format = get_log_format(long=long, short=short, line=line)
 
1797
        lf = log_formatter(log_format, sys.stdout,
 
1798
                           show_ids=show_ids,
 
1799
                           show_timezone='original')
 
1800
        if reverse is False:
 
1801
            local_extra.reverse()
 
1802
            remote_extra.reverse()
 
1803
        if local_extra and not theirs_only:
 
1804
            print "You have %d extra revision(s):" % len(local_extra)
 
1805
            for data in iter_log_data(local_extra, local_branch, verbose):
 
1806
                lf.show(*data)
 
1807
            printed_local = True
 
1808
        else:
 
1809
            printed_local = False
 
1810
        if remote_extra and not mine_only:
 
1811
            if printed_local is True:
 
1812
                print "\n\n"
 
1813
            print "You are missing %d revision(s):" % len(remote_extra)
 
1814
            for data in iter_log_data(remote_extra, remote_branch, verbose):
 
1815
                lf.show(*data)
 
1816
        if not remote_extra and not local_extra:
 
1817
            status_code = 0
 
1818
            print "Branches are up to date."
 
1819
        else:
 
1820
            status_code = 1
 
1821
        if parent is None and other_branch is not None:
 
1822
            local_branch.set_parent(other_branch)
 
1823
        return status_code
1754
1824
 
1755
1825
 
1756
1826
class cmd_plugins(Command):
1760
1830
    def run(self):
1761
1831
        import bzrlib.plugin
1762
1832
        from inspect import getdoc
1763
 
        for plugin in bzrlib.plugin.all_plugins:
 
1833
        for name, plugin in bzrlib.plugin.all_plugins().items():
1764
1834
            if hasattr(plugin, '__path__'):
1765
1835
                print plugin.__path__[0]
1766
1836
            elif hasattr(plugin, '__file__'):