some support for Phabricator server;
authorwenzelm
Wed, 30 Oct 2019 15:50:57 +0100
changeset 70967 79736ffe77c3
parent 70966 acc3bac0d7c5
child 70968 46847076477c
some support for Phabricator server;
etc/options
src/Pure/System/isabelle_tool.scala
src/Pure/Tools/phabricator.scala
src/Pure/build-jars
--- a/etc/options	Tue Oct 29 19:42:40 2019 +0100
+++ b/etc/options	Wed Oct 30 15:50:57 2019 +0100
@@ -343,6 +343,21 @@
 option build_log_transaction_size : int = 1  -- "number of log files for each db update"
 
 
+section "Phabricator server"
+
+option phabricator_user : string = "phabricator"
+
+option phabricator_www_user : string = "www-data"
+option phabricator_www_root : string = "/var/www"
+
+option phabricator_smtp_host : string = ""
+option phabricator_smtp_port : int = 465
+option phabricator_smtp_user : string = ""
+option phabricator_smtp_passwd : string = ""
+option phabricator_smtp_protocol : string = "ssl"
+option phabricator_smtp_message_id : bool = true
+
+
 section "Isabelle/Scala/ML system channel"
 
 option system_channel_address : string = ""
--- a/src/Pure/System/isabelle_tool.scala	Tue Oct 29 19:42:40 2019 +0100
+++ b/src/Pure/System/isabelle_tool.scala	Wed Oct 30 15:50:57 2019 +0100
@@ -151,6 +151,8 @@
   ML_Process.isabelle_tool,
   Mkroot.isabelle_tool,
   Options.isabelle_tool,
+  Phabricator.isabelle_tool1,
+  Phabricator.isabelle_tool2,
   Present.isabelle_tool,
   Profiling_Report.isabelle_tool,
   Server.isabelle_tool,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pure/Tools/phabricator.scala	Wed Oct 30 15:50:57 2019 +0100
