1use crate::{
9 common::{
10 Compression,
11 SupportedFormat,
12 UnsupportedFormat,
13 },
14 consts::{
15 BZ2_MIME,
16 GZ_MIME,
17 SUPPORTED_MIME_TYPES,
18 TAR_MIME,
19 XZ_MIME,
20 ZST_MIME,
21 },
22};
23use glob::glob;
24use rayon::prelude::*;
25use std::{
26 fs,
27 io,
28 path::{
29 Path,
30 PathBuf,
31 },
32};
33use terminfo::{
34 Database,
35 capability as cap,
36};
37#[allow(unused_imports)]
38use tracing::{
39 debug,
40 error,
41 info,
42 trace,
43 warn,
44};
45use tracing_subscriber::EnvFilter;
46
47pub fn start_tracing()
50{
51 let terminfodb = Database::from_env().map_err(|e| {
52 error!(err = ?e, "Unable to access terminfo db. This is a bug!");
53 io::Error::other(
54 "Unable to access terminfo db. This is a bug! Setting color option to false!",
55 )
56 });
57
58 let is_termcolorsupported = match terminfodb
59 {
60 Ok(hasterminfodb) => hasterminfodb.get::<cap::MaxColors>().is_some(),
61 Err(_) => false,
62 };
63 let filter_layer = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
64
65 let builder = tracing_subscriber::fmt()
66 .with_level(true)
67 .with_ansi(is_termcolorsupported)
68 .with_env_filter(filter_layer)
69 .with_level(true);
70
71 let builder = if cfg!(debug_assertions)
72 {
73 builder.with_file(true).with_line_number(true)
74 }
75 else
76 {
77 builder
78 };
79
80 builder.init();
81}
82
83pub fn is_supported_format(src: &Path) -> Result<SupportedFormat, UnsupportedFormat>
87{
88 if let Ok(identified_src) = infer::get_from_path(src)
89 {
90 if let Some(known) = identified_src
91 {
92 debug!(?known);
93 if SUPPORTED_MIME_TYPES.contains(&known.mime_type())
94 {
95 return if known.mime_type().eq(GZ_MIME)
96 {
97 Ok(SupportedFormat::Compressed(Compression::Gz, src.to_path_buf()))
98 }
99 else if known.mime_type().eq(XZ_MIME)
100 {
101 Ok(SupportedFormat::Compressed(Compression::Xz, src.to_path_buf()))
102 }
103 else if known.mime_type().eq(ZST_MIME)
104 {
105 Ok(SupportedFormat::Compressed(Compression::Zst, src.to_path_buf()))
106 }
107 else if known.mime_type().eq(BZ2_MIME)
108 {
109 Ok(SupportedFormat::Compressed(Compression::Bz2, src.to_path_buf()))
110 }
111 else if known.mime_type().eq(TAR_MIME)
112 {
113 Ok(SupportedFormat::Compressed(Compression::Not, src.to_path_buf()))
114 }
115 else
116 {
117 error!("Should not be able to reach here!");
118 unreachable!()
119 };
120 }
121 }
122 else
123 {
124 let get_ext = match src.extension()
125 {
126 Some(ext) => ext.to_string_lossy().to_string(),
127 None => "unknown format".to_string(),
128 };
129 return Err(UnsupportedFormat { ext: get_ext });
130 }
131 }
132 Err(UnsupportedFormat { ext: "unknown format".to_string() })
133}
134
135pub fn copy_dir_all(src: impl AsRef<Path>, dst: &Path) -> Result<(), io::Error>
136{
137 debug!("Copying sources");
138 debug!(?dst);
139 fs::create_dir_all(dst)?;
140 let custom_walker = fs::read_dir(src)?;
141 custom_walker.par_bridge().into_par_iter().try_for_each(|entry| {
142 let entry = entry?;
143 let ty = entry.file_type()?;
144 trace!(?entry);
145 trace!(?ty);
146 if ty.is_dir()
147 {
148 trace!(?ty, "Is directory?");
149 copy_dir_all(entry.path(), &dst.join(entry.file_name()))
150
151 }
166 else if ty.is_file()
167 {
168 trace!(?ty, "Is file?");
169 fs::copy(entry.path(), dst.join(entry.file_name()))?;
170 Ok(())
171 }
172 else
173 {
174 Ok(())
175 }
176 })?;
177 Ok(())
178}
179
180pub fn process_globs(src: &Path) -> io::Result<PathBuf>
187{
188 let glob_iter = match glob(&src.as_os_str().to_string_lossy())
189 {
190 Ok(gi) =>
191 {
192 trace!(?gi);
193 gi
194 }
195 Err(e) =>
196 {
197 error!(err = ?e, "Invalid glob input");
198 return Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid glob input"));
199 }
200 };
201
202 let mut globs = glob_iter.into_iter().collect::<Result<Vec<_>, _>>().map_err(|e| {
203 error!(?e, "glob error");
204 io::Error::new(io::ErrorKind::InvalidInput, "Glob error")
205 })?;
206
207 globs.sort_unstable();
216
217 if globs.len() > 1
218 {
219 warn!("⚠️ Multiple files matched glob");
220 for item in &globs
221 {
222 warn!("- {}", item.display());
223 }
224 }
225
226 globs.pop().inspect(|item| info!("✅ Matched an item: {}", item.display())).ok_or_else(|| {
228 error!("No files/directories matched src glob input");
229 io::Error::new(io::ErrorKind::InvalidInput, "No files/directories matched src glob input")
230 })
231}