##// END OF EJS Templates
revert: remove dangerous `parents` argument from `cmdutil.revert()`...
revert: remove dangerous `parents` argument from `cmdutil.revert()` As we found out the hard way (thanks to spectral@ for figuring it out!), `cmdutil.revert()`'s `parents` argument must be `repo.dirstate.parents()` or things may go wrong. We had an extension that passed in the target commit as the first parent. The `hg split` command from the evolve extension seems to have made the same mistake, but I haven't looked carefully. The problem is that `cmdutil._performrevert()` calls `dirstate.normal()` on reverted files if the commit to revert to equals the first parent. So if you pass in `ctx=foo` and `parents=(foo.node(), nullid)`, then `dirstate.normal()` will be called for the revert files, even though they might not be clean in the working copy. There doesn't seem to be any reason, other than a tiny performance benefit, to passing the `parents` around instead of looking them up again in `cmdutil._performrevert()`, so that's what this patch does. Differential Revision: https://phab.mercurial-scm.org/D8925

File last commit:

r45714:10f48720 default
r45935:8c466bcb default
Show More
diffhelper.py
83 lines | 2.3 KiB | text/x-python | PythonLexer
# diffhelper.py - helper routines for patch
#
# 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 __future__ import absolute_import
from .i18n import _
from . import (
error,
pycompat,
)
MISSING_NEWLINE_MARKER = b'\\ No newline at end of file\n'
def addlines(fp, hunk, lena, lenb, a, b):
"""Read lines from fp into the hunk
The hunk is parsed into two arrays, a and b. a gets the old state of
the text, b gets the new state. The control char from the hunk is saved
when inserting into a, but not b (for performance while deleting files.)
"""
while True:
todoa = lena - len(a)
todob = lenb - len(b)
num = max(todoa, todob)
if num == 0:
break
for i in pycompat.xrange(num):
s = fp.readline()
if not s:
raise error.ParseError(_(b'incomplete hunk'))
if s == MISSING_NEWLINE_MARKER:
fixnewline(hunk, a, b)
continue
if s == b'\n' or s == b'\r\n':
# Some patches may be missing the control char
# on empty lines. Supply a leading space.
s = b' ' + s
hunk.append(s)
if s.startswith(b'+'):
b.append(s[1:])
elif s.startswith(b'-'):
a.append(s)
else:
b.append(s[1:])
a.append(s)
def fixnewline(hunk, a, b):
"""Fix up the last lines of a and b when the patch has no newline at EOF"""
l = hunk[-1]
# tolerate CRLF in last line
if l.endswith(b'\r\n'):
hline = l[:-2]
else:
hline = l[:-1]
if hline.startswith((b' ', b'+')):
b[-1] = hline[1:]
if hline.startswith((b' ', b'-')):
a[-1] = hline
hunk[-1] = hline
def testhunk(a, b, bstart):
"""Compare the lines in a with the lines in b
a is assumed to have a control char at the start of each line, this char
is ignored in the compare.
"""
alen = len(a)
blen = len(b)
if alen > blen - bstart or bstart < 0:
return False
for i in pycompat.xrange(alen):
if a[i][1:] != b[i + bstart]:
return False
return True