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