D8184: nodemap: track the tip_node for validation

2020-03-11 Thread marmoute (Pierre-Yves David)
Closed by commit rHG6c906eaedd0d: nodemap: track the tip_node for validation 
(authored by marmoute).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs 
Review".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D8184?vs=20681&id=20703

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D8184/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D8184

AFFECTED FILES
  mercurial/configitems.py
  mercurial/debugcommands.py
  mercurial/revlog.py
  mercurial/revlogutils/nodemap.py
  tests/test-persistent-nodemap.t

CHANGE DETAILS

diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t
--- a/tests/test-persistent-nodemap.t
+++ b/tests/test-persistent-nodemap.t
@@ -14,10 +14,11 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5000
+  tip-node: 06ddac466af534d365326c13c3879f97caca3cb1
   data-length: 122880
   data-unused: 0
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 Simple lookup works
 
@@ -95,18 +96,20 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 122880
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 123072
   data-unused: 192
 #endif
 
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 (The pure code use the debug code that perform incremental update, the C code 
reencode from scratch)
 
@@ -148,6 +151,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -157,6 +161,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -166,6 +171,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -181,12 +187,14 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #endif
@@ -215,6 +223,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5003
+  tip-node: 5c049e9c4a4af159bdcd65dce1b6bf303a0da6cf
   data-length: 123200 (pure !)
   data-length: 123200 (rust !)
   data-length: 122944 (no-rust no-pure !)
@@ -225,7 +234,50 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ hg log -r "$NODE" -T '{rev}\n'
   5003
