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::Unknown => vec![],
43 },
44 _ => {
45 vec![]
46 }
47 },
48 done: v,
49 }),
50 }
51}
52
53pub fn extract_zip_if_new(
61 rt: &mut RustRuntimeServices<'_>,
62 deps: ExtractZipDeps<VarClaimed>,
63 file: &Path,
64 file_version: &str,
65) -> anyhow::Result<PathBuf> {
66 let ExtractZipDeps {
67 persistent_dir,
68 bsdtar_installed: _,
69 } = deps;
70
71 let sh = xshell::Shell::new()?;
72
73 let root_dir = match persistent_dir {
74 Some(dir) => rt.read(dir),
75 None => sh.current_dir(),
76 };
77
78 let filename = file.file_name().expect("zip file was not a file");
79 let extract_dir = root_dir.join(FLOWEY_EXTRACT_DIR).join(filename);
80 fs_err::create_dir_all(&extract_dir)?;
81
82 let pkg_info_dir = root_dir.join(FLOWEY_INFO_DIR);
83 fs_err::create_dir_all(&pkg_info_dir)?;
84 let pkg_info_file = pkg_info_dir.join(filename);
85
86 let mut already_extracted = false;
87 if let Ok(info) = fs_err::read_to_string(&pkg_info_file) {
88 if info == file_version {
89 already_extracted = true;
90 }
91 }
92
93 if !already_extracted {
94 fs_err::remove_dir_all(&extract_dir)?;
100 fs_err::create_dir(&extract_dir)?;
101
102 sh.change_dir(&extract_dir);
103
104 let bsdtar = crate::_util::bsdtar_name(rt);
105 xshell::cmd!(sh, "{bsdtar} -xf {file}").run()?;
106 fs_err::write(pkg_info_file, file_version)?;
107 } else {
108 log::info!("already extracted!");
109 }
110
111 Ok(extract_dir)
112}
113
114#[derive(Clone)]
115#[non_exhaustive]
116pub struct ExtractTarBz2Deps<C = VarNotClaimed> {
117 persistent_dir: Option<ReadVar<PathBuf, C>>,
118 lbzip2_installed: ReadVar<SideEffect, C>,
119}
120
121impl ClaimVar for ExtractTarBz2Deps {
122 type Claimed = ExtractTarBz2Deps<VarClaimed>;
123
124 fn claim(self, ctx: &mut StepCtx<'_>) -> Self::Claimed {
125 let Self {
126 persistent_dir,
127 lbzip2_installed,
128 } = self;
129 ExtractTarBz2Deps {
130 persistent_dir: persistent_dir.claim(ctx),
131 lbzip2_installed: lbzip2_installed.claim(ctx),
132 }
133 }
134}
135
136#[track_caller]
137pub fn extract_tar_bz2_if_new_deps(ctx: &mut NodeCtx<'_>) -> ExtractTarBz2Deps {
138 ExtractTarBz2Deps {
139 persistent_dir: ctx.persistent_dir(),
140 lbzip2_installed: ctx.reqv(|v| crate::install_dist_pkg::Request::Install {
141 package_names: vec!["lbzip2".into()],
142 done: v,
143 }),
144 }
145}
146
147pub fn extract_tar_bz2_if_new(
155 rt: &mut RustRuntimeServices<'_>,
156 deps: ExtractTarBz2Deps<VarClaimed>,
157 file: &Path,
158 file_version: &str,
159) -> anyhow::Result<PathBuf> {
160 let ExtractTarBz2Deps {
161 persistent_dir,
162 lbzip2_installed: _,
163 } = deps;
164
165 let sh = xshell::Shell::new()?;
166
167 let root_dir = match persistent_dir {
168 Some(dir) => rt.read(dir),
169 None => sh.current_dir(),
170 };
171
172 let filename = file.file_name().expect("tar.bz2 file was not a file");
173 let extract_dir = root_dir.join(FLOWEY_EXTRACT_DIR).join(filename);
174 fs_err::create_dir_all(&extract_dir)?;
175
176 let pkg_info_dir = root_dir.join(FLOWEY_INFO_DIR);
177 fs_err::create_dir_all(&pkg_info_dir)?;
178 let pkg_info_file = pkg_info_dir.join(filename);
179
180 let mut already_extracted = false;
181 if let Ok(info) = fs_err::read_to_string(&pkg_info_file) {
182 if info == file_version {
183 already_extracted = true;
184 }
185 }
186
187 if !already_extracted {
188 sh.change_dir(&extract_dir);
189
190 fs_err::remove_dir_all(&extract_dir)?;
196 fs_err::create_dir(&extract_dir)?;
197
198 xshell::cmd!(sh, "tar -xf {file}").run()?;
200
201 fs_err::write(pkg_info_file, file_version)?;
202 } else {
203 log::info!("already extracted!");
204 }
205
206 Ok(extract_dir)
207}