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