Patchwork D8784: tags: adjust file node cache to have space for 32 bytes node ids

login
register
mail settings
Submitter phabricator
Date July 21, 2020, 10:27 p.m.
Message ID <differential-rev-PHID-DREV-zzsrxhc2h5osaxl4mi3l-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/46828/
State New
Headers show

Comments

phabricator - July 21, 2020, 10:27 p.m.
joerg.sonnenberger created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  The .hgtags processing uses two different caches. The first cache is
  essentially a global version of all .hgtags files and a textual format
  without hard size requirements. The second cache stores the file node of
  the .hgtags file for those changesets that modify it as fixed size
  records. Use a new file name for this record and pad the entries to 32
  bytes in preparation for replacing SHA1.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  mercurial/cacheutil.py
  mercurial/debugcommands.py
  mercurial/tags.py
  tests/test-cache-abuse.t
  tests/test-debugcommands.t
  tests/test-help.t
  tests/test-server-view.t
  tests/test-static-http.t
  tests/test-tags.t

CHANGE DETAILS




To: joerg.sonnenberger, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-tags.t b/tests/test-tags.t
--- a/tests/test-tags.t
+++ b/tests/test-tags.t
@@ -15,7 +15,7 @@ 
   > }
 
   $ fnodescacheexists() {
-  >   [ -f .hg/cache/hgtagsfnodes1 ] && echo "fnodes cache exists" || echo "no fnodes cache"
+  >   [ -f .hg/cache/hgtagsfnodes2 ] && echo "fnodes cache exists" || echo "no fnodes cache"
   > }
 
   $ dumptags() {
@@ -98,34 +98,38 @@ 
 
   $ fnodescacheexists
   fnodes cache exists
-  $ f --size --hexdump .hg/cache/hgtagsfnodes1
-  .hg/cache/hgtagsfnodes1: size=48
+  $ f --size --hexdump .hg/cache/hgtagsfnodes2
+  .hg/cache/hgtagsfnodes2: size=72
   0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-  0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
-  0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
+  0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+  0020: ff ff ff ff b9 15 46 36 26 b7 b4 a7 73 e0 9e e3 |......F6&...s...|
+  0030: c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 00 00 00 00 |./Q...^..f.Y....|
+  0040: 00 00 00 00 00 00 00 00                         |........|
   $ hg debugtagscache
   0 acb14030fe0a21b60322c440ad2d20cf7685a376 missing/invalid
   1 b9154636be938d3d431e75a7c906504a079bfe07 26b7b4a773e09ee3c52f510e19e05e1ff966d859
 
 Repeat with cold tag cache:
 
-  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
+  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes2
   $ hg identify
   b9154636be93 tip
 
   $ fnodescacheexists
   fnodes cache exists
-  $ f --size --hexdump .hg/cache/hgtagsfnodes1
-  .hg/cache/hgtagsfnodes1: size=48
+  $ f --size --hexdump .hg/cache/hgtagsfnodes2
+  .hg/cache/hgtagsfnodes2: size=72
   0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-  0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
-  0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
+  0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+  0020: ff ff ff ff b9 15 46 36 26 b7 b4 a7 73 e0 9e e3 |......F6&...s...|
+  0030: c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 00 00 00 00 |./Q...^..f.Y....|
+  0040: 00 00 00 00 00 00 00 00                         |........|
 
 And again, but now unable to write tag cache or lock file:
 
 #if unix-permissions no-fsmonitor
 
-  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
+  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes2
   $ chmod 555 .hg/cache
   $ hg identify
   b9154636be93 tip
@@ -142,12 +146,12 @@ 
 
 Tag cache debug info written to blackbox log
 
-  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
+  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes2
   $ hg identify
   b9154636be93 tip
   $ hg blackbox -l 6
   1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> identify
-  1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> writing 48 bytes to cache/hgtagsfnodes1
+  1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> writing 72 bytes to cache/hgtagsfnodes2
   1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> 0/2 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> writing .hg/cache/tags2-visible with 1 tags
   1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> identify exited 0 after * seconds (glob)
@@ -155,13 +159,13 @@ 
 
 Failure to acquire lock results in no write
 
-  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
+  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes2
   $ echo 'foo:1' > .hg/wlock
   $ hg identify
   b9154636be93 tip
   $ hg blackbox -l 6
   1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> identify
-  1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> not writing .hg/cache/hgtagsfnodes1 because lock cannot be acquired
+  1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> not writing .hg/cache/hgtagsfnodes2 because lock cannot be acquired
   1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> 0/2 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> writing .hg/cache/tags2-visible with 1 tags
   1970/01/01 00:00:00 bob @b9154636be938d3d431e75a7c906504a079bfe07 (5000)> identify exited 0 after * seconds (glob)
@@ -172,7 +176,7 @@ 
 
   $ rm .hg/wlock
 
-  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes1
+  $ rm -f .hg/cache/tags2-visible .hg/cache/hgtagsfnodes2
   $ hg identify
   b9154636be93 tip
 
@@ -201,24 +205,28 @@ 
 Creating a new commit shouldn't append the .hgtags fnodes cache until
 tags info is accessed
 
-  $ f --size --hexdump .hg/cache/hgtagsfnodes1
-  .hg/cache/hgtagsfnodes1: size=48
+  $ f --size --hexdump .hg/cache/hgtagsfnodes2
+  .hg/cache/hgtagsfnodes2: size=72
   0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-  0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
-  0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
+  0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+  0020: ff ff ff ff b9 15 46 36 26 b7 b4 a7 73 e0 9e e3 |......F6&...s...|
+  0030: c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 00 00 00 00 |./Q...^..f.Y....|
+  0040: 00 00 00 00 00 00 00 00                         |........|
 
   $ hg id
   c8edf04160c7 tip
 
 First 4 bytes of record 3 are changeset fragment
 
-  $ f --size --hexdump .hg/cache/hgtagsfnodes1
-  .hg/cache/hgtagsfnodes1: size=72
+  $ f --size --hexdump .hg/cache/hgtagsfnodes2
+  .hg/cache/hgtagsfnodes2: size=108
   0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-  0010: ff ff ff ff ff ff ff ff b9 15 46 36 26 b7 b4 a7 |..........F6&...|
-  0020: 73 e0 9e e3 c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 |s..../Q...^..f.Y|
-  0030: c8 ed f0 41 00 00 00 00 00 00 00 00 00 00 00 00 |...A............|
-  0040: 00 00 00 00 00 00 00 00                         |........|
+  0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+  0020: ff ff ff ff b9 15 46 36 26 b7 b4 a7 73 e0 9e e3 |......F6&...s...|
+  0030: c5 2f 51 0e 19 e0 5e 1f f9 66 d8 59 00 00 00 00 |./Q...^..f.Y....|
+  0040: 00 00 00 00 00 00 00 00 c8 ed f0 41 00 00 00 00 |...........A....|
+  0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+  0060: 00 00 00 00 00 00 00 00 00 00 00 00             |............|
 
 Merge the two heads:
 
@@ -341,21 +349,25 @@ 
   bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar
   78391a272241d70354aa14c874552cad6b51bb42 bar
 
-  $ f --size --hexdump .hg/cache/hgtagsfnodes1
-  .hg/cache/hgtagsfnodes1: size=120
+  $ f --size --hexdump .hg/cache/hgtagsfnodes2
+  .hg/cache/hgtagsfnodes2: size=180
   0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
   0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
   0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-  0030: 7a 94 12 77 0c 04 f2 a8 af 31 de 17 fa b7 42 28 |z..w.....1....B(|
-  0040: 78 ee 5a 2d ad bc 94 3d 6f a4 50 21 7d 3b 71 8c |x.Z-...=o.P!};q.|
-  0050: 96 4e f3 7b 89 e5 50 eb da fd 57 89 e7 6c e1 b0 |.N.{..P...W..l..|
-  0060: 0c 19 2d 7d 0c 04 f2 a8 af 31 de 17 fa b7 42 28 |..-}.....1....B(|
-  0070: 78 ee 5a 2d ad bc 94 3d                         |x.Z-...=|
+  0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+  0040: ff ff ff ff ff ff ff ff 7a 94 12 77 0c 04 f2 a8 |........z..w....|
+  0050: af 31 de 17 fa b7 42 28 78 ee 5a 2d ad bc 94 3d |.1....B(x.Z-...=|
+  0060: 00 00 00 00 00 00 00 00 00 00 00 00 6f a4 50 21 |............o.P!|
+  0070: 7d 3b 71 8c 96 4e f3 7b 89 e5 50 eb da fd 57 89 |};q..N.{..P...W.|
+  0080: e7 6c e1 b0 00 00 00 00 00 00 00 00 00 00 00 00 |.l..............|
+  0090: 0c 19 2d 7d 0c 04 f2 a8 af 31 de 17 fa b7 42 28 |..-}.....1....B(|
+  00a0: 78 ee 5a 2d ad bc 94 3d 00 00 00 00 00 00 00 00 |x.Z-...=........|
+  00b0: 00 00 00 00                                     |....|
 
 Corrupt the .hgtags fnodes cache
 Extra junk data at the end should get overwritten on next cache update
 
-  $ echo extra >> .hg/cache/hgtagsfnodes1
+  $ echo extra >> .hg/cache/hgtagsfnodes2
   $ echo dummy1 > foo
   $ hg commit -m throwaway1
 
@@ -365,7 +377,7 @@ 
 
   $ hg blackbox -l 6
   1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> tags
-  1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> writing 24 bytes to cache/hgtagsfnodes1
+  1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> writing 36 bytes to cache/hgtagsfnodes2
   1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> 3/4 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> writing .hg/cache/tags2-visible with 1 tags
   1970/01/01 00:00:00 bob @8dbfe60eff306a54259cfe007db9e330e7ecf866 (5000)> tags exited 0 after * seconds (glob)
@@ -375,7 +387,7 @@ 
 
   $ rm -f .hg/cache/tags2-visible
   >>> import os
-  >>> with open(".hg/cache/hgtagsfnodes1", "ab+") as fp:
+  >>> with open(".hg/cache/hgtagsfnodes2", "ab+") as fp:
   ...     fp.seek(-10, os.SEEK_END) and None
   ...     fp.truncate() and None
 
@@ -395,7 +407,7 @@ 
   $ echo dummy2 > foo
   $ hg commit -m throwaway2
 
-  $ chmod a-w .hg/cache/hgtagsfnodes1
+  $ chmod a-w .hg/cache/hgtagsfnodes2
   $ rm -f .hg/cache/tags2-visible
 
   $ hg tags
@@ -404,13 +416,13 @@ 
 
   $ hg blackbox -l 6
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags
-  1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> couldn't write cache/hgtagsfnodes1: [Errno *] * (glob)
+  1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> couldn't write cache/hgtagsfnodes2: [Errno *] * (glob)
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> 3/4 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> writing .hg/cache/tags2-visible with 1 tags
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags exited 0 after * seconds (glob)
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> blackbox -l 6
 
-  $ chmod a+w .hg/cache/hgtagsfnodes1
+  $ chmod a+w .hg/cache/hgtagsfnodes2
 
   $ rm -f .hg/cache/tags2-visible
   $ hg tags
@@ -419,27 +431,27 @@ 
 
   $ hg blackbox -l 6
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags
-  1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> writing 24 bytes to cache/hgtagsfnodes1
+  1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> writing 36 bytes to cache/hgtagsfnodes2
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> 3/4 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> writing .hg/cache/tags2-visible with 1 tags
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> tags exited 0 after * seconds (glob)
   1970/01/01 00:00:00 bob @b968051b5cf3f624b771779c6d5f84f1d4c3fb5d (5000)> blackbox -l 6
 
-  $ f --size .hg/cache/hgtagsfnodes1
-  .hg/cache/hgtagsfnodes1: size=168
+  $ f --size .hg/cache/hgtagsfnodes2
+  .hg/cache/hgtagsfnodes2: size=252
 
   $ hg -q --config extensions.strip= strip -r 6 --no-backup
 #endif
 
 Stripping doesn't truncate the tags cache until new data is available
 
-  $ rm -f .hg/cache/hgtagsfnodes1 .hg/cache/tags2-visible
+  $ rm -f .hg/cache/hgtagsfnodes2 .hg/cache/tags2-visible
   $ hg tags
   tip                                5:8dbfe60eff30
   bar                                1:78391a272241
 
-  $ f --size .hg/cache/hgtagsfnodes1
-  .hg/cache/hgtagsfnodes1: size=144
+  $ f --size .hg/cache/hgtagsfnodes2
+  .hg/cache/hgtagsfnodes2: size=216
 
   $ hg -q --config extensions.strip= strip -r 5 --no-backup
   $ hg tags
@@ -447,14 +459,14 @@ 
   bar                                1:78391a272241
 
   $ hg blackbox -l 5
-  1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> writing 24 bytes to cache/hgtagsfnodes1
+  1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> writing 36 bytes to cache/hgtagsfnodes2
   1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> 2/4 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> writing .hg/cache/tags2-visible with 1 tags
   1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> tags exited 0 after * seconds (glob)
   1970/01/01 00:00:00 bob @0c192d7d5e6b78a714de54a2e9627952a877e25a (5000)> blackbox -l 5
 
-  $ f --size .hg/cache/hgtagsfnodes1
-  .hg/cache/hgtagsfnodes1: size=120
+  $ f --size .hg/cache/hgtagsfnodes2
+  .hg/cache/hgtagsfnodes2: size=180
 
   $ echo dummy > foo
   $ hg commit -m throwaway3
@@ -465,13 +477,13 @@ 
 
   $ hg blackbox -l 6
   1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> tags
-  1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> writing 24 bytes to cache/hgtagsfnodes1
+  1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> writing 36 bytes to cache/hgtagsfnodes2
   1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> 3/4 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> writing .hg/cache/tags2-visible with 1 tags
   1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> tags exited 0 after * seconds (glob)
   1970/01/01 00:00:00 bob @035f65efb448350f4772141702a81ab1df48c465 (5000)> blackbox -l 6
-  $ f --size .hg/cache/hgtagsfnodes1
-  .hg/cache/hgtagsfnodes1: size=144
+  $ f --size .hg/cache/hgtagsfnodes2
+  .hg/cache/hgtagsfnodes2: size=216
 
   $ hg -q --config extensions.strip= strip -r 5 --no-backup
 
@@ -721,20 +733,23 @@ 
 
   $ ls tagsclient/.hg/cache
   branch2-base
-  hgtagsfnodes1
+  hgtagsfnodes2
   rbc-names-v1
   rbc-revs-v1
 
 Cache should contain the head only, even though other nodes have tags data
 
-  $ f --size --hexdump tagsclient/.hg/cache/hgtagsfnodes1
-  tagsclient/.hg/cache/hgtagsfnodes1: size=96
+  $ f --size --hexdump tagsclient/.hg/cache/hgtagsfnodes2
+  tagsclient/.hg/cache/hgtagsfnodes2: size=144
   0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
   0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
   0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
   0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-  0040: ff ff ff ff ff ff ff ff 40 f0 35 8c 19 e0 a7 d3 |........@.5.....|
-  0050: 8a 5c 6a 82 4d cf fb a5 87 d0 2f a3 1e 4f 2f 8a |.\j.M...../..O/.|
+  0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+  0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+  0060: ff ff ff ff ff ff ff ff ff ff ff ff 40 f0 35 8c |............@.5.|
+  0070: 19 e0 a7 d3 8a 5c 6a 82 4d cf fb a5 87 d0 2f a3 |.....\j.M...../.|
+  0080: 1e 4f 2f 8a 00 00 00 00 00 00 00 00 00 00 00 00 |.O/.............|
 
 Running hg tags should produce tags2* file and not change cache
 
@@ -745,19 +760,22 @@ 
 
   $ ls tagsclient/.hg/cache
   branch2-base
-  hgtagsfnodes1
+  hgtagsfnodes2
   rbc-names-v1
   rbc-revs-v1
   tags2-visible
 
-  $ f --size --hexdump tagsclient/.hg/cache/hgtagsfnodes1
-  tagsclient/.hg/cache/hgtagsfnodes1: size=96
+  $ f --size --hexdump tagsclient/.hg/cache/hgtagsfnodes2
+  tagsclient/.hg/cache/hgtagsfnodes2: size=144
   0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
   0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
   0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
   0030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
-  0040: ff ff ff ff ff ff ff ff 40 f0 35 8c 19 e0 a7 d3 |........@.5.....|
-  0050: 8a 5c 6a 82 4d cf fb a5 87 d0 2f a3 1e 4f 2f 8a |.\j.M...../..O/.|
+  0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+  0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+  0060: ff ff ff ff ff ff ff ff ff ff ff ff 40 f0 35 8c |............@.5.|
+  0070: 19 e0 a7 d3 8a 5c 6a 82 4d cf fb a5 87 d0 2f a3 |.....\j.M...../.|
+  0080: 1e 4f 2f 8a 00 00 00 00 00 00 00 00 00 00 00 00 |.O/.............|
 
 Check that the bundle includes cache data
 
diff --git a/tests/test-static-http.t b/tests/test-static-http.t
--- a/tests/test-static-http.t
+++ b/tests/test-static-http.t
@@ -230,7 +230,7 @@ 
   $ cat server.log | sed -n -e 's|.*GET \(/[^ ]*\).*|\1|p' | sort -u
   /.hg/bookmarks
   /.hg/bookmarks.current
-  /.hg/cache/hgtagsfnodes1
+  /.hg/cache/hgtagsfnodes2
   /.hg/cache/rbc-names-v1
   /.hg/cache/rbc-revs-v1
   /.hg/dirstate
@@ -247,7 +247,7 @@ 
   /remote-with-names/.hg/bookmarks
   /remote-with-names/.hg/bookmarks.current
   /remote-with-names/.hg/cache/branch2-served
-  /remote-with-names/.hg/cache/hgtagsfnodes1
+  /remote-with-names/.hg/cache/hgtagsfnodes2
   /remote-with-names/.hg/cache/rbc-names-v1
   /remote-with-names/.hg/cache/rbc-revs-v1
   /remote-with-names/.hg/cache/tags2-served
@@ -264,7 +264,7 @@ 
   /remote/.hg/cache/branch2-base
   /remote/.hg/cache/branch2-immutable
   /remote/.hg/cache/branch2-served
-  /remote/.hg/cache/hgtagsfnodes1
+  /remote/.hg/cache/hgtagsfnodes2
   /remote/.hg/cache/rbc-names-v1
   /remote/.hg/cache/rbc-revs-v1
   /remote/.hg/cache/tags2-served
@@ -287,7 +287,7 @@ 
   /remotempty/.hg/store/00manifest.i
   /sub/.hg/bookmarks
   /sub/.hg/bookmarks.current
-  /sub/.hg/cache/hgtagsfnodes1
+  /sub/.hg/cache/hgtagsfnodes2
   /sub/.hg/cache/rbc-names-v1
   /sub/.hg/cache/rbc-revs-v1
   /sub/.hg/dirstate
diff --git a/tests/test-server-view.t b/tests/test-server-view.t
--- a/tests/test-server-view.t
+++ b/tests/test-server-view.t
@@ -56,7 +56,7 @@ 
   branch2-served.hidden%89c45d2fa07e
   branch2-visible%89c45d2fa07e
   branch2-visible-hidden%89c45d2fa07e
-  hgtagsfnodes1
+  hgtagsfnodes2
   rbc-names-v1
   rbc-revs-v1
   tags2
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -1069,7 +1069,7 @@ 
    debugsuccessorssets
                  show set of successors for revision
    debugtagscache
-                 display the contents of .hg/cache/hgtagsfnodes1
+                 display the contents of .hg/cache/hgtagsfnodes2
    debugtemplate
                  parse and apply a template
    debuguigetpass
diff --git a/tests/test-debugcommands.t b/tests/test-debugcommands.t
--- a/tests/test-debugcommands.t
+++ b/tests/test-debugcommands.t
@@ -545,7 +545,7 @@ 
   .hg/cache/tags2
   .hg/cache/rbc-revs-v1
   .hg/cache/rbc-names-v1
-  .hg/cache/hgtagsfnodes1
+  .hg/cache/hgtagsfnodes2
   .hg/cache/branch2-visible-hidden
   .hg/cache/branch2-visible
   .hg/cache/branch2-served.hidden
diff --git a/tests/test-cache-abuse.t b/tests/test-cache-abuse.t
--- a/tests/test-cache-abuse.t
+++ b/tests/test-cache-abuse.t
@@ -70,7 +70,7 @@ 
 
   $ damage "tags --hidden" tags2
   $ damage tags tags2-visible
-  $ damage "tag -f t3" hgtagsfnodes1
+  $ damage "tag -f t3" hgtagsfnodes2
   1 new orphan changesets
   1 new orphan changesets
   1 new orphan changesets
diff --git a/mercurial/tags.py b/mercurial/tags.py
--- a/mercurial/tags.py
+++ b/mercurial/tags.py
@@ -36,7 +36,7 @@ 
 # Tags computation can be expensive and caches exist to make it fast in
 # the common case.
 #
-# The "hgtagsfnodes1" cache file caches the .hgtags filenode values for
+# The "hgtagsfnodes2" cache file caches the .hgtags filenode values for
 # each revision in the repository. The file is effectively an array of
 # fixed length records. Read the docs for "hgtagsfnodescache" for technical
 # details.
@@ -60,10 +60,10 @@ 
 #
 #   <tiprev> <tipnode> [<filteredhash>]
 #
-# <tiprev> is an integer revision and <tipnode> is a 40 character hex
+# <tiprev> is an integer revision and <tipnode> is a 40 or 64 character hex
 # node for that changeset. These redundantly identify the repository
 # tip from the time the cache was written. In addition, <filteredhash>,
-# if present, is a 40 character hex hash of the contents of the filtered
+# if present, is a 40 or 64 character hex hash of the contents of the filtered
 # revisions for this filter. If the set of filtered revs changes, the
 # hash will change and invalidate the cache.
 #
@@ -73,7 +73,7 @@ 
 #
 # (This format is identical to that of .hgtags files.)
 #
-# <tag> is the tag name and <node> is the 40 character hex changeset
+# <tag> is the tag name and <node> is the 40 or 64 character hex changeset
 # the tag is associated with.
 #
 # Tags are written sorted by tag name.
@@ -668,9 +668,9 @@ 
     return tagnode
 
 
-_fnodescachefile = b'hgtagsfnodes1'
-_fnodesrecsize = 4 + 20  # changeset fragment + filenode
-_fnodesmissingrec = b'\xff' * 24
+_fnodescachefile = b'hgtagsfnodes2'
+_fnodesrecsize = 4 + 32  # changeset fragment + filenode
+_fnodesmissingrec = b'\xff' * _fnodesrecsize
 
 
 class hgtagsfnodescache(object):
@@ -764,7 +764,7 @@ 
 
             if fileprefix == properprefix:
                 self.hitcount += 1
-                return record[4:]
+                return record[4 : len(node) + 4]
 
             # Fall through.
 
@@ -806,7 +806,7 @@ 
 
     def setfnode(self, node, fnode):
         """Set the .hgtags filenode for a given changeset."""
-        assert len(fnode) == 20
+        assert len(fnode) in (20, 32)
         ctx = self._repo[node]
 
         # Do a lookup first to avoid writing if nothing has changed.
@@ -817,7 +817,8 @@ 
 
     def _writeentry(self, offset, prefix, fnode):
         # Slices on array instances only accept other array.
-        entry = bytearray(prefix + fnode)
+        padding = _fnodesrecsize - len(prefix) - len(fnode)
+        entry = bytearray(prefix + fnode + b'\x00' * padding)
         self._raw[offset : offset + _fnodesrecsize] = entry
         # self._dirtyoffset could be None.
         self._dirtyoffset = min(self._dirtyoffset or 0, offset or 0)
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -3655,7 +3655,7 @@ 
 
 @command(b'debugtagscache', [])
 def debugtagscache(ui, repo):
-    """display the contents of .hg/cache/hgtagsfnodes1"""
+    """display the contents of .hg/cache/hgtagsfnodes2"""
     cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
     for r in repo:
         node = repo[r].node()
diff --git a/mercurial/cacheutil.py b/mercurial/cacheutil.py
--- a/mercurial/cacheutil.py
+++ b/mercurial/cacheutil.py
@@ -18,5 +18,5 @@ 
     cachefiles += [b'rbc-names-v1', b'rbc-revs-v1']
     cachefiles += [b'tags2']
     cachefiles += [b'tags2-%s' % f for f in repoview.filtertable]
-    cachefiles += [b'hgtagsfnodes1']
+    cachefiles += [b'hgtagsfnodes2']
     return cachefiles