The fundamental problem is that RA->do_switch() is anemic. It doesn't
work on a single file, because dir_delta() can't do a single file
switch either: dir_delta wants to delete the old basename and re-add
the new basename, not simply switch the contents.
Thus svn_client_switch() has a hacky workaround at the moment. If
switching a directory, run RA->do_switch(). If switching a file, call
RA->get_file() and manually install the new contents.
The other user of RA->do_switch(), namely the codepath for "svn
diff/merge URL1 URL2", doesn't have this hacky workaround. Instead,
it's attempting to switch to a fileURL, and we have semi-confusing
code in mod_dav_svn/update.c to detect this case and send back a
reasonable update report.
The correct long-term solution is to make dir_delta() comfortable with
single-file switches. Cmpilato sez:
Make svn_repos_dir_delta() understand how to handle switches. How?
Well, first, consider what switch wants. Switch wants to be told
how to make PATH_A look exactly like PATH_B while still being named
PATH_A. So an option to PRESERVE_BASENAME would be nice, and would
work in such a way that svn_repos_dir_delta would, if tempted to
delete()+add() a top-level thing, would be sure to re-add the thing
using SRC's basename (as opposed to DST's basename, which is the
usual case), and *then* recursively deltify.
I'm pretty sure this means that instead of just having a source path
and a target path (for the internal support functions used by
svn_repos_dir_delta), we would also need an `edit_path' that looks
just like the target path, but has source-path's basename.
Once dir_delta() can do this, then we don't any more special cases in
mod_dav_svn, or in svn_client_switch either. It *also* means that
RA->do_switch() will be able to change dirs into files, or files into
dirs, just like RA->do_update() does. This is a hole gstein pointed
out a while ago.