Code Monkey home page Code Monkey logo

lein-parent's Introduction

lein-parent

A Leiningen plugin for inheriting properties from a parent project.

This plugin is useful when you have a series of related projects that all share some set of properties and want to avoid duplicating the values across projects. e.g. you have several projects that all share the same Maven private repository information.

lein-parent is the conceptual reverse of lein-sub.

Usage

Put [lein-parent "0.3.9"] into the :plugins vector of your project.clj.

Specify a parent in your project.clj and which properties to inherit from it as follows.

:parent-project {:path "../project.clj"
                 :inherit [:dependencies :repositories [:profiles :dev]]
                 :only-deps [org.clojure/clojure com.stuartsierra/component]}

As of lein-parent 0.3.0 and leiningen 2.7.0, you can also reference a parent project by its lein/maven coords, like this:

:parent-project {:coords [org.foo/clojure-parent-project "1.0.0"]
                 :inherit [:managed-dependencies]}

Inherited properties may be either keywords or sequences of keywords. These values are used to select which properties from your parent to merge into your project. To select only specific dependencies, specify the first part of the dependency atoms in a sequence with :only-deps. To see the actual values of these properties, run:

$ lein parent

Managed Dependencies

Leiningen 2.7.0 introduced support for a :managed-dependencies property in your leiningen project file. Using this property, you can define version numbers in the :managed-dependencies section without causing the dependencies to be realized / enforced. Then, you can omit the version number from the :dependencies section and just specify the dependency group id / artifact id. This will cause the dependency to be realized, and the version will be inherited from the :managed-dependencies section.

When combined with lein-parent, this allows you to :inherit the :managed-dependencies section from a parent project and share the version numbers for common dependencies across many child projects. This can be very powerful in reducing the burden of dealing with transitive dependency version conflicts across multiple projects.

For example:

(defproject superfun/myparent "1.0.0"
   :managed-dependencies [[clj-time "0.12.0"]
                            [me.raynes/fs "1.4.6"]
                            [ring/ring-codec "1.0.1"]])

(defproject superfun/kid-a "1.0.0-SNAPSHOT"
   :parent-project {:coords [superfun/myparent "1.0.0"]
                    :inherit [:managed-dependencies]}
   :dependencies [[clj-time]
                  [me.raynes/fs]])

(defproject superfun/kid-b "1.0.0-SNAPSHOT"
 :parent-project {:coords [superfun/myparent "1.0.0"]
                  :inherit [:managed-dependencies]}
 :dependencies [[clj-time]
                [ring/ring-codec]])

For more information, see leiningen's docs on Managed Dependencies

License

Copyright © 2014 Alex Chin

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

lein-parent's People

Contributors

achin avatar aletts avatar axrs avatar bbbates avatar cprice404 avatar justinstoller avatar libbymo avatar tkocmathla avatar vemv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

lein-parent's Issues

lein deps :tree doesn't show dependencies where the project inherits :managed-dependencies

A project that doesn't use lein-parent but does use :managed-dependencies displays dependencies correctly:

(defproject foo "0.1.0-SNAPSHOT"
  :managed-dependencies [[org.clojure/clojure "1.8.0"] [cc.artifice/clojure-solr "2.1.1"]]
  :dependencies [[org.clojure/clojure]
                             [cc.artifice/clojure-solr]]
)

produces

 [cc.artifice/clojure-solr "2.1.1"]
   [clj-time "0.11.0" :exclusions [[org.clojure/clojure]]]
     [joda-time "2.8.2"]
   [commons-fileupload "1.4" :exclusions [[commons-io]]]
   [commons-io "2.6"]
   [org.apache.solr/solr-core "6.6.6" :exclusions [[commons-fileupload] [joda-time]]]
     [com.carrotsearch/hppc "0.7.1"]
     [com.fasterxml.jackson.core/jackson-annotations "2.5.4"]
     [com.fasterxml.jackson.core/jackson-core "2.5.4"]
     [com.fasterxml.jackson.core/jackson-databind "2.5.4" :exclusions [[com.fasterxml.jackson.core/jackson-annotations] [com.fasterxml.jackson.core/jackson-core]]]
     [com.fasterxml.jackson.dataformat/jackson-dataformat-smile "2.5.4" :exclusions [[com.fasterxml.jackson.core/jackson-core]]]
     [com.github.ben-manes.caffeine/caffeine "2.4.0"]
     [com.google.guava/guava "14.0.1"]
     [com.google.protobuf/protobuf-java "3.1.0"]
     [com.tdunning/t-digest "3.1"]
     [commons-cli "1.2"]
     [commons-codec "1.10"]
    ... and so on ...

