--- 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