From e00de1a6160b3928bb19548d36ce6cda1819d907 Mon Sep 17 00:00:00 2001 From: lilydjwg Date: Tue, 8 Aug 2017 14:54:32 +0800 Subject: [PATCH] add support for a spool directory --- archrepo.ini.example | 5 +++ archrepo2/__init__.py | 2 +- archrepo2/archreposrv.py | 8 +++-- archrepo2/repomon.py | 67 ++++++++++++++++++++++++++++++++++++---- 4 files changed, 72 insertions(+), 10 deletions(-) diff --git a/archrepo.ini.example b/archrepo.ini.example index 5d37b75..53afa53 100644 --- a/archrepo.ini.example +++ b/archrepo.ini.example @@ -19,6 +19,11 @@ name: archlinuxcn # files in this directory, remember to update the configuration of inotify. path: /home/lilydjwg/tmpfs/test +# If enabled, packages put into this directory will be moved into the repo. +# This path should be on the same filesystem as the repo path +# Should be used with auto-rename on +#spool-directory: /tmp/repo + # A database to store package info. Default to ${path}/pkginfo.db #info-db: /home/lilydjwg/tmpfs/test/pkginfo.db diff --git a/archrepo2/__init__.py b/archrepo2/__init__.py index 5a6f84c..29a4dbe 100644 --- a/archrepo2/__init__.py +++ b/archrepo2/__init__.py @@ -1 +1 @@ -__version__ = '0.5' +__version__ = '0.6dev' diff --git a/archrepo2/archreposrv.py b/archrepo2/archreposrv.py index c5ee515..923e71e 100755 --- a/archrepo2/archreposrv.py +++ b/archrepo2/archreposrv.py @@ -33,16 +33,18 @@ def main(): config.read(conffile) repos = check_and_get_repos(config) - notifiers = [repomon(config[repo]) for repo in repos] + notifiers = [] + for repo in repos: + notifiers.extend(repomon(config[repo])) - ioloop = IOLoop.instance() + ioloop = IOLoop.current() logger.info('starting archreposrv.') try: ioloop.start() except KeyboardInterrupt: - ioloop.close() for notifier in notifiers: notifier.stop() + ioloop.close() print() if __name__ == '__main__': diff --git a/archrepo2/repomon.py b/archrepo2/repomon.py index 4b55e1f..4febc91 100755 --- a/archrepo2/repomon.py +++ b/archrepo2/repomon.py @@ -34,7 +34,6 @@ def same_existent_file(a, b): class ActionInfo(archpkg.PkgNameInfo): def __new__(cls, path, action, four=None, five=None, pkgpath=None): - print(path, action, four) if four is not None: return super().__new__(cls, path, action, four, five) file = os.path.split(pkgpath or path)[1] @@ -53,7 +52,7 @@ class RepoMan: def __init__(self, config, base, ioloop=None): self.action = [] - self._ioloop = ioloop or IOLoop.instance() + self._ioloop = ioloop or IOLoop.current() self._base = base self._repo_dir = config.get('path') @@ -225,7 +224,7 @@ class EventHandler(pyinotify.ProcessEvent): self.repomans = {} # TODO: use an expiring dict self.our_links = set() - self._ioloop = ioloop or IOLoop.instance() + self._ioloop = ioloop or IOLoop.current() base = config.get('path') dbname = config.get('info-db', os.path.join(base, 'pkginfo.db')) @@ -467,7 +466,7 @@ def pkgsortkey(path): def repomon(config): wm = pyinotify.WatchManager() - ioloop = IOLoop.instance() + ioloop = IOLoop.current() supported_archs = config.get('supported-archs', 'i686 x86_64').split() if 'any' not in supported_archs: @@ -484,8 +483,64 @@ def repomon(config): wm = wm, ioloop = ioloop, ) - return pyinotify.TornadoAsyncNotifier( + ret = [pyinotify.TornadoAsyncNotifier( wm, ioloop, default_proc_fun=handler, - ) + )] + + if config.get('spool-directory'): + wm = pyinotify.WatchManager() + handler = SpoolHandler( + filter_func, + filter_pkg = filter_func, + path = config.get('spool-directory'), + dstpath = os.path.join(config.get('path'), 'any'), + wm = wm, + ) + ret.append(pyinotify.TornadoAsyncNotifier( + wm, ioloop, + default_proc_fun=handler, + )) + + return ret + +class SpoolHandler(pyinotify.ProcessEvent): + def my_init(self, filter_pkg, path, dstpath, wm): + self.filter_pkg = filter_pkg + self.dstpath = dstpath + + files = set() + for f in os.listdir(path): + p = os.path.join(path, f) + if os.path.exists(p): # filter broken symlinks + files.add(p) + + wm.add_watch(path, pyinotify.IN_CLOSE_WRITE | pyinotify.IN_CREATE | + pyinotify.IN_MOVED_TO) + self._initial_update(files) + + def _initial_update(self, files): + for f in sorted(filterfalse(self.filter_pkg, files), + key=pkgsortkey): + self.dispatch(f) + + def process_IN_CLOSE_WRITE(self, event): + logger.debug('Writing done: %s', event.pathname) + self.dispatch(event.pathname) + + def process_IN_CREATE(self, event): + file = event.pathname + if os.path.islink(file): + logger.debug('Symlinked: %s', file) + else: + logger.debug('Linked: %s', file) + self.dispatch(file) + + def process_IN_MOVED_TO(self, event): + logger.debug('Moved here: %s', event.pathname) + self.dispatch(event.pathname) + + def dispatch(self, path): + filename = os.path.basename(path) + os.rename(path, os.path.join(self.dstpath, filename))