changeset 44951:83e41b73d115

git: add debug logging when there's a mismatch in the cached heads list The dag rebuild can be expensive, so let's try and avoid bugs where it transparently rebuilds all the time for no reason. This would have prevented the issue fixed in D8622. Differential Revision: https://phab.mercurial-scm.org/D8625
author Augie Fackler <augie@google.com>
date Tue, 09 Jun 2020 17:13:26 -0400
parents f9734b2d59cc
children a4438263b228
files hgext/git/__init__.py hgext/git/gitlog.py hgext/git/index.py tests/test-git-interop.t
diffstat 4 files changed, 35 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/git/__init__.py	Wed Jun 10 13:02:39 2020 +0200
+++ b/hgext/git/__init__.py	Tue Jun 09 17:13:26 2020 -0400
@@ -16,6 +16,7 @@
     extensions,
     localrepo,
     pycompat,
+    registrar,
     scmutil,
     store,
     util,
@@ -28,6 +29,13 @@
     index,
 )
 
+configtable = {}
+configitem = registrar.configitem(configtable)
+# git.log-index-cache-miss: internal knob for testing
+configitem(
+    b"git", b"log-index-cache-miss", default=False,
+)
+
 # TODO: extract an interface for this in core
 class gitstore(object):  # store.basicstore):
     def __init__(self, path, vfstype):
@@ -41,13 +49,14 @@
             os.path.normpath(os.path.join(path, b'..', b'.git'))
         )
         self._progress_factory = lambda *args, **kwargs: None
+        self._logfn = lambda x: None
 
     @util.propertycache
     def _db(self):
         # We lazy-create the database because we want to thread a
         # progress callback down to the indexing process if it's
         # required, and we don't have a ui handle in makestore().
-        return index.get_index(self.git, self._progress_factory)
+        return index.get_index(self.git, self._logfn, self._progress_factory)
 
     def join(self, f):
         """Fake store.join method for git repositories.
@@ -276,6 +285,8 @@
     if repo.local() and isinstance(repo.store, gitstore):
         orig = repo.__class__
         repo.store._progress_factory = repo.ui.makeprogress
+        if ui.configbool(b'git', b'log-index-cache-miss'):
+            repo.store._logfn = repo.ui.warn
 
         class gitlocalrepo(orig):
             def _makedirstate(self):
--- a/hgext/git/gitlog.py	Wed Jun 10 13:02:39 2020 +0200
+++ b/hgext/git/gitlog.py	Tue Jun 09 17:13:26 2020 -0400
@@ -399,7 +399,7 @@
             'refs/hg/internal/latest-commit', oid, force=True
         )
         # Reindex now to pick up changes. We omit the progress
-        # callback because this will be very quick.
+        # and log callbacks because this will be very quick.
         index._index_repo(self.gitrepo, self._db)
         return oid.raw
 
--- a/hgext/git/index.py	Wed Jun 10 13:02:39 2020 +0200
+++ b/hgext/git/index.py	Tue Jun 09 17:13:26 2020 -0400
@@ -216,7 +216,12 @@
     db.commit()
 
 
-def _index_repo(gitrepo, db, progress_factory=lambda *args, **kwargs: None):
+def _index_repo(
+    gitrepo,
+    db,
+    logfn=lambda x: None,
+    progress_factory=lambda *args, **kwargs: None,
+):
     # Identify all references so we can tell the walker to visit all of them.
     all_refs = gitrepo.listall_references()
     possible_heads = set()
@@ -253,6 +258,7 @@
     cur_cache_heads = {h.hex for h in possible_heads}
     if cur_cache_heads == cache_heads:
         return
+    logfn(b'heads mismatch, rebuilding dagcache\n')
     for start in possible_heads:
         if walker is None:
             walker = gitrepo.walk(start, _OUR_ORDER)
@@ -339,7 +345,9 @@
         prog.complete()
 
 
-def get_index(gitrepo, progress_factory=lambda *args, **kwargs: None):
+def get_index(
+    gitrepo, logfn=lambda x: None, progress_factory=lambda *args, **kwargs: None
+):
     cachepath = os.path.join(
         pycompat.fsencode(gitrepo.path), b'..', b'.hg', b'cache'
     )
@@ -349,5 +357,5 @@
     db = _createdb(dbpath)
     # TODO check against gitrepo heads before doing a full index
     # TODO thread a ui.progress call into this layer
-    _index_repo(gitrepo, db, progress_factory)
+    _index_repo(gitrepo, db, logfn, progress_factory)
     return db
--- a/tests/test-git-interop.t	Wed Jun 10 13:02:39 2020 +0200
+++ b/tests/test-git-interop.t	Tue Jun 09 17:13:26 2020 -0400
@@ -36,8 +36,12 @@
   $ cd ..
 
 Now globally enable extension for the rest of the test:
-  $ echo "[extensions]" >> $HGRCPATH
-  > echo "git=" >> $HGRCPATH
+  $ cat <<EOF >> $HGRCPATH
+  > [extensions]
+  > git=
+  > [git]
+  > log-index-cache-miss = yes
+  > EOF
 
 Make a new repo with git:
   $ mkdir foo
@@ -68,6 +72,7 @@
 But if you run hg init --git, it works:
   $ hg init --git
   $ hg id --traceback
+  heads mismatch, rebuilding dagcache
   3d9be8deba43 tip master
   $ hg status
   ? gamma
@@ -167,9 +172,12 @@
   $ hg ci -m 'more alpha' --traceback --date '1583522787 18000'
   $ echo b >> beta
   $ hg ci -m 'more beta'
+  heads mismatch, rebuilding dagcache
   $ echo a >> alpha
   $ hg ci -m 'even more alpha'
+  heads mismatch, rebuilding dagcache
   $ hg log -G alpha
+  heads mismatch, rebuilding dagcache
   @  changeset:   4:6626247b7dc8
   :  bookmark:    master
   :  tag:         tip
@@ -238,6 +246,7 @@
   On branch master
   nothing to commit, working tree clean
   $ hg status
+  heads mismatch, rebuilding dagcache
 
 
 node|shortest works correctly