@@ -0,0 +1,203 @@
+/*  Title:      Pure/Tools/phabricator.scala
+    Author:     Makarius
+
+Support for Phabricator server. See also:
+  - https://www.phacility.com/phabricator
+  - https://secure.phabricator.com/book/phabricator
+*/
+
+package isabelle
+
+
+object Phabricator
+{
+  /** defaults **/
+
+  val default_name = "vcs"
+
+  def default_prefix(name: String): String = "phabricator_" + name
+
+  def default_root(options: Options, name: String): Path =
+    Path.explode(options.string("phabricator_www_root")) + Path.basic(default_prefix(name))
+
+  def default_repo(options: Options, name: String): Path =
+    default_root(options, name) + Path.basic("repo")
+
+  val packages: List[String] =
+    Build_Docker.packages :::
+    // https://secure.phabricator.com/source/phabricator/browse/master/scripts/install/install_ubuntu.sh 15e6e2adea61
+    List("git", "mysql-server", "apache2", "libapache2-mod-php", "php", "php-mysql",
+      "php-gd", "php-curl", "php-apcu", "php-cli", "php-json", "php-mbstring")
+
+
+
+  /** global configuration **/
+
+  val global_config = Path.explode("/etc/isabelle-phabricator.conf")
+
+  sealed case class Config(name: String, root: Path)
+
+  def read_config(): List[Config] =
+  {
+    if (global_config.is_file) {
+      for (entry <- Library.trim_split_lines(File.read(global_config)) if entry.nonEmpty)
+      yield {
+        space_explode(':', entry) match {
+          case List(name, root) => Config(name, Path.explode(root))
+          case _ => error("Malformed config file " + global_config + "\nentry " + quote(entry))
+        }
+      }
+    }
+    else Nil
+  }
+
+  def write_config(configs: List[Config])
+  {
+    File.write(global_config,
+      configs.map(config => config.name + ":" + config.root.implode).mkString("", "\n", "\n"))
+  }
+
+  def get_config(name: String): Config =
+    read_config().find(config => config.name == name) getOrElse
+      error("Bad Isabelle/Phabricator installation " + quote(name))
+
+
+
+  /** setup **/
+
+  def phabricator_setup(
+    options: Options,
+    name: String = default_name,
+    prefix: String = "",
+    root: String = "",
+    repo: String = "",
+    progress: Progress = No_Progress)
+  {
+    /* system environment */
+
+    Linux.check_system_root()
+
+    Linux.package_update(progress = progress)
+    Linux.check_reboot_required()
+
+    Linux.package_install(packages, progress = progress)
+    Linux.check_reboot_required()
+
+
+    /* basic installation */
+
+    val prefix_name = proper_string(prefix) getOrElse default_prefix(name)
+    val root_path = if (root.nonEmpty) Path.explode(root) else default_root(options, name)
+    val repo_path = if (repo.nonEmpty) Path.explode(repo) else default_repo(options, name)
+
+    val configs = read_config()
+
+    for (config <- configs if config.name == name) {
+      error("Duplicate Phabricator installation " + quote(name) + " in " + config.root)
+    }
+
+    if (!Isabelle_System.bash("mkdir -p " + File.bash_path(root_path)).ok) {
+      error("Failed to create root directory " + root_path)
+    }
+
+    progress.bash(cwd = root_path.file, echo = true,
+      script = """
+        set -e
+        chown """ + Bash.string(options.string("phabricator_www_user")) + """ .
+        chmod 755 .
+
+        git clone https://github.com/phacility/libphutil.git
+        git clone https://github.com/phacility/arcanist.git
+        git clone https://github.com/phacility/phabricator.git
+      """).check
+
+    val config = Config(name, root_path)
+    write_config(configs ::: List(config))
+  }
+
+
+  /* Isabelle tool wrapper */
+
+  val isabelle_tool1 =
+    Isabelle_Tool("phabricator_setup", "setup Phabricator server on Ubuntu Linux", args =>
+    {
+      var options = Options.init()
+      var prefix = ""
+      var root = ""
+      var repo = ""
+
+      val getopts =
+        Getopts("""
+Usage: isabelle phabricator_setup [OPTIONS] [NAME]
+
+  Options are:
+    -R DIR       repository directory (default: """ + default_repo(options, "NAME") + """)
+    -o OPTION    override Isabelle system OPTION (via NAME=VAL or NAME)
+    -p PREFIX    prefix for derived names (default: """ + default_prefix("NAME") + """)
+    -r DIR       installation root directory (default: """ + default_root(options, "NAME") + """)
+
+  Install Phabricator as Ubuntu LAMP application (Linux, Apache, MySQL, PHP).
+
+  Slogan: "Discuss. Plan. Code. Review. Test.
+  Every application your project needs, all in one tool."
+
+  The installation NAME (default: """ + quote(default_name) + """) is mapped to
+  a regular Unix user and used for public SSH access.
+""",
+          "R:" -> (arg => repo = arg),
+          "o:" -> (arg => options = options + arg),
+          "p:" -> (arg => prefix = arg),
+          "r:" -> (arg => root = arg))
+
+      val more_args = getopts(args)
+
+      val name =
+        more_args match {
+          case Nil => default_name
+          case List(name) => name
+          case _ => getopts.usage()
+        }
+
+      val progress = new Console_Progress
+
+      phabricator_setup(options, name, prefix = prefix, root = root, repo = repo,
+        progress = progress)
+    })
+
+
+
+  /** update **/
+
+  def phabricator_update(name: String, progress: Progress = No_Progress)
+  {
+    Linux.check_system_root()
+
+    ???
+  }
+
+
+  /* Isabelle tool wrapper */
+
+  val isabelle_tool2 =
+    Isabelle_Tool("phabricator_update", "update Phabricator server installation", args =>
+    {
+      val getopts =
+        Getopts("""
+Usage: isabelle phabricator_update [NAME]
+
+  Update Phabricator installation, with lookup of NAME (default + """ + quote(default_name) + """)
+  in """ + global_config + "\n")
+
+      val more_args = getopts(args)
+      val name =
+        more_args match {
+          case Nil => default_name
+          case List(name) => name
+          case _ => getopts.usage()
+        }
+
+      val progress = new Console_Progress
+
+      phabricator_update(name, progress = progress)
+    })
+}
--- a/src/Pure/build-jars	Tue Oct 29 19:42:40 2019 +0100
+++ b/src/Pure/build-jars	Wed Oct 30 15:50:57 2019 +0100
@@ -154,6 +154,7 @@
   Tools/fontforge.scala
   Tools/main.scala
   Tools/mkroot.scala
+  Tools/phabricator.scala
   Tools/print_operation.scala
   Tools/profiling_report.scala
   Tools/server.scala