src/Pure/System/build.scala
changeset 48421 c4d337782de4
parent 48419 6d7b6e47f3ef
child 48422 9613780a805b
equal deleted inserted replaced
48420:a8ed41b6280b 48421:c4d337782de4
    15 
    15 
    16 object Build
    16 object Build
    17 {
    17 {
    18   /** session information **/
    18   /** session information **/
    19 
    19 
    20   type Options = List[(String, Option[String])]
       
    21 
       
    22   object Session
    20   object Session
    23   {
    21   {
       
    22     /* Key */
       
    23 
    24     object Key
    24     object Key
    25     {
    25     {
    26       object Ordering extends scala.math.Ordering[Key]
    26       object Ordering extends scala.math.Ordering[Key]
    27       {
    27       {
    28         def compare(key1: Key, key2: Key): Int =
    28         def compare(key1: Key, key2: Key): Int =
    36     sealed case class Key(name: String, order: Int)
    36     sealed case class Key(name: String, order: Int)
    37     {
    37     {
    38       override def toString: String = name
    38       override def toString: String = name
    39     }
    39     }
    40 
    40 
       
    41 
       
    42     /* Info */
       
    43 
       
    44     sealed abstract class Status
       
    45     case object Pending extends Status
       
    46     case object Running extends Status
       
    47 
    41     sealed case class Info(
    48     sealed case class Info(
    42       dir: Path,
    49       dir: Path,
    43       parent: Option[String],
    50       parent: Option[String],
    44       description: String,
    51       description: String,
    45       options: Options,
    52       options: Options,
    46       theories: List[(Options, List[String])],
    53       theories: List[(Options, List[Path])],
    47       files: List[String])
    54       files: List[Path],
       
    55       status: Status = Pending)
       
    56 
       
    57 
       
    58     /* Queue */
    48 
    59 
    49     object Queue
    60     object Queue
    50     {
    61     {
    51       val empty: Queue = new Queue()
    62       val empty: Queue = new Queue()
    52     }
    63     }
    99     reset: Boolean,
   110     reset: Boolean,
   100     order: Int,
   111     order: Int,
   101     path: Option[String],
   112     path: Option[String],
   102     parent: Option[String],
   113     parent: Option[String],
   103     description: String,
   114     description: String,
   104     options: Options,
   115     options: List[Options.Spec],
   105     theories: List[(Options, List[String])],
   116     theories: List[(List[Options.Spec], List[String])],
   106     files: List[String])
   117     files: List[String])
   107 
   118 
   108   private object Parser extends Parse.Parser
   119   private object Parser extends Parse.Parser
   109   {
   120   {
   110     val SESSION = "session"
   121     val SESSION = "session"
   159   private val ROOT = Path.explode("ROOT")
   170   private val ROOT = Path.explode("ROOT")
   160   private val SESSIONS = Path.explode("etc/sessions")
   171   private val SESSIONS = Path.explode("etc/sessions")
   161 
   172 
   162   private def is_pure(name: String): Boolean = name == "RAW" || name == "Pure"
   173   private def is_pure(name: String): Boolean = name == "RAW" || name == "Pure"
   163 
   174 
   164   private def sessions_root(dir: Path, root: JFile, queue: Session.Queue): Session.Queue =
   175   private def sessions_root(options: Options, dir: Path, root: JFile, queue: Session.Queue)
       
   176     : Session.Queue =
   165   {
   177   {
   166     (queue /: Parser.parse_entries(root))((queue1, entry) =>
   178     (queue /: Parser.parse_entries(root))((queue1, entry) =>
   167       try {
   179       try {
   168         if (entry.name == "") error("Bad session name")
   180         if (entry.name == "") error("Bad session name")
   169 
   181 
   185             case Some(p) => Path.explode(p)
   197             case Some(p) => Path.explode(p)
   186             case None => Path.basic(entry.name)
   198             case None => Path.basic(entry.name)
   187           }
   199           }
   188 
   200 
   189         val key = Session.Key(full_name, entry.order)
   201         val key = Session.Key(full_name, entry.order)
       
   202 
       
   203         val theories =
       
   204           entry.theories.map({ case (opts, thys) => (options ++ opts, thys.map(Path.explode(_))) })
       
   205         val files = entry.files.map(Path.explode(_))
   190         val info =
   206         val info =
   191           Session.Info(dir + path, entry.parent,
   207           Session.Info(dir + path, entry.parent,
   192             entry.description, entry.options, entry.theories, entry.files)
   208             entry.description, options ++ entry.options, theories, files)
   193 
   209 
   194         queue1 + (key, info)
   210         queue1 + (key, info)
   195       }
   211       }
   196       catch {
   212       catch {
   197         case ERROR(msg) =>
   213         case ERROR(msg) =>
   198           error(msg + "\nThe error(s) above occurred in session entry " +
   214           error(msg + "\nThe error(s) above occurred in session entry " +
   199             quote(entry.name) + Position.str_of(Position.file(root)))
   215             quote(entry.name) + Position.str_of(Position.file(root)))
   200       })
   216       })
   201   }
   217   }
   202 
   218 
   203   private def sessions_dir(strict: Boolean, dir: Path, queue: Session.Queue): Session.Queue =
   219   private def sessions_dir(options: Options, strict: Boolean, dir: Path, queue: Session.Queue)
       
   220     : Session.Queue =
   204   {
   221   {
   205     val root = (dir + ROOT).file
   222     val root = (dir + ROOT).file
   206     if (root.isFile) sessions_root(dir, root, queue)
   223     if (root.isFile) sessions_root(options, dir, root, queue)
   207     else if (strict) error("Bad session root file: " + quote(root.toString))
   224     else if (strict) error("Bad session root file: " + quote(root.toString))
   208     else queue
   225     else queue
   209   }
   226   }
   210 
   227 
   211   private def sessions_catalog(dir: Path, catalog: JFile, queue: Session.Queue): Session.Queue =
   228   private def sessions_catalog(options: Options, dir: Path, catalog: JFile, queue: Session.Queue)
       
   229     : Session.Queue =
   212   {
   230   {
   213     val dirs =
   231     val dirs =
   214       split_lines(File.read(catalog)).filterNot(line => line == "" || line.startsWith("#"))
   232       split_lines(File.read(catalog)).filterNot(line => line == "" || line.startsWith("#"))
   215     (queue /: dirs)((queue1, dir1) =>
   233     (queue /: dirs)((queue1, dir1) =>
   216       try {
   234       try {
   217         val dir2 = dir + Path.explode(dir1)
   235         val dir2 = dir + Path.explode(dir1)
   218         if (dir2.file.isDirectory) sessions_dir(true, dir2, queue1)
   236         if (dir2.file.isDirectory) sessions_dir(options, true, dir2, queue1)
   219         else error("Bad session directory: " + dir2.toString)
   237         else error("Bad session directory: " + dir2.toString)
   220       }
   238       }
   221       catch {
   239       catch {
   222         case ERROR(msg) =>
   240         case ERROR(msg) =>
   223           error(msg + "\nThe error(s) above occurred in session catalog " + quote(catalog.toString))
   241           error(msg + "\nThe error(s) above occurred in session catalog " + quote(catalog.toString))
   224       })
   242       })
   225   }
   243   }
   226 
   244 
   227   def find_sessions(all_sessions: Boolean, sessions: List[String],
   245   def find_sessions(options: Options, all_sessions: Boolean, sessions: List[String],
   228     more_dirs: List[Path]): Session.Queue =
   246     more_dirs: List[Path]): Session.Queue =
   229   {
   247   {
   230     var queue = Session.Queue.empty
   248     var queue = Session.Queue.empty
   231 
   249 
   232     for (dir <- Isabelle_System.components()) {
   250     for (dir <- Isabelle_System.components()) {
   233       queue = sessions_dir(false, dir, queue)
   251       queue = sessions_dir(options, false, dir, queue)
   234 
   252 
   235       val catalog = (dir + SESSIONS).file
   253       val catalog = (dir + SESSIONS).file
   236       if (catalog.isFile)
   254       if (catalog.isFile)
   237         queue = sessions_catalog(dir, catalog, queue)
   255         queue = sessions_catalog(options, dir, catalog, queue)
   238     }
   256     }
   239 
   257 
   240     for (dir <- more_dirs) queue = sessions_dir(true, dir, queue)
   258     for (dir <- more_dirs) queue = sessions_dir(options, true, dir, queue)
   241 
   259 
   242     sessions.filter(name => !queue.defined(name)) match {
   260     sessions.filter(name => !queue.defined(name)) match {
   243       case Nil =>
   261       case Nil =>
   244       case bad => error("Undefined session(s): " + commas_quote(bad))
   262       case bad => error("Undefined session(s): " + commas_quote(bad))
   245     }
   263     }
   298         """
   316         """
   299       }
   317       }
   300     val args_xml =
   318     val args_xml =
   301     {
   319     {
   302       import XML.Encode._
   320       import XML.Encode._
   303       def symbol_string: T[String] = (s => string(Symbol.encode(s)))
   321       pair(bool, pair(string, pair(string, list(string))))(
   304       pair(bool, pair(symbol_string, pair(symbol_string, list(symbol_string))))(
   322         save, (parent, (name, info.theories.map(_._2).flatten.map(_.implode))))
   305         save, (parent, (name, info.theories.map(_._2).flatten)))
       
   306     }
   323     }
   307     new Build_Job(cwd, env, script, YXML.string_of_body(args_xml))
   324     new Build_Job(cwd, env, script, YXML.string_of_body(args_xml))
   308   }
   325   }
   309 
   326 
   310   def build(all_sessions: Boolean, build_images: Boolean, list_only: Boolean,
   327   def build(all_sessions: Boolean, build_images: Boolean, list_only: Boolean,
   311     more_dirs: List[Path], more_options: List[String], sessions: List[String]): Int =
   328     more_dirs: List[Path], more_options: List[String], sessions: List[String]): Int =
   312   {
   329   {
   313     val options = (Options.init() /: more_options)(_.define_simple(_))
   330     val options = (Options.init() /: more_options)(_.define_simple(_))
   314     val queue = find_sessions(all_sessions, sessions, more_dirs)
   331     val queue = find_sessions(options, all_sessions, sessions, more_dirs)
   315 
   332 
   316 
   333 
   317     // prepare browser info dir
   334     // prepare browser info dir
   318     if (options.bool("browser_info") &&
   335     if (options.bool("browser_info") &&
   319       !Path.explode("$ISABELLE_BROWSER_INFO/index.html").file.isFile)
   336       !Path.explode("$ISABELLE_BROWSER_INFO/index.html").file.isFile)