]>
Commit | Line | Data |
---|---|---|
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 |
22 | import os |
23 | ||
14ea3228 | 24 | import pakfire.downloader |
862bea4d | 25 | import pakfire.filelist |
14ea3228 | 26 | |
47a4cb89 | 27 | from base import Package |
e0636b31 | 28 | from file import BinaryPackage |
4f91860e | 29 | |
e871a081 | 30 | import pakfire.util as util |
4f91860e | 31 | from pakfire.constants import * |
47a4cb89 | 32 | |
fa6d335b MT |
33 | class 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? |
346 | class InstalledPackage(DatabasePackage): | |
347 | type = "installed" | |
348 |