1use log::info;
2use log::warn;
3
4use crate::Bin;
5use crate::Database;
6use crate::Error;
7
8use std::{fs::DirBuilder, path::PathBuf};
9
10const MAP_DIR: &str = "maps";
11const BLOBS_DIR: &str = "blobs";
12const MELD_DB: &str = "meld.db";
13
14impl Bin {
15 pub fn get_maps_str(&self) -> Result<String, Error> {
17 match self.maps.to_str() {
18 Some(s) => Ok(s.to_string()),
19 None => Err(Error::IOError {
20 msg: "Failed to get maps".to_string(),
21 }),
22 }
23 }
24
25 pub fn get_blobs_str(&self) -> Result<String, Error> {
26 match self.blobs.to_str() {
27 Some(s) => Ok(s.to_string()),
28 None => Err(Error::IOError {
29 msg: "Failed to get maps".to_string(),
30 }),
31 }
32 }
33
34 fn is_valid(&self) -> bool {
35 return self.path.exists()
36 && self.blobs.exists()
37 && self.maps.exists()
38 && self.db.path.exists()
39 && self.db.is_valid();
40 }
41
42 pub fn from(path: String) -> Result<Self, Error> {
44 info!("Opening bin at {}", path);
45 let bin = Bin {
46 path: PathBuf::from(&path),
47 maps: PathBuf::from(format!("{}/{}", &path, MAP_DIR)),
48 blobs: PathBuf::from(format!("{}/{}", &path, BLOBS_DIR)),
49 db: Database {
50 path: PathBuf::from(format!("{}/{}", &path, MELD_DB)),
51 },
52 };
53
54 return if bin.is_valid() {
56 Ok(bin)
57 } else {
58 Err(Error::InitFailed {
59 msg: "Selected bin is invalid".to_string(),
60 })
61 };
62 }
63
64 fn create_dir(dirb: &DirBuilder, path: &PathBuf) -> Result<(), Error> {
66 info!("Creating {:?}", path);
67 match dirb.create(path) {
68 Ok(_) => Ok(()),
69 Err(e) => {
70 if e.kind() == std::io::ErrorKind::NotFound {
71 return Err(Error::ParentsDontExist);
72 } else {
73 return Err(Error::InitFailed {
74 msg: "Failed to Create Valid Bin".to_string(),
75 });
76 }
77 }
78 }
79 }
80
81 pub fn new(path: String, force: bool, parents: bool) -> Result<Self, Error> {
83 info!("Creating bin at {}", path);
84 let bin = Bin {
85 path: PathBuf::from(&path),
86 maps: PathBuf::from(format!("{}/{}", &path, MAP_DIR)),
87 blobs: PathBuf::from(format!("{}/{}", &path, BLOBS_DIR)),
88 db: Database {
89 path: PathBuf::from(format!("{}/{}", &path, MELD_DB)),
90 },
91 };
92
93 let mut dirb = DirBuilder::new();
95 dirb.recursive(parents);
96 if bin.path.exists() {
97 warn!("Bin folder already exists");
98 if !force {
99 return Err(Error::BinAlreadyExists { bin: path });
100 } else {
101 warn!("Removing {}", path);
102 match std::fs::remove_dir_all(path) {
103 Ok(_) => {}
104 Err(e) => return Err(Error::InitFailed { msg: e.to_string() }),
105 }
106 }
107 }
108
109 Bin::create_dir(&dirb, &bin.path)?;
111 Bin::create_dir(&dirb, &bin.maps)?;
112 Bin::create_dir(&dirb, &bin.blobs)?;
113
114 bin.db.create_db_schema()?;
116
117 return if bin.is_valid() {
119 Ok(bin)
120 } else {
121 Err(Error::InitFailed {
122 msg: "Failed to Create Valid Bin".to_string(),
123 })
124 };
125 }
126}