chiark / gitweb /
agpl.py: Fix up symbolic links between directories being dumped.
[chopwood] / agpl.py
diff --git a/agpl.py b/agpl.py
index b89330cb56de6e64f66303af0743e7dd184fc819..43eba824d5be38993b17d9cadfd3ff77ec36d6a2 100644 (file)
--- a/agpl.py
+++ b/agpl.py
 ### <http://www.gnu.org/licenses/>.
 
 import contextlib as CTX
 ### <http://www.gnu.org/licenses/>.
 
 import contextlib as CTX
+import grp as GR
 import os as OS
 import os as OS
+import pwd as PW
 import shlex as SL
 import shutil as SH
 import subprocess as SUB
 import sys as SYS
 import tarfile as TAR
 import tempfile as TF
 import shlex as SL
 import shutil as SH
 import subprocess as SUB
 import sys as SYS
 import tarfile as TAR
 import tempfile as TF
+import time as T
+
+from cStringIO import StringIO
 
 from auto import PACKAGE, VERSION
 import util as U
 
 from auto import PACKAGE, VERSION
 import util as U
@@ -74,9 +79,10 @@ def filez(cmd):
         z = buf.find('\0', i)
         if z < 0: break
         f = buf[i:z]
         z = buf.find('\0', i)
         if z < 0: break
         f = buf[i:z]
+        i = z + 1
+        if f == '.': continue
         if f.startswith('./'): f = f[2:]
         yield f
         if f.startswith('./'): f = f[2:]
         yield f
-        i = z + 1
       left = buf[i:]
     if left:
       raise U.ExpectedError, \
       left = buf[i:]
     if left:
       raise U.ExpectedError, \
@@ -88,16 +94,31 @@ DUMPERS = [
                            filez('find .git -print0')]),
   (lambda d: True, [filez('find . ( ! -perm +004 -prune ) -o -print0')])]
 
                            filez('find .git -print0')]),
   (lambda d: True, [filez('find . ( ! -perm +004 -prune ) -o -print0')])]
 
-def dump_dir(dir, tf, root):
+def dump_dir(name, dir, dirmap, tf, root):
   for test, listers in DUMPERS:
     if test(dir): break
   else:
     raise U.ExpectedError, (500, "no dumper for `%s'" % dir)
   for test, listers in DUMPERS:
     if test(dir): break
   else:
     raise U.ExpectedError, (500, "no dumper for `%s'" % dir)
+  tf.add(dir, OS.path.join(root, name), recursive = False)
   for lister in listers:
   for lister in listers:
-    base = OS.path.basename(dir)
     for file in lister(dir):
     for file in lister(dir):
-      tf.add(OS.path.join(dir, file), OS.path.join(root, base, file),
-             recursive = False)
+      full = OS.path.join(dir, file)
+      tarname = OS.path.join(root, name, file)
+      skip = False
+      if OS.path.islink(full):
+        dest = OS.path.realpath(full)
+        for d, local in dirmap:
+          if dest.startswith(d):
+            fix = OS.path.relpath(OS.path.join('/', local, dest[len(d):]),
+                                  OS.path.join('/', name,
+                                               OS.path.dirname(file)))
+            st = OS.stat(full)
+            ti = tf.gettarinfo(full, tarname)
+            ti.linkname = fix
+            tf.addfile(ti)
+            skip = True
+      if not skip:
+        tf.add(full, tarname, recursive = False)
 
 def source(out):
   if SYS.version_info >= (2, 6):
 
 def source(out):
   if SYS.version_info >= (2, 6):
@@ -105,8 +126,32 @@ def source(out):
   else:
     tf = TAR.open(fileobj = out, mode = 'w|gz')
     tf.posix = True
   else:
     tf = TAR.open(fileobj = out, mode = 'w|gz')
     tf.posix = True
-  for d in dirs_to_dump():
-    dump_dir(d, tf, '%s-%s' % (PACKAGE, VERSION))
+  root = '%s-%s' % (PACKAGE, VERSION)
+  seen = set()
+  dirmap = []
+  festout = StringIO()
+  for dir in dirs_to_dump():
+    dir = dir.rstrip('/')
+    base = OS.path.basename(dir)
+    if base not in seen:
+      name = base
+    else:
+      for i in I.count():
+        name = '%s.%d' % (base, i)
+        if name not in seen: break
+    dirmap.append((dir + '/', name))
+    festout.write('%s = %s\n' % (name, dir))
+  fest = festout.getvalue()
+  ti = TAR.TarInfo(OS.path.join(root, 'MANIFEST'))
+  ti.size = len(fest)
+  ti.mtime = T.time()
+  ti.mode = 0664
+  ti.type = TAR.REGTYPE
+  uid = OS.getuid(); ti.uid, ti.uname = uid, PW.getpwuid(uid).pw_name
+  gid = OS.getgid(); ti.gid, ti.gname = gid, GR.getgrgid(gid).gr_name
+  tf.addfile(ti, fileobj = StringIO(fest))
+  for dir, name in dirmap:
+    dump_dir(name, dir, dirmap, tf, root)
   tf.close()
 
 ###----- That's all, folks --------------------------------------------------
   tf.close()
 
 ###----- That's all, folks --------------------------------------------------