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