[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [repo-management] hooks: Preliminary support for EOL violations exception: the changed file's
From:       Luca Beltrame <lbeltrame () kde ! org>
Date:       2012-04-09 8:19:51
Message-ID: 20120409081951.AB75DA60A9 () git ! kde ! org
[Download RAW message or body]

Git commit f1d1c0d0387406f45dc767d29f9c2664870e8941 by Luca Beltrame.
Committed on 09/04/2012 at 10:06.
Pushed by lbeltrame into branch 'master'.

Preliminary support for EOL violations exception: the changed file's
MIME type is checked against known "allowed" types and if there's a
match the violation is ignored

M  +51   -28   hooks/hooklib.py

http://commits.kde.org/repo-management/f1d1c0d0387406f45dc767d29f9c2664870e8941

diff --git a/hooks/hooklib.py b/hooks/hooklib.py
index abbef63..93e3adb 100644
--- a/hooks/hooklib.py
+++ b/hooks/hooklib.py
@@ -16,6 +16,7 @@ from email.mime.text import MIMEText
 from email.header import Header
 from email import Charset
 
+import mime
 from ordereddict import OrderedDict
 import lxml.etree as etree
 from lxml.builder import E
@@ -82,7 +83,7 @@ class Repository(object):
         self.change_type = self.__get_change_type()
         ref_name_match = re.match("^refs/(.+?)/(.+)$", self.ref)
         self.ref_name = ref_name_match.group(2)
-        
+
         # Determine commit type for the top most commit
         if self.change_type == ChangeType.Delete:
             self.commit_type = "commit"
@@ -127,7 +128,7 @@ class Repository(object):
         # If we have no revisions... don't continue
         if not revisions:
             return
-            
+
         # Build the git pretty format + regex.
         l = (
              ('CH' , ('%H%n',  '(?P<sha1>.+)\n')),
@@ -185,22 +186,22 @@ class Repository(object):
                     stats[changed_file]["source"] = unicode(source_file, "utf-8", \
"replace")  stats[changed_file]["added"] = added
                 stats[changed_file]["removed"] = removed
-                
+
             # Parse the way files changed
             status = \
re.findall("\x00?(A|C|D|M|R|T|U|X)(?:(?<=C|R)([0-9]+)\x00([^\x00]+)|)\x00([^\x00]+)?", \
self.commits[sha1].files_changed)  for change, similarity, source_file, changed_file \
in status:  stats[changed_file]["change"] = change
                 if source_file:
                     stats[changed_file]["similarity"] = similarity
-                    
+
             for filename, data in stats.iteritems():
                 if "source" in data.keys() and "similarity" not in data.keys():
                     del data["source"]
-                
+
             # Remove items with invalid data (ie. number of changed lines but no \
status)  data = OrderedDict((unicode(filename, "utf-8", "replace"), data) for \
filename, data in sorted(stats.items(), key=operator.itemgetter(0)) if "change" in \
data and "added" in data)  self.commits[sha1].files_changed = data
-                
+
     def __write_metadata(self):
 
         """Write repository metatdata."""
@@ -218,7 +219,7 @@ class Repository(object):
         if not os.path.exists(nick_path):
             with open(nick_path, "w") as rid_file:
                 rid_file.write(self.path + "\n")            
-                
+
         with open(nick_path, "r") as rid_file:
             return rid_file.readline().strip()
 
@@ -275,6 +276,8 @@ class CommitAuditor(object):
 
     """Performs all audits on commits"""
 
+    ALLOWED_EOL_FILENAMES = set("text/vcard",)
+
     def __init__(self, repository):
         self.repository = repository
         self.__failed = False
@@ -330,6 +333,10 @@ class CommitAuditor(object):
         re_filename = re.compile("^diff --(cc |git a\/.+ b\/)(.+)$")
         blocked_eol = re.compile(r"(?:\r\n|\n\r|\r)$")
 
+        # Bool to allow special files such as vcards to bypass the check
+        eol_allowed = False
+
+
         # Do EOL audit!
         process = get_change_diff( self.repository, ["-p"] )
         for line in process.stdout:
@@ -342,6 +349,16 @@ class CommitAuditor(object):
             if file_change:
                 filename = file_change.group(2)
                 eol_violation = False
+
+                # Check if it's an allowed mimetype
+                # If so, we ignore EOL violations
+
+                guessed_type = mime.MimeType.fromName(filename)
+                if guessed_type.name() in self.ALLOWED_EOL_FILENAMES:
+                    eol_allowed = True
+                else:
+                    eol_allowed = False
+
                 continue
 
             # Unless they added it, ignore it
@@ -349,6 +366,12 @@ class CommitAuditor(object):
                 continue
 
             if re.search( blocked_eol, line ) and not eol_violation:
+
+                # Is this an allowed filename?
+
+                if eol_allowed:
+                    continue
+
                 # Failure has been found... handle it
                 eol_violation = True
                 self.__log_failure(commit, "End Of Line Style - " + filename);
@@ -405,11 +428,11 @@ class CommitAuditor(object):
                         self.__log_failure(commit.sha1, "Email Address - " + \
email_address)  except dns.resolver.NXDOMAIN:
                     self.__log_failure(commit.sha1, "Email Address - " + \
                email_address)
-    
+
     def audit_hashes(self, blocked_list):
         with open(blocked_list, "r") as blockedfile:
             blocked = blockedfile.readlines()
-    
+
         for sha1 in blocked:
             sha1 = sha1.strip()
             if sha1 in self.repository.commits:
@@ -417,7 +440,7 @@ class CommitAuditor(object):
 
 class CommitNotifier(object):
     "Contains items needed to send notifications for commits"
-    
+
     def __init__(self):
         self.smtp = smtplib.SMTP()
         self.smtp.connect()
@@ -441,7 +464,7 @@ class CommitNotifier(object):
 
         if builder.keywords['email_gui']:
             cc_addresses.append( 'kde-doc-english@kde.org' )
-            
+
         if builder.repository.repo_type == RepoType.Website:
             bcc_addresses.append( 'scmupdate@spider-mail.kde.org' )
 
@@ -464,7 +487,7 @@ class CommitNotifier(object):
         # Send email...
         to_addresses = cc_addresses + bcc_addresses + [notification_address]
         self.smtp.sendmail("null@kde.org", to_addresses, message.as_string())
-        
+
     def notify_bugzilla(self, builder):
         commit_regex = re.compile("^\s*((CC)?BUGS?|FEATURE)[:=](.+)\n", \
                re.MULTILINE)
         bugs_changed = builder.keywords['bug_fixed'] + builder.keywords['bug_cc']
@@ -494,7 +517,7 @@ class CommitNotifier(object):
             message['To']      = Header( "bug-control@bugs.kde.org" )
             self.smtp.sendmail(builder.commit.committer_email, \
["bug-control@bugs.kde.org"],  message.as_string())
-                               
+
     def notify_reviewboard(self, builder):
         for review in builder.keywords['review']:
             # Call the helper program
@@ -504,12 +527,12 @@ class CommitNotifier(object):
                         builder.commit.author_name, ref_changed)
             # Fork into the background - we don't want it to block the hook
             subprocess.Popen(cmdline, shell=False)
