diff --git a/README.mkd b/README.mkd index aabd0cc..2b84eb8 100644 --- a/README.mkd +++ b/README.mkd @@ -5,7 +5,7 @@ Edit a copy of `archrepo.ini` and then run `./archreposrv `. DEPENDENCIES ==== -* Python, >= 3.3 +* Python, >= 3.3, with gdbm support * tornado, > 2.4.1 * pyinotify, tested 0.9.4 * winterpy diff --git a/archrepo.ini b/archrepo.ini index 7ac1d6e..fbf954f 100644 --- a/archrepo.ini +++ b/archrepo.ini @@ -8,6 +8,9 @@ name: archlinuxcn # files in this directory, remember to update the configuration of inotify. path: /home/lilydjwg/tmpfs/test +# A database to store package filenames. Default to ${path}/repofiles.db +#files-db: /home/lilydjwg/tmpfs/test/repofiles.db + # Specify where to find these commands #command-add: repo-add #command-remove: repo-remove diff --git a/archreposrv b/archreposrv index 12ff2cd..111b97d 100755 --- a/archreposrv +++ b/archreposrv @@ -7,6 +7,7 @@ import configparser from functools import partial import queue import logging +import dbm.gnu import pyinotify from tornado.ioloop import IOLoop @@ -16,6 +17,8 @@ import archpkg from myutils import enable_pretty_logging enable_pretty_logging(logging.DEBUG) +# FIXME: 如果一个软件包消失了,那么如果它在仓库数据库里,它就应当从数据库删除。否则不应该 + class ActionInfo: def __init__(self, path, action): self.pkginfo = archpkg.parsePkgName(path) @@ -116,11 +119,13 @@ class RepoMan: class EventHandler(pyinotify.ProcessEvent): def my_init(self, config, wm, ioloop=None): self.moved_away = {} - self.files = files = set() self.repomans = {} self._ioloop = ioloop or IOLoop.instance() base = config.get('path') + dbname = config.get('files-db', os.path.join(base, 'repofiles.db')) + self._db = dbm.gnu.open(dbname, 'cs') + dirs = [os.path.join(base, x) for x in ('any', 'i686', 'x86_64')] for d in dirs: @@ -128,6 +133,15 @@ class EventHandler(pyinotify.ProcessEvent): wm.add_watch(d, pyinotify.ALL_EVENTS) self.repomans[d] = RepoMan(config, d, self._ioloop) + self._initial_update(files) + + def _initial_update(self, files): + oldfiles = {f.decode('utf-8') for f in self._db.keys()} + for f in files - oldfiles: + self.dispatch(f, 'add') + for f in oldfiles - files: + self.dispatch(f, 'remove') + def process_IN_CLOSE_WRITE(self, event): logging.debug('Writing done: %s', event.pathname) self.dispatch(event.pathname, 'add') @@ -188,7 +202,7 @@ class EventHandler(pyinotify.ProcessEvent): newpath = os.path.join(newd, file) if action == 'add': os.symlink(os.path.join('..', arch, file), newpath) - self.repomans[newd].add_action(ActionInfo(newpath, action)) + self._real_dispatch(newd, ActionInfo(newpath, action)) else: try: os.unlink(newpath) @@ -197,6 +211,18 @@ class EventHandler(pyinotify.ProcessEvent): # someone deleted the file for us pass + self._real_dispatch(d, act) + + def _real_dispatch(self, d, act): + key = act.path.encode('utf-8') + if act.action == 'add': + self._db[key] = b'\x01' + else: + try: + del self._db[key] + except KeyError: + logging.warn('files db inconsistent: key %s not there', key) + self.repomans[d].add_action(act) # def process_default(self, event):