Keeping a part of a Subversion repository, but there is a path change in the middle

I have a Subversion repository where a directory was moved once. I want to send to someone only a part of the repository, which includes this directory.

I believe I have read and understood the manual.

What I tried:

svnadmin dump /home/Subversion-Repository | \
   svndumpfilter include new-name /new-name /foo/bar/old-name > something.svn

svnadmin create /new/repos
# Create directories foo/bar and new-name
svnadmin load /new/repos < something.svn

But it fails:

<<< Started new transaction, based on original revision 5944
svnadmin: File not found: transaction '5944-4l4', path 'new-name/myfile'
     * editing path : new-name/myfile ...

What surprises me is that, in the full dump (without going through svndumpfilter), there is a revision which adds the files at the new place:

Node-path: new-name
Node-kind: dir
Node-action: add
Prop-content-length: 10
Content-length: 10

but svndumpfilter does not keep it. So, the first revision mentioning a file under new-name is 'Node-action: change' and not 'Node-action: add' and it fails. Why?

An Unix shell script to reproduce the problem at will is available.

[I asked the question on the Subversion mailing list but the message was not distributed, probably eaten by an overzealous spam filter.]

UPDATE: I tested Insyte's suggestion. Both svndumpfilter2 and svndumpfilter3 fail. Both do not even check the argument, you can give them a non-existing repository, they would not complain.

With svndumpfilter2, modifying my script to use ${SVNDUMPFILTER2} ${REPOS} other/new-name/bar foo/old-name/bar > ${DUMP}:

<<< Started new transaction, based on original revision 7
svnadmin: File not found: transaction '8-8', path 'other/new-name/bar/myfile'
     * editing path : other/new-name/bar/myfile ...

With svndumpfilter3, modifying my script to use ${SVNDUMPFILTER3} --untangle=${REPOS} other/new-name/bar foo/old-name/bar > ${DUMP}:

<<< Started new transaction, based on original revision 7
svnadmin: File not found: transaction '8-8', path '/other/new-name/bar/myfile'
     * editing path : other/new-name/bar/myfile ...

Solution 1:

I believe you're encountering a variant of the svndumpfilter: Invalid copy source path problem. This problem occurs when one of the directories/files included by svndumpfilter originally was copied (or, in your case, moved) from a section of the tree that is not being included. The original solution to this was Simon Tatham's svndumpfilter2 but his svn server seems to be down at the moment.

A slightly modified version is available here: http://www.dehora.net/hg/tools/raw-file/tip/svn/svndumpfilter2

Another variant here: http://furius.ca/pubcode/pub/conf/bin/svndumpfilter3.html

And another here: http://www.undersea.com/~nmb/svndumpfilter4

with explanation for svndumpfilter4 here (from archive.org - unfortunately the original is no longer accessible): http://replay.waybackmachine.org/20080827213200/http://www.undersea.com/~nburrell/blog/node/81

The variants are smart enough to use svnlook to retrieve the necessary source material even if it lives outside the included section of the tree.

Solution 2:

OK, I have a now a solution which works, tested on a real repository. The idea is to dump only revisions until (and not including) the renaming, then the revisions after it (with the --incremental option). Then, I reload the first dump, I do a renaming in the new repository, and I reload the second dump. It seems to work properly.

I made a modified version of my script which show the detailed steps.

If I understand properly, the original issue was that the renaming took place at a higher level in the tree than the directories I wanted to keep and so was not kept by svndumpfilter. Therefore, the operations on files after the renaming failed because the nodes in the dump were of type change and there was no node of type add for the new location.

Solution 3:

You could also try out dumpsanitizer. It handles the problem cases where files/directories have been moved, without having to do it manually. We used this approach to set part of an older repository as a baseline for a new repository.