> It seems that the merge code depends on the loophole in commit.
Well, if there's a loophole and whether merge depends on it, I don't
know, but ...
> The attached shell script demonstrates this by replacing a directory
> 'X' that contains a file 'foo'.
... the problem you describe below looks an awful lot like issue
> If the dir replacement is done manually via 'svn del' and 'svn add',
> the status is nominal:
> D 1 1 steve /tmp/del-w-hist/wc/A/X/foo
> A 0 ? ? /tmp/del-w-hist/wc/A/X/bar
> R 1 1 steve /tmp/del-w-hist/wc/A/X
> 1 1 steve /tmp/del-w-hist/wc/A
> Status against revision: 1
> and during commit, foo is implicitly deleted with its parent dir:
> Replacing tmp/del-w-hist/wc/A/X
> Adding tmp/del-w-hist/wc/A/X/bar
> Transmitting file data .
> Committed revision 2.
> If the dir replacement is done via 'svn merge', then the status looks
> rather strange (foo appears to be "deleted-with-history"):
> D + - 3 steve /tmp/del-w-hist/wc/B/X/foo
> A + - 2 steve /tmp/del-w-hist/wc/B/X/bar
> R + - 3 steve /tmp/del-w-hist/wc/B/X
> M 3 3 steve /tmp/del-w-hist/wc/B
> Status against revision: 3
The '+'-es come from svn_wc_add2() which marks the complete subtree as
> and during commit, foo is deleted explicitly *after* its parent dir
> has been deleted.
> Sending tmp/del-w-hist/wc/B
> Replacing tmp/del-w-hist/wc/B/X
> Adding tmp/del-w-hist/wc/B/X/bar
> Deleting tmp/del-w-hist/wc/B/X/foo
> subversion/libsvn_client/commit.c:916: (apr_err=160028)
> svn: Commit failed (details follow):
> subversion/libsvn_repos/commit.c:125: (apr_err=160028)
> svn: File or directory '/B/X/foo' is out of date
The fact that the delete comes after the delete of the parent dir is
normal: that's how the svn_delta_path_driver works: depth-first,
processing tree nodes as they are passed
> This causes an error in my patched Subversion, which forbids
> committing a delete of an item that does not exist in the repository.
Right. Here you have the essence of the problem: in the wc-1.0 schema,
files which are part of the deleted subtree in a replaced subtree have
to be marked 'deleted'. If they were not, there would be no way to put
another file in its place.
However, a schedule delete is a valid state in a added-with-history
subtree too: you may want to delete part of the subtree before you
So, what we're facing here is: we want to be able to tell the file is
part of a deleted subtree *and* we want to be able to tell a file has
been removed from the add-with-history subtree we copied on top of it.
The problem is that we do that with the same schedule-delete status of
the file, which then becomes ambiguous.
> Comparing the working copies before the commits, I noticed something
> odd in /B/X/.svn/entries: the file foo is marked as "copied". This
> explains the 'D +' above. It contradicts the .entries format rules
> in subversion/libsvn_wc/README:
> A boolean: true if this entry was added with history; only allowed
> when schedule is add. (### Why aren't the copyfrom attributes
> enough for this?)
This is plain wrong: files which are part of a
schedule-add-with-history subtree are marked schedule-normal, but have
the 'copied' flag. (Not that I actually like this design, but that's
how it is now.)
> Certainly we should not mark schedule-delete items as "copied". Is
> there a good reason for merge to cause commit to visit all items in a
> tree that is already deleted?
No, there is not. The copied flag comes from svn_wc_add2() which
markes all files in the subtree as copied (and rewrites their URL),
making this operation a *huge* problem for replaced subtrees.
> I suspect the practical reason for the current behavior is the code
> shared with diff, which certainly needs to visit everything. For more
> on the diff/merge dependency, see my earlier post at
I wouldn't go this far: I think it should be possible to get the right
diffs and commits without a copied flag all over the place, but we'll
need to design what we want from our library.
To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: dev-help_at_subversion.tigris.org
Received on 2008-03-24 09:41:09 CET