[Bug 4836] New: hg keeps rewriting the dirstate when files have mtimes in some specific range

mercurial-bugs at selenic.com mercurial-bugs at selenic.com
Wed Sep 23 20:59:37 UTC 2015


http://bz.selenic.com/show_bug.cgi?id=4836

            Bug ID: 4836
           Summary: hg keeps rewriting the dirstate when files have mtimes
                    in some specific range
           Product: Mercurial
           Version: 3.5
          Hardware: PC
                OS: Linux
            Status: UNCONFIRMED
          Severity: feature
          Priority: wish
         Component: Mercurial
          Assignee: bugzilla at selenic.com
          Reporter: vgatien-baron at janestreet.com
                CC: mercurial-devel at selenic.com

One would expect that, as long as nothing changes in a repository, the
dirstate is not going to change needlessly when calling hg many times
in a row. This is useful to figure out quickly when commands that
depends on the dirstate need to be rerun (and more efficient
obviously).

This expectation sometimes does not hold. hg has two sligthly
different ways of getting the mtimes for a file (os.lstat and
osutils.listdir(stat = True, ..) when using the C code), and they
sometimes do not return the same mtime, even after the value has been
truncated to the previous second by int(). When files have an mtime
where the number of nanoseconds is very close to one billion, the
computation 'sec + 1e-9 * nsec' in os.lstat returns 'sec + 1', whereas
osutils returns 'sec' (it doesn't even look at the number of
nanoseconds), which means the contents of the dirstate never matches
the timestamp from dirstate.walk (at least when going through
dirstate.normal).
Disabling the C code stops this problem.

Reproduction:

#!/bin/bash
rm -rf repo2
hg init repo2
cd repo2
touch a
hg add a
hg commit -m a
sleep 2.

echo "Dirstate is stable:"

stat .hg/dirstate | md5sum
hg st
stat .hg/dirstate | md5sum
hg st
stat .hg/dirstate | md5sum
hg st
stat .hg/dirstate | md5sum
hg st
stat .hg/dirstate | md5sum

echo "But when the number of nanoseconds of the mtime is within 120ns of one
billion, hg keeps rewriting the dirstate."

cat > ../timestamp.c <<EOF
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

int main(int argc, char* argv[]) {
  struct timespec times[2];
  times[0].tv_sec = 1442958099;
  times[0].tv_nsec = 999999997;
  times[1].tv_sec = 1442958099;
  times[1].tv_nsec = 999999997;
  int fd = open(argv[1], O_RDONLY);
  futimens(fd, times);
}
EOF
gcc ../timestamp.c -o ../timestamp
../timestamp a
stat .hg/dirstate | md5sum
hg st
stat .hg/dirstate | md5sum
hg st
stat .hg/dirstate | md5sum
hg st
stat .hg/dirstate | md5sum
hg st
stat .hg/dirstate | md5sum

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the Mercurial-devel mailing list