Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jgit-dev] Understanding Racy Git Handling in JGit: detection of coarse timers

Christian Halstrick <christian.halstrick@xxxxxxxxx> wrote:
> In GitIndex.Entry.ismodified() there is a detection for
> filesystem-timer resolution. This detection looks weird to us. That's
> the code:
> 			// Git under windows only stores seconds so we round the timestamp
> 			// Java gives us if it looks like the timestamp in index is seconds
> 			// only. Otherwise we compare the timestamp at millisecond prevision.
> 			long javamtime = mtime / 1000000L;
> 			long lastm = file.lastModified();
> 			if (javamtime % 1000 == 0)
> 				lastm = lastm - lastm % 1000;
> 			if (lastm != javamtime) {
> 				if (!forceContentCheck)
> It is not clear to us:
> - why this works
>   Filesystem-timers could be coarse but not report constant, non-null
> milliseconds. Or granularity could be split-seconds.
> - why it is needed
>   in which use cases do we compare timestamps which come from timers
> with different granularity?

In msysgit they only store the seconds portion of the timestamp
they get back from Windows.  The sub-seconds portion (if it exists
at all) is flat out discarded.  So the time_ns field in the index
record is always 0.

You can see this inside of the compat/mingw.c code within git.git,
the do_lstat function only returns seconds.

So if the end-user is using msysgit on this repository, we wind up
with the time_ns field being empty.  But JGit on the same directory
would use up to millisecond precision, as that is what the JRE is
exporting to us from the native filesystem calls.

Since NTFS actually wrote the last modified timestamp of the file,
and NTFS can store subsecond timestamps, its likely that any source
file created by a `git checkout` in msysgit has a non-zero number
of milliseconds... but msysgit truncated that and only stored the
number of seconds.

When we try to stat that in Java in JGit, we see the milliseconds
from NTFS, and it doesn't match what is in the index.  The local
file appears modified, because its a few milliseconds newer than
what msysgit put into the index.  Thus we falsely concluded that
the file was modified by the user.

This 0 millisecond check is about trying to guess that the user
created the file through msysgit, and is now reading it from Java.


Back to the top