diff -r 2372284d9457 -r 687b865b95ad mercurial/manifest.py --- a/mercurial/manifest.py Sun Oct 06 09:45:02 2019 -0400 +++ b/mercurial/manifest.py Sun Oct 06 09:48:39 2019 -0400 @@ -45,18 +45,18 @@ # class exactly matches its C counterpart to try and help # prevent surprise breakage for anyone that develops against # the pure version. - if data and data[-1:] != '\n': - raise ValueError('Manifest did not end in a newline.') + if data and data[-1:] != b'\n': + raise ValueError(b'Manifest did not end in a newline.') prev = None for l in data.splitlines(): if prev is not None and prev > l: - raise ValueError('Manifest lines not in sorted order.') + raise ValueError(b'Manifest lines not in sorted order.') prev = l - f, n = l.split('\0') + f, n = l.split(b'\0') if len(n) > 40: yield f, bin(n[:40]), n[40:] else: - yield f, bin(n), '' + yield f, bin(n), b'' def _text(it): @@ -66,10 +66,10 @@ files.append(f) # if this is changed to support newlines in filenames, # be sure to check the templates/ dir again (especially *-raw.tmpl) - lines.append("%s\0%s%s\n" % (f, hex(n), fl)) + lines.append(b"%s\0%s%s\n" % (f, hex(n), fl)) _checkforbidden(files) - return ''.join(lines) + return b''.join(lines) class lazymanifestiter(object): @@ -89,7 +89,7 @@ self.pos += 1 return data[0] self.pos += 1 - zeropos = data.find('\x00', pos) + zeropos = data.find(b'\x00', pos) return data[pos:zeropos] __next__ = next @@ -111,7 +111,7 @@ if pos == -1: self.pos += 1 return data - zeropos = data.find('\x00', pos) + zeropos = data.find(b'\x00', pos) hashval = unhexlify(data, self.lm.extrainfo[self.pos], zeropos + 1, 40) flags = self.lm._getflags(data, self.pos, zeropos) self.pos += 1 @@ -173,18 +173,18 @@ def findlines(self, data): if not data: return [] - pos = data.find("\n") - if pos == -1 or data[-1:] != '\n': - raise ValueError("Manifest did not end in a newline.") + pos = data.find(b"\n") + if pos == -1 or data[-1:] != b'\n': + raise ValueError(b"Manifest did not end in a newline.") positions = [0] - prev = data[: data.find('\x00')] + prev = data[: data.find(b'\x00')] while pos < len(data) - 1 and pos != -1: positions.append(pos + 1) - nexts = data[pos + 1 : data.find('\x00', pos + 1)] + nexts = data[pos + 1 : data.find(b'\x00', pos + 1)] if nexts < prev: - raise ValueError("Manifest lines not in sorted order.") + raise ValueError(b"Manifest lines not in sorted order.") prev = nexts - pos = data.find("\n", pos + 1) + pos = data.find(b"\n", pos + 1) return positions def _get(self, index): @@ -198,7 +198,7 @@ def _getkey(self, pos): if pos >= 0: - return self.data[pos : self.data.find('\x00', pos + 1)] + return self.data[pos : self.data.find(b'\x00', pos + 1)] return self.extradata[-pos - 1][0] def bsearch(self, key): @@ -244,23 +244,23 @@ def _getflags(self, data, needle, pos): start = pos + 41 - end = data.find("\n", start) + end = data.find(b"\n", start) if end == -1: end = len(data) - 1 if start == end: - return '' + return b'' return self.data[start:end] def __getitem__(self, key): if not isinstance(key, bytes): - raise TypeError("getitem: manifest keys must be a bytes.") + raise TypeError(b"getitem: manifest keys must be a bytes.") needle = self.bsearch(key) if needle == -1: raise KeyError data, pos = self._get(needle) if pos == -1: return (data[1], data[2]) - zeropos = data.find('\x00', pos) + zeropos = data.find(b'\x00', pos) assert 0 <= needle <= len(self.positions) assert len(self.extrainfo) == len(self.positions) hashval = unhexlify(data, self.extrainfo[needle], zeropos + 1, 40) @@ -277,22 +277,24 @@ if cur >= 0: # This does NOT unsort the list as far as the search functions are # concerned, as they only examine lines mapped by self.positions. - self.data = self.data[:cur] + '\x00' + self.data[cur + 1 :] + self.data = self.data[:cur] + b'\x00' + self.data[cur + 1 :] self.hasremovals = True def __setitem__(self, key, value): if not isinstance(key, bytes): - raise TypeError("setitem: manifest keys must be a byte string.") + raise TypeError(b"setitem: manifest keys must be a byte string.") if not isinstance(value, tuple) or len(value) != 2: - raise TypeError("Manifest values must be a tuple of (node, flags).") + raise TypeError( + b"Manifest values must be a tuple of (node, flags)." + ) hashval = value[0] if not isinstance(hashval, bytes) or not 20 <= len(hashval) <= 22: - raise TypeError("node must be a 20-byte byte string") + raise TypeError(b"node must be a 20-byte byte string") flags = value[1] if len(hashval) == 22: hashval = hashval[:-1] if not isinstance(flags, bytes) or len(flags) > 1: - raise TypeError("flags must a 0 or 1 byte string, got %r", flags) + raise TypeError(b"flags must a 0 or 1 byte string, got %r", flags) needle, found = self.bsearch2(key) if found: # put the item @@ -353,14 +355,14 @@ # before the next position. if ( self.hasremovals - and self.data.find('\n\x00', cur, self.positions[i]) + and self.data.find(b'\n\x00', cur, self.positions[i]) != -1 ): break offset += self.positions[i] - cur cur = self.positions[i] - end_cut = self.data.find('\n', cur) + end_cut = self.data.find(b'\n', cur) if end_cut != -1: end_cut += 1 offset += end_cut - cur @@ -375,12 +377,12 @@ self.extrainfo[i] = ord(t[1][21]) offset += len(l[-1]) i += 1 - self.data = ''.join(l) + self.data = b''.join(l) self.hasremovals = False self.extradata = [] def _pack(self, d): - return d[0] + '\x00' + hex(d[1][:20]) + d[2] + '\n' + return d[0] + b'\x00' + hex(d[1][:20]) + d[2] + b'\n' def text(self): self._compact() @@ -393,7 +395,7 @@ for fn, e1, flags in self.iterentries(): if fn not in m2: - diff[fn] = (e1, flags), (None, '') + diff[fn] = (e1, flags), (None, b'') else: e2 = m2[fn] if (e1, flags) != e2: @@ -403,7 +405,7 @@ for fn, e2, flags in m2.iterentries(): if fn not in self: - diff[fn] = (None, ''), (e2, flags) + diff[fn] = (None, b''), (e2, flags) return diff @@ -421,7 +423,7 @@ def filtercopy(self, filterfn): # XXX should be optimized - c = _lazymanifest('') + c = _lazymanifest(b'') for f, n, fl in self.iterentries(): if filterfn(f): c[f] = n, fl @@ -436,7 +438,7 @@ @interfaceutil.implementer(repository.imanifestdict) class manifestdict(object): - def __init__(self, data=''): + def __init__(self, data=b''): self._lm = _lazymanifest(data) def __getitem__(self, key): @@ -456,7 +458,7 @@ __bool__ = __nonzero__ def __setitem__(self, key, node): - self._lm[key] = node, self.flags(key, '') + self._lm[key] = node, self.flags(key, b'') def __contains__(self, key): if key is None: @@ -538,7 +540,7 @@ # for dirstate.walk, files=[''] means "walk the whole tree". # follow that here, too - fset.discard('') + fset.discard(b'') for fn in sorted(fset): if not self.hasdir(fn): @@ -591,7 +593,7 @@ except KeyError: return default - def flags(self, key, default=''): + def flags(self, key, default=b''): try: return self._lm[key][1] except KeyError: @@ -622,7 +624,7 @@ delta = [] dstart = None dend = None - dline = [""] + dline = [b""] start = 0 # zero copy representation of base as a buffer addbuf = util.buffer(base) @@ -636,14 +638,14 @@ start, end = _msearch(addbuf, f, start) if not todelete: h, fl = self._lm[f] - l = "%s\0%s%s\n" % (f, hex(h), fl) + l = b"%s\0%s%s\n" % (f, hex(h), fl) else: if start == end: # item we want to delete was not found, error out raise AssertionError( - _("failed to remove %s from manifest") % f + _(b"failed to remove %s from manifest") % f ) - l = "" + l = b"" if dstart is not None and dstart <= start and dend >= start: if dend < end: dend = end @@ -651,13 +653,13 @@ dline.append(l) else: if dstart is not None: - delta.append([dstart, dend, "".join(dline)]) + delta.append([dstart, dend, b"".join(dline)]) dstart = start dend = end dline = [l] if dstart is not None: - delta.append([dstart, dend, "".join(dline)]) + delta.append([dstart, dend, b"".join(dline)]) # apply the delta to the base, and get a delta for addrevision deltatext, arraytext = _addlistdelta(base, delta) else: @@ -694,21 +696,21 @@ while lo < hi: mid = (lo + hi) // 2 start = mid - while start > 0 and m[start - 1 : start] != '\n': + while start > 0 and m[start - 1 : start] != b'\n': start -= 1 - end = advance(start, '\0') + end = advance(start, b'\0') if bytes(m[start:end]) < s: # we know that after the null there are 40 bytes of sha1 # this translates to the bisect lo = mid + 1 - lo = advance(end + 40, '\n') + 1 + lo = advance(end + 40, b'\n') + 1 else: # this translates to the bisect hi = mid hi = start - end = advance(lo, '\0') + end = advance(lo, b'\0') found = m[lo:end] if s == found: # we know that after the null there are 40 bytes of sha1 - end = advance(end + 40, '\n') + end = advance(end + 40, b'\n') return (lo, end + 1) else: return (lo, lo) @@ -717,9 +719,9 @@ def _checkforbidden(l): """Check filenames for illegal characters.""" for f in l: - if '\n' in f or '\r' in f: + if b'\n' in f or b'\r' in f: raise error.StorageError( - _("'\\n' and '\\r' disallowed in filenames: %r") + _(b"'\\n' and '\\r' disallowed in filenames: %r") % pycompat.bytestr(f) ) @@ -741,26 +743,26 @@ newaddlist += addlist[currentposition:] - deltatext = "".join( - struct.pack(">lll", start, end, len(content)) + content + deltatext = b"".join( + struct.pack(b">lll", start, end, len(content)) + content for start, end, content in x ) return deltatext, newaddlist def _splittopdir(f): - if '/' in f: - dir, subpath = f.split('/', 1) - return dir + '/', subpath + if b'/' in f: + dir, subpath = f.split(b'/', 1) + return dir + b'/', subpath else: - return '', f + return b'', f _noop = lambda s: None class treemanifest(object): - def __init__(self, dir='', text=''): + def __init__(self, dir=b'', text=b''): self._dir = dir self._node = nullid self._loadfunc = _noop @@ -775,7 +777,7 @@ def readsubtree(subdir, subm): raise AssertionError( - 'treemanifest constructor only accepts ' 'flat manifests' + b'treemanifest constructor only accepts ' b'flat manifests' ) self.parse(text, readsubtree) @@ -806,13 +808,13 @@ def _loadchildrensetlazy(self, visit): if not visit: return None - if visit == 'all' or visit == 'this': + if visit == b'all' or visit == b'this': self._loadalllazy() return None loadlazy = self._loadlazy for k in visit: - loadlazy(k + '/') + loadlazy(k + b'/') return visit def _loaddifflazy(self, t1, t2): @@ -862,7 +864,7 @@ return not self._dirs or all(m._isempty() for m in self._dirs.values()) def __repr__(self): - return '' % ( + return b'' % ( self._dir, hex(self._node), bool(self._loadfunc is _noop), @@ -893,7 +895,7 @@ itertools.chain(self._dirs.items(), self._files.items()) ): if p in self._files: - yield self._subpath(p), n, self._flags.get(p, '') + yield self._subpath(p), n, self._flags.get(p, b'') else: for x in n.iterentries(): yield x @@ -972,12 +974,12 @@ self._loadlazy(dir) if dir not in self._dirs: - return '' + return b'' return self._dirs[dir].flags(subpath) else: if f in self._lazydirs or f in self._dirs: - return '' - return self._flags.get(f, '') + return b'' + return self._flags.get(f, b'') def find(self, f): self._load() @@ -987,7 +989,7 @@ return self._dirs[dir].find(subpath) else: - return self._files[f], self._flags.get(f, '') + return self._files[f], self._flags.get(f, b'') def __delitem__(self, f): self._load() @@ -1109,7 +1111,7 @@ if topdir in self._dirs: return self._dirs[topdir].hasdir(subdir) return False - dirslash = dir + '/' + dirslash = dir + b'/' return dirslash in self._dirs or dirslash in self._lazydirs def walk(self, match): @@ -1135,7 +1137,7 @@ # for dirstate.walk, files=[''] means "walk the whole tree". # follow that here, too - fset.discard('') + fset.discard(b'') for fn in sorted(fset): if not self.hasdir(fn): @@ -1172,7 +1174,7 @@ ''' visit = match.visitchildrenset(self._dir[:-1]) - if visit == 'all': + if visit == b'all': return self.copy() ret = treemanifest(self._dir) if not visit: @@ -1185,7 +1187,7 @@ # If visit == 'this', we should obviously look at the files in this # directory; if visit is a set, and fn is in it, we should inspect # fn (but no need to inspect things not in the set). - if visit != 'this' and fn not in visit: + if visit != b'this' and fn not in visit: continue fullp = self._subpath(fn) # visitchildrenset isn't perfect, we still need to call the regular @@ -1248,9 +1250,9 @@ stack.append((emptytree, m2)) for fn, n1 in t1._files.iteritems(): - fl1 = t1._flags.get(fn, '') + fl1 = t1._flags.get(fn, b'') n2 = t2._files.get(fn, None) - fl2 = t2._flags.get(fn, '') + fl2 = t2._flags.get(fn, b'') if n1 != n2 or fl1 != fl2: result[t1._subpath(fn)] = ((n1, fl1), (n2, fl2)) elif clean: @@ -1258,8 +1260,8 @@ for fn, n2 in t2._files.iteritems(): if fn not in t1._files: - fl2 = t2._flags.get(fn, '') - result[t2._subpath(fn)] = ((None, ''), (n2, fl2)) + fl2 = t2._flags.get(fn, b'') + result[t2._subpath(fn)] = ((None, b''), (n2, fl2)) stackls = [] _iterativediff(self, m2, stackls) @@ -1276,12 +1278,12 @@ selflazy = self._lazydirs subpath = self._subpath for f, n, fl in _parse(text): - if fl == 't': - f = f + '/' + if fl == b't': + f = f + b'/' # False below means "doesn't need to be copied" and can use the # cached value from readsubtree directly. selflazy[f] = (subpath(f), n, readsubtree, False) - elif '/' in f: + elif b'/' in f: # This is a flat manifest, so use __setitem__ and setflag rather # than assigning directly to _files and _flags, so we can # assign a path in a subdirectory, and to mark dirty (compared @@ -1307,8 +1309,8 @@ """ self._load() flags = self.flags - lazydirs = [(d[:-1], v[1], 't') for d, v in self._lazydirs.iteritems()] - dirs = [(d[:-1], self._dirs[d]._node, 't') for d in self._dirs] + lazydirs = [(d[:-1], v[1], b't') for d, v in self._lazydirs.iteritems()] + dirs = [(d[:-1], self._dirs[d]._node, b't') for d in self._dirs] files = [(f, self._files[f], flags(f)) for f in self._files] return _text(sorted(dirs + files + lazydirs)) @@ -1334,7 +1336,7 @@ # let's skip investigating things that `match` says we do not need. visit = match.visitchildrenset(self._dir[:-1]) visit = self._loadchildrensetlazy(visit) - if visit == 'this' or visit == 'all': + if visit == b'this' or visit == b'all': visit = None for d, subm in self._dirs.iteritems(): if visit and d[:-1] not in visit: @@ -1375,7 +1377,7 @@ """ - _file = 'manifestfulltextcache' + _file = b'manifestfulltextcache' def __init__(self, max): super(manifestfulltextcache, self).__init__(max) @@ -1396,7 +1398,7 @@ if len(node) < 20: break try: - size = struct.unpack('>L', fp.read(4))[0] + size = struct.unpack(b'>L', fp.read(4))[0] except struct.error: break value = bytearray(fp.read(size)) @@ -1415,13 +1417,13 @@ return # rotate backwards to the first used node with self._opener( - self._file, 'w', atomictemp=True, checkambig=True + self._file, b'w', atomictemp=True, checkambig=True ) as fp: node = self._head.prev while True: if node.key in self._cache: fp.write(node.key) - fp.write(struct.pack('>L', len(node.value))) + fp.write(struct.pack(b'>L', len(node.value))) fp.write(node.value) if node is self._head: break @@ -1491,7 +1493,7 @@ def __init__( self, opener, - tree='', + tree=b'', dirlogcache=None, indexfile=None, treemanifest=False, @@ -1513,20 +1515,20 @@ optiontreemanifest = False opts = getattr(opener, 'options', None) if opts is not None: - cachesize = opts.get('manifestcachesize', cachesize) - optiontreemanifest = opts.get('treemanifest', False) + cachesize = opts.get(b'manifestcachesize', cachesize) + optiontreemanifest = opts.get(b'treemanifest', False) self._treeondisk = optiontreemanifest or treemanifest self._fulltextcache = manifestfulltextcache(cachesize) if tree: - assert self._treeondisk, 'opts is %r' % opts + assert self._treeondisk, b'opts is %r' % opts if indexfile is None: - indexfile = '00manifest.i' + indexfile = b'00manifest.i' if tree: - indexfile = "meta/" + tree + indexfile + indexfile = b"meta/" + tree + indexfile self.tree = tree @@ -1534,7 +1536,7 @@ if tree: self._dirlogcache = dirlogcache else: - self._dirlogcache = {'': self} + self._dirlogcache = {b'': self} self._revlog = revlog.revlog( opener, @@ -1551,7 +1553,7 @@ def _setupmanifestcachehooks(self, repo): """Persist the manifestfulltextcache on lock release""" - if not util.safehasattr(repo, '_wlockref'): + if not util.safehasattr(repo, b'_wlockref'): return self._fulltextcache._opener = repo.wcachevfs @@ -1604,7 +1606,7 @@ readtree=None, match=None, ): - if p1 in self.fulltextcache and util.safehasattr(m, 'fastdelta'): + if p1 in self.fulltextcache and util.safehasattr(m, b'fastdelta'): # If our first parent is in the manifest cache, we can # compute a delta here using properties we know about the # manifest up-front, which may save time later for the @@ -1629,8 +1631,8 @@ # through to the revlog layer, and let it handle the delta # process. if self._treeondisk: - assert readtree, "readtree must be set for treemanifest writes" - assert match, "match must be specified for treemanifest writes" + assert readtree, b"readtree must be set for treemanifest writes" + assert match, b"match must be specified for treemanifest writes" m1 = readtree(self.tree, p1) m2 = readtree(self.tree, p2) n = self._addtree( @@ -1650,7 +1652,9 @@ def _addtree(self, m, transaction, link, m1, m2, readtree, match): # If the manifest is unchanged compared to one parent, # don't write a new revision - if self.tree != '' and (m.unmodifiedsince(m1) or m.unmodifiedsince(m2)): + if self.tree != b'' and ( + m.unmodifiedsince(m1) or m.unmodifiedsince(m2) + ): return m.node() def writesubtree(subm, subp1, subp2, match): @@ -1670,7 +1674,7 @@ m.writesubtrees(m1, m2, writesubtree, match) text = m.dirtext() n = None - if self.tree != '': + if self.tree != b'': # Double-check whether contents are unchanged to one parent if text == m1.dirtext(): n = m1.node() @@ -1763,7 +1767,7 @@ def clone(self, tr, destrevlog, **kwargs): if not isinstance(destrevlog, manifestrevlog): - raise error.ProgrammingError('expected manifestrevlog to clone()') + raise error.ProgrammingError(b'expected manifestrevlog to clone()') return self._revlog.clone(tr, destrevlog._revlog, **kwargs) @@ -1816,8 +1820,8 @@ opts = getattr(opener, 'options', None) if opts is not None: - usetreemanifest = opts.get('treemanifest', usetreemanifest) - cachesize = opts.get('manifestcachesize', cachesize) + usetreemanifest = opts.get(b'treemanifest', usetreemanifest) + cachesize = opts.get(b'manifestcachesize', cachesize) self._treemanifests = usetreemanifest @@ -1827,7 +1831,7 @@ # A cache of the manifestctx or treemanifestctx for each directory self._dirmancache = {} - self._dirmancache[''] = util.lrucachedict(cachesize) + self._dirmancache[b''] = util.lrucachedict(cachesize) self._cachesize = cachesize @@ -1835,7 +1839,7 @@ """Retrieves the manifest instance for the given node. Throws a LookupError if not found. """ - return self.get('', node) + return self.get(b'', node) def get(self, tree, node, verify=True): """Retrieves the manifest instance for the given node. Throws a @@ -1861,8 +1865,8 @@ else: raise error.Abort( _( - "cannot ask for manifest directory '%s' in a flat " - "manifest" + b"cannot ask for manifest directory '%s' in a flat " + b"manifest" ) % tree ) @@ -1872,7 +1876,7 @@ self._rootstore.rev(node) if self._treemanifests: - m = treemanifestctx(self, '', node) + m = treemanifestctx(self, b'', node) else: m = manifestctx(self, node) @@ -2012,7 +2016,7 @@ @interfaceutil.implementer(repository.imanifestrevisionwritable) class memtreemanifestctx(object): - def __init__(self, manifestlog, dir=''): + def __init__(self, manifestlog, dir=b''): self._manifestlog = manifestlog self._dir = dir self._treemanifest = treemanifest() @@ -2020,7 +2024,7 @@ def _storage(self): return self._manifestlog.getstorage(b'') - def new(self, dir=''): + def new(self, dir=b''): return memtreemanifestctx(self._manifestlog, dir=dir) def copy(self): @@ -2105,7 +2109,7 @@ def node(self): return self._node - def new(self, dir=''): + def new(self, dir=b''): return memtreemanifestctx(self._manifestlog, dir=dir) def copy(self): @@ -2186,8 +2190,8 @@ self._node = node # Add an empty file, which will be included by iterators and such, # appearing as the directory itself (i.e. something like "dir/") - self._files[''] = node - self._flags[''] = 't' + self._files[b''] = node + self._flags[b''] = b't' # Manifests outside the narrowspec should never be modified, so avoid # copying. This makes a noticeable difference when there are very many @@ -2210,7 +2214,7 @@ def write(self, *args): raise error.ProgrammingError( - 'attempt to write manifest from excluded dir %s' % self._dir + b'attempt to write manifest from excluded dir %s' % self._dir ) @@ -2229,22 +2233,22 @@ def __len__(self): raise error.ProgrammingError( - 'attempt to get length of excluded dir %s' % self._dir + b'attempt to get length of excluded dir %s' % self._dir ) def rev(self, node): raise error.ProgrammingError( - 'attempt to get rev from excluded dir %s' % self._dir + b'attempt to get rev from excluded dir %s' % self._dir ) def linkrev(self, node): raise error.ProgrammingError( - 'attempt to get linkrev from excluded dir %s' % self._dir + b'attempt to get linkrev from excluded dir %s' % self._dir ) def node(self, rev): raise error.ProgrammingError( - 'attempt to get node from excluded dir %s' % self._dir + b'attempt to get node from excluded dir %s' % self._dir ) def add(self, *args, **kwargs):