| #!/usr/bin/python |
| """ |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| """ |
| |
| from optparse import OptionParser |
| from zipfile import ZipFile |
| from subprocess import Popen,PIPE |
| from glob import glob |
| import os,re |
| |
| def main() : |
| usage= "usage: %prog [optons]" |
| description = "Generate a jar file which contains the OpenJPA class files which have been changed. The output from svn info and svn diff may also be included. A typical \ |
| use is to run from the same directory as the parent pom. This will automatically include all changed files with a .java extension." |
| version = "$prog 0.5" |
| parser = OptionParser(usage=usage, version=version, description = description) |
| parser.add_option("-f", "--files", dest="files", help="list of filenames to include") |
| parser.add_option("-p", "--patchfile", dest="patchfile", help="patch file name", default="patch.jar") |
| parser.add_option("-i", "--noinfo", action="store_false", dest="includeInfo", help="exclude output from svn info", default=True) |
| parser.add_option("-d", "--nodiff", action="store_false", dest="includeDiff", help="exclude output from svn diff",default=True) |
| parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="print debug information",default=False) |
| # parser.add_option("-p", "--pattern", dest="pattern", help="regex of filenames to match") |
| |
| global options |
| (options,args) = parser.parse_args() |
| |
| genZip(options) |
| |
| def genZip(options): |
| """ generate the zip file """ |
| if options.files == None: |
| files = getAllFiles() |
| else : |
| files = getFilesFromList(options.files) |
| |
| zip = ZipFile(options.patchfile, 'w') |
| |
| if options.includeInfo: |
| writeInfo(zip, files) |
| if options.includeDiff: |
| writeDiff(zip, files) |
| |
| writeClasses(zip, files) |
| |
| zip.close() |
| |
| print 'Wrote patch to %s. ' % (options.patchfile) |
| if options.verbose: |
| print 'Files in patch: %s' % ("\n".join(files)) |
| |
| def getAllFiles(): |
| """ get the list of all modified files. Only Added or Modified .java, .properties files will be considered """ |
| if options.verbose: |
| print ' > getAllFiles' |
| files = [] |
| |
| commandOutput = Popen(['svn', 'stat'], stdout=PIPE).communicate()[0].splitlines() |
| prog = re.compile('([A|M] *)(.*\.java)') |
| for candidate in commandOutput: |
| match = prog.match(candidate) |
| if match : |
| files.append(match.group(2)) |
| |
| prog = re.compile('([A|M] *)(.*\.properties)') |
| for candidate in commandOutput: |
| match = prog.match(candidate) |
| if match : |
| files.append(match.group(2)) |
| |
| |
| if options.verbose: |
| print 'Found modified files : ' + str(files) |
| print ' < getAllFiles' |
| return files |
| |
| def getFilesFromList(files) : |
| """ get a list of modified files from a comma separated list usually from the command line """ |
| |
| if options.verbose : |
| print ' > getFilesFromList' |
| print ' returning ' + str(files.split(',')) |
| print ' < getFilesFromList' |
| |
| return files.split(',') |
| |
| def writeInfo(zip, files=None): |
| """ write the output of svn info to a temp file and store in a zip """ |
| if options.verbose : |
| print ' > writeInfo' |
| |
| patchFile = open('info.txt', 'w') |
| args = ['svn', 'info'] |
| |
| if files: |
| args.extend(files) |
| |
| Popen(args=args, stdout=patchFile).communicate()[0] |
| |
| zip.write(patchFile.name) |
| patchFile.close() |
| os.remove(patchFile.name) |
| |
| if options.verbose: |
| print ' < writeInfo' |
| |
| def writeDiff(zip, files=None): |
| """ Write the output of svn diff to a temp file and store in a zip """ |
| if options.verbose: |
| print ' > writeDiff' |
| |
| patchFile = open('patch.txt', 'w') |
| args = ['svn', 'diff'] |
| if files: |
| args.extend(files) |
| |
| Popen(args=args, stdout=patchFile).communicate()[0] |
| |
| zip.write(patchFile.name) |
| patchFile.close() |
| os.remove(patchFile.name) |
| |
| if options.verbose: |
| print ' < writeDiff' |
| |
| def javaToClass(file) : |
| """ simple helper function, converts a string from svn stat (or command line) to its corresponding |
| .class file |
| """ |
| |
| rval = file.replace('src','target').replace('main','classes').replace('test','test-classes').replace('.java', '.class').replace('java','').replace('\\\\','\\') |
| return rval; |
| |
| def javaToInnerClass(file): |
| """ helper function, converts .java file to a glob pattern that matches inner classes """ |
| return javaToClass(file).replace('.class', '$*.class') |
| |
| def writeClasses(zip, files=None): |
| """ Write class files to a zip """ |
| |
| prog = re.compile('(.*classes.)(.*)') |
| propertiesProg = re.compile('(.*resources.)(.*)') |
| |
| for file in files : |
| if str(file).endswith('.java'): |
| for globMatch in glob(javaToClass(file)) : |
| if(prog.match(globMatch)): |
| target = prog.match(globMatch).group(2) |
| zip.write(os.path.realpath(globMatch), target) |
| |
| # match again on inner classes, not sure if glob supports optional matches. |
| for globMatch in glob(javaToInnerClass(file)) : |
| if(prog.match(globMatch)): |
| target = prog.match(globMatch).group(2) |
| zip.write(os.path.realpath(globMatch), target) |
| elif str(file).endswith('.properties'): |
| for globMatch in glob(file) : |
| if(propertiesProg.match(globMatch)): |
| target = propertiesProg.match(globMatch).group(2) |
| zip.write(os.path.realpath(globMatch), target) |
| |
| if __name__ == "__main__": |
| main() |
| |