Karl Fogel <kfogel_at_red-bean.com> writes:
> 1) Start an SVN commit.
>
> 2) While the commit is in progress, edit and save a
> change to one of the files that's being committed.
>
> 3) The commit completes successfully, or "successfully", but...
>
> ...now the repository has the file contents from before my edit of
> (2), the working copy has the file contents from *after* my edit of
> (2), but SVN reports no local modifications when I do 'svn status'.
> That's... bad, right? :-)
The post-commit processing on the client side is not checking for
modifications before recording filesize/timestamp in the nodes table in
.svn/wc.db.
In first terminal:
$ svnadmin create repo
$ svnmucc -mm put <(echo foo) file://`pwd`/repo/f
$ svn co file://`pwd`/repo wc
$ echo bar > wc/f
$ gdb --arg svn ci -mm wc
(gdb) b svn_client__do_commit
(gdb) r
hit breakpoint
(gdb) fin
run to end of svn_client__do_commit
Switch to second terminal:
$ svn st wc
L wc
M wc/f
$ cat wc/.svn/pristine/*/*
foo
bar
$ echo zigzag > wc/f
Switch back to first terminal:
(gdb) c
(gdb) q
$
I believe that reproduces the problem:
$ svn cat -r1 wc/f
foo
$ svn cat -r2 wc/f
bar
$ cat wc/f
zigzag
$ sqlite3 wc/.svn/wc.db "select translated_size from nodes where local_relpath='f'"
7
$ svn st wc
$
$ touch wc/f # to break timestamp
$ svn st wc
M wc/f
To fix this we would need to have the client's post-commit processing do
a full-text comparison to catch modifications before storing the
timestamp/size in .svn/wc.db. Avoid a race is a bit tricky, perhaps:
1) stat() to get timestamp/filesize
2) full-text compare to ensure text is unchanged
3) stat() to ensure timestamp/filesize is unchanged
4) store timestamp/filesize
--
Philip
Received on 2017-07-27 19:56:52 CEST