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/
Escape leading spaces and tabs in markdown processing.

When escaping plain text as markdown, we need to handle leading spaces (four or
more) and leading tabs, as these blocks are considered to be code samples. This
meant that some basic syntax highlighting would be applied (often erroneously),
and that URLs were not properly linked.

After experimenting for quite some time with escaping the first tab or space, I
gave up on that approach. Markdown renderers do not handle escaped spaces well.
The solution that I settled on was to replace the first space with a
non-breaking space entity (for leading spaces), and prepend the line with an
nbsp (for leading tabs). This renders correctly while still allowing us to
escape and unescape.

Testing done:
- Reproduced the bug (using `--description="$(git log -n 1 in `rbt post`) and
  saw that it indented the commit message without treating it as a code block.
- Used the API with `?force-text-type=plain` to verify unescaping of the nbsp
  entities.
- Ran unit tests.

Fixes bug 3503.

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