Interactive workflow with external libraries in Clojure [duplicate] - clojure

I have multiple, separate leiningen projects that ostensibly could depend on one-another.
Example:
~/projects/mywebapp (my own project)
~/projects/noir (a clone of the github repo)
~/projects/clojureql (a clone of the github repo)
I want to have them all compiled into the same JVM at the same time. I would like to run the git repos bleeding edge (pulling new commits/making my own commits) and not have to run lein jar or lein deps and certainly not have to restart the VM if I change any of the projects.
Here's a use case:
After running lein swank, from within emacs, I connect to the repl and compile a file from mywebapp (with C-c-k), which requires a file from noir. It finds the version of the file in my projects directory. Later, I open that file, edit it, and compile it (with C-c-k).
Note that I'm not asking for auto-compiling when I do git pull. I just don't want to have to restart the JVM or do lengthy jar compiling processes.
Is this possible in leiningen? How can I set this up?

Does this question from the Lein FAQ help?
Q: I want to hack two projects in parallel, but it's annoying to switch between them.
A: Use a feature called checkout dependencies. If you create a directory called checkouts in your project root and symlink some other
project roots into it, Leiningen will allow you to hack on them in
parallel. That means changes in the dependency will be visible in the
main project without having to go through the whole
install/switch-projects/deps/restart-repl cycle. Note that this is not
a replacement for listing the project in :dependencies; it simply
supplements that for tighter change cycles.

If you're already using swank, you don't need lein checkout dependencies. You can just C-c C-k your project (which will load the jarred versions of noir/whatever), and then browse to your local version of noir and C-c C-k that as well. Swank happily sends all the code to your repl, and the jvm never need know that it came from a different place!
I can only recommend this for smallish changes though, because I think if you compile noir.core, which depends on (say) noir.internal, clojure will load the jarred version of noir.internal even while you compile the local version of noir.core. Even so, it's a handy trick in general.

Related

Patch Library From Clojars

