mercurial/manifest.py
author Bryan O'Sullivan <bos@serpentine.com>
Sat, 17 Sep 2005 00:27:27 -0700
changeset 1270 fc3b41570082
parent 1098 50a0a36dd48a
child 1400 cf9a1233738a
permissions -rw-r--r--
Switch to new syntax for .hgignore files. Here is the new syntax, in summary. Trailing white space is dropped. The escape character is "\". Comments start with #. Empty lines are skipped. Lines can be of the following formats: syntax: regexp # defaults following lines to non-rooted regexps syntax: glob # defaults following lines to non-rooted globs re:pattern # non-rooted regular expression glob:pattern # non-rooted glob pattern # pattern of the current default type The default pattern type is regexp, which is completely backwards compatible with the old hgignore syntax. In the dirstate class, the ignore method has been reworked to be based on the util.matcher function, by way of a new dirstate.hgignore method.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1089
142b5d5ec9cc Break apart hg.py
mpm@selenic.com
parents: 1072
diff changeset
     1
# manifest.py - manifest revision class for mercurial
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     2
#
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     3
# Copyright 2005 Matt Mackall <mpm@selenic.com>
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     4
#
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     5
# This software may be used and distributed according to the terms
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     6
# of the GNU General Public License, incorporated herein by reference.
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     7
1089
142b5d5ec9cc Break apart hg.py
mpm@selenic.com
parents: 1072
diff changeset
     8
import sys, struct
262
3db700146536 implement demand loading hack
mpm@selenic.com
parents: 256
diff changeset
     9
from revlog import *
3db700146536 implement demand loading hack
mpm@selenic.com
parents: 256
diff changeset
    10
from demandload import *
1089
142b5d5ec9cc Break apart hg.py
mpm@selenic.com
parents: 1072
diff changeset
    11
demandload(globals(), "bisect")
79
837d473d54d5 Add basic annotation support
mpm@selenic.com
parents: 78
diff changeset
    12
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    13
class manifest(revlog):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    14
    def __init__(self, opener):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    15
        self.mapcache = None
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    16
        self.listcache = None
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    17
        self.addlist = None
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    18
        revlog.__init__(self, opener, "00manifest.i", "00manifest.d")
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    19
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    20
    def read(self, node):
313
e75ea4662d81 Minor caching improvement for manifest
mpm@selenic.com
parents: 312
diff changeset
    21
        if node == nullid: return {} # don't upset local cache
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    22
        if self.mapcache and self.mapcache[0] == node:
561
cdddf4652aec Fix dodiff/changes
mpm@selenic.com
parents: 557
diff changeset
    23
            return self.mapcache[1]
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    24
        text = self.revision(node)
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    25
        map = {}
276
10e325db7347 add tracking of execute permissions
mpm@selenic.com
parents: 275
diff changeset
    26
        flag = {}
25
daa724b27300 Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents: 20
diff changeset
    27
        self.listcache = (text, text.splitlines(1))
daa724b27300 Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents: 20
diff changeset
    28
        for l in self.listcache[1]:
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    29
            (f, n) = l.split('\0')
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    30
            map[f] = bin(n[:40])
276
10e325db7347 add tracking of execute permissions
mpm@selenic.com
parents: 275
diff changeset
    31
            flag[f] = (n[40:-1] == "x")
10e325db7347 add tracking of execute permissions
mpm@selenic.com
parents: 275
diff changeset
    32
        self.mapcache = (node, map, flag)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    33
        return map
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    34
276
10e325db7347 add tracking of execute permissions
mpm@selenic.com
parents: 275
diff changeset
    35
    def readflags(self, node):
313
e75ea4662d81 Minor caching improvement for manifest
mpm@selenic.com
parents: 312
diff changeset
    36
        if node == nullid: return {} # don't upset local cache
358
9f4077d7ef6f [PATCH] manifest.readflags performance buglet
mpm@selenic.com
parents: 350
diff changeset
    37
        if not self.mapcache or self.mapcache[0] != node:
