| Age | Commit message (Collapse) | Author | 
|---|
|  | Have each `write_to_file` test pass in a custom filename to the helper
function. This way each test has its own file to deal with, eliminating
the race condition when running tests in parallel (the default). | 
|  | If we get an `AliasSearchError::NotFound` error we still want to write
the alias to the file. After all, it's an email we haven't encountered
yet so we should store an alias for it.
If the email exists, we can do what we were doing before and change the
current alias to be unique.
Rename our "append" `write_to_file` test method to be a little more
clear about its purpose.
Create a new `write_to_file` test function that tests the case we're
adding here.
Note that having these two tests together seems to cause a race
condition because they're both using the same temporary test file. If we
run tests with `RUST_TEST_THREADS=1 cargo test` then they pass. Will see
about fixing that next. | 
|  | We want to be able to write a test that ensures aliases can be written
to the file even if they don't already exist.
To do this, I want to be able to reuse the code in the helper function.
We can't use the code that appends to the file because this is relevant
only to the `alias_write_to_file_must_write_given_alias_to_file` test
(which I just realised should actually be renamed to something more
specific).
In order to run this code without requiring it to be in the helper
function, extract it to a closure that gets passed to the helper.
We need to pass `alias` into the function explicitly in order to use it
otherwise we get an error on an immutable borrow. | 
|  | Create a new helper function that does the work of
`alias_write_to_file_must_write_given_alias_to_file`. We want to be able
to add another test of the `write_to_file` method that does the same
thing but for non-preexisting aliases. Making a helper method will allow
us to avoid duplicating work. | 
|  | Take all of our Alias code, functions, errors, etc. and move them into
their own module. This removes some clutter from our `main.rs` file and
makes things better organised. Now all the alias code lives in its own
dedicated place.
Update our test file imports to match this change.
Updates to alias code:
* Reordered imports alphabetically
* Made `Alias` public
* Made `AliasSearchError` public
* Made all methods on `Alias` public | 
|  | Expand the responsibility of `Alias#write_to_file` so that it performs
what it used to do plus all of what `write_alias` did.
This allows us to consolidate the functionality into a single method,
and move it into the `Alias` implementation.
The change required some modification to our `write_to_file` test:
* Create our test alias as mutable
* Write a new alias to the test file based on our test alias but with a
  different email. This allows the `write_to_file` method to work
  without erroring with an `AliasSearchError::NotFound`.
* Needed to `derive(Clone)` on `Alias` in order to be able to easily
  clone it into the new near-duplicate alias.
* Change our `unwrap()` calls to `expect()` to make it easier to see
  where exactly we panicked. Otherwise I didn't really have any way of
  knowing.
* Add some comments for clarity | 
|  | Makes more sense for this function to live in a method on `Alias`
because it operates directly on an alias.
Refactor our tests and code to support this new organisation. | 
|  | The test compiler complained that I should make my constant uppercase.
Do this to eliminate our compiler warnings. | 
|  | Changed the test to use a file with multiple alias lines for a more
real-world scenario. Achieving this by copying the `testdata/aliases`
file into a new temporary test file instead of creating a new blank
file.
Then needed to change our assertion so that we get the correct line from
the file to compare on. This is always the last line in the file. Note
that `.len() - 2` is used because `.len() - 1` is the final newline.
The test change revealed two errors in my code:
1. I needed to open the file for appending, not just for writing.
2. A newline needs to be appended to the end of the file (otherwise all
   our aliases get written to the same line).
