~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

[patch] use unicode literals for all hardcoded paths (Alexander Belchenko)

> When you use flat string on Windows for base part of file names then all
> derived file names is always representing as flat string. On Linux/Cygwin as
> I can see in situations when path cannot be represented as flat string (or in
> ascii encoding?) it silently converted to unicode. As result we have
> different behaviour with non-ascii (non-english) file names.

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
 
 
19
17
# DO NOT change this to cStringIO - it results in control files 
20
18
# written as UCS4
21
19
# FIXIT! (Only deal with byte streams OR unicode at any one layer.)
22
20
# RBC 20051018
23
 
 
24
21
from StringIO import StringIO
25
22
import sys
26
23
import os
39
36
import bzrlib.trace
40
37
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
41
38
from bzrlib.workingtree import WorkingTree
42
 
from bzrlib.log import show_one_log
43
39
 
44
40
 
45
41
def tree_files(file_list, default_branch=u'.'):
62
58
    for filename in file_list:
63
59
        try:
64
60
            new_list.append(tree.relpath(filename))
65
 
        except errors.PathNotChild:
 
61
        except NotBranchError:
66
62
            raise FileInWrongBranch(tree.branch, filename)
67
63
    return tree, new_list
68
64
 
161
157
    """Show current revision number.
162
158
 
163
159
    This is equal to the number of revisions on this branch."""
164
 
    takes_args = ['location?']
165
160
    @display_command
166
 
    def run(self, location=u'.'):
167
 
        print Branch.open_containing(location)[0].revno()
 
161
    def run(self):
 
162
        print Branch.open_containing(u'.')[0].revno()
168
163
 
169
164
 
170
165
class cmd_revision_info(Command):
217
212
    implicitly add the parent, and so on up to the root. This means
218
213
    you should never need to explictly add a directory, they'll just
219
214
    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.
223
215
    """
224
216
    takes_args = ['file*']
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
 
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
238
223
        else:
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."
 
224
            reporter = add_reporter_print
 
225
        smart_add(file_list, not no_recurse, reporter)
254
226
 
255
227
 
256
228
class cmd_mkdir(Command):
411
383
            else:
412
384
                print "Using saved location: %s" % stored_loc
413
385
                location = stored_loc
414
 
 
415
386
        br_from = Branch.open(location)
416
387
        br_to = tree_to.branch
417
 
 
418
 
        old_rh = br_to.revision_history()
419
 
        count = tree_to.pull(br_from, overwrite)
420
 
 
 
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.")
421
396
        if br_to.get_parent() is None or remember:
422
397
            br_to.set_parent(location)
423
 
        note('%d revision(s) pulled.' % (count,))
424
 
 
 
398
        note('%d revision(s) pulled.', count)
425
399
        if verbose:
426
400
            new_rh = tree_to.branch.revision_history()
427
401
            if old_rh != new_rh:
503
477
                            raise BzrCommandError("Could not creeate "
504
478
                                                  "path prefix.")
505
479
            br_to = Branch.initialize(location)
506
 
        old_rh = br_to.revision_history()
507
480
        try:
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)
 
481
            old_rh = br_to.revision_history()
 
482
            count = br_to.pull(br_from, overwrite)
518
483
        except DivergedBranches:
519
484
            raise BzrCommandError("These branches have diverged."
520
485
                                  "  Try a merge then push with overwrite.")
521
486
        if br_from.get_push_location() is None or remember:
522
487
            br_from.set_push_location(location)
523
488
        note('%d revision(s) pushed.' % (count,))
524
 
 
525
489
        if verbose:
526
490
            new_rh = br_to.revision_history()
527
491
            if old_rh != new_rh:
892
856
                            help='show from oldest to newest'),
893
857
                     'timezone', 'verbose', 
894
858
                     'show-ids', 'revision',
895
 
                     'line', 'long', 
 
859
                     Option('line', help='format with one line per revision'),
 
860
                     'long', 
896
861
                     Option('message',
897
862
                            help='show revisions whose message matches this regexp',
898
863
                            type=str),
899
 
                     'short',
 
864
                     Option('short', help='use moderately short format'),
900
865
                     ]
901
866
    @display_command
902
867
    def run(self, filename=None, timezone='original',
960
925
        # in e.g. the default C locale.
961
926
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
962
927
 
963
 
        log_format = get_log_format(long=long, short=short, line=line)
 
928
        log_format = 'long'
 
929
        if short:
 
930
            log_format = 'short'
 
931
        if line:
 
932
            log_format = 'line'
964
933
        lf = log_formatter(log_format,
965
934
                           show_ids=show_ids,
966
935
                           to_file=outf,
975
944
                 end_revision=rev2,
976
945
                 search=message)
977
946
 
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
987
947
 
988
948
 
989
949
class cmd_touching_revisions(Command):
1209
1169
 
1210
1170
    @display_command
1211
1171
    def run(self, filename, revision=None):
1212
 
        if revision is not None and len(revision) != 1:
 
1172
        if revision is None:
 
1173
            raise BzrCommandError("bzr cat requires a revision number")
 
1174
        elif len(revision) != 1:
1213
1175
            raise BzrCommandError("bzr cat --revision takes exactly one number")
1214
1176
        tree = None
1215
1177
        try:
1217
1179
            b = tree.branch
1218
1180
        except NotBranchError:
1219
1181
            pass
1220
 
 
1221
1182
        if tree is None:
1222
1183
            b, relpath = Branch.open_containing(filename)
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)
 
1184
        b.print_file(relpath, revision[0].in_history(b).revno)
1228
1185
 
1229
1186
 
1230
1187
class cmd_local_time_offset(Command):
1275
1232
            unchanged=False, strict=False):
1276
1233
        from bzrlib.errors import (PointlessCommit, ConflictsInTree,
1277
1234
                StrictCommitFailed)
1278
 
        from bzrlib.msgeditor import edit_commit_message, \
1279
 
                make_commit_message_template
 
1235
        from bzrlib.msgeditor import edit_commit_message
1280
1236
        from bzrlib.status import show_status
1281
 
        from tempfile import TemporaryFile
1282
 
        import codecs
1283
 
 
1284
 
        # TODO: Need a blackbox test for invoking the external editor; may be
1285
 
        # slightly problematic to run this cross-platform.
1286
 
 
1287
 
        # TODO: do more checks that the commit will succeed before 
1288
 
        # spending the user's valuable time typing a commit message.
1289
 
        #
1290
 
        # TODO: if the commit *does* happen to fail, then save the commit 
1291
 
        # message to a temporary file where it can be recovered
 
1237
        from cStringIO import StringIO
 
1238
 
1292
1239
        tree, selected_list = tree_files(selected_list)
1293
1240
        if message is None and not file:
1294
 
            template = make_commit_message_template(tree, selected_list)
1295
 
            message = edit_commit_message(template)
 
1241
            catcher = StringIO()
 
1242
            show_status(tree.branch, specific_files=selected_list,
 
1243
                        to_file=catcher)
 
1244
            message = edit_commit_message(catcher.getvalue())
 
1245
 
1296
1246
            if message is None:
1297
1247
                raise BzrCommandError("please specify a commit message"
1298
1248
                                      " with either --message or --file")
1321
1271
            raise BzrCommandError("Commit refused because there are unknown "
1322
1272
                                  "files in the working tree.")
1323
1273
        note('Committed revision %d.' % (tree.branch.revno(),))
1324
 
 
 
1274
        
1325
1275
 
1326
1276
class cmd_check(Command):
1327
1277
    """Validate consistency of branch history.
1461
1411
            bzrlib.ui.ui_factory = save_ui
1462
1412
 
1463
1413
 
1464
 
def _get_bzr_branch():
1465
 
    """If bzr is run from a branch, return Branch or None"""
1466
 
    import bzrlib.errors
1467
 
    from bzrlib.branch import Branch
1468
 
    from bzrlib.osutils import abspath
1469
 
    from os.path import dirname
1470
 
    
1471
 
    try:
1472
 
        branch = Branch.open(dirname(abspath(dirname(__file__))))
1473
 
        return branch
1474
 
    except bzrlib.errors.BzrError:
1475
 
        return None
1476
 
    
1477
 
 
1478
1414
def show_version():
1479
1415
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
1480
1416
    # is bzrlib itself in a branch?
1481
 
    branch = _get_bzr_branch()
1482
 
    if branch:
1483
 
        rh = branch.revision_history()
1484
 
        revno = len(rh)
1485
 
        print "  bzr checkout, revision %d" % (revno,)
1486
 
        print "  nick: %s" % (branch.nick,)
1487
 
        if rh:
1488
 
            print "  revid: %s" % (rh[-1],)
 
1417
    bzrrev = bzrlib.get_bzr_revision()
 
1418
    if bzrrev:
 
1419
        print "  (bzr checkout, revision %d {%s})" % bzrrev
1489
1420
    print bzrlib.__copyright__
1490
1421
    print "http://bazaar-ng.org/"
1491
1422
    print
1782
1713
 
1783
1714
 
1784
1715
class cmd_missing(Command):
1785
 
    """Show unmerged/unpulled revisions between two branches.
1786
 
 
1787
 
    OTHER_BRANCH may be local or remote."""
