--- 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