Index: precommit-hook
===================================================================
--- precommit-hook	(revision 0)
+++ precommit-hook	(revision 0)
@@ -0,0 +1,178 @@
+#!/usr/bin/env python
+
+# If you install this as a pre-commit hook in your Subversion repository, it
+# will only let proceed commits that has a valid, approved, not submited 
+# reviews stated somewhere in the commited message after the REVIEW: 
+# keyword. After commited the REVIEW will be marked as submit.
+# If the REVIEW: NEW sentence is found a new Review request is created and
+# its id printed in the error log.
+#
+# INSTALLATION:
+# A superuser status user is needed in order to control the reviewboard
+# its name and password is stated below.
+# post-review is needed in the hook dirs or in the python path and must
+# be renamed to postreview.py 
+# It is recommended to be call from the pre-commit with
+# REPOS="$1"
+# TXN="$2"
+# SVNLOOK=/usr/bin/svnlook
+# LOG=`$SVNLOOK log -t "$TXN" "$REPOS"`
+# AUTHOR=`$SVNLOOK author -t "$TXN" "$REPOS"`
+# FILES=`$SVNLOOK changed  -t "$TXN" "$REPOS"`
+# ${REPOS}/hooks/precommit_hook.py  "$REPOS" "$TXN" "$LOG"  "$FILES" "$AUTHOR" || exit -1
+
+
+
+import sys
+
+# The reviewboar server URL for API connection
+reviewboard_server="http://rvboard_server:8002/"
+# The SVN url as reviewboard knows this repository
+svn_server="http://svn/svn"
+# The user and password with superuser status
+args=["--password=rviewPw","--username=review_checker"]
+# The file extensions that force a review, None for all files force an
+# review
+#review_extensions = ['java','jsp', 'rb', 'erb', 'js', 'yml' ]
+review_extensions = None   
+
+# END of configuration
+
+
+repos = sys.argv[1]
+txn = sys.argv[2]
+log = sys.argv[3]
+files = sys.argv[4]
+author = sys.argv[5]
+
+# Checks if any of the files forces a review
+def need_to_be_reviewed(filesStr):
+   if review_extensions = None:
+     return True 
+   files = filesStr.splitlines()
+   for fileStr in files:
+     (type,fileName) = fileStr.split(None,1)
+     extension = fileName.rsplit('.',1)
+     if len(extension) < 2:
+        continue           
+     if (extension[1] in review_extensions):
+        return True
+
+def debug(str,exit=False):
+   print >>sys.stderr, str
+   if exit:
+      sys.exit(-1);
+      
+if not need_to_be_reviewed(files):
+   sys.exit(0)
+
+import postreview
+import re
+
+
+# A subclass of SVNClient that takes into account that is running in
+# a precommit hook so the change hasn't been commit yet.
+class SVNLookClient(postreview.SVNClient):
+   def __init__(self, transId, repo):
+      self.repo = repo
+      self.transId = transId
+   def get_repository_info(self):
+      return postreview.RepositoryInfo(path=svn_server,base_path='/')
+   
+   def diff(self, files):
+      return (self.do_diff(["/usr/bin/svnlook", "diff", "-t",  self.transId, self.repo] ),
+                                       None)
+
+   def svn_info(self, file):
+      result={}
+      result["URL"] = svn_server + file
+      result["Repository Root"] = svn_server
+      return result
+
+   def handle_renames(self, diff_content):
+        result = []
+
+        for line in diff_content:
+            if line.startswith('Copied:'):
+               copy_line = line
+               result.append(line)
+               continue
+            if line.startswith('---'):
+                if copy_line:
+                   m = re.search(r'^Copied: .* \(from rev (\d*), (.*)\)', copy_line, re.M)
+                   if m:
+                      from_file = m.group(2)
+                      rev = m.group(1)
+                      result.append("--- %s\t2008-12-09 18:29:40 UTC (rev %s)\n" % (from_file,rev))
+                      continue
+                else:
+                   m = re.search(r'(^--- [^\t]*)\t\s*\(rev 0\)', line, re.M)
+                   if m:
+                      result.append(m.group(1) + "\t2008-12-09 18:29:40 UTC (rev 0)\n")
+                      continue
+            if line != 67*'=' + '\n':
+               copy_line = None
+            result.append(line)
+
+        return result
+
+client=SVNLookClient(txn,repos)
+
+# Search for the REVIEW: line
+postreview.parse_options(client,client.get_repository_info() ,args)
+m = re.search(r'^REVIEW:\s*([0-9]+|new)', log, re.M | re.I )
+
+if not m:
+	print >>sys.stderr, """Tag REVIEW: not found in commit log, use post-review and/or go to %s to obtain review number""" % (reviewboard_server) 
+	exit(-1)
+
+id=m.group(1)
+p=postreview.ReviewBoardServer(reviewboard_server, client.get_repository_info(), "/tmp/cookie")
+try:
+  p.login()
+except:
+  print >>sys.stderr, "Wrong password, or reviewboard down."
+  sys.exit(-1)
+
+if id.lower() == "new":
+  # Create a new request with the diff
+  a = p.new_review_request(None, author)
+  repl = re.compile(r'^REVIEW:\s*new', re.M | re.I )
+  log = re.sub(repl,r'REVIEW: %s' % a['id'], log) 
+  logLines = log.splitlines()
+  p.set_review_request_field(a, 'summary', logLines[0])
+  p.set_review_request_field(a, 'description', "\n".join(logLines[1:]))
+  p.save_draft(a)
+  (diff,parent) = client.diff([])
+  p.upload_diff(a, diff, parent)
+  print >>sys.stderr, "NEW REQUEST %s\nRember to add REVIEW:%s to your comment log" % (a['id'],a['id'])
+  sys.exit(-1)
+
+try:
+  a=p.api_get('/api/json/reviewrequests/%s/' % id)
+except:
+  print >>sys.stderr, "Review %s not found, check the number or look here if it is right  ( %sr/%s )" % (id, reviewboard_server, id)
+  sys.exit(-1)
+
+if a['review_request']['status']=='submitted':
+  print  >>sys.stderr, "The review is already submitted check the url ( %sr/%s )" % (reviewboard_server, id)
+  sys.exit(-1)
+
+a=p.api_get('/api/json/reviewrequests/%s/reviews/' % id)
+approved=False
+for rev in a["reviews"]:
+  if rev['ship_it']:
+    approved = True
+    break
+
+if not approved:
+   #Upload the new diff if needed
+   (diff,parent) = client.diff([])
+   p.upload_diff(p.get_review_request(id), diff, parent)
+   print >>sys.stderr, "The review is not approved, bother the reviewers  ( %sr/%s )" % (reviewboard_server, id)
+   sys.exit(-1)
+
+#TODO MOVE THIS TO OTHER STEP (like a post commit hook)
+p.http_get('/api/json/reviewrequests/%s/close/submitted' % id)
+#TODO Should also publish the svn revision for checking the real changes.
+
