py3 blame

Summary: plain hg blame for non-binary files

Reviewed By: quark-zju

Differential Revision: D19676073

fbshipit-source-id: 203b0421c6279ea1ca6bb6e253e7952e64b5edeb
This commit is contained in:
Genevieve Helsel 2020-02-07 03:15:18 -08:00 committed by Facebook Github Bot
parent 4acc40424c
commit 0a2fd56bba
6 changed files with 57 additions and 11 deletions

View File

@ -213,12 +213,12 @@ class revmap(object):
@staticmethod
def _readcstr(f):
"""read a C-language-like '\0'-terminated string"""
buf = ""
buf = b""
while True:
ch = f.read(1)
if not ch: # unexpected eof
raise error.CorruptedFileError()
if ch == "\0":
if ch == b"\0":
break
buf += ch
return buf

View File

@ -128,6 +128,8 @@ class unioncontentstore(object):
A partial chain is a chain that may not be terminated in a full-text.
"""
assert isinstance(name, str)
assert isinstance(node, bytes)
for store in self.stores:
try:
return store.getdeltachain(name, node)
@ -171,23 +173,33 @@ class remotecontentstore(object):
self._shared = shared
def _prefetch(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
self._fileservice.prefetch(
[(name, hex(node))], force=True, fetchdata=True, fetchhistory=False
)
def get(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
self._prefetch(name, node)
return self._shared.get(name, node)
def getdelta(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
self._prefetch(name, node)
return self._shared.getdelta(name, node)
def getdeltachain(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
self._prefetch(name, node)
return self._shared.getdeltachain(name, node)
def getmeta(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
self._prefetch(name, node)
return self._shared.getmeta(name, node)
@ -208,17 +220,25 @@ class manifestrevlogstore(object):
self._repackstartlinkrev = 0
def get(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
return self._revlog(name).revision(node, raw=True)
def getdelta(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
revision = self.get(name, node)
return revision, name, nullid, self.getmeta(name, node)
def getdeltachain(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
revision = self.get(name, node)
return [(name, node, None, nullid, revision)]
def getmeta(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
rl = self._revlog(name)
rev = rl.rev(node)
return {
@ -227,6 +247,8 @@ class manifestrevlogstore(object):
}
def getnodeinfo(self, name, node):
assert isinstance(name, str)
assert isinstance(node, bytes)
cl = self.repo.changelog
rl = self._revlog(name)
parents = rl.parents(node)
@ -237,6 +259,7 @@ class manifestrevlogstore(object):
raise RuntimeError("cannot add to a revlog store")
def _revlog(self, name):
assert isinstance(name, str)
rl = self._revlogs.get(name)
if rl is None:
indexfile = None
@ -251,6 +274,8 @@ class manifestrevlogstore(object):
def getmissing(self, keys):
missing = []
for name, node in keys:
assert isinstance(name, str)
assert isinstance(node, bytes)
mfrevlog = self._revlog(name)
if node not in mfrevlog.nodemap:
missing.append((name, node))

View File

@ -471,8 +471,13 @@ def annotate(ui, repo, *pats, **opts):
continue
fm = rootfm.nested("lines")
lines = fctx.annotate(
follow=follow, linenumber=linenumber, skiprevs=skiprevs, diffopts=diffopts
lines = list(
fctx.annotate(
follow=follow,
linenumber=linenumber,
skiprevs=skiprevs,
diffopts=diffopts,
)
)
if not lines:
fm.end()
@ -496,10 +501,10 @@ def annotate(ui, repo, *pats, **opts):
fm.startitem()
sep = "* " if l[0].skip else ": "
fm.write(fields, "".join(f) + sep, *p, label="blame.age." + a)
fm.write("line", "%s", l[1])
fm.writebytes("line", b"%s", l[1])
if not lines[-1][1].endswith("\n"):
fm.plain("\n")
if not lines[-1][1].endswith(b"\n"):
fm.plainbytes(b"\n")
fm.end()
rootfm.end()

View File

@ -1137,9 +1137,9 @@ class basefilectx(object):
"""
def lines(text):
if text.endswith("\n"):
return text.count("\n")
return text.count("\n") + int(bool(text))
if text.endswith(b"\n"):
return text.count(b"\n")
return text.count(b"\n") + int(bool(text))
if linenumber:

View File

@ -213,6 +213,12 @@ class baseformatter(object):
assert len(fieldkeys) == len(fielddata)
self._item.update(zip(fieldkeys, fielddata))
def writebytes(self, fields, deftext, *fielddata, **opts):
"""do default text output while assigning data to item"""
fieldkeys = fields.split()
assert len(fieldkeys) == len(fielddata)
self._item.update(zip(fieldkeys, fielddata))
def condwrite(self, cond, fields, deftext, *fielddata, **opts):
"""do conditional write (primarily for plain formatter)"""
fieldkeys = fields.split()
@ -222,6 +228,9 @@ class baseformatter(object):
def plain(self, text, **opts):
"""show raw text for non-templated mode"""
def plainbytes(self, text, **opts):
"""show raw bytes for non-templated mode"""
def isplain(self):
"""check for plain formatter usage"""
return False
@ -292,8 +301,10 @@ class plainformatter(baseformatter):
self.hexfunc = short
if ui is out:
self._write = ui.write
self._writebytes = ui.writebytes
else:
self._write = lambda s, **opts: out.write(s)
self._writebytes = lambda s, **opts: out.writebytes(s)
def startitem(self):
pass
@ -304,6 +315,9 @@ class plainformatter(baseformatter):
def write(self, fields, deftext, *fielddata, **opts):
self._write(deftext % fielddata, **opts)
def writebytes(self, fields, deftext, *fielddata, **opts):
self._writebytes(deftext % fielddata, **opts)
def condwrite(self, cond, fields, deftext, *fielddata, **opts):
"""do conditional write"""
if cond:
@ -312,6 +326,9 @@ class plainformatter(baseformatter):
def plain(self, text, **opts):
self._write(text, **opts)
def plainbytes(self, text, **opts):
self._writebytes(text, **opts)
def isplain(self):
return True

View File

@ -1,4 +1,3 @@
#require py2
#chg-compatible
$ disable treemanifest