1/*  Title:      Pure/Admin/build_cygwin.scala
2    Author:     Makarius
3
4Produce pre-canned Cygwin distribution for Isabelle.
5*/
6
7package isabelle
8
9
10object Build_Cygwin
11{
12  val default_mirror: String = "https://isabelle.sketis.net/cygwin_2018"
13
14  val packages: List[String] =
15    List("curl", "nano", "perl", "perl-libwww-perl", "rlwrap", "unzip")
16
17  def build_cygwin(progress: Progress,
18    mirror: String = default_mirror,
19    more_packages: List[String] = Nil)
20  {
21    require(Platform.is_windows)
22
23    Isabelle_System.with_tmp_dir("cygwin")(tmp_dir =>
24      {
25        val cygwin = tmp_dir + Path.explode("cygwin")
26        val cygwin_etc = cygwin + Path.explode("etc")
27        val cygwin_isabelle = cygwin + Path.explode("isabelle")
28        Isabelle_System.mkdirs(cygwin_isabelle)
29
30        val cygwin_exe_name = mirror + "/setup-x86_64.exe"
31        val cygwin_exe = cygwin_isabelle + Path.explode("cygwin.exe")
32        Bytes.write(cygwin_exe,
33          try { Bytes.read(Url(cygwin_exe_name)) }
34          catch { case ERROR(_) => error("Failed to download " + quote(cygwin_exe_name)) })
35
36        File.write(cygwin_isabelle + Path.explode("cygwin_mirror"), mirror)
37
38        Isabelle_System.bash(
39          "chmod +x " + File.bash_path(cygwin_exe) + " && " +
40          File.bash_path(cygwin_exe) + " -h </dev/null >/dev/null").check
41
42        val res =
43          progress.bash(
44            File.bash_path(cygwin_exe) + " --site " + Bash.string(mirror) + " --no-verify" +
45              " --local-package-dir 'C:\\temp'" +
46              " --root " + Bash.string(File.platform_path(cygwin)) +
47              " --packages " + quote((packages ::: more_packages).mkString(",")) +
48              " --no-shortcuts --no-startmenu --no-desktop --quiet-mode",
49            echo = true)
50        if (!res.ok || !cygwin_etc.is_dir) error("Failed")
51
52        for (name <- List("hosts", "protocols", "services", "networks", "passwd", "group"))
53          (cygwin_etc + Path.explode(name)).file.delete
54
55        (cygwin + Path.explode("Cygwin.bat")).file.delete
56
57        val archive = "cygwin-" + Date.Format("uuuuMMdd")(Date.now()) + ".tar.gz"
58        Isabelle_System.gnutar("-C " + File.bash_path(tmp_dir) +
59          " -czf " + Bash.string(archive) + " cygwin").check
60      })
61  }
62
63
64  /* Isabelle tool wrapper */
65
66  val isabelle_tool =
67    Isabelle_Tool("build_cygwin", "produce pre-canned Cygwin distribution for Isabelle", args =>
68    {
69      var mirror = default_mirror
70      var more_packages: List[String] = Nil
71
72      val getopts =
73        Getopts("""
74Usage: isabelle build_cygwin [OPTIONS]
75
76  Options are:
77    -R MIRROR    Cygwin mirror site (default """ + quote(default_mirror) + """)
78    -p NAME      additional Cygwin package
79
80  Produce pre-canned Cygwin distribution for Isabelle: this requires
81  Windows administrator mode.
82""",
83          "R:" -> (arg => mirror = arg),
84          "p:" -> (arg => more_packages ::= arg))
85
86      val more_args = getopts(args)
87      if (more_args.nonEmpty) getopts.usage()
88
89      build_cygwin(new Console_Progress(), mirror = mirror, more_packages = more_packages)
90    }, admin = true)
91}
92