src/Pure/System/cygwin_init.scala
author wenzelm
Tue, 16 Jul 2013 13:23:37 +0200
changeset 52672 8de4235298cb
parent 52669 fb59e6e9442a
child 53419 1c87e79bb838
permissions -rw-r--r--
more robust executable path specifications; afford final test of Isabelle.init; tuned;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52667
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
     1
/*  Title:      Pure/System/cygwin_init.scala
52553
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
     3
52669
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
     4
Initialize Isabelle distribution after extracting via 7zip.
52553
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
     5
*/
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
     6
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
     7
package isabelle
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
     8
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
     9
52667
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    10
import java.lang.System
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    11
import java.io.{File => JFile, BufferedReader, InputStreamReader}
52553
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
    12
import java.nio.file.{Paths, Files}
52667
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    13
import java.awt.{GraphicsEnvironment, Point, Font}
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    14
import javax.swing.ImageIcon
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    15
52669
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
    16
import scala.annotation.tailrec
52667
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    17
import scala.swing.{ScrollPane, Button, FlowPanel,
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    18
  BorderPanel, MainFrame, TextArea, SwingApplication}
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    19
import scala.swing.event.ButtonClicked
52553
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
    20
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
    21
52667
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    22
object Cygwin_Init
52553
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
    23
{
52667
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    24
  /* command-line entry point */
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    25
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    26
  def main(args: Array[String]) =
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    27
  {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    28
    GUI.init_laf()
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    29
    try {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    30
      require(Platform.is_windows)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    31
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    32
      val isabelle_home = System.getProperty("isabelle.home")
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    33
      if (isabelle_home == null || isabelle_home == "")
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    34
        error("Unknown Isabelle home directory")
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    35
      if (!(new JFile(isabelle_home)).isDirectory)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    36
        error("Bad Isabelle home directory: " + quote(isabelle_home))
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    37
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    38
      Swing_Thread.later { main_frame(isabelle_home) }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    39
    }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    40
    catch {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    41
      case exn: Throwable =>
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    42
        GUI.error_dialog(null, "Isabelle init failure", GUI.scrollable_text(Exn.message(exn)))
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    43
        sys.exit(2)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    44
    }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    45
  }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    46
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    47
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    48
  /* main window */
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    49
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    50
  private def main_frame(isabelle_home: String) = new MainFrame
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    51
  {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    52
    title = "Isabelle system initialization"
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    53
    iconImage = new ImageIcon(isabelle_home + "\\lib\\logo\\isabelle.gif").getImage
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    54
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    55
    val layout_panel = new BorderPanel
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    56
    contents = layout_panel
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    57
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    58
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    59
    /* text area */
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    60
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    61
    def echo(msg: String) { text_area.append(msg + "\n") }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    62
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    63
    val text_area = new TextArea {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    64
      font = new Font("SansSerif", Font.PLAIN, GUI.resolution_scale(10) max 14)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    65
      editable = false
52672
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
    66
      columns = 50
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
    67
      rows = 15
52667
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    68
    }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    69
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    70
    layout_panel.layout(new ScrollPane(text_area)) = BorderPanel.Position.Center
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    71
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    72
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    73
    /* exit button */
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    74
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    75
    var _return_code: Option[Int] = None
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    76
    def maybe_exit(): Unit = _return_code.foreach(sys.exit(_))
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    77
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    78
    def return_code(rc: Int): Unit =
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    79
      Swing_Thread.later {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    80
        _return_code = Some(rc)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    81
        button.peer.getRootPane.setDefaultButton(button.peer)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    82
        layout_panel.repaint
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    83
      }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    84
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    85
    override def closeOperation { maybe_exit() }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    86
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    87
    val button = new Button {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    88
      text = "Done"
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    89
      reactions += { case ButtonClicked(_) => maybe_exit() }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    90
    }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    91
    val button_panel = new FlowPanel(FlowPanel.Alignment.Center)(button)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    92
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    93
    layout_panel.layout(button_panel) = BorderPanel.Position.South
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    94
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    95
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    96
    /* show window */
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    97
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    98
    pack()
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
    99
    val point = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint()
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   100
    location = new Point(point.x - size.width / 2, point.y - size.height / 2)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   101
    visible = true
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   102
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   103
    default_thread_pool.submit(() =>
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   104
      try {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   105
        init(isabelle_home, echo)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   106
        return_code(0)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   107
      }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   108
      catch {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   109
        case exn: Throwable =>
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   110
          text_area.append("Error:\n" + Exn.message(exn) + "\n")
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   111
          return_code(2)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   112
      }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   113
    )
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   114
  }
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   115
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   116
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   117
  /* init Cygwin file-system */
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   118
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   119
  private def init(isabelle_home: String, echo: String => Unit)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   120
  {
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   121
    val cygwin_root = isabelle_home + "\\contrib\\cygwin"
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   122
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   123
    if (!(new JFile(cygwin_root)).isDirectory)
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   124
      error("Bad Isabelle Cygwin directory: " + quote(cygwin_root))
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   125
52672
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   126
    def execute(args: String*): Int =
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   127
    {
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   128
      val cwd = new JFile(isabelle_home)
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   129
      val env = Map("CYGWIN" -> "nodosfilewarning")
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   130
      val proc = Isabelle_System.raw_execute(cwd, env, true, args: _*)
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   131
      proc.getOutputStream.close
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   132
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   133
      val stdout = new BufferedReader(new InputStreamReader(proc.getInputStream, UTF8.charset))
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   134
      try {
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   135
        var line = stdout.readLine
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   136
        while (line != null) {
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   137
          echo(line)
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   138
          line = stdout.readLine
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   139
        }
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   140
      }
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   141
      finally { stdout.close }
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   142
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   143
      proc.waitFor
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   144
    }
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   145
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   146
    echo("Initializing Cygwin:")
52669
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   147
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   148
    echo("symlinks ...")
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   149
    val symlinks =
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   150
    {
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   151
      val path = (new JFile(cygwin_root, "isabelle\\symlinks")).toPath
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   152
      Files.readAllLines(path, UTF8.charset).toArray.toList.asInstanceOf[List[String]]
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   153
    }
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   154
    @tailrec def recover_symlinks(list: List[String]): Unit =
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   155
    {
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   156
      list match {
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   157
        case Nil | List("") =>
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   158
        case link :: content :: rest =>
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   159
          val path = (new JFile(isabelle_home, link)).toPath
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   160
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   161
          val writer = Files.newBufferedWriter(path, UTF8.charset)
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   162
          try { writer.write("!<symlink>" + content + "\0") }
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   163
          finally { writer.close }
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   164
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   165
          Files.setAttribute(path, "dos:system", true)
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   166
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   167
          recover_symlinks(rest)
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   168
        case _ => error("Unbalanced symlinks list")
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   169
      }
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   170
    }
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   171
    recover_symlinks(symlinks)
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   172
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   173
    echo("rebaseall ...")
52672
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   174
    execute(cygwin_root + "\\bin\\dash.exe", "/isabelle/rebaseall")
52669
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   175
fb59e6e9442a recover Cygwin symlinks via Windows file-system operations;
wenzelm
parents: 52667
diff changeset
   176
    echo("postinstall ...")
52672
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   177
    execute(cygwin_root + "\\bin\\bash.exe", "/isabelle/postinstall")
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   178
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   179
    echo("init ...")
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   180
    System.setProperty("cygwin.root", cygwin_root)
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   181
    Isabelle_System.init()
8de4235298cb more robust executable path specifications;
wenzelm
parents: 52669
diff changeset
   182
    echo("OK")
52667
d2b12523186d Scala version of init.bat;
wenzelm
parents: 52553
diff changeset
   183
  }
52553
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
   184
}
d5d150d159ad some support for Cygwin;
wenzelm
parents:
diff changeset
   185