Add support for per-LocalSite SSH keys to all SCMTools that support SSH
Review Request #2331 — Created May 1, 2011 and submitted
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.