Guess a file attachment's content type if application/octet-stream.

If a browser claims a file's content type is application/octet-stream,
get a second opinion by asking `file --mime-type`. This helps with some
browsers or server setups where that useless mimetype is being used,
preventing some files from being reviewable.

Fixes bug #2269
Reviewed at https://reviews.reviewboard.org/r/6016/
Don't trust the browser-provided mimetype if it looks bogus.

A user was reporting that their PDF file uploads were being assigned the
mimetype of "text/text/application/pdf", which is completely bogus. If
splitting on '/' produces anything other than a list of two strings, don't
allow it to proceed.

Testing done: Ran unit tests.

Fixes bug 3427.

Reviewed at https://reviews.reviewboard.org/r/6118/
Make SVN keyword handling case-insensitive.

Our existing handling for SVN keywords only works when the keywords had very
specific casing. This change fixes it to lower-case everything first, and does
a case-insensitive regex substitution.

Testing done:
Tested with several diffs that used svn:keywords with various casing.

Reviewed at https://reviews.reviewboard.org/r/6199/
Merge branch 'release-1.7.x' into release-2.0.x
Finish the merge.
Fix unicode problems when processing errors from SVN.

When processing any errors that come out of the pysvn client, we would cast the
exception to unicode without specifying an encoding. This resulted in any utf-8
filenames or other text triggering a UnicodeDecodeError. I've changed this to
first coerce the exception to bytes, and then decode. While I was in here, I
also fixed up a duplicate cast.

Testing done:
Ran unit tests (this error handler is exercised in the tests).

Fixes bug 3518.

Reviewed at https://reviews.reviewboard.org/r/6196/
Fix compatibility with Python < 2.7

My change for handling alternate casing in svn:keywords only worked with Python
2.7 (prior versions don't have a `flags` argument to `re.sub()`).

This change makes it so we compile the regex first using re.IGNORECASE, and
then call the substitution method on the regex object.

Testing done: Ran tests under python 2.6

Reviewed at https://reviews.reviewboard.org/r/6207/
Merge branch 'release-1.7.x' into release-2.0.x
Don't cache commits as aggressively if 'branch' and 'start' aren't provided.

The code for getting the list of commits would cache for one day, but we only
want to do that if the branch and start commit are explicitly specified. If
not, we should still cache but for a much shorter period (to avoid the list
being up to one day out of date). This change fixes that.

Testing done:
- Tested svn post-commit list.
- Ran unit tests.

Fixes bug 3511.

Reviewed at https://reviews.reviewboard.org/r/6201/
Fixed subvertpy "Assertion `svn_uri_is_canonical(child_uri, ((void *)0))' failed"

There is an error in `list` function of subvertpy `Client` when `path`
parameter ends with trailing slash. This error also displays when running tests.

python: /build/buildd/subversion-1.8.8/subversion/libsvn_subr/dirent_uri.c:1499: uri_skip_ancestor: Assertion `svn_uri_is_canonical(child_uri, ((void *)0))' failed.

This change strips the trailing slash, fixing the error.

Testing Done: Ran unit tests.

Reviewed at https://reviews.reviewboard.org/r/6215/
Fix posting changes with an empty commit ID.

Posting with an empty commit ID (a blank string) resulted in the blank
string being set for the review request or draft. This resulted in
conflicts, since a blank string is considered a valid value for unique
constraints. We now normalize it to None in this case.

Reviewed at https://reviews.reviewboard.org/r/6219/
Fix the file sizes and percentages shown for condensediffs.

When running condensediffs, the decoded diff content was being used for
the byte counts, rather than the stored base64 content. This gave an
inaccurate result for the total number of bytes and the bytes saved.

The percentage was also wrong, due to a bad calculation. Now it shows an
accurate savings as a percentage, and also shows up to 2 decimal places.

Reviewed at https://reviews.reviewboard.org/r/6208/