Skip to main content

unin_bin/
registry.rs

1//unPack ver 0.0.1
2
3use 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(&registry_path).parent().unwrap();
102
103    let _ = create_dir_all(registry_dir);
104
105    let existing_content = fs::read_to_string(&registry_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(&registry_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(&registry_path).is_ok() {
170            // Create the DIRECTORY, not the file path
171            println!("Failed to create registry for unPack ver 0.0.1");
172            false //the directory didn't get created, so it doesn't exist.
173        } else {
174            // Create the empty registry file
175            if let Ok(mut file) = std::fs::File::create(&registry_file) {
176                let _ = file.write_all(b"[]"); // Write empty JSON array
177                true //it exists now
178            } else {
179                println!("Failed to create registry file");
180                false //It didn't get created, so it doesn't exist.
181            }
182        }
183    } else {
184        true //It existed and it will exist forever.
185    }
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}