!/usr/bin/env python
# @file aeolus.py 
# @author Krzysztof Danile Ciba (Krzysztof.Ciba@NOSPAMgmail.com)
# @brief svn pre-commit hook for checking correct line endings
import os, sys
import re
import svn
import svn.fs
import svn.repos
import svn.core
import getopt
    
## usage and exit, help, ero messages 
def usage_and_exit(error_msg=None):
    import os.path
    stream = error_msg and sys.stderr or sys.stdout
    if error_msg:
        stream.write("ERROR: %s\n\n" % error_msg )
        stream.write("USAGE: %s -t TXN_NAME REPOS\n" % (os.path.basename(sys.argv[0])))
        sys.exit(error_msg and 1 or 0)
##
# @class aeolus
# @author Krzysztof Daniel Ciba (Krztysztof.Ciba@NOSPAMgmail.com)
# @brief blocks commit to repo if property svn:eol-style is not set or is not correct (ne LF)
class Aeolus:
    
    reText = re.compile(".+\.h$|.+\.cpp$|.+\.cxx$|.+\.hh$|.+\.icc$|.+\.C$|.+\.c$|.+\.py$|.+\.f$|.+\.F$|.+\.f90$|.+\.F90$|.+\.java$|.+\.php$|.+\.sh$|.+\.csh$|.+\.tex$|.+ChangeLog$|.+\.cmt$|.+requirements$|.+\.txt$|.+\.xml$|.+\.css$.+\.html$")
                       
    ## c'tor 
    # @param self "Me, myself and Irene"
    def __init__(self):

        self.repos_path = None
        self.txn_name = None
        try:
            opts, args = getopt.getopt(sys.argv[1:], 't:h?', ["help"])
        except:
            usage_and_exit("problem processing arguments / options.")
        for opt, value in opts:
            if opt == '--help' or opt == '-h' or opt == '-?':
                usage_and_exit()
            elif opt == '-t':
                self.txn_name = value
            else:
                usage_and_exit("unknown option '%s'." % opt )
                                                                            
        if self.txn_name is None:
            usage_and_exit("must provide -t argument")
        if len(args) != 1:
            usage_and_exit("only one argument allowed (the repository).")
        self.repos_path = svn.core.svn_path_canonicalize( args[0] )
        
        self.fs = svn.repos.svn_repos_fs( svn.repos.svn_repos_open( self.repos_path ) )
        self.txn = svn.fs.svn_fs_open_txn ( self.fs, self.txn_name )
        self.txn_root = svn.fs.svn_fs_txn_root( self.txn )
        changed_paths = svn.fs.paths_changed( self.txn_root )
        for path, change in changed_paths.iteritems():
            if ( svn.fs.svn_fs_is_file( self.txn_root, path ) == 1 ):
                
                if ( self.reText.match( path ) ):
                    node_props = svn.fs.node_proplist( self.txn_root, path )
                    if ( "svn:eol-style" in node_props ):
                        if ( node_props["svn:eol-style"] != "LF" ):
                            sys.stderr.write("ERROR: file " + path + " has got wrong line endings!\n\n")
                            sys.stderr.write("In this repository only UNIX/Linux(=LF) line endings are allowed,\n")
                            sys.stderr.write("but this file is using " +  node_props["svn:eol-style"] + " line endigs.\n\n")
                            sys.stderr.write("You should modify 'svn:eol-style' property:\n\n")
                            sys.stderr.write("[1] using command:\n")
                            sys.stderr.write("    shell> svn propset svn:eol-style LF WORKING_COPY/FILENAME\n\n" )
                            sys.stderr.write("[2] by changing your svn client settings (usualy stored in $HOME/.subversion/config file):\n")
                            sys.stderr.write("    - in section [miscellany] make sure that 'enable-auto-props' is set to 'yes'\n" )
                            sys.stderr.write("         [miscellany]\n")
                            sys.stderr.write("         enable-auto-props = yes\n" )
                            sys.stderr.write("    - in section [auto-props] add pattern for your source file (i.e. *.py for python source file)\n")
                            sys.stderr.write("         [auto-props]\n")
                            sys.stderr.write("          *.py = svn:eol-style=LF\n\n")
                            sys.stderr.write("Contact librarian ('librarian@somewhere') for details.\n")
                            sys.exit(1)
                    else:
                        # silently set eol-style prop to LF
                        svn.fs.change_node_prop( self.txn_root, path, "svn:eol-style", "LF" )                       
        sys.exit(0)

## execution
if __name__ == "__main__":
    Aeolus()