Sat 29 Mar 2008 10:35:17 PM UTC, original submission:
Last November, and again a few weeks ago, right after Daylight Savings Time changed in the USA, I found that a simple cvs update (using cvs 1.11.22 on Windows XP) took a very long time. I found it was uploading over half the files in the sandbox to the server, even though they were nearly all unchanged. So I dived into the source code, and found the problems, and have now fixed them to my own satisfaction.
Attached is a patch for rev 1.11.22 that solves the problem (hopefully) once and for all. This patch also includes the fix to bug 22710.
Someone had previously done work to try to correct the Unix-like time_t timestamps obtained from stat and lstat, and that may have helped at one time, but that change was insufficient, IMO. It changed SOME stat and lstat calls to use code that attempted to correct the time_t's. But it didn't get ALL the calls to stat and lstat, and didn't get ANY calls to fstat.
The BIG problem, untouched by that code, was that it didn't fix the DST bug in Windows' utime function. When you call utime to set the modification time on a file to some date in the past that is NOT in the same DST "season" as the present time, utime will add or subtract an hour from the time you specify, causing the file's modification time to NOT be the same as on the server. And (as already known) the *stat functions also compensate for timestamps that are in a different DST "season" by adding or subtracting an hour in the opposite direction of the change made by utime. Consequently, if you set a file's modification time with utime and immediately read it back with (unmodified) stat (as CVS update does), it will appear that the time has been set correctly, but it may actually have been set to a time that is an hour off.
I fixed the problem as follows:
a) wrote new stat, lstat, and fstat function implementations that get the UTC times via calls to Windows GetFileTime function and correctly convert them to Unix time_t's.
b) write a new utime implementation that correctly converts the Unit time_t to a UTC FILETIME, and sets the time stamp using Windows' SetFileTime call.
c) changed ALL stat, lstat, fstat and utime calls to use those new functions on Windows.
I tested this on both NTFS and FAT file systems, and in my tests, it got the right results in all test cases on both types of file systems.
If you have a sandbox that has files with modification times in both seasons, then sadly, a massive update is unavoidable to correct the timestamps on the files whose timestamps are an hour off. But with this patch, the new timesstamps are correct UTC timestamps, and future DST season changes should NOT cause more massive uploading.
As part of implementing this fix, I had to port the code to build with MSVC version V8 (a.k.a Express 2005). This means time_t's are 64 bits, and many of the standard header files that were absent in older versions are now present. I had to fix some function declarations that conflicted with Windows' existing declarations. Also, some formerly used variables names are now reserved words, so I had to rename some variables, e.g. errCode -> errorCode.
I also had to change the Makefiles to deal with several differences, including
a) several of the old compiler command line switches are no longer supported
b) Extra build step to combine the manifest files (new in VC8) into the .exe,
c) Fixed the Makefiles to output the full commands it executes, just like on Unix. :)
The result will not run on Windows 9x or ME, but will run on Win2K and later
OSes.
I've been using CVS for over 10 years now, and am happy to be able to make a small contribution to it in return for all the good service it has given me. This is my first real submission of a patch of any magnitude for CVS, so the patch may not meet the CVS team's coding style standards or other standards of which I am not aware. I invite any/all feedback.
/Nelson
|