Skip to content

Commit

Permalink
Extract out the lein command finding fns.
Browse files Browse the repository at this point in the history
This makes them available for plugins to use for testing.
  • Loading branch information
tobias committed Sep 27, 2012
1 parent 6e788e8 commit fb0b8e5
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 67 deletions.
14 changes: 14 additions & 0 deletions README.md
Expand Up @@ -22,6 +22,20 @@ leinjacker is a library of utilities for Leiningen plug-in developers. Current
since it was renamed between generations.
* `abort` - 1.x- and 2.x-compatible way to signal task failure.

4. `leinjacker.lein-runner` has functions for finding and running the `lein` command on the
path for each Leiningen generation. Useful for testing plugins under various Leiningen
versions. It provides:

* `find-lein-cmd` - looks for `lein` on the $PATH by trying to call it. It takes a
`generation` argument, which should be `1` or `2`. It will then look for a command
called `lein` or `lein<generation>` that reports the correct generation when called
with `lein version`. It will memoize the found cmd to `./.lein-commands` to speed
up subsequent calls. This can be disabled via the `memoize?` arg.
* `run-lein` - Will execute the given Leiningen `generation` in `dir` with the given
`args`, returning the result map from the 'clojure.java.shell/sh' call.

See leinjacker's tests for examples of usage.

## Usage

Just drop the following into your plug-in’s `project.clj`:
Expand Down
60 changes: 60 additions & 0 deletions src/leinjacker/lein_runner.clj
@@ -0,0 +1,60 @@
(ns leinjacker.lein-runner
"Functions to locate and run the 'lein' command for either lein generation."
(:require [clojure.java.io :as io]
[clojure.java.shell :as shell]))

(defn- clean-lein-env
"Gets a copy of the system environment tha removes Leiningen environment variables."
[]
(dissoc (into {} (System/getenv))
"CLASSPATH" "LEIN_JVM_OPTS"))

(defn- memoize-to-file
"Memoizes the result if not-found-fn under key in filename."
[filename key not-found-fn]
(let [cache-file (io/file filename)
cache (if (.exists cache-file) (read-string (slurp cache-file)) {})]
(or (cache key)
(let [cmd (not-found-fn key)]
(spit cache-file (prn-str (assoc cache key cmd)))
cmd))))

(defn- find-lein-cmd*
"Does the work of looking up the lein command without any memoization options."
[generation]
(if-let [cmd (some
(fn [cmd]
(try
(if (.contains (:out (shell/sh cmd "version" :env (clean-lein-env)))
(str "Leiningen " generation "."))
cmd)
(catch java.io.IOException _)))
["lein" (str "lein" generation)])]
cmd
(throw (IllegalStateException.
(str "Unable to find Leiningen " generation
" in the path as lein or lein" generation
". Please make sure it is installed and in your path under one of those names.")))))

(defn find-lein-cmd
"Attempts to locate the lein command for the given command on the path.
Looks for: lein, lein<generation>. If memoize? isn't provided or is true,
the results are cached in ./.lein-commands."
([generation]
(find-lein-cmd generation true))
([generation memoize?]
(if memoize?
(memoize-to-file ".lein-commands" generation find-lein-cmd*)
(find-lein-cmd* generation))))

(defn run-lein
"Runs lein for the given generation with args.
:dir and :env options may be specified with kwargs. Returns the result from sh."
[generation & args]
(let [[real-args {:as opts}] (split-with string? args)]
(apply shell/sh (find-lein-cmd generation)
(conj (vec real-args)
:dir (:dir opts)
:env (assoc (merge (clean-lein-env) (:env opts))
"LEIN_GENERATION" generation)))))

67 changes: 0 additions & 67 deletions test/leinjacker/multiple_leins_runner.clj

This file was deleted.

29 changes: 29 additions & 0 deletions test/leinjacker/test_multiple_lein_versions.clj
@@ -0,0 +1,29 @@
(ns leinjacker.test-multiple-lein-versions
"Runs the tests in the test-projects projects under lein1 and lein2."
{:author "Toby Crawley"}
(:use midje.sweet)
(:require [leinjacker.utils :as utils]
[leinjacker.lein-runner :as runner]
[leiningen.install :as install]))

(defn- run-lein-on-sub-project
"Runs the midje command for the given generation of lein in test-project/"
[generation]
(println "\n==> Running 'lein midje' (generation" (str generation \)) "in test-project/")
(let [result (runner/run-lein generation "midje" :dir "test-project")]
(print (:out result))
(print (:err result))
(println "==> Done\n")
(:exit result)))

;; install leinjacker for the test project to use
(install/install (utils/read-lein-project))

(fact "run lein1 tests."
;; lein1 needs deps resolved to see the installed leinjacker
(runner/run-lein "1" "deps" :dir "test-project")
(run-lein-on-sub-project "1") => 0)

(fact "run lein2 tests."
(run-lein-on-sub-project "2") => 0)

0 comments on commit fb0b8e5

Please sign in to comment.