[Pkg-bazaar-commits] r191 ./bzr-builddeb/people/jdw/dev: Internal hook execution support.

James Westby jw+debian at jameswestby.net
Sun Sep 16 17:48:11 UTC 2007


------------------------------------------------------------
revno: 191
committer: James Westby <jw+debian at jameswestby.net>
branch nick: dev
timestamp: Sun 2007-09-16 18:48:11 +0100
message:
  Internal hook execution support.
  
  Hooks are run from the [HOOKS] section of the config files, with the normal
  precedence rules.
  
  Undefined hooks are ignored, and failing hooks raise an exception.
  
  There is no policy defined here on the names of hooks, nor where they are
  executed, and passed hook name will be looked up, and the working directory
  for the hook can also be passed.
added:
  hooks.py
  tests/test_hooks.py
modified:
  config.py
  errors.py
  tests/__init__.py
-------------- next part --------------
=== added file 'hooks.py'
--- a/hooks.py	1970-01-01 00:00:00 +0000
+++ b/hooks.py	2007-09-16 17:48:11 +0000
@@ -0,0 +1,40 @@
+#    hooks.py -- Hook support for builddeb.
+#    Copyright (C) 2006 James Westby <jw+debian at jameswestby.net>
+#    
+#    This file is part of bzr-builddeb.
+#
+#    bzr-builddeb is free software; you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation; either version 2 of the License, or
+#    (at your option) any later version.
+#
+#    bzr-builddeb is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with bzr-builddeb; if not, write to the Free Software
+#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+import subprocess
+
+from bzrlib.trace import info
+
+from errors import HookFailedError
+
+
+def run_hook(hook_name, config, wd=None):
+  hook = config.get_hook(hook_name)
+  if hook is None:
+    return
+  info("Running %s as %s hook" % (hook, hook_name))
+  kwargs = {}
+  if wd is not None:
+    kwargs['cwd'] = wd
+  proc = subprocess.Popen(hook, shell=True, **kwargs)
+  proc.wait()
+  if proc.returncode != 0:
+    raise HookFailedError(hook_name)
+

=== added file 'tests/test_hooks.py'
--- a/tests/test_hooks.py	1970-01-01 00:00:00 +0000
+++ b/tests/test_hooks.py	2007-09-16 17:48:11 +0000
@@ -0,0 +1,107 @@
+#    test_hooks.py -- Tests for builddeb hooks.
+#    Copyright (C) 2006 James Westby <jw+debian at jameswestby.net>
+#    
+#    This file is part of bzr-builddeb.
+#
+#    bzr-builddeb is free software; you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation; either version 2 of the License, or
+#    (at your option) any later version.
+#
+#    bzr-builddeb is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with bzr-builddeb; if not, write to the Free Software
+#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+import os
+
+from bzrlib.tests import TestCaseInTempDir
+
+from config import DebBuildConfig
+from errors import HookFailedError
+from hooks import run_hook
+
+
+class HookTests(TestCaseInTempDir):
+
+  default_conf = 'default.conf'
+  local_conf = 'local.conf'
+
+  def test_run_hook_allows_no_hook_defined(self):
+    f = open(self.default_conf, 'wb')
+    f.close()
+    config = DebBuildConfig([(self.default_conf, False)])
+    run_hook('pre-build', config)
+
+  def test_run_hook_raises_when_hook_fails(self):
+    f = open(self.default_conf, 'wb')
+    try:
+      f.write('[HOOKS]\npre-build = false\n')
+    finally:
+      f.close()
+    config = DebBuildConfig([(self.default_conf, False)])
+    self.assertRaises(HookFailedError, run_hook, 'pre-build', config)
+
+  def test_run_hook_when_hook_passes(self):
+    f = open(self.default_conf, 'wb')
+    try:
+      f.write('[HOOKS]\npre-build = true\n')
+    finally:
+      f.close()
+    config = DebBuildConfig([(self.default_conf, False)])
+    run_hook('pre-build', config)
+
+  def test_run_hook_uses_cwd_by_default(self):
+    f = open(self.default_conf, 'wb')
+    try:
+      f.write('[HOOKS]\npre-build = touch a\n')
+    finally:
+      f.close()
+    config = DebBuildConfig([(self.default_conf, False)])
+    run_hook('pre-build', config)
+    self.failUnlessExists('a')
+
+  def test_run_hook_uses_passed_wd(self):
+    os.mkdir('dir')
+    f = open(self.default_conf, 'wb')
+    try:
+      f.write('[HOOKS]\npre-build = touch a\n')
+    finally:
+      f.close()
+    config = DebBuildConfig([(self.default_conf, False)])
+    run_hook('pre-build', config, wd='dir')
+    self.failUnlessExists('dir/a')
+
+  def test_run_hook_uses_shell(self):
+    f = open(self.default_conf, 'wb')
+    try:
+      f.write('[HOOKS]\npost-build = touch a && touch b\n')
+    finally:
+      f.close()
+    config = DebBuildConfig([(self.default_conf, False)])
+    run_hook('post-build', config)
+    self.failUnlessExists('a')
+    self.failUnlessExists('b')
+
+  def test_run_hook_uses_local_over_global(self):
+    f = open(self.default_conf, 'wb')
+    try:
+      f.write('[HOOKS]\npost-build = touch a\n')
+    finally:
+      f.close()
+    f = open(self.local_conf, 'wb')
+    try:
+      f.write('[HOOKS]\npost-build = touch b\n')
+    finally:
+      f.close()
+    config = DebBuildConfig([(self.local_conf, False),
+                             (self.default_conf, False)])
+    run_hook('post-build', config)
+    self.failIfExists('a')
+    self.failUnlessExists('b')
+

