Skip to content

Commit

Permalink
Implement a clojure wrapper
Browse files Browse the repository at this point in the history
Fixes #2

Closes #8
  • Loading branch information
vemv committed Jan 14, 2022
1 parent 5a08135 commit 429dc4b
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,4 @@ workflows:
matrix:
parameters:
executor: [openjdk8, openjdk11, openjdk16, openjdk17]
integration_test_parallelism: ["1", "8"]
integration_test_parallelism: ["1"]
6 changes: 3 additions & 3 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
os: ["ubuntu-18.04", "macOS-latest"]
lein-version: ["2.8.1", "2.9.4"]
java-version: ["8", "11", "16"]
integration-test-parallelism: ["1", "4"]
integration-test-parallelism: ["1"]
steps:
- name: m2 cache
uses: actions/cache@v2
Expand All @@ -32,9 +32,9 @@ jobs:
distribution: 'adopt'
java-version: ${{ matrix.java-version }}
- run: java -version
- uses: DeLaGuardo/setup-clojure@91054c3b9dc15fdc6a2f45be47405d891e672ef0
- uses: DeLaGuardo/setup-clojure@fa522696baadfef7de0fe810135f446221e665c2
with:
cli: '1.10.1.469'
cli: '1.10.3.1058'
lein: ${{ matrix.lein-version }}
# should match with `#'integration-test/lein`:
- run: which lein
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
clean:
lein clean
rm -f .inline-deps
rm -rf .cpcache

