From 55f5afaf3c5369ef80d111f2323da5bb496abc9d Mon Sep 17 00:00:00 2001
From: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Date: Sun, 12 Apr 2020 22:14:59 +0200
Subject: [PATCH] database: maintain in-memory consistency on remove (#15777)

The performance improvements done in #14693 where leaving the DB in an inconsistent state when specs were removed from it. This PR updates the DB internal state whenever the DB is written to a file.

Note that we still cannot properly enumerate installed dependents, so there is a TODO in this code. Fixing that will require the dependents dictionaries in specs to be re-keyed (either by hash, or not keyed at all -- a list would do).  See #11983 for details.
---
 lib/spack/spack/database.py           |  6 ++++++
 lib/spack/spack/test/cmd/uninstall.py | 16 +++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/lib/spack/spack/database.py b/lib/spack/spack/database.py
index ca9ed67fb5..001f96d1ff 100644
--- a/lib/spack/spack/database.py
+++ b/lib/spack/spack/database.py
@@ -1128,6 +1128,12 @@ def _remove(self, spec):
 
         del self._data[key]
         for dep in rec.spec.dependencies(_tracked_deps):
+            # FIXME: the two lines below needs to be updated once #11983 is
+            # FIXME: fixed. The "if" statement should be deleted and specs are
+            # FIXME: to be removed from dependents by hash and not by name.
+            # FIXME: See https://github.com/spack/spack/pull/15777#issuecomment-607818955
+            if dep._dependents.get(spec.name):
+                del dep._dependents[spec.name]
             self._decrement_ref_count(dep)
 
         if rec.deprecated_for:
diff --git a/lib/spack/spack/test/cmd/uninstall.py b/lib/spack/spack/test/cmd/uninstall.py
index 882f075ec7..a5adcdc74b 100644
--- a/lib/spack/spack/test/cmd/uninstall.py
+++ b/lib/spack/spack/test/cmd/uninstall.py
@@ -4,6 +4,7 @@
 # SPDX-License-Identifier: (Apache-2.0 OR MIT)
 
 import pytest
+import llnl.util.tty as tty
 import spack.store
 from spack.main import SpackCommand, SpackCommandError
 
@@ -30,7 +31,7 @@ def test_multiple_matches(mutable_database):
 
 @pytest.mark.db
 def test_installed_dependents(mutable_database):
-    """Test can't uninstall when ther are installed dependents."""
+    """Test can't uninstall when there are installed dependents."""
     with pytest.raises(SpackCommandError):
         uninstall('-y', 'libelf')
 
@@ -155,3 +156,16 @@ def db_specs():
     assert len(mpileaks_specs) == 3
     assert len(callpath_specs) == 3  # back to 3
     assert len(mpi_specs) == 3
+
+
+@pytest.mark.db
+@pytest.mark.regression('15773')
+def test_in_memory_consistency_when_uninstalling(
+        mutable_database, monkeypatch
+):
+    """Test that uninstalling doesn't raise warnings"""
+    def _warn(*args, **kwargs):
+        raise RuntimeError('a warning was triggered!')
+    monkeypatch.setattr(tty, 'warn', _warn)
+    # Now try to uninstall and check this doesn't trigger warnings
+    uninstall('-y', '-a')
-- 
GitLab