But:

(defproject foo "0.1.0-SNAPSHOT"
  :parent-project {:coords [group/artifact "2020.1.1-SNAPSHOT"]
                   :inherit [:managed-dependencies ]}
  :dependencies [[org.clojure/clojure]
                 [cc.artifice/clojure-solr]]
  :plugins [[lein-parent "0.3.8"]]
)

produces

 [clojure-complete "0.2.5" :exclusions [[org.clojure/clojure]]]
 [nrepl "0.7.0" :exclusions [[org.clojure/clojure]]]
 [org.clojure/clojure "1.8.0"]

The dependency on cc.artifice/clojure-solr is lost in lein deps :tree but it is correctly processed for classpath purposes and appears in a generated pom.xml. Does lein deps somehow not correctly execute with lein-parent middleware?

NullPointerException when using dev profile and coordinates

We've run into a NPE when trying to resolve a parent from coordinates and loading in a dev plugin.

; Parent
(defproject lein-parent/parent-with-profile-plugin "0.0.1"
  :description "Parent project that provides profile plugins"
  :dependencies [[org.clojure/clojure "1.9.0"]]
  :exclusions [org.clojure/clojure
               org.clojure/clojurescript]
  :profiles {:dev {:plugins [[venantius/ultra "0.5.2" :exclusions [org.clojure/clojure]]]}})

; Child
(defproject child-with-parent-profile-plugin "0.0.1"
  :description "Child project that references parent project with profile plugins"
  :dependencies [[medley "1.0.0"]]
  :parent-project {:coords  [lein-parent/parent-with-profile-plugin "0.0.1"]
                   :inherit [:dependencies [:profiles :dev]]})
{[fipp "0.6.6"] #{[org.clojure/core.rrb-vector "0.0.11"]},
 [grimradical/clj-semver "0.3.0" :exclusions [[org.clojure/clojure]]]
 nil,
 [org.clojure/data.codec "0.1.0"] nil,
 [org.clojars.brenton/google-diff-match-patch "0.1"] nil,
 [venantius/glow "0.1.4" :exclusions [[hiccup] [garden]]]
 #{[instaparse "1.4.1"] [clj-antlr "0.2.3"]},
 [robert/hooke "1.3.0"] nil,
 [org.antlr/antlr4 "4.5.3"] nil,
 [org.clojure/clojure
  "1.9.0"
  :exclusions
  [[org.clojure/clojurescript] [org.clojure/clojure]]]
 #{[org.clojure/core.specs.alpha "0.1.24"]
   [org.clojure/spec.alpha "0.1.143"]},
 [io.aviso/pretty "0.1.30"] nil,
 [mvxcvi/whidbey "1.3.0"] #{[org.clojure/data.codec "0.1.0"]},
 [venantius/ultra "0.5.2"]
 #{[grimradical/clj-semver "0.3.0" :exclusions [[org.clojure/clojure]]]
   [org.clojars.brenton/google-diff-match-patch "0.1"]
   [venantius/glow "0.1.4" :exclusions [[hiccup] [garden]]]
   [robert/hooke "1.3.0"] [io.aviso/pretty "0.1.30"]
   [mvxcvi/whidbey "1.3.0"] [org.clojure/tools.nrepl "0.2.12"]
   [mvxcvi/puget "1.0.1"]},
 [org.clojure/tools.nrepl "0.2.12"] nil,
 [instaparse "1.4.1"] nil,
 [mvxcvi/puget "1.0.1"] #{[fipp "0.6.6"] [mvxcvi/arrangement "1.1.0"]},
 [org.clojure/core.specs.alpha "0.1.24"] nil,
 [mvxcvi/arrangement "1.1.0"] nil,
 [org.clojure/core.rrb-vector "0.0.11"] nil,
 [lein-parent/parent-with-dev-plugin "0.0.1"]
 #{[org.clojure/clojure
    "1.9.0"
    :exclusions
    [[org.clojure/clojurescript] [org.clojure/clojure]]]
   [venantius/ultra "0.5.2"]},
 [clj-antlr "0.2.3"]
 #{[org.antlr/antlr4 "4.5.3"] [org.antlr/antlr4-runtime "4.5.3"]},
 [org.clojure/spec.alpha "0.1.143"] nil,
 [org.antlr/antlr4-runtime "4.5.3"] nil}

