]> git.ipfire.org Git - pakfire.git/blame - src/pakfire/packages/installed.py
Fix updating UsrMove packages.
[pakfire.git] / src / 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
87da3448
MT
153 @property
154 def dependencies(self):
155 if not hasattr(self, "__dependencies"):
156 self.__dependencies = {}
157
158 c = self.db.cursor()
159 c.execute("SELECT type, dependency FROM dependencies WHERE pkg = ?", (self.id,))
160
161 for type, dependency in c.fetchall():
162 try:
163 self.__dependencies[type].append(dependency)
164 except KeyError:
165 self.__dependencies[type] = [dependency,]
166
167 return self.__dependencies
168
47a4cb89
MT
169 @property
170 def provides(self):
87da3448 171 return self.dependencies.get("provides", [])
47a4cb89
MT
172
173 @property
174 def requires(self):
87da3448 175 return self.dependencies.get("requires", [])
47a4cb89
MT
176
177 @property
178 def conflicts(self):
87da3448 179 return self.dependencies.get("conflicts", [])
ae20b05f
MT
180
181 @property
182 def obsoletes(self):
87da3448 183 return self.dependencies.get("obsoletes", [])
47a4cb89 184
a60f0f7d
MT
185 @property
186 def recommends(self):
87da3448 187 return self.dependencies.get("recommends", [])
a60f0f7d
MT
188
189 @property
190 def suggests(self):
87da3448 191 return self.dependencies.get("suggests", [])
a60f0f7d 192
4f91860e
MT
193 @property
194 def hash1(self):
195 return self.metadata.get("hash1")
196
a5f5fced
MT
197 @property
198 def scriptlet(self):
199 return self.metadata.get("scriptlet")
200
4f91860e
MT
201 @property
202 def filename(self):
9b68f47c 203 return self.metadata.get("filename")
4f91860e 204
47a4cb89
MT
205 @property
206 def filelist(self):
9b68f47c
MT
207 if self._filelist is None:
208 self._filelist = []
862bea4d 209
9b68f47c
MT
210 c = self.db.cursor()
211 c.execute("SELECT * FROM files WHERE pkg = ?", (self.id,))
862bea4d 212
9b68f47c
MT
213 for row in c.fetchall():
214 file = pakfire.filelist.FileDatabase(self.pakfire, self.db, row["id"], row)
215 self._filelist.append(file)
47a4cb89 216
9b68f47c 217 return self._filelist
47a4cb89 218
6ee3d6b9
MT
219 @property
220 def configfiles(self):
482d1ada
MT
221 ret = []
222
223 for file in self.filelist:
224 if not file.is_config():
225 continue
226
227 ret.append(file)
228
229 return ret
6ee3d6b9 230
3c5a85f3
MT
231 @property
232 def datafiles(self):
233 ret = []
234
235 for file in self.filelist:
236 if not file.is_datafile():
237 continue
238
239 ret.append(file)
240
241 return ret
242
a88d2cdc
MT
243 def _does_provide_file(self, requires):
244 """
245 A faster version to find a file in the database.
246 """
247 c = self.db.cursor()
311ce792 248 c.execute("SELECT * FROM files WHERE name GLOB ? AND pkg = ?",
a2d1644c 249 (requires.requires, self.id))
a88d2cdc
MT
250
251 ret = False
252 for pkg in c:
a2d1644c
MT
253 ret = True
254 break
a88d2cdc
MT
255
256 c.close()
257
258 return ret
259
14ea3228 260 def download(self, text=""):
4f91860e
MT
261 """
262 Downloads the package from repository and returns a new instance
263 of BinaryPackage.
264 """
d4c94aa5
MT
265
266 # XXX a bit hacky, but InstalledRepository has no cache.
267 if self.repo.name == "installed":
268 return self
269
4f91860e
MT
270 # Marker, if we need to download the package.
271 download = True
272
273 # Add shortcut for cache.
274 cache = self.repo.cache
275
276 cache_filename = "packages/%s" % os.path.basename(self.filename)
277
278 # Check if file already exists in cache.
279 if cache.exists(cache_filename):
280 # If the file does already exist, we check if the hash1 matches.
281 if cache.verify(cache_filename, self.hash1):
282 # We already got the right file. Skip download.
283 download = False
284 else:
285 # The file in cache has a wrong hash. Remove it and repeat download.
286 cache.remove(cache_filename)
287
288 if download:
4f91860e
MT
289 # Make sure filename is of type string (and not unicode)
290 filename = str(self.filename)
291
14ea3228
MT
292 # Get a package grabber and add mirror download capabilities to it.
293 grabber = pakfire.downloader.PackageDownloader(
294 text=text + os.path.basename(filename),
295 )
296 grabber = self.repo.mirrors.group(grabber)
297
298 i = grabber.urlopen(filename)
299
300 # Open input and output files and download the file.
301 o = cache.open(cache_filename, "w")
4f91860e
MT
302
303 buf = i.read(BUFFER_SIZE)
304 while buf:
305 o.write(buf)
306 buf = i.read(BUFFER_SIZE)
307
308 i.close()
309 o.close()
310
311 # Verify if the download was okay.
312 if not cache.verify(cache_filename, self.hash1):
313 raise Exception, "XXX this should never happen..."
314
315 filename = os.path.join(cache.path, cache_filename)
316 return BinaryPackage(self.pakfire, self.repo, filename)
fa6d335b 317
e871a081
MT
318 def cleanup(self, message, prefix):
319 c = self.db.cursor()
320
321 # Get all files, that are in this package and check for all of
322 # them if they need to be removed.
323 files = self.filelist
324
325 # Fetch the whole filelist of the system from the database and create
326 # a diff. Exclude files from this package - of course.
9999260a 327 c.execute("SELECT DISTINCT name FROM files WHERE pkg != ?", (self.id,))
e871a081 328
9999260a 329 installed_files = set()
e871a081 330 for row in c:
9999260a 331 installed_files.add(row["name"])
e871a081
MT
332 c.close()
333
9999260a
MT
334 # List with files to be removed.
335 remove_files = []
336
337 for f in files:
eb93662e
MT
338 # Try to find the if an other package owns the file.
339 # Handles packages that move files from / to /usr.
340 try:
341 filename = os.path.abspath(f.name)
342 except OSError:
343 filename = f.name
344
345 if filename in installed_files:
9999260a
MT
346 continue
347
348 remove_files.append(f)
349
350 self._remove_files(remove_files, message, prefix)
e871a081 351
0f8d6745
MT
352 @property
353 def signatures(self):
354 # Database packages do not have any signatures.
355 return []
356
e871a081 357
fa6d335b
MT
358# XXX maybe we can remove this later?
359class InstalledPackage(DatabasePackage):
360 type = "installed"
361