]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/bin/python | |
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 | ############################################################################### | |
21 | ||
22 | import os | |
23 | ||
24 | import pakfire.downloader | |
25 | ||
26 | from base import Package | |
27 | from file import BinaryPackage | |
28 | ||
29 | import pakfire.util as util | |
30 | from pakfire.constants import * | |
31 | ||
32 | class DatabasePackage(Package): | |
33 | type = "db" | |
34 | ||
35 | def __init__(self, pakfire, repo, db, data): | |
36 | Package.__init__(self, pakfire, repo) | |
37 | ||
38 | self.db = db | |
39 | ||
40 | self._data = {} | |
41 | ||
42 | for key in data.keys(): | |
43 | self._data[key] = data[key] | |
44 | ||
45 | def __repr__(self): | |
46 | return "<%s %s>" % (self.__class__.__name__, self.friendly_name) | |
47 | ||
48 | @property | |
49 | def metadata(self): | |
50 | return self._data | |
51 | ||
52 | @property | |
53 | def id(self): | |
54 | id = self.metadata.get("id") | |
55 | if not id: | |
56 | id = 0 | |
57 | ||
58 | return id | |
59 | ||
60 | @property | |
61 | def name(self): | |
62 | return self.metadata.get("name") | |
63 | ||
64 | @property | |
65 | def version(self): | |
66 | return self.metadata.get("version") | |
67 | ||
68 | @property | |
69 | def release(self): | |
70 | return self.metadata.get("release") | |
71 | ||
72 | @property | |
73 | def epoch(self): | |
74 | epoch = self.metadata.get("epoch", 0) | |
75 | ||
76 | return int(epoch) | |
77 | ||
78 | @property | |
79 | def arch(self): | |
80 | return self.metadata.get("arch") | |
81 | ||
82 | @property | |
83 | def maintainer(self): | |
84 | return self.metadata.get("maintainer") | |
85 | ||
86 | @property | |
87 | def license(self): | |
88 | return self.metadata.get("license") | |
89 | ||
90 | @property | |
91 | def summary(self): | |
92 | return self.metadata.get("summary") | |
93 | ||
94 | @property | |
95 | def description(self): | |
96 | return self.metadata.get("description") | |
97 | ||
98 | @property | |
99 | def groups(self): | |
100 | groups = self.metadata.get("groups", "") | |
101 | ||
102 | if groups: | |
103 | return groups.split() | |
104 | ||
105 | return [] | |
106 | ||
107 | @property | |
108 | def build_date(self): | |
109 | return self.metadata.get("build_date") | |
110 | ||
111 | @property | |
112 | def build_time(self): | |
113 | build_time = self.metadata.get("build_time", 0) | |
114 | ||
115 | try: | |
116 | return int(build_time) | |
117 | except TypeError: | |
118 | return 0 | |
119 | ||
120 | @property | |
121 | def build_host(self): | |
122 | return self.metadata.get("build_host") | |
123 | ||
124 | @property | |
125 | def build_id(self): | |
126 | return self.metadata.get("build_id") | |
127 | ||
128 | @property | |
129 | def uuid(self): | |
130 | return self.metadata.get("uuid") | |
131 | ||
132 | @property | |
133 | def size(self): | |
134 | return self.metadata.get("size", 0) | |
135 | ||
136 | @property | |
137 | def inst_size(self): | |
138 | # XXX to be done | |
139 | return 0 | |
140 | ||
141 | @property | |
142 | def provides(self): | |
143 | return self.metadata.get("provides", "").split() | |
144 | ||
145 | @property | |
146 | def requires(self): | |
147 | return self.metadata.get("requires", "").split() | |
148 | ||
149 | @property | |
150 | def conflicts(self): | |
151 | return self.metadata.get("conflicts", "").split() | |
152 | ||
153 | @property | |
154 | def obsoletes(self): | |
155 | return self.metadata.get("obsoletes", "").split() | |
156 | ||
157 | @property | |
158 | def hash1(self): | |
159 | return self.metadata.get("hash1") | |
160 | ||
161 | @property | |
162 | def scriptlet(self): | |
163 | return self.metadata.get("scriptlet") | |
164 | ||
165 | @property | |
166 | def filename(self): | |
167 | return self.metadata.get("filename") # XXX basename? | |
168 | ||
169 | @property | |
170 | def filelist(self): | |
171 | c = self.db.cursor() | |
172 | try: | |
173 | c.execute("SELECT name FROM files WHERE pkg = ?", (self.id,)) | |
174 | ||
175 | return [f["name"] for f in c] | |
176 | finally: | |
177 | c.close() | |
178 | ||
179 | @property | |
180 | def configfiles(self): | |
181 | return [] # XXX to be done | |
182 | ||
183 | def _does_provide_file(self, requires): | |
184 | """ | |
185 | A faster version to find a file in the database. | |
186 | """ | |
187 | c = self.db.cursor() | |
188 | c.execute("SELECT * FROM files WHERE name GLOB ? AND pkg = ?", | |
189 | (requires.requires, self.id)) | |
190 | ||
191 | ret = False | |
192 | for pkg in c: | |
193 | ret = True | |
194 | break | |
195 | ||
196 | c.close() | |
197 | ||
198 | return ret | |
199 | ||
200 | def download(self, text=""): | |
201 | """ | |
202 | Downloads the package from repository and returns a new instance | |
203 | of BinaryPackage. | |
204 | """ | |
205 | ||
206 | # XXX a bit hacky, but InstalledRepository has no cache. | |
207 | if self.repo.name == "installed": | |
208 | return self | |
209 | ||
210 | # Marker, if we need to download the package. | |
211 | download = True | |
212 | ||
213 | # Add shortcut for cache. | |
214 | cache = self.repo.cache | |
215 | ||
216 | cache_filename = "packages/%s" % os.path.basename(self.filename) | |
217 | ||
218 | # Check if file already exists in cache. | |
219 | if cache.exists(cache_filename): | |
220 | # If the file does already exist, we check if the hash1 matches. | |
221 | if cache.verify(cache_filename, self.hash1): | |
222 | # We already got the right file. Skip download. | |
223 | download = False | |
224 | else: | |
225 | # The file in cache has a wrong hash. Remove it and repeat download. | |
226 | cache.remove(cache_filename) | |
227 | ||
228 | if download: | |
229 | # Make sure filename is of type string (and not unicode) | |
230 | filename = str(self.filename) | |
231 | ||
232 | # Get a package grabber and add mirror download capabilities to it. | |
233 | grabber = pakfire.downloader.PackageDownloader( | |
234 | text=text + os.path.basename(filename), | |
235 | ) | |
236 | grabber = self.repo.mirrors.group(grabber) | |
237 | ||
238 | i = grabber.urlopen(filename) | |
239 | ||
240 | # Open input and output files and download the file. | |
241 | o = cache.open(cache_filename, "w") | |
242 | ||
243 | buf = i.read(BUFFER_SIZE) | |
244 | while buf: | |
245 | o.write(buf) | |
246 | buf = i.read(BUFFER_SIZE) | |
247 | ||
248 | i.close() | |
249 | o.close() | |
250 | ||
251 | # Verify if the download was okay. | |
252 | if not cache.verify(cache_filename, self.hash1): | |
253 | raise Exception, "XXX this should never happen..." | |
254 | ||
255 | filename = os.path.join(cache.path, cache_filename) | |
256 | return BinaryPackage(self.pakfire, self.repo, filename) | |
257 | ||
258 | def cleanup(self, message, prefix): | |
259 | c = self.db.cursor() | |
260 | ||
261 | # Get all files, that are in this package and check for all of | |
262 | # them if they need to be removed. | |
263 | files = self.filelist | |
264 | ||
265 | # Fetch the whole filelist of the system from the database and create | |
266 | # a diff. Exclude files from this package - of course. | |
267 | c.execute("SELECT name FROM files WHERE pkg != ?", (self.id,)) | |
268 | ||
269 | for row in c: | |
270 | # Check if file in filelist. | |
271 | if row["name"] in files: | |
272 | files.remove(row["name"]) | |
273 | ||
274 | c.close() | |
275 | ||
276 | self._remove_files(files, message, prefix) | |
277 | ||
278 | ||
279 | # XXX maybe we can remove this later? | |
280 | class InstalledPackage(DatabasePackage): | |
281 | type = "installed" | |
282 |