1use colored::Colorize;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use std::fmt::{Debug, Display};
7use std::fs::{self, OpenOptions, create_dir_all};
8use std::io::Write;
9use std::path::{Path, PathBuf};
10use std::process::exit;
11use time::{OffsetDateTime, PrimitiveDateTime};
12
13#[derive(Serialize, Deserialize, PartialEq, Clone)]
14pub struct UninPackage {
15 pub name: String,
16 pub paths: Vec<PathBuf>,
17 pub change_date: String,
18 pub updated: bool,
19}
20
21impl Display for UninPackage {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 write!(
24 f,
25 "\tName: {}\n\tPaths: {:?}\n\tChange Date: {}\n",
26 self.name, self.paths, self.change_date
27 )
28 }
29}
30impl UninPackage {
31 pub fn new(name: String) -> Self {
32 UninPackage {
33 name,
34 paths: Vec::new(),
35 change_date: "1970-01-01 00:00:00.0".to_string(),
36 updated: false,
37 }
38 }
39}
40pub struct DebuggableOptionUninPackage(pub Option<UninPackage>);
41
42impl Debug for DebuggableOptionUninPackage {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 match &self.0 {
45 Some(p) => write!(f, "{}", p),
46 None => write!(f, "None"),
47 }
48 }
49}
50
51pub fn get_registry() {
52 if !registry_exists() {
53 println!("{}", "Registry couldn't be found nor created. Consider creating it manually at ~/.unin/registry/registry.json".red());
54 }
55 let home = std::env::var("HOME").unwrap();
56 let registry_path = PathBuf::from(format!("{}/.unin/registry/", home));
57 let registry_file = PathBuf::from(format!("{}/registry.json", registry_path.to_str().unwrap()));
58 let data = fs::read_to_string(registry_file).unwrap();
59 let packages: Vec<UninPackage> =
60 serde_json::from_str(&data).unwrap_or_else(|e| panic!("Shit happened: {:?}", e));
61 for p in packages {
62 println!("\n{}", p);
63 }
64}
65pub fn time_create() -> String {
66 let now_utc = OffsetDateTime::now_utc();
67 let primitive_now_utc = PrimitiveDateTime::new(
68 now_utc.date(),
69 now_utc
70 .time()
71 .truncate_to_second()
72 .replace_nanosecond(0)
73 .unwrap(),
74 );
75 let fucking_string = PrimitiveDateTime::to_string(&primitive_now_utc);
76 format!("{}", fucking_string)
77}
78
79pub fn time_read() -> PrimitiveDateTime {
80 let registry_path = PathBuf::from(format!(
81 "{}/.unin/registry/",
82 String::from(std::env::var("HOME").unwrap_or_else(|_| "/root/".to_string()))
83 ));
84 let registry_file = PathBuf::from(format!("{}/registry.json", registry_path.to_str().unwrap()));
85 let data = std::fs::read_to_string(registry_file).unwrap();
86 let p: UninPackage =
87 serde_json::from_str(&data).unwrap_or_else(|e| panic!("Shit happened: {:?}", e));
88 let time_string: String = p.change_date.clone();
89 let x: PrimitiveDateTime =
90 PrimitiveDateTime::parse(&time_string, &time::format_description::well_known::Rfc3339)
91 .unwrap();
92 println!("{}", String::from(x.to_string()));
93 x
94}
95
96pub fn registry_write(package: &UninPackage) {
97 let registry_path = format!(
98 "{}/.unin/registry/registry.json",
99 std::env::var("HOME").unwrap()
100 );
101 let registry_dir = Path::new(®istry_path).parent().unwrap();
102
103 let _ = create_dir_all(registry_dir);
104
105 let existing_content = fs::read_to_string(®istry_path).unwrap_or_else(|_| String::new());
106 let mut is_new = true;
107 for line in existing_content.lines() {
108 if line.contains(package.name.trim()) {
109 is_new = false;
110 break;
111 }
112 }
113
114 let mut packages: Vec<UninPackage> =
115 serde_json::from_str(&existing_content).unwrap_or_else(|_| Vec::new());
116
117 let package_name = package.name.clone();
118
119 if let Some(pos) = packages.iter().position(|p| p.name == package.name) {
120 packages[pos].updated = true;
121 packages[pos].change_date = time_create();
122 packages[pos].paths = package.paths.clone();
123 } else {
124 packages.push((*package).clone())
125 }
126
127 let mut file = OpenOptions::new()
128 .write(true)
129 .create(true)
130 .truncate(true)
131 .open(®istry_path)
132 .unwrap();
133
134 serde_json::to_writer(&mut file, &packages).unwrap();
135 file.flush().unwrap();
136
137 if is_new {
138 println!(
139 "Registry for entry {} created successfully!",
140 package_name.green()
141 );
142 } else {
143 println!(
144 "Registry for entry {} updated successfully!",
145 package_name.green()
146 );
147 }
148}
149pub fn registry_get_package(package_name: String) -> Option<UninPackage> {
150 if !registry_exists() {
151 println!("{}", "Registry couldn't be found nor created. Consider creating it manually at ~/.unin/registry/registry.json".red());
152 }
153 let home = std::env::var("HOME").unwrap();
154 let registry_path = PathBuf::from(format!("{}/.unin/registry/", home));
155 let registry_file = PathBuf::from(format!("{}/registry.json", registry_path.to_str().unwrap()));
156 let data = fs::read_to_string(registry_file).unwrap();
157 let packages: Vec<UninPackage> =
158 serde_json::from_str(&data).unwrap_or_else(|e| panic!("Shit happened: {:?}", e));
159
160 packages.into_iter().find(|p| p.name == package_name)
161}
162pub fn registry_exists() -> bool {
163 let registry_path = PathBuf::from(format!(
164 "{}/.unin/registry/",
165 std::env::var("HOME").unwrap()
166 ));
167 let registry_file = PathBuf::from(format!("{}/registry.json", registry_path.to_str().unwrap()));
168 if !registry_file.exists() {
169 if !create_dir_all(®istry_path).is_ok() {
170 println!("Failed to create registry for unPack ver 0.0.1");
172 false } else {
174 if let Ok(mut file) = std::fs::File::create(®istry_file) {
176 let _ = file.write_all(b"[]"); true } else {
179 println!("Failed to create registry file");
180 false }
182 }
183 } else {
184 true }
186}
187pub fn registry_uninstall(package_name: String) {
188 let home = std::env::var("HOME").unwrap();
189 let registry_path: PathBuf = PathBuf::from(format!("{}/.unin/registry/registry.json", home));
190 let registry_json: Value =
191 serde_json::from_str(&fs::read_to_string(registry_path.clone()).unwrap()).unwrap();
192 let mut packages: Vec<UninPackage> = serde_json::from_value(registry_json).unwrap();
193 let package_remove_queued = packages
194 .clone()
195 .into_iter()
196 .find(|p| p.name == package_name);
197 println!("\n{}", &package_remove_queued.clone().unwrap());
198
199 let confirmation = dialoguer::Confirm::new()
200 .with_prompt("Are you sure you want to delete this application?")
201 .interact()
202 .unwrap();
203 if !confirmation {
204 exit(0)
205 }
206
207 let delete_job = std::process::Command::new("sudo")
208 .arg("rm".to_string())
209 .arg("-f")
210 .arg(
211 &package_remove_queued.clone().unwrap().paths[0]
212 .to_str()
213 .unwrap(),
214 )
215 .output()
216 .unwrap()
217 .status;
218
219 if !delete_job.success() {
220 println!(
221 "Failed to delete the file for {}",
222 package_remove_queued.clone().unwrap().name
223 );
224 let confirmation = dialoguer::Confirm::new()
225 .with_prompt("Do you want to delete the registry entry anyway?")
226 .interact()
227 .unwrap();
228 if confirmation {
229 packages.retain(|p| p.name != package_name);
230 let _ = std::fs::write(registry_path, serde_json::to_string(&packages).unwrap());
231 println!("Registry entry for {} deleted", package_name);
232 exit(0)
233 } else {
234 println!("Aborting");
235 }
236 } else {
237 packages.retain(|p| p.name != package_name);
238 let _ = fs::write(registry_path, serde_json::to_string(&packages).unwrap());
239 println!("Registry entry for {} deleted", package_name);
240 }
241}
242
243pub fn temp_test() {
244 let x: UninPackage = UninPackage {
245 name: String::from("dev"),
246 paths: vec![PathBuf::from("/root/ad"), PathBuf::from("/root/da")],
247 change_date: String::from(time_create()),
248 updated: false,
249 };
250 let _lol = get_registry();
251}
252pub fn return_registry_path() -> PathBuf {
253 let registry_path = PathBuf::from(format!(
254 "{}/.unin/registry/registry.json",
255 std::env::var("HOME").unwrap()
256 ));
257 registry_path
258}