From 2fe77ca953e916966a28e4cf3895565a464cc8fd Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 17 Nov 2008 20:55:28 +0000 Subject: Add win32 registry support to thandy. untested. git-svn-id: file:///home/or/svnrepo/updater/trunk@17319 55e972cd-5a19-0410-ae62-a4d7a52db4cd --- lib/thandy/formats.py | 27 ++++++++++++++++++++++++--- lib/thandy/packagesys/ExePackages.py | 23 +++++++++++++++++++++-- lib/thandy/packagesys/PackageDB.py | 2 +- lib/thandy/util.py | 20 ++++++++++++++++++++ samples/example-package.cfg | 13 +++++++++++-- 5 files changed, 77 insertions(+), 8 deletions(-) diff --git a/lib/thandy/formats.py b/lib/thandy/formats.py index ff65173..e047d87 100644 --- a/lib/thandy/formats.py +++ b/lib/thandy/formats.py @@ -456,6 +456,18 @@ PACKAGE_SCHEMA = S.Obj( shortdesc=S.DictOf(S.AnyStr(), S.AnyStr()), longdesc=S.DictOf(S.AnyStr(), S.AnyStr())) +def checkWinRegistryKeyname(keyname): + """Check keyname for superficial well-formedness as a win32 registry entry + name.""" + hkey, rest = keyname.split("\\", 1) + key, value = rest.rsplit("\\", 1) + if hkey not in [ "HKEY_CURRENT_CONFIG", + "HKEY_CURRENT_USER", + "HKEY_LOCAL_MACHINE" ]: + raise thandy.FormatException("Bad hkey on registry entry.") + elif not key or not value: + raise thandy.FormatException("Bad registry entry.") + ALL_ROLES = ('timestamp', 'mirrors', 'bundle', 'package', 'master') class Key: @@ -613,7 +625,8 @@ def makePackageObj(config_fname, package_fname): 'format', 'location', 'relpath', - ], ['rpm_version', 'exe_args'], preload) + ], ['rpm_version', 'exe_args', + 'exe_registry_ent' ], preload) f = open(package_fname, 'rb') digest = getFileDigest(f) @@ -633,12 +646,20 @@ def makePackageObj(config_fname, package_fname): if format == 'rpm': if not r.get('rpm_version'): - raise Thandy.FormatException("missing rpm_version value") + raise thandy.FormatException("missing rpm_version value") extra['rpm_version'] = r['rpm_version'] elif format == 'exe': if not r.get('exe_args'): - raise Thandy.FormatException("missing exe_args value") + raise thandy.FormatException("missing exe_args value") extra['exe_args'] = r['exe_args'] + if r.get('exe_registry_ent'): + if len(exe_registry_ent) != 2: + raise thandy.FormatException("Bad length on exe_registry_ent") + regkey, regval = r['exe_registry_ent'] + checkWinRegistryKeyname(regkey) + if not isinstance(regval, basestring): + raise thandy.FormatException("Bad version on exe_registry_ent") + extra['registry_ent'] = [ regkey, regval ] PACKAGE_SCHEMA.checkMatch(result) diff --git a/lib/thandy/packagesys/ExePackages.py b/lib/thandy/packagesys/ExePackages.py index 4989f3a..d82d86e 100644 --- a/lib/thandy/packagesys/ExePackages.py +++ b/lib/thandy/packagesys/ExePackages.py @@ -31,7 +31,8 @@ class ExePackageSystem(pdb.DBBackedPackageSystem): [], # filelist not implemented in this. rp, self._repo.getFilename(rp), - extra['exe_args'])) + arguments=extra['exe_args'], + registry_ent=extra.get('registry_ent'))) return handles def canBeAutomatic(self): @@ -42,15 +43,33 @@ class ExePackageSystem(pdb.DBBackedPackageSystem): class ExePackageHandle(pdb.DBBackedPackageHandle): def __init__(self, packageDB, name, version, filelist, relpath, filename, - arguments): + arguments, registry_ent=None): pdb.DBBackedPackageHandle.__init__(packageDB, name, version, filelist) self._relPath = relpath self._filename = filename self._arguments = arguments + self._registry_ent = registry_ent def getRelativePath(self): return self._relPath + def getInstalledVersion(self, transaction=None): + if self._registry_ent != None: + ver = thandy.util.getRegistryValue(self._registry_ent[0]) + if ver != None: + return ver + else: + return pdb.DBBackedPackageHandle.getInstalledVersion(self, transaction) + + def isInstalled(self, transaction=None): + if self._registry_ent != None: + ver = thandy.util.getRegistryValue(self._registry_ent[0]) + if ver == self._registry_ent[1] + return True + else: + return pdb.DBBackedPackageHandle.isInstalled(self, transaction) + + def _doInstall(self): commandline = [ self._filename ] + self._arguments logging.info("Installing %s. Command line: %s", self._filename, diff --git a/lib/thandy/packagesys/PackageDB.py b/lib/thandy/packagesys/PackageDB.py index c829ac3..d4070bf 100644 --- a/lib/thandy/packagesys/PackageDB.py +++ b/lib/thandy/packagesys/PackageDB.py @@ -56,7 +56,7 @@ class DBBackedPackageHandle(thandy.packagesys.PackageSystem.PackageHandle): raise NotImplemented() def anyVersionInstalled(self, transaction=None): - return self._packageDB.getCurVersion(self._name) != None + return self.getInstalledVersion(transaction) != None def getInstalledVersion(self, transaction=None): return self._packageDB.getCurVersion(self._name) diff --git a/lib/thandy/util.py b/lib/thandy/util.py index f2bac17..0c0aa9d 100644 --- a/lib/thandy/util.py +++ b/lib/thandy/util.py @@ -109,3 +109,23 @@ def randChooseWeighted(lst): return lst[-1][1] +def getRegistryValue(keyname): + """Read the contents of a Windows registry key from a given base.""" + + hkey, rest = keyname.split("\\", 1) + key, value = rest.rsplit("\\", 1) + if not hkey.startswith("HKEY_"): + return None + + base = getattr(_winreg, hkey) + settings = None + + try: + try: + settings = _winreg.OpenKey(base, key) + return _winreg.QueryValueEx(settings, value)[0] + except (WindowsError, ValueError, TypeError): + return None + finally: + if settings is not None: + settings.close() diff --git a/samples/example-package.cfg b/samples/example-package.cfg index 8e0b578..6df6ac0 100644 --- a/samples/example-package.cfg +++ b/samples/example-package.cfg @@ -37,8 +37,17 @@ format = "none" # # that does not have its own built-in installation mechanism.) # # format = "exe" +# # # What arguments do you pass to this package to install it? # # This needs to be a list of strings. # exe_args = [ "--silent", "--automatic", "--omit-bugs", ] - - +# +# # Optional: a registry key, value pair for a version number that this +# # package will set when it installs itself. The exe is responsible for +# # setting this value; thandy only reads the value to see whether the +# # exe is installed. +# # (Remember to prefix your registry string with r, so that the internal +# # backslashes are automatically escaped.) +# +# exe_registry_ent = [ r'HKEY_LOCAL_MACHINE\Software\Blahblahblach\Version', +# '0.1.2' ] -- cgit v1.2.3