Introduction
VisualSVN Server is a basic package of Subversion with the Apache web server and a visual management console (MMC). The VisualSVN Server browser view is very basic, but it is easy to customise via the provided XSLT stylesheet. Just keep in mind that the files are auto generated and can be overwritten by the VisualSVN server management console. Always backup any files before editing them. There are two things that I think would be very handy when using the SVN browser view:
- A shortcut for TortoiseSVN checkout.
- While developers will most likely have an SVN client installed, the same can not always be said for project managers and document writersn and to explain the concepts of how the versioning works can be a pain. The solution to this is auto versioning and the ability to open repository directories with Windows Explorer (web folder).
Updates
Update (18 Oct 2008)
Problems when accessing WebDav (Web Distributed Authoring and Versioning) from Vista.
If you are experiencing problems accessing WebDav (Web Distributed Authoring and Versioning) from Vista, please try the following updates:
Update (22 Oct 2008)
After applying the above updates and rebooting, try to add a new "Network Place" to initialize the connection to the WebDAV folder.
Note (22 Oct 2008): The ability to open repository directories with Windows Explorer will not always work when displayed within a SharePoint IFrame WebPart.
Using the code
I will assume the default install location for VisualSVN Server as 'c:\Program Files\VisualSVN Server'. Add these two images to the 'htdocs' folder: and . In the 'htdocs' folder, you should find 'svnindex.xsl'. This is the stylesheet that renders the WebDAV XML in your browser. Open the file in your favourite text editor and find the '<xsl:template match="dir">...<xsl:template>
' section. Replace the following bit:
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="@href"/>
</xsl:attribute>
<img src="/dir.png"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>/</xsl:text>
</xsl:element>
with:
<table border="0" style="width:99%"><tr><td>
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="@href"/>
</xsl:attribute>
<img src="/dir.png"/>
<xsl:text> </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>/</xsl:text>
</xsl:element>
</td><td nowrap="nowrap" style="width:1%">
<xsl:element name="a">
<xsl:attribute name="href">
javascript:void(0);
</xsl:attribute>
<xsl:attribute name="onclick">
javascript:document.location.href='tsvn:'+document.location.href.substr(0,
document.location.href.lastIndexOf('/'))+
'/<xsl:value-of select="@href"/>';
</xsl:attribute>
<xsl:attribute name="title">
Checkout with TortoiseSVN
</xsl:attribute>
<img alt="Checkout with TortoiseSVN" src="/tsvn.png"/>
</xsl:element>
</td><td nowrap="nowrap" style="width:1%">
<xsl:element name="a">
<xsl:attribute name="href">
javascript:void(0);
</xsl:attribute>
<xsl:attribute name="onclick">
javascript:NavigateHttpFolderIfSupported(document.location.href.substr(0,
document.location.href.lastIndexOf('/'))+
'/<xsl:value-of select="@href"/>', '_blank');
</xsl:attribute>
<xsl:attribute name="title">
Open Folder with Windows Explorer
</xsl:attribute>
<img alt="Open Folder with Windows Explorer" src="/explorer.png"/>
</xsl:element>
</td></tr></table>
Add a new text file to the 'htdocs' folder, name it 'dav.js', and paste the following into it:
function BrowserIs ()
{
var agt=navigator.userAgent.toLowerCase();
this.osver=1.0;
if (agt)
{
var stOSVer=agt.substring(agt.indexOf("windows ")+11);
this.osver=parseFloat(stOSVer);
}
this.major=parseInt(navigator.appVersion);
this.nav=((agt.indexOf('mozilla')!=-1)&&
((agt.indexOf('spoofer')==-1) && (agt.indexOf('compatible')==-1)));
this.nav6=this.nav && (this.major==5);
this.nav6up=this.nav && (this.major >=5);
this.nav7up=false;
if (this.nav6up)
{
var navIdx=agt.indexOf("netscape/");
if (navIdx >=0 )
this.nav7up=parseInt(agt.substring(navIdx+9)) >=7;
}
this.ie=(agt.indexOf("msie")!=-1);
this.aol=this.ie && agt.indexOf(" aol ")!=-1;
if (this.ie)
{
var stIEVer=agt.substring(agt.indexOf("msie ")+5);
this.iever=parseInt(stIEVer);
this.verIEFull=parseFloat(stIEVer);
}
else
this.iever=0;
this.ie4up=this.ie && (this.major >=4);
this.ie5up=this.ie && (this.iever >=5);
this.ie55up=this.ie && (this.verIEFull >=5.5);
this.ie6up=this.ie && (this.iever >=6);
this.winnt=((agt.indexOf("winnt")!=-1)||(agt.indexOf("windows nt")!=-1));
this.win32=((this.major >=4) && (navigator.platform=="Win32")) ||
(agt.indexOf("win32")!=-1) || (agt.indexOf("32bit")!=-1);
this.mac=(agt.indexOf("mac")!=-1);
this.w3c=this.nav6up;
this.safari=(agt.indexOf("safari")!=-1);
this.safari125up=false;
if (this.safari && this.major >=5)
{
var navIdx=agt.indexOf("safari/");
if (navIdx >=0)
this.safari125up=parseInt(agt.substring(navIdx+7)) >=125;
}
}
var browseris=new BrowserIs();
var L_WebFoldersError_Text = "Your client does not support opening " +
"this list with Windows Explorer.";
var L_WebFoldersRequired_Text="Please wait while Explorer View is loaded. " +
"If Explorer View does not appear, your browser may not support it.";
function SupportsNavigateHttpFolder()
{
return (browseris.ie5up && browseris.win32);
}
var httpFolderTarget=null;
var httpFolderSource=null;
var httpFolderDiv=null;
function NavigateHttpFolderCore()
{
if (httpFolderDiv==null)
{
httpFolderDiv=document.createElement('DIV');
document.body.appendChild(httpFolderDiv);
httpFolderDiv.onreadystatechange=NavigateHttpFolderCore;
httpFolderDiv.addBehavior('#default#httpFolder');
}
if (httpFolderDiv.readyState=="complete")
{
httpFolderDiv.onreadystatechange=null;
try
{
var targetFrame=document.frames.item(httpFolderTarget);
if (targetFrame !=null)
{
targetFrame.document.body.innerText=L_WebFoldersRequired_Text;
}
}
catch (e) {}
var isOk=false;
try
{
var ret="";
ret=httpFolderDiv.navigateFrame(httpFolderSource,
httpFolderTarget);
if (ret=="OK")
isOk=true;
}
catch (e) { }
if (!isOk &&
0==httpFolderSource.search("http://[a-zA-Z0-9\-\.]+(:80)?/"))
{
var sUrl=httpFolderSource
.replace(/http:\/\/([a-zA-Z0-9\-\.]+)(:80)?[\/]/, "//$1/")
.replace(/[\/]/g, "\\");
var targetFrame=document.frames.item(httpFolderTarget);
if (targetFrame !=null)
{
try
{
targetFrame.onload=null;
targetFrame.document.location.href=sUrl;
isOk=true;
}
catch (e) { }
}
}
if (!isOk)
{
alert(L_WebFoldersError_Text);
}
}
}
function NavigateHttpFolder(urlSrc, frameTarget)
{
if ('/'==urlSrc.charAt(0))
{
urlSrc=document.location.protocol+"//"+document.location.host+urlSrc;
}
httpFolderSource=urlSrc;
httpFolderTarget=frameTarget;
NavigateHttpFolderCore();
}
function NavigateHttpFolderIfSupported(urlSrc, frameTarget)
{
if (SupportsNavigateHttpFolder())
{
NavigateHttpFolder(urlSrc, frameTarget);
}
else
{
alert(L_WebFoldersError_Text);
window.history.back();
}
}
When refreshing the browser now, you'll have the following:
Notice the new icons on the right of the folders. When the tortoise image is clicked, the TortoiseSVN checkout window should appear with the repository URL filled in:
If you are using Internet Explorer, the repository window will open with Windows Explorer when the explore image is clicked:
To enable auto versioning, we need to make a change to the Apache config file 'conf\httpd.conf'. Look for the 'SVNParentPath
' attribute in the '<Location /svn/>
' section, and just under it, add 'SVNAutoversioning on'. Restart the VisualSVN Server for the configuration change to take effect. Of course, this is now only the beginning. You can change the skin by editing 'htdocs\svnindex.css' and add your company logo etc.
History
- 28 June 2008
- 14 July 2008
- Updated links to JS files and images in svnindex.xsl.
- 18/22 October 2008
- Added some connection troubleshooting info.