archive: add symlink support
authorAlexis S. L. Carvalho <alexis@cecm.usp.br>
Wed, 11 Jul 2007 17:40:41 -0300
changeset 4831 6f08bc1bd00b
parent 4830 74f36b1027f4
child 4832 0875082d5471
archive: add symlink support
mercurial/archival.py
tests/test-archive-symlinks
tests/test-archive-symlinks.out
--- a/mercurial/archival.py	Wed Jul 11 17:40:41 2007 -0300
+++ b/mercurial/archival.py	Wed Jul 11 17:40:41 2007 -0300
@@ -86,12 +86,19 @@
             # Python 2.5-2.5.1 have a regression that requires a name arg
             self.z = taropen(name='', mode='w|', fileobj=dest)
 
-    def addfile(self, name, mode, data):
+    def addfile(self, name, mode, islink, data):
         i = tarfile.TarInfo(self.prefix + name)
         i.mtime = self.mtime
         i.size = len(data)
-        i.mode = mode
-        self.z.addfile(i, cStringIO.StringIO(data))
+        if islink:
+            i.type = tarfile.SYMTYPE
+            i.mode = 0777
+            i.linkname = data
+            data = None
+        else:
+            i.mode = mode
+            data = cStringIO.StringIO(data)
+        self.z.addfile(i, data)
 
     def done(self):
         self.z.close()
@@ -130,13 +137,17 @@
                                  zipfile.ZIP_STORED)
         self.date_time = time.gmtime(mtime)[:6]
 
-    def addfile(self, name, mode, data):
+    def addfile(self, name, mode, islink, data):
         i = zipfile.ZipInfo(self.prefix + name, self.date_time)
         i.compress_type = self.z.compression
         # unzip will not honor unix file modes unless file creator is
         # set to unix (id 3).
         i.create_system = 3
-        i.external_attr = (mode | stat.S_IFREG) << 16L
+        ftype = stat.S_IFREG
+        if islink:
+            mode = 0777
+            ftype = stat.S_IFLNK
+        i.external_attr = (mode | ftype) << 16L
         self.z.writestr(i, data)
 
     def done(self):
@@ -151,7 +162,10 @@
         self.basedir = name
         self.opener = util.opener(self.basedir)
 
-    def addfile(self, name, mode, data):
+    def addfile(self, name, mode, islink, data):
+        if islink:
+            self.opener.symlink(data, name)
+            return
         f = self.opener(name, "w", atomictemp=True)
         f.write(data)
         f.rename()
@@ -186,20 +200,20 @@
 
     prefix is name of path to put before every archive member.'''
 
-    def write(name, mode, data):
+    def write(name, mode, islink, data):
         if matchfn and not matchfn(name): return
         if decode:
             data = repo.wwritedata(name, data)
-        archiver.addfile(name, mode, data)
+        archiver.addfile(name, mode, islink, data)
 
     ctx = repo.changectx(node)
     archiver = archivers[kind](dest, prefix, mtime or ctx.date()[0])
     m = ctx.manifest()
     items = m.items()
     items.sort()
-    write('.hg_archival.txt', 0644,
+    write('.hg_archival.txt', 0644, False,
           'repo: %s\nnode: %s\n' % (hex(repo.changelog.node(0)), hex(node)))
     for filename, filenode in items:
-        write(filename, m.execf(filename) and 0755 or 0644,
+        write(filename, m.execf(filename) and 0755 or 0644, m.linkf(filename),
               repo.file(filename).read(filenode))
     archiver.done()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-archive-symlinks	Wed Jul 11 17:40:41 2007 -0300
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+origdir=`pwd`
+
+cat >> readlink.py <<EOF
+import os
+import sys
+
+for f in sys.argv[1:]:
+    print f, '->', os.readlink(f)
+EOF
+
+hg init repo
+cd repo
+ln -s nothing dangling
+hg ci -qAm 'add symlink'
+
+hg archive -t files ../archive
+hg archive -t tar -p tar ../archive.tar
+hg archive -t zip -p zip ../archive.zip
+
+echo '% files'
+cd "$origdir"
+cd archive
+python ../readlink.py dangling
+
+echo '% tar'
+cd "$origdir"
+tar xf archive.tar
+cd tar
+python ../readlink.py dangling
+
+echo '% zip'
+cd "$origdir"
+unzip archive.zip > /dev/null
+cd zip
+python ../readlink.py dangling
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-archive-symlinks.out	Wed Jul 11 17:40:41 2007 -0300
@@ -0,0 +1,6 @@
+% files
+dangling -> nothing
+% tar
+dangling -> nothing
+% zip
+dangling -> nothing