| dh-clojure-lein(7) | Debhelper Clojure tools | dh-clojure-lein(7) |
dh-clojure-lein - Debhelper support for Leiningen projects
Support for Leiningen projects consists of a Debhelper build system, available via the dh --buildsystem argument, and support for automatic and customizable adjustments to projects.
Currently under development, and should not be considered stable until (at least) the dh-clojure major version is no longer 0 and this notice changes.
The build system is designed to facilitate packaging Leiningen-based Clojure projects for Debian, and can be activated by passing the --buildsystem=leiningen option to dh:
%:
dh $@ --buildsystem=leiningen
It takes action during these debhelper stages:
The Leiningen project.clj will be automatically adjusted by the buildsystem (see above). By default, it will set all of the dependency versions in the project to "debian", excepting "org.clojure/clojure", which will be set to "1.x".
The project adjustments may be customized by code in an optional debian/dh-clojure-lein.clj file. That file may define an "dh-clj-adjust-project" function which will be invoked like this:
(dh-clj-adjust-project get-project when ...)
The first argument is a function that returns the Leiningen project map. The second argument indicates the current point in the project build sequence. At the moment it will be ":before-plugins" or ":after-middleware", but to allow for future changes, unexpected values should be ignored, as should additional arguments. "dh-clj-adjust-project" must return the "(get-project)" map after any adjusments. See EXAMPLES below.
An ":after-middleware" call can assume that the project map has been adjusted by a preceding ":before-plugins" call, and a call for a given keyword may be made more than once, so any actions must be repeatable.
When making dependency adjustments, any changes to ":plugins" should be done during ":before-plugins" invocations, and other dependency changes should normally be made during ":after-middleware" invocations.
Note that all definition names starting with "dh-clj" are reserved by dh-clojure-lein.
In the project map passed to "dh-clj-adjust-project" the values of the dependency-related entries ":dependencies", ":managed-dependencies", and ":plugins" are not dependency vectors (as in project.clj), but are in leiningen's dependency *map* format, which is more suitable for manipulation. For example
[[org.clojure/clojure "42.x"]]
is represented as
{{:group-id "org.clojure", :artifact-id "clojure"}
{:artifact-id "clojure", :group-id "org.clojure", :version "42.x"}}
Though in most cases, this won't be important because the following client functions (defined in "debian.dh-clojure-lein.client") handle the common project manipulations (see the EXAMPLES section below). Note that only the public functions in "client" are part of the stable API. Other functions in dh-clojure-lein should not be invoked via "dh-clojure-lein.clj".
A DEP-KEY is the subset of a lein project dependency vector that uniquely identifies a dependency, either a symbol like "org.clojure/tools.cli" or a a lein project dependency vector starting with that symbol, optionally followed by a ":classifier", and/or ":extension", for example "[org.clojure/tools.cli :classifier "test"]".
A DEP-SPECs is a lein project dependency vector with the exception that it may omit the version, for example "[org.clojure/tools.cli "1.x"]" or "[org.clojure/tools.cli :classifier "test"]".
Note that unless otherwise specified, the default value for all dependencies will be set to either "debian", or for "org.clojure/clojure", to "1.x".
Some adjustments should only apply when specific profiles are active, for example, removing a dependency in a test profile. The active profile(s) can be investigated via
Emacs clojure-mode and paredit (via elpa-clojure-mode and elpa-paredit in Debian) can be quite helpful if you're editing a lot of these files. They provide automatic indentation, highlighting, structural editing, etc.
See the Clojure API <https://clojure.github.io/clojure/clojure.core-api.html#clojure.core> for documentation of specific calls like "assoc", "update", and "->".
Remove a plugin:
(require '[debian.dh-clojure-lein.client :as deb])
(defn dh-clj-adjust-project [project when & _]
(if-not (= when :before-plugins)
(project)
(update :plugins deb/del-dep 'lein-pprint)))
Adjust dependency:
(require '[debian.dh-clojure-lein.client :as deb])
(defn dh-clj-adjust-project [project when & _]
(if (= when :after-middleware)
(update (project) :dependencies deb/set-dep 'y :version "5.x"))
(project))
Adjust more dependencies:
(require '[debian.dh-clojure-lein.client :as deb])
(defn adjust-deps [deps]
(-> deps
(deb/add-dep '[w "1.x"])
(deb/add-dep 'org.clojure/core.match)
(deb/del-dep 'murphy)
(deb/set-dep 'y :version "5.x")
(deb/set-dep 'y :exclusions nil) ;; delete exclusions
(deb/set-dep '[x/y :classifier "test"] :version "5.x")))
(defn dh-clj-adjust-project [project when & _]
(if (= when :after-middleware)
(update (project) :dependencies adjust-deps)
(project)))
Equivalently:
(require '[debian.dh-clojure-lein.client :as deb])
(defn dh-clj-adjust-project [project when & _]
(if-not (= when :after-middleware)
(project)
(-> (project)
(assoc :version "11.x")
(update :dependencies deb/add-dep '[w "1.x"])
(update :dependencies deb/add-dep 'org.clojure/core.match)
(update :dependencies deb/del-dep 'murphy)
(update :dependencies deb/set-dep 'y :version "5.x")
(update :dependencies deb/set-dep '[x/y :classifier "test"] :version "5.x"))))
Make profile-specific adjustments:
(require '[debian.dh-clojure-lein.client :as deb])
(defn adjust-deps [deps proj]
(let [test? (some #{:test} (deb/active-profiles proj))
dev? (some #{:dev} (deb/active-profiles proj))]
(cond-> deps
true (deb/add-dep '[w "1.x"])
dev? (deb/add-dep 'a/b)
test? (deb/del-dep 'murphy)
true (deb/set-dep 'x :version "5.x")
true (deb/set-dep '[x/y :classifier "test"] :version "5.x"))))
(defn dh-clj-adjust-project [project when & _]
(let [proj (project)]
(if (= when :after-middleware)
(update proj :dependencies adjust-deps proj)
proj)))
Equivalently:
(require '[debian.dh-clojure-lein.client
:refer [active-profiles add-dep set-dep]])
(defn fix-shared [deps]
(-> %
(add-dep '[w "1.x"])
(set-dep 'x :version "5.x")
(set-dep '[x/y :classifier "test"] :version "5.x")))
(defn adjust-deps [deps proj]
(let [test? (some #{:test} (active-profiles proj))
dev? (some #{:dev} (active-profiles proj)])
(cond
test? (-> deps fix-shared (add-dep 'a/b))
dev? (-> deps fix-shared (del-dep 'murphy))
:else (fix-shared deps))))
(defn dh-clj-adjust-project [project when & _]
(let [proj (project)]
(if (= when :after-middleware)
(update proj :dependencies adjust-deps proj)
proj)))
Remove a dependency that might not exist:
(cond-> deps
...
(deb/get-dep deps 'x/y) (deb/del-dep 'x/y)
...)
For debugging, you can use Clojure's existing print statements, for example:
(prn :active (active-profiles))
And for more readable output that can be inserted directly into the threading forms (e.g. "->" and "-><gt">), you can do something like this:
(require 'clojure.pprint)
(defn spy> [x tag]
(binding [*out* *err*] (clojure.pprint/pprint [tag x]))
x)
(defn spy>> [tag x]
(binding [*out* *err*] (clojure.pprint/pprint [tag x]))
x)
...
(defn fix-shared [deps]
(-> %
(add-dep '[w "1.x"])
(spy> :after-w)
(set-dep 'x :version "5.x")
(spy> :after-version)
(set-dep '[x/y :classifier "test"] :version "5.x")))
Since Debian might not package some of the plugins, or might package versions that differ from those specified in project.clj adjustments must be made before Leiningen attempts to find them. That means that they cannot be handled by a dh-clojure-lein middleware (e.g. a plugin).
debian/dh-clojure-lein.clj
dh-clojure(7), dh(1), lein(1), and <https://clojure.github.io/clojure/clojure.core-api.html>
| 2024-12-20 | 0.2.0 |