diff --git a/.build/bb.edn b/.build/bb.edn index b68f2790..c1e5ff3e 100644 --- a/.build/bb.edn +++ b/.build/bb.edn @@ -2,5 +2,5 @@ :deps {borkdude/gh-release-artifact #_{:local/root "../gh-release-artifact"} {:git/url "https://github.com/borkdude/gh-release-artifact" - :sha "f34f3e382e6a0ef7f52748b2f27eb681f799a822"}} + :sha "cf082df46a648178d1904e9cbcb787d8136a35c6"}} :tasks {release-artifact babashka.release-artifact/release}} diff --git a/.circleci/config.yml b/.circleci/config.yml index 2c2c1bd5..3e0293e5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,484 +3,38 @@ # Check https://circleci.com/docs/2.0/language-clojure/ for more details # version: 2.1 -commands: - setup-docker-buildx: - steps: - - run: - name: Create multi-platform capabale buildx builder - command: | - docker run --privileged --rm tonistiigi/binfmt --install all - docker buildx create --name ci-builder --use -jobs: - jvm: - docker: - - image: circleci/clojure:openjdk-11-lein-2.9.8-bullseye - working_directory: ~/repo - environment: - LEIN_ROOT: "true" - BABASHKA_PLATFORM: linux # could be used in jar name - resource_class: large - steps: - - checkout - - run: - name: "Pull Submodules" - command: | - git submodule init - git submodule update - - restore_cache: - keys: - - v1-dependencies-{{ checksum "project.clj" }}-{{ checksum "deps.edn" }} - # fallback to using the latest cache if no exact match is found - - v1-dependencies- - - run: - name: Install Clojure - command: | - sudo script/install-clojure - - run: - name: Run JVM tests - command: | - export BABASHKA_FEATURE_JDBC=true - export BABASHKA_FEATURE_POSTGRESQL=true - script/test - script/run_lib_tests - - run: - name: Run as lein command - command: | - .circleci/script/lein - - run: - name: Create uberjar - command: | - mkdir -p /tmp/release - script/uberjar - VERSION=$(cat resources/BABASHKA_VERSION) - jar=target/babashka-$VERSION-standalone.jar - cp $jar /tmp/release - java -jar $jar script/reflection.clj - reflection="babashka-$VERSION-reflection.json" - java -jar "$jar" --config .build/bb.edn --deps-root . release-artifact "$jar" - java -jar "$jar" --config .build/bb.edn --deps-root . release-artifact "$reflection" - - store_artifacts: - path: /tmp/release - destination: release - - save_cache: - paths: - - ~/.m2 - key: v1-dependencies-{{ checksum "project.clj" }}-{{ checksum "deps.edn" }} - linux: - docker: - - image: circleci/clojure:openjdk-11-lein-2.9.8-bullseye - working_directory: ~/repo - environment: - LEIN_ROOT: "true" - GRAALVM_VERSION: "22.0.0.2" - GRAALVM_HOME: /home/circleci/graalvm-ce-java11-22.0.0.2 - BABASHKA_PLATFORM: linux # used in release script - BABASHKA_TEST_ENV: native - BABASHKA_XMX: "-J-Xmx6500m" - resource_class: large - steps: - - checkout - - run: - name: "Pull Submodules" - command: | - git submodule init - git submodule update - - restore_cache: - keys: - - linux-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - run: - name: Install Clojure - command: | - sudo script/install-clojure - - run: - name: Install native dev tools - command: | - sudo apt-get update - sudo apt-get -y install build-essential zlib1g-dev - - run: - name: Download GraalVM - command: | - script/install-graalvm - - run: - name: Build binary - command: | - script/uberjar - script/compile - no_output_timeout: 30m - - run: - name: Run tests - command: | - script/test - script/run_lib_tests - - run: - name: Release - command: | - .circleci/script/release - - persist_to_workspace: - root: /tmp - paths: - - release - - save_cache: - paths: - - ~/.m2 - - ~/graalvm-ce-java11-22.0.0.2 - key: linux-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - store_artifacts: - path: /tmp/release - destination: release - - run: - name: Publish artifact link to Slack - command: | - ./bb .circleci/script/publish_artifact.clj || true - linux-static: - docker: - - image: circleci/clojure:openjdk-11-lein-2.9.8-bullseye - working_directory: ~/repo - environment: - LEIN_ROOT: "true" - GRAALVM_VERSION: "22.0.0.2" - GRAALVM_HOME: /home/circleci/graalvm-ce-java11-22.0.0.2 - BABASHKA_PLATFORM: linux # used in release script - BABASHKA_TEST_ENV: native - BABASHKA_STATIC: "true" - BABASHKA_MUSL: "true" - BABASHKA_XMX: "-J-Xmx6500m" - resource_class: large - steps: - - checkout - - attach_workspace: - at: /tmp - - run: - name: "Pull Submodules" - command: | - git submodule init - git submodule update - # - run: - # name: "Short circuit on SNAPSHOT" - # command: | - # VERSION=$(cat resources/BABASHKA_VERSION) - # if [[ "$VERSION" == *-SNAPSHOT ]] - # then - # circleci task halt - # fi - - restore_cache: - keys: - - linux-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - run: - name: Install Clojure - command: | - sudo script/install-clojure - - run: - name: Install native dev tools - command: | - sudo apt-get update - sudo apt-get -y install build-essential zlib1g-dev - sudo -E script/setup-musl - - run: - name: Download GraalVM - command: | - script/install-graalvm - - run: - name: Build binary - command: | - script/uberjar - script/compile - no_output_timeout: 30m - - run: - name: Run tests - command: | - script/test - script/run_lib_tests - - run: - name: Release - command: | - .circleci/script/release - - persist_to_workspace: - root: /tmp - paths: - - release - - save_cache: - paths: - - ~/.m2 - - ~/graalvm-ce-java11-22.0.0.2 - key: linux-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - store_artifacts: - path: /tmp/release - destination: release - - run: - name: Publish artifact link to Slack - command: | - ./bb .circleci/script/publish_artifact.clj || true - linux-aarch64: - machine: - enabled: true - image: ubuntu-2004:202101-01 - resource_class: arm.large - working_directory: ~/repo - environment: - LEIN_ROOT: "true" - GRAALVM_VERSION: "22.0.0.2" - GRAALVM_HOME: /home/circleci/graalvm-ce-java11-22.0.0.2 - BABASHKA_PLATFORM: linux # used in release script - BABASHKA_ARCH: aarch64 - BABASHKA_TEST_ENV: native - BABASHKA_XMX: "-J-Xmx6500m" - steps: - - checkout - - run: - name: "Pull Submodules" - command: | - git submodule init - git submodule update - - run: - name: Install Clojure - command: | - sudo script/install-clojure - - restore_cache: - keys: - - linux-aarch64-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - run: - name: Install native dev tools - command: | - sudo apt-get update - sudo apt-get -y install build-essential zlib1g-dev - - run: - name: Download GraalVM - command: | - script/install-graalvm - - run: - name: Build binary - command: | - script/uberjar - script/compile - no_output_timeout: 30m - - run: - name: Run tests - command: | - script/test - script/run_lib_tests - - run: - name: Release - command: | - .circleci/script/release - - persist_to_workspace: - root: /tmp - paths: - - release - - save_cache: - paths: - - ~/.m2 - - ~/graalvm-ce-java11-22.0.0.2 - key: linux-aarch64-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - store_artifacts: - path: /tmp/release - destination: release - - run: - name: Publish artifact link to Slack - command: | - ./bb .circleci/script/publish_artifact.clj || true - linux-aarch64-static: - machine: - enabled: true - image: ubuntu-2004:202101-01 - resource_class: arm.large - working_directory: ~/repo - environment: - LEIN_ROOT: "true" - GRAALVM_VERSION: "22.0.0.2" - GRAALVM_HOME: /home/circleci/graalvm-ce-java11-22.0.0.2 - BABASHKA_PLATFORM: linux # used in release script - BABASHKA_ARCH: aarch64 - BABASHKA_TEST_ENV: native - BABASHKA_XMX: "-J-Xmx6500m" - BABASHKA_STATIC: "true" - steps: - - checkout - - run: - name: "Pull Submodules" - command: | - git submodule init - git submodule update - # - run: - # name: "Short circuit on SNAPSHOT" - # command: | - # VERSION=$(cat resources/BABASHKA_VERSION) - # if [[ "$VERSION" == *-SNAPSHOT ]] - # then - # circleci task halt - # fi - - run: - name: Install Clojure - command: | - sudo script/install-clojure - - restore_cache: - keys: - - linux-aarch64-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - run: - name: Install native dev tools - command: | - sudo apt-get update - sudo apt-get -y install build-essential zlib1g-dev - # sudo -E script/setup-musl - - run: - name: Download GraalVM - command: | - script/install-graalvm - - run: - name: Build binary - command: | - script/uberjar - script/compile - no_output_timeout: 30m - - run: - name: Run tests - command: | - script/test - script/run_lib_tests - - run: - name: Release - command: | - .circleci/script/release - - persist_to_workspace: - root: /tmp - paths: - - release - - save_cache: - paths: - - ~/.m2 - - ~/graalvm-ce-java11-22.0.0.2 - key: linux-aarch64-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - store_artifacts: - path: /tmp/release - destination: release - - run: - name: Publish artifact link to Slack - command: | - ./bb .circleci/script/publish_artifact.clj || true - mac: - macos: - xcode: "12.0.0" - environment: - MACOSX_DEPLOYMENT_TARGET: 10.13 # 10.12 is EOL - GRAALVM_VERSION: "22.0.0.2" - GRAALVM_HOME: /Users/distiller/graalvm-ce-java11-22.0.0.2/Contents/Home - BABASHKA_PLATFORM: macos # used in release script - BABASHKA_TEST_ENV: native - BABASHKA_XMX: "-J-Xmx6500m" - resource_class: large - steps: - - checkout - - run: - name: "Pull Submodules" - command: | - git submodule init - git submodule update - - restore_cache: - keys: - - mac-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - run: - name: Install Clojure - command: | - script/install-clojure - - run: - name: Install Leiningen - command: | - script/install-leiningen - - run: - name: Download GraalVM - command: | - script/install-graalvm - - run: - name: Build binary - command: | - export PATH=$GRAALVM_HOME/bin:$PATH - script/uberjar - script/compile - no_output_timeout: 30m - - run: - name: Run tests - command: | - export PATH=$GRAALVM_HOME/bin:$PATH - script/test - script/run_lib_tests - - run: - name: Release - command: | - .circleci/script/release - - save_cache: - paths: - - ~/.m2 - - ~/graalvm-ce-java11-22.0.0.2/Contents/Home - key: mac-{{ checksum "project.clj" }}-{{ checksum ".circleci/config.yml" }} - - store_artifacts: - path: /tmp/release - destination: release - - run: - name: Publish artifact link to Slack - command: | - ./bb .circleci/script/publish_artifact.clj || true - deploy: - resource_class: large - docker: - - image: circleci/clojure:lein-2.9.8 - working_directory: ~/repo - environment: - LEIN_ROOT: "true" - steps: - - checkout - - run: - name: "Pull Submodules" - command: | - git submodule init - git submodule update - - restore_cache: - keys: - - v1-dependencies-{{ checksum "project.clj" }} - # fallback to using the latest cache if no exact match is found - - v1-dependencies- - - run: .circleci/script/deploy - - save_cache: - paths: - - ~/.m2 - key: v1-dependencies-{{ checksum "project.clj" }} - docker: - machine: - image: ubuntu-2004:202111-01 - steps: - - checkout - - setup-docker-buildx - - attach_workspace: - at: /tmp - - run: - name: Build Docker image - environment: - PLATFORM: linux/amd64,linux/arm64 - command: .circleci/script/docker +# this allows you to use CircleCI's dynamic configuration feature +setup: true + +# the continuation orb is required in order to use dynamic configuration +orbs: + continuation: circleci/continuation@0.1.2 + +# our defined job, and its steps +jobs: + setup: + docker: + - image: cimg/clojure:1.11.1 + steps: + - checkout + - run: + name: Bootstrap Babashka + command: | + curl -sLO https://raw.githubusercontent.com/babashka/babashka/master/install + sudo bash install --dir /tmp + - run: + name: Rename bb binary + command: mv /tmp/bb /tmp/bbb + - run: + name: Generate config + command: | + /tmp/bbb .circleci/script/short_ci.clj > generated_config.yml + - continuation/continue: + configuration_path: generated_config.yml + +# our single workflow, that triggers the setup job defined above workflows: - version: 2 - ci: + setup: jobs: - - jvm - - linux - - linux-static - - mac - - linux-aarch64 - - linux-aarch64-static - - deploy: - filters: - branches: - only: master - requires: - - jvm - - linux - - mac - - docker: - filters: - branches: - only: - - master - requires: - - linux - - linux-static - - linux-aarch64 + - setup diff --git a/.circleci/script/docker b/.circleci/script/docker deleted file mode 100755 index f16447b6..00000000 --- a/.circleci/script/docker +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash - -set -eo pipefail - -image_name="babashka/babashka" -image_tag=$(cat resources/BABASHKA_VERSION) -platform=${PLATFORM:-"linux/amd64"} -latest_tag="latest" -label_args=("--label" "'org.opencontainers.image.description=Native, fast starting Clojure interpreter for scripting'" - "--label" "org.opencontainers.image.title=Babashka" - "--label" "org.opencontainers.image.created=$(date -Iseconds)" - "--label" "org.opencontainers.image.url=${CIRCLE_REPOSITORY_URL}" - "--label" "org.opencontainers.image.documentation=${CIRCLE_REPOSITORY_URL}" - "--label" "org.opencontainers.image.source=${CIRCLE_REPOSITORY_URL}" - "--label" "org.opencontainers.image.revision=${CIRCLE_SHA1}" - "--label" "org.opencontainers.image.ref.name=${CIRCLE_TAG}:${CIRCLE_BRANCH}" - "--label" "org.opencontainers.image.version=${image_tag}") - -if [[ $image_tag =~ SNAPSHOT$ ]]; then - echo "This is a snapshot version" - snapshot="true" -else - echo "This is a non-snapshot version" - snapshot="false" -fi - -if [ -z "$CIRCLE_PULL_REQUEST" ] && [ "$CIRCLE_BRANCH" = "master" ]; then - echo "Building & pushing $platform Docker image(s) $image_name:$image_tag" - echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USER" --password-stdin - IFS=',' read -r -a platforms <<< "$platform" - for p in "${platforms[@]}"; do - tarball_platform=${p//\//-} - if [[ $tarball_platform == "linux-arm64" ]]; then tarball_platform="linux-aarch64"; fi - mkdir -p $p - tar zxvf "/tmp/release/babashka-${image_tag}-${tarball_platform}.tar.gz" -C $p - # this overwrites, but this is to work around having built the uberjar/metabom multiple times - cp "/tmp/release/${tarball_platform}-metabom.jar" ./metabom.jar - done - docker buildx build -t "$image_name:$image_tag" --platform "$platform" "${label_args[@]}" --push -f Dockerfile.ci . - if [[ $snapshot == "false" ]]; then - echo "Building & pushing $platform Docker image(s) $image_name:$latest_tag" - docker buildx build -t "$image_name:$latest_tag" --platform "$platform" "${label_args[@]}" --push -f Dockerfile.ci . - fi - for p in "${platforms[@]}"; do - rm -rf $p - done - - # build alpine image for linux-amd64 only (no upstream arm64 support yet) - tar zxvf "/tmp/release/babashka-${image_tag}-linux-amd64-static.tar.gz" - echo "Building & pushing Docker image $image_name:$image_tag-alpine" - docker buildx build -t "$image_name:$image_tag-alpine" --platform=linux/amd64 "${label_args[@]}" --push -f Dockerfile.alpine . - - if [[ $snapshot == "false" ]]; then - echo "Building & pushing Docker image $image_name:alpine" - docker buildx build -t "$image_name:alpine" --platform=linux/amd64 "${label_args[@]}" --push -f Dockerfile.alpine . - fi -else - echo "Not publishing Docker image" -fi - -exit 0; diff --git a/.circleci/script/docker.clj b/.circleci/script/docker.clj new file mode 100644 index 00000000..a884c893 --- /dev/null +++ b/.circleci/script/docker.clj @@ -0,0 +1,98 @@ +(require '[clojure.string :as str] + '[babashka.process :as proc] + '[babashka.fs :as fs]) +(import '[java.time Instant]) + +(defn read-env + ([k] + (read-env k nil)) + ([k default] + (or (System/getenv k) + default))) + +(def image-name "babashka/babashka") + +(def image-tag (slurp "resources/BABASHKA_VERSION")) + +(def latest-tag "latest") + +(def platforms (read-env "PLATFORMS" "linux/amd64")) + +(def circle-repository-url (read-env "CIRCLE_REPOSITORY_URL")) + +(def label-args + ["--label" "'org.opencontainers.image.description=Native, fast starting Clojure interpreter for scripting'" + "--label" "org.opencontainers.image.title=Babashka" + "--label" (str "org.opencontainers.image.created=" (Instant/now)) + "--label" (str "org.opencontainers.image.url=" circle-repository-url) + "--label" (str "org.opencontainers.image.documentation=" circle-repository-url) + "--label" (str "org.opencontainers.image.source=" circle-repository-url) + "--label" (str "org.opencontainers.image.revision=" (read-env "CIRCLE_SHA1")) + "--label" + (format "org.opencontainers.image.ref.name=%s:%s" + (read-env "CIRCLE_TAG") + (read-env "CIRCLE_BRANCH")) + "--label" (str "org.opencontainers.image.version=" image-tag)]) + +(def snapshot? (str/includes? image-tag "SNAPSHOT")) + +(defn exec + [cmd] + (-> cmd + (proc/process {:out :inherit :err :inherit}) + (proc/check))) + +(defn docker-login + [username password] + (exec ["docker" "login" "-u" username "-p" password])) + +(defn build-push + [image-tag platform docker-file] + (println (format "Building and pushing %s Docker image(s) %s:%s" + platform + image-name + image-tag)) + (let [base-cmd ["docker" "buildx" "build" + "-t" (str image-name ":" image-tag) + "--platform" platform + "--push" + "-f" docker-file]] + (exec (concat base-cmd label-args ["."])))) + +(defn build-push-images + [] + (doseq [platform (str/split platforms #",")] + (let [tarball-platform (str/replace platform #"\/" "-") + tarball-platform (if (= "linux-arm64" tarball-platform) + "linux-aarch64" + tarball-platform) + tarball-path (format "/tmp/release/babashka-%s-%s.tar.gz" + image-tag + tarball-platform)] + (fs/create-dirs platform) + (exec ["tar" "zxvf" tarball-path "-C" platform]) + ; this overwrites, but this is to work around having built the uberjar/metabom multiple times + (fs/copy (format "/tmp/release/%s-metabom.jar" tarball-platform) "metabom.jar" {:replace-existing true}))) + (build-push image-tag platforms "Dockerfile.ci") + (when-not snapshot? + (build-push latest-tag platforms "Dockerfile.ci"))) + +(defn build-push-alpine-images + "Build alpine image for linux-amd64 only (no upstream arm64 support yet)" + [] + (exec ["tar" "zxvf" (str "/tmp/release/babashka-" image-tag "-linux-amd64-static.tar.gz")]) + (build-push (str image-tag "-alpine") "linux/amd64" "Dockerfile.alpine") + (when-not snapshot? + (build-push "alpine" "linux/amd64" "Dockerfile.alpine"))) + +(when (= *file* (System/getProperty "babashka.file")) + (if (and (nil? (read-env "CIRCLE_PULL_REQUEST")) + (= "master" (read-env "CIRCLE_BRANCH"))) + (do + (if snapshot? + (println "This is a snapshot version") + (println "This is a non-snapshot version")) + (docker-login (read-env "DOCKERHUB_USER") (read-env "DOCKERHUB_PASS")) + (build-push-images) + (build-push-alpine-images)) + (println "Not publishing docker image(s)."))) diff --git a/.circleci/script/short_ci.clj b/.circleci/script/short_ci.clj new file mode 100644 index 00000000..90dab434 --- /dev/null +++ b/.circleci/script/short_ci.clj @@ -0,0 +1,271 @@ +(ns short-ci + (:require + [babashka.tasks :as tasks] + [clj-yaml.core :as yaml] + [clojure.string :as str] + [flatland.ordered.map :refer [ordered-map]])) + +(defn run + ([cmd-name cmd] + (run cmd-name cmd nil)) + ([cmd-name cmd no-output-timeout] + (let [base {:run {:name cmd-name + :command cmd}}] + (if no-output-timeout + (assoc-in base [:run :no_output_timeout] no-output-timeout) + base)))) + +(defn gen-steps + [shorted? steps] + (if shorted? + [(run "Shorted" "echo 'Skipping Run'")] + steps)) + +(defn gen-job + [shorted? conf] + (if shorted? + (-> conf + (dissoc :machine :macos) + (assoc :resource_class "small" :docker [{:image "ubuntu:latest"}])) + conf)) + +(defn pull-submodules + [] + (run "Pull Submodules" "git submodule init\ngit submodule update")) + +(defn deploy + [shorted?] + (gen-job shorted? + (ordered-map + :resource_class "large" + :docker [{:image "circleci/clojure:lein-2.9.8"}] + :working_directory "~/repo" + :environment {:LEIN_ROOT "true"} + :steps (gen-steps + shorted? + [:checkout + (pull-submodules) + {:restore_cache {:keys ["v1-dependencies-{{ checksum \"project.clj\" }}" + "v1-dependencies-"]}} + {:run ".circleci/script/deploy"} + {:save_cache {:paths ["~/.m2"] + :key "v1-dependencies-{{ checksum \"project.clj\" }}"}}])))) + +(defn docker + [shorted?] + (gen-job + shorted? + (ordered-map + :machine {:image "ubuntu-2004:202111-01"} + :steps + (gen-steps + shorted? + [:checkout + (pull-submodules) + "setup-docker-buildx" + {:attach_workspace {:at "/tmp"}} + (run "Build uberjar" "script/uberjar") + {:run + {:name "Build Docker image" + :environment {:PLATFORMS "linux/amd64,linux/arm64"} + :command + "java -jar ./target/babashka-$(cat resources/BABASHKA_VERSION)-standalone.jar .circleci/script/docker.clj"}}])))) + +(defn jvm + [shorted?] + (gen-job + shorted? + (ordered-map + :docker [{:image "circleci/clojure:openjdk-11-lein-2.9.8-bullseye"}] + :working_directory "~/repo" + :environment {:LEIN_ROOT "true" + :BABASHKA_PLATFORM "linux"} + :resource_class "large" + :steps + (gen-steps + shorted? + [:checkout + (pull-submodules) + {:restore_cache {:keys ["v1-dependencies-{{ checksum \"project.clj\" }}-{{ checksum \"deps.edn\" }}" + "v1-dependencies-"]}} + (run "Install Clojure" "sudo script/install-clojure") + (run + "Run JVM tests" + "export BABASHKA_FEATURE_JDBC=true +export BABASHKA_FEATURE_POSTGRESQL=true +script/test\nscript/run_lib_tests") + (run "Run as lein command" ".circleci/script/lein") + (run + "Create uberjar" + "mkdir -p /tmp/release +script/uberjar +VERSION=$(cat resources/BABASHKA_VERSION) +jar=target/babashka-$VERSION-standalone.jar +cp $jar /tmp/release +java -jar $jar script/reflection.clj +reflection=\"babashka-$VERSION-reflection.json\" +java -jar \"$jar\" --config .build/bb.edn --deps-root . release-artifact \"$jar\" +java -jar \"$jar\" --config .build/bb.edn --deps-root . release-artifact \"$reflection\"") + {:store_artifacts {:path "/tmp/release" + :destination "release"}} + {:save_cache {:paths ["~/.m2"] + :key "v1-dependencies-{{ checksum \"project.clj\" }}-{{ checksum \"deps.edn\" }}"}}])))) + +(defn unix + [shorted? static? musl? arch executor-conf resource-class graalvm-home platform] + (let [env {:LEIN_ROOT "true" + :GRAALVM_VERSION "22.2.0" + :GRAALVM_HOME graalvm-home + :BABASHKA_PLATFORM (if (= "mac" platform) + "macos" + platform) + :BABASHKA_TEST_ENV "native" + :BABASHKA_XMX "-J-Xmx6500m"} + env (if (= "aarch64" arch) + (assoc env :BABASHKA_ARCH arch) + env) + env (if static? + (assoc env :BABASHKA_STATIC "true") + env) + env (if musl? + (assoc env :BABASHKA_MUSL "true") + env) + env (if (= "mac" platform) + (assoc env :MACOSX_DEPLOYMENT_TARGET 10.13) + env) + base-install-cmd "sudo apt-get update\nsudo apt-get -y install build-essential zlib1g-dev" + cache-key (format "%s-%s{{ checksum \"project.clj\" }}-{{ checksum \".circleci/config.yml\" }}" + platform + (if (= "aarch64" arch) + "aarch64-" + ""))] + (gen-job shorted? + (merge + executor-conf + (ordered-map + :working_directory "~/repo" + :environment env + :resource_class resource-class + :steps (gen-steps shorted? + (filter some? + [:checkout + {:attach_workspace {:at "/tmp"}} + (run "Pull Submodules" "git submodule init\ngit submodule update") + {:restore_cache + {:keys [cache-key]}} + (run "Install Clojure" "sudo script/install-clojure") + (when (= "mac" platform) + (run "Install Leiningen" "script/install-leiningen")) + (when (not= "mac" platform) + (run "Install native dev tools" + (if (and static? musl? (not= "aarch64" arch)) + (str base-install-cmd "\nsudo -E script/setup-musl") + base-install-cmd))) + (run "Download GraalVM" "script/install-graalvm") + (run "Build binary" "script/uberjar\nscript/compile" "30m") + (run "Run tests" "script/test\nscript/run_lib_tests") + (run "Release" ".circleci/script/release") + {:persist_to_workspace {:root "/tmp" + :paths ["release"]}} + {:save_cache + {:paths ["~/.m2" "~/graalvm-ce-java11-22.2.0"] + :key cache-key}} + {:store_artifacts {:path "/tmp/release" + :destination "release"}} + (run "Publish artifact link to Slack" + "./bb .circleci/script/publish_artifact.clj || true")]))))))) + +(defn make-config + [shorted?] + (let [docker-executor-conf {:docker [{:image "circleci/clojure:openjdk-11-lein-2.9.8-bullseye"}]} + machine-executor-conf {:machine {:image "ubuntu-2004:202111-01"}} + mac-executor-conf {:macos {:xcode "14.0.0"}} + linux-graalvm-home "/home/circleci/graalvm-ce-java11-22.2.0" + mac-graalvm-home "/Users/distiller/graalvm-ce-java11-22.2.0/Contents/Home"] + (ordered-map + :version 2.1 + :commands + {:setup-docker-buildx + {:steps + [{:run + {:name "Create multi-platform capabale buildx builder" + :command + "docker run --privileged --rm tonistiigi/binfmt --install all\ndocker buildx create --name ci-builder --use"}}]}} + :jobs (ordered-map + :jvm (jvm shorted?) + :linux (unix shorted? false false "amd64" docker-executor-conf "large" linux-graalvm-home "linux") + :linux-static + (unix shorted? true true "amd64" docker-executor-conf "large" linux-graalvm-home "linux") + :linux-aarch64 (unix shorted? + false + false + "aarch64" + machine-executor-conf + "arm.large" + linux-graalvm-home + "linux") + :linux-aarch64-static + (unix shorted? true false "aarch64" machine-executor-conf "arm.large" linux-graalvm-home "linux") + :mac (unix shorted? false false "amd64" mac-executor-conf "large" mac-graalvm-home "mac") + :deploy (deploy shorted?) + :docker (docker shorted?)) + :workflows (ordered-map + :version 2 + :ci {:jobs ["jvm" + "linux" + "linux-static" + "mac" + "linux-aarch64" + "linux-aarch64-static" + {:deploy {:filters {:branches {:only "master"}} + :requires ["jvm" "linux"]}} + {:docker {:filters {:branches {:only "master"}} + :requires ["linux" "linux-static" "linux-aarch64"]}}]})))) + +(def skip-config + {:skip-if-only [#".*.md$" + #"^logo\/.*$"]}) + +(defn get-changes + [] + (-> (tasks/shell {:out :string} "git diff --name-only HEAD~1") + (:out) + (str/split-lines))) + +(defn irrelevant-change? + [change regexes] + (some? (some #(re-matches % change) regexes))) + +(defn relevant? + [change-set regexes] + (some? (some #(not (irrelevant-change? % regexes)) change-set))) + +(defn main + [] + (let [{:keys [skip-if-only]} skip-config + changed-files (get-changes) + conf (make-config (not (relevant? changed-files skip-if-only)))] + (println (yaml/generate-string conf + :dumper-options + {:flow-style :block})))) + +(when (= *file* (System/getProperty "babashka.file")) + (main)) + +(comment + (main) + + (def regexes + [#".*.md$" + #".*.clj$" ; ignore clojure files + #"^logo\/.*$"]) + + (:out (tasks/shell {:out :string} "ls")) + + (irrelevant-change? "src/file.png" regexes) + + (re-matches #".*.clj$" "src/file.clj.dfff") + + (re-matches #"^logo\/.*$" "logo/foo/bar.jpg") + + (relevant? ["src/file.clj"] regexes)) diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 00000000..8e7dccc8 --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,38 @@ +macos_instance: + image: ghcr.io/cirruslabs/macos-monterey-base:latest + +task: + skip: "changesIncludeOnly('logo/*', '**.md')" + env: + LEIN_ROOT: "true" + GRAALVM_VERSION: "22.1.0" + GRAALVM_HOME: ${HOME}/graalvm-ce-java11-22.1.0/Contents/Home + BABASHKA_PLATFORM: macos # used in release script + BABASHKA_ARCH: aarch64 + BABASHKA_TEST_ENV: native + BABASHKA_XMX: "-J-Xmx6500m" + GITHUB_TOKEN: ENCRYPTED[d6ff8cdc392157f211c754fa0763875434d1bfde0c00a05e48ba9470003a76c14c9213adb80623f81e13f2f0fa8fbd57] + script: | + git submodule init + git submodule update + + sudo script/install-clojure + sudo script/install-leiningen + script/install-graalvm + export PATH=$GRAALVM_HOME/bin:$PATH + sudo /usr/sbin/softwareupdate --install-rosetta --agree-to-license + java -version + + script/uberjar + script/compile + + # script/test + # script/run_lib_tests + + VERSION=$(cat resources/BABASHKA_VERSION) + arch=${BABASHKA_ARCH:-amd64} + archive="babashka-$VERSION-$BABASHKA_PLATFORM-$arch.tar.gz" + tar zcvf "$archive" bb + ./bb --config .build/bb.edn --deps-root . release-artifact "$archive" || true + binaries_artifacts: + path: "babashka-*.tar.gz" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 57b20f95..d1bb7dc5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,82 +2,77 @@ name: build on: push: + paths-ignore: + - "**.md" + - "logo/**" + branches: + - master + pull_request: + paths-ignore: + - "**.md" + - "logo/**" branches: - master +# TODO: Add deploy if needed jobs: - - scratch: - if: "!contains(github.event.head_commit.message, 'skip ci')" - runs-on: ubuntu-18.04 - steps: - - name: Git checkout - uses: actions/checkout@v1 - with: - fetch-depth: 1 - submodules: 'true' - - - name: Scratch - run: | - echo "Scratch" - jvm: - if: "!contains(github.event.head_commit.message, 'skip ci')" - # ubuntu 18.04 comes with lein + java8 installed - runs-on: ubuntu-18.04 + if: ${{ false }} # Disabled + # if: "!contains(github.event.head_commit.message, 'skip ci')" + runs-on: ubuntu-latest + env: + LEIN_ROOT: "true" + BABASHKA_PLATFORM: linux # could be used in jar name + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Git checkout - uses: actions/checkout@v1 + uses: actions/checkout@v2 with: fetch-depth: 1 submodules: 'true' - name: Cache deps - uses: actions/cache@v1 + uses: actions/cache@v2 id: cache-deps with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('project.clj') }} - restore-keys: | - ${{ runner.os }}-maven- + restore-keys: ${{ runner.os }}-maven- - - name: Cache GraalVM - uses: actions/cache@v1 - id: cache-graalvm + - name: Prepare java + uses: actions/setup-java@v2 with: - path: ~/graalvm-ce-java11-22.0.0.2 - key: ${{ runner.os }}-graalvm-22.0.0.2 - restore-keys: | - ${{ runner.os }}-graalvm-22.0.0.2 + distribution: 'adopt-hotspot' + java-version: '11' - - name: Download GraalVM - run: | - cd ~ - if ! [ -d graalvm-ce-java11-22.0.0.2 ]; then - curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz - tar xzf graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz - fi - - - name: Fetch deps - if: steps.cache-deps.outputs.cache-hit != 'true' - run: | - lein deps + - name: Install clojure tools + uses: DeLaGuardo/setup-clojure@5.0 + with: + cli: 1.10.3.1040 + lein: 2.9.8 - name: Run tests + env: + BABASHKA_FEATURE_JDBC: "true" + BABASHKA_FEATURE_POSTGRESQL: "true" run: | - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2" script/test - - - name: Test libraries - run: | - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2" - sudo script/install-clojure script/run_lib_tests + - name: Run as lein command + run: echo '{:a 1}' | lein bb '(:a *in*)' + - name: Build uberjar run: | - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2" + mkdir -p /tmp/release script/uberjar + VERSION=$(cat resources/BABASHKA_VERSION) + jar=target/babashka-$VERSION-standalone.jar + cp $jar /tmp/release + java -jar $jar script/reflection.clj + reflection="babashka-$VERSION-reflection.json" + java -jar "$jar" --config .build/bb.edn --deps-root . release-artifact "$jar" + java -jar "$jar" --config .build/bb.edn --deps-root . release-artifact "$reflection" - name: Babashka version id: babashka-version @@ -87,50 +82,76 @@ jobs: - uses: actions/upload-artifact@v1 with: - name: jar + name: babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar path: target/babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar - linux: + native: if: "!contains(github.event.head_commit.message, 'skip ci')" - needs: [jvm] - runs-on: ubuntu-18.04 + strategy: + matrix: + include: + - os: macos-12 + name: macos + static: false + #- os: ubuntu-latest + # name: linux + # static: false + #- os: ubuntu-latest + # name: linux + # static: true + runs-on: ${{ matrix.os }} + env: + LEIN_ROOT: "true" + GRAALVM_VERSION: "22.2.0" + BABASHKA_PLATFORM: ${{ matrix.name }} # used in release script + BABASHKA_TEST_ENV: native + BABASHKA_XMX: "-J-Xmx6500m" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Git checkout - uses: actions/checkout@v1 + uses: actions/checkout@v2 with: fetch-depth: 1 submodules: 'true' - - uses: actions/download-artifact@v1 - with: - name: jar - path: . - - name: Cache deps - uses: actions/cache@v1 + uses: actions/cache@v2 id: cache-deps with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('project.clj') }} - restore-keys: | - ${{ runner.os }}-maven- + restore-keys: ${{ runner.os }}-maven- - - name: Cache GraalVM - uses: actions/cache@v1 - id: cache-graalvm + - name: Setup GraalVM + if: "matrix.static == false" + uses: graalvm/setup-graalvm@v1 with: - path: ~/graalvm-ce-java11-22.0.0.2 - key: ${{ runner.os }}-graalvm-22.0.0.2 - restore-keys: | - ${{ runner.os }}-graalvm-22.0.0.2 + version: '22.2.0' + java-version: '11' + components: 'native-image' + github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Download GraalVM + - name: Setup GraalVM+musl + if: "matrix.static == true" + uses: graalvm/setup-graalvm@v1 + with: + version: '22.2.0' + java-version: '11' + components: 'native-image' + native-image-musl: true + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install clojure tools + uses: DeLaGuardo/setup-clojure@5.0 + with: + cli: 1.10.3.1040 + lein: 2.9.8 + + - name: Install native dev tools + if: matrix.os == 'ubuntu-latest' run: | - cd ~ - if ! [ -d graalvm-ce-java11-22.0.0.2 ]; then - curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz - tar xzf graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz - fi + sudo apt-get update + sudo apt-get -y install build-essential zlib1g-dev - name: Babashka version id: babashka-version @@ -138,209 +159,50 @@ jobs: BABASHKA_VERSION=$(cat resources/BABASHKA_VERSION) echo "##[set-output name=version;]${BABASHKA_VERSION}" - - name: Build Linux native image - run: | - export BABASHKA_JAR=babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar - export BABASHKA_XMX="-J-Xmx6g" - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2" - script/compile + - name: Build uberjar + run: script/uberjar - - name: Test binary - run: | - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2" - BABASHKA_TEST_ENV=native script/test + - name: Build native image + if: "matrix.static == false" + run: script/compile - - name: Install clojure - run: | - sudo script/install-clojure /usr/local - - - name: Test libraries - run: | - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2" - BABASHKA_TEST_ENV=native script/run_lib_tests - - - name: Upload artifact - uses: actions/upload-artifact@v2 - with: - path: bb - name: babashka-${{ steps.babashka-version.outputs.version }}-linux-amd64.zip - - linux-static: - if: "!contains(github.event.head_commit.message, 'skip ci')" - needs: [jvm] - runs-on: ubuntu-16.04 - steps: - - name: Git checkout - uses: actions/checkout@v1 - with: - fetch-depth: 1 - submodules: 'true' - - - uses: actions/download-artifact@v1 - with: - name: jar - path: . - - - name: Cache deps - uses: actions/cache@v1 - id: cache-deps - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('project.clj') }} - restore-keys: | - ${{ runner.os }}-maven- - - - name: Cache GraalVM - uses: actions/cache@v1 - id: cache-graalvm - with: - path: ~/graalvm-ce-java11-22.0.0.2 - key: ${{ runner.os }}-graalvm-22.0.0.2 - restore-keys: | - ${{ runner.os }}-graalvm-22.0.0.2 - - - name: Download GraalVM - run: | - cd ~ - if ! [ -d graalvm-ce-java11-22.0.0.2 ]; then - curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz - tar xzf graalvm-ce-java11-linux-amd64-22.0.0.2.tar.gz - fi - - - name: Babashka version - id: babashka-version - run: | - BABASHKA_VERSION=$(cat resources/BABASHKA_VERSION) - echo "##[set-output name=version;]${BABASHKA_VERSION}" - - - name: Build Linux native image - run: | - export BABASHKA_JAR=babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar - export BABASHKA_XMX="-J-Xmx6g" - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2" - export BABASHKA_STATIC=true - script/compile - - - name: Test binary - run: | - ./bb '(+ 1 2 3)' - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2" - BABASHKA_TEST_ENV=native script/test - - - name: Install clojure - run: | - sudo script/install-clojure - - - name: Test libraries - run: | - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2" - BABASHKA_TEST_ENV=native script/run_lib_tests - - - name: Upload artifact - uses: actions/upload-artifact@v2 - with: - path: bb - name: babashka-${{ steps.babashka-version.outputs.version }}-linux-static-amd64.zip - - mac: - if: "!contains(github.event.head_commit.message, 'skip ci')" - needs: [jvm] - runs-on: macos-latest - steps: - - name: Git checkout - uses: actions/checkout@v1 - with: - fetch-depth: 1 - submodules: 'true' - - - uses: actions/download-artifact@v1 - with: - name: jar - path: . - - - name: Cache GraalVM - uses: actions/cache@v1 - id: cache-graalvm - with: - path: ~/graalvm-ce-java11-22.0.0.2 - key: ${{ runner.os }}-graalvm-22.0.0.2 - restore-keys: | - ${{ runner.os }}-graalvm-22.0.0.2 - - - name: Download GraalVM - run: | - cd ~ - if ! [ -d graalvm-ce-java11-22.0.0.2 ]; then - curl -O -sL https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-darwin-amd64-22.0.0.2.tar.gz - tar xzf graalvm-ce-java11-darwin-amd64-22.0.0.2.tar.gz - fi - - - name: Babashka version - id: babashka-version - run: | - BABASHKA_VERSION=$(cat resources/BABASHKA_VERSION) - echo "##[set-output name=version;]${BABASHKA_VERSION}" - - - name: Build macOS native image - run: | - export BABASHKA_JAR=babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar - export BABASHKA_XMX="-J-Xmx6g" - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2/Contents/Home" - script/compile - - - name: Test binary - run: | - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2/Contents/Home" - sudo script/install-leiningen - BABASHKA_TEST_ENV=native script/test - - - name: Test libraries - run: | - export GRAALVM_HOME="$HOME/graalvm-ce-java11-22.0.0.2/Contents/Home" - sudo script/install-clojure - BABASHKA_TEST_ENV=native script/run_lib_tests - - - uses: actions/upload-artifact@v1 - with: - path: bb - name: babashka-${{ steps.babashka-version.outputs.version }}-macos-amd64.zip - - deploy: - if: "!contains(github.event.head_commit.message, 'skip ci') && github.event_name == 'push' && github.ref == 'refs/heads/master'" - needs: [jvm, linux, linux-static, mac] - runs-on: ubuntu-18.04 - steps: - - name: Git checkout - uses: actions/checkout@v1 - with: - fetch-depth: 1 - submodules: 'true' - - - name: Cache deps - uses: actions/cache@v1 - id: cache-deps - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('project.clj') }} - restore-keys: | - ${{ runner.os }}-maven- - - - name: Deploy + - name: Build static native image + if: "matrix.static == true" env: - CLOJARS_USER: "${{ secrets.CLOJARS_USER }}" - CLOJARS_PASS: "${{ secrets.CLOJARS_PASS }}" + BABASHKA_STATIC: "true" + BABASHKA_MUSL: "true" + run: script/compile + + - name: Test binary and libs run: | - .github/script/deploy + script/test + script/run_lib_tests + + - name: Release + run: .circleci/script/release + + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + path: bb + name: babashka-${{ steps.babashka-version.outputs.version }}-${{ matrix.name }}-amd64 + + - name: Upload static artifact + if: "matrix.static == true" + uses: actions/upload-artifact@v2 + with: + path: bb + name: babashka-${{ steps.babashka-version.outputs.version }}-${{ matrix.name }}-static-amd64 docker: - if: "!contains(github.event.head_commit.message, 'skip ci') && github.event_name == 'push' && github.ref == 'refs/heads/master'" + if: ${{ false }} # Disabled + # if: "!contains(github.event.head_commit.message, 'skip ci') && github.event_name == 'push' && github.ref == 'refs/heads/master'" needs: - - linux - - linux-static - runs-on: ubuntu-18.04 + - native + runs-on: ubuntu-latest steps: - name: Git checkout - uses: actions/checkout@v1 + uses: actions/checkout@v2 with: fetch-depth: 1 submodules: 'true' @@ -366,9 +228,16 @@ jobs: name: babashka-${{ steps.babashka-version.outputs.version }}-linux-static-amd64.zip path: /tmp/release-static + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + + - name: Build uberjar + run: script/uberjar + - name: Docker build env: DOCKERHUB_USER: "${{ secrets.DOCKERHUB_USER }}" DOCKERHUB_PASS: "${{ secrets.DOCKERHUB_PASS }}" - run: | - .github/script/docker + PLATFORMS: linux/amd64,linux/arm64 + run: java -jar ./target/babashka-$(cat resources/BABASHKA_VERSION)-standalone.jar .circleci/script/docker.clj diff --git a/.gitignore b/.gitignore index fb29f608..284c61e2 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ org_babashka*.h .envrc .lsp bb.build_artifacts.txt +target +.nrepl-port +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index 16f03588..5b6d8c11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,142 @@ For a list of breaking changes, check [here](#breaking-changes). A preview of the next release can be installed from [babashka-dev-builds](https://github.com/babashka/babashka-dev-builds). -## 0.8.0 (TBD) +## Unreleased + +- Add single argument read method support to PipedInputStream proxy ([@retrogradeorbit](https://github.com/retrogradeorbit)) + +## 0.10.163 (2022-09-24) + +- [#808](https://github.com/babashka/babashka/issues/808): support `-Sdeps` option to support passing extra deps map which will be merged last +- [#1336](https://github.com/babashka/babashka/issues/1336): tasks subcommand doesn't work with global `-Sforce` option ([@bobisageek](https://github.com/bobisageek)) +- [#1340](https://github.com/babashka/babashka/issues/1340): `defprotocol` methods are missing `:doc` metadata ([@bobisageek](https://github.com/bobisageek)) +- [#1368](https://github.com/babashka/babashka/issues/1368): `-x`: do not pick up on aliases in `user` ns +- [#1367](https://github.com/babashka/babashka/issues/1367): Fix line number in clojure.test output ([@retrogradeorbit](https://github.com/retrogradeorbit)) +- [#1370](https://github.com/babashka/babashka/issues/1370): Add `core.async` `to-chan!`, `to-chan!!`, `onto-chan!` ([@cap10morgan](https://github.com/cap10morgan)) +- [#1358](https://github.com/babashka/babashka/issues/1358): Expose a subset of `java.lang.ref` to enable hooking into the destruction/GC of objects ([@retrogradeorbit](https://github.com/retrogradeorbit)) +- [#1364](https://github.com/babashka/babashka/issues/1364): Be tolerant of unknown tags in `bb.edn` +- Add and expose `babashka.classes/all-classes` to get a list of all available classes (as `java.lang.Class` objects) ([@eerohele](https://github.com/eerohele)) +- Add more reflection class methods ([@eerohele](https://github.com/eerohele)) +- Bump `clj-yaml` +- Add `-x` help +- Set `TCP_NODELAY` in pods for performance +- Expose `clojure.main/with-bindings` +- Add `ThreadPoolExecutor` rejection policy classes ([@eerohele](https://github.com/eerohele)) +- Download but don't run pods when `os.name` / `os.arch` don't match ([@cap10morgan](https://github.com/cap10morgan)) +- Add `clojure.core.server/stop-server` ([@eerohele](https://github.com/eerohele)) +- Add `ns-unalias` +- Add `AtomicInteger` and `AtomicLong` to full interop +- Add `PrintWriter-on` +- Improve `reify` error messages ([@retrogradeorbit](https://github.com/retrogradeorbit)) +- Expose `core.async` `ManyToManyChannel` +- fs: add `write-lines` +- fs: add `write-bytes` +- [#1350](https://github.com/babashka/babashka/issues/1350): map `clojure.lang.Var` to `sci.lang.Var` +- Use temporary fork of `clj-yaml` with new `:load-all`, `:unknown-tag-fn` + options and preserves strings with numbers that start with zeros as strings + (this solves a problem when YAML 1.1 output is read as YAML 1.2.). Once + upstream SnakeYAML 1.33 lands, this will be used again. + +## 0.9.162 (2022-09-04) + +Check out our new project: [bbin](https://github.com/babashka/bbin): install any Babashka script or project with one command. Thanks [@rads](https://github.com/rads)! + +- Throw exception on attempt to reify multiple interfaces ([@retrogradeorbit](https://github.com/retrogradeorbit)) +- Allow java.lang.Object reify with empty methods ([@retrogradeorbit](https://github.com/retrogradeorbit)) +- [#1343](https://github.com/babashka/babashka/issues/1343): Fix postgres feature +- [#1345](https://github.com/babashka/babashka/issues/1345): add `javax.net.ssl.SSLException` and `java.net.SocketTimeoutException` classes ([@lread](https://github.com/lread)) +- Fix `satisfies?` with marker protocol (no methods) +- Update `rewrite-clj` +- Update `deps.clj` +- Update `babashka.cli` +- Update `org.clj-commons/clj-yaml` +- `babashka.fs`: fix `expand-home` on Windows +- `babashka.fs`: expose `:win-exts` +- nREPL: preserve stacktrace on exception +- Fix [#1322](https://github.com/babashka/babashka/issues/1322): improve error location +- Fix [#1338](https://github.com/babashka/babashka/issues/1338): `add-watch` segfault +- Fix [#1339](https://github.com/babashka/babashka/issues/1339): resolve record name ending with dot. + +## 0.9.161 (2022-07-31) + +- Fix `exec` + +## 0.9.160 (2022-07-29) + +- Breaking: change `exec`, introduced in `0.9.159` to a function instead. + You now write `(exec 'mynamespace.function)` instead. + +## 0.9.159 (2022-07-29) + +Read the introductory blog post about the new babashka CLI integration [here](https://blog.michielborkent.nl/babashka-tasks-meets-babashka-cli.html). + +- [#1324](https://github.com/babashka/babashka/issues/1324): `-x` to invoke a function with babashka CLI +- [#1324](https://github.com/babashka/babashka/issues/1324): `babashka.tasks/exec` to invoke a function with babashka CLI in tasks +- SCI: don't eval metatada on defn body +- SCI issue 774: make interpreter stacktrace available to user +- `babashka.process`: improve `tokenize` +- Upgrade to GraalVM 22.2.0 (#1325) + +## 0.8.157 (2022-07-01) + +- Add compatibility with [`metosin/malli`](https://github.com/metosin/malli#babashka) `{:mvn/version "0.8.9"}`. +- Expose `babashka.nrepl.server/start-server!`- and `stop-server!`-functions to support programmatically starting + an nrepl-server. `start-server!` is redefined to not require a sci-context as its first argument. +- Fix misspelling in script/uberjar: `BABASHKA_FEATURE_TRANSIT` + +## 0.8.156 (2022-06-08) + +- macOS aarch64 support. Upgrading via brew or the installer script should + install the aarch64 version on an M1 system. +- Support for running [prismatic/schema](https://github.com/plumatic/schema) + from source. There is an open PR for babashka. Until it is merged you can use + [this](https://github.com/borkdude/schema/tree/bb-test-suite) fork. +- SCI: many small improvements, especially in `defrecord` (discovered while + trying to make `schema.core` work) +- Switch version schema to major.minor.release_count. +- babashka.nrepl: fix completions for static Java interop +- `fs/read-all-lines`, support charset +- fs: `strip` and `split-ext` are less reliant on file system and are now just + string operations +- Bump cheshire +- Add `babashka.process/exec` for exec call (replacing the current process) +- Improve `babashka.process/tokenize` +- [#1264](https://github.com/babashka/babashka/issues/1264): add support for calling `ScheduledExecutorService` +- Add support for `sun.misc.SignalHandler` +- Add `java.net.BindException`, `clojure.lang.AFunction`, `AbstractMethodError` +- Upgrade httpkit to `2.6.0-RC1` +- Add `process/shell`, similar to `babashka.tasks/shell` but in process ns +- pods: fix benign socket closed exception error output + +## 0.8.2 (2022-05-06) + +- Convey `*print-length*` to pprint and allow `set!` +- `babashka.nrepl`: support pprint length +- SCI: support invoking field, without dash +- Add compatibility with clojure numeric tower +- Update deps.clj to tools jar `1.11.1.1113` +- Compatibility with fipp and puget +- Fix [#1233](https://github.com/babashka/babashka/issues/1233): don't print error to stdout in prepl +- Update process with `:pre-start-fn` option +- Update fs with `cwd` and Windows glob improvements +- Expose edamame, fixes [#549](https://github.com/babashka/babashka/issues/549) and [#1258](https://github.com/babashka/babashka/issues/1258) (#1259) +- Support `BABASBHKA_PODS_DIR` environment variable + +## 0.8.1 (2022-04-15) + +- Add `prepare` subcommand to download deps & pods and cache pod metadata +- [#1041](https://github.com/babashka/babashka/issues/1041): Improve error message when regex literal in EDN config +- [#1223](https://github.com/babashka/babashka/issues/1223): Ensure that var metadata (specifically `:name`) aligns with the var's symbol (which in turn ensures that `doc` will print the var's name) +- [#556](https://github.com/babashka/babashka/issues/556) Add server-status to org.httpkit.server +- [#1231](https://github.com/babashka/babashka/issues/1231): missing methods in `reify` should fall back to default interface methods +- Fix destructuring in defrecord protocol impls +- Support `*print-dup*` + +## 0.8.0 (2022-04-04) ### New -- [#863](https://github.com/babashka/babashka/issues/863): allow pods to be declared in `bb.edn` and load them when required - - See [updated pod library docs for details](TODO: link) +- [#863](https://github.com/babashka/babashka/issues/863): allow pods to be declared in `bb.edn` and load them when required. See [pod library docs](https://github.com/babashka/pods#in-a-babashka-project) and the entry in the [babashka book](https://book.babashka.org/#_pods_in_bb_edn) for details. ### Enhanced @@ -19,7 +149,7 @@ A preview of the next release can be installed from - [#1211](https://github.com/babashka/babashka/issues/1211): return exit code 130 on sigint - [#1224](https://github.com/babashka/babashka/issues/1224): add `proxy` support for `java.io.PipedInputStream` and `java.io.PipedOutputStream`. Add reflection for `java.utils.Scanner`. - [babashka.curl#43](https://github.com/babashka/babashka.curl/issues/43) fix: last set-cookie headers on a page overwrites the ones before -- #1216: fix `core.async` alts example with polyfill +- [#1216](https://github.com/babashka/babashka/issues/1216): fix `core.async` alts example with polyfill - SCI: support `let*` special form - Add compatibility with GraalVM 22.1 - Bump timbre @@ -30,6 +160,8 @@ A preview of the next release can be installed from - Proxy support for PipedInputStream and PipedOutputStream - Expose `java.util.Scanner` for interop - Bump Selmer +- Add `->Eduction` +- Add `*unchecked-math` for compatibility ## 0.7.8 (2022-03-13) diff --git a/Dockerfile b/Dockerfile index 8ffb784f..13ee10fa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ RUN apt update RUN apt install --no-install-recommends -yy build-essential zlib1g-dev WORKDIR "/opt" -ENV GRAALVM_VERSION="22.0.0.2" +ENV GRAALVM_VERSION="22.2.0" ARG TARGETARCH ENV BABASHKA_ARCH=${TARGETARCH} ENV GRAALVM_ARCH=${TARGETARCH} @@ -34,7 +34,7 @@ ARG BABASHKA_FEATURE_CSV= ARG BABASHKA_FEATURE_JAVA_NET_HTTP= ARG BABASHKA_FEATURE_JAVA_NIO= ARG BABASHKA_FEATURE_JAVA_TIME= -ARG BABAHSKA_FEATURE_TRANSIT= +ARG BABASHKA_FEATURE_TRANSIT= ARG BABASHKA_FEATURE_XML= ARG BABASHKA_FEATURE_YAML= ARG BABASHKA_FEATURE_HTTPKIT_CLIENT= @@ -51,7 +51,7 @@ ENV BABASHKA_FEATURE_CSV=$BABASHKA_FEATURE_CSV ENV BABASHKA_FEATURE_JAVA_NET_HTTP=$BABASHKA_FEATURE_JAVA_NET_HTTP ENV BABASHKA_FEATURE_JAVA_NIO=$BABASHKA_FEATURE_JAVA_NIO ENV BABASHKA_FEATURE_JAVA_TIME=$BABASHKA_FEATURE_JAVA_TIME -ENV BABAHSKA_FEATURE_TRANSIT=$BABAHSKA_FEATURE_TRANSIT +ENV BABASHKA_FEATURE_TRANSIT=$BABASHKA_FEATURE_TRANSIT ENV BABASHKA_FEATURE_XML=$BABASHKA_FEATURE_XML ENV BABASHKA_FEATURE_YAML=$BABASHKA_FEATURE_YAML ENV BABASHKA_FEATURE_HTTPKIT_CLIENT=$BABASHKA_FEATURE_HTTPKIT_CLIENT diff --git a/README.md b/README.md index 083863c7..a1e17bef 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - +[Babashka](https://babashka.org) [![CircleCI](https://circleci.com/gh/babashka/babashka/tree/master.svg?style=shield)](https://circleci.com/gh/babashka/babashka/tree/master) [![project chat](https://img.shields.io/badge/slack-join_chat-brightgreen.svg)](https://app.slack.com/client/T03RZGPFR/CLX41ASCS) @@ -153,15 +153,33 @@ Install: brew install borkdude/brew/babashka -On macOS with an M1 processor: + - softwareupdate --install-rosetta - arch -x86_64 brew install borkdude/brew/babashka + + Upgrade: brew upgrade babashka +### Nix + +Linux and macOS (including ARM Macs) binaries are provided via nix (see the installation instructions for nix [here](https://nixos.org/download.html)). + +Install: + + # Adding `nixpkgs-unstable` channel for more up-to-date binaries, skip this if you already have `nixpkgs-unstable` in your channel list + nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs-unstable + nix-channel --update + nix-env -iA nixpkgs-unstable.babashka + +Upgrade: + + nix-channel --update + nix-env -iA nixpkgs-unstable.babashka + +You can find more documentation on how to use babashka with nix [here](./doc/nix.md). + ### Arch (Linux) `babashka` is [available](https://aur.archlinux.org/packages/babashka-bin/) in the [Arch User Repository](https://aur.archlinux.org). It can be installed using your favorite [AUR](https://aur.archlinux.org) helper such as @@ -180,6 +198,8 @@ Babashka can be installed using a plugin as follows: ### Windows +#### Scoop + On Windows you can install using [scoop](https://scoop.sh/) and the [scoop-clojure](https://github.com/littleli/scoop-clojure) bucket. @@ -194,6 +214,12 @@ scoop bucket add extras scoop install babashka ``` +#### Manual + +If scoop does not work for you, then you can also just download the `bb.exe` +binary from [Github releases](https://github.com/babashka/babashka/releases) and +place it on your path manually. + ### Installer script Install via the installer script: @@ -260,13 +286,68 @@ Check out the [news](doc/news.md) page to keep track of babashka-related news it Go [here](https://book.babashka.org/#built-in-namespaces) to see the full list of built-in namespaces. -## [Projects](doc/projects.md) +## [Compatible Projects](doc/projects.md) A list of projects (scripts, libraries, pods and tools) known to work with babashka. -Have a library that is already compatible or has recently been made compatible? Add the official badge to add some flair to your repo! +## Badges + -[![bb compatible](https://img.shields.io/badge/babashka-compatible-green?logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNDcyIDE0NzIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOTk1LjkxMSAxMTkzLjg5QzExMTAuOTMgMTExMi4zOCAxMTg2IDk3OC4yMDYgMTE4NiA4MjYuNUMxMTg2IDU3Ny45NzIgMTAxNCAyNTQuNSA3MzYgMTEzQzQ2MC41IDI2MiAyODYgNTc3Ljk3MiAyODYgODI2LjVDMjg2IDk3OC4yMDYgMzYxLjA3IDExMTIuMzggNDc2LjA4OSAxMTkzLjg5QzQ3MS45ODMgMTE5NC40NCA0NjcuOTQ5IDExOTUuMTQgNDY0IDExOTZDMzc2LjYxMSAxMjE1LjA3IDI3MCAxMzU5LjA1IDI3MCAxMzU5LjA1SDUzNEM1ODAuOTcyIDEzNTkuMDUgNjI1LjYzMSAxMzQxLjQxIDY2MC45NTYgMTMyMS42MkM2NzguMTE1IDEzNDQuMzIgNzA1LjM0NCAxMzU5IDczNiAxMzU5Qzc2Ni42NTYgMTM1OSA3OTMuODg1IDEzNDQuMzIgODExLjA0NCAxMzIxLjYyQzg0Ni4zNjkgMTM0MS40MSA4OTEuMDI4IDEzNTkuMDUgOTM4IDEzNTkuMDVIMTIwMkMxMjAyIDEzNTkuMDUgMTA5NS4zOSAxMjE1LjA3IDEwMDggMTE5NkMxMDA0LjA1IDExOTUuMTQgMTAwMC4wMiAxMTk0LjQ0IDk5NS45MTEgMTE5My44OVoiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcikiLz4KPGNpcmNsZSBjeD0iNzM1LjUiIGN5PSI4NTIuNSIgcj0iMzExLjUiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik00NDMgNzUwLjQxN0M2NjIgNzY1Ljg2NiA3OTEuMzgyIDcxMi4zODggODgxIDU3OS44ODFDODgxIDU3OS44ODEgNzA4LjI5MyA1MjEuNjQ5IDYwMy4yNDQgNTc5Ljg4MUM0OTguNTUgNjM3LjkxNiA0NDMgNzUwLjQxNyA0NDMgNzUwLjQxN1oiIGZpbGw9IiNCNEI0QjQiLz4KPHBhdGggZD0iTTEwMzkuOTkgNzQ4LjI4MkM5MTQuODYyIDczNC43NDUgODAzLjI2NCA2OTQuMTM1IDc1MCA1NDFDNzUwIDU0MSA4NjAuNjMzIDU2Ni4yNzIgOTcyLjM1NSA2NjguMTAxQzEwODguMzkgNzczLjg1NyAxMDM5Ljk5IDc0OC4yODIgMTAzOS45OSA3NDguMjgyWiIgZmlsbD0iI0I0QjRCNCIvPgo8Y2lyY2xlIGN4PSI3MzUuNSIgY3k9Ijg1Mi41IiByPSIzMTEuNSIgc3Ryb2tlPSIjMEEwMDAwIiBzdHJva2Utd2lkdGg9IjQwIi8+CjxwYXRoIGQ9Ik03OTcgNzE5SDY3NEw3MDQgNzQ5VjgzOUM3MDguNSA4MDkuNSA3NjQuNSA4MDguNSA3NjcuNSA4MzlMNzc1IDc0OUw3OTcgNzE5WiIgZmlsbD0iYmxhY2siLz4KPHBhdGggZD0iTTM1MS4xMTcgNzU5QzM1MS4xMTcgNzM2LjkwOSAzNjkuMDI2IDcxOSAzOTEuMTE3IDcxOUg2NzYuMDE4QzcwMC4yIDcxOSA3MTguODUyIDc0MC4yOTIgNzE1LjY3IDc2NC4yNjRMNjkwLjkxIDk1MC43NjRDNjg4LjI3IDk3MC42NDYgNjcxLjMxNCA5ODUuNSA2NTEuMjU4IDk4NS41SDM5MS4xMTdDMzY5LjAyNiA5ODUuNSAzNTEuMTE3IDk2Ny41OTEgMzUxLjExNyA5NDUuNVY3NTlaIiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNNzU2LjAxMiA3NjQuMjY3Qzc1Mi44MjggNzQwLjI5NCA3NzEuNDgxIDcxOSA3OTUuNjY0IDcxOUgxMDgwQzExMDIuMDkgNzE5IDExMjAgNzM2LjkwOSAxMTIwIDc1OVY5NDUuMDk2QzExMjAgOTY3LjE4NyAxMTAyLjA5IDk4NS4wOTYgMTA4MCA5ODUuMDk2SDgyMC4zODFDODAwLjMyNSA5ODUuMDk2IDc4My4zNyA5NzAuMjQ0IDc4MC43MjkgOTUwLjM2Mkw3NTYuMDEyIDc2NC4yNjdaIiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNMTAyNCA5NTJWOTIxLjQ3SDEwMTMuNzFDMTAwNy4wMyA5MjEuNDcgMTAwMi41OCA5MTYuNzUyIDEwMDAuMzUgOTA5LjgxM0w5NTguMDY0IDc4Mi42OTdDOTU1LjI4MiA3NzQuNjQ5IDk1MS45NDQgNzY4LjgyIDk0Ny40OTIgNzY0LjM3OUM5MzkuMTQ2IDc1NS43NzUgOTI4LjI5NiA3NTMgOTE2LjA1NCA3NTNIOTAyLjdWNzg0LjkxOEg5MTEuNjAzQzkxOS4xMTUgNzg0LjkxOCA5MjQuOTU3IDc4Ny42OTMgOTI3LjQ2MSA3OTYuNTc1TDkzMy4zMDMgODE3LjExM0w4ODEgOTUySDkxOS4xMTVMOTUwLjU1MyA4NjMuMTg1TDk2Ny4yNDUgOTE2Ljc1MkM5NzMuNjQ0IDkzNy41NjggOTg0LjQ5NCA5NTIgMTAwOC45OCA5NTJIMTAyNFoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik01OTAgOTUyVjkyMS40N0g1NzkuNzA2QzU3My4wMjkgOTIxLjQ3IDU2OC41NzggOTE2Ljc1MiA1NjYuMzUyIDkwOS44MTNMNTI0LjA2NCA3ODIuNjk3QzUyMS4yODIgNzc0LjY0OSA1MTcuOTQ0IDc2OC44MiA1MTMuNDkyIDc2NC4zNzlDNTA1LjE0NiA3NTUuNzc1IDQ5NC4yOTYgNzUzIDQ4Mi4wNTQgNzUzSDQ2OC43Vjc4NC45MThINDc3LjYwM0M0ODUuMTE1IDc4NC45MTggNDkwLjk1NyA3ODcuNjkzIDQ5My40NjEgNzk2LjU3NUw0OTkuMzAzIDgxNy4xMTNMNDQ3IDk1Mkg0ODUuMTE1TDUxNi41NTMgODYzLjE4NUw1MzMuMjQ1IDkxNi43NTJDNTM5LjY0NCA5MzcuNTY4IDU1MC40OTQgOTUyIDU3NC45NzcgOTUySDU5MFoiIGZpbGw9IndoaXRlIi8+CjxkZWZzPgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXIiIHgxPSI3NTIiIHkxPSIxMTMiIHgyPSI3NTIiIHkyPSIxMzU5LjUyIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiNFNDFGMjYiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjQjcwMDAwIi8+CjwvbGluZWFyR3JhZGllbnQ+CjwvZGVmcz4KPC9zdmc+Cg==)](https://babashka.org) +[![bb compatible](/logo/badge.svg)](https://babashka.org) + +The babashka compatible badge indicates that a [library can be used as babashka dependency](doc/projects.md). + +If this is the case for your library, we encourage you to proudly display this badge. + +
Markdown + +```markdown +[![bb compatible](https://raw.githubusercontent.com/babashka/babashka/master/logo/badge.svg)](https://babashka.org) +``` +
+ +
AsciiDoc + +```asciidoc +https://babashka.org[image:https://raw.githubusercontent.com/babashka/babashka/master/logo/badge.svg[bb compatible]] +``` +
+ +
HTML + +```html +bb compatible +``` +
+
+ +[![bb built-in](/logo/built-in-badge.svg)](https://babashka.org) + +The babashka built-in badge means that a [library has been built directly into babashka](https://book.babashka.org/#built-in-namespaces) and requires no extra dependencies to use it. + +If this rare honor belongs to your library, you should display this badge. + +
Markdown + +```markdown +[![bb built-in](https://raw.githubusercontent.com/babashka/babashka/master/logo/built-in-badge.svg)](https://babashka.org) +``` +
+ +
AsciiDoc + +```asciidoc +https://babashka.org[image:https://raw.githubusercontent.com/babashka/babashka/master/logo/built-in-badge.svg[bb built-in]] +``` +
+ +
HTML + +```html +bb built-in +``` +
+
## [Pods](https://github.com/babashka/babashka.pods) @@ -316,7 +397,18 @@ handling of SIGINT and SIGPIPE. This can be done by setting ## Articles, podcasts and videos +- [Deleting AWS Glacier vaults with babashka](https://javahippie.net/clojure/2022/07/23/deleting-aws-glacier-vaults-with-babashka.html) by Tim Zöller +- [Recursive document transformations with Pandoc and Clojure](https://play.teod.eu/document-transform-pandoc-clojure/) by Teodor Heggelund +- [Blambda!](https://jmglov.net/blog/2022-07-03-blambda.html) by Josh Glover +- [Babashka CLI](https://blog.michielborkent.nl/babashka-cli.html): turn Clojure functions into CLIs! +- [Breakneck Babashka on K8s](Breakneck Babashka on K8s) by Heow Goodman +- [Recursive document transformations with Pandoc and Clojure](https://play.teod.eu/document-transform-pandoc-clojure/) +- [Detecting inconsistent aliases in a clojure codebase](https://www.youtube.com/watch?v=bf8KLKkCH2g) by Oxalorg +- [I, too, Wrote Myself a Static Site Generator](https://dawranliou.com/blog/i-too-wrote-myself-a-static-site-generator/) by Daw-Ran Liou +- [Babashka and Clojure](https://youtu.be/ZvOs5Ele6VE) by Rahul Dé at North Virginia Linux Users Group - [Create a password manager with Clojure using Babashka, sqlite, honeysql and stash](https://youtu.be/jm0RXmyjRJ8) by Daniel Amber +- [Writing Clojure-living-cookbooks](https://www.loop-code-recur.io/live-clojure-cookbooks) by Cyprien Pannier +- [Using babashka with PHP](https://blog.michielborkent.nl/using-babashka-with-php.html) by Michiel Borkent - [Moldable Emacs: a Clojure Playground with Babashka](https://ag91.github.io/blog/2021/11/05/moldable-emacs-a-clojure-playground-with-babashka/) by Andrea - [Finding my inner Wes Anderson with #Babashka](https://javahippie.net/clojure/2021/10/18/finding-my-inner-wes-anderson.html) by Tim Zöller - [Awesome Babashka: Parse & produce HTML and SQLite](https://blog.jakubholy.net/2021/awesome-babashka-dash/) by Jakub Holý @@ -365,7 +457,7 @@ binary, these evaluation criteria are considered: - The library cannot be interpreted by with babashka using `--classpath`. - The functionality can't be met by shelling out to another CLI or can't be written as a small layer over an existing CLI (like `babashka.curl`) instead. -- The library cannot be implemented a +- The library cannot be implemented as a [pod](https://github.com/babashka/babashka.pods). If not all of the criteria are met, but adding a feature is still useful to a diff --git a/appveyor.yml b/appveyor.yml index b9e771c4..7ad68110 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,10 +7,15 @@ image: Visual Studio 2017 clone_folder: C:\projects\babashka environment: - GRAALVM_HOME: C:\projects\babashka\graalvm\graalvm-ce-java11-22.0.0.2 - JAVA_HOME: C:\projects\babashka\graalvm\graalvm-ce-java11-22.0.0.2 + GRAALVM_HOME: C:\projects\babashka\graalvm\graalvm-ce-java11-22.2.0 + JAVA_HOME: C:\projects\babashka\graalvm\graalvm-ce-java11-22.2.0 BABASHKA_XMX: "-J-Xmx5g" +skip_commits: + files: + - "logo/*" + - "**/*.md" + cache: - C:\ProgramData\chocolatey\lib -> project.clj, appveyor.yml - '%USERPROFILE%\.m2 -> project.clj' @@ -33,7 +38,7 @@ clone_script: build_script: - cmd: >- - powershell -Command "if (Test-Path('graalvm')) { return } else { (New-Object Net.WebClient).DownloadFile('https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.0.0.2/graalvm-ce-java11-windows-amd64-22.0.0.2.zip', 'graalvm.zip') }" + powershell -Command "if (Test-Path('graalvm')) { return } else { (New-Object Net.WebClient).DownloadFile('https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.2.0/graalvm-ce-java11-windows-amd64-22.2.0.zip', 'graalvm.zip') }" powershell -Command "if (Test-Path('graalvm')) { return } else { Expand-Archive graalvm.zip graalvm }" diff --git a/babashka.nrepl b/babashka.nrepl index d3fce671..c8c8a766 160000 --- a/babashka.nrepl +++ b/babashka.nrepl @@ -1 +1 @@ -Subproject commit d3fce67198b042707f01d841c032f841cc57ab7f +Subproject commit c8c8a766e026d5f87e0968a179dad70e13aa13ee diff --git a/deps.clj b/deps.clj index c948c2f5..d4d6d720 160000 --- a/deps.clj +++ b/deps.clj @@ -1 +1 @@ -Subproject commit c948c2f5c1e240c0e0ea4201877695f729ee309e +Subproject commit d4d6d720c0d62eb3e2230fa85291a5fd68398d6a diff --git a/deps.edn b/deps.edn index d4e67e14..7cb15a30 100644 --- a/deps.edn +++ b/deps.edn @@ -10,14 +10,18 @@ "feature-selmer" "feature-logging" "feature-priority-map" + "feature-rrb-vector" "feature-jdbc" "pods/src" "babashka.nrepl/src" "depstar/src" "process/src" "deps.clj/src" "deps.clj/resources" - "resources" "sci/resources"], - :deps {org.clojure/clojure {:mvn/version "1.11.0"}, - borkdude/sci {:local/root "sci"} + "resources" "sci/resources" + "reify/src"], + :deps {org.clojure/clojure {:mvn/version "1.11.1"}, + org.babashka/sci {:local/root "sci"} + org.babashka/babashka.impl.reify {:mvn/version "0.1.3"} + org.babashka/sci.impl.types {:mvn/version "0.0.2"} babashka/babashka.curl {:local/root "babashka.curl"} babashka/fs {:local/root "fs"} babashka/babashka.core {:local/root "babashka.core"} @@ -25,9 +29,9 @@ org.clojure/core.async {:mvn/version "1.5.648"}, org.clojure/tools.cli {:mvn/version "1.0.206"}, org.clojure/data.csv {:mvn/version "1.0.0"}, - cheshire/cheshire {:mvn/version "5.10.2"} - org.clojure/data.xml {:mvn/version "0.2.0-alpha6"} - clj-commons/clj-yaml {:mvn/version "0.7.108"} + cheshire/cheshire {:mvn/version "5.11.0"} + org.clojure/data.xml {:mvn/version "0.2.0-alpha8"} + clj-commons/clj-yaml {:mvn/version "0.7.169"} com.cognitect/transit-clj {:mvn/version "1.0.329"} org.clojure/test.check {:mvn/version "1.1.1"} nrepl/bencode {:mvn/version "1.1.0"} @@ -35,15 +39,18 @@ org.postgresql/postgresql {:mvn/version "42.2.18"} org.hsqldb/hsqldb {:mvn/version "2.5.1"} datascript/datascript {:mvn/version "1.0.1"} - http-kit/http-kit {:mvn/version "2.5.3"} + http-kit/http-kit {:mvn/version "2.6.0-RC1"} babashka/clojure-lanterna {:mvn/version "0.9.8-SNAPSHOT"} org.clojure/core.match {:mvn/version "1.0.0"} hiccup/hiccup {:mvn/version "2.0.0-alpha2"} - rewrite-clj/rewrite-clj {:mvn/version "1.0.699-alpha"} + rewrite-clj/rewrite-clj {:mvn/version "1.1.45"} selmer/selmer {:mvn/version "1.12.50"} com.taoensso/timbre {:mvn/version "5.2.1"} org.clojure/tools.logging {:mvn/version "1.1.0"} - org.clojure/data.priority-map {:mvn/version "1.1.0"}} + org.clojure/data.priority-map {:mvn/version "1.1.0"} + insn/insn {:mvn/version "0.5.2"} + org.clojure/core.rrb-vector {:mvn/version "0.1.2"} + org.babashka/cli {:mvn/version "0.4.37"}} :aliases {:babashka/dev {:main-opts ["-m" "babashka.main"]} :profile @@ -129,9 +136,25 @@ clojure-msgpack/clojure-msgpack {:mvn/version "1.2.1"} cli-matic/cli-matic {:git/url "https://github.com/l3nz/cli-matic.git", :git/sha "9cd53ba7336363e3d06650dbad413b6f8b06e471"} aysylu/loom {:mvn/version "1.0.2"} - com.layerware/hugsql-core {:mvn/version "0.5.1"} + com.layerware/hugsql-core {:mvn/version "0.5.3"} com.github.seancorfield/expectations {:mvn/version "2.0.157"} - com.rpl/specter {:mvn/version "1.1.4"}} + com.rpl/specter {:mvn/version "1.1.4"} + com.github.askonomm/clarktown {:mvn/version "1.1.2"} + org.clojure/math.numeric-tower {:git/tag "math.numeric-tower-0.0.5", :git/sha "12eb9c5", :git/url "https://github.com/clojure/math.numeric-tower"} + prismatic/schema {:git/url "https://github.com/plumatic/schema" + :git/sha "6846dc7c3a9df5bfd718f68f183c683ce0f621ff" + :git/tag "schema-1.3.0"} + metosin/malli {:git/url "https://github.com/metosin/malli" + :git/sha "588147ef49b2e41c7d12a8aa994b39c1c6fedd99" + :git/tag "0.8.9"} + meander/epsilon {:git/url "https://github.com/noprompt/meander" + :git/sha "55f5ce70e6ef717e95c58260f6bc725d70c0cb6d"} + cc.qbits/auspex {:git/url "https://github.com/mpenet/auspex" + :git/sha "1a9d7427e60e1a434a764aa820d1c53f7e22504a" + :deps/manifest :deps} + exoscale/interceptor {:git/url "https://github.com/exoscale/interceptor" + :git/sha "ca115fe00a0abf3a2f78452ab309c3aa4c00fc4e" + :deps/manifest :deps}} :classpath-overrides {org.clojure/clojure nil org.clojure/spec.alpha nil}} :clj-nvd @@ -147,3 +170,4 @@ :test-pod {:extra-paths ["test-resources"] :main-opts ["-m" "babashka.main" "test-resources/pod.clj"]}}} +;; release diff --git a/doc/build.md b/doc/build.md index 5571fa02..2b5fa2e1 100644 --- a/doc/build.md +++ b/doc/build.md @@ -3,24 +3,24 @@ ## Prerequisites - Install [lein](https://leiningen.org/) for producing uberjars -- Download [GraalVM](https://www.graalvm.org/downloads/). Currently we use *java11-22.0.0.2*. +- Download [GraalVM](https://www.graalvm.org/downloads/). Currently we use *java11-22.2.0*. - For Windows, installing Visual Studio 2019 with the "Desktop development with C++" workload is recommended. - Set `$GRAALVM_HOME` to the GraalVM distribution directory. On macOS this can look like: ``` shell - export GRAALVM_HOME=~/Downloads/graalvm-ce-java11-22.0.0.2/Contents/Home + export GRAALVM_HOME=~/Downloads/graalvm-ce-java11-22.2.0/Contents/Home ``` On linux: ``` shell - export GRAALVM_HOME=~/Downloads/graalvm-ce-java11-22.0.0.2 + export GRAALVM_HOME=~/Downloads/graalvm-ce-java11-22.2.0 ``` On Windows, from the [Visual Studio 2019 x64 Native Tools Command Prompt](https://github.com/oracle/graal/issues/2116#issuecomment-590470806) or `cmd.exe` (not Powershell): ``` - set GRAALVM_HOME=%USERPROFILE%\Downloads\graalvm-ce-java11-22.0.0.2 + set GRAALVM_HOME=%USERPROFILE%\Downloads\graalvm-ce-java11-22.2.0 ``` If you are not running from the x64 Native Tools Command Prompt, you will need to set additional environment variables using: ``` diff --git a/doc/companies.md b/doc/companies.md index ea76a3eb..b068313a 100644 --- a/doc/companies.md +++ b/doc/companies.md @@ -61,6 +61,7 @@ Sponsoring via [Cognitect](https://www.cognitect.com/). - [Datil](https://datil.com/) - [Deon Digital](https://www.deondigital.com/) - [Fluent](https://fluent.to/) +- [Fluree](https://flur.ee/) - [Hi](https://www.hi.group/) - [Juxt](https://www.juxt.pro/) - [Latacora](https://www.latacora.com/) diff --git a/doc/dev.md b/doc/dev.md index 7d4155f7..3f1ecd49 100644 --- a/doc/dev.md +++ b/doc/dev.md @@ -37,7 +37,7 @@ reasons: ## Requirements -You need [lein](https://leiningen.org/) for running JVM tests and/or producing uberjars. For building binaries you need GraalVM. Currently we use java11-22.0.0.2. +You need [lein](https://leiningen.org/) for running JVM tests and/or producing uberjars. For building binaries you need GraalVM. Currently we use java11-22.2.0. ## Clone repository diff --git a/doc/fly_io/Dockerfile b/doc/fly_io/Dockerfile new file mode 100644 index 00000000..8c9149ca --- /dev/null +++ b/doc/fly_io/Dockerfile @@ -0,0 +1,5 @@ +FROM babashka/babashka:0.8.2 + +COPY example.clj / + +ENTRYPOINT bb /example.clj diff --git a/doc/fly_io/README.md b/doc/fly_io/README.md new file mode 100644 index 00000000..f21090d5 --- /dev/null +++ b/doc/fly_io/README.md @@ -0,0 +1,19 @@ +# Deploying a babashka app to fly.io + +[Fly.io](https://fly.io/) is a service that can run full stack apps with minimal +configuration. If you like the ease of Heroku, you might like fly.io and perhaps +even better! This document shows how to get a minimal babashka application up +and running on `fly.io`. + +In `example.clj` we start an http-kit web server which spits out some HTML. You +can run this locally by invoking `bb example.clj` from the command line. + +To get this site running on `fly.io`, you need to +[install](https://fly.io/docs/getting-started/installing-flyctl/) and [log +in](https://fly.io/docs/getting-started/log-in-to-fly/). + +Then run `flyctl launch` to create a new application. After making changes, you +can re-deploy the site with `flyctl deploy`. + +That's it! See this +[tweet](https://twitter.com/borkdude/status/1526175120825401344) for a demo. diff --git a/doc/fly_io/example.clj b/doc/fly_io/example.clj new file mode 100644 index 00000000..2250fb95 --- /dev/null +++ b/doc/fly_io/example.clj @@ -0,0 +1,21 @@ +(ns example + (:require [hiccup2.core :refer [html]] + [org.httpkit.server :refer [run-server]])) + +(def port (or (some-> (System/getenv "PORT") + parse-long) + 8092)) + +(run-server + (fn [_] + {:body + (str (html + [:html + [:body + [:h1 "Hello world!"] + [:p (str "This site is running with babashka v" + (System/getProperty "babashka.version"))]]]))}) + {:port port}) + +(println "Site running on port" port) +@(promise) diff --git a/doc/fly_io/fly.toml b/doc/fly_io/fly.toml new file mode 100644 index 00000000..6ebbdeeb --- /dev/null +++ b/doc/fly_io/fly.toml @@ -0,0 +1,41 @@ +# fly.toml file generated for shy-sound-2847 on 2022-05-16T14:12:38+02:00 + +app = "shy-sound-2847" + +kill_signal = "SIGINT" +kill_timeout = 5 +processes = [] + +[env] + PORT = "8092" + +[experimental] + allowed_public_ports = [] + auto_rollback = true + +[[services]] + http_checks = [] + internal_port = 8092 + processes = ["app"] + protocol = "tcp" + script_checks = [] + + [services.concurrency] + hard_limit = 25 + soft_limit = 20 + type = "connections" + + [[services.ports]] + force_https = true + handlers = ["http"] + port = 80 + + [[services.ports]] + handlers = ["tls", "http"] + port = 443 + + [[services.tcp_checks]] + grace_period = "1s" + interval = "15s" + restart_limit = 0 + timeout = "2s" diff --git a/doc/libraries.csv b/doc/libraries.csv index c12c85e7..b6d89c55 100644 --- a/doc/libraries.csv +++ b/doc/libraries.csv @@ -17,6 +17,7 @@ clojure-csv/clojure-csv,https://github.com/davidsantiago/clojure-csv clojure-msgpack/clojure-msgpack,https://github.com/edma2/clojure-msgpack clojure-term-colors/clojure-term-colors,https://github.com/trhura/clojure-term-colors com.exoscale/lingo,https://github.com/exoscale/lingo +com.github.askonomm/clarktown,https://github.com/askonomm/clarktown com.github.seancorfield/expectations,https://github.com/clojure-expectations/clojure-test com.github.seancorfield/honeysql,https://github.com/seancorfield/honeysql com.grammarly/omniconf,https://github.com/grammarly/omniconf @@ -73,6 +74,7 @@ org.clojure/data.generators,https://github.com/clojure/data.generators org.clojure/data.json,https://github.com/clojure/data.json org.clojure/data.zip,https://github.com/clojure/data.zip org.clojure/math.combinatorics,https://github.com/clojure/math.combinatorics +org.clojure/math.numeric-tower,https://github.com/clojure/math.numeric-tower org.clojure/test.check,https://github.com/clojure/test.check org.clojure/tools.gitlibs,https://github.com/clojure/tools.gitlibs org.clojure/tools.namespace,https://github.com/babashka/tools.namespace diff --git a/doc/news.md b/doc/news.md index 8ba49892..f5eb263c 100644 --- a/doc/news.md +++ b/doc/news.md @@ -5,13 +5,88 @@ you have anything to add. Also see [#babashka](https://twitter.com/hashtag/babashka?src=hashtag_click&f=live) on Twitter. - +## [2022-02](https://twitter.com/search?q=(%23babashka)%20until%3A2022-03-01%20since%3A2022-02-01&src=typed_query&f=live) + +- Releases: [0.7.5 - 0.7.6](https://github.com/babashka/babashka/blob/master/CHANGELOG.md). +- [Spire is available as a babashka pod](https://twitter.com/epic_castle/status/1496784352256008194) +- Babashka Clojure template on [Repl.it](https://replit.com/@eccentric-j/Babashka-Clojure-Template?v=1#replit.nix) by Eccentric J +- Create a self-contained executable with [caxa](https://github.com/babashka/babashka/wiki/Self-contained-executable) +- Cli-matic is now compatible due to this [PR](https://github.com/l3nz/cli-matic/pull/145) +- [I, too, Wrote Myself a Static Site Generator](https://dawranliou.com/blog/i-too-wrote-myself-a-static-site-generator/) by Daw-Ran Liou +- [Staplegun](https://github.com/escherize/staplegun): Single file clipboard-manager +- [Bbb](https://github.com/nikvdp/bbb): make executable CLI tools from bb scripts +- [Apptemplate](https://github.com/redstarssystems/apptemplate): Application project template for Clojure featuring bb tasks + + +## [2022-01](https://twitter.com/search?f=live&q=(%23babashka)%20until%3A2022-02-01%20since%3A2022-01-01&src=typed_query) + +- Releases: [0.7.4](https://github.com/babashka/babashka/blob/master/CHANGELOG.md). +- [Babashka dev builds](https://github.com/babashka/babashka-dev-builds) +- [Writing Clojure-living-cookbooks](https://www.loop-code-recur.io/live-clojure-cookbooks/) by Cyprien Pannier +- [HTMX Todo App](https://github.com/prestancedesign/babashka-htmx-todoapp) +- [Better linting for `bb.edn`](https://twitter.com/borkdude/status/1484100071134220291) +- [Unwordle](https://github.com/mknoszlig/unwordle): solver for wordle puzzles +- [Using babashka with PHP](https://blog.michielborkent.nl/using-babashka-with-php.html) by Michiel Borkent ## 2021-12 @@ -74,7 +149,7 @@ Twitter. - [Cursive](https://twitter.com/CursiveIDE/status/1439022267187433472) adds support for babashka in 1.11.0 - How to filter tail output with babashka on [StackOverflow](https://stackoverflow.com/questions/69241046/how-to-filter-output-of-tail-with-babashka/69241911?stw=2#69241911) - [Awesome Babashka: Parse & produce HTML and SQLite](https://blog.jakubholy.net/2021/awesome-babashka-dash/) by Jakub Holy -- [neil](https://github.com/babashka/neil): an installable babashka script to add common aliases and features to deps.edn-based projects. +- [Neil](https://github.com/babashka/neil): an installable babashka script to add common aliases and features to deps.edn-based projects. ## 2021-08 diff --git a/doc/nix.md b/doc/nix.md new file mode 100644 index 00000000..68b26178 --- /dev/null +++ b/doc/nix.md @@ -0,0 +1,119 @@ +# Using Babashka with Nix + +Babashka is [packaged](https://search.nixos.org/packages?type=packages&query=babashka) in nixpkgs and can be easily used from the Nix package manager. + +The following assumes a recent installation of nix and uses the unstable [nix cli](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix.html) and [Flakes](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake.html). + +To enable the unstable cli and flakes add the following to `/etc/nix/nix.conf`: + +``` +extra-experimental-features flakes nix-command +``` + +## Imperative install on Nix + +To imperatively install nix for the current user, run `nix profile install babashka`. + +## Declarative global install on NixOS + +To install babashka for all users on a NixOS system, place it in `environment.systemPackages` in your `configuration.nix`: + +```nix +{ pkgs, ... }: +{ + environment.systemPackages = with pkgs; [ + babashka + ]; +} +``` + +Then run `nixos-rebuild switch`, to activate the new configuration. + +## Declarative per-user install with home-manager + +You can install babashka for a specific user using [home-manager](https://github.com/nix-community/home-manager). Add the following to your `~/.config/nixpkgs/home.nix`: + +```nix +{ pkgs, ... }: +{ + home.packages = with pkgs; [ + babashka + ]; +} +``` + +Then run `home-manager switch`, to activate the new configuration. + +## Per project install with direnv + +To make babashka available on a per-project basis, you can use [direnv](https://direnv.net/). + +Create a file `.envrc` in the project directory with the following contents: + +``` +use flake +``` + +Create a file `flake.nix` in the project directory with the following contents: + +```nix +{ + outputs = {nixpkgs, ...}: let + supportedSystems = ["x86_64-linux" "x86_64-darwin"]; + forAllSystems = nixpkgs.lib.genAttrs supportedSystems; + nixpkgsFor = system: import nixpkgs {inherit system;}; + in { + devShell = forAllSystems (system: let + pkgs = nixpkgsFor system; + in + pkgs.mkShell { + packages = with pkgs; [ + babashka + ]; + }); + }; +} +``` + +After running `direnv allow`, babashka should be available on the `$PATH`, when you are inside the project directory. + +## Write Babashka Application + +You can write babashka scripts with native dependencies using [WriteBabashkaApplication](https://github.com/sohalt/write-babashka-application). + +Here is an example `flake.nix` using `cowsay` as an external dependency: + +```nix +{ + inputs.wbba.url = "github:sohalt/write-babashka-application"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + outputs = { nixpkgs, flake-utils, wbba, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ wbba.overlay ]; + }; + hello-babashka = pkgs.writeBabashkaApplication { + name = "hello"; + runtimeInputs = with pkgs;[ + cowsay # add your dependencies here + ]; + text = '' + (ns hello + (:require [babashka.process :refer [sh]])) + + (-> (sh ["cowsay" "hello from babashka"]) + :out + print) + ''; + }; + in + { + defaultApp = hello-babashka; + defaultPackage = hello-babashka; + }); +} +``` + +You can then build the application using `nix build` or run it using `nix run`. diff --git a/doc/projects.md b/doc/projects.md index d136ed88..53076656 100644 --- a/doc/projects.md +++ b/doc/projects.md @@ -7,7 +7,6 @@ The following libraries and projects are known to work with babashka. - [tools.namespace](#toolsnamespace) - [test-runner](#test-runner) - [spec.alpha](#specalpha) - - [tools.bbuild](#toolsbbuild) - [clj-http-lite](#clj-http-lite) - [spartan.spec](#spartanspec) - [missing.test.assertions](#missingtestassertions) @@ -62,6 +61,10 @@ The following libraries and projects are known to work with babashka. - [datalog-parser](#datalog-parser) - [at-at](#at-at) - [aysylu/loom](#aysyluloom) + - [Clarktown](#clarktown) + - [Malli](#malli) + - [Meander](#meander) + - [Schema](#schema) - [Pods](#pods) - [Projects](#projects-1) - [babashka-test-action](#babashka-test-action) @@ -88,6 +91,7 @@ The following libraries and projects are known to work with babashka. - [Babashka + scittle guestbook](#babashka--scittle-guestbook) - [bb htmx todo app](#bb-htmx-todo-app) - [bb aws lambda runtime](#bb-aws-lambda-runtime) + - [bb-github-app](#bb-github-app) Also keep an eye on the [news](news.md) page for new projects, gists and other developments around babashka. @@ -114,9 +118,9 @@ A fork of `clojure.spec.alpha` that includes support for generation and instrumentation! Its readme also contains instructions on how to use `clojure.core.specs.alpha`. -### [tools.bbuild](https://github.com/babashka/tools.bbuild) + -A fork of `tools.build`. + ### [clj-http-lite](https://github.com/clj-commons/clj-http-lite) @@ -808,6 +812,22 @@ Ahead-of-time function scheduler. Compatible with babashka 0.7.7+. Graph library for Clojure. Compatible with babashka 0.7.8+. +### [Clarktown](https://github.com/askonomm/clarktown) + +An extensible and modular zero-dependency, pure-Clojure Markdown parser. + +### [Malli](https://github.com/metosin/malli#babashka) + +Data-Driven Schemas for Clojure/Script + +### [Meander](https://github.com/noprompt/meander) + +Tools for transparent data transformation + +### [Schema](https://github.com/plumatic/schema) + +Clojure(Script) library for declarative data description and validation + ## Pods [Babashka pods](https://github.com/babashka/babashka.pods) are programs that can @@ -875,7 +895,7 @@ A babashka script to obtain covid-19 related information. ### [bb-spotify](https://github.com/kolharsam/bb-spotify) -Contol your spotify player using babashka. +Control your spotify player using babashka. ### [lambdaisland/open-source](https://github.com/lambdaisland/open-source) @@ -935,3 +955,8 @@ Quick example of a todo list SPA using Babashka and htmx. ### [bb aws lambda runtime](https://github.com/tatut/bb-lambda) AWS Lambda custom runtime for Babashka scripts. + +### [bb-github-app](https://github.com/brandonstubbs/bb-github-app) + +An example Babashka script that can authenticate as a Github Application, +this example focuses on the checks api. diff --git a/feature-datascript/babashka/impl/datascript.clj b/feature-datascript/babashka/impl/datascript.clj index 986723f3..e6e33fd8 100644 --- a/feature-datascript/babashka/impl/datascript.clj +++ b/feature-datascript/babashka/impl/datascript.clj @@ -2,11 +2,10 @@ {:no-doc true} (:require [datascript.core :as d] [datascript.db :as db] - [sci.impl.namespaces :refer [copy-var]] - [sci.impl.vars :as vars])) + [sci.core :as sci :refer [copy-var]])) -(def datascript-ns (vars/->SciNamespace 'datascript.core nil)) -(def datascript-db-ns (vars/->SciNamespace 'datascript.db nil)) +(def datascript-ns (sci/create-ns 'datascript.core nil)) +(def datascript-db-ns (sci/create-ns 'datascript.db nil)) (def datascript-namespace {'create-conn (copy-var d/create-conn datascript-ns) diff --git a/feature-hiccup/babashka/impl/hiccup.clj b/feature-hiccup/babashka/impl/hiccup.clj index 7263fb88..d2903b06 100644 --- a/feature-hiccup/babashka/impl/hiccup.clj +++ b/feature-hiccup/babashka/impl/hiccup.clj @@ -52,10 +52,10 @@ util/raw-string) (def hiccup-namespace - {'html (copy-var html-1 hns)}) + {'html (copy-var html-1 hns {:name 'html})}) (def hiccup2-namespace - {'html (copy-var html-2 hns2)}) + {'html (copy-var html-2 hns2 {:name 'html})}) (def html-mode (copy-var util/*html-mode* uns)) (def escape-strings? (copy-var util/*escape-strings?* uns)) diff --git a/feature-httpkit-client/babashka/impl/httpkit_client.clj b/feature-httpkit-client/babashka/impl/httpkit_client.clj index bb3e10ea..f51ccaf8 100644 --- a/feature-httpkit-client/babashka/impl/httpkit_client.clj +++ b/feature-httpkit-client/babashka/impl/httpkit_client.clj @@ -76,4 +76,4 @@ (def sni-client-namespace {'ssl-configurer (copy-var sni-client/ssl-configurer sns) - 'default-client (sci/new-var 'sni-client sni-client {:ns sns})}) + 'default-client (sci/new-var 'default-client sni-client {:ns sns})}) diff --git a/feature-httpkit-server/babashka/impl/httpkit_server.clj b/feature-httpkit-server/babashka/impl/httpkit_server.clj index f7e1935c..42608208 100644 --- a/feature-httpkit-server/babashka/impl/httpkit_server.clj +++ b/feature-httpkit-server/babashka/impl/httpkit_server.clj @@ -8,6 +8,7 @@ {:obj sns 'server-stop! (copy-var server/server-stop! sns) 'server-port (copy-var server/server-port sns) + 'server-status (copy-var server/server-status sns) 'run-server (copy-var server/run-server sns) 'sec-websocket-accept (copy-var server/sec-websocket-accept sns) 'websocket-handshake-check (copy-var server/websocket-handshake-check sns) diff --git a/feature-jdbc/babashka/impl/jdbc.clj b/feature-jdbc/babashka/impl/jdbc.clj index a9a4a3bc..23c28950 100644 --- a/feature-jdbc/babashka/impl/jdbc.clj +++ b/feature-jdbc/babashka/impl/jdbc.clj @@ -1,12 +1,13 @@ (ns babashka.impl.jdbc {:no-doc true} - (:require [next.jdbc :as njdbc] - [next.jdbc.result-set :as rs] - [next.jdbc.sql :as sql] - [sci.impl.namespaces :refer [copy-var macrofy]] - [sci.impl.vars :as vars])) + (:require + [next.jdbc :as njdbc] + [next.jdbc.result-set :as rs] + [next.jdbc.sql :as sql] + [sci.core :as sci] + [sci.impl.namespaces :refer [copy-var macrofy]])) -(def next-ns (vars/->SciNamespace 'next.jdbc nil)) +(def next-ns (sci/create-ns 'next.jdbc nil)) (defn with-transaction "Given a transactable object, gets a connection and binds it to `sym`, @@ -31,12 +32,12 @@ 'transact (copy-var njdbc/transact next-ns) 'with-transaction (macrofy 'with-transaction with-transaction next-ns)}) -(def sns (vars/->SciNamespace 'next.jdbc.sql nil)) +(def sns (sci/create-ns 'next.jdbc.sql nil)) (def next-sql-namespace {'insert-multi! (copy-var sql/insert-multi! sns)}) -(def rsns (vars/->SciNamespace 'next.jdbc.result-set nil)) +(def rsns (sci/create-ns 'next.jdbc.result-set nil)) (def result-set-namespace {'as-maps (copy-var rs/as-maps rsns) diff --git a/feature-rrb-vector/babashka/impl/rrb_vector.clj b/feature-rrb-vector/babashka/impl/rrb_vector.clj new file mode 100644 index 00000000..955e5d7b --- /dev/null +++ b/feature-rrb-vector/babashka/impl/rrb_vector.clj @@ -0,0 +1,7 @@ +(ns babashka.impl.rrb-vector + (:require [clojure.core.rrb-vector :as rrb] + [sci.core :as sci])) + +(def rrbns (sci/create-ns 'clojure.core.rrb-vector)) + +(def rrb-vector-namespace {'catvec (sci/copy-var rrb/catvec rrbns)}) diff --git a/feature-transit/babashka/impl/transit.clj b/feature-transit/babashka/impl/transit.clj index ab249c6a..15b0f19a 100644 --- a/feature-transit/babashka/impl/transit.clj +++ b/feature-transit/babashka/impl/transit.clj @@ -1,10 +1,9 @@ (ns babashka.impl.transit - (:require [cognitect.transit :as transit] - [sci.impl.namespaces :refer [copy-var]] - [sci.impl.vars :as vars])) + (:require + [cognitect.transit :as transit] + [sci.core :as sci :refer [copy-var]])) - -(def tns (vars/->SciNamespace 'cognitect.transit nil)) +(def tns (sci/create-ns 'cognitect.transit nil)) (def transit-namespace {'write (copy-var transit/write tns) diff --git a/feature-xml/babashka/impl/xml.clj b/feature-xml/babashka/impl/xml.clj index d889aa79..123310e5 100644 --- a/feature-xml/babashka/impl/xml.clj +++ b/feature-xml/babashka/impl/xml.clj @@ -12,7 +12,7 @@ (def xtns (sci/create-ns 'clojure.data.xml.tree nil)) (defn- clj-ns-name [ns] - (cond (instance? sci.impl.vars.SciNamespace ns) (str ns) + (cond (instance? sci.lang.Namespace ns) (str ns) (keyword? ns) (name ns) :else (str ns))) diff --git a/fs b/fs index f421d50c..73210e83 160000 --- a/fs +++ b/fs @@ -1 +1 @@ -Subproject commit f421d50c1e48c14dd5be61daadab85be2f8e956b +Subproject commit 73210e83808b8bfe664cba7d2148464a2fa38aae diff --git a/install b/install index 50a07309..cf1fb916 100755 --- a/install +++ b/install @@ -74,7 +74,7 @@ if [[ "$checksum" != "" ]] && [[ "$version" == "" ]]; then fi if [[ "$version" == "" ]]; then - version="$(curl -sL https://raw.githubusercontent.com/babashka/babashka/master/resources/BABASHKA_RELEASED_VERSION)" + version="$(curl -sL https://raw.githubusercontent.com/babashka/babashka/master/resources/BABASHKA_RELEASED_VERSION)" fi case "$(uname -s)" in @@ -82,21 +82,27 @@ case "$(uname -s)" in Darwin*) platform=macos;; esac -case "$(uname -m)" in - aarch64) arch=aarch64;; - *) arch=amd64;; -esac - # Ugly ugly conversion of version to a comparable number IFS='.' read -ra VER <<< "${version//-SNAPSHOT/}" vernum=$(printf "%03d%03d%03d" "${VER[0]}" "${VER[1]}" "${VER[2]}") +case "$(uname -m)" in + aarch64) arch=aarch64;; + arm64) if [[ 10#$vernum -le 10#000008002 ]]; then + arch="amd64" + else + arch="aarch64" + fi + ;; + *) arch=amd64;; +esac + if [[ 10#$vernum -le 10#000002013 ]]; then - ext="zip" - util="$(which unzip) -qqo" + ext="zip" + util="$(which unzip) -qqo" else - ext="tar.gz" - util="$(which tar) -zxf" + ext="tar.gz" + util="$(which tar) -zxf" fi case "$platform-$static_binary" in @@ -121,13 +127,13 @@ download_url="https://github.com/babashka/$repo/releases/download/v$version/$fil # macOS only have shasum available by default # Some Linux distros (RHEL-like) only have sha256sum avaiable by default (others have both) if command -v sha256sum >/dev/null; then - sha256sum_cmd="sha256sum" + sha256sum_cmd="sha256sum" elif command -v shasum >/dev/null; then - sha256sum_cmd="shasum -a 256" + sha256sum_cmd="shasum -a 256" else - >&2 echo "Either 'sha256sum' or 'shasum' needs to be on PATH for '--checksum' flag!" - >&2 echo "Exiting..." - exit 1 + >&2 echo "Either 'sha256sum' or 'shasum' needs to be on PATH for '--checksum' flag!" + >&2 echo "Exiting..." + exit 1 fi # Running this part in a subshell so when it finishes we go back to the previous directory diff --git a/logo/babashka-blue-yellow.png b/logo/babashka-blue-yellow.png new file mode 100644 index 00000000..ff85cd2b Binary files /dev/null and b/logo/babashka-blue-yellow.png differ diff --git a/logo/babashka-blue-yellow.svg b/logo/babashka-blue-yellow.svg new file mode 100644 index 00000000..7e298b09 --- /dev/null +++ b/logo/babashka-blue-yellow.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/logo/babashka_red.png b/logo/babashka_red.png new file mode 100644 index 00000000..f178d08f Binary files /dev/null and b/logo/babashka_red.png differ diff --git a/logo/babashka_red.svg b/logo/babashka_red.svg new file mode 100644 index 00000000..ad915719 --- /dev/null +++ b/logo/babashka_red.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/logo/badge.svg b/logo/badge.svg new file mode 100644 index 00000000..cc95918c --- /dev/null +++ b/logo/badge.svg @@ -0,0 +1 @@ +babashka: compatiblebabashkacompatible \ No newline at end of file diff --git a/logo/built-in-badge.svg b/logo/built-in-badge.svg new file mode 100644 index 00000000..afeae2eb --- /dev/null +++ b/logo/built-in-badge.svg @@ -0,0 +1 @@ +babashka: built-inbabashkabuilt-in \ No newline at end of file diff --git a/pods b/pods index e075b13b..53f79da0 160000 --- a/pods +++ b/pods @@ -1 +1 @@ -Subproject commit e075b13bfe3666a73f82c12817bdf5f1d6c692e3 +Subproject commit 53f79da09d5da542204f3cb0161724221276dfcb diff --git a/process b/process index 8d72f209..bd203b79 160000 --- a/process +++ b/process @@ -1 +1 @@ -Subproject commit 8d72f2097a1dc49b81a52af6733b8beb836efbdc +Subproject commit bd203b79a21b6155b61b4b4efda5a497dec2567d diff --git a/project.clj b/project.clj index cdc3c290..3dd6e582 100644 --- a/project.clj +++ b/project.clj @@ -10,30 +10,36 @@ :source-paths ["src" "sci/src" "babashka.curl/src" "fs/src" "pods/src" "babashka.core/src" "babashka.nrepl/src" "depstar/src" "process/src" - "deps.clj/src" "deps.clj/resources"] + "deps.clj/src" "deps.clj/resources" + "reify/src"] ;; for debugging Reflector.java code: ;; :java-source-paths ["sci/reflector/src-java"] :java-source-paths ["src-java"] :resource-paths ["resources" "sci/resources"] :test-selectors {:default (complement :windows-only) :windows (complement :skip-windows)} - :dependencies [[org.clojure/clojure "1.11.0"] - [borkdude/edamame "0.0.19"] + :dependencies [[org.clojure/clojure "1.11.1"] + [borkdude/edamame "1.0.0"] [borkdude/graal.locking "0.0.2"] [org.clojure/tools.cli "1.0.206"] - [cheshire "5.10.2"] + [cheshire "5.11.0"] [nrepl/bencode "1.1.0"] [borkdude/sci.impl.reflector "0.0.1"] + [org.babashka/sci.impl.types "0.0.2"] + [org.babashka/babashka.impl.reify "0.1.3"] [org.clojure/core.async "1.5.648"] [org.clojure/test.check "1.1.1"] [com.github.clj-easy/graal-build-time "0.1.0"] - [rewrite-clj/rewrite-clj "1.0.699-alpha"]] + [rewrite-clj/rewrite-clj "1.1.45"] + [insn/insn "0.5.2"] + [org.babashka/cli "0.4.37"]] :plugins [[org.kipz/lein-meta-bom "0.1.1"]] :metabom {:jar-name "metabom.jar"} :profiles {:feature/xml {:source-paths ["feature-xml"] - :dependencies [[org.clojure/data.xml "0.2.0-alpha6"]]} + :dependencies [[org.clojure/data.xml "0.2.0-alpha8"]]} :feature/yaml {:source-paths ["feature-yaml"] - :dependencies [[clj-commons/clj-yaml "0.7.108"]]} + :dependencies [[clj-commons/clj-yaml "0.7.169" + #_#_clj-commons/clj-yaml "0.7.110"]]} :feature/jdbc {:source-paths ["feature-jdbc"] :dependencies [[seancorfield/next.jdbc "1.1.610"]]} :feature/sqlite [:feature/jdbc {:dependencies [[org.xerial/sqlite-jdbc "3.36.0.3"]]}] @@ -48,9 +54,9 @@ :feature/datascript {:source-paths ["feature-datascript"] :dependencies [[datascript "1.3.10"]]} :feature/httpkit-client {:source-paths ["feature-httpkit-client"] - :dependencies [[http-kit "2.5.3"]]} + :dependencies [[http-kit "2.6.0-RC1"]]} :feature/httpkit-server {:source-paths ["feature-httpkit-server"] - :dependencies [[http-kit "2.5.3"]]} + :dependencies [[http-kit "2.6.0-RC1"]]} :feature/lanterna {:source-paths ["feature-lanterna"] :dependencies [[babashka/clojure-lanterna "0.9.8-SNAPSHOT"]]} :feature/core-match {:source-paths ["feature-core-match"] @@ -66,6 +72,8 @@ [org.clojure/tools.logging "1.1.0"]]} :feature/priority-map {:source-paths ["feature-priority-map"] :dependencies [[org.clojure/data.priority-map "1.1.0"]]} + :feature/rrb-vector {:source-paths ["feature-rrb-vector"] + :dependencies [[org.clojure/core.rrb-vector "0.1.2"]]} :test [:feature/xml :feature/lanterna :feature/yaml @@ -83,6 +91,7 @@ :feature/selmer :feature/logging :feature/priority-map + :feature/rrb-vector {:dependencies [[com.clojure-goes-fast/clj-async-profiler "0.5.0"] [com.opentable.components/otj-pg-embedded "0.13.3"]]}] :uberjar {:global-vars {*assert* false} diff --git a/reify/.dir-locals.el b/reify/.dir-locals.el new file mode 100644 index 00000000..85a2d84d --- /dev/null +++ b/reify/.dir-locals.el @@ -0,0 +1,2 @@ +((nil + (cider-clojure-cli-global-options . "-A:test:build"))) diff --git a/reify/bb.edn b/reify/bb.edn new file mode 100644 index 00000000..adce8f9c --- /dev/null +++ b/reify/bb.edn @@ -0,0 +1,2 @@ +{:tasks {install (clojure "-T:build install") + deploy (clojure "-T:build deploy")}} diff --git a/reify/build.clj b/reify/build.clj new file mode 100644 index 00000000..c0493917 --- /dev/null +++ b/reify/build.clj @@ -0,0 +1,50 @@ +(ns build + (:require [build.reify2 :as reify2] + [clojure.tools.build.api :as b])) + +(def lib 'org.babashka/babashka.impl.reify) +(def version "0.1.3") +(def class-dir "target/classes") +(def basis (b/create-basis {:project "deps.edn"})) +(def jar-file (format "target/%s-%s.jar" (name lib) version)) + +(defn clean [_] + (b/delete {:path "target"})) + +(defn gen-classes [_] + (reify2/gen-classes nil)) + +(defn jar [_] + (gen-classes nil) + (b/write-pom {:class-dir class-dir + :lib lib + :version version + :basis basis + :src-dirs ["src"]}) + (b/copy-dir {:src-dirs ["src"] + :target-dir class-dir}) + (b/jar {:class-dir class-dir + :jar-file jar-file})) + +(defn install [_] + (jar nil) + (b/install {:basis basis + :lib lib + :version version + :jar-file jar-file + :class-dir class-dir})) + +(defn deploy [opts] + (jar opts) + ((requiring-resolve 'deps-deploy.deps-deploy/deploy) + (merge {:installer :remote + :artifact jar-file + :pom-file (b/pom-path {:lib lib :class-dir class-dir})} + opts)) + opts) + +;;;; Scratch + +(comment + (gen-classes nil) + ) diff --git a/reify/build/reify2.clj b/reify/build/reify2.clj new file mode 100644 index 00000000..4dcc9f35 --- /dev/null +++ b/reify/build/reify2.clj @@ -0,0 +1,188 @@ +(ns build.reify2 + {:no-doc true} + (:require [babashka.impl.reify2.interfaces :refer [interfaces]] + [insn.core :as insn])) + +(set! *warn-on-reflection* false) + +(defn set-symbol! [s] + [[:aconst-null] + [:ldc s] + [:invokestatic clojure.lang.Symbol "intern" [String String clojure.lang.Symbol]] + [:putstatic :this (str "_sym_" s) clojure.lang.Symbol]]) + +(defn return [desc] + (case (last desc) + :void [:return] + (:boolean :int) [:ireturn] + [:areturn])) + +(defn loads [desc cast?] + (let [desc (butlast desc)] + (vec + (mapcat (fn [i e] + (case e + :boolean [[:iload i] + (when cast? [:invokestatic Boolean "valueOf" [:boolean Boolean]])] + :int [[:iload i] + (when cast? [:invokestatic Integer "valueOf" [:int Integer]])] + [[:aload i]])) + (range 1 (inc (count desc))) + desc)))) + +(defn emit-method [class meth desc default] + (let [args (dec (count desc))] + [[[:aload 0] + [:getfield :this "_methods" java.util.Map] + [:getstatic :this (str "_sym_" meth) clojure.lang.Symbol] + [:invokeinterface java.util.Map "get" [Object Object]] + [:checkcast clojure.lang.IFn] + [:astore (inc args)] + [:aload (inc args)] + [:ifnull :fallback] + [:aload (inc args)] + ;; load this, always the first argument of IFn + [:aload 0]] + ;; load remaining args + (loads desc true) + [[:invokeinterface clojure.lang.IFn "invoke" (vec (repeat (inc (count desc)) Object))] + (let [ret-type* (last desc) + ret-type (if (class? ret-type*) + (.getName ^Class ret-type*) + ret-type*)] + (case ret-type + :void [:pop] + :boolean [[:checkcast Boolean] + [:invokevirtual Boolean "booleanValue"]] + :int [[:checkcast Integer] + [:invokevirtual Integer "intValue"]] + "java.lang.Object" nil + (when (class? ret-type*) + [[:checkcast ret-type*]]))) + (return desc) + [:mark :fallback]] + (if default + [[[:aload 0]] + (loads desc false) + [[:invokespecial class meth desc true] + (return desc)]] + [[:new java.lang.UnsupportedOperationException] + [:dup] + [:ldc (format "No implementation of method found: %s %s" meth desc)] + [:invokespecial java.lang.UnsupportedOperationException :init [String :void]] + [:athrow]])])) + +(defn interface-data [^Class interface methods] + (let [class-sym (symbol (.getName interface)) + method-names (distinct (map :name methods))] + {:name (symbol (str "babashka.impl." (.getName interface))) + :version 1.8 + :interfaces [class-sym + 'sci.impl.types.IReified + 'clojure.lang.IMeta + 'clojure.lang.IObj] + :flags [:super :public] + :fields (into [{:flags #{:private}, + :name "_methods" :type java.util.Map} + {:flags #{:private}, + :name "_interfaces" :type Object} + {:flags #{:private}, + :name "_protocols" :type Object} + {:flags #{:private}, + :name "_meta" :type clojure.lang.IPersistentMap}] + (for [name method-names] + {:flags #{:private :static}, + :name (str "_sym_" name) :type clojure.lang.Symbol})) + :methods (into [{:name :clinit + :emit (reduce into + [] + (conj + (mapv set-symbol! method-names) + [[:return]]))} + {:name :init + :desc [:void] + :emit [[:aload 0] + [:invokespecial :super :init [:void]] + [:return]]} + {:name :init + :desc [java.util.Map Object Object :void] + :emit [[:aload 0] + [:invokespecial :super :init [:void]] + [:aload 0] + [:aload 1] + [:putfield :this "_methods" java.util.Map] + [:aload 0] + [:aload 2] + [:putfield :this "_interfaces" Object] + [:aload 0] + [:aload 3] + [:putfield :this "_protocols" Object] + [:return]]} + {:name :meta + :desc [clojure.lang.IPersistentMap] + :emit [[:aload 0] + [:getfield :this "_meta" clojure.lang.IPersistentMap] + [:areturn]]} + {:name :withMeta + :desc [clojure.lang.IPersistentMap clojure.lang.IObj] + :emit [[:aload 0] + [:aload 1] + [:putfield :this "_meta" clojure.lang.IPersistentMap] + [:aload 0] + [:areturn]]} + {:name :getInterfaces + :desc [Object] + :emit [[:aload 0] + [:getfield :this "_interfaces" Object] + [:areturn]]} + {:name :getMethods + :desc [Object] + :emit [[:aload 0] + [:getfield :this "_methods" java.util.Map] + [:areturn]]} + {:name :getProtocols + :desc [Object] + :emit [[:aload 0] + [:getfield :this "_protocols" Object] + [:areturn]]}] + (for [{:keys [name desc default]} methods] + {:flags #{:public}, :name name + :desc desc + :emit (emit-method interface name desc default)} + ))})) + +(set! *warn-on-reflection* true) + +(defn type->kw [type] + (condp = type + Void/TYPE :void + Boolean/TYPE :boolean + Integer/TYPE :int + type)) + +(defn class->methods [^Class clazz] + (let [meths (.getMethods clazz) + meths (mapv bean meths) + ;; TODO: fix problems with clojure.lang.IFn, special cased for now + ;; The problem is that the 20-arity (highest one) could not be reified + ;; meths (filter #(<= (:parameterCount %) 19) meths) + meths (mapv (fn [{:keys [name + parameterTypes + returnType + default]}] + (let [ret-type (type->kw returnType)] + {:name name + :desc (conj (mapv type->kw parameterTypes) ret-type) + :default default})) + meths)] + (distinct meths))) + +(let [i clojure.lang.IFn] + (insn/define (insn/visit (interface-data i (class->methods i))))) + +(def reified (babashka.impl.clojure.lang.IFn. {'invoke (fn [& _args] :yep)} {} {})) + +(defn gen-classes [_] + (doseq [i interfaces] + (insn/write (doto (insn/visit (interface-data i (class->methods i))) + insn/define) "target/classes"))) diff --git a/reify/deps.edn b/reify/deps.edn new file mode 100644 index 00000000..35a3c915 --- /dev/null +++ b/reify/deps.edn @@ -0,0 +1,13 @@ +{:deps {org.babashka/sci.impl.types {:mvn/version "0.0.2"}} + :aliases + {:build ;; added by neil + {:paths ["." "build" "src"] + :deps {io.github.clojure/tools.build {:git/tag "v0.8.1" :git/sha "7d40500"} + slipset/deps-deploy {:mvn/version "0.2.0"} + org.babashka/sci.impl.types {:mvn/version "0.0.2"} + ;; insn/insn {:mvn/version "0.5.3"} + insn/insn { + :git/sha "f85da286d429b507480f8527b12ce3e1e0e17296" + :git/url "https://github.com/phronmophobic/insn" + }} + :ns-default build}}} diff --git a/reify/src/babashka/impl/reify2.clj b/reify/src/babashka/impl/reify2.clj new file mode 100644 index 00000000..dff57479 --- /dev/null +++ b/reify/src/babashka/impl/reify2.clj @@ -0,0 +1,90 @@ +(ns babashka.impl.reify2 + (:require [babashka.impl.reify2.interfaces :refer [interfaces]])) + +(set! *warn-on-reflection* false) + +(defn method-or-bust [methods k] + (or (get methods k) + (throw (UnsupportedOperationException. "Method not implemented: " k)))) + +(defn reify-ifn [m] + (let [methods (:methods m) + invoke-fn (or (get methods 'invoke) + (fn [& _args] + (throw (UnsupportedOperationException. "Method not implemented: invoke")))) + apply-fn (or (get methods 'applyTo) + (fn [& _args] + (throw (UnsupportedOperationException. "Method not implemented: applyTo"))))] + (reify + sci.impl.types.IReified + (getMethods [_] (:methods m)) + (getInterfaces [_] (:interfaces m)) + (getProtocols [_] (:protocols m)) + clojure.lang.IFn + (invoke [this] (invoke-fn this)) + (invoke [this a0] (invoke-fn this a0)) + (invoke [this a0 a1] (invoke-fn this a0 a1)) + (invoke [this a0 a1 a2] (invoke-fn this a0 a1 a2)) + (invoke [this a0 a1 a2 a3] (invoke-fn this a0 a1 a2 a3)) + (invoke [this a0 a1 a2 a3 a4] (invoke-fn this a0 a1 a2 a3 a4)) + (invoke [this a0 a1 a2 a3 a4 a5] (invoke-fn this a0 a1 a2 a3 a4 a5)) + (invoke [this a0 a1 a2 a3 a4 a5 a6] (invoke-fn this a0 a1 a2 a3 a4 a5 a6)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19)) + (invoke [this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20] (invoke-fn this a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20)) + (applyTo [this arglist] (apply-fn this arglist))))) + +(defn reify-object [m] + (let [methods (:methods m) + toString-fn (or (get methods 'toString) + (fn [this] + (str + (.getName (.getClass this)) + "@" + (Integer/toHexString (.hashCode this)))))] + (reify + sci.impl.types.IReified + (getMethods [_] (:methods m)) + (getInterfaces [_] (:interfaces m)) + (getProtocols [_] (:protocols m)) + java.lang.Object + (toString [this] (toString-fn this))))) + +(defmacro gen-reify-fn [] + `(fn [~'m] + (when (> (count (:interfaces ~'m)) 1) + (throw (UnsupportedOperationException. "babashka reify only supports implementing a single interface"))) + (if (empty? (:interfaces ~'m)) + (reify + sci.impl.types.IReified + (getMethods [_] (:methods ~'m)) + (getInterfaces [_] (:interfaces ~'m)) + (getProtocols [_] (:protocols ~'m))) + (case (.getName ~(with-meta `(first (:interfaces ~'m)) + {:tag 'Class})) + ~@(mapcat identity + (cons + ["clojure.lang.IFn" + `(reify-ifn ~'m) + "java.lang.Object" + `(reify-object ~'m)] + (for [i interfaces] + (let [in (.getName ^Class i)] + [in + `(new ~(symbol (str "babashka.impl." in)) + (:methods ~'m) + (:interfaces ~'m) + (:protocols ~'m))])))))))) + +(def reify-fn (gen-reify-fn)) diff --git a/reify/src/babashka/impl/reify2/interfaces.clj b/reify/src/babashka/impl/reify2/interfaces.clj new file mode 100644 index 00000000..a94feec3 --- /dev/null +++ b/reify/src/babashka/impl/reify2/interfaces.clj @@ -0,0 +1,34 @@ +(ns babashka.impl.reify2.interfaces) + +(def interfaces [java.nio.file.FileVisitor + java.io.FileFilter + java.io.FilenameFilter + clojure.lang.Associative + clojure.lang.ILookup + java.util.Map$Entry + ;; TODO: fix problems with clojure.lang.IFn, special cased for now + ;; The problem is that the 20-arity (highest one) could not be reified + ;; clojure.lang.IFn + clojure.lang.IPersistentCollection + clojure.lang.IReduce + clojure.lang.IReduceInit + clojure.lang.IKVReduce + clojure.lang.Indexed + clojure.lang.IPersistentMap + clojure.lang.IPersistentStack + clojure.lang.Reversible + clojure.lang.Seqable + java.lang.Iterable + java.lang.Runnable + java.net.http.WebSocket$Listener + java.util.Iterator + java.util.function.Consumer + java.util.function.BiConsumer + java.util.function.Function + java.util.function.BiFunction + java.util.function.Predicate + java.util.function.Supplier + java.lang.Comparable + javax.net.ssl.X509TrustManager + clojure.lang.LispReader$Resolver + sun.misc.SignalHandler]) diff --git a/resources/BABASHKA_RELEASED_VERSION b/resources/BABASHKA_RELEASED_VERSION index f83dbb32..f303f848 100644 --- a/resources/BABASHKA_RELEASED_VERSION +++ b/resources/BABASHKA_RELEASED_VERSION @@ -1 +1 @@ -0.7.8 \ No newline at end of file +0.10.163 \ No newline at end of file diff --git a/resources/BABASHKA_VERSION b/resources/BABASHKA_VERSION index 6287e3f0..9fb7894f 100644 --- a/resources/BABASHKA_VERSION +++ b/resources/BABASHKA_VERSION @@ -1 +1 @@ -0.7.9-SNAPSHOT \ No newline at end of file +0.10.164-SNAPSHOT \ No newline at end of file diff --git a/resources/META-INF/babashka/deps.edn b/resources/META-INF/babashka/deps.edn deleted file mode 100644 index d4e67e14..00000000 --- a/resources/META-INF/babashka/deps.edn +++ /dev/null @@ -1,149 +0,0 @@ -{:paths ["src" "feature-xml" - "feature-yaml" "feature-csv" "feature-transit" - "feature-java-time" "feature-java-nio" - "feature-httpkit-client" "feature-httpkit-server" - "feature-lanterna" - "feature-core-match" - "feature-hiccup" - "feature-test-check" - "feature-spec-alpha" - "feature-selmer" - "feature-logging" - "feature-priority-map" - "feature-jdbc" - "pods/src" - "babashka.nrepl/src" - "depstar/src" "process/src" - "deps.clj/src" "deps.clj/resources" - "resources" "sci/resources"], - :deps {org.clojure/clojure {:mvn/version "1.11.0"}, - borkdude/sci {:local/root "sci"} - babashka/babashka.curl {:local/root "babashka.curl"} - babashka/fs {:local/root "fs"} - babashka/babashka.core {:local/root "babashka.core"} - borkdude/graal.locking {:mvn/version "0.0.2"}, - org.clojure/core.async {:mvn/version "1.5.648"}, - org.clojure/tools.cli {:mvn/version "1.0.206"}, - org.clojure/data.csv {:mvn/version "1.0.0"}, - cheshire/cheshire {:mvn/version "5.10.2"} - org.clojure/data.xml {:mvn/version "0.2.0-alpha6"} - clj-commons/clj-yaml {:mvn/version "0.7.108"} - com.cognitect/transit-clj {:mvn/version "1.0.329"} - org.clojure/test.check {:mvn/version "1.1.1"} - nrepl/bencode {:mvn/version "1.1.0"} - seancorfield/next.jdbc {:mvn/version "1.1.610"} - org.postgresql/postgresql {:mvn/version "42.2.18"} - org.hsqldb/hsqldb {:mvn/version "2.5.1"} - datascript/datascript {:mvn/version "1.0.1"} - http-kit/http-kit {:mvn/version "2.5.3"} - babashka/clojure-lanterna {:mvn/version "0.9.8-SNAPSHOT"} - org.clojure/core.match {:mvn/version "1.0.0"} - hiccup/hiccup {:mvn/version "2.0.0-alpha2"} - rewrite-clj/rewrite-clj {:mvn/version "1.0.699-alpha"} - selmer/selmer {:mvn/version "1.12.50"} - com.taoensso/timbre {:mvn/version "5.2.1"} - org.clojure/tools.logging {:mvn/version "1.1.0"} - org.clojure/data.priority-map {:mvn/version "1.1.0"}} - :aliases {:babashka/dev - {:main-opts ["-m" "babashka.main"]} - :profile - {:extra-deps - {com.clojure-goes-fast/clj-async-profiler {:mvn/version "0.5.0"}} - :extra-paths ["test"] - :jvm-opts ["-Djdk.attach.allowAttachSelf" - "-Dclojure.compiler.direct-linking=true"] - :main-opts ["-m" "babashka.profile"]} - :lib-tests - {:extra-paths ["process/src" "process/test" "test-resources/lib_tests"] - :extra-deps {org.clj-commons/clj-http-lite {:mvn/version "0.4.392"} - org.babashka/spec.alpha {:git/url "https://github.com/babashka/spec.alpha" - :sha "0dec1f88cbde74a0470b454396f09a03adb4ae39"} - lambdaisland/regal {:mvn/version "0.0.143"} - cprop/cprop {:mvn/version "0.1.16"} - comb/comb {:mvn/version "0.1.1"} - mvxcvi/arrangement {:mvn/version "2.0.0"} - org.clojure/data.zip {:mvn/version "1.0.0"} - clojure-csv/clojure-csv {:mvn/version "2.0.2"} - org.clojure/math.combinatorics {:mvn/version "0.1.6"} - doric/doric {:mvn/version "0.9.0"} - henryw374/cljc.java-time - {:git/url "https://github.com/henryw374/cljc.java-time.git" - :sha "e3d184b78e933322b3fcaa6ca66cbb8f42a6b35c"} - camel-snake-kebab/camel-snake-kebab {:mvn/version "0.4.2"} - aero/aero {:mvn/version "1.1.6"} - org.clojure/data.generators {:mvn/version "1.0.0"} - honeysql/honeysql {:mvn/version "1.0.461"} - com.github.seancorfield/honeysql {:mvn/version "2.2.840"} - minimallist/minimallist {:mvn/version "0.0.10"} - circleci/bond {:mvn/version "0.6.0"} - version-clj/version-clj {:mvn/version "2.0.2"} - gaka/gaka {:mvn/version "0.3.0"} - failjure/failjure {:mvn/version "2.2.0"} - io.helins/binf {:mvn/version "1.1.0-beta0"} - rm-hull/jasentaa {:mvn/version "0.2.5"} - slingshot/slingshot {:mvn/version "0.12.2"} - io.replikativ/hasch {:mvn/version "0.3.7"} - com.grammarly/omniconf {:mvn/version "0.4.3"} - crispin/crispin {:mvn/version "0.3.8"} - org.clojure/data.json {:mvn/version "2.4.0"} - clj-commons/multigrep {:mvn/version "0.5.0"} - amperity/vault-clj {:mvn/version "1.0.4"} - java-http-clj/java-http-clj {:mvn/version "0.4.3"} - com.stuartsierra/component {:mvn/version "1.0.0"} - org.clojars.askonomm/ruuter {:mvn/version "1.2.2"} - org.clj-commons/digest {:mvn/version "1.4.100"} - hato/hato {:mvn/version "0.8.2"} - better-cond/better-cond {:mvn/version "2.1.1"} - org.clojure/core.specs.alpha {:mvn/version "0.2.62"} - reifyhealth/specmonstah {:git/url "https://github.com/reifyhealth/specmonstah", :sha "a2b357009a3aa99a0c2d2361f3bbcd0b0e36505e"} - exoscale/coax {:mvn/version "1.0.0-alpha14"} - orchestra/orchestra {:mvn/version "2021.01.01-1"} - expound/expound {:mvn/version "0.8.10"} - integrant/integrant {:mvn/version "0.8.0"} - com.stuartsierra/dependency {:mvn/version "1.0.0"} - listora/again {:mvn/version "1.0.0"} - org.clojure/tools.gitlibs {:mvn/version "2.4.172"} - environ/environ {:mvn/version "1.2.0"} - table/table {:git/url "https://github.com/cldwalker/table", :sha "f6293c5f3dac1dd6f525a80fc80930f8ccdf16b7"} - markdown-clj/markdown-clj {:mvn/version "1.10.8"} - org.clojure/tools.namespace {:git/url "https://github.com/babashka/tools.namespace", :sha "a13b037215e21a2e71aa34b27e1dd52c801a2a7b"} - medley/medley {:mvn/version "1.3.0"} - io.github.cognitect-labs/test-runner {:git/tag "v0.5.0", :git/sha "b3fd0d2"} - borkdude/missing.test.assertions {:git/url "https://github.com/borkdude/missing.test.assertions", :sha "603cb01bee72fb17addacc53c34c85612684ad70"} - dev.nubank/docopt {:mvn/version "0.6.1-fix7"} - testdoc/testdoc {:mvn/version "1.4.1"} - org.clojars.lispyclouds/contajners {:mvn/version "0.0.4"} - borkdude/rewrite-edn {:mvn/version "0.1.0"} - clojure-term-colors/clojure-term-colors {:mvn/version "0.1.0"} - io.aviso/pretty {:mvn/version "1.1.1"} - progrock/progrock {:mvn/version "0.1.2"} - djblue/portal {:mvn/version "0.19.0"} - com.wsscode/cljc-misc {:mvn/version "2021.10.16"} - edn-query-language/eql {:mvn/version "2021.07.18"} - meta-merge/meta-merge {:mvn/version "1.0.0"} - com.exoscale/lingo {:mvn/version "1.0.0-alpha14"} - io.github.swirrl/dogstatsd {:mvn/version "0.1.39"} - org.clojure/algo.monads {:mvn/version "0.1.6"} - io.lambdaforge/datalog-parser {:mvn/version "0.1.9"} - clj-stacktrace/clj-stacktrace {:mvn/version "0.2.8"} - clojure-msgpack/clojure-msgpack {:mvn/version "1.2.1"} - cli-matic/cli-matic {:git/url "https://github.com/l3nz/cli-matic.git", :git/sha "9cd53ba7336363e3d06650dbad413b6f8b06e471"} - aysylu/loom {:mvn/version "1.0.2"} - com.layerware/hugsql-core {:mvn/version "0.5.1"} - com.github.seancorfield/expectations {:mvn/version "2.0.157"} - com.rpl/specter {:mvn/version "1.1.4"}} - :classpath-overrides {org.clojure/clojure nil - org.clojure/spec.alpha nil}} - :clj-nvd - {:extra-deps {clj-nvd/clj-nvd {:git/url "https://github.com/miikka/clj-nvd.git" - :sha "f2ec98699e057a379baf170cb49cf7ad76874a70"}} - :main-opts ["-m" "clj-nvd.core"]} - :test - {:extra-paths ["test"] - :extra-deps {io.github.cognitect-labs/test-runner - {:git/tag "v0.5.0" :git/sha "b3fd0d2"}} - :main-opts ["-m" "cognitect.test-runner"] - :exec-fn cognitect.test-runner.api/test} - :test-pod - {:extra-paths ["test-resources"] - :main-opts ["-m" "babashka.main" "test-resources/pod.clj"]}}} diff --git a/resources/META-INF/native-image/babashka/babashka/native-image.properties b/resources/META-INF/native-image/babashka/babashka/native-image.properties index 2577a2dc..77553bc9 100644 --- a/resources/META-INF/native-image/babashka/babashka/native-image.properties +++ b/resources/META-INF/native-image/babashka/babashka/native-image.properties @@ -13,6 +13,7 @@ Args=-H:+ReportExceptionStackTraces \ --report-unsupported-elements-at-runtime \ --initialize-at-build-time=com.fasterxml.jackson \ --initialize-at-build-time=java.sql.SQLException \ + --initialize-at-build-time=org.yaml.snakeyaml \ --initialize-at-run-time=org.postgresql.sspi.SSPIClient \ --initialize-at-run-time=org.httpkit.client.ClientSslEngineFactory$SSLHolder \ -H:ServiceLoaderFeatureExcludeServices=javax.sound.sampled.spi.AudioFileReader \ diff --git a/sci b/sci index 4e6d8e21..42bd17de 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 4e6d8e215a379e3c1a36e39dce43148c8ab0915b +Subproject commit 42bd17def34633b03d663211693eff972c9735bb diff --git a/script/add-libtest.clj b/script/add_libtest.clj similarity index 99% rename from script/add-libtest.clj rename to script/add_libtest.clj index 9eeea5f2..dd968c1e 100755 --- a/script/add-libtest.clj +++ b/script/add_libtest.clj @@ -11,11 +11,11 @@ (:require [babashka.deps :as deps] [babashka.fs :as fs] [babashka.tasks :refer [shell]] - [org.httpkit.client :as http] - [clojure.string :as str] + [clojure.edn :as edn] [clojure.java.io :as io] + [clojure.string :as str] [clojure.tools.cli :as cli] - [clojure.edn :as edn])) + [org.httpkit.client :as http])) (deps/add-deps '{:deps {org.clojure/tools.gitlibs {:mvn/version "2.4.172"} borkdude/rewrite-edn {:mvn/version "0.1.0"} diff --git a/script/babashka/release_artifact.clj b/script/babashka/release_artifact.clj index b88a1e20..09d3ba3f 100644 --- a/script/babashka/release_artifact.clj +++ b/script/babashka/release_artifact.clj @@ -7,19 +7,25 @@ (or (System/getenv "APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH") (System/getenv "APPVEYOR_REPO_BRANCH") (System/getenv "CIRCLE_BRANCH") + (System/getenv "GITHUB_REF_NAME") + (System/getenv "CIRRUS_BRANCH") (-> (sh "git" "rev-parse" "--abbrev-ref" "HEAD") :out str/trim))) (defn release [& args] (let [ght (System/getenv "GITHUB_TOKEN") + _ (println "Github token found") file (first args) + _ (println "File" file) branch (current-branch) + _ (println "On branch:" branch) current-version (-> (slurp "resources/BABASHKA_VERSION") str/trim)] (if (and ght (contains? #{"master" "main"} branch)) (do (assert file "File name must be provided") + (println "On main branch. Publishing asset.") (ghr/overwrite-asset {:org "babashka" :repo "babashka" :file file diff --git a/script/bump_graal_version.clj b/script/bump_graal_version.clj index 29fa58f6..fc80ea12 100755 --- a/script/bump_graal_version.clj +++ b/script/bump_graal_version.clj @@ -43,7 +43,9 @@ ".github/workflows/build.yml" ".circleci/config.yml" "appveyor.yml" - "project.clj"]) + "project.clj" + "script/bump_graal_version.clj" + ".circleci/script/short_ci.clj"]) ;; We might have to keep changing these from ;; time to time whenever the version is bumped @@ -51,10 +53,8 @@ ;; OR ;; ;; We could have them as environment variables -(def current-graal-version "21.3.0") +(def current-graal-version "22.2.0") (def current-java-version "java11") -(def valid-graal-bumps ["19.3.2" "20.1.0" "20.2.0" "20.3.0" "21.0.0" "21.1.0" "21.2.0" "21.3.0" "22.0.0.2"]) -(def valid-java-bumps ["java8" "java11"]) (def cl-options [["-g" "--graal VERSION" "graal version"] @@ -65,8 +65,8 @@ (:options (cli/parse-opts *command-line-args* cl-options))) (defn is-valid-bump? - [version valid-bumps] - (some #(= % version) valid-bumps)) + [_version _valid-bumps] + true) (defn replace-current [file current new] @@ -93,13 +93,13 @@ (let [new-graal-version (:graal args) new-java-version (:java args)] (when (not (nil? new-graal-version)) - (if (is-valid-bump? new-graal-version valid-graal-bumps) + (if (is-valid-bump? new-graal-version nil) (do (println "Performing Graal bump...") (bump-current current-graal-version new-graal-version)) (show-error new-graal-version))) (when (not (nil? new-java-version)) - (if (is-valid-bump? new-java-version valid-java-bumps) + (if (is-valid-bump? new-java-version nil) (do (println "Performing Java bump...") (bump-current current-java-version new-java-version)) diff --git a/script/compile b/script/compile index 42ab80c2..17b7dc76 100755 --- a/script/compile +++ b/script/compile @@ -78,6 +78,12 @@ if [ "$BABASHKA_FEATURE_HSQLDB" = "true" ]; then args+=("-H:IncludeResources=org/hsqldb/.*\.properties" "-H:IncludeResources=org/hsqldb/.*\.sql") fi +BABASHKA_FEATURE_POSTGRESQL=${BABASHKA_FEATURE_POSTGRESQL:-} + +if [ "$BABASHKA_FEATURE_POSTGRESQL" = "true" ]; then + args+=("--initialize-at-build-time=org.postgresql.PGProperty") +fi + BABASHKA_FEATURE_SELMER=${BABASHKA_FEATURE_SELMER:-} if [ "$BABASHKA_FEATURE_SELMER" = "true" ]; then @@ -92,7 +98,7 @@ then export BABASHKA_FEATURE_XML="${BABASHKA_FEATURE_XML:-false}" export BABASHKA_FEATURE_YAML="${BABASHKA_FEATURE_YAML:-false}" export BABASHKA_FEATURE_CSV="${BABASHKA_FEATURE_CSV:-false}" - export BABAHSKA_FEATURE_TRANSIT="${BABAHSKA_FEATURE_TRANSIT:-false}" + export BABASHKA_FEATURE_TRANSIT="${BABASHKA_FEATURE_TRANSIT:-false}" export BABASHKA_FEATURE_JAVA_TIME="${BABASHKA_FEATURE_JAVA_TIME:-false}" export BABASHKA_FEATURE_JAVA_NET_HTTP="${BABASHKA_FEATURE_JAVA_NET_HTTP:-false}" export BABASHKA_FEATURE_JAVA_NIO="${BABASHKA_FEATURE_JAVA_NIO:-false}" diff --git a/script/uberjar b/script/uberjar index cef77020..b067b17f 100755 --- a/script/uberjar +++ b/script/uberjar @@ -16,7 +16,7 @@ then export BABASHKA_FEATURE_XML="${BABASHKA_FEATURE_XML:-false}" export BABASHKA_FEATURE_YAML="${BABASHKA_FEATURE_YAML:-false}" export BABASHKA_FEATURE_CSV="${BABASHKA_FEATURE_CSV:-false}" - export BABAHSKA_FEATURE_TRANSIT="${BABAHSKA_FEATURE_TRANSIT:-false}" + export BABASHKA_FEATURE_TRANSIT="${BABASHKA_FEATURE_TRANSIT:-false}" export BABASHKA_FEATURE_JAVA_TIME="${BABASHKA_FEATURE_JAVA_TIME:-false}" export BABASHKA_FEATURE_JAVA_NET_HTTP="${BABASHKA_FEATURE_JAVA_NET_HTTP:-false}" export BABASHKA_FEATURE_JAVA_NIO="${BABASHKA_FEATURE_JAVA_NIO:-false}" @@ -168,6 +168,13 @@ else BABASHKA_LEIN_PROFILES+=",-feature/priority-map" fi +if [ "$BABASHKA_FEATURE_RRB_VECTOR" = "true" ] +then + BABASHKA_LEIN_PROFILES+=",+feature/rrb-vector" +else + BABASHKA_LEIN_PROFILES+=",-feature/rrb-vector" +fi + cp deps.edn resources/META-INF/babashka/deps.edn if [ -z "$BABASHKA_JAR" ]; then diff --git a/script/uberjar.bat b/script/uberjar.bat index 457fffdf..5ced217b 100755 --- a/script/uberjar.bat +++ b/script/uberjar.bat @@ -130,6 +130,12 @@ set BABASHKA_LEIN_PROFILES=%BABASHKA_LEIN_PROFILES%,+feature/priority-map set BABASHKA_LEIN_PROFILES=%BABASHKA_LEIN_PROFILES%,-feature/priority-map ) +if not "%BABASHKA_FEATURE_RRB_VECTOR%"=="false" ( +set BABASHKA_LEIN_PROFILES=%BABASHKA_LEIN_PROFILES%,+feature/rrb-vector +) else ( +set BABASHKA_LEIN_PROFILES=%BABASHKA_LEIN_PROFILES%,-feature/rrb-vector +) + call lein with-profiles %BABASHKA_LEIN_PROFILES% bb "(+ 1 2 3)" call lein with-profiles %BABASHKA_LEIN_PROFILES%,+reflection,-uberjar do run diff --git a/src/babashka/deps.clj b/src/babashka/deps.clj index 16e56668..d37218f2 100644 --- a/src/babashka/deps.clj +++ b/src/babashka/deps.clj @@ -1,5 +1,6 @@ (ns babashka.deps - (:require [babashka.process :as p] + (:require [babashka.impl.process :as pp] + [babashka.process :as p] [borkdude.deps :as deps] [sci.core :as sci])) @@ -41,8 +42,8 @@ deps/*env* (:env opts) deps/*extra-env* (:extra-env opts) deps/*process-fn* (fn - ([cmd] (p/process cmd opts)) - ([cmd _] (p/process cmd opts))) + ([cmd] (pp/process cmd opts)) + ([cmd _] (pp/process cmd opts))) deps/*exit-fn* (fn ([_]) ([_exit-code msg] diff --git a/src/babashka/impl/bencode.clj b/src/babashka/impl/bencode.clj index 70ed7ea1..b608b7d9 100644 --- a/src/babashka/impl/bencode.clj +++ b/src/babashka/impl/bencode.clj @@ -1,10 +1,10 @@ (ns babashka.impl.bencode {:no-doc true} - (:require [bencode.core :as bencode] - [sci.impl.namespaces :refer [copy-var]] - [sci.impl.vars :as vars])) + (:require + [bencode.core :as bencode] + [sci.core :as sci :refer [copy-var]])) -(def tns (vars/->SciNamespace 'bencode.core nil)) +(def tns (sci/create-ns 'bencode.core nil)) (def bencode-namespace {'read-bencode (copy-var bencode/read-bencode tns) diff --git a/src/babashka/impl/cheshire.clj b/src/babashka/impl/cheshire.clj index 6ce73d43..4e89afcb 100644 --- a/src/babashka/impl/cheshire.clj +++ b/src/babashka/impl/cheshire.clj @@ -1,10 +1,9 @@ (ns babashka.impl.cheshire {:no-doc true} (:require [cheshire.core :as json] - [sci.impl.namespaces :refer [copy-var]] - [sci.impl.vars :as vars])) + [sci.core :as sci :refer [copy-var]])) -(def tns (vars/->SciNamespace 'cheshire.core nil)) +(def tns (sci/create-ns 'cheshire.core nil)) (def cheshire-core-namespace {'encode (copy-var json/encode tns) diff --git a/src/babashka/impl/classes.clj b/src/babashka/impl/classes.clj index d9b08b00..5a2c669d 100644 --- a/src/babashka/impl/classes.clj +++ b/src/babashka/impl/classes.clj @@ -4,6 +4,8 @@ [babashka.impl.features :as features] [babashka.impl.proxy :as proxy] [cheshire.core :as json] + [clojure.core.async] + [sci.core :as sci] [sci.impl.types :as t])) (def base-custom-map @@ -78,11 +80,25 @@ ;; this fixes clojure.lang.Reflector for Java 11 java.lang.reflect.AccessibleObject {:methods [{:name "canAccess"}]} - java.lang.reflect.Method + java.lang.Package {:methods [{:name "getName"}]} + java.lang.reflect.Member + {:methods [{:name "getModifiers"}]} + java.lang.reflect.Method + {:methods [{:name "getName"} + {:name "getModifiers"} + {:name "getParameterTypes"} + {:name "getReturnType"}]} + java.lang.reflect.Modifier + {:methods [{:name "isStatic"}]} + java.lang.reflect.Field + {:methods [{:name "getName"} + {:name "getModifiers"}]} java.lang.reflect.Array {:methods [{:name "newInstance"} {:name "set"}]} + java.lang.Runnable + {:methods [{:name "run"}]} java.net.Inet4Address {:methods [{:name "getHostAddress"}]} java.net.Inet6Address @@ -97,7 +113,8 @@ {:name "aset"} {:name "aclone"}]} clojure.lang.Compiler - {:fields [{:name "specials"}]} + {:fields [{:name "specials"} + {:name "CHAR_MAP"}]} clojure.lang.PersistentHashMap {:fields [{:name "EMPTY"}]} clojure.lang.APersistentVector @@ -110,10 +127,17 @@ {:methods [{:name "disjoin"}]} clojure.lang.Indexed {:methods [{:name "nth"}]} + clojure.lang.Ratio + {:fields [{:name "numerator"} + {:name "denominator"}]} + clojure.lang.Agent + {:fields [{:name "pooledExecutor"} + {:name "soloExecutor"}]} java.util.Iterator {:methods [{:name "hasNext"} {:name "next"}]} - }) + java.util.TimeZone + {:methods [{:name "getTimeZone"}]}}) (def custom-map (cond-> @@ -124,7 +148,8 @@ :parameterTypes ["org.hsqldb.Database"]}]} `java.util.ResourceBundle {:methods [{:name "getBundle" - :parameterTypes ["java.lang.String","java.util.Locale","java.lang.ClassLoader"]}]}))) + :parameterTypes ["java.lang.String","java.util.Locale", + "java.lang.ClassLoader"]}]}))) (def java-net-http-classes "These classes must be initialized at run time since GraalVM 22.1" @@ -136,6 +161,7 @@ java.net.HttpCookie java.net.PasswordAuthentication java.net.ProxySelector + java.net.SocketTimeoutException java.net.http.HttpClient java.net.http.HttpClient$Builder java.net.http.HttpClient$Redirect @@ -159,6 +185,7 @@ javax.net.ssl.HttpsURLConnection ;; clj-http-lite javax.net.ssl.KeyManagerFactory javax.net.ssl.SSLContext + javax.net.ssl.SSLException javax.net.ssl.SSLParameters javax.net.ssl.SSLSession ;; clj-http-lite javax.net.ssl.TrustManager @@ -253,10 +280,14 @@ java.lang.System java.lang.Throwable ;; java.lang.UnsupportedOperationException + java.lang.ref.WeakReference + java.lang.ref.ReferenceQueue + java.lang.ref.Cleaner java.math.BigDecimal java.math.BigInteger java.math.MathContext java.math.RoundingMode + java.net.BindException java.net.ConnectException java.net.DatagramSocket java.net.DatagramPacket @@ -353,10 +384,26 @@ java.time.temporal.Temporal java.time.temporal.TemporalAccessor java.time.temporal.TemporalAdjuster]) + java.util.concurrent.atomic.AtomicInteger + java.util.concurrent.atomic.AtomicLong + java.util.concurrent.atomic.AtomicReference + java.util.concurrent.CancellationException + java.util.concurrent.CompletionException java.util.concurrent.ExecutionException + java.util.concurrent.Executor java.util.concurrent.LinkedBlockingQueue java.util.concurrent.ScheduledThreadPoolExecutor java.util.concurrent.ThreadPoolExecutor + java.util.concurrent.ThreadPoolExecutor$AbortPolicy + java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy + java.util.concurrent.ThreadPoolExecutor$DiscardOldestPolicy + java.util.concurrent.ThreadPoolExecutor$DiscardPolicy + java.util.concurrent.ScheduledExecutorService + java.util.concurrent.Future + java.util.concurrent.FutureTask + java.util.concurrent.CompletableFuture + java.util.concurrent.Executors + java.util.concurrent.TimeUnit java.util.jar.Attributes$Name java.util.jar.JarFile java.util.jar.JarEntry @@ -377,6 +424,9 @@ java.util.Base64$Decoder java.util.Base64$Encoder java.util.Date + java.util.HashMap + java.util.IdentityHashMap + java.util.List java.util.Locale java.util.Map java.util.MissingResourceException @@ -386,12 +436,13 @@ java.util.Scanner java.util.Set java.util.StringTokenizer + java.util.WeakHashMap java.util.UUID - java.util.concurrent.Future - java.util.concurrent.CompletableFuture - java.util.concurrent.Executors - java.util.concurrent.TimeUnit + java.util.function.Consumer java.util.function.Function + java.util.function.BiConsumer + java.util.function.BiFunction + java.util.function.Predicate java.util.function.Supplier java.util.zip.Inflater java.util.zip.InflaterInputStream @@ -405,6 +456,8 @@ java.util.zip.ZipEntry java.util.zip.ZipException java.util.zip.ZipFile + sun.misc.Signal + sun.misc.SignalHandler ~(symbol "[B") ~(symbol "[I") ~(symbol "[Ljava.lang.Object;") @@ -434,6 +487,7 @@ ;; list above and then everything reachable via the public class will be ;; visible in the native image. :instance-checks [clojure.lang.AFn + clojure.lang.AFunction clojure.lang.AMapEntry ;; for proxy clojure.lang.APersistentMap ;; for proxy clojure.lang.APersistentSet @@ -484,10 +538,17 @@ clojure.lang.Sequential clojure.lang.Seqable clojure.lang.Volatile - java.util.concurrent.atomic.AtomicInteger - java.util.concurrent.atomic.AtomicLong + ;; the only way to check if something is a channel is to + ;; call instance? on this... + clojure.core.async.impl.channels.ManyToManyChannel + java.lang.AbstractMethodError + java.lang.ExceptionInInitializerError + java.lang.LinkageError + java.lang.ThreadDeath + java.lang.VirtualMachineError + java.sql.Timestamp + java.util.concurrent.TimeoutException java.util.Collection - java.util.List java.util.Map$Entry ~@(when features/xml? ['clojure.data.xml.node.Element])] :custom ~custom-map}) @@ -505,6 +566,8 @@ c)) m (assoc m :public-class (fn [v] + ;; NOTE: a series of instance check, so far, is still cheaper + ;; than piggybacking on defmulti or defprotocol (cond (instance? java.lang.Process v) java.lang.Process (instance? java.lang.ProcessHandle v) @@ -557,13 +620,19 @@ java.nio.file.attribute.BasicFileAttributes (instance? java.util.concurrent.Future v) java.util.concurrent.Future + (instance? java.util.concurrent.ScheduledExecutorService v) + java.util.concurrent.ScheduledExecutorService + (instance? java.util.Iterator v) + java.util.Iterator ;; keep commas for merge friendliness - ,,,)))] + ,,,))) + m (assoc m (list 'quote 'clojure.lang.Var) 'sci.lang.Var)] m)) (def class-map* - "This contains mapping of symbol to class of all classes that are allowed to be initialized at build time." + "This contains mapping of symbol to class of all classes that are + allowed to be initialized at build time." (gen-class-map)) (def class-map @@ -574,7 +643,8 @@ java-net-http-classes))))) (def imports - '{Appendable java.lang.Appendable + '{AbstractMethodError java.lang.AbstractMethodError + Appendable java.lang.Appendable ArithmeticException java.lang.ArithmeticException AssertionError java.lang.AssertionError BigDecimal java.math.BigDecimal @@ -589,6 +659,7 @@ Comparable java.lang.Comparable Double java.lang.Double Exception java.lang.Exception + ExceptionInInitializerError java.lang.ExceptionInInitializerError IndexOutOfBoundsException java.lang.IndexOutOfBoundsException IllegalArgumentException java.lang.IllegalArgumentException IllegalStateException java.lang.IllegalStateException @@ -598,6 +669,7 @@ File java.io.File Float java.lang.Float Long java.lang.Long + LinkageError java.lang.LinkageError Math java.lang.Math NullPointerException java.lang.NullPointerException Number java.lang.Number @@ -614,6 +686,8 @@ System java.lang.System Thread java.lang.Thread Throwable java.lang.Throwable + VirtualMachineError java.lang.VirtualMachineError + ThreadDeath java.lang.ThreadDeath ;; UnsupportedOperationException java.lang.UnsupportedOperationException }) @@ -654,7 +728,8 @@ (let [all-entries (reflection-file-entries)] (spit (or (first args) - "resources/META-INF/native-image/babashka/babashka/reflect-config.json") (json/generate-string all-entries {:pretty true})))) + "resources/META-INF/native-image/babashka/babashka/reflect-config.json") + (json/generate-string all-entries {:pretty true})))) (defn public-declared-method? [c m] (and (= c (.getDeclaringClass m)) @@ -670,18 +745,25 @@ (sort-by :name) (vec))) -(defn all-methods [] +(defn all-classes [] + "Returns every java.lang.Class instance Babashka supports." (->> (reflection-file-entries) (map :name) - (map #(Class/forName %)) - (mapcat public-declared-method-names))) + (map #(Class/forName %)))) + +(defn all-methods [] + (mapcat public-declared-method-names (all-classes))) + +(def cns (sci/create-ns 'babashka.classes nil)) + +(def classes-namespace + {:obj cns + 'all-classes (sci/copy-var all-classes cns)}) (comment (public-declared-method-names java.net.URL) (public-declared-method-names java.util.Properties) - (->> (reflection-file-entries) - (map :name) - (map #(Class/forName %))) + (all-classes) ) diff --git a/src/babashka/impl/cli.clj b/src/babashka/impl/cli.clj new file mode 100644 index 00000000..fcbbe8ef --- /dev/null +++ b/src/babashka/impl/cli.clj @@ -0,0 +1,36 @@ +(ns babashka.impl.cli + (:require + [babashka.cli] + [sci.core :as sci])) + +(def cns (sci/create-ns 'babashka.cli)) + +(def cli-namespace + (sci/copy-ns babashka.cli cns)) + +(defn exec-fn-snippet + ([sym] (exec-fn-snippet sym nil)) + ([sym extra-opts] + (format " +(ns exec-%s + (:require [babashka.cli :as cli])) +(let [extra-opts '%s + sym `%s + the-var (requiring-resolve sym) + the-var-meta (meta the-var) + ns (:ns (meta the-var)) + ns-meta (meta ns) + ct (babashka.tasks/current-task) + cli-opts (babashka.cli/merge-opts (:org.babashka/cli ns-meta) + (:org.babashka/cli the-var-meta) + (:org.babashka/cli ct) + extra-opts) + opts (babashka.cli/parse-opts *command-line-args* cli-opts) + task-exec-args (:exec-args ct) + cli-exec-args (:exec-args cli-opts) + opts (babashka.cli/merge-opts cli-exec-args task-exec-args opts)] +(the-var opts))" + (random-uuid) + (pr-str extra-opts) + sym + ))) diff --git a/src/babashka/impl/clojure/core.clj b/src/babashka/impl/clojure/core.clj index ece78db3..e970cf77 100644 --- a/src/babashka/impl/clojure/core.clj +++ b/src/babashka/impl/clojure/core.clj @@ -9,7 +9,8 @@ [sci.core :as sci] [sci.impl.namespaces :refer [copy-core-var core-var macrofy]] [sci.impl.parser :as parser] - [sci.impl.vars :as vars :refer [clojure-core-ns]])) + [sci.impl.utils :refer [clojure-core-ns]] + [sci.impl.vars :as vars])) (defn locking* [form bindings v f & args] (apply @#'locking/locking form bindings v f args)) @@ -31,6 +32,7 @@ (def command-line-args (core-dynamic-var '*command-line-args*)) (def warn-on-reflection (core-dynamic-var '*warn-on-reflection* false)) (def compile-files (core-dynamic-var '*compile-files* false)) +(def unchecked-math (core-dynamic-var '*unchecked-math* false)) (def math-context (core-dynamic-var '*math-context*)) (defn read+string @@ -169,6 +171,7 @@ '*command-line-args* command-line-args '*warn-on-reflection* warn-on-reflection '*compile-files* compile-files + '*unchecked-math* unchecked-math '*math-context* math-context 'with-precision (sci/copy-var with-precision clojure-core-ns) '-with-precision (sci/copy-var -with-precision clojure-core-ns) @@ -192,6 +195,8 @@ 'iteration (sci/copy-var iteration clojure-core-ns) 'abs (sci/copy-var abs clojure-core-ns) 'StackTraceElement->vec (sci/copy-var StackTraceElement->vec clojure-core-ns) - 'memfn (sci/copy-var memfn clojure-core-ns) - 'into-array (sci/copy-var into-array clojure-core-ns)} + 'into-array (sci/copy-var into-array clojure-core-ns) + 'print-method (sci/copy-var print-method clojure-core-ns) + 'print-dup (sci/copy-var print-dup clojure-core-ns) + 'PrintWriter-on (sci/copy-var PrintWriter-on clojure-core-ns)} ) diff --git a/src/babashka/impl/clojure/core/async.clj b/src/babashka/impl/clojure/core/async.clj index f7112f67..6ae94083 100644 --- a/src/babashka/impl/clojure/core/async.clj +++ b/src/babashka/impl/clojure/core/async.clj @@ -2,7 +2,8 @@ {:no-doc true} (:require [clojure.core.async :as async] [clojure.core.async.impl.protocols :as protocols] - [sci.impl.namespaces :refer [copy-var macrofy]] + [sci.core :as sci :refer [copy-var]] + [sci.impl.namespaces :refer [macrofy]] [sci.impl.vars :as vars])) (def ^java.util.concurrent.Executor executor @#'async/thread-macro-executor) @@ -39,7 +40,7 @@ [_ _ bindings & body] (list 'clojure.core.async/thread (list* 'loop bindings body))) -(def core-async-namespace (vars/->SciNamespace 'clojure.core.async nil)) +(def core-async-namespace (sci/create-ns 'clojure.core.async nil)) (def async-namespace {:obj core-async-namespace @@ -67,6 +68,8 @@ 'mult (copy-var async/mult core-async-namespace) 'offer! (copy-var async/offer! core-async-namespace) 'onto-chan (copy-var async/onto-chan core-async-namespace) + 'onto-chan! (copy-var async/onto-chan! core-async-namespace) + 'onto-chan!! (copy-var async/onto-chan!! core-async-namespace) 'partition (copy-var async/partition core-async-namespace) 'partition-by (copy-var async/partition-by core-async-namespace) 'pipe (copy-var async/pipe core-async-namespace) @@ -91,6 +94,8 @@ 'thread-call (copy-var thread-call core-async-namespace) 'timeout (copy-var async/timeout core-async-namespace) 'to-chan (copy-var async/to-chan core-async-namespace) + 'to-chan! (copy-var async/to-chan! core-async-namespace) + 'to-chan!! (copy-var async/to-chan!! core-async-namespace) 'toggle (copy-var async/toggle core-async-namespace) 'transduce (copy-var async/transduce core-async-namespace) 'unblocking-buffer? (copy-var async/unblocking-buffer? core-async-namespace) @@ -103,13 +108,13 @@ 'untap-all (copy-var async/untap-all core-async-namespace) ;; polyfill 'go (macrofy 'go thread core-async-namespace) - '! (copy-var async/>!! core-async-namespace) + '! (copy-var async/>!! core-async-namespace {:name '>!}) 'alt! (macrofy 'alt! alt!! core-async-namespace) - 'alts! (copy-var async/alts!! core-async-namespace) + 'alts! (copy-var async/alts!! core-async-namespace {:name 'alts!}) 'go-loop (macrofy 'go-loop go-loop core-async-namespace)}) -(def async-protocols-ns (vars/->SciNamespace 'clojure.core.async.impl.protocols nil)) +(def async-protocols-ns (sci/create-ns 'clojure.core.async.impl.protocols nil)) (def async-protocols-namespace {:obj async-protocols-ns diff --git a/src/babashka/impl/clojure/core/server.clj b/src/babashka/impl/clojure/core/server.clj index 6211d7a5..fb3c1e90 100644 --- a/src/babashka/impl/clojure/core/server.clj +++ b/src/babashka/impl/clojure/core/server.clj @@ -18,7 +18,7 @@ [babashka.impl.common :refer [debug]] [sci.core :as sci] [sci.impl.parser :as p] - [sci.impl.vars :as vars]) + [sci.impl.utils :as utils]) (:import [clojure.lang LineNumberingPushbackReader] [java.io BufferedWriter InputStreamReader OutputStreamWriter] @@ -214,12 +214,11 @@ :val (if (instance? Throwable ret) (Throwable->map ret) ret) - :ns (str (vars/current-ns-name)) + :ns (str (utils/current-ns-name)) :ms ms :form s}) true))) (catch Throwable ex - (prn (ex-message ex)) (set! *e ex) (out-fn {:tag :ret :val (ex->data ex (or (-> ex ex-data :clojure.error/phase) :execution)) :ns (str (.name *ns*)) :form s diff --git a/src/babashka/impl/clojure/test.clj b/src/babashka/impl/clojure/test.clj index 0053e289..2810192e 100644 --- a/src/babashka/impl/clojure/test.clj +++ b/src/babashka/impl/clojure/test.clj @@ -232,13 +232,13 @@ For additional event types, see the examples in the code. "} babashka.impl.clojure.test - (:require [babashka.impl.common :refer [ctx]] - [clojure.stacktrace :as stack] - [clojure.template :as temp] - [sci.core :as sci] - [sci.impl.namespaces :as sci-namespaces] - [sci.impl.resolve :as resolve] - [sci.impl.vars :as vars])) + (:require + [babashka.impl.common :refer [ctx]] + [clojure.stacktrace :as stack] + [clojure.template :as temp] + [sci.core :as sci] + [sci.impl.namespaces :as sci-namespaces] + [sci.impl.resolve :as resolve])) ;; Nothing is marked "private" here, so you can rebind things to plug ;; in your own testing or reporting frameworks. @@ -332,7 +332,7 @@ :added "1.1"} report-impl :type) -(def report (sci/copy-var report-impl tns)) +(def report (sci/copy-var report-impl tns {:name 'report})) (defn do-report "Add file and line information to a test result and call report. @@ -409,7 +409,7 @@ [x] (if (symbol? x) (when-let [v (second (resolve/lookup @ctx x false))] - (when-let [value (if (vars/var? v) + (when-let [value (if (instance? sci.lang.Var v) (get-possibly-unbound-var v) v)] (and (fn? value) @@ -667,7 +667,7 @@ value of key." {:added "1.1"} [key coll] - (swap! ns->fixtures assoc-in [(sci-namespaces/sci-ns-name @vars/current-ns) key] coll)) + (swap! ns->fixtures assoc-in [(sci-namespaces/sci-ns-name @sci/ns) key] coll)) (defmulti use-fixtures "Wrap test runs in a fixture function to perform setup and @@ -722,7 +722,7 @@ :expected nil, :actual e}))) (do-report {:type :end-test-var, :var v})))) -(def test-var (sci/copy-var test-var-impl tns)) +(def test-var (sci/copy-var test-var-impl tns {:name 'test-var})) (defn test-vars "Groups vars by their namespace and runs test-vars on them with @@ -779,7 +779,7 @@ Defaults to current namespace if none given. Returns a map summarizing test results." {:added "1.1"} - ([ctx] (run-tests ctx @vars/current-ns)) + ([ctx] (run-tests ctx @sci/ns)) ([ctx & namespaces] (let [summary (assoc (apply merge-with + (map #(test-ns ctx %) namespaces)) :type :summary)] diff --git a/src/babashka/impl/clojure/zip.clj b/src/babashka/impl/clojure/zip.clj index 8a101d26..67ee39d1 100644 --- a/src/babashka/impl/clojure/zip.clj +++ b/src/babashka/impl/clojure/zip.clj @@ -1,10 +1,9 @@ (ns babashka.impl.clojure.zip {:no-doc true} (:require [clojure.zip :as zip] - [sci.impl.namespaces :refer [copy-var]] - [sci.impl.vars :as vars])) + [sci.core :as sci :refer [copy-var]])) -(def zip-ns (vars/->SciNamespace 'clojure.zip nil)) +(def zip-ns (sci/create-ns 'clojure.zip nil)) (def zip-namespace {'zipper (copy-var zip/zipper zip-ns) diff --git a/src/babashka/impl/curl.clj b/src/babashka/impl/curl.clj index 264a5443..ce0d36bc 100644 --- a/src/babashka/impl/curl.clj +++ b/src/babashka/impl/curl.clj @@ -1,10 +1,10 @@ (ns babashka.impl.curl {:no-doc true} - (:require [babashka.curl :as curl] - [sci.impl.namespaces :refer [copy-var]] - [sci.impl.vars :as vars])) + (:require + [babashka.curl :as curl] + [sci.core :as sci :refer [copy-var]])) -(def tns (vars/->SciNamespace 'babashka.curl nil)) +(def tns (sci/create-ns 'babashka.curl nil)) (def curl-namespace {'request (copy-var curl/request tns) diff --git a/src/babashka/impl/data.clj b/src/babashka/impl/data.clj index fd38dfa5..e5900b89 100644 --- a/src/babashka/impl/data.clj +++ b/src/babashka/impl/data.clj @@ -1,10 +1,10 @@ (ns babashka.impl.data {:no-doc true} - (:require [babashka.impl.clojure.data :as data] - [sci.impl.namespaces :refer [copy-var]] - [sci.impl.vars :as vars])) + (:require + [babashka.impl.clojure.data :as data] + [sci.core :as sci :refer [copy-var]])) -(def data-ns (vars/->SciNamespace 'clojure.data nil)) +(def data-ns (sci/create-ns 'clojure.data nil)) (def data-namespace {'diff (copy-var data/diff data-ns)}) diff --git a/src/babashka/impl/datafy.clj b/src/babashka/impl/datafy.clj index d0c7a3e5..4f389fc8 100644 --- a/src/babashka/impl/datafy.clj +++ b/src/babashka/impl/datafy.clj @@ -3,8 +3,7 @@ (:refer-clojure :exclude [create-ns]) (:require [babashka.impl.protocols :as protocols] - [sci.core :as sci :refer [copy-var]] - [sci.impl.vars])) + [sci.core :as sci :refer [copy-var]])) (def datafy-ns (sci/create-ns 'clojure.datafy nil)) diff --git a/src/babashka/impl/deps.clj b/src/babashka/impl/deps.clj index 735ec477..3224ebce 100644 --- a/src/babashka/impl/deps.clj +++ b/src/babashka/impl/deps.clj @@ -101,4 +101,4 @@ 'clojure (sci/copy-var bdeps/clojure dns) 'merge-deps (sci/copy-var merge-deps dns) ;; undocumented - 'merge-defaults (sci/copy-var merge-default-deps dns)}) + 'merge-defaults (sci/copy-var merge-default-deps dns {:name 'merge-defaults})}) diff --git a/src/babashka/impl/edamame.clj b/src/babashka/impl/edamame.clj new file mode 100644 index 00000000..62035e3d --- /dev/null +++ b/src/babashka/impl/edamame.clj @@ -0,0 +1,7 @@ +(ns babashka.impl.edamame + (:require [edamame.core] + [sci.core :as sci])) + +(def ens (sci/create-ns 'edamame.core)) + +(def edamame-namespace (sci/copy-ns edamame.core ens)) diff --git a/src/babashka/impl/error_handler.clj b/src/babashka/impl/error_handler.clj index b48adb76..e780c33c 100644 --- a/src/babashka/impl/error_handler.clj +++ b/src/babashka/impl/error_handler.clj @@ -108,7 +108,7 @@ stacktrace (dedupe (concat (sequence (comp (map StackTraceElement->vec) (take-while #(not (str/starts-with? (first %) "sci.impl."))) - (map render-native-stacktrace-elem)) + (keep render-native-stacktrace-elem)) (.getStackTrace (or (ex-cause e) e))) (sci/stacktrace e)))] (if exit-code diff --git a/src/babashka/impl/features.clj b/src/babashka/impl/features.clj index 2a04db6f..00456b37 100644 --- a/src/babashka/impl/features.clj +++ b/src/babashka/impl/features.clj @@ -26,6 +26,7 @@ (def hsqldb? (= "true" (System/getenv "BABASHKA_FEATURE_HSQLDB"))) (def datascript? (= "true" (System/getenv "BABASHKA_FEATURE_DATASCRIPT"))) (def lanterna? (= "true" (System/getenv "BABASHKA_FEATURE_LANTERNA"))) +(def rrb-vector? (= "true" (System/getenv "BABASHKA_FEATURE_RRB_VECTOR"))) (when xml? (require '[babashka.impl.xml])) @@ -75,3 +76,6 @@ (when priority-map? (require '[babashka.impl.priority-map])) + +(when rrb-vector? + (require '[babashka.impl.rrb-vector])) diff --git a/src/babashka/impl/nrepl_server.clj b/src/babashka/impl/nrepl_server.clj new file mode 100644 index 00000000..096981b5 --- /dev/null +++ b/src/babashka/impl/nrepl_server.clj @@ -0,0 +1,16 @@ +(ns babashka.impl.nrepl-server + {:no-doc true} + (:require [babashka.impl.common :as common] + [babashka.nrepl.server :as server] + [sci.core :as sci])) + +(defn start-server! + ([] + (server/start-server! @common/ctx)) + ([opts] + (server/start-server! @common/ctx opts))) + +(def nrepl-server-namespace + (let [ns-sci (sci/create-ns 'babashka.nrepl.server)] + {'start-server! (sci/copy-var start-server! ns-sci) + 'stop-server! (sci/copy-var server/stop-server! ns-sci)})) diff --git a/src/babashka/impl/patches/datafy.clj b/src/babashka/impl/patches/datafy.clj index c0127599..738e664c 100644 --- a/src/babashka/impl/patches/datafy.clj +++ b/src/babashka/impl/patches/datafy.clj @@ -1,13 +1,15 @@ (ns babashka.impl.patches.datafy - (:require [babashka.impl.common :refer [ctx]] - [clojure.core.protocols :as p] - [clojure.datafy] - ;; ensure datafy is loaded, we're going to override its - ;; clojure.lang.Namespace implementation for datafy - [clojure.reflect] - [sci.impl.namespaces :refer [sci-ns-name sci-ns-publics sci-ns-imports sci-ns-interns]] - [sci.impl.vars]) - (:import [sci.impl.vars SciNamespace])) + (:require ;; ensure datafy is loaded, we're going to override its + ;; clojure.lang.Namespace implementation for datafy + [babashka.impl.common :refer [ctx]] + [clojure.core.protocols :as p] + [clojure.datafy] + [clojure.reflect] + [sci.impl.namespaces :refer [sci-ns-imports sci-ns-interns sci-ns-name + sci-ns-publics]] + [sci.impl.vars]) + (:import + [sci.lang Namespace])) (defn- sortmap [m] (into (sorted-map) m)) @@ -29,7 +31,7 @@ (assoc ret :name (-> c .getName symbol) :members (->> members (group-by :name) sortmap))))) (extend-protocol p/Datafiable - SciNamespace + Namespace (datafy [n] (with-meta {:name (sci-ns-name n) :publics (->> n (sci-ns-publics @ctx) sortmap) diff --git a/src/babashka/impl/pods.clj b/src/babashka/impl/pods.clj index fb07c087..54e7cf22 100644 --- a/src/babashka/impl/pods.clj +++ b/src/babashka/impl/pods.clj @@ -9,20 +9,20 @@ (defn load-pod [& args] (apply pods/load-pod @ctx args)) -(defn load-pods-metadata [pods-map] +(defn load-pods-metadata [pods-map opts] (reduce-kv (fn [pod-namespaces pod-spec coord] (merge pod-namespaces (condp #(contains? %2 %1) coord :version (pods/load-pod-metadata pod-spec - (merge {:cache true} + (merge opts {:cache true} (select-keys coord [:version :cache]))) :path (pods/load-pod-metadata (-> @bb-edn :file io/file) pod-spec - (merge {:cache true} + (merge opts {:cache true} (select-keys coord [:path :cache]))) (throw (IllegalArgumentException. diff --git a/src/babashka/impl/pprint.clj b/src/babashka/impl/pprint.clj index 8047638b..ffd31e28 100644 --- a/src/babashka/impl/pprint.clj +++ b/src/babashka/impl/pprint.clj @@ -1,7 +1,8 @@ (ns babashka.impl.pprint {:no-doc true} (:require [clojure.pprint :as pprint] - [sci.core :as sci])) + [sci.core :as sci] + [sci.pprint])) (defonce patched? (volatile! false)) @@ -95,32 +96,33 @@ pprint/*print-pprint-dispatch* @print-pprint-dispatch pprint/*print-miser-width* @print-miser-width *print-meta* @sci/print-meta - *print-readably* @sci/print-readably] + *print-readably* @sci/print-readably + *print-length* @sci/print-length] (pprint/pprint s writer)))) (defn cl-format - "An implementation of a Common Lisp compatible format function. cl-format formats its -arguments to an output stream or string based on the format control string given. It -supports sophisticated formatting of structured data. -Writer is an instance of java.io.Writer, true to output to *out* or nil to output -to a string, format-in is the format control string and the remaining arguments -are the data to be formatted. -The format control string is a string to be output with embedded 'format directives' -describing how to format the various arguments passed in. -If writer is nil, cl-format returns the formatted result string. Otherwise, cl-format -returns nil. -For example: - (let [results [46 38 22]] - (cl-format true \"There ~[are~;is~:;are~]~:* ~d result~:p: ~{~d~^, ~}~%\" + "An implementation of a Common Lisp compatible format function. cl-format formats its + arguments to an output stream or string based on the format control string given. It + supports sophisticated formatting of structured data. + Writer is an instance of java.io.Writer, true to output to *out* or nil to output + to a string, format-in is the format control string and the remaining arguments + are the data to be formatted. + The format control string is a string to be output with embedded 'format directives' + describing how to format the various arguments passed in. + If writer is nil, cl-format returns the formatted result string. Otherwise, cl-format + returns nil. + For example: + (let [results [46 38 22]] + (cl-format true \"There ~[are~;is~:;are~]~:* ~d result~:p: ~{~d~^, ~}~%\" (count results) results)) -Prints to *out*: - There are 3 results: 46, 38, 22 -Detailed documentation on format control strings is available in the \"Common Lisp the -Language, 2nd edition\", Chapter 22 (available online at: -http://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/clm/node200.html#SECTION002633000000000000000) -and in the Common Lisp HyperSpec at -http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm -" + Prints to *out*: + There are 3 results: 46, 38, 22 + Detailed documentation on format control strings is available in the \"Common Lisp the + Language, 2nd edition\", Chapter 22 (available online at: + http://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/clm/node200.html#SECTION002633000000000000000) + and in the Common Lisp HyperSpec at + http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm + " [& args] ;; bind *out* to sci/out, so with-out-str works (binding [*out* @sci/out] @@ -134,36 +136,63 @@ http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm (apply #'pprint/execute-format args))) (defn get-pretty-writer - "Returns the java.io.Writer passed in wrapped in a pretty writer proxy, unless it's -already a pretty writer. Generally, it is unnecessary to call this function, since pprint, -write, and cl-format all call it if they need to. However if you want the state to be -preserved across calls, you will want to wrap them with this. -For example, when you want to generate column-aware output with multiple calls to cl-format, -do it like in this example: + "Returns the java.io.Writer passed in wrapped in a pretty writer proxy, unless it's + already a pretty writer. Generally, it is unnecessary to call this function, since pprint, + write, and cl-format all call it if they need to. However if you want the state to be + preserved across calls, you will want to wrap them with this. + For example, when you want to generate column-aware output with multiple calls to cl-format, + do it like in this example: (defn print-table [aseq column-width] (binding [*out* (get-pretty-writer *out*)] (doseq [row aseq] (doseq [col row] (cl-format true \"~4D~7,vT\" col column-width)) (prn)))) -Now when you run: + Now when you run: user> (print-table (map #(vector % (* % %) (* % % %)) (range 1 11)) 8) -It prints a table of squares and cubes for the numbers from 1 to 10: - 1 1 1 - 2 4 8 - 3 9 27 - 4 16 64 - 5 25 125 - 6 36 216 - 7 49 343 - 8 64 512 - 9 81 729 + It prints a table of squares and cubes for the numbers from 1 to 10: + 1 1 1 + 2 4 8 + 3 9 27 + 4 16 64 + 5 25 125 + 6 36 216 + 7 49 343 + 8 64 512 + 9 81 729 10 100 1000" [writer] (binding [pprint/*print-right-margin* @print-right-margin pprint/*print-miser-width* @print-miser-width] (pprint/get-pretty-writer writer))) +(def current-length #'pprint/*current-length*) + +(defn write-out + "Write an object to *out* subject to the current bindings of the printer control + variables. Use the kw-args argument to override individual variables for this call (and + any recursive calls). + *out* must be a PrettyWriter if pretty printing is enabled. This is the responsibility + of the caller. + This method is primarily intended for use by pretty print dispatch functions that + already know that the pretty printer will have set up their environment appropriately. + Normal library clients should use the standard \"write\" interface. " + {:added "1.2"} + [object] + (let [length-reached (and + @current-length + @sci/print-length + (>= @current-length @sci/print-length))] + (if-not pprint/*print-pretty* + (pr object) + (if length-reached + (print "...") + (do + (when @current-length + (.set ^clojure.lang.Var current-length (inc @current-length))) + (print-pprint-dispatch object)))) + length-reached)) + (def pprint-namespace {'pp (sci/copy-var pprint/pp pprint-ns) 'pprint (sci/copy-var pprint pprint-ns) @@ -180,6 +209,7 @@ It prints a table of squares and cubes for the numbers from 1 to 10: 'with-pprint-dispatch (sci/copy-var pprint/with-pprint-dispatch pprint-ns) '*print-pprint-dispatch* print-pprint-dispatch '*print-miser-width* print-miser-width - 'get-pretty-writer (sci/copy-var get-pretty-writer pprint-ns)}) + 'get-pretty-writer (sci/copy-var get-pretty-writer pprint-ns) + 'write-out (sci/copy-var write-out pprint-ns)}) (vreset! patched? true) diff --git a/src/babashka/impl/print_deps.clj b/src/babashka/impl/print_deps.clj index e11703b5..45e2b3f8 100644 --- a/src/babashka/impl/print_deps.clj +++ b/src/babashka/impl/print_deps.clj @@ -20,6 +20,7 @@ :git/sha "52a6037bd4b632bffffb04394fb4efd0cdab6b1e"}) deps (dissoc deps 'borkdude/sci + 'org.babashka/sci 'borkdude/graal.locking 'org.postgresql/postgresql 'babashka/clojure-lanterna diff --git a/src/babashka/impl/process.clj b/src/babashka/impl/process.clj index 7a457196..6bc455cc 100644 --- a/src/babashka/impl/process.clj +++ b/src/babashka/impl/process.clj @@ -27,4 +27,6 @@ 'tokenize (copy-var process/tokenize tns) '*defaults* defaults 'destroy (copy-var process/destroy tns) - 'destroy-tree (copy-var process/destroy-tree tns)}) + 'destroy-tree (copy-var process/destroy-tree tns) + 'exec (copy-var process/exec tns) + 'shell (copy-var process/shell tns)}) diff --git a/src/babashka/impl/proxy.clj b/src/babashka/impl/proxy.clj index 1c0018d4..f40b7ab1 100644 --- a/src/babashka/impl/proxy.clj +++ b/src/babashka/impl/proxy.clj @@ -74,6 +74,11 @@ (proxy [javax.net.ssl.HostnameVerifier] [] (verify [host-name session] ((method-or-bust methods 'verify) this host-name session))) + ["sun.misc.SignalHandler" #{}] + (proxy [sun.misc.SignalHandler] [] + (handle [sig] + ((method-or-bust methods 'handle) this sig))) + ["java.io.PipedInputStream" #{}] (proxy [java.io.PipedInputStream] [] (available [] ((method-or-bust methods 'available) this)) @@ -81,8 +86,10 @@ (read ([] ((method-or-bust methods 'read) this)) - ([b off len] - ((method-or-bust methods 'read) this b off len))) + ([bs] + ((method-or-bust methods 'read) this bs)) + ([bs off len] + ((method-or-bust methods 'read) this bs off len))) (receive [b] ((method-or-bust methods 'receive) this b))) ["java.io.PipedOutputStream" #{}] @@ -92,7 +99,9 @@ (flush [] ((method-or-bust methods 'flush) this)) (write ([b] ((method-or-bust methods 'write) this b)) - ([b off len] ((method-or-bust methods 'write) this b off len))))))) + ([b off len] ((method-or-bust methods 'write) this b off len)))) + , ;; keep this for merge friendliness + ))) (defn class-sym [c] (symbol (class-name c))) diff --git a/src/babashka/impl/reify.clj b/src/babashka/impl/reify.clj index f9f5895a..63dbf9e4 100644 --- a/src/babashka/impl/reify.clj +++ b/src/babashka/impl/reify.clj @@ -161,7 +161,9 @@ java.util.Iterator {hasNext [[this]] - next [[this]]} + next [[this]] + remove [[this]] + forEachRemaining [[this action]]} java.util.function.Function {apply [[this t]]} @@ -183,4 +185,7 @@ resolveAlias [[this sym]] resolveVar [[this sym]]} + sun.misc.SignalHandler + {handle [[this signal]]} + })) diff --git a/src/babashka/impl/repl.clj b/src/babashka/impl/repl.clj index 9cbf4d95..e1083b5b 100644 --- a/src/babashka/impl/repl.clj +++ b/src/babashka/impl/repl.clj @@ -9,7 +9,7 @@ [sci.impl.interpreter :refer [eval-form]] [sci.impl.io :as sio] [sci.impl.parser :as parser] - [sci.impl.vars :as vars])) + [sci.impl.utils :as utils])) (set! *warn-on-reflection* true) @@ -80,7 +80,7 @@ (let [ret (eval-form sci-ctx expr)] ret)))) :need-prompt (or need-prompt (fn [] true)) - :prompt (or prompt #(sio/printf "%s=> " (vars/current-ns-name))) + :prompt (or prompt #(sio/printf "%s=> " (utils/current-ns-name))) :flush (or flush sio/flush) :print (or print sio/prn) :caught (or caught repl-caught))))) diff --git a/src/babashka/impl/server.clj b/src/babashka/impl/server.clj index 687056a4..1bb01f2b 100644 --- a/src/babashka/impl/server.clj +++ b/src/babashka/impl/server.clj @@ -21,4 +21,5 @@ {'repl (sci/copy-var socket-repl/repl sns) 'prepl (sci/copy-var prepl sns) 'io-prepl (sci/copy-var io-prepl sns) - 'start-server (sci/copy-var start-server sns)}) + 'start-server (sci/copy-var start-server sns) + 'stop-server (sci/copy-var server/stop-server sns)}) diff --git a/src/babashka/impl/tasks.clj b/src/babashka/impl/tasks.clj index 2b376f0d..a5d9592c 100644 --- a/src/babashka/impl/tasks.clj +++ b/src/babashka/impl/tasks.clj @@ -1,15 +1,19 @@ (ns babashka.impl.tasks - (:require [babashka.deps :as deps] - [babashka.impl.common :refer [ctx bb-edn debug]] - [babashka.process :as p] - [clojure.core.async :refer [SciNamespace 'clojure.tools.cli nil)) +(def cli-ns (sci/create-ns 'clojure.tools.cli nil)) (def tools-cli-namespace {'format-lines (copy-var tools.cli/format-lines cli-ns) diff --git a/src/babashka/main.clj b/src/babashka/main.clj index 41575a6e..e5bd9b4b 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -7,10 +7,12 @@ [babashka.fs :as fs] [babashka.impl.bencode :refer [bencode-namespace]] [babashka.impl.cheshire :refer [cheshire-core-namespace]] - [babashka.impl.classes :as classes] + [babashka.impl.classes :as classes :refer [classes-namespace]] [babashka.impl.classpath :as cp :refer [classpath-namespace]] + [babashka.impl.cli :as cli] [babashka.impl.clojure.core :as core :refer [core-extras]] - [babashka.impl.clojure.core.async :refer [async-namespace async-protocols-namespace]] + [babashka.impl.clojure.core.async :refer [async-namespace + async-protocols-namespace]] [babashka.impl.clojure.instant :as instant] [babashka.impl.clojure.java.browse :refer [browse-namespace]] [babashka.impl.clojure.java.io :refer [io-namespace]] @@ -18,7 +20,8 @@ [babashka.impl.clojure.main :as clojure-main :refer [demunge]] [babashka.impl.clojure.math :refer [math-namespace]] [babashka.impl.clojure.stacktrace :refer [stacktrace-namespace]] - [babashka.impl.clojure.tools.reader-types :refer [edn-namespace reader-types-namespace]] + [babashka.impl.clojure.tools.reader-types :refer [edn-namespace + reader-types-namespace]] [babashka.impl.clojure.zip :refer [zip-namespace]] [babashka.impl.common :as common] [babashka.impl.core :as bbcore] @@ -26,16 +29,18 @@ [babashka.impl.data :as data] [babashka.impl.datafy :refer [datafy-namespace]] [babashka.impl.deps :as deps :refer [deps-namespace]] + [babashka.impl.edamame :refer [edamame-namespace]] [babashka.impl.error-handler :refer [error-handler]] [babashka.impl.features :as features] [babashka.impl.fs :refer [fs-namespace]] + [babashka.impl.nrepl-server :refer [nrepl-server-namespace]] [babashka.impl.pods :as pods] [babashka.impl.pprint :refer [pprint-namespace]] [babashka.impl.print-deps :as print-deps] [babashka.impl.process :refer [process-namespace]] [babashka.impl.protocols :refer [protocols-namespace]] [babashka.impl.proxy :refer [proxy-fn]] - [babashka.impl.reify :refer [reify-fn]] + [babashka.impl.reify2 :refer [reify-fn]] [babashka.impl.repl :as repl] [babashka.impl.rewrite-clj :as rewrite] [babashka.impl.server :refer [clojure-core-server-namespace]] @@ -84,6 +89,7 @@ (sci/alter-var-root sci/in (constantly *in*)) (sci/alter-var-root sci/out (constantly *out*)) (sci/alter-var-root sci/err (constantly *err*)) +(sci/alter-var-root sci/read-eval (constantly *read-eval*)) (set! *warn-on-reflection* true) ;; To detect problems when generating the image, run: @@ -115,7 +121,8 @@ "socket-repl" "nrepl-server" "describe" - "print-deps") true + "print-deps" + "prepare") true false)) (defn print-error [& msgs] @@ -138,10 +145,11 @@ Global opts: -cp, --classpath Classpath to use. Overrides bb.edn classpath. --debug Print debug information and internal stacktrace in case of exception. - --force Passes -Sforce to deps.clj, forcing recalculation of the classpath. --init Load file after any preloads and prior to evaluation/subcommands. --config Replacing bb.edn with file. Relative paths are resolved relative to file. --deps-root Treat dir as root of relative paths in config. + -Sforce Force recalculation of the classpath (don't use the cache) + -Sdeps Deps data to use as the last deps file to be merged Help: @@ -155,6 +163,7 @@ Evaluation: -e, --eval Evaluate an expression. -f, --file Evaluate a file. -m, --main Call the -main function from a namespace or call a fully qualified var. + -x, --exec Call the fully qualified var. Args are parsed by babashka CLI. REPL: @@ -175,6 +184,7 @@ Packaging: uberscript [eval-opt] Collect all required namespaces from the classpath into a single file. Accepts additional eval opts, like `-m`. uberjar [eval-opt] Similar to uberscript but creates jar file. + prepare Download deps & pods defined in bb.edn and cache their metadata. Only an optimization, this will happen on demand when needed. In- and output flags (only to be used with -e one-liners): @@ -244,6 +254,7 @@ Use bb run --help to show this help output. :feature/yaml %s :feature/jdbc %s :feature/postgresql %s + :feature/sqlite %s :feature/hsqldb %s :feature/oracledb %s :feature/httpkit-client %s @@ -262,8 +273,8 @@ Use bb run --help to show this help output. features/xml? features/yaml? features/jdbc? - features/sqlite? features/postgresql? + features/sqlite? features/hsqldb? features/oracledb? features/httpkit-client? @@ -309,7 +320,9 @@ Use bb run --help to show this help output. (def aliases (cond-> - '{tools.cli clojure.tools.cli + '{str clojure.string + set clojure.set + tools.cli clojure.tools.cli edn clojure.edn wait babashka.wait signal babashka.signal @@ -333,6 +346,11 @@ Use bb run --help to show this help output. (def clojure-main-ns (sci/create-ns 'clojure.main)) +(defn catvec [& xs] + (into [] cat xs)) + +(def sci-ns (sci/create-ns 'sci.core)) + (def namespaces (cond-> {'user {'*input* (reify @@ -342,6 +360,7 @@ Use bb run --help to show this help output. 'clojure.tools.cli tools-cli-namespace 'clojure.java.shell shell-namespace 'babashka.core bbcore/core-namespace + 'babashka.nrepl.server nrepl-server-namespace 'babashka.wait wait-namespace 'babashka.signal signal-ns 'clojure.java.io io-namespace @@ -356,10 +375,12 @@ Use bb run --help to show this help output. 'repl (sci/new-var 'repl (fn [& opts] (let [opts (apply hash-map opts)] - (repl/start-repl! @common/ctx opts))) {:ns clojure-main-ns})} + (repl/start-repl! @common/ctx opts))) {:ns clojure-main-ns}) + 'with-bindings (sci/copy-var clojure-main/with-bindings clojure-main-ns)} 'clojure.test t/clojure-test-namespace 'clojure.math math-namespace 'babashka.classpath classpath-namespace + 'babashka.classes classes-namespace 'clojure.pprint pprint-namespace 'babashka.curl curl-namespace 'babashka.fs fs-namespace @@ -380,7 +401,21 @@ Use bb run --help to show this help output. 'rewrite-clj.paredit rewrite/paredit-namespace 'rewrite-clj.parser rewrite/parser-namespace 'rewrite-clj.zip rewrite/zip-namespace - 'rewrite-clj.zip.subedit rewrite/subedit-namespace} + 'rewrite-clj.zip.subedit rewrite/subedit-namespace + 'clojure.core.rrb-vector (if features/rrb-vector? + @(resolve 'babashka.impl.rrb-vector/rrb-vector-namespace) + {'catvec (sci/copy-var catvec + (sci/create-ns 'clojure.core.rrb-vector))}) + 'edamame.core edamame-namespace + 'sci.core {'format-stacktrace (sci/copy-var sci/format-stacktrace sci-ns) + 'stacktrace (sci/copy-var sci/stacktrace sci-ns) + ;; 'eval-string (sci/copy-var sci/eval-string sci-ns) + ;; 'eval-string* (sci/copy-var sci/eval-string* sci-ns) + ;; 'init (sci/copy-var sci/init sci-ns) + ;; 'fork (sci/copy-var sci/fork sci-ns) + } + 'babashka.cli cli/cli-namespace + } features/xml? (assoc 'clojure.data.xml @(resolve 'babashka.impl.xml/xml-namespace) 'clojure.data.xml.event @(resolve 'babashka.impl.xml/xml-event-namespace) 'clojure.data.xml.tree @(resolve 'babashka.impl.xml/xml-tree-namespace)) @@ -518,9 +553,6 @@ Use bb run --help to show this help output. ("--verbose") (recur (next options) (assoc opts-map :verbose? true)) - ("--force") (recur (next options) - (assoc opts-map - :force? true)) ("--describe") (recur (next options) (assoc opts-map :describe? true)) @@ -614,6 +646,12 @@ Use bb run --help to show this help output. :command-line-args (if (= "--" (second options)) (nthrest options 2) (rest options)))) + ("--exec", "-x",) + (let [options (next options)] + (assoc opts-map :exec (first options) + :command-line-args (if (= "--" (second options)) + (nthrest options 2) + (rest options)))) ("--run") (parse-run-opts opts-map (next options)) ("--tasks") @@ -621,6 +659,10 @@ Use bb run --help to show this help output. :command-line-args (next options)) ("--print-deps") (parse-print-deps-opts opts-map (next options)) + ("--prepare") + (let [options (next options)] + (recur (next options) + (assoc opts-map :prepare true))) ;; fallback (if (and opts-map (some opts-map [:file :jar :socket-repl :expressions :main :run])) @@ -655,6 +697,12 @@ Use bb run --help to show this help output. ("--init") (recur (nnext options) (assoc opts-map :init (second options))) + ("--force" "-Sforce") + (recur (next options) (assoc opts-map :force? true)) + + ("-Sdeps") + (recur (nnext options) (assoc opts-map :merge-deps (second options))) + ("--config") (recur (nnext options) (assoc opts-map :config (second options))) @@ -700,11 +748,32 @@ Use bb run --help to show this help output. (def pod-namespaces (volatile! {})) +(defn download-only? + "If we're preparing pods for another OS / arch, don't try to run them." + [] + (let [env-os-name (System/getenv "BABASHKA_PODS_OS_NAME") + env-os-name-present? (not (str/blank? env-os-name)) + sys-os-name (System/getProperty "os.name") + env-os-arch (System/getenv "BABASHKA_PODS_OS_ARCH") + env-os-arch-present? (not (str/blank? env-os-arch)) + sys-os-arch (System/getProperty "os.arch")] + (when @common/debug + (binding [*out* *err*] + (println "System OS name:" sys-os-name) + (when env-os-name-present? (println "BABASHKA_PODS_OS_NAME:" env-os-name)) + (println "System OS arch:" sys-os-arch) + (when env-os-arch-present? (println "BABASHKA_PODS_OS_ARCH:" env-os-arch)))) + (cond + env-os-name-present? (not= env-os-name sys-os-name) + env-os-arch-present? (not= env-os-arch sys-os-arch)))) + (defn exec [cli-opts] (binding [*unrestricted* true] (sci/binding [core/warn-on-reflection @core/warn-on-reflection + core/unchecked-math @core/unchecked-math core/data-readers @core/data-readers - sci/ns @sci/ns] + sci/ns @sci/ns + sci/print-length @sci/print-length] (let [{version-opt :version :keys [:shell-in :edn-in :shell-out :edn-out :help :file :command-line-args @@ -714,11 +783,13 @@ Use bb run --help to show this help output. :main :uberscript :describe? :jar :uberjar :clojure :doc :run :list-tasks - :print-deps]} + :print-deps :prepare] + exec-fn :exec} cli-opts _ (when debug (vreset! common/debug true)) _ (do ;; set properties (when main (System/setProperty "babashka.main" main)) + ;; TODO: what about exec here? (System/setProperty "babashka.version" version)) read-next (fn [*in*] (if (pipe-signal-received?) @@ -750,40 +821,45 @@ Use bb run --help to show this help output. _ (when jar (cp/add-classpath jar)) load-fn (fn [{:keys [:namespace :reload]}] - (or (when-let [{:keys [:loader]} - @cp/cp-state] - (if ;; ignore built-in namespaces when uberscripting, unless with :reload - (and uberscript - (not reload) - (or (contains? namespaces namespace) - (contains? sci-namespaces/namespaces namespace))) - "" - (when-let [res (cp/source-for-namespace loader namespace nil)] - (if uberscript - (do (swap! uberscript-sources conj (:source res)) - (uberscript/uberscript {:ctx @common/ctx - :expressions [(:source res)]}) - {}) - res)))) - (if-let [pod (get @pod-namespaces namespace)] - (if uberscript - (do - (swap! uberscript-sources conj - (format - "(babashka.pods/load-pod '%s \"%s\" '%s)\n" - (:pod-spec pod) (:version (:opts pod)) - (dissoc (:opts pod) - :version :metadata))) - {}) - (pods/load-pod (:pod-spec pod) (:opts pod))) - (case namespace - clojure.spec.alpha - (binding [*out* *err*] - (println "[babashka] WARNING: Use the babashka-compatible version of clojure.spec.alpha, available here: https://github.com/babashka/spec.alpha")) - clojure.core.specs.alpha - (binding [*out* *err*] - (println "[babashka] WARNING: clojure.core.specs.alpha is removed from the classpath, unless you explicitly add the dependency.")) - nil)))) + (let [{:keys [loader]} + @cp/cp-state] + (or + (when ;; ignore built-in namespaces when uberscripting, unless with :reload + (and uberscript + (not reload) + (or (contains? namespaces namespace) + (contains? sci-namespaces/namespaces namespace))) + "") + ;; pod namespaces go before namespaces from source, + ;; unless reload is used + (when-not reload + (when-let [pod (get @pod-namespaces namespace)] + (if uberscript + (do + (swap! uberscript-sources conj + (format + "(babashka.pods/load-pod '%s \"%s\" '%s)\n" + (:pod-spec pod) (:version (:opts pod)) + (dissoc (:opts pod) + :version :metadata))) + {}) + (pods/load-pod (:pod-spec pod) (:opts pod))))) + (when loader + (when-let [res (cp/source-for-namespace loader namespace nil)] + (if uberscript + (do (swap! uberscript-sources conj (:source res)) + (uberscript/uberscript {:ctx @common/ctx + :expressions [(:source res)]}) + {}) + res))) + (case namespace + clojure.spec.alpha + (binding [*out* *err*] + (println "[babashka] WARNING: Use the babashka-compatible version of clojure.spec.alpha, available here: https://github.com/babashka/spec.alpha")) + clojure.core.specs.alpha + (binding [*out* *err*] + (println "[babashka] WARNING: clojure.core.specs.alpha is removed from the classpath, unless you explicitly add the dependency.")) + nil)))) main (if (and jar (not main)) (when-let [res (cp/getResource (cp/loader jar) @@ -809,7 +885,8 @@ Use bb run --help to show this help output. sci-ctx (sci/init opts) _ (vreset! common/ctx sci-ctx) _ (when-let [pods (:pods @common/bb-edn)] - (let [pod-metadata (pods/load-pods-metadata pods)] + (when-let [pod-metadata (pods/load-pods-metadata + pods {:download-only (download-only?)})] (vreset! pod-namespaces pod-metadata))) preloads (some-> (System/getenv "BABASHKA_PRELOADS") (str/trim)) [expressions exit-code] @@ -823,6 +900,9 @@ Use bb run --help to show this help output. "-main")] [[(format "(ns user (:require [%1$s])) (apply %1$s/%2$s *command-line-args*)" ns var-name)] nil]) + exec-fn + (let [sym (symbol exec-fn)] + [[(cli/exec-fn-snippet sym)] nil]) run (if (:run-help cli-opts) [(print-run-help) 0] (do @@ -882,6 +962,7 @@ Use bb run --help to show this help output. uberjar [nil 0] list-tasks [(tasks/list-tasks sci-ctx) 0] print-deps [(print-deps/print-deps (:print-deps-format cli-opts)) 0] + prepare [nil 0] uberscript [nil (do (uberscript/uberscript {:ctx sci-ctx :expressions expressions}) @@ -890,8 +971,8 @@ Use bb run --help to show this help output. ;; execute code (sci/binding [sci/file abs-path] (try - ; when evaluating expression(s), add in repl-requires so things like - ; pprint and dir are available + ;; when evaluating expression(s), add in repl-requires so things like + ;; pprint and dir are available (sci/eval-form sci-ctx `(apply require (quote ~clojure-main/repl-requires))) (loop [] (let [in (read-next *in*)] @@ -963,20 +1044,31 @@ Use bb run --help to show this help output. (and (= minor-current minor-min) (>= patch-current patch-min))))))) +(defn load-bb-edn [string] + (try (edn/read-string {:default tagged-literal} string) + (catch java.lang.RuntimeException e + (if (re-find #"No dispatch macro for: \"" (.getMessage e)) + (throw (ex-info "Invalid regex literal found in EDN config, use re-pattern instead" {})) + (throw e))))) + (defn main [& args] (let [[args global-opts] (parse-global-opts args) {:keys [:jar] :as file-opt} (when (some-> args first io/file .isFile) (parse-file-opt args global-opts)) config (:config global-opts) + merge-deps (:merge-deps global-opts) abs-path #(-> % io/file .getAbsolutePath) bb-edn-file (cond config (when (fs/exists? config) (abs-path config)) jar (some-> jar cp/loader (cp/resource "META-INF/bb.edn") .toString) :else (when (fs/exists? "bb.edn") (abs-path "bb.edn"))) - bb-edn (when bb-edn-file - (System/setProperty "babashka.config" bb-edn-file) - (let [raw-string (slurp bb-edn-file) - edn (edn/read-string raw-string) + bb-edn (when (or bb-edn-file merge-deps) + (when bb-edn-file (System/setProperty "babashka.config" bb-edn-file)) + (let [raw-string (when bb-edn-file (slurp bb-edn-file)) + edn (when bb-edn-file (load-bb-edn raw-string)) + edn (if merge-deps + (deps/merge-deps [edn (load-bb-edn merge-deps)]) + edn) edn (assoc edn :raw raw-string :file bb-edn-file) @@ -985,6 +1077,7 @@ Use bb run --help to show this help output. (assoc edn :deps-root deps-root) edn)] (vreset! common/bb-edn edn))) + ;; _ (.println System/err (str bb-edn)) min-bb-version (:min-bb-version bb-edn)] (when min-bb-version (when-not (satisfies-min-version? min-bb-version) diff --git a/src/babashka/wait.clj b/src/babashka/wait.clj index 5cbea999..d8c4fe69 100644 --- a/src/babashka/wait.clj +++ b/src/babashka/wait.clj @@ -26,8 +26,9 @@ :wait-for-port.impl/timed-out :wait-for-port.impl/try-again))))] (cond (identical? :wait-for-port.impl/try-again v) - (do (Thread/sleep (or pause 100)) - (recur)) + (let [^long pause (or pause 100)] + (Thread/sleep pause) + (recur)) (identical? :wait-for-port.impl/timed-out v) default :else @@ -51,8 +52,9 @@ :wait-for-path.impl/timed-out :wait-for-path.impl/try-again)))] (cond (identical? :wait-for-path.impl/try-again v) - (do (Thread/sleep (or pause 100)) - (recur)) + (let [^long pause (or pause 100)] + (Thread/sleep pause) + (recur)) (identical? :wait-for-path.impl/timed-out v) default :else diff --git a/test-resources/babashka/exec_test.clj b/test-resources/babashka/exec_test.clj new file mode 100644 index 00000000..6eca718f --- /dev/null +++ b/test-resources/babashka/exec_test.clj @@ -0,0 +1,7 @@ +(ns babashka.exec-test + {:org.babashka/cli {:coerce {:foo []}}}) + +(defn exec-test + {:org.babashka/cli {:coerce {:bar :keyword}}} + [m] + (prn m)) diff --git a/test-resources/lib_tests/babashka/run_all_libtests.clj b/test-resources/lib_tests/babashka/run_all_libtests.clj index 56fcda74..72c9d8fb 100644 --- a/test-resources/lib_tests/babashka/run_all_libtests.clj +++ b/test-resources/lib_tests/babashka/run_all_libtests.clj @@ -1,5 +1,7 @@ (ns babashka.run-all-libtests - (:require [babashka.core :refer [windows?]] + (:require [babashka.classpath :as cp :refer [add-classpath]] + [babashka.core :refer [windows?]] + [babashka.fs :as fs] [clojure.edn :as edn] [clojure.java.io :as io] [clojure.test :as t :refer [*report-counters*]])) @@ -42,7 +44,13 @@ ;; Standard test-runner for libtests (let [lib-tests (edn/read-string (slurp (io/resource "bb-tested-libs.edn")))] - (doseq [{tns :test-namespaces skip-windows :skip-windows} (vals lib-tests)] + (doseq [[libname {tns :test-namespaces skip-windows :skip-windows + :keys [test-paths + git-sha]}] lib-tests] + (let [git-dir (format ".gitlibs/libs/%s/%s" libname git-sha) + git-dir (fs/file (fs/home) git-dir)] + (doseq [p test-paths] + (add-classpath (str (fs/file git-dir p))))) (when-not (and skip-windows (windows?)) (apply test-namespaces tns)))) diff --git a/test-resources/lib_tests/bb-tested-libs.edn b/test-resources/lib_tests/bb-tested-libs.edn index bca25eba..99d4bdab 100644 --- a/test-resources/lib_tests/bb-tested-libs.edn +++ b/test-resources/lib_tests/bb-tested-libs.edn @@ -47,7 +47,7 @@ doric/doric {:git-sha "8747fdce565187a5c368c575cf4ca794084b0a5c", :git-url "https://github.com/joegallo/doric", :test-namespaces (doric.test.core doric.test.readme doric.test.doctest)} com.github.seancorfield/honeysql {:git-sha "6e4e1f6928450788353c181f32474d930d6afe84", :git-url "https://github.com/seancorfield/honeysql", :test-namespaces (honey.sql-test honey.sql.helpers-test honey.sql.postgres-test), :branch "develop"} honeysql/honeysql {:git-sha "1137dd12350afdc30ad4976c3718279581390b36", :git-url "https://github.com/seancorfield/honeysql", :test-namespaces (honeysql.format-test honeysql.core-test), :branch "v1"} - ; skip tests on Windows because of the :compressed thing + ; skip tests on Windows because of the :compressed thing babashka/babashka.curl {:git-url "https://github.com/babashka/babashka.curl", :test-namespaces [babashka.curl-test], :skip-windows true, :manually-added true} http-kit/http-kit {:git-url "https://github.com/http-kit/http-kit", :test-namespaces [httpkit.client-test], :manually-added true} org.clojure/core.match {:git-url "https://github.com/clojure/core.match", :test-namespaces [core-match.core-tests], :manually-added true} @@ -112,4 +112,59 @@ com.layerware/hugsql-core {:test-namespaces (hugsql.babashka-test)} com.github.seancorfield/expectations {:git-url "https://github.com/clojure-expectations/clojure-test", :test-namespaces (expectations.clojure.test-test), :git-sha "b30fefd97d9eb7d1f47e06956521f354cb926b03"} com.rpl/specter {:git-url "https://github.com/redplanetlabs/specter", :test-namespaces (com.rpl.specter.cljs-test-helpers com.rpl.specter.test-helpers com.rpl.specter.core-test com.rpl.specter.zipper-test), :git-sha "67e86806020b9d02fbca8cdb1efad3002fc81a32"} -} + com.github.askonomm/clarktown {:git-url "https://github.com/askonomm/clarktown", :test-namespaces (clarktown.core-test clarktown.parsers.horizontal-line-block-test clarktown.parsers.italic-test clarktown.parsers.link-and-image-test clarktown.parsers.empty-block-test clarktown.parsers.inline-code-test clarktown.parsers.heading-block-test clarktown.parsers.bold-test clarktown.parsers.quote-block-test clarktown.parsers.code-block-test clarktown.parsers.strikethrough-test), :git-sha "059bfa7bd9bfdde0c75646bf1dfc20d23da8a02c"} + org.clojure/math.numeric-tower {:git-url "https://github.com/clojure/math.numeric-tower", :test-namespaces (clojure.math.test-numeric-tower), :git-sha "97827be66f35feebc3c89ba81c546fef4adc7947"} + prismatic/schema {:test-namespaces [schema.core-test + schema.macros-test + schema.coerce-test + schema.experimental.abstract-map-test + schema.test-test + schema.utils-test] + :git-url "https://github.com/plumatic/schema" + :git-sha "6846dc7c3a9df5bfd718f68f183c683ce0f621ff" + :git-tag "schema-1.3.0" + ;; specify for adding tests to classpath + :test-paths ["test/clj" "test/cljc"]} + metosin/malli {:test-namespaces [malli.clj-kondo-test + malli.core-test + malli.destructure-test + malli.dot-test + malli.error-test + malli.experimental-test + ;; malli.generator-test + malli.instrument-test + malli.json-schema-test + malli.plantuml-test + malli.provider-test + malli.registry-test + malli.swagger-test + malli.transform-test + malli.util-test] + :git-url "https://github.com/metosin/malli" + :git-sha "588147ef49b2e41c7d12a8aa994b39c1c6fedd99" + :git-tag "0.8.9" + ;; specify for adding tests to classpath + :test-paths ["test"]} + meander/epsilon {:test-namespaces [meander.epsilon-test + meander.defsyntax-test + meander.syntax.epsilon-test + meander.substitute.epsilon-test + meander.strategy.epsilon-test + meander.matrix.epsilon-test + meander.match.epsilon-test + meander.match.ir.epsilon-test + meander.match.check.epsilon-test + meander.interpreter.epsilon-test + meander.defsyntax-test.gh-145] + :test-paths ["test"] + :git-url "https://github.com/noprompt/meander" + :git-sha "55f5ce70e6ef717e95c58260f6bc725d70c0cb6d"} + cc.qbits/auspex {:git-url "https://github.com/mpenet/auspex" + :git-sha "1a9d7427e60e1a434a764aa820d1c53f7e22504a" + :test-paths ["test"] + :test-namespaces [qbits.auspex-test]} + exoscale/interceptor {:git-url "https://github.com/exoscale/interceptor" + :git-sha "ca115fe00a0abf3a2f78452ab309c3aa4c00fc4e" + :test-paths ["test"] + :test-namespaces [exoscale.interceptor-test]} + } diff --git a/test-resources/lib_tests/clarktown/core.md b/test-resources/lib_tests/clarktown/core.md new file mode 100644 index 00000000..6a5b2f17 --- /dev/null +++ b/test-resources/lib_tests/clarktown/core.md @@ -0,0 +1,93 @@ +Lorem ipsum dolor **sit** amet. Lorem ipsum *dolor* _sit_ __amet__. + +There's a [link here](https://example.com/that_has_things?!???!#in-it). + +1. List item +2. Another list item + 1. Sub list item + 2. Another sub list item + 1. Sub sub list item + 3. Continuing sub list item +3. Continuing list item + +```javascript +// Detect horizontal line block +function isHorizontalLineBlock(block) { + return block === "***"; +} + +// Render horizontal line block +function horizontalLineBlock(block) { + return `
`; +} + +// Compose an array of parsers +const parsers = [{ + matcher: isHorizontalLineBlock, + renderers: [horizontalLineBlock] +}]; + +// And finally, our parser itself +function markdownToHTML(markdown) { + // Create blocks + const blocks = content.split(/\n\n/); + + // Parse blocks + const parsedBlocks = blocks.map((block) => { + // Let's find a parser that has a matcher that matches + const parser = parsers.find((parser) => parser.matcher(block)); + + // If match was found, let's run our renderers over `block` + if (parser) { + for (const renderer of match.renderers) { + block = renderer(block); + } + } + + return block; + }); + + // And at last, join the blocks together for one big block. + return parsedBlocks.join(""); +} +``` + +- Test 123 +- Test 223 + - Test 334 + 1. Test test + +This is ___bold italic text___ and ***this is also***. *What about italic text that **has bold text***? + +## Hi there, world! + +* List item +* Another list ~~item~~ + * Sub list item + * Another sub list item + * Sub sub list item + * Continuing sub list item +* Continuing list item + +*** + +* List item +* Another list item + * Sub list item + * Another sub list item + 1. Sub sub list item + 2. Continuing sub list item +* Continuing list item + +This is a H1 heading with settext +================================= + +And this is a H2 heading with settext +------------------------------------- + +Testing paragraph right before a code block +``` +code goes here +``` +# Heading goes here +Paragraph right after heading diff --git a/test-resources/lib_tests/clarktown/core_result.html b/test-resources/lib_tests/clarktown/core_result.html new file mode 100644 index 00000000..d604bf58 --- /dev/null +++ b/test-resources/lib_tests/clarktown/core_result.html @@ -0,0 +1,69 @@ +

Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.

+ +

There's a link here.

+ +
  1. List item
  2. Another list item
    1. Sub list item
    2. Another sub list item
      1. Sub sub list item
    3. Continuing sub list item
  3. Continuing list item
+ +
// Detect horizontal line block
+function isHorizontalLineBlock(block) {
+  return block === "***";
+}
+
+// Render horizontal line block
+function horizontalLineBlock(block) {
+  return `<hr>`;
+}
+
+// Compose an array of parsers
+const parsers = [{
+  matcher: isHorizontalLineBlock,
+  renderers: [horizontalLineBlock]
+}];
+
+// And finally, our parser itself
+function markdownToHTML(markdown) {
+  // Create blocks
+  const blocks = content.split(/\n\n/);
+
+  // Parse blocks
+  const parsedBlocks = blocks.map((block) => {
+    // Let's find a parser that has a matcher that matches
+    const parser = parsers.find((parser) => parser.matcher(block));
+
+    // If match was found, let's run our renderers over `block`
+    if (parser) {
+      for (const renderer of match.renderers) {
+        block = renderer(block);
+      }
+    }
+
+    return block;
+  });
+
+  // And at last, join the blocks together for one big block.
+  return parsedBlocks.join("");
+}
+ +
  • Test 123
  • Test 223
    • Test 334
      1. Test test
+ +

This is bold italic text and this is also. What about italic text that has bold text?

+ +

Hi there, world!

+ +
  • List item
  • Another list item
    • Sub list item
    • Another sub list item
      • Sub sub list item
      • Continuing sub list item
  • Continuing list item
+ +
+ +
  • List item
  • Another list item
    • Sub list item
    • Another sub list item
      1. Sub sub list item
      2. Continuing sub list item
  • Continuing list item
+ +

This is a H1 heading with settext

+ +

And this is a H2 heading with settext

+ +

Testing paragraph right before a code block

+ +
code goes here
+ +

Heading goes here

+ +

Paragraph right after heading

diff --git a/test-resources/lib_tests/clarktown/core_test.clj b/test-resources/lib_tests/clarktown/core_test.clj new file mode 100644 index 00000000..86ca1765 --- /dev/null +++ b/test-resources/lib_tests/clarktown/core_test.clj @@ -0,0 +1,15 @@ +(ns clarktown.core-test + (:require + ;; BB-TEST-PATCH: require clojure.string for split-lines patch below + [clojure.string :as str] + [clojure.test :refer [deftest testing is]] + [clojure.java.io :as io] + [clarktown.core :as core])) + + +(deftest overall-test + (testing "Overall" + ;; BB-TEST-PATCH: library uses hard-coded \n, so using split-lines for platform-agnostic testing + ;; BB-TEST-PATCH: change file paths to match bb folder structure (and copy resource files) + (is (= (str/split-lines (core/render (slurp (io/file (io/resource "clarktown/core.md"))))) + (str/split-lines (slurp (io/file (io/resource "clarktown/core_result.html")))))))) diff --git a/test-resources/lib_tests/clarktown/parsers/bold_test.clj b/test-resources/lib_tests/clarktown/parsers/bold_test.clj new file mode 100644 index 00000000..a082d418 --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/bold_test.clj @@ -0,0 +1,18 @@ +(ns clarktown.parsers.bold-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.parsers.bold :as bold])) + + +(deftest bold-test + (testing "Creating bold text with two surrounding asterisk characters" + (is (= "This is bold." + (bold/render "**This is bold.**" nil)))) + + (testing "Creating bold text with two surrounding underscore characters" + (is (= "This is bold." + (bold/render "__This is bold.__" nil)))) + + (testing "Creating bold text with both underscores and asterisks mixed" + (is (= "Hi, my name is John, what is your name?" + (bold/render "Hi, my name is **John**, what is __your name?__" nil))))) \ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/code_block.md b/test-resources/lib_tests/clarktown/parsers/code_block.md new file mode 100644 index 00000000..8e6f863f --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/code_block.md @@ -0,0 +1,41 @@ +```javascript +// Detect horizontal line block +function isHorizontalLineBlock(block) { + return block === "***"; +} + +// Render horizontal line block +function horizontalLineBlock(block) { + return `
`; +} + +// Compose an array of parsers +const parsers = [{ + matcher: isHorizontalLineBlock, + renderers: [horizontalLineBlock] +}]; + +// And finally, our parser itself +function markdownToHTML(markdown) { + // Create blocks + const blocks = content.split(/\n\n/); + + // Parse blocks + const parsedBlocks = blocks.map((block) => { + // Let's find a parser that has a matcher that matches + const parser = parsers.find((parser) => parser.matcher(block)); + + // If match was found, let's run our renderers over `block` + if (parser) { + for (const renderer of match.renderers) { + block = renderer(block); + } + } + + return block; + }); + + // And at last, join the blocks together for one big block. + return parsedBlocks.join(""); +} +``` \ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/code_block_no_language.md b/test-resources/lib_tests/clarktown/parsers/code_block_no_language.md new file mode 100644 index 00000000..dbba1f11 --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/code_block_no_language.md @@ -0,0 +1,41 @@ +``` +// Detect horizontal line block +function isHorizontalLineBlock(block) { + return block === "***"; +} + +// Render horizontal line block +function horizontalLineBlock(block) { + return `
`; +} + +// Compose an array of parsers +const parsers = [{ + matcher: isHorizontalLineBlock, + renderers: [horizontalLineBlock] +}]; + +// And finally, our parser itself +function markdownToHTML(markdown) { + // Create blocks + const blocks = content.split(/\n\n/); + + // Parse blocks + const parsedBlocks = blocks.map((block) => { + // Let's find a parser that has a matcher that matches + const parser = parsers.find((parser) => parser.matcher(block)); + + // If match was found, let's run our renderers over `block` + if (parser) { + for (const renderer of match.renderers) { + block = renderer(block); + } + } + + return block; + }); + + // And at last, join the blocks together for one big block. + return parsedBlocks.join(""); +} +``` \ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/code_block_no_language_result.html b/test-resources/lib_tests/clarktown/parsers/code_block_no_language_result.html new file mode 100644 index 00000000..0512d3eb --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/code_block_no_language_result.html @@ -0,0 +1,39 @@ +
// Detect horizontal line block
+function isHorizontalLineBlock(block) {
+  return block === "***";
+}
+
+// Render horizontal line block
+function horizontalLineBlock(block) {
+  return `<hr>`;
+}
+
+// Compose an array of parsers
+const parsers = [{
+  matcher: isHorizontalLineBlock,
+  renderers: [horizontalLineBlock]
+}];
+
+// And finally, our parser itself
+function markdownToHTML(markdown) {
+  // Create blocks
+  const blocks = content.split(/\n\n/);
+
+  // Parse blocks
+  const parsedBlocks = blocks.map((block) => {
+    // Let's find a parser that has a matcher that matches
+    const parser = parsers.find((parser) => parser.matcher(block));
+
+    // If match was found, let's run our renderers over `block`
+    if (parser) {
+      for (const renderer of match.renderers) {
+        block = renderer(block);
+      }
+    }
+
+    return block;
+  });
+
+  // And at last, join the blocks together for one big block.
+  return parsedBlocks.join("");
+}
\ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/code_block_result.html b/test-resources/lib_tests/clarktown/parsers/code_block_result.html new file mode 100644 index 00000000..21b92144 --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/code_block_result.html @@ -0,0 +1,39 @@ +
// Detect horizontal line block
+function isHorizontalLineBlock(block) {
+  return block === "***";
+}
+
+// Render horizontal line block
+function horizontalLineBlock(block) {
+  return `<hr>`;
+}
+
+// Compose an array of parsers
+const parsers = [{
+  matcher: isHorizontalLineBlock,
+  renderers: [horizontalLineBlock]
+}];
+
+// And finally, our parser itself
+function markdownToHTML(markdown) {
+  // Create blocks
+  const blocks = content.split(/\n\n/);
+
+  // Parse blocks
+  const parsedBlocks = blocks.map((block) => {
+    // Let's find a parser that has a matcher that matches
+    const parser = parsers.find((parser) => parser.matcher(block));
+
+    // If match was found, let's run our renderers over `block`
+    if (parser) {
+      for (const renderer of match.renderers) {
+        block = renderer(block);
+      }
+    }
+
+    return block;
+  });
+
+  // And at last, join the blocks together for one big block.
+  return parsedBlocks.join("");
+}
\ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/code_block_test.clj b/test-resources/lib_tests/clarktown/parsers/code_block_test.clj new file mode 100644 index 00000000..b965e5fa --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/code_block_test.clj @@ -0,0 +1,18 @@ +(ns clarktown.parsers.code-block-test + (:require + ;; require clojure.string to accomodate line break hack below + [clojure.string :as str] + [clojure.test :refer [deftest testing is]] + [clojure.java.io :as io] + [clarktown.parsers.code-block :as code-block])) + +;; BB-TEST-PATCH: change paths to match folder structure (and copy resource files) +;; BB-TEST-PATCH: use split-lines to make tests platform-agnostic +(deftest code-block-test + (testing "Code block with language specification" + (is (= (str/split-lines (slurp (io/file (io/resource "clarktown/parsers/code_block_result.html")))) + (str/split-lines (code-block/render (slurp (io/file (io/resource "clarktown/parsers/code_block.md"))) nil))))) + + (testing "Code block with NO language specification" + (is (= (str/split-lines (slurp (io/file (io/resource "clarktown/parsers/code_block_no_language_result.html")))) + (str/split-lines (code-block/render (slurp (io/file (io/resource "clarktown/parsers/code_block_no_language.md"))) nil)))))) diff --git a/test-resources/lib_tests/clarktown/parsers/empty_block_test.clj b/test-resources/lib_tests/clarktown/parsers/empty_block_test.clj new file mode 100644 index 00000000..a8d89c48 --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/empty_block_test.clj @@ -0,0 +1,14 @@ +(ns clarktown.parsers.empty-block-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.parsers.empty-block :as empty-block])) + + +(deftest empty-block-test + (testing "Rendering an empty block" + (is (= (empty-block/render "" nil) + ""))) + + (testing "Checking an empty block" + (is (true? (empty-block/is? ""))) + (is (true? (empty-block/is? " "))))) diff --git a/test-resources/lib_tests/clarktown/parsers/heading_block_test.clj b/test-resources/lib_tests/clarktown/parsers/heading_block_test.clj new file mode 100644 index 00000000..9bfff4fd --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/heading_block_test.clj @@ -0,0 +1,44 @@ +(ns clarktown.parsers.heading-block-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.parsers.heading-block :as heading-block])) + + +(deftest hashbang-heading-test + (testing "Hashbang heading block that's a H1" + (is (= "

This is a heading block.

" + (heading-block/render "# This is a heading block." nil)))) + + (testing "Hashbang heading block that's a H2" + (is (= "

This is a heading block.

" + (heading-block/render "## This is a heading block." nil)))) + + (testing "Hashbang heading block that's a H3" + (is (= "

This is a heading block.

" + (heading-block/render "### This is a heading block." nil)))) + + (testing "Hashbang heading block that's a H4" + (is (= "

This is a heading block.

" + (heading-block/render "#### This is a heading block." nil)))) + + (testing "Hashbang heading block that's a H5" + (is (= "
This is a heading block.
" + (heading-block/render "##### This is a heading block." nil))))) + + +(deftest settext-heading-text + (testing "Settext heading block that's a H1" + (is (= "

This is a heading block.

" + (heading-block/render "This is a heading block.\n=========" nil)))) + + (testing "Settext heading block that's a H1 spanning multiple lines" + (is (= "

This is a \nheading block spanning multiple lines.

" + (heading-block/render "This is a \nheading block spanning multiple lines.\n========" nil)))) + + (testing "Settext heading block that's a H2" + (is (= "

This is a heading block.

" + (heading-block/render "This is a heading block.\n---------" nil)))) + + (testing "Settext heading block that's a H2 spanning multiple lines" + (is (= "

This is a \nheading block spanning multiple lines.

" + (heading-block/render "This is a \nheading block spanning multiple lines.\n--------" nil))))) \ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/horizontal_line_block_test.clj b/test-resources/lib_tests/clarktown/parsers/horizontal_line_block_test.clj new file mode 100644 index 00000000..21617b6c --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/horizontal_line_block_test.clj @@ -0,0 +1,21 @@ +(ns clarktown.parsers.horizontal-line-block-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.parsers.horizontal-line-block :as horizontal-line-block])) + + +(deftest horizontal-line-block-test + (testing "Creating a horizontal line" + (is (= "
" + (horizontal-line-block/render "***" nil))) + + (is (= "
" + (horizontal-line-block/render "---" nil)))) + + (testing "Is a horizontal line block" + (is (true? (horizontal-line-block/is? "***"))) + (is (true? (horizontal-line-block/is? " ***"))) + (is (false? (horizontal-line-block/is? "Test *** 123"))) + (is (true? (horizontal-line-block/is? "---"))) + (is (true? (horizontal-line-block/is? " ---"))) + (is (false? (horizontal-line-block/is? "Test --- 123"))))) \ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/inline_code_test.clj b/test-resources/lib_tests/clarktown/parsers/inline_code_test.clj new file mode 100644 index 00000000..028c4b7d --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/inline_code_test.clj @@ -0,0 +1,14 @@ +(ns clarktown.parsers.inline-code-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.parsers.inline-code :as inline-code])) + + +(deftest inline-code-test + (testing "Creating inline code text" + (is (= "This is inline code." + (inline-code/render "`This is inline code.`" nil)))) + + (testing "Creating inline-code text in the middle of regular text" + (is (= "This is regular text, mixed with some inline code., and it's great." + (inline-code/render "This is regular text, mixed with `some inline code.`, and it's great." nil))))) \ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/italic_test.clj b/test-resources/lib_tests/clarktown/parsers/italic_test.clj new file mode 100644 index 00000000..8ab13698 --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/italic_test.clj @@ -0,0 +1,18 @@ +(ns clarktown.parsers.italic-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.parsers.italic :as italic])) + + +(deftest italic-test + (testing "Creating italic text with one surrounding asterisk character" + (is (= "This is italic." + (italic/render "*This is italic.*" nil)))) + + (testing "Creating italic text with one surrounding underscore character" + (is (= "This is italic." + (italic/render "_This is italic._" nil)))) + + (testing "Creating italic text with both underscores and asterisks mixed" + (is (= "Hi, my name is John, what is your name?" + (italic/render "Hi, my name is *John*, what is _your name?_" nil))))) \ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/link_and_image_test.clj b/test-resources/lib_tests/clarktown/parsers/link_and_image_test.clj new file mode 100644 index 00000000..348a8f90 --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/link_and_image_test.clj @@ -0,0 +1,23 @@ +(ns clarktown.parsers.link-and-image-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.parsers.link-and-image :as link-and-image])) + + +(deftest link-test + (testing "Creating a link" + (is (= (link-and-image/render "[This is a link](https://example.com)" nil) + "This is a link")) + + (is (= (link-and-image/render "[This-is-a-link](https://example.com)" nil) + "This-is-a-link")) + + (is (= (link-and-image/render "[x] [label](link)" nil) + "[x] label")) + + (is (= (link-and-image/render "[ ] [label](link)" nil) + "[ ] label"))) + + (testing "Creating an image" + (is (= (link-and-image/render "![This is an image](https://example.com)" nil) + "\"This")))) \ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/quote_block_test.clj b/test-resources/lib_tests/clarktown/parsers/quote_block_test.clj new file mode 100644 index 00000000..94553cf1 --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/quote_block_test.clj @@ -0,0 +1,15 @@ +(ns clarktown.parsers.quote-block-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.parsers.quote-block :as quote-block])) + + +(deftest quote-block-block-test + (testing "Creating a quote block line" + (is (= (quote-block/render "> First line\n> second line" nil) + "
First line\nsecond line
"))) + + (testing "Checking a quote block" + (is (true? (quote-block/is? "> Test"))) + (is (true? (quote-block/is? " > Test"))) + (is (true? (quote-block/is? ">"))))) \ No newline at end of file diff --git a/test-resources/lib_tests/clarktown/parsers/strikethrough_test.clj b/test-resources/lib_tests/clarktown/parsers/strikethrough_test.clj new file mode 100644 index 00000000..fdf61888 --- /dev/null +++ b/test-resources/lib_tests/clarktown/parsers/strikethrough_test.clj @@ -0,0 +1,14 @@ +(ns clarktown.parsers.strikethrough-test + (:require + [clojure.test :refer [deftest testing is]] + [clarktown.parsers.strikethrough :as strikethrough])) + + +(deftest strikethrough-test + (testing "Creating strikethrough text" + (is (= (strikethrough/render "~~This is strikethrough text.~~" nil) + "This is strikethrough text."))) + + (testing "Creating strikethrough text mixed with regular text" + (is (= (strikethrough/render "Some other text, ~~This is strikethrough text.~~ And more text." nil) + "Some other text, This is strikethrough text. And more text.")))) \ No newline at end of file diff --git a/test-resources/lib_tests/clojure/math/test_numeric_tower.clj b/test-resources/lib_tests/clojure/math/test_numeric_tower.clj new file mode 100644 index 00000000..ba0ba266 --- /dev/null +++ b/test-resources/lib_tests/clojure/math/test_numeric_tower.clj @@ -0,0 +1,129 @@ +(ns clojure.math.test-numeric-tower + (:use clojure.test + clojure.math.numeric-tower)) + +(deftest test-expt + (are [x y] (= x y) + (expt 2 3) 8 + (expt (expt 2 16) 2) (expt 2 32) + (expt 4/3 2) 16/9 + (expt 2 -10) 1/1024 + (expt 0.5M 2) 0.25M + (expt 5 4.2) (Math/pow 5 4.2) + (expt 5.3 4) (Math/pow 5.3 4) + (expt 5.3 4) (Math/pow 5.3 4) + (expt 2 0) 1 + (expt (java.math.BigInteger. "4") 0) (java.math.BigInteger. "1") + (expt 4M 0) 1M + (expt 8M 1) 8M + (expt 16M 16) 18446744073709551616M)) + +(when-available clojure.lang.BigInt + (deftest test-expt-bigint + (are [x y] (= x y) + (expt (bigint 4) 0) (bigint 1)))) + +(deftest test-abs + (are [x y] (= x y) + (abs -2) 2 + (abs 0) 0 + (abs 5) 5 + (abs 123456789123456789) 123456789123456789 + (abs -123456789123456789) 123456789123456789 + (abs 5/3) 5/3 + (abs -4/3) 4/3 + (abs 4.3M) 4.3M + (abs -4.3M) 4.3M + (abs 2.8) 2.8 + (abs -2.8) 2.8)) + +(deftest test-gcd + (are [x y] (= x y) + (gcd 4 3) 1 + (gcd 24 12) 12 + (gcd 24 27) 3 + (gcd 1 0) 1 + (gcd 0 1) 1 + (gcd 0 0) 0) + (is (thrown? IllegalArgumentException (gcd nil 0))) + (is (thrown? IllegalArgumentException (gcd 0 nil))) + (is (thrown? IllegalArgumentException (gcd 7.0 0)))) + +(deftest test-lcm + (are [x y] (= x y) + (lcm 2 3) 6 + (lcm 3 2) 6 + (lcm -2 3) 6 + (lcm 2 -3) 6 + (lcm -2 -3) 6 + (lcm 4 10) 20 + (lcm 1 0) 0 + (lcm 0 1) 0 + (lcm 0 0) 0) + (is (thrown? IllegalArgumentException (lcm nil 0))) + (is (thrown? IllegalArgumentException (lcm 0 nil))) + (is (thrown? IllegalArgumentException (lcm 7.0 0)))) + +(deftest test-floor + (are [x y] (== x y) + (floor 6) 6 + (floor -6) -6 + (floor 123456789123456789) 123456789123456789 + (floor -123456789123456789) -123456789123456789 + (floor 4/3) 1 + (floor -4/3) -2 + (floor 4.3M) 4 + (floor -4.3M) -5 + (floor 4.3) 4.0 + (floor -4.3) -5.0)) + +(deftest test-ceil + (are [x y] (== x y) + (ceil 6) 6 + (ceil -6) -6 + (ceil 123456789123456789) 123456789123456789 + (ceil -123456789123456789) -123456789123456789 + (ceil 4/3) 2 + (ceil -4/3) -1 + (ceil 4.3M) 5 + (ceil -4.3M) -4 + (ceil 4.3) 5.0 + (ceil -4.3) -4.0)) + +(deftest test-round + (are [x y] (== x y) + (round 6) 6 + (round -6) -6 + (round 123456789123456789) 123456789123456789 + (round -123456789123456789) -123456789123456789 + (round 4/3) 1 + (round 5/3) 2 + (round 5/2) 3 + (round -4/3) -1 + (round -5/3) -2 + (round -5/2) -2 + (round 4.3M) 4 + (round 4.7M) 5 + (round -4.3M) -4 + (round -4.7M) -5 + (round 4.5M) 5 + (round -4.5M) -4 + (round 4.3) 4 + (round 4.7) 5 + (round -4.3) -4 + (round -4.7) -5 + (round 4.5) 5 + (round -4.5) -4)) + +(deftest test-sqrt + (are [x y] (= x y) + (sqrt 9) 3 + (sqrt 16/9) 4/3 + (sqrt 0.25M) 0.5M + (sqrt 2) (Math/sqrt 2))) + +(deftest test-exact-integer-sqrt + (are [x y] (= x y) + (exact-integer-sqrt 15) [3 6] + (exact-integer-sqrt (inc (expt 2 32))) [(expt 2 16) 1] + (exact-integer-sqrt 1000000000000) [1000000 0])) diff --git a/test-resources/lib_tests/honeysql/core_test.cljc b/test-resources/lib_tests/honeysql/core_test.cljc index d1fc2f8b..c5736c6c 100644 --- a/test-resources/lib_tests/honeysql/core_test.cljc +++ b/test-resources/lib_tests/honeysql/core_test.cljc @@ -11,6 +11,17 @@ insert-into with merge-where merge-having]] honeysql.format-test)) +;; BB_TEST_PATCH: must explicitly set data readers +#?(:clj + (do + (require '[honeysql.types]) + (set! *data-readers* {'sql/call honeysql.types/read-sql-call + 'sql/inline honeysql.types/read-sql-inline + 'sql/raw honeysql.types/read-sql-raw + 'sql/param honeysql.types/read-sql-param + 'sql/array honeysql.types/read-sql-array + 'sql/regularize honeysql.format/regularize}))) + ;; TODO: more tests (deftest test-select diff --git a/test-resources/lib_tests/slingshot/slingshot_test.clj b/test-resources/lib_tests/slingshot/slingshot_test.clj index f787a862..f9e7c541 100644 --- a/test-resources/lib_tests/slingshot/slingshot_test.clj +++ b/test-resources/lib_tests/slingshot/slingshot_test.clj @@ -36,7 +36,8 @@ [:class-string e#]) ;; by clojure record type - (catch exception-record e# + ;; BB test patch, exception-record != class?, so this expands into incorrect code + #_(catch exception-record e# [:class-exception-record e#]) ;; by key-value diff --git a/test-resources/line_number_test_test.clj b/test-resources/line_number_test_test.clj new file mode 100644 index 00000000..e3d3fdba --- /dev/null +++ b/test-resources/line_number_test_test.clj @@ -0,0 +1,7 @@ +(ns line-number-test-test + (:require [clojure.test :refer [is deftest run-tests]])) + +(deftest test-is + (is false)) + +(run-tests 'line-number-test-test) diff --git a/test/babashka/bb_edn_test.clj b/test/babashka/bb_edn_test.clj index 69a3a7a7..0422fe2b 100644 --- a/test/babashka/bb_edn_test.clj +++ b/test/babashka/bb_edn_test.clj @@ -200,6 +200,12 @@ (is (thrown-with-msg? Exception #"Cyclic task: b" (bb "run" "b"))))) + (testing "friendly regex literal error handling" + (test-utils/with-config + "{:tasks {something (clojure.string/split \"1-2\" #\"-\")}}" + (is (thrown-with-msg? + Exception #"Invalid regex literal" + (bb "run" "something"))))) (testing "doc" (test-utils/with-config '{:tasks {b {:doc "Beautiful docstring"}}} (let [s (test-utils/bb nil "doc" "b")] @@ -439,3 +445,15 @@ even more stuff here\" (pr-str '{:paths ["test-resources"] :pods {pod/test-pod {:path "test-resources/pod"}}}) (is (= "42\n" (test-utils/bb nil "-m" "pod-tests.local"))))) + +(deftest tag-test + (test-utils/with-config + "{:deps {} + :aliases {:foo {:env-vars {:dude #env \"DUDE\"}}}}" + (is (= 6 (bb "-e" "(+ 1 2 3)"))))) + +(deftest merge-deps-test + (test-utils/with-config + "{:deps {}}" + (is (= {1 {:a 1}} + (bb "-Sdeps" "{:deps {medley/medley {:mvn/version \"1.4.0\"}}}" "-e" "(require 'medley.core) (medley.core/index-by :a [{:a 1}])"))))) diff --git a/test/babashka/classes_test.clj b/test/babashka/classes_test.clj new file mode 100644 index 00000000..31b7872e --- /dev/null +++ b/test/babashka/classes_test.clj @@ -0,0 +1,11 @@ +(ns babashka.classes-test + (:require [babashka.test-utils :as tu] + [clojure.edn :as edn] + [clojure.test :as t :refer [deftest is testing]])) + +(defn bb + [& args] + (edn/read-string (apply tu/bb nil (map pr-str args)))) + +(deftest all-classes-test + (is (true? (bb '(let [classes (babashka.classes/all-classes)] (and (seq classes) (every? class? classes))))))) diff --git a/test/babashka/deps_test.clj b/test/babashka/deps_test.clj index 397a01f9..d3edade2 100644 --- a/test/babashka/deps_test.clj +++ b/test/babashka/deps_test.clj @@ -35,6 +35,7 @@ (bb (pr-str `(do (babashka.deps/add-deps '{:deps {babashka/process {:git/url "https://github.com/babashka/process" :sha "4c6699d06b49773d3e5c5b4c11d3334fb78cc996"}}} {:force true :env {"PATH" (System/getenv "PATH") + "JAVA_HOME" (System/getenv "JAVA_HOME") "GITLIBS" ~(str libs-dir)}}) nil))) (bb (pr-str `(do (babashka.deps/add-deps '{:deps {babashka/process {:git/url "https://github.com/babashka/process" :sha "4c6699d06b49773d3e5c5b4c11d3334fb78cc996"}}} {:force true @@ -86,6 +87,7 @@ true libs-dir2 (fs/file tmp-dir ".gitlibs2") template (pr-str '(do (babashka.deps/clojure ["-Sforce" "-Spath" "-Sdeps" "{:deps {babashka/process {:git/url \"https://github.com/babashka/process\" :sha \"4c6699d06b49773d3e5c5b4c11d3334fb78cc996\"}}}"] {:out :string :env-key {"PATH" (System/getenv "PATH") + "JAVA_HOME" (System/getenv "JAVA_HOME") "GITLIBS" :gitlibs}}) nil))] (bb (-> template (str/replace ":gitlibs" (pr-str (str libs-dir))) (str/replace ":env-key" ":env"))) diff --git a/test/babashka/exec_test.clj b/test/babashka/exec_test.clj new file mode 100644 index 00000000..4493e356 --- /dev/null +++ b/test/babashka/exec_test.clj @@ -0,0 +1,36 @@ +(ns babashka.exec-test + (:require + [babashka.test-utils :as u] + [cheshire.core :as cheshire] + [clojure.edn :as edn] + [clojure.test :as t :refer [deftest is]])) + +(defn bb [& args] + (apply u/bb nil args)) + +(deftest exec-test + (is (= {:foo 1} (edn/read-string (bb "-x" "prn" "--foo" "1")))) + (is (thrown? Exception (bb "-x" "json/generate-string" "--foo" "1"))) + (is (= {:foo 1} (cheshire/parse-string + (edn/read-string + (bb "-x" "cheshire.core/generate-string" "--foo" "1")) true)))) + +(deftest tasks-exec-test + (u/with-config + "{:deps {} + :tasks {foo (exec 'clojure.core/prn)}}" + (is (= {:dude 1} (edn/read-string (bb "run" "foo" "--dude" "1"))))) + (u/with-config + "{:deps {} + :tasks {foo (exec 'clojure.core/prn)}}" + (is (= {:dude 1} (edn/read-string (bb "run" "foo" "--dude" "1"))))) + (u/with-config + "{:deps {} + :tasks {foo {:org.babashka/cli {:coerce {:dude []}} + :task (exec 'clojure.core/prn)}}}" + (is (= {:dude [1]} (edn/read-string (bb "run" "foo" "--dude" "1"))))) + (u/with-config + "{:deps {} + :tasks {foo {:task (exec 'babashka.exec-test/exec-test)}}}" + (is (= {:foo [1], :bar :yeah} + (edn/read-string (bb "-cp" "test-resources" "run" "foo" "--foo" "1" "--bar" "yeah")))))) diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index 976d2644..e645c82b 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -60,7 +60,12 @@ (is (:feature/xml v))) (is (= {:force? true} (parse-opts ["--force"]))) (is (= {:main "foo", :command-line-args '("-h")} (parse-opts ["-m" "foo" "-h"]))) - (is (= {:main "foo", :command-line-args '("-h")} (parse-opts ["-m" "foo" "--" "-h"])))) + (is (= {:main "foo", :command-line-args '("-h")} (parse-opts ["-m" "foo" "--" "-h"]))) + (is (= {:force? true :list-tasks true :command-line-args nil} (parse-opts ["--force" "tasks"]))) + (is (= {:force? true :run "sometask" :command-line-args nil} (parse-opts ["--force" "run" "sometask"]))) + (is (= {:force? true :repl true} (parse-opts ["--force" "repl"]))) + (is (= {:force? true :clojure true :command-line-args '("-M" "-r")} + (parse-opts ["--force" "clojure" "-M" "-r"])))) (deftest version-test (is (= [1 0 0] (main/parse-version "1.0.0-SNAPSHOT"))) @@ -825,6 +830,13 @@ true"))) (is (= :f (bb nil "(first (into-array [:f]))"))) (is (= :f (bb nil "(first (first (into-array [(into-array [:f])])))")))) +(deftest var-names-test + (testing "for all public vars, ns/symbol from ns map matches metadata" + (is (empty? (bb nil (.getPath (io/file "test" "babashka" "scripts" "check_var_names.bb"))))))) + +(deftest clojure-lang-var-mapping-test + (is (= :var (bb nil "(defprotocol Foo (foo [_])) (extend-protocol Foo clojure.lang.Var (foo [_] :var)) (foo #'inc)")))) + ;;;; Scratch (comment diff --git a/test/babashka/pprint_test.clj b/test/babashka/pprint_test.clj new file mode 100644 index 00000000..4679db46 --- /dev/null +++ b/test/babashka/pprint_test.clj @@ -0,0 +1,12 @@ +(ns babashka.pprint-test + (:require + [babashka.test-utils :as test-utils] + [clojure.string :as str] + [clojure.test :as test :refer [deftest is]])) + +(defn bb [& args] + (str/trim (apply test-utils/bb (map str args)))) + +(deftest print-length-test + (is (= "(0 1 2 3 4 5 6 7 8 9 ...)" + (bb "-e" "(set! *print-length* 10) (clojure.pprint/pprint (range 20))")))) diff --git a/test/babashka/reify_test.clj b/test/babashka/reify_test.clj index 72624c65..a9911dd7 100644 --- a/test/babashka/reify_test.clj +++ b/test/babashka/reify_test.clj @@ -2,6 +2,7 @@ (:require [babashka.test-utils :as test-utils] [clojure.edn :as edn] + [clojure.string :as str] [clojure.test :as test :refer [deftest is testing]])) (defn bb [input & args] @@ -51,12 +52,22 @@ ]"))))) (deftest reify-object + (testing "empty methods" + (is (str/starts-with? + (bb nil " +(str (reify Object))") + "babashka.impl.reify"))) (testing "toString" (is (= ":foo" (bb nil " (def m (reify Object (toString [_] (str :foo)))) (str m) +")))) + (testing "toString + protocol" + (is (= ":dude1:dude2" + (bb nil " +(defprotocol Dude (dude [_])) (def obj (reify Object (toString [_] (str :dude1)) Dude (dude [_] :dude2))) (str (str obj) (dude obj)) ")))) (testing "Hashcode still works when only overriding toString" (is (number? @@ -97,3 +108,48 @@ [x y] (bb nil prog)] (is (pos? x)) (is (zero? y)))) + +(deftest reify-default-method-test + (let [prog '(do (def iter (let [coll [:a :b :c] idx (volatile! -1)] + (reify java.util.Iterator (hasNext [_] (< @idx 2)) + (next [_] (nth coll (vswap! idx inc)))))) + (def res (volatile! [])) + (vswap! res conj (.hasNext iter)) + (vswap! res conj (.next iter)) + (.forEachRemaining + iter (reify java.util.function.Consumer (accept [_ x] (vswap! res conj x)))) + (= [true :a :b :c] @res))] + (is (true? (bb nil prog))))) + +(deftest reify-multiple-interfaces-test + (testing "throws exception" + (is (thrown? + clojure.lang.ExceptionInfo + (bb nil " +(reify + java.lang.Object (toString [_] \"foo\") + clojure.lang.Seqable (seq [_] '(1 2 3)))"))))) + +(deftest reify-runnable-and-garbage-collection-test + (is (bb nil " +(def cleaner (java.lang.ref.Cleaner/create)) +(def deleted? (atom false)) +(defn make-cleanable-ref [] + (let [obj (Object.)] + (.register cleaner obj + (reify java.lang.Runnable + (run [_] + (reset! deleted? true)))) + nil)) +(defn force-gc [] + (let [t (atom (Object.)) + wr (java.lang.ref.WeakReference. @t)] + (reset! t nil) + (while (or (.get wr) + (not @deleted?)) + (System/gc) + (System/runFinalization)))) +(make-cleanable-ref) +(force-gc) +@deleted? +"))) diff --git a/test/babashka/scripts/check_var_names.bb b/test/babashka/scripts/check_var_names.bb new file mode 100644 index 00000000..a689cb05 --- /dev/null +++ b/test/babashka/scripts/check_var_names.bb @@ -0,0 +1,14 @@ +(require '[clojure.string :as str]) +(let [ns-maps (->> (all-ns) + (map (fn [nmspc] [(ns-name nmspc) (ns-publics nmspc)])) + (into {})) ; a map of { ns-name {symbol var, ...}} + ns-maps (update ns-maps 'user #(dissoc % '*input*))] ; *input* is a special case that we'll skip over + (->> + (for [[ns-nm _] ns-maps + [sym vr] (ns-maps ns-nm) + :let [{var-meta-ns :ns, var-meta-name :name} (meta vr) + var-meta-ns-name (some-> var-meta-ns ns-name)]] + ; build a seq of maps containing the ns/symbol from the ns and the ns/symbol from the var's metadata + {:actual-ns ns-nm :actual-ns-symbol sym :var-meta-ns var-meta-ns-name :var-meta-name var-meta-name}) + ; and remove the matches + (remove #(and (= (:actual-ns %) (:var-meta-ns %)) (= (:actual-ns-symbol %) (:var-meta-name %)))))) diff --git a/test/babashka/test_test.clj b/test/babashka/test_test.clj index d88c3fd5..08a58249 100644 --- a/test/babashka/test_test.clj +++ b/test/babashka/test_test.clj @@ -108,3 +108,7 @@ (t/with-test-out (t/run-tests *ns*))) (str/includes? (str sw) \"Ran 1 tests containing 2 assertions.\"))")] (is (str/includes? output "true")))) + +(deftest line-number-test + (is (str/includes? (bb "test-resources/line_number_test_test.clj") + "line_number_test_test.clj:4")))