patch: pass linereader to scangitpatch(), extract from iterhunks()

It's good because it unifies the patch file access methods.
This commit is contained in:
Patrick Mezard 2008-10-18 23:45:46 +02:00
parent 92038e51fa
commit 7e769ebcae

View File

@ -166,15 +166,9 @@ class patchmeta:
isexec = mode & 0100
self.mode = (islink, isexec)
def readgitpatch(fp, firstline=None):
def readgitpatch(lr):
"""extract git-style metadata about patches from <patchname>"""
def reader(fp, firstline):
if firstline is not None:
yield firstline
for line in fp:
yield line
# Filter patch for git information
gitre = re.compile('diff --git a/(.*) b/(.*)')
gp = None
@ -183,7 +177,7 @@ def readgitpatch(fp, firstline=None):
dopatch = 0
lineno = 0
for line in reader(fp, firstline):
for line in lr:
lineno += 1
if line.startswith('diff --git'):
m = gitre.match(line)
@ -461,7 +455,7 @@ class hunk:
self.lenb = int(self.lenb)
self.starta = int(self.starta)
self.startb = int(self.startb)
diffhelpers.addlines(lr.fp, self.hunk, self.lena, self.lenb, self.a, self.b)
diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
# if we hit eof before finishing out the hunk, the last line will
# be zero length. Lets try to fix it up.
while len(self.hunk[-1]) == 0:
@ -771,7 +765,8 @@ class linereader:
self.buf = []
def push(self, line):
self.buf.append(line)
if line is not None:
self.buf.append(line)
def readline(self):
if self.buf:
@ -780,6 +775,39 @@ class linereader:
return l
return self.fp.readline()
def __iter__(self):
while 1:
l = self.readline()
if not l:
break
yield l
def scangitpatch(lr, firstline):
"""
Git patches can emit:
- rename a to b
- change b
- copy a to c
- change c
We cannot apply this sequence as-is, the renamed 'a' could not be
found for it would have been renamed already. And we cannot copy
from 'b' instead because 'b' would have been changed already. So
we scan the git patch for copy and rename commands so we can
perform the copies ahead of time.
"""
pos = 0
try:
pos = lr.fp.tell()
fp = lr.fp
except IOError:
fp = cStringIO.StringIO(lr.fp.read())
gitlr = linereader(fp)
gitlr.push(firstline)
(dopatch, gitpatches) = readgitpatch(gitlr)
fp.seek(pos)
return fp, dopatch, gitpatches
def iterhunks(ui, fp, sourcefile=None):
"""Read a patch and yield the following events:
- ("file", afile, bfile, firsthunk): select a new target file.
@ -788,24 +816,6 @@ def iterhunks(ui, fp, sourcefile=None):
- ("git", gitchanges): current diff is in git format, gitchanges
maps filenames to gitpatch records. Unique event.
"""
def scangitpatch(fp, firstline):
'''git patches can modify a file, then copy that file to
a new file, but expect the source to be the unmodified form.
So we scan the patch looking for that case so we can do
the copies ahead of time.'''
pos = 0
try:
pos = fp.tell()
except IOError:
fp = cStringIO.StringIO(fp.read())
(dopatch, gitpatches) = readgitpatch(fp, firstline)
fp.seek(pos)
return fp, dopatch, gitpatches
changed = {}
current_hunk = None
afile = ""
@ -869,7 +879,7 @@ def iterhunks(ui, fp, sourcefile=None):
afile, bfile = m.group(1, 2)
if not git:
git = True
fp, dopatch, gitpatches = scangitpatch(fp, x)
fp, dopatch, gitpatches = scangitpatch(lr, x)
yield 'git', gitpatches
for gp in gitpatches:
changed[gp.path] = gp