You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ne...@apache.org on 2011/05/20 15:10:33 UTC

svn commit: r1125370 - /subversion/trunk/contrib/hook-scripts/hook_toolbox.py

Author: neels
Date: Fri May 20 13:10:32 2011
New Revision: 1125370

URL: http://svn.apache.org/viewvc?rev=1125370&view=rev
Log:
* contrib/hook-scripts/hook_toolbox.py: Add file, courtesy of elego.

Added:
    subversion/trunk/contrib/hook-scripts/hook_toolbox.py

Added: subversion/trunk/contrib/hook-scripts/hook_toolbox.py
URL: http://svn.apache.org/viewvc/subversion/trunk/contrib/hook-scripts/hook_toolbox.py?rev=1125370&view=auto
==============================================================================
--- subversion/trunk/contrib/hook-scripts/hook_toolbox.py (added)
+++ subversion/trunk/contrib/hook-scripts/hook_toolbox.py Fri May 20 13:10:32 2011
@@ -0,0 +1,124 @@
+# Python module helpful for writing hook scripts.
+#
+# This is mostly an example for calling 'svnlook' and 'svn' from Python hooks
+# and for reading simple configuration files. While it's an example, this may
+# also be useful in a production environment as is.
+#
+# To use this, place this file next to your python hook scripts (e.g. in
+# 'repos/hooks/'). To be able use these functions, you may simply write:
+#   from hook_toolbox import *
+
+# NOTE: Adjust the BIN_PATH according to your operating system, to get valid
+# paths to your binaries (e.g. '/usr/bin/svnlook'):
+BIN_PATH = '/usr/bin'
+
+
+import sys, os, subprocess, shlex
+
+
+def get_log_message(*args):
+  '''Synopsis:
+       get_log_message(repos, '-t', transaction)   (from pre-commit hook)
+       get_log_message(repos, '-r', revision)      (from post-commit hook)
+     Returns the log message as a string.
+  '''
+  cmd = [os.path.join(BIN_PATH, 'svnlook'), 'propget', '--revprop']
+  cmd.extend(args)
+  cmd.append('svn:log')
+  return run(*cmd)
+
+
+def get_changed_paths(*args):
+  '''Synopsis:
+       get_changed_paths(repos, '-t', transaction)   (from pre-commit hook)
+       get_changed_paths(repos, '-r', revision)      (from post-commit hook)
+     Returns the list of changed paths, relative to the repository root.
+  '''
+  cmd = [os.path.join(BIN_PATH, 'svnlook'), 'changed']
+  cmd.extend(args)
+  changes = run(*cmd)
+  #print changes
+
+  # First four chars of each svnlook output line show the kind of change.
+  # The rest of the line is the complete repository path. See:
+  # http://svnbook.red-bean.com/nightly/en/svn.ref.svnlook.c.changed.html
+  changed_paths = [ line[4:] for line in changes.split('\n') if len(line) > 4 ]
+
+  #print '%s:\n '%(' '.join(args)), '\n  '.join(changed_paths)
+  return changed_paths
+
+  
+def has_path_changed(path, changed_paths):
+  '''Returns True if any changed path begins with the given path.
+     path: A path relative to the repos root, without leading slash.
+     changed_paths: A list obtained from the function get_changed_paths().'''
+
+  for changed_path in changed_paths:
+    if changed_path.startswith(path):
+      return True
+  return False
+
+
+def read_config(repos, filename, expected_tokens_per_line=-1):
+  '''Reads the file <repos>/conf/<filename> line wise and tokenizes each
+  line according to shell syntax rules. For example, a file like
+
+   # comments & blank lines ignored
+
+   aaa bb
+   cccc "d d d" ee
+   ff
+
+  would return a list
+
+   [ ['aaa', 'bb'],
+     ['cccc', 'd d d', 'ee'],
+     ['ff']                   ]
+
+  If expected_tokens_per_line is > 0, then only the lines matching the
+  given number of tokens are returned. In above example, passing
+  expected_tokens_per_line=2 would yield just:
+
+   [ ['aaa', 'bb'] ]
+
+  Returns an empty list if no such config file exists.
+  '''
+  path = os.path.join(repos, 'conf', filename)
+  if not os.path.exists(path):
+    print 'Not present:', path
+    return []
+
+  config_lines = open(path).readlines()
+
+  tokenized_lines = [ shlex.split(line, True) for line in config_lines ]
+  tokenized_lines = [ tokens for tokens in tokenized_lines if tokens ]
+
+  if expected_tokens_per_line < 1:
+    return tokenized_lines
+
+  matching_lines = [ tokens for tokens in tokenized_lines
+                     if len(tokens) == expected_tokens_per_line ]
+
+  if len(matching_lines) < len(tokenized_lines):
+    print '*** %d syntax errors in %s' % (
+             len(tokenized_lines) - len(matching_lines),
+             path)
+
+  return matching_lines
+
+
+def update_working_copy(wc_path):
+  if not os.path.exists(wc_path):
+    print '--> *** Cannot find working copy', wc_path
+    return None
+  return run(os.path.join(BIN_PATH, 'svn'), 'update', wc_path)
+
+
+def run(*cmd):
+  '''Call the given command & args and return what it printed to stdout.
+     e.g. result = run('/usr/bin/svn', 'info', wc_dir_path) '''
+  print '-->', ' '.join(cmd)
+  stdout = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
+  print stdout.strip()
+  return stdout
+