276
10e325db7347 add tracking of execute permissions
mpm@selenic.com
parents: 275
diff changeset
    38
            self.read(node)
10e325db7347 add tracking of execute permissions
mpm@selenic.com
parents: 275
diff changeset
    39
        return self.mapcache[2]
10e325db7347 add tracking of execute permissions
mpm@selenic.com
parents: 275
diff changeset
    40
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    41
    def diff(self, a, b):
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    42
        # this is sneaky, as we're not actually using a and b
140
30ef77113872 Minor safety checks to manifest diff
mpm@selenic.com
parents: 118
diff changeset
    43
        if self.listcache and self.addlist and self.listcache[0] == a:
98
3dde7c87e36d Add paranoia to diff code
mpm@selenic.com
parents: 96
diff changeset
    44
            d = mdiff.diff(self.listcache[1], self.addlist, 1)
3dde7c87e36d Add paranoia to diff code
mpm@selenic.com
parents: 96
diff changeset
    45
            if mdiff.patch(a, d) != b:
1098
50a0a36dd48a manifest: convert sys.stderr bits to AssertionError
mpm@selenic.com
parents: 1089
diff changeset
    46
                raise AssertionError("sortdiff failed!")
98
3dde7c87e36d Add paranoia to diff code
mpm@selenic.com
parents: 96
diff changeset
    47
            return d
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    48
        else:
44
e825a68d7227 Fix occassional diff bug with manifests
mpm@selenic.com
parents: 40
diff changeset
    49
            return mdiff.textdiff(a, b)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    50
741
156dc2f3be7f Fix some line wrapping
mpm@selenic.com
parents: 740
diff changeset
    51
    def add(self, map, flags, transaction, link, p1=None, p2=None,
156dc2f3be7f Fix some line wrapping
mpm@selenic.com
parents: 740
diff changeset
    52
            changed=None):
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    53
        # directly generate the mdiff delta from the data collected during
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    54
        # the bisect loop below
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    55
        def gendelta(delta):
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    56
            i = 0
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    57
            result = []
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    58
            while i < len(delta):
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    59
                start = delta[i][2]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    60
                end = delta[i][3]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    61
                l = delta[i][4]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    62
                if l == None:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    63
                    l = ""
741
156dc2f3be7f Fix some line wrapping
mpm@selenic.com
parents: 740
diff changeset
    64
                while i < len(delta) - 1 and start <= delta[i+1][2] \
156dc2f3be7f Fix some line wrapping
mpm@selenic.com
parents: 740
diff changeset
    65
                          and end >= delta[i+1][2]:
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    66
                    if delta[i+1][3] > end:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    67
                        end = delta[i+1][3]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    68
                    if delta[i+1][4]:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    69
                        l += delta[i+1][4]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    70
                    i += 1
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    71
                result.append(struct.pack(">lll", start, end, len(l)) +  l)
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    72
                i += 1
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    73
            return result
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    74
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    75
        # apply the changes collected during the bisect loop to our addlist
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    76
        def addlistdelta(addlist, delta):
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    77
            # apply the deltas to the addlist.  start from the bottom up
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    78
            # so changes to the offsets don't mess things up.
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    79
            i = len(delta)
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    80
            while i > 0:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    81
                i -= 1
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    82
                start = delta[i][0]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    83
                end = delta[i][1]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    84
                if delta[i][4]:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    85
                    addlist[start:end] = [delta[i][4]]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    86
                else:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    87
                    del addlist[start:end]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    88
            return addlist
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    89
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    90
        # calculate the byte offset of the start of each line in the
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    91
        # manifest
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    92
        def calcoffsets(addlist):
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    93
            offsets = [0] * (len(addlist) + 1)
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    94
            offset = 0
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    95
            i = 0
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    96
            while i < len(addlist):
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    97
                offsets[i] = offset
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    98
                offset += len(addlist[i])
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
    99
                i += 1
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   100
            offsets[i] = offset
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   101
            return offsets
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   102
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   103
        # if we're using the listcache, make sure it is valid and
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   104
        # parented by the same node we're diffing against