-        
+
     def handler(self, repository):
         # If there are no commits -> nothing to notify on :)
         if len(repository.commits) == 0:
             return
-        
+
         # We will incrementally notify as we gather up the diffs....
         process = get_change_diff( repository, ["-p"] )
         diff = list()
@@ -528,26 +551,26 @@ class CommitNotifier(object):
 
         if commit:
             yield(repository.commits[commit], diff)
-        
+
 class MessageBuilder(object):
     """Creates the components needed to send emails and other notifications"""
-        
+
     def __init__(self, repository, commit, checker = None, include_url = True):
         self.repository = repository
         self.commit = commit
         self.checker = checker
         self.keywords = defaultdict(list)
         self.include_url = include_url
-        
+
         # Generate directories affected by the commit
         commit_directories = [os.path.dirname(filename) for filename in \
commit.files_changed]  self.commit_directories = list( set(commit_directories) )
-        
+
     def from_header(self):
         """Helper function to construct a From header for emails - as Python stuffs \
it up"""  fixed_name = Header( self.commit.committer_name ).encode()
         return unicode("{0} <{1}>").format(fixed_name, self.commit.committer_email)
-        
+
     @property
     def subject(self):
         if len(self.commit_directories) == 1:
@@ -575,7 +598,7 @@ class MessageBuilder(object):
         if self.keywords['notes']:
             subject += ' (silent,notes)'
         return subject
-            
+
     @property
     def body(self):
         commit = self.commit
@@ -600,7 +623,7 @@ class MessageBuilder(object):
             if self.checker:
                 data.extend( self.checker.commit_notes[filename] )
             summary.append( ' '.join(data) )
-            
+
         if self.checker and self.checker.license_problem:
             summary.append( "\nThe files marked with a * at the end have a non valid \
                "
                 "license. Please read: \
http://techbase.kde.org/Policies/Licensing_Policy " @@ -614,7 +637,7 @@ class \
MessageBuilder(object):  if self.include_url:
             summary.append( "\n" + commit.url )
         return '\n'.join( summary ) + '\n'
-        
+
     def determine_keywords(self):
         """Parse special keywords in commits to determine further post-commit
         actions."""
@@ -651,7 +674,7 @@ class MessageBuilder(object):
                     results[name] = True
 
         self.keywords = results
-            
+
 class CiaNotifier(object):
     "Notifies CIA of changes to a repository"
 
@@ -734,7 +757,7 @@ class CiaNotifier(object):
 class Commit(object):
 
     """Represents a git commit"""
-    
+
     UrlPattern = "http://commits.kde.org/{0}/{1}"
 
     def __init__(self, repository, commit_data):
@@ -754,7 +777,7 @@ class Commit(object):
 
         value = self._commit_data[key]
         return unicode(value, "utf-8", 'replace')
-        
+
     def __setattr__(self, key, value):
         if key not in ['_commit_data', '_raw_properties', 'repository']:
             self._commit_data[key] = value
@@ -763,7 +786,7 @@ class Commit(object):
 
     def __repr__(self):
         return str(self._commit_data)
-        
+
 class CommitChecker(object):
 
     """Checker class for commit information such as licenses, or potentially
@@ -913,7 +936,7 @@ class CommitChecker(object):
     def check_commit_problems(self, commit, diff):
 
         """Check for potential problems in a commit."""
-        
+
         # Initialise
         self._license_problem = False
         self._commit_problem = False


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic