24

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 
Brad Koch
  • 19,267
  • 19
  • 110
  • 137
zcaudate
  • 13,998
  • 7
  • 64
  • 124
  • If you just want the project version, it is mentioned here: http://stackoverflow.com/questions/11235445/embed-version-string-from-leiningen-project-in-application – ktsujister Sep 18 '13 at 06:48

8 Answers8

18

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")
bfontaine
  • 18,169
  • 13
  • 73
  • 107
Paul Legato
  • 1,202
  • 13
  • 11
14

Leiningen project files are just Clojure data :)

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

deprecated
  • 5,142
  • 3
  • 41
  • 62
  • 1
    Just use `(some-> (io/resource "project.clj") slurp edn/read-string (nth 2))` – joelittlejohn Sep 21 '16 at 10:46
  • 3
    @joelittlejohn Chances of getting arbitrary project.clj from your classpath considered high. I got clj-time/clj-time and I haven't even explicitly pulled in that library. Be careful reaching into darkened boxes to withdraw an item at random. – pete23 Oct 23 '18 at 09:21
  • @pete23 Good point. If you built your jar with lein then you can also use `(some->> (io/resource "META-INF/maven/myproject/myproject/pom.properties") slurp (re-find #"version=(.*)") second)` – joelittlejohn Oct 23 '18 at 13:10
11

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"
bballant
  • 1,425
  • 2
  • 10
  • 8
9

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.

Ankur
  • 33,367
  • 2
  • 46
  • 72
9

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
radu122
  • 2,865
  • 24
  • 24
7

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.

Community
  • 1
  • 1
Leonid Beschastny
  • 50,364
  • 10
  • 118
  • 122
7

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.

Alex
  • 13,811
  • 1
  • 37
  • 50
0

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))
Michel A.
  • 201
  • 2
  • 8