.inline-deps: clean
lein with-profile -user inline-deps
Expand Down
17 changes: 8 additions & 9 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
(defproject mx.cider/enrich-classpath "1.6.2"
(defproject mx.cider/enrich-classpath "1.7.0"
:description "Makes available .jars with Java sources and javadocs for a given project."

:url "https://github.com/clojure-emacs/enrich-classpath"

:license {:name "EPL-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}

:dependencies [[org.clojure/clojure "1.10.3"] ;; Hard-require a recent-enough version of Clojure, since other plugins may require an overly old one which would make Fipp fail.
^:inline-dep [fipp "0.6.25" :exclusions [org.clojure/clojure]]]
:dependencies [;; lein assumes it but t.deps requires it:
[clj-commons/pomegranate "1.2.1"]
^:inline-dep [fipp "0.6.25" :exclusions [org.clojure/clojure]]
[org.clojure/clojure "1.10.3"] ;; Hard-require a recent-enough version of Clojure, since other plugins may require an overly old one which would make Fipp fail.
[org.clojure/tools.deps.alpha "0.12.1109"]]

:eval-in-leiningen ~(nil? (System/getenv "no_eval_in_leiningen"))

:plugins [[thomasa/mranderson "0.5.4-SNAPSHOT"]]
:plugins [[thomasa/mranderson "0.5.3"]]

:mranderson {:project-prefix "cider.enrich-classpath.inlined-deps"
:expositions []
Expand All @@ -22,11 +25,7 @@
:password :env/clojars_password
:sign-releases false}]]

:profiles {;; Helps developing the plugin when (false? eval-in-leiningen):
:test {:dependencies [[clj-commons/pomegranate "1.2.0"]
[org.clojure/clojure "1.10.3"]]}

:integration-testing {:source-paths ["integration-testing"]}
:profiles {:integration-testing {:source-paths ["integration-testing"]}

:self-test {:middleware [cider.enrich-classpath/middleware]
;; ensure that at least one dependency will fetch sources:
Expand Down
6 changes: 6 additions & 0 deletions sample.deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{:paths ["src" "test" "resource" "resources" "other"]
:aliases {:some-alias {:extra-paths ["the-extra-path"]
:extra-deps {refactor-nrepl/refactor-nrepl {:mvn/version "3.2.0"}}}}
:deps {org.clojure/clojure {:mvn/version "1.10.3"}
org.clojars.brenton/google-diff-match-patch {:mvn/version "0.1"}
org.ow2.asm/asm-all {:mvn/version "5.2"}}}
30 changes: 21 additions & 9 deletions src/cider/enrich_classpath.clj
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,19 @@
(defn resolve-with-timeout! [coordinates repositories]
{:pre [(vector? coordinates)
(-> coordinates count #{1})]}
(try
(deref (future
(cemerick.pomegranate.aether/resolve-dependencies :coordinates coordinates
:repositories repositories))
;; timing out should be very rare, it's not here for a strong reason
27500
::timed-out)
(catch ExecutionException e
(-> e .getCause throw))))
(let [repositories (or (not-empty repositories)
[["central" {:url "https://repo1.maven.org/maven2/" :snapshots false}]
["clojars" {:url "https://repo.clojars.org/"}]])]

(try
(deref (future
(cemerick.pomegranate.aether/resolve-dependencies :coordinates coordinates
:repositories repositories))
;; timing out should be very rare, it's not here for a strong reason
27500
::timed-out)
(catch ExecutionException e
(-> e .getCause throw)))))

(defn maybe-add-exclusions* [x]
(->> x
Expand Down Expand Up @@ -141,13 +145,19 @@
(not (bad-source? x)))]
(when good-artifact?
(info (str ::found " " (pr-str x))))
(info (str ::debug {:matching-artifact? matching-artifact?
:good-artifact? good-artifact?
:v v
:x x}))
(if (and matching-artifact? (not good-artifact?))
(do
(info (str ::omitting-empty-source " " (pr-str x)))
[])
;; ensure the cache gets set to something:
(doto v assert)))))
(catch AbstractMethodError e
(when (System/getenv "CI")
(-> e (.printStackTrace)))
;; Catches:

;; "Tried to use insecure HTTP repository without TLS:
Expand All @@ -158,6 +168,8 @@
;; but AbstractMethodErrors are rare enough that we can simply assume they have a single possible cause)
[])
(catch Exception e
(when (System/getenv "CI")
(-> e (.printStackTrace)))
(if (#{(Class/forName "org.eclipse.aether.resolution.DependencyResolutionException")
(Class/forName "org.eclipse.aether.transfer.ArtifactNotFoundException")
(Class/forName "org.eclipse.aether.resolution.ArtifactResolutionException")}
Expand Down
129 changes: 129 additions & 0 deletions src/cider/enrich_classpath/clojure.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
(ns cider.enrich-classpath.clojure
(:require
[cider.enrich-classpath :as enrich-classpath]
[clojure.java.io :as io]
[clojure.string :as string]
[clojure.tools.deps.alpha :as tools.deps])
(:import
(java.io File)))

(defn commandize [args clojure]
(->> args
(apply vector clojure)
(string/join " ")))

(defn impl ^String [clojure deps-edn-filename pwd args]
{:pre [(vector? args)]} ;; for conj
(let [aliases (into #{}
(comp (mapcat (fn [^String s]
(when (-> s (.startsWith "-A"))
(-> s
(string/replace #"-A:" "")
(string/replace #"-A" "")
(string/split #":")))))
(map keyword))
args)
{:keys [paths deps]
{:keys [extra-paths extra-deps]} :classpath-args
:as basis} (tools.deps/create-basis {:project (-> pwd (io/file deps-edn-filename) str)
:aliases aliases})
paths (into paths extra-paths)
deps (into deps extra-deps)
original-paths-set (set paths)
original-deps-set (->> deps (map first) set)
{:keys [dependencies
resource-paths]} (enrich-classpath/middleware {:dependencies (->> deps
(keep (fn [[artifact-name {mv :mvn/version}]]
(when mv
[artifact-name mv])))
(vec))
;; XXX
;; :repositories repositories
;; :managed-dependencies managed-dependencies
:resource-paths paths})
{:keys [classpath]} (tools.deps/calc-basis {:paths paths
:deps (->> dependencies
(map (fn [[k v marker classifier]]
[(cond-> k
(#{:classifier} marker)
(str "$" classifier)

true symbol)
{:mvn/version v}]))
(into {}))})
;; Avoids
;; `WARNING: Use of :paths external to the project has been deprecated, please remove: ...`:
classpath (->> resource-paths
(remove original-paths-set)
(map (fn [entry]
{entry {:path-key ::_}}))
(into classpath))
classpath (->> classpath
(sort-by (fn [[^String entry {:keys [lib-name path-key]}]]
{:pre [(or lib-name path-key)]}
(let [original-path? (and path-key (original-paths-set entry))]
(cond
(and original-path?
(-> entry (.contains "src")))
(str "0" entry)

(and original-path?
(-> entry (.contains "test")))
(str "1" entry)

(and original-path?
(-> entry (.contains "resource")))
(str "3" entry)

original-path?
(str "2" entry)

;; Let the original Clojure .clj libs go before any other deps -
;; makes it less likely for other libs to overwrite Clojure stuff:
(and lib-name
(-> entry (.contains "/org/clojure/"))
(not (-> lib-name str (.contains "$"))))
(str "4" lib-name)

(original-deps-set lib-name)
(str "5" lib-name)

(and lib-name
(not (-> lib-name str (.contains "$"))))
(str "6" lib-name)

(and path-key
(-> entry (.contains "unzipped-jdk-sources")))
(str "99" entry)

path-key ;; JDK sources
(str "7" entry)

lib-name ;; artifacts with sources or javadocs
(str "8" lib-name)

true ;; shouldn't happen, anyway we leave something reasonable
(str "9" (or lib-name path-key))))))
(map first)
(string/join File/pathSeparator))]
(-> args
(conj "-Sforce" "-Srepro" "-J-XX:-OmitStackTraceInFastThrow" "-J-Dclojure.main.report=stderr" "-Scp" classpath)
(commandize clojure))))

(defn -main [clojure pwd & args]
(println (try
(impl clojure "deps.edn" pwd (vec args))
(catch AssertionError e
(-> e .printStackTrace)
(commandize args clojure))
(catch Exception e
(-> e .printStackTrace)
(commandize args clojure))))
(shutdown-agents)
(System/exit 0))

(comment
(impl "clojure"
"deps.edn"
(System/getProperty "user.dir")
["-Asome-alias"]))
41 changes: 41 additions & 0 deletions src/cider/enrich_classpath/clojure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -Eeuxo pipefail
# sample usage: src/cider/enrich_classpath/clojure.sh clojure -Asome-alias <<< "(System/getProperty \"java.class.path\")"

clojure="$1"
# remove it from "$@"/"$*":
shift

file="deps.edn"

if [ ! -e $file ]; then
echo "$file not found."
$clojure "$@"
elif [[ "$*" == *Spath* ]]; then
echo "-Spath passed; skipping enrich-classpath."
$clojure "$@"
elif [[ "$*" == *Scp* ]]; then
echo "-Scp passed; skipping enrich-classpath."
$clojure "$@"
else

here="$PWD"

# don't let local deps.edn files interfere:
cd

output=$("$clojure" -Sforce -Srepro -J-XX:-OmitStackTraceInFastThrow -J-Dclojure.main.report=stderr -Sdeps '{:deps {mx.cider/enrich-classpath {:mvn/version "1.7.0"}}}' -M -m cider.enrich-classpath.clojure "$clojure" "$here" "$@")
cmd=$(tail -n1 <(echo "$output"))

cd "$here"

if grep --silent "^$clojure" <<< "$cmd"; then
$cmd
else
# Print errors:
echo "$output"
$clojure "$@"
fi
# (System/getProperty "java.class.path")

fi
20 changes: 20 additions & 0 deletions test/integration/cider/enrich_classpath/clojure.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
(ns integration.cider.enrich-classpath.clojure
(:require
[cider.enrich-classpath.clojure :as sut]
[clojure.test :refer [deftest is testing]]))

(deftest works
(testing "Returns a valid command with an -Scp specifying an enriched classpath, carefully sorted, and honoring aliases"
(let [actual (sut/impl "clojure" "sample.deps.edn"
(System/getProperty "user.dir")
["-Asome-alias"])]
(testing actual
(is (-> actual (.contains "src:test:other:the-extra-path:resource:resources")))
(is (-> actual (.contains "the-extra-path")))
(is (-> actual (.contains "refactor-nrepl")))
(is (-> actual (.contains "-Scp")))
(is (-> actual (.contains "src.zip")))
(is (-> actual (.contains "-sources.jar")))
(is (-> actual (.contains "-javadoc.jar")))
(when (re-find #"^1\.8\." (System/getProperty "java.version"))
(is (-> actual (.contains "unzipped-jdk-sources"))))))))

0 comments on commit 429dc4b

Please sign in to comment.