X-Git-Url: http://source.jalview.org/gitweb/?p=jalview.git;a=blobdiff_plain;f=build.gradle;h=4f9798cc05f9739e4e5f9b01587a9ad5d0068697;hp=2060073b19e51e4f5b6ee471d6a5be61ff3461d2;hb=282aa9129a74235dc8d6c22b123d51eb1abd2f55;hpb=49524339723648257ede072113f9fa4928435b20 diff --git a/build.gradle b/build.gradle index 2060073..4f9798c 100644 --- a/build.gradle +++ b/build.gradle @@ -3,19 +3,41 @@ */ import org.apache.tools.ant.filters.ReplaceTokens import org.gradle.internal.os.OperatingSystem +import org.gradle.plugins.ide.internal.generator.PropertiesPersistableConfigurationObject +import org.gradle.api.internal.PropertiesTransformer +import org.gradle.util.ConfigureUtil import org.gradle.plugins.ide.eclipse.model.Output import org.gradle.plugins.ide.eclipse.model.Library import java.security.MessageDigest import groovy.transform.ExternalizeMethods import groovy.util.XmlParser import groovy.xml.XmlUtil - +import groovy.json.JsonBuilder +import com.vladsch.flexmark.util.ast.Node +import com.vladsch.flexmark.html.HtmlRenderer +import com.vladsch.flexmark.parser.Parser +import com.vladsch.flexmark.util.data.MutableDataSet +import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension +import com.vladsch.flexmark.ext.tables.TablesExtension +import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension +import com.vladsch.flexmark.ext.autolink.AutolinkExtension +import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension +import com.vladsch.flexmark.ext.toc.TocExtension +import com.google.common.hash.HashCode +import com.google.common.hash.Hashing +import com.google.common.io.Files +import org.jsoup.Jsoup +import org.jsoup.nodes.Element buildscript { repositories { mavenCentral() mavenLocal() } + dependencies { + classpath "com.vladsch.flexmark:flexmark-all:0.62.0" + classpath "org.jsoup:jsoup:1.14.3" + } } @@ -23,9 +45,11 @@ plugins { id 'java' id 'application' id 'eclipse' + id "com.diffplug.gradle.spotless" version "3.28.0" id 'com.github.johnrengelman.shadow' version '4.0.3' - id 'com.install4j.gradle' version '8.0.4' - id 'com.dorongold.task-tree' version '1.5' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree + id 'com.install4j.gradle' version '9.0.6' + id 'com.dorongold.task-tree' version '2.1.0' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree + id 'com.palantir.git-version' version '0.13.0' apply false } repositories { @@ -35,29 +59,19 @@ repositories { } + // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use def string(Object o) { return o == null ? "" : o.toString() } - -ext { - jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath() - jalviewDirRelativePath = jalviewDir - - // local build environment properties - // can be "projectDir/local.properties" - def localProps = "${projectDir}/local.properties" - def propsFile = null; - if (file(localProps).exists()) { - propsFile = localProps - } - // or "../projectDir_local.properties" - def dirLocalProps = projectDir.getParent() + "/" + projectDir.getName() + "_local.properties" - if (file(dirLocalProps).exists()) { - propsFile = dirLocalProps +def overrideProperties(String propsFileName, boolean output = false) { + if (propsFileName == null) { + return } - if (propsFile != null) { + def propsFile = file(propsFileName) + if (propsFile != null && propsFile.exists()) { + println("Using properties from file '${propsFileName}'") try { def p = new Properties() def localPropsFIS = new FileInputStream(propsFile) @@ -65,24 +79,51 @@ ext { localPropsFIS.close() p.each { key, val -> - def oldval = findProperty(key) - setProperty(key, val) - if (oldval != null) { - println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'") + def oldval + if (project.hasProperty(key)) { + oldval = project.findProperty(key) + project.setProperty(key, val) + if (output) { + println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'") + } } else { - println("Setting unknown property '${key}' with ${file(propsFile).getName()}s value '${val}'") + ext.setProperty(key, val) + if (output) { + println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'") + } } } } catch (Exception e) { - System.out.println("Exception reading local.properties") + println("Exception reading local.properties") + e.printStackTrace() } } +} + +ext { + jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath() + jalviewDirRelativePath = jalviewDir + date = new Date() + + getdownChannelName = CHANNEL.toLowerCase() + // default to "default". Currently only has different cosmetics for "develop", "release", "default" + propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default" + // Import channel_properties + channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}") + channelGradleProperties = string("${channelDir}/channel_gradle.properties") + channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}") + overrideProperties(channelGradleProperties, false) + // local build environment properties + // can be "projectDir/local.properties" + overrideProperties("${projectDir}/local.properties", true) + // or "../projectDir_local.properties" + overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true) //// // Import releaseProps from the RELEASE file // or a file specified via JALVIEW_RELEASE_FILE if defined // Expect jalview.version and target release branch in jalview.release - def releaseProps = new Properties(); + releaseProps = new Properties(); def releasePropFile = findProperty("JALVIEW_RELEASE_FILE"); def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE"; try { @@ -94,9 +135,10 @@ ext { } //// // Set JALVIEW_VERSION if it is not already set - if (findProperty(JALVIEW_VERSION)==null || "".equals(JALVIEW_VERSION)) { + if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) { JALVIEW_VERSION = releaseProps.get("jalview.version") } + println("JALVIEW_VERSION is set to '${JALVIEW_VERSION}'") // this property set when running Eclipse headlessly j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild") @@ -115,6 +157,11 @@ ext { } else { println("HEADLESS BUILD") } + + J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable") + if (J2S_ENABLED) { + println("J2S ENABLED") + } /* *-/ System.properties.sort { it.key }.each { key, val -> println("SYSTEM PROPERTY ${key}='${val}'") @@ -125,6 +172,9 @@ ext { } */ + // datestamp + buildDate = new Date().format("yyyyMMdd") + // essentials bareSourceDir = string(source_dir) sourceDir = string("${jalviewDir}/${bareSourceDir}") @@ -145,29 +195,43 @@ ext { //cloverTestClassesDir = cloverClassesDir cloverDb = string("${cloverBuildDir}/clover.db") - resourceClassesDir = useClover ? cloverClassesDir : classesDir - testSourceDir = useClover ? cloverTestInstrDir : testDir testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}" - getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}") + getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}") + getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}") + getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}") + getdownFullArchiveDir = null + getdownTextLines = [] + getdownLaunchJvl = null + getdownVersionLaunchJvl = null buildDist = true + buildProperties = null // the following values might be overridden by the CHANNEL switch - getdownChannelName = CHANNEL.toLowerCase() getdownDir = string("${getdownChannelName}/${JAVA_VERSION}") getdownAppBase = string("${getdown_channel_base}/${getdownDir}") + getdownArchiveAppBase = getdown_archive_base getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}") getdownAppDistDir = getdown_app_dir_alt - buildProperties = string("${classesDir}/${build_properties_file}") + getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}") + getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application reportRsyncCommand = false jvlChannelName = CHANNEL.toLowerCase() install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build - install4jDSStore = "DS_Store-NON-RELEASE" - install4jDMGBackgroundImage = "jalview_dmg_background-NON-RELEASE.png" + install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}" + install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}" install4jInstallerName = "${jalview_name} Non-Release Installer" - install4jExecutableName = jalview_name.replaceAll("[^\\w]+", "_").toLowerCase() + install4jExecutableName = install4j_executable_name install4jExtraScheme = "jalviewx" + install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}") + install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}") + install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}") + install4jBackground = string("${install4j_images_dir}/${install4j_background}") + install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}" + install4jCheckSums = true + + applicationName = "${jalview_name}" switch (CHANNEL) { case "BUILD": @@ -183,12 +247,11 @@ ext { install4jExtraScheme = "jalviewb" break - case "RELEASE": + case [ "RELEASE", "JALVIEWJS-RELEASE" ]: getdownAppDistDir = getdown_app_dir_release + getdownSetAppBaseProperty = true reportRsyncCommand = true install4jSuffix = "" - install4jDSStore = "DS_Store" - install4jDMGBackgroundImage = "jalview_dmg_background.png" install4jInstallerName = "${jalview_name} Installer" break @@ -210,7 +273,7 @@ ext { case "ARCHIVELOCAL": getdownChannelName = string("archive/${JALVIEW_VERSION}") getdownDir = string("${getdownChannelName}/${JAVA_VERSION}") - getdownAppBase = file(getdownWebsiteDir).toURI().toString() + getdownAppBase = file(getdownAppBaseDir).toURI().toString() if (!file("${ARCHIVEDIR}/${package_dir}").exists()) { throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution") } else { @@ -226,32 +289,33 @@ ext { case "DEVELOP": reportRsyncCommand = true - + getdownSetAppBaseProperty = true // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version - JALVIEW_VERSION=JALVIEW_VERSION+"-develop" + JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}" install4jSuffix = "Develop" - install4jDSStore = "DS_Store-DEVELOP" - install4jDMGBackgroundImage = "jalview_dmg_background-DEVELOP.png" install4jExtraScheme = "jalviewd" install4jInstallerName = "${jalview_name} Develop Installer" break case "TEST-RELEASE": reportRsyncCommand = true - - // TEST-RELEASE is usually associated with a Jalview release series so set the version - JALVIEW_VERSION=JALVIEW_VERSION+"-test" - + getdownSetAppBaseProperty = true + // Don't ignore transpile errors for release build + if (jalviewjs_ignore_transpile_errors.equals("true")) { + jalviewjs_ignore_transpile_errors = "false" + println("Setting jalviewjs_ignore_transpile_errors to 'false'") + } + JALVIEW_VERSION = JALVIEW_VERSION+"-test" install4jSuffix = "Test" - install4jDSStore = "DS_Store-TEST-RELEASE" - install4jDMGBackgroundImage = "jalview_dmg_background-TEST.png" install4jExtraScheme = "jalviewt" install4jInstallerName = "${jalview_name} Test Installer" break case ~/^SCRATCH(|-[-\w]*)$/: getdownChannelName = CHANNEL + JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL + getdownDir = string("${getdownChannelName}/${JAVA_VERSION}") getdownAppBase = string("${getdown_channel_base}/${getdownDir}") reportRsyncCommand = true @@ -267,16 +331,17 @@ ext { } JALVIEW_VERSION = "TEST" install4jSuffix = "Test-Local" - install4jDSStore = "DS_Store-TEST-RELEASE" - install4jDMGBackgroundImage = "jalview_dmg_background-TEST.png" install4jExtraScheme = "jalviewt" install4jInstallerName = "${jalview_name} Test Installer" break - case "LOCAL": - getdownAppBase = file(getdownWebsiteDir).toURI().toString() + case [ "LOCAL", "JALVIEWJS" ]: + JALVIEW_VERSION = "TEST" + getdownAppBase = file(getdownAppBaseDir).toURI().toString() + getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString() getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}") install4jExtraScheme = "jalviewl" + install4jCheckSums = false break default: // something wrong specified @@ -284,20 +349,31 @@ ext { break } + JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_") + hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json") + hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md") // override getdownAppBase if requested if (findProperty("getdown_appbase_override") != null) { - getdownAppBase = string(getProperty("getdown_appbase_override")) + // revert to LOCAL if empty string + if (string(getdown_appbase_override) == "") { + getdownAppBase = file(getdownAppBaseDir).toURI().toString() + getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}") + } else if (string(getdown_appbase_override).startsWith("file://")) { + getdownAppBase = string(getdown_appbase_override) + getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}") + } else { + getdownAppBase = string(getdown_appbase_override) + } println("Overriding getdown appbase with '${getdownAppBase}'") } // sanitise file name for jalview launcher file for this channel jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_") // install4j application and folder names if (install4jSuffix == "") { - install4jApplicationName = "${jalview_name}" install4jBundleId = "${install4j_bundle_id}" install4jWinApplicationId = install4j_release_win_application_id } else { - install4jApplicationName = "${jalview_name} ${install4jSuffix}" + applicationName = "${jalview_name} ${install4jSuffix}" install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase() // add int hash of install4jSuffix to the last part of the application_id def id = install4j_release_win_application_id @@ -307,33 +383,47 @@ ext { } // sanitise folder and id names // install4jApplicationFolder = e.g. "Jalview Build" - install4jApplicationFolder = install4jApplicationName + install4jApplicationFolder = applicationName .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \ .replaceAll("_+", "_") // collapse __ - install4jInternalId = install4jApplicationName + install4jInternalId = applicationName .replaceAll(" ","_") .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.] .replaceAll("_+", "") // collapse __ //.replaceAll("_*-_*", "-") // collapse _-_ - install4jUnixApplicationFolder = install4jApplicationName + install4jUnixApplicationFolder = applicationName .replaceAll(" ","_") .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.] .replaceAll("_+", "_") // collapse __ .replaceAll("_*-_*", "-") // collapse _-_ .toLowerCase() - getdownAppDir = string("${getdownWebsiteDir}/${getdownAppDistDir}") - //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}" - getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}") - getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}") + getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local" + getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}") + //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}" + getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}") + getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}") getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/") getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}") /* compile without modules -- using classpath libraries modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"]) modules_runtimeClasspath = modules_compileClasspath */ - gitHash = string("") - gitBranch = string("") + + gitHash = "SOURCE" + gitBranch = "Source" + try { + apply plugin: "com.palantir.git-version" + def details = versionDetails() + gitHash = details.gitHash + gitBranch = details.branchName + } catch(org.gradle.api.internal.plugins.PluginApplicationException e) { + println("Not in a git repository. Using git values from RELEASE properties file.") + gitHash = releaseProps.getProperty("git.hash") + gitBranch = releaseProps.getProperty("git.branch") + } catch(java.lang.RuntimeException e1) { + throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.") + } println("Using a ${CHANNEL} profile.") @@ -369,16 +459,16 @@ ext { '--add-modules', j11modules ] */ - } else if (JAVA_VERSION.equals("12") || JAVA_VERSION.equals("13")) { - JAVA_INTEGER_VERSION = JAVA_VERSION - libDir = j11libDir - libDistDir = j11libDir - compile_source_compatibility = JAVA_VERSION - compile_target_compatibility = JAVA_VERSION + } else if (JAVA_VERSION.equals("17")) { + JAVA_INTEGER_VERSION = string("17") + libDir = j17libDir + libDistDir = j17libDir + compile_source_compatibility = 17 + compile_target_compatibility = 17 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version")) getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version")) getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location")) - eclipseJavaRuntimeName = string("JavaSE-11") + eclipseJavaRuntimeName = string("JavaSE-17") /* compile without modules -- using classpath libraries additional_compiler_args += [ '--module-path', modules_compileClasspath.asPath, @@ -398,11 +488,11 @@ ext { jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1) } macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre") - macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-mac-x64.tar.gz") windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre") - windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-windows-x64.tar.gz") linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre") - linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-linux-x64.tar.gz") + macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz") + windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz") + linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz") install4jDir = string("${jalviewDir}/${install4j_utils_dir}") install4jConfFileName = string("jalview-install4j-conf.install4j") install4jConfFile = file("${install4jDir}/${install4jConfFileName}") @@ -411,12 +501,18 @@ ext { install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1) } + resourceBuildDir = string("${buildDir}/resources") + resourcesBuildDir = string("${resourceBuildDir}/resources_build") + helpBuildDir = string("${resourceBuildDir}/help_build") + docBuildDir = string("${resourceBuildDir}/doc_build") - + if (buildProperties == null) { + buildProperties = string("${resourcesBuildDir}/${build_properties_file}") + } buildingHTML = string("${jalviewDir}/${doc_dir}/building.html") - helpFile = string("${resourceClassesDir}/${help_dir}/help.jhm") helpParentDir = string("${jalviewDir}/${help_parent_dir}") helpSourceDir = string("${helpParentDir}/${help_dir}") + helpFile = string("${helpBuildDir}/${help_dir}/help.jhm") relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath()) @@ -435,7 +531,9 @@ ext { jalviewjsCoreClasslists = [] jalviewjsJalviewTemplateName = string(jalviewjs_name) jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}") + jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}") jalviewjsJ2sProps = null + jalviewjsJ2sPlugin = jalviewjs_j2s_plugin eclipseWorkspace = null eclipseBinary = string("") @@ -453,16 +551,14 @@ sourceSets { } resources { - srcDirs resourceDir - srcDirs += helpParentDir + srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ] } - jar.destinationDir = file("${jalviewDir}/${package_dir}") - compileClasspath = files(sourceSets.main.java.outputDir) compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"]) runtimeClasspath = compileClasspath + runtimeClasspath += files(sourceSets.main.resources.srcDirs) } clover { @@ -499,6 +595,7 @@ sourceSets { compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"]) runtimeClasspath = compileClasspath + runtimeClasspath += files(sourceSets.test.resources.srcDirs) } } @@ -519,14 +616,12 @@ eclipse { classpath { //defaultOutputDir = sourceSets.main.java.outputDir - def removeThese = [] - configurations.each{ - if (it.isCanBeResolved()) { - removeThese += it + configurations.each{ c-> + if (c.isCanBeResolved()) { + minusConfigurations += [c] } } - minusConfigurations += removeThese plusConfigurations = [ ] file { @@ -625,6 +720,22 @@ eclipse { props.putAt(t, v) } } + // codestyle file -- overrides previous formatter prefs + def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}") + if (csFile.exists()) { + XmlParser parser = new XmlParser() + def profiles = parser.parse(csFile) + def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") } + if (profile != null) { + profile.'setting'.each { s -> + def id = s.'@id' + def value = s.'@value' + if (id != null && value != null) { + props.putAt(id, value) + } + } + } + } } } @@ -633,11 +744,68 @@ eclipse { if (IN_ECLIPSE) { // Don't want these to be activated if in headless build synchronizationTasks "eclipseSynchronizationTask" - autoBuildTasks "eclipseAutoBuildTask" + //autoBuildTasks "eclipseAutoBuildTask" + + } +} + + +/* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */ +// Class to allow updating arbitrary properties files +class PropertiesFile extends PropertiesPersistableConfigurationObject { + public PropertiesFile(PropertiesTransformer t) { super(t); } + @Override protected void load(Properties properties) { } + @Override protected void store(Properties properties) { } + @Override protected String getDefaultResourceName() { return ""; } + // This is necessary, because PropertiesPersistableConfigurationObject fails + // if no default properties file exists. + @Override public void loadDefaults() { load(new StringBufferInputStream("")); } +} +// Task to update arbitrary properties files (set outputFile) +class PropertiesFileTask extends PropertiesGeneratorTask { + private final PropertiesFileContentMerger file; + public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); } + protected PropertiesFile create() { return new PropertiesFile(getTransformer()); } + protected void configure(PropertiesFile props) { + file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props); + } + public void file(Closure closure) { ConfigureUtil.configure(closure, file); } +} + +task eclipseUIPreferences(type: PropertiesFileTask) { + description = "Generate Eclipse additional settings" + def filename = "org.eclipse.jdt.ui.prefs" + outputFile = "$projectDir/.settings/${filename}" as File + file { + withProperties { + it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String) + } + } +} + +task eclipseGroovyCorePreferences(type: PropertiesFileTask) { + description = "Generate Eclipse additional settings" + def filename = "org.eclipse.jdt.groovy.core.prefs" + outputFile = "$projectDir/.settings/${filename}" as File + file { + withProperties { + it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String) + } } } +task eclipseAllPreferences { + dependsOn eclipseJdt + dependsOn eclipseUIPreferences + dependsOn eclipseGroovyCorePreferences +} + +eclipseUIPreferences.mustRunAfter eclipseJdt +eclipseGroovyCorePreferences.mustRunAfter eclipseJdt + +/* end of eclipse preferences hack */ + // clover bits @@ -859,22 +1027,23 @@ compileCloverJava { compileJava { - + // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ? + sourceCompatibility = compile_source_compatibility + targetCompatibility = compile_target_compatibility + options.compilerArgs = additional_compiler_args + options.encoding = "UTF-8" doFirst { - sourceCompatibility = compile_source_compatibility - targetCompatibility = compile_target_compatibility - options.compilerArgs = additional_compiler_args - print ("Setting target compatibility to "+targetCompatibility+"\n") + print ("Setting target compatibility to "+compile_target_compatibility+"\n") } } compileTestJava { + sourceCompatibility = compile_source_compatibility + targetCompatibility = compile_target_compatibility + options.compilerArgs = additional_compiler_args doFirst { - sourceCompatibility = compile_source_compatibility - targetCompatibility = compile_target_compatibility - options.compilerArgs = additional_compiler_args print ("Setting target compatibility to "+targetCompatibility+"\n") } } @@ -897,115 +1066,358 @@ cleanTest { // format is a string like date.format("dd MMMM yyyy") def getDate(format) { - def date = new Date() return date.format(format) } -task setGitVals { - def hashStdOut = new ByteArrayOutputStream() - exec { - commandLine "git", "rev-parse", "--short", "HEAD" - standardOutput = hashStdOut - ignoreExitValue true - } +def convertMdToHtml (FileTree mdFiles, File cssFile) { + MutableDataSet options = new MutableDataSet() + + def extensions = new ArrayList<>() + extensions.add(AnchorLinkExtension.create()) + extensions.add(AutolinkExtension.create()) + extensions.add(StrikethroughExtension.create()) + extensions.add(TaskListExtension.create()) + extensions.add(TablesExtension.create()) + extensions.add(TocExtension.create()) + + options.set(Parser.EXTENSIONS, extensions) + + // set GFM table parsing options + options.set(TablesExtension.WITH_CAPTION, false) + options.set(TablesExtension.COLUMN_SPANS, false) + options.set(TablesExtension.MIN_HEADER_ROWS, 1) + options.set(TablesExtension.MAX_HEADER_ROWS, 1) + options.set(TablesExtension.APPEND_MISSING_COLUMNS, true) + options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true) + options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true) + // GFM anchor links + options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false) + options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor") + options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true) + options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "") + + Parser parser = Parser.builder(options).build() + HtmlRenderer renderer = HtmlRenderer.builder(options).build() + + mdFiles.each { mdFile -> + // add table of contents + def mdText = "[TOC]\n"+mdFile.text + + // grab the first top-level title + def title = null + def titleRegex = /(?m)^#(\s+|([^#]))(.*)/ + def matcher = mdText =~ titleRegex + if (matcher.size() > 0) { + // matcher[0][2] is the first character of the title if there wasn't any whitespace after the # + title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3] + } + // or use the filename if none found + if (title == null) { + title = mdFile.getName() + } - def branchStdOut = new ByteArrayOutputStream() - exec { - commandLine "git", "rev-parse", "--abbrev-ref", "HEAD" - standardOutput = branchStdOut - ignoreExitValue true + Node document = parser.parse(mdText) + String htmlBody = renderer.render(document) + def htmlText = ''' + + + + + + +''' + htmlText += ((title != null) ? " ${title}" : '' ) + htmlText += ''' + +''' + htmlText += ((cssFile != null) ? cssFile.text : '') + htmlText += ''' + +''' + htmlText += htmlBody + htmlText += ''' + + +''' + + def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html") + def htmlFile = file(htmlFilePath) + println("Creating ${htmlFilePath}") + htmlFile.text = htmlText } +} - gitHash = hashStdOut.toString().trim() - gitBranch = branchStdOut.toString().trim() - outputs.upToDateWhen { false } +task copyDocs(type: Copy) { + def inputDir = "${jalviewDir}/${doc_dir}" + def outputDir = "${docBuildDir}/${doc_dir}" + from(inputDir) { + include('**/*.txt') + include('**/*.md') + include('**/*.html') + include('**/*.xml') + filter(ReplaceTokens, + beginToken: '$$', + endToken: '$$', + tokens: [ + 'Version-Rel': JALVIEW_VERSION, + 'Year-Rel': getDate("yyyy") + ] + ) + } + from(inputDir) { + exclude('**/*.txt') + exclude('**/*.md') + exclude('**/*.html') + exclude('**/*.xml') + } + into outputDir + + inputs.dir(inputDir) + outputs.dir(outputDir) } -task createBuildProperties(type: WriteProperties) { - dependsOn setGitVals - inputs.dir(sourceDir) - inputs.dir(resourceDir) - file(buildProperties).getParentFile().mkdirs() - outputFile (buildProperties) - // taking time specific comment out to allow better incremental builds - comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss") - //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd") - property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy") - property "VERSION", JALVIEW_VERSION - property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]" - outputs.file(outputFile) -} +task convertMdFiles { + dependsOn copyDocs + def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md") + def cssFile = file("${jalviewDir}/${flexmark_css}") + + doLast { + convertMdToHtml(mdFiles, cssFile) + } + inputs.files(mdFiles) + inputs.file(cssFile) -task cleanBuildingHTML(type: Delete) { - doFirst { - delete buildingHTML + def htmlFiles = [] + mdFiles.each { mdFile -> + def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html") + htmlFiles.add(file(htmlFilePath)) } + outputs.files(htmlFiles) } -task convertBuildingMD(type: Exec) { - dependsOn cleanBuildingHTML - def buildingMD = "${jalviewDir}/${doc_dir}/building.md" - def css = "${jalviewDir}/${doc_dir}/github.css" - - def pandoc = null - pandoc_exec.split(",").each { - if (file(it.trim()).exists()) { - pandoc = it.trim() - return true +def hugoTemplateSubstitutions(String input, Map extras=null) { + def replacements = [ + DATE: getDate("yyyy-MM-dd"), + CHANNEL: propertiesChannelName, + APPLICATION_NAME: applicationName, + GIT_HASH: gitHash, + GIT_BRANCH: gitBranch, + VERSION: JALVIEW_VERSION, + JAVA_VERSION: JAVA_VERSION, + VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES, + DRAFT: "false", + JVL_HEADER: "" + ] + def output = input + if (extras != null) { + extras.each{ k, v -> + output = output.replaceAll("__${k}__", ((v == null)?"":v)) } } + replacements.each{ k, v -> + output = output.replaceAll("__${k}__", ((v == null)?"":v)) + } + return output +} - def hostname = "hostname".execute().text.trim() - def buildtoolsPandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc" - if ((pandoc == null || ! file(pandoc).exists()) && file(buildtoolsPandoc).exists()) { - pandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc" +def mdFileComponents(File mdFile, def dateOnly=false) { + def map = [:] + def content = "" + if (mdFile.exists()) { + def inFrontMatter = false + def firstLine = true + mdFile.eachLine { line -> + if (line.matches("---")) { + def prev = inFrontMatter + inFrontMatter = firstLine + if (inFrontMatter != prev) + return false + } + if (inFrontMatter) { + def m = null + 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})/) { + map["date"] = new Date().parse("yyyy-MM-dd", m[0][1]) + } else if (m = line =~ /^channel:\s*(\S+)/) { + map["channel"] = m[0][1] + } else if (m = line =~ /^version:\s*(\S+)/) { + map["version"] = m[0][1] + } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) { + map[ m[0][1] ] = m[0][2] + } + if (dateOnly && map["date"] != null) { + return false + } + } else { + if (dateOnly) + return false + content += line+"\n" + } + firstLine = false + } } + return dateOnly ? map["date"] : [map, content] +} + +task hugoTemplates { + group "website" + description "Create partially populated md pages for hugo website build" + + def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}") + def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}" + def templateFiles = fileTree(dir: hugoTemplatesDir) + def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md") + def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md") + def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}") + def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}") doFirst { - if (pandoc != null && file(pandoc).exists()) { - commandLine pandoc, '-s', '-o', buildingHTML, '--metadata', 'pagetitle="Building Jalview from Source"', '--toc', '-H', css, buildingMD - } else { - println("Cannot find pandoc. Skipping convert building.md to HTML") - throw new StopExecutionException("Cannot find pandoc. Skipping convert building.md to HTML") + // specific release template for version archive + def changes = "" + def whatsnew = null + def givenDate = null + def givenChannel = null + def givenVersion = null + if (CHANNEL == "RELEASE") { + def (map, content) = mdFileComponents(releaseMdFile) + givenDate = map.date + givenChannel = map.channel + givenVersion = map.version + changes = content + if (givenVersion != null && givenVersion != JALVIEW_VERSION) { + throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})") + } + + if (whatsnewMdFile.exists()) + whatsnew = whatsnewMdFile.text + } + + def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : [] + def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : [] + + def changesHugo = null + if (changes != null) { + changesHugo = '
\n\n' + def inSection = false + changes.eachLine { line -> + def m = null + if (m = line =~ /^##([^#].*)$/) { + if (inSection) { + changesHugo += "
\n\n" + } + def section = m[0][1].trim() + section = section.toLowerCase() + section = section.replaceAll(/ +/, "_") + section = section.replaceAll(/[^a-z0-9_\-]/, "") + changesHugo += "
\n\n" + inSection = true + } else if (m = line =~ /^(\s*-\s*)(.*?)()?\s*$/) { + def comment = m[0][2].trim() + if (comment != "") { + comment = comment.replaceAll('"', """) + def issuekeys = [] + comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal } + def newline = m[0][1] + if (comment.trim() != "") + newline += "{{}}${comment}{{}} " + newline += m[0][3].trim() + if (issuekeys.size() > 0) + newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}" + if (m[0][4] != null) + newline += m[0][4] + line = newline + } + } + changesHugo += line+"\n" + } + if (inSection) { + changesHugo += "\n
\n\n" + } + changesHugo += '' } - } - ignoreExitValue true + templateFiles.each{ templateFile -> + def newFileName = string(hugoTemplateSubstitutions(templateFile.getName())) + def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent() + def newRelPathName = hugoTemplateSubstitutions( relPath.toString() ) - inputs.file(buildingMD) - inputs.file(css) - outputs.file(buildingHTML) -} + def outPathName = string("${hugoBuildDir}/$newRelPathName") + copy { + from templateFile + rename(templateFile.getName(), newFileName) + into outPathName + } + + def newFile = file("${outPathName}/${newFileName}".toString()) + def content = newFile.text + newFile.text = hugoTemplateSubstitutions(content, + [ + WHATSNEW: whatsnew, + CHANGES: changesHugo, + DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"), + DRAFT: givenDate == null ? "true" : "false", + JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false", + JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : "" + ] + ) + } -clean { - doFirst { - delete buildingHTML } -} + inputs.file(oldJvlFile) + inputs.dir(hugoTemplatesDir) + inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION }) + inputs.property("CHANNEL", { CHANNEL }) +} -task syncDocs(type: Sync) { - dependsOn convertBuildingMD - def syncDir = "${resourceClassesDir}/${doc_dir}" - from fileTree("${jalviewDir}/${doc_dir}") - into syncDir +def getMdDate(File mdFile) { + return mdFileComponents(mdFile, true) +} +def getMdSections(String content) { + def sections = [:] + def sectionContent = "" + def sectionName = null + content.eachLine { line -> + def m = null + if (m = line =~ /^##([^#].*)$/) { + if (sectionName != null) { + sections[sectionName] = sectionContent + sectionName = null + sectionContent = "" + } + sectionName = m[0][1].trim() + sectionName = sectionName.toLowerCase() + sectionName = sectionName.replaceAll(/ +/, "_") + sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "") + } else if (sectionName != null) { + sectionContent += line+"\n" + } + } + if (sectionContent != null) { + sections[sectionName] = sectionContent + } + return sections } task copyHelp(type: Copy) { def inputDir = helpSourceDir - def outputDir = "${resourceClassesDir}/${help_dir}" + def outputDir = "${helpBuildDir}/${help_dir}" from(inputDir) { - exclude '**/*.gif' - exclude '**/*.jpg' - exclude '**/*.png' + include('**/*.txt') + include('**/*.md') + include('**/*.html') + include('**/*.hs') + include('**/*.xml') + include('**/*.jhm') filter(ReplaceTokens, beginToken: '$$', endToken: '$$', @@ -1016,9 +1428,12 @@ task copyHelp(type: Copy) { ) } from(inputDir) { - include '**/*.gif' - include '**/*.jpg' - include '**/*.png' + exclude('**/*.txt') + exclude('**/*.md') + exclude('**/*.html') + exclude('**/*.hs') + exclude('**/*.xml') + exclude('**/*.jhm') } into outputDir @@ -1028,39 +1443,258 @@ task copyHelp(type: Copy) { } -task syncLib(type: Sync) { - def syncDir = "${resourceClassesDir}/${libDistDir}" - from fileTree("${jalviewDir}/${libDistDir}") - into syncDir +task releasesTemplates { + group "help" + description "Recreate whatsNew.html and releases.html from markdown files and templates in help" + + dependsOn copyHelp + + def releasesTemplateFile = file("${jalviewDir}/${releases_template}") + def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}") + def releasesHtmlFile = file("${helpBuildDir}/${help_dir}/${releases_html}") + def whatsnewHtmlFile = file("${helpBuildDir}/${help_dir}/${whatsnew_html}") + def releasesMdDir = "${jalviewDir}/${releases_dir}" + def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}" + + doFirst { + def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md") + def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md") + + if (CHANNEL == "RELEASE") { + if (!releaseMdFile.exists()) { + throw new GradleException("File ${releaseMdFile} must be created for RELEASE") + } + if (!whatsnewMdFile.exists()) { + throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE") + } + } + + def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md") + def releaseFilesDates = releaseFiles.collectEntries { + [(it): getMdDate(it)] + } + releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) } + + def releasesTemplate = releasesTemplateFile.text + def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/ + def versionTemplate = m[0][1] + + MutableDataSet options = new MutableDataSet() + + def extensions = new ArrayList<>() + options.set(Parser.EXTENSIONS, extensions) + options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true) + + Parser parser = Parser.builder(options).build() + HtmlRenderer renderer = HtmlRenderer.builder(options).build() + + def actualVersions = releaseFiles.collect { rf -> + def (rfMap, rfContent) = mdFileComponents(rf) + return rfMap.version + } + def versionsHtml = "" + def linkedVersions = [] + releaseFiles.reverse().each { rFile -> + def (rMap, rContent) = mdFileComponents(rFile) + + def versionLink = "" + def partialVersion = "" + def firstPart = true + rMap.version.split("\\.").each { part -> + def displayPart = ( firstPart ? "" : "." ) + part + partialVersion += displayPart + if ( + linkedVersions.contains(partialVersion) + || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version ) + ) { + versionLink += displayPart + } else { + versionLink += "${displayPart}" + linkedVersions += partialVersion + } + firstPart = false + } + def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy") + + def lm = null + def rContentProcessed = "" + rContent.eachLine { line -> + if (lm = line =~ /^(\s*-)(\s*)(.*)$/) { + line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}" + } else if (lm = line =~ /^###([^#]+.*)$/) { + line = "_${lm[0][1].trim()}_" + } + rContentProcessed += line + "\n" + } + + def rContentSections = getMdSections(rContentProcessed) + def rVersion = versionTemplate + if (rVersion != "") { + def rNewFeatures = rContentSections["new_features"] + def rIssuesResolved = rContentSections["issues_resolved"] + Node newFeaturesNode = parser.parse(rNewFeatures) + String newFeaturesHtml = renderer.render(newFeaturesNode) + Node issuesResolvedNode = parser.parse(rIssuesResolved) + String issuesResolvedHtml = renderer.render(issuesResolvedNode) + rVersion = hugoTemplateSubstitutions(rVersion, + [ + VERSION: rMap.version, + VERSION_LINK: versionLink, + DISPLAY_DATE: displayDate, + NEW_FEATURES: newFeaturesHtml, + ISSUES_RESOLVED: issuesResolvedHtml + ] + ) + versionsHtml += rVersion + } + } + + releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml) + releasesTemplate = hugoTemplateSubstitutions(releasesTemplate) + releasesHtmlFile.text = releasesTemplate + + if (whatsnewMdFile.exists()) { + def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : "" + def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text) + Node whatsnewNode = parser.parse(whatsnewMd) + String whatsnewHtml = renderer.render(whatsnewNode) + whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml) + whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml, + [ + DISPLAY_DATE: wnDisplayDate + ] + ) + } else if (gradle.taskGraph.hasTask(":linkCheck")) { + whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss") + } + + } + + inputs.file(releasesTemplateFile) + inputs.file(whatsnewTemplateFile) + inputs.dir(releasesMdDir) + inputs.dir(whatsnewMdDir) + outputs.file(releasesHtmlFile) + outputs.file(whatsnewHtmlFile) } -task syncResources(type: Sync) { - from resourceDir - include "**/*.*" - into "${resourceClassesDir}" - preserve { - include "**" +task copyResources(type: Copy) { + group = "build" + description = "Copy (and make text substitutions in) the resources dir to the build area" + + def inputDir = resourceDir + def outputDir = resourcesBuildDir + from(inputDir) { + include('**/*.txt') + include('**/*.md') + include('**/*.html') + include('**/*.xml') + filter(ReplaceTokens, + beginToken: '$$', + endToken: '$$', + tokens: [ + 'Version-Rel': JALVIEW_VERSION, + 'Year-Rel': getDate("yyyy") + ] + ) + } + from(inputDir) { + exclude('**/*.txt') + exclude('**/*.md') + exclude('**/*.html') + exclude('**/*.xml') + } + into outputDir + + inputs.dir(inputDir) + outputs.dir(outputDir) +} + +task copyChannelResources(type: Copy) { + dependsOn copyResources + group = "build" + description = "Copy the channel resources dir to the build resources area" + + def inputDir = "${channelDir}/${resource_dir}" + def outputDir = resourcesBuildDir + from inputDir + into outputDir + + inputs.dir(inputDir) + outputs.dir(outputDir) +} + +task createBuildProperties(type: WriteProperties) { + dependsOn copyResources + group = "build" + description = "Create the ${buildProperties} file" + + inputs.dir(sourceDir) + inputs.dir(resourcesBuildDir) + outputFile (buildProperties) + // taking time specific comment out to allow better incremental builds + comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss") + //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd") + property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy") + property "VERSION", JALVIEW_VERSION + property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]" + if (getdownSetAppBaseProperty) { + property "GETDOWNAPPBASE", getdownAppBase + property "GETDOWNAPPDISTDIR", getdownAppDistDir } + outputs.file(outputFile) +} + + +task buildIndices(type: JavaExec) { + dependsOn copyHelp + classpath = sourceSets.main.compileClasspath + main = "com.sun.java.help.search.Indexer" + workingDir = "${helpBuildDir}/${help_dir}" + def argDir = "html" + args = [ argDir ] + inputs.dir("${workingDir}/${argDir}") + + outputs.dir("${classesDir}/doc") + outputs.dir("${classesDir}/help") + outputs.file("${workingDir}/JavaHelpSearch/DOCS") + outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB") + outputs.file("${workingDir}/JavaHelpSearch/OFFSETS") + outputs.file("${workingDir}/JavaHelpSearch/POSITIONS") + outputs.file("${workingDir}/JavaHelpSearch/SCHEMA") + outputs.file("${workingDir}/JavaHelpSearch/TMAP") } +task buildResources { + dependsOn copyResources + dependsOn copyChannelResources + dependsOn createBuildProperties +} task prepare { - dependsOn syncResources - dependsOn syncDocs + dependsOn buildResources + dependsOn copyDocs dependsOn copyHelp + dependsOn releasesTemplates + dependsOn convertMdFiles + dependsOn buildIndices } +compileJava.dependsOn prepare +run.dependsOn compileJava +//run.dependsOn prepare + + //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir test { dependsOn prepare - //dependsOn compileJava ////? DELETE if (useClover) { dependsOn cloverClasses } else { //? - dependsOn compileJava //? + dependsOn compileJava //? } useTestNG() { @@ -1073,7 +1707,6 @@ test { maxHeapSize = "1024m" workingDir = jalviewDir - //systemProperties 'clover.jar' System.properties.clover.jar def testLaf = project.findProperty("test_laf") if (testLaf != null) { println("Setting Test LaF to '${testLaf}'") @@ -1096,26 +1729,6 @@ test { } -task buildIndices(type: JavaExec) { - dependsOn copyHelp - classpath = sourceSets.main.compileClasspath - main = "com.sun.java.help.search.Indexer" - workingDir = "${classesDir}/${help_dir}" - def argDir = "html" - args = [ argDir ] - inputs.dir("${workingDir}/${argDir}") - - outputs.dir("${classesDir}/doc") - outputs.dir("${classesDir}/help") - outputs.file("${workingDir}/JavaHelpSearch/DOCS") - outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB") - outputs.file("${workingDir}/JavaHelpSearch/OFFSETS") - outputs.file("${workingDir}/JavaHelpSearch/POSITIONS") - outputs.file("${workingDir}/JavaHelpSearch/SCHEMA") - outputs.file("${workingDir}/JavaHelpSearch/TMAP") -} - - task compileLinkCheck(type: JavaCompile) { options.fork = true classpath = files("${jalviewDir}/${utils_dir}") @@ -1130,30 +1743,31 @@ task compileLinkCheck(type: JavaCompile) { task linkCheck(type: JavaExec) { - dependsOn prepare, compileLinkCheck + dependsOn prepare + dependsOn compileLinkCheck def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out") classpath = files("${jalviewDir}/${utils_dir}") main = "HelpLinksChecker" - workingDir = jalviewDir - args = [ "${classesDir}/${help_dir}", "-nointernet" ] + workingDir = "${helpBuildDir}" + args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ] def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append - def errFOS = outFOS standardOutput = new org.apache.tools.ant.util.TeeOutputStream( outFOS, - standardOutput) + System.out) errorOutput = new org.apache.tools.ant.util.TeeOutputStream( outFOS, - errorOutput) + System.err) - inputs.dir("${classesDir}/${help_dir}") + inputs.dir(helpBuildDir) outputs.file(helpLinksCheckerOutFile) } + // import the pubhtmlhelp target ant.properties.basedir = "${jalviewDir}" -ant.properties.helpBuildDir = "${jalviewDirAbsolutePath}/${classes_dir}/${help_dir}" +ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}" ant.importBuild "${utils_dir}/publishHelp.xml" @@ -1163,20 +1777,24 @@ task cleanPackageDir(type: Delete) { } } + jar { + dependsOn prepare dependsOn linkCheck - dependsOn buildIndices - dependsOn createBuildProperties manifest { attributes "Main-Class": main_class, "Permissions": "all-permissions", - "Application-Name": "Jalview Desktop", - "Codebase": application_codebase + "Application-Name": applicationName, + "Codebase": application_codebase, + "Implementation-Version": JALVIEW_VERSION } - destinationDir = file("${jalviewDir}/${package_dir}") - archiveName = rootProject.name+".jar" + def outputDir = "${jalviewDir}/${package_dir}" + destinationDirectory = file(outputDir) + archiveFileName = rootProject.name+".jar" + duplicatesStrategy "EXCLUDE" + exclude "cache*/**" exclude "*.jar" @@ -1184,8 +1802,11 @@ jar { exclude "**/*.jar" exclude "**/*.jar.*" - inputs.dir(classesDir) - outputs.file("${jalviewDir}/${package_dir}/${archiveName}") + inputs.dir(sourceSets.main.java.outputDir) + sourceSets.main.resources.srcDirs.each{ dir -> + inputs.dir(dir) + } + outputs.file("${outputDir}/${archiveFileName}") } @@ -1197,10 +1818,11 @@ task copyJars(type: Copy) { // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well task syncJars(type: Sync) { + dependsOn jar from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files into "${jalviewDir}/${package_dir}" preserve { - include jar.archiveName + include jar.archiveFileName.getOrNull() } } @@ -1224,8 +1846,10 @@ task cleanDist { dependsOn clean } + shadowJar { group = "distribution" + description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar" if (buildDist) { dependsOn makeDist } @@ -1233,8 +1857,12 @@ shadowJar { include("*.jar") } manifest { - attributes 'Implementation-Version': JALVIEW_VERSION + attributes "Implementation-Version": JALVIEW_VERSION, + "Application-Name": applicationName } + + duplicatesStrategy "INCLUDE" + mainClassName = shadow_jar_main_class mergeServiceFiles() classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION @@ -1250,23 +1878,28 @@ task getdownWebsite() { } def getdownWebsiteResourceFilenames = [] - def getdownTextString = "" def getdownResourceDir = getdownResourceDir def getdownResourceFilenames = [] doFirst { // clean the getdown website and files dir before creating getdown folders - delete getdownWebsiteDir + delete getdownAppBaseDir delete getdownFilesDir copy { from buildProperties - rename(build_properties_file, getdown_build_properties) + rename(file(buildProperties).getName(), getdown_build_properties) into getdownAppDir } getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}" - // set some getdown_txt_ properties then go through all properties looking for getdown_txt_... + copy { + from channelPropsFile + into getdownAppBaseDir + } + getdownWebsiteResourceFilenames += file(channelPropsFile).getName() + + // set some getdownTxt_ properties then go through all properties looking for getdownTxt_... def props = project.properties.sort { it.key } if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) { props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion) @@ -1277,19 +1910,27 @@ task getdownWebsite() { if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) { props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation) } + if (getdownImagesDir != null && file(getdownImagesDir).exists()) { + props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}") + props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}") + props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}") + props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}") + props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}") + props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}") + } props.put("getdown_txt_title", jalview_name) - props.put("getdown_txt_ui.name", install4jApplicationName) + props.put("getdown_txt_ui.name", applicationName) // start with appbase - getdownTextString += "appbase = ${getdownAppBase}\n" + getdownTextLines += "appbase = ${getdownAppBase}" props.each{ prop, val -> if (prop.startsWith("getdown_txt_") && val != null) { if (prop.startsWith("getdown_txt_multi_")) { def key = prop.substring(18) val.split(",").each{ v -> - def line = "${key} = ${v}\n" - getdownTextString += line + def line = "${key} = ${v}" + getdownTextLines += line } } else { // file values rationalised @@ -1309,15 +1950,15 @@ task getdownWebsite() { } } if (! prop.startsWith("getdown_txt_resource")) { - def line = prop.substring(12) + " = ${val}\n" - getdownTextString += line + def line = prop.substring(12) + " = ${val}" + getdownTextLines += line } } } } getdownWebsiteResourceFilenames.each{ filename -> - getdownTextString += "resource = ${filename}\n" + getdownTextLines += "resource = ${filename}" } getdownResourceFilenames.each{ filename -> copy { @@ -1325,6 +1966,18 @@ task getdownWebsite() { into getdownResourceDir } } + + def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ] + getdownWrapperScripts.each{ script -> + def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" ) + if (s.exists()) { + copy { + from s + into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}" + } + getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}" + } + } def codeFiles = [] fileTree(file(package_dir)).each{ f -> @@ -1335,10 +1988,12 @@ task getdownWebsite() { codeFiles += f } } - codeFiles.sort().each{f -> + def jalviewJar = jar.archiveFileName.getOrNull() + // put jalview.jar first for CLASSPATH and .properties files reasons + codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f -> def name = f.getName() - def line = "code = ${getdownAppDistDir}/${name}\n" - getdownTextString += line + def line = "code = ${getdownAppDistDir}/${name}" + getdownTextLines += line copy { from f.getPath() into getdownAppDir @@ -1351,8 +2006,8 @@ task getdownWebsite() { def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles() j11libFiles.sort().each{f -> def name = f.getName() - def line = "code = ${getdown_j11lib_dir}/${name}\n" - getdownTextString += line + def line = "code = ${getdown_j11lib_dir}/${name}" + getdownTextLines += line copy { from f.getPath() into getdownJ11libDir @@ -1362,59 +2017,71 @@ task getdownWebsite() { */ // getdown-launcher.jar should not be in main application class path so the main application can move it when updated. Listed as a resource so it gets updated. - //getdownTextString += "class = " + file(getdownLauncher).getName() + "\n" - getdownTextString += "resource = ${getdown_launcher_new}\n" - getdownTextString += "class = ${mainClass}\n" + //getdownTextLines += "class = " + file(getdownLauncher).getName() + getdownTextLines += "resource = ${getdown_launcher_new}" + getdownTextLines += "class = ${main_class}" + // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache + if (getdownSetAppBaseProperty) { + getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}" + getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}" + } - def getdown_txt = file("${getdownWebsiteDir}/getdown.txt") - getdown_txt.write(getdownTextString) + def getdownTxt = file("${getdownAppBaseDir}/getdown.txt") + getdownTxt.write(getdownTextLines.join("\n")) - def getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl" - def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}") + getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl" + def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}") launchJvl.write("appbase=${getdownAppBase}") + // files going into the getdown website dir: getdown-launcher.jar copy { from getdownLauncher rename(file(getdownLauncher).getName(), getdown_launcher_new) - into getdownWebsiteDir + into getdownAppBaseDir } + // files going into the getdown website dir: getdown-launcher(-local).jar copy { from getdownLauncher if (file(getdownLauncher).getName() != getdown_launcher) { rename(file(getdownLauncher).getName(), getdown_launcher) } - into getdownWebsiteDir + into getdownAppBaseDir } + // files going into the getdown website dir: ./install dir and files if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) { copy { - from getdown_txt + from getdownTxt from getdownLauncher - from "${getdownWebsiteDir}/${getdown_build_properties}" + from "${getdownAppDir}/${getdown_build_properties}" if (file(getdownLauncher).getName() != getdown_launcher) { rename(file(getdownLauncher).getName(), getdown_launcher) } into getdownInstallDir } + // and make a copy in the getdown files dir (these are not downloaded by getdown) copy { from getdownInstallDir into getdownFilesInstallDir } } + // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties copy { - from getdown_txt + from getdownTxt from launchJvl from getdownLauncher - from "${getdownWebsiteDir}/${getdown_build_properties}" + from "${getdownAppBaseDir}/${getdown_build_properties}" + from "${getdownAppBaseDir}/${channel_props}" if (file(getdownLauncher).getName() != getdown_launcher) { rename(file(getdownLauncher).getName(), getdown_launcher) } into getdownFilesDir } + // and ./resource (not all downloaded by getdown) copy { from getdownResourceDir into "${getdownFilesDir}/${getdown_resource_dir}" @@ -1424,7 +2091,7 @@ task getdownWebsite() { if (buildDist) { inputs.dir("${jalviewDir}/${package_dir}") } - outputs.dir(getdownWebsiteDir) + outputs.dir(getdownAppBaseDir) outputs.dir(getdownFilesDir) } @@ -1455,9 +2122,9 @@ task getdownDigest(type: JavaExec) { classpath = files(getdownLauncher) } main = "com.threerings.getdown.tools.Digester" - args getdownWebsiteDir - inputs.dir(getdownWebsiteDir) - outputs.file("${getdownWebsiteDir}/digest2.txt") + args getdownAppBaseDir + inputs.dir(getdownAppBaseDir) + outputs.file("${getdownAppBaseDir}/digest2.txt") } @@ -1467,7 +2134,7 @@ task getdown() { dependsOn getdownDigest doLast { if (reportRsyncCommand) { - def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/') + def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/') def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/') println "LIKELY RSYNC COMMAND:" println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'" @@ -1484,10 +2151,116 @@ task getdown() { } +task getdownArchiveBuild() { + group = "distribution" + description = "Put files in the archive dir to go on the website" + + dependsOn getdownWebsite + + def v = "v${JALVIEW_VERSION_UNDERSCORES}" + def vDir = "${getdownArchiveDir}/${v}" + getdownFullArchiveDir = "${vDir}/getdown" + getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl" + + def vAltDir = "alt_${v}" + def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images" + + doFirst { + // cleanup old "old" dir + delete getdownArchiveDir + + def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt") + getdownArchiveTxt.getParentFile().mkdirs() + def getdownArchiveTextLines = [] + def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/" + + // the libdir + copy { + from "${getdownAppBaseDir}/${getdownAppDistDir}" + into "${getdownFullArchiveDir}/${vAltDir}" + } + + getdownTextLines.each { line -> + line = line.replaceAll("^(?appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase) + line = line.replaceAll("^(?(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/") + line = line.replaceAll("^(?ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png") + line = line.replaceAll("^(?ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png") + line = line.replaceAll("^(?ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png") + line = line.replaceAll("^(?ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png") + // remove the existing resource = resource/ or bin/ lines + if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) { + getdownArchiveTextLines += line + } + } + + // the resource dir -- add these files as resource lines in getdown.txt + copy { + from "${archiveImagesDir}" + into "${getdownFullArchiveDir}/${getdown_resource_dir}" + eachFile { file -> + getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}" + } + } + + getdownArchiveTxt.write(getdownArchiveTextLines.join("\n")) + + def vLaunchJvl = file(getdownVersionLaunchJvl) + vLaunchJvl.getParentFile().mkdirs() + vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n") + def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath() + def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath() + // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong + //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath)); + java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName())); + + // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties + copy { + from getdownLauncher + from "${getdownAppBaseDir}/${getdownLaunchJvl}" + from "${getdownAppBaseDir}/${getdown_launcher_new}" + from "${getdownAppBaseDir}/${channel_props}" + if (file(getdownLauncher).getName() != getdown_launcher) { + rename(file(getdownLauncher).getName(), getdown_launcher) + } + into getdownFullArchiveDir + } + + } +} + +task getdownArchiveDigest(type: JavaExec) { + group = "distribution" + description = "Digest the getdown archive folder" + + dependsOn getdownArchiveBuild + + doFirst { + classpath = files(getdownLauncher) + args getdownFullArchiveDir + } + main = "com.threerings.getdown.tools.Digester" + inputs.dir(getdownFullArchiveDir) + outputs.file("${getdownFullArchiveDir}/digest2.txt") +} + +task getdownArchive() { + group = "distribution" + description = "Build the website archive dir with getdown digest" + + dependsOn getdownArchiveBuild + dependsOn getdownArchiveDigest +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + + clean { doFirst { - delete getdownWebsiteDir + delete getdownAppBaseDir delete getdownFilesDir + delete getdownArchiveDir } } @@ -1527,13 +2300,15 @@ task copyInstall4jTemplate { } } + // disable install screen for OSX dmg (for 2.11.2.0) + install4jConfigXml.'**'.macosArchive.each { macosArchive -> + macosArchive.attributes().remove('executeSetupApp') + macosArchive.attributes().remove('setupAppId') + } + // turn off checksum creation for LOCAL channel def e = install4jConfigXml.application[0] - if (CHANNEL == "LOCAL") { - e.'@createChecksums' = "false" - } else { - e.'@createChecksums' = "true" - } + e.'@createChecksums' = string(install4jCheckSums) // put file association actions where placeholder action is def install4jFileAssociationsText = install4jFileAssociationsFile.text @@ -1574,12 +2349,6 @@ task copyInstall4jTemplate { } } - // remove the "Uninstall Old Jalview (optional)" symlink from DMG for non-release DS_Stores - if (! (CHANNEL == "RELEASE" || CHANNEL == "TEST-RELEASE" ) ) { - def symlink = install4jConfigXml.'**'.topLevelFiles.symlink.find { sl -> sl.'@name' == "Uninstall Old Jalview (optional).app" } - symlink.parent().remove(symlink) - } - // write install4j file install4jConfFile.text = XmlUtil.serialize(install4jConfigXml) } @@ -1592,13 +2361,23 @@ clean { } } +task cleanInstallersDataFiles { + def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt") + def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums") + def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json") + doFirst { + delete installersOutputTxt + delete installersSha256 + delete hugoDataJsonFile + } +} -task installers(type: com.install4j.gradle.Install4jTask) { +task installerFiles(type: com.install4j.gradle.Install4jTask) { group = "distribution" description = "Create the install4j installers" - dependsOn setGitVals dependsOn getdown dependsOn copyInstall4jTemplate + dependsOn cleanInstallersDataFiles projectFile = install4jConfFile @@ -1613,14 +2392,14 @@ task installers(type: com.install4j.gradle.Install4jTask) { filesMd5 = filesMd5.substring(0,8) } def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}" - // make install4jBuildDir relative to jalviewDir - def install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}" variables = [ 'JALVIEW_NAME': jalview_name, - 'JALVIEW_APPLICATION_NAME': install4jApplicationName, + 'JALVIEW_APPLICATION_NAME': applicationName, 'JALVIEW_DIR': "../..", 'OSX_KEYSTORE': OSX_KEYSTORE, + 'OSX_APPLEID': OSX_APPLEID, + 'OSX_ALTOOLPASS': OSX_ALTOOLPASS, 'JSIGN_SH': JSIGN_SH, 'JRE_DIR': getdown_app_dir_java, 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion, @@ -1640,11 +2419,15 @@ task installers(type: com.install4j.gradle.Install4jTask) { 'BUNDLE_ID': install4jBundleId, 'INTERNAL_ID': install4jInternalId, 'WINDOWS_APPLICATION_ID': install4jWinApplicationId, - 'MACOS_DS_STORE': install4jDSStore, + 'MACOS_DMG_DS_STORE': install4jDMGDSStore, 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage, + 'WRAPPER_LINK': getdownWrapperLink, + 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script, + 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script, + 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir, 'INSTALLER_NAME': install4jInstallerName, 'INSTALL4J_UTILS_DIR': install4j_utils_dir, - 'GETDOWN_WEBSITE_DIR': getdown_website_dir, + 'GETDOWN_CHANNEL_DIR': getdownChannelDir, 'GETDOWN_FILES_DIR': getdown_files_dir, 'GETDOWN_RESOURCE_DIR': getdown_resource_dir, 'GETDOWN_DIST_DIR': getdownAppDistDir, @@ -1657,6 +2440,11 @@ task installers(type: com.install4j.gradle.Install4jTask) { 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder, 'EXECUTABLE_NAME': install4jExecutableName, 'EXTRA_SCHEME': install4jExtraScheme, + 'MAC_ICONS_FILE': install4jMacIconsFile, + 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile, + 'PNG_ICON_FILE': install4jPngIconFile, + 'BACKGROUND': install4jBackground, + ] //println("INSTALL4J VARIABLES:") @@ -1668,17 +2456,27 @@ task installers(type: com.install4j.gradle.Install4jTask) { if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) { faster = true disableSigning = true + disableNotarization = true } if (OSX_KEYPASS) { macKeystorePassword = OSX_KEYPASS + } + + if (OSX_ALTOOLPASS) { + appleIdPassword = OSX_ALTOOLPASS + disableNotarization = false + } else { + disableNotarization = true } doFirst { println("Using projectFile "+projectFile) + if (!disableNotarization) { println("Will notarize OSX App DMG") } } + //verbose=true - inputs.dir(getdownWebsiteDir) + inputs.dir(getdownAppBaseDir) inputs.file(install4jConfFile) inputs.file("${install4jDir}/${install4j_info_plist_file_associations}") inputs.dir(macosJavaVMDir) @@ -1686,17 +2484,120 @@ task installers(type: com.install4j.gradle.Install4jTask) { outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}") } +def getDataHash(File myFile) { + HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256()) + return myFile.exists() + ? [ + "file" : myFile.getName(), + "filesize" : myFile.length(), + "sha256" : hash.toString() + ] + : null +} + +def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) { + def hash = [ + "channel" : getdownChannelName, + "date" : getDate("yyyy-MM-dd HH:mm:ss"), + "git-commit" : "${gitHash} [${gitBranch}]", + "version" : JALVIEW_VERSION + ] + // install4j installer files + if (installersOutputTxt.exists()) { + def idHash = [:] + installersOutputTxt.readLines().each { def line -> + if (line.startsWith("#")) { + return; + } + line.replaceAll("\n","") + def vals = line.split("\t") + def filename = vals[3] + def filesize = file(filename).length() + filename = filename.replaceAll(/^.*\//, "") + hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ] + idHash."${filename}" = vals[0] + } + if (install4jCheckSums && installersSha256.exists()) { + installersSha256.readLines().each { def line -> + if (line.startsWith("#")) { + return; + } + line.replaceAll("\n","") + def vals = line.split(/\s+\*?/) + def filename = vals[1] + def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0] + } + } + } + + [ + "JAR": shadowJar.archiveFile, // executable JAR + "JVL": getdownVersionLaunchJvl, // version JVL + "SOURCE": sourceDist.archiveFile // source TGZ + ].each { key, value -> + def file = file(value) + if (file.exists()) { + def fileHash = getDataHash(file) + if (fileHash != null) { + hash."${key}" = fileHash; + } + } + } + return dataJsonFile.write(new JsonBuilder(hash).toPrettyString()) +} -task sourceDist(type: Tar) { +task staticMakeInstallersJsonFile { + doFirst { + def output = findProperty("i4j_output") + def sha256 = findProperty("i4j_sha256") + def json = findProperty("i4j_json") + if (output == null || sha256 == null || json == null) { + throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...") + } + writeDataJsonFile(file(output), file(sha256), file(json)) + } +} + +task installers { + dependsOn installerFiles +} + + +spotless { + java { + eclipse().configFile(eclipse_codestyle_file) + } +} + +task createSourceReleaseProperties(type: WriteProperties) { + group = "distribution" + description = "Create the source RELEASE properties file" - def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_") - def outputFileName = "${project.name}_${VERSION_UNDERSCORES}.tar.gz" - // cater for buildship < 3.1 [3.0.1 is max version in eclipse 2018-09] - try { - archiveFileName = outputFileName - } catch (Exception e) { - archiveName = outputFileName + def sourceTarBuildDir = "${buildDir}/sourceTar" + def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE" + outputFile (sourceReleasePropertiesFile) + + doFirst { + releaseProps.each{ key, val -> property key, val } + property "git.branch", gitBranch + property "git.hash", gitHash } + + outputs.file(outputFile) +} + +task sourceDist(type: Tar) { + group "distribution" + description "Create a source .tar.gz file for distribution" + + dependsOn createBuildProperties + dependsOn convertMdFiles + dependsOn eclipseAllPreferences + dependsOn createSourceReleaseProperties + + + def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz" + archiveFileName = outputFileName compression Compression.GZIP @@ -1717,6 +2618,7 @@ task sourceDist(type: Tar) { "*locales/**", "utils/InstallAnywhere", "**/*.log", + "RELEASE", ] def PROCESS_FILES=[ "AUTHORS", @@ -1726,7 +2628,6 @@ task sourceDist(type: Tar) { "FEATURETODO", "LICENSE", "**/README", - "RELEASE", "THIRDPARTYLIBS", "TESTNG", "build.gradle", @@ -1741,7 +2642,9 @@ task sourceDist(type: Tar) { "**/*.sh", ] def INCLUDE_FILES=[ - ".settings/org.eclipse.jdt.core.jalview.prefs", + ".classpath", + ".settings/org.eclipse.buildship.core.prefs", + ".settings/org.eclipse.jdt.core.prefs" ] from(jalviewDir) { @@ -1765,10 +2668,12 @@ task sourceDist(type: Tar) { exclude ("utils/InstallAnywhere") exclude (getdown_files_dir) - exclude (getdown_website_dir) + // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown + //exclude (getdown_website_dir) + //exclude (getdown_archive_dir) // exluding these as not using jars as modules yet - exclude ("$j11modDir/**/*.jar") + exclude ("${j11modDir}/**/*.jar") } from(jalviewDir) { include(INCLUDE_FILES) @@ -1779,17 +2684,1142 @@ task sourceDist(type: Tar) { // exclude(EXCLUDE_FILES) // exclude(PROCESS_FILES) // } + + from(file(buildProperties).getParent()) { + include(file(buildProperties).getName()) + rename(file(buildProperties).getName(), "build_properties") + filter({ line -> + line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]") + }) + } + + def sourceTarBuildDir = "${buildDir}/sourceTar" + from(sourceTarBuildDir) { + // this includes the appended RELEASE properties file + } } +task dataInstallersJson { + group "website" + description "Create the installers-VERSION.json data file for installer files created" + + mustRunAfter installers + mustRunAfter shadowJar + mustRunAfter sourceDist + mustRunAfter getdownArchive + + def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt") + def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums") + + if (installersOutputTxt.exists()) { + inputs.file(installersOutputTxt) + } + if (install4jCheckSums && installersSha256.exists()) { + inputs.file(installersSha256) + } + [ + shadowJar.archiveFile, // executable JAR + getdownVersionLaunchJvl, // version JVL + sourceDist.archiveFile // source TGZ + ].each { fileName -> + if (file(fileName).exists()) { + inputs.file(fileName) + } + } + + outputs.file(hugoDataJsonFile) + + doFirst { + writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile) + } +} task helppages { + group "help" + description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'." + dependsOn copyHelp dependsOn pubhtmlhelp - inputs.dir("${classesDir}/${help_dir}") + inputs.dir("${helpBuildDir}/${help_dir}") outputs.dir("${buildDir}/distributions/${help_dir}") } -// LARGE AMOUNT OF JALVIEWJS STUFF DELETED HERE -task eclipseAutoBuildTask {} -task eclipseSynchronizationTask {} + +task j2sSetHeadlessBuild { + doFirst { + IN_ECLIPSE = false + } +} + + +task jalviewjsEnableAltFileProperty(type: WriteProperties) { + group "jalviewjs" + description "Enable the alternative J2S Config file for headless build" + + outputFile = jalviewjsJ2sSettingsFileName + def j2sPropsFile = file(jalviewjsJ2sSettingsFileName) + def j2sProps = new Properties() + if (j2sPropsFile.exists()) { + try { + def j2sPropsFileFIS = new FileInputStream(j2sPropsFile) + j2sProps.load(j2sPropsFileFIS) + j2sPropsFileFIS.close() + + j2sProps.each { prop, val -> + property(prop, val) + } + } catch (Exception e) { + println("Exception reading ${jalviewjsJ2sSettingsFileName}") + e.printStackTrace() + } + } + if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) { + property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property) + } +} + + +task jalviewjsSetEclipseWorkspace { + def propKey = "jalviewjs_eclipse_workspace" + def propVal = null + if (project.hasProperty(propKey)) { + propVal = project.getProperty(propKey) + if (propVal.startsWith("~/")) { + propVal = System.getProperty("user.home") + propVal.substring(1) + } + } + def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}" + def propsFile = file(propsFileName) + def eclipseWsDir = propVal + def props = new Properties() + + def writeProps = true + if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) { + def ins = new FileInputStream(propsFileName) + props.load(ins) + ins.close() + if (props.getProperty(propKey, null) != null) { + eclipseWsDir = props.getProperty(propKey) + writeProps = false + } + } + + if (eclipseWsDir == null || !file(eclipseWsDir).exists()) { + def tempDir = File.createTempDir() + eclipseWsDir = tempDir.getAbsolutePath() + writeProps = true + } + eclipseWorkspace = file(eclipseWsDir) + + doFirst { + // do not run a headless transpile when we claim to be in Eclipse + if (IN_ECLIPSE) { + println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}") + throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'") + } else { + println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}") + } + + if (writeProps) { + props.setProperty(propKey, eclipseWsDir) + propsFile.parentFile.mkdirs() + def bytes = new ByteArrayOutputStream() + props.store(bytes, null) + def propertiesString = bytes.toString() + propsFile.text = propertiesString + print("NEW ") + } else { + print("EXISTING ") + } + + println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath()) + } + + //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date + outputs.file(propsFileName) + outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() } +} + + +task jalviewjsEclipsePaths { + def eclipseProduct + + def eclipseRoot = jalviewjs_eclipse_root + if (eclipseRoot.startsWith("~/")) { + eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1) + } + if (OperatingSystem.current().isMacOsX()) { + eclipseRoot += "/Eclipse.app" + eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse" + eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct" + } else if (OperatingSystem.current().isWindows()) { // check these paths!! + if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) { + eclipseRoot += "/eclipse" + } + eclipseBinary = "${eclipseRoot}/eclipse.exe" + eclipseProduct = "${eclipseRoot}/.eclipseproduct" + } else { // linux or unix + if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) { + eclipseRoot += "/eclipse" +println("eclipseDir exists") + } + eclipseBinary = "${eclipseRoot}/eclipse" + eclipseProduct = "${eclipseRoot}/.eclipseproduct" + } + + eclipseVersion = "4.13" // default + def assumedVersion = true + if (file(eclipseProduct).exists()) { + def fis = new FileInputStream(eclipseProduct) + def props = new Properties() + props.load(fis) + eclipseVersion = props.getProperty("version") + fis.close() + assumedVersion = false + } + + def propKey = "eclipse_debug" + eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true")) + + doFirst { + // do not run a headless transpile when we claim to be in Eclipse + if (IN_ECLIPSE) { + println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}") + throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'") + } else { + println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}") + } + + if (!assumedVersion) { + println("ECLIPSE VERSION=${eclipseVersion}") + } + } +} + + +task printProperties { + group "Debug" + description "Output to console all System.properties" + doFirst { + System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") } + } +} + + +task eclipseSetup { + dependsOn eclipseProject + dependsOn eclipseClasspath + dependsOn eclipseJdt +} + + +// this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir +task jalviewjsEclipseCopyDropins(type: Copy) { + dependsOn jalviewjsEclipsePaths + + def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar") + inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}") + def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" + + from inputFiles + into outputDir +} + + +// this eclipse -clean doesn't actually work +task jalviewjsCleanEclipse(type: Exec) { + dependsOn eclipseSetup + dependsOn jalviewjsEclipsePaths + dependsOn jalviewjsEclipseCopyDropins + + executable(eclipseBinary) + args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"]) + if (eclipseDebug) { + args += "-debug" + } + args += "-l" + + def inputString = """exit +y +""" + def inputByteStream = new ByteArrayInputStream(inputString.getBytes()) + standardInput = inputByteStream +} + +/* not really working yet +jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse +*/ + + +task jalviewjsTransferUnzipSwingJs { + def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}" + + doLast { + copy { + from zipTree(file_zip) + into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}" + } + } + + inputs.file file_zip + outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}" +} + + +task jalviewjsTransferUnzipLib { + def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip") + + doLast { + zipFiles.each { file_zip -> + copy { + from zipTree(file_zip) + into "${jalviewDir}/${jalviewjsTransferSiteLibDir}" + } + } + } + + inputs.files zipFiles + outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}" +} + + +task jalviewjsTransferUnzipAllLibs { + dependsOn jalviewjsTransferUnzipSwingJs + dependsOn jalviewjsTransferUnzipLib +} + + +task jalviewjsCreateJ2sSettings(type: WriteProperties) { + group "JalviewJS" + description "Create the alternative j2s file from the j2s.* properties" + + jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key } + def siteDirProperty = "j2s.site.directory" + def setSiteDir = false + jalviewjsJ2sProps.each { prop, val -> + if (val != null) { + if (prop == siteDirProperty) { + if (!(val.startsWith('/') || val.startsWith("file://") )) { + val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}" + } + setSiteDir = true + } + property(prop,val) + } + if (!setSiteDir) { // default site location, don't override specifically set property + property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}") + } + } + outputFile = jalviewjsJ2sAltSettingsFileName + + if (! IN_ECLIPSE) { + inputs.properties(jalviewjsJ2sProps) + outputs.file(jalviewjsJ2sAltSettingsFileName) + } +} + + +task jalviewjsEclipseSetup { + dependsOn jalviewjsEclipseCopyDropins + dependsOn jalviewjsSetEclipseWorkspace + dependsOn jalviewjsCreateJ2sSettings +} + + +task jalviewjsSyncAllLibs (type: Sync) { + dependsOn jalviewjsTransferUnzipAllLibs + def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}") + inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}") + def outputDir = "${jalviewDir}/${jalviewjsSiteDir}" + + from inputFiles + into outputDir + def outputFiles = [] + rename { filename -> + outputFiles += "${outputDir}/${filename}" + null + } + preserve { + include "**" + } + + // should this be exclude really ? + duplicatesStrategy "INCLUDE" + + outputs.files outputFiles + inputs.files inputFiles +} + + +task jalviewjsSyncResources (type: Sync) { + dependsOn buildResources + + def inputFiles = fileTree(dir: resourcesBuildDir) + def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}" + + from inputFiles + into outputDir + def outputFiles = [] + rename { filename -> + outputFiles += "${outputDir}/${filename}" + null + } + preserve { + include "**" + } + outputs.files outputFiles + inputs.files inputFiles +} + + +task jalviewjsSyncSiteResources (type: Sync) { + def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}") + def outputDir = "${jalviewDir}/${jalviewjsSiteDir}" + + from inputFiles + into outputDir + def outputFiles = [] + rename { filename -> + outputFiles += "${outputDir}/${filename}" + null + } + preserve { + include "**" + } + outputs.files outputFiles + inputs.files inputFiles +} + + +task jalviewjsSyncBuildProperties (type: Sync) { + dependsOn createBuildProperties + def inputFiles = [file(buildProperties)] + def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}" + + from inputFiles + into outputDir + def outputFiles = [] + rename { filename -> + outputFiles += "${outputDir}/${filename}" + null + } + preserve { + include "**" + } + outputs.files outputFiles + inputs.files inputFiles +} + + +task jalviewjsProjectImport(type: Exec) { + dependsOn eclipseSetup + dependsOn jalviewjsEclipsePaths + dependsOn jalviewjsEclipseSetup + + doFirst { + // do not run a headless import when we claim to be in Eclipse + if (IN_ECLIPSE) { + println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}") + throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'") + } else { + println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}") + } + } + + //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core" + def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview" + executable(eclipseBinary) + args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath]) + if (eclipseDebug) { + args += "-debug" + } + args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ] + if (!IN_ECLIPSE) { + args += [ "-D${j2sHeadlessBuildProperty}=true" ] + args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ] + } + + inputs.file("${jalviewDir}/.project") + outputs.upToDateWhen { + file(projdir).exists() + } +} + + +task jalviewjsTranspile(type: Exec) { + dependsOn jalviewjsEclipseSetup + dependsOn jalviewjsProjectImport + dependsOn jalviewjsEclipsePaths + if (!IN_ECLIPSE) { + dependsOn jalviewjsEnableAltFileProperty + } + + doFirst { + // do not run a headless transpile when we claim to be in Eclipse + if (IN_ECLIPSE) { + println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}") + throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'") + } else { + println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}") + } + } + + executable(eclipseBinary) + args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ]) + if (eclipseDebug) { + args += "-debug" + } + args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ] + if (!IN_ECLIPSE) { + args += [ "-D${j2sHeadlessBuildProperty}=true" ] + args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ] + } + + def stdout + def stderr + doFirst { + stdout = new ByteArrayOutputStream() + stderr = new ByteArrayOutputStream() + + def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}" + def logOutFile = file(logOutFileName) + logOutFile.createNewFile() + logOutFile.text = """ROOT: ${jalviewjs_eclipse_root} +BINARY: ${eclipseBinary} +VERSION: ${eclipseVersion} +WORKSPACE: ${eclipseWorkspace} +DEBUG: ${eclipseDebug} +---- +""" + def logOutFOS = new FileOutputStream(logOutFile, true) // true == append + // combine stdout and stderr + def logErrFOS = logOutFOS + + if (jalviewjs_j2s_to_console.equals("true")) { + standardOutput = new org.apache.tools.ant.util.TeeOutputStream( + new org.apache.tools.ant.util.TeeOutputStream( + logOutFOS, + stdout), + System.out) + errorOutput = new org.apache.tools.ant.util.TeeOutputStream( + new org.apache.tools.ant.util.TeeOutputStream( + logErrFOS, + stderr), + System.err) + } else { + standardOutput = new org.apache.tools.ant.util.TeeOutputStream( + logOutFOS, + stdout) + errorOutput = new org.apache.tools.ant.util.TeeOutputStream( + logErrFOS, + stderr) + } + } + + doLast { + if (stdout.toString().contains("Error processing ")) { + // j2s did not complete transpile + //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'") + if (jalviewjs_ignore_transpile_errors.equals("true")) { + println("IGNORING TRANSPILE ERRORS") + println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'") + } else { + throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'") + } + } + } + + inputs.dir("${jalviewDir}/${sourceDir}") + outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}") + outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } ) +} + + +def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) { + + def stdout = new ByteArrayOutputStream() + def stderr = new ByteArrayOutputStream() + + def coreFile = file(jsfile) + def msg = "" + msg = "Creating core for ${name}...\nGenerating ${jsfile}" + println(msg) + logOutFile.createNewFile() + logOutFile.append(msg+"\n") + + def coreTop = file(prefixFile) + def coreBottom = file(suffixFile) + coreFile.getParentFile().mkdirs() + coreFile.createNewFile() + coreFile.write( coreTop.getText("UTF-8") ) + list.each { + f -> + if (f.exists()) { + def t = f.getText("UTF-8") + t.replaceAll("Clazz\\.([^_])","Clazz_${1}") + coreFile.append( t ) + } else { + msg = "...file '"+f.getPath()+"' does not exist, skipping" + println(msg) + logOutFile.append(msg+"\n") + } + } + coreFile.append( coreBottom.getText("UTF-8") ) + + msg = "Generating ${zjsfile}" + println(msg) + logOutFile.append(msg+"\n") + def logOutFOS = new FileOutputStream(logOutFile, true) // true == append + def logErrFOS = logOutFOS + + javaexec { + classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"]) + main = "com.google.javascript.jscomp.CommandLineRunner" + jvmArgs = [ "-Dfile.encoding=UTF-8" ] + args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ] + maxHeapSize = "2g" + + msg = "\nRunning '"+commandLine.join(' ')+"'\n" + println(msg) + logOutFile.append(msg+"\n") + + if (logOutConsole) { + standardOutput = new org.apache.tools.ant.util.TeeOutputStream( + new org.apache.tools.ant.util.TeeOutputStream( + logOutFOS, + stdout), + standardOutput) + errorOutput = new org.apache.tools.ant.util.TeeOutputStream( + new org.apache.tools.ant.util.TeeOutputStream( + logErrFOS, + stderr), + System.err) + } else { + standardOutput = new org.apache.tools.ant.util.TeeOutputStream( + logOutFOS, + stdout) + errorOutput = new org.apache.tools.ant.util.TeeOutputStream( + logErrFOS, + stderr) + } + } + msg = "--" + println(msg) + logOutFile.append(msg+"\n") +} + + +task jalviewjsBuildAllCores { + group "JalviewJS" + description "Build the core js lib closures listed in the classlists dir" + dependsOn jalviewjsTranspile + dependsOn jalviewjsTransferUnzipSwingJs + + def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}" + def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}" + def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}" + def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}" + def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core" + def prefixFile = "${jsDir}/core/coretop2.js" + def suffixFile = "${jsDir}/core/corebottom2.js" + + inputs.file prefixFile + inputs.file suffixFile + + def classlistFiles = [] + // add the classlists found int the jalviewjs_classlists_dir + fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each { + file -> + def name = file.getName() - ".txt" + classlistFiles += [ + 'file': file, + 'name': name + ] + } + + // _jmol and _jalview cores. Add any other peculiar classlist.txt files here + //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ] + classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ] + + jalviewjsCoreClasslists = [] + + classlistFiles.each { + hash -> + + def file = hash['file'] + if (! file.exists()) { + //println("...classlist file '"+file.getPath()+"' does not exist, skipping") + return false // this is a "continue" in groovy .each closure + } + def name = hash['name'] + if (name == null) { + name = file.getName() - ".txt" + } + + def filelist = [] + file.eachLine { + line -> + filelist += line + } + def list = fileTree(dir: j2sDir, includes: filelist) + + def jsfile = "${outputDir}/core${name}.js" + def zjsfile = "${outputDir}/core${name}.z.js" + + jalviewjsCoreClasslists += [ + 'jsfile': jsfile, + 'zjsfile': zjsfile, + 'list': list, + 'name': name + ] + + inputs.file(file) + inputs.files(list) + outputs.file(jsfile) + outputs.file(zjsfile) + } + + // _stevesoft core. add any cores without a classlist here (and the inputs and outputs) + def stevesoftClasslistName = "_stevesoft" + def stevesoftClasslist = [ + 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js", + 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js", + 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"), + 'name': stevesoftClasslistName + ] + jalviewjsCoreClasslists += stevesoftClasslist + inputs.files(stevesoftClasslist['list']) + outputs.file(stevesoftClasslist['jsfile']) + outputs.file(stevesoftClasslist['zjsfile']) + + // _all core + def allClasslistName = "_all" + def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js") + allJsFiles += fileTree( + dir: libJ2sDir, + include: "**/*.js", + excludes: [ + // these exlusions are files that the closure-compiler produces errors for. Should fix them + "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js", + "**/org/jmol/export/JSExporter.js" + ] + ) + allJsFiles += fileTree( + dir: swingJ2sDir, + include: "**/*.js", + excludes: [ + // these exlusions are files that the closure-compiler produces errors for. Should fix them + "**/sun/misc/Unsafe.js", + "**/swingjs/jquery/jquery-editable-select.js", + "**/swingjs/jquery/j2sComboBox.js", + "**/sun/misc/FloatingDecimal.js" + ] + ) + def allClasslist = [ + 'jsfile': "${outputDir}/core${allClasslistName}.js", + 'zjsfile': "${outputDir}/core${allClasslistName}.z.js", + 'list': allJsFiles, + 'name': allClasslistName + ] + // not including this version of "all" core at the moment + //jalviewjsCoreClasslists += allClasslist + inputs.files(allClasslist['list']) + outputs.file(allClasslist['jsfile']) + outputs.file(allClasslist['zjsfile']) + + doFirst { + def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}") + logOutFile.getParentFile().mkdirs() + logOutFile.createNewFile() + logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n") + + jalviewjsCoreClasslists.each { + jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true")) + } + } + +} + + +def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) { + copy { + from inputFile + into file(outputFile).getParentFile() + rename { filename -> + if (filename.equals(inputFile.getName())) { + return file(outputFile).getName() + } + return null + } + filter(ReplaceTokens, + beginToken: '_', + endToken: '_', + tokens: [ + 'MAIN': '"'+main_class+'"', + 'CODE': "null", + 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]", + 'COREKEY': jalviewjs_core_key, + 'CORENAME': coreName + ] + ) + } +} + + +task jalviewjsPublishCoreTemplates { + dependsOn jalviewjsBuildAllCores + def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}" + def inputFile = file(inputFileName) + def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}" + + def outputFiles = [] + jalviewjsCoreClasslists.each { cl -> + def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html" + cl['outputfile'] = outputFile + outputFiles += outputFile + } + + doFirst { + jalviewjsCoreClasslists.each { cl -> + jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile) + } + } + inputs.file(inputFile) + outputs.files(outputFiles) +} + + +task jalviewjsSyncCore (type: Sync) { + dependsOn jalviewjsBuildAllCores + dependsOn jalviewjsPublishCoreTemplates + def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}") + def outputDir = "${jalviewDir}/${jalviewjsSiteDir}" + + from inputFiles + into outputDir + def outputFiles = [] + rename { filename -> + outputFiles += "${outputDir}/${filename}" + null + } + preserve { + include "**" + } + outputs.files outputFiles + inputs.files inputFiles +} + + +// this Copy version of TransferSiteJs will delete anything else in the target dir +task jalviewjsCopyTransferSiteJs(type: Copy) { + dependsOn jalviewjsTranspile + from "${jalviewDir}/${jalviewjsTransferSiteJsDir}" + into "${jalviewDir}/${jalviewjsSiteDir}" +} + + +// this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes +task jalviewjsSyncTransferSiteJs(type: Sync) { + from "${jalviewDir}/${jalviewjsTransferSiteJsDir}" + include "**/*.*" + into "${jalviewDir}/${jalviewjsSiteDir}" + preserve { + include "**" + } +} + + +jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs +jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs +jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs +jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs + +jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs +jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs +jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs +jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs + + +task jalviewjsPrepareSite { + group "JalviewJS" + description "Prepares the website folder including unzipping files and copying resources" + dependsOn jalviewjsSyncAllLibs + dependsOn jalviewjsSyncResources + dependsOn jalviewjsSyncSiteResources + dependsOn jalviewjsSyncBuildProperties + dependsOn jalviewjsSyncCore +} + + +task jalviewjsBuildSite { + group "JalviewJS" + description "Builds the whole website including transpiled code" + dependsOn jalviewjsCopyTransferSiteJs + dependsOn jalviewjsPrepareSite +} + + +task cleanJalviewjsTransferSite { + doFirst { + delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}" + delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}" + delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}" + delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}" + } +} + + +task cleanJalviewjsSite { + dependsOn cleanJalviewjsTransferSite + doFirst { + delete "${jalviewDir}/${jalviewjsSiteDir}" + } +} + + +task jalviewjsSiteTar(type: Tar) { + group "JalviewJS" + description "Creates a tar.gz file for the website" + dependsOn jalviewjsBuildSite + def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz" + archiveFileName = outputFilename + + compression Compression.GZIP + + from "${jalviewDir}/${jalviewjsSiteDir}" + into jalviewjs_site_dir // this is inside the tar file + + inputs.dir("${jalviewDir}/${jalviewjsSiteDir}") +} + + +task jalviewjsServer { + group "JalviewJS" + def filename = "jalviewjsTest.html" + description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port." + def htmlFile = "${jalviewDirAbsolutePath}/${filename}" + doLast { + + def factory + try { + def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory") + factory = f.newInstance() + } catch (ClassNotFoundException e) { + throw new GradleException("Unable to create SimpleHttpFileServerFactory") + } + def port = Integer.valueOf(jalviewjs_server_port) + def start = port + def running = false + def url + def jalviewjsServer + while(port < start+1000 && !running) { + try { + def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}") + jalviewjsServer = factory.start(doc_root, port) + running = true + url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource) + println("SERVER STARTED with document root ${doc_root}.") + println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).") + println("For debug: "+url+"?j2sdebug") + println("For verbose: "+url+"?j2sverbose") + } catch (Exception e) { + port++; + } + } + def htmlText = """ +

JalviewJS Test. <${url}>

+

JalviewJS Test with debug. <${url}?j2sdebug>

+

JalviewJS Test with verbose. <${url}?j2sdebug>

+ """ + jalviewjsCoreClasslists.each { cl -> + def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName()) + htmlText += """ +

${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}>

+ """ + println("For core ${cl.name}: "+urlcore) + } + + file(htmlFile).text = htmlText + } + + outputs.file(htmlFile) + outputs.upToDateWhen({false}) +} + + +task cleanJalviewjsAll { + group "JalviewJS" + description "Delete all configuration and build artifacts to do with JalviewJS build" + dependsOn cleanJalviewjsSite + dependsOn jalviewjsEclipsePaths + + doFirst { + delete "${jalviewDir}/${jalviewjsBuildDir}" + delete "${jalviewDir}/${eclipse_bin_dir}" + if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) { + delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata") + } + delete jalviewjsJ2sAltSettingsFileName + } + + outputs.upToDateWhen( { false } ) +} + + +task jalviewjsIDE_checkJ2sPlugin { + group "00 JalviewJS in Eclipse" + description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)" + + doFirst { + def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}") + def j2sPluginFile = file(j2sPlugin) + def eclipseHome = System.properties["eclipse.home.location"] + if (eclipseHome == null || ! IN_ECLIPSE) { + throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.") + } + def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ] + def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"] + if (altPluginsDir != null && file(altPluginsDir).exists()) { + eclipseJ2sPluginDirs += altPluginsDir + } + def foundPlugin = false + def j2sPluginFileName = j2sPluginFile.getName() + def eclipseJ2sPlugin + def eclipseJ2sPluginFile + eclipseJ2sPluginDirs.any { dir -> + eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}" + eclipseJ2sPluginFile = file(eclipseJ2sPlugin) + if (eclipseJ2sPluginFile.exists()) { + foundPlugin = true + return true + } + } + if (!foundPlugin) { + def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin" + System.err.println(msg) + throw new StopExecutionException(msg) + } + + def digest = MessageDigest.getInstance("MD5") + + digest.update(j2sPluginFile.text.bytes) + def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0') + + digest.update(eclipseJ2sPluginFile.text.bytes) + def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0') + + if (j2sPluginMd5 != eclipseJ2sPluginMd5) { + def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'" + System.err.println(msg) + throw new StopExecutionException(msg) + } else { + def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)" + println(msg) + } + } +} + +task jalviewjsIDE_copyJ2sPlugin { + group "00 JalviewJS in Eclipse" + description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir" + + doFirst { + def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}") + def j2sPluginFile = file(j2sPlugin) + def eclipseHome = System.properties["eclipse.home.location"] + if (eclipseHome == null || ! IN_ECLIPSE) { + throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.") + } + def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}" + def eclipseJ2sPluginFile = file(eclipseJ2sPlugin) + def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart" + System.err.println(msg) + copy { + from j2sPlugin + eclipseJ2sPluginFile.getParentFile().mkdirs() + into eclipseJ2sPluginFile.getParent() + } + } +} + + +task jalviewjsIDE_j2sFile { + group "00 JalviewJS in Eclipse" + description "Creates the .j2s file" + dependsOn jalviewjsCreateJ2sSettings +} + + +task jalviewjsIDE_SyncCore { + group "00 JalviewJS in Eclipse" + description "Build the core js lib closures listed in the classlists dir and publish core html from template" + dependsOn jalviewjsSyncCore +} + + +task jalviewjsIDE_SyncSiteAll { + dependsOn jalviewjsSyncAllLibs + dependsOn jalviewjsSyncResources + dependsOn jalviewjsSyncSiteResources + dependsOn jalviewjsSyncBuildProperties +} + + +cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll + + +task jalviewjsIDE_PrepareSite { + group "00 JalviewJS in Eclipse" + description "Sync libs and resources to site dir, but not closure cores" + + dependsOn jalviewjsIDE_SyncSiteAll + //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task +} + + +task jalviewjsIDE_AssembleSite { + group "00 JalviewJS in Eclipse" + description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site" + dependsOn jalviewjsPrepareSite +} + + +task jalviewjsIDE_SiteClean { + group "00 JalviewJS in Eclipse" + description "Deletes the Eclipse transpiled site" + dependsOn cleanJalviewjsSite +} + + +task jalviewjsIDE_Server { + group "00 JalviewJS in Eclipse" + description "Starts a webserver on localhost to test the website" + dependsOn jalviewjsServer +} + + +// buildship runs this at import or gradle refresh +task eclipseSynchronizationTask { + //dependsOn eclipseSetup + dependsOn createBuildProperties + if (J2S_ENABLED) { + dependsOn jalviewjsIDE_j2sFile + dependsOn jalviewjsIDE_checkJ2sPlugin + dependsOn jalviewjsIDE_PrepareSite + } +} + + +// buildship runs this at build time or project refresh +task eclipseAutoBuildTask { + //dependsOn jalviewjsIDE_checkJ2sPlugin + //dependsOn jalviewjsIDE_PrepareSite +} + + +task jalviewjs { + group "JalviewJS" + description "Build the site" + dependsOn jalviewjsBuildSite +}