Mercurial > hg > truffle
comparison mxtool/mx.py @ 15226:f1c66b738dae
mx: refactored archive command
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Fri, 18 Apr 2014 13:36:48 +0200 |
parents | 2c7b18ae25d2 |
children | 7be43cbf3568 |
comparison
equal
deleted
inserted
replaced
15225:aee7eeb554ad | 15226:f1c66b738dae |
---|---|
83 return self.name | 83 return self.name |
84 | 84 |
85 def add_update_listener(self, listener): | 85 def add_update_listener(self, listener): |
86 self.update_listeners.add(listener) | 86 self.update_listeners.add(listener) |
87 | 87 |
88 def make_archive(self): | |
89 # are sources combined into main archive? | |
90 unified = self.path == self.sourcesPath | |
91 | |
92 with Archiver(self.path) as arc, Archiver(None if unified else self.sourcesPath) as srcArcRaw: | |
93 srcArc = arc if unified else srcArcRaw | |
94 services = {} | |
95 def overwriteCheck(zf, arcname, source): | |
96 if not hasattr(zf, '_provenance'): | |
97 zf._provenance = {} | |
98 existingSource = zf._provenance.get(arcname, None) | |
99 if existingSource and existingSource != source and not arcname.endswith('/'): | |
100 log('warning: ' + self.path + ': overwriting ' + arcname + '\n new: ' + source + '\n old: ' + existingSource) | |
101 zf._provenance[arcname] = source | |
102 | |
103 for dep in self.sorted_deps(includeLibs=True): | |
104 if dep.isLibrary(): | |
105 l = dep | |
106 # merge library jar into distribution jar | |
107 logv('[' + self.path + ': adding library ' + l.name + ']') | |
108 lpath = l.get_path(resolve=True) | |
109 libSourcePath = l.get_source_path(resolve=True) | |
110 if lpath: | |
111 with zipfile.ZipFile(lpath, 'r') as lp: | |
112 for arcname in lp.namelist(): | |
113 if arcname.startswith('META-INF/services/') and not arcname == 'META-INF/services/': | |
114 service = arcname[len('META-INF/services/'):] | |
115 assert '/' not in service | |
116 services.setdefault(service, []).extend(lp.read(arcname).splitlines()) | |
117 else: | |
118 overwriteCheck(arc.zf, arcname, lpath + '!' + arcname) | |
119 arc.zf.writestr(arcname, lp.read(arcname)) | |
120 if srcArc.zf and libSourcePath: | |
121 with zipfile.ZipFile(libSourcePath, 'r') as lp: | |
122 for arcname in lp.namelist(): | |
123 overwriteCheck(srcArc.zf, arcname, lpath + '!' + arcname) | |
124 srcArc.zf.writestr(arcname, lp.read(arcname)) | |
125 else: | |
126 p = dep | |
127 # skip a Java project if its Java compliance level is "higher" than the configured JDK | |
128 jdk = java(p.javaCompliance) | |
129 if not jdk: | |
130 log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, self.path)) | |
131 continue | |
132 | |
133 logv('[' + self.path + ': adding project ' + p.name + ']') | |
134 outputDir = p.output_dir() | |
135 for root, _, files in os.walk(outputDir): | |
136 relpath = root[len(outputDir) + 1:] | |
137 if relpath == join('META-INF', 'services'): | |
138 for service in files: | |
139 with open(join(root, service), 'r') as fp: | |
140 services.setdefault(service, []).extend([provider.strip() for provider in fp.readlines()]) | |
141 elif relpath == join('META-INF', 'providers'): | |
142 for provider in files: | |
143 with open(join(root, provider), 'r') as fp: | |
144 for service in fp: | |
145 services.setdefault(service.strip(), []).append(provider) | |
146 else: | |
147 for f in files: | |
148 arcname = join(relpath, f).replace(os.sep, '/') | |
149 overwriteCheck(arc.zf, arcname, join(root, f)) | |
150 arc.zf.write(join(root, f), arcname) | |
151 if srcArc.zf: | |
152 sourceDirs = p.source_dirs() | |
153 for srcDir in sourceDirs: | |
154 for root, _, files in os.walk(srcDir): | |
155 relpath = root[len(srcDir) + 1:] | |
156 for f in files: | |
157 if f.endswith('.java'): | |
158 arcname = join(relpath, f).replace(os.sep, '/') | |
159 overwriteCheck(srcArc.zf, arcname, join(root, f)) | |
160 srcArc.zf.write(join(root, f), arcname) | |
161 | |
162 for service, providers in services.iteritems(): | |
163 arcname = 'META-INF/services/' + service | |
164 arc.zf.writestr(arcname, '\n'.join(providers)) | |
165 | |
166 self.notify_updated() | |
167 | |
168 | |
88 def notify_updated(self): | 169 def notify_updated(self): |
89 for l in self.update_listeners: | 170 for l in self.update_listeners: |
90 l(self) | 171 l(self) |
91 | 172 |
92 """ | 173 """ |
356 os.mkdir(dirname(currentApsFile)) | 437 os.mkdir(dirname(currentApsFile)) |
357 with open(currentApsFile, 'w') as fp: | 438 with open(currentApsFile, 'w') as fp: |
358 for ap in aps: | 439 for ap in aps: |
359 print >> fp, ap | 440 print >> fp, ap |
360 return outOfDate | 441 return outOfDate |
442 | |
443 def make_archive(self, path=None): | |
444 outputDir = self.output_dir() | |
445 if not path: | |
446 path = join(self.dir, self.name + '.jar') | |
447 with Archiver(path) as arc: | |
448 for root, _, files in os.walk(outputDir): | |
449 for f in files: | |
450 relpath = root[len(outputDir) + 1:] | |
451 arcname = join(relpath, f).replace(os.sep, '/') | |
452 arc.zf.write(join(root, f), arcname) | |
453 return path | |
361 | 454 |
362 def _make_absolute(path, prefix): | 455 def _make_absolute(path, prefix): |
363 """ | 456 """ |
364 Makes 'path' absolute if it isn't already by prefixing 'prefix' | 457 Makes 'path' absolute if it isn't already by prefixing 'prefix' |
365 """ | 458 """ |
2183 | 2276 |
2184 for pyfile in pyfiles: | 2277 for pyfile in pyfiles: |
2185 log('Running pylint on ' + pyfile + '...') | 2278 log('Running pylint on ' + pyfile + '...') |
2186 run(['pylint', '--reports=n', '--rcfile=' + rcfile, pyfile], env=env) | 2279 run(['pylint', '--reports=n', '--rcfile=' + rcfile, pyfile], env=env) |
2187 | 2280 |
2281 """ | |
2282 Utility for creating and updating a zip file atomically. | |
2283 """ | |
2284 class Archiver: | |
2285 def __init__(self, path): | |
2286 self.path = path | |
2287 | |
2288 def __enter__(self): | |
2289 if self.path: | |
2290 fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path)) | |
2291 self.tmpFd = fd | |
2292 self.tmpPath = tmp | |
2293 self.zf = zipfile.ZipFile(tmp, 'w') | |
2294 else: | |
2295 self.tmpFd = None | |
2296 self.tmpPath = None | |
2297 self.zf = None | |
2298 return self | |
2299 | |
2300 def __exit__(self, exc_type, exc_value, traceback): | |
2301 if self.zf: | |
2302 self.zf.close() | |
2303 os.close(self.tmpFd) | |
2304 # Correct the permissions on the temporary file which is created with restrictive permissions | |
2305 os.chmod(self.tmpPath, 0o666 & ~currentUmask) | |
2306 # Atomic on Unix | |
2307 shutil.move(self.tmpPath, self.path) | |
2308 | |
2188 def archive(args): | 2309 def archive(args): |
2189 """create jar files for projects and distributions""" | 2310 """create jar files for projects and distributions""" |
2190 parser = ArgumentParser(prog='mx archive') | 2311 parser = ArgumentParser(prog='mx archive') |
2191 parser.add_argument('names', nargs=REMAINDER, metavar='[<project>|@<distribution>]...') | 2312 parser.add_argument('names', nargs=REMAINDER, metavar='[<project>|@<distribution>]...') |
2192 args = parser.parse_args(args) | 2313 args = parser.parse_args(args) |
2193 | 2314 |
2194 | |
2195 class Archive: | |
2196 def __init__(self, path): | |
2197 self.path = path | |
2198 | |
2199 def __enter__(self): | |
2200 if self.path: | |
2201 fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path)) | |
2202 self.tmpFd = fd | |
2203 self.tmpPath = tmp | |
2204 self.zf = zipfile.ZipFile(tmp, 'w') | |
2205 else: | |
2206 self.tmpFd = None | |
2207 self.tmpPath = None | |
2208 self.zf = None | |
2209 return self | |
2210 | |
2211 def __exit__(self, exc_type, exc_value, traceback): | |
2212 if self.zf: | |
2213 self.zf.close() | |
2214 os.close(self.tmpFd) | |
2215 # Correct the permissions on the temporary file which is created with restrictive permissions | |
2216 os.chmod(self.tmpPath, 0o666 & ~currentUmask) | |
2217 # Atomic on Unix | |
2218 shutil.move(self.tmpPath, self.path) | |
2219 | |
2220 archives = [] | 2315 archives = [] |
2221 for name in args.names: | 2316 for name in args.names: |
2222 if name.startswith('@'): | 2317 if name.startswith('@'): |
2223 dname = name[1:] | 2318 dname = name[1:] |
2224 d = distribution(dname) | 2319 d = distribution(dname) |
2225 with Archive(d.path) as arc, Archive(d.sourcesPath) as srcArc: | 2320 d.make_archive() |
2226 services = {} | |
2227 def overwriteCheck(zf, arcname, source): | |
2228 if arcname in zf.namelist(): | |
2229 log('warning: ' + d.path + ': overwriting ' + arcname + ' [source: ' + source + ']') | |
2230 | |
2231 for dep in d.sorted_deps(includeLibs=True): | |
2232 if dep.isLibrary(): | |
2233 l = dep | |
2234 # merge library jar into distribution jar | |
2235 logv('[' + d.path + ': adding library ' + l.name + ']') | |
2236 lpath = l.get_path(resolve=True) | |
2237 libSourcePath = l.get_source_path(resolve=True) | |
2238 if lpath: | |
2239 with zipfile.ZipFile(lpath, 'r') as lp: | |
2240 for arcname in lp.namelist(): | |
2241 if arcname.startswith('META-INF/services/') and not arcname == 'META-INF/services/': | |
2242 service = arcname[len('META-INF/services/'):] | |
2243 assert '/' not in service | |
2244 services.setdefault(service, []).extend(lp.read(arcname).splitlines()) | |
2245 else: | |
2246 overwriteCheck(arc.zf, arcname, lpath + '!' + arcname) | |
2247 arc.zf.writestr(arcname, lp.read(arcname)) | |
2248 if srcArc.zf and libSourcePath: | |
2249 with zipfile.ZipFile(libSourcePath, 'r') as lp: | |
2250 for arcname in lp.namelist(): | |
2251 overwriteCheck(srcArc.zf, arcname, lpath + '!' + arcname) | |
2252 srcArc.zf.writestr(arcname, lp.read(arcname)) | |
2253 else: | |
2254 p = dep | |
2255 # skip a Java project if its Java compliance level is "higher" than the configured JDK | |
2256 jdk = java(p.javaCompliance) | |
2257 if not jdk: | |
2258 log('Excluding {0} from {2} (Java compliance level {1} required)'.format(p.name, p.javaCompliance, d.path)) | |
2259 continue | |
2260 | |
2261 logv('[' + d.path + ': adding project ' + p.name + ']') | |
2262 outputDir = p.output_dir() | |
2263 for root, _, files in os.walk(outputDir): | |
2264 relpath = root[len(outputDir) + 1:] | |
2265 if relpath == join('META-INF', 'services'): | |
2266 for service in files: | |
2267 with open(join(root, service), 'r') as fp: | |
2268 services.setdefault(service, []).extend([provider.strip() for provider in fp.readlines()]) | |
2269 elif relpath == join('META-INF', 'providers'): | |
2270 for provider in files: | |
2271 with open(join(root, provider), 'r') as fp: | |
2272 for service in fp: | |
2273 services.setdefault(service.strip(), []).append(provider) | |
2274 else: | |
2275 for f in files: | |
2276 arcname = join(relpath, f).replace(os.sep, '/') | |
2277 overwriteCheck(arc.zf, arcname, join(root, f)) | |
2278 arc.zf.write(join(root, f), arcname) | |
2279 if srcArc.zf: | |
2280 for srcDir in p.source_dirs(): | |
2281 for root, _, files in os.walk(srcDir): | |
2282 relpath = root[len(srcDir) + 1:] | |
2283 for f in files: | |
2284 if f.endswith('.java'): | |
2285 arcname = join(relpath, f).replace(os.sep, '/') | |
2286 overwriteCheck(srcArc.zf, arcname, join(root, f)) | |
2287 srcArc.zf.write(join(root, f), arcname) | |
2288 | |
2289 for service, providers in services.iteritems(): | |
2290 arcname = 'META-INF/services/' + service | |
2291 arc.zf.writestr(arcname, '\n'.join(providers)) | |
2292 | |
2293 d.notify_updated() | |
2294 archives.append(d.path) | 2321 archives.append(d.path) |
2295 | |
2296 else: | 2322 else: |
2297 p = project(name) | 2323 p = project(name) |
2298 outputDir = p.output_dir() | 2324 archives.append(p.make_archive()) |
2299 with Archive(join(p.dir, p.name + '.jar')) as arc: | |
2300 for root, _, files in os.walk(outputDir): | |
2301 for f in files: | |
2302 relpath = root[len(outputDir) + 1:] | |
2303 arcname = join(relpath, f).replace(os.sep, '/') | |
2304 arc.zf.write(join(root, f), arcname) | |
2305 archives.append(arc.path) | |
2306 | 2325 |
2307 return archives | 2326 return archives |
2308 | 2327 |
2309 def canonicalizeprojects(args): | 2328 def canonicalizeprojects(args): |
2310 """process all project files to canonicalize the dependencies | 2329 """process all project files to canonicalize the dependencies |