I have an old subversion repository that was set up as the only repo on a machine. We accessed the URLs like this:
http://myserver.com/svn/trunk/...
http://myserver.com/svn/branches/...
We're moving to a new server where we have several repositories set up under a dav-svn installation under apache2, so by default we access them like this:
http://myserver.com/svn/repo/trunk/
http://myserver.com/svn/repo/branches/
or
http://192.168.0.1/svn/repo/trunk/
http://192.168.0.1/svn/repo/branches/
I need to move the old repo to the new machine without changing the URLs, so I want to set up a repo and then have apache redirect it depending on the url, so:
http://myserver.com/svn/trunk
redirects to
http://myserver.com/svn/repo/trunk
transparently. I can get it to redirect to the IP-based URL, but when I try to get it to redirect using the domain name itself, it gives me forbidden messages or "Could not open the requested SVN filesystem":
<VirtualHost *:80>
ServerName myserver.com
ServerAlias www.myserver.com
DocumentRoot /var/www/vhosts/myserver.com/html
CustomLog /var/www/vhosts/myserver.com/logs/access_log combined
ErrorLog /var/www/vhosts/myserver.com/logs/error_log
RewriteEngine On
RewriteRule ^/svn(.*)$ /svn/myrepo$1 [L,QSA]
# THE FOLLOWING WORKS, BUT IS NOT TRANSPARENT
# RewriteRule ^/svn(.*)$ http://192.168.0.1/svn/myrepo$1 [L,QSA]
<Directory /var/www/vhosts/myserver.com/html>
AllowOverride All
</Directory>
</VirtualHost>
And the subversion.conf file:
<Location /svn>
DAV svn
SVNParentPath /var/svn/repository
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /var/svn/repository/.htpasswd
Require valid-user
</Location>
Ideas on how to solve the problem?
Best Answer
Short answer: Use the
PT
flag on your RewriteRule.First, a little Apache backstory. When Apache receives a request, it goes though a process of mapping that request to the local storage. After that, Apache actually has two pieces of data on what you requested. The request url, and the file path. So a request for
/svn/blah
is translated into/var/www/vhosts/myserver.com/html/svn/blah
and that path is stored separately. mod_rewrite lets you tweak this behavior to route urls where you want.Now, the two RewriteRules you have there are implicitly doing different things.
The first one you have there is a rewrite. It takes a url like
/svn/blah
and instead of using the behavior above, it maps it as if you actually requested/svn/myrepo/blah
, so the resulting filepath would be/var/www/vhosts/myserver.com/html/svn/myrepo/blah
. However, and here's the sticking point, it does not modify the requested url. The request url is still/svn/blah
, apache just now thinks that file is to be found at.../svn/myrepo/blah
rather than.../svn/blah
.Why does this matter you ask? Because the subversion module doesn't use the filepath. It looks at the request url. So apache and mod_rewrite just wasted time doing all that, because mod_dav_svn just ignores it. What you need is for mod_rewrite to change the request url. And that's what
PT
does. It modifies both the request url and the file path, so later when it gets to mod_dav_svn, it will see the changed url.The second one is a redirect. Since the substitution starts with
http://
and apache doesn't have a virtualhost named192.168.0.1
, it assumes you actually meant to put anR
in your flags, since it can't translate that into a filepath. That is sending back a "Hey, it's over here" message to the subversion client, and it's making another request for it.Now, having said all that, you're never going to have more than one repository on there anyway with this setup unless you do something to force mod_rewrite to skip the urls of the other repositories. mod_rewrite will cheerfully change
/svn/bignewproject/blah
into/svn/myrepo/bignewproject/blah
for you every time. You could add a rule before the RewriteRule you have such as:That will cause it to skip the next rule. However, you're going to be updating it by hand from here on out. You might be able to pull off something automated with some RewriteCond magic, but it'll probably be tricky. I'm not really familiar with that, so someone else would have to help you out there.
If this is only used by a small group of people, then you might be better off skipping this rewriting stuff entirely and just update everyone's working copies.
svn switch --relocate
is meant specifically for situations where the repos is moved and you just want to update your working copy without checking it out again. I understand there are situations where this simply isn't feasible though.