Merge branch 'hardcode'
[jalview.git] / build.gradle
index d02b08c..a917a0d 100644 (file)
@@ -10,6 +10,10 @@ import org.gradle.plugins.ide.eclipse.model.Output
 import org.gradle.plugins.ide.eclipse.model.Library
 import java.security.MessageDigest
 import java.util.regex.Matcher
+import java.util.concurrent.Executors
+import java.util.concurrent.Future
+import java.util.concurrent.ScheduledExecutorService
+import java.util.concurrent.TimeUnit
 import groovy.transform.ExternalizeMethods
 import groovy.util.XmlParser
 import groovy.xml.XmlUtil
@@ -47,8 +51,9 @@ plugins {
   id 'java'
   id 'application'
   id 'eclipse'
+  id "com.diffplug.spotless" version "6.18.0" //.gradle.spotless" "3.28.0"
+  id 'com.github.johnrengelman.shadow' version '8.1.1' // was 4.0.3
   id "com.diffplug.gradle.spotless" version "3.28.0"
-  id 'com.github.johnrengelman.shadow' version '4.0.3'
   id 'com.install4j.gradle' version '10.0.3'
   id 'com.dorongold.task-tree' version '2.1.1' // only needed to display task dependency tree with  gradle task1 [task2 ...] taskTree
   id 'com.palantir.git-version' version '0.13.0' apply false
@@ -189,6 +194,7 @@ ext {
   testDir = string("${jalviewDir}/${bareTestSourceDir}")
 
   classesDir = string("${jalviewDir}/${classes_dir}")
+  outputDir = file(classesDir)
 
   // clover
   useClover = clover.equals("true")
@@ -574,7 +580,10 @@ ext {
   eclipseBinary = string("")
   eclipseVersion = string("")
   eclipseDebug = false
-  
+
+  jalviewjsChromiumUserDir = "${jalviewjsBuildDir}/${jalviewjs_chromium_user_dir}"
+  jalviewjsChromiumProfileDir = "${ext.jalviewjsChromiumUserDir}/${jalviewjs_chromium_profile_name}"
+
   // ENDEXT
 }
 
@@ -1276,15 +1285,15 @@ def mdFileComponents(File mdFile, def dateOnly=false) {
       }
       if (inFrontMatter) {
         def m = null
-        if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
+        if (m == line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
           map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
-        } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
+        } else if (m == line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
           map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
-        } else if (m = line =~ /^channel:\s*(\S+)/) {
+        } else if (m == line =~ /^channel:\s*(\S+)/) {
           map["channel"] = m[0][1]
-        } else if (m = line =~ /^version:\s*(\S+)/) {
+        } else if (m == line =~ /^version:\s*(\S+)/) {
           map["version"] = m[0][1]
-        } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
+        } else if (m == line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
           map[ m[0][1] ] = m[0][2]
         }
         if (dateOnly && map["date"] != null) {
@@ -1343,7 +1352,7 @@ task hugoTemplates {
       def inSection = false
       changes.eachLine { line ->
         def m = null
-        if (m = line =~ /^##([^#].*)$/) {
+        if (m == line =~ /^##([^#].*)$/) {
           if (inSection) {
             changesHugo += "</div>\n\n"
           }
@@ -1353,7 +1362,7 @@ task hugoTemplates {
           section = section.replaceAll(/[^a-z0-9_\-]/, "")
           changesHugo += "<div class=\"${section}\">\n\n"
           inSection = true
-        } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
+        } else if (m == line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
           def comment = m[0][2].trim()
           if (comment != "") {
             comment = comment.replaceAll('"', "&quot;")
@@ -1423,7 +1432,7 @@ def getMdSections(String content) {
   def sectionName = null
   content.eachLine { line ->
     def m = null
-    if (m = line =~ /^##([^#].*)$/) {
+    if (m == line =~ /^##([^#].*)$/) {
       if (sectionName != null) {
         sections[sectionName] = sectionContent
         sectionName = null
@@ -1479,6 +1488,7 @@ task copyHelp(type: Copy) {
 }
 
 
+/*
 task releasesTemplates {
   group "help"
   description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
@@ -1555,9 +1565,9 @@ task releasesTemplates {
       def lm = null
       def rContentProcessed = ""
       rContent.eachLine { line ->
-        if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
+        if (lm == line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
           line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
-      } else if (lm = line =~ /^###([^#]+.*)$/) {
+      } else if (lm == line =~ /^###([^#]+.*)$/) {
           line = "_${lm[0][1].trim()}_"
         }
         rContentProcessed += line + "\n"
@@ -1615,6 +1625,7 @@ task releasesTemplates {
   outputs.file(whatsnewHtmlFile)
 }
 
+*/
 
 task copyResources(type: Copy) {
   group = "build"
@@ -1676,6 +1687,7 @@ task copyChannelResources(type: Copy) {
 
 task createBuildProperties(type: WriteProperties) {
   dependsOn copyResources
+  dependsOn copyChannelResources
   group = "build"
   description = "Create the ${buildProperties} file"
   
@@ -1699,6 +1711,7 @@ task createBuildProperties(type: WriteProperties) {
 
 task buildIndices(type: JavaExec) {
   dependsOn copyHelp
+  //dependsOn releasesTemplates
   classpath = sourceSets.main.compileClasspath
   main = "com.sun.java.help.search.Indexer"
   workingDir = "${helpBuildDir}/${help_dir}"
@@ -1726,18 +1739,25 @@ task prepare {
   dependsOn buildResources
   dependsOn copyDocs
   dependsOn copyHelp
-  dependsOn releasesTemplates
+  //dependsOn releasesTemplates
   dependsOn convertMdFiles
   dependsOn buildIndices
 }
 
 
+// random block of dependencies
 compileJava.dependsOn prepare
 run.dependsOn compileJava
-compileTestJava.dependsOn compileJava
-
-
-
+//run.dependsOn prepare
+compileTestJava.dependsOn compileJava //
+compileTestJava.dependsOn buildIndices //
+processResources.dependsOn copyChannelResources //
+processResources.dependsOn copyResources //
+processResources.dependsOn createBuildProperties //
+processResources.dependsOn copyDocs //
+processResources.dependsOn convertMdFiles //
+processResources.dependsOn copyHelp //
+processResources.dependsOn buildIndices //
 test {
   group = "Verification"
   description = "Runs all testTaskN tasks)"
@@ -1998,6 +2018,7 @@ private static void printResults(allResults) {
 /* END of test tasks results summary */
 
 
+/*
 task compileLinkCheck(type: JavaCompile) {
   options.fork = true
   classpath = files("${jalviewDir}/${utils_dir}")
@@ -2032,6 +2053,7 @@ task linkCheck(type: JavaExec) {
   inputs.dir(helpBuildDir)
   outputs.file(helpLinksCheckerOutFile)
 }
+*/
 
 
 // import the pubhtmlhelp target
@@ -2046,10 +2068,14 @@ task cleanPackageDir(type: Delete) {
   }
 }
 
+// block of dependencies
+//compileTestJava.dependsOn compileLinkCheck //
+//copyChannelResources.dependsOn compileLinkCheck //
+//convertMdFiles.dependsOn compileLinkCheck //
 
 jar {
   dependsOn prepare
-  dependsOn linkCheck
+  dependsOn //linkCheck
 
   manifest {
     attributes "Main-Class": main_class,
@@ -2060,7 +2086,7 @@ jar {
   }
 
   def outputDir = "${jalviewDir}/${package_dir}"
-  destinationDirectory = file(outputDir)
+  outputDir = file(outputDir)
   archiveFileName = rootProject.name+".jar"
   duplicatesStrategy "EXCLUDE"
 
@@ -2134,7 +2160,7 @@ shadowJar {
 
   mainClassName = shadow_jar_main_class
   mergeServiceFiles()
-  classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
+  archiveClassifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
   minimize()
 }
 
@@ -4203,13 +4229,6 @@ task eclipseAutoBuildTask {
 }
 
 
-task jalviewjs {
-  group "JalviewJS"
-  description "Build the site"
-  dependsOn jalviewjsBuildSite
-}
-
-
 task jalviewjsCopyStderrLaunchFile(type: Copy) {
   from file(jalviewjs_stderr_launch)
   into jalviewjsSiteDir
@@ -4218,56 +4237,133 @@ task jalviewjsCopyStderrLaunchFile(type: Copy) {
   outputs.file jalviewjsStderrLaunchFilename
 }
 
+task cleanJalviewjsChromiumUserDir {
+  doFirst {
+    delete jalviewjsChromiumUserDir
+  }
+  outputs.dir jalviewjsChromiumUserDir
+  // always run when depended on
+  outputs.upToDateWhen { !file(jalviewjsChromiumUserDir).exists() }
+}
+
 task jalviewjsChromiumProfile {
-  def profileDir = "${jalviewjsBuildDir}/${jalviewjs_chromium_user_dir}/${jalviewjs_chromium_profile_name}"
-  def firstRun = file("${profileDir}/First Run")
+  dependsOn cleanJalviewjsChromiumUserDir
+  mustRunAfter cleanJalviewjsChromiumUserDir
+
+  def firstRun = file("${jalviewjsChromiumUserDir}/First Run")
 
   doFirst {
-    mkdir profileDir
+    mkdir jalviewjsChromiumProfileDir
     firstRun.text = ""
   }
-  
   outputs.file firstRun
 }
 
-task jalviewjsLaunchTest(type: Exec) {
+task jalviewjsLaunchTest {
   group "Test"
   description "Check JalviewJS opens in a browser"
   dependsOn jalviewjsBuildSite
   dependsOn jalviewjsCopyStderrLaunchFile
   dependsOn jalviewjsChromiumProfile
 
-  def chromiumBinary = jalviewjs_chromium_binary
+  def macOS = OperatingSystem.current().isMacOsX()
+  def chromiumBinary = macOS ? jalviewjs_macos_chromium_binary : jalviewjs_chromium_binary
   if (chromiumBinary.startsWith("~/")) {
     chromiumBinary = System.getProperty("user.home") + chromiumBinary.substring(1)
   }
   
+  def stdout
+  def stderr
   doFirst {
-    def exec = file(chromiumBinary)
-    if (!exec.exists()) {
-      throw new GradleException("Could not find chromium binary '${chromiumBinary}'. Cannot run task ${name}.")
+    def timeoutms = Integer.valueOf(jalviewjs_chromium_overall_timeout) * 1000
+    
+    def binary = file(chromiumBinary)
+    if (!binary.exists()) {
+      throw new StopExecutionException("Could not find chromium binary '${chromiumBinary}'. Cannot run task ${name}.")
     }
-  }
+    stdout = new ByteArrayOutputStream()
+    stderr = new ByteArrayOutputStream()
+    def execStdout
+    def execStderr
+    if (jalviewjs_j2s_to_console.equals("true")) {
+      execStdout = new org.apache.tools.ant.util.TeeOutputStream(
+        stdout,
+        System.out)
+      execStderr = new org.apache.tools.ant.util.TeeOutputStream(
+        stderr,
+        System.err)
+    } else {
+      execStdout = stdout
+      execStderr = stderr
+    }
+    def execArgs = [
+      "--no-sandbox", // --no-sandbox IS USED BY THE THORIUM APPIMAGE ON THE BUILDSERVER
+      "--headless=new",
+      "--disable-gpu",
+      "--timeout=${timeoutms}",
+      "--virtual-time-budget=${timeoutms}",
+      "--user-data-dir=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_chromium_user_dir}",
+      "--profile-directory=${jalviewjs_chromium_profile_name}",
+      "--allow-file-access-from-files",
+      "--enable-logging=stderr",
+      "file://${jalviewDirAbsolutePath}/${jalviewjsStderrLaunchFilename}"
+    ]
+    
+    if (true || macOS) {
+      ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
+      Future f1 = executor.submit(
+        () -> {
+          exec {
+            standardOutput = execStdout
+            errorOutput = execStderr
+            executable(chromiumBinary)
+            args(execArgs)
+            println "COMMAND: '"+commandLine.join(" ")+"'"
+          }
+          executor.shutdownNow()
+        }
+      )
 
-  executable(chromiumBinary)
-  args([
-    "--headless=new",
-    "--timeout=60000",
-    "--virtual-time-budget=60000",
-    "--user-data-dir=${jalviewjsBuildDir}/${jalviewjs_chromium_user_dir}",
-    "--profile-directory=${jalviewjs_chromium_profile_name}",
-    "--allow-file-access-from-files",
-    "--enable-logging=stderr",
-    jalviewjsStderrLaunchFilename
-  ])
-
-  standardOutput = new ByteArrayOutputStream()
-  errorOutput = new ByteArrayOutputStream()
+      def noChangeBytes = 0
+      def noChangeIterations = 0
+      executor.scheduleAtFixedRate(
+        () -> {
+          String stderrString = stderr.toString()
+          // shutdown the task if we have a success string
+          if (stderrString.contains(jalviewjs_desktop_init_string)) {
+            f1.cancel()
+            Thread.sleep(1000)
+            executor.shutdownNow()
+          }
+          // if no change in stderr for 10s then also end
+          if (noChangeIterations >= jalviewjs_chromium_idle_timeout) {
+            executor.shutdownNow()
+          }
+          if (stderrString.length() == noChangeBytes) {
+            noChangeIterations++
+          } else {
+            noChangeBytes = stderrString.length()
+            noChangeIterations = 0
+          }
+        },
+        1, 1, TimeUnit.SECONDS)
+
+      executor.schedule(new Runnable(){
+        public void run(){
+          f1.cancel()
+          executor.shutdownNow()
+        }
+      }, timeoutms, TimeUnit.MILLISECONDS)
+
+      executor.awaitTermination(timeoutms+10000, TimeUnit.MILLISECONDS)
+      executor.shutdownNow()
+    }
+
+  }
   
   doLast {
     def found = false
-    def stderr = errorOutput.toString()
-    stderr.eachLine { line ->
+    stderr.toString().eachLine { line ->
       if (line.contains(jalviewjs_desktop_init_string)) {
         println("Found line '"+line+"'")
         found = true
@@ -4279,3 +4375,11 @@ task jalviewjsLaunchTest(type: Exec) {
     }
   }
 }
+  
+
+task jalviewjs {
+  group "JalviewJS"
+  description "Build the JalviewJS site and run the launch test"
+  dependsOn jalviewjsBuildSite
+  dependsOn jalviewjsLaunchTest
+}