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