lein test :only leiningen.t-parent/inherited-values-test

ERROR in (inherited-values-test) (ZipFile.java:361)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.NullPointerException: entry
 at java.util.zip.ZipFile.getInputStream (ZipFile.java:361)
    leiningen.parent$resolve_project_from_coords.invokeStatic (parent.clj:66)
    leiningen.parent$resolve_project_from_coords.invoke (parent.clj:53)
    leiningen.parent$get_parent_project.invokeStatic (parent.clj:74)
    leiningen.parent$get_parent_project.invoke (parent.clj:70)

Allow parent project dependency to be force-updated

With regular lein dependencies, I can force an update of snapshots a few ways: setting the :update property of the repository to :always in my project config, adding the -U switch on the command line, or including the "update" profile. The latter two have the advantage of being dynamic, and it would be nice if lein-parent were able to respect that setting to force an update of the parent project snapshot.

Alias Merge Order

We have a parent project that has several aliases pre defined.
In the child project, we really wanted to change how an alias was run. What we found was that the parent aliases took prescedence.

For example:

...
; Parent
:aliases {"lint-nsorg" ["nsorg" "--replace"]}
...

...
; Child
:aliases {"lint-nsorg" ["nsorg"]
          "new-alias" ["preserved"]}
...

; Produces
:aliases {"lint-nsorg" ["nsorg" "--replace"]
          "new-alias" ["preserved"]}

I feel like the child aliases should be merged last to allow overriding aliases. For example: (merge grand-parent parent child)

only-plugins?

  1. What would it take to support :only-plugins similar to :only-deps that would allow the inheritance of a subset of plugins?
  2. Is that a good idea?

Problem with inheriting profiles

Hey, wondering if anyone has experienced this. I am trying to inherit profiles. I see the profiles when I run lein parent but when I try to use a profile I get an error that the profile is not found. I wonder if profiles cause leiningen to re-evaluate and skip the middleware?

My parent looks like this:

(defproject cb.cljbeat.parent-project "0.1.0-SNAPSHOT"
   :description "Parent 'POM' for clojure leiningen projects"
  :url "http://chartbeat.com/"
  :plugins [[s3-wagon-private "1.1.2"] [lein-cloverage "1.0.6"]]
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [tcp-server "0.1.0"]]
  :profiles {:1.5 {:dependencies [[org.clojure/clojure "1.5.0"]]}
             :1.6 {:dependencies [[org.clojure/clojure "1.6.0"]]}
             :1.7 {:dependencies [[org.clojure/clojure "1.7.0"]]}             
             :dev {:dependencies [[clj-stacktrace "0.2.8"]]}
             :uberjar {:aot :all}}

)

And trying to use it:

(defproject com.chartbeat.opentsdb "0.1.1-SNAPSHOT"
  :description "Simple lil' clojure library for OpenTSDB"
  :url "http://chartbeat.com/"
  :plugins [[lein-parent "0.2.1"]]
  :dependencies [[org.clojure/clojure "1.7.0"]
                 [tcp-server "0.1.0"]]
  :aot :all
  :profiles {:benchmark {:main com.chartbeat.opentsdb.example_usage}}
  :aliases {"benchmark" ["with-profile" "benchmark" "run"]}
  :vcs :git
  :parent-project {:path "../cb-parent/project.clj" :inherit [:plugins :repositories :deploy-repositories :profiles]}

)

(note: I tried [:profiles :1.7] and [:profiles] but none worked)

Running parent shows these profiles:

:profiles
 {:dev
  {:jvm-opts nil,
   :eval-in nil,
   :dependencies ([clj-stacktrace/clj-stacktrace "0.2.8"])},
  :1.7
  {:jvm-opts nil,
   :eval-in nil,
   :dependencies ([org.clojure/clojure "1.7.0"])},
  :1.6
  {:jvm-opts nil,
   :eval-in nil,
   :dependencies ([org.clojure/clojure "1.6.0"])},
  :1.5
  {:jvm-opts nil,
   :eval-in nil,
   :dependencies ([org.clojure/clojure "1.5.0"])},
  :uberjar {:aot [:all], :jvm-opts nil, :eval-in nil},
  :benchmark
  {:main com.chartbeat.opentsdb.example_usage,
   :jvm-opts nil,
   :eval-in nil}},

But using one

