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>
Binary file lib/commons-cli-1.4.jar has changed
--- /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
+}