Switch to more REST-ful URLs

- / now redirects to /authors; eventual / will host a comprehensive
  dashboard
- /authors (formerly /) now maps to "authors/index" instead of
  "commit_stats"
- /authors/:slug now maps to "authors/show" instead of "profile"

Change-Id: I18633a70e8f14d7682ffecdefd4a8812549d80b6
Reviewed-on: https://gerrit.causes.com/25814
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Make modals wider

As we're using modals to do things like display commit messages, make
them wider but still responsive, for readability.

Targeted using `body .modal` in order to beat the specificity in
Bootstrap's own styles, which target the modal with just `.modal`.

Change-Id: If017385b9290ae2b4775803315598740057a39c8
Reviewed-on: https://gerrit.causes.com/25815
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Move twigg files into subdirectory

As Twigg grows, and we add more features, we bring in more dependencies.
For example, we currently depend on Sinatra and Haml. Soon, we'll
depend on Sequel and likely mysql2 as we add the `gerrit stats` feature.

In order to prevent the gem from becoming bloated, we're going to split
it up into multiple gems. The main gem will be "twigg" and will depend
on nothing. Then we'll add "twigg-app", which will depend on "twigg" and
"sinatra". Later will come "twigg-gerrit", which will depend on "twigg"
and "mysql2" (likely) and "sequel".

We'll teach `twigg` to degrade gracefully when the various component
gems aren't available, but if you want everything, you'll be able to:

  gem install twigg twigg-app twigg-gerrit # etc

This commit is the first step in that process; we move all of the files
into a "twigg" subdirectory. These will form the basis of the "twigg"
gem. The next step will have us extracting the app files out into
"twigg-app".

Change-Id: Iac274836fd09ea376355adea87a8af14649b51b3
Reviewed-on: https://gerrit.causes.com/25816
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Remove useless .gitignore

Change-Id: Ib28825eb1d89bdf95536d64197a4dd5566b0ac50
Reviewed-on: https://gerrit.causes.com/25817
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Extract twigg-app gem

Move most the app files out of "twigg" into "twigg-app", and make the
later depend on the former in the gemspec (for easy installation) and
the former depend on the later in the Gemfile (for development).

In order for `bundle check` to work in both subdirectories, we manually
add the relative path to the other subdirectory in the "twigg-app"
Gemfile as well.

Other than that, this is mostly a straight move. Added `Twigg::App.root`
so that the code in the "twigg-app" gem could also have a convenient way
of finding its root directory, and added `Twigg::App::VERSION`.

Change-Id: I3d6013a9298bc2ea1c38e3b882d6ef9f31252854
Reviewed-on: https://gerrit.causes.com/25818
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Fix homepage URL in twigg gemspec

I renamed the projects on Gerrit and GitHub yesterday; update the
gemspec to match.

Change-Id: Ib51950f687b20989392767f04af7649d7693882d
Reviewed-on: https://gerrit.causes.com/25819
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add `#error` method to Console module and use it

Change-Id: I5b9bb2cc82dea3b4f4fb2c80c0b623c579123432
Reviewed-on: https://gerrit.causes.com/25820
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Use keyword arguments in Repo#commits method

Keyword arguments are good for readability and expressiveness, so use
them.

Change-Id: I89d93aa99f51e681a162246338024df8efe66e19
Reviewed-on: https://gerrit.causes.com/25821
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Extract twigg-gerrit gem

Much as we did with the twigg-app gem, extract the Gerrit functionality
into a gem, twigg-gerrit. We're doing this in order to keep the number
of dependencies of the main twigg gem small; if you want the Gerrit
functionality, you install the twigg-gerrit gem.

For now, this won't make much of a difference, but it will matter more
shortly, because we're going to be adding at least the sequel gem, and
likely the mysql2 gem as well, for the purposes of the "gerrit stats"
subcommand.

Most of this commit is just a straight move. Added a
`Command#with_dependency` method to encapsulate the pattern of working
with optional dependencies. I also needed to add a couple of `require
'forwardable'` calls, because the load ordering with this new set-up
meant that it wasn't pre-loaded by the time the code that was using it
needed it.

Change-Id: I672b478a66e9d8e7a81488c4f2305870d9346d7a
Reviewed-on: https://gerrit.causes.com/25822
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Kill an unnecessary blank line in the README

Change-Id: Id887f95f1aa37425b55fcf3668c6f7ece1b63698
Reviewed-on: https://gerrit.causes.com/25823
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add sequel as a dependency to twigg-gerrit

We make sequel a hard dependency. mysql2 is only a "soft" dependency
because it is possible that people may want to use different adapters
with it (for example, mysql or postgres).

Note that the "twigg/Gemfile" still changes here, because in the
development environment (only) "twigg" depends on the "twigg-gerrit"
(and "twigg-app") repos, and so drags in all their dependencies as well.

This will be used in a forthcoming commit to mediate access to the
Gerrit database.

Change-Id: Ice212b00c694b79b958349979292487c422cb50a
Reviewed-on: https://gerrit.causes.com/25824
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Move GitHost::SUB_SUBCOMMANDS into a method

This will allow subclasses to override it. The first subclass to take
advantage of this will be the Twigg::Command::Gerrit subclass, which
will soon be adding a "stats" subcommand.

Change-Id: Iacbc3b4586271445052b1295be466e1eec27c0e3
Reviewed-on: https://gerrit.causes.com/25825
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add first simple cut of "gerrit stats" subcommand

