#!/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()

