1 |
# AccumulateBuilder |
2 |
# |
3 |
# Based on code from http://www.scons.org/wiki/AccumulateBuilder |
4 |
# |
5 |
# Converted to SCons 'tool' format by John Pye, 10 Sept 2007. |
6 |
|
7 |
import os, os.path, shutil |
8 |
|
9 |
def copypackaged(src,dest, symlinks=False): |
10 |
"""Recursive copy of files listed in a local file named PACKAGE |
11 |
|
12 |
Look in the current directory for a file named PACKAGE. If found, |
13 |
copy the files listed there. |
14 |
|
15 |
Then recurse into subdirectories. |
16 |
|
17 |
Behaviour is intended to facilitate packaging of a user-contributed |
18 |
code library, where many files are 'experimental' but some files are |
19 |
tested and intended to distribution. Suitable for software plugins, |
20 |
code examples, documentation fragments, etc. |
21 |
""" |
22 |
|
23 |
print "Entering directory '%s'" % src |
24 |
|
25 |
files = os.listdir(src) |
26 |
|
27 |
pfiles = [] |
28 |
if 'PACKAGE' in files: |
29 |
plistfile = os.path.join(src,'PACKAGE') |
30 |
plist = file(plistfile) |
31 |
for line in plist: |
32 |
l = line.strip() |
33 |
if l[0]=="#": |
34 |
continue |
35 |
if l in files: |
36 |
if os.path.isdir(os.path.join(src,l)): |
37 |
print "Package file '%s' ignored (is a directory)" % l |
38 |
continue |
39 |
print "Package '%s'" % l |
40 |
pfiles.append(l) |
41 |
else: |
42 |
print "Not found: '%s'" % l |
43 |
|
44 |
# copy any listed files in the current directory first |
45 |
if pfiles: |
46 |
if not os.path.exists(dest): |
47 |
os.makedirs(dest) |
48 |
for f in pfiles: |
49 |
srcPath = os.path.join(src, f) |
50 |
if os.path.islink(srcPath) and symlinks: |
51 |
linkto = os.readlink(f) |
52 |
os.symlink(linkto, dest) |
53 |
else: |
54 |
shutil.copy2(srcPath, dest) |
55 |
|
56 |
# now recurse into subdirectories |
57 |
for f in files: |
58 |
srcPath = os.path.join(src, f) |
59 |
if os.path.isdir(srcPath): |
60 |
# a directory must be recursed into, but defer creating the dir |
61 |
srcBasename = os.path.basename(srcPath) |
62 |
destDirPath = os.path.join(dest, srcBasename) |
63 |
copypackaged(srcPath, destDirPath, symlinks) |
64 |
|
65 |
print "Leaving directory '%s'" % src |
66 |
|
67 |
|
68 |
def copytree(src, dest, symlinks=False): |
69 |
"""My own copyTree which does not fail if the directory exists. |
70 |
|
71 |
Recursively copy a directory tree using copy2(). |
72 |
|
73 |
If the optional symlinks flag is true, symbolic links in the |
74 |
source tree result in symbolic links in the destination tree; if |
75 |
it is false, the contents of the files pointed to by symbolic |
76 |
links are copied. |
77 |
|
78 |
Behavior is meant to be identical to GNU 'cp -R'. |
79 |
""" |
80 |
def copyItems(src, dest, symlinks=False): |
81 |
"""Function that does all the work. |
82 |
|
83 |
It is necessary to handle the two 'cp' cases: |
84 |
- destination does exist |
85 |
- destination does not exist |
86 |
|
87 |
See 'cp -R' documentation for more details |
88 |
""" |
89 |
files = os.listdir(src) |
90 |
if 'PACKAGE' in files: |
91 |
copypackaged(src,dest,symlinks) |
92 |
return |
93 |
|
94 |
for item in files: |
95 |
srcPath = os.path.join(src, item) |
96 |
if os.path.isdir(srcPath): |
97 |
srcBasename = os.path.basename(srcPath) |
98 |
destDirPath = os.path.join(dest, srcBasename) |
99 |
if not os.path.exists(destDirPath): |
100 |
os.makedirs(destDirPath) |
101 |
copyItems(srcPath, destDirPath |
102 |
, use_package_list=use_package_list |
103 |
) |
104 |
elif os.path.islink(item) and symlinks: |
105 |
linkto = os.readlink(item) |
106 |
os.symlink(linkto, dest) |
107 |
else: |
108 |
shutil.copy2(srcPath, dest) |
109 |
|
110 |
|
111 |
# case 'cp -R src/ dest/' where dest/ already exists |
112 |
if os.path.exists(dest): |
113 |
destPath = os.path.join(dest, os.path.basename(src)) |
114 |
if not os.path.exists(destPath): |
115 |
os.makedirs(destPath) |
116 |
# case 'cp -R src/ dest/' where dest/ does not exist |
117 |
else: |
118 |
os.makedirs(dest) |
119 |
destPath = dest |
120 |
# actually copy the files |
121 |
copyItems(src, destPath) |
122 |
|
123 |
|
124 |
## |
125 |
## AccumulatorAction.py |
126 |
## |
127 |
|
128 |
def accumulatorFunction(target, source, env): |
129 |
"""Function called when builder is called""" |
130 |
destDir = str(target[0]) |
131 |
if not os.path.exists(destDir): |
132 |
os.makedirs(destDir) |
133 |
for s in source: |
134 |
s = str(s) |
135 |
if os.path.isdir(s): |
136 |
myShutil.copytree(s, destDir, symlinks = False) |
137 |
else: |
138 |
shutil.copy2(s, destDir) |
139 |
|
140 |
|
141 |
## |
142 |
## Zipper.py |
143 |
## |
144 |
import distutils.archive_util |
145 |
|
146 |
def zipperFunction(target, source, env): |
147 |
"""Function to use as an action which creates a ZIP file from the arguments""" |
148 |
targetName = str(target[0]) |
149 |
sourceDir = str(source[0]) |
150 |
distutils.archive_util.make_archive(targetName, 'zip', sourceDir) |
151 |
|
152 |
|
153 |
## |
154 |
## register the above builders... |
155 |
## |
156 |
|
157 |
def generate(env): |
158 |
|
159 |
# add builder to accumulate files |
160 |
accuBuilder = env.Builder(action=AccumulatorAction.accumulatorFunction, |
161 |
source_factory=SCons.Node.FS.default_fs.Entry, |
162 |
target_factory=SCons.Node.FS.default_fs.Entry, |
163 |
multi=1) |
164 |
env['BUILDERS']['Accumulate'] = accuBuilder |
165 |
|
166 |
# add builder to zip files |
167 |
zipBuilder = env.Builder(action=Zipper.zipperFunction, |
168 |
source_factory=SCons.Node.FS.default_fs.Entry, |
169 |
target_factory=SCons.Node.FS.default_fs.Entry, |
170 |
multi=0) |
171 |
env['BUILDERS']['Zipper'] = zipBuilder |
172 |
|
173 |
def exists(env): |
174 |
""" |
175 |
Make sure this tool exists. |
176 |
""" |
177 |
try: |
178 |
import distutils.archive_util |
179 |
import shutil |
180 |
import os, os.path |
181 |
except ImportError: |
182 |
return False |
183 |
else: |
184 |
return True |
185 |
|