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