[projects/git-slug: 58/170] Introduce watch daemon

glen glen at pld-linux.org
Mon Sep 21 21:43:41 CEST 2015


commit 85265450223ffc83c735e509425dd076740b1feb
Author: Kacper Kornet <draenog at pld-linux.org>
Date:   Wed Sep 21 14:02:46 2011 +0200

    Introduce watch daemon
    
    To avoid global lock on all repositories post-receive hook does not
    longer modifies REFREPO. Instead it creates a file with unique name in
    WATCHDIR directory. REFREPO is updated by a daemon which watches the
    WATCHDIR by a inotify mechanism.

 git_slug/serverconst.py |  3 +++
 post-receive            | 19 +++++---------
 watch.py                | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+), 12 deletions(-)
---
diff --git a/git_slug/serverconst.py b/git_slug/serverconst.py
new file mode 100644
index 0000000..3d176ea
--- /dev/null
+++ b/git_slug/serverconst.py
@@ -0,0 +1,3 @@
+from os.path import join, expanduser
+
+WATCHDIR = expanduser('~/watchdir')
diff --git a/post-receive b/post-receive
index 751ad3a..d1c5f04 100755
--- a/post-receive
+++ b/post-receive
@@ -2,11 +2,13 @@
 
 import fcntl
 import os
+import tempfile
 import sys
 import subprocess
 
 from git_slug.refsdata import RemoteRefsData
 from git_slug.gitconst import REFREPO, REFFILE
+from git_slug.serverconst import WATCHDIR
 from git_slug.gitrepo import GitRepo
 
 
@@ -23,15 +25,8 @@ if gitrepo.startswith('packages/'):
 else:
     sys.exit()
 
-with open(os.path.join(os.getenv('HOME'), REFREPO, REFFILE), 'r+') as headfile:
-    fcntl.lockf(headfile, fcntl.LOCK_EX)
-    print('Lock obtained')
-    refs = RemoteRefsData(headfile, '*')
-    refs.put(gitrepo, data)
-    headfile.seek(0)
-    headfile.truncate()
-    refs.dump(headfile)
-    headfile.flush()
-    os.fsync(headfile.fileno())
-    headrepo = GitRepo(os.path.join(os.getenv('HOME'), REFREPO), os.path.join(os.getenv('GL_REPO_BASE_ABS'), REFREPO+'.git'))
-    headrepo.commitfile(REFFILE, 'Changes by {}'.format(os.getenv('GL_USER')))
+(tfile, name) = tempfile.mkstemp(prefix=gitrepo+'.', dir=WATCHDIR)
+os.write(tfile,(os.getenv('GL_USER')+'\n').encode('utf-8'))
+os.write(tfile,(gitrepo+'\n').encode('utf-8'))
+os.write(tfile,''.join(data).encode('utf-8'))
+os.close(tfile)
diff --git a/watch.py b/watch.py
new file mode 100755
index 0000000..7ee9625
--- /dev/null
+++ b/watch.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python3
+
+import heapq
+import os
+import pyinotify
+import shutil
+
+from git_slug.gitconst import REFREPO, REFFILE
+from git_slug.serverconst import WATCHDIR
+from git_slug.refsdata import RemoteRefsData
+from git_slug.gitrepo import GitRepo
+
+
+PIDFILE = os.path.expanduser('~/watch.pid')
+REFFILE_NEW = REFFILE + '.new'
+REFREPO_WDIR = os.path.expanduser('~/Refs')
+REFREPO_GDIR = os.path.join(os.path.expanduser('~/repositories'), REFREPO+'.git')
+
+WATCHDIR=WATCHDIR
+
+wm = pyinotify.WatchManager()  # Watch Manager
+mask = pyinotify.IN_CLOSE_WRITE # watched events
+
+def convertstream(stream):
+    for line in stream:
+        (sha1, ref, repo) = line.split()
+        yield (repo, ref, 1, sha1)
+
+def processnewfile(stream):
+    repo = stream.readline().strip()
+    for line in stream:
+        (sha1old, sha1, ref) = line.split()
+        if ref.startswith('refs/heads/'):
+            yield (repo, ref, 0, sha1)
+
+
+def process_file(pathname):
+    if not os.path.isfile(pathname):
+        print('{} is not an ordinary file'.format(pathname))
+        return
+    with open(os.path.join(REFREPO_WDIR, REFFILE),'r') as headfile, open(os.path.join(REFREPO_WDIR, REFFILE_NEW),'w') as headfile_new, open(pathname, 'r') as newfile:
+        committer = newfile.readline().strip()
+        oldtuple = None
+        for (repo, ref, number, sha1) in heapq.merge(sorted(processnewfile(newfile)), convertstream(headfile)):
+            if (repo, ref) == oldtuple:
+                continue
+            oldtuple = (repo, ref)
+            print(sha1, ref, repo, file=headfile_new)
+    shutil.copyfile(os.path.join(REFREPO_WDIR, REFFILE_NEW), os.path.join(REFREPO_WDIR, REFFILE))
+
+    headrepo = GitRepo(REFREPO_WDIR, REFREPO_GDIR)
+    headrepo.commitfile(REFFILE, 'Changes by {}'.format(committer))
+    os.remove(pathname)
+
+class EventHandler(pyinotify.ProcessEvent):
+    def process_IN_CLOSE_WRITE(self, event):
+        process_file(event.pathname)
+
+if not os.path.isdir(WATCHDIR):
+    print('Creating {}'.format(WATCHDIR))
+    os.mkdir(WATCHDIR)
+notifier = pyinotify.Notifier(wm, EventHandler())
+wdd = wm.add_watch(WATCHDIR, mask, rec=False)
+
+for filename in sorted(os.listdir(WATCHDIR), key=lambda f: os.stat(os.path.join(WATCHDIR, f)).st_mtime):
+    process_file(os.path.join(WATCHDIR,filename))
+
+notifier.loop(daemonize=True, pid_file=os.path.expanduser(PIDFILE),
+            stdout=os.path.expanduser('~/watch.stdout'))
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/projects/git-slug.git/commitdiff/4ed64f73960519a2f4fd04c42950b2c96ae795c5



More information about the pld-cvs-commit mailing list