linting changes

This commit is contained in:
Dietrich 2020-11-09 09:56:24 +01:00
parent 647881f022
commit 467c8ee007
15 changed files with 142 additions and 143 deletions

View File

@ -1,3 +1,4 @@
#![allow(clippy::default_trait_access)]
use std::path::PathBuf;
#[derive(Debug, Clone, Eq, PartialEq)]
@ -12,7 +13,6 @@ pub enum DeletePrimaryGroup {
Keep,
DeleteIfEmpty,
}
#[derive(Debug, Builder, Eq, PartialEq)]
#[builder(public)]
#[builder(default)]
@ -23,6 +23,7 @@ pub struct NewUserArgs<'a> {
}
impl<'a> NewUserArgs<'a> {
#[must_use]
pub fn builder() -> NewUserArgsBuilder<'a> {
NewUserArgsBuilder::default()
}

View File

@ -2,6 +2,9 @@ use std::path::PathBuf;
extern crate adduser;
use adduser::api::UserDBWrite;
use adduser::api::UserRead;
extern crate env_logger;
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};
@ -9,9 +12,6 @@ use log::{debug, error, info, trace, warn};
fn main() {
env_logger::init();
use adduser::api::UserDBWrite;
use adduser::api::UserRead;
let mf = adduser::Files {
passwd: Some(PathBuf::from("./passwd")),
shadow: Some(PathBuf::from("./shadow")),

View File

@ -1,4 +1,5 @@
extern crate adduser;
use adduser::api::UserDBRead;
fn main() {
simplelog::CombinedLogger::init(vec![simplelog::TermLogger::new(
@ -7,7 +8,6 @@ fn main() {
simplelog::TerminalMode::Mixed,
)])
.unwrap();
use adduser::api::UserDBRead;
let db = adduser::UserDBLocal::load_files(adduser::Files::default()).unwrap();

View File

@ -1,6 +1,7 @@
use std::error::Error;
use std::fmt::{self, Display};
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, PartialEq)]
pub enum ParseError {
Username,
@ -12,6 +13,7 @@ pub enum ParseError {
ShellDir,
}
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, PartialEq)]
pub enum UserLibError {
NotFound,
@ -36,8 +38,8 @@ impl PartialEq for MyMessage {
impl Display for MyMessage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MyMessage::Simple(m) => write!(f, "{}", m),
MyMessage::IOError(m, e) => write!(f, "{},{}", m, e),
Self::Simple(m) => write!(f, "{}", m),
Self::IOError(m, e) => write!(f, "{},{}", m, e),
}
}
}
@ -47,7 +49,7 @@ impl Display for UserLibError {
match self {
Self::NotFound => write!(f, "not found"),
Self::ParseError => write!(f, "failed to parse"),
UserLibError::FilesRequired => write!(
Self::FilesRequired => write!(
f,
"File locking is only possible if some files are specified"
),
@ -63,12 +65,12 @@ impl Display for UserLibError {
impl Error for UserLibError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match *self {
UserLibError::NotFound
| UserLibError::ParseError
| UserLibError::FilesChanged
| UserLibError::FilesRequired => None,
UserLibError::Message(MyMessage::IOError(_, ref e)) => Some(e),
UserLibError::Message(MyMessage::Simple(_)) => None,
Self::NotFound
| Self::ParseError
| Self::FilesChanged
| Self::FilesRequired
| Self::Message(MyMessage::Simple(_)) => None,
Self::Message(MyMessage::IOError(_, ref e)) => Some(e),
}
}
}
@ -87,13 +89,13 @@ impl From<String> for UserLibError {
impl From<std::io::Error> for UserLibError {
fn from(e: std::io::Error) -> Self {
UserLibError::Message(MyMessage::Simple(e.to_string()))
Self::Message(MyMessage::Simple(e.to_string()))
}
}
impl From<(String, std::io::Error)> for UserLibError {
fn from((m, e): (String, std::io::Error)) -> Self {
UserLibError::Message(MyMessage::IOError(m, e))
Self::Message(MyMessage::IOError(m, e))
}
}
/*

View File

@ -1,10 +1,3 @@
#![warn(
clippy::all,
/* clippy::restriction,*/
clippy::pedantic,
clippy::nursery,
clippy::cargo
)]
#![allow(clippy::non_ascii_literal)]
use crate::userlib::NewFromString;
@ -57,10 +50,11 @@ pub struct Group {
}
impl Group {
#[must_use]
pub fn remove_in(&self, content: &str) -> String {
content
.split(&self.source)
.map(|x| x.trim())
.map(str::trim)
.collect::<Vec<&str>>()
.join("\n")
}
@ -75,7 +69,7 @@ impl GroupRead for Group {
#[must_use]
fn get_member_names(&self) -> Option<Vec<&str>> {
let mut r: Vec<&str> = Vec::new();
for u in self.members.iter() {
for u in &self.members {
r.push(&u.username);
}
Some(r)
@ -128,7 +122,7 @@ impl NewFromString for Group {
if elements.len() == 4 {
Ok(Self {
pos: position,
source: line.clone(),
source: line,
groupname: Groupname::try_from(elements.get(0).unwrap().to_string())?,
password: crate::Password::Disabled,
gid: crate::Gid::try_from(elements.get(2).unwrap().to_string())?,

View File

@ -1,3 +1,12 @@
#![warn(
clippy::all,
//clippy::restriction,
clippy::pedantic,
clippy::nursery,
clippy::cargo
)]
//#![allow(clippy::non_ascii_literal)]
#[macro_use]
extern crate lazy_static;
#[macro_use]

View File

@ -1,3 +1,4 @@
#![allow(clippy::non_ascii_literal)]
use crate::UserLibError;
use std::cmp::Eq;
use std::convert::TryFrom;
@ -26,19 +27,19 @@ impl Gecos {
#[must_use]
pub fn get_comment(&self) -> Option<&str> {
match &self {
Gecos::Simple { comment, .. } => Some(&comment),
Gecos::Detail { .. } => None,
Self::Simple { comment, .. } => Some(comment),
Self::Detail { .. } => None,
}
}
#[must_use]
pub fn get_full_name(&self) -> Option<&str> {
match &self {
Gecos::Simple { .. } => None,
Gecos::Detail { full_name, .. } => {
Self::Simple { .. } => None,
Self::Detail { full_name, .. } => {
if full_name.is_empty() {
None
} else {
Some(&full_name)
Some(full_name)
}
}
}
@ -46,12 +47,12 @@ impl Gecos {
#[must_use]
pub fn get_room(&self) -> Option<&str> {
match &self {
Gecos::Simple { .. } => None,
Gecos::Detail { room, .. } => {
Self::Simple { .. } => None,
Self::Detail { room, .. } => {
if room.is_empty() {
None
} else {
Some(&room)
Some(room)
}
}
}
@ -59,12 +60,12 @@ impl Gecos {
#[must_use]
pub fn get_phone_work(&self) -> Option<&str> {
match &self {
Gecos::Simple { .. } => None,
Gecos::Detail { phone_work, .. } => {
Self::Simple { .. } => None,
Self::Detail { phone_work, .. } => {
if phone_work.is_empty() {
None
} else {
Some(&phone_work)
Some(phone_work)
}
}
}
@ -72,12 +73,12 @@ impl Gecos {
#[must_use]
pub fn get_phone_home(&self) -> Option<&str> {
match &self {
Gecos::Simple { .. } => None,
Gecos::Detail { phone_home, .. } => {
Self::Simple { .. } => None,
Self::Detail { phone_home, .. } => {
if phone_home.is_empty() {
None
} else {
Some(&phone_home)
Some(phone_home)
}
}
}
@ -85,8 +86,8 @@ impl Gecos {
#[must_use]
pub const fn get_other(&self) -> Option<&Vec<String>> {
match self {
Gecos::Simple { .. } => None,
Gecos::Detail { other, .. } => match other {
Self::Simple { .. } => None,
Self::Detail { other, .. } => match other {
None => None,
Some(comments) => Some(comments),
},
@ -97,8 +98,8 @@ impl Gecos {
impl Display for Gecos {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self {
Gecos::Simple { comment } => write!(f, "{}", comment),
Gecos::Detail {
Self::Simple { comment } => write!(f, "{}", comment),
Self::Detail {
full_name,
room,
phone_work,
@ -125,7 +126,7 @@ impl TryFrom<String> for Gecos {
fn try_from(source: String) -> std::result::Result<Self, Self::Error> {
let vals: Vec<String> = source.split(',').map(ToString::to_string).collect();
if vals.len() > 3 {
Ok(Gecos::Detail {
Ok(Self::Detail {
full_name: vals[0].clone(),
room: vals[1].clone(),
phone_work: vals[2].clone(),
@ -137,7 +138,7 @@ impl TryFrom<String> for Gecos {
},
})
} else if vals.len() == 1 {
Ok(Gecos::Simple {
Ok(Self::Simple {
comment: vals.get(0).unwrap().into(),
})
} else {
@ -145,7 +146,6 @@ impl TryFrom<String> for Gecos {
}
}
}
#[test]
fn test_parse_gecos() {
// test if the Gecos field can be parsed and the resulting struct is populated correctly.

View File

@ -24,11 +24,11 @@ pub struct User {
}
impl User {
pub fn get_shadow(&self) -> Option<&crate::Shadow> {
#[must_use]
pub const fn get_shadow(&self) -> Option<&crate::Shadow> {
match self.password {
crate::Password::Encrypted(_) => None,
crate::Password::Encrypted(_) | crate::Password::Disabled => None,
crate::Password::Shadow(ref s) => Some(s),
crate::Password::Disabled => None,
}
}
/*fn get_nth_line(content: &str, n: u32) -> (String, u64) {
@ -49,17 +49,16 @@ impl User {
trace!("Olduser:\n\t{}\nNewuser\n\t{}", &self.source, &line);
(offset, line.len(), line == self.source)
}*/
#[must_use]
pub fn remove_in(&self, content: &str) -> String {
content
.split(&self.source)
.map(|x| x.trim())
.map(str::trim)
.collect::<Vec<&str>>()
.join("\n")
}
pub fn username(&mut self, name: String) -> &mut Self {
self.username = crate::Username {
username: name.into(),
};
self.username = crate::Username { username: name };
self
}
pub fn disable_password(&mut self) -> &mut Self {
@ -131,7 +130,7 @@ impl crate::api::UserRead for User {
#[must_use]
fn get_password(&self) -> Option<&str> {
match &self.password {
crate::Password::Encrypted(crate::EncryptedPassword { password }) => Some(&password),
crate::Password::Encrypted(crate::EncryptedPassword { password }) => Some(password),
crate::Password::Shadow(crate::Shadow { ref password, .. }) => Some(&password.password),
crate::Password::Disabled => None,
}
@ -287,6 +286,7 @@ fn test_new_from_string() {
#[test]
fn test_parse_passwd() {
// Test wether the passwd file can be parsed and recreated without throwing an exception
use std::convert::TryInto;
use std::fs::File;
use std::io::{prelude::*, BufReader};
let file = File::open("/etc/passwd").unwrap();
@ -295,7 +295,7 @@ fn test_parse_passwd() {
for (n, line) in reader.lines().enumerate() {
let lineorig: String = line.unwrap();
let linecopy = lineorig.clone();
let pass_struc = User::new_from_string(linecopy, n as u32).unwrap();
let pass_struc = User::new_from_string(linecopy, n.try_into().unwrap()).unwrap();
assert_eq!(
// ignoring the numbers of `,` since the implementation does not (yet) reproduce a missing comment field.
lineorig,

View File

@ -1,10 +1,3 @@
#![warn(
clippy::all,
/* clippy::restriction,*/
clippy::pedantic,
clippy::nursery,
clippy::cargo
)]
#![allow(clippy::non_ascii_literal)]
use log::warn;
@ -65,8 +58,7 @@ impl Display for Password {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Encrypted(EncryptedPassword { password }) => write!(f, "{}", password,),
Self::Shadow(_) => write!(f, "x"),
Self::Disabled => write!(f, "x"),
Self::Shadow(_) | Self::Disabled => write!(f, "x"),
}
}
}
@ -85,11 +77,11 @@ impl Display for EncryptedPassword {
impl TryFrom<String> for EncryptedPassword {
type Error = UserLibError;
fn try_from(source: String) -> std::result::Result<Self, Self::Error> {
if source == "x" {
/*if source == "x" {
//warn!("password from shadow not loaded!")
} else {
//warn!("Password field has an unexpected value")
};
};*/
Ok(Self { password: source })
}
}
@ -149,6 +141,7 @@ impl Gid {
self.gid < 1000
}
#[must_use]
pub const fn get_gid(&self) -> u32 {
self.gid
}

View File

@ -1,14 +1,4 @@
#![warn(
clippy::all,
/* clippy::restriction,*/
clippy::pedantic,
clippy::nursery,
clippy::cargo
)]
#![allow(clippy::non_ascii_literal)]
use crate::userlib::NewFromString;
use log::warn;
use crate::UserLibError;
use std::cmp::Eq;
@ -40,10 +30,11 @@ impl Shadow {
pub fn get_password(&self) -> &str {
&self.password.password
}
#[must_use]
pub fn remove_in(&self, content: &str) -> String {
content
.split(&self.source)
.map(|x| x.trim())
.map(str::trim)
.collect::<Vec<&str>>()
.join("\n")
}
@ -108,7 +99,7 @@ impl NewFromString for Shadow {
let extra = elements.get(8).unwrap();
Ok(Self {
pos: position,
source: line.clone(),
source: line,
username: crate::Username::try_from(elements.get(0).unwrap().to_string())?,
password: crate::EncryptedPassword::try_from(elements.get(1).unwrap().to_string())?,
last_change: date_since_epoch(elements.get(2).unwrap()),

View File

@ -26,7 +26,8 @@ impl Default for Files {
impl Files {
/// Check if all the files are defined. Because some operations require the files to be present
pub fn is_virtual(&self) -> bool {
#[must_use]
pub const fn is_virtual(&self) -> bool {
!(self.group.is_some() & self.passwd.is_some() & self.shadow.is_some())
}
pub fn lock_and_get_passwd(&self) -> Result<LockedFileGuard, crate::UserLibError> {
@ -89,7 +90,7 @@ impl LockedFileGuard {
Ok(_) => (),
Err(e) => return Err(("Could not write (all) users. ".to_owned(), e).into()),
};
let _ = self.file.write("\n".as_bytes());
let _ = self.file.write(b"\n");
Ok(())
}
@ -155,12 +156,19 @@ impl LockedFileGuard {
);
// write the pid into the tempfile
{
let mut tempfile = File::create(&*tempfilepath)
.expect(&format!("Failed to open {}", filename.to_str().unwrap()));
match write!(tempfile, "{}", pid) {
Ok(_) => {}
Err(_) => error!("could not write to {}", filename.to_string_lossy()),
};
let mut tempfile = File::create(&*tempfilepath).unwrap_or_else(|e| {
panic!("Failed to open {} error: {}", filename.to_str().unwrap(), e)
});
write!(tempfile, "{}", pid).or_else(|e| {
let error_msg = format!(
"could not write to {} error {}",
filename.to_string_lossy(),
e
);
error!("{}", error_msg);
let err: crate::UserLibError = error_msg.into();
Err(err)
})?;
}
// try to make a hardlink from the lockfile to the tempfile
@ -198,12 +206,9 @@ impl LockedFileGuard {
}
};
let mut content = String::new();
match lf.read_to_string(&mut content) {
Ok(_) => {}
Err(_) => {
panic!("failed to read the lockfile{}", e);
}
}
lf.read_to_string(&mut content)
.unwrap_or_else(|e| panic!("failed to read the lockfile{}", e));
let content = content.trim().trim_matches(char::from(0));
let lock_pid = content.parse::<u32>();
match lock_pid {

View File

@ -5,11 +5,13 @@ pub struct SourceHash {
}
impl SourceHash {
#[must_use]
pub fn new(src: &str) -> Self {
Self {
hashvalue: src.to_owned(),
}
}
#[must_use]
pub fn has_changed(&self, new: &str) -> bool {
trace!(
"Old and new lengths: {}, {}",
@ -27,6 +29,7 @@ pub struct Hashes {
}
impl Hashes {
#[must_use]
pub fn new(passwd: &str, shadow: &str, group: &str) -> Self {
Self {
passwd: SourceHash::new(passwd),

View File

@ -1,10 +1,3 @@
#![warn(
clippy::all,
//clippy::restriction,
clippy::pedantic,
clippy::nursery,
clippy::cargo
)]
#![allow(clippy::non_ascii_literal)]
pub mod files;
@ -33,11 +26,11 @@ impl UserDBLocal {
shadow_content: &str,
group_content: &str,
) -> Self {
let shadow_entries: Vec<crate::Shadow> = string_to(&shadow_content);
let mut users = user_vec_to_hashmap(string_to(&passwd_content));
let groups = string_to(&group_content);
let shadow_entries: Vec<crate::Shadow> = string_to(shadow_content);
let mut users = user_vec_to_hashmap(string_to(passwd_content));
let groups = string_to(group_content);
shadow_to_users(&mut users, shadow_entries);
let res = Self {
Self {
source_files: files::Files {
passwd: None,
group: None,
@ -45,13 +38,11 @@ impl UserDBLocal {
},
users,
groups,
source_hashes: hashes::Hashes::new(&passwd_content, &shadow_content, &group_content),
};
res
source_hashes: hashes::Hashes::new(passwd_content, shadow_content, group_content),
}
}
/// Import the database from a [`Files`] struct
#[must_use]
pub fn load_files(files: files::Files) -> Result<Self, crate::UserLibError> {
// Get the Strings for the files use an inner block to drop references after read.
let (my_passwd_lines, my_shadow_lines, my_group_lines) = {
@ -77,10 +68,10 @@ impl UserDBLocal {
}
fn delete_from_passwd(
user: &crate::User,
passwd_file_content: String,
passwd_file_content: &str,
locked_p: &mut files::LockedFileGuard,
) -> Result<(), UserLibError> {
let modified_p = user.remove_in(&passwd_file_content);
let modified_p = user.remove_in(passwd_file_content);
// write the new content to the file.
let ncont = locked_p.replace_contents(modified_p);
@ -92,13 +83,13 @@ impl UserDBLocal {
fn delete_from_shadow(
user: &crate::User,
shadow_file_content: String,
shadow_file_content: &str,
locked_s: &mut files::LockedFileGuard,
) -> Result<(), UserLibError> {
let shad = user.get_shadow();
match shad {
Some(shadow) => {
let modified_s = shadow.remove_in(&shadow_file_content);
let modified_s = shadow.remove_in(shadow_file_content);
let ncont = locked_s.replace_contents(modified_s);
match ncont {
Ok(_) => Ok(()),
@ -116,10 +107,10 @@ impl UserDBLocal {
fn delete_from_group(
group: &crate::Group,
group_file_content: String,
group_file_content: &str,
locked_g: &mut files::LockedFileGuard,
) -> Result<(), UserLibError> {
let modified_g = group.remove_in(&group_file_content);
let modified_g = group.remove_in(group_file_content);
let replace_result = locked_g.replace_contents(modified_g);
match replace_result {
Ok(_) => Ok(()),
@ -133,17 +124,17 @@ impl UserDBLocal {
}
fn delete_home(user: &crate::User) -> std::io::Result<()> {
match user.get_home_dir() {
Some(dir) => std::fs::remove_dir_all(dir),
None => {
error!("Failed to remove the home directory! As the user did not have one.");
if let Some(dir) = user.get_home_dir() {
std::fs::remove_dir_all(dir)
} else {
let error_msg = "Failed to remove the home directory! As the user did not have one.";
error!("{}", error_msg);
Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Failed to remove the home directory! As the user did not have one.",
error_msg,
))
}
}
}
fn get_group_pos_by_id(&self, id: u32) -> Option<(&crate::Group, usize)> {
for (i, group) in self.groups.iter().enumerate() {
@ -190,8 +181,8 @@ impl UserDBWrite for UserDBLocal {
error!("The source files have changed. Deleting the user could corrupt the userdatabase. Aborting!");
Err(format!("The userdatabase has been changed {}", args.username).into())
} else {
Self::delete_from_passwd(user, passwd_file_content, &mut locked_p)?;
Self::delete_from_shadow(user, shadow_file_content, &mut locked_s)?;
Self::delete_from_passwd(user, &passwd_file_content, &mut locked_p)?;
Self::delete_from_shadow(user, &shadow_file_content, &mut locked_s)?;
if args.delete_home == DeleteHome::Delete {
Self::delete_home(user)?;
}
@ -206,7 +197,7 @@ impl UserDBWrite for UserDBLocal {
{
UserDBLocal::delete_from_group(
group,
group_file_content,
&group_file_content,
&mut locked_g,
)?;
let _gres = self.groups.remove(id);
@ -297,9 +288,9 @@ impl UserDBRead for UserDBLocal {
fn get_user_by_id(&self, uid: u32) -> Option<&crate::User> {
// could probably be more efficient - on the other hand its no problem to loop a thousand users.
for (_, user) in self.users.iter() {
for user in self.users.values() {
if user.get_uid() == uid {
return Some(&user);
return Some(user);
}
}
None
@ -310,7 +301,7 @@ impl UserDBRead for UserDBLocal {
}
fn get_group_by_name(&self, name: &str) -> Option<&crate::Group> {
for group in self.groups.iter() {
for group in &self.groups {
if group.get_groupname()? == name {
return Some(group);
}
@ -319,7 +310,7 @@ impl UserDBRead for UserDBLocal {
}
fn get_group_by_id(&self, id: u32) -> Option<&crate::Group> {
for group in self.groups.iter() {
for group in &self.groups {
if group.get_gid()? == id {
return Some(group);
}
@ -376,7 +367,7 @@ fn shadow_to_users(
for pass in shadow {
let user = users
.get_mut(pass.get_username())
.expect(&format!("the user {} does not exist", pass.get_username()));
.unwrap_or_else(|| panic!("the user {} does not exist", pass.get_username()));
user.password = crate::Password::Shadow(pass);
}
users
@ -397,7 +388,7 @@ fn user_vec_to_hashmap(users: Vec<crate::User>) -> HashMap<String, crate::User>
.collect()
}
/// Try to parse a String into some Object
/// Try to parse a String into some Object.
///
/// # Errors
/// if the parsing failed a [`UserLibError::Message`](crate::userlib_error::UserLibError::Message) is returned containing a more detailed error message.
@ -412,12 +403,20 @@ fn string_to<T>(source: &str) -> Vec<T>
where
T: NewFromString,
{
use std::convert::TryInto;
source
.lines()
.enumerate()
.filter_map(|(n, line)| {
if line.len() > 5 {
Some(T::new_from_string(line.to_owned(), n as u32).expect("failed to read lines"))
Some(
T::new_from_string(
line.to_owned(),
n.try_into()
.unwrap_or_else(|e| panic!("Failed to convert usize to u32 {}", e)),
)
.expect("failed to read lines"),
)
} else {
None
}
@ -484,10 +483,10 @@ fn test_user_db_write_implementation() {
assert_eq!(data.get_all_users().len(), 1);
assert!(data
.delete_user(NewUserArgs::builder().username(&user).build().unwrap())
.delete_user(NewUserArgs::builder().username(user).build().unwrap())
.is_ok());
assert!(data
.delete_user(NewUserArgs::builder().username(&user).build().unwrap())
.delete_user(NewUserArgs::builder().username(user).build().unwrap())
.is_err());
assert_eq!(data.get_all_users().len(), 0);
}

View File

@ -17,8 +17,8 @@ fn test_test() {
let mf = adduser::Files {
passwd: Some(p.path.clone()),
shadow: Some(s.path.clone()),
group: Some(g.path.clone()),
shadow: Some(s.path),
group: Some(g.path),
};
let mut db = adduser::UserDBLocal::load_files(mf).unwrap();
@ -32,9 +32,9 @@ fn test_test() {
);
let pf2 = fs::read_to_string(&p.path).unwrap();
assert_eq!(user_res.unwrap().get_username().unwrap(), "teste");
let pfl = pf.lines();
let pfl2 = pf2.lines();
for (l1, l2) in pfl.zip(pfl2) {
let pflines = pf.lines();
let pflines2 = pf2.lines();
for (l1, l2) in pflines.zip(pflines2) {
if l1 != l2 {
dbg!(l1, l2);
assert!(l1.starts_with("teste"));

View File

@ -12,6 +12,7 @@ pub struct Fixture {
}
impl Fixture {
#[must_use]
pub fn blank(fixture_filename: &str) -> Self {
// First, figure out the right file in `tests/fixtures/`:
let root_dir = &env::var("CARGO_MANIFEST_DIR").expect("$CARGO_MANIFEST_DIR");
@ -24,14 +25,15 @@ impl Fixture {
let mut path = PathBuf::from(&tempdir.path());
path.push(&fixture_filename);
Fixture {
Self {
_tempdir: tempdir,
source,
path,
}
}
#[must_use]
pub fn copy(fixture_filename: &str) -> Self {
let fixture = Fixture::blank(fixture_filename);
let fixture = Self::blank(fixture_filename);
fs::copy(&fixture.source, &fixture.path).unwrap();
fixture
}
@ -41,6 +43,6 @@ impl Deref for Fixture {
type Target = Path;
fn deref(&self) -> &Self::Target {
self.path.deref()
&self.path
}
}