Mercurial > public > mercurial-scm > hg
comparison mercurial/manifest.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | c59eb1560c44 |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
43 # This method does a little bit of excessive-looking | 43 # This method does a little bit of excessive-looking |
44 # precondition checking. This is so that the behavior of this | 44 # precondition checking. This is so that the behavior of this |
45 # class exactly matches its C counterpart to try and help | 45 # class exactly matches its C counterpart to try and help |
46 # prevent surprise breakage for anyone that develops against | 46 # prevent surprise breakage for anyone that develops against |
47 # the pure version. | 47 # the pure version. |
48 if data and data[-1:] != '\n': | 48 if data and data[-1:] != b'\n': |
49 raise ValueError('Manifest did not end in a newline.') | 49 raise ValueError(b'Manifest did not end in a newline.') |
50 prev = None | 50 prev = None |
51 for l in data.splitlines(): | 51 for l in data.splitlines(): |
52 if prev is not None and prev > l: | 52 if prev is not None and prev > l: |
53 raise ValueError('Manifest lines not in sorted order.') | 53 raise ValueError(b'Manifest lines not in sorted order.') |
54 prev = l | 54 prev = l |
55 f, n = l.split('\0') | 55 f, n = l.split(b'\0') |
56 if len(n) > 40: | 56 if len(n) > 40: |
57 yield f, bin(n[:40]), n[40:] | 57 yield f, bin(n[:40]), n[40:] |
58 else: | 58 else: |
59 yield f, bin(n), '' | 59 yield f, bin(n), b'' |
60 | 60 |
61 | 61 |
62 def _text(it): | 62 def _text(it): |
63 files = [] | 63 files = [] |
64 lines = [] | 64 lines = [] |
65 for f, n, fl in it: | 65 for f, n, fl in it: |
66 files.append(f) | 66 files.append(f) |
67 # if this is changed to support newlines in filenames, | 67 # if this is changed to support newlines in filenames, |
68 # be sure to check the templates/ dir again (especially *-raw.tmpl) | 68 # be sure to check the templates/ dir again (especially *-raw.tmpl) |
69 lines.append("%s\0%s%s\n" % (f, hex(n), fl)) | 69 lines.append(b"%s\0%s%s\n" % (f, hex(n), fl)) |
70 | 70 |
71 _checkforbidden(files) | 71 _checkforbidden(files) |
72 return ''.join(lines) | 72 return b''.join(lines) |
73 | 73 |
74 | 74 |
75 class lazymanifestiter(object): | 75 class lazymanifestiter(object): |
76 def __init__(self, lm): | 76 def __init__(self, lm): |
77 self.pos = 0 | 77 self.pos = 0 |
87 raise StopIteration | 87 raise StopIteration |
88 if pos == -1: | 88 if pos == -1: |
89 self.pos += 1 | 89 self.pos += 1 |
90 return data[0] | 90 return data[0] |
91 self.pos += 1 | 91 self.pos += 1 |
92 zeropos = data.find('\x00', pos) | 92 zeropos = data.find(b'\x00', pos) |
93 return data[pos:zeropos] | 93 return data[pos:zeropos] |
94 | 94 |
95 __next__ = next | 95 __next__ = next |
96 | 96 |
97 | 97 |
109 except IndexError: | 109 except IndexError: |
110 raise StopIteration | 110 raise StopIteration |
111 if pos == -1: | 111 if pos == -1: |
112 self.pos += 1 | 112 self.pos += 1 |
113 return data | 113 return data |
114 zeropos = data.find('\x00', pos) | 114 zeropos = data.find(b'\x00', pos) |
115 hashval = unhexlify(data, self.lm.extrainfo[self.pos], zeropos + 1, 40) | 115 hashval = unhexlify(data, self.lm.extrainfo[self.pos], zeropos + 1, 40) |
116 flags = self.lm._getflags(data, self.pos, zeropos) | 116 flags = self.lm._getflags(data, self.pos, zeropos) |
117 self.pos += 1 | 117 self.pos += 1 |
118 return (data[pos:zeropos], hashval, flags) | 118 return (data[pos:zeropos], hashval, flags) |
119 | 119 |
171 self.hasremovals = hasremovals | 171 self.hasremovals = hasremovals |
172 | 172 |
173 def findlines(self, data): | 173 def findlines(self, data): |
174 if not data: | 174 if not data: |
175 return [] | 175 return [] |
176 pos = data.find("\n") | 176 pos = data.find(b"\n") |
177 if pos == -1 or data[-1:] != '\n': | 177 if pos == -1 or data[-1:] != b'\n': |
178 raise ValueError("Manifest did not end in a newline.") | 178 raise ValueError(b"Manifest did not end in a newline.") |
179 positions = [0] | 179 positions = [0] |
180 prev = data[: data.find('\x00')] | 180 prev = data[: data.find(b'\x00')] |
181 while pos < len(data) - 1 and pos != -1: | 181 while pos < len(data) - 1 and pos != -1: |
182 positions.append(pos + 1) | 182 positions.append(pos + 1) |
183 nexts = data[pos + 1 : data.find('\x00', pos + 1)] | 183 nexts = data[pos + 1 : data.find(b'\x00', pos + 1)] |
184 if nexts < prev: | 184 if nexts < prev: |
185 raise ValueError("Manifest lines not in sorted order.") | 185 raise ValueError(b"Manifest lines not in sorted order.") |
186 prev = nexts | 186 prev = nexts |
187 pos = data.find("\n", pos + 1) | 187 pos = data.find(b"\n", pos + 1) |
188 return positions | 188 return positions |
189 | 189 |
190 def _get(self, index): | 190 def _get(self, index): |
191 # get the position encoded in pos: | 191 # get the position encoded in pos: |
192 # positive number is an index in 'data' | 192 # positive number is an index in 'data' |
196 return self.data, pos | 196 return self.data, pos |
197 return self.extradata[-pos - 1], -1 | 197 return self.extradata[-pos - 1], -1 |
198 | 198 |
199 def _getkey(self, pos): | 199 def _getkey(self, pos): |
200 if pos >= 0: | 200 if pos >= 0: |
201 return self.data[pos : self.data.find('\x00', pos + 1)] | 201 return self.data[pos : self.data.find(b'\x00', pos + 1)] |
202 return self.extradata[-pos - 1][0] | 202 return self.extradata[-pos - 1][0] |
203 | 203 |
204 def bsearch(self, key): | 204 def bsearch(self, key): |
205 first = 0 | 205 first = 0 |
206 last = len(self.positions) - 1 | 206 last = len(self.positions) - 1 |
242 def __contains__(self, key): | 242 def __contains__(self, key): |
243 return self.bsearch(key) != -1 | 243 return self.bsearch(key) != -1 |
244 | 244 |
245 def _getflags(self, data, needle, pos): | 245 def _getflags(self, data, needle, pos): |
246 start = pos + 41 | 246 start = pos + 41 |
247 end = data.find("\n", start) | 247 end = data.find(b"\n", start) |
248 if end == -1: | 248 if end == -1: |
249 end = len(data) - 1 | 249 end = len(data) - 1 |
250 if start == end: | 250 if start == end: |
251 return '' | 251 return b'' |
252 return self.data[start:end] | 252 return self.data[start:end] |
253 | 253 |
254 def __getitem__(self, key): | 254 def __getitem__(self, key): |
255 if not isinstance(key, bytes): | 255 if not isinstance(key, bytes): |
256 raise TypeError("getitem: manifest keys must be a bytes.") | 256 raise TypeError(b"getitem: manifest keys must be a bytes.") |
257 needle = self.bsearch(key) | 257 needle = self.bsearch(key) |
258 if needle == -1: | 258 if needle == -1: |
259 raise KeyError | 259 raise KeyError |
260 data, pos = self._get(needle) | 260 data, pos = self._get(needle) |
261 if pos == -1: | 261 if pos == -1: |
262 return (data[1], data[2]) | 262 return (data[1], data[2]) |
263 zeropos = data.find('\x00', pos) | 263 zeropos = data.find(b'\x00', pos) |
264 assert 0 <= needle <= len(self.positions) | 264 assert 0 <= needle <= len(self.positions) |
265 assert len(self.extrainfo) == len(self.positions) | 265 assert len(self.extrainfo) == len(self.positions) |
266 hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, 40) | 266 hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, 40) |
267 flags = self._getflags(data, needle, zeropos) | 267 flags = self._getflags(data, needle, zeropos) |
268 return (hashval, flags) | 268 return (hashval, flags) |
275 self.positions = self.positions[:needle] + self.positions[needle + 1 :] | 275 self.positions = self.positions[:needle] + self.positions[needle + 1 :] |
276 self.extrainfo = self.extrainfo[:needle] + self.extrainfo[needle + 1 :] | 276 self.extrainfo = self.extrainfo[:needle] + self.extrainfo[needle + 1 :] |
277 if cur >= 0: | 277 if cur >= 0: |
278 # This does NOT unsort the list as far as the search functions are | 278 # This does NOT unsort the list as far as the search functions are |
279 # concerned, as they only examine lines mapped by self.positions. | 279 # concerned, as they only examine lines mapped by self.positions. |
280 self.data = self.data[:cur] + '\x00' + self.data[cur + 1 :] | 280 self.data = self.data[:cur] + b'\x00' + self.data[cur + 1 :] |
281 self.hasremovals = True | 281 self.hasremovals = True |
282 | 282 |
283 def __setitem__(self, key, value): | 283 def __setitem__(self, key, value): |
284 if not isinstance(key, bytes): | 284 if not isinstance(key, bytes): |
285 raise TypeError("setitem: manifest keys must be a byte string.") | 285 raise TypeError(b"setitem: manifest keys must be a byte string.") |
286 if not isinstance(value, tuple) or len(value) != 2: | 286 if not isinstance(value, tuple) or len(value) != 2: |
287 raise TypeError("Manifest values must be a tuple of (node, flags).") | 287 raise TypeError( |
288 b"Manifest values must be a tuple of (node, flags)." | |
289 ) | |
288 hashval = value[0] | 290 hashval = value[0] |
289 if not isinstance(hashval, bytes) or not 20 <= len(hashval) <= 22: | 291 if not isinstance(hashval, bytes) or not 20 <= len(hashval) <= 22: |
290 raise TypeError("node must be a 20-byte byte string") | 292 raise TypeError(b"node must be a 20-byte byte string") |
291 flags = value[1] | 293 flags = value[1] |
292 if len(hashval) == 22: | 294 if len(hashval) == 22: |
293 hashval = hashval[:-1] | 295 hashval = hashval[:-1] |
294 if not isinstance(flags, bytes) or len(flags) > 1: | 296 if not isinstance(flags, bytes) or len(flags) > 1: |
295 raise TypeError("flags must a 0 or 1 byte string, got %r", flags) | 297 raise TypeError(b"flags must a 0 or 1 byte string, got %r", flags) |
296 needle, found = self.bsearch2(key) | 298 needle, found = self.bsearch2(key) |
297 if found: | 299 if found: |
298 # put the item | 300 # put the item |
299 pos = self.positions[needle] | 301 pos = self.positions[needle] |
300 if pos < 0: | 302 if pos < 0: |
351 # overwritten first byte. Break out and find the end of the | 353 # overwritten first byte. Break out and find the end of the |
352 # current good entry/entries if there is a removed file | 354 # current good entry/entries if there is a removed file |
353 # before the next position. | 355 # before the next position. |
354 if ( | 356 if ( |
355 self.hasremovals | 357 self.hasremovals |
356 and self.data.find('\n\x00', cur, self.positions[i]) | 358 and self.data.find(b'\n\x00', cur, self.positions[i]) |
357 != -1 | 359 != -1 |
358 ): | 360 ): |
359 break | 361 break |
360 | 362 |
361 offset += self.positions[i] - cur | 363 offset += self.positions[i] - cur |
362 cur = self.positions[i] | 364 cur = self.positions[i] |
363 end_cut = self.data.find('\n', cur) | 365 end_cut = self.data.find(b'\n', cur) |
364 if end_cut != -1: | 366 if end_cut != -1: |
365 end_cut += 1 | 367 end_cut += 1 |
366 offset += end_cut - cur | 368 offset += end_cut - cur |
367 l.append(self.data[last_cut:end_cut]) | 369 l.append(self.data[last_cut:end_cut]) |
368 else: | 370 else: |
373 self.positions[i] = offset | 375 self.positions[i] = offset |
374 if len(t[1]) > 20: | 376 if len(t[1]) > 20: |
375 self.extrainfo[i] = ord(t[1][21]) | 377 self.extrainfo[i] = ord(t[1][21]) |
376 offset += len(l[-1]) | 378 offset += len(l[-1]) |
377 i += 1 | 379 i += 1 |
378 self.data = ''.join(l) | 380 self.data = b''.join(l) |
379 self.hasremovals = False | 381 self.hasremovals = False |
380 self.extradata = [] | 382 self.extradata = [] |
381 | 383 |
382 def _pack(self, d): | 384 def _pack(self, d): |
383 return d[0] + '\x00' + hex(d[1][:20]) + d[2] + '\n' | 385 return d[0] + b'\x00' + hex(d[1][:20]) + d[2] + b'\n' |
384 | 386 |
385 def text(self): | 387 def text(self): |
386 self._compact() | 388 self._compact() |
387 return self.data | 389 return self.data |
388 | 390 |
391 # XXX think whether efficiency matters here | 393 # XXX think whether efficiency matters here |
392 diff = {} | 394 diff = {} |
393 | 395 |
394 for fn, e1, flags in self.iterentries(): | 396 for fn, e1, flags in self.iterentries(): |
395 if fn not in m2: | 397 if fn not in m2: |
396 diff[fn] = (e1, flags), (None, '') | 398 diff[fn] = (e1, flags), (None, b'') |
397 else: | 399 else: |
398 e2 = m2[fn] | 400 e2 = m2[fn] |
399 if (e1, flags) != e2: | 401 if (e1, flags) != e2: |
400 diff[fn] = (e1, flags), e2 | 402 diff[fn] = (e1, flags), e2 |
401 elif clean: | 403 elif clean: |
402 diff[fn] = None | 404 diff[fn] = None |
403 | 405 |
404 for fn, e2, flags in m2.iterentries(): | 406 for fn, e2, flags in m2.iterentries(): |
405 if fn not in self: | 407 if fn not in self: |
406 diff[fn] = (None, ''), (e2, flags) | 408 diff[fn] = (None, b''), (e2, flags) |
407 | 409 |
408 return diff | 410 return diff |
409 | 411 |
410 def iterentries(self): | 412 def iterentries(self): |
411 return lazymanifestiterentries(self) | 413 return lazymanifestiterentries(self) |
419 def __len__(self): | 421 def __len__(self): |
420 return len(self.positions) | 422 return len(self.positions) |
421 | 423 |
422 def filtercopy(self, filterfn): | 424 def filtercopy(self, filterfn): |
423 # XXX should be optimized | 425 # XXX should be optimized |
424 c = _lazymanifest('') | 426 c = _lazymanifest(b'') |
425 for f, n, fl in self.iterentries(): | 427 for f, n, fl in self.iterentries(): |
426 if filterfn(f): | 428 if filterfn(f): |
427 c[f] = n, fl | 429 c[f] = n, fl |
428 return c | 430 return c |
429 | 431 |
434 pass | 436 pass |
435 | 437 |
436 | 438 |
437 @interfaceutil.implementer(repository.imanifestdict) | 439 @interfaceutil.implementer(repository.imanifestdict) |
438 class manifestdict(object): | 440 class manifestdict(object): |
439 def __init__(self, data=''): | 441 def __init__(self, data=b''): |
440 self._lm = _lazymanifest(data) | 442 self._lm = _lazymanifest(data) |
441 | 443 |
442 def __getitem__(self, key): | 444 def __getitem__(self, key): |
443 return self._lm[key][0] | 445 return self._lm[key][0] |
444 | 446 |
454 return len(self._lm) != 0 | 456 return len(self._lm) != 0 |
455 | 457 |
456 __bool__ = __nonzero__ | 458 __bool__ = __nonzero__ |
457 | 459 |
458 def __setitem__(self, key, node): | 460 def __setitem__(self, key, node): |
459 self._lm[key] = node, self.flags(key, '') | 461 self._lm[key] = node, self.flags(key, b'') |
460 | 462 |
461 def __contains__(self, key): | 463 def __contains__(self, key): |
462 if key is None: | 464 if key is None: |
463 return False | 465 return False |
464 return key in self._lm | 466 return key in self._lm |
536 if match(fn): | 538 if match(fn): |
537 yield fn | 539 yield fn |
538 | 540 |
539 # for dirstate.walk, files=[''] means "walk the whole tree". | 541 # for dirstate.walk, files=[''] means "walk the whole tree". |
540 # follow that here, too | 542 # follow that here, too |
541 fset.discard('') | 543 fset.discard(b'') |
542 | 544 |
543 for fn in sorted(fset): | 545 for fn in sorted(fset): |
544 if not self.hasdir(fn): | 546 if not self.hasdir(fn): |
545 match.bad(fn, None) | 547 match.bad(fn, None) |
546 | 548 |
589 try: | 591 try: |
590 return self._lm[key][0] | 592 return self._lm[key][0] |
591 except KeyError: | 593 except KeyError: |
592 return default | 594 return default |
593 | 595 |
594 def flags(self, key, default=''): | 596 def flags(self, key, default=b''): |
595 try: | 597 try: |
596 return self._lm[key][1] | 598 return self._lm[key][1] |
597 except KeyError: | 599 except KeyError: |
598 return default | 600 return default |
599 | 601 |
620 relative to that text, compute a delta that can be used by revlog. | 622 relative to that text, compute a delta that can be used by revlog. |
621 """ | 623 """ |
622 delta = [] | 624 delta = [] |
623 dstart = None | 625 dstart = None |
624 dend = None | 626 dend = None |
625 dline = [""] | 627 dline = [b""] |
626 start = 0 | 628 start = 0 |
627 # zero copy representation of base as a buffer | 629 # zero copy representation of base as a buffer |
628 addbuf = util.buffer(base) | 630 addbuf = util.buffer(base) |
629 | 631 |
630 changes = list(changes) | 632 changes = list(changes) |
634 for f, todelete in changes: | 636 for f, todelete in changes: |
635 # bs will either be the index of the item or the insert point | 637 # bs will either be the index of the item or the insert point |
636 start, end = _msearch(addbuf, f, start) | 638 start, end = _msearch(addbuf, f, start) |
637 if not todelete: | 639 if not todelete: |
638 h, fl = self._lm[f] | 640 h, fl = self._lm[f] |
639 l = "%s\0%s%s\n" % (f, hex(h), fl) | 641 l = b"%s\0%s%s\n" % (f, hex(h), fl) |
640 else: | 642 else: |
641 if start == end: | 643 if start == end: |
642 # item we want to delete was not found, error out | 644 # item we want to delete was not found, error out |
643 raise AssertionError( | 645 raise AssertionError( |
644 _("failed to remove %s from manifest") % f | 646 _(b"failed to remove %s from manifest") % f |
645 ) | 647 ) |
646 l = "" | 648 l = b"" |
647 if dstart is not None and dstart <= start and dend >= start: | 649 if dstart is not None and dstart <= start and dend >= start: |
648 if dend < end: | 650 if dend < end: |
649 dend = end | 651 dend = end |
650 if l: | 652 if l: |
651 dline.append(l) | 653 dline.append(l) |
652 else: | 654 else: |
653 if dstart is not None: | 655 if dstart is not None: |
654 delta.append([dstart, dend, "".join(dline)]) | 656 delta.append([dstart, dend, b"".join(dline)]) |
655 dstart = start | 657 dstart = start |
656 dend = end | 658 dend = end |
657 dline = [l] | 659 dline = [l] |
658 | 660 |
659 if dstart is not None: | 661 if dstart is not None: |
660 delta.append([dstart, dend, "".join(dline)]) | 662 delta.append([dstart, dend, b"".join(dline)]) |
661 # apply the delta to the base, and get a delta for addrevision | 663 # apply the delta to the base, and get a delta for addrevision |
662 deltatext, arraytext = _addlistdelta(base, delta) | 664 deltatext, arraytext = _addlistdelta(base, delta) |
663 else: | 665 else: |
664 # For large changes, it's much cheaper to just build the text and | 666 # For large changes, it's much cheaper to just build the text and |
665 # diff it. | 667 # diff it. |
692 if not hi: | 694 if not hi: |
693 hi = lenm | 695 hi = lenm |
694 while lo < hi: | 696 while lo < hi: |
695 mid = (lo + hi) // 2 | 697 mid = (lo + hi) // 2 |
696 start = mid | 698 start = mid |
697 while start > 0 and m[start - 1 : start] != '\n': | 699 while start > 0 and m[start - 1 : start] != b'\n': |
698 start -= 1 | 700 start -= 1 |
699 end = advance(start, '\0') | 701 end = advance(start, b'\0') |
700 if bytes(m[start:end]) < s: | 702 if bytes(m[start:end]) < s: |
701 # we know that after the null there are 40 bytes of sha1 | 703 # we know that after the null there are 40 bytes of sha1 |
702 # this translates to the bisect lo = mid + 1 | 704 # this translates to the bisect lo = mid + 1 |
703 lo = advance(end + 40, '\n') + 1 | 705 lo = advance(end + 40, b'\n') + 1 |
704 else: | 706 else: |
705 # this translates to the bisect hi = mid | 707 # this translates to the bisect hi = mid |
706 hi = start | 708 hi = start |
707 end = advance(lo, '\0') | 709 end = advance(lo, b'\0') |
708 found = m[lo:end] | 710 found = m[lo:end] |
709 if s == found: | 711 if s == found: |
710 # we know that after the null there are 40 bytes of sha1 | 712 # we know that after the null there are 40 bytes of sha1 |
711 end = advance(end + 40, '\n') | 713 end = advance(end + 40, b'\n') |
712 return (lo, end + 1) | 714 return (lo, end + 1) |
713 else: | 715 else: |
714 return (lo, lo) | 716 return (lo, lo) |
715 | 717 |
716 | 718 |
717 def _checkforbidden(l): | 719 def _checkforbidden(l): |
718 """Check filenames for illegal characters.""" | 720 """Check filenames for illegal characters.""" |
719 for f in l: | 721 for f in l: |
720 if '\n' in f or '\r' in f: | 722 if b'\n' in f or b'\r' in f: |
721 raise error.StorageError( | 723 raise error.StorageError( |
722 _("'\\n' and '\\r' disallowed in filenames: %r") | 724 _(b"'\\n' and '\\r' disallowed in filenames: %r") |
723 % pycompat.bytestr(f) | 725 % pycompat.bytestr(f) |
724 ) | 726 ) |
725 | 727 |
726 | 728 |
727 # apply the changes collected during the bisect loop to our addlist | 729 # apply the changes collected during the bisect loop to our addlist |
739 | 741 |
740 currentposition = end | 742 currentposition = end |
741 | 743 |
742 newaddlist += addlist[currentposition:] | 744 newaddlist += addlist[currentposition:] |
743 | 745 |
744 deltatext = "".join( | 746 deltatext = b"".join( |
745 struct.pack(">lll", start, end, len(content)) + content | 747 struct.pack(b">lll", start, end, len(content)) + content |
746 for start, end, content in x | 748 for start, end, content in x |
747 ) | 749 ) |
748 return deltatext, newaddlist | 750 return deltatext, newaddlist |
749 | 751 |
750 | 752 |
751 def _splittopdir(f): | 753 def _splittopdir(f): |
752 if '/' in f: | 754 if b'/' in f: |
753 dir, subpath = f.split('/', 1) | 755 dir, subpath = f.split(b'/', 1) |
754 return dir + '/', subpath | 756 return dir + b'/', subpath |
755 else: | 757 else: |
756 return '', f | 758 return b'', f |
757 | 759 |
758 | 760 |
759 _noop = lambda s: None | 761 _noop = lambda s: None |
760 | 762 |
761 | 763 |
762 class treemanifest(object): | 764 class treemanifest(object): |
763 def __init__(self, dir='', text=''): | 765 def __init__(self, dir=b'', text=b''): |
764 self._dir = dir | 766 self._dir = dir |
765 self._node = nullid | 767 self._node = nullid |
766 self._loadfunc = _noop | 768 self._loadfunc = _noop |
767 self._copyfunc = _noop | 769 self._copyfunc = _noop |
768 self._dirty = False | 770 self._dirty = False |
773 self._flags = {} | 775 self._flags = {} |
774 if text: | 776 if text: |
775 | 777 |
776 def readsubtree(subdir, subm): | 778 def readsubtree(subdir, subm): |
777 raise AssertionError( | 779 raise AssertionError( |
778 'treemanifest constructor only accepts ' 'flat manifests' | 780 b'treemanifest constructor only accepts ' b'flat manifests' |
779 ) | 781 ) |
780 | 782 |
781 self.parse(text, readsubtree) | 783 self.parse(text, readsubtree) |
782 self._dirty = True # Mark flat manifest dirty after parsing | 784 self._dirty = True # Mark flat manifest dirty after parsing |
783 | 785 |
804 del self._lazydirs[d] | 806 del self._lazydirs[d] |
805 | 807 |
806 def _loadchildrensetlazy(self, visit): | 808 def _loadchildrensetlazy(self, visit): |
807 if not visit: | 809 if not visit: |
808 return None | 810 return None |
809 if visit == 'all' or visit == 'this': | 811 if visit == b'all' or visit == b'this': |
810 self._loadalllazy() | 812 self._loadalllazy() |
811 return None | 813 return None |
812 | 814 |
813 loadlazy = self._loadlazy | 815 loadlazy = self._loadlazy |
814 for k in visit: | 816 for k in visit: |
815 loadlazy(k + '/') | 817 loadlazy(k + b'/') |
816 return visit | 818 return visit |
817 | 819 |
818 def _loaddifflazy(self, t1, t2): | 820 def _loaddifflazy(self, t1, t2): |
819 """load items in t1 and t2 if they're needed for diffing. | 821 """load items in t1 and t2 if they're needed for diffing. |
820 | 822 |
860 return False | 862 return False |
861 self._loadalllazy() | 863 self._loadalllazy() |
862 return not self._dirs or all(m._isempty() for m in self._dirs.values()) | 864 return not self._dirs or all(m._isempty() for m in self._dirs.values()) |
863 | 865 |
864 def __repr__(self): | 866 def __repr__(self): |
865 return '<treemanifest dir=%s, node=%s, loaded=%s, dirty=%s at 0x%x>' % ( | 867 return b'<treemanifest dir=%s, node=%s, loaded=%s, dirty=%s at 0x%x>' % ( |
866 self._dir, | 868 self._dir, |
867 hex(self._node), | 869 hex(self._node), |
868 bool(self._loadfunc is _noop), | 870 bool(self._loadfunc is _noop), |
869 self._dirty, | 871 self._dirty, |
870 id(self), | 872 id(self), |
891 self._loadalllazy() | 893 self._loadalllazy() |
892 for p, n in sorted( | 894 for p, n in sorted( |
893 itertools.chain(self._dirs.items(), self._files.items()) | 895 itertools.chain(self._dirs.items(), self._files.items()) |
894 ): | 896 ): |
895 if p in self._files: | 897 if p in self._files: |
896 yield self._subpath(p), n, self._flags.get(p, '') | 898 yield self._subpath(p), n, self._flags.get(p, b'') |
897 else: | 899 else: |
898 for x in n.iterentries(): | 900 for x in n.iterentries(): |
899 yield x | 901 yield x |
900 | 902 |
901 def items(self): | 903 def items(self): |
970 dir, subpath = _splittopdir(f) | 972 dir, subpath = _splittopdir(f) |
971 if dir: | 973 if dir: |
972 self._loadlazy(dir) | 974 self._loadlazy(dir) |
973 | 975 |
974 if dir not in self._dirs: | 976 if dir not in self._dirs: |
975 return '' | 977 return b'' |
976 return self._dirs[dir].flags(subpath) | 978 return self._dirs[dir].flags(subpath) |
977 else: | 979 else: |
978 if f in self._lazydirs or f in self._dirs: | 980 if f in self._lazydirs or f in self._dirs: |
979 return '' | 981 return b'' |
980 return self._flags.get(f, '') | 982 return self._flags.get(f, b'') |
981 | 983 |
982 def find(self, f): | 984 def find(self, f): |
983 self._load() | 985 self._load() |
984 dir, subpath = _splittopdir(f) | 986 dir, subpath = _splittopdir(f) |
985 if dir: | 987 if dir: |
986 self._loadlazy(dir) | 988 self._loadlazy(dir) |
987 | 989 |
988 return self._dirs[dir].find(subpath) | 990 return self._dirs[dir].find(subpath) |
989 else: | 991 else: |
990 return self._files[f], self._flags.get(f, '') | 992 return self._files[f], self._flags.get(f, b'') |
991 | 993 |
992 def __delitem__(self, f): | 994 def __delitem__(self, f): |
993 self._load() | 995 self._load() |
994 dir, subpath = _splittopdir(f) | 996 dir, subpath = _splittopdir(f) |
995 if dir: | 997 if dir: |
1107 if topdir: | 1109 if topdir: |
1108 self._loadlazy(topdir) | 1110 self._loadlazy(topdir) |
1109 if topdir in self._dirs: | 1111 if topdir in self._dirs: |
1110 return self._dirs[topdir].hasdir(subdir) | 1112 return self._dirs[topdir].hasdir(subdir) |
1111 return False | 1113 return False |
1112 dirslash = dir + '/' | 1114 dirslash = dir + b'/' |
1113 return dirslash in self._dirs or dirslash in self._lazydirs | 1115 return dirslash in self._dirs or dirslash in self._lazydirs |
1114 | 1116 |
1115 def walk(self, match): | 1117 def walk(self, match): |
1116 '''Generates matching file names. | 1118 '''Generates matching file names. |
1117 | 1119 |
1133 fset.remove(fn) | 1135 fset.remove(fn) |
1134 yield fn | 1136 yield fn |
1135 | 1137 |
1136 # for dirstate.walk, files=[''] means "walk the whole tree". | 1138 # for dirstate.walk, files=[''] means "walk the whole tree". |
1137 # follow that here, too | 1139 # follow that here, too |
1138 fset.discard('') | 1140 fset.discard(b'') |
1139 | 1141 |
1140 for fn in sorted(fset): | 1142 for fn in sorted(fset): |
1141 if not self.hasdir(fn): | 1143 if not self.hasdir(fn): |
1142 match.bad(fn, None) | 1144 match.bad(fn, None) |
1143 | 1145 |
1170 def _matches(self, match): | 1172 def _matches(self, match): |
1171 '''recursively generate a new manifest filtered by the match argument. | 1173 '''recursively generate a new manifest filtered by the match argument. |
1172 ''' | 1174 ''' |
1173 | 1175 |
1174 visit = match.visitchildrenset(self._dir[:-1]) | 1176 visit = match.visitchildrenset(self._dir[:-1]) |
1175 if visit == 'all': | 1177 if visit == b'all': |
1176 return self.copy() | 1178 return self.copy() |
1177 ret = treemanifest(self._dir) | 1179 ret = treemanifest(self._dir) |
1178 if not visit: | 1180 if not visit: |
1179 return ret | 1181 return ret |
1180 | 1182 |
1183 # While visitchildrenset *usually* lists only subdirs, this is | 1185 # While visitchildrenset *usually* lists only subdirs, this is |
1184 # actually up to the matcher and may have some files in the set(). | 1186 # actually up to the matcher and may have some files in the set(). |
1185 # If visit == 'this', we should obviously look at the files in this | 1187 # If visit == 'this', we should obviously look at the files in this |
1186 # directory; if visit is a set, and fn is in it, we should inspect | 1188 # directory; if visit is a set, and fn is in it, we should inspect |
1187 # fn (but no need to inspect things not in the set). | 1189 # fn (but no need to inspect things not in the set). |
1188 if visit != 'this' and fn not in visit: | 1190 if visit != b'this' and fn not in visit: |
1189 continue | 1191 continue |
1190 fullp = self._subpath(fn) | 1192 fullp = self._subpath(fn) |
1191 # visitchildrenset isn't perfect, we still need to call the regular | 1193 # visitchildrenset isn't perfect, we still need to call the regular |
1192 # matcher code to further filter results. | 1194 # matcher code to further filter results. |
1193 if not match(fullp): | 1195 if not match(fullp): |
1246 for d, m2 in t2._dirs.iteritems(): | 1248 for d, m2 in t2._dirs.iteritems(): |
1247 if d not in t1._dirs: | 1249 if d not in t1._dirs: |
1248 stack.append((emptytree, m2)) | 1250 stack.append((emptytree, m2)) |
1249 | 1251 |
1250 for fn, n1 in t1._files.iteritems(): | 1252 for fn, n1 in t1._files.iteritems(): |
1251 fl1 = t1._flags.get(fn, '') | 1253 fl1 = t1._flags.get(fn, b'') |
1252 n2 = t2._files.get(fn, None) | 1254 n2 = t2._files.get(fn, None) |
1253 fl2 = t2._flags.get(fn, '') | 1255 fl2 = t2._flags.get(fn, b'') |
1254 if n1 != n2 or fl1 != fl2: | 1256 if n1 != n2 or fl1 != fl2: |
1255 result[t1._subpath(fn)] = ((n1, fl1), (n2, fl2)) | 1257 result[t1._subpath(fn)] = ((n1, fl1), (n2, fl2)) |
1256 elif clean: | 1258 elif clean: |
1257 result[t1._subpath(fn)] = None | 1259 result[t1._subpath(fn)] = None |
1258 | 1260 |
1259 for fn, n2 in t2._files.iteritems(): | 1261 for fn, n2 in t2._files.iteritems(): |
1260 if fn not in t1._files: | 1262 if fn not in t1._files: |
1261 fl2 = t2._flags.get(fn, '') | 1263 fl2 = t2._flags.get(fn, b'') |
1262 result[t2._subpath(fn)] = ((None, ''), (n2, fl2)) | 1264 result[t2._subpath(fn)] = ((None, b''), (n2, fl2)) |
1263 | 1265 |
1264 stackls = [] | 1266 stackls = [] |
1265 _iterativediff(self, m2, stackls) | 1267 _iterativediff(self, m2, stackls) |
1266 while stackls: | 1268 while stackls: |
1267 t1, t2 = stackls.pop() | 1269 t1, t2 = stackls.pop() |
1274 | 1276 |
1275 def parse(self, text, readsubtree): | 1277 def parse(self, text, readsubtree): |
1276 selflazy = self._lazydirs | 1278 selflazy = self._lazydirs |
1277 subpath = self._subpath | 1279 subpath = self._subpath |
1278 for f, n, fl in _parse(text): | 1280 for f, n, fl in _parse(text): |
1279 if fl == 't': | 1281 if fl == b't': |
1280 f = f + '/' | 1282 f = f + b'/' |
1281 # False below means "doesn't need to be copied" and can use the | 1283 # False below means "doesn't need to be copied" and can use the |
1282 # cached value from readsubtree directly. | 1284 # cached value from readsubtree directly. |
1283 selflazy[f] = (subpath(f), n, readsubtree, False) | 1285 selflazy[f] = (subpath(f), n, readsubtree, False) |
1284 elif '/' in f: | 1286 elif b'/' in f: |
1285 # This is a flat manifest, so use __setitem__ and setflag rather | 1287 # This is a flat manifest, so use __setitem__ and setflag rather |
1286 # than assigning directly to _files and _flags, so we can | 1288 # than assigning directly to _files and _flags, so we can |
1287 # assign a path in a subdirectory, and to mark dirty (compared | 1289 # assign a path in a subdirectory, and to mark dirty (compared |
1288 # to nullid). | 1290 # to nullid). |
1289 self[f] = n | 1291 self[f] = n |
1305 """Get the full data of this directory as a bytestring. Make sure that | 1307 """Get the full data of this directory as a bytestring. Make sure that |
1306 any submanifests have been written first, so their nodeids are correct. | 1308 any submanifests have been written first, so their nodeids are correct. |
1307 """ | 1309 """ |
1308 self._load() | 1310 self._load() |
1309 flags = self.flags | 1311 flags = self.flags |
1310 lazydirs = [(d[:-1], v[1], 't') for d, v in self._lazydirs.iteritems()] | 1312 lazydirs = [(d[:-1], v[1], b't') for d, v in self._lazydirs.iteritems()] |
1311 dirs = [(d[:-1], self._dirs[d]._node, 't') for d in self._dirs] | 1313 dirs = [(d[:-1], self._dirs[d]._node, b't') for d in self._dirs] |
1312 files = [(f, self._files[f], flags(f)) for f in self._files] | 1314 files = [(f, self._files[f], flags(f)) for f in self._files] |
1313 return _text(sorted(dirs + files + lazydirs)) | 1315 return _text(sorted(dirs + files + lazydirs)) |
1314 | 1316 |
1315 def read(self, gettext, readsubtree): | 1317 def read(self, gettext, readsubtree): |
1316 def _load_for_read(s): | 1318 def _load_for_read(s): |
1332 return m._dirs.get(d, emptytree)._node | 1334 return m._dirs.get(d, emptytree)._node |
1333 | 1335 |
1334 # let's skip investigating things that `match` says we do not need. | 1336 # let's skip investigating things that `match` says we do not need. |
1335 visit = match.visitchildrenset(self._dir[:-1]) | 1337 visit = match.visitchildrenset(self._dir[:-1]) |
1336 visit = self._loadchildrensetlazy(visit) | 1338 visit = self._loadchildrensetlazy(visit) |
1337 if visit == 'this' or visit == 'all': | 1339 if visit == b'this' or visit == b'all': |
1338 visit = None | 1340 visit = None |
1339 for d, subm in self._dirs.iteritems(): | 1341 for d, subm in self._dirs.iteritems(): |
1340 if visit and d[:-1] not in visit: | 1342 if visit and d[:-1] not in visit: |
1341 continue | 1343 continue |
1342 subp1 = getnode(m1, d) | 1344 subp1 = getnode(m1, d) |
1373 | 1375 |
1374 These are written in reverse cache order (oldest to newest). | 1376 These are written in reverse cache order (oldest to newest). |
1375 | 1377 |
1376 """ | 1378 """ |
1377 | 1379 |
1378 _file = 'manifestfulltextcache' | 1380 _file = b'manifestfulltextcache' |
1379 | 1381 |
1380 def __init__(self, max): | 1382 def __init__(self, max): |
1381 super(manifestfulltextcache, self).__init__(max) | 1383 super(manifestfulltextcache, self).__init__(max) |
1382 self._dirty = False | 1384 self._dirty = False |
1383 self._read = False | 1385 self._read = False |
1394 while True: | 1396 while True: |
1395 node = fp.read(20) | 1397 node = fp.read(20) |
1396 if len(node) < 20: | 1398 if len(node) < 20: |
1397 break | 1399 break |
1398 try: | 1400 try: |
1399 size = struct.unpack('>L', fp.read(4))[0] | 1401 size = struct.unpack(b'>L', fp.read(4))[0] |
1400 except struct.error: | 1402 except struct.error: |
1401 break | 1403 break |
1402 value = bytearray(fp.read(size)) | 1404 value = bytearray(fp.read(size)) |
1403 if len(value) != size: | 1405 if len(value) != size: |
1404 break | 1406 break |
1413 def write(self): | 1415 def write(self): |
1414 if not self._dirty or self._opener is None: | 1416 if not self._dirty or self._opener is None: |
1415 return | 1417 return |
1416 # rotate backwards to the first used node | 1418 # rotate backwards to the first used node |
1417 with self._opener( | 1419 with self._opener( |
1418 self._file, 'w', atomictemp=True, checkambig=True | 1420 self._file, b'w', atomictemp=True, checkambig=True |
1419 ) as fp: | 1421 ) as fp: |
1420 node = self._head.prev | 1422 node = self._head.prev |
1421 while True: | 1423 while True: |
1422 if node.key in self._cache: | 1424 if node.key in self._cache: |
1423 fp.write(node.key) | 1425 fp.write(node.key) |
1424 fp.write(struct.pack('>L', len(node.value))) | 1426 fp.write(struct.pack(b'>L', len(node.value))) |
1425 fp.write(node.value) | 1427 fp.write(node.value) |
1426 if node is self._head: | 1428 if node is self._head: |
1427 break | 1429 break |
1428 node = node.prev | 1430 node = node.prev |
1429 | 1431 |
1489 ''' | 1491 ''' |
1490 | 1492 |
1491 def __init__( | 1493 def __init__( |
1492 self, | 1494 self, |
1493 opener, | 1495 opener, |
1494 tree='', | 1496 tree=b'', |
1495 dirlogcache=None, | 1497 dirlogcache=None, |
1496 indexfile=None, | 1498 indexfile=None, |
1497 treemanifest=False, | 1499 treemanifest=False, |
1498 ): | 1500 ): |
1499 """Constructs a new manifest revlog | 1501 """Constructs a new manifest revlog |
1511 # stacks of commits, the number can go up, hence the config knob below. | 1513 # stacks of commits, the number can go up, hence the config knob below. |
1512 cachesize = 4 | 1514 cachesize = 4 |
1513 optiontreemanifest = False | 1515 optiontreemanifest = False |
1514 opts = getattr(opener, 'options', None) | 1516 opts = getattr(opener, 'options', None) |
1515 if opts is not None: | 1517 if opts is not None: |
1516 cachesize = opts.get('manifestcachesize', cachesize) | 1518 cachesize = opts.get(b'manifestcachesize', cachesize) |
1517 optiontreemanifest = opts.get('treemanifest', False) | 1519 optiontreemanifest = opts.get(b'treemanifest', False) |
1518 | 1520 |
1519 self._treeondisk = optiontreemanifest or treemanifest | 1521 self._treeondisk = optiontreemanifest or treemanifest |
1520 | 1522 |
1521 self._fulltextcache = manifestfulltextcache(cachesize) | 1523 self._fulltextcache = manifestfulltextcache(cachesize) |
1522 | 1524 |
1523 if tree: | 1525 if tree: |
1524 assert self._treeondisk, 'opts is %r' % opts | 1526 assert self._treeondisk, b'opts is %r' % opts |
1525 | 1527 |
1526 if indexfile is None: | 1528 if indexfile is None: |
1527 indexfile = '00manifest.i' | 1529 indexfile = b'00manifest.i' |
1528 if tree: | 1530 if tree: |
1529 indexfile = "meta/" + tree + indexfile | 1531 indexfile = b"meta/" + tree + indexfile |
1530 | 1532 |
1531 self.tree = tree | 1533 self.tree = tree |
1532 | 1534 |
1533 # The dirlogcache is kept on the root manifest log | 1535 # The dirlogcache is kept on the root manifest log |
1534 if tree: | 1536 if tree: |
1535 self._dirlogcache = dirlogcache | 1537 self._dirlogcache = dirlogcache |
1536 else: | 1538 else: |
1537 self._dirlogcache = {'': self} | 1539 self._dirlogcache = {b'': self} |
1538 | 1540 |
1539 self._revlog = revlog.revlog( | 1541 self._revlog = revlog.revlog( |
1540 opener, | 1542 opener, |
1541 indexfile, | 1543 indexfile, |
1542 # only root indexfile is cached | 1544 # only root indexfile is cached |
1549 self.version = self._revlog.version | 1551 self.version = self._revlog.version |
1550 self._generaldelta = self._revlog._generaldelta | 1552 self._generaldelta = self._revlog._generaldelta |
1551 | 1553 |
1552 def _setupmanifestcachehooks(self, repo): | 1554 def _setupmanifestcachehooks(self, repo): |
1553 """Persist the manifestfulltextcache on lock release""" | 1555 """Persist the manifestfulltextcache on lock release""" |
1554 if not util.safehasattr(repo, '_wlockref'): | 1556 if not util.safehasattr(repo, b'_wlockref'): |
1555 return | 1557 return |
1556 | 1558 |
1557 self._fulltextcache._opener = repo.wcachevfs | 1559 self._fulltextcache._opener = repo.wcachevfs |
1558 if repo._currentlock(repo._wlockref) is None: | 1560 if repo._currentlock(repo._wlockref) is None: |
1559 return | 1561 return |
1602 added, | 1604 added, |
1603 removed, | 1605 removed, |
1604 readtree=None, | 1606 readtree=None, |
1605 match=None, | 1607 match=None, |
1606 ): | 1608 ): |
1607 if p1 in self.fulltextcache and util.safehasattr(m, 'fastdelta'): | 1609 if p1 in self.fulltextcache and util.safehasattr(m, b'fastdelta'): |
1608 # If our first parent is in the manifest cache, we can | 1610 # If our first parent is in the manifest cache, we can |
1609 # compute a delta here using properties we know about the | 1611 # compute a delta here using properties we know about the |
1610 # manifest up-front, which may save time later for the | 1612 # manifest up-front, which may save time later for the |
1611 # revlog layer. | 1613 # revlog layer. |
1612 | 1614 |
1627 # The first parent manifest isn't already loaded, so we'll | 1629 # The first parent manifest isn't already loaded, so we'll |
1628 # just encode a fulltext of the manifest and pass that | 1630 # just encode a fulltext of the manifest and pass that |
1629 # through to the revlog layer, and let it handle the delta | 1631 # through to the revlog layer, and let it handle the delta |
1630 # process. | 1632 # process. |
1631 if self._treeondisk: | 1633 if self._treeondisk: |
1632 assert readtree, "readtree must be set for treemanifest writes" | 1634 assert readtree, b"readtree must be set for treemanifest writes" |
1633 assert match, "match must be specified for treemanifest writes" | 1635 assert match, b"match must be specified for treemanifest writes" |
1634 m1 = readtree(self.tree, p1) | 1636 m1 = readtree(self.tree, p1) |
1635 m2 = readtree(self.tree, p2) | 1637 m2 = readtree(self.tree, p2) |
1636 n = self._addtree( | 1638 n = self._addtree( |
1637 m, transaction, link, m1, m2, readtree, match=match | 1639 m, transaction, link, m1, m2, readtree, match=match |
1638 ) | 1640 ) |
1648 return n | 1650 return n |
1649 | 1651 |
1650 def _addtree(self, m, transaction, link, m1, m2, readtree, match): | 1652 def _addtree(self, m, transaction, link, m1, m2, readtree, match): |
1651 # If the manifest is unchanged compared to one parent, | 1653 # If the manifest is unchanged compared to one parent, |
1652 # don't write a new revision | 1654 # don't write a new revision |
1653 if self.tree != '' and (m.unmodifiedsince(m1) or m.unmodifiedsince(m2)): | 1655 if self.tree != b'' and ( |
1656 m.unmodifiedsince(m1) or m.unmodifiedsince(m2) | |
1657 ): | |
1654 return m.node() | 1658 return m.node() |
1655 | 1659 |
1656 def writesubtree(subm, subp1, subp2, match): | 1660 def writesubtree(subm, subp1, subp2, match): |
1657 sublog = self.dirlog(subm.dir()) | 1661 sublog = self.dirlog(subm.dir()) |
1658 sublog.add( | 1662 sublog.add( |
1668 ) | 1672 ) |
1669 | 1673 |
1670 m.writesubtrees(m1, m2, writesubtree, match) | 1674 m.writesubtrees(m1, m2, writesubtree, match) |
1671 text = m.dirtext() | 1675 text = m.dirtext() |
1672 n = None | 1676 n = None |
1673 if self.tree != '': | 1677 if self.tree != b'': |
1674 # Double-check whether contents are unchanged to one parent | 1678 # Double-check whether contents are unchanged to one parent |
1675 if text == m1.dirtext(): | 1679 if text == m1.dirtext(): |
1676 n = m1.node() | 1680 n = m1.node() |
1677 elif text == m2.dirtext(): | 1681 elif text == m2.dirtext(): |
1678 n = m2.node() | 1682 n = m2.node() |
1761 def files(self): | 1765 def files(self): |
1762 return self._revlog.files() | 1766 return self._revlog.files() |
1763 | 1767 |
1764 def clone(self, tr, destrevlog, **kwargs): | 1768 def clone(self, tr, destrevlog, **kwargs): |
1765 if not isinstance(destrevlog, manifestrevlog): | 1769 if not isinstance(destrevlog, manifestrevlog): |
1766 raise error.ProgrammingError('expected manifestrevlog to clone()') | 1770 raise error.ProgrammingError(b'expected manifestrevlog to clone()') |
1767 | 1771 |
1768 return self._revlog.clone(tr, destrevlog._revlog, **kwargs) | 1772 return self._revlog.clone(tr, destrevlog._revlog, **kwargs) |
1769 | 1773 |
1770 def storageinfo( | 1774 def storageinfo( |
1771 self, | 1775 self, |
1814 usetreemanifest = False | 1818 usetreemanifest = False |
1815 cachesize = 4 | 1819 cachesize = 4 |
1816 | 1820 |
1817 opts = getattr(opener, 'options', None) | 1821 opts = getattr(opener, 'options', None) |
1818 if opts is not None: | 1822 if opts is not None: |
1819 usetreemanifest = opts.get('treemanifest', usetreemanifest) | 1823 usetreemanifest = opts.get(b'treemanifest', usetreemanifest) |
1820 cachesize = opts.get('manifestcachesize', cachesize) | 1824 cachesize = opts.get(b'manifestcachesize', cachesize) |
1821 | 1825 |
1822 self._treemanifests = usetreemanifest | 1826 self._treemanifests = usetreemanifest |
1823 | 1827 |
1824 self._rootstore = rootstore | 1828 self._rootstore = rootstore |
1825 self._rootstore._setupmanifestcachehooks(repo) | 1829 self._rootstore._setupmanifestcachehooks(repo) |
1826 self._narrowmatch = narrowmatch | 1830 self._narrowmatch = narrowmatch |
1827 | 1831 |
1828 # A cache of the manifestctx or treemanifestctx for each directory | 1832 # A cache of the manifestctx or treemanifestctx for each directory |
1829 self._dirmancache = {} | 1833 self._dirmancache = {} |
1830 self._dirmancache[''] = util.lrucachedict(cachesize) | 1834 self._dirmancache[b''] = util.lrucachedict(cachesize) |
1831 | 1835 |
1832 self._cachesize = cachesize | 1836 self._cachesize = cachesize |
1833 | 1837 |
1834 def __getitem__(self, node): | 1838 def __getitem__(self, node): |
1835 """Retrieves the manifest instance for the given node. Throws a | 1839 """Retrieves the manifest instance for the given node. Throws a |
1836 LookupError if not found. | 1840 LookupError if not found. |
1837 """ | 1841 """ |
1838 return self.get('', node) | 1842 return self.get(b'', node) |
1839 | 1843 |
1840 def get(self, tree, node, verify=True): | 1844 def get(self, tree, node, verify=True): |
1841 """Retrieves the manifest instance for the given node. Throws a | 1845 """Retrieves the manifest instance for the given node. Throws a |
1842 LookupError if not found. | 1846 LookupError if not found. |
1843 | 1847 |
1859 | 1863 |
1860 m = treemanifestctx(self, tree, node) | 1864 m = treemanifestctx(self, tree, node) |
1861 else: | 1865 else: |
1862 raise error.Abort( | 1866 raise error.Abort( |
1863 _( | 1867 _( |
1864 "cannot ask for manifest directory '%s' in a flat " | 1868 b"cannot ask for manifest directory '%s' in a flat " |
1865 "manifest" | 1869 b"manifest" |
1866 ) | 1870 ) |
1867 % tree | 1871 % tree |
1868 ) | 1872 ) |
1869 else: | 1873 else: |
1870 if verify: | 1874 if verify: |
1871 # Side-effect is LookupError is raised if node doesn't exist. | 1875 # Side-effect is LookupError is raised if node doesn't exist. |
1872 self._rootstore.rev(node) | 1876 self._rootstore.rev(node) |
1873 | 1877 |
1874 if self._treemanifests: | 1878 if self._treemanifests: |
1875 m = treemanifestctx(self, '', node) | 1879 m = treemanifestctx(self, b'', node) |
1876 else: | 1880 else: |
1877 m = manifestctx(self, node) | 1881 m = manifestctx(self, node) |
1878 | 1882 |
1879 if node != nullid: | 1883 if node != nullid: |
1880 mancache = self._dirmancache.get(tree) | 1884 mancache = self._dirmancache.get(tree) |
2010 return self.read().find(key) | 2014 return self.read().find(key) |
2011 | 2015 |
2012 | 2016 |
2013 @interfaceutil.implementer(repository.imanifestrevisionwritable) | 2017 @interfaceutil.implementer(repository.imanifestrevisionwritable) |
2014 class memtreemanifestctx(object): | 2018 class memtreemanifestctx(object): |
2015 def __init__(self, manifestlog, dir=''): | 2019 def __init__(self, manifestlog, dir=b''): |
2016 self._manifestlog = manifestlog | 2020 self._manifestlog = manifestlog |
2017 self._dir = dir | 2021 self._dir = dir |
2018 self._treemanifest = treemanifest() | 2022 self._treemanifest = treemanifest() |
2019 | 2023 |
2020 def _storage(self): | 2024 def _storage(self): |
2021 return self._manifestlog.getstorage(b'') | 2025 return self._manifestlog.getstorage(b'') |
2022 | 2026 |
2023 def new(self, dir=''): | 2027 def new(self, dir=b''): |
2024 return memtreemanifestctx(self._manifestlog, dir=dir) | 2028 return memtreemanifestctx(self._manifestlog, dir=dir) |
2025 | 2029 |
2026 def copy(self): | 2030 def copy(self): |
2027 memmf = memtreemanifestctx(self._manifestlog, dir=self._dir) | 2031 memmf = memtreemanifestctx(self._manifestlog, dir=self._dir) |
2028 memmf._treemanifest = self._treemanifest.copy() | 2032 memmf._treemanifest = self._treemanifest.copy() |
2103 return self._data | 2107 return self._data |
2104 | 2108 |
2105 def node(self): | 2109 def node(self): |
2106 return self._node | 2110 return self._node |
2107 | 2111 |
2108 def new(self, dir=''): | 2112 def new(self, dir=b''): |
2109 return memtreemanifestctx(self._manifestlog, dir=dir) | 2113 return memtreemanifestctx(self._manifestlog, dir=dir) |
2110 | 2114 |
2111 def copy(self): | 2115 def copy(self): |
2112 memmf = memtreemanifestctx(self._manifestlog, dir=self._dir) | 2116 memmf = memtreemanifestctx(self._manifestlog, dir=self._dir) |
2113 memmf._treemanifest = self.read().copy() | 2117 memmf._treemanifest = self.read().copy() |
2184 def __init__(self, dir, node): | 2188 def __init__(self, dir, node): |
2185 super(excludeddir, self).__init__(dir) | 2189 super(excludeddir, self).__init__(dir) |
2186 self._node = node | 2190 self._node = node |
2187 # Add an empty file, which will be included by iterators and such, | 2191 # Add an empty file, which will be included by iterators and such, |
2188 # appearing as the directory itself (i.e. something like "dir/") | 2192 # appearing as the directory itself (i.e. something like "dir/") |
2189 self._files[''] = node | 2193 self._files[b''] = node |
2190 self._flags[''] = 't' | 2194 self._flags[b''] = b't' |
2191 | 2195 |
2192 # Manifests outside the narrowspec should never be modified, so avoid | 2196 # Manifests outside the narrowspec should never be modified, so avoid |
2193 # copying. This makes a noticeable difference when there are very many | 2197 # copying. This makes a noticeable difference when there are very many |
2194 # directories outside the narrowspec. Also, it makes sense for the copy to | 2198 # directories outside the narrowspec. Also, it makes sense for the copy to |
2195 # be of the same type as the original, which would not happen with the | 2199 # be of the same type as the original, which would not happen with the |
2208 def read(self): | 2212 def read(self): |
2209 return excludeddir(self._dir, self._node) | 2213 return excludeddir(self._dir, self._node) |
2210 | 2214 |
2211 def write(self, *args): | 2215 def write(self, *args): |
2212 raise error.ProgrammingError( | 2216 raise error.ProgrammingError( |
2213 'attempt to write manifest from excluded dir %s' % self._dir | 2217 b'attempt to write manifest from excluded dir %s' % self._dir |
2214 ) | 2218 ) |
2215 | 2219 |
2216 | 2220 |
2217 class excludedmanifestrevlog(manifestrevlog): | 2221 class excludedmanifestrevlog(manifestrevlog): |
2218 """Stand-in for excluded treemanifest revlogs. | 2222 """Stand-in for excluded treemanifest revlogs. |
2227 def __init__(self, dir): | 2231 def __init__(self, dir): |
2228 self._dir = dir | 2232 self._dir = dir |
2229 | 2233 |
2230 def __len__(self): | 2234 def __len__(self): |
2231 raise error.ProgrammingError( | 2235 raise error.ProgrammingError( |
2232 'attempt to get length of excluded dir %s' % self._dir | 2236 b'attempt to get length of excluded dir %s' % self._dir |
2233 ) | 2237 ) |
2234 | 2238 |
2235 def rev(self, node): | 2239 def rev(self, node): |
2236 raise error.ProgrammingError( | 2240 raise error.ProgrammingError( |
2237 'attempt to get rev from excluded dir %s' % self._dir | 2241 b'attempt to get rev from excluded dir %s' % self._dir |
2238 ) | 2242 ) |
2239 | 2243 |
2240 def linkrev(self, node): | 2244 def linkrev(self, node): |
2241 raise error.ProgrammingError( | 2245 raise error.ProgrammingError( |
2242 'attempt to get linkrev from excluded dir %s' % self._dir | 2246 b'attempt to get linkrev from excluded dir %s' % self._dir |
2243 ) | 2247 ) |
2244 | 2248 |
2245 def node(self, rev): | 2249 def node(self, rev): |
2246 raise error.ProgrammingError( | 2250 raise error.ProgrammingError( |
2247 'attempt to get node from excluded dir %s' % self._dir | 2251 b'attempt to get node from excluded dir %s' % self._dir |
2248 ) | 2252 ) |
2249 | 2253 |
2250 def add(self, *args, **kwargs): | 2254 def add(self, *args, **kwargs): |
2251 # We should never write entries in dirlogs outside the narrow clone. | 2255 # We should never write entries in dirlogs outside the narrow clone. |
2252 # However, the method still gets called from writesubtree() in | 2256 # However, the method still gets called from writesubtree() in |