Daniel Shahaf wrote on Thu, Sep 06, 2012 at 09:07:58 +0100:
> RFC: teach svnwcsub to optionally run an arbitrary command (a hook)
> after updating the working copy. The interface might be:
> % ${/path/to/hook/from/config} "post-update" "/path/to/wc/root" "$URL" "$updated_to_revision"
>
> Use-case: we'd like to be able to change SQL schemas when deploying code
> to QA.
[[[
[in tools/server-side/svnpubsub]
Teach svnwcsub to run a post-update hook.
* example.conf
([DEFAULT].hook): New config value.
* svnwcsub.py
(BigDoEverythingClasss.__init__): Parse 'hook' from the config,
pass it to BackgroundWorker.__init__().
(BigDoEverythingClasss.wc_ready): Use OP_BOOT instead of OP_UPDATE.
(OP_BOOT): New op.
(BackgroundWorker.__init__): Grow 'hook' parameter.
(BackgroundWorker.run): Recognize OP_BOOT.
(BackgroundWorker._update): Grow 'boot' parameter. Run the hook
(in both OP_UPDATE and OP_BOOT).
]]]
[[[
Index: example.conf
===================================================================
--- example.conf (revision 1381512)
+++ example.conf (working copy)
@@ -3,6 +3,7 @@
[DEFAULT]
svnbin: /usr/local/bin/svn
streams: http://svn.example.org:2069/commits/xml
+hook: /usr/bin/true
## The values below are used by ConfigParser's interpolation syntax.
## See http://docs.python.org/library/configparser
Index: svnwcsub.py
===================================================================
--- svnwcsub.py (revision 1381512)
+++ svnwcsub.py (working copy)
@@ -132,7 +132,8 @@ class BigDoEverythingClasss(object):
self.svnbin = config.get_value('svnbin')
self.env = config.get_env()
self.tracking = config.get_track()
- self.worker = BackgroundWorker(self.svnbin, self.env)
+ self.hook = config.get_value('hook')
+ self.worker = BackgroundWorker(self.svnbin, self.env, self.hook)
self.watch = [ ]
self.hostports = [ ]
@@ -151,7 +152,7 @@ class BigDoEverythingClasss(object):
# Add it to our watchers, and trigger an svn update.
logging.info("Watching WC at %s <-> %s" % (wc.path, wc.url))
self.watch.append(wc)
- self.worker.add_work(OP_UPDATE, wc)
+ self.worker.add_work(OP_BOOT, wc)
def _normalize_path(self, path):
if path[0] != '/':
@@ -183,11 +184,12 @@ class BigDoEverythingClasss(object):
# Start logging warnings if the work backlog reaches this many items
BACKLOG_TOO_HIGH = 20
+OP_BOOT = 'boot'
OP_UPDATE = 'update'
OP_CLEANUP = 'cleanup'
class BackgroundWorker(threading.Thread):
- def __init__(self, svnbin, env):
+ def __init__(self, svnbin, env, hook):
threading.Thread.__init__(self)
# The main thread/process should not wait for this thread to exit.
@@ -196,6 +198,7 @@ class BackgroundWorker(threading.Thread):
self.svnbin = svnbin
self.env = env
+ self.hook = hook
self.q = Queue.Queue()
self.has_started = False
@@ -210,6 +213,8 @@ class BackgroundWorker(threading.Thread):
try:
if operation == OP_UPDATE:
self._update(wc)
+ if operation == OP_BOOT:
+ self._update(wc, boot=True)
elif operation == OP_CLEANUP:
self._cleanup(wc)
else:
@@ -229,7 +234,7 @@ class BackgroundWorker(threading.Thread):
self.q.put((operation, wc))
- def _update(self, wc):
+ def _update(self, wc, boot=False):
"Update the specified working copy."
# For giggles, let's clean up the working copy in case something
@@ -263,6 +268,12 @@ class BackgroundWorker(threading.Thread):
raise
open(dotrevision, 'w').write(info['Revision'])
+ ## Run the hook
+ if self.hook:
+ args = [self.hook, ['post-update', 'boot'][boot],
+ wc.path, info['Revision'], wc.url]
+ subprocess.check_call(args, env=self.env)
+
def _cleanup(self, wc):
"Run a cleanup on the specified working copy."
]]]
Received on 2012-09-06 10:49:06 CEST