1788
 
    takes_args = ['other_branch?']
1789
 
    takes_options = [Option('reverse', 'Reverse the order of revisions'),
1790
 
                     Option('mine-only', 
1791
 
                            'Display changes in the local branch only'),
1792
 
                     Option('theirs-only', 
1793
 
                            'Display changes in the remote branch only'), 
1794
 
                     'line',
1795
 
                     'long', 
1796
 
                     'short',
1797
 
                     'show-ids',
1798
 
                     'verbose'
1799
 
                     ]
1800
 
 
1801
 
    def run(self, other_branch=None, reverse=False, mine_only=False,
1802
 
            theirs_only=False, long=True, short=False, line=False, 
1803
 
            show_ids=False, verbose=False):
1804
 
        from bzrlib.missing import find_unmerged, iter_log_data
1805
 
        from bzrlib.log import log_formatter
1806
 
        local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
1807
 
        parent = local_branch.get_parent()
1808
 
        if other_branch is None:
1809
 
            other_branch = parent
1810
 
            if other_branch is None:
 
1716
    """What is missing in this branch relative to other branch.
 
1717
    """
 
1718
    # TODO: rewrite this in terms of ancestry so that it shows only
 
1719
    # unmerged things
 
1720
    
 
1721
    takes_args = ['remote?']
 
1722
    aliases = ['mis', 'miss']
 
1723
    takes_options = ['verbose']
 
1724
 
 
1725
    @display_command
 
1726
    def run(self, remote=None, verbose=False):
 
1727
        from bzrlib.errors import BzrCommandError
 
1728
        from bzrlib.missing import show_missing
 
1729
 
 
1730
        if verbose and is_quiet():
 
1731
            raise BzrCommandError('Cannot pass both quiet and verbose')
 
1732
 
 
1733
        tree = WorkingTree.open_containing(u'.')[0]
 
1734
        parent = tree.branch.get_parent()
 
1735
        if remote is None:
 
1736
            if parent is None:
1811
1737
                raise BzrCommandError("No missing location known or specified.")
1812
 
            print "Using last location: " + local_branch.get_parent()
1813
 
        remote_branch = bzrlib.branch.Branch.open(other_branch)
1814
 
        local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
1815
 
        log_format = get_log_format(long=long, short=short, line=line)
1816
 
        lf = log_formatter(log_format, sys.stdout,
1817
 
                           show_ids=show_ids,
1818
 
                           show_timezone='original')
1819
 
        if reverse is False:
1820
 
            local_extra.reverse()
1821
 
            remote_extra.reverse()
1822
 
        if local_extra and not theirs_only:
1823
 
            print "You have %d extra revision(s):" % len(local_extra)
1824
 
            for data in iter_log_data(local_extra, local_branch, verbose):
1825
 
                lf.show(*data)
1826
 
            printed_local = True
1827
 
        else:
1828
 
            printed_local = False
1829
 
        if remote_extra and not mine_only:
1830
 
            if printed_local is True:
1831
 
                print "\n\n"
1832
 
            print "You are missing %d revision(s):" % len(remote_extra)
1833
 
            for data in iter_log_data(remote_extra, remote_branch, verbose):
1834
 
                lf.show(*data)
1835
 
        if not remote_extra and not local_extra:
1836
 
            status_code = 0
1837
 
            print "Branches are up to date."
1838
 
        else:
1839
 
            status_code = 1
1840
 
        if parent is None and other_branch is not None:
1841
 
            local_branch.set_parent(other_branch)
1842
 
        return status_code
 
1738
            else:
 
1739
                if not is_quiet():
 
1740
                    print "Using last location: %s" % parent
 
1741
                remote = parent
 
1742
        elif parent is None:
 
1743
            # We only update parent if it did not exist, missing
 
1744
            # should not change the parent
 
1745
            tree.branch.set_parent(remote)
 
1746
        br_remote = Branch.open_containing(remote)[0]
 
1747
        return show_missing(tree.branch, br_remote, verbose=verbose, 
 
1748
                            quiet=is_quiet())
1843
1749
 
1844
1750
 
1845
1751
class cmd_plugins(Command):
1849
1755
    def run(self):
1850
1756
        import bzrlib.plugin
1851
1757
        from inspect import getdoc
1852
 
        for name, plugin in bzrlib.plugin.all_plugins().items():
 
1758
        for plugin in bzrlib.plugin.all_plugins:
1853
1759
            if hasattr(plugin, '__path__'):
1854
1760
                print plugin.__path__[0]
1855
1761
            elif hasattr(plugin, '__file__'):