mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 00:14:35 +03:00
cf3f4a0258
Previously we'd place files written in the last second in the lookup set. This can lead to pathological cases where a file always remains in the lookup set if it gets modified before the next time status is run. With this patch, only the mtime of those files is invalidated. This means that if a file's size or mode changes, we can immediately declare it as modified without needing to compare file contents.
116 lines
3.3 KiB
Python
116 lines
3.3 KiB
Python
# parsers.py - Python implementation of parsers.c
|
|
#
|
|
# Copyright 2009 Matt Mackall <mpm@selenic.com> and others
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
from mercurial.node import bin, nullid
|
|
from mercurial import util
|
|
import struct, zlib, cStringIO
|
|
|
|
_pack = struct.pack
|
|
_unpack = struct.unpack
|
|
_compress = zlib.compress
|
|
_decompress = zlib.decompress
|
|
_sha = util.sha1
|
|
|
|
def parse_manifest(mfdict, fdict, lines):
|
|
for l in lines.splitlines():
|
|
f, n = l.split('\0')
|
|
if len(n) > 40:
|
|
fdict[f] = n[40:]
|
|
mfdict[f] = bin(n[:40])
|
|
else:
|
|
mfdict[f] = bin(n)
|
|
|
|
def parse_index2(data, inline):
|
|
def gettype(q):
|
|
return int(q & 0xFFFF)
|
|
|
|
def offset_type(offset, type):
|
|
return long(long(offset) << 16 | type)
|
|
|
|
indexformatng = ">Qiiiiii20s12x"
|
|
|
|
s = struct.calcsize(indexformatng)
|
|
index = []
|
|
cache = None
|
|
off = 0
|
|
|
|
l = len(data) - s
|
|
append = index.append
|
|
if inline:
|
|
cache = (0, data)
|
|
while off <= l:
|
|
e = _unpack(indexformatng, data[off:off + s])
|
|
append(e)
|
|
if e[1] < 0:
|
|
break
|
|
off += e[1] + s
|
|
else:
|
|
while off <= l:
|
|
e = _unpack(indexformatng, data[off:off + s])
|
|
append(e)
|
|
off += s
|
|
|
|
if off != len(data):
|
|
raise ValueError('corrupt index file')
|
|
|
|
if index:
|
|
e = list(index[0])
|
|
type = gettype(e[0])
|
|
e[0] = offset_type(0, type)
|
|
index[0] = tuple(e)
|
|
|
|
# add the magic null revision at -1
|
|
index.append((0, 0, 0, -1, -1, -1, -1, nullid))
|
|
|
|
return index, cache
|
|
|
|
def parse_dirstate(dmap, copymap, st):
|
|
parents = [st[:20], st[20: 40]]
|
|
# dereference fields so they will be local in loop
|
|
format = ">cllll"
|
|
e_size = struct.calcsize(format)
|
|
pos1 = 40
|
|
l = len(st)
|
|
|
|
# the inner loop
|
|
while pos1 < l:
|
|
pos2 = pos1 + e_size
|
|
e = _unpack(">cllll", st[pos1:pos2]) # a literal here is faster
|
|
pos1 = pos2 + e[4]
|
|
f = st[pos2:pos1]
|
|
if '\0' in f:
|
|
f, c = f.split('\0')
|
|
copymap[f] = c
|
|
dmap[f] = e[:4]
|
|
return parents
|
|
|
|
def pack_dirstate(dmap, copymap, pl, now):
|
|
now = int(now)
|
|
cs = cStringIO.StringIO()
|
|
write = cs.write
|
|
write("".join(pl))
|
|
for f, e in dmap.iteritems():
|
|
if e[0] == 'n' and e[3] == now:
|
|
# The file was last modified "simultaneously" with the current
|
|
# write to dirstate (i.e. within the same second for file-
|
|
# systems with a granularity of 1 sec). This commonly happens
|
|
# for at least a couple of files on 'update'.
|
|
# The user could change the file without changing its size
|
|
# within the same second. Invalidate the file's mtime in
|
|
# dirstate, forcing future 'status' calls to compare the
|
|
# contents of the file if the size is the same. This prevents
|
|
# mistakenly treating such files as clean.
|
|
e = (e[0], e[1], e[2], -1)
|
|
dmap[f] = e
|
|
|
|
if f in copymap:
|
|
f = "%s\0%s" % (f, copymap[f])
|
|
e = _pack(">cllll", e[0], e[1], e[2], e[3], len(f))
|
|
write(e)
|
|
write(f)
|
|
return cs.getvalue()
|