Karl Fogel <kfo...@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

Reply via email to