How to build Subversion on Debian GNU/Linux

Looks like a trivial question? Unfortunately, because of this bug standard “configure + make + sudo make install” approach doesn’t work.

The problem occurs because Subversion sources contain libsvn_XXX libraries in it. But if libsvn1 package is installed, it contains these libraries too, and they are confused. If libsvn1 package is not installed, compilation succeeds, but anyway the number of features supported depends on the currently installed libraries.

Fortunately, Subversion sources contain a script that downloads all necessary dependencies in Maven-like fashion and doesn’t touch local libraries (except openssl). The algorithm is:

1. Install packages necessary to run the script.

$ sudo aptitude install subversion gperf autoconf libssl-dev make gcc binutils libtool libxml2-dev

2. Download and run the script.

$ mkdir build
$ cd build
$ svn co
$ ln -s unix-build/Makefile.svn Makefile
$ make

If the script fails (e.g. because of absence of some utility or library) one can solve the problem and continue with just

$ make

The build result will be put to svn-trunk directory.

$ svn-trunk/subversion/svn/svn --version
svn, version 1.8.0-dev (under development)
   compiled Jun 16 2012, 21:01:03

Copyright (C) 2012 The Apache Software Foundation.
This software consists of contributions made by many people; see the NOTICE
file for more information.
Subversion is open source software, see

The following repository access (RA) modules are available:

* ra_svn : Module for accessing a repository using the svn network protocol.
  - with Cyrus SASL authentication
  - handles 'svn' scheme
* ra_local : Module for accessing a repository on local disk.
  - handles 'file' scheme
* ra_serf : Module for accessing a repository via WebDAV protocol using serf.
  - handles 'http' scheme
  - handles 'https' scheme

E200030: BUSY error explained

As I wrote in my previous post, Subversion 1.7 keeps all working copy metadata in .svn/wc.db SQLite database. I earlier working copy formats (versions <= 1.6) every subdirectory of a working copy could be considered independently. In particular, one could run 2 processes/threads which could modify different working copy subdirectories at the same time. With SVN 1.7 one cannot.

Every SVN 1.7 write operation (add, copy, mv, rm, …) locks .svn/wc.db database. When another process tries to obtain a write lock on the same .svn/wc.db at the same time, it fails with an error.

Let’s reproduce the problem to make things clear. First, install SQLite library and development packages.

$ sudo aptitude install libsqlite3-0 libsqlite3-dev

Let’s write a small program that would lock our database:

#include <sqlite3.h>
#include <stdio.h>