Fix the errors. | 
|  | Writes the alias to a given file.
Thinking I should modify the test so that we can know it works with
multiple alias lines. | 
|  | Eliminate some of the repeated setup code in our tests for this method.
Instead of doing this work inside the test functions, move them to a new
constant binding and function respectively.
A `const` seemed like a good fit because our alias identifier is just a
string. For the `Alias`, we have a new function that returns a
test object for us, making it possible to get two mutable copies of it
(one for each of our test functions).
Tests still pass, I guess it worked. | 
|  | This function takes a list of aliases and updates the current `Alias`'s
alias using an auto-incremented numeric id.
Not happy with the repetition in the tests. Need to figure out if
there's a way to abstract that. | 
|  | My next step is to get the list produced by this function and use it to
build a new alias of `#{alias}-#{id + 1}`.
In trying to figure out how best to do that, I realised that it would be
easier to do if I had actual aliases to work with instead of full Mutt
alias lines that I'd have to parse (again).
Update our function to give us a list of aliases instead of full alias
lines. | 
|  | New test for when alias matches are found in the given file. We want to
match all aliases that don't have the searched email and start with the
searched alias string.
This gives us a list of aliases. We'll then be able to use this list to
determine the highest-ranking id of the searched alias and append
${id}+1 to it to create our new alias. | 
|  | When the given alias being searched for does not appear in the alias
file, a `NotFound` error should be returned. | 
|  | When the email of the alias we're looking is already in the file, expect
an `AliasSearchError::EmailExists` error.
Oh man, this was a tough one. After much searching, finally figured out
how to implement the `PartialEq` trait for my error type so that we
could actually test it.
Many thanks to @peterbudai for an example in the 'redux' project of how
to do this
(https://github.com/peterbudai/redux/blob/ef5d47a0a64cef9fa9e1e9c6f21badc46fa283fc/src/lib.rs):
    #[cfg(test)]
    impl PartialEq<Error> for Error {
        fn eq(&self, other: &Error) -> bool {
           match *self {
               Error::Eof => match *other { Error::Eof => true, _ => false },
               Error::InvalidInput => match *other { Error::InvalidInput => true, _ => false },
               Error::IoError(_)  => match *other { Error::IoError(_) => true, _ => false },
           }
        }
    }
With that example, I was able to correctly build an equality function to
get past my compiler errors which complained that
    an implementation of `std::cmp::PartialEq` might be missing for `std::io::error::Error`
when I tried to `#[derive(PartialEq)]` on my `AliasSearchError` type. | 
|  | I think we should return a list of matched aliases from this function
instead of a simple boolean value. As such, we'll start by renaming the
function to something that makes sense in that context.
We now need to modify the function and return type in order to provide
that information. | 
|  | Saw this pattern in the Rust book chapter Error Handling
(http://doc.rust-lang.org/stable/book/error-handling.html#composing-option-and-result).
Not sure if this is right but it seems better and more clearly evokes
our intentions, so use `to_owned` here. | 
|  | This allows us to more easily compare parts of the alias line.
Update our test to pass an `Alias` also. | 
|  | Conflicts:
	src/tests.rs | 
|  | Update tests to use our new `Alias::new` method for building an alias
string. The `build_alias` function will be removed and replaced with
this new function.
We have a test failure in `new_alias_with_only_email` which has an extra
space after the alias. | 
|  | This will allow us to pass an alias and grep for it in a given file.
Just a rough outline to start. Added a super basic test and a file in
"testdata" to operate on for testing. | 
|  | Instead of putting all our asserts in a single test function, make a
function for each assert. This allows us to give our test functions more
specific names based on what exactly we're testing, and produces better
output from `cargo test`. Also, if one of those fails for whatever
reason, it's nice to know it will do so with a meaningful name. | 
|  | Make the function a bit more DRY by taking the `push_str` calls out of
the `if` block.
Add a new test and some code to remove commas and quotes from aliases. | 
|  | Copy of the functionality in W. Caleb McDaniel's Bash script implemented
in Rust:
    echo "${MESSAGE}" | grep ^"From: " | sed s/[\,\"\']//g | awk '{$1=""; if (NF == 3) {print "alias" $0;} else if (NF == 2) {print "alias" $0 $0;} else if (NF > 3) {print "alias", tolower($(NF-1))"-"tolower($2) $0;}}'
Doesn't currently include the [,"'] filtering.
Added a couple of new test cases to cover other address formats.
Not sure if I should use `if..else if` here or a `match`. I feel like I
should return an empty string at the end if we can't build an alias
line. | 
|  | Create a new `tests` module. This lives in its own file. Not sure if
this is idiomatic Rust, but I prefer the idea of my tests living in a
different file from my code. This module gets included in `main.rs`.
We `use` `build_alias` directly because it's currently a private
function, so doing `use super::*` didn't import it. Not sure if I should
be making it a public function in order to mitigate this.
Add a couple of variant test cases to check the string transformation
that this function should be doing. |