patch: handle symlinks without symlinkhunk
Symlink creations and deletions were handled with a special symlinkhunk object,
working like a binary hunk. However, this model does not support symlink
updates or replacements, so we teach regular hunks how to handle symlinks.
--- a/mercurial/patch.py Sat Oct 10 12:19:58 2009 +0200
+++ b/mercurial/patch.py Thu Oct 15 23:15:30 2009 +0200
@@ -292,13 +292,15 @@
self.hunks = 0
def readlines(self, fname):
+ if os.path.islink(fname):
+ return [os.readlink(fname)]
fp = self.opener(fname, 'r')
try:
return list(linereader(fp, self.eol is not None))
finally:
fp.close()
- def writelines(self, fname, lines):
+ def writelines(self, fname, lines):
fp = self.opener(fname, 'w')
try:
if self.eol and self.eol != '\n':
@@ -405,7 +407,7 @@
self.rej.append(h)
return -1
- if isinstance(h, githunk):
+ if isinstance(h, binhunk):
if h.rmfile():
self.unlink(self.fname)
else:
@@ -696,12 +698,12 @@
def new(self, fuzz=0, toponly=False):
return self.fuzzit(self.b, fuzz, toponly)
-class githunk(object):
- """A git hunk"""
+class binhunk:
+ 'A binary patch file. Only understands literals so far.'
def __init__(self, gitpatch):
self.gitpatch = gitpatch
self.text = None
- self.hunk = []
+ self.hunk = ['GIT binary patch\n']
def createfile(self):
return self.gitpatch.op in ('ADD', 'RENAME', 'COPY')
@@ -715,12 +717,6 @@
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)
@@ -748,18 +744,6 @@
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')
@@ -897,10 +881,6 @@
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
--- a/tests/test-mq-symlinks Sat Oct 10 12:19:58 2009 +0200
+++ b/tests/test-mq-symlinks Thu Oct 15 23:15:30 2009 +0200
@@ -8,12 +8,13 @@
hg init
hg qinit
hg qnew base.patch
-echo a > a
-echo b > b
+echo aaa > a
+echo bbb > b
hg add a b
hg qrefresh
$TESTDIR/readlink.py a
+echo '% test replacing a file with a symlink'
hg qnew symlink.patch
rm a
ln -s b a
@@ -24,6 +25,7 @@
hg qpush
$TESTDIR/readlink.py a
+echo '% test symlink removal'
hg qnew removesl.patch
hg rm a
hg qrefresh --git
--- a/tests/test-mq-symlinks.out Sat Oct 10 12:19:58 2009 +0200
+++ b/tests/test-mq-symlinks.out Thu Oct 15 23:15:30 2009 +0200
@@ -1,9 +1,11 @@
a -> a not a symlink
+% test replacing a file with a symlink
a -> b
now at: base.patch
applying symlink.patch
now at: symlink.patch
a -> b
+% test symlink removal
now at: symlink.patch
applying removesl.patch
now at: removesl.patch