Heh, found this one while writing a script to test "svn log"...
We have a timestamp issue, at least on my Linux 2.2.16 system. If you
modify a file too quickly after it's checked out or updated (i.e.,
after its entry timestamp got set), then the file's on-disk timestamp
will not be different from the entry's, and therefore Subversion will
not detect your local mods unless those mods also changed the file's
size.
A human probably can't modify a file that fast, but a script sure
can (I've included one such at the end of this mail).
So, here's the dilemna:
- If we no longer compare timestamps, we can guarantee correctness,
but at the expense of speed. A very drastic expense -- any
command that crawls the working copy looking for local mods will
now have to do a byte-for-byte comparison on most files (because
most files are not modified at any given time, and therefore the
filesize check will be inconclusive for them). We can expect
"svn status" and "svn commit" to become rather painful.
- But if we keep the current timestamp code, then depending on your
system granularity, there may occasionally be times when a local
mod is not detected. If you happen to *know* about the mod, you
can easily solve the problem by `touch'ing the file or doing
whatever to change its timestamp. But if you were depending on
Subversion to reliably tell you what's modified, you'll be
hosed.
(Hm, does CVS have this problem too? It has *only* timestamps to go
on, no text-base. I don't recall ever running into this, though.)
Anyway, the only solution I can think of is kind of weird:
Normally, after we've written out a working file as part of checkout
or update, we then store an entry timestamp according to the new
working file's on-disk timestamp. We make the entry timestamp be
precisely the same as the on-disk timestamp. See this line
entry->text_time = text_time;
in libsvn_wc/log.c:log_do_modify_entry().
If we instead write a timestamp slightly in the future w.r.t. the
working file -- where "slightly" means "by an amount greater than the
greatest system granularity you ever heard of" -- then if we ever saw
a working file whose on-disk timestamp were closer to the entry stamp
than that amount, we'd know it had been modified. Uh, right? :-)
Anyone got any other thoughts?
Repro script follows:
--------------------8-<-------cut-here---------8-<-----------------------
#!/bin/sh
# With no arguments, demonstrate a bug whereby very fast working copy
# modifications can result in a wc that contains local mods
# undetectable by Subversion (due to timestamp badness).
#
# With an argument, sleep for a second between each commit, so the
# timestamp problem is avoided, and see all the commits succeed,
# ending with revision 6. Frightening, eh?
#
# Use this script like so:
#
# $ cd top-level-of-subversion-wc/
# $ make
# $ make check
# $ cd subversion/tests/clients/cmdline
# $ ...put this script here as `repro.sh'...
# $ ...edit repro.sh so the $WD and $SVN vars are correct for you...
# $ chmod a+x repro.sh
# $ ./repro.sh
# $ ./repro.sh blah /* blah can be literally "blah" */
### YOU SHOULD ONLY NEED TO MODIFY THESE TWO VARIABLES ###
WD=${HOME}/src/subversion/subversion/tests/clients/cmdline
SVN=${HOME}/src/subversion/subversion/clients/cmdline/svn
cd ${WD}
rm -rf safe-repo safe-wc repo wc
cp -a repositories/basic_tests-1 ./safe-repo
cp -a safe-repo repo
${SVN} co file://${WD}/repo -d safe-wc
${SVN} co file://${WD}/repo -d wc
cd wc
echo "This is rev 2" > iota; ${SVN} ci -m "Log msg for rev two."
echo "Committed revision 2";
if [ "${1-X}" != "X" ]; then sleep 1; fi
echo "This is rev 3" > iota; ${SVN} ci -m "Log msg for rev three."
echo "Committed revision 3";
if [ "${1-X}" != "X" ]; then sleep 1; fi
echo "This is rev 4" > iota; ${SVN} ci -m "Log msg for rev four."
echo "Committed revision 4";
if [ "${1-X}" != "X" ]; then sleep 1; fi
echo "This is rev 5" > iota; ${SVN} ci -m "Log msg for rev five."
echo "Committed revision 5";
if [ "${1-X}" != "X" ]; then sleep 1; fi
echo "This is rev 6" > iota; ${SVN} ci -m "Log msg for rev six."
echo "Committed revision 6";
if [ "${1-X}" != "X" ]; then sleep 1; fi
${SVN} up
${SVN} st -uv
echo ""
echo "NOTE:"
echo "If the status output above does not show everything at revision 6,"
echo "including a head revision of 6, then you have reproduced the bug."
echo "Congratulations."
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Oct 21 14:36:46 2006