/[ascend]/trunk/scons/accumulate.py
ViewVC logotype

Contents of /trunk/scons/accumulate.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1633 - (show annotations) (download) (as text)
Thu Oct 11 14:14:24 2007 UTC (12 years, 4 months ago) by jpye
File MIME type: text/x-python
File size: 5956 byte(s)
More work on AccumulateBuilder
1 # Accumulate
2 #
3 # Based on code from http://www.scons.org/wiki/AccumulateBuilder
4
5 # The goal here was to be able to distribute a source code tarball that
6 # contains all the required source code to build our program, plus a LIMITED
7 # subset of our test/sample code, because we have many sample files that are
8 # not yet ready for distribution. We wanted to manage our list of distributable
9 # files using a simple plain text-file system that would be informative to
10 # end users and not tied to a particular build system (SCons).
11
12 # This tool faciltates creation of tarballs with some files excluded using
13 # a convenient text-file based mechanism. By default, the tool collects copies
14 # of the files you list using the syntax below, and places them in your
15 # 'destination' directory:
16 #
17 # env.Accumulate('dist/temp/src',"src")
18 # env.Accumulate('dist/temp',['prog1.exe','prog2.exe'])
19 #
20 # There is a special exception however. If, while recursing into directories
21 # listed in the Accumulate source list, a file named 'PACKAGE' is found, then
22 # only files listed therein will be copied to the destination directory.
23 # The 'PACKAGE' file can contain comment lines; they must begin with a '#'.
24 # Once a directory has been found to contain a 'PACKAGE' file, subdirectories
25 # of that directory will not be recursed into unless they also contain a
26 # 'PACKAGE' file.
27
28 # Converted to SCons 'tool' format by John Pye, 10 Sept 2007.
29
30 import os, os.path, shutil
31 import SCons.Node.FS
32
33 def copypackaged(src,dest, symlinks=False):
34 """Recursive copy of files listed in a local file named PACKAGE
35
36 Look in the current directory for a file named PACKAGE. If found,
37 copy the files listed there.
38
39 Then recurse into subdirectories.
40
41 Behaviour is intended to facilitate packaging of a user-contributed
42 code library, where many files are 'experimental' but some files are
43 tested and intended to distribution. Suitable for software plugins,
44 code examples, documentation fragments, etc.
45 """
46
47 print "Entering directory '%s'" % src
48
49 files = os.listdir(src)
50
51 pfiles = []
52 if 'PACKAGE' in files:
53 plistfile = os.path.join(src,'PACKAGE')
54 plist = file(plistfile)
55 for line in plist:
56 l = line.strip()
57 if not len(l) or l[0]=="#":
58 continue
59 if l in files:
60 if os.path.isdir(os.path.join(src,l)):
61 print "Package file '%s' ignored (is a directory)" % l
62 continue
63 print "Package '%s'" % l
64 pfiles.append(l)
65 else:
66 print "Not found: '%s'" % l
67
68 # copy any listed files in the current directory first
69 if pfiles:
70 if not os.path.exists(dest):
71 os.makedirs(dest)
72 for f in pfiles:
73 srcPath = os.path.join(src, f)
74 if os.path.islink(srcPath) and symlinks:
75 linkto = os.readlink(f)
76 os.symlink(linkto, dest)
77 else:
78 shutil.copy2(srcPath, dest)
79
80 # now recurse into subdirectories
81 for f in files:
82 srcPath = os.path.join(src, f)
83 if os.path.isdir(srcPath):
84 # a directory must be recursed into, but defer creating the dir
85 srcBasename = os.path.basename(srcPath)
86 destDirPath = os.path.join(dest, srcBasename)
87 copypackaged(srcPath, destDirPath, symlinks)
88
89 print "Leaving directory '%s'" % src
90
91
92 def my_copytree(src, dest, env, symlinks=False):
93 """My own copyTree which does not fail if the directory exists.
94
95 Recursively copy a directory tree using copy2().
96
97 If the optional symlinks flag is true, symbolic links in the
98 source tree result in symbolic links in the destination tree; if
99 it is false, the contents of the files pointed to by symbolic
100 links are copied.
101
102 Behavior is meant to be identical to GNU 'cp -R'.
103 """
104 def copyItems(src, dest, symlinks=False):
105 """Function that does all the work.
106
107 It is necessary to handle the two 'cp' cases:
108 - destination does exist
109 - destination does not exist
110
111 See 'cp -R' documentation for more details
112 """
113 files = os.listdir(src)
114 if 'PACKAGE' in files:
115 copypackaged(src,dest,symlinks)
116 return
117
118 for item in files:
119 srcPath = os.path.join(src, item)
120 if os.path.isdir(srcPath):
121 print "DIR = %s" % srcPath
122 srcBasename = os.path.basename(srcPath)
123 destDirPath = os.path.join(dest, srcBasename)
124 if not os.path.exists(destDirPath):
125 #print "CREATE DIR %s" % destDirPath
126 os.makedirs(destDirPath)
127 #print "RECURSE INTO %s" % srcPath
128 copyItems(srcPath, destDirPath
129 , symlinks
130 )
131 elif os.path.islink(item) and symlinks:
132 print "LINK = %s" % srcPath
133 linkto = os.readlink(item)
134 os.symlink(linkto, dest)
135 else:
136 print "FILE = %s" % srcPath
137 shutil.copy2(srcPath, dest)
138
139 # case 'cp -R src/ dest/' where dest/ already exists
140 if os.path.exists(dest):
141 destPath = os.path.join(dest, os.path.basename(src))
142 if not os.path.exists(destPath):
143 os.makedirs(destPath)
144 # case 'cp -R src/ dest/' where dest/ does not exist
145 else:
146 os.makedirs(dest)
147 destPath = dest
148 # actually copy the files
149 copyItems(src, destPath)
150
151
152 ##
153 ## AccumulatorAction.py
154 ##
155
156 def accumulatorFunction(target, source, env):
157 """Function called when builder is called"""
158 destDir = str(target[0])
159 #print "DEST DIR = %s" % destDir
160 if not os.path.exists(destDir):
161 #print "CREATE DIR %s" % destDir
162 os.makedirs(destDir)
163 #print "SOURCES: %s" % source
164 for s in source:
165 s = str(s)
166 if os.path.isdir(s):
167 #print "COPYTREE from source %s" % s
168 my_copytree(s, destDir, env, symlinks = False)
169 else:
170 #print "COPY FILE from source %s" % s
171 shutil.copy2(s, destDir)
172
173 ##
174 ## register the above builders...
175 ##
176
177 def generate(env):
178
179 # add builder to accumulate files
180 accuBuilder = env.Builder(action=accumulatorFunction,
181 source_factory=SCons.Node.FS.default_fs.Entry,
182 target_factory=SCons.Node.FS.default_fs.Entry,
183 multi=1)
184 env['BUILDERS']['Accumulate'] = accuBuilder
185
186 def exists(env):
187 """
188 Make sure this tool exists.
189 """
190 try:
191 import distutils.archive_util
192 import shutil
193 import os, os.path
194 except ImportError:
195 return False
196 else:
197 return True
198

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22