lein with-profile 1.7 compile
Leiningen's classpath: :/usr/local/Cellar/leiningen/2.5.1/libexec/leiningen-2.5.1-standalone.jar
Applying task with-profile to [1.7 compile]
(Warning: profile :1.7 not found.)
Applying task compile to nil
All namespaces already AOT compiled.

Global exclusions are not inherited

Given the following project files:

; parent/project.clj
(defproject parent-project "1.0.0"
  :managed-dependencies [[org.apache.httpcomponents/httpclient "4.5.11"]]
  :exclusions [commons-logging])
; child/project.clj
(defproject child-project "1.0.0"
  :dependencies [[org.apache.httpcomponents/httpclient]]
  :plugins [[lein-parent "0.3.7"]]
  :parent-project {:path "../parent/project.clj"
                   :inherit [:managed-dependencies :exclusions]})

When running lein deps :tree in the child project, it currently prints:

 [clojure-complete "0.2.5" :exclusions [[org.clojure/clojure]]]
 [nrepl "0.6.0" :exclusions [[org.clojure/clojure]]]
 [org.apache.httpcomponents/httpclient "4.5.11"]
   [commons-codec "1.11"]
   [commons-logging "1.2"]
   [org.apache.httpcomponents/httpcore "4.4.13"]

But the expected behaviour would be for the :exclusions to be inherited, so that the child project's dependencies would be:

 [clojure-complete "0.2.5" :exclusions [[commons-logging] [org.clojure/clojure]]]
 [nrepl "0.6.0" :exclusions [[commons-logging] [org.clojure/clojure]]]
 [org.apache.httpcomponents/httpclient "4.5.11" :exclusions [[commons-logging]]]
   [commons-codec "1.11"]
   [org.apache.httpcomponents/httpcore "4.4.13"]

(Leiningen 2.9.1 on Java 13 Java HotSpot(TM) 64-Bit Server VM)

URL to Parent

Hi there,

I'm fairly new to Clojure. I am wondering if instead of using a path to the parent on the file system, there is a way to link to the parent on a remote repo such as on the nexus. So for example, how would I make something like this possible?

