Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .circleci/images/primary/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ spec_alpha_version="0.2.177-SNAPSHOT"

set -xeo pipefail

rep_home=$PWD

# Build a patched Clojure (see CLJ-1472)
cd /tmp
git clone https://github.com/clojure/clojure.git
cd clojure
git checkout "$clojure_commit_hash"

# dead link
#curl https://dev.clojure.org/jira/secure/attachment/18767/clj-1472-3.patch |patch -p1
curl 'https://api.media.atlassian.com/file/2af127ec-44e4-4bcd-9e0d-40fa2c737c00/binary?client=44579ec4-9d32-4a41-b3c1-ceed2de443de&collection=&dl=true&token=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI0NDU3OWVjNC05ZDMyLTRhNDEtYjNjMS1jZWVkMmRlNDQzZGUiLCJhY2Nlc3MiOnsidXJuOmZpbGVzdG9yZTpmaWxlOjcyMjc5YjNiLTgwNDctNGE0YS04MjhhLWZkNWM2MjUwMGI0MCI6WyJyZWFkIl0sInVybjpmaWxlc3RvcmU6ZmlsZToyYWYxMjdlYy00NGU0LTRiY2QtOWUwZC00MGZhMmM3MzdjMDAiOlsicmVhZCJdLCJ1cm46ZmlsZXN0b3JlOmZpbGU6OTAwNzcyNzItYmEwNC00NTFiLTk3MTgtNTA1OTNlOGRmOGU1IjpbInJlYWQiXSwidXJuOmZpbGVzdG9yZTpmaWxlOjcxYjY4ZmRkLTg5NTMtNGQ2Ny04ZGQ1LWEzY2Y0Yjg3ZTY3YiI6WyJyZWFkIl0sInVybjpmaWxlc3RvcmU6ZmlsZTpiOGFiOWNiMy1iMDdlLTQ2MzctOWM4ZC1lODZmYWUwNjFmY2EiOlsicmVhZCJdLCJ1cm46ZmlsZXN0b3JlOmZpbGU6M2NiOWYxM2ItYTg1MC00YTI5LWI0ZjgtNTc4MWI4NDQ0ZTdkIjpbInJlYWQiXX0sImV4cCI6MTU3MjYxNTAzNiwibmJmIjoxNTcyNjE0MDc2fQ.fG1uECS3YhkSIYqGgcEZvIahpxGDcNCNN0JAdPaJINw' | patch -p1

# [CLJ-1472] The locking macro fails bytecode verification on Graal native-image and ART runtime
# https://clojure.atlassian.net/browse/CLJ-1472
patch -p1 < $rep_home/CLJ-1472-3.patch

mvn -Dmaven.test.skip install

Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Change Log
https://github.com/eraserhd/rep/compare/v0.1.2...HEAD[Unreleased]
----------------------------------------------------------------

=== Added

* Allow streaming code from STDIN

https://github.com/eraserhd/rep/compare/v0.1.1...v0.1.2[v0.1.2]
----------------------------------------------------------------
Expand Down
58 changes: 58 additions & 0 deletions CLJ-1472-3.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
From c9db05268075ff63e9a12cb41c92399faa45ac8f Mon Sep 17 00:00:00 2001
From: Adam Clements <adam.clements@gmail.com>
Date: Wed, 12 Dec 2018 12:24:46 -0600
Subject: [PATCH] CLJ-1472 Use Java synchronized block for locking macro

