rust_apt/cache.rs
1//! Contains Cache related structs.
2
3use std::cell::OnceCell;
4use std::fs;
5use std::path::Path;
6
7use cxx::{Exception, UniquePtr};
8
9use crate::config::{Config, init_config_system};
10use crate::depcache::DepCache;
11use crate::error::{AptErrors, pending_error};
12use crate::pkgmanager::raw::OrderResult;
13use crate::progress::{AcquireProgress, InstallProgress, OperationProgress};
14use crate::raw::{
15 IntoRawIter, IterPkgIterator, PackageManager, PkgCacheFile, PkgIterator, ProblemResolver,
16 create_cache, create_pkgmanager, create_problem_resolver,
17};
18use crate::records::{PackageRecords, SourceRecords};
19use crate::util::{apt_lock, apt_unlock, apt_unlock_inner};
20use crate::{Package, PackageFile};
21
22struct AptLockGuard;
23
24impl AptLockGuard {
25 fn acquire() -> Result<Self, AptErrors> {
26 apt_lock()?;
27 Ok(Self)
28 }
29}
30
31impl Drop for AptLockGuard {
32 fn drop(&mut self) { apt_unlock() }
33}
34
35fn handle_install_result(result: OrderResult) -> Result<(), AptErrors> {
36 let message = match result {
37 OrderResult::Completed => return Ok(()),
38 OrderResult::Failed => "Package installation failed without an error from libapt",
39 OrderResult::Incomplete => {
40 "Package installation is incomplete because media swapping is not supported"
41 },
42 _ => "Package installation returned an unknown result from libapt",
43 };
44
45 Err(AptErrors::from(message.to_string()))
46}
47
48/// Selection of Upgrade type
49#[repr(i32)]
50#[derive(Clone, Debug)]
51pub enum Upgrade {
52 /// Upgrade will Install new and Remove packages in addition to
53 /// upgrading them.
54 ///
55 /// Equivalent to `apt full-upgrade` and `apt-get dist-upgrade`.
56 FullUpgrade = 0,
57 /// Upgrade will Install new but not Remove packages.
58 ///
59 /// Equivalent to `apt upgrade`.
60 Upgrade = 1,
61 /// Upgrade will Not Install new or Remove packages.
62 ///
63 /// Equivalent to `apt-get upgrade`.
64 SafeUpgrade = 3,
65}
66
67#[derive(Clone, Debug)]
68pub struct PinnedPackage {
69 pub name: String,
70 pub version: String,
71 pub priority: i32,
72}
73
74/// Selection of how to sort
75enum Sort {
76 /// Disable the sort method.
77 Disable,
78 /// Enable the sort method.
79 Enable,
80 /// Reverse the sort method.
81 Reverse,
82}
83
84/// Determines how to sort packages from the Cache.
85pub struct PackageSort {
86 names: bool,
87 upgradable: Sort,
88 virtual_pkgs: Sort,
89 installed: Sort,
90 auto_installed: Sort,
91 auto_removable: Sort,
92}
93
94impl Default for PackageSort {
95 fn default() -> PackageSort {
96 PackageSort {
97 names: false,
98 upgradable: Sort::Disable,
99 virtual_pkgs: Sort::Disable,
100 installed: Sort::Disable,
101 auto_installed: Sort::Disable,
102 auto_removable: Sort::Disable,
103 }
104 }
105}
106
107impl PackageSort {
108 /// Packages will be sorted by their names a -> z.
109 pub fn names(mut self) -> Self {
110 self.names = true;
111 self
112 }
113
114 /// Only packages that are upgradable will be included.
115 pub fn upgradable(mut self) -> Self {
116 self.upgradable = Sort::Enable;
117 self
118 }
119
120 /// Only packages that are NOT upgradable will be included.
121 pub fn not_upgradable(mut self) -> Self {
122 self.upgradable = Sort::Reverse;
123 self
124 }
125
126 /// Virtual packages will be included.
127 pub fn include_virtual(mut self) -> Self {
128 self.virtual_pkgs = Sort::Enable;
129 self
130 }
131
132 /// Only Virtual packages will be included.
133 pub fn only_virtual(mut self) -> Self {
134 self.virtual_pkgs = Sort::Reverse;
135 self
136 }
137
138 /// Only packages that are installed will be included.
139 pub fn installed(mut self) -> Self {
140 self.installed = Sort::Enable;
141 self
142 }
143
144 /// Only packages that are NOT installed will be included.
145 pub fn not_installed(mut self) -> Self {
146 self.installed = Sort::Reverse;
147 self
148 }
149
150 /// Only packages that are auto installed will be included.
151 pub fn auto_installed(mut self) -> Self {
152 self.auto_installed = Sort::Enable;
153 self
154 }
155
156 /// Only packages that are manually installed will be included.
157 pub fn manually_installed(mut self) -> Self {
158 self.auto_installed = Sort::Reverse;
159 self.installed = Sort::Enable;
160 self
161 }
162
163 /// Only packages that are auto removable will be included.
164 pub fn auto_removable(mut self) -> Self {
165 self.auto_removable = Sort::Enable;
166 self
167 }
168
169 /// Only packages that are NOT auto removable will be included.
170 pub fn not_auto_removable(mut self) -> Self {
171 self.auto_removable = Sort::Reverse;
172 self
173 }
174}
175
176/// The main struct for accessing any and all `apt` data.
177pub struct Cache {
178 pub(crate) ptr: UniquePtr<PkgCacheFile>,
179 depcache: OnceCell<DepCache>,
180 records: OnceCell<PackageRecords>,
181 source_records: OnceCell<SourceRecords>,
182 pkgmanager: OnceCell<UniquePtr<PackageManager>>,
183 problem_resolver: OnceCell<UniquePtr<ProblemResolver>>,
184 local_debs: Vec<String>,
185}
186
187impl Cache {
188 /// Initialize the configuration system, open and return the cache.
189 /// This is the entry point for all operations of this crate.
190 ///
191 /// `local_files` allows you to temporarily add local files to the cache, as
192 /// long as they are one of the following:
193 ///
194 /// - `*.deb` or `*.ddeb` files
195 /// - `Packages` and `Sources` files from apt repositories. These files can
196 /// be compressed.
197 /// - `*.dsc` or `*.changes` files
198 /// - A valid directory containing the file `./debian/control`
199 ///
200 /// This function returns an [`AptErrors`] if any of the files cannot
201 /// be found or are invalid.
202 ///
203 /// Note that if you run [`Cache::commit`] or [`Cache::update`],
204 /// You will be required to make a new cache to perform any further changes
205 pub fn new<T: AsRef<str>>(local_files: &[T]) -> Result<Cache, AptErrors> {
206 let volatile_files: Vec<_> = local_files.iter().map(|d| d.as_ref()).collect();
207
208 init_config_system();
209 Ok(Cache {
210 ptr: create_cache(&volatile_files)?,
211 depcache: OnceCell::new(),
212 records: OnceCell::new(),
213 source_records: OnceCell::new(),
214 pkgmanager: OnceCell::new(),
215 problem_resolver: OnceCell::new(),
216 local_debs: volatile_files
217 .into_iter()
218 .filter(|f| f.ends_with(".deb"))
219 .map(|f| f.to_string())
220 .collect(),
221 })
222 }
223
224 /// Internal Method for generating the package list.
225 pub fn raw_pkgs(&self) -> impl Iterator<Item = UniquePtr<PkgIterator>> {
226 unsafe { self.begin().raw_iter() }
227 }
228
229 /// Get the DepCache
230 pub fn depcache(&self) -> &DepCache {
231 self.depcache
232 .get_or_init(|| DepCache::new(unsafe { self.create_depcache() }))
233 }
234
235 /// Get the PkgRecords
236 pub fn records(&self) -> &PackageRecords {
237 self.records
238 .get_or_init(|| PackageRecords::new(unsafe { self.create_records() }))
239 }
240
241 /// Get the PkgRecords
242 pub fn source_records(&self) -> Result<&SourceRecords, AptErrors> {
243 if let Some(records) = self.source_records.get() {
244 return Ok(records);
245 }
246
247 match unsafe { self.ptr.source_records() } {
248 Ok(raw_records) => {
249 self.source_records
250 .set(SourceRecords::new(raw_records))
251 // Unwrap: This is verified empty at the beginning.
252 .unwrap_or_default();
253 // Unwrap: Records was just added above.
254 Ok(self.source_records.get().unwrap())
255 },
256 Err(_) => Err(AptErrors::new()),
257 }
258 }
259
260 /// Get the PkgManager
261 pub fn pkg_manager(&self) -> &PackageManager {
262 self.pkgmanager
263 .get_or_init(|| unsafe { create_pkgmanager(self.depcache()) })
264 }
265
266 /// Get the ProblemResolver
267 pub fn resolver(&self) -> &ProblemResolver {
268 self.problem_resolver
269 .get_or_init(|| unsafe { create_problem_resolver(self.depcache()) })
270 }
271
272 /// Iterate through the packages in a random order
273 pub fn iter(&self) -> CacheIter<'_> {
274 CacheIter {
275 pkgs: unsafe { self.begin().raw_iter() },
276 cache: self,
277 }
278 }
279
280 /// An iterator of package files used to build the cache.
281 pub fn package_files(&self) -> impl Iterator<Item = PackageFile<'_>> {
282 unsafe { self.file_begin().raw_iter() }.map(|file| PackageFile::new(file, self))
283 }
284
285 /// An iterator of pinned packages as shown in `apt-cache policy`.
286 pub fn pinned_packages(&self) -> impl Iterator<Item = PinnedPackage> + '_ {
287 self.iter().filter_map(|pkg| {
288 let cand = pkg.candidate()?;
289 let priority = cand.priority_with_files(false);
290 if priority == 0 {
291 return None;
292 }
293
294 Some(PinnedPackage {
295 name: pkg.name().to_string(),
296 version: cand.version().to_string(),
297 priority,
298 })
299 })
300 }
301
302 /// An iterator of packages in the cache.
303 pub fn packages(&self, sort: &PackageSort) -> impl Iterator<Item = Package<'_>> {
304 let mut pkg_list = vec![];
305 for pkg in self.raw_pkgs() {
306 match sort.virtual_pkgs {
307 // Virtual packages are enabled, include them.
308 // This works differently than the rest. I should probably change defaults.
309 Sort::Enable => {},
310 // If disabled and pkg has no versions, exclude
311 Sort::Disable => {
312 if unsafe { pkg.versions().end() } {
313 continue;
314 }
315 },
316 // If reverse and the package has versions, exclude
317 // This section is for if you only want virtual packages
318 Sort::Reverse => {
319 if unsafe { !pkg.versions().end() } {
320 continue;
321 }
322 },
323 }
324
325 match sort.upgradable {
326 // Virtual packages are enabled, include them.
327 Sort::Disable => {},
328 // If disabled and pkg has no versions, exclude
329 Sort::Enable => {
330 // If the package isn't installed, then it can not be
331 // upgradable
332 if unsafe { pkg.current_version().end() }
333 || !self.depcache().is_upgradable(&pkg)
334 {
335 continue;
336 }
337 },
338 // If reverse and the package is installed and upgradable, exclude
339 // This section is for if you only want packages that are not upgradable
340 Sort::Reverse => {
341 if unsafe { !pkg.current_version().end() }
342 && self.depcache().is_upgradable(&pkg)
343 {
344 continue;
345 }
346 },
347 }
348
349 match sort.installed {
350 // Installed Package is Disabled, so we keep them
351 Sort::Disable => {},
352 Sort::Enable => {
353 if unsafe { pkg.current_version().end() } {
354 continue;
355 }
356 },
357 // Only include installed packages.
358 Sort::Reverse => {
359 if unsafe { !pkg.current_version().end() } {
360 continue;
361 }
362 },
363 }
364
365 match sort.auto_installed {
366 // Installed Package is Disabled, so we keep them
367 Sort::Disable => {},
368 Sort::Enable => {
369 if !self.depcache().is_auto_installed(&pkg) {
370 continue;
371 }
372 },
373 // Only include installed packages.
374 Sort::Reverse => {
375 if self.depcache().is_auto_installed(&pkg) {
376 continue;
377 }
378 },
379 }
380
381 match sort.auto_removable {
382 // auto_removable is Disabled, so we keep them
383 Sort::Disable => {},
384 // If the package is not auto removable skip it.
385 Sort::Enable => {
386 // If the Package isn't auto_removable skip
387 if !self.depcache().is_garbage(&pkg) {
388 continue;
389 }
390 },
391 // If the package is auto removable skip it.
392 Sort::Reverse => {
393 if self.depcache().is_garbage(&pkg) {
394 continue;
395 }
396 },
397 }
398
399 // If this is reached we're clear to include the package.
400 pkg_list.push(pkg);
401 }
402
403 if sort.names {
404 pkg_list.sort_by_cached_key(|pkg| pkg.name().to_string());
405 }
406
407 pkg_list.into_iter().map(|pkg| Package::new(self, pkg))
408 }
409
410 /// Updates the package cache and returns a Result
411 ///
412 /// Here is an example of how you may parse the Error messages.
413 ///
414 /// ```
415 /// use rust_apt::new_cache;
416 /// use rust_apt::progress::AcquireProgress;
417 ///
418 /// let cache = new_cache!().unwrap();
419 /// let mut progress = AcquireProgress::apt();
420 /// if let Err(e) = cache.update(&mut progress) {
421 /// for error in e.iter() {
422 /// if error.is_error {
423 /// println!("Error: {}", error.msg);
424 /// } else {
425 /// println!("Warning: {}", error.msg);
426 /// }
427 /// }
428 /// }
429 /// ```
430 /// # Known Errors:
431 /// * E:Could not open lock file /var/lib/apt/lists/lock - open (13:
432 /// Permission denied)
433 /// * E:Unable to lock directory /var/lib/apt/lists/
434 pub fn update(self, progress: &mut AcquireProgress) -> Result<(), AptErrors> {
435 Ok(self.ptr.update(progress.mut_status())?)
436 }
437
438 /// Mark all packages for upgrade
439 ///
440 /// # Example:
441 ///
442 /// ```
443 /// use rust_apt::new_cache;
444 /// use rust_apt::cache::Upgrade;
445 ///
446 /// let cache = new_cache!().unwrap();
447 ///
448 /// cache.upgrade(Upgrade::FullUpgrade).unwrap();
449 /// ```
450 pub fn upgrade(&self, upgrade_type: Upgrade) -> Result<(), AptErrors> {
451 let mut progress = OperationProgress::quiet();
452 Ok(self
453 .depcache()
454 .upgrade(progress.pin().as_mut(), upgrade_type as i32)?)
455 }
456
457 /// Resolve dependencies with the changes marked on all packages. This marks
458 /// additional packages for installation/removal to satisfy the dependency
459 /// chain.
460 ///
461 /// Note that just running a `mark_*` function on a package doesn't
462 /// guarantee that the selected state will be kept during dependency
463 /// resolution. If you need such, make sure to run
464 /// [`crate::Package::protect`] after marking your requested
465 /// modifications.
466 ///
467 /// If `fix_broken` is set to [`true`], the library will try to repair
468 /// broken dependencies of installed packages.
469 ///
470 /// Returns [`Err`] if there was an error reaching dependency resolution.
471 #[allow(clippy::result_unit_err)]
472 pub fn resolve(&self, fix_broken: bool) -> Result<(), AptErrors> {
473 Ok(self
474 .resolver()
475 .resolve(fix_broken, OperationProgress::quiet().pin().as_mut())?)
476 }
477
478 /// Autoinstall every broken package and run the problem resolver
479 /// Returns false if the problem resolver fails.
480 ///
481 /// # Example:
482 ///
483 /// ```
484 /// use rust_apt::new_cache;
485 ///
486 /// let cache = new_cache!().unwrap();
487 ///
488 /// cache.fix_broken();
489 ///
490 /// for pkg in cache.get_changes(false) {
491 /// println!("Pkg Name: {}", pkg.name())
492 /// }
493 /// ```
494 pub fn fix_broken(&self) -> bool { self.depcache().fix_broken() }
495
496 /// Fetch any archives needed to complete the transaction.
497 ///
498 /// # Returns:
499 /// * A [`Result`] enum: the [`Ok`] variant if fetching succeeded, and
500 /// [`Err`] if there was an issue.
501 ///
502 /// # Example:
503 /// ```
504 /// use rust_apt::new_cache;
505 /// use rust_apt::progress::AcquireProgress;
506 ///
507 /// let cache = new_cache!().unwrap();
508 /// let pkg = cache.get("neovim").unwrap();
509 /// let mut progress = AcquireProgress::apt();
510 ///
511 /// pkg.mark_install(true, true);
512 /// pkg.protect();
513 /// cache.resolve(true).unwrap();
514 ///
515 /// cache.get_archives(&mut progress).unwrap();
516 /// ```
517 /// # Known Errors:
518 /// * W:Problem unlinking the file
519 /// /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
520 /// PrepareFiles (13: Permission denied)
521 /// * W:Problem unlinking the file
522 /// /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
523 /// PrepareFiles (13: Permission denied)
524 /// * W:Problem unlinking the file
525 /// /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
526 /// PrepareFiles (13: Permission denied)
527 /// * W:Problem unlinking the file
528 /// /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
529 /// PrepareFiles (13: Permission denied)
530 /// * W:Problem unlinking the file
531 /// /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
532 /// PrepareFiles (13: Permission denied)
533 /// * W:Problem unlinking the file /var/log/apt/eipp.log.xz - FileFd::Open
534 /// (13: Permission denied)
535 /// * W:Could not open file /var/log/apt/eipp.log.xz - open (17: File
536 /// exists)
537 /// * W:Could not open file '/var/log/apt/eipp.log.xz' - EIPP::OrderInstall
538 /// (17: File exists)
539 /// * E:Internal Error, ordering was unable to handle the media swap"
540 pub fn get_archives(&self, progress: &mut AcquireProgress) -> Result<(), Exception> {
541 self.pkg_manager()
542 .get_archives(&self.ptr, self.records(), progress.mut_status())
543 }
544
545 /// Install, remove, and do any other actions requested by the cache.
546 ///
547 /// # Returns:
548 /// * A [`Result`] enum: the [`Ok`] variant if transaction was successful,
549 /// and [`Err`] if there was an issue.
550 ///
551 /// # Example:
552 /// ```
553 /// use rust_apt::new_cache;
554 /// use rust_apt::progress::{AcquireProgress, InstallProgress};
555 ///
556 /// let cache = new_cache!().unwrap();
557 /// let pkg = cache.get("neovim").unwrap();
558 /// let mut acquire_progress = AcquireProgress::apt();
559 /// let mut install_progress = InstallProgress::apt();
560 ///
561 /// pkg.mark_install(true, true);
562 /// pkg.protect();
563 /// cache.resolve(true).unwrap();
564 ///
565 /// // These need root
566 /// // cache.get_archives(&mut acquire_progress).unwrap();
567 /// // cache.do_install(&mut install_progress).unwrap();
568 /// ```
569 ///
570 /// # Known Errors:
571 /// * W:Problem unlinking the file /var/log/apt/eipp.log.xz - FileFd::Open
572 /// (13: Permission denied)
573 /// * W:Could not open file /var/log/apt/eipp.log.xz - open (17: File
574 /// exists)
575 /// * W:Could not open file '/var/log/apt/eipp.log.xz' - EIPP::OrderInstall
576 /// (17: File exists)
577 /// * E:Could not create temporary file for /var/lib/apt/extended_states -
578 /// mkstemp (13: Permission denied)
579 /// * E:Failed to write temporary StateFile /var/lib/apt/extended_states
580 /// * W:Could not open file '/var/log/apt/term.log' - OpenLog (13:
581 /// Permission denied)
582 /// * E:Sub-process /usr/bin/dpkg returned an error code (2)
583 /// * W:Problem unlinking the file /var/cache/apt/pkgcache.bin -
584 /// pkgDPkgPM::Go (13: Permission denied)
585 pub fn do_install(self, progress: &mut InstallProgress) -> Result<(), AptErrors> {
586 let res = match progress {
587 InstallProgress::Fancy(inner) => self.pkg_manager().do_install(inner.pin().as_mut()),
588 InstallProgress::Fd(fd) => self.pkg_manager().do_install_fd(*fd),
589 };
590
591 if pending_error() {
592 return Err(AptErrors::new());
593 }
594
595 handle_install_result(res)
596 }
597
598 /// Handle get_archives and do_install in an easy wrapper.
599 ///
600 /// # Returns:
601 /// * A [`Result`]: the [`Ok`] variant if transaction was successful, and
602 /// [`Err`] if there was an issue.
603 /// # Example:
604 /// ```
605 /// use rust_apt::new_cache;
606 /// use rust_apt::progress::{AcquireProgress, InstallProgress};
607 ///
608 /// let cache = new_cache!().unwrap();
609 /// let pkg = cache.get("neovim").unwrap();
610 /// let mut acquire_progress = AcquireProgress::apt();
611 /// let mut install_progress = InstallProgress::apt();
612 ///
613 /// pkg.mark_install(true, true);
614 /// pkg.protect();
615 /// cache.resolve(true).unwrap();
616 ///
617 /// // This needs root
618 /// // cache.commit(&mut acquire_progress, &mut install_progress).unwrap();
619 /// ```
620 pub fn commit(
621 self,
622 progress: &mut AcquireProgress,
623 install_progress: &mut InstallProgress,
624 ) -> Result<(), AptErrors> {
625 // Lock the whole thing so as to prevent tamper
626 let _lock = AptLockGuard::acquire()?;
627
628 let config = Config::new();
629 let archive_dir = config.dir("Dir::Cache::Archives", "/var/cache/apt/archives/");
630
631 // Copy local debs into archives dir
632 for deb in &self.local_debs {
633 // If file is already in the archive we don't copy
634 if deb.starts_with(archive_dir.as_str()) {
635 continue;
636 }
637 // If it reaches this point it really will be a valid filename,
638 // allegedly
639 if let Some(filename) = Path::new(deb).file_name() {
640 // Append the file name onto the archive dir
641 fs::copy(deb, archive_dir.to_string() + &filename.to_string_lossy())?;
642 }
643 }
644
645 // The archives can be grabbed during the apt lock.
646 self.get_archives(progress)?;
647
648 // If the system is locked we will want to unlock the dpkg files.
649 // This way when dpkg is running it can access its files.
650 apt_unlock_inner();
651
652 // Perform the operation.
653 self.do_install(install_progress)?;
654
655 Ok(())
656 }
657
658 /// Get a single package.
659 ///
660 /// `cache.get("apt")` Returns a Package object for the native arch.
661 ///
662 /// `cache.get("apt:i386")` Returns a Package object for the i386 arch
663 pub fn get(&self, name: &str) -> Option<Package<'_>> {
664 Some(Package::new(self, unsafe {
665 self.find_pkg(name).make_safe()?
666 }))
667 }
668
669 /// An iterator over the packages
670 /// that will be altered when `cache.commit()` is called.
671 ///
672 /// # sort_name:
673 /// * [`true`] = Packages will be in alphabetical order
674 /// * [`false`] = Packages will not be sorted by name
675 pub fn get_changes(&self, sort_name: bool) -> impl Iterator<Item = Package<'_>> {
676 let mut changed = Vec::new();
677 let depcache = self.depcache();
678
679 for pkg in self.raw_pkgs() {
680 if depcache.marked_install(&pkg)
681 || depcache.marked_delete(&pkg)
682 || depcache.marked_upgrade(&pkg)
683 || depcache.marked_downgrade(&pkg)
684 || depcache.marked_reinstall(&pkg)
685 {
686 changed.push(pkg);
687 }
688 }
689
690 if sort_name {
691 // Sort by cached key seems to be the fastest for what we're doing.
692 // Maybe consider impl ord or something for these.
693 changed.sort_by_cached_key(|pkg| pkg.name().to_string());
694 }
695
696 changed
697 .into_iter()
698 .map(|pkg_ptr| Package::new(self, pkg_ptr))
699 }
700}
701
702#[cfg(test)]
703mod tests {
704 use super::{OrderResult, handle_install_result};
705
706 #[test]
707 fn install_outcomes_return_results() {
708 assert!(handle_install_result(OrderResult::Completed).is_ok());
709 assert!(handle_install_result(OrderResult::Failed).is_err());
710 assert!(handle_install_result(OrderResult::Incomplete).is_err());
711 }
712}
713
714/// Iterator Implementation for the Cache.
715pub struct CacheIter<'a> {
716 pkgs: IterPkgIterator,
717 cache: &'a Cache,
718}
719
720impl<'a> Iterator for CacheIter<'a> {
721 type Item = Package<'a>;
722
723 fn next(&mut self) -> Option<Self::Item> { Some(Package::new(self.cache, self.pkgs.next()?)) }
724}
725
726#[cxx::bridge]
727pub(crate) mod raw {
728 impl UniquePtr<PkgRecords> {}
729
730 unsafe extern "C++" {
731 include!("rust-apt/apt-pkg-c/cache.h");
732 type PkgCacheFile;
733
734 type PkgIterator = crate::raw::PkgIterator;
735 type VerIterator = crate::raw::VerIterator;
736 type PkgFileIterator = crate::raw::PkgFileIterator;
737 type PkgRecords = crate::records::raw::PkgRecords;
738 type SourceRecords = crate::records::raw::SourceRecords;
739 type IndexFile = crate::records::raw::IndexFile;
740 type PkgDepCache = crate::depcache::raw::PkgDepCache;
741 type AcqTextStatus = crate::acquire::raw::AcqTextStatus;
742 type PkgAcquire = crate::acquire::raw::PkgAcquire;
743
744 /// Create the CacheFile.
745 pub fn create_cache(volatile_files: &[&str]) -> Result<UniquePtr<PkgCacheFile>>;
746
747 /// Update the package lists, handle errors and return a Result.
748 pub fn update(self: &PkgCacheFile, progress: Pin<&mut AcqTextStatus>) -> Result<()>;
749
750 /// Loads the index files into PkgAcquire.
751 ///
752 /// Used to get to source list uris.
753 ///
754 /// It's not clear if this returning a bool is useful.
755 pub fn get_indexes(self: &PkgCacheFile, fetcher: &PkgAcquire) -> bool;
756
757 /// Return a pointer to PkgDepcache.
758 ///
759 /// # Safety
760 ///
761 /// The returned UniquePtr cannot outlive the cache.
762 unsafe fn create_depcache(self: &PkgCacheFile) -> UniquePtr<PkgDepCache>;
763
764 /// Return a pointer to PkgRecords.
765 ///
766 /// # Safety
767 ///
768 /// The returned UniquePtr cannot outlive the cache.
769 unsafe fn create_records(self: &PkgCacheFile) -> UniquePtr<PkgRecords>;
770
771 unsafe fn source_records(self: &PkgCacheFile) -> Result<UniquePtr<SourceRecords>>;
772
773 /// The priority of the Version as shown in `apt policy`.
774 pub fn priority(self: &PkgCacheFile, version: &VerIterator) -> i32;
775
776 /// The priority of the Version as shown in `apt policy`.
777 ///
778 /// When `consider_files` is `true`, this is equivalent to
779 /// [`crate::Version::priority`] and includes package-file priorities in
780 /// the result.
781 ///
782 /// When `consider_files` is `false`, this returns only pin priority
783 /// without considering package-file priorities.
784 pub fn priority_with_files(
785 self: &PkgCacheFile,
786 version: &VerIterator,
787 consider_files: bool,
788 ) -> i32;
789
790 /// Lookup the IndexFile of the Package file
791 ///
792 /// # Safety
793 ///
794 /// The IndexFile can not outlive PkgCacheFile.
795 ///
796 /// The returned UniquePtr cannot outlive the cache.
797 unsafe fn find_index(self: &PkgCacheFile, file: &PkgFileIterator) -> UniquePtr<IndexFile>;
798
799 /// Return a package by name and optionally architecture.
800 ///
801 /// # Safety
802 ///
803 /// If the Internal Pkg Pointer is NULL, operations can segfault.
804 /// You should call `make_safe()` asap to convert it to an Option.
805 ///
806 /// The returned UniquePtr cannot outlive the cache.
807 unsafe fn find_pkg(self: &PkgCacheFile, name: &str) -> UniquePtr<PkgIterator>;
808
809 /// Return the pointer to the start of the PkgIterator.
810 ///
811 /// # Safety
812 ///
813 /// If the Internal Pkg Pointer is NULL, operations can segfault.
814 /// You should call `raw_iter()` asap.
815 ///
816 /// The returned UniquePtr cannot outlive the cache.
817 unsafe fn begin(self: &PkgCacheFile) -> UniquePtr<PkgIterator>;
818
819 /// Return the pointer to the start of the PkgFileIterator list.
820 ///
821 /// # Safety
822 ///
823 /// The returned UniquePtr cannot outlive the cache.
824 unsafe fn file_begin(self: &PkgCacheFile) -> UniquePtr<PkgFileIterator>;
825
826 /// Return the priority for a PackageFile as shown in `apt-cache
827 /// policy`.
828 pub fn file_priority(self: &PkgCacheFile, file: &PkgFileIterator) -> i32;
829 }
830}