svn+ssh on windows

time to read 4 min | 707 words

How to create a svn server on windows is explained elsewhere, but there is a real problem when trying to do this over ssh.
Here is how you do it.
This nessage lies the foundation to how I did it.

You need a SSH Server such as OpenSSH for Windows.
Follow the installation instructions quickstart.txt file.

Make sure that you can connect using "ssh localhost"

Now comes the tough part, svn on ssh uses the following command to connect to your computer:
ssh svnserve -t

This works in case you are want to access you repository like svn+ssh://server/path/to/repos
But if you want a different path, or if your repository reside on a different drive than your SSH server, you are in a problem.
You can fix this by passing the -r arguement to svnserve, but you can't do that normally because svn calls to svnserve directly.

The solution to this problem is to have a wrapper around svnserve that calls to svnserve with the correct paramters. The problem is that on windows, batch of .cmd files aren't executed when the SSH server atempts to call svnserve (this is probably a because it attempt to CreateProcess, instead of using a command interepter). So, you need an executable file that will be a warpper.

I experimented with a lot of standard input / output redirections schemes but none of them worked correctly, and I didn't want to try to solve that.

What I did finally is using the system() call in C/C++ which does exactly what I want.
So I wrote a small wrapper exe that reads from a redirect.inf file that is located in the same directory as the exe, and then run the command in the file as well as any command line parameters that were passed to it.
You can download it here (source below).
My redirect.inf file contain the following line:

svnserve2 -r D:\path\to\repos

I renamed svnserve.exe to svnserve2.exe and renamed svnproxy.exe svnserve.exe, then put both the proxy and the redirect.inf file in Subverion\bin directory and that was it, I had secured access to my repository.


Note: The following code is neither elegant nor very robust, but it does the job.

#include <WINDOWS.H>
#include <FSTREAM>
#include <IOSTREAM>
#include <TCHAR.H>

using namespace std;
int _tmain(int argc, TCHAR * argv[])
{
 char str[2000];
 string full;
 fstream in;
 
 GetModuleFileName(0,str,2000);
 string filename(str);
 int s = filename.find_last_of('\\');
 filename = filename.substr(0,s);
 filename += "\\Redirect.inf";
 in.open(filename.c_str(),ios_base::in);
 if(!in.is_open())
 {
  cout<<"File not open"<ENDL<<FILENAME.C_STR()<<ENDL<<<"Error: "
<   return -1;
 }
 while(!in.eof())
 {
  in.getline(str,2000);
  full += str;
 }
 for(int
 i=1;i  {
  full += ' ';
  full += argv[i];
 }
 return system(full.c_str());
}