<s> """<STR_LIT>""" <EOL> __author__ = "<STR_LIT>" <EOL> __email__ = "<STR_LIT>" <EOL> import re <EOL> import os <EOL> import sys <EOL> import ldap <EOL> import pysvn <EOL> import shutil <EOL> import fnmatch <EOL> import smtplib <EOL> import logging <EOL> import logging . handlers <EOL> import tempfile <EOL> import lxml . etree <EOL> from email . Message import Message <EOL> from optparse import OptionParser , OptionError <EOL> from ConfigParser import SafeConfigParser <EOL> SEPARATOR = "<STR_LIT:=>" * <NUM_LIT> <EOL> LOGGER = None <EOL> def get_logger ( verbose = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> global LOGGER <EOL> if LOGGER is None : <EOL> LOGGER = logging . getLogger ( sys . argv [ <NUM_LIT:0> ] ) <EOL> stderr = logging . StreamHandler ( ) <EOL> level = logging . WARNING <EOL> lformat = "<STR_LIT>" <EOL> if verbose == <NUM_LIT:1> : <EOL> level = logging . INFO <EOL> elif verbose > <NUM_LIT:1> : <EOL> stderr . setFormatter ( logging . Formatter ( "<STR_LIT>" ) ) <EOL> level = logging . DEBUG <EOL> LOGGER . setLevel ( level ) <EOL> LOGGER . addHandler ( stderr ) <EOL> syslog = logging . handlers . SysLogHandler ( "<STR_LIT>" ) <EOL> syslog . setFormatter ( logging . Formatter ( "<STR_LIT>" ) ) <EOL> LOGGER . addHandler ( syslog ) <EOL> LOGGER . debug ( "<STR_LIT>" % verbose ) <EOL> return LOGGER <EOL> def parse_log_message ( message ) : <EOL> """<STR_LIT>""" <EOL> keywords = dict ( subject = None , resolve = None ) <EOL> logger = get_logger ( ) <EOL> for keyword in keywords . iterkeys ( ) : <EOL> pattern = re . compile ( ( r'<STR_LIT>' % <EOL> keyword ) , <EOL> re . IGNORECASE | re . MULTILINE ) <EOL> match = pattern . search ( message ) <EOL> if match : <EOL> keywords [ keyword ] = match . group ( <NUM_LIT:1> ) . strip ( ) <EOL> logger . debug ( "<STR_LIT>" % ( keyword , <EOL> match . group ( <NUM_LIT:0> ) ) ) <EOL> message = pattern . sub ( '<STR_LIT>' , message ) <EOL> return ( message , keywords ) <EOL> def build_summary ( changes ) : <EOL> """<STR_LIT>""" <EOL> summary = dict ( ) <EOL> logger = get_logger ( ) <EOL> for change in changes : <EOL> logger . info ( "<STR_LIT>" % ( change . summarize_kind , <EOL> change . path ) ) <EOL> if change . summarize_kind not in summary : <EOL> summary [ change . summarize_kind ] = [ ] <EOL> summary [ change . summarize_kind ] . append ( change . path ) <EOL> return summary <EOL> def get_author_email ( author ) : <EOL> """<STR_LIT>""" <EOL> logger = get_logger ( ) <EOL> ldapconf = dict ( ) <EOL> for conffile in [ "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" ] : <EOL> if '<STR_LIT>' in ldapconf and '<STR_LIT:host>' in ldapconf : <EOL> break <EOL> logger . debug ( "<STR_LIT>" % conffile ) <EOL> try : <EOL> for line in open ( conffile ) . read ( ) . splitlines ( ) : <EOL> match = re . search ( r'<STR_LIT>' , line ) <EOL> if match : <EOL> ldapconf [ match . group ( <NUM_LIT:1> ) ] = match . group ( <NUM_LIT:2> ) <EOL> except IOError : <EOL> pass <EOL> if '<STR_LIT>' in ldapconf and '<STR_LIT:host>' in ldapconf : <EOL> ldapconf [ '<STR_LIT:host>' ] = ldapconf [ '<STR_LIT:host>' ] . split ( ) [ <NUM_LIT:0> ] <EOL> if not re . search ( r'<STR_LIT>' , ldapconf [ '<STR_LIT:host>' ] ) : <EOL> if ( '<STR_LIT>' in ldapconf and <EOL> ldapconf [ '<STR_LIT>' ] in [ '<STR_LIT>' , '<STR_LIT:yes>' , '<STR_LIT>' ] ) : <EOL> ldapconf [ '<STR_LIT:host>' ] = "<STR_LIT>" % ldapconf [ '<STR_LIT:host>' ] <EOL> else : <EOL> ldapconf [ '<STR_LIT:host>' ] = "<STR_LIT>" % ldapconf [ '<STR_LIT:host>' ] <EOL> logger . debug ( "<STR_LIT>" % ldapconf [ '<STR_LIT:host>' ] ) <EOL> try : <EOL> conn = ldap . initialize ( ldapconf [ '<STR_LIT:host>' ] ) <EOL> except ldap . LDAPError , err : <EOL> logger . warn ( "<STR_LIT>" % <EOL> ( ldapconf [ '<STR_LIT:host>' ] , err ) ) <EOL> return author <EOL> if '<STR_LIT>' in ldapconf and ldapconf [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> logger . debug ( "<STR_LIT>" ) <EOL> try : <EOL> conn . start_tls_s ( ) <EOL> except ldap . LDAPError , err : <EOL> if err [ <NUM_LIT:0> ] [ '<STR_LIT:info>' ] != '<STR_LIT>' : <EOL> logger . warn ( "<STR_LIT>" % err ) <EOL> ldap_filter = "<STR_LIT>" % author <EOL> logger . debug ( "<STR_LIT>" % ( ldap_filter , ldapconf [ '<STR_LIT>' ] ) ) <EOL> try : <EOL> res = conn . search_s ( ldapconf [ '<STR_LIT>' ] , ldap . SCOPE_SUBTREE , <EOL> ldap_filter , [ '<STR_LIT>' ] ) <EOL> if len ( res ) == <NUM_LIT:1> : <EOL> attrs = res . pop ( ) [ <NUM_LIT:1> ] <EOL> logger . debug ( "<STR_LIT>" % attrs [ '<STR_LIT>' ] [ <NUM_LIT:0> ] ) <EOL> return attrs [ '<STR_LIT>' ] [ <NUM_LIT:0> ] <EOL> elif len ( res ) : <EOL> logger . warn ( "<STR_LIT>" % <EOL> ldap_filter ) <EOL> return author <EOL> elif not res : <EOL> logger . warn ( "<STR_LIT>" % ldap_filter ) <EOL> return author <EOL> except ldap . LDAPError , err : <EOL> logger . warn ( "<STR_LIT>" % <EOL> ( ldap_filter , ldapconf [ '<STR_LIT:host>' ] , err ) ) <EOL> return author <EOL> else : <EOL> logger . warn ( "<STR_LIT>" ) <EOL> return author <EOL> def get_diff_set ( change , baseuri , largediff = <NUM_LIT:100> , rev = None , <EOL> blacklist = None ) : <EOL> """<STR_LIT>""" <EOL> logger = get_logger ( ) <EOL> client = pysvn . Client ( ) <EOL> revision = pysvn . Revision ( pysvn . opt_revision_kind . number , rev ) <EOL> previous = pysvn . Revision ( pysvn . opt_revision_kind . number , rev - <NUM_LIT:1> ) <EOL> logger . info ( "<STR_LIT>" % ( change . summarize_kind , change . path ) ) <EOL> change_uri = os . path . join ( baseuri , change . path ) <EOL> if plugin_blacklist is None : <EOL> plugin_blacklist = [ ] <EOL> if change . summarize_kind == pysvn . diff_summarize_kind . delete : <EOL> logger . debug ( "<STR_LIT>" % ( change . path , <EOL> change . summarize_kind ) ) <EOL> return ( None , None ) <EOL> if ( "<STR_LIT>" in change . path or <EOL> change . path . endswith ( "<STR_LIT>" ) ) : <EOL> logger . debug ( "<STR_LIT>" % <EOL> change . path ) <EOL> return ( "<STR_LIT>" , change . path ) <EOL> for pattern in blacklist : <EOL> if fnmatch . fnmatch ( change . path , pattern ) : <EOL> logger . debug ( "<STR_LIT>" ) <EOL> return ( None , None ) <EOL> info = client . info2 ( change_uri , revision = revision , recurse = False ) [ <NUM_LIT:0> ] [ <NUM_LIT:1> ] <EOL> if info . kind == pysvn . node_kind . dir : <EOL> logger . debug ( "<STR_LIT>" % change . path ) <EOL> return ( None , None ) <EOL> mime = client . propget ( '<STR_LIT>' , change_uri , revision = revision ) <EOL> if change_uri in mime : <EOL> logger . debug ( "<STR_LIT>" % <EOL> ( change . path , mime [ change_uri ] ) ) <EOL> return ( '<STR_LIT>' , change . path ) <EOL> diff = None <EOL> if change . summarize_kind == pysvn . diff_summarize_kind . modified : <EOL> tempdir = tempfile . mkdtemp ( ) <EOL> diff = client . diff ( tempdir , change_uri , <EOL> revision1 = previous , <EOL> revision2 = revision ) <EOL> shutil . rmtree ( tempdir ) <EOL> else : <EOL> diff = ( "<STR_LIT>" % <EOL> ( change . path , SEPARATOR , <EOL> client . cat ( change_uri , revision = revision ) ) ) <EOL> if len ( diff . splitlines ( ) ) > largediff : <EOL> logger . debug ( "<STR_LIT>" % <EOL> ( change . path , len ( diff . splitlines ( ) ) ) ) <EOL> return ( '<STR_LIT>' , change . path ) <EOL> if fnmatch . fnmatch ( change . path , "<STR_LIT>" ) : <EOL> logger . info ( "<STR_LIT>" % os . path . dirname ( change . path ) ) <EOL> tempdir = tempfile . mkdtemp ( ) <EOL> try : <EOL> client . checkout ( os . path . join ( baseuri , os . path . dirname ( change . path ) ) , <EOL> tempdir , revision = revision ) <EOL> xdata = lxml . etree . parse ( os . path . join ( tempdir , <EOL> os . path . basename ( change . path ) ) ) <EOL> finally : <EOL> shutil . rmtree ( tempdir ) <EOL> if xdata . getroot ( ) . get ( "<STR_LIT>" , "<STR_LIT:false>" ) . lower ( ) == "<STR_LIT:true>" : <EOL> return ( "<STR_LIT>" , change . path ) <EOL> if ( "<STR_LIT>" in change . path and <EOL> os . path . basename ( change . path ) != "<STR_LIT>" ) : <EOL> logger . info ( "<STR_LIT>" % os . path . dirname ( change . path ) ) <EOL> tempdir = tempfile . mkdtemp ( ) <EOL> try : <EOL> try : <EOL> client . checkout ( os . path . join ( baseuri , <EOL> os . path . dirname ( change . path ) ) , <EOL> tempdir , revision = revision ) <EOL> root = lxml . etree . parse ( os . path . join ( tempdir , <EOL> "<STR_LIT>" ) ) . getroot ( ) <EOL> except IOError : <EOL> logger . debug ( "<STR_LIT>" % change . path ) <EOL> except : <EOL> raise <EOL> finally : <EOL> shutil . rmtree ( tempdir ) <EOL> if root is not None : <EOL> for el in root . xpath ( "<STR_LIT>" ) : <EOL> if el . get ( "<STR_LIT>" , "<STR_LIT:false>" ) . lower ( ) == "<STR_LIT:true>" : <EOL> return ( "<STR_LIT>" , change . path ) <EOL> return ( '<STR_LIT>' , diff ) <EOL> def parse_args ( ) : <EOL> """<STR_LIT>""" <EOL> usage = """<STR_LIT>""" <EOL> parser = OptionParser ( usage = usage ) <EOL> parser . add_option ( "<STR_LIT>" , "<STR_LIT>" , help = "<STR_LIT>" , action = "<STR_LIT:count>" ) <EOL> parser . add_option ( "<STR_LIT:-c>" , "<STR_LIT>" , help = "<STR_LIT>" , <EOL> default = "<STR_LIT>" ) <EOL> parser . add_option ( "<STR_LIT>" , "<STR_LIT>" , help = "<STR_LIT>" ) <EOL> parser . add_option ( "<STR_LIT>" , help = "<STR_LIT>" ) <EOL> try : <EOL> ( options , args ) = parser . parse_args ( ) <EOL> except OptionError : <EOL> parser . print_help ( ) <EOL> raise SystemExit ( <NUM_LIT:1> ) <EOL> if not len ( args ) : <EOL> parser . print_help ( ) <EOL> raise SystemExit ( <NUM_LIT:1> ) <EOL> get_logger ( options . verbose ) <EOL> return ( options , args . pop ( ) ) <EOL> def get_config ( configfile , repos_name ) : <EOL> """<STR_LIT>""" <EOL> logger = get_logger ( ) <EOL> defaults = dict ( largediff = <NUM_LIT:100> , <EOL> subject = '<STR_LIT>' , <EOL> blacklist = "<STR_LIT>" ) <EOL> config = SafeConfigParser ( defaults ) <EOL> if os . path . exists ( configfile ) : <EOL> config . read ( configfile ) <EOL> else : <EOL> logger . fatal ( "<STR_LIT>" % configfile ) <EOL> raise SystemExit ( <NUM_LIT:1> ) <EOL> if not config . has_section ( repos_name ) : <EOL> logger . fatal ( "<STR_LIT>" % <EOL> repos_name ) <EOL> raise SystemExit ( <NUM_LIT:2> ) <EOL> return config <EOL> def main ( ) : <EOL> """<STR_LIT>""" <EOL> ( options , path ) = parse_args ( ) <EOL> uri = "<STR_LIT>" % path <EOL> logger = get_logger ( ) <EOL> repos_name = os . path . basename ( uri ) <EOL> config = get_config ( options . config , repos_name ) <EOL> client = pysvn . Client ( ) <EOL> revision = pysvn . Revision ( pysvn . opt_revision_kind . number , options . rev ) <EOL> previous = pysvn . Revision ( pysvn . opt_revision_kind . number , <EOL> int ( options . rev ) - <NUM_LIT:1> ) <EOL> changes = client . diff_summarize ( uri , <EOL> revision1 = previous , <EOL> revision2 = revision ) <EOL> log = client . log ( uri , revision_end = revision ) [ <NUM_LIT:0> ] <EOL> logger . info ( "<STR_LIT>" % ( options . rev , log . author ) ) <EOL> ( message , keywords ) = parse_log_message ( log . message ) <EOL> summary = build_summary ( changes ) <EOL> diffs = dict ( diff = [ ] , large = [ ] , binary = [ ] , sensitive = [ ] ) <EOL> for change in changes : <EOL> ( dtype , ddata ) = get_diff_set ( change , uri , <EOL> rev = int ( options . rev ) , <EOL> largediff = int ( config . get ( repos_name , <EOL> '<STR_LIT>' ) ) ) <EOL> if dtype is not None : <EOL> diffs [ dtype ] . append ( ddata ) <EOL> body = [ message . strip ( ) , <EOL> '<STR_LIT>' , <EOL> "<STR_LIT>" % log . author , <EOL> "<STR_LIT>" % options . rev , <EOL> '<STR_LIT>' , <EOL> "<STR_LIT>" , '<STR_LIT>' ] <EOL> for ctype in summary : <EOL> body . extend ( [ "<STR_LIT>" % ( f , ctype ) for f in summary [ ctype ] ] ) <EOL> body . append ( '<STR_LIT>' ) <EOL> if diffs [ '<STR_LIT>' ] : <EOL> body . extend ( [ SEPARATOR , '<STR_LIT>' , "<STR_LIT>" , <EOL> '<STR_LIT>' ] ) <EOL> body . extend ( diffs [ '<STR_LIT>' ] ) <EOL> body . append ( '<STR_LIT>' ) <EOL> if diffs [ '<STR_LIT>' ] : <EOL> body . extend ( [ SEPARATOR , '<STR_LIT>' , <EOL> "<STR_LIT>" , <EOL> '<STR_LIT>' ] ) <EOL> body . extend ( diffs [ '<STR_LIT>' ] ) <EOL> body . append ( '<STR_LIT>' ) <EOL> if diffs [ '<STR_LIT>' ] : <EOL> body . extend ( [ SEPARATOR , '<STR_LIT>' , <EOL> "<STR_LIT>" , '<STR_LIT>' ] ) <EOL> body . extend ( diffs [ '<STR_LIT>' ] ) <EOL> body . append ( '<STR_LIT>' ) <EOL> if diffs [ '<STR_LIT>' ] : <EOL> body . extend ( [ SEPARATOR , '<STR_LIT>' , "<STR_LIT>" , '<STR_LIT>' ] ) <EOL> body . extend ( diffs [ '<STR_LIT>' ] ) <EOL> if keywords [ '<STR_LIT>' ] : <EOL> body . extend ( [ '<STR_LIT>' , <EOL> "<STR_LIT>" % keywords [ '<STR_LIT>' ] , <EOL> "<STR_LIT>" % keywords [ '<STR_LIT>' ] , <EOL> "<STR_LIT>" % keywords [ '<STR_LIT>' ] ] ) <EOL> if config . has_option ( repos_name , '<STR_LIT:email>' ) and not options . stdout : <EOL> msg = Message ( ) <EOL> msg . set_payload ( "<STR_LIT:\n>" . join ( body ) ) <EOL> subject = None <EOL> if keywords [ '<STR_LIT>' ] : <EOL> subject = keywords [ '<STR_LIT>' ] <EOL> elif "<STR_LIT:\n>" in message : <EOL> subject = message [ <NUM_LIT:0> : max ( <NUM_LIT> , message . index ( "<STR_LIT:\n>" ) ) ] <EOL> else : <EOL> subject = message [ <NUM_LIT:0> : <NUM_LIT> ] <EOL> msg [ '<STR_LIT>' ] = "<STR_LIT>" % ( config . get ( repos_name , '<STR_LIT>' ) , subject ) <EOL> msg [ '<STR_LIT>' ] = get_author_email ( log . author ) <EOL> msg [ '<STR_LIT>' ] = config . get ( repos_name , '<STR_LIT:email>' ) <EOL> logger . debug ( "<STR_LIT>" % ( msg [ '<STR_LIT>' ] , <EOL> msg [ '<STR_LIT>' ] , <EOL> msg [ '<STR_LIT>' ] ) ) <EOL> smtp = smtplib . SMTP ( '<STR_LIT:localhost>' ) <EOL> if options . verbose > <NUM_LIT:2> : <EOL> smtp . set_debuglevel ( options . verbose - <NUM_LIT:1> ) <EOL> smtp . sendmail ( msg [ '<STR_LIT>' ] , [ msg [ '<STR_LIT>' ] ] , msg . as_string ( ) ) <EOL> smtp . quit ( ) <EOL> else : <EOL> print ( "<STR_LIT:\n>" . join ( body ) ) <EOL> if __name__ == "<STR_LIT:__main__>" : <EOL> sys . exit ( main ( ) ) </s>
