1/*  Title:      Pure/System/cygwin.scala
2    Author:     Makarius
3
4Cygwin as POSIX emulation on Windows.
5*/
6
7package isabelle
8
9
10import java.io.{File => JFile}
11import java.nio.file.Files
12
13import scala.annotation.tailrec
14
15
16object Cygwin
17{
18  /* init (e.g. after extraction via 7zip) */
19
20  def init(isabelle_root: String, cygwin_root: String)
21  {
22    require(Platform.is_windows)
23
24    def exec(cmdline: String*)
25    {
26      val cwd = new JFile(isabelle_root)
27      val env = sys.env + ("CYGWIN" -> "nodosfilewarning")
28      val proc = Isabelle_System.process(cmdline.toList, cwd = cwd, env = env, redirect = true)
29      val (output, rc) = Isabelle_System.process_output(proc)
30      if (rc != 0) error(output)
31    }
32
33    val uninitialized_file = new JFile(cygwin_root, "isabelle\\uninitialized")
34    val uninitialized = uninitialized_file.isFile && uninitialized_file.delete
35
36    if (uninitialized) {
37      val symlinks =
38      {
39        val path = (new JFile(cygwin_root + "\\isabelle\\symlinks")).toPath
40        Files.readAllLines(path, UTF8.charset).toArray.toList.asInstanceOf[List[String]]
41      }
42      @tailrec def recover_symlinks(list: List[String]): Unit =
43      {
44        list match {
45          case Nil | List("") =>
46          case link :: content :: rest =>
47            val path = (new JFile(isabelle_root, link)).toPath
48
49            val writer = Files.newBufferedWriter(path, UTF8.charset)
50            try { writer.write("!<symlink>" + content + "\u0000") }
51            finally { writer.close }
52
53            Files.setAttribute(path, "dos:system", true)
54
55            recover_symlinks(rest)
56          case _ => error("Unbalanced symlinks list")
57        }
58      }
59      recover_symlinks(symlinks)
60
61      exec(cygwin_root + "\\bin\\dash.exe", "/isabelle/rebaseall")
62      exec(cygwin_root + "\\bin\\bash.exe", "/isabelle/postinstall")
63    }
64  }
65}
66