pub use netrc::{Authenticator, Netrc};
use std::fs;
use std::io;
use std::io::ErrorKind;
use std::path::{Path, PathBuf};
use std::result;
mod lex;
mod netrc;
pub type Result<T> = result::Result<T, Error>;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("{parser} in the file '{filename}'")]
Parsing {
parser: netrc::ParsingError,
filename: String,
},
}
impl Netrc {
pub fn new() -> Result<Self> {
Self::get_file()
.ok_or(Error::Io(io::Error::new(
ErrorKind::NotFound,
"no netrc file found",
)))
.and_then(|f| Netrc::from_file(f.as_path()))
}
pub fn from_file(file: &Path) -> Result<Self> {
String::from_utf8_lossy(&fs::read(file)?)
.parse()
.map_err(|e| Error::Parsing {
parser: e,
filename: file.display().to_string(),
})
}
pub fn get_file() -> Option<PathBuf> {
let file = std::env::var("NETRC").unwrap_or(String::from("~/.netrc"));
let p = Path::new(&file);
if p.exists() {
Some(p.to_path_buf())
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
const CONTENT: &str = "\
machine cocolog-nifty.com
login jmarten0
password cC2&yt7OT
machine wired.com
login mstanlack1
password gH4={wx=>VixU
machine joomla.org
login mbutterley2
password hY5>yKqU&$vq&0
";
fn create_netrc_file() -> PathBuf {
let dest = std::env::temp_dir().join("mynetrc");
if !dest.exists() {
std::fs::write(&dest, CONTENT).unwrap();
}
dest
}
fn check_nrc(nrc: &Netrc) {
assert_eq!(nrc.hosts.len(), 3);
assert_eq!(
nrc.hosts["cocolog-nifty.com"],
Authenticator::new("jmarten0", "", "cC2&yt7OT")
);
assert_eq!(
nrc.hosts["wired.com"],
Authenticator::new("mstanlack1", "", "gH4={wx=>VixU")
);
assert_eq!(
nrc.hosts["joomla.org"],
Authenticator::new("mbutterley2", "", "hY5>yKqU&$vq&0")
);
}
#[test]
fn test_new_env() {
let fi = create_netrc_file();
std::env::set_var("NETRC", fi);
let nrc = Netrc::new().unwrap();
check_nrc(&nrc);
}
#[test]
fn test_new_default() {}
#[test]
fn test_from_file_failed() {
assert_eq!(
Netrc::from_file(Path::new("/netrc/file/not/exists/on/no/netrc"))
.unwrap_err()
.to_string(),
"I/O error: No such file or directory (os error 2)"
);
}
#[test]
fn test_from_file() {
let fi = create_netrc_file();
let nrc = Netrc::from_file(fi.as_path()).unwrap();
check_nrc(&nrc);
}
}