Skip to content

Commit

Permalink
Remove erroneous add_entry stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
deciduously committed Jul 21, 2018
1 parent 3f2de06 commit afc674c
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 181 deletions.
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@ with this exact need but not using either of those two operating systems.

FLAGS:

* `-e, --email` Placeholder command for developing email functionality
* `-h, --help` Prints help information
* `-p, --preview` Displays the current contents of the batch
* `-r, --report` Daily report comparing inputs to outputs for the day
* `-V, --version` Prints version information

OPTIONS:

* `-a, --add <INPUT_FILE>` Add a new file to the register
* `-c, --config <CONFIG_FILE>` Specify an alternate toml config file

Feel free to mix and match any of the above, it's fun.
Expand All @@ -38,7 +36,6 @@ With no config given it will default to `Bot.toml`, and with no flags or options
* [clap](https://github.com/kbknapp/clap-rs)
* [error-chain](https://github.com/rust-lang-nursery/error-chain)
* [lazy_static](https://github.com/rust-lang-nursery/lazy-static.rs)
* [lettre](https://github.com/lettre/lettre)
* [regex](https://github.com/rust-lang/regex)
* [serde/serde_derive](https://serde.rs)
* [toml](https://github.com/alexcrichton/toml-rs)
Expand Down
37 changes: 24 additions & 13 deletions src/batch.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// batch.rs handles the string parsing and batching logic for eliminating redundant line items
use brain::{Brain, Email};
use chrono::prelude::*;
use errors::*;
use regex::Regex;
Expand Down Expand Up @@ -70,24 +71,18 @@ impl Entry {
}
}

impl fmt::Display for Entry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ID: {}, PRODUCT {}", self.id, self.product)
}
}

impl FromStr for Entry {
type Err = Error;

impl Entry {
// TODO this will eventually be getting a whole email
// including headers, time, etc
// instead of Utc::now(), store whatever time the email was received
// For now, this is close enough
fn from_str(s: &str) -> Result<Self> {
fn from_email(e: &Email) -> Result<Self> {
lazy_static! {
static ref AD_RE: Regex = Regex::new(r"^The \w+ Invoice For iMIS ID (?P<id>\d+) For the Product (?P<product>.+) Has Changed You need to verify the Autodraft is now correct").unwrap();
}

let s = &e.contents;

if AD_RE.is_match(s) {
let captures = AD_RE.captures(s).unwrap();
Ok(Entry {
Expand All @@ -103,6 +98,11 @@ impl FromStr for Entry {
}
}

impl fmt::Display for Entry {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ID: {}, PRODUCT {}", self.id, self.product)
}
}
// Can store multiple entries
#[derive(Clone, Debug, PartialEq)]
pub struct BatchEntry {
Expand Down Expand Up @@ -181,12 +181,21 @@ impl Batch {
Ok(())
}

pub fn from_brain(brain: &Brain) -> Result<Self> {
// call add_entry on each email in the brain
let mut ret = Batch::new();
for email in &brain.emails {
ret.add_entry(Entry::from_email(email)?)?;
}
Ok(ret)
}

#[cfg(test)]
// Test batch with one entry inserted
pub fn test() -> Self {
let mut batch = Batch::new();
batch
.add_entry(Entry::from_str(TEST_COOL_STR).unwrap())
.add_entry(Entry::from_email(&Email::from_str(TEST_COOL_STR).unwrap()).unwrap())
.unwrap();
batch
}
Expand Down Expand Up @@ -218,7 +227,9 @@ impl FromStr for Batch {
let lines = s.split('\n');
let mut entries = Vec::new();
for line in lines {
entries.push(BatchEntry::from(Entry::from_str(line)?));
entries.push(BatchEntry::from(Entry::from_email(&Email::from_str(
line,
)?)?));
}
Ok(Batch { entries })
}
Expand All @@ -231,7 +242,7 @@ mod tests {
#[test]
fn test_entry_from_str() {
assert_eq!(
Entry::from_str(TEST_COOL_STR).unwrap(),
Entry::from_email(&Email::from_str(TEST_COOL_STR).unwrap()).unwrap(),
Entry {
id: 12345,
product: Product::Other(String::from("COOL_PROD")),
Expand Down
173 changes: 50 additions & 123 deletions src/brain.rs
Original file line number Diff line number Diff line change
@@ -1,60 +1,32 @@
// brain.rs handles all internal storage directory access
use batch::{Batch, Entry};
use config::Config;
use errors::*;
use regex::Regex;
use std::{
fmt, fs::{create_dir, read_dir, remove_dir_all, File}, io::prelude::*, path::{Path, PathBuf},
str::FromStr,
fmt, fs::{create_dir, read_dir}, path::PathBuf, str::FromStr,
};
use util::*;

// This is my internal folder
// I want to be able to serialize/deserialize the contents
#[derive(Debug, PartialEq)]
pub struct Brain {
pub batch: Batch,
pub emails: Vec<Email>,
}

// I want to change how it works
// Instead of holding on to a batch, a batch is ONLY a function of the emails inside.
// So, this wont hold on to a running copy of it.
impl Brain {
pub fn new() -> Self {
Brain {
batch: Batch::new(),
emails: Vec::new(),
}
}
pub fn add_entry(&mut self, input_p: &str) -> Result<()> {
// Read the file given into contents
let contents = file_contents_from_str_path(input_p)?;

// add raw email to brain
self.emails.push(Email::new(&input_p, &contents)?);

// add entry to the batch
self.batch.add_entry(Entry::from_str(&contents)?)?;

Ok(())
}

// This just returns a prefilled Brain for testing purposes
#[cfg(test)]
fn test(temp_dir: &str) -> Self {
Brain {
batch: Batch::test(),
emails: vec![Email {
filename: format!("{}/sample-email.html", temp_dir),
contents: TEST_COOL_STR.into(),
}],
}
Brain { emails: Vec::new() }
}

// maybe have a len() returning the hwo many emails we have
}

impl fmt::Display for Brain {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "batch: {}\nemails: {:?}", self.batch, self.emails)
write!(f, "emails: {:?}", self.emails)
}
}

Expand All @@ -77,18 +49,20 @@ impl Context {
Ok(ctx)
}
// Reads the brain dir into memory from the dir specified in config. If no brain exists, makes a new one
// this is still prpbably all relevant
// TODO proper Path usage. Lets start here.
pub fn read_fs(&mut self) -> Result<()> {
lazy_static! {
static ref BATCH_RE: Regex = Regex::new(r"^batch-TEMPDATE.html").unwrap();
}

let path = &format!("{}/", self.config.directory.path);
let brain_path = &self.config.directory.path;

// If no path exists, create it.
// std::fs::create_dir will return an error if the path exists
if !Path::new(path).exists() {
if !brain_path.exists() {
println!("No brain found! Creating...");
create_dir(path).chain_err(|| "Could not create brain dir")?;
create_dir(brain_path).chain_err(|| "Could not create brain dir")?;
}

// This should be:
Expand All @@ -101,20 +75,19 @@ impl Context {

// There will be a cleanup task (maybe as part of report() that will push everything to hx)
// dir_lisitng holds str paths of each file in Brain
let dir_listing: Vec<PathBuf> = read_dir(path)
let dir_listing: Vec<PathBuf> = read_dir(brain_path)
.chain_err(|| "Could not read brain!")?
.map(|f| f.expect("Could not read brain entry").path())
.collect();
println!("{:#?}", dir_listing);

// Grab the current batch
// Save any emails
let mut current_batch_p = "";
let mut emails = Vec::new();
for l in &dir_listing {
let p_str = l.to_str().unwrap();
if BATCH_RE.is_match(p_str) {
current_batch_p = p_str;
continue;
} else {
// TODO check if its actually an email?
// what do we do with non-expected files?
Expand All @@ -125,68 +98,49 @@ impl Context {
}
}

// Read in the current batch
// If none exists, make a new one
let batch = if current_batch_p == "" {
Batch::new()
} else {
Batch::from_str(&file_contents_from_str_path(current_batch_p)?)?
};

// Put together the brain and store it back in the context
self.brain = Brain { batch, emails };
self.brain = Brain { emails };
println!("Brain:\n{}\n", self.brain);

Ok(())
}
// Writes the in-memory brain out to the filesystem
pub fn write_fs(&self) -> Result<()> {
let prefix = &format!("{}/", self.config.directory.path);
let path = Path::new(prefix);

// Start from scratch
remove_dir_all(path).chain_err(|| "Could not clean Brain")?;
create_dir(path).chain_err(|| "Could not write fresh Brain")?;

// write the batch
let date = "TEMPDATE";

// FIXME this should be more explicit than a dot expansion
let batch_filename = format!("{}batch-{}.html", prefix, date);
let mut batch_file =
File::create(&batch_filename).chain_err(|| "Could not create batch file")?;
batch_file
.write_all(format!("{}", self.brain.batch).as_bytes())
.chain_err(|| "Could not write to batch file")?;
// Compression will be easy - just use as_compressed_bytes or something

// write each email
//
for email in &self.brain.emails {
let mut e_file =
File::create(&email.filename).chain_err(|| "Could not create email file")?;
e_file
.write_all(email.contents.as_bytes())
.chain_err(|| "Could not write to email file")?;
}

Ok(())
}
// Have Brain::add_entry insert it properly, then persist it to disk
pub fn add_entry(&mut self, input_p: &str) -> Result<()> {
println!("Context::add_entry: {}", input_p);
self.brain.add_entry(&input_p)?;
self.write_fs()?;
Ok(())
}
// BE CAREFUL - empties itself out. Potential data loss if you call write_fs() afterwards
// this is for testing purposes only
// you should probably get rid of it asap
#[cfg(test)]
pub fn clean(&mut self) {
self.brain = Brain::new();
self.write_fs().unwrap();
}
// This is going to change - no more full-file stuff.
// The "brain" concept probably needs to be renamed.
// We're just writing a digest and copying files into hx/
// some of this will be useful for wirting the digest
// pub fn write_fs(&self) -> Result<()> {
// let prefix = &format!("{:?}/", self.config.directory.path); // TODO this is bad
// let path = Path::new(prefix);
//
// // Start from scratch
// remove_dir_all(path).chain_err(|| "Could not clean Brain")?;
// create_dir(path).chain_err(|| "Could not write fresh Brain")?;
//
// // write the batch
// let date = "TEMPDATE";
//
// // FIXME this should be more explicit than a dot expansion
// let batch_filename = format!("{}batch-{}.html", prefix, date);
// let mut batch_file =
// File::create(&batch_filename).chain_err(|| "Could not create batch file")?;
// batch_file
// .write_all(format!("{}", self.brain.batch).as_bytes())
// .chain_err(|| "Could not write to batch file")?;
// // Compression will be easy - just use as_compressed_bytes or something
//
// // write each email
// //
// for email in &self.brain.emails {
// let mut e_file =
// File::create(&email.filename).chain_err(|| "Could not create email file")?;
// e_file
// .write_all(email.contents.as_bytes())
// .chain_err(|| "Could not write to email file")?;
// }
//
// Ok(())
// }
}

#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -222,7 +176,6 @@ impl FromStr for Email {
#[cfg(test)]
mod tests {
use super::*;
use rand::{thread_rng, Rng};

//#[test]
//fn test_initialize_empty() {
Expand All @@ -233,30 +186,4 @@ mod tests {
//fn test_initialize_not_empty() {

//}

#[test]
fn test_add_entry() {
// Start with fresh test dir
println!("Preparing temp dir...");
let test_dir = format!{"{}", thread_rng().gen::<u32>()};
::std::fs::remove_dir_all(&test_dir)
.unwrap_or_else(|e| eprintln!("Failed to remove test dir: {}", e));
::std::fs::create_dir(&test_dir).unwrap();

let mut test_context: Context = Context::initialize(Config::test(&test_dir)).unwrap();

// add our sample email AFTER init
let sample_p = &format!("{}/sample-email.html", test_dir);
let mut file = ::std::fs::File::create(sample_p).unwrap();
file.write_all(TEST_COOL_STR.as_bytes()).unwrap();

test_context.add_entry(sample_p).unwrap();
let test_brain = test_context.brain;

println!("Cleaning temp dir...");
::std::fs::remove_dir_all(&test_dir)
.unwrap_or_else(|e| eprintln!("Failed to remove test dir: {}", e));

assert_eq!(test_brain, Brain::test(&test_dir))
}
}
Loading

0 comments on commit afc674c

Please sign in to comment.