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 upgradable
305					if unsafe { pkg.current_version().end() }
306						|| !self.depcache().is_upgradable(&pkg)
307					{
308						continue;
309					}
310				},
311				// If reverse and the package is installed and upgradable, exclude
312				// This section is for if you only want packages that are not upgradable
313				Sort::Reverse => {
314					if unsafe { !pkg.current_version().end() }
315						&& self.depcache().is_upgradable(&pkg)
316					{
317						continue;
318					}
319				},
320			}
321
322			match sort.installed {
323				// Installed Package is Disabled, so we keep them
324				Sort::Disable => {},
325				Sort::Enable => {
326					if unsafe { pkg.current_version().end() } {
327						continue;
328					}
329				},
330				// Only include installed packages.
331				Sort::Reverse => {
332					if unsafe { !pkg.current_version().end() } {
333						continue;
334					}
335				},
336			}
337
338			match sort.auto_installed {
339				// Installed Package is Disabled, so we keep them
340				Sort::Disable => {},
341				Sort::Enable => {
342					if !self.depcache().is_auto_installed(&pkg) {
343						continue;
344					}
345				},
346				// Only include installed packages.
347				Sort::Reverse => {
348					if self.depcache().is_auto_installed(&pkg) {
349						continue;
350					}
351				},
352			}
353
354			match sort.auto_removable {
355				// auto_removable is Disabled, so we keep them
356				Sort::Disable => {},
357				// If the package is not auto removable skip it.
358				Sort::Enable => {
359					// If the Package isn't auto_removable skip
360					if !self.depcache().is_garbage(&pkg) {
361						continue;
362					}
363				},
364				// If the package is auto removable skip it.
365				Sort::Reverse => {
366					if self.depcache().is_garbage(&pkg) {
367						continue;
368					}
369				},
370			}
371
372			// If this is reached we're clear to include the package.
373			pkg_list.push(pkg);
374		}
375
376		if sort.names {
377			pkg_list.sort_by_cached_key(|pkg| pkg.name().to_string());
378		}
379
380		pkg_list.into_iter().map(|pkg| Package::new(self, pkg))
381	}
382
383	/// Updates the package cache and returns a Result
384	///
385	/// Here is an example of how you may parse the Error messages.
386	///
387	/// ```
388	/// use rust_apt::new_cache;
389	/// use rust_apt::progress::AcquireProgress;
390	///
391	/// let cache = new_cache!().unwrap();
392	/// let mut progress = AcquireProgress::apt();
393	/// if let Err(e) = cache.update(&mut progress) {
394	///     for error in e.iter() {
395	///         if error.is_error {
396	///             println!("Error: {}", error.msg);
397	///         } else {
398	///             println!("Warning: {}", error.msg);
399	///         }
400	///     }
401	/// }
402	/// ```
403	/// # Known Errors:
404	/// * E:Could not open lock file /var/lib/apt/lists/lock - open (13:
405	///   Permission denied)
406	/// * E:Unable to lock directory /var/lib/apt/lists/
407	pub fn update(self, progress: &mut AcquireProgress) -> Result<(), AptErrors> {
408		Ok(self.ptr.update(progress.mut_status())?)
409	}
410
411	/// Mark all packages for upgrade
412	///
413	/// # Example:
414	///
415	/// ```
416	/// use rust_apt::new_cache;
417	/// use rust_apt::cache::Upgrade;
418	///
419	/// let cache = new_cache!().unwrap();
420	///
421	/// cache.upgrade(Upgrade::FullUpgrade).unwrap();
422	/// ```
423	pub fn upgrade(&self, upgrade_type: Upgrade) -> Result<(), AptErrors> {
424		let mut progress = OperationProgress::quiet();
425		Ok(self
426			.depcache()
427			.upgrade(progress.pin().as_mut(), upgrade_type as i32)?)
428	}
429
430	/// Resolve dependencies with the changes marked on all packages. This marks
431	/// additional packages for installation/removal to satisfy the dependency
432	/// chain.
433	///
434	/// Note that just running a `mark_*` function on a package doesn't
435	/// guarantee that the selected state will be kept during dependency
436	/// resolution. If you need such, make sure to run
437	/// [`crate::Package::protect`] after marking your requested
438	/// modifications.
439	///
440	/// If `fix_broken` is set to [`true`], the library will try to repair
441	/// broken dependencies of installed packages.
442	///
443	/// Returns [`Err`] if there was an error reaching dependency resolution.
444	#[allow(clippy::result_unit_err)]
445	pub fn resolve(&self, fix_broken: bool) -> Result<(), AptErrors> {
446		Ok(self
447			.resolver()
448			.resolve(fix_broken, OperationProgress::quiet().pin().as_mut())?)
449	}
450
451	/// Autoinstall every broken package and run the problem resolver
452	/// Returns false if the problem resolver fails.
453	///
454	/// # Example:
455	///
456	/// ```
457	/// use rust_apt::new_cache;
458	///
459	/// let cache = new_cache!().unwrap();
460	///
461	/// cache.fix_broken();
462	///
463	/// for pkg in cache.get_changes(false) {
464	///     println!("Pkg Name: {}", pkg.name())
465	/// }
466	/// ```
467	pub fn fix_broken(&self) -> bool { self.depcache().fix_broken() }
468
469	/// Fetch any archives needed to complete the transaction.
470	///
471	/// # Returns:
472	/// * A [`Result`] enum: the [`Ok`] variant if fetching succeeded, and
473	///   [`Err`] if there was an issue.
474	///
475	/// # Example:
476	/// ```
477	/// use rust_apt::new_cache;
478	/// use rust_apt::progress::AcquireProgress;
479	///
480	/// let cache = new_cache!().unwrap();
481	/// let pkg = cache.get("neovim").unwrap();
482	/// let mut progress = AcquireProgress::apt();
483	///
484	/// pkg.mark_install(true, true);
485	/// pkg.protect();
486	/// cache.resolve(true).unwrap();
487	///
488	/// cache.get_archives(&mut progress).unwrap();
489	/// ```
490	/// # Known Errors:
491	/// * W:Problem unlinking the file
492	///   /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
493	///   PrepareFiles (13: Permission denied)
494	/// * W:Problem unlinking the file
495	///   /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
496	///   PrepareFiles (13: Permission denied)
497	/// * W:Problem unlinking the file
498	///   /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
499	///   PrepareFiles (13: Permission denied)
500	/// * W:Problem unlinking the file
501	///   /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
502	///   PrepareFiles (13: Permission denied)
503	/// * W:Problem unlinking the file
504	///   /var/cache/apt/archives/partial/neofetch_7.1.0-4_all.deb -
505	///   PrepareFiles (13: Permission denied)
506	/// * W:Problem unlinking the file /var/log/apt/eipp.log.xz - FileFd::Open
507	///   (13: Permission denied)
508	/// * W:Could not open file /var/log/apt/eipp.log.xz - open (17: File
509	///   exists)
510	/// * W:Could not open file '/var/log/apt/eipp.log.xz' - EIPP::OrderInstall
511	///   (17: File exists)
512	/// * E:Internal Error, ordering was unable to handle the media swap"
513	pub fn get_archives(&self, progress: &mut AcquireProgress) -> Result<(), Exception> {
514		self.pkg_manager()
515			.get_archives(&self.ptr, self.records(), progress.mut_status())
516	}
517
518	/// Install, remove, and do any other actions requested by the cache.
519	///
520	/// # Returns:
521	/// * A [`Result`] enum: the [`Ok`] variant if transaction was successful,
522	///   and [`Err`] if there was an issue.
523	///
524	/// # Example:
525	/// ```
526	/// use rust_apt::new_cache;
527	/// use rust_apt::progress::{AcquireProgress, InstallProgress};
528	///
529	/// let cache = new_cache!().unwrap();
530	/// let pkg = cache.get("neovim").unwrap();
531	/// let mut acquire_progress = AcquireProgress::apt();
532	/// let mut install_progress = InstallProgress::apt();
533	///
534	/// pkg.mark_install(true, true);
535	/// pkg.protect();
536	/// cache.resolve(true).unwrap();
537	///
538	/// // These need root
539	/// // cache.get_archives(&mut acquire_progress).unwrap();
540	/// // cache.do_install(&mut install_progress).unwrap();
541	/// ```
542	///
543	/// # Known Errors:
544	/// * W:Problem unlinking the file /var/log/apt/eipp.log.xz - FileFd::Open
545	///   (13: Permission denied)
546	/// * W:Could not open file /var/log/apt/eipp.log.xz - open (17: File
547	///   exists)
548	/// * W:Could not open file '/var/log/apt/eipp.log.xz' - EIPP::OrderInstall
549	///   (17: File exists)
550	/// * E:Could not create temporary file for /var/lib/apt/extended_states -
551	///   mkstemp (13: Permission denied)
552	/// * E:Failed to write temporary StateFile /var/lib/apt/extended_states
553	/// * W:Could not open file '/var/log/apt/term.log' - OpenLog (13:
554	///   Permission denied)
555	/// * E:Sub-process /usr/bin/dpkg returned an error code (2)
556	/// * W:Problem unlinking the file /var/cache/apt/pkgcache.bin -
557	///   pkgDPkgPM::Go (13: Permission denied)
558	pub fn do_install(self, progress: &mut InstallProgress) -> Result<(), AptErrors> {
559		let res = match progress {
560			InstallProgress::Fancy(inner) => self.pkg_manager().do_install(inner.pin().as_mut()),
561			InstallProgress::Fd(fd) => self.pkg_manager().do_install_fd(*fd),
562		};
563
564		if pending_error() {
565			return Err(AptErrors::new());
566		}
567
568		match res {
569			OrderResult::Completed => {},
570			OrderResult::Failed => panic!(
571				"DoInstall failed with no error from libapt. Please report this as an issue."
572			),
573			OrderResult::Incomplete => {
574				panic!("Result is 'Incomplete', please request media swapping as a feature.")
575			},
576			_ => unreachable!(),
577		}
578
579		Ok(())
580	}
581
582	/// Handle get_archives and do_install in an easy wrapper.
583	///
584	/// # Returns:
585	/// * A [`Result`]: the [`Ok`] variant if transaction was successful, and
586	///   [`Err`] if there was an issue.
587	/// # Example:
588	/// ```
589	/// use rust_apt::new_cache;
590	/// use rust_apt::progress::{AcquireProgress, InstallProgress};
591	///
592	/// let cache = new_cache!().unwrap();
593	/// let pkg = cache.get("neovim").unwrap();
594	/// let mut acquire_progress = AcquireProgress::apt();
595	/// let mut install_progress = InstallProgress::apt();
596	///
597	/// pkg.mark_install(true, true);
598	/// pkg.protect();
599	/// cache.resolve(true).unwrap();
600	///
601	/// // This needs root
602	/// // cache.commit(&mut acquire_progress, &mut install_progress).unwrap();
603	/// ```
604	pub fn commit(
605		self,
606		progress: &mut AcquireProgress,
607		install_progress: &mut InstallProgress,
608	) -> Result<(), AptErrors> {
609		// Lock the whole thing so as to prevent tamper
610		apt_lock()?;
611
612		let config = Config::new();
613		let archive_dir = config.dir("Dir::Cache::Archives", "/var/cache/apt/archives/");
614
615		// Copy local debs into archives dir
616		for deb in &self.local_debs {
617			// If file is already in the archive we don't copy
618			if deb.starts_with(archive_dir.as_str()) {
619				continue;
620			}
621			// If it reaches this point it really will be a valid filename, allegedly
622			if let Some(filename) = Path::new(deb).file_name() {
623				// Append the file name onto the archive dir
624				fs::copy(deb, archive_dir.to_string() + &filename.to_string_lossy())?;
625			}
626		}
627
628		// The archives can be grabbed during the apt lock.
629		self.get_archives(progress)?;
630
631		// If the system is locked we will want to unlock the dpkg files.
632		// This way when dpkg is running it can access its files.
633		apt_unlock_inner();
634
635		// Perform the operation.
636		self.do_install(install_progress)?;
637
638		// Finally Unlock the whole thing.
639		apt_unlock();
640		Ok(())
641	}
642
643	/// Get a single package.
644	///
645	/// `cache.get("apt")` Returns a Package object for the native arch.
646	///
647	/// `cache.get("apt:i386")` Returns a Package object for the i386 arch
648	pub fn get(&self, name: &str) -> Option<Package<'_>> {
649		Some(Package::new(self, unsafe {
650			self.find_pkg(name).make_safe()?
651		}))
652	}
653
654	/// An iterator over the packages
655	/// that will be altered when `cache.commit()` is called.
656	///
657	/// # sort_name:
658	/// * [`true`] = Packages will be in alphabetical order
659	/// * [`false`] = Packages will not be sorted by name
660	pub fn get_changes(&self, sort_name: bool) -> impl Iterator<Item = Package<'_>> {
661		let mut changed = Vec::new();
662		let depcache = self.depcache();
663
664		for pkg in self.raw_pkgs() {
665			if depcache.marked_install(&pkg)
666				|| depcache.marked_delete(&pkg)
667				|| depcache.marked_upgrade(&pkg)
668				|| depcache.marked_downgrade(&pkg)
669				|| depcache.marked_reinstall(&pkg)
670			{
671				changed.push(pkg);
672			}
673		}
674
675		if sort_name {
676			// Sort by cached key seems to be the fastest for what we're doing.
677			// Maybe consider impl ord or something for these.
678			changed.sort_by_cached_key(|pkg| pkg.name().to_string());
679		}
680
681		changed
682			.into_iter()
683			.map(|pkg_ptr| Package::new(self, pkg_ptr))
684	}
685}
686
687/// Iterator Implementation for the Cache.
688pub struct CacheIter<'a> {
689	pkgs: IterPkgIterator,
690	cache: &'a Cache,
691}
692
693impl<'a> Iterator for CacheIter<'a> {
694	type Item = Package<'a>;
695
696	fn next(&mut self) -> Option<Self::Item> { Some(Package::new(self.cache, self.pkgs.next()?)) }
697}
698
699#[cxx::bridge]
700pub(crate) mod raw {
701	impl UniquePtr<PkgRecords> {}
702
703	unsafe extern "C++" {
704		include!("rust-apt/apt-pkg-c/cache.h");
705		type PkgCacheFile;
706
707		type PkgIterator = crate::raw::PkgIterator;
708		type VerIterator = crate::raw::VerIterator;
709		type PkgFileIterator = crate::raw::PkgFileIterator;
710		type PkgRecords = crate::records::raw::PkgRecords;
711		type SourceRecords = crate::records::raw::SourceRecords;
712		type IndexFile = crate::records::raw::IndexFile;
713		type PkgDepCache = crate::depcache::raw::PkgDepCache;
714		type AcqTextStatus = crate::acquire::raw::AcqTextStatus;
715		type PkgAcquire = crate::acquire::raw::PkgAcquire;
716
717		/// Create the CacheFile.
718		pub fn create_cache(volatile_files: &[&str]) -> Result<UniquePtr<PkgCacheFile>>;
719
720		/// Update the package lists, handle errors and return a Result.
721		pub fn update(self: &PkgCacheFile, progress: Pin<&mut AcqTextStatus>) -> Result<()>;
722
723		/// Loads the index files into PkgAcquire.
724		///
725		/// Used to get to source list uris.
726		///
727		/// It's not clear if this returning a bool is useful.
728		pub fn get_indexes(self: &PkgCacheFile, fetcher: &PkgAcquire) -> bool;
729
730		/// Return a pointer to PkgDepcache.
731		///
732		/// # Safety
733		///
734		/// The returned UniquePtr cannot outlive the cache.
735		unsafe fn create_depcache(self: &PkgCacheFile) -> UniquePtr<PkgDepCache>;
736
737		/// Return a pointer to PkgRecords.
738		///
739		/// # Safety
740		///
741		/// The returned UniquePtr cannot outlive the cache.
742		unsafe fn create_records(self: &PkgCacheFile) -> UniquePtr<PkgRecords>;
743
744		unsafe fn source_records(self: &PkgCacheFile) -> Result<UniquePtr<SourceRecords>>;
745
746		/// The priority of the Version as shown in `apt policy`.
747		pub fn priority(self: &PkgCacheFile, version: &VerIterator) -> i32;
748
749		/// The priority of the Version as shown in `apt policy`.
750		///
751		/// When `consider_files` is `true`, this is equivalent to
752		/// [`crate::Version::priority`] and includes package-file priorities in
753		/// the result.
754		///
755		/// When `consider_files` is `false`, this returns only pin priority
756		/// without considering package-file priorities.
757		pub fn priority_with_files(
758			self: &PkgCacheFile,
759			version: &VerIterator,
760			consider_files: bool,
761		) -> i32;
762
763		/// Lookup the IndexFile of the Package file
764		///
765		/// # Safety
766		///
767		/// The IndexFile can not outlive PkgCacheFile.
768		///
769		/// The returned UniquePtr cannot outlive the cache.
770		unsafe fn find_index(self: &PkgCacheFile, file: &PkgFileIterator) -> UniquePtr<IndexFile>;
771
772		/// Return a package by name and optionally architecture.
773		///
774		/// # Safety
775		///
776		/// If the Internal Pkg Pointer is NULL, operations can segfault.
777		/// You should call `make_safe()` asap to convert it to an Option.
778		///
779		/// The returned UniquePtr cannot outlive the cache.
780		unsafe fn find_pkg(self: &PkgCacheFile, name: &str) -> UniquePtr<PkgIterator>;
781
782		/// Return the pointer to the start of the PkgIterator.
783		///
784		/// # Safety
785		///
786		/// If the Internal Pkg Pointer is NULL, operations can segfault.
787		/// You should call `raw_iter()` asap.
788		///
789		/// The returned UniquePtr cannot outlive the cache.
790		unsafe fn begin(self: &PkgCacheFile) -> UniquePtr<PkgIterator>;
791
792		/// Return the pointer to the start of the PkgFileIterator list.
793		///
794		/// # Safety
795		///
796		/// The returned UniquePtr cannot outlive the cache.
797		unsafe fn file_begin(self: &PkgCacheFile) -> UniquePtr<PkgFileIterator>;
798
799		/// Return the priority for a PackageFile as shown in `apt-cache
800		/// policy`.
801		pub fn file_priority(self: &PkgCacheFile, file: &PkgFileIterator) -> i32;
802	}
803}