119 raise StopIteration |
119 raise StopIteration |
120 if pos == -1: |
120 if pos == -1: |
121 self.pos += 1 |
121 self.pos += 1 |
122 return data |
122 return data |
123 zeropos = data.find(b'\x00', pos) |
123 zeropos = data.find(b'\x00', pos) |
124 hashval = unhexlify(data, self.lm.extrainfo[self.pos], zeropos + 1, 40) |
124 nlpos = data.find(b'\n', pos) |
125 flags = self.lm._getflags(data, self.pos, zeropos) |
125 if zeropos == -1 or nlpos == -1 or nlpos < zeropos: |
|
126 raise error.StorageError(b'Invalid manifest line') |
|
127 flags = data[nlpos - 1 : nlpos] |
|
128 if flags in _manifestflags: |
|
129 hlen = nlpos - zeropos - 2 |
|
130 else: |
|
131 hlen = nlpos - zeropos - 1 |
|
132 flags = b'' |
|
133 if hlen not in (40, 64): |
|
134 raise error.StorageError(b'Invalid manifest line') |
|
135 hashval = unhexlify( |
|
136 data, self.lm.extrainfo[self.pos], zeropos + 1, hlen |
|
137 ) |
126 self.pos += 1 |
138 self.pos += 1 |
127 return (data[pos:zeropos], hashval, flags) |
139 return (data[pos:zeropos], hashval, flags) |
128 |
140 |
129 __next__ = next |
141 __next__ = next |
130 |
142 |
136 return s |
148 return s |
137 |
149 |
138 |
150 |
139 def _cmp(a, b): |
151 def _cmp(a, b): |
140 return (a > b) - (a < b) |
152 return (a > b) - (a < b) |
|
153 |
|
154 |
|
155 _manifestflags = {b'', b'l', b't', b'x'} |
141 |
156 |
142 |
157 |
143 class _lazymanifest(object): |
158 class _lazymanifest(object): |
144 """A pure python manifest backed by a byte string. It is supplimented with |
159 """A pure python manifest backed by a byte string. It is supplimented with |
145 internal lists as it is modified, until it is compacted back to a pure byte |
160 internal lists as it is modified, until it is compacted back to a pure byte |
249 return (first, False) |
264 return (first, False) |
250 |
265 |
251 def __contains__(self, key): |
266 def __contains__(self, key): |
252 return self.bsearch(key) != -1 |
267 return self.bsearch(key) != -1 |
253 |
268 |
254 def _getflags(self, data, needle, pos): |
|
255 start = pos + 41 |
|
256 end = data.find(b"\n", start) |
|
257 if end == -1: |
|
258 end = len(data) - 1 |
|
259 if start == end: |
|
260 return b'' |
|
261 return self.data[start:end] |
|
262 |
|
263 def __getitem__(self, key): |
269 def __getitem__(self, key): |
264 if not isinstance(key, bytes): |
270 if not isinstance(key, bytes): |
265 raise TypeError(b"getitem: manifest keys must be a bytes.") |
271 raise TypeError(b"getitem: manifest keys must be a bytes.") |
266 needle = self.bsearch(key) |
272 needle = self.bsearch(key) |
267 if needle == -1: |
273 if needle == -1: |
271 return (data[1], data[2]) |
277 return (data[1], data[2]) |
272 zeropos = data.find(b'\x00', pos) |
278 zeropos = data.find(b'\x00', pos) |
273 nlpos = data.find(b'\n', zeropos) |
279 nlpos = data.find(b'\n', zeropos) |
274 assert 0 <= needle <= len(self.positions) |
280 assert 0 <= needle <= len(self.positions) |
275 assert len(self.extrainfo) == len(self.positions) |
281 assert len(self.extrainfo) == len(self.positions) |
|
282 if zeropos == -1 or nlpos == -1 or nlpos < zeropos: |
|
283 raise error.StorageError(b'Invalid manifest line') |
276 hlen = nlpos - zeropos - 1 |
284 hlen = nlpos - zeropos - 1 |
277 # Hashes sometimes have an extra byte tucked on the end, so |
285 flags = data[nlpos - 1 : nlpos] |
278 # detect that. |
286 if flags in _manifestflags: |
279 if hlen % 2: |
|
280 hlen -= 1 |
287 hlen -= 1 |
|
288 else: |
|
289 flags = b'' |
|
290 if hlen not in (40, 64): |
|
291 raise error.StorageError(b'Invalid manifest line') |
281 hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, hlen) |
292 hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, hlen) |
282 flags = self._getflags(data, needle, zeropos) |
|
283 return (hashval, flags) |
293 return (hashval, flags) |
284 |
294 |
285 def __delitem__(self, key): |
295 def __delitem__(self, key): |
286 needle, found = self.bsearch2(key) |
296 needle, found = self.bsearch2(key) |
287 if not found: |
297 if not found: |
607 m2 = m2._matches(match) |
615 m2 = m2._matches(match) |
608 return m1.diff(m2, clean=clean) |
616 return m1.diff(m2, clean=clean) |
609 return self._lm.diff(m2._lm, clean) |
617 return self._lm.diff(m2._lm, clean) |
610 |
618 |
611 def setflag(self, key, flag): |
619 def setflag(self, key, flag): |
|
620 if flag not in _manifestflags: |
|
621 raise TypeError(b"Invalid manifest flag set.") |
612 self._lm[key] = self[key], flag |
622 self._lm[key] = self[key], flag |
613 |
623 |
614 def get(self, key, default=None): |
624 def get(self, key, default=None): |
615 try: |
625 try: |
616 return self._lm[key][0] |
626 return self._lm[key][0] |
1047 if dir not in self._dirs: |
1057 if dir not in self._dirs: |
1048 self._dirs[dir] = treemanifest(self._subpath(dir)) |
1058 self._dirs[dir] = treemanifest(self._subpath(dir)) |
1049 self._dirs[dir].__setitem__(subpath, n) |
1059 self._dirs[dir].__setitem__(subpath, n) |
1050 else: |
1060 else: |
1051 # manifest nodes are either 20 bytes or 32 bytes, |
1061 # manifest nodes are either 20 bytes or 32 bytes, |
1052 # depending on the hash in use. An extra byte is |
1062 # depending on the hash in use. Assert this as historically |
1053 # occasionally used by hg, but won't ever be |
1063 # sometimes extra bytes were added. |
1054 # persisted. Trim to 21 or 33 bytes as appropriate. |
1064 assert len(n) in (20, 32) |
1055 trim = 21 if len(n) < 25 else 33 |
1065 self._files[f] = n |
1056 self._files[f] = n[:trim] # to match manifestdict's behavior |
|
1057 self._dirty = True |
1066 self._dirty = True |
1058 |
1067 |
1059 def _load(self): |
1068 def _load(self): |
1060 if self._loadfunc is not _noop: |
1069 if self._loadfunc is not _noop: |
1061 lf, self._loadfunc = self._loadfunc, _noop |
1070 lf, self._loadfunc = self._loadfunc, _noop |
1064 cf, self._copyfunc = self._copyfunc, _noop |
1073 cf, self._copyfunc = self._copyfunc, _noop |
1065 cf(self) |
1074 cf(self) |
1066 |
1075 |
1067 def setflag(self, f, flags): |
1076 def setflag(self, f, flags): |
1068 """Set the flags (symlink, executable) for path f.""" |
1077 """Set the flags (symlink, executable) for path f.""" |
|
1078 if flags not in _manifestflags: |
|
1079 raise TypeError(b"Invalid manifest flag set.") |
1069 self._load() |
1080 self._load() |
1070 dir, subpath = _splittopdir(f) |
1081 dir, subpath = _splittopdir(f) |
1071 if dir: |
1082 if dir: |
1072 self._loadlazy(dir) |
1083 self._loadlazy(dir) |
1073 if dir not in self._dirs: |
1084 if dir not in self._dirs: |