patch: handle git patches that remove symlinks (
issue1438)
--- a/mercurial/patch.py Sun Dec 14 17:35:19 2008 +0100
+++ b/mercurial/patch.py Sun Dec 14 23:04:29 2008 -0800
@@ -210,6 +210,8 @@
gp.path = line[8:].rstrip()
elif line.startswith('deleted file'):
gp.op = 'DELETE'
+ # is the deleted file a symlink?
+ gp.setmode(int(line.rstrip()[-6:], 8))
elif line.startswith('new file mode '):
gp.op = 'ADD'
gp.setmode(int(line.rstrip()[-6:], 8))
@@ -364,7 +366,7 @@
self.rej.append(h)
return -1
- if isinstance(h, binhunk):
+ if isinstance(h, githunk):
if h.rmfile():
self.unlink(self.fname)
else:
@@ -654,12 +656,12 @@
def new(self, fuzz=0, toponly=False):
return self.fuzzit(self.b, fuzz, toponly)
-class binhunk:
- 'A binary patch file. Only understands literals so far.'
+class githunk(object):
+ """A git hunk"""
def __init__(self, gitpatch):
self.gitpatch = gitpatch
self.text = None
- self.hunk = ['GIT binary patch\n']
+ self.hunk = []
def createfile(self):
return self.gitpatch.op in ('ADD', 'RENAME', 'COPY')
@@ -673,6 +675,12 @@
def new(self):
return [self.text]
+class binhunk(githunk):
+ 'A binary patch file. Only understands literals so far.'
+ def __init__(self, gitpatch):
+ super(binhunk, self).__init__(gitpatch)
+ self.hunk = ['GIT binary patch\n']
+
def extract(self, lr):
line = lr.readline()
self.hunk.append(line)
@@ -700,6 +708,18 @@
len(text), size)
self.text = text
+class symlinkhunk(githunk):
+ """A git symlink hunk"""
+ def __init__(self, gitpatch, hunk):
+ super(symlinkhunk, self).__init__(gitpatch)
+ self.hunk = hunk
+
+ def complete(self):
+ return True
+
+ def fix_newline(self):
+ return
+
def parsefilename(str):
# --- filename \t|space stuff
s = str[4:].rstrip('\r\n')
@@ -859,6 +879,10 @@
create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD'
remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE'
current_hunk = hunk(x, hunknum + 1, lr, context, create, remove)
+ if remove:
+ gpatch = changed.get(afile[2:])
+ if gpatch and gpatch.mode[0]:
+ current_hunk = symlinkhunk(gpatch, current_hunk)
except PatchError, err:
ui.debug(err)
current_hunk = None
@@ -1040,7 +1064,7 @@
if gp.op == 'ADD' and not os.path.exists(dst):
flags = (isexec and 'x' or '') + (islink and 'l' or '')
repo.wwrite(gp.path, '', flags)
- else:
+ elif gp.op != 'DELETE':
util.set_flags(dst, islink, isexec)
cmdutil.addremove(repo, cfiles, similarity=similarity)
files = patches.keys()
--- a/tests/test-mq-symlinks Sun Dec 14 17:35:19 2008 +0100
+++ b/tests/test-mq-symlinks Sun Dec 14 23:04:29 2008 -0800
@@ -23,3 +23,10 @@
hg qpop
hg qpush
$TESTDIR/readlink.py a
+
+hg qnew removesl.patch
+hg rm a
+hg qrefresh --git
+hg qpop
+hg qpush
+hg st -c
--- a/tests/test-mq-symlinks.out Sun Dec 14 17:35:19 2008 +0100
+++ b/tests/test-mq-symlinks.out Sun Dec 14 23:04:29 2008 -0800
@@ -4,3 +4,7 @@
applying symlink.patch
Now at: symlink.patch
a -> b
+Now at: symlink.patch
+applying removesl.patch
+Now at: removesl.patch
+C b