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