src/Pure/Tools/build_log.scala
changeset 64110 c0b96b34c7b9
parent 64109 d54aa68e33dc
child 64111 b2290b9d0175
equal deleted inserted replaced
64109:d54aa68e33dc 64110:c0b96b34c7b9
     1 /*  Title:      Pure/Tools/build_log.scala
     1 /*  Title:      Pure/Tools/build_log.scala
     2     Author:     Makarius
     2     Author:     Makarius
     3 
     3 
     4 Build log parsing for current and historic versions.
     4 Build log parsing for current and historic formats.
     5 */
     5 */
     6 
     6 
     7 package isabelle
     7 package isabelle
     8 
     8 
     9 
     9 
    10 import java.io.{File => JFile}
    10 import java.io.{File => JFile}
    11 import java.time.ZoneId
    11 import java.time.ZoneId
    12 import java.time.format.DateTimeParseException
    12 import java.time.format.{DateTimeFormatter, DateTimeParseException}
    13 import java.util.Locale
    13 import java.util.Locale
    14 
    14 
    15 import scala.collection.mutable
    15 import scala.collection.mutable
    16 import scala.util.matching.Regex
    16 import scala.util.matching.Regex
    17 
    17 
    88       apply(base_name, text)
    88       apply(base_name, text)
    89     }
    89     }
    90 
    90 
    91     def apply(path: Path): Log_File = apply(path.file)
    91     def apply(path: Path): Log_File = apply(path.file)
    92 
    92 
       
    93 
       
    94     /* date format */
       
    95 
    93     val Date_Format =
    96     val Date_Format =
    94     {
    97     {
    95       val fmts =
    98       val fmts =
    96         Date.Formatter.variants(
    99         Date.Formatter.variants(
    97           List("EEE MMM d HH:mm:ss VV yyyy", "EEE MMM d HH:mm:ss O yyyy"),
   100           List("EEE MMM d HH:mm:ss VV yyyy", "EEE MMM d HH:mm:ss O yyyy"),
    98           List(Locale.ENGLISH, Locale.GERMAN)) :::
   101           List(Locale.ENGLISH, Locale.GERMAN)) :::
    99         List(Date.Formatter.pattern("EEE MMM d HH:mm:ss yyyy").withZone(ZoneId.of("Europe/Berlin")))
   102         List(
       
   103           DateTimeFormatter.RFC_1123_DATE_TIME,
       
   104           Date.Formatter.pattern("EEE MMM d HH:mm:ss yyyy").withZone(ZoneId.of("Europe/Berlin")))
   100 
   105 
   101       def tune_timezone(s: String): String =
   106       def tune_timezone(s: String): String =
   102         s match {
   107         s match {
   103           case "CET" | "MET" => "GMT+1"
   108           case "CET" | "MET" => "GMT+1"
   104           case "CEST" | "MEST" => "GMT+2"
   109           case "CEST" | "MEST" => "GMT+2"
   247     val Isabelle_Version = new Regex("""^Isabelle version: .* -- hg id (\S+)$""")
   252     val Isabelle_Version = new Regex("""^Isabelle version: .* -- hg id (\S+)$""")
   248     val AFP_Version = new Regex("""^AFP version: .* -- hg id (\S+)$""")
   253     val AFP_Version = new Regex("""^AFP version: .* -- hg id (\S+)$""")
   249     val Bad_Init = new Regex("""^cp:.*: Disc quota exceeded$""")
   254     val Bad_Init = new Regex("""^cp:.*: Disc quota exceeded$""")
   250   }
   255   }
   251 
   256 
       
   257   object Jenkins
       
   258   {
       
   259     val engine = "jenkins"
       
   260     val Start = new Regex("""^Started .*$""")
       
   261     val Start_Date = new Regex("""^Build started at (.+)$""")
       
   262     val No_End = new Regex("""$.""")
       
   263     val Isabelle_Version = new Regex("""^Isabelle id (\S+)$""")
       
   264     val AFP_Version = new Regex("""^AFP id (\S+)$""")
       
   265     val CONFIGURATION = "=== CONFIGURATION ==="
       
   266     val BUILD = "=== BUILD ==="
       
   267     val FINISHED = "Finished: "
       
   268   }
       
   269 
   252   private def parse_meta_info(log_file: Log_File): Meta_Info =
   270   private def parse_meta_info(log_file: Log_File): Meta_Info =
   253   {
   271   {
   254     def parse(engine: String, host: String, start: Date,
   272     def parse(engine: String, host: String, start: Date,
   255       End: Regex, Isabelle_Version: Regex, AFP_Version: Regex): Meta_Info =
   273       End: Regex, Isabelle_Version: Regex, AFP_Version: Regex): Meta_Info =
   256     {
   274     {
   286 
   304 
   287       case AFP_Test.Start_Old(log_file.Strict_Date(start)) :: _ =>
   305       case AFP_Test.Start_Old(log_file.Strict_Date(start)) :: _ =>
   288         parse(AFP_Test.engine, "", start, AFP_Test.End,
   306         parse(AFP_Test.engine, "", start, AFP_Test.End,
   289           AFP_Test.Isabelle_Version, AFP_Test.AFP_Version)
   307           AFP_Test.Isabelle_Version, AFP_Test.AFP_Version)
   290 
   308 
       
   309       case Jenkins.Start() :: _
       
   310       if log_file.lines.contains(Jenkins.CONFIGURATION) ||
       
   311          log_file.lines.last.startsWith(Jenkins.FINISHED) =>
       
   312         log_file.lines.dropWhile(_ != Jenkins.BUILD) match {
       
   313           case Jenkins.BUILD :: _ :: Jenkins.Start_Date(log_file.Strict_Date(start)) :: _ =>
       
   314             parse(Jenkins.engine, "", start, Jenkins.No_End,
       
   315               Jenkins.Isabelle_Version, Jenkins.AFP_Version)
       
   316           case _ => Meta_Info.empty
       
   317         }
       
   318 
   291       case line :: _ if line.startsWith("\0") => Meta_Info.empty
   319       case line :: _ if line.startsWith("\0") => Meta_Info.empty
   292       case List(Isatest.End(_)) => Meta_Info.empty
   320       case List(Isatest.End(_)) => Meta_Info.empty
   293       case _ :: AFP_Test.Bad_Init() :: _ => Meta_Info.empty
   321       case _ :: AFP_Test.Bad_Init() :: _ => Meta_Info.empty
   294       case Nil => Meta_Info.empty
   322       case Nil => Meta_Info.empty
   295 
   323 
   296       case _ => log_file.err("cannot detect log header format")
   324       case _ => log_file.err("cannot detect log file format")
   297     }
   325     }
   298   }
   326   }
   299 
   327 
   300 
   328 
   301 
   329