branching: merge stable into default
authorPierre-Yves David <pierre-yves.david@octobus.net>
Fri, 14 Sep 2018 10:47:57 +0200
changeset 4110 b3b861a7f6f7
parent 4108 ef3c9ecb8099 (current diff)
parent 4109 d562316c548f (diff)
child 4118 d3ea35ad88f3
branching: merge stable into default
--- a/CHANGELOG	Thu Sep 13 00:04:17 2018 +0800
+++ b/CHANGELOG	Fri Sep 14 10:47:57 2018 +0200
@@ -1,7 +1,14 @@
 Changelog
 =========
 
-8.1.2 -- 2018-09-03
+8.2.1 - in progress
+-------------------
+
+  * obshashrange: issue the "long stable cache" update message only once
+  * obshashrange: reduce impact of cache invalidation from many new obsmarkers
+  * caches: properly silence permission error related to caches
+
+8.2.0 -- 2018-09-03
 -------------------
 
   * prune: rename `--biject` flag to `--pair` (old flag is kept as an alias)
--- a/hgext3rd/evolve/depthcache.py	Thu Sep 13 00:04:17 2018 +0800
+++ b/hgext3rd/evolve/depthcache.py	Fri Sep 14 10:47:57 2018 +0200
@@ -198,9 +198,14 @@
         if self._cachekey is None or self._cachekey == self._ondiskkey:
             return
 
-        cachevfs = compat.getcachevfs(repo)
-        cachefile = cachevfs(self._filepath, 'w', atomictemp=True)
-        headerdata = self._serializecachekey()
-        cachefile.write(headerdata)
-        cachefile.write(self._data.tostring())
-        cachefile.close()
+        try:
+            cachevfs = compat.getcachevfs(repo)
+            cachefile = cachevfs(self._filepath, 'w', atomictemp=True)
+            headerdata = self._serializecachekey()
+            cachefile.write(headerdata)
+            cachefile.write(self._data.tostring())
+            cachefile.close()
+            self._ondiskkey = self._cachekey
+        except (IOError, OSError) as exc:
+            repo.ui.log('depthcache', 'could not write update %s\n' % exc)
+            repo.ui.debug('depthcache: could not write update %s\n' % exc)
--- a/hgext3rd/evolve/evolvecmd.py	Thu Sep 13 00:04:17 2018 +0800
+++ b/hgext3rd/evolve/evolvecmd.py	Fri Sep 14 10:47:57 2018 +0200
@@ -355,7 +355,7 @@
     # we don't handle split in content-divergence yet
     if len(others) > 1:
         othersstr = "[%s]" % (','.join([str(i) for i in others]))
