diff --git a/.github/workflows/typedclojure.yml b/.github/workflows/typedclojure.yml
new file mode 100644
index 0000000..c3fc266
--- /dev/null
+++ b/.github/workflows/typedclojure.yml
@@ -0,0 +1,29 @@
+name: Test and deploy
+
+on: [push]
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/cache@v1
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+ - name: Set up JDK 11
+ uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - uses: DeLaGuardo/setup-clojure@e73bf2b6435244b2c9c5c226ae5022d91d0ce702
+ with:
+ tools-deps: latest
+ - name: Configure settings.xml
+ run: |
+ mkdir -p ~/.m2
+ echo "clojarstypedclojure-clojars${{ secrets.ClojarsPassword }}" > ~/.m2/settings.xml
+
+ - name: Deploy
+ run: ./script/deploy-actions.sh
diff --git a/.gitignore b/.gitignore
index c30a559..0ec7787 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@
.lein*
.nrepl-port
.cpcache
+.*.swp
diff --git a/pom.xml b/pom.xml
index cef60fd..19649dd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,8 +1,9 @@
4.0.0
+ org.clojars.typedclojure-clojars
alpha.spec
- 0.2.177-SNAPSHOT
+ 0.2.177-typedclojure-3-SNAPSHOT
alpha.spec
Specification of data and functions
@@ -21,11 +22,26 @@
+
+
+ clojars
+ Clojars repository
+ https://clojars.org/repo
+
+
+ clojars
+ Clojars repository
+ https://clojars.org/repo
+
+
+
+
@@ -37,6 +53,13 @@
1.10.0
+
+ false
+
+ src/main/clojure
+ src/test/clojure
+ UTF-8
@@ -107,6 +130,75 @@
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.0.0
+
+
+ add-clojure-source-dirs
+ generate-sources
+
+ add-source
+ add-resource
+
+
+
+
+
+
+
+ ${clojure.source.dir}
+
+
+
+
+
+ add-clojure-test-source-dirs
+ generate-sources
+
+ add-test-source
+ add-test-resource
+
+
+
+
+
+
+
+ ${clojure.testSource.dir}
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ 1.8
+ ${project.build.sourceEncoding}
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 2.5.3
+
+ true
+ @{project.version}
+
+ false
+ true
+
+
diff --git a/script/deploy-actions.sh b/script/deploy-actions.sh
new file mode 100755
index 0000000..dab7100
--- /dev/null
+++ b/script/deploy-actions.sh
@@ -0,0 +1,27 @@
+#! /bin/bash
+# Deploys either a snapshot or release in GitHub Actions.
+# If the commit message is of the form:
+# [typedclojure-release]
+
+set -e
+
+if [[ "$GITHUB_ACTIONS" != 'true' ]]; then
+ echo "Only call this script in GitHub Actions"
+ exit 1
+fi
+
+if [[ "$GITHUB_REPOSITORY" != 'typedclojure/spec-alpha2' ]]; then
+ echo "This script only deploys in typedclojure/spec-alpha2, not $GITHUB_REPOSITORY. Doing nothing."
+ exit 0
+fi
+
+COMMIT_MSG=$(git log --format=%B -n 1 "${GITHUB_SHA}")
+echo $COMMIT_MSG
+if [[ "$COMMIT_MSG" =~ ^\[prep-release\] ]]; then
+ #https://stackoverflow.com/a/9294015
+ COMMIT_MSG_ARRAY=($COMMIT_MSG)
+ ./script/release-and-push.sh "${COMMIT_MSG_ARRAY[1]}" "${COMMIT_MSG_ARRAY[2]}"
+else
+ echo "Not deploying snapshot releases"
+ #./script/deploy-snapshot.sh
+fi
diff --git a/script/increment-semversion.sh b/script/increment-semversion.sh
new file mode 100755
index 0000000..f8353c5
--- /dev/null
+++ b/script/increment-semversion.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+#The MIT License (MIT)
+#
+#Copyright (c) 2014 Fritz Mahnke
+#
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+#
+#The above copyright notice and this permission notice shall be included in all
+#copies or substantial portions of the Software.
+#
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+#SOFTWARE.
+
+# Copied from: https://github.com/fmahnke/shell-semver/blob/4c89b49beb11034d7b384680a02f1bcfb1db249e/increment_version.sh
+
+# Increment a version string using Semantic Versioning (SemVer) terminology.
+
+# Parse command line options.
+
+while getopts ":Mmp" Option
+do
+ case $Option in
+ M ) major=true;;
+ m ) minor=true;;
+ p ) patch=true;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+
+version=$1
+
+# Build array from version string.
+
+a=( ${version//./ } )
+
+# If version string is missing or has the wrong number of members, show usage message.
+
+if [ ${#a[@]} -ne 3 ]
+then
+ echo "usage: $(basename $0) [-Mmp] major.minor.patch"
+ exit 1
+fi
+
+# Increment version numbers as requested.
+
+if [ ! -z $major ]
+then
+ ((a[0]++))
+ a[1]=0
+ a[2]=0
+fi
+
+if [ ! -z $minor ]
+then
+ ((a[1]++))
+ a[2]=0
+fi
+
+if [ ! -z $patch ]
+then
+ ((a[2]++))
+fi
+
+echo "${a[0]}.${a[1]}.${a[2]}"
+
diff --git a/script/prep-actions-release.sh b/script/prep-actions-release.sh
new file mode 100755
index 0000000..6f8d952
--- /dev/null
+++ b/script/prep-actions-release.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+#
+# Prompts for next release version and dev version and
+# creates a commit that triggers GitHub Actions to deploy
+# the release version and bump the repo to the next dev
+# version.
+
+echo "Determining current version..."
+
+TYPED_VERSION=$(mvn -q \
+ -Dexec.executable="echo" \
+ -Dexec.args='${project.version}' \
+ --non-recursive \
+ org.codehaus.mojo:exec-maven-plugin:1.6.0:exec)
+
+
+if [[ "$TYPED_VERSION" == *-SNAPSHOT ]]; then
+ echo "Current version: ${TYPED_VERSION}"
+
+ #https://stackoverflow.com/a/125340
+ DEFAULT_RELEASE_VERSION="${TYPED_VERSION%-SNAPSHOT}"
+ #https://stackoverflow.com/a/2642592 (bash 3 compatible)
+ read -p "Choose release version [${DEFAULT_RELEASE_VERSION}]: " RELEASE_VERSION
+ RELEASE_VERSION=${RELEASE_VERSION:-${DEFAULT_RELEASE_VERSION}}
+
+ # default: increment patch
+ DEFAULT_DEV_VERSION=$(printf "%s-SNAPSHOT" $(./script/increment-semversion.sh -p ${RELEASE_VERSION}))
+ read -p "Choose next dev version [${DEFAULT_DEV_VERSION}]: " DEV_VERSION
+ DEV_VERSION=${DEV_VERSION:-${DEFAULT_DEV_VERSION}}
+
+ git commit --allow-empty -m "$(printf "[prep-release] %s %s" "${RELEASE_VERSION}" "${DEV_VERSION}")"
+else
+ echo "Can only prep a release from a SNAPSHOT version, found $TYPED_VERSION"
+ exit 1
+fi
diff --git a/script/release-and-push.sh b/script/release-and-push.sh
new file mode 100755
index 0000000..62c1878
--- /dev/null
+++ b/script/release-and-push.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+#
+# Cuts a release of spec-alpha2. Requires two arguments:
+# - the release version to use
+# - the development SNAPSHOT version to use
+#
+# eg., to cut version 1.0.0 and then move to 1.0.1-SNAPSHOT,
+# call this script like so:
+#
+# ./script/release-and-push.sh 1.0.0 1.0.1-SNAPSHOT
+#
+# and then push the resulting commit to the master branch.
+# GitHub Actions will automatically deploy a 1.0.0 release and
+# update the dev version to 1.0.1-SNAPSHOT.
+
+set -e
+
+DEPLOY_BRANCH="typedclojure"
+DEPLOY_REPO="typedclojure/spec-alpha2"
+ALLOWED_ACTOR="frenchy64"
+USER_EMAIL="abonnairesergeant@gmail.com"
+USER_NAME="Ambrose Bonnaire-Sergeant"
+
+
+if [[ "$GITHUB_ACTIONS" != 'true' ]]; then
+ echo "Must release on GitHub Actions only."
+ exit 1
+fi
+
+if [[ `git symbolic-ref --short HEAD` != "$DEPLOY_BRANCH" ]]; then
+ echo "Releases only triggered on the master branch. Doing nothing."
+ exit 0
+fi
+
+if [[ "$GITHUB_ACTOR" != "$ALLOWED_ACTOR" ]]; then
+ echo "Only maintainers may deploy a release. Doing nothing."
+ exit 0
+fi
+
+if [[ "$GITHUB_REPOSITORY" != "$DEPLOY_REPO" ]]; then
+ echo "Releases only allowed from $DEPLOY_REPO. Doing nothing."
+ exit 0
+fi
+
+git config --local user.email "$USER_EMAIL"
+git config --local user.name "$USER_NAME"
+
+RELEASE_VERSION=$1
+DEVELOPMENT_VERSION=$2
+
+if [[ -z "$RELEASE_VERSION" ]]; then
+ echo "Must specify release version"
+ exit 1
+fi
+
+if [[ -z "$DEVELOPMENT_VERSION" ]]; then
+ echo "Must specify development version"
+ exit 1
+fi
+
+# there's a chance this can fail and we have a partial
+# release to Clojars. We minimize the damage by avoiding
+# pushing back to master, but there's a chance the version
+# was partially deployed. The correct fix (wrt clojars) is to simply
+# deploy a new version (eg., if 1.0.0 fails, try 1.0.1 next).
+( set -x;
+mvn release:prepare release:perform \
+ -DreleaseVersion="$RELEASE_VERSION" \
+ -Dtag="$RELEASE_VERSION" \
+ -DdevelopmentVersion="$DEVELOPMENT_VERSION"
+ )
+
+#( set -x;
+#./script/bump-readme-version "$RELEASE_VERSION"
+#)
+
+#git add .
+#git commit -m "Bump README versions for $RELEASE_VERSION"
+
+# DON'T PRINT HERE
+git push "https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "${DEPLOY_BRANCH}" --tags
diff --git a/src/main/clojure/clojure/alpha/spec.clj b/src/main/clojure/clojure/alpha/spec.clj
index 61edbbe..6b771df 100644
--- a/src/main/clojure/clojure/alpha/spec.clj
+++ b/src/main/clojure/clojure/alpha/spec.clj
@@ -424,7 +424,7 @@
"Given a function symbol, set of constants, or anonymous function,
returns a spec object."
[s]
- `(resolve-spec '~(explicate (ns-name *ns*) s)))
+ `(resolve-spec '~(explicate (ns-name *ns*) `(spec ~s))))
(defn register
"Given a namespace-qualified keyword or resolvable symbol k, and a
diff --git a/src/main/clojure/clojure/alpha/spec/impl.clj b/src/main/clojure/clojure/alpha/spec/impl.clj
index 8023b99..249d046 100644
--- a/src/main/clojure/clojure/alpha/spec/impl.clj
+++ b/src/main/clojure/clojure/alpha/spec/impl.clj
@@ -521,6 +521,18 @@
[{:keys [schemas]}]
(union-impl schemas nil))
+(defmethod s/expand-spec `s/spec
+ [[_ s :as form]]
+ {:clojure.spec/op `s/spec
+ :s s
+ :form form})
+
+(defmethod s/create-spec `s/spec
+ [{:keys [s form]}]
+ (let [rs (s/resolve-spec s)]
+ (cond-> rs
+ (::s/op rs) (assoc ::s/wrap-spec form))))
+
(defn- select-impl
[schema-form selection gfn]
(let [id (java.util.UUID/randomUUID)
@@ -1144,10 +1156,11 @@
(describe* [_] describe-form)))))
(defmethod s/expand-spec `s/every
- [[_ pred & opts]]
+ [[_ pred & opts :as form]]
{:clojure.spec/op `s/every
:spec pred
- :opts (apply hash-map opts)})
+ :opts (-> (apply hash-map opts)
+ (update ::s/describe #(or % form)))})
(defmethod s/create-spec `s/every
[{:keys [spec opts]}]
@@ -1182,7 +1195,7 @@
(s/create-spec
{:clojure.spec/op `s/every
:spec `(s/tuple ~kspec ~vspec)
- :opts (merge opts {::s/kfn (fn [i# v#] (nth v# 0))
+ :opts (merge opts {::s/kfn `(fn [i# v#] (nth v# 0))
:into {}
::s/describe `(s/every-kv ~(resolve-form kspec) ~(resolve-form vspec) ~@(mapcat identity opts))})}))
@@ -1212,7 +1225,7 @@
(s/create-spec
{:clojure.spec/op `s/every
:spec `(s/tuple ~kspec ~vspec)
- :opts (merge opts {::s/kfn (fn [i# v#] (nth v# 0))
+ :opts (merge opts {::s/kfn `(fn [i# v#] (nth v# 0))
:into {}
::s/conform-all true
:kind `map?
@@ -1438,20 +1451,24 @@
(when (accept-nil? p1) (deriv (rep* p2 p2 (add-ret p1 ret nil) splice forms) x)))))))
(defn- op-describe [p]
- (let [{:keys [::s/op ps ks forms splice p1 rep+ maybe amp] :as p} (#'s/reg-resolve! p)]
+ (let [{:keys [::s/op ps ks forms splice p1 rep+ maybe amp ::s/wrap-spec] :as p} (#'s/reg-resolve! p)]
;;(prn {:op op :ks ks :forms forms :p p})
(when p
- (case op
- ::s/accept nil
- nil p
- ::s/amp (list* 'clojure.alpha.spec/& (resolve-form amp) (resolve-forms forms))
- ::s/pcat (if rep+
- (list `s/+ rep+)
- (cons `s/cat (mapcat vector (or (seq ks) (repeat :_)) (resolve-forms forms))))
- ::s/alt (if maybe
- (list `s/? maybe)
- (cons `s/alt (mapcat vector ks (resolve-forms forms))))
- ::s/rep (list (if splice `s/+ `s/*) (resolve-form forms))))))
+ (let [d (case op
+ ::s/accept nil
+ nil p
+ ::s/amp (list* 'clojure.alpha.spec/& (resolve-form amp) (resolve-forms forms))
+ ::s/pcat (if rep+
+ (list `s/+ rep+)
+ (cons `s/cat (mapcat vector (or (seq ks) (repeat :_)) (resolve-forms forms))))
+ ::s/alt (if maybe
+ (list `s/? maybe)
+ (cons `s/alt (mapcat vector ks (resolve-forms forms))))
+ ::s/rep (list (if splice `s/+ `s/*) (resolve-form forms)))]
+ (if wrap-spec
+ (-> (list (first wrap-spec) d)
+ (with-meta (meta wrap-spec)))
+ d)))))
(defn- op-explain [form p path via in input settings-key settings]
;;(prn {:form form :p p :path path :input input})
diff --git a/src/test/clojure/clojure/test_clojure/spec.clj b/src/test/clojure/clojure/test_clojure/spec.clj
index 11b72e1..63f2d9a 100644
--- a/src/test/clojure/clojure/test_clojure/spec.clj
+++ b/src/test/clojure/clojure/test_clojure/spec.clj
@@ -309,8 +309,12 @@
(is (= (s/describe sp) (s/form sp) #{1 2})))
(is (= (s/describe (s/spec odd?)) 'odd?))
+ (is (= (s/describe (s/resolve-spec `(s/spec odd?))) 'odd?))
(is (= (s/form (s/spec odd?)) 'clojure.core/odd?))
+ (is (= (s/form (s/spec (s/* integer?))) `(s/spec (s/* integer?))))
+ (is (= (s/form (s/resolve-spec `(s/spec (s/* integer?)))) `(s/spec (s/* integer?))))
+
(is (= (s/describe (s/spec #(odd? %))) '(odd? %)))
(is (= (s/form (s/spec #(odd? %))) '(fn [%] (clojure.core/odd? %)))))
@@ -351,6 +355,9 @@
(s/every int?)
'(clojure.alpha.spec/every clojure.core/int?)
+ (s/resolve-spec `(s/every int?))
+ '(clojure.alpha.spec/every clojure.core/int?)
+
(s/coll-of (s/tuple (s/tuple int?)))
'(clojure.alpha.spec/coll-of (clojure.alpha.spec/tuple (clojure.alpha.spec/tuple clojure.core/int?)))