comparison mercurial/manifest.py @ 22930:1acb81d10eaf

manifest: move _search to module level and rename to _msearch The rename is intended to provide a slight hint that it is manifest-specific.
author Augie Fackler <raf@durin42.com>
date Wed, 08 Oct 2014 15:21:59 -0400
parents bf69cb09a6c9
children 48c0b101a9de
comparison
equal deleted inserted replaced
22929:bf69cb09a6c9 22930:1acb81d10eaf
47 hex, flags = revlog.hex, self.flags 47 hex, flags = revlog.hex, self.flags
48 # if this is changed to support newlines in filenames, 48 # if this is changed to support newlines in filenames,
49 # be sure to check the templates/ dir again (especially *-raw.tmpl) 49 # be sure to check the templates/ dir again (especially *-raw.tmpl)
50 return ''.join("%s\0%s%s\n" % (f, hex(self[f]), flags(f)) for f in fl) 50 return ''.join("%s\0%s%s\n" % (f, hex(self[f]), flags(f)) for f in fl)
51 51
52 def _msearch(m, s, lo=0, hi=None):
53 '''return a tuple (start, end) that says where to find s within m.
54
55 If the string is found m[start:end] are the line containing
56 that string. If start == end the string was not found and
57 they indicate the proper sorted insertion point.
58
59 m should be a buffer or a string
60 s is a string'''
61 def advance(i, c):
62 while i < lenm and m[i] != c:
63 i += 1
64 return i
65 if not s:
66 return (lo, lo)
67 lenm = len(m)
68 if not hi:
69 hi = lenm
70 while lo < hi:
71 mid = (lo + hi) // 2
72 start = mid
73 while start > 0 and m[start - 1] != '\n':
74 start -= 1
75 end = advance(start, '\0')
76 if m[start:end] < s:
77 # we know that after the null there are 40 bytes of sha1
78 # this translates to the bisect lo = mid + 1
79 lo = advance(end + 40, '\n') + 1
80 else:
81 # this translates to the bisect hi = mid
82 hi = start
83 end = advance(lo, '\0')
84 found = m[lo:end]
85 if s == found:
86 # we know that after the null there are 40 bytes of sha1
87 end = advance(end + 40, '\n')
88 return (lo, end + 1)
89 else:
90 return (lo, lo)
91
52 def _checkforbidden(l): 92 def _checkforbidden(l):
53 """Check filenames for illegal characters.""" 93 """Check filenames for illegal characters."""
54 for f in l: 94 for f in l:
55 if '\n' in f or '\r' in f: 95 if '\n' in f or '\r' in f:
56 raise error.RevlogError( 96 raise error.RevlogError(
111 arraytext = array.array('c', text) 151 arraytext = array.array('c', text)
112 mapping = _parse(text) 152 mapping = _parse(text)
113 self._mancache[node] = (mapping, arraytext) 153 self._mancache[node] = (mapping, arraytext)
114 return mapping 154 return mapping
115 155
116 def _search(self, m, s, lo=0, hi=None):
117 '''return a tuple (start, end) that says where to find s within m.
118
119 If the string is found m[start:end] are the line containing
120 that string. If start == end the string was not found and
121 they indicate the proper sorted insertion point.
122
123 m should be a buffer or a string
124 s is a string'''
125 def advance(i, c):
126 while i < lenm and m[i] != c:
127 i += 1
128 return i
129 if not s:
130 return (lo, lo)
131 lenm = len(m)
132 if not hi:
133 hi = lenm
134 while lo < hi:
135 mid = (lo + hi) // 2
136 start = mid
137 while start > 0 and m[start - 1] != '\n':
138 start -= 1
139 end = advance(start, '\0')
140 if m[start:end] < s:
141 # we know that after the null there are 40 bytes of sha1
142 # this translates to the bisect lo = mid + 1
143 lo = advance(end + 40, '\n') + 1
144 else:
145 # this translates to the bisect hi = mid
146 hi = start
147 end = advance(lo, '\0')
148 found = m[lo:end]
149 if s == found:
150 # we know that after the null there are 40 bytes of sha1
151 end = advance(end + 40, '\n')
152 return (lo, end + 1)
153 else:
154 return (lo, lo)
155
156 def find(self, node, f): 156 def find(self, node, f):
157 '''look up entry for a single file efficiently. 157 '''look up entry for a single file efficiently.
158 return (node, flags) pair if found, (None, None) if not.''' 158 return (node, flags) pair if found, (None, None) if not.'''
159 if node in self._mancache: 159 if node in self._mancache:
160 mapping = self._mancache[node][0] 160 mapping = self._mancache[node][0]
161 return mapping.get(f), mapping.flags(f) 161 return mapping.get(f), mapping.flags(f)
162 text = self.revision(node) 162 text = self.revision(node)
163 start, end = self._search(text, f) 163 start, end = _msearch(text, f)
164 if start == end: 164 if start == end:
165 return None, None 165 return None, None
166 l = text[start:end] 166 l = text[start:end]
167 f, n = l.split('\0') 167 f, n = l.split('\0')
168 return revlog.bin(n[:40]), n[40:-1] 168 return revlog.bin(n[:40]), n[40:-1]
193 193
194 # start with a readonly loop that finds the offset of 194 # start with a readonly loop that finds the offset of
195 # each line and creates the deltas 195 # each line and creates the deltas
196 for f, todelete in work: 196 for f, todelete in work:
197 # bs will either be the index of the item or the insert point 197 # bs will either be the index of the item or the insert point
198 start, end = self._search(addbuf, f, start) 198 start, end = _msearch(addbuf, f, start)
199 if not todelete: 199 if not todelete:
200 l = "%s\0%s%s\n" % (f, revlog.hex(map[f]), map.flags(f)) 200 l = "%s\0%s%s\n" % (f, revlog.hex(map[f]), map.flags(f))
201 else: 201 else:
202 if start == end: 202 if start == end:
203 # item we want to delete was not found, error out 203 # item we want to delete was not found, error out