|
|
@ -1,11 +1,13 @@ |
|
|
|
|
|
|
|
use crate::paths; |
|
|
|
use crate::encoder; |
|
|
|
use crate::encoder; |
|
|
|
|
|
|
|
use crate::git; |
|
|
|
|
|
|
|
|
|
|
|
use encoder::Encoder; |
|
|
|
use encoder::Encoder; |
|
|
|
|
|
|
|
use git::Git; |
|
|
|
|
|
|
|
|
|
|
|
use std::collections::HashSet; |
|
|
|
use std::collections::HashSet; |
|
|
|
use std::hash::{Hash, Hasher}; |
|
|
|
use std::hash::{Hash, Hasher}; |
|
|
|
|
|
|
|
|
|
|
|
use std::env; |
|
|
|
|
|
|
|
use std::fs; |
|
|
|
use std::fs; |
|
|
|
use std::path::Path; |
|
|
|
use std::path::Path; |
|
|
|
use std::io::{self, Write, BufRead}; |
|
|
|
use std::io::{self, Write, BufRead}; |
|
|
@ -13,11 +15,6 @@ use std::fmt; |
|
|
|
use std::cmp::{PartialEq, Ordering}; |
|
|
|
use std::cmp::{PartialEq, Ordering}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static ENV_MPS_HOME: &str = "MPS_HOME"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static PATH_STORAGE: &str = "storage"; // should be under git
|
|
|
|
|
|
|
|
static PATH_DB: &str = "db.mps"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)] |
|
|
|
#[derive(Clone)] |
|
|
|
pub struct Item { |
|
|
|
pub struct Item { |
|
|
@ -82,20 +79,6 @@ impl Storage { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn get_storage_path() -> io::Result<String> { |
|
|
|
|
|
|
|
let mps_home = env::var(ENV_MPS_HOME).map_err(|err| { |
|
|
|
|
|
|
|
io::Error::new(io::ErrorKind::NotFound, format!("{} error: {}", ENV_MPS_HOME, err)) |
|
|
|
|
|
|
|
})?; |
|
|
|
|
|
|
|
let result = format!("{}/{}", mps_home, PATH_STORAGE); |
|
|
|
|
|
|
|
Ok(result) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn get_db_path() -> io::Result<String> { |
|
|
|
|
|
|
|
let st = Storage::get_storage_path()?; |
|
|
|
|
|
|
|
let result = format!("{}/{}", st, PATH_DB); |
|
|
|
|
|
|
|
Ok(result) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn from_db(passphrase: String) -> io::Result<Storage> { |
|
|
|
pub fn from_db(passphrase: String) -> io::Result<Storage> { |
|
|
|
if !Storage::is_inited()? { |
|
|
|
if !Storage::is_inited()? { |
|
|
|
return Err(io::Error::new( |
|
|
|
return Err(io::Error::new( |
|
|
@ -104,7 +87,7 @@ impl Storage { |
|
|
|
)); |
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
let encoder = Encoder::from(&passphrase); |
|
|
|
let encoder = Encoder::from(&passphrase); |
|
|
|
let file = fs::File::open(Storage::get_db_path()?)?; |
|
|
|
let file = fs::File::open(paths::get_db_path()?)?; |
|
|
|
let reader = io::BufReader::new(file); |
|
|
|
let reader = io::BufReader::new(file); |
|
|
|
let mut items = HashSet::<Item>::new(); |
|
|
|
let mut items = HashSet::<Item>::new(); |
|
|
|
let mut id: Option<String> = None; |
|
|
|
let mut id: Option<String> = None; |
|
|
@ -144,7 +127,7 @@ impl Storage { |
|
|
|
|
|
|
|
|
|
|
|
pub fn init(passphrase: String) -> io::Result<()> { |
|
|
|
pub fn init(passphrase: String) -> io::Result<()> { |
|
|
|
Storage::check_installed()?; |
|
|
|
Storage::check_installed()?; |
|
|
|
let db_path = Storage::get_db_path()?; |
|
|
|
let db_path = paths::get_db_path()?; |
|
|
|
fs::File::create(db_path)?; |
|
|
|
fs::File::create(db_path)?; |
|
|
|
let st = Storage::new(passphrase); |
|
|
|
let st = Storage::new(passphrase); |
|
|
|
st.dump()?; |
|
|
|
st.dump()?; |
|
|
@ -153,20 +136,20 @@ impl Storage { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn check_installed() -> io::Result<()> { |
|
|
|
pub fn check_installed() -> io::Result<()> { |
|
|
|
let sp = Storage::get_storage_path()?; |
|
|
|
let sp = paths::get_storage_path()?; |
|
|
|
let storage_path = Path::new(&sp); |
|
|
|
let storage_path = Path::new(&sp); |
|
|
|
// Check if the folder exists and is a directory
|
|
|
|
// Check if the folder exists and is a directory
|
|
|
|
if !storage_path.exists() || !storage_path.is_dir() { |
|
|
|
if !storage_path.exists() || !storage_path.is_dir() { |
|
|
|
return Err(io::Error::new( |
|
|
|
return Err(io::Error::new( |
|
|
|
io::ErrorKind::NotFound, |
|
|
|
io::ErrorKind::NotFound, |
|
|
|
format!("{} does not exist or not a dir", Storage::get_storage_path()?) |
|
|
|
format!("{} does not exist or not a dir", sp) |
|
|
|
)); |
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
let git_path = storage_path.join(".git"); |
|
|
|
let git_path = storage_path.join(".git"); |
|
|
|
if !git_path.exists() || !git_path.is_dir() { |
|
|
|
if !git_path.exists() || !git_path.is_dir() { |
|
|
|
return Err(io::Error::new( |
|
|
|
return Err(io::Error::new( |
|
|
|
io::ErrorKind::NotFound, |
|
|
|
io::ErrorKind::NotFound, |
|
|
|
format!("{} not under git", Storage::get_storage_path()?) |
|
|
|
format!("{} not under git", sp) |
|
|
|
)); |
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
@ -174,7 +157,7 @@ impl Storage { |
|
|
|
|
|
|
|
|
|
|
|
pub fn is_inited() -> io::Result<bool> { |
|
|
|
pub fn is_inited() -> io::Result<bool> { |
|
|
|
Storage::check_installed()?; |
|
|
|
Storage::check_installed()?; |
|
|
|
let db = Storage::get_db_path()?; |
|
|
|
let db = paths::get_db_path()?; |
|
|
|
let db_path = Path::new(&db); |
|
|
|
let db_path = Path::new(&db); |
|
|
|
Ok(db_path.exists()) |
|
|
|
Ok(db_path.exists()) |
|
|
|
} |
|
|
|
} |
|
|
@ -211,7 +194,7 @@ impl Storage { |
|
|
|
let mut file = fs::OpenOptions::new() |
|
|
|
let mut file = fs::OpenOptions::new() |
|
|
|
.write(true) |
|
|
|
.write(true) |
|
|
|
.append(false) |
|
|
|
.append(false) |
|
|
|
.open(Storage::get_db_path()?)?; |
|
|
|
.open(paths::get_db_path()?)?; |
|
|
|
writeln!(file, "{}", self.encoder.get_encoded_test_passphrase()?)?; |
|
|
|
writeln!(file, "{}", self.encoder.get_encoded_test_passphrase()?)?; |
|
|
|
|
|
|
|
|
|
|
|
for item in self.items.iter() { |
|
|
|
for item in self.items.iter() { |
|
|
@ -219,6 +202,7 @@ impl Storage { |
|
|
|
let content = self.encoder.encrypt(&item.content)?; |
|
|
|
let content = self.encoder.encrypt(&item.content)?; |
|
|
|
writeln!(file, "{}", content)?; |
|
|
|
writeln!(file, "{}", content)?; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// TODO: run git commit
|
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|