diff options
| author | Nick Mathewson <nickm@torproject.org> | 2008-11-16 20:15:34 +0000 | 
|---|---|---|
| committer | Nick Mathewson <nickm@torproject.org> | 2008-11-16 20:15:34 +0000 | 
| commit | c5749895ab4f6893bdf1d398691d1dd33e81574c (patch) | |
| tree | 4ee47c3c6c56e313c3074f04c77a3637cf0fe31d /lib/thandy/packagesys | |
| parent | 02a2e5807f23ad0cad9a49b5febe08ec25fcc74c (diff) | |
have some more thandy.  This update includes a working downloader with tor support, a package system framework, and more.  Most of what's left is glue code.
git-svn-id: file:///home/or/svnrepo/updater/trunk@17288 55e972cd-5a19-0410-ae62-a4d7a52db4cd
Diffstat (limited to 'lib/thandy/packagesys')
| -rw-r--r-- | lib/thandy/packagesys/ExePackages.py | 33 | ||||
| -rw-r--r-- | lib/thandy/packagesys/PackageDB.py | 81 | ||||
| -rw-r--r-- | lib/thandy/packagesys/PackageSystem.py | 58 | ||||
| -rw-r--r-- | lib/thandy/packagesys/RPMPackages.py | 156 | ||||
| -rw-r--r-- | lib/thandy/packagesys/__init__.py | 4 | 
5 files changed, 332 insertions, 0 deletions
| diff --git a/lib/thandy/packagesys/ExePackages.py b/lib/thandy/packagesys/ExePackages.py new file mode 100644 index 0000000..1688da3 --- /dev/null +++ b/lib/thandy/packagesys/ExePackages.py @@ -0,0 +1,33 @@ +# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information. + +import thandy.packagesys.PackageSystem as ps +import thandy.packagesys.PackageDB as pdb + +class ExePackageSystem(pdb.DBBackedPackageSystem): + +    def getName(self): +        return "executable" + +    def packageHandleFromJSON(self, json): +        raise NotImplemented()  #XXXX???? + +    def canBeAutomatic(self): +        return True + +    def canHaveUI(self): +        return True + +class ExePackageHandle(pdb.DBBackedPackageHandle): +    def __init__(self, packageDB, name, version, filelist, filename, +                 arguments): +        pdb.DBBackedPackageHandle.__init__(packageDB, name, version, filelist) +        self._filename = filename +        self._arguments = arguments + +    def _doInstall(self): +        commandline = [ self._filename ] + self._arguments +        logging.info("Installing %s.  Command line: %s", self._filename, +                     commandLine) +        subprocess.call(commandline) + + diff --git a/lib/thandy/packagesys/PackageDB.py b/lib/thandy/packagesys/PackageDB.py new file mode 100644 index 0000000..bb218be --- /dev/null +++ b/lib/thandy/packagesys/PackageDB.py @@ -0,0 +1,81 @@ +# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information. + +import anydbm +import shelve + +import thandy.util +import thandy.formats + +class SimplePackageDB: + +    def __init__(self, filename): +        self._db = anydbm.open(filename, 'c') + +    def setVersion(self, package, version, filelist): +        pass + +    def setInstallParameters(self, package, params): +        pass + +    def getCurVersion(self, package): +        pass + +    def getInstallParameters(self, package): +        pass + + +class DBBackedPackageSystem(thandy.packagesys.PackageSystem): +    def __init__(self, packageDB): +        self._packageDB = packageDB + +class DBBackedPackageHandle(thandy.packagesys.PackageHandle): +    def __init__(self, packageDB, name, version, filelist): +        thandy.packagesys.PackageSystem.PackageHandle.__init__(self) +        self._packageDB = packageDB +        self._name = name +        self._version = version +        self._filelist = filelist + +        self._metaData = None + +    def _getInstallBase(self): +        raise NotImplemented() + +    def anyVersionInstalled(self, transaction=None): +        return self._packageDB.getCurVersion(self._name) != None + +    def getInstalledVersion(self, transaction=None): +        return self._packageDB.getCurVersion(self._name) + +    def install(self): +        params = self._doInstall() +        self._packageDB.setCurVersion( +            self._name, self._version, self._filelist) +        self._packageDB.setInstallParameters(self._name, params) + +    def _doInstall(self): +        raise NotImplemented() + +    def isInstalled(self): +        return self.getInstalledVersion(self, transaction) == self._version + +    def checkInstall(self): +        base = self._getInstallBase() + +        all_ok = True +        for fn, hash in self._filelist: +            fn = os.path.join(base, fn) +            if not os.path.exists(fn): +                all_ok = False +            else: +                f = open(fn, 'rb') +                try: +                    try: +                        d = thandy.formats.getFileDigest(f) +                    except OSError: +                        all_ok = False +                        break +                finally: +                    f.close() + +        return all_ok diff --git a/lib/thandy/packagesys/PackageSystem.py b/lib/thandy/packagesys/PackageSystem.py new file mode 100644 index 0000000..ad1e221 --- /dev/null +++ b/lib/thandy/packagesys/PackageSystem.py @@ -0,0 +1,58 @@ +# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information. + +class PackageSystem: +    def getName(self): +        raise NotImplemented() + +    def packageHandleFromJSON(self, json): +        raise NotImplemented() + +    def canBeAutomatic(self): +        return True + +    def canHaveUI(self): +        return False + +    def getTransaction(self): +        return PackageTransaction() + +class PackageTransaction: +    def __init__(self): +        self._transactions = [] + +    def _start(self): +        pass + +    def _commit(self): +        pass + +    def run(self): +        self._start() +        for cb in self._transactions: +            cb(self) +        self._commit() + +    def addInstall(self, packageHandle): +        self._transactions.append(packageHandle.install) + +    def addRemove(self, packageHandle): +        self._transactions.append(packageHandle.remove) + +class PackageHandle: +    def isInstalled(self, transaction=None): +        raise NotImplemented() + +    def anyVersionInstalled(self, transaction=None): +        raise NotImplemented() + +    def getInstalledVersion(self, transaction=None): +        raise NotImplemented() + +    def install(self, transaction): +        raise NotImplemented() + +    def remove(self, transaction): +        raise NotImplemented() + +    def checkInstall(self, transaction=None): +        raise NotImplemented() diff --git a/lib/thandy/packagesys/RPMPackages.py b/lib/thandy/packagesys/RPMPackages.py new file mode 100644 index 0000000..5e4c960 --- /dev/null +++ b/lib/thandy/packagesys/RPMPackages.py @@ -0,0 +1,156 @@ +# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information. + +import thandy.packagesys.PackageSystem + +import os +import rpm +import md5 + +__all__ = [ 'RPMPackageSystem' ] + +class RPMPackageSystem(thandy.packagesys.PackageSystem.PackageSystem): +    def getName(self): +        return "RPM" + +    def packageHandleFromJSON(self, json): +        raise NotImplemented() # XXXX + +    def getTransaction(self): +        return RPMPackageTransaction() + +_CALLBACK_CODES = {} + +for name in dir(rpm): +    if name.startswith("RPMCALLBACK_"): +        _CALLBACK_CODES[getattr(rpm, name)] = name[12:] +del name + +class RPMPackageTransaction(thandy.packagesys.PackageSystem.PackageTransaction): + +    def _start(self): +        thandy.packagesys.PackageSystem.PackageTransaction.__init__(self) +        self._tset = rpm.TransactionSet() + +    def _commit(self): +        self._tset.run(self._callback, "") + +    def _callback(self, what, amount, total, mydata, _): +        if what == rpm.RPMCALLBACK_INST_OPEN_FILE: +            hdr, path = mydata +            logging.info("Installing RPM for %s [%s]", hdr['name'], path) + +        elif what == rpm.RPMCALLBACK_INST_CLOSE_FILE: +            hdr, path = mydata +            logging.info("Done installing RPM for %s", path) + +        elif what == rpm.RPMCALLBACK_INST_PROGRESS: +            hdr, path = mydata +            logging.info("%s: %.5s%% done", name, float(amount)/total*100) + +        else: +            hdr, path = mydata +            logging.info("RPM event %s on %s [%s/%s]", +                         _CALLBACK_CODES.get(what,str(what)), +                         hdr['name'], amount, total) + +def addRPMInstall(ts, path): +    fd = os.open(path, os.O_RDONLY) +    try: +        hdr = ts.hdrFromFdno(fd) +    finally: +        os.close(fd) +    ts.addInstall(hdr, (hdr, path), "u") + +def addRPMErase(ts, name): +    ts.addErase(name) + +def getInstalledRPMVersions(name, ts=None): +    if ts is None: +        ts = rpm.TransactionSet() +        #XXXX need to close? + +    versions = set() +    for match in ts.dbMatch(rpm.RPMTAG_NAME, name): +        versions.add(match['version']) + +    return versions + +def fileMD5(fname): +    d = md5.new() +    try: +        f = open(fname, 'r') +        try: +            while 1: +                s = f.read(4096) +                if not s: +                    break +                d.update(s) + +        finally: +            f.close() +    except OSError, e: +        logging.warn("Couldn't get digest of %s: %s", fname, e) +        return None + +    return d.hexdigest() + +def checkRPMInstall(name, version, ts=None): +    if ts is None: +        ts = rpm.TransactionSet() +        #XXXX need to close? + +    found = False +    all_ok = True + +    for h in ts.dbMatch(rpm.RPMTAG_NAME, name): +        if h['version'] != version: +            continue + +        found = True + +        for fname, flags, md5sum in zip(h['filenames'], h['fileflags'], h['filemd5s']): +            haveMD5 = fileMD5(fname) +            if not haveMD5: +                if flags & RPMFILE_MISSINGOK: +                    logging.info("%s is missing or unreadable from %s %s; " +                                 "that's ok.", fname, name, h['version']) +                else: +                    logging.warn("%s is missing or unreadable from %s %s." +                                 fname, name, h['version']) +                    all_ok = False +            elif haveMD5 == md5sum: +                logging.info("%s is unchanged from %s %s", +                             fname, name, h['version']) +            else: +                # file changed.  If it's not configuration, that's a problem. +                if not flags & RPMFILE_CONFIG: +                    logging.warn("%s changed from installed version of %s %s", +                                 fname, name, h['version']) +                    all_ok = False + +    return found and all_ok + +class RPMPackageHandle(thandy.packagesys.PackageSystem.PackageHandle): +    def __init__(self, name, version, filename): +        self._name = name +        self._version = version +        self._filename = filename + +    def anyVersionInstalled(self, transaction=None): +        return len(getInstalledRPMVersions(self.name, transaction)) > 1 + +    def getInstalledVersion(self, transaction=None): +        s = max(getInstalledRPMVersions(self._name, transaction)) + +    def install(self, transaction): +        addRPMInstall(transaction._trans, self._filename) + +    def remove(self, transaction): +        addRPMErase(transaction._trans, self._name) + +    def isInstalled(self, transaction=None): +        return self._version in getInstalledRPMVersions(self._name,transaction) + +    def checkInstall(self, transaction=None): +        return checkRPMInstall(self._name, self._version) + diff --git a/lib/thandy/packagesys/__init__.py b/lib/thandy/packagesys/__init__.py new file mode 100644 index 0000000..4dd7019 --- /dev/null +++ b/lib/thandy/packagesys/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information. + +__all__ = [ ] + | 
