26 def copy(self): |
26 def copy(self): |
27 return manifestdict(self, dict.copy(self._flags)) |
27 return manifestdict(self, dict.copy(self._flags)) |
28 |
28 |
29 class manifest(revlog.revlog): |
29 class manifest(revlog.revlog): |
30 def __init__(self, opener): |
30 def __init__(self, opener): |
31 self._mancache = None |
31 # we expect to deal with not more than three revs at a time in merge |
|
32 self._mancache = util.lrucachedict(3) |
32 revlog.revlog.__init__(self, opener, "00manifest.i") |
33 revlog.revlog.__init__(self, opener, "00manifest.i") |
33 |
34 |
34 def parse(self, lines): |
35 def parse(self, lines): |
35 mfdict = manifestdict() |
36 mfdict = manifestdict() |
36 parsers.parse_manifest(mfdict, mfdict._flags, lines) |
37 parsers.parse_manifest(mfdict, mfdict._flags, lines) |
49 return self.read(node) |
50 return self.read(node) |
50 |
51 |
51 def read(self, node): |
52 def read(self, node): |
52 if node == revlog.nullid: |
53 if node == revlog.nullid: |
53 return manifestdict() # don't upset local cache |
54 return manifestdict() # don't upset local cache |
54 if self._mancache and self._mancache[0] == node: |
55 if node in self._mancache: |
55 return self._mancache[1] |
56 return self._mancache[node][0] |
56 text = self.revision(node) |
57 text = self.revision(node) |
57 arraytext = array.array('c', text) |
58 arraytext = array.array('c', text) |
58 mapping = self.parse(text) |
59 mapping = self.parse(text) |
59 self._mancache = (node, mapping, arraytext) |
60 self._mancache[node] = (mapping, arraytext) |
60 return mapping |
61 return mapping |
61 |
62 |
62 def _search(self, m, s, lo=0, hi=None): |
63 def _search(self, m, s, lo=0, hi=None): |
63 '''return a tuple (start, end) that says where to find s within m. |
64 '''return a tuple (start, end) that says where to find s within m. |
64 |
65 |
100 return (lo, lo) |
101 return (lo, lo) |
101 |
102 |
102 def find(self, node, f): |
103 def find(self, node, f): |
103 '''look up entry for a single file efficiently. |
104 '''look up entry for a single file efficiently. |
104 return (node, flags) pair if found, (None, None) if not.''' |
105 return (node, flags) pair if found, (None, None) if not.''' |
105 if self._mancache and self._mancache[0] == node: |
106 if node in self._mancache: |
106 return self._mancache[1].get(f), self._mancache[1].flags(f) |
107 mapping = self._mancache[node][0] |
|
108 return mapping.get(f), mapping.flags(f) |
107 text = self.revision(node) |
109 text = self.revision(node) |
108 start, end = self._search(text, f) |
110 start, end = self._search(text, f) |
109 if start == end: |
111 if start == end: |
110 return None, None |
112 return None, None |
111 l = text[start:end] |
113 l = text[start:end] |
141 raise error.RevlogError( |
143 raise error.RevlogError( |
142 _("'\\n' and '\\r' disallowed in filenames: %r") % f) |
144 _("'\\n' and '\\r' disallowed in filenames: %r") % f) |
143 |
145 |
144 # if we're using the cache, make sure it is valid and |
146 # if we're using the cache, make sure it is valid and |
145 # parented by the same node we're diffing against |
147 # parented by the same node we're diffing against |
146 if not (changed and self._mancache and p1 and self._mancache[0] == p1): |
148 if not (changed and p1 and (p1 in self._mancache)): |
147 files = sorted(map) |
149 files = sorted(map) |
148 checkforbidden(files) |
150 checkforbidden(files) |
149 |
151 |
150 # if this is changed to support newlines in filenames, |
152 # if this is changed to support newlines in filenames, |
151 # be sure to check the templates/ dir again (especially *-raw.tmpl) |
153 # be sure to check the templates/ dir again (especially *-raw.tmpl) |
154 for f in files) |
156 for f in files) |
155 arraytext = array.array('c', text) |
157 arraytext = array.array('c', text) |
156 cachedelta = None |
158 cachedelta = None |
157 else: |
159 else: |
158 added, removed = changed |
160 added, removed = changed |
159 addlist = self._mancache[2] |
161 addlist = self._mancache[p1][1] |
160 |
162 |
161 checkforbidden(added) |
163 checkforbidden(added) |
162 # combine the changed lists into one list for sorting |
164 # combine the changed lists into one list for sorting |
163 work = [(x, False) for x in added] |
165 work = [(x, False) for x in added] |
164 work.extend((x, True) for x in removed) |
166 work.extend((x, True) for x in removed) |
206 cachedelta = (self.rev(p1), deltatext) |
208 cachedelta = (self.rev(p1), deltatext) |
207 arraytext = addlist |
209 arraytext = addlist |
208 text = util.buffer(arraytext) |
210 text = util.buffer(arraytext) |
209 |
211 |
210 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) |
212 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) |
211 self._mancache = (n, map, arraytext) |
213 self._mancache[n] = (map, arraytext) |
212 |
214 |
213 return n |
215 return n |