dependencies of entries vs. sessions;
authorwenzelm
Mon, 09 Oct 2017 20:26:02 +0200
changeset 66821 c0e8c199cb2e
parent 66820 fc516da7ee4f
child 66822 4642cf4a7ebb
dependencies of entries vs. sessions; json output like "isabelle afp_dependencies"; misc tuning;
src/Pure/Admin/afp.scala
--- a/src/Pure/Admin/afp.scala	Mon Oct 09 17:09:08 2017 +0200
+++ b/src/Pure/Admin/afp.scala	Mon Oct 09 20:26:02 2017 +0200
@@ -9,24 +9,78 @@
 
 object AFP
 {
-  sealed case class Entry(name: String, sessions: List[String])
+  def init(base_dir: Path = Path.explode("$AFP_BASE")): AFP =
+    new AFP(base_dir)
 
-  def init(base_dir: Path = Path.explode("$AFP_BASE")): AFP = new AFP(base_dir)
+  sealed case class Entry(name: String, sessions: List[String])
+  {
+    def sessions_deps(afp_sessions: Sessions.T): List[String] =
+      sessions.flatMap(afp_sessions.imports_graph.imm_preds(_)).distinct.sorted
+  }
 }
 
 class AFP private(val base_dir: Path)
 {
+  override def toString: String = base_dir.expand.toString
+
   val main_dir: Path = base_dir + Path.explode("thys")
 
+
+  /* entries and sessions */
+
   val entries: List[AFP.Entry] =
-    (for (name <- Sessions.parse_roots(main_dir + Sessions.ROOTS))
-    yield {
+    (for (name <- Sessions.parse_roots(main_dir + Sessions.ROOTS)) yield {
       val sessions =
         Sessions.parse_root_entries(main_dir + Path.explode(name) + Sessions.ROOT).map(_.name)
       AFP.Entry(name, sessions)
     }).sortBy(_.name)
 
-  val sessions: List[String] = entries.flatMap(_.sessions).sorted
+  val sessions: List[String] = entries.flatMap(_.sessions)
+  val sessions_set: Set[String] = sessions.toSet
+
+
+  /* dependencies */
+
+  def dependencies(options: Options): Dependencies =
+  {
+    val (_, afp_sessions) =
+      Sessions.load(options, dirs = List(main_dir)).
+        selection(Sessions.Selection(sessions = sessions.toList))
+
+    val session_entries =
+      (Multi_Map.empty[String, String] /: entries) { case (m1, e) =>
+        (m1 /: e.sessions) { case (m2, s) => m2.insert(s, e.name) }
+      }
 
-  override def toString: String = base_dir.expand.toString
+    val entries_graph: Graph[String, Unit] =
+      (Graph.empty[String, Unit] /: entries) { case (g, e1) =>
+        val name1 = e1.name
+        val g1 = g.default_node(name1, ())
+        (g1 /: e1.sessions_deps(afp_sessions)) { case (g2, s2) =>
+          (g2 /: session_entries.get_list(s2)) { case (g3, name2) =>
+            if (name1 == name2) g3 else g3.default_node(name2, ()).add_edge(name2, name1)
+          }
+        }
+      }
+
+    new Dependencies(afp_sessions, entries_graph)
+  }
+
+  final class Dependencies private [AFP](
+    val afp_sessions: Sessions.T,
+    val entries_graph: Graph[String, Unit])
+  {
+    def entries_json_text: String =
+      (for (entry <- entries)
+      yield {
+        val distrib_deps = entry.sessions_deps(afp_sessions).filterNot(sessions_set)
+        val afp_deps = entries_graph.imm_preds(entry.name).toList
+        """
+ {""" + JSON.Format(entry.name) + """:
+  {"distrib_deps": """ + JSON.Format(distrib_deps) + """,
+   "afp_deps": """ + JSON.Format(afp_deps) + """
+  }
+ }"""
+      }).mkString("[", ", ", "\n]\n")
+  }
 }