741
156dc2f3be7f Fix some line wrapping
mpm@selenic.com
parents: 740
diff changeset
   105
        if not changed or not self.listcache or not p1 or \
156dc2f3be7f Fix some line wrapping
mpm@selenic.com
parents: 740
diff changeset
   106
               self.mapcache[0] != p1:
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   107
            files = map.keys()
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   108
            files.sort()
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   109
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   110
            self.addlist = ["%s\000%s%s\n" %
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   111
                            (f, hex(map[f]), flags[f] and "x" or '')
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   112
                            for f in files]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   113
            cachedelta = None
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   114
        else:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   115
            addlist = self.listcache[1]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   116
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   117
            # find the starting offset for each line in the add list
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   118
            offsets = calcoffsets(addlist)
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   119
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   120
            # combine the changed lists into one list for sorting
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   121
            work = [[x, 0] for x in changed[0]]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   122
            work[len(work):] = [[x, 1] for x in changed[1]]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   123
            work.sort()
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   124
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   125
            delta = []
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   126
            bs = 0
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   127
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   128
            for w in work:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   129
                f = w[0]
741
156dc2f3be7f Fix some line wrapping
mpm@selenic.com
parents: 740
diff changeset
   130
                # bs will either be the index of the item or the insert point
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   131
                bs = bisect.bisect(addlist, f, bs)
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   132
                if bs < len(addlist):
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   133
                    fn = addlist[bs][:addlist[bs].index('\0')]
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   134
                else:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   135
                    fn = None
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   136
                if w[1] == 0:
741
156dc2f3be7f Fix some line wrapping
mpm@selenic.com
parents: 740
diff changeset
   137
                    l = "%s\000%s%s\n" % (f, hex(map[f]),
156dc2f3be7f Fix some line wrapping
mpm@selenic.com
parents: 740
diff changeset
   138
                                          flags[f] and "x" or '')
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   139
                else:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   140
                    l = None
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   141
                start = bs
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   142
                if fn != f:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   143
                    # item not found, insert a new one
659
3662e3d6b690 Whitespace cleanup
Matt Mackall <mpm@selenic.com>
parents: 658
diff changeset
   144
                    end = bs
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   145
                    if w[1] == 1:
1098
50a0a36dd48a manifest: convert sys.stderr bits to AssertionError
mpm@selenic.com
parents: 1089
diff changeset
   146
                        raise AssertionError(
50a0a36dd48a manifest: convert sys.stderr bits to AssertionError
mpm@selenic.com
parents: 1089
diff changeset
   147
                            "failed to remove %s from manifest\n" % f)
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   148
                else:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   149
                    # item is found, replace/delete the existing line
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   150
                    end = bs + 1
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   151
                delta.append([start, end, offsets[start], offsets[end], l])
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   152
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   153
            self.addlist = addlistdelta(addlist, delta)
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   154
            if self.mapcache[0] == self.tip():
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   155
                cachedelta = "".join(gendelta(delta))
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   156
            else:
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   157
                cachedelta = None
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   158
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   159
        text = "".join(self.addlist)
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   160
        if cachedelta and mdiff.patch(self.listcache[0], cachedelta) != text:
1098
50a0a36dd48a manifest: convert sys.stderr bits to AssertionError
mpm@selenic.com
parents: 1089
diff changeset
   161
            raise AssertionError("manifest delta failure\n")
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   162
        n = self.addrevision(text, transaction, link, p1, p2, cachedelta)
302
498fb0fa2795 various fixups for git import
mpm@selenic.com
parents: 299
diff changeset
   163
        self.mapcache = (n, map, flags)
25
daa724b27300 Fix corruption from manifest.listcache optimization
mpm@selenic.com
parents: 20
diff changeset
   164
        self.listcache = (text, self.addlist)
140
30ef77113872 Minor safety checks to manifest diff
mpm@selenic.com
parents: 118
diff changeset
   165
        self.addlist = None
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   166
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   167
        return n