aboutsummaryrefslogtreecommitdiffstats
AgeCommit message (Collapse)Author
2016-04-27Add CHANGELOGHEADv0.0.2masterTeddy Wing
Include some information about our two releases.
2016-04-27Increase version 0.0.1 -> 0.0.2Teddy Wing
2016-04-27Makefile: Add task to compress/package a release buildTeddy Wing
Provide a convenient way of creating a binary package that can be uploaded to the GitHub releases page.
2016-04-27Merge branch 'use-writer-for-STDOUT-instead-of-println'Teddy Wing
2016-04-27main: Ignore errors, don't write to STDERRTeddy Wing
Well, after all that error handling I'm going to have to remove error output. The problem was that this STDERR output interfered with the output of the email in Mutt. When viewing a message, the screen would become mangled (for certain messages), and I'd have to refresh (Ctrl-L) the view. After initially thinking this was because I was using `println!` instead of flushing a full buffer to STDOUT, I just now realised that my output to STDERR could be causing the problem. Sure enough, removing the STDERR output fixed the issue. This is certainly not ideal, so in the long term we'll probably want to add some kind of logging mechanism so that users actually have visibility into errors. But for now and for my own personal purposes, I think this works. And at least it gets me around the immediate annoying screen mangling issue.
2016-04-27Makefile: Add some new targetsTeddy Wing
To save me some time from having to write commands. Started with a `reinstall` target to make it easier to put a new build on my PATH. Then added a `test-all` target so I wouldn't have to use two commands to run both test suites. Needed to create a `test` task also in order to run the unit tests before the integration test. Ensure that we `cargo build` before running integration tests. Otherwise we might be testing against an old build.
2016-04-27README: Add section on testingv0.0.1Teddy Wing
Describe the commands to use to run the test suite.
2016-04-27README: Update GitHub URLTeddy Wing
Now that we've actually created and published the GitHub repo, use the new name. When I wrote the README I just guessed at a name and obviously that wasn't final.
2016-04-27Merge branch 'stream-did-not-contain-valid-utf8-error'Teddy Wing
2016-04-27Read aliases file as bytes and convert to stringTeddy Wing
Discovered that my Mutt aliases file uses the latin1 character encoding. That caused a "stream did not contain valid UTF-8" error when trying to read the file in the `Alias#find_in_file` function. This error was ostensibly triggered by a `str::from_utf8` call in the standard library (https://github.com/rust-lang/rust/blob/2174bd97c1458d89a87eb2b614135d7ad68d6f18/src/libstd/io/mod.rs#L315-L338). I ended up finding this Stack Overflow answer with an easy solution: http://stackoverflow.com/questions/28169745/what-are-the-options-to-convert-iso-8859-1-latin-1-to-a-string-utf-8/28175593#28175593 fn latin1_to_string(s: &[u8]) -> String { s.iter().map(|c| c as char).collect() } Since latin1 is a subset of Unicode, we can just read the bytes from the file and typecast them to Rust chars (which are UTF-8). That gives us the opportunity to easily get the text into an encoding that we can actually work with in Rust. At first I got frustrated because the suggestion didn't compile for me. It was suggested in January 2015, before Rust 1.0, so perhaps that factors into the error I was getting. Here it is: src/alias.rs:59:41: 59:45 error: mismatched types: expected `&[u8]`, found `core::result::Result<collections::string::String, std::io::error::Error>` (expected &-ptr, found enum `core::result::Result`) [E0308] src/alias.rs:59 let line = latin1_to_string(line); ^~~~ src/alias.rs:59:41: 59:45 help: run `rustc --explain E0308` to see a detailed explanation src/alias.rs:99:22: 99:31 error: only `u8` can be cast as `char`, not `&u8` src/alias.rs:99 s.iter().map(|c| c as char).collect() ^~~~~~~~~ error: aborting due to 2 previous errors A recommendation from 'niconii' Mozilla#rust-beginners was to use the Encoding library in order to do the conversion (https://github.com/lifthrasiir/rust-encoding). That certainly seems more robust and would be a good idea to try if this change doesn't work out in the long term. But the Stack Overflow answer just seemed so short and sweet that I really didn't like the idea of adding a dependency if I could get what I wanted with 3 lines of code. Finally took another look and reworked the suggested code to take a vector (which is what `BufReader#split` gives us) and clone the u8 characters to clear the compiler error of not being able to cast an &u8.
2016-04-25README: Fix Mutt `display_filter` settingTeddy Wing
* Should use `/usr/local/bin` not /usr/local` * Should be enclosed in quotes, otherwise Mutt complains
2016-04-25Merge branch 'add-readme'Teddy Wing
2016-04-25Add READMETeddy Wing
Initial draft of the README. Include a description of the program, installation and uninstallation directions, and license information.
2016-04-25Set `install.root` configurationTeddy Wing
Set the default installation path to `/usr/local/bin`. This allows us to install the program to that path using `cargo install`. The default can be overridden using `cargo install --root /some/path`.
2016-04-24Merge branch 'append-alias-even-if-it-doesn,t-already-exist'Teddy Wing
2016-04-24test: Fix `write_to_file` race conditionTeddy Wing
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).
2016-04-24Write alias even if we haven't found a matching oneTeddy Wing
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.
2016-04-24`write_to_file` test: Extract append lines to closureTeddy Wing
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.
2016-04-24Extract `alias_write_to_file` test function contents to helperTeddy Wing
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.
2016-04-24Add a documentation comment to our crateTeddy Wing
2016-04-24main: Change `unwrap` to `expect`Teddy Wing
Give us a better error message if a failure ever happens here. Was inspired by my experience in 2d1f7031f03194fbceffc15b1d6376abea243e22, where the `unwrap` calls gave no useful information.
2016-04-24Merge branch 'extract-alias-module'Teddy Wing
2016-04-24Move `Alias` to separate alias moduleTeddy Wing
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
2016-04-24Move `write_alias` function to `Alias#write_to_file`Teddy Wing
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
2016-04-24Move `find_alias_in_file` function to `Alias#find_in_file`Teddy Wing
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.
2016-04-23Add license information (GPLv3)Teddy Wing
Include a copy of the GNU GPL and a copyright notice. Decided not to put the GPL notice in each source file because I found that idea bothersome. Perhaps I'll change my mind later on.
2016-04-23Merge branch 'specify-alias-file-on-command-line'Teddy Wing
2016-04-23Update integration test to use the better test alias fileTeddy Wing
Instead of using the temporary `./testaliases` alias file, use a copy of the `./testdata/aliases` file. We're able to do this with our new ability to specify our alias file as the first argument to our executable.
2016-04-23Add a test email fileTeddy Wing
Meant to commit this as part of 9b967f55333c82d333d88bfda41dd576b9ff5b46 when I first added the TAP integration test but forgot to do so. This is a sample email that we can use in our integration test.
2016-04-23Remove dependency on 'getopts'Teddy Wing
As described in 0b12b2bae1130746ed49cc3c7a2daa819ede1b58, we don't need to depend on 'getopts' because we don't have any command line options, just a single required argument. Rewrite our code to factor out getopts and assume that the first argument to our program is an alias file path.
2016-04-23Specify alias file as a command line argumentTeddy Wing
* Add a dependency on 'getopts' * Remove the hard-coded "testaliases" file used previously. * write_alias: Update to include a `file` attribute that can reference an arbitrary file * find_alias_in_file: Change the `file` parameter to be a Path reference instead of a string so that it can be called correctly from `write_alias`. Also because it matches the File module's signature. Originally I planned to make the file argument available under a `-f` command-line option. Later I decided instead to make it a required argument, so it made more sense not to prefix it with an option flag. Since I no longer need command line options—just the first argument—I realised that I could get rid of the `getopts` dependency and use `std::env::args`. Will do this in a later commit.
2016-04-22Merge branch 'integration-test'Teddy Wing
2016-04-22Add MakefileTeddy Wing
Give us a task to run integration tests. This provides us with an explicit definition of how these should be run, rather than me just knowing that you have to run `prove` in order to execute them.
2016-04-22Add integration testTeddy Wing
Use the TAP harness with `prove` to give ourselves an integration test of the executable. This checks that when passing an email to it over STDIN, the proper alias gets added to the aliases file. For the moment, we're using the temporary `./testaliases` file. In the future we'll want to update our program and test code to use something like `./testdata/tmp` or something like that.
2016-04-22Revert "test.sh: Initial stab at an integration test"Teddy Wing
This reverts commit 6f078aecf87d39882c0fce1cc61b6220add43208. Decided that I'd rather use TAP/prove to do this integration test. It feels more comfortable to be able to rely on a test harness. Removing this file but keeping it in the log for posterity.
2016-04-22test.sh: Initial stab at an integration testTeddy Wing
Would like to modify the program to take a `--file` attribute so that we can supply a file on the command line to do an integration test with. The idea is that we pipe an email to the program and check that the right alias was added to our aliases file.
2016-04-22Add descriptions to `AliasSearchError` `fmt::Display`Teddy Wing
Use the descriptions from our `error::Error` implementation. To do so needed to `use std::error::Error`. Change those `write!` calls to `writeln!` also so that we get decent output on the command line. We now output errors from `AliasSearchError::{NotFound, EmailExists}` to STDERR for better error reporting.
2016-04-22Write alias errors to STDERR instead of panickingTeddy Wing
We use an `.ok()` call on the result of the write so that we can ignore these errors. I think we shouldn't really worry too much about not being to write to STDERR, and instead try to print out the full email message as best we can. In order to write the error (`e.to_string()`), we needed to implement `fmt::Display` on `AliasSearchError`. While I was at it also implemented the `error::Error` trait.
2016-04-22main: Simplify the STDOUT writerTeddy Wing
I wrote it the way I originally did because I wanted to be more explicit, but I don't think that was right. Doing it this way because it makes the code much simpler. Also found out there's a `writeln!` macro which I probably should have used instead of manually adding a newline before.
2016-04-22main: Write message to STDOUTTeddy Wing
We need to write the full messgae to STDOUT so that Mutt can read it back in. Remove our two return statements as this will interrupt the message.
2016-04-22tests: Make constant name uppercaseTeddy Wing
The test compiler complained that I should make my constant uppercase. Do this to eliminate our compiler warnings.
2016-04-22Get the full integration working for realTeddy Wing
Rename `handle_alias` to `write_alias` and implement the function. This function integrates all our steps together and writes our new alias if we have one. Alter our `main` function to remove some of the old code. Don't convert STDIN to a vector. That was naïve. Instead iterate over its lines directly. Handle all our errors with either a "no news is good news" or a panic.
2016-04-22main: Remove pseudocodeTeddy Wing
The program is nearly implemented and this information is no longer needed.
2016-04-22Merge branch 'check-for-alias-in-file'Teddy Wing
2016-04-22Alias#write_to_file: Fix append and ending newlineTeddy Wing
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.
2016-04-22Add `Alias#write_to_file`Teddy Wing
Writes the alias to a given file. Thinking I should modify the test so that we can know it works with multiple alias lines.
2016-04-22Make `update_alias_id` tests more DRYTeddy Wing
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.
2016-04-21Add Alias#update_alias_idTeddy Wing
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.
2016-04-21find_alias_in_file: Return list of aliases not alias linesTeddy Wing
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.
2016-04-21Remove `build_alias` functionTeddy Wing
This has been superseded by the `Alias::new` method (introduced in b182ea18dd664bc36e56601635ceb5ffdd67dc69). We can now safely remove this function.