flowey_lib_common/_util/
extract.rs1use flowey::node::prelude::*;
5
6const FLOWEY_INFO_DIR: &str = ".flowey_info";
7const FLOWEY_EXTRACT_DIR: &str = "extracted";
8
9#[derive(Clone)]
10#[non_exhaustive]
11pub struct ExtractZipDeps<C = VarNotClaimed> {
12 persistent_dir: Option<ReadVar<PathBuf, C>>,
13 bsdtar_installed: ReadVar<SideEffect, C>,
14}
15
16impl ClaimVar for ExtractZipDeps {
17 type Claimed = ExtractZipDeps<VarClaimed>;
18
19 fn claim(self, ctx: &mut StepCtx<'_>) -> Self::Claimed {
20 let Self {
21 persistent_dir,
22 bsdtar_installed,
23 } = self;
24 ExtractZipDeps {
25 persistent_dir: persistent_dir.claim(ctx),
26 bsdtar_installed: bsdtar_installed.claim(ctx),
27 }
28 }
29}
30
31#[track_caller]
32pub fn extract_zip_if_new_deps(ctx: &mut NodeCtx<'_>) -> ExtractZipDeps {
33 let platform = ctx.platform();
34 ExtractZipDeps {
35 persistent_dir: ctx.persistent_dir(),
36 bsdtar_installed: ctx.reqv(|v| crate::install_dist_pkg::Request::Install {
37 package_names: match platform {
38 FlowPlatform::Linux(linux_distribution) => match linux_distribution {
39 FlowPlatformLinuxDistro::Fedora => vec!["bsdtar".into()],
40 FlowPlatformLinuxDistro::Ubuntu => vec!["libarchive-tools".into()],
41 FlowPlatformLinuxDistro::Arch => vec!["libarchive".into()],
42 FlowPlatformLinuxDistro::Nix => vec![],
43 FlowPlatformLinuxDistro::Unknown => vec![],
44 },
45 _ => {
46 vec![]
47 }
48 },
49 done: v,
50 }),
51 }
52}
53
54pub fn extract_zip_if_new(
62 rt: &mut RustRuntimeServices<'_>,
63 deps: ExtractZipDeps<VarClaimed>,
64 file: &Path,
65 file_version: &str,
66) -> anyhow::Result<PathBuf> {
67 let ExtractZipDeps {
68 persistent_dir,
69 bsdtar_installed: _,
70 } = deps;
71
72 let root_dir = match persistent_dir {
73 Some(dir) => rt.read(dir),
74 None => rt.sh.current_dir(),
75 };
76
77 let filename = file.file_name().expect("zip file was not a file");
78 let extract_dir = root_dir.join(FLOWEY_EXTRACT_DIR).join(filename);
79 fs_err::create_dir_all(&extract_dir)?;
80
81 let pkg_info_dir = root_dir.join(FLOWEY_INFO_DIR);
82 fs_err::create_dir_all(&pkg_info_dir)?;
83 let pkg_info_file = pkg_info_dir.join(filename);
84
85 let mut already_extracted = false;
86 if let Ok(info) = fs_err::read_to_string(&pkg_info_file) {
87 if info == file_version {
88 already_extracted = true;
89 }
90 }
91
92 if !already_extracted {
93 fs_err::remove_dir_all(&extract_dir)?;
99 fs_err::create_dir(&extract_dir)?;
100
101 rt.sh.change_dir(&extract_dir);
102
103 let bsdtar = crate::_util::bsdtar_name(rt);
104 flowey::shell_cmd!(rt, "{bsdtar} -xf {file}").run()?;
105 fs_err::write(pkg_info_file, file_version)?;
106 } else {
107 log::info!("already extracted!");
108 }
109
110 Ok(extract_dir)
111}
112
113#[derive(Clone)]
114#[non_exhaustive]
115pub struct ExtractTarBz2Deps<C = VarNotClaimed> {
116 persistent_dir: Option<ReadVar<PathBuf, C>>,
117 bzip2_installed: ReadVar<SideEffect, C>,
118}
119
120impl ClaimVar for ExtractTarBz2Deps {
121 type Claimed = ExtractTarBz2Deps<VarClaimed>;
122
123 fn claim(self, ctx: &mut StepCtx<'_>) -> Self::Claimed {
124 let Self {
125 persistent_dir,
126 bzip2_installed,
127 } = self;
128 ExtractTarBz2Deps {
129 persistent_dir: persistent_dir.claim(ctx),
130 bzip2_installed: bzip2_installed.claim(ctx),
131 }
132 }
133}
134
135#[track_caller]
136pub fn extract_tar_bz2_if_new_deps(ctx: &mut NodeCtx<'_>) -> ExtractTarBz2Deps {
137 ExtractTarBz2Deps {
138 persistent_dir: ctx.persistent_dir(),
139 bzip2_installed: ctx.reqv(|v| crate::install_dist_pkg::Request::Install {
140 package_names: vec!["bzip2".into()],
141 done: v,
142 }),
143 }
144}
145
146pub fn extract_tar_bz2_if_new(
154 rt: &mut RustRuntimeServices<'_>,
155 deps: ExtractTarBz2Deps<VarClaimed>,
156 file: &Path,
157 file_version: &str,
158) -> anyhow::Result<PathBuf> {
159 let ExtractTarBz2Deps {
160 persistent_dir,
161 bzip2_installed: _,
162 } = deps;
163
164 let root_dir = match persistent_dir {
165 Some(dir) => rt.read(dir),
166 None => rt.sh.current_dir(),
167 };
168
169 let filename = file.file_name().expect("tar.bz2 file was not a file");
170 let extract_dir = root_dir.join(FLOWEY_EXTRACT_DIR).join(filename);
171 fs_err::create_dir_all(&extract_dir)?;
172
173 let pkg_info_dir = root_dir.join(FLOWEY_INFO_DIR);
174 fs_err::create_dir_all(&pkg_info_dir)?;
175 let pkg_info_file = pkg_info_dir.join(filename);
176
177 let mut already_extracted = false;
178 if let Ok(info) = fs_err::read_to_string(&pkg_info_file) {
179 if info == file_version {
180 already_extracted = true;
181 }
182 }
183
184 if !already_extracted {
185 rt.sh.change_dir(&extract_dir);
186
187 fs_err::remove_dir_all(&extract_dir)?;
193 fs_err::create_dir(&extract_dir)?;
194
195 flowey::shell_cmd!(rt, "tar -xf {file}").run()?;
197
198 fs_err::write(pkg_info_file, file_version)?;
199 } else {
200 log::info!("already extracted!");
201 }
202
203 Ok(extract_dir)
204}