svn: OPTIONS of ‘‘: SSL handshake failed: SSL error: A TLS warning alert has been received. ()

If your svn client suddenly starts complaining about something similar to

svn: OPTIONS of '...': SSL handshake failed: SSL error: A TLS warning alert has been received. (...)

The reason might be that the host in the URL (https://example.com/ => example.com) doesn’t match the ServerName setting in the SSL host for your web server. You might not have configured this, so for Apache add:

ServerName example.com

.. and restart the server. It might just work again!

svn: Can’t convert string from native encoding to ‘UTF-8’

The error “svn: Can’t convert string from native encoding to ‘UTF-8′” suddenly made it impossible to update one of the projects on our staging servers. The project contains loads of file under SVN control, and several data directories which up to this time wasn’t svn:ignore’d. One of the files in one of these directories had norwegian letters in ISO-8859-1 in its filename (which didn’t work in the project anyhow, as it was something left around from earlier).

This single file borked svn from actually being able to update or do anything useful with the actual files under SVN control. When Subversion analyzed the directory structure to check which files it should attempt to update, it would just barf before seeing any files with the error message about the file name not being in UTF-8. You’d think it would be better to ignore errors for filenames that aren’t a part of svn and that you’re not trying to add, but there’s probably a good reason for this behaviour.

Anyways: The solution: delete the file. We didn’t use it anyway. There’s also a good chapter in the SVN Book about localization issues which contain information about how you can solve the issue by changing your active character set.

Adding SVN Revision to a Configuration File

After a while you realize that the best way to serve almost-never-changing content is to give the content an expire date way ahead in the future. The allows your server and your network pipes to do more sensible stuff than delivering the same old versions of files again and again and again and again.

A problem does however surface when you want to update the files and make the visiting user request the new version instead of the old. The trick here is to change the URL for the resource, so that the browser requests the new file. You can do this by appending a version number to the file and either rewriting it behind the scenes to the original file, or by appending a timestamp (or some other item) to the URL as a GET value. The web server ignores this for regular files, but as it identifies a new unique resource, the web browser has to request it again and use the new and improved ™ file.

Using the timestamp of the file is a bit cumbersome and requires you to hit the disk one additional time each time you’re going to show an URL to one of the almost-static resources, but luckily we already have an identifier describing which version the file is in: the SVN revision number (.. if you use subversion, that is). You could use the SVN revision for each file by itself, but we usually decide that the global version number for SVN is good enough. This means that each time you update the live code base through svn up or something like that (remember to block .svn directories and their files if you run your production directory from a SVN branch. This can be discussed over and over, but I’m growing more and more fond of actually doing just that..). To avoid having to call svnversion each time, it’s useful to be able to insert the current revision number into the configuration file for the application (or a header file / bootstrap file).

Here’s an example of how you can insert the current SVN revision into a config file for a PHP application.

  1. Create a backup of the current configuration file.
  2. Update the current revision through svn up.
  3. Retrieve the current revision number from svnversion.
  4. Insert the revision number using sed into a temporary copy of the configuration file.
  5. Move the new configuration file into place as the current configuration file.
  6. Party like it’s 1999!

This assumes that you use an array named $config in your configuration file. I suggest that you name it something else, but for simplicity I’m going with that here. First, create a $config[‘svn’] entry in your config file. If you have some other naming scheme, you’re going to have to change the relevant parts below.

#!/bin/bash
cp ./config/config.php ./config/config.backup.php
svn up
VERSION=`svnversion .`
echo $VERSION
sed "s/config\['svn'\] = '[0-9M]*';/config\['svn'\] = '$VERSION';/" < ./config/config.php > ./config/config.fixed.php
mv ./config/config.fixed.php ./config/config.php

Save this into a file named upgrade.sh, make it executable by doing chmod u+x upgrade.sh and run it by typing ./upgrade.sh.

And this is where you put your hands above your head and wave them about. When you’re done with that, you can refer to your current SVN revision using $config[‘svn’] in your PHP application (preferrably in your template or where you build the URLs to your static resources). Simply append ?v=$config[‘svn’] to your current filenames. When you have a new version available, run ./upgrade.sh (or whatever name you gave the script) again and let your users enjoy the new experience.

Replacing / Moving a Branch to Trunk in Subversion (SVN)

After developing a feature branch for Way Too Long, we finally reached our milestone a couple of weeks ago. In the meantime a few patches had been ported back to trunk, but most work had been done in the branch. The easiest way to handle this dependency in Subversion seemed to be to simply switch trunk with the current feature branch, and so we did. It works something along the lines of:

  • svn del trunk
  • svn commit
  • svn mv branches/Name trunk
  • svn commit

A handly little recipe can be found at BigSmoke: Replacing SVN trunk with branch. Enjoy!

Post-commit hook failed with error output: .. and nothing more.

While getting the trac-svn integration up and running in one of our repositories tonight, I stumbled across this issue. Most links I found on Google said to try to run the post-commit script by itself under the same user, which worked just fine. Checked that all my paths were absolute paths to avoid assuming any CWD, but still nothing. After trying to minimize the problem I discovered that even with a post-commit-script of just environmental assignments, things were still failing. This nabble archived thread did however give a very important hint by Ryan Schmidt (who obviously has solved the post-commit problems for every single developer out there, if I were to judge by the number of times his name comes up. Awesome work, Ryan.):

Your post-commit must also begin with a line like “#!/bin/sh” and have its executable bit set.

Wow. Homer Simpson “Doh!”-moment right there. No #!/bin/bash (or #!/bin/sh) ment that SVN weren’t able to run the script with the proper interpreter. When running it from the command line, bash were already running of course, so it just assumed that it was a bash script .. and it were right.

Thanks Ryan, saved me a couple of hours tonight.

Adding an External SVN Resource With Tortoise SVN

Most of my projects are usually checked out at several different computers and several different operating systems. For Windows, there is The One SVN Client Above All Else, namely TortoiseSVN. As Christer and I’ve been working on an unnamed project lately, we’ve built up a set of resources in regards to basic functionality (user registration, user verification, access management, etc). These resources have become a small framework for a basic site, so I’ve adopted the set of files for several other projects. When using the “Framework” in other codebases, I still want to keep the framework versioned against the original SVN repository, so that if Christer commits his Überkool Must Have Feature v2.5 to the framework, I get all the magic with a single svn up.

The magical way ofdoing this is using the svn:external property to tell svn that you depend on an external repository. The property is set on the parent directory, and contains the value Directory RepositoryURL; i.e:

Property Value
svn:externals Framework https://svn.example.com/Framework/trunk/Framework
OtherRepository https://svn.example.com/OtherRepository/trunk/

To set a property using TortoiseSVN, right click on the parent directory (i.e. libs or whatever you prefer to call your directory of common code), and select “TortoiseSVN” and “Properties”. Click “Add” and select svn:externals from the pulldown menu. In the value field you simply add Framework https://svn.example.com/Framework/trunk/Framework. Close the dialogs and select SVN Update when right clicking on your libs directory. This will create a directory named Framework in libs and check out the svn repository to the directory.

If you want several repositories as external dependencies in the same directory, add each repository on a new line.

Voilá!

UPDATE: Erik Hansen adds:
In order for Tortoise to “Update” your local copy with the external files, you first need to commit the property change to the REPO before it will do that.

UPDATE: Harry asked:

How do I provide other usernames and passwords for the other repositories? If my memory serves me right, as long as you’ve checked out the resource previously with TortoiseSVN, it will remember your username and password. I’d like an update for this, tho, as I’ve not been able to test it myself at the present time.

UPDATE: Chris added:
If you want several repositories checked out as external sources, add each repository on a new line under the same svn:externals property. Each directory can only have one externals entry, but the property may contain several repositories as long as they’re each put on a new line.