Hi folks,
If an item has been modified or deleted in the repository since
the item was last updated in the working copy, Subversion should
disallow committing that item. This is a prerequisite for tree
conflict detection. The user should have to update in order to
integrate the repo changes, possibly revealing tree conflicts.
I had assumed that Subversion would block a commit that includes an
item that has been modified or deleted on the repo. But that's not
true in all cases:
WC State Repo State Blocked?
======== ========== ========
Modified Modified Yes
Modified Deleted Yes
Deleted Modified Yes
Deleted Deleted No
We'd like to plug that gap. I have a patch ready that does so,
including an extension to the relevant cmdline test (#28) in
commit_tests.py. Unfortunately, the patch makes merge_tests.py
fail at #33 ("merge a replacement of a directory", w/refs to
issues #2144 & #2607).
It seems that the merge code depends on the loophole in commit.
The attached shell script demonstrates this by replacing a directory
'X' that contains a file 'foo'.
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
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
This causes an error in my patched Subversion, which forbids
committing a delete of an item that does not exist in the repository.
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:
copied:
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?)
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?
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
http://svn.haxx.se/dev/archive-2008-02/0776.shtml.
Regards,
Steve
--
Stephen Butler | Software Developer
elego Software Solutions GmbH
Gustav-Meyer-Allee 25 | 13355 Berlin | Germany
fon: +49 30 2345 8696 | mobile: +49 163 25 45 015
fax: +49 30 2345 8695 | http://www.elegosoft.com
Geschäftsführer: Olaf Wagner | Sitz der Gesellschaft: Berlin
Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: dev-help_at_subversion.tigris.org
Received on 2008-02-29 15:29:32 CET