[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

libsvn_wc bug: pristine contents for locally replaced file

From: Neels J Hofmeyr <neels_at_elego.de>
Date: Sat, 16 Jan 2010 23:48:38 +0100


is there a good reason why a local replace has to get rid of the pristine
base file? Because, if the file was kept, the problems described below would
be resolved.

I stumbled over an error using 'svn cat <wc_path>' on a locally replaced
file. (Not a common use case, but read on.) 'svn cat <wc_path>' appears to
want to output the pristine base content (which is not documented).

But when a file is locally replaced (not committed), it currently has no
pristine base file, apparently;
 'svn cat wc/locally_replaced_file'
which errors with:

$ svn cat file
subversion/svn/cat-cmd.c:81: (apr_err=2)
subversion/svn/util.c:960: (apr_err=2)
subversion/libsvn_client/cat.c:88: (apr_err=2)
subversion/libsvn_client/cat.c:88: (apr_err=2)
subversion/libsvn_subr/stream.c:774: (apr_err=2)
subversion/libsvn_subr/stream.c:774: (apr_err=2)
subversion/libsvn_subr/io.c:2711: (apr_err=2)
svn: Can't open file '/tmp/wc/.svn/text-base/file.svn-base': No such file or
(reproduction script attached)

'svn cat' is just an example of how to hit this. This same function is used
in many other places. A quick impact grep study suggests at least export,
copy, update, diff, and probably others.
(Todo: investigation on whether current callers can hit a locally replaced
file and whether they work around it.)

I guess svn_wc__get_pristine_contents() wants to return the contents of the
file that were committed in revision <BASE>. But the implementation expects
a file to exist which isn't there:

svn_error_t *
svn_wc__get_pristine_contents(svn_stream_t **contents,
                              svn_wc__db_t *db,
                              const char *local_abspath,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool)
  const char *text_base;

  SVN_ERR(svn_wc__text_base_path(&text_base, db, local_abspath, FALSE,

  if (text_base == NULL)
      *contents = NULL;
      return SVN_NO_ERROR;

  return svn_stream_open_readonly(contents, text_base, result_pool,
  // ^^^^^ hits error here, file *text_base does not exist.

I see two ill things:

(1) Looking at the function's intention, it should return an empty stream if
there is no base file. But svn_wc__text_base_path() returns a path that
doesn't exist.

(2) When the file is locally replaced, it theoretically *does* have a
pristine base, i.e. the file's content committed at revision <BASE>. The
function fails to return that content.

So, back to the question: is there a good reason why a local delete followed
by a local add has to get rid of the pristine base file?



## 1. Adjust your PATH to point at your custom installed location:
## export PATH="$HOME/prefix/svn-trunk/bin:$PATH"
## OR
## 2. Uncomment the four lines below to use aliases into your
## built source tree. The next line is the only line you should
## need to adjust.
#alias svn=${SVNDIR}/subversion/svn/svn
#alias svnserve=${SVNDIR}/subversion/svnserve/svnserve
#alias svnadmin=${SVNDIR}/subversion/svnadmin/svnadmin

svn --version
rm -rf repos wc
svnadmin create repos

svn co -q ${URL} wc

set -x
cd wc


# make a file that is locally replaced...
echo content > file
svn add file
svn ci -mm

svn rm file
echo "new content" > file
svn add file

# ...and 'svn cat' that file.
svn st
svn cat file

Received on 2010-01-16 23:51:10 CET

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.