wscript
changeset 2622 6440851b111a
parent 2345 79f77914c31c
child 2846 7689461231ac
--- a/wscript	Sat Mar 15 23:25:13 2008 +0100
+++ b/wscript	Sun Mar 16 14:35:32 2008 +0000
@@ -458,3 +458,117 @@
     finally:
         os.chdir("..")
 
+
+
+
+##
+## The default WAF DistDir implementation is rather slow, because it
+## first copies everything and only later removes unwanted files and
+## directories; this means that it needless copies the full build dir
+## and the .hg repository tree.  Here we provide a replacement DistDir
+## implementation that is more efficient.
+##
+import Scripting
+from Scripting import g_dist_exts, g_excludes, BLDDIR
+import Utils
+import os
+
+def copytree(src, dst, symlinks=False, excludes=(), build_dir=None):
+    """Recursively copy a directory tree using copy2().
+
+    The destination directory must not already exist.
+    If exception(s) occur, an Error is raised with a list of reasons.
+
+    If the optional symlinks flag is true, symbolic links in the
+    source tree result in symbolic links in the destination tree; if
+    it is false, the contents of the files pointed to by symbolic
+    links are copied.
+
+    XXX Consider this example code rather than the ultimate tool.
+
+    Note: this is a modified version of shutil.copytree from python
+    2.5.2 library; modified for WAF purposes to exclude dot dirs and
+    another list of files.
+    """
+    names = os.listdir(src)
+    os.makedirs(dst)
+    errors = []
+    for name in names:
+        srcname = os.path.join(src, name)
+        dstname = os.path.join(dst, name)
+        try:
+            if symlinks and os.path.islink(srcname):
+                linkto = os.readlink(srcname)
+                os.symlink(linkto, dstname)
+            elif os.path.isdir(srcname):
+                if name in excludes:
+                    continue
+                elif name.startswith('.') or name.startswith(',,') or name.startswith('++'):
+                    continue
+                elif name == build_dir:
+                    continue
+                else:
+                    ## build_dir is not passed into the recursive
+                    ## copytree, but that is intentional; it is a
+                    ## directory name valid only at the top level.
+                    copytree(srcname, dstname, symlinks, excludes)
+            else:
+                ends = name.endswith
+                to_remove = False
+                if name.startswith('.') or name.startswith('++'):
+                    to_remove = True
+                else:
+                    for x in g_dist_exts:
+                        if ends(x):
+                            to_remove = True
+                            break
+                if not to_remove:
+                    shutil.copy2(srcname, dstname)
+            # XXX What about devices, sockets etc.?
+        except (IOError, os.error), why:
+            errors.append((srcname, dstname, str(why)))
+        # catch the Error from the recursive copytree so that we can
+        # continue with other files
+        except shutil.Error, err:
+            errors.extend(err.args[0])
+    try:
+        shutil.copystat(src, dst)
+    except WindowsError:
+        # can't copy file access times on Windows
+        pass
+    except OSError, why:
+        errors.extend((src, dst, str(why)))
+    if errors:
+        raise shutil.Error, errors
+
+
+def DistDir(appname, version):
+    "make a distribution directory with all the sources in it"
+    import shutil
+
+    # Our temporary folder where to put our files
+    TMPFOLDER=appname+'-'+version
+
+    # Remove an old package directory
+    if os.path.exists(TMPFOLDER): shutil.rmtree(TMPFOLDER)
+
+    global g_dist_exts, g_excludes
+
+    # Remove the Build dir
+    build_dir = getattr(Utils.g_module, BLDDIR, None)
+
+    # Copy everything into the new folder
+    copytree('.', TMPFOLDER, excludes=g_excludes, build_dir=build_dir)
+
+    # TODO undocumented hook
+    dist_hook = getattr(Utils.g_module, 'dist_hook', None)
+    if dist_hook:
+        os.chdir(TMPFOLDER)
+        try:
+            dist_hook()
+        finally:
+            # go back to the root directory
+            os.chdir('..')
+    return TMPFOLDER
+
+Scripting.DistDir = DistDir