---
src/clj/clojure/core.clj | 6 +-----
src/jvm/clojure/lang/Util.java | 9 +++++++++
2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index 8e98e072..01c7a002 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -1648,15 +1648,11 @@ (defmacro locking
"Executes exprs in an implicit do, while holding the monitor of x.
Will release the monitor of x in all circumstances."
{:added "1.0"}
[x & body]
`(let [lockee# ~x]
- (try
- (monitor-enter lockee#)
- ~@body
- (finally
- (monitor-exit lockee#)))))
+ (clojure.lang.Util/lock lockee# (^{:once true} fn* [] ~@body))))

(defmacro ..
"form => fieldName-symbol or (instanceMethodName-symbol args*)

Expands into a member access (.) of the first member on the first
diff --git a/src/jvm/clojure/lang/Util.java b/src/jvm/clojure/lang/Util.java
index e3be3e8c..89d3a1e9 100644
--- a/src/jvm/clojure/lang/Util.java
+++ b/src/jvm/clojure/lang/Util.java
@@ -242,10 +242,19 @@ static public RuntimeException sneakyThrow(Throwable t) {
@SuppressWarnings("unchecked")
static private <T extends Throwable> void sneakyThrow0(Throwable t) throws T {
throw (T) t;
}

+/**
+ * Invoke f under lockee monitor
+ */
+static public Object lock(final Object lockee, final IFn f) {
+ synchronized(lockee) {
+ return f.invoke();
+ }
+}
+
static public Object loadWithClass(String scriptbase, Class<?> loadFrom) throws IOException, ClassNotFoundException{
Var.pushThreadBindings(RT.map(new Object[] { Compiler.LOADER, loadFrom.getClassLoader() }));
try {
return RT.var("clojure.core", "load").invoke(scriptbase);
}
--
2.17.2 (Apple Git-113)

6 changes: 6 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ This issue is being tracked
https://dev.clojure.org/jira/browse/CLJ-1472[here] and
https://github.com/oracle/graal/issues/861[here].

Contributors
------------

- Jason M. Felice
- Arne Brasseur

License
-------

Expand Down
2 changes: 2 additions & 0 deletions rep.1.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Unlike other nREPL clients, `rep` does not try to maintain a persistent
connection, meaning that thread-local variables and bindings like `*e` and
`*1` will not persist across invocations of `rep`.

If `EXPR` is omitted then code is read from STDIN.

== OPTIONS
*--*::
End of options. Useful to send code which starts with a dash.
Expand Down
65 changes: 42 additions & 23 deletions src/rep/core.clj
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
(ns rep.core
(:require
[clojure.tools.cli :as cli]
[nrepl.core :as nrepl]
[rep.format :as format])
(:import
(java.io File))
(:require [clojure.tools.cli :as cli]
[clojure.edn :as edn]
[nrepl.core :as nrepl]
[rep.format :as format])
(:import (java.io File))
(:gen-class))

(defn- take-until
Expand Down Expand Up @@ -35,7 +34,7 @@
([result] (rf result))
([result input]
(when (contains? input key)
(let [^java.io.Writer out (case fd
(let [^java.io.Writer out (case (long fd)
1 *out*
2 *err*)
text ^String (format/format format input)]
Expand Down Expand Up @@ -175,31 +174,51 @@
(let [^String dir (System/getProperty "user.dir")]
(loop [option-value (:port (:options opts))]
(if-some [[_ ^String filename :as x] (re-matches #"^@(.*)" option-value)]
(if (.isAbsolute (File. filename))
(recur (slurp filename))
(recur (slurp (str (File. dir filename)))))
(let [file (File. filename)
file (if (.isAbsolute file)
file
(File. dir filename))]
(if (.exists file)
(recur (slurp file))
(do
(binding [*out* *err*]
(println "Can't read nREPL port, no such file:" (str file)))
(System/exit 2))))
(if-some [[_ host port] (re-matches #"(.*):(.*)" option-value)]
[:host host :port (Long/parseLong port)]
[:port (Long/parseLong option-value)])))))

(defn edn-seq [^java.io.BufferedReader rdr]
(let [edn-val (edn/read {:eof ::EOF} rdr)]
(when (not (identical? ::EOF edn-val))
(cons edn-val (lazy-seq (edn-seq rdr))))))

(defn eval-form [options session code]
(let [msg-seq (session (merge (:line options)
(:send options)
{:op (:op options)
:ns (:namespace options)
:code code}))]
(transduce (comp (until-status "done")
(printing (:print options))
report-exceptions)
null-reducer
{:exit-code 0}
msg-seq)))

(defmethod command :eval
[{:keys [options arguments] :as opts}]
(let [conn (apply nrepl/connect (nrepl-connect-args opts))
client (nrepl/client conn 60000)
session (nrepl/client-session client)
msg-seq (session (merge (:line options)
(:send options)
{:op (:op options)
:ns (:namespace options)
:code (apply str arguments)}))
result (transduce
(comp
(until-status "done")
(printing (:print options))
report-exceptions)
null-reducer
{:exit-code 0}
msg-seq)
code-seq (if (empty? arguments)
(map #(binding [*print-dup* true] (pr-str %)) (edn-seq *in*))
[(apply str arguments)])
result (loop [[code & code-seq] code-seq]
(let [result (eval-form options session code)]
(if (and (= 0 (:exit-code result)) (seq code-seq))
(recur code-seq)
result)))
^java.io.Closeable cc conn]
(.close cc)
(:exit-code result)))
Expand Down