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__ = [ ] + |