in eden/scm/edenscm/mercurial/patch.py [0:0]
def split(stream):
"""return an iterator of individual patches from a stream"""
def isheader(line, inheader):
if inheader and line[:1] in (b" ", b"\t"):
# continuation
return True
if line[:1] in (b" ", b"-", b"+"):
# diff line - don't check for header pattern in there
return False
l = line.split(b": ", 1)
return len(l) == 2 and b" " not in l[0]
def chunk(lines):
return stringio(b"".join(lines))
def hgsplit(stream, cur):
inheader = True
for line in stream:
if not line.strip():
inheader = False
if not inheader and line.startswith(b"# HG changeset patch"):
yield chunk(cur)
cur = []
inheader = True
cur.append(line)
if cur:
yield chunk(cur)
def mboxsplit(stream, cur):
for line in stream:
if line.startswith(b"From "):
for c in split(chunk(cur[1:])):
yield c
cur = []
cur.append(line)
if cur:
for c in split(chunk(cur[1:])):
yield c
def mimesplit(stream, cur):
def msgfp(m):
fp = stringio()
g = email.Generator.Generator(fp, mangle_from_=False)
g.flatten(m)
fp.seek(0)
return fp
for line in stream:
cur.append(line)
c = chunk(cur)
m = pycompat.parse_email(c)
if not m.is_multipart():
yield msgfp(m)
else:
ok_types = ("text/plain", "text/x-diff", "text/x-patch")
for part in m.walk():
ct = part.get_content_type()
if ct not in ok_types:
continue
yield msgfp(part)
def headersplit(stream, cur):
inheader = False
for line in stream:
if not inheader and isheader(line, inheader):
yield chunk(cur)
cur = []
inheader = True
if inheader and not isheader(line, inheader):
inheader = False
cur.append(line)
if cur:
yield chunk(cur)
def remainder(cur):
yield chunk(cur)
class fiter(object):
def __init__(self, fp):
self.fp = fp
def __iter__(self):
return self
def next(self):
l = self.fp.readline()
if not l:
raise StopIteration
return l
__next__ = next
inheader = False
cur = []
mimeheaders = ["content-type"]
if not util.safehasattr(stream, "next"):
# http responses, for example, have readline but not next
stream = fiter(stream)
for line in stream:
cur.append(line)
if line.startswith(b"# HG changeset patch"):
return hgsplit(stream, cur)
elif line.startswith(b"From "):
return mboxsplit(stream, cur)
elif isheader(line, inheader):
inheader = True
if line.split(b":", 1)[0].lower() in mimeheaders:
# let email parser handle this
return mimesplit(stream, cur)
elif line.startswith(b"--- ") and inheader:
# No evil headers seen by diff start, split by hand
return headersplit(stream, cur)
# Not enough info, keep reading
# if we are here, we have a very plain patch
return remainder(cur)