comparison mxtool/mx.py @ 14964:e1ce6c66f56e

refactored archive command to use "with" statement
author Doug Simon <doug.simon@oracle.com>
date Thu, 03 Apr 2014 20:53:52 +0200
parents 82971f397b94
children 858d2b91c1f8
comparison
equal deleted inserted replaced
14963:0c2e34446bd7 14964:e1ce6c66f56e
63 class Distribution: 63 class Distribution:
64 def __init__(self, suite, name, path, sourcesPath, deps, excludedLibs): 64 def __init__(self, suite, name, path, sourcesPath, deps, excludedLibs):
65 self.suite = suite 65 self.suite = suite
66 self.name = name 66 self.name = name
67 self.path = path.replace('/', os.sep) 67 self.path = path.replace('/', os.sep)
68 self.sourcesPath = sourcesPath.replace('/', os.sep) if sourcesPath else None 68 self.path = _make_absolute(self.path, suite.dir)
69 if not isabs(self.path): 69 self.sourcesPath = _make_absolute(sourcesPath.replace('/', os.sep), suite.dir) if sourcesPath else None
70 self.path = join(suite.dir, self.path)
71 self.deps = deps 70 self.deps = deps
72 self.update_listeners = set() 71 self.update_listeners = set()
73 self.excludedLibs = excludedLibs 72 self.excludedLibs = excludedLibs
74 73
75 def sorted_deps(self, includeLibs=False): 74 def sorted_deps(self, includeLibs=False):
357 with open(currentApsFile, 'w') as fp: 356 with open(currentApsFile, 'w') as fp:
358 for ap in aps: 357 for ap in aps:
359 print >> fp, ap 358 print >> fp, ap
360 return outOfDate 359 return outOfDate
361 360
361 def _make_absolute(path, prefix):
362 """
363 Makes 'path' absolute if it isn't already by prefixing 'prefix'
364 """
365 if not isabs(path):
366 return join(prefix, path)
367 return path
368
362 def _download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False): 369 def _download_file_with_sha1(name, path, urls, sha1, sha1path, resolve, mustExist, sources=False):
363 def _download_lib(): 370 def _download_lib():
364 print 'Downloading ' + ("Sources " if sources else "") + name + ' from ' + str(urls) 371 print 'Downloading ' + ("Sources " if sources else "") + name + ' from ' + str(urls)
365 download(path, urls) 372 download(path, urls)
366 373
427 return result 434 return result
428 return not result 435 return not result
429 436
430 437
431 def get_path(self, resolve): 438 def get_path(self, resolve):
432 path = self.path 439 path = _make_absolute(self.path, self.suite.dir)
433 if not isabs(path):
434 path = join(self.suite.dir, path)
435 sha1path = path + '.sha1' 440 sha1path = path + '.sha1'
436 441
437 includedInJDK = getattr(self, 'includedInJDK', None) 442 includedInJDK = getattr(self, 'includedInJDK', None)
438 if includedInJDK and java().javaCompliance >= JavaCompliance(includedInJDK): 443 if includedInJDK and java().javaCompliance >= JavaCompliance(includedInJDK):
439 return None 444 return None
440 445
441 return _download_file_with_sha1(self.name, path, self.urls, self.sha1, sha1path, resolve, self.mustExist) 446 return _download_file_with_sha1(self.name, path, self.urls, self.sha1, sha1path, resolve, self.mustExist)
442 447
443 448
444 def get_source_path(self, resolve): 449 def get_source_path(self, resolve):
445 path = self.sourcePath 450 if self.path is None:
446 if path is None:
447 return None 451 return None
448 if not isabs(path): 452 path = _make_absolute(self.path, self.suite.dir)
449 path = join(self.suite.dir, path)
450 sha1path = path + '.sha1' 453 sha1path = path + '.sha1'
451 454
452 return _download_file_with_sha1(self.name, path, self.sourceUrls, self.sourceSha1, sha1path, resolve, len(self.sourceUrls) != 0, sources=True) 455 return _download_file_with_sha1(self.name, path, self.sourceUrls, self.sourceSha1, sha1path, resolve, len(self.sourceUrls) != 0, sources=True)
453 456
454 def append_to_classpath(self, cp, resolve): 457 def append_to_classpath(self, cp, resolve):
2166 """create jar files for projects and distributions""" 2169 """create jar files for projects and distributions"""
2167 parser = ArgumentParser(prog='mx archive') 2170 parser = ArgumentParser(prog='mx archive')
2168 parser.add_argument('names', nargs=REMAINDER, metavar='[<project>|@<distribution>]...') 2171 parser.add_argument('names', nargs=REMAINDER, metavar='[<project>|@<distribution>]...')
2169 args = parser.parse_args(args) 2172 args = parser.parse_args(args)
2170 2173
2174
2175 class Archive:
2176 def __init__(self, path):
2177 self.path = path
2178
2179 def __enter__(self):
2180 if self.path:
2181 fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(self.path) + '.', dir=dirname(self.path))
2182 self.tmpFd = fd
2183 self.tmpPath = tmp
2184 self.zf = zipfile.ZipFile(tmp, 'w')
2185 else:
2186 self.tmpFd = None
2187 self.tmpPath = None
2188 self.zf = None
2189 return self
2190
2191 def __exit__(self, exc_type, exc_value, traceback):
2192 if self.zf:
2193 self.zf.close()
2194 os.close(self.tmpFd)
2195 # Correct the permissions on the temporary file which is created with restrictive permissions
2196 os.chmod(self.tmpPath, 0o666 & ~currentUmask)
2197 # Atomic on Unix
2198 shutil.move(self.tmpPath, self.path)
2199
2171 archives = [] 2200 archives = []
2172 for name in args.names: 2201 for name in args.names:
2173 if name.startswith('@'): 2202 if name.startswith('@'):
2174 dname = name[1:] 2203 dname = name[1:]
2175 d = distribution(dname) 2204 d = distribution(dname)
2176 fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(d.path) + '.', dir=dirname(d.path)) 2205 with Archive(d.path) as arc, Archive(d.sourcesPath) as srcArc:
2177 if d.sourcesPath: 2206 services = {}
2178 sourcesFd, sourcesTmp = tempfile.mkstemp(suffix='', prefix=basename(d.sourcesPath) + '.', dir=dirname(d.sourcesPath)) 2207 def overwriteCheck(zf, arcname, source):
2179 else: 2208 if arcname in zf.namelist():
2180 sourcesTmp = None 2209 log('warning: ' + d.path + ': overwriting ' + arcname + ' [source: ' + source + ']')
2181 services = tempfile.mkdtemp(suffix='', prefix=basename(d.path) + '.', dir=dirname(d.path)) 2210
2182
2183 def overwriteCheck(zf, arcname, source):
2184 if arcname in zf.namelist():
2185 log('warning: ' + d.path + ': overwriting ' + arcname + ' [source: ' + source + ']')
2186
2187 try:
2188 zf = zipfile.ZipFile(tmp, 'w')
2189 szf = zipfile.ZipFile(sourcesTmp, 'w') if sourcesTmp else None
2190 for dep in d.sorted_deps(includeLibs=True): 2211 for dep in d.sorted_deps(includeLibs=True):
2191 if dep.isLibrary(): 2212 if dep.isLibrary():
2192 l = dep 2213 l = dep
2193 # merge library jar into distribution jar 2214 # merge library jar into distribution jar
2194 logv('[' + d.path + ': adding library ' + l.name + ']') 2215 logv('[' + d.path + ': adding library ' + l.name + ']')
2196 libSourcePath = l.get_source_path(resolve=True) 2217 libSourcePath = l.get_source_path(resolve=True)
2197 if lpath: 2218 if lpath:
2198 with zipfile.ZipFile(lpath, 'r') as lp: 2219 with zipfile.ZipFile(lpath, 'r') as lp:
2199 for arcname in lp.namelist(): 2220 for arcname in lp.namelist():
2200 if arcname.startswith('META-INF/services/') and not arcname == 'META-INF/services/': 2221 if arcname.startswith('META-INF/services/') and not arcname == 'META-INF/services/':
2201 f = arcname[len('META-INF/services/'):].replace('/', os.sep) 2222 service = arcname[len('META-INF/services/'):]
2202 with open(join(services, f), 'a') as outfile: 2223 assert '/' not in service
2203 for line in lp.read(arcname).splitlines(): 2224 services.setdefault(service, []).extend(lp.read(arcname).splitlines())
2204 outfile.write(line)
2205 else: 2225 else:
2206 overwriteCheck(zf, arcname, lpath + '!' + arcname) 2226 overwriteCheck(arc.zf, arcname, lpath + '!' + arcname)
2207 zf.writestr(arcname, lp.read(arcname)) 2227 arc.zf.writestr(arcname, lp.read(arcname))
2208 if szf and libSourcePath: 2228 if srcArc.zf and libSourcePath:
2209 with zipfile.ZipFile(libSourcePath, 'r') as lp: 2229 with zipfile.ZipFile(libSourcePath, 'r') as lp:
2210 for arcname in lp.namelist(): 2230 for arcname in lp.namelist():
2211 overwriteCheck(szf, arcname, lpath + '!' + arcname) 2231 overwriteCheck(srcArc.zf, arcname, lpath + '!' + arcname)
2212 szf.writestr(arcname, lp.read(arcname)) 2232 srcArc.zf.writestr(arcname, lp.read(arcname))
2213 else: 2233 else:
2214 p = dep 2234 p = dep
2215 # skip a Java project if its Java compliance level is "higher" than the configured JDK 2235 # skip a Java project if its Java compliance level is "higher" than the configured JDK
2216 jdk = java(p.javaCompliance) 2236 jdk = java(p.javaCompliance)
2217 if not jdk: 2237 if not jdk:
2221 logv('[' + d.path + ': adding project ' + p.name + ']') 2241 logv('[' + d.path + ': adding project ' + p.name + ']')
2222 outputDir = p.output_dir() 2242 outputDir = p.output_dir()
2223 for root, _, files in os.walk(outputDir): 2243 for root, _, files in os.walk(outputDir):
2224 relpath = root[len(outputDir) + 1:] 2244 relpath = root[len(outputDir) + 1:]
2225 if relpath == join('META-INF', 'services'): 2245 if relpath == join('META-INF', 'services'):
2226 for f in files: 2246 for service in files:
2227 with open(join(services, f), 'a') as outfile: 2247 with open(join(root, service), 'r') as fp:
2228 with open(join(root, f), 'r') as infile: 2248 services.setdefault(service, []).extend([provider.strip() for provider in fp.readlines()])
2229 for line in infile:
2230 outfile.write(line)
2231 elif relpath == join('META-INF', 'providers'): 2249 elif relpath == join('META-INF', 'providers'):
2232 for f in files: 2250 for provider in files:
2233 with open(join(root, f), 'r') as infile: 2251 with open(join(root, provider), 'r') as fp:
2234 for line in infile: 2252 for service in fp:
2235 with open(join(services, line.strip()), 'a') as outfile: 2253 services.setdefault(service.strip(), []).append(provider)
2236 outfile.write(f + '\n')
2237 else: 2254 else:
2238 for f in files: 2255 for f in files:
2239 arcname = join(relpath, f).replace(os.sep, '/') 2256 arcname = join(relpath, f).replace(os.sep, '/')
2240 overwriteCheck(zf, arcname, join(root, f)) 2257 overwriteCheck(arc.zf, arcname, join(root, f))
2241 zf.write(join(root, f), arcname) 2258 arc.zf.write(join(root, f), arcname)
2242 if szf: 2259 if srcArc.zf:
2243 for srcDir in p.source_dirs(): 2260 for srcDir in p.source_dirs():
2244 for root, _, files in os.walk(srcDir): 2261 for root, _, files in os.walk(srcDir):
2245 relpath = root[len(srcDir) + 1:] 2262 relpath = root[len(srcDir) + 1:]
2246 for f in files: 2263 for f in files:
2247 if f.endswith('.java'): 2264 if f.endswith('.java'):
2248 arcname = join(relpath, f).replace(os.sep, '/') 2265 arcname = join(relpath, f).replace(os.sep, '/')
2249 overwriteCheck(szf, arcname, join(root, f)) 2266 overwriteCheck(srcArc.zf, arcname, join(root, f))
2250 szf.write(join(root, f), arcname) 2267 srcArc.zf.write(join(root, f), arcname)
2251 2268
2252 for f in os.listdir(services): 2269 for service, providers in services.iteritems():
2253 arcname = join('META-INF', 'services', f).replace(os.sep, '/') 2270 arcname = 'META-INF/services/' + service
2254 zf.write(join(services, f), arcname) 2271 arc.zf.writestr(arcname, '\n'.join(providers))
2255 zf.close() 2272
2256 os.close(fd) 2273 d.notify_updated()
2257 shutil.rmtree(services) 2274 archives.append(d.path)
2258 # Atomic on Unix
2259 shutil.move(tmp, d.path)
2260 # Correct the permissions on the temporary file which is created with restrictive permissions
2261 os.chmod(d.path, 0o666 & ~currentUmask)
2262 archives.append(d.path)
2263
2264 if szf:
2265 szf.close()
2266 os.close(sourcesFd)
2267 shutil.move(sourcesTmp, d.sourcesPath)
2268 os.chmod(d.sourcesPath, 0o666 & ~currentUmask)
2269
2270 d.notify_updated()
2271 finally:
2272 if exists(tmp):
2273 os.remove(tmp)
2274 if exists(services):
2275 shutil.rmtree(services)
2276 2275
2277 else: 2276 else:
2278 p = project(name) 2277 p = project(name)
2279 outputDir = p.output_dir() 2278 outputDir = p.output_dir()
2280 fd, tmp = tempfile.mkstemp(suffix='', prefix=p.name, dir=p.dir) 2279 with Archive(join(p.dir, p.name + '.jar')) as arc:
2281 try:
2282 zf = zipfile.ZipFile(tmp, 'w')
2283 for root, _, files in os.walk(outputDir): 2280 for root, _, files in os.walk(outputDir):
2284 for f in files: 2281 for f in files:
2285 relpath = root[len(outputDir) + 1:] 2282 relpath = root[len(outputDir) + 1:]
2286 arcname = join(relpath, f).replace(os.sep, '/') 2283 arcname = join(relpath, f).replace(os.sep, '/')
2287 zf.write(join(root, f), arcname) 2284 arc.zf.write(join(root, f), arcname)
2288 zf.close() 2285 archives.append(arc.path)
2289 os.close(fd) 2286
2290 # Atomic on Unix
2291 jarFile = join(p.dir, p.name + '.jar')
2292 shutil.move(tmp, jarFile)
2293 # Correct the permissions on the temporary file which is created with restrictive permissions
2294 os.chmod(jarFile, 0o666 & ~currentUmask)
2295 archives.append(jarFile)
2296 finally:
2297 if exists(tmp):
2298 os.remove(tmp)
2299 return archives 2287 return archives
2300 2288
2301 def canonicalizeprojects(args): 2289 def canonicalizeprojects(args):
2302 """process all project files to canonicalize the dependencies 2290 """process all project files to canonicalize the dependencies
2303 2291
2878 path = dep.path 2866 path = dep.path
2879 dep.get_path(resolve=True) 2867 dep.get_path(resolve=True)
2880 if not path or (not exists(path) and not dep.mustExist): 2868 if not path or (not exists(path) and not dep.mustExist):
2881 continue 2869 continue
2882 2870
2883 if not isabs(path): 2871 # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
2884 # Relative paths for "lib" class path entries have various semantics depending on the Eclipse 2872 # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
2885 # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's 2873 # safest to simply use absolute paths.
2886 # safest to simply use absolute paths. 2874 path = _make_absolute(path, p.suite.dir)
2887 path = join(p.suite.dir, path)
2888 2875
2889 attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path} 2876 attributes = {'exported' : 'true', 'kind' : 'lib', 'path' : path}
2890 2877
2891 sourcePath = dep.get_source_path(resolve=True) 2878 sourcePath = dep.get_source_path(resolve=True)
2892 if sourcePath is not None: 2879 if sourcePath is not None:
3037 if dep.isLibrary(): 3024 if dep.isLibrary():
3038 if not hasattr(dep, 'eclipse.container') and not hasattr(dep, 'eclipse.project'): 3025 if not hasattr(dep, 'eclipse.container') and not hasattr(dep, 'eclipse.project'):
3039 if dep.mustExist: 3026 if dep.mustExist:
3040 path = dep.get_path(resolve=True) 3027 path = dep.get_path(resolve=True)
3041 if path: 3028 if path:
3042 if not isabs(path): 3029 # Relative paths for "lib" class path entries have various semantics depending on the Eclipse
3043 # Relative paths for "lib" class path entries have various semantics depending on the Eclipse 3030 # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's
3044 # version being used (e.g. see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274737) so it's 3031 # safest to simply use absolute paths.
3045 # safest to simply use absolute paths. 3032 path = _make_absolute(path, p.suite.dir)
3046 path = join(p.suite.dir, path)
3047 out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'}) 3033 out.element('factorypathentry', {'kind' : 'EXTJAR', 'id' : path, 'enabled' : 'true', 'runInBatchMode' : 'false'})
3048 files.append(path) 3034 files.append(path)
3049 else: 3035 else:
3050 out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'}) 3036 out.element('factorypathentry', {'kind' : 'WKSPJAR', 'id' : '/' + dep.name + '/' + dep.name + '.jar', 'enabled' : 'true', 'runInBatchMode' : 'false'})
3051 out.close('factorypath') 3037 out.close('factorypath')