Merge with crew-stable
authorPatrick Mezard <pmezard@gmail.com>
Fri, 16 Oct 2009 00:06:23 +0200
changeset 9598 a981ddb16b80
parent 9597 fbed59b61a1c (current diff)
parent 9587 d80a251baf9a (diff)
child 9599 f3404b7f37ca
Merge with crew-stable
hgext/convert/subversion.py
mercurial/patch.py
tests/test-mq-symlinks.out
--- a/hgext/convert/subversion.py	Tue Oct 13 13:43:55 2009 -0700
+++ b/hgext/convert/subversion.py	Fri Oct 16 00:06:23 2009 +0200
@@ -115,7 +115,11 @@
 
     def __iter__(self):
         while True:
-            entry = pickle.load(self._stdout)
+            try:
+                entry = pickle.load(self._stdout)
+            except EOFError:
+                raise util.Abort(_('Mercurial failed to run itself, check'
+                                   ' hg executable is in PATH'))
             try:
                 orig_paths, revnum, author, date, message = entry
             except:
--- a/mercurial/patch.py	Tue Oct 13 13:43:55 2009 -0700
+++ b/mercurial/patch.py	Fri Oct 16 00:06:23 2009 +0200
@@ -292,14 +292,23 @@
         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):
-        fp = self.opener(fname, 'w')
+    def writelines(self, fname, lines):        
+        # Ensure supplied data ends in fname, being a regular file or
+        # a symlink. updatedir() will -too magically- take care of
+        # setting it to the proper type afterwards.
+        islink = os.path.islink(fname)
+        if islink:
+            fp = cStringIO.StringIO()
+        else:
+            fp = self.opener(fname, 'w')
         try:
             if self.eol and self.eol != '\n':
                 for l in lines:
@@ -308,6 +317,8 @@
                     fp.write(l)
             else:
                 fp.writelines(lines)
+            if islink:
+                self.opener.symlink(fp.getvalue(), fname)
         finally:
             fp.close()
 
@@ -399,7 +410,7 @@
             self.rej.append(h)
             return -1
 
-        if isinstance(h, githunk):
+        if isinstance(h, binhunk):
             if h.rmfile():
                 self.unlink(self.fname)
             else:
@@ -665,12 +676,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')
@@ -684,12 +695,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)
@@ -717,18 +722,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')
@@ -875,10 +868,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-convert-svn-branches	Tue Oct 13 13:43:55 2009 -0700
+++ b/tests/test-convert-svn-branches	Fri Oct 16 00:06:23 2009 +0200
@@ -28,3 +28,7 @@
 hg branches | sed 's/:.*/:/'
 hg tags -q
 cd ..
+
+echo '% test hg failing to call itself'
+HG=foobar hg convert svn-repo B-hg 2>&1 | grep -v foobar
+
--- a/tests/test-convert-svn-branches.out	Tue Oct 13 13:43:55 2009 -0700
+++ b/tests/test-convert-svn-branches.out	Fri Oct 16 00:06:23 2009 +0200
@@ -48,3 +48,6 @@
 old                            9:
 old2                           8:
 tip
+% test hg failing to call itself
+initializing destination B-hg repository
+abort: Mercurial failed to run itself, check hg executable is in PATH
--- a/tests/test-mq-symlinks	Tue Oct 13 13:43:55 2009 -0700
+++ b/tests/test-mq-symlinks	Fri Oct 16 00:06:23 2009 +0200
@@ -8,12 +8,14 @@
 hg init
 hg qinit
 hg qnew base.patch
-echo a > a
-echo b > b
-hg add a b
+echo aaa > a
+echo bbb > b
+echo ccc > c
+hg add a b c
 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 +26,29 @@
 hg qpush
 $TESTDIR/readlink.py a
 
+echo '% test updating a symlink'
+rm a
+ln -s c a
+hg qnew --git -f updatelink
+$TESTDIR/readlink.py a
+hg qpop
+hg qpush --debug
+$TESTDIR/readlink.py a
+hg st
+
+echo '% test replacing a symlink with a file'
+ln -s c s
+hg add s
+hg qnew --git -f addlink
+rm s
+echo sss > s
+hg qnew --git -f replacelinkwithfile
+hg qpop
+hg qpush
+cat s
+hg st
+
+echo '% test symlink removal' 
 hg qnew removesl.patch
 hg rm a
 hg qrefresh --git
--- a/tests/test-mq-symlinks.out	Tue Oct 13 13:43:55 2009 -0700
+++ b/tests/test-mq-symlinks.out	Fri Oct 16 00:06:23 2009 +0200
@@ -1,12 +1,31 @@
 a -> a not a symlink
+% test replacing a file with a symlink
 a -> b
 popping symlink.patch
 now at: base.patch
 applying symlink.patch
 now at: symlink.patch
 a -> b
+% test updating a symlink
+a -> c
+popping updatelink
+now at: symlink.patch
+applying updatelink
+patching file a
+a
+now at: updatelink
+a -> c
+% test replacing a symlink with a file
+popping replacelinkwithfile
+now at: addlink
+applying replacelinkwithfile
+now at: replacelinkwithfile
+sss
+% test symlink removal
 popping removesl.patch
-now at: symlink.patch
+now at: replacelinkwithfile
 applying removesl.patch
 now at: removesl.patch
 C b
+C c
+C s