-        msg = _("skipping %d:%s with a changeset that got split"
+        msg = _("skipping %s: %s with a changeset that got split"
                 " into multiple ones:\n"
                 "|[%s]\n"
                 "| This is not handled by automatic evolution yet\n"
--- a/hgext3rd/evolve/firstmergecache.py	Thu Sep 13 00:04:17 2018 +0800
+++ b/hgext3rd/evolve/firstmergecache.py	Fri Sep 14 10:47:57 2018 +0200
@@ -135,9 +135,14 @@
         if self._cachekey is None or self._cachekey == self._ondiskkey:
             return
 
-        cachevfs = compat.getcachevfs(repo)
-        cachefile = cachevfs(self._filepath, 'w', atomictemp=True)
-        headerdata = self._serializecachekey()
-        cachefile.write(headerdata)
-        cachefile.write(self._data.tostring())
-        cachefile.close()
+        try:
+            cachevfs = compat.getcachevfs(repo)
+            cachefile = cachevfs(self._filepath, 'w', atomictemp=True)
+            headerdata = self._serializecachekey()
+            cachefile.write(headerdata)
+            cachefile.write(self._data.tostring())
+            cachefile.close()
+            self._ondiskkey = self._cachekey
+        except (IOError, OSError) as exc:
+            repo.ui.log('firstmergecache', 'could not write update %s\n' % exc)
+            repo.ui.debug('firstmergecache: could not write update %s\n' % exc)
--- a/hgext3rd/evolve/obscache.py	Thu Sep 13 00:04:17 2018 +0800
+++ b/hgext3rd/evolve/obscache.py	Fri Sep 14 10:47:57 2018 +0200
@@ -404,11 +404,16 @@
         if self._cachekey is None or self._cachekey == self._ondiskkey:
             return
 
-        cachefile = self._vfs(self._filepath, 'w', atomictemp=True)
-        headerdata = struct.pack(self._headerformat, *self._cachekey)
-        cachefile.write(headerdata)
-        cachefile.write(self._data)
-        cachefile.close()
+        try:
+            cachefile = self._vfs(self._filepath, 'w', atomictemp=True)
+            headerdata = struct.pack(self._headerformat, *self._cachekey)
+            cachefile.write(headerdata)
+            cachefile.write(self._data)
+            cachefile.close()
+            self._ondiskkey = self._cachekey
+        except (IOError, OSError) as exc:
+            repo.ui.log('obscache', 'could not write update %s\n' % exc)
+            repo.ui.debug('obscache: could not write update %s\n' % exc)
 
     def load(self, repo):
         """load data from disk"""
--- a/hgext3rd/evolve/obsdiscovery.py	Thu Sep 13 00:04:17 2018 +0800
+++ b/hgext3rd/evolve/obsdiscovery.py	Fri Sep 14 10:47:57 2018 +0200
@@ -397,6 +397,9 @@
 
     return affected_nodes
 
+# if there is that many new obsmarkers, reset without analysing them
+RESET_ABOVE = 10000
+
 class _obshashcache(obscache.dualsourcecache):
 
     _schemaversion = 3
@@ -470,23 +473,43 @@
 
         con = self._con
         if con is not None:
-            max_stored = con.execute(_query_max_stored).fetchall()[0][0]
-            affected_nodes = _affectedby(repo, obsmarkers)
+            reset = False
+            affected = []
+            if RESET_ABOVE < len(obsmarkers):
+                # lots of new obsmarkers, probably smarter to reset the cache
+                repo.ui.log('evoext-cache', 'obshashcache reset - '
+                            'many new markers (%d)\n'
+                            % len(obsmarkers))
+                reset = True
+            elif obsmarkers:
+                max_stored = con.execute(_query_max_stored).fetchall()[0][0]
+                affected_nodes = _affectedby(repo, obsmarkers)
 
-            rev = repo.changelog.nodemap.get
-            affected = [rev(n) for n in affected_nodes]
-            affected = [r for r in affected
-                        if r is not None and r <= max_stored]
+                rev = repo.changelog.nodemap.get
+                affected = [rev(n) for n in affected_nodes]
+                affected = [r for r in affected
+                            if r is not None and r <= max_stored]
 
-            if affected:
-                repo.ui.log('evoext-cache', 'obshashcache clean - '
-                            'new markers affect %d changeset and cached ranges\n'
+            if RESET_ABOVE < len(affected):
+                repo.ui.log('evoext-cache', 'obshashcache reset - '
+                            'new markers affect many changeset (%d)\n'
                             % len(affected))
+                reset = True
+
+            if affected or reset:
+                if not reset:
+                    repo.ui.log('evoext-cache', 'obshashcache clean - '
+                                'new markers affect %d changeset and cached ranges\n'
+                                % len(affected))
                 if con is not None:
                     # always reset for now, the code detecting affect is buggy
                     # so we need to reset more broadly than we would like.
                     try:
                         if repo.stablerange._con is None:
+                            repo.ui.log('evoext-cache', 'obshashcache reset - '
+                                        'underlying stablerange cache unavailable\n')
+                            reset = True
+                        if reset:
                             con.execute(_reset)
                             self._data.clear()
                         else:
@@ -589,7 +612,7 @@
             return
         try:
             return self._trysave(repo)
-        except (sqlite3.DatabaseError, sqlite3.OperationalError, sqlite3.IntegrityError) as exc:
+        except (IOError, OSError, sqlite3.DatabaseError, sqlite3.OperationalError, sqlite3.IntegrityError) as exc:
             # Catch error that may arise under stress
             #
             # operational error catch read-only and locked database
@@ -598,6 +621,7 @@
                 del self._con
             self._new.clear()
             repo.ui.log('evoext-cache', 'error while saving new data: %s' % exc)
+            repo.ui.debug('evoext-cache: error while saving new data: %s' % exc)
 
     def _trysave(self, repo):
         if self._con is None:
--- a/hgext3rd/evolve/rewind.py	Thu Sep 13 00:04:17 2018 +0800
+++ b/hgext3rd/evolve/rewind.py	Fri Sep 14 10:47:57 2018 +0200
@@ -27,49 +27,49 @@
 
 @eh.command(
     '^rewind',
-    [('', 'to', [], _("rewind to these revision")),
+    [('', 'to', [], _("rewind to these revisions")),
      ('', 'as-divergence', None, _("preserve current latest successors")),
      ('', 'exact', None, _("only rewind explicitly selected revisions")),
      ('', 'from', [], _("rewind these revisions to their predecessors")),
     ],
     _(''))
 def rewind(ui, repo, **opts):
-    """rewind stacks of changeset to a previous content
+    """rewind a stack of changesets to a previous state
 
     This command can be used to restore stacks of changesets to an obsolete
-    state, creating identical identical copies.
+    state, creating identical copies.
 
-    There are two mains way to select the rewind target. Rewinding "from"
-    changesets will restore the direct precursors of theses changesets (and
+    There are two main ways to select the rewind target. Rewinding "from"
+    changesets will restore the direct predecessors of these changesets (and
     obsolete the changeset you rewind from). Rewinding "to" will restore the
     changeset you have selected (and obsolete their latest successors).
 
     By default, we rewind from the working copy parents, restoring its
-    precursor.
+    predecessor.
 
     When we rewind to an obsolete version, we also rewind to all its obsolete
-    ancestors. To only rewind to the explicitly selection changesets use the
+    ancestors. To only rewind to the explicitly selected changesets use the
     `--exact` flag. Using the `--exact` flag can restore some changesets as
     orphan.
 
-    The latest successors the obsolete changesets will be superseed by these
-    new copies. This behavior can be disabled using `--as-divergence`, the
-    current latest successors won't be affected and content-divergence will
-    appears between them and the restored version of the obsolete changesets.
+    The latest successors of the obsolete changesets will be superseded by
+    these new copies. This behavior can be disabled using `--as-divergence`,
+    the current latest successors won't be affected and content-divergence will
+    appear between them and the restored version of the obsolete changesets.
 
-    Current rought edges:
+    Current rough edges:
 
       * fold: rewinding to only some of the initially folded changesets will be
               problematic. The fold result is marked obsolete and the part not
-              rewinded too are "lost".  Please use --as-divergence when you
+              rewinded to are "lost".  Please use --as-divergence when you
               need to perform such operation.
 
-      * :hg:`rewind` might affect changeset outside the current stack. Without --exact, we
-              also restore ancestors of the rewind target, obsoleting their
-              latest successors (unless --as-divergent is provided). In some
-              case, these latest successors will be on branches unrelated to
-              the changeset you rewind from.
-              (We plan to automatically detect this cases in the future)
+      * :hg:`rewind` might affect changesets outside the current stack. Without
+              --exact, we also restore ancestors of the rewind target,
+              obsoleting their latest successors (unless --as-divergent is
+              provided). In some case, these latest successors will be on
+              branches unrelated to the changeset you rewind from.
+              (We plan to automatically detect this case in the future)
 
     """
     unfi = repo.unfiltered()
--- a/hgext3rd/evolve/stablerangecache.py	Thu Sep 13 00:04:17 2018 +0800
+++ b/hgext3rd/evolve/stablerangecache.py	Fri Sep 14 10:47:57 2018 +0200
@@ -94,6 +94,7 @@
                     progress_new = time.time()
                     if not warned_long and LONG_WARNING_TIME < (progress_new - initial_time):
                         repo.ui.warn(LONG_MESSAGE)
+                        warned_long = True
                     if (1 < progress_each) and (0.1 < progress_new - progress_last):
                         progress_each /= 10
                     ui.progress(_("filling stablerange cache"), seen,
@@ -265,7 +266,7 @@
             return
         try:
             return self._trysave(repo)
-        except (sqlite3.DatabaseError, sqlite3.OperationalError, sqlite3.IntegrityError) as exc:
+        except (IOError, OSError, sqlite3.DatabaseError, sqlite3.OperationalError, sqlite3.IntegrityError) as exc:
             # Catch error that may arise under stress
             #
             # operational error catch read-only and locked database
@@ -274,6 +275,7 @@
                 del self._con
             self._unsavedsubranges.clear()
             repo.ui.log('evoext-cache', 'error while saving new data: %s' % exc)
+            repo.ui.debug('evoext-cache: error while saving new data: %s' % exc)
 
     def _trysave(self, repo):
         repo = repo.unfiltered()
--- a/hgext3rd/evolve/stablesort.py	Thu Sep 13 00:04:17 2018 +0800
+++ b/hgext3rd/evolve/stablesort.py	Fri Sep 14 10:47:57 2018 +0200
@@ -634,21 +634,26 @@
         """
         if self._cachekey is None or self._cachekey == self._ondiskkey:
             return
-        cachevfs = compat.getcachevfs(repo)
-        cachefile = cachevfs(self._filepath, 'w', atomictemp=True)
+        try:
+            cachevfs = compat.getcachevfs(repo)
+            cachefile = cachevfs(self._filepath, 'w', atomictemp=True)
+
+            # data to write
+            headerdata = self._serializecachekey()
+            indexdata = self._index.tostring()
+            data = self._data.tostring()
+            indexsize = S_INDEXSIZE.pack(len(indexdata))
 
-        # data to write
-        headerdata = self._serializecachekey()
-        indexdata = self._index.tostring()
-        data = self._data.tostring()
-        indexsize = S_INDEXSIZE.pack(len(indexdata))
-
-        # writing
-        cachefile.write(headerdata)
-        cachefile.write(indexsize)
-        cachefile.write(indexdata)
-        cachefile.write(data)
-        cachefile.close()
+            # writing
+            cachefile.write(headerdata)
+            cachefile.write(indexsize)
+            cachefile.write(indexdata)
+            cachefile.write(data)
+            cachefile.close()
+            self._ondiskkey = self._cachekey
+        except (IOError, OSError) as exc:
+            repo.ui.log('stablesortcache', 'could not write update %s\n' % exc)
+            repo.ui.debug('stablesortcache: could not write update %s\n' % exc)
 
 @eh.reposetup
 def setupcache(ui, repo):