Simplify `PairMatrix#pairs` by extracting a `#sparse_matrix` method

Get rid of some of the clutter form the `PairMatrix#pairs` method by
extracting a `#sparse_matrix` method. This makes the `#pairs` method
more readable, and, as a bonus, provides us with a space to document
what the sparse-matrix logic is doing.

Change-Id: Icfc72ee9e672496cc04031cf3683a3a68dd4c104
Reviewed-on: https://gerrit.causes.com/26182
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add some documentation to the PairMatrix class

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

This gives us a one-to-one mapping:

  lib/twigg/**/*        ->      spec/lib/twigg/**/*_spec.rb

Change-Id: I386cccdfa79fcc6c391d451ccfc306826e0fa799
Reviewed-on: https://gerrit.causes.com/26184
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add Factory Girl as a development dependency

I'll be using this shortly in the spec suite.

Change-Id: I6576647a9a467f6caeaf7b0bfe2b3b334e894ac8
Reviewed-on: https://gerrit.causes.com/26185
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add regression specs for PairMatrix class

This commit adds specs that test the commit-counting logic of the
PairMatrix class; the specific motivation here is to prevent a
regression of the bug fixed in commit 3be3791, where we were
double-counting solo commits.

As we don't need a real repo to exercise this code, we set up a Factory
Girl factory for producing Commit instances. For the time-being, we
provide those Commit instances with a phoney "Repo" fake (an OpenStruct
that implements the one method that the Commit class cares about,
`#name`).

Included are sequences for generating realistic-looking Commit objects,
including names (the result of some Google searching and some massaging
with awk, Ruby and Vim) and subjects (sampled from the Twigg repo
itself). We use unique sequences where possible/practical, and random
ones where it simply doesn't matter. We're not currently making much use
of this fanciness, but I did want the returned objects to look like real
commits.

Change-Id: Iaf38aacb05c81c57db19bb94342df9c446dd97a9
Reviewed-on: https://gerrit.causes.com/26186
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add spec coverage for other PairMatrix methods

With this commit we have some coverage of all methods in the PairMatrix
class.

Change-Id: I16388ae5c20c72d3e03965868d0297abeca71fdb
Reviewed-on: https://gerrit.causes.com/26187
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add Repo factory

This commit addresses the minor smell of using an OpenStruct instance to
stand in for a Repo when using the Commit factory. Now we have a real
repo instance, albeit one without any real commits in it.

Change-Id: Ieb1b23a3e9bb62a177228eb8b443c24564032d0e
Reviewed-on: https://gerrit.causes.com/26188
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Use `#pluralize` consistently

We won't often run into it, but lets make sure that we elegantly handle
the edge case of "1".

Change-Id: Ic9786470b2241865272904b74810e68b5be93078
Reviewed-on: https://gerrit.causes.com/26189
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add scaffolding for /gerrit path

This commit creates a space into which we will insert Gerrit stats (the
equivalent of the `twigg gerrit stats` command-line command. Here we add
a route and a template and a basic controller action. At the moment it
basically renders an empty page. I'll follow up shortly with a commit
(or two) that builds out the back-end and plugs it in to the front-end.

Note that this feature won't be enabled by default; you have to
explicitly turn it on. The reason is that most places that use Twigg
most likely won't be using Gerrit. We could also try to be smart and
assume that you want to use /gerrit if you have the twigg-gerrit gem
installed, but let's start dumb for now.

Change-Id: Ia5020d0ff9803c8983f97a606f8794edc26fe5cc
Reviewed-on: https://gerrit.causes.com/26190
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Move `#age` method into `Twigg::Util`

This never really belonged in the `Twigg::Command::Gerrit` class; it was
just there for expediency during the development of the `twigg gerrit
stats` subcommand.

As we're about to expose the Gerrit stats in the web app, we need to
scoop some of the functionality out of the command class and put it
where it will also be useful to the web app.

This commit is a first step in that direction.

Change-Id: Idcf1a44d746008ceca4225f5deb093437df00d0c
Reviewed-on: https://gerrit.causes.com/26191
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Move (most of) Gerrit database interaction into separate class

This commit moves the core database interaction out of the Gerrit
command class and into a dedicated DB class. This required some
rejigging of the `with_dependency` method to make it accessible from the
various places that we now need it.

A subsequent commit will move the remaining DB interactions into a
better location, in service of getting the Gerrit stats into the web
app.

Change-Id: I5e43d21c56e0e3729775a6115296e1794b37c556
Reviewed-on: https://gerrit.causes.com/26192
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Move remaining Gerrit DB interaction into new Change class

With this change we're now fairly well set up to get change stat
information into the web UI. The Gerrit Command subclass is now just
talking to an abstraction, and the web UI will be able to do the same.

Change-Id: Ibf4a811df5f4e913dfbeeac3bd4987a0aba251cb
Reviewed-on: https://gerrit.causes.com/26193
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Display open changes at /gerrit

This will work only in the development environment for now, because it
assumes the presence of the twigg-gerrit gem.

Some reorganizing will be required (in future commits) so that we can
use `#with_dependency` to bring in the gem and degrade with an
informative diagnostic message when it is not present.

Change-Id: I5e7fb57cae2d101bc8750f29b914602341d2ea13
Reviewed-on: https://gerrit.causes.com/26194
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Linkify to Gerrit change in /gerrit

Change-Id: I06e5bc84762ce864de120f99358b024d54542150
Reviewed-on: https://gerrit.causes.com/26195
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Move App server to App::Server

Having the App class serve simultaneously as the "namespace" for the
twigg-app gem and also the Sinatra::Base subclass that we use to run the
web app was making it difficult to use `#with_dependency` in the app.

Specifically, the App class was being loaded at gemspec-evaluation time
(in order to access the VERSION constant), which meant that we couldn't
use things like `#with_dependency` in any meaninfgul way (doing so would
occur before the gem itself had been fully loaded, creating a circular
dependency, because `#with_dependency` is defined in the twigg gem, and
the twigg gem depends on the twigg-app gem in development).

This commit makes the problem go away by cleaning out App so that it
serves only as a namespace, and moving the server code into a new class,
App::Server. Now everything is just dandy.

Change-Id: Ie5720a24dd84d6a5e54f7c67ea6dfd513ba2f889
Reviewed-on: https://gerrit.causes.com/26196
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add `#with_dependency` call to Twigg::App::Server

With this change, Twigg will warn you (or rather, explode loudly) if you
try to boot the server with Gerrit support turned on but without the
twigg-gerrit gem installed.

In order to get `#with_dependency` to work in this context we needed to
make the `Console.die` method public, so that it could be called from
anywhere. The alternative of having `#with_dependency` require the
Console methods to have been mixed in was deemed too subtle and flakey,
as was the thought of bundling `#with_dependency` into Console itself,
where it doesn't seem to belong.

Change-Id: Ieb6080c141a39977ca0d9cb8c981ea305b9b1a4a
Reviewed-on: https://gerrit.causes.com/26197
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Apply minor tweaks to Quips module

We don't need a fully qualified namespace to access the App root, so
trim it.

Likewise, we can use Array#sample to achieve the same effects, while
avoiding getting our hands dirty with the random numbers.

Change-Id: I8909540e85477118cf2042a74e2517bb41f42c42
Reviewed-on: https://gerrit.causes.com/26198
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Add Gerrit section to dashboard

Change-Id: I671d7df82d9987c6fcbcbe9192ef0ac004a1c46f
Reviewed-on: https://gerrit.causes.com/26199
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Move cumulative line-counting logic into CommitSet

This is best kept down in the "model" layer; it will make it easier for
us to show cumulative stats in the web UI without re-doing the work
already done for the command-line version.

Change-Id: I9a17a51cac5964d85ace504f4a1f14bd9d304b8e
Reviewed-on: https://gerrit.causes.com/26200
Reviewed-by: Greg Hurrell <greg@causes.com>
Tested-by: Greg Hurrell <greg@causes.com>
Rename "top_author_data" to just "author_data"

It's not just "top" authors; it's all authors.

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