=== modified file 'config.py'
--- a/config.py	2007-09-15 17:32:44 +0000
+++ b/config.py	2007-09-16 17:48:11 +0000
@@ -127,15 +127,17 @@
     else:
       self._branch_config = None
 
-  def _get_opt(self, config, key):
+  def _get_opt(self, config, key, section=None):
     """Returns the value for key from config, of None if it is not defined in 
     the file"""
+    if section is None:
+      section = self.section
     try:
-      return config.get_value(self.section, key)
+      return config.get_value(section, key)
     except KeyError:
       return None
 
-  def _get_best_opt(self, key, trusted=False):
+  def _get_best_opt(self, key, trusted=False, section=None):
     """Returns the value for key, obeying precedence.
     
     Returns the value for the key from the first file in which it is defined,
@@ -145,6 +147,8 @@
     marked as trusted.
     
     """
+    if section is None:
+      section = self.section
     if self._branch_config is not None:
       if not trusted:
         value = self._branch_config.get_option(key, section=self.section)
@@ -153,13 +157,16 @@
           return value
     for config_file in self._config_files:
       if not trusted or config_file[1]:
-        value = self._get_opt(config_file[0], key)
+        value = self._get_opt(config_file[0], key, section=section)
         if value is not None:
           mutter("Using %s for %s, taken from %s", value, key,
                  config_file[0].filename)
           return value
     return None
 
+  def get_hook(self, hook_name):
+    return self._get_best_opt(hook_name, section='HOOKS')
+
   def _get_bool(self, config, key):
     try:
       return True, config.get_bool('BUILDDEB', key)

=== modified file 'errors.py'
--- a/errors.py	2007-09-13 21:56:04 +0000
+++ b/errors.py	2007-09-16 17:48:11 +0000
@@ -68,3 +68,10 @@
     BzrError.__init__(self)
     self.reason = reason
 
+class HookFailedError(BzrError):
+  _fmt = """The %(hook_name)s hook failed."""
+
+  def __init__(self, hook_name):
+    BzrError.__init__(self)
+    self.hook_name = hook_name
+

=== modified file 'tests/__init__.py'
--- a/tests/__init__.py	2007-09-13 21:56:04 +0000
+++ b/tests/__init__.py	2007-09-16 17:48:11 +0000
@@ -136,6 +136,7 @@
     testmod_names = [
             'test_builder',
             'test_config',
+            'test_hooks',
             'test_import_dsc',
             'test_repack_tarball_extra',
             'test_util',



More information about the Pkg-bazaar-commits mailing list