:parent-project {:path "http://.../nexus/content/groups/public/myrepo/project.clj"
:inherit [:dependencies]

Feature request: lein parent merged

If there was a sub-command for showing the parent + child (merged) profile.clj, this would be helpful for users trying to debug their project relationships (also, might help with diagnosing the issue reported in #3).

lein-parent does not honor `:mirrors` for fetching the artifact

  :mirrors
  {#".*"
   {:name "my-internal-artifactory"
    :url "https://my-internal-artifactory"}}

is not sufficient to pull the library specified in :parent-project :coords

The workaround is to add

:repositories
{"my-internal-artifactory" {:url "https://my-internal-artifactory"}}

Support artifact coordinates for parent, rather than relative path

I'm interested in adding support for specifying an artifact coordinate tuple as the parent project (e.g. [myorg/myparent "1.0.0"], instead of a relative file path. I'm happy to hack on the code for this; wondering if that would be considered for inclusion, and/or if this plugin is still being maintained? I can also just fork and release a new plugin based on that if this is no longer maintained.

cemerick/pomegranate version doesn't work with Java 9

Trying to use lein-parent under Java 9.0.4, I get an error like

java.lang.IllegalArgumentException: Provided artifact is missing a version: [clj-yaml/clj-yaml nil]
 at cemerick.pomegranate.aether$add_version_from_managed_coord.invokeStatic (aether.clj:654)
    cemerick.pomegranate.aether$add_version_from_managed_coord.invoke (aether.clj:646)
    cemerick.pomegranate.aether$add_version_from_managed_coords_if_missing.invokeStatic (aether.clj:682)
    cemerick.pomegranate.aether$add_version_from_managed_coords_if_missing.invoke (aether.clj:676)
    clojure.core$partial$fn__4759.invoke (core.clj:2515)
    clojure.core$map$fn__4785.invoke (core.clj:2646)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.PersistentVector.create (PersistentVector.java:73)
    clojure.lang.LazilyPersistentVector.create (LazilyPersistentVector.java:44)
    clojure.core$vec.invokeStatic (core.clj:377)
    clojure.core$vec.invoke (core.clj:367)
    cemerick.pomegranate.aether$merge_versions_from_managed_coords.invokeStatic (aether.clj:691)
    cemerick.pomegranate.aether$merge_versions_from_managed_coords.invoke (aether.clj:685)
    cemerick.pomegranate.aether$resolve_dependencies_STAR_.invokeStatic (aether.clj:793)
    cemerick.pomegranate.aether$resolve_dependencies_STAR_.doInvoke (aether.clj:707)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:646)
    clojure.core$apply.invoke (core.clj:641)
    cemerick.pomegranate.aether$resolve_dependencies.invokeStatic (aether.clj:815)
    cemerick.pomegranate.aether$resolve_dependencies.doInvoke (aether.clj:809)
    clojure.lang.RestFn.invoke (RestFn.java:2793)
    leiningen.core.classpath$get_dependencies_STAR_.invokeStatic (classpath.clj:273)
    leiningen.core.classpath$get_dependencies_STAR_.invoke (classpath.clj:265)
    clojure.lang.AFn.applyToHelper (AFn.java:165)
    clojure.lang.AFn.applyTo (AFn.java:144)
    clojure.core$apply.invokeStatic (core.clj:646)
    clojure.core$memoize$fn__5708.doInvoke (core.clj:6107)
    clojure.lang.RestFn.invoke (RestFn.java:457)
    leiningen.core.classpath$get_dependencies$fn__3844.invoke (classpath.clj:332)
    leiningen.core.classpath$get_dependencies.invokeStatic (classpath.clj:330)
    leiningen.core.classpath$get_dependencies.doInvoke (classpath.clj:324)
    clojure.lang.RestFn.invoke (RestFn.java:445)
    clojure.lang.AFn.applyToHelper (AFn.java:160)
    clojure.lang.RestFn.applyTo (RestFn.java:132)
    clojure.core$apply.invokeStatic (core.clj:652)
    clojure.core$apply.invoke (core.clj:641)
    leiningen.core.classpath$resolve_managed_dependencies.invokeStatic (classpath.clj:441)
    leiningen.core.classpath$resolve_managed_dependencies.doInvoke (classpath.clj:428)
    clojure.lang.RestFn.invoke (RestFn.java:445)
    leiningen.deps$deps.invokeStatic (deps.clj:179)
    leiningen.deps$deps.invoke (deps.clj:106)
    leiningen.deps$deps.invokeStatic (deps.clj:150)
    leiningen.deps$deps.invoke (deps.clj:106)
    clojure.lang.Var.invoke (Var.java:379)
    clojure.lang.AFn.applyToHelper (AFn.java:154)
    clojure.lang.Var.applyTo (Var.java:700)
    clojure.core$apply.invokeStatic (core.clj:648)
    clojure.core$apply.invoke (core.clj:641)
    leiningen.core.main$partial_task$fn__4667.doInvoke (main.clj:284)
    clojure.lang.RestFn.invoke (RestFn.java:410)
    clojure.lang.AFn.applyToHelper (AFn.java:154)
    clojure.lang.RestFn.applyTo (RestFn.java:132)
    clojure.lang.AFunction$1.doInvoke (AFunction.java:29)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:648)
    clojure.core$apply.invoke (core.clj:641)
    leiningen.core.main$apply_task.invokeStatic (main.clj:334)
    leiningen.core.main$apply_task.invoke (main.clj:320)
    leiningen.core.main$resolve_and_apply.invokeStatic (main.clj:340)
    leiningen.core.main$resolve_and_apply.invoke (main.clj:336)
    leiningen.core.main$_main$fn__4734.invoke (main.clj:420)
    leiningen.core.main$_main.invokeStatic (main.clj:411)
    leiningen.core.main$_main.doInvoke (main.clj:408)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.lang.Var.invoke (Var.java:379)
    clojure.lang.AFn.applyToHelper (AFn.java:154)
    clojure.lang.Var.applyTo (Var.java:700)
    clojure.core$apply.invokeStatic (core.clj:646)
    clojure.main$main_opt.invokeStatic (main.clj:314)
    clojure.main$main_opt.invoke (main.clj:310)
    clojure.main$main.invokeStatic (main.clj:421)
    clojure.main$main.doInvoke (main.clj:384)
    clojure.lang.RestFn.invoke (RestFn.java:436)
    clojure.lang.Var.invoke (Var.java:388)
    clojure.lang.AFn.applyToHelper (AFn.java:160)
    clojure.lang.Var.applyTo (Var.java:700)
    clojure.main.main (main.java:37)

https://github.com/cemerick/pomegranate#urlclassloader-modifiability notes a change in pomegranate 1.0 to support Java 9. It seems like a version bump might be needed.

Needs to handle parent POMs

You know it would be really nice if this handled parent POMs as well as parent lein projects. :)

runs away

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.