Mercurial > cgi-bin > hgweb.cgi > Osdep
changeset 0:895aa9a8d628
Initial commit.
author | David Barts <n5jrn@me.com> |
---|---|
date | Sat, 08 Feb 2020 08:46:17 -0800 |
parents | |
children | 5ea54efa8e45 |
files | .hgignore build.xml lib/commons-cli-1.4.jar setup.sh src/name/blackcap/osdep/Osdep.kt |
diffstat | 5 files changed, 274 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sat Feb 08 08:46:17 2020 -0800 @@ -0,0 +1,4 @@ +~$ +\.bak$ +^work/ +^bundles/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/build.xml Sat Feb 08 08:46:17 2020 -0800 @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project name="Osdep" default="help" basedir="." xmlns:fx="javafx:com.sun.javafx.tools.ant"> + <!-- import all environment variables as env.* --> + <property environment="env"/> + + <!-- ensure required environment variables are set --> + <macrodef name="env-require"> + <attribute name="name"/> + <sequential> + <fail message="Environment variable @{name} not set!"> + <condition> + <not><isset property="env.@{name}"/></not> + </condition> + </fail> + </sequential> + </macrodef> + <env-require name="JRE_HOME"/> + <env-require name="KOTLIN_HOME"/> + + <!-- define the kotlin task --> + <property name="kotlin.lib" value="${env.KOTLIN_HOME}/libexec/lib"/> + <typedef resource="org/jetbrains/kotlin/ant/antlib.xml" + classpath="${kotlin.lib}/kotlin-ant.jar"/> + + <!-- cribbed from https://stackoverflow.com/questions/7129672/uppercase-lowercase-capitalize-an-ant-property --> + <scriptdef language="javascript" name="toLowerCase"> + <attribute name="value" /> + <attribute name="target" /> + <![CDATA[ + project.setProperty( attributes.get( "target" ), + attributes.get( "value" ).toLowerCase() ); + ]]> + </scriptdef> + + <!-- Define the properties used by the build --> + <property name="app.name" value="${ant.project.name}"/> + <property name="app.entry" value="name.blackcap.osdep.OsdepKt"/> + <toLowerCase target="lc.app.name" value="${app.name}"/> + <property name="jar.name" value="${basedir}/${lc.app.name}.jar"/> + <property name="work.jar" value="${basedir}/work.jar"/> + <property name="lib.home" value="${basedir}/lib"/> + <property name="src.home" value="${basedir}/src"/> + + <!-- help message --> + <target name="help"> + <echo>You can use the following targets:</echo> + <echo> </echo> + <echo> help : (default) Prints this message </echo> + <echo> all : Cleans, compiles, and stages application</echo> + <echo> clean : Deletes work directories</echo> + <echo> compile : Compiles servlets into class files</echo> + <echo> jar : Make JAR file.</echo> + <echo> </echo> + <echo>For example, to clean, compile, and package all at once, run:</echo> + <echo>prompt> ant all </echo> + </target> + + <!-- Define the CLASSPATH --> + <target name="classpath"> + <path id="std.classpath"> + <fileset dir="${lib.home}"> + <include name="*.jar"/> + </fileset> + </path> + <path id="compile.classpath"> + <path refid="std.classpath"/> + <pathelement location="${src.home}"/> + </path> + <path id="test.classpath"> + <path refid="std.classpath"/> + <pathelement location="${work.home}"/> + </path> + </target> + + <!-- do everything but install --> + <target name="all" depends="jar" + description="Clean work dirs, compile, make JAR."/> + + <!-- compile *.kt to *.class --> + <target name="compile" depends="classpath" + description="Compile Java sources to ${work.home}"> + <kotlinc src="${src.home}" output="${work.jar}" + classpathref="compile.classpath"/> + </target> + + <!-- make .jar file --> + <target name="jar" depends="compile" description="Create JAR file."> + <jar destfile="${jar.name}"> + <manifest> + <attribute name="Main-Class" value="${app.entry}"/> + </manifest> + <zipgroupfileset dir="${lib.home}" includes="*.jar"/> + <zipfileset src="${work.jar}"/> + </jar> + </target> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.sh Sat Feb 08 08:46:17 2020 -0800 @@ -0,0 +1,10 @@ +#!/bin/bash + +export JRE_HOME="$(/usr/libexec/java_home)" +export KOTLIN_HOME="/usr/local/Cellar/kotlin/1.3.61" + +export ANT_HOME="$HOME/java/apache-ant-1.10.1" +if [[ "$PATH" != *$ANT_HOME/bin* ]] +then + export PATH="$ANT_HOME/bin:$PATH" +fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/name/blackcap/osdep/Osdep.kt Sat Feb 08 08:46:17 2020 -0800 @@ -0,0 +1,164 @@ +/* + * Recursively examines the specified directories for files that end in + * .<type>.osdep, where <type> is one of unix, mac, windows, or default. + * The file that matches the current OS type (or the type specified with + * the -t option) + */ +package name.blackcap.osdep + +import java.io.File +import java.io.FileInputStream +import java.io.FileOutputStream +import java.io.IOException +import kotlin.collections.HashMap +import kotlin.collections.HashSet +import org.apache.commons.cli.CommandLine +import org.apache.commons.cli.DefaultParser +import org.apache.commons.cli.HelpFormatter +import org.apache.commons.cli.Option +import org.apache.commons.cli.Options +import org.apache.commons.cli.ParseException + +var ostype = run { + val rawType = System.getProperty("os.name")?.toLowerCase() + if (rawType == null) { + "default" + } else if (rawType.contains("win")) { + "windows" + } else if (rawType.contains("mac")) { + "mac" + } else if (rawType.contains("nix") || rawType.contains("nux") || rawType.contains("aix") || rawType.contains("sunos")) { + "unix" + } else { + "default" + } +} + +val MYNAME = "osdep" +val MYEXT = ".osdep" + +val files = HashMap<String, HashSet<String>>() + +var errors = 0 + +fun main(args: Array<String>) { + val options = Options().apply { + addOption("?", "help", false, "Print this help message.") + addOption("c", "clean", false, "Clean instead of copying.") + addOption("t", "type", true, "Specify OS type (default ${ostype}).") + } + var cmdLine: CommandLine? = null + try { + cmdLine = DefaultParser().parse(options, args) + } catch (e: ParseException) { + System.err.format("%s: %s%n", MYNAME, e.message) + System.exit(2) + } + + if (cmdLine!!.hasOption("help")) { + val usage = MYNAME + " [--help] [--clean] [--type=type] directory [...]" + HelpFormatter().printHelp(usage, options, false); + System.exit(0); + } + + val clOstype = cmdLine!!.getOptionValue("type") + if (clOstype != null) { + ostype = clOstype + } + + for (arg in cmdLine.args) { + try { + File(arg).walk().forEach { build(it) } + } catch (e: Exception) { + handle(e, "cannot walk '${arg}'") + } + } + + val process = if (cmdLine!!.hasOption("clean")) ::clean else ::copy + files.forEach { + process(it.key, it.value) + } + System.exit(if (errors == 0) 0 else 1) +} + +fun build(file: File) { + if (!file.isFile()) { + return + } + val path = file.toString() + if (!path.endsWith(MYEXT)) { + return + } + val dot2 = path.lastIndexOf('.') + if (dot2 <= 0) { + return + } + val dot1 = path.lastIndexOf('.', dot2 - 1) + if (dot1 <= 0) { + return + } + val base = path.substring(0 .. (dot1 - 1)) + val type = path.substring((dot1 + 1) .. (dot2 - 1)) + println("base=${base}, type=${type}") /* debug */ + val fset = files[base] + if (fset != null) { + fset.add(type) + } else { + files[base] = HashSet<String>().apply { add(type) } + } +} + +fun copy(base: String, types: HashSet<String>) { + val type = if (ostype in types) ostype else "default" + if (type !in types) { + System.err.format("%s: type '%s' missing for '%s'%n", MYNAME, type, base) + errors += 1 + return + } + copf("${base}.${type}${MYEXT}", base) +} + +fun copf(source: String, target: String) { + val sf = File(source) + val tf = File(target) + try { + FileInputStream(sf).use { sfp -> + FileOutputStream(tf).use { tfp -> + sfp.copyTo(tfp) + } + } + } catch (e: Exception) { + handle(e, "cannot copy '${source}' to '${target}'") + return + } + try { + tf.setLastModified(sf.lastModified()) + } catch (e: Exception) { + handle(e, "cannot set time of '${target}'") + } +} + +fun clean(base: String, @Suppress("UNUSED_PARAMETER") ignored: HashSet<String>) { + val file = File(base) + if (file.exists()) { + try { + if (!file.delete()) { + System.err.format("%s: '%s' not deleted%n", MYNAME, base) + errors += 1 + } + } catch (e: Exception) { + handle(e, "cannot delete '${base}'") + } + } +} + +fun handle(exception: Exception, message: String) { + val fallback = when (exception) { + is SecurityException -> "security violation" + is IOException -> "I/O error" + else -> throw exception + } + System.err.format("%s: %s%n", MYNAME, exception.message ?: fallback) + System.err.format("%s: %s%n", MYNAME, message) + errors += 1 +}