]> git.ipfire.org Git - pakfire.git/blame - python/pakfire/packages/installed.py
database: Save installed package size.
[pakfire.git] / python / pakfire / packages / installed.py
CommitLineData
47a4cb89 1#!/usr/bin/python
b792d887
MT
2###############################################################################
3# #
4# Pakfire - The IPFire package management system #
5# Copyright (C) 2011 Pakfire development team #
6# #
7# This program is free software: you can redistribute it and/or modify #
8# it under the terms of the GNU General Public License as published by #
9# the Free Software Foundation, either version 3 of the License, or #
10# (at your option) any later version. #
11# #
12# This program is distributed in the hope that it will be useful, #
13# but WITHOUT ANY WARRANTY; without even the implied warranty of #
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15# GNU General Public License for more details. #
16# #
17# You should have received a copy of the GNU General Public License #
18# along with this program. If not, see <http://www.gnu.org/licenses/>. #
19# #
20###############################################################################
47a4cb89 21
4f91860e
MT
22import os
23
14ea3228 24import pakfire.downloader
862bea4d 25import pakfire.filelist
14ea3228 26
47a4cb89 27from base import Package
e0636b31 28from file import BinaryPackage
4f91860e 29
e871a081 30import pakfire.util as util
4f91860e 31from pakfire.constants import *
47a4cb89 32
fa6d335b
MT
33class DatabasePackage(Package):
34 type = "db"
47a4cb89 35
4f91860e
MT
36 def __init__(self, pakfire, repo, db, data):
37 Package.__init__(self, pakfire, repo)
3723913b 38
47a4cb89
MT
39 self.db = db
40
41 self._data = {}
9b68f47c 42 self._filelist = None
47a4cb89
MT
43
44 for key in data.keys():
45 self._data[key] = data[key]
46
47 def __repr__(self):
48 return "<%s %s>" % (self.__class__.__name__, self.friendly_name)
49
50 @property
51 def metadata(self):
52 return self._data
53
54 @property
55 def id(self):
56 id = self.metadata.get("id")
57 if not id:
58 id = 0
59
60 return id
61
62 @property
63 def name(self):
64 return self.metadata.get("name")
65
66 @property
67 def version(self):
68 return self.metadata.get("version")
69
70 @property
71 def release(self):
72 return self.metadata.get("release")
73
74 @property
75 def epoch(self):
76 epoch = self.metadata.get("epoch", 0)
77
78 return int(epoch)
79
80 @property
81 def arch(self):
82 return self.metadata.get("arch")
83
84 @property
85 def maintainer(self):
86 return self.metadata.get("maintainer")
87
88 @property
89 def license(self):
90 return self.metadata.get("license")
91
92 @property
93 def summary(self):
94 return self.metadata.get("summary")
95
96 @property
97 def description(self):
98 return self.metadata.get("description")
99
100 @property
8537c16d 101 def groups(self):
e74f185d
MT
102 groups = self.metadata.get("groups", "")
103
104 if groups:
105 return groups.split()
106
107 return []
47a4cb89
MT
108
109 @property
0c665250
MT
110 def build_date(self):
111 return self.metadata.get("build_date")
112
113 @property
114 def build_time(self):
b566f7e3
MT
115 build_time = self.metadata.get("build_time", 0)
116
6b151a68
MT
117 try:
118 return int(build_time)
119 except TypeError:
120 return 0
47a4cb89
MT
121
122 @property
123 def build_host(self):
124 return self.metadata.get("build_host")
125
126 @property
127 def build_id(self):
128 return self.metadata.get("build_id")
129
85a1120f
MT
130 @property
131 def vendor(self):
132 return self.metadata.get("vendor")
133
1317485d
MT
134 @property
135 def uuid(self):
136 return self.metadata.get("uuid")
137
e399ad3a
MT
138 @property
139 def size(self):
a5f5fced 140 return self.metadata.get("size", 0)
e399ad3a 141
0304200a
MT
142 @property
143 def inst_size(self):
ba5dc639
MT
144 inst_size = self.metadata.get("inst_size", None)
145
146 # As install size has not always been saved in the database
147 # use the package size instead.
148 if inst_size is None:
149 return self.size
150
151 return inst_size
0304200a 152
47a4cb89
MT
153 @property
154 def provides(self):
63029754 155 return self.metadata.get("provides", "").splitlines()
47a4cb89
MT
156
157 @property
158 def requires(self):
63029754 159 return self.metadata.get("requires", "").splitlines()
47a4cb89
MT
160
161 @property
162 def conflicts(self):
63029754 163 return self.metadata.get("conflicts", "").splitlines()
ae20b05f
MT
164
165 @property
166 def obsoletes(self):
63029754 167 return self.metadata.get("obsoletes", "").splitlines()
47a4cb89 168
a60f0f7d
MT
169 @property
170 def recommends(self):
171 recommends = self.metadata.get("recommends", None)
172
173 if recommends:
174 return recommends.splitlines()
175
176 return []
177
178 @property
179 def suggests(self):
180 suggests = self.metadata.get("suggests", None)
181
182 if suggests:
183 return suggests.splitlines()
184
185 return []
186
4f91860e
MT
187 @property
188 def hash1(self):
189 return self.metadata.get("hash1")
190
a5f5fced
MT
191 @property
192 def scriptlet(self):
193 return self.metadata.get("scriptlet")
194
4f91860e
MT
195 @property
196 def filename(self):
9b68f47c 197 return self.metadata.get("filename")
4f91860e 198
47a4cb89
MT
199 @property
200 def filelist(self):
9b68f47c
MT
201 if self._filelist is None:
202 self._filelist = []
862bea4d 203
9b68f47c
MT
204 c = self.db.cursor()
205 c.execute("SELECT * FROM files WHERE pkg = ?", (self.id,))
862bea4d 206
9b68f47c
MT
207 for row in c.fetchall():
208 file = pakfire.filelist.FileDatabase(self.pakfire, self.db, row["id"], row)
209 self._filelist.append(file)
47a4cb89 210
9b68f47c 211 return self._filelist
47a4cb89 212
6ee3d6b9
MT
213 @property
214 def configfiles(self):
482d1ada
MT
215 ret = []
216
217 for file in self.filelist:
218 if not file.is_config():
219 continue
220
221 ret.append(file)
222
223 return ret
6ee3d6b9 224
3c5a85f3
MT
225 @property
226 def datafiles(self):
227 ret = []
228
229 for file in self.filelist:
230 if not file.is_datafile():
231 continue
232
233 ret.append(file)
234
235 return ret
236
a88d2cdc
MT
237 def _does_provide_file(self, requires):
238 """
239 A faster version to find a file in the database.
240 """
241 c = self.db.cursor()
311ce792 242 c.execute("SELECT * FROM files WHERE name GLOB ? AND pkg = ?",
a2d1644c 243 (requires.requires, self.id))
a88d2cdc
MT
244
245 ret = False
246 for pkg in c:
a2d1644c
MT
247 ret = True
248 break
a88d2cdc
MT
249
250 c.close()
251
252 return ret
253
14ea3228 254 def download(self, text=""):
4f91860e
MT
255 """
256 Downloads the package from repository and returns a new instance
257 of BinaryPackage.
258 """
d4c94aa5
MT
259
260 # XXX a bit hacky, but InstalledRepository has no cache.
261 if self.repo.name == "installed":
262 return self
263
4f91860e
MT
264 # Marker, if we need to download the package.
265 download = True
266
267 # Add shortcut for cache.
268 cache = self.repo.cache
269
270 cache_filename = "packages/%s" % os.path.basename(self.filename)
271
272 # Check if file already exists in cache.
273 if cache.exists(cache_filename):
274 # If the file does already exist, we check if the hash1 matches.
275 if cache.verify(cache_filename, self.hash1):
276 # We already got the right file. Skip download.
277 download = False
278 else:
279 # The file in cache has a wrong hash. Remove it and repeat download.
280 cache.remove(cache_filename)
281
282 if download:
4f91860e
MT
283 # Make sure filename is of type string (and not unicode)
284 filename = str(self.filename)
285
14ea3228
MT
286 # Get a package grabber and add mirror download capabilities to it.
287 grabber = pakfire.downloader.PackageDownloader(
288 text=text + os.path.basename(filename),
289 )
290 grabber = self.repo.mirrors.group(grabber)
291
292 i = grabber.urlopen(filename)
293
294 # Open input and output files and download the file.
295 o = cache.open(cache_filename, "w")
4f91860e
MT
296
297 buf = i.read(BUFFER_SIZE)
298 while buf:
299 o.write(buf)
300 buf = i.read(BUFFER_SIZE)
301
302 i.close()
303 o.close()
304
305 # Verify if the download was okay.
306 if not cache.verify(cache_filename, self.hash1):
307 raise Exception, "XXX this should never happen..."
308
309 filename = os.path.join(cache.path, cache_filename)
310 return BinaryPackage(self.pakfire, self.repo, filename)
fa6d335b 311
e871a081
MT
312 def cleanup(self, message, prefix):
313 c = self.db.cursor()
314
315 # Get all files, that are in this package and check for all of
316 # them if they need to be removed.
317 files = self.filelist
318
319 # Fetch the whole filelist of the system from the database and create
320 # a diff. Exclude files from this package - of course.
9999260a 321 c.execute("SELECT DISTINCT name FROM files WHERE pkg != ?", (self.id,))
e871a081 322
9999260a 323 installed_files = set()
e871a081 324 for row in c:
9999260a 325 installed_files.add(row["name"])
e871a081
MT
326 c.close()
327
9999260a
MT
328 # List with files to be removed.
329 remove_files = []
330
331 for f in files:
332 if f.name in installed_files:
333 continue
334
335 remove_files.append(f)
336
337 self._remove_files(remove_files, message, prefix)
e871a081 338
0f8d6745
MT
339 @property
340 def signatures(self):
341 # Database packages do not have any signatures.
342 return []
343
e871a081 344
fa6d335b
MT
345# XXX maybe we can remove this later?
346class InstalledPackage(DatabasePackage):
347 type = "installed"
348