+
+changelog altered
+-
+
+If the nodemap is not gated behind a requirements, an unaware client can alter
+the repository so the revlog used to generate the nodemap is not longer
+compatible with the persistent nodemap. We need to detect that.
+
+  $ hg up "$NODE~5"
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo bar > babar
+  $ hg add babar
+  $ hg ci -m 'babar'
+  created new head
+  $ OTHERNODE=`hg log -r tip -T '{node}\n'`
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5004
+
+  $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
+
+the nodemap should detect the changelog have been tampered with and recover.
+
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 42bf3068c7ddfdfded53c4eb11d02266faeebfee
+  data-length: 123456 (pure !)
+  data-length: 246464 (rust !)
+  data-length: 123008 (no-pure no-rust !)
+  data-unused: 448 (pure !)
+  data-unused: 123904 (rust !)
+  data-unused: 0 (no-pure no-rust !)
+
+  $ cp -f ../tmp-copies/* .hg/store/
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
+  data-length: 122944
+  data-unused: 0
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5002
diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py
--- a/mercurial/revlogutils/nodemap.py
+++ b/mercurial/revlogutils/nodemap.py
@@ -38,10 +38,12 @@
 return None
 offset += S_VERSION.size
 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
- 

D8184: nodemap: track the tip_node for validation

2020-03-10 Thread marmoute (Pierre-Yves David)
marmoute added a comment.
marmoute updated this revision to Diff 20681.


  rebase above latest default up to landed-D8182

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D8184?vs=20581&id=20681

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D8184/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D8184

AFFECTED FILES
  mercurial/configitems.py
  mercurial/debugcommands.py
  mercurial/revlog.py
  mercurial/revlogutils/nodemap.py
  tests/test-persistent-nodemap.t

CHANGE DETAILS

diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t
--- a/tests/test-persistent-nodemap.t
+++ b/tests/test-persistent-nodemap.t
@@ -14,10 +14,11 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5000
+  tip-node: 06ddac466af534d365326c13c3879f97caca3cb1
   data-length: 122880
   data-unused: 0
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 Simple lookup works
 
@@ -95,18 +96,20 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 122880
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 123072
   data-unused: 192
 #endif
 
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 (The pure code use the debug code that perform incremental update, the C code 
reencode from scratch)
 
@@ -148,6 +151,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -157,6 +161,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -166,6 +171,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -181,12 +187,14 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #endif
@@ -215,6 +223,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5003
+  tip-node: 5c049e9c4a4af159bdcd65dce1b6bf303a0da6cf
   data-length: 123200 (pure !)
   data-length: 123200 (rust !)
   data-length: 122944 (no-rust no-pure !)
@@ -225,7 +234,50 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ hg log -r "$NODE" -T '{rev}\n'
   5003
+
+changelog altered
+-
+
+If the nodemap is not gated behind a requirements, an unaware client can alter
+the repository so the revlog used to generate the nodemap is not longer
+compatible with the persistent nodemap. We need to detect that.
+
+  $ hg up "$NODE~5"
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo bar > babar
+  $ hg add babar
+  $ hg ci -m 'babar'
+  created new head
+  $ OTHERNODE=`hg log -r tip -T '{node}\n'`
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5004
+
+  $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
+
+the nodemap should detect the changelog have been tampered with and recover.
+
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 42bf3068c7ddfdfded53c4eb11d02266faeebfee
+  data-length: 123456 (pure !)
+  data-length: 246464 (rust !)
+  data-length: 123008 (no-pure no-rust !)
+  data-unused: 448 (pure !)
+  data-unused: 123904 (rust !)
+  data-unused: 0 (no-pure no-rust !)
+
+  $ cp -f ../tmp-copies/* .hg/store/
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
+  data-length: 122944
+  data-unused: 0
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5002
diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py
--- a/mercurial/revlogutils/nodemap.py
+++ b/mercurial/revlogutils/nodemap.py
@@ -38,10 +38,12 @@
 return None
 offset += S_VERSION.size
 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
-uid_size, tip_rev, data_length, data_unused = headers
+uid_size, tip_rev, data_length, data_unused, tip_node_si

D8184: nodemap: track the tip_node for validation

2020-03-06 Thread marmoute (Pierre-Yves David)
marmoute added a comment.
marmoute updated this revision to Diff 20581.


  eventless rebase past D8255 

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D8184?vs=20437&id=20581

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D8184/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D8184

AFFECTED FILES
  mercurial/configitems.py
  mercurial/debugcommands.py
  mercurial/revlog.py
  mercurial/revlogutils/nodemap.py
  tests/test-persistent-nodemap.t

CHANGE DETAILS

diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t
--- a/tests/test-persistent-nodemap.t
+++ b/tests/test-persistent-nodemap.t
@@ -14,10 +14,11 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5000
+  tip-node: 06ddac466af534d365326c13c3879f97caca3cb1
   data-length: 122880
   data-unused: 0
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 Simple lookup works
 
@@ -95,18 +96,20 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 122880
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 123072
   data-unused: 192
 #endif
 
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 (The pure code use the debug code that perform incremental update, the C code 
reencode from scratch)
 
@@ -148,6 +151,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -157,6 +161,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -166,6 +171,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -181,12 +187,14 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #endif
@@ -215,6 +223,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5003
+  tip-node: 5c049e9c4a4af159bdcd65dce1b6bf303a0da6cf
   data-length: 123200 (pure !)
   data-length: 123200 (rust !)
   data-length: 122944 (no-rust no-pure !)
@@ -225,7 +234,50 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ hg log -r "$NODE" -T '{rev}\n'
   5003
+
+changelog altered
+-
+
+If the nodemap is not gated behind a requirements, an unaware client can alter
+the repository so the revlog used to generate the nodemap is not longer
+compatible with the persistent nodemap. We need to detect that.
+
+  $ hg up "$NODE~5"
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo bar > babar
+  $ hg add babar
+  $ hg ci -m 'babar'
+  created new head
+  $ OTHERNODE=`hg log -r tip -T '{node}\n'`
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5004
+
+  $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
+
+the nodemap should detect the changelog have been tampered with and recover.
+
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 42bf3068c7ddfdfded53c4eb11d02266faeebfee
+  data-length: 123456 (pure !)
+  data-length: 246464 (rust !)
+  data-length: 123008 (no-pure no-rust !)
+  data-unused: 448 (pure !)
+  data-unused: 123904 (rust !)
+  data-unused: 0 (no-pure no-rust !)
+
+  $ cp -f ../tmp-copies/* .hg/store/
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
+  data-length: 122944
+  data-unused: 0
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5002
diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py
--- a/mercurial/revlogutils/nodemap.py
+++ b/mercurial/revlogutils/nodemap.py
@@ -38,10 +38,12 @@
 return None
 offset += S_VERSION.size
 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
-uid_size, tip_rev, data_length, data_unused = headers
+uid_size, tip_rev, data_length, data

D8184: nodemap: track the tip_node for validation

2020-03-03 Thread marmoute (Pierre-Yves David)
marmoute added a comment.
marmoute updated this revision to Diff 20437.


  simple rebase

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D8184?vs=20387&id=20437

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D8184/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D8184

AFFECTED FILES
  mercurial/configitems.py
  mercurial/debugcommands.py
  mercurial/revlog.py
  mercurial/revlogutils/nodemap.py
  tests/test-persistent-nodemap.t

CHANGE DETAILS

diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t
--- a/tests/test-persistent-nodemap.t
+++ b/tests/test-persistent-nodemap.t
@@ -14,10 +14,11 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5000
+  tip-node: 06ddac466af534d365326c13c3879f97caca3cb1
   data-length: 122880
   data-unused: 0
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 Simple lookup works
 
@@ -95,18 +96,20 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 122880
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 123072
   data-unused: 192
 #endif
 
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 (The pure code use the debug code that perform incremental update, the C code 
reencode from scratch)
 
@@ -148,6 +151,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -157,6 +161,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -166,6 +171,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -181,12 +187,14 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #endif
@@ -215,6 +223,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5003
+  tip-node: 5c049e9c4a4af159bdcd65dce1b6bf303a0da6cf
   data-length: 123200 (pure !)
   data-length: 123200 (rust !)
   data-length: 122944 (no-rust no-pure !)
@@ -225,7 +234,50 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ hg log -r "$NODE" -T '{rev}\n'
   5003
+
+changelog altered
+-
+
+If the nodemap is not gated behind a requirements, an unaware client can alter
+the repository so the revlog used to generate the nodemap is not longer
+compatible with the persistent nodemap. We need to detect that.
+
+  $ hg up "$NODE~5"
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo bar > babar
+  $ hg add babar
+  $ hg ci -m 'babar'
+  created new head
+  $ OTHERNODE=`hg log -r tip -T '{node}\n'`
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5004
+
+  $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
+
+the nodemap should detect the changelog have been tampered with and recover.
+
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 42bf3068c7ddfdfded53c4eb11d02266faeebfee
+  data-length: 123456 (pure !)
+  data-length: 246464 (rust !)
+  data-length: 123008 (no-pure no-rust !)
+  data-unused: 448 (pure !)
+  data-unused: 123904 (rust !)
+  data-unused: 0 (no-pure no-rust !)
+
+  $ cp -f ../tmp-copies/* .hg/store/
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
+  data-length: 122944
+  data-unused: 0
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5002
diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py
--- a/mercurial/revlogutils/nodemap.py
+++ b/mercurial/revlogutils/nodemap.py
@@ -38,10 +38,12 @@
 return None
 offset += S_VERSION.size
 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
-uid_size, tip_rev, data_length, data_unused = headers
+uid_size, tip_rev, data_length, data_unused, tip_node_size = headers
 offset += S_HEA

D8184: nodemap: track the tip_node for validation

2020-02-28 Thread marmoute (Pierre-Yves David)
marmoute created this revision.
Herald added a reviewer: indygreg.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D8184

AFFECTED FILES
  mercurial/configitems.py
  mercurial/debugcommands.py
  mercurial/revlog.py
  mercurial/revlogutils/nodemap.py
  tests/test-persistent-nodemap.t

CHANGE DETAILS

diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t
--- a/tests/test-persistent-nodemap.t
+++ b/tests/test-persistent-nodemap.t
@@ -14,10 +14,11 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5000
+  tip-node: 06ddac466af534d365326c13c3879f97caca3cb1
   data-length: 122880
   data-unused: 0
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 Simple lookup works
 
@@ -95,18 +96,20 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 122880
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5001
+  tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
   data-length: 123072
   data-unused: 192
 #endif
 
   $ f --size .hg/store/00changelog.n
-  .hg/store/00changelog.n: size=42
+  .hg/store/00changelog.n: size=70
 
 (The pure code use the debug code that perform incremental update, the C code 
reencode from scratch)
 
@@ -148,6 +151,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -157,6 +161,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 123328
   data-unused: 384
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -166,6 +171,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ f --sha256 .hg/store/00changelog-*.nd --size
@@ -181,12 +187,14 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #else
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
 #endif
@@ -215,6 +223,7 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5003
+  tip-node: 5c049e9c4a4af159bdcd65dce1b6bf303a0da6cf
   data-length: 123200 (pure !)
   data-length: 123200 (rust !)
   data-length: 122944 (no-rust no-pure !)
@@ -225,7 +234,50 @@
   $ hg debugnodemap --metadata
   uid:  (glob)
   tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
   data-length: 122944
   data-unused: 0
   $ hg log -r "$NODE" -T '{rev}\n'
   5003
+
+changelog altered
+-
+
+If the nodemap is not gated behind a requirements, an unaware client can alter
+the repository so the revlog used to generate the nodemap is not longer
+compatible with the persistent nodemap. We need to detect that.
+
+  $ hg up "$NODE~5"
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo bar > babar
+  $ hg add babar
+  $ hg ci -m 'babar'
+  created new head
+  $ OTHERNODE=`hg log -r tip -T '{node}\n'`
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5004
+
+  $ hg --config extensions.strip= strip --rev "$NODE~1" --no-backup
+
+the nodemap should detect the changelog have been tampered with and recover.
+
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 42bf3068c7ddfdfded53c4eb11d02266faeebfee
+  data-length: 123456 (pure !)
+  data-length: 246464 (rust !)
+  data-length: 123008 (no-pure no-rust !)
+  data-unused: 448 (pure !)
+  data-unused: 123904 (rust !)
+  data-unused: 0 (no-pure no-rust !)
+
+  $ cp -f ../tmp-copies/* .hg/store/
+  $ hg debugnodemap --metadata
+  uid:  (glob)
+  tip-rev: 5002
+  tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
+  data-length: 122944
+  data-unused: 0
+  $ hg log -r "$OTHERNODE" -T '{rev}\n'
+  5002
diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py
--- a/mercurial/revlogutils/nodemap.py
+++ b/mercurial/revlogutils/nodemap.py
@@ -38,10 +38,12 @@
 return None
 offset += S_VERSION.size
 headers = S_HEADER.unpack(pdata[offset : offset + S_HEADER.size])
-uid_size, tip_rev, data_length, data_unused = headers
+uid_size, tip_rev, data_length, data_unused, tip_node_size = headers
 offset += S_HEADER.size
 docket = NodeMapDocket(pdata[offset : offset + uid_size])
+offset += uid_size