24
votes

Is it possible to grab the project information within the clojure repl?

For example, if there was a project defined:

(defproject blahproject "0.1.2" ....)

When running a repl in the project directory, is there a function like this?

> (project-version) 
;=> 0.1.2 
8
If you just want the project version, it is mentioned here: stackoverflow.com/questions/11235445/…ktsujister

8 Answers

18
votes

While you can parse project.clj yourself, this may be annoying. It's also a lot of work. Instead, you can just do:

(System/getProperty "projectname.version")
14
votes

Leiningen project files are just Clojure data :)

(-> "/path/to/project.clj" slurp read-string (nth 2))

11
votes

I use environ (https://github.com/weavejester/environ) which sucks in settings from a number of sources, including system properties. The project version appears as :<project-name>-version:

foobar.repl=> (require '[environ.core :refer [env]])
nil
foobar.repl=> (:foobar-version env)
"0.1.0-SNAPSHOT"
9
votes

Add the below code to the end of project.clj:

(def project (assoc-in project [:repl-options :init]
                       `(~'def ~'project-version ~(project :version))))

Now you will have a var called project-version in the initial namespace for the repl.

8
votes

As described in this discussion.

(ns myproject.example
  (:require [clojure.java.io :as io])
  (:import java.util.Properties))

(defn get-version [dep]
  (let [path (str "META-INF/maven/" (or (namespace dep) (name dep))
                  "/" (name dep) "/pom.properties")
        props (io/resource path)]
    (when props
      (with-open [stream (io/input-stream props)]
        (let [props (doto (Properties.) (.load stream))]
          (.getProperty props "version"))))))

(get-version 'myproject) ; => 0.1.0
(get-version 'org.clojure/clojure) ; => 1.3.0
7
votes

As vemv said, Leiningen project files are just Clojure data. So, it's easy to access your project as an ordinary hash-map:

(->> "project.clj"
     slurp
     read-string
     (drop 2)
     (cons :version)
     (apply hash-map)
     (def project))

If you need this variable only in your repl, you can add it to repl-options to your project.clj:

(defproject yourproject "0.1.0"
  :description ""
  :url ""
  :dependencies [ [org.clojure/clojure  "1.4.0"]]
  :repl-options { :init (->>  "project.clj"
                              slurp
                              read-string
                              (drop 2)
                              (cons :version)
                              (apply hash-map)
                              (def project))})

Now, you have project variable in your repl. So, to access the version of your project you can simply type (:version project).

Of course, you can simply use native Leiningen code to parse you project file:

(defproject yourproject "0.1.0"
  :description ""
  :url ""
  :dependencies [ [org.clojure/clojure  "1.4.0"]
                  [leiningen-core       "2.1.3"]]
  :repl-options { :init (do (require 'leiningen.core.project)
                            (def project
                                 (leiningen.core.project/read)))})

But, if you need only the version of your project and nothing more, then it's best to use Ankur's solution.

7
votes

For a more fully-featured approach, you might want to take a look at the configleaf plugin for Leiningen (https://github.com/davidsantiago/configleaf). It will make the project map, with active profiles merged in, available to project code in a namespace of your choosing.

0
votes

In case you need to do this from clojurescript you could create a macro (from another clj file) and call it from the cljs code :

;;ex: macro.clj
(defmacro get-project-version [] 
  (System/getProperty "penelope.version"))

;;my_logic_code.cljs
(ns my-logic-code
  (:require-macros [macros :as m]))

(def project-version (m/get-project-version))