Say I'm using a library in a leiningen project, hosted on Clojars. And I run into a bug. I fork the project on Github, and fix the bug. Now what?
What's the most appropriate way to use my version of the library in my leiningen project?
P.S. I'm coming from the Ruby world, so I've obviously got Bundler on the mind...
If you only want your modified version available locally, you can follow Arthur's process up to the "Test my program" step. This is fine if you're working on an application which you'll package together with its dependencies for deployment (with lein uberjar, say). You might also want to use Leiningen's checkouts feature to work on your main project and the modified library in parallel (documented in Leiningen's tutorial -- link to the version from the current 2.2.0 release).
If you want your modified version to be accessible in a public Maven repository, the accepted thing to do (indeed, encouraged for this specific use case and no other) is to release a version of the project with the original artefact id and a group id of org.clojars.{your-clojars-account-name}.
For example, if you wanted to release your own version of project foo with (defproject foo "upstream-version" ...) in its project.clj, you'd change its defproject form to (defproject org.clojars.kendallb/foo "your-version" ...) before release. Then you could depend on [org.clojars.kendallb/foo "your-version"] in your projects.
This way there won't be any conflict either with the original artefact id or any other forks.
As for getting your change merged upstream, Arthur's process is perfectly reasonable.
my process:
Fork the project on github
Change the version from project-0.1.2-SNAPSHOT to project-0.1.2-arthur-SNAPSHOT in project.clj of the dependency
Fix the bug
Run "lein install" to add my fork to my local repo
cd to my project (the one using the dependency)
Change my porject.clj to depend on project-0.1.2-arthur-SNAPSHOT
Test my program
Submit a pull request to the maintainer of the dependency
Hop onto IRC and chat with the maintainer about the fix, and ask politely if my coding style matches their vision for the project. (this also helps expedite their merging)
Once they merge the fix remove the -arthur- from the name and test their SNAPSHOT branch
Beg and plead for them to release the fixed project so you can drop the SNAPSHOT dependency.
While you are waiting for the dependency to merge and release you can push your fork to clojars under your name and with a version string that identifies it as your fork (in my case I use -arthur-.
Tt's tempting to apply lots of "style fixes" to a project when you're just in there digging around to fix a bug. If you want to do this do try to work with the project maintainer because they are in it for the long haul and more emotionally invested in the code.

Installing libraries with leiningen without creating project

I am learning Clojure and coming from a Ruby background.
I am looking for something analogous to gem install <library>. The various incantations of lein install do not seem to fit this bill.
Is there a way to simply install a library locally so that it can be referenced in the REPL without the need to create a project?
Seems like, you want to install a library with lein. Here is the plugin, install it and use like
lein localrepo install <filename> <[groupId/]artifactId> <version>
If your aim is merely to load libraries in the REPL consider using alembic. It loads dynamically classpaths, resolve dependencies and automatically pulls libraries from the repositories.
Here is a use case:
(require 'alembic.still)
(alembic.still/distill '[enlive "1.1.1"])
It simply requires you to add the following entry to your .lein/project.clj:
{:dev {:dependencies [[alembic "0.1.1"]]}}
See this answer.
Java and thus clojure do not generally have the the idea of globally installed libraries. You should always be creating a classpath with the minimal set of dependencies. You need somehow to specify and manage this classpath and the easiest way to do this is with leiningen, which requires a project.
leiningen automates the process of retrieving the remote libraries and placing them in your local repository which is somewhat analogous to gem install, but these libraries do not become automatically available to a REPL.
The easiest way to have a set of libraries always available is to have a 'scratch' project which you use for REPL experiments before starting a new project. It's not too much of an overhead.
In lein 2 you can update profiles.clj with package you want to install:
~\user\.lein\profiles.clj
With the first run of any project with lein, the local repo will be updated with what was incereased in profiles.clj.
Sometimes I just run lein deps without being in a project folder, this will update the local repo for you.
This way you can add any library to your project.clj or call it from repl and it will be extracted from local repo.
If you don’t have a project, you add your dependencies in your global lein user profile instead located at ~/.lein/profiles.clj.
The doc isn’t great for lein to be honest. So this part is confusing. But you edit that file as such:
{:user {:plugins [[lein-pprint "1.1.1"]]
:dependencies [[slamhound "1.3.1"]]}}
In the :plugins vector you add whatever global lein plugin you want to have. And in the :dependencies vector you add whatever library you want available globally.
Then anywhere you start a lein repl you’d have those dependencies available to you. And everywhere you run lein you’ll have the additional plugin features available to you.
If you use tools.deps instead of lein, aka, the clj command instead of the lein command. Then it is a bit different. You instead want to modify your ~/.clojure/deps.edn file. Where you’d add dependencies there instead:
{:deps {clj-time {:mvn/version "0.14.2"}}}
So if you put the above in your user deps.edn whenever you run clj command the clj-time library will be available to you.

How to use lein to manage the dependency of a dependency?

Should I create a local repository to change the dependencies of a dependency in my project?
I have a clojure project that is using docjure. docjure contains a dependency on poi 3.6.
Because of a bug in generated Excel files I am reading, I have a local version of poi 3.8 that I hacked to workaround the bug.
It's easy enough to stick my poi 3.8 jars into my projects lib/ directory so that my project will run ok at the repl.
But, lein deps (or jar and uberjar) happily cleans the lib/ directory and reinstalls the 3.6 versions of poi, breaking my build.
I think the probable solution is two-fold:
1 - put my hacked poi 3.8 into a local repository
2 - create my own local copy of docjure and update it's dependencies to point to that local repository.
I am looking for confirmation that this is the "right thing" to do in this case or someone to point out that it is much easier to just do something else.
It is worth reading Leiningen's Repeatability wiki page if you haven't already. To quote part of it:
If the code is public, you should open a bug report with upstream to get them to publish it in a public repository like Clojars, Sonatype, or Maven Central, depending on the project. If they are resistant or too slow it's always possible to publish "Clojars forks"; see lein help deploying for further details there.
The ultimate solution is to try and get your changes pushed upstream. Then you can depend on the version you need, and I think Leiningen will prefer that version if it's higher than the transitive version.
Another option might be to include your jar in a safe (checked-in) directory. Then write a plugin that can hook into a built-in task and copy the jar to your lib directory for you. I really don't know if this will be successful, but it's worth looking into.

Workflow for hacking on Clojure libraries using swank-clojure

Is there a typical workflow for hacking on Clojure libraries?
Say I have my application "Foo" which relies on a third-party library "Bar", which was obtained from a repository, and included in project Foo via lein deps.
Then, say I want to hack on library "Bar", so I clone it from github.
Now, I would like to hack on my local clone "Bar" while at the same time working on application "Foo" that depends on it. I would like all of the source files for "Bar" to open in Emacs along with all the source files in "Foo", using one instance of swank.
Is there an easy way to do this?
I want to alter my environment and not the project. Therefore I do not want to edit project.clj for "Foo" in order to accomplish this.
Does this require setting the classpath before starting up lein swank, or is there a better way?
Create a checkouts directory in your Foo project and create a symlink to your clone of the Bar project inside this directory.
To quote the Leiningen FAQ:
Q: I want to hack two projects in parallel, but it's annoying to switch between them.
A: If you create a directory called checkouts in your project root and symlink some other project roots into it, Leiningen will allow you to hack on them in parallel. That means changes in the dependency will be visible in the main project without having to go through the whole install/switch-projects/deps/restart-repl cycle, and the copy in checkouts will take precedence over the dependency declared in project.clj. Note that this is not a replacement for listing the project in :dependencies; it simply supplements that for convenience.

How can I set up leiningen to work with multiple projects?

I have multiple, separate leiningen projects that ostensibly could depend on one-another.
Example:
~/projects/mywebapp (my own project)
~/projects/noir (a clone of the github repo)
~/projects/clojureql (a clone of the github repo)
I want to have them all compiled into the same JVM at the same time. I would like to run the git repos bleeding edge (pulling new commits/making my own commits) and not have to run lein jar or lein deps and certainly not have to restart the VM if I change any of the projects.
Here's a use case:
After running lein swank, from within emacs, I connect to the repl and compile a file from mywebapp (with C-c-k), which requires a file from noir. It finds the version of the file in my projects directory. Later, I open that file, edit it, and compile it (with C-c-k).
Note that I'm not asking for auto-compiling when I do git pull. I just don't want to have to restart the JVM or do lengthy jar compiling processes.
Is this possible in leiningen? How can I set this up?
Does this question from the Lein FAQ help?
Q: I want to hack two projects in parallel, but it's annoying to switch between them.
A: Use a feature called checkout dependencies. If you create a directory called checkouts in your project root and symlink some other
project roots into it, Leiningen will allow you to hack on them in
parallel. That means changes in the dependency will be visible in the
main project without having to go through the whole
install/switch-projects/deps/restart-repl cycle. Note that this is not
a replacement for listing the project in :dependencies; it simply
supplements that for tighter change cycles.
If you're already using swank, you don't need lein checkout dependencies. You can just C-c C-k your project (which will load the jarred versions of noir/whatever), and then browse to your local version of noir and C-c C-k that as well. Swank happily sends all the code to your repl, and the jvm never need know that it came from a different place!
I can only recommend this for smallish changes though, because I think if you compile noir.core, which depends on (say) noir.internal, clojure will load the jarred version of noir.internal even while you compile the local version of noir.core. Even so, it's a handy trick in general.