[PATCH 1 of 5 V2 in-clowncopter] tags: don't read .hgtags fnodes from tags cache files

Pierre-Yves David pierre-yves.david at ens-lyon.org
Thu Apr 16 19:21:52 UTC 2015


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1429193564 14400
#      Thu Apr 16 10:12:44 2015 -0400
# Node ID 37b5afa2d72ee80ddc6d75fd47ac0ae101c423e8
# Parent  d5711c886d0b1acb2d18b92bf6e8ba6d9ad0c4b3
tags: don't read .hgtags fnodes from tags cache files

Now that we have a standalone and shared cache for .hgtags fnodes, the
.hgtags fnodes stored in the tags cache files are redundant.

Upcoming patches will change the format of the tags cache files to
remove this data and to improve the validation. To prepare for this, we
change the tags reading code to ignore all but the tip .hgtags fnodes
entries in existing tags cache files.

All fnodes lookups now go through our new shared cache, which is why
test output changed. Format of tags cache files has not yet changed.

diff --git a/mercurial/tags.py b/mercurial/tags.py
--- a/mercurial/tags.py
+++ b/mercurial/tags.py
@@ -276,39 +276,38 @@ def _readtagcache(ui, repo):
         # force reading the file for static-http
         cachelines = iter(cachefile)
     except IOError:
         cachefile = None
 
-    cacherevs = []  # list of headrev
-    cacheheads = [] # list of headnode
-    cachefnode = {} # map headnode to filenode
+    cachetiprev = None
+    cachetipnode = None
     if cachefile:
         try:
-            for line in cachelines:
+            for i, line in enumerate(cachelines):
+                # Getting the first line and consuming all fnode lines.
                 if line == "\n":
                     break
+                if i != 0:
+                    continue
+
                 line = line.split()
-                cacherevs.append(int(line[0]))
-                headnode = bin(line[1])
-                cacheheads.append(headnode)
-                if len(line) == 3:
-                    fnode = bin(line[2])
-                    cachefnode[headnode] = fnode
+                cachetiprev = int(line[0])
+                cachetipnode = bin(line[1])
         except Exception:
-            # corruption of the tags cache, just recompute it
-            cacheheads = []
-            cacherevs = []
-            cachefnode = {}
+            # corruption of the cache, just recompute it.
+            pass
 
     tipnode = repo.changelog.tip()
     tiprev = len(repo.changelog) - 1
 
     # Case 1 (common): tip is the same, so nothing has changed.
     # (Unchanged tip trivially means no changesets have been added.
     # But, thanks to localrepository.destroyed(), it also means none
     # have been destroyed by strip or rollback.)
-    if cacheheads and cacheheads[0] == tipnode and cacherevs[0] == tiprev:
+    if (cachetiprev is not None
+            and cachetiprev == tiprev
+            and cachetipnode == tipnode):
         tags = _readtags(ui, repo, cachelines, cachefile.name)
         cachefile.close()
         return (None, None, tags, False)
     if cachefile:
         cachefile.close()               # ignore rest of file
@@ -333,24 +332,21 @@ def _readtagcache(ui, repo):
     # N.B. in case 4 (nodes destroyed), "new head" really means "newly
     # exposed".
     if not len(repo.file('.hgtags')):
         # No tags have ever been committed, so we can avoid a
         # potentially expensive search.
-        return (repoheads, cachefnode, None, True)
+        return (repoheads, {}, None, True)
 
     starttime = time.time()
 
-    newheads = [head
-                for head in repoheads
-                if head not in set(cacheheads)]
-
     # Now we have to lookup the .hgtags filenode for every new head.
     # This is the most expensive part of finding tags, so performance
     # depends primarily on the size of newheads.  Worst case: no cache
     # file, so newheads == repoheads.
     fnodescache = hgtagsfnodescache(repo.unfiltered())
-    for head in reversed(newheads):
+    cachefnode = {}
+    for head in reversed(repoheads):
         fnode = fnodescache.getfnode(head)
         if fnode != nullid:
             cachefnode[head] = fnode
 
     fnodescache.write()
diff --git a/tests/test-tags.t b/tests/test-tags.t
--- a/tests/test-tags.t
+++ b/tests/test-tags.t
@@ -343,11 +343,11 @@ Extra junk data at the end should get ov
   bar                                1:78391a272241
 
   $ hg blackbox -l 5
   1970/01/01 00:00:00 bob> tags
   1970/01/01 00:00:00 bob> writing 24 bytes to cache/hgtagsfnodes1
-  1970/01/01 00:00:00 bob> 0/1 cache hits/lookups in * seconds (glob)
+  1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob> writing tags cache file with 3 heads and 1 tags
   1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
 
 #if unix-permissions no-root
 Errors writing to .hgtags fnodes cache are silently ignored
@@ -394,11 +394,11 @@ Stripping doesn't truncate the tags cach
   tip                                4:0c192d7d5e6b
   bar                                1:78391a272241
 
   $ hg blackbox -l 4
   1970/01/01 00:00:00 bob> tags
-  1970/01/01 00:00:00 bob> 1/1 cache hits/lookups in * seconds (glob)
+  1970/01/01 00:00:00 bob> 3/3 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob> writing tags cache file with 3 heads and 1 tags
   1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
 
   $ f --size .hg/cache/hgtagsfnodes1
   .hg/cache/hgtagsfnodes1: size=168
@@ -411,11 +411,11 @@ Stripping doesn't truncate the tags cach
   bar                                1:78391a272241
 
   $ hg blackbox -l 5
   1970/01/01 00:00:00 bob> tags
   1970/01/01 00:00:00 bob> writing 24 bytes to cache/hgtagsfnodes1
-  1970/01/01 00:00:00 bob> 0/1 cache hits/lookups in * seconds (glob)
+  1970/01/01 00:00:00 bob> 2/3 cache hits/lookups in * seconds (glob)
   1970/01/01 00:00:00 bob> writing tags cache file with 3 heads and 1 tags
   1970/01/01 00:00:00 bob> tags exited 0 after * seconds (glob)
   $ f --size .hg/cache/hgtagsfnodes1
   .hg/cache/hgtagsfnodes1: size=144
 


More information about the Mercurial-devel mailing list