src/Pure/Thy/export.scala
author wenzelm
Fri, 20 Nov 2020 23:47:34 +0100
changeset 72669 5e7916535860
parent 72634 5cea0993ee4f
child 72682 e0443773ef1a
permissions -rw-r--r--
generate theory HTML in Isabelle/Scala; discontinued HTML support in Isabelle/ML;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/Thy/export.scala
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
     3
68102
813b5d0904c6 clarified signature;
wenzelm
parents: 68101
diff changeset
     4
Manage theory exports: compressed blobs.
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
     5
*/
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
     6
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
     7
package isabelle
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
     8
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
     9
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    10
import scala.annotation.tailrec
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    11
import scala.util.matching.Regex
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    12
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    13
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    14
object Export
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    15
{
69756
1907222d974e clarified modules;
wenzelm
parents: 69671
diff changeset
    16
  /* name structure */
69634
70f1994988d4 more operations;
wenzelm
parents: 69630
diff changeset
    17
69756
1907222d974e clarified modules;
wenzelm
parents: 69671
diff changeset
    18
  def explode_name(s: String): List[String] = space_explode('/', s)
1907222d974e clarified modules;
wenzelm
parents: 69671
diff changeset
    19
  def implode_name(elems: Iterable[String]): String = elems.mkString("/")
69634
70f1994988d4 more operations;
wenzelm
parents: 69630
diff changeset
    20
70f1994988d4 more operations;
wenzelm
parents: 69630
diff changeset
    21
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    22
  /* SQL data model */
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    23
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    24
  object Data
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    25
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    26
    val session_name = SQL.Column.string("session_name").make_primary_key
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    27
    val theory_name = SQL.Column.string("theory_name").make_primary_key
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    28
    val name = SQL.Column.string("name").make_primary_key
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
    29
    val executable = SQL.Column.bool("executable")
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    30
    val compressed = SQL.Column.bool("compressed")
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    31
    val body = SQL.Column.bytes("body")
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    32
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    33
    val table =
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
    34
      SQL.Table("isabelle_exports",
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
    35
        List(session_name, theory_name, name, executable, compressed, body))
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    36
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    37
    def where_equal(session_name: String, theory_name: String = "", name: String = ""): SQL.Source =
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    38
      "WHERE " + Data.session_name.equal(session_name) +
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    39
        (if (theory_name == "") "" else " AND " + Data.theory_name.equal(theory_name)) +
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    40
        (if (name == "") "" else " AND " + Data.name.equal(name))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    41
  }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    42
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    43
  def read_name(db: SQL.Database, session_name: String, theory_name: String, name: String): Boolean =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    44
  {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    45
    val select =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    46
      Data.table.select(List(Data.name), Data.where_equal(session_name, theory_name, name))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    47
    db.using_statement(select)(stmt => stmt.execute_query().next())
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    48
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    49
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    50
  def read_names(db: SQL.Database, session_name: String, theory_name: String): List[String] =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    51
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    52
    val select = Data.table.select(List(Data.name), Data.where_equal(session_name, theory_name))
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    53
    db.using_statement(select)(stmt =>
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    54
      stmt.execute_query().iterator(res => res.string(Data.name)).toList)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    55
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    56
68222
3c1a716e7f59 tuned queries;
wenzelm
parents: 68221
diff changeset
    57
  def read_theory_names(db: SQL.Database, session_name: String): List[String] =
3c1a716e7f59 tuned queries;
wenzelm
parents: 68221
diff changeset
    58
  {
3c1a716e7f59 tuned queries;
wenzelm
parents: 68221
diff changeset
    59
    val select =
3c1a716e7f59 tuned queries;
wenzelm
parents: 68221
diff changeset
    60
      Data.table.select(List(Data.theory_name), Data.where_equal(session_name), distinct = true)
3c1a716e7f59 tuned queries;
wenzelm
parents: 68221
diff changeset
    61
    db.using_statement(select)(stmt =>
3c1a716e7f59 tuned queries;
wenzelm
parents: 68221
diff changeset
    62
      stmt.execute_query().iterator(_.string(Data.theory_name)).toList)
3c1a716e7f59 tuned queries;
wenzelm
parents: 68221
diff changeset
    63
  }
3c1a716e7f59 tuned queries;
wenzelm
parents: 68221
diff changeset
    64
3c1a716e7f59 tuned queries;
wenzelm
parents: 68221
diff changeset
    65
  def read_theory_exports(db: SQL.Database, session_name: String): List[(String, String)] =
68115
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    66
  {
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    67
    val select = Data.table.select(List(Data.theory_name, Data.name), Data.where_equal(session_name))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    68
    db.using_statement(select)(stmt =>
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    69
      stmt.execute_query().iterator(res =>
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    70
        (res.string(Data.theory_name), res.string(Data.name))).toList)
68115
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    71
  }
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    72
68104
wenzelm
parents: 68103
diff changeset
    73
  def message(msg: String, theory_name: String, name: String): String =
wenzelm
parents: 68103
diff changeset
    74
    msg + " " + quote(name) + " for theory " + quote(theory_name)
wenzelm
parents: 68103
diff changeset
    75
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    76
  def compound_name(a: String, b: String): String = a + ":" + b
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    77
72634
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
    78
  def empty_entry(session_name: String, theory_name: String, name: String): Entry =
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
    79
    Entry(session_name, theory_name, name, false, Future.value(false, Bytes.empty))
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
    80
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    81
  sealed case class Entry(
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    82
    session_name: String,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    83
    theory_name: String,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    84
    name: String,
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
    85
    executable: Boolean,
68167
327bb0f5f768 clarified implicit compression;
wenzelm
parents: 68166
diff changeset
    86
    body: Future[(Boolean, Bytes)])
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    87
  {
69635
95dc926fa39c clarified output (again);
wenzelm
parents: 69634
diff changeset
    88
    override def toString: String = name
69630
aaa0b5f571e8 clarified output;
wenzelm
parents: 69629
diff changeset
    89
71141
b1c555d3cd71 tuned signature -- more operations;
wenzelm
parents: 71014
diff changeset
    90
    def compound_name: String = Export.compound_name(theory_name, name)
b1c555d3cd71 tuned signature -- more operations;
wenzelm
parents: 71014
diff changeset
    91
69634
70f1994988d4 more operations;
wenzelm
parents: 69630
diff changeset
    92
    val name_elems: List[String] = explode_name(name)
70f1994988d4 more operations;
wenzelm
parents: 69630
diff changeset
    93
70f1994988d4 more operations;
wenzelm
parents: 69630
diff changeset
    94
    def name_extends(elems: List[String]): Boolean =
70f1994988d4 more operations;
wenzelm
parents: 69630
diff changeset
    95
      name_elems.startsWith(elems) && name_elems != elems
70f1994988d4 more operations;
wenzelm
parents: 69630
diff changeset
    96
69630
aaa0b5f571e8 clarified output;
wenzelm
parents: 69629
diff changeset
    97
    def text: String = uncompressed().text
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    98
69629
wenzelm
parents: 68924
diff changeset
    99
    def uncompressed(cache: XZ.Cache = XZ.cache()): Bytes =
wenzelm
parents: 68924
diff changeset
   100
    {
wenzelm
parents: 68924
diff changeset
   101
      val (compressed, bytes) = body.join
wenzelm
parents: 68924
diff changeset
   102
      if (compressed) bytes.uncompress(cache = cache) else bytes
wenzelm
parents: 68924
diff changeset
   103
    }
wenzelm
parents: 68924
diff changeset
   104
wenzelm
parents: 68924
diff changeset
   105
    def uncompressed_yxml(cache: XZ.Cache = XZ.cache()): XML.Body =
wenzelm
parents: 68924
diff changeset
   106
      YXML.parse_body(UTF8.decode_permissive(uncompressed(cache = cache)))
wenzelm
parents: 68924
diff changeset
   107
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   108
    def write(db: SQL.Database)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   109
    {
68167
327bb0f5f768 clarified implicit compression;
wenzelm
parents: 68166
diff changeset
   110
      val (compressed, bytes) = body.join
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   111
      db.using_statement(Data.table.insert())(stmt =>
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   112
      {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   113
        stmt.string(1) = session_name
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   114
        stmt.string(2) = theory_name
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   115
        stmt.string(3) = name
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
   116
        stmt.bool(4) = executable
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
   117
        stmt.bool(5) = compressed
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
   118
        stmt.bytes(6) = bytes
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   119
        stmt.execute()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   120
      })
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   121
    }
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   122
  }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   123
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   124
  def make_regex(pattern: String): Regex =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   125
  {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   126
    @tailrec def make(result: List[String], depth: Int, chs: List[Char]): Regex =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   127
      chs match {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   128
        case '*' :: '*' :: rest => make("[^:]*" :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   129
        case '*' :: rest => make("[^:/]*" :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   130
        case '?' :: rest => make("[^:/]" :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   131
        case '\\' :: c :: rest => make(("\\" + c) :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   132
        case '{' :: rest => make("(" :: result, depth + 1, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   133
        case ',' :: rest if depth > 0 => make("|" :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   134
        case '}' :: rest if depth > 0 => make(")" :: result, depth - 1, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   135
        case c :: rest if ".+()".contains(c) => make(("\\" + c) :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   136
        case c :: rest => make(c.toString :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   137
        case Nil => result.reverse.mkString.r
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   138
      }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   139
    make(Nil, 0, pattern.toList)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   140
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   141
68151
wenzelm
parents: 68116
diff changeset
   142
  def make_matcher(pattern: String): (String, String) => Boolean =
wenzelm
parents: 68116
diff changeset
   143
  {
wenzelm
parents: 68116
diff changeset
   144
    val regex = make_regex(pattern)
wenzelm
parents: 68116
diff changeset
   145
    (theory_name: String, name: String) =>
wenzelm
parents: 68116
diff changeset
   146
      regex.pattern.matcher(compound_name(theory_name, name)).matches
wenzelm
parents: 68116
diff changeset
   147
  }
wenzelm
parents: 68116
diff changeset
   148
71624
f0499449e149 clarified modules;
wenzelm
parents: 71601
diff changeset
   149
  def make_entry(session_name: String, args: Protocol.Export.Args, body: Bytes,
68166
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   150
    cache: XZ.Cache = XZ.cache()): Entry =
68101
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
diff changeset
   151
  {
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
   152
    Entry(session_name, args.theory_name, args.name, args.executable,
71963
3e7d89d9912e back to parallel compression: full AFP build does require 16GB Java heap (reverting 107472ccc60d);
wenzelm
parents: 71939
diff changeset
   153
      if (args.compress) Future.fork(body.maybe_compress(cache = cache))
68167
327bb0f5f768 clarified implicit compression;
wenzelm
parents: 68166
diff changeset
   154
      else Future.value((false, body)))
68101
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
diff changeset
   155
  }
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
diff changeset
   156
68202
a99180ad3441 clarified signature;
wenzelm
parents: 68171
diff changeset
   157
  def read_entry(db: SQL.Database, session_name: String, theory_name: String, name: String)
a99180ad3441 clarified signature;
wenzelm
parents: 68171
diff changeset
   158
    : Option[Entry] =
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   159
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   160
    val select =
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
   161
      Data.table.select(List(Data.executable, Data.compressed, Data.body),
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   162
        Data.where_equal(session_name, theory_name, name))
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   163
    db.using_statement(select)(stmt =>
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   164
    {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   165
      val res = stmt.execute_query()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   166
      if (res.next()) {
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
   167
        val executable = res.bool(Data.executable)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   168
        val compressed = res.bool(Data.compressed)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   169
        val body = res.bytes(Data.body)
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
   170
        Some(Entry(session_name, theory_name, name, executable, Future.value(compressed, body)))
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   171
      }
68202
a99180ad3441 clarified signature;
wenzelm
parents: 68171
diff changeset
   172
      else None
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   173
    })
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   174
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   175
68831
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   176
  def read_entry(dir: Path, session_name: String, theory_name: String, name: String): Option[Entry] =
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   177
  {
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   178
    val path = dir + Path.basic(theory_name) + Path.explode(name)
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   179
    if (path.is_file) {
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
   180
      val executable = File.is_executable(path)
68831
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   181
      val uncompressed = Bytes.read(path)
69788
c175499a7537 added executable flag for exports;
wenzelm
parents: 69756
diff changeset
   182
      Some(Entry(session_name, theory_name, name, executable, Future.value((false, uncompressed))))
68831
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   183
    }
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   184
    else None
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   185
  }
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   186
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   187
72634
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   188
  /* database context */
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   189
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   190
  def open_database_context(
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   191
    sessions_structure: Sessions.Structure,
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   192
    store: Sessions.Store): Database_Context =
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   193
  {
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   194
    new Database_Context(sessions_structure, store,
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   195
      if (store.database_server) Some(store.open_database_server()) else None)
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   196
  }
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   197
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   198
  class Database_Context private[Export](
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   199
    sessions_structure: Sessions.Structure,
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   200
    store: Sessions.Store,
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   201
    database_server: Option[SQL.Database]) extends AutoCloseable
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   202
  {
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   203
    def close { database_server.foreach(_.close) }
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   204
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   205
    def try_entry(session: String, theory_name: String, name: String): Option[Entry] =
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   206
    {
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   207
      val hierarchy = sessions_structure.build_graph.all_preds(List(session)).view
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   208
      val attempts =
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   209
        database_server match {
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   210
          case Some(db) =>
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   211
            hierarchy.map(session_name => read_entry(db, session_name, theory_name, name))
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   212
          case None =>
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   213
            hierarchy.map(session_name =>
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   214
              store.try_open_database(session_name) match {
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   215
                case Some(db) => using(db)(read_entry(_, session_name, theory_name, name))
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   216
                case None => None
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   217
              })
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   218
        }
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   219
      attempts.collectFirst({ case Some(entry) => entry })
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   220
    }
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   221
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   222
    def entry(session: String, theory_name: String, name: String): Entry =
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   223
      try_entry(session, theory_name, name) getOrElse empty_entry(session, theory_name, name)
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   224
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   225
    override def toString: String =
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   226
    {
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   227
      val s =
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   228
        database_server match {
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   229
          case Some(db) => db.toString
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   230
          case None => "input_dirs = " + store.input_dirs.map(_.absolute).mkString(", ")
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   231
        }
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   232
      "Database_Context(" + s + ")"
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   233
    }
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   234
  }
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   235
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   236
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   237
  /* database consumer thread */
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   238
68289
c29fc61fb1b1 clarified cache;
wenzelm
parents: 68288
diff changeset
   239
  def consumer(db: SQL.Database, cache: XZ.Cache = XZ.cache()): Consumer = new Consumer(db, cache)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   240
68289
c29fc61fb1b1 clarified cache;
wenzelm
parents: 68288
diff changeset
   241
  class Consumer private[Export](db: SQL.Database, cache: XZ.Cache)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   242
  {
68924
wenzelm
parents: 68832
diff changeset
   243
    private val errors = Synchronized[List[String]](Nil)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   244
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   245
    private val consumer =
71145
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   246
      Consumer_Thread.fork_bulk[(Entry, Boolean)](name = "export")(
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   247
        bulk = { case (entry, _) => entry.body.is_finished },
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   248
        consume =
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   249
          (args: List[(Entry, Boolean)]) =>
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   250
          {
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   251
            val results =
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   252
              db.transaction {
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   253
                for ((entry, strict) <- args)
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   254
                yield {
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   255
                  if (read_name(db, entry.session_name, entry.theory_name, entry.name)) {
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   256
                    if (strict) {
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   257
                      val msg = message("Duplicate export", entry.theory_name, entry.name)
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   258
                      errors.change(msg :: _)
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   259
                    }
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   260
                    Exn.Res(())
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   261
                  }
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   262
                  else Exn.capture { entry.write(db) }
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   263
                }
70499
f389019024ce allow duplicate exports via strict = false;
wenzelm
parents: 69854
diff changeset
   264
              }
71145
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   265
            (results, true)
2f782d5f5d5a improved performance of session exports via bulk transactions;
wenzelm
parents: 71141
diff changeset
   266
          })
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   267
71624
f0499449e149 clarified modules;
wenzelm
parents: 71601
diff changeset
   268
    def apply(session_name: String, args: Protocol.Export.Args, body: Bytes): Unit =
70499
f389019024ce allow duplicate exports via strict = false;
wenzelm
parents: 69854
diff changeset
   269
      consumer.send(make_entry(session_name, args, body, cache = cache) -> args.strict)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   270
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   271
    def shutdown(close: Boolean = false): List[String] =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   272
    {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   273
      consumer.shutdown()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   274
      if (close) db.close()
68924
wenzelm
parents: 68832
diff changeset
   275
      errors.value.reverse
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   276
    }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   277
  }
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   278
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   279
68418
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   280
  /* abstract provider */
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   281
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   282
  object Provider
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   283
  {
71014
58022ee70b35 more operations;
wenzelm
parents: 70539
diff changeset
   284
    def none: Provider =
58022ee70b35 more operations;
wenzelm
parents: 70539
diff changeset
   285
      new Provider {
58022ee70b35 more operations;
wenzelm
parents: 70539
diff changeset
   286
        def apply(export_name: String): Option[Entry] = None
58022ee70b35 more operations;
wenzelm
parents: 70539
diff changeset
   287
        def focus(other_theory: String): Provider = this
58022ee70b35 more operations;
wenzelm
parents: 70539
diff changeset
   288
58022ee70b35 more operations;
wenzelm
parents: 70539
diff changeset
   289
        override def toString: String = "none"
58022ee70b35 more operations;
wenzelm
parents: 70539
diff changeset
   290
      }
58022ee70b35 more operations;
wenzelm
parents: 70539
diff changeset
   291
72634
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   292
    def database_context(
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   293
        context: Database_Context, session: String, theory_name: String): Provider =
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   294
      new Provider {
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   295
        def apply(export_name: String): Option[Entry] =
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   296
          context.try_entry(session, theory_name, export_name)
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   297
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   298
        def focus(other_theory: String): Provider = this
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   299
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   300
        override def toString: String = context.toString
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   301
      }
5cea0993ee4f clarified access to single database server vs. collection of database files;
wenzelm
parents: 72375
diff changeset
   302
68418
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   303
    def database(db: SQL.Database, session_name: String, theory_name: String): Provider =
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   304
      new Provider {
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   305
        def apply(export_name: String): Option[Entry] =
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   306
          read_entry(db, session_name, theory_name, export_name)
68832
9b9fc9ea9dd1 tuned output;
wenzelm
parents: 68831
diff changeset
   307
70539
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   308
        def focus(other_theory: String): Provider =
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   309
          if (other_theory == theory_name) this
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   310
          else Provider.database(db, session_name, other_theory)
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   311
68832
9b9fc9ea9dd1 tuned output;
wenzelm
parents: 68831
diff changeset
   312
        override def toString: String = db.toString
68418
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   313
      }
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   314
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   315
    def snapshot(snapshot: Document.Snapshot): Provider =
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   316
      new Provider {
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   317
        def apply(export_name: String): Option[Entry] =
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   318
          snapshot.exports_map.get(export_name)
68832
9b9fc9ea9dd1 tuned output;
wenzelm
parents: 68831
diff changeset
   319
70539
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   320
        def focus(other_theory: String): Provider =
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   321
          if (other_theory == snapshot.node_name.theory) this
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   322
          else {
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   323
            val node_name =
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   324
              snapshot.version.nodes.theory_name(other_theory) getOrElse
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   325
                error("Bad theory " + quote(other_theory))
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   326
            Provider.snapshot(snapshot.state.snapshot(node_name))
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   327
          }
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   328
68832
9b9fc9ea9dd1 tuned output;
wenzelm
parents: 68831
diff changeset
   329
        override def toString: String = snapshot.toString
68418
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   330
      }
68831
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   331
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   332
    def directory(dir: Path, session_name: String, theory_name: String): Provider =
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   333
      new Provider {
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   334
        def apply(export_name: String): Option[Entry] =
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   335
          read_entry(dir, session_name, theory_name, export_name)
68832
9b9fc9ea9dd1 tuned output;
wenzelm
parents: 68831
diff changeset
   336
70539
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   337
        def focus(other_theory: String): Provider =
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   338
          if (other_theory == theory_name) this
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   339
          else Provider.directory(dir, session_name, other_theory)
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   340
68832
9b9fc9ea9dd1 tuned output;
wenzelm
parents: 68831
diff changeset
   341
        override def toString: String = dir.toString
68831
a6c69599ab99 Export.Provider for "isabelle dump" output_dir;
wenzelm
parents: 68418
diff changeset
   342
      }
68418
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   343
  }
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   344
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   345
  trait Provider
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   346
  {
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   347
    def apply(export_name: String): Option[Entry]
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   348
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   349
    def uncompressed_yxml(export_name: String, cache: XZ.Cache = XZ.cache()): XML.Body =
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   350
      apply(export_name) match {
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   351
        case Some(entry) => entry.uncompressed_yxml(cache = cache)
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   352
        case None => Nil
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   353
      }
70539
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   354
30b3c58a1933 support Export_Theory.read_proof, based on theory_name and serial;
wenzelm
parents: 70499
diff changeset
   355
    def focus(other_theory: String): Provider
68418
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   356
  }
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   357
366e43cddd20 more abstract Export.Provider;
wenzelm
parents: 68331
diff changeset
   358
68288
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   359
  /* export to file-system */
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   360
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   361
  def export_files(
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   362
    store: Sessions.Store,
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   363
    session_name: String,
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   364
    export_dir: Path,
71726
a5fda30edae2 clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents: 71624
diff changeset
   365
    progress: Progress = new Progress,
69671
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   366
    export_prune: Int = 0,
68288
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   367
    export_list: Boolean = false,
69811
18f61ce86425 clarified 'export_files' in session ROOT: require explicit "isabelle build -e";
wenzelm
parents: 69789
diff changeset
   368
    export_patterns: List[String] = Nil)
68288
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   369
  {
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   370
    using(store.open_database(session_name))(db =>
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   371
    {
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   372
      db.transaction {
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   373
        val export_names = read_theory_exports(db, session_name)
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   374
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   375
        // list
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   376
        if (export_list) {
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   377
          (for ((theory_name, name) <- export_names) yield compound_name(theory_name, name)).
71601
97ccf48c2f0c misc tuning based on hints by IntelliJ IDEA;
wenzelm
parents: 71145
diff changeset
   378
            sorted.foreach(progress.echo)
68288
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   379
        }
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   380
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   381
        // export
68290
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   382
        if (export_patterns.nonEmpty) {
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   383
          val exports =
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   384
            (for {
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   385
              export_pattern <- export_patterns.iterator
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   386
              matcher = make_matcher(export_pattern)
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   387
              (theory_name, name) <- export_names if matcher(theory_name, name)
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   388
            } yield (theory_name, name)).toSet
68288
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   389
          for {
68290
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   390
            (theory_name, group) <- exports.toList.groupBy(_._1).toList.sortBy(_._1)
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   391
            name <- group.map(_._2).sorted
68288
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   392
            entry <- read_entry(db, session_name, theory_name, name)
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   393
          } {
69671
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   394
            val elems = theory_name :: space_explode('/', name)
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   395
            val path =
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   396
              if (elems.length < export_prune + 1) {
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   397
                error("Cannot prune path by " + export_prune + " element(s): " + Path.make(elems))
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   398
              }
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   399
              else export_dir + Path.make(elems.drop(export_prune))
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   400
69811
18f61ce86425 clarified 'export_files' in session ROOT: require explicit "isabelle build -e";
wenzelm
parents: 69789
diff changeset
   401
            progress.echo("export " + path + (if (entry.executable) " (executable)" else ""))
72375
e48d93811ed7 clarified signature;
wenzelm
parents: 71963
diff changeset
   402
            Isabelle_System.make_directory(path.dir)
68289
c29fc61fb1b1 clarified cache;
wenzelm
parents: 68288
diff changeset
   403
            Bytes.write(path, entry.uncompressed(cache = store.xz_cache))
69789
2c3e5e58d93f more thorough File.set_executable, notably for Windows;
wenzelm
parents: 69788
diff changeset
   404
            File.set_executable(path, entry.executable)
68288
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   405
          }
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   406
        }
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   407
      }
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   408
    })
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   409
  }
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   410
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   411
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   412
  /* Isabelle tool wrapper */
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   413
71601
97ccf48c2f0c misc tuning based on hints by IntelliJ IDEA;
wenzelm
parents: 71145
diff changeset
   414
  val default_export_dir: Path = Path.explode("export")
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   415
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   416
  val isabelle_tool = Isabelle_Tool("export", "retrieve theory exports", args =>
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   417
  {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   418
    /* arguments */
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   419
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   420
    var export_dir = default_export_dir
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   421
    var dirs: List[Path] = Nil
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   422
    var export_list = false
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   423
    var no_build = false
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   424
    var options = Options.init()
69671
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   425
    var export_prune = 0
68290
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   426
    var export_patterns: List[String] = Nil
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   427
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   428
    val getopts = Getopts("""
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   429
Usage: isabelle export [OPTIONS] SESSION
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   430
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   431
  Options are:
68314
2acbf8129d8b clarified option -O: avoid conflict with build/dump option -D;
wenzelm
parents: 68305
diff changeset
   432
    -O DIR       output directory for exported files (default: """ + default_export_dir + """)
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   433
    -d DIR       include session directory
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   434
    -l           list exports
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   435
    -n           no build of session
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   436
    -o OPTION    override Isabelle system OPTION (via NAME=VAL or NAME)
69671
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   437
    -p NUM       prune path of exported files by NUM elements
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   438
    -x PATTERN   extract files matching pattern (e.g. "*:**" for all)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   439
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   440
  List or export theory exports for SESSION: named blobs produced by
68290
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   441
  isabelle build. Option -l or -x is required; option -x may be repeated.
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   442
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   443
  The PATTERN language resembles glob patterns in the shell, with ? and *
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   444
  (both excluding ":" and "/"), ** (excluding ":"), and [abc] or [^abc],
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   445
  and variants {pattern1,pattern2,pattern3}.
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   446
""",
68314
2acbf8129d8b clarified option -O: avoid conflict with build/dump option -D;
wenzelm
parents: 68305
diff changeset
   447
      "O:" -> (arg => export_dir = Path.explode(arg)),
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   448
      "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))),
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   449
      "l" -> (_ => export_list = true),
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   450
      "n" -> (_ => no_build = true),
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   451
      "o:" -> (arg => options = options + arg),
69671
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   452
      "p:" -> (arg => export_prune = Value.Int.parse(arg)),
68290
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   453
      "x:" -> (arg => export_patterns ::= arg))
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   454
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   455
    val more_args = getopts(args)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   456
    val session_name =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   457
      more_args match {
68290
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   458
        case List(session_name) if export_list || export_patterns.nonEmpty => session_name
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   459
        case _ => getopts.usage()
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   460
      }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   461
68305
5321218147d3 clarified signature;
wenzelm
parents: 68291
diff changeset
   462
    val progress = new Console_Progress()
5321218147d3 clarified signature;
wenzelm
parents: 68291
diff changeset
   463
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   464
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   465
    /* build */
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   466
68305
5321218147d3 clarified signature;
wenzelm
parents: 68291
diff changeset
   467
    if (!no_build) {
5321218147d3 clarified signature;
wenzelm
parents: 68291
diff changeset
   468
      val rc =
68331
7eaaa8f48331 clarified outermost progress.interrupt_handler;
wenzelm
parents: 68314
diff changeset
   469
        progress.interrupt_handler {
69854
cc0b3e177b49 system option "system_heaps" supersedes various command-line options for "system build mode";
wenzelm
parents: 69811
diff changeset
   470
          Build.build_logic(options, session_name, progress = progress, dirs = dirs)
68331
7eaaa8f48331 clarified outermost progress.interrupt_handler;
wenzelm
parents: 68314
diff changeset
   471
        }
68305
5321218147d3 clarified signature;
wenzelm
parents: 68291
diff changeset
   472
      if (rc != 0) sys.exit(rc)
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   473
    }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   474
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   475
68288
d20770229f99 tuned signature;
wenzelm
parents: 68222
diff changeset
   476
    /* export files */
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   477
69854
cc0b3e177b49 system option "system_heaps" supersedes various command-line options for "system build mode";
wenzelm
parents: 69811
diff changeset
   478
    val store = Sessions.store(options)
69671
2486792eaf61 support pruning of export names;
wenzelm
parents: 69635
diff changeset
   479
    export_files(store, session_name, export_dir, progress = progress, export_prune = export_prune,
68290
f1f5ccc85b25 support multiple patterns;
wenzelm
parents: 68289
diff changeset
   480
      export_list = export_list, export_patterns = export_patterns)
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   481
  })
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   482
}