For now this just shows currently open issues. As we add functionality
here we'll probably want to encapsulate the database functionality
inside a dedicated abstraction, but for now, this simple prototype
works.

Change-Id: I8ea036df4ed322e7420f8039a6d169293d74bea6
Reviewed-on: https://gerrit.causes.com/25826
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add -c/--config switches

As noted in the comments, there is an unfortunate smell here that we
have little choice but to work around.

In "production", most (or all?) interaction will occur via the `twigg`
executable, and that means the Twigg::Command.run method, which can
process the options.

In development, crazy things happen, even when running the `twigg`
executable. First of all, we use Bundler in development, which looks
at the gemspec but also the Gemfile, and so ends up evaluating the
gemspec of dependent gems like twigg-app. This in turn forces the App
class to load (because we need to access `Twigg::App::VERSION`) even
before we get to our Twigg::Command.run call, and the class-level DSL
there ends up invoking Twigg::Config.config before we've had a chance to
process the arguments.

The only way to defend against this insanity is to teach the
Twigg::Config class to process `-c`/`--config` options. We put the logic
for processing options in the Twigg::Console class, where it is not so
out of place, and we make sure that Twigg::Command.run at least calls
Twigg::Config.config to ensure the options get processed.

On the bright side, this implementation is robust enough to work even
with things like `bundle exec shotgun config.ru` in development, which
bypass the `twigg` executable entirely.

It's ugly, but a necessary evil in order to support this feature.

Change-Id: I79ef80181bcdf121bc039a26f5302fea77eb1f9d
Reviewed-on: https://gerrit.causes.com/25827
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Switch away from RSpec `should` to `expect` syntax

As of mid-2012, the official recommendation has been to eschew `should`,
opting instead for `expect`:

  https://github.com/rspec/rspec-expectations/blob/master/Should.md
  https://github.com/rspec/rspec-expectations
  http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax

There are a few reasons why this is advisable, main among which are:

  - consistency with pre-existing block-based `expect` syntax
  - lack of contamination of global object space
  - robustness, even in the face of extreme edge cases (BasicObject,
    proxies etc)

As `should` will eventually go away, let's get this right from the start
while the Twigg spec suite is still young.

Change-Id: Iab7e8af035afe5501740439a95dfdd1e6a6277f3
Reviewed-on: https://gerrit.causes.com/25828
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Teach Repo to respect .mailmap

Ideally I'd be able to pass `--use-mailmap` to our log command and
everything would continue to function as normal, but alas,
`--format=raw` trumps that, leading it to have no effect.

So, we use a custom "format" instead. This lead me to rewrite the
parser, seeing as I could control the output to return exactly what I
needed and nothing else.

While at it, I decided to make it use an enumerator so as to avoid
reading the entire Git output into memory at once. This makes the code a
little more complicated, because it has us passing blocks around, but on
the bright side it should be faster and the parser code itself is
arguably cleaner and easier to read now.

That's the theory, anyway. The practice reveals the approach to be about
half as fast. Presumably this is because there is overhead in managing
the enumerator (perhaps it does something stupid behind the scenes like
array-ifying the input before beginning enumeration) and the all-at-once
approach benefits from being able to compile the regex up front and then
power through the input.

I'll leave this commit as-is for posterity, but I'm going to go back in
presently and make things fast again (hopefully) by replacing the
enumerator.

Change-Id: I9a1b79982dd6a9a2f36546324a6d4e0bc15ba1af
Reviewed-on: https://gerrit.causes.com/25829
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Go back to reading entire input in one fell swoop

As mentioned in the previous commit, switching to a "lazy" enumerator
based approach actually made things slower:

  scanner (3 sample runs of 3,000 days of history across 113 repos):
  63 secs
  65 secs
  62 secs

  enumerator
  113 secs
  119 secs

This commit goes back to reading the entire file at once. We're still
using an enumerator, but we're no longer passing blocks around:

  enumerator, but reading entire file at once
  63 secs
  60 secs

This is marginally faster than what we had before, but the difference is
small enough to be classified as noise.

Change-Id: I38ef8a1fc2af7c306174b6a25413e92b7db10a78
Reviewed-on: https://gerrit.causes.com/25830
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Handle -c/--config option application better

Instead of waiting until the `.run` method is called, we can do better,
and ensure that the -c/--config option is applied before any other, by
doing it in the top of the `#initialize` method. Note that this also
cleans up some sloppiness, where we could potentially consume the option
from `ARGV`, but not from the `args` array, depending on the order of
evaluation.

It still isn't the prettiest code ever, but it is at least in a better
place now.

Change-Id: I51918b3d801e7c17eba9a9f5863fa5afbdbef659
Reviewed-on: https://gerrit.causes.com/25831
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Remove extraneous single quotes from log output

These quotes were actually making it into the Commit objects, because
there is no intervening shell when we run this stuff under IO.popen.

Change-Id: I8c217b73f7c3db19c79e621710186fb6f1449e14
Reviewed-on: https://gerrit.causes.com/25832
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Teach new parser to handle --allow-empty + --allow-empty-message

Just as we did in the old parser, make sure we can handle the (rare)
combination of --allow-empty and --allow-empty-message.

Change-Id: If3022d031842cdeb4c5ec7db0ca04893f912afff
Reviewed-on: https://gerrit.causes.com/25833
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>