def run(self, context): mkdir(os.path.dirname(self.path)) alreadyDone = set() with zipfile.ZipFile(normLongPath(self.path), 'w') as output: for (f, o) in self.inputs.resolveWithDestinations(context): # if we don't check for duplicate entries we'll end up creating an invalid zip if o in alreadyDone: dupsrc = ['"%s"'%src for (src, dest) in self.inputs.resolveWithDestinations(context) if dest == o] raise BuildException('Duplicate zip entry "%s" from: %s'%(o, ', '.join(dupsrc))) alreadyDone.add(o) # can't compress directory entries! (it messes up Java) output.write(normLongPath(f).rstrip('/\\'), o, zipfile.ZIP_STORED if isDirPath(f) else zipfile.ZIP_DEFLATED)
def run(self, context): self.log.info('Cleaning existing files from %s', self.path) deleteDir(self.path) iswindows = IS_WINDOWS for a in self.archives: a_is_filteredarchivecontents = isinstance(a, FilteredArchiveContents) if a_is_filteredarchivecontents: items = [(a.getResolvedPath(context), '')] else: assert isinstance(a, BasePathSet) filteredMembers = None items = a.resolveWithDestinations(context) for (srcAbs, destRel) in items: if destRel and not isDirPath(destRel): destRel = os.path.dirname(destRel) # strip off the zip filename if '..' in destRel: raise Exception('This target does not permit destination paths to contain ".." relative path expressions') try: filesize = os.path.getsize(srcAbs) except Exception: filesize = 0 self.log.info("Unpacking %s (%0.1f MB) to %s", os.path.basename(srcAbs), filesize/1024.0/1024, self.name+destRel) starttime = time.time() with self. __openArchive(srcAbs) as f: mkdir(self.path+destRel) if a_is_filteredarchivecontents and a.hasIncludeExcludeFilters(): fullList = _getnames(f) if not fullList: raise BuildException('No files were found in archive "%s"'%(srcAbs)) filteredMembers = [x for x in fullList if a.isIncluded(context, x)] self.log.info("Unpacking %d of %d members in %s", len(filteredMembers), len(fullList), os.path.basename(srcAbs)) if not filteredMembers: raise BuildException('No files matching the specified include/exclude filters were found in archive "%s": %s'%(srcAbs, a)) if len(filteredMembers)==len(fullList): raise BuildException('No files were excluded from the unpacking operation by the specified filters (check filters are correct): %s'%a) else: filteredMembers = _getnames(f) # NB: some archive types want a list of string members, others want TarInfo objects etc, so # if we support other archive types in future might need to do a bit of work here path = normLongPath(self.path+destRel) for m in filteredMembers: if not isDirPath(m): info = _getinfo(f, m) if a_is_filteredarchivecontents: _setfilename(info, a.mapDestPath(context, _getfilename(info))) if iswindows: _setfilename(info, _getfilename(info).replace('/', '\\')) f.extract(info, path=path) else: # we should create empty directories too if a_is_filteredarchivecontents: m = a.mapDestPath(context, m).rstrip('/') m = path.rstrip('/\\')+'/'+m if iswindows: m = m.replace('/', '\\') mkdir(m) self.log.info("Completed unpacking %s (%0.1f MB) in %0.1f seconds", os.path.basename(srcAbs), filesize/1024.0/1024, (time.time()-starttime))
def updateStampFile(self): """ .. private:: Not useful enough to be in the public API. Assumes self.path is a stamp file that just needs creating / timestamp updating and does so """ path = normLongPath(self.path) mkdir(os.path.dirname(path)) with openForWrite(path, 'wb') as f: pass
def jar(path, manifest, sourcedir, options, preserveManifestFormatting=False, update=False, outputHandler=None): """ Create a jar file containing a manifest and some other files @param path: jar file to create. Typically this file does not already exist, but if it does then the specified files or manifest will be merged into it. @param manifest: path to the manifest.mf file (or None to disable manifest entirely) @param sourcedir: the directory to pack everything from (this method may add extra files to this dir) @param options: options map. jar.options is a list of additional arguments @param preserveManifestFormatting: an advanced option that prevents that jar executable from reformatting the specified manifest file to comply with Java conventions (also prevents manifest merging if jar already exists) """ # work out if we need to create a parent directory dir = os.path.dirname(path) if dir and not os.path.exists(dir): mkdir(dir) # location of jar if options['java.home']: binary = os.path.join(options['java.home'], "bin/jar") else: binary = "jar" # build up arguments args = [binary] args.extend(options['jar.options']) if update: mode='-u' else: mode='-c' if not manifest: args.extend([mode+"fM", path]) elif preserveManifestFormatting: mkdir(sourcedir+'/META-INF') srcf = normLongPath(sourcedir+'/META-INF/manifest.mf') with open(manifest, 'rb') as s: with openForWrite(srcf, 'wb') as d: d.write(s.read()) args.extend([mode+"f", path]) else: args.extend([mode+"fm", path, manifest]) if sourcedir: args.extend(["-C", sourcedir, "."]) # actually call jar call(args, outputHandler=outputHandler, timeout=options['process.timeout'])
def run(self, context): contents = self._getContents(context) mkdir(os.path.dirname(self.path)) path = normLongPath(self.path) with self.openFile(context, path, 'wb' if isinstance(contents, bytes) else 'w', encoding=self.__encoding) as f: f.write(contents) if self.__mode and not IS_WINDOWS: os.chmod(path, self.__mode) if self.__executable and not IS_WINDOWS: os.chmod( path, stat.S_IXOTH | stat.S_IXUSR | stat.S_IXGRP | os.stat(self.path).st_mode)
def run(self, context): self.log.info("Copying %s to %s", self.src, self.path) src = self.src.resolveWithDestinations( context) # a map of srcAbsolute: destRelative symlinks = self.options['Copy.symlinks'] if isinstance(symlinks, str): symlinks = symlinks.lower() == 'true' assert symlinks in [True, False], repr(symlinks) # implicitly ensure parent of target exists, to keep things simple copied = 0 if not isDirPath(self.name): # it's a simple file operation. if len(src) != 1: raise BuildException( 'Copy destination must be a directory (ending with "/") when multiple sources are specified (not: %s)' % src) src, mappedDest = src[0] if isDirPath(src): raise BuildException( 'Copy source must be files (or PathSets) not directories: %s' % src) mkdir(os.path.dirname(self.path)) self._copyFile( context, src, self.path ) # we kindof have to ignore mappedDest here, since the target path already fully defines it if self.mode: os.chmod(self.path, self.mode) copied += 1 else: lastDirCreated = None for (srcAbs, destRel) in src: srcAbs = normLongPath(srcAbs) dest = normLongPath(self.path + destRel) # there should not be any directories here only files from pathsets if '..' in destRel: # to avoid people abusing this to copy files outside the dest directory! raise Exception( 'This target does not permit destination paths to contain ".." relative path expressions' ) issymlink = symlinks and os.path.islink(srcAbs.rstrip(os.sep)) if isDirPath( srcAbs ) and not issymlink: # allows creating of empty directories. mkdir(dest) else: #self.log.debug('Processing %s -> %s i.e. %s', srcAbs, destRel, dest) if issymlink: # this may be a directory path, and dirname will fail unless we strip off the / dest = dest.rstrip(os.sep) if not lastDirCreated or lastDirCreated != os.path.dirname( dest): lastDirCreated = os.path.dirname(dest) self.log.debug('Creating intermediate dir %s', lastDirCreated) mkdir(lastDirCreated) try: if issymlink: os.symlink(os.readlink(srcAbs.rstrip(os.sep)), dest) else: self._copyFile(context, srcAbs, dest) if self.mode: os.chmod(dest, self.mode) except Exception as e: raise BuildException( 'Error copying from "%s" to "%s"' % (srcAbs, dest), causedBy=True) copied += 1 self.log.info('Copied %d file(s) to %s', copied, self.path)
def run(self, context): options = self.options # make sure temp dir exists mkdir(self.workDir) classes = os.path.join(self.workDir, "classes") # output dir for classes # create the classpath, sorting within PathSet (for determinism), but retaining original order of # PathSet elements in the list classpath = os.pathsep.join(self.classpath.resolve(context)) # compile everything mkdir(classes) # (need this for assembling other files to package later on, even if we don't do any javac) if self.compile: mkdir(self.getOption('javac.logs')) javac(classes, self.compile.resolve(context), classpath, options=options, logbasename=options.get('javac.logs')+'/'+targetNameToUniqueId(self.name), targetname=self.name, workDir=self.workDir) manifest = os.path.join(self.workDir, "MANIFEST.MF") # manifest file if isinstance(self.manifest, str): manifest = context.getFullPath(self.manifest, self.baseDir) elif self.manifest == None: manifest = None else: # generate one # rewrite property values in the manifest manifest_entries = {} for i in self.manifest: manifest_entries[i] = context.expandPropertyValues(self.manifest[i]) # determine classpath for manifest classpath_entries = [] if "Class-path" not in manifest_entries: # assuming it wasn't hardcoded, set it here for src, dest in self.classpath.resolveWithDestinations(context): # we definitely do want to support use of ".." in destinations here, it can be very useful classpath_entries.append(dest) assert isinstance(options['jar.manifest.classpathAppend'], list), options['jar.manifest.classpathAppend'] # must not be a string classpath_entries.extend(options['jar.manifest.classpathAppend'] or []) # need to always use / not \ for these to be valid classpath_entries = [p.replace(os.path.sep, '/').replace('\\', '/') for p in classpath_entries if p] if classpath_entries: manifest_entries["Class-path"] = " ".join(classpath_entries) # include the classpath from here if not manifest_entries.get('Class-path'): # suppress this element entirely if not needed, otherwise there would be no way to have an empty classpath manifest_entries.pop('Class-path','') # create the manifest file create_manifest(manifest, manifest_entries, options=options) # copy in the additional things to include for (src, dest) in self.package.resolveWithDestinations(context): if '..' in dest: raise Exception('This target does not permit packaged destination paths to contain ".." relative path expressions') mkdir(os.path.dirname(os.path.join(classes, dest))) destpath = normLongPath(classes+'/'+dest) srcpath = normLongPath(src) if os.path.isdir(srcpath): mkdir(destpath) else: with open(srcpath, 'rb') as s: with openForWrite(destpath, 'wb') as d: d.write(s.read()) # create the jar jar(self.path, manifest, classes, options=options, preserveManifestFormatting=self.preserveManifestFormatting, outputHandler=ProcessOutputHandler.create('jar', treatStdErrAsErrors=False,options=options))
def run(self, context): mkdir(os.path.dirname(self.path)) with tarfile.open(normLongPath(self.path), 'w:gz') as output: for (f, o) in self.inputs.resolveWithDestinations(context): output.add(normLongPath(f).rstrip('/\\'), o)