Improve error handling on /createreview

Input of invalid remotes or remote refs should produce error dialogs
describing the problem to the user, not be treated as an "unexpected
error" and reported only to the system administrator.
Avoid generating emails about failure to deliver emails

By default, all warnings or errors logged by a background service is
delivered by email to the system administrator(s).  This included errors
logged by the mail delivery service.  But errors logged by it are
typically about inability to deliver email in the first place, so it
makes little sense to send further emails about it.

What's worse, attempting to send emails about mail delivery problems can
lead to exponential amounts of emails being generated as long as mail
delivery is broken.

With these changes, a single email is sent to the system administrator(s)
after an (unrelated) email has been successfully delivered, if any errors
or warnings have been logged, urging the system administrator(s) to check
the logs.  This email is also delivered directly rather than going
through the normal outbox mechanism, thus avoiding treating this as any
other email that in turn can trigger normal error handling.
Include CPU time per background service on /services
Preserve file mode information in reduced merge changeset

Reduced/filtered merge changesets copy files from the full diff between
parent and merge commit, with a filtered list of chunks.  The file mode
information was lost in this copying, which is not an advantage to begin
with, and is really bad for sub-module changes, since the fact that it is
a sub-module change is indicated only by the file mode.  Rendering a
change in a sub-module (git link) as a change in a regular file fails,
since the SHA-1 of the tree entry typically isn't present in the
repository (since it's the SHA-1 of a commit in another repository.)
Improve error handling when creating review

If the review branch is impossible because it's on the form "<base>/<rest>"
and "<base>" already exists as a ref (IOW as a file), give the user a
meaningful error message.
Add limit to number of commits on branch when creating review

If a user requests to create a review containing all commits on a branch,
check that the branch doesn't contain too many commits (default 2000.)
If it does, refuse to do anything.  (It's relatively easy to accidentally
trigger a load of /createreview with branch=master, which might contain
thousands of commits.)
Handle unexpected transaction rollbacks better

Once in a while, two transactions will deadlock, and one of them will
roll back (fail to commit.)  Handle this error in a slightly more user-
friendly fashion by telling the user what went wrong and suggesting he
try again.

Retrying again automatically (once) would be another option, obviously,
but some more work.  This will do for now.
Handle invalid review IDs better
Improve support for rebasing tracking review branches

In particular, when re-enabling the tracking, allow the name of the
tracked branch to be changed.
Fix crash when detecting moved code on some diffs

In particular squashed diffs where one or more files are changed by the
squashed commits but have no changes in the result diffs.
Remove broken /showfile link for deleted files

The /showfile link from diffs always link to the new version of the file.
If the file was deleted, there is no new version, and the link is broken.
It would be meaningful to link to the old version of the file instead in
this case, but as a workaround until that's fixed, don't link at all.
Rewrite how preferences are installed and updated

Drop the maintenance/installpreferences.py script, and store the
preference data in as JSON in installation/data/preferences.json.

Heavily modify prefs.py to read this file both during installation and
upgrading and use the information to update the 'preferences' table.
During upgrade, changes to preferences.json (added / removed / modified
preferences) trigger updates of the database, possibly after asking the
user whether the update is desired (typically when default values are
modified, and have also been modified in the database.)

Also a slight change in config.py to allow "later" installation modules
(such as prefs.py) to import modules that depend on the 'configuration'
module, primarily 'dbutils'.
Add possibility to opt out of review emails by default

If a user enables the preference 'review.defaultOptOut' then the user
automatically opts out of review emails (after the "New review" email)
in any review that isn't opt-in.

This is considered a short-term quick-fix solution; long term this
should be an option per filter rather than per user, but that requires
a larger set of changes.
Support for user configurable timezone

Let users configure which timezone they want various timestamps presented
in.

Not all timestamps everywhere are adjusted yet.
Improve error handling when failing to create review branch

Simply echo Git's error message back to the user; it's typically short
and understandable enough.
Close database connection earlier when finishing requests

For requests that return their response as a single fragment, close the
database connection before yielding that fragment.  For requests that
return their response as multiple fragments, roll back the database
transaction before yielding each fragment; to avoid leaving the database
connection idle in transaction, possibly with tables locked.

As a (necessary) side-effect of this, stop rendering /statistics page
incrementally.  The statistics page creates some temporary tables and
uses them later, and thus depends on rendering within a single database
transaction.  It's really fast enough to render in a single go anyway,
especially given its entirely non-critical nature.

Also make sure to only run registered "atexit" callbacks once.  If a
session was closed more than once, "atexit" callbacks would run each
time.
Support user absence without end date
Support "automatic" rebase of reviews tracking remote branches

The user inputs the name of a new, rebased branch in the same remote as
the currently tracked branch.  Alternatively, if the customization
module customization.branches has a functions getRebasedBranchPattern()
and isRebasedBranchCandidate(), the remote can be scanned for likely
rebased branches based on some branch naming scheme, if there is one.

The rebased remote branch is fetched, its status as a rebased version of
the branch is checked, indicating whether there seem to be conflicts or
unexpected changes on it compared to the current review branch.  If all
looks well, the rebase can be performed (without the need to run any git
commands) and the review is set to track the new branch in the remote
instead.
Fix generation of error message when updating tags
Keep fewer 'git cat-file --batch' processes alive

The branch tracker will have long-lived gitutils.Repository objects for
every repository that has tracking branches.  Those repository objects
would have equally long-lived 'git cat-file --batch' processes.

So stop all those processes whenever the branch tracker sleeps waiting
for something to do.  Also commit the database transaction at that point
to avoid leaving it idle in transaction (potentially with tables locked.)