use super::Result;
shell!(Pass, "/usr/bin/pass");
impl Pass {
pub fn list(&self) -> Result<String> {
let lines: Vec<String> = self
.inner
.exec(vec!["git".into(), "ls-files".into()])?
.lines()
.filter(|line| {
std::path::Path::new(line)
.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("gpg"))
})
.map(|line| line.strip_suffix(".gpg").unwrap_or(line))
.map(std::string::ToString::to_string)
.collect();
Ok(lines.join("\n"))
}
pub fn show(&self, entry: String) -> Result<String> {
self.inner.exec(vec!["show".into(), entry])
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_default() {
let store = Pass::default();
assert_eq!(Pass::new(String::from("/usr/bin/pass")), store);
}
#[test]
fn test_list() {
let store = mock_password_store();
let expected = "Bank/bank.example.com\nStore/store.example.com";
check_result(expected, store.list());
}
#[test]
fn test_show() {
let store = mock_password_store();
for item in [
(
"Bank/bank.example.com",
"Very Secret Password\n---\nuser: me@examble.com\nurl: https://bank.example.com/login\nautotype: user :tab :password :enter",
),
(
"Bank/bank.example_integer.com",
"Very Secret Password\n---\nuser: 123456789\nurl: https://bank.example.com/login\nautotype: user :tab :password :enter",
),
] {
let (entry, expected) = item;
check_result(expected, store.show(entry.into()));
}
}
fn check_result(expected: &str, result: Result<String>) {
assert!(result.is_ok());
if let Ok(actual) = result {
assert_eq!(expected, actual);
}
}
fn mock_password_store() -> Pass {
Pass::new("test/scripts/mock-pass".into())
}
}