summaryrefslogtreecommitdiff
path: root/lib/thandy/packagesys/PackageDB.py
blob: 74208688b215c635beac16052a5dae6c47ea94fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Copyright 2008 The Tor Project, Inc.  See LICENSE for licensing information.

import atexit
import shelve
import logging

import thandy.util
import thandy.formats

import thandy.packagesys.PackageSystem as PS

class SimplePackageDB:
    """Trivial wrapper around Python's shelve module to provide storage for
       installation information for package items that don't automatically
       record their presence.
    """
    def __init__(self, filename):
        thandy.util.ensureParentDir(filename)
        self._db = shelve.open(filename, 'c')
        atexit.register(self.close)

    def close(self):
        self._db.close()

    def setVersion(self, package, version, filelist):
        self._db['pv_%s'%str(package)] = (version, filelist)

    def setInstallParameters(self, package, params):
        self._db['ip_%s'%str(package)] = params

    def setManifest(self, package, fnameToDigest):
        self._db['mf_%s'%str(package)] = fnameToDigest

    def getCurVersion(self, package):
        v = self._db.get('pv_%s'%str(package))
        if v != None:
            return v[0]
        else:
            return None

    def getInstallParameters(self, package):
        return self._db.get('pi_%s'%str(package))

    def getManifest(self, package):
        return self._db.get('mf_%s'%str(package), {})

    def removeAll(self, package):
        for template in ["pv_%s", "ip_%s", "mf_%s"]:
            try:
                del self._db[template % str(package)]
            except KeyError:
                pass

_DB_INSTANCE = None

def getPackageDBInstance():
    global _DB_INSTANCE
    if _DB_INSTANCE == None:
        fname = thandy.util.userFilename("db/packages")
        logging.info("Opening package database in %s", fname)
        _DB_INSTANCE = SimplePackageDB(fname)
    return _DB_INSTANCE

class _DBMixin:
    def setDB(self, db):
        self._db = db

    def getDB(self):
        if self._db is None:
            self._db = getPackageDBInstance()
        return self._db

class DBChecker(PS.Checker, _DBMixin):
    def __init__(self, name, version):
        PS.Checker.__init__(self)
        self._name = name
        self._version = version
        self._db = None

    def __repr__(self):
        return "DBChecker(%r, %r)"%(self._name, self._version)

#    def checkInstall(self):
#        if not self.isInstalled():
#            return False
#        else:
#            return self._checkManifest()
#
#    def _getInstallRoot(self):
#        return "/"
#
#    def _checkManifest(self):
#        manifest = self.getDB().getManifest(self._name)
#        root = self._getInstallRoot()
#        all_ok = True
#        for fname, digest_want in manifest:
#            real_fname = os.path.join(self._getInstallRoot(), fname)
#            logging.info("Checking digest on %s", fname)
#            try:
#                digest = thandy.formats.getFileDigest(real_fname):
#                if digest != digest_want:
#                    logging.warn("Digest on %s not as expected", real_fname)
#                    all_ok = False
#            except OSError:
#                logging.warn("File %s not found.", real_fname)
#                all_ok = False
#        return all_ok
#
    def getInstalledVersions(self):
        return [ self.getDB().getCurVersion(self._name) ]

    def isInstalled(self):
        return self._version in self.getInstalledVersions()

class DBInstaller(PS.Installer, _DBMixin):
    def __init__(self, name, version, relPath, installer):
        PS.Installer.__init__(self, relPath)
        self._name = name
        self._version = version
        self._installer = installer

    def __repr__(self):
        return "DBInstaller(%r, %r, %r, %r)"%(self._name,
                                              self._version,
                                              self._relPath,
                                              self._installer)

    def setTransaction(self, transaction):
        self._installer.setTransaction(transaction)

    def setCacheRoot(self, cacheRoot):
        self._installer.setCacheRoot(cacheRoot)

    def install(self):
        self._installer.install()

        params, manifest = self._installer.getInstallResult()
        self.getDB().setCurVersion(self._name, self._version)
        if params != None:
            self.getDB().getInstallParameters(self._name, params)
        if manifest != None:
            self.getDB().setManifest(self._name, manifest)

    def remove(self):
        self._installer.remove()
        self.getDB().removeAll(self._name)