int main(int argc, char** argv) {
    sqlite3 *db;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <sqlite_database.db>\n", argv[0]);
        return 1;

    sqlite3_open_v2(argv[1], &db, SQLITE_OPEN_READWRITE, NULL);
    sqlite3_exec(db, "PRAGMA locking_mode = EXCLUSIVE;",
        NULL, NULL, NULL);
    sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
    sqlite3_exec(db, "DELETE FROM NODES;", NULL, NULL, NULL);

    while (1) {

    return 0;

Don’t worry, without “COMMIT” statement it won’t execute the query. But anyway I wouldn’t recommend you to run it on .svn/wc.db, that it important for you: every software contains a bug.

Let’s compile and try it:

$ gcc lock_sqlite.c -lsqlite3 -o lock_sqlite
$ ./lock_sqlite .svn/wc.db

While the program is running, our SQLite database is locked. Let’s try to modify .svn/wc.db with SVN. SVN says

$ svn add file
svn: E155004: Working copy '/tmp/test-co' locked
svn: E200033: sqlite: database is locked
svn: E200033: sqlite: database is locked
svn: run 'svn cleanup' to remove locks (type 'svn help cleanup' for details)

SVNKit is a pure Java SVN implementation (actually, there’re only 2 SVN implentations: native SVN and SVNKit). Nearly all Java programs that work with Subversion use SVNKit. Let’s try to modify .svn/wc.db with SVNKit:

$ jsvn add file
svn: E200030: BUSY

So if you use Java-based SVN client and see this message there’re 2 explanations:

  1. You have a backgroud process that tries to access your working copy at the same time.
  2. Your SVN client tries to access the working copy from several threads. Then it’s a bug, report it to the client developers.

Missing pristine files in SVN working copy

In SVN 1.7 working copy format all SVN-specific information is kept in .svn/wc.db database and pristine files in .svn/pristine directory.

$ ls -a
.  ..  anotherFile  file  .svn

$ find .svn

Pristine file is an analog of Git blob. SHA-1 of contents of any pristine file corresponds to its name. da39a3ee5e6b4b0d3255bfef95601890afd80709 corresponds to empty contents.

.svn/wc.db is an SQLite database that contains all SVN-specific metadata (path, URLs, properties and so on). The most interesting table is NODES. It contains entries for every path in the working copy (1 entry if the path is not changed, more than 1 otherwise).

$ sqlite3 .svn/wc.db
SQLite version 3.7.11 2012-03-20 11:35:50
Enter ".help" for instructions
Enter SQL statements terminated with a ";"

sqlite> .tables

sqlite> select local_relpath, revision, checksum from NODES;

As one can see there’re 3 entries: for working copy root (“”) and 2 for files in it. And contents is referenced by SHA-1 hash.

For some reasons SVN keeps references count for every SHA-1 checksum instead of calculation on-the-fly.

sqlite> select checksum, size, refcount, md5_checksum from PRISTINE;
$sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709|0|2|$md5 $d41d8cd98f00b204e9800998ecf8427e

Here in the example one checksum is referenced twice. When the refcount in PRISTINE table becomes 0, corresponding pristine files are not deleted automatically, but only after "svn cleanup" command.

Every software contains a bug. Sometime refcount becomes wrong. If it is greater than actual value, it is not a problem. But if less, it can lead to a problem.

One won’t notice the problem immediately, but the working copy becomes a time bomb. refcount value may reach zero but some entries can still reference to a pristine file by SHA-1 checksum. If one runs "svn cleanup" and the pristine file is deleted, there’re problems: one can’t commit the file referencing to missing pristine, one can’t revert it, one can’t get working copy diff and so on.

Let’s emulate the problem:

sqlite> update PRISTINE set refcount=0;

$ svn cleanup
svn: E155010: Pristine text 'da39a3ee5e6b4b0d3255bfef95601890afd80709' not present

$ find .svn/pristine/

Now our working copy is corrupted. It is locked (because "svn cleanup" failed) and consequent cleanups do not help.

$ echo text > file

$ svn diff
svn: E155010: Pristine text 'da39a3ee5e6b4b0d3255bfef95601890afd80709' not present

$ svn cleanup
svn: E155010: Pristine text 'da39a3ee5e6b4b0d3255bfef95601890afd80709' not present

$ svn status
  L     .
svn: E155010: Pristine text 'da39a3ee5e6b4b0d3255bfef95601890afd80709' not present

Despite the fact that the problem is not so hard to resolve (and I hope SVN will be able to repair this some day), currently I know only one tool that allows to restore missing pristine files — SmartSVN. Unfortunately it is not free. Fortunately it has 30 days free period, that’s enough to repair the working copy.

To repair our working copy select Modify | Validate Admin Area...


Repair pristine files with SmartSVN

Repair pristine files with SmartSVN

Lets check the result.

$ find .svn/pristine/

$ sqlite3 .svn/wc.db
SQLite version 3.7.11 2012-03-20 11:35:50
Enter ".help" for instructions
Enter SQL statements terminated with a ";"

sqlite> select * from PRISTINE;
$sha1$da39a3ee5e6b4b0d3255bfef95601890afd80709||0|2|$md5 $d41d8cd98f00b204e9800998ecf8427e

$ svn diff
Index: file
--- file        (revision 1)
+++ file        (working copy)
@@ -0,0 +1 @@

Our working copy is repaired and unlocked, local changes are untouched.