]>
git.ipfire.org Git - pakfire.git/blob - pakfire/repository/index.py
9 import pakfire
.compress
as compress
10 import pakfire
.downloader
as downloader
11 import pakfire
.packages
as packages
12 import pakfire
.satsolver
as satsolver
13 import pakfire
.util
as util
15 from pakfire
.constants
import *
16 from pakfire
.i18n
import _
19 def __init__(self
, pakfire
, repo
):
20 self
.pakfire
= pakfire
22 # Create reference to repository and the solver repo.
24 self
.solver_repo
= repo
.solver_repo
28 # Check, if initialization was okay.
32 return "<%s %s>" % (self
.__class
__.__name
__, self
.repo
)
39 return self
.repo
.cache
46 Check if everything was correctly initialized.
48 raise NotImplementedError
50 def update(self
, force
=False):
51 raise NotImplementedError
53 def read(self
, filename
):
55 Read file in SOLV format from filename.
57 self
.solver_repo
.read(filename
)
59 def write(self
, filename
):
61 Write content to filename in SOLV format.
63 self
.solver_repo
.write(filename
)
65 def create_relation(self
, *args
, **kwargs
):
66 return self
.pakfire
.create_relation(*args
, **kwargs
)
68 def add_package(self
, pkg
):
69 # XXX Skip packages without a UUID
71 # logging.warning("Skipping package which lacks UUID: %s" % pkg)
73 if not pkg
.build_time
:
76 logging
.debug("Adding package to index %s: %s" % (self
, pkg
))
78 solvable
= satsolver
.Solvable(self
.solver_repo
, pkg
.name
,
79 pkg
.friendly_version
, pkg
.arch
)
83 solvable
.set_vendor(pkg
.vendor
)
87 solvable
.set_hash1(hash1
)
90 solvable
.set_uuid(pkg
.uuid
)
93 solvable
.set_maintainer(pkg
.maintainer
)
96 solvable
.set_groups(" ".join(pkg
.groups
))
98 # Save upstream information (summary, description, license, url).
100 solvable
.set_summary(pkg
.summary
)
103 solvable
.set_description(pkg
.description
)
106 solvable
.set_license(pkg
.license
)
109 solvable
.set_url(pkg
.url
)
111 # Save build information.
113 solvable
.set_buildhost(pkg
.build_host
)
116 solvable
.set_buildtime(pkg
.build_time
)
119 filename
= os
.path
.basename(pkg
.filename
)
121 solvable
.set_filename(filename
)
123 solvable
.set_downloadsize(pkg
.size
)
124 solvable
.set_installsize(pkg
.inst_size
)
126 # Import all requires.
127 for req
in pkg
.requires
:
128 rel
= self
.create_relation(req
)
129 solvable
.add_requires(rel
)
131 # Import all provides.
132 for prov
in pkg
.provides
:
133 rel
= self
.create_relation(prov
)
134 solvable
.add_provides(rel
)
136 # Import all conflicts.
137 for conf
in pkg
.conflicts
:
138 rel
= self
.create_relation(conf
)
139 solvable
.add_conflicts(rel
)
141 # Import all obsoletes.
142 for obso
in pkg
.obsoletes
:
143 rel
= self
.create_relation(obso
)
144 solvable
.add_obsoletes(rel
)
146 # Import all files that are in the package.
147 rel
= self
.create_relation("solvable:filemarker")
148 solvable
.add_provides(rel
)
149 for file in pkg
.filelist
:
150 rel
= self
.create_relation(file)
151 solvable
.add_provides(rel
)
155 Forget all packages from memory.
157 self
.solver_repo
.clear()
160 class IndexSolv(Index
):
162 pass # XXX to be done
164 def update(self
, force
=False):
165 self
._update
_metadata
(force
)
166 self
._update
_database
(force
)
168 def _update_metadata(self
, force
):
169 filename
= os
.path
.join(METADATA_DOWNLOAD_PATH
, METADATA_DOWNLOAD_FILE
)
171 # Marker if we need to do the download.
174 # Marker for the current metadata.
178 # Check if file does exists and is not too old.
179 if self
.cache
.exists(filename
):
180 age
= self
.cache
.age(filename
)
181 if age
and age
< TIME_10M
:
183 logging
.debug("Metadata is recent enough. I don't download it again.")
185 # Open old metadata for comparison.
186 old_metadata
= metadata
.Metadata(self
.pakfire
, self
,
187 self
.cache
.abspath(filename
))
190 logging
.debug("Going to (re-)download the repository metadata.")
192 # Initialize a grabber for download.
193 grabber
= downloader
.MetadataDownloader()
194 grabber
= self
.repo
.mirrors
.group(grabber
)
196 data
= grabber
.urlread(filename
, limit
=METADATA_DOWNLOAD_LIMIT
)
198 # Parse new metadata for comparison.
199 new_metadata
= metadata
.Metadata(self
.pakfire
, self
, metadata
=data
)
201 if old_metadata
and new_metadata
< old_metadata
:
202 logging
.warning("The downloaded metadata was less recent than the current one. Trashing that.")
205 # We explicitely rewrite the metadata if it is equal to have
206 # a new timestamp and do not download it over and over again.
207 with self
.cache
.open(filename
, "w") as o
:
210 # Parse the metadata that we just downloaded or load it from cache.
211 self
.metadata
= metadata
.Metadata(self
.pakfire
, self
,
212 self
.cache
.abspath(filename
))
214 def _update_database(self
, force
):
215 # Construct cache and download filename.
216 filename
= os
.path
.join(METADATA_DOWNLOAD_PATH
, self
.metadata
.database
)
218 if not self
.cache
.exists(filename
):
219 # Initialize a grabber for download.
220 grabber
= downloader
.DatabaseDownloader(
221 text
= _("%s: package database") % self
.repo
.name
,
223 grabber
= self
.repo
.mirrors
.group(grabber
)
225 data
= grabber
.urlread(filename
)
227 with self
.cache
.open(filename
, "w") as o
:
230 # decompress the database
231 if self
.metadata
.database_compression
:
232 # Open input file and remove the file immediately.
233 # The fileobj is still open and the data will be removed
235 compress
.decompress(self
.cache
.abspath(filename
),
236 algo
=self
.metadata
.database_compression
)
238 # check the hashsum of the downloaded file
239 if not util
.calc_hash1(self
.cache
.abspath(filename
)) == self
.metadata
.database_hash1
:
240 # XXX an exception is not a very good idea because this file could
241 # be downloaded from another mirror. need a better way to handle this.
243 # Remove bad file from cache.
244 self
.cache
.remove(filename
)
246 raise Exception, "Downloaded file did not match the hashsum. Need to re-download it."
248 # (Re-)open the database.
249 self
.read(self
.cache
.abspath(filename
))
252 class IndexDir(Index
):
254 pass # XXX to be done
258 path
= self
.repo
.path
260 if path
.startswith("file://"):
265 def update(self
, force
=False):
266 logging
.debug("Updating repository index '%s' (force=%s)" % (self
.path
, force
))
268 # Do nothing if the update is not forced but populate the database
269 # if no packages are present.
270 if not force
and len(self
.repo
):
273 # Collect all packages from default path.
274 self
.collect_packages(self
.path
)
276 def collect_packages(self
, path
):
277 logging
.debug("Collecting all packages from %s" % path
)
280 # Get a filelist of all files that could possibly be packages.
282 for dir, subdirs
, _files
in os
.walk(path
):
283 for file in sorted(_files
):
284 # Skip files that do not have the right extension
285 if not file.endswith(".%s" % PACKAGE_EXTENSION
):
288 file = os
.path
.join(dir, file)
294 # Create progress bar.
295 pb
= util
.make_progress(_("Loading from %s") % path
, len(files
))
303 package
= packages
.open(self
.pakfire
, self
.repo
, file)
305 if isinstance(package
, packages
.BinaryPackage
):
306 if not package
.arch
in (self
.repo
.arch
, "noarch"):
307 logging
.warning("Skipped package with wrong architecture: %s (%s)" \
308 % (package
.filename
, package
.arch
))
312 # Skip all source packages.
313 elif isinstance(package
, packages
.SourcePackage
):
316 self
.add_package(package
)
325 class IndexLocal(Index
):
327 self
.db
= database
.DatabaseLocal(self
.pakfire
, self
.repo
)
330 # XXX Create the database and lock it or something.
333 def update(self
, force
=True):
334 if self
.solver_repo
.size() == 0:
338 package_count
= len(self
.db
)
340 # Nothing to do here, if there are no packages in the database.
341 if not package_count
:
344 # Add all packages from the database to the index.
345 pb
= util
.make_progress(_("Loading installed packages"), package_count
)
348 for pkg
in self
.db
.packages
:
353 self
.add_package(pkg
)