parsers: make pack_dirstate take now in integer for consistency
On recent OS, 'stat.st_mtime' has a double precision floating point
value to represent nano seconds, but it is not wide enough for actual
file timestamp: nowadays, only 52 - 32 = 20 bit width is available for
decimal places in sec.
Therefore, casting it to 'int' may cause unexpected result. See also
changeset 13272104bb07 fixing issue4836 for detail.
For example, changed file A may be treated as "clean" unexpectedly in
steps below. "rounded now" is the value gotten by rounding via
'int(st.st_mtime)' or so.
---------------------+--------------------+------------------------
"now" | | timestamp of A (time_t)
float rounded time_t| action | FS dirstate
------ ------- ------+--------------------+-------- ---------------
N+.nnn N N | | --- ---
| update file A | N
| dirstate.normal(A) | N
N+.999 N+1 N | |
| dirstate.write() | N (*1)
| : |
| change file A | N
| : |
N+1.00 N+1 N+1 | |
| "hg status" (*2) | N N
------ ------- ------+--------------------+-------- ---------------
Timestamp N of A in dirstate isn't dropped at (*1), because "rounded
now" is N+1 at that time, even if 'st_mtime' in 'time_t' is still N.
Then, file A is unexpectedly treated as "clean" at (*2) in this case.
For consistent handling of 'stat.st_mtime', this patch makes
'pack_dirstate()' take 'now' argument not in floating point but in
integer.
This patch makes 'PyArg_ParseTuple()' in 'pack_dirstate()' use format
'i' (= checking type mismatch or overflow), even though it is ensured
that 'now' is in the range of 32bit signed integer by masking with
'_rangemask' (= 0x7fffffff) on caller side.
It should be cheaper enough than packing itself, and useful to
detect that legacy code invokes 'pack_dirstate()' with 'now' in
floating point value.
$ cat <<EOF >> $HGRCPATH
> [extensions]
> mq =
> [mq]
> git = keep
> EOF
$ hg init a
$ cd a
$ echo 'base' > base
$ hg ci -Ambase
adding base
$ hg qnew -mmqbase mqbase
$ echo 'patched' > base
$ hg qrefresh
qdiff:
$ hg qdiff
diff -r d20a80d4def3 base
--- a/base Thu Jan 01 00:00:00 1970 +0000
+++ b/base* (glob)
@@ -1,1 +1,1 @@
-base
+patched
qdiff dirname:
$ hg qdiff --nodates .
diff -r d20a80d4def3 base
--- a/base
+++ b/base
@@ -1,1 +1,1 @@
-base
+patched
qdiff filename:
$ hg qdiff --nodates base
diff -r d20a80d4def3 base
--- a/base
+++ b/base
@@ -1,1 +1,1 @@
-base
+patched
$ hg revert -a
$ hg qpop
popping mqbase
patch queue now empty
$ hg qdelete mqbase
$ printf '1\n2\n3\n4\nhello world\ngoodbye world\n7\n8\n9\n' > lines
$ hg ci -Amlines -d '2 0'
adding lines
$ hg qnew -mmqbase2 mqbase2
$ printf '\n\n1\n2\n3\n4\nhello world\n goodbye world\n7\n8\n9\n' > lines
$ hg qdiff --nodates -U 1
diff -r b0c220e1cf43 lines
--- a/lines
+++ b/lines
@@ -1,1 +1,3 @@
+
+
1
@@ -4,4 +6,4 @@
4
-hello world
-goodbye world
+hello world
+ goodbye world
7
$ hg qdiff --nodates -b
diff -r b0c220e1cf43 lines
--- a/lines
+++ b/lines
@@ -1,9 +1,11 @@
+
+
1
2
3
4
hello world
-goodbye world
+ goodbye world
7
8
9
$ hg qdiff --nodates -U 1 -B
diff -r b0c220e1cf43 lines
--- a/lines
+++ b/lines
@@ -4,4 +4,4 @@
4
-hello world
-goodbye world
+hello world
+ goodbye world
7
$ hg qdiff --nodates -w
diff -r b0c220e1cf43 lines
--- a/lines
+++ b/lines
@@ -1,3 +1,5 @@
+
+
1
2
3
$ hg qdiff --nodates --reverse
diff -r b0c220e1cf43 lines
--- a/lines
+++ b/lines
@@ -1,11 +1,9 @@
-
-
1
2
3
4
-hello world
- goodbye world
+hello world
+goodbye world
7
8
9
qdiff preserve existing git flag:
$ hg qrefresh --git
$ echo a >> lines
$ hg qdiff
diff --git a/lines b/lines
--- a/lines
+++ b/lines
@@ -1,9 +1,12 @@
+
+
1
2
3
4
-hello world
-goodbye world
+hello world
+ goodbye world
7
8
9
+a
$ hg qdiff --stat
lines | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
$ hg qrefresh
qdiff when file deleted (but not removed) in working dir:
$ hg qnew deleted-file
$ echo a > newfile
$ hg add newfile
$ hg qrefresh
$ rm newfile
$ hg qdiff
$ cd ..