1use std::{
2 fs::{remove_dir_all, write},
3 path::PathBuf,
4 process::exit,
5};
6
7use alpm_common::MetadataFile;
8use alpm_srcinfo::{SourceInfo, SourceInfoV1};
9use log::warn;
10use serde_json::to_string_pretty;
11use strum::IntoEnumIterator;
12
13use crate::{
14 CacheDir,
15 Error,
16 cli::{CleanTarget, DownloadCmd, TestFileFormat},
17 consts::{DATABASES_DIR, DOWNLOAD_DIR, PACKAGES_DIR, PKGSRC_DIR},
18 sync::{
19 PackageRepositories,
20 aur::AurDownloader,
21 mirror::MirrorDownloader,
22 pkgsrc::PkgSrcDownloader,
23 },
24 testing::TestRunner,
25};
26
27pub(crate) fn test_files(
35 cache_dir: CacheDir,
36 file_type: TestFileFormat,
37 repositories: Option<Vec<PackageRepositories>>,
38) -> Result<(), Error> {
39 let runner = TestRunner {
40 cache_dir,
41 file_type,
42 repositories,
43 };
44 runner.run_tests()?;
45
46 Ok(())
47}
48
49pub(crate) fn download_files(
51 cache_dir: CacheDir,
52 source: DownloadCmd,
53 repositories: Option<Vec<PackageRepositories>>,
54) -> Result<(), Error> {
55 let repositories = PackageRepositories::iter()
56 .filter(|v| repositories.clone().is_none_or(|r| r.contains(v)))
57 .collect();
58
59 match source {
60 DownloadCmd::PkgSrcRepositories {} => {
61 let downloader = PkgSrcDownloader { cache_dir };
62 downloader.download_package_source_repositories()?;
63 }
64 DownloadCmd::Aur {} => {
65 let downloader = AurDownloader { cache_dir };
66 downloader.download_packages()?;
67 }
68 DownloadCmd::Databases {
69 mirror,
70 force_extract,
71 } => {
72 let downloader = MirrorDownloader {
73 cache_dir,
74 mirror,
75 repositories,
76 extract_all: force_extract,
77 };
78 warn!(
79 "Beginning database retrieval\nIf the process is unexpectedly halted, rerun with `--force-extract` flag"
80 );
81 downloader.sync_remote_databases()?;
82 }
83 DownloadCmd::Packages {
84 mirror,
85 force_extract,
86 } => {
87 let downloader = MirrorDownloader {
88 cache_dir,
89 mirror,
90 repositories,
91 extract_all: force_extract,
92 };
93 warn!(
94 "Beginning package retrieval\nIf the process is unexpectedly halted, rerun with `--force-extract` flag"
95 );
96 downloader.sync_remote_packages()?;
97 }
98 }
99
100 Ok(())
101}
102
103pub(crate) fn clean_files(target: CleanTarget, cache_dir: CacheDir) -> Result<(), Error> {
105 let dirs = match target {
106 CleanTarget::PkgSrcRepositories => [
107 cache_dir.as_ref().join(DOWNLOAD_DIR).join(PKGSRC_DIR),
108 cache_dir.as_ref().join(PKGSRC_DIR),
109 ],
110 CleanTarget::Databases => [
111 cache_dir.as_ref().join(DOWNLOAD_DIR).join(DATABASES_DIR),
112 cache_dir.as_ref().join(DATABASES_DIR),
113 ],
114 CleanTarget::Packages => [
115 cache_dir.as_ref().join(DOWNLOAD_DIR).join(PACKAGES_DIR),
116 cache_dir.as_ref().join(PACKAGES_DIR),
117 ],
118 };
119
120 for dir in dirs {
121 remove_dir_all(&dir).map_err(|source| Error::IoPath {
122 path: dir,
123 context: "recursively deleting the directory".to_string(),
124 source,
125 })?;
126 }
127
128 Ok(())
129}
130
131pub fn compare_source_info(pkgbuild_path: PathBuf, srcinfo_path: PathBuf) -> Result<(), Error> {
154 let pkgbuild_source_info: SourceInfoV1 = SourceInfoV1::from_pkgbuild(&pkgbuild_path)?;
155
156 let source_info = SourceInfo::from_file_with_schema(srcinfo_path, None)?;
157 let SourceInfo::V1(source_info) = source_info;
158
159 if source_info != pkgbuild_source_info {
160 let pkgbuild_source_info =
161 to_string_pretty(&pkgbuild_source_info).map_err(|source| Error::Json {
162 context: "deserializing a PKGBUILD based SRCINFO as pretty JSON".to_string(),
163 source,
164 })?;
165 let source_info = to_string_pretty(&source_info).map_err(|source| Error::Json {
166 context: "deserializing a SRCINFO as pretty JSON".to_string(),
167 source,
168 })?;
169
170 let pkgbuild_json_path = PathBuf::from("pkgbuild.json");
171 write("pkgbuild.json", pkgbuild_source_info).map_err(|source| Error::IoPath {
172 path: pkgbuild_json_path,
173 context: "writing pkgbuild.json file".to_string(),
174 source,
175 })?;
176 let srcinfo_json_path = PathBuf::from("srcinfo.json");
177 write("srcinfo.json", source_info).map_err(|source| Error::IoPath {
178 path: srcinfo_json_path,
179 context: "writing srcinfo.json file".to_string(),
180 source,
181 })?;
182
183 eprintln!(
184 "SRCINFO data generated from PKGBUILD file differs from the .SRCINFO file read from disk.\n\
185 Compare the two generated files pkgbuild.json and srcinfo.json for details."
186 );
187 exit(1);
188 } else {
189 println!("The generated content matches that read from disk.");
190 }
191
192 Ok(())
193}