Hi there,
So I believe I have a resolution for TNS-6 in clojure.tools.namespace. I have a consistent repro and a resolution in the form of a one-line patch (see the patch for more detail). All the tests still pass, though I'm not sure they cover the changes. I have also tested the resolution in a number of local dependent repos, and it resolves the issue.
However, I am not a Clojure contributor so I cannot comment or submitt the patch or comment on relevant Jira ticket.
From b5a62f894e049a09d5fcf099ac7b4d6591fb4f18 Mon Sep 17 00:00:00 2001
From: zalky <zalan.k@gmail.com>
Date: Mon, 24 May 2021 13:08:30 -0400
Subject: [PATCH] Fix TNS-6: fully remove ns from deps graph
The clojure.tools.namespace.dependency/remove-node fn removes a
namespace's :dependencies set from the graph (outgoing edges), but
does not remove that namespace from the :dependents set of other
namespaces (ingoing edges). If a namespace is removed and one of its
dependencies is changed at the same time, as commonly occurs when
switching branches, then the removed namespace is still in the
:dependents of the changed namespace when it is reloaded. As all the
of the dependents of a changed namespace are also reloaded, this
throws a missing namespace error.
The resolution is to use clojure.tools.namespace.depedency/remove-all
to remove both outgoing (:dependencies) and ingoing (:dependents)
edges in the dependency graph.
However, care must be taken when choosing the point of change, because
clojure.tools.namespace.track/add relies on the partial removal
behaviour of clojure.tools.namespace.track/remove-deps. It uses
remove-deps to wipe the dependencies of a node, and cannot know how to
re-insert dependents if lost. Therefore the point of change should be
in clojure.tools.namespace.track/remove.
---
src/main/clojure/clojure/tools/namespace/track.cljc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/clojure/clojure/tools/namespace/track.cljc b/src/main/clojure/clojure/tools/namespace/track.cljc
index 683c35d..ce666d5 100644
--- a/src/main/clojure/clojure/tools/namespace/track.cljc
+++ b/src/main/clojure/clojure/tools/namespace/track.cljc
@@ -96,7 +96,7 @@
:or {load (), unload (), deps (dep/graph)}} tracker
known (set (dep/nodes deps))
removed-names (filter known names)
- new-deps (remove-deps deps removed-names)
+ new-deps (reduce dep/remove-all deps removed-names)
changed (affected-namespaces deps removed-names)]
(assoc tracker
::deps new-deps
--
2.30.1 (Apple Git-130)
[Patch updated after further testing]