From 58f2c19bc9c5956773f2801da16bf7ab44c5cfa9 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Sat, 13 Jan 2024 21:55:57 -0800 Subject: [PATCH] make dynamic loading conditional on 1.12 Signed-off-by: Sean Corfield --- CHANGELOG.md | 2 +- README.md | 44 ++++++++++++++++++++++++++++++++--- src/org/corfield/new.clj | 2 ++ src/org/corfield/new/impl.clj | 29 +++++++++++++++++------ 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3faceb1..5c97f1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changes -* v0.7.0 in progress +* v0.7.0 -- 2024-01-13 * Address [#55](https://github.com/seancorfield/deps-new/issues/55) by adding support for compound template names that can be resolved to git repositories and template paths within them. * v0.6.0 64e79d1 -- 2023-12-25 diff --git a/README.md b/README.md index 9500274..5016c5e 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,12 @@ generate the documentation, e.g., com.acme/cool-lib FIXME: my new org.corfield.new/pom project. https://github.com/com.acme/cool-lib + + + Eclipse Public License + http://www.eclipse.org/legal/epl-v10.html + + ... https://github.com/acme/cool-lib @@ -207,16 +213,48 @@ if present, uses that template to create a project, in `mynewproject`. Instead o could use `-Sdeps` to specify the dependencies needed to make the template available: ```bash -clojure -Sdeps '{:deps {com.acme.project/cool-lib COORDINATES}}' -Tnew create :template com.acme.project/cool-lib :name myusername/mynewproject +clojure -Sdeps '{:deps {io.github.acme/templates COORDINATES}}' -Tnew create :template com.acme.project/cool-lib :name myusername/mynewproject ``` The `COORDINATES` could be something like `{:local/root "/path/to/cool-lib"}` for a template that exists on the local filesystem, or it could be based on `:git/url`/`:git/sha` etc for a template that exists in a `git` repository. +As of v0.7.0, if you are using Clojure 1.12 -- either as the default `:deps` in +your `deps.edn` file or via an alias, such as `-A:1.12` -- you can use a +shorter syntax for the template dependency: + +```bash +clojure -A:1.12 -Tnew create :template io.github.acme/templates%com.acme.project/cool-lib :name myusername/mynewproject +``` + +`deps-new` will infer a `git` dependency, as `https://github.com/acme/templates`, +figure out the latest version on the default branch, check that out, and add it +to the classpath, and then proceed to use `com.acme.project/cool-lib` as above. +If you want to use a specific tag, you can use `#` to append that to the +template specification, e.g., `io.github.acme/templates%com.acme.project/cool-lib#v1.2.3`. +If the repo is structured such that the Clojure root is not the root of the +repo itself, i.e., you would normally use `:deps/root` in the coordinates, you +can specify that with an extra `%` in the template specification, after the +repo and before the actual template name, e.g., `io.github.acme/templates%lib%com.acme.project/cool-lib#v1.2.3`. +This would be equivalent to `{:deps {io.github.acme/templates {:git/tag "v1.2.3" :deps/root "lib"}}}` +(which would not be legal without `:git/sha` as well for `-Sdeps` but +`deps-new` will resolve the tag to a SHA for you). + +If your template name matches the `git` "lib" name, you can omit the template +from the specification, e.g., `io.github.acme/cool-lib` would be treated as +both the implied `git` repo and also the template name, as if you had specified: +`io.github.acme/cool-lib%io.github.acme/cool-lib`. + +The examples above using `-A:1.12` assume an alias like this in your `deps.edn` file: + +```clojure + :1.12 {:override-deps {org.clojure/clojure {:mvn/version "1.12.0-alpha5"}}} +``` + > Note: if you are on Windows, read [**Quoting keys and values**](https://clojure.org/reference/deps_and_cli#quoting) in the official **Deps and CLI Reference** documentation to understand how the above command needs to look on Powershell. Or take a look at the [Babashka CLI](#babashka-cli) library support. -> Note: because `deps-new` is based on `tools.build` and uses its file copying functions, the template must ultimately live on the filesystem, so `:local/root` and `git`-based coordinates are supported, but Maven/Clojars coordinates are not. +> Note: because `deps-new` is based on `tools.build` and uses its file copying functions, the template must ultimately live on the filesystem, so `:local/root` and `git`-based coordinates are supported, **but Maven/Clojars coordinates are not**. As of v0.6.0, `:src-dirs` can be used to specify a list of directories to search for templates, in addition to the classpath. @@ -305,6 +343,6 @@ $ clj -M:new app --name foo/bar --overwrite delete # License -Copyright © 2021-2023 Sean Corfield +Copyright © 2021-2024 Sean Corfield Distributed under the Eclipse Public License version 1.0. diff --git a/src/org/corfield/new.clj b/src/org/corfield/new.clj index 0cdc860..0b7623f 100644 --- a/src/org/corfield/new.clj +++ b/src/org/corfield/new.clj @@ -50,6 +50,8 @@ for `:delete`, to delete it first; if `:overwrite` is `nil` or `false`, an existing directory will not be overwritten." [opts] + ;; try to establish a DynamicClassLoader so that we can load + ;; templates onto the classpath (if we're running Clojure 1.12): (try (let [cl (.getContextClassLoader (Thread/currentThread))] (.setContextClassLoader (Thread/currentThread) (clojure.lang.DynamicClassLoader. cl))) diff --git a/src/org/corfield/new/impl.clj b/src/org/corfield/new/impl.clj index 50d4efe..0f1805b 100644 --- a/src/org/corfield/new/impl.clj +++ b/src/org/corfield/new/impl.clj @@ -3,7 +3,6 @@ (ns ^:no-doc org.corfield.new.impl "The implementation helpers for `org.corfield.new/create`." (:require [clojure.java.io :as io] - [clojure.repl.deps :as deps] [clojure.string :as str] [clojure.tools.deps.extensions.git :as git] [clojure.tools.build.api :as b] @@ -16,6 +15,23 @@ (set! *warn-on-reflection* true) +;; Clojure 1.11 compatibility until TDEPS-258 is fixed: +(declare add-lib say-resolving) ; to quiet the linter! +(defmacro patch-add-lib [] + (if (resolve 'clojure.core/*repl*) + `(do + (def ~'add-lib (requiring-resolve 'clojure.repl.deps/add-lib)) + (defn ~'say-resolving [repo# tag#] + (println "Resolving" repo# "as a git dependency" + (str (when tag# (str "at " tag#)))))) + `(do ; define these locally as stubs on Clojure 1.11: + (def ~(with-meta '*repl* {:dynamic true}) false) + (defn ~'add-lib [lib# _coords#] + (println "Dynamically adding" lib# "to the classpath requires Clojure 1.12!")) + (defn ~'say-resolving [repo# tag#] + (println repo# "matches a git dependency but will not be used!"))))) +(patch-add-lib) + (defn- ->ns "Given a string or symbol, presumably representing a file path, return a string that represents the @@ -216,13 +232,12 @@ [git-sha git-dir] (get-git-sha (symbol repo) tag) _ (when git-sha - (println "Resolving" repo "as a git dependency" - (str (when tag (str "at " tag)))) + (say-resolving repo tag) (binding [*repl* true] - (deps/add-lib (symbol repo) - (cond-> {:git/sha git-sha} - deps-root - (assoc :deps/root deps-root))))) + (add-lib (symbol repo) + (cond-> {:git/sha git-sha} + deps-root + (assoc :deps/root deps-root))))) {:keys [main] :as name-data} (deconstruct-project-name (symbol project-name)) ; allow for string or symbol target-dir (str (or target-dir main))