Switch from Rc<RefCell> to Arc<Mutex<T>> or Arc<ReentrantMutex<RefCell<T>>>.

This commit is contained in:
Oleksandr Kozachuk
2023-01-06 13:12:58 +01:00
parent a2978c1230
commit 538a32a471
13 changed files with 384 additions and 214 deletions
+1
View File
@@ -22,6 +22,7 @@ base64 = "0.20.0"
shlex = "1.1.0"
shellexpand = "3.0.0"
scopeguard = "1.1.0"
parking_lot = { version = "0.12.1", features = ["deadlock_detection"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
chrono = "0.4.23"
+76 -71
View File
@@ -11,14 +11,14 @@ use crate::password::fix_password_recursion;
use crate::password::{Name, Password, PasswordRef};
use crate::repl::LKEval;
use crate::structs::{LKOut, Radix, CORRECT_FILE, DUMP_FILE};
use crate::utils::{call_cmd_with_input, get_cmd_args_from_command, get_copy_command_from_env, rnd};
use crate::utils::editor::password;
use crate::utils::{call_cmd_with_input, get_cmd_args_from_command, get_copy_command_from_env, rnd};
impl<'a> LKEval<'a> {
pub fn get_password(&self, name: &String) -> Option<PasswordRef> {
match self.state.borrow().ls.get(name) {
match self.state.lock().borrow().ls.get(name) {
Some(pwd) => Some(pwd.clone()),
None => match self.state.borrow().db.get(name) {
None => match self.state.lock().borrow().db.get(name) {
Some(pwd) => Some(pwd.clone()),
None => None,
},
@@ -34,15 +34,15 @@ impl<'a> LKEval<'a> {
None => (),
}
}
let parent = match &pwd.borrow().parent {
Some(p) => p.borrow().name.to_string(),
let parent = match &pwd.lock().borrow().parent {
Some(p) => p.lock().borrow().name.to_string(),
None => "/".to_string(),
};
let secret = match self.state.borrow().secrets.get(&parent) {
let secret = match self.state.lock().borrow().secrets.get(&parent) {
Some(p) => Some(p.clone()),
None => None,
};
match (pwd.borrow().parent.clone(), secret) {
match (pwd.lock().borrow().parent.clone(), secret) {
(_, Some(s)) => Some(s.to_string()),
(None, None) => {
if read {
@@ -50,7 +50,7 @@ impl<'a> LKEval<'a> {
Ok(password) => {
let name = "/".to_string();
self.cmd_correct(&out, &name, true, Some(password.clone()));
self.state.borrow_mut().secrets.insert(name, password.clone());
self.state.lock().borrow_mut().secrets.insert(name, password.clone());
Some(password)
}
Err(_) => None,
@@ -61,22 +61,22 @@ impl<'a> LKEval<'a> {
}
(Some(pn), None) => {
let password = if read {
(self.read_password)(format!("Password for {}: ", pn.borrow().name)).ok()
(self.read_password)(format!("Password for {}: ", pn.lock().borrow().name)).ok()
} else {
None
};
if password.is_some() && password.as_ref().unwrap().len() > 0 {
let name = pn.borrow().name.to_string();
let name = pn.lock().borrow().name.to_string();
self.cmd_correct(&out, &name, true, Some(password.as_ref().unwrap().clone()));
self.state.borrow_mut().secrets.insert(name, password.as_ref().unwrap().clone());
self.state.lock().borrow_mut().secrets.insert(name, password.as_ref().unwrap().clone());
password
} else {
match self.read_master(&out, pn.clone(), read) {
Some(master) => {
let password = pn.borrow().encode(master.as_str());
let name = pn.borrow().name.to_string();
let password = pn.lock().borrow().encode(master.as_str());
let name = pn.lock().borrow().name.to_string();
self.cmd_correct(&out, &name, true, Some(password.to_string()));
self.state.borrow_mut().secrets.insert(name, password.clone());
self.state.lock().borrow_mut().secrets.insert(name, password.clone());
Some(password)
}
None => None,
@@ -87,15 +87,15 @@ impl<'a> LKEval<'a> {
}
pub fn cmd_add(&self, out: &LKOut, name: &PasswordRef) {
let state = &mut self.state.borrow_mut();
let state_cell = self.state.lock();
let mut state = state_cell.borrow_mut();
let mut fix = false;
{
let db = &mut state.db;
let pwname = &name.borrow().name.to_string();
if db.get(pwname).is_some() {
let pwname = &name.lock().borrow().name.to_string();
if state.db.get(pwname).is_some() {
out.e(format!("error: password {} already exist", pwname));
} else {
db.insert(pwname.to_string(), name.clone());
state.db.insert(pwname.to_string(), name.clone());
fix = true;
}
}
@@ -105,9 +105,12 @@ impl<'a> LKEval<'a> {
}
pub fn cmd_leave(&self, out: &LKOut, name: &Name) {
let pwd = match self.state.borrow().ls.get(name) {
let pwd = match self.state.lock().borrow().ls.get(name) {
Some(pwd) => pwd.clone(),
None => { out.e(format!("error: {} not found", name)); return; }
None => {
out.e(format!("error: {} not found", name));
return;
}
};
self.cmd_add(&out, &pwd);
}
@@ -116,11 +119,11 @@ impl<'a> LKEval<'a> {
match self.get_password(name) {
Some(pwd) => {
if folder == "/" {
pwd.borrow_mut().parent = None
pwd.lock().borrow_mut().parent = None
} else {
match self.get_password(folder) {
Some(fld) => {
pwd.borrow_mut().parent = Some(fld.clone());
pwd.lock().borrow_mut().parent = Some(fld.clone());
fix_password_recursion(pwd.clone());
}
None => out.e(format!("error: folder {} not found", folder)),
@@ -134,18 +137,15 @@ impl<'a> LKEval<'a> {
pub fn cmd_pass(&self, out: &LKOut, name: &String) {
match self.get_password(name) {
Some(p) => {
let pwd = (self.read_password)(format!("Password for {}: ", p.borrow().name)).unwrap();
self.cmd_correct(&out, &p.borrow().name, true, Some(pwd.clone()));
self.state.borrow_mut().secrets.insert(p.borrow().name.to_string(), pwd);
let pwd = (self.read_password)(format!("Password for {}: ", p.lock().borrow().name)).unwrap();
self.cmd_correct(&out, &p.lock().borrow().name, true, Some(pwd.clone()));
self.state.lock().borrow_mut().secrets.insert(p.lock().borrow().name.to_string(), pwd);
}
None => {
if name == "/" {
let pwd = (self.read_password)("Master: ".to_string()).unwrap();
self.cmd_correct(&out, &"/".to_string(), true, Some(pwd.clone()));
self.state
.borrow_mut()
.secrets
.insert("/".to_string(), pwd);
self.state.lock().borrow_mut().secrets.insert("/".to_string(), pwd);
} else {
out.e(format!("error: password with name {} not found", name));
}
@@ -156,7 +156,7 @@ impl<'a> LKEval<'a> {
pub fn cmd_comment(&self, out: &LKOut, name: &String, comment: &Option<String>) {
match self.get_password(name) {
Some(pwd) => {
pwd.borrow_mut().comment = match comment {
pwd.lock().borrow_mut().comment = match comment {
Some(c) => Some(c.to_string()),
None => None,
}
@@ -167,8 +167,8 @@ impl<'a> LKEval<'a> {
pub fn cmd_enc(&self, out: &LKOut, name: &String) -> Option<(String, String)> {
let root_folder = "/".to_string();
let (name, pass) = if name == "/" && self.state.borrow().secrets.contains_key(&root_folder) {
(root_folder.to_string(), self.state.borrow().secrets.get(&root_folder).unwrap().to_string())
let (name, pass) = if name == "/" && self.state.lock().borrow().secrets.contains_key(&root_folder) {
(root_folder.to_string(), self.state.lock().borrow().secrets.get(&root_folder).unwrap().to_string())
} else {
let pwd = match self.get_password(name) {
Some(p) => p.clone(),
@@ -177,12 +177,12 @@ impl<'a> LKEval<'a> {
return None;
}
};
let name = pwd.borrow().name.to_string();
if self.state.borrow().secrets.contains_key(&name) {
(name.clone(), self.state.borrow().secrets.get(&name).unwrap().to_string())
let name = pwd.lock().borrow().name.to_string();
if self.state.lock().borrow().secrets.contains_key(&name) {
(name.clone(), self.state.lock().borrow().secrets.get(&name).unwrap().to_string())
} else {
match self.read_master(&out, pwd.clone(), true) {
Some(sec) => (name.clone(), pwd.borrow().encode(sec.as_str())),
Some(sec) => (name.clone(), pwd.lock().borrow().encode(sec.as_str())),
None => {
out.e(format!("error: master for {} not found", name));
return None;
@@ -253,7 +253,9 @@ impl<'a> LKEval<'a> {
for cmd in cmd_list {
let print = LKEval::new(cmd, self.state.clone(), password).eval();
print.out.copy(&out);
if print.quit { return true; }
if print.quit {
return true;
}
}
}
Err(e) => {
@@ -273,9 +275,9 @@ impl<'a> LKEval<'a> {
let file = fs::File::create(script)?;
let mut writer = BufWriter::new(file);
let mut vals = data.values().map(|v| v.clone()).collect::<Vec<PasswordRef>>();
vals.sort_by(|a, b| a.borrow().name.cmp(&b.borrow().name));
vals.sort_by(|a, b| a.lock().borrow().name.cmp(&b.lock().borrow().name));
for pwd in vals {
writeln!(writer, "add {}", pwd.borrow().to_string())?
writeln!(writer, "add {}", pwd.lock().borrow().to_string())?
}
Ok(())
}
@@ -289,10 +291,11 @@ impl<'a> LKEval<'a> {
};
let data = self
.state
.lock()
.borrow()
.db
.values()
.map(|v| format!("add {}", v.borrow().to_string()))
.map(|v| format!("add {}", v.lock().borrow().to_string()))
.collect::<Vec<String>>()
.join("\n");
let output = match call_cmd_with_input(&cmd, &args, data.as_str()) {
@@ -309,13 +312,13 @@ impl<'a> LKEval<'a> {
out.o(format!("Passwords saved to command {}", cmd));
}
} else if script.trim() == "-" {
let mut vals = (&self.state.borrow().db).values().map(|v| v.clone()).collect::<Vec<PasswordRef>>();
vals.sort_by(|a, b| a.borrow().name.cmp(&b.borrow().name));
let mut vals = (&self.state.lock().borrow().db).values().map(|v| v.clone()).collect::<Vec<PasswordRef>>();
vals.sort_by(|a, b| a.lock().borrow().name.cmp(&b.lock().borrow().name));
for pwd in vals {
out.o(format!("add {}", pwd.borrow().to_string()))
};
out.o(format!("add {}", pwd.lock().borrow().to_string()))
}
} else {
match save_dump(&self.state.borrow().db, &script) {
match save_dump(&self.state.lock().borrow().db, &script) {
Ok(()) => out.o(format!("Passwords saved to file {}", script)),
Err(e) => out.e(format!("error: failed to dump passswords to {}: {}", script, e.to_string())),
};
@@ -334,24 +337,26 @@ impl<'a> LKEval<'a> {
}
};
let mut tmp: Vec<PasswordRef> = vec![];
for (_, name) in &self.state.borrow().db {
if re.find(&name.borrow().to_string()).is_some() {
for (_, name) in &self.state.lock().borrow().db {
if re.find(&name.lock().borrow().to_string()).is_some() {
tmp.push(name.clone());
} else if re.find(&name.borrow().name).is_some() {
} else if re.find(&name.lock().borrow().name).is_some() {
tmp.push(name.clone());
} else if name.borrow().comment.is_some() && re.find(&name.borrow().comment.as_ref().unwrap()).is_some() {
} else if name.lock().borrow().comment.is_some()
&& re.find(&name.lock().borrow().comment.as_ref().unwrap()).is_some()
{
tmp.push(name.clone());
}
}
tmp.sort_by(|a,b| a.borrow().name.cmp(&b.borrow().name));
tmp.sort_by(|a, b| a.lock().borrow().name.cmp(&b.lock().borrow().name));
tmp.sort_by(sort_by);
self.state.borrow_mut().ls.clear();
self.state.lock().borrow_mut().ls.clear();
let mut counter = 1;
for pwd in tmp {
let key = Radix::new(counter, 36).unwrap().to_string();
counter += 1;
self.state.borrow_mut().ls.insert(key.clone(), pwd.clone());
out.o(format!("{:>3} {}", key, pwd.borrow().to_string()));
self.state.lock().borrow_mut().ls.insert(key.clone(), pwd.clone());
out.o(format!("{:>3} {}", key, pwd.lock().borrow().to_string()));
}
}
@@ -435,42 +440,42 @@ impl<'a> LKEval<'a> {
static ref RE: Regex = Regex::new(r"^.+?(G+|X+)$").unwrap();
}
let num: usize = (*num).try_into().unwrap();
let pwd = name.borrow();
let pwd = name.lock();
let mut genpwds: Vec<PasswordRef> = Vec::new();
match RE.captures(pwd.name.as_ref()) {
match RE.captures(pwd.borrow().name.as_ref()) {
Some(caps) => {
let gen = &caps[1];
if gen.starts_with("G") {
let name = pwd.name.trim_end_matches('G');
let name = pwd.borrow().name.trim_end_matches('G').to_string();
for num in 1..10_u32.pow(gen.len().try_into().unwrap()) {
let npwd = Password::from_password(&pwd);
npwd.borrow_mut().name = format!("{}{}", name, num).to_string();
let npwd = Password::from_password_ref(&pwd.borrow());
npwd.lock().borrow_mut().name = format!("{}{}", name, num).to_string();
genpwds.push(npwd);
}
} else {
let name = pwd.name.trim_end_matches('X');
let name = pwd.borrow().name.trim_end_matches('X').to_string();
let num = rnd::range(1, 10_u32.pow(gen.len().try_into().unwrap()));
let npwd = Password::from_password(&pwd);
npwd.borrow_mut().name = format!("{}{}", name, num).to_string();
let npwd = Password::from_password_ref(&pwd.borrow());
npwd.lock().borrow_mut().name = format!("{}{}", name, num).to_string();
genpwds.push(npwd);
}
}
None => {
let npwd = Password::from_password(&pwd);
let npwd = Password::from_password_ref(&pwd.borrow());
genpwds.push(npwd);
}
}
self.state.borrow_mut().ls.clear();
self.state.lock().borrow_mut().ls.clear();
let mut counter = 1;
let mut lspwds: Vec<(PasswordRef, String)> = Vec::new();
for num in 0..genpwds.len() {
let pwd = genpwds[num].clone();
let key = Radix::new(counter, 36).unwrap().to_string();
counter += 1;
self.state.borrow_mut().ls.insert(key.to_string(), pwd.clone());
self.state.lock().borrow_mut().ls.insert(key.to_string(), pwd.clone());
lspwds.push((pwd, key));
}
self.state.borrow().fix_hierarchy();
self.state.lock().borrow().fix_hierarchy();
let mut err = match &out.err {
Some(e) => Some(e.clone()),
None => None,
@@ -479,8 +484,8 @@ impl<'a> LKEval<'a> {
for (pwd, key) in lspwds {
let pass = match self.cmd_enc(&LKOut::from_lkout(None, err), &key) {
Some((name, pass)) => {
if name != pwd.borrow().name {
panic!("INTERNAL_ERROR: wrong name found: {} != {}", name, pwd.borrow().name);
if name != pwd.lock().borrow().name {
panic!("INTERNAL_ERROR: wrong name found: {} != {}", name, pwd.lock().borrow().name);
};
pass
}
@@ -493,15 +498,15 @@ impl<'a> LKEval<'a> {
encpwds.push((pwd.clone(), pass));
}
encpwds.sort_by(|a, b| b.1.len().cmp(&a.1.len()));
self.state.borrow_mut().ls.clear();
self.state.lock().borrow_mut().ls.clear();
let mut counter = 1;
out.o(format!("{:>3} {:>36} {:>4} {}", "", "Password", "Len", "Name"));
for num in (encpwds.len() - min(genpwds.len(), num))..encpwds.len() {
let (pwd, pass) = (encpwds[num].0.clone(), encpwds[num].1.to_string());
let key = Radix::new(counter, 36).unwrap().to_string();
counter += 1;
self.state.borrow_mut().ls.insert(key.clone(), pwd.clone());
out.o(format!("{:>3} {:>36} {:>4} {}", key, pass, pass.len(), pwd.borrow().to_string()));
self.state.lock().borrow_mut().ls.insert(key.clone(), pwd.clone());
out.o(format!("{:>3} {:>36} {:>4} {}", key, pass, pass.len(), pwd.lock().borrow().to_string()));
}
}
}
-1
View File
@@ -12,4 +12,3 @@ pub mod repl;
pub mod skey;
pub mod structs;
pub mod utils;
+28 -4
View File
@@ -1,8 +1,13 @@
use crate::password::{fix_password_recursion, Name, PasswordRef};
use parking_lot::ReentrantMutex;
use regex::{Captures, Regex};
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::Arc;
#[derive(PartialEq, Debug)]
pub type LKRef = Arc<ReentrantMutex<RefCell<LK>>>;
#[derive(Debug)]
pub struct LK {
pub db: HashMap<Name, PasswordRef>,
pub ls: HashMap<String, PasswordRef>,
@@ -24,7 +29,7 @@ impl LK {
}
for db in vec![&self.db, &self.ls] {
for (_, name) in db {
let comment = name.borrow().comment.clone();
let comment = name.lock().borrow().comment.clone();
match comment {
Some(comment) => {
let mut changed = false;
@@ -33,7 +38,7 @@ impl LK {
let folder = c[1].to_string();
match self.db.get(&folder) {
Some(entry) => {
name.borrow_mut().parent = Some(entry.clone());
name.lock().borrow_mut().parent = Some(entry.clone());
changed = true;
}
None => (),
@@ -43,7 +48,7 @@ impl LK {
.trim()
.to_string();
if changed && new != comment {
name.borrow_mut().comment = if new.len() > 0 { Some(new) } else { None }
name.lock().borrow_mut().comment = if new.len() > 0 { Some(new) } else { None }
}
}
None => (),
@@ -53,3 +58,22 @@ impl LK {
}
}
}
impl PartialEq for LK {
fn eq(&self, other: &Self) -> bool {
if self.db.len() != other.db.len() || self.ls.len() != other.ls.len() || self.secrets != other.secrets {
return false;
}
for (k, v) in &self.db {
if !other.db.contains_key(k) || *other.db[k].lock() != *v.lock() {
return false;
}
}
for (k, v) in &self.ls {
if !other.ls.contains_key(k) || *other.ls[k].lock() != *v.lock() {
return false;
}
}
true
}
}
+20 -21
View File
@@ -3,7 +3,6 @@ extern crate peg;
use crate::password::Password;
use crate::structs::{Command, LKErr, Mode};
use crate::utils::date::Date;
use std::{cell::RefCell, rc::Rc};
peg::parser! {
pub grammar command_parser() for str {
@@ -89,10 +88,10 @@ peg::parser! {
rule source_cmd() -> Command<'input> = "source" _ s:$(([' '..='~'])+) { Command::Source(s.to_string()) }
rule ls_cmd() -> Command<'input> = "ls" f:comment()? { Command::Ls(f.unwrap_or(".".to_string())) }
rule ld_cmd() -> Command<'input> = "ld" f:comment()? { Command::Ld(f.unwrap_or(".".to_string())) }
rule add_cmd() -> Command<'input> = "add" _ name:name() { Command::Add(Rc::new(RefCell::new(name))) }
rule add_cmd() -> Command<'input> = "add" _ name:name() { Command::Add(Password::from_password(name)) }
rule leave_cmd() -> Command<'input> = "leave" _ name:word() { Command::Leave(name.to_string()) }
rule gen_cmd() -> Command<'input> = "gen" n:num()? _ name:name() {
Command::Gen(match n { Some(n) => n, None => 10_u32 }, Rc::new(RefCell::new(name)))
Command::Gen(match n { Some(n) => n, None => 10_u32 }, Password::from_password(name))
}
rule error_cmd() -> Command<'input> = "error" _ e:$(([' '..='~'])+) { Command::Error(LKErr::Error(e)) }
rule mv_cmd() -> Command<'input> = "mv" _ name:word() _ folder:word() { Command::Mv(name, folder) }
@@ -119,7 +118,7 @@ add t2 C 99 2022-12-14
add t3 C 99 2022-12-14"###
),
Ok(vec![
Command::Add(Rc::new(RefCell::new(Password {
Command::Add(Password::from_password(Password {
parent: None,
prefix: None,
name: "t1".to_string(),
@@ -128,8 +127,8 @@ add t3 C 99 2022-12-14"###
seq: 99,
date: Date::new(2022, 12, 14),
comment: None
}))),
Command::Add(Rc::new(RefCell::new(Password {
})),
Command::Add(Password::from_password(Password {
parent: None,
prefix: None,
name: "t2".to_string(),
@@ -138,8 +137,8 @@ add t3 C 99 2022-12-14"###
seq: 99,
date: Date::new(2022, 12, 14),
comment: None
}))),
Command::Add(Rc::new(RefCell::new(Password {
})),
Command::Add(Password::from_password(Password {
parent: None,
prefix: None,
name: "t3".to_string(),
@@ -148,7 +147,7 @@ add t3 C 99 2022-12-14"###
seq: 99,
date: Date::new(2022, 12, 14),
comment: None
})))
}))
])
);
assert_eq!(
@@ -159,7 +158,7 @@ add t3 C 99 2022-12-14
"###
),
Ok(vec![
Command::Add(Rc::new(RefCell::new(Password {
Command::Add(Password::from_password(Password {
parent: None,
prefix: None,
name: "t1".to_string(),
@@ -168,8 +167,8 @@ add t3 C 99 2022-12-14
seq: 99,
date: Date::new(2022, 12, 14),
comment: None
}))),
Command::Add(Rc::new(RefCell::new(Password {
})),
Command::Add(Password::from_password(Password {
parent: None,
prefix: None,
name: "t2".to_string(),
@@ -178,8 +177,8 @@ add t3 C 99 2022-12-14
seq: 99,
date: Date::new(2022, 12, 14),
comment: None
}))),
Command::Add(Rc::new(RefCell::new(Password {
})),
Command::Add(Password::from_password(Password {
parent: None,
prefix: None,
name: "t3".to_string(),
@@ -188,7 +187,7 @@ add t3 C 99 2022-12-14
seq: 99,
date: Date::new(2022, 12, 14),
comment: None
}))),
})),
Command::Noop
])
);
@@ -201,7 +200,7 @@ add t3 C 99 2022-12-14
"###
),
Ok(vec![
Command::Add(Rc::new(RefCell::new(Password {
Command::Add(Password::from_password(Password {
parent: None,
prefix: None,
name: "t1".to_string(),
@@ -210,8 +209,8 @@ add t3 C 99 2022-12-14
seq: 99,
date: Date::new(2022, 12, 14),
comment: None
}))),
Command::Add(Rc::new(RefCell::new(Password {
})),
Command::Add(Password::from_password(Password {
parent: None,
prefix: None,
name: "t2".to_string(),
@@ -220,8 +219,8 @@ add t3 C 99 2022-12-14
seq: 99,
date: Date::new(2022, 12, 14),
comment: None
}))),
Command::Add(Rc::new(RefCell::new(Password {
})),
Command::Add(Password::from_password(Password {
parent: None,
prefix: None,
name: "t3".to_string(),
@@ -230,7 +229,7 @@ add t3 C 99 2022-12-14
seq: 99,
date: Date::new(2022, 12, 14),
comment: None
}))),
})),
Command::Noop,
Command::Noop
])
+56 -33
View File
@@ -1,17 +1,19 @@
use crate::skey::SKey;
use crate::structs::Mode;
use crate::utils::date::Date;
use std::{cell::RefCell, rc::Rc};
use parking_lot::ReentrantMutex;
use std::cell::RefCell;
use std::sync::Arc;
pub type Name = String;
pub type Prefix = Option<String>;
pub type Comment = Option<String>;
pub type PasswordRef = Rc<RefCell<Password>>;
pub type PasswordRef = Arc<ReentrantMutex<RefCell<Password>>>;
pub type Parent = Option<PasswordRef>;
pub type Length = Option<u32>;
pub type Seq = u32;
#[derive(PartialEq, Debug)]
#[derive(Debug)]
pub struct Password {
pub parent: Parent,
pub prefix: Prefix,
@@ -45,8 +47,8 @@ impl Password {
}
}
pub fn from_password(password: &Password) -> PasswordRef {
Rc::new(RefCell::new(Self {
pub fn from_password_ref(password: &Password) -> PasswordRef {
Arc::new(ReentrantMutex::new(RefCell::new(Self {
parent: password.parent.clone(),
prefix: password.prefix.clone(),
name: password.name.clone(),
@@ -55,7 +57,11 @@ impl Password {
seq: password.seq,
date: password.date.clone(),
comment: password.comment.clone(),
}))
})))
}
pub fn from_password(password: Password) -> PasswordRef {
Arc::new(ReentrantMutex::new(RefCell::new(password)))
}
pub fn encode(&self, secret: &str) -> String {
@@ -109,13 +115,28 @@ impl std::string::ToString for Password {
None => "".to_string(),
};
let parent = match &self.parent {
Some(s) => format!(" ^{}", s.borrow().name),
Some(s) => format!(" ^{}", s.lock().borrow().name),
None => "".to_string(),
};
format!("{:>6}{} {}{} {} {}{}{}", prefix, self.name, length, self.mode, self.seq, self.date, comment, parent)
}
}
impl PartialEq for Password {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
&& match (&self.parent, &other.parent) {
(Some(s), Some(o)) => *s.lock() == *o.lock(),
(None, None) => true,
_ => false,
}
&& self.prefix == other.prefix
&& self.length == other.length
&& self.mode == other.mode
&& self.seq == other.seq
}
}
fn camel_case(words: [&str; 6]) -> String {
let mut camel_case_string = String::new();
@@ -128,34 +149,34 @@ fn camel_case(words: [&str; 6]) -> String {
camel_case_string
}
pub fn fix_password_recursion(entry: Rc<RefCell<Password>>) {
pub fn fix_password_recursion(entry: PasswordRef) {
let mut t1 = entry.clone();
let mut t2 = entry;
let mut t3: Option<Rc<RefCell<Password>>> = None;
let mut t3: Option<PasswordRef> = None;
loop {
t2 = match &t2.clone().borrow().parent {
t2 = match &t2.clone().lock().borrow().parent {
Some(o) => o.clone(),
None => break,
};
if std::ptr::eq(&*t1.borrow(), &*t2.borrow()) {
if std::ptr::eq(&*t1.lock().borrow(), &*t2.lock().borrow()) {
t3 = Some(t2.clone());
break;
}
t1 = match &t1.clone().borrow().parent {
t1 = match &t1.clone().lock().borrow().parent {
Some(o) => o.clone(),
None => break,
};
t2 = match &t2.clone().borrow().parent {
t2 = match &t2.clone().lock().borrow().parent {
Some(o) => o.clone(),
None => break,
};
if std::ptr::eq(&*t1.borrow(), &*t2.borrow()) {
if std::ptr::eq(&*t1.lock().borrow(), &*t2.lock().borrow()) {
t3 = Some(t2.clone());
break;
}
}
match t3 {
Some(o) => o.borrow_mut().parent = None,
Some(o) => o.lock().borrow_mut().parent = None,
None => (),
}
}
@@ -166,7 +187,7 @@ mod tests {
#[test]
fn exec_recursion_test() {
let p1 = Rc::new(RefCell::new(Password::new(
let p1 = Password::from_password(Password::new(
None,
"p1".to_string(),
None,
@@ -174,13 +195,15 @@ mod tests {
99,
Date::new(2022, 12, 3),
None,
)));
));
p1.borrow_mut().parent = Some(p1.clone());
{
p1.lock().borrow_mut().parent = Some(p1.clone());
};
fix_password_recursion(p1.clone());
assert_eq!(p1.borrow().parent, None);
assert_eq!(p1.lock().borrow().parent.is_none(), true);
let p2 = Rc::new(RefCell::new(Password::new(
let p2 = Password::from_password(Password::new(
None,
"p2".to_string(),
None,
@@ -188,9 +211,9 @@ mod tests {
99,
Date::new(2022, 12, 3),
None,
)));
p2.borrow_mut().parent = Some(p1.clone());
let p3 = Rc::new(RefCell::new(Password::new(
));
p2.lock().borrow_mut().parent = Some(p1.clone());
let p3 = Password::from_password(Password::new(
None,
"p3".to_string(),
None,
@@ -198,9 +221,9 @@ mod tests {
99,
Date::new(2022, 12, 3),
None,
)));
p3.borrow_mut().parent = Some(p2.clone());
let p4 = Rc::new(RefCell::new(Password::new(
));
p3.lock().borrow_mut().parent = Some(p2.clone());
let p4 = Password::from_password(Password::new(
None,
"p4".to_string(),
None,
@@ -208,9 +231,9 @@ mod tests {
99,
Date::new(2022, 12, 3),
None,
)));
p4.borrow_mut().parent = Some(p3.clone());
let p5 = Rc::new(RefCell::new(Password::new(
));
p4.lock().borrow_mut().parent = Some(p3.clone());
let p5 = Password::from_password(Password::new(
None,
"p5".to_string(),
None,
@@ -218,12 +241,12 @@ mod tests {
99,
Date::new(2022, 12, 3),
None,
)));
p5.borrow_mut().parent = Some(p4.clone());
));
p5.lock().borrow_mut().parent = Some(p4.clone());
p1.borrow_mut().parent = Some(p3.clone());
p1.lock().borrow_mut().parent = Some(p3.clone());
fix_password_recursion(p5.clone());
assert_eq!(p3.borrow().parent, None);
assert_eq!(p3.lock().borrow().parent.is_none(), true);
}
#[test]
+89 -42
View File
@@ -1,15 +1,13 @@
use std::{cell::RefCell, rc::Rc};
use crate::lk::LK;
use crate::lk::LKRef;
use crate::parser::command_parser;
use crate::structs::{Command, LKErr, LKOut, HISTORY_FILE};
use crate::utils::editor::{ Editor, password };
use crate::utils::editor::{password, Editor};
#[derive(Debug)]
pub struct LKRead {
pub rl: Editor,
pub prompt: String,
pub state: Rc<RefCell<LK>>,
pub state: LKRef,
pub cmd: String,
pub read_password: fn(String) -> std::io::Result<String>,
}
@@ -17,19 +15,19 @@ pub struct LKRead {
#[derive(Debug)]
pub struct LKEval<'a> {
pub cmd: Command<'a>,
pub state: Rc<RefCell<LK>>,
pub state: LKRef,
pub read_password: fn(String) -> std::io::Result<String>,
}
#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub struct LKPrint {
pub out: LKOut,
pub quit: bool,
pub state: Rc<RefCell<LK>>,
pub state: LKRef,
}
impl LKRead {
pub fn new(rl: Editor, prompt: String, state: Rc<RefCell<LK>>) -> Self {
pub fn new(rl: Editor, prompt: String, state: LKRef) -> Self {
Self {
rl,
prompt,
@@ -77,7 +75,7 @@ impl LKRead {
}
impl<'a> LKEval<'a> {
pub fn new(cmd: Command<'a>, state: Rc<RefCell<LK>>, read_password: fn(String) -> std::io::Result<String>) -> Self {
pub fn new(cmd: Command<'a>, state: LKRef, read_password: fn(String) -> std::io::Result<String>) -> Self {
Self {
cmd,
state,
@@ -94,25 +92,33 @@ impl<'a> LKEval<'a> {
out.e("Bye!".to_string());
quit = true;
}
Command::Ls(filter) => self.cmd_ls(&out, filter.to_string(), |a,b| a.borrow().name.cmp(&b.borrow().name)),
Command::Ld(filter) => self.cmd_ls(&out, filter.to_string(), |a,b| a.borrow().date.cmp(&b.borrow().date)),
Command::Ls(filter) => {
self.cmd_ls(&out, filter.to_string(), |a, b| a.lock().borrow().name.cmp(&b.lock().borrow().name))
}
Command::Ld(filter) => {
self.cmd_ls(&out, filter.to_string(), |a, b| a.lock().borrow().date.cmp(&b.lock().borrow().date))
}
Command::Add(name) => self.cmd_add(&out, &name),
Command::Leave(name) => self.cmd_leave(&out, &name),
Command::Comment(name, comment) => self.cmd_comment(&out, &name, &comment),
Command::Rm(name) => match self.get_password(name) {
Some(pwd) => {
self.state.borrow_mut().db.remove(&pwd.borrow().name);
out.o(format!("removed {}", pwd.borrow().name));
self.state.lock().borrow_mut().db.remove(&pwd.lock().borrow().name);
out.o(format!("removed {}", pwd.lock().borrow().name));
}
None => out.e(format!("error: password {} not found", name)),
},
Command::Enc(name) => { self.cmd_enc(&out, name); }
Command::Enc(name) => {
self.cmd_enc(&out, name);
}
Command::Gen(num, name) => self.cmd_gen(&out, &num, &name),
Command::PasteBuffer(command) => self.cmd_pb(&out, command),
Command::Source(script) => { quit = self.cmd_source(&out, script); }
Command::Source(script) => {
quit = self.cmd_source(&out, script);
}
Command::Dump(script) => self.cmd_dump(&out, script),
Command::Pass(name) => self.cmd_pass(&out, &name),
Command::UnPass(name) => match self.state.borrow_mut().secrets.remove(name) {
Command::UnPass(name) => match self.state.lock().borrow_mut().secrets.remove(name) {
Some(_) => out.o(format!("Removed saved password for {}", name)),
None => out.e(format!("error: saved password for {} not found", name)),
},
@@ -136,7 +142,7 @@ impl<'a> LKEval<'a> {
}
impl LKPrint {
pub fn new(out: LKOut, quit: bool, state: Rc<RefCell<LK>>) -> Self {
pub fn new(out: LKOut, quit: bool, state: LKRef) -> Self {
Self { out, quit, state }
}
@@ -147,16 +153,26 @@ impl LKPrint {
}
}
impl PartialEq for LKPrint {
fn eq(&self, other: &Self) -> bool {
self.out == other.out && self.quit == other.quit && *self.state.lock() == *other.state.lock()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::lk::LK;
use crate::password::Password;
use crate::structs::Mode;
use std::collections::HashMap;
use crate::utils::date::Date;
use parking_lot::ReentrantMutex;
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::Arc;
impl<'a> LKEval<'a> {
pub fn news(cmd: Command<'a>, state: Rc<RefCell<LK>>) -> Self {
pub fn news(cmd: Command<'a>, state: LKRef) -> Self {
Self {
cmd,
state,
@@ -169,12 +185,12 @@ mod tests {
#[test]
fn exec_cmds_basic() {
let lk = Rc::new(RefCell::new(LK::new()));
let lk = Arc::new(ReentrantMutex::new(RefCell::new(LK::new())));
assert_eq!(
LKEval::news(Command::Ls(".".to_string()), lk.clone()).eval(),
LKPrint::new(LKOut::from_vecs(vec![], vec![]), false, lk.clone())
);
let pwd1 = Rc::new(RefCell::new(Password {
let pwd1 = Password::from_password(Password {
name: "t1".to_string(),
prefix: None,
length: None,
@@ -183,12 +199,25 @@ mod tests {
date: Date::new(2022, 12, 30),
comment: Some("comment".to_string()),
parent: None,
}));
assert_eq!(LKEval::news(Command::Add(pwd1.clone()), lk.clone()).eval().state.borrow().db, {
let mut db = HashMap::new();
db.insert(pwd1.borrow().name.to_string(), pwd1.clone());
db
});
assert_eq!(
LKEval::news(Command::Add(pwd1.clone()), lk.clone())
.eval()
.state
.lock()
.borrow()
.db
.iter()
.map(|x| (x.0.to_string(), x.1.lock().borrow().to_string()))
.collect::<Vec<(String, String)>>(),
{
let mut db = HashMap::new();
db.insert(pwd1.lock().borrow().name.to_string(), pwd1.clone());
db.into_iter()
.map(|x| (x.0.to_string(), x.1.lock().borrow().to_string()))
.collect::<Vec<(String, String)>>()
}
);
assert_eq!(
LKEval::news(Command::Ls(".".to_string()), lk.clone()).eval(),
LKPrint::new(
@@ -201,7 +230,7 @@ mod tests {
LKEval::news(Command::Quit, lk.clone()).eval(),
LKPrint::new(LKOut::from_vecs(vec![], vec!["Bye!".to_string()]), true, lk.clone())
);
let pwd2 = Rc::new(RefCell::new(Password {
let pwd2 = Password::from_password(Password {
name: "t2".to_string(),
prefix: None,
length: None,
@@ -210,18 +239,32 @@ mod tests {
date: Date::new(2022, 12, 31),
comment: Some("bli blup".to_string()),
parent: None,
}));
assert_eq!(LKEval::news(Command::Add(pwd2.clone()), lk.clone()).eval().state.borrow().db, {
let mut db = HashMap::new();
db.insert(pwd1.borrow().name.to_string(), pwd1.clone());
db.insert(pwd2.borrow().name.to_string(), pwd2.clone());
db
});
assert_eq!(
LKEval::news(Command::Add(pwd2.clone()), lk.clone())
.eval()
.state
.lock()
.borrow()
.db
.iter()
.map(|x| (x.0.to_string(), x.1.lock().borrow().to_string()))
.collect::<Vec<(String, String)>>(),
{
let mut db = HashMap::new();
db.insert(pwd1.lock().borrow().name.to_string(), pwd1.clone());
db.insert(pwd2.lock().borrow().name.to_string(), pwd2.clone());
db.into_iter().map(|x| (x.0, x.1.lock().borrow().to_string())).collect::<Vec<(String, String)>>()
}
);
assert_eq!(
LKEval::news(Command::Ls(".".to_string()), lk.clone()).eval(),
LKPrint::new(
LKOut::from_vecs(
vec![" 1 t1 R 99 2022-12-30 comment".to_string(), " 2 t2 R 99 2022-12-31 bli blup".to_string()],
vec![
" 1 t1 R 99 2022-12-30 comment".to_string(),
" 2 t2 R 99 2022-12-31 bli blup".to_string()
],
vec![]
),
false,
@@ -244,8 +287,8 @@ mod tests {
#[test]
fn read_pwd_test() {
let lk = Rc::new(RefCell::new(LK::new()));
let t1 = Rc::new(RefCell::new(Password::new(
let lk = Arc::new(ReentrantMutex::new(RefCell::new(LK::new())));
let t1 = Password::from_password(Password::new(
None,
"t1".to_string(),
None,
@@ -253,8 +296,8 @@ mod tests {
99,
Date::new(2022, 12, 30),
None,
)));
let t2 = Rc::new(RefCell::new(Password::new(
));
let t2 = Password::from_password(Password::new(
None,
"t2".to_string(),
None,
@@ -262,8 +305,8 @@ mod tests {
99,
Date::new(2022, 12, 30),
None,
)));
let t3 = Rc::new(RefCell::new(Password::new(
));
let t3 = Password::from_password(Password::new(
None,
"t3".to_string(),
None,
@@ -271,19 +314,23 @@ mod tests {
99,
Date::new(2022, 12, 30),
None,
)));
));
println!("POINT 1");
assert_eq!(
LKEval::news(Command::Add(t1.clone()), lk.clone()).eval(),
LKPrint::new(LKOut::from_vecs(vec![], vec![]), false, lk.clone())
);
println!("POINT 2");
assert_eq!(
LKEval::news(Command::Add(t2.clone()), lk.clone()).eval(),
LKPrint::new(LKOut::from_vecs(vec![], vec![]), false, lk.clone())
);
println!("POINT 3");
assert_eq!(
LKEval::news(Command::Add(t3.clone()), lk.clone()).eval(),
LKPrint::new(LKOut::from_vecs(vec![], vec![]), false, lk.clone())
);
println!("POINT 4");
assert_eq!(
LKEval::news(Command::Mv("t3".to_string(), "t2".to_string()), lk.clone()).eval(),
LKPrint::new(LKOut::from_vecs(vec![], vec![]), false, lk.clone())
+81 -36
View File
@@ -1,13 +1,16 @@
use crate::password::{Comment, Name, PasswordRef};
use parking_lot::Mutex;
use parking_lot::ReentrantMutex;
use std::cell::RefCell;
use std::fmt;
use std::path::Path;
use std::{cell::RefCell, rc::Rc};
use std::sync::Arc;
use crate::lk::LK;
use crate::parser::command_parser;
use crate::repl::{LKEval, LKRead};
use crate::utils::editor::{password, Editor};
use crate::utils::home;
use crate::utils::editor::{ Editor, password };
lazy_static! {
pub static ref HISTORY_FILE: Box<Path> = {
@@ -54,7 +57,7 @@ pub enum LKErr<'a> {
ParseError(peg::error::ParseError<peg::str::LineCol>),
}
#[derive(PartialEq, Debug)]
#[derive(Debug)]
pub enum Command<'a> {
Add(PasswordRef),
Leave(Name),
@@ -78,6 +81,34 @@ pub enum Command<'a> {
Quit,
}
impl<'a> PartialEq for Command<'a> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Command::Add(s), Command::Add(o)) => *s.lock() == *o.lock(),
(Command::Leave(s), Command::Leave(o)) => s == o,
(Command::Ls(s), Command::Ls(o)) => s == o,
(Command::Ld(s), Command::Ld(o)) => s == o,
(Command::Mv(a, b), Command::Mv(x, y)) => a == x && b == y,
(Command::Rm(s), Command::Rm(o)) => s == o,
(Command::Enc(s), Command::Enc(o)) => s == o,
(Command::Gen(a, b), Command::Gen(x, y)) => a == x && *b.lock() == *y.lock(),
(Command::Pass(s), Command::Pass(o)) => s == o,
(Command::UnPass(s), Command::UnPass(o)) => s == o,
(Command::Correct(s), Command::Correct(o)) => s == o,
(Command::Uncorrect(s), Command::Uncorrect(o)) => s == o,
(Command::PasteBuffer(s), Command::PasteBuffer(o)) => s == o,
(Command::Source(s), Command::Source(o)) => s == o,
(Command::Dump(s), Command::Dump(o)) => s == o,
(Command::Comment(a, b), Command::Comment(x, y)) => a == x && b == y,
(Command::Error(s), Command::Error(o)) => s == o,
(Command::Noop, Command::Noop) => true,
(Command::Help, Command::Help) => true,
(Command::Quit, Command::Quit) => true,
_ => false,
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub enum Mode {
Regular,
@@ -114,21 +145,21 @@ impl std::fmt::Display for Mode {
}
}
#[derive(PartialEq, Debug)]
#[derive(Debug)]
pub struct LKOut {
pub out: Option<Rc<RefCell<Vec<String>>>>,
pub err: Option<Rc<RefCell<Vec<String>>>>,
pub out: Option<Arc<Mutex<Vec<String>>>>,
pub err: Option<Arc<Mutex<Vec<String>>>>,
}
impl LKOut {
pub fn new() -> Self {
Self {
out: Some(Rc::new(RefCell::new(vec![]))),
err: Some(Rc::new(RefCell::new(vec![]))),
out: Some(Arc::new(Mutex::new(vec![]))),
err: Some(Arc::new(Mutex::new(vec![]))),
}
}
pub fn from_lkout(out: Option<Rc<RefCell<Vec<String>>>>, err: Option<Rc<RefCell<Vec<String>>>>) -> Self {
pub fn from_lkout(out: Option<Arc<Mutex<Vec<String>>>>, err: Option<Arc<Mutex<Vec<String>>>>) -> Self {
let o = match out {
Some(v) => Some(v.clone()),
None => None,
@@ -143,8 +174,8 @@ impl LKOut {
#[allow(dead_code)]
pub fn from_vecs(out: Vec<String>, err: Vec<String>) -> Self {
Self {
out: Some(Rc::new(RefCell::new(out))),
err: Some(Rc::new(RefCell::new(err))),
out: Some(Arc::new(Mutex::new(out))),
err: Some(Arc::new(Mutex::new(err))),
}
}
@@ -152,7 +183,7 @@ impl LKOut {
if !self.out.is_some() {
return;
}
for line in self.out.as_ref().unwrap().borrow().iter() {
for line in self.out.as_ref().unwrap().lock().iter() {
out.o(line.to_string())
}
}
@@ -161,7 +192,7 @@ impl LKOut {
if !self.err.is_some() {
return;
}
for line in self.err.as_ref().unwrap().borrow().iter() {
for line in self.err.as_ref().unwrap().lock().iter() {
out.e(line.to_string())
}
}
@@ -170,7 +201,7 @@ impl LKOut {
if !self.out.is_some() {
return;
}
for line in self.out.as_ref().unwrap().borrow().iter() {
for line in self.out.as_ref().unwrap().lock().iter() {
println!("{}", line);
}
}
@@ -179,7 +210,7 @@ impl LKOut {
if !self.err.is_some() {
return;
}
for line in self.err.as_ref().unwrap().borrow().iter() {
for line in self.err.as_ref().unwrap().lock().iter() {
eprintln!("{}", line);
}
}
@@ -191,7 +222,7 @@ impl LKOut {
pub fn data(&self) -> String {
if self.out.is_some() {
self.out.as_ref().unwrap().borrow().join("\n")
self.out.as_ref().unwrap().lock().join("\n")
} else {
"".to_string()
}
@@ -202,16 +233,30 @@ impl LKOut {
}
pub fn o(&self, line: String) {
if self.out.is_some() {
self.out.as_ref().unwrap().borrow_mut().push(line);
self.out.as_ref().unwrap().lock().push(line);
}
}
pub fn e(&self, line: String) {
if self.err.is_some() {
self.err.as_ref().unwrap().borrow_mut().push(line);
self.err.as_ref().unwrap().lock().push(line);
}
}
}
impl PartialEq for LKOut {
fn eq(&self, other: &Self) -> bool {
(match (&self.out, &other.out) {
(Some(a), Some(b)) => *a.lock() == *b.lock(),
(None, None) => true,
_ => false,
} && match (&self.err, &other.err) {
(Some(a), Some(b)) => *a.lock() == *b.lock(),
(None, None) => true,
_ => false,
})
}
}
pub struct Radix {
x: i32,
radix: u32,
@@ -263,13 +308,15 @@ impl fmt::Display for Radix {
}
pub fn init() -> Option<LKRead> {
let lk = Rc::new(RefCell::new(LK::new()));
let lk = Arc::new(ReentrantMutex::new(RefCell::new(LK::new())));
match std::fs::read_to_string(INIT_FILE.to_str().unwrap()) {
Ok(script) => match command_parser::script(&script) {
Ok(cmd_list) => {
for cmd in cmd_list {
if !LKEval::new(cmd, lk.clone(), password).eval().print() { return None; }
if !LKEval::new(cmd, lk.clone(), password).eval().print() {
return None;
}
}
}
Err(err) => {
@@ -349,9 +396,9 @@ mod tests {
let lkread = init().unwrap();
assert_eq!(lkread.prompt, "test> ");
assert_eq!(lkread.state.borrow().db.contains_key("t1"), true);
assert_eq!(lkread.state.lock().borrow().db.contains_key("t1"), true);
let t1 = Rc::new(RefCell::new(Password::new(
let t1 = Password::from_password(Password::new(
None,
"t1".to_string(),
None,
@@ -359,8 +406,8 @@ mod tests {
99,
Date::new(2022, 10, 10),
None,
)));
let t2 = Rc::new(RefCell::new(Password::new(
));
let t2 = Password::from_password(Password::new(
None,
"t2".to_string(),
None,
@@ -368,9 +415,9 @@ mod tests {
99,
Date::new(2022, 10, 10),
Some("test".to_string()),
)));
t2.borrow_mut().parent = Some(t1.clone());
let t3 = Rc::new(RefCell::new(Password::new(
));
t2.lock().borrow_mut().parent = Some(t1.clone());
let t3 = Password::from_password(Password::new(
None,
"t3".to_string(),
None,
@@ -378,15 +425,13 @@ mod tests {
99,
Date::new(2022, 10, 10),
Some("aoeu".to_string()),
)));
t3.borrow_mut().parent = Some(t2.clone());
assert_eq!(*lkread.state.borrow().db.get("t1").unwrap().borrow(), *t1.borrow());
assert_eq!(*lkread.state.borrow().db.get("t2").unwrap().borrow(), *t2.borrow());
assert_eq!(*lkread.state.borrow().db.get("t3").unwrap().borrow(), *t3.borrow());
));
t3.lock().borrow_mut().parent = Some(t2.clone());
assert_eq!(*lkread.state.lock().borrow().db.get("t1").unwrap().lock(), *t1.lock());
assert_eq!(*lkread.state.lock().borrow().db.get("t2").unwrap().lock(), *t2.lock());
assert_eq!(*lkread.state.lock().borrow().db.get("t3").unwrap().lock(), *t3.lock());
LKEval::new(command_parser::cmd("save").unwrap(), lkread.state.clone(), password)
.eval()
.print();
LKEval::new(command_parser::cmd("save").unwrap(), lkread.state.clone(), password).eval().print();
assert_eq!(
std::fs::read_to_string("test_dump").expect("read"),
"add t1 R 99 2022-10-10\nadd t2 R 99 2022-10-10 test ^t1\nadd t3 R 99 2022-10-10 aoeu ^t2\n".to_string()
@@ -412,7 +457,7 @@ mod tests {
]
)
);
lkread.state.borrow_mut().secrets.clear();
lkread.state.lock().borrow_mut().secrets.clear();
let pr = LKEval::new(command_parser::cmd("pb enc t3").unwrap(), lkread.state.clone(), |v| {
if v == "/" {
Ok("a".to_string())
+10 -4
View File
@@ -11,12 +11,14 @@ pub mod date {
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct Date {
date: NaiveDate
date: NaiveDate,
}
impl Date {
pub fn new(year: i32, month: u32, day: u32) -> Self {
Self { date: NaiveDate::from_ymd_opt(year, month, day).unwrap() }
Self {
date: NaiveDate::from_ymd_opt(year, month, day).unwrap(),
}
}
pub fn try_new(year: i32, month: u32, day: u32) -> Result<Self, &'static str> {
@@ -27,7 +29,9 @@ pub mod date {
}
pub fn now() -> Self {
Self { date: Local::now().naive_local().date() }
Self {
date: Local::now().naive_local().date(),
}
}
pub fn cmp(&self, other: &Self) -> core::cmp::Ordering {
@@ -95,7 +99,9 @@ pub mod editor {
impl Editor {
pub fn new() -> Self {
Self { editor: rustyline::Editor::<()>::new().unwrap() }
Self {
editor: rustyline::Editor::<()>::new().unwrap(),
}
}
pub fn clear_history(&mut self) {