changeset 5071:35d47b06d4e3

patch: add git symlink support
author Brendan Cully <brendan@kublai.com>
date Sat, 04 Aug 2007 23:07:52 -0700
parents 5023af9fcba4
children c89ed1f27e78
files mercurial/patch.py tests/test-symlinks tests/test-symlinks.out
diffstat 3 files changed, 45 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -202,9 +202,9 @@ def readgitpatch(fp, firstline=None):
                 gp.op = 'DELETE'
             elif line.startswith('new file mode '):
                 gp.op = 'ADD'
-                gp.mode = int(line.rstrip()[-3:], 8)
+                gp.mode = int(line.rstrip()[-6:], 8)
             elif line.startswith('new mode '):
-                gp.mode = int(line.rstrip()[-3:], 8)
+                gp.mode = int(line.rstrip()[-6:], 8)
             elif line.startswith('GIT binary patch'):
                 dopatch |= GP_BINARY
                 gp.binary = True
@@ -1048,12 +1048,15 @@ def updatedir(ui, repo, patches):
         ctype, gp = patches[f]
         if gp and gp.mode:
             x = gp.mode & 0100 != 0
+            l = gp.mode & 020000 != 0
             dst = os.path.join(repo.root, gp.path)
             # patch won't create empty files
             if ctype == 'ADD' and not os.path.exists(dst):
                 repo.wwrite(gp.path, '', x and 'x' or '')
             else:
-                util.set_exec(dst, x)
+                util.set_link(dst, l)
+                if not l:
+                    util.set_exec(dst, x)
     cmdutil.addremove(repo, cfiles)
     files = patches.keys()
     files.extend([r for r in removes if r not in files])
@@ -1145,11 +1148,15 @@ def diff(repo, node1=None, node2=None, f
     if node2:
         ctx2 = context.changectx(repo, node2)
         execf2 = ctx2.manifest().execf
+        linkf2 = ctx2.manifest().linkf
     else:
         ctx2 = context.workingctx(repo)
         execf2 = util.execfunc(repo.root, None)
+        linkf2 = util.linkfunc(repo.root, None)
         if execf2 is None:
-            execf2 = ctx2.parents()[0].manifest().copy().execf
+            mc = ctx2.parents()[0].manifest().copy()
+            execf2 = mc.execf
+            linkf2 = mc.linkf
 
     # returns False if there was no rename between ctx1 and ctx2
     # returns None if the file was created between ctx1 and ctx2
@@ -1206,8 +1213,8 @@ def diff(repo, node1=None, node2=None, f
         if f not in removed:
             tn = getfilectx(f, ctx2).data()
         if opts.git:
-            def gitmode(x):
-                return x and '100755' or '100644'
+            def gitmode(x, l):
+                return l and '120000' or (x and '100755' or '100644')
             def addmodehdr(header, omode, nmode):
                 if omode != nmode:
                     header.append('old mode %s\n' % omode)
@@ -1215,10 +1222,10 @@ def diff(repo, node1=None, node2=None, f
 
             a, b = f, f
             if f in added:
-                mode = gitmode(execf2(f))
+                mode = gitmode(execf2(f), linkf2(f))
                 if f in copied:
                     a = copied[f]
-                    omode = gitmode(man1.execf(a))
+                    omode = gitmode(man1.execf(a), man1.linkf(a))
                     addmodehdr(header, omode, mode)
                     if a in removed and a not in gone:
                         op = 'rename'
@@ -1236,11 +1243,11 @@ def diff(repo, node1=None, node2=None, f
                 if f in srcs:
                     dodiff = False
                 else:
-                    mode = gitmode(man1.execf(f))
+                    mode = gitmode(man1.execf(f), man1.linkf(f))
                     header.append('deleted file mode %s\n' % mode)
             else:
-                omode = gitmode(man1.execf(f))
-                nmode = gitmode(execf2(f))
+                omode = gitmode(man1.execf(f), man1.linkf(f))
+                nmode = gitmode(execf2(f), linkf2(f))
                 addmodehdr(header, omode, nmode)
                 if util.binary(to) or util.binary(tn):
                     dodiff = 'binary'
--- a/tests/test-symlinks
+++ b/tests/test-symlinks
@@ -72,3 +72,13 @@ hg commit -A -m 'add symlink in a/b/c su
 echo '2. clone it'
 cd ..
 hg clone test testclone
+
+echo '# git symlink diff'
+cd testclone
+hg diff --git -r null:tip
+hg export --git tip > ../sl.diff
+echo '# import git symlink diff'
+hg rm a/b/c/demo
+hg commit -m'remove link'
+hg import ../sl.diff
+hg diff --git -r 1:tip
--- a/tests/test-symlinks.out
+++ b/tests/test-symlinks.out
@@ -20,3 +20,20 @@ 1. commit a symlink
 adding a/b/c/demo
 2. clone it
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+# git symlink diff
+diff --git a/a/b/c/demo b/a/b/c/demo
+new file mode 120000
+--- /dev/null
++++ b/a/b/c/demo
+@@ -0,0 +1,1 @@
++/path/to/symlink/source
+\ No newline at end of file
+# import git symlink diff
+applying ../sl.diff
+diff --git a/a/b/c/demo b/a/b/c/demo
+new file mode 120000
+--- /dev/null
++++ b/a/b/c/demo
+@@ -0,0 +1,1 @@
++/path/to/symlink/source
+\ No newline at end of file