Add support for per-LocalSite SSH keys to all SCMTools that support SSH

Review Request #2331 — Created May 1, 2011 and submitted

Review Board
This implements full per-LocalSite SSH key support for CVS, Git, Subversion, Bazaar and Mercurial.

CVS and Git are fairly straight-forward. We pass the local_site_name around and eventually call
SCMTool.popen, which will pass it on to rbssh nice and cleanly.

Mercurial is similar, but sets a config value for the session to invoke rbssh with the
--rb-local-site= parameter.

Subversion and Bazaar are way more complicated.

Subversion has a $SVN_SSH environment variable, but we can't rely upon it as it's global across
all instances, and setting it before a request is potentially risky. So what we do is check for
the existence of a ~/.subversion/<local_site_name>/ directory when initializing the SCMTool.
If it doesn't exist, we create it and populate a config file that builds a proper command to
rbssh, passing --rb-local-site=. If a repository's LocalSite ever changes, it'll just rebuild
the config in a new directory. It may mean manual cleanup of stale LocalSite directories, but
that's not a big problem and can be solved by a small cleanup script.

Bazaar has its own method for invoking SSH processes, which we already partially use to invoke
rbssh in the first place. You register a SSHVendor subclass with bzrlib, which again, we
already do. However, this cannot be done per-request, or per-session, or anything like that.
It's global, with no way through the API to funnel information. So what we do is augment
the URL in check_repository and get_file to add a '?rb-local-site-name='. We then override
the transport layer (which can have its own SSHVendor associated) by subclassing it
(RBRemoteSSHTransport), which parses the URL we're accessing, strips out the extra data,
and creates a new RBSSHVendor.

This also introduces unit tests for all these.
All unit tests pass! Did some hand tests too. Seems to work fine.
  2. reviewboard/scmtools/ (Diff revision 1)
    Can you assign None in an else: block?
  3. reviewboard/scmtools/ (Diff revision 1)
    Same comment as on your previous change with _ and the import above.
  4. reviewboard/scmtools/ (Diff revision 1)
    1. Already fixed locally. Forgot to update the review request.
Review request changed
  1. Ship It!