Fix singular/plural form in commit list

Avoid writing "1 hours" etc in the commit list.
Add Felix Ekblom to CONTRIBUTORS
Fix branch update race causing review breakage

In rare cases, two users pushing conflicting updates of a review branch
at the same time could trigger concurrent invocations of Critic's hook,
that could both accept the update, and add all of the added commits to
the review.  This then lead to a review with an invalid set of commits
(and a "invalid commit-set: multiple heads" crash when loading the review
front-page.)

Git would inevitably reject one of the updates, since the actual ref
updating is "safe" (the ref is locked, and then updated with a check that
it still has the same value as it did when the whole updating process
started.)

Fix this using "SELECT ... FOR UPDATE" when fetching each updated
branch's row from the database.  This row contains the 'head' value,
which we use to validate the update (IOW check that the old value from
Git matches what we think it should be.)  By locking the row, we force
the "second" call of Critic's hook to wait until the first call has
completed and has updated the branch's row with the new head value.

Or, rather, since the second call would then most likely reject the
update ("wrong old value") we might as well not wait (using "FOR UPDATE
NOWAIT") and instead fail immediately if the row is locked.  We can then
provide a more to-the-point error message (since "wrong old value"
typically indicates that the repository and the database are out-of-sync,
and produces a much more serious sounding error message.)
Add 'u' keyboard shortcut for going back to the review front-page

The shortcut works on all pages that have a global variable named
'review' and isn't a review front-page.
Add basic test for tracking reviews

Tests creation of a tracking review, and a straight-forward rebase of it,
and also tests disabling and enabling of the tracking, and checks that the
tracking (and its status) is correctly reflected on the review front-page.

To make disabling/enabling easier, have the /submitreview operation return
the tracked branch id when creating a tracking review.
Make temporary references truly temporary

Some operations create temporary references (refs/temporary/$SHA1 or
refs/commit/$SHA1 traditionally,) for instance to be able to fetch a
specific commit into a temporary cloned repository.  These temporary
references were never cleaned up, making them more permanent than
temporary in practice.

This commit introduces the utility function Repository.temporaryref()
with acts as a context manager and returns a temporary reference name
that is deleted when the context manager's __exit__() is called.  Code
that used to create "temporary" references is modified to use this
instead.

Also, the utility function Repository.fetchTemporaryFromRemote() is
adjusted to also act as a context manager that returns the fetched SHA-1,
and also makes sure to clean up the temporary reference name it creates
in the context manager's __exit__().

The /fetchremotebranch operation, which is the only current user of
Repository.fetchTemporaryFromRemote(), is adjusted to add a permanent
keepalive reference to the fetched commits instead.  In practice, the
operation returns SHA-1s back to web front-end clients, that will later
supply them as arguments to /submitreview, so the commits need to be
referenced at least semi-persistently.  We don't have semi-persistently,
so make it fully persistently instead.  (It's likely the commits will be
used to create a review, in which case they can never be GC:ed anyway.)

Also add a migration script that deletes all existing refs/temporary/
and refs/commit/ references in every repository.
Pack keepalive refs into a single ref

Before running the nightly maintenance GC on each repository, pack all
"loose" keepalive refs (refs/keepalive/$SHA1) into a single keepalive
ref (refs/keepalive-chain), and delete all the loose keepalive refs.
This is done to reduce the total number of refs in the repository,
which improves the performance of various operations on it, and also
reduces network traffic when pushing to the repository.

The single keepalive ref will always point to a chain of "manufactured"
merge commits, that point to the empty tree, and whose parents will be
another such merge commit (or a root commit) and the commit we wish to
keep alive.

Also add a migration script that converts all existing refs/replays/*
refs into refs/keepalive/* commits, so that they are then packed and
deleted by this packing mechanism too.
Fix /rebasetrackingreview output for rebases that introduce changes

Due to a typo/copy-paste-error the "Has unexpected changes!" status
would never be reported; that case would say "Clean." instead.  Also,
there would be no link to a diff displaying the changes.

The outcome of the rebase was not affected, but this might cause users
to not notice invalid rebases before-hand when they could have if the
system had helped them out a little more.
Run "late upgrade" tests whenever migration scripts are added/modified

Typically, the point of late upgrading is upgrading with some data in the
database or branches in the Git repository, and typically the only part
of upgrading that cares about such things are migration scripts.

And, when there are migration scripts, they almost always do care, so it
makes sense to always run the late upgrading tests then.
Rename refs/keepalive-chain to refs/internal/keepalive-chain

It turns out Git has the bug/feature/misbehavior that it includes
refs directly under refs/ in the set of fetched refs, but not the
objects referenced by them in the set of fetched objects, which
leads to fetch failing due to missing objects.

Putting the ref under an arbitrary sub-directory instead solves
the problem.

Calling the ref refs/keepalive/chain, which would have been the
logical name, makes listing all loose keepalive refs somewhat more
complicated (we'd need to ignore the */chain ref,) so we don't.
Use comma delimitation for most lines reviewed by self
Set title of statistics page
Add Andreas Tolfsen to CONTRIBUTORS
Drop unused hashlib import
Make sure installer and criticctl can run even without passlib installed

(i.e. for "--auth-mode host" installations on systems where python-passlib
package is not installed and the user selects not to install it when the
Critic installer asks)
Display absence and retired status of owners
Fix detection of extension resource content type

For extension resources (loaded via /extension-resource/$EXT/$NAME) we
detect the content type simply by looking at the filename extensions
and the list of mappings in configuration.mimetypes.MIMETYPES.  (This is
in itself not perfect; there should be some way for the extension to
declare the content types of its resources itself.)

The old code used "everything after the first period" in the full
file-system path of the resource as its extension, used to look up the
content type.  This is obviously broken, and for instance breaks down
completely if the user hosting the extension has a period in his/her
user name, or if the extension's name contains a period.

The new code looks only at the resource's basename, and also tries to
look up every possible extension, longest first.  For example, given the
resource name "a.b.c.d" it will look up "b.c.d" first, then "c.d", and
finally "d".
Add background service synchronization mechanism for testing

To avoid code that waits some arbitrary amount of time for background
services to do asynchronous work (e.g. maildelivery delivering pending
mail or branchtracker updating a branch) and thus risks test flakes
due to timing issues, add a mechanism using which tests can wait for
a given background service to return to an idle state.

The mechanism is fairly simple: create a file named <pidfile_path>.busy,
send SIGUSR1 to the service process, and then wait for the .busy file to
be deleted.

Alternatively, SIGUSR2 can be sent to force the service to also run its
maintenance tasks before reporting that it's idle.  This is not currently
used, but will be useful for testing specific maintenance tasks.
Check background service logs for errors when testing

After each test, check and report any errors (or warnings) written to
any background service's log.
Common up calls to index.processCommits()

The processCommits() function inserts a commit and all its ancestors into
the 'commits' table in the database, if they aren't already there.  It
needs to be called before running any code that expects to be able to
access commits as gitutils.Commit objects.

It was previously both from src/background/githook.py and from various
functions in src/index.py (e.g. createBranch() and updateBranch().)  Now
it's simply called on all new SHA-1s that the commit hook receives as
input.  This is effectively what it did before as well, of course, but
with less code.

Also, since processCommits() can raise IndexException, and the handler
for that exception uses the 'info' local which is first assigned after
some of the calls to processCommits(), the exception handler would
sometimes crash, and not emit a proper error message.  This problem is
addressed by this fix.