Skip to main content

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}