Fork me on GitHub
#boot
<
2016-11-22
>
pseud10:11:17

I think I had something working but accidentally rm’ed it (I know.. -_-)… But.. I’m trying to replace a task (using replace-task!) and specify the task options for the new task:

(replace-task!
  [task test-cljs]
  (fn [o once? bool "run tests once and exit"]
    (comp (if once? identity (watch))
          (task :exit? (not once?) :optimizations :none))))
This won’t work, however, because the last form is a regular function, not something parsed by deftask… What might past me have done to make a replace-task! with some task options ?

kacurez10:11:15

Hi, I have a problem with boot watch build, the execution of jar starts failing after second rebuild, I described it here: http://stackoverflow.com/questions/40739803/boot-clj-watch-build-run-jar-ok-change-code-run-jar-fail-could-not

grant15:11:44

When you get a warning like Warning: version conflict detected: org.clojure/clojure version changes from 1.9.0-alpha14 to 1.7.0, am I correct in interpreting that as the classpath of the current pod being changed to downgrade a dependency? And if that is the case, are there any generic hints on where to start looking to figure out why this is happening?

micha15:11:29

@grant this happens when one version of a dependency is already on the classpath when another version of it is added to the classpath, too

micha15:11:44

it is something you want to avoid doing, so there is a warning

micha15:11:57

but there isn't a good way to handle it automatically

micha16:11:29

it usually happens when you add dependencies in multiple separate calls to set-env!

micha16:11:03

this is related to the way maven automatic dependency conflict resolution is implemented

micha16:11:48

maven collects all of your :dependnecies and builds a graph inclusing dependencies of your dependencies (transitive deps)

micha16:11:33

then, if there are conflicts, like say dependency X version 1 is needed by dependency A, but X version 2 is needed by dependency B

micha16:11:06

(and X is not one of your specified dependencies, so you have not specified a specific version of it)

micha16:11:35

in that case maven will choose the version of X that is needed by the dependency that is the closest to your own dependencies in the transitive dependency chain

micha16:11:11

or in other words it chooses the version of the transitive dependency X that is at the least depth in the dependency tree

micha16:11:59

but this really only works well when you let maven resolve conflicts all in one shot

micha16:11:16

maven needs to know all of your dependencies for this resolution strategy to work

micha16:11:34

when you make two separate set-env! calls, the second one is at a disadvantage

micha16:11:59

if the first call knew about the other dependencies you would have added, it would perhaps have chosen a different version of some transitive dependencies

micha16:11:11

does that make sense?

micha16:11:33

oh an important fact to know is that dependencies cannot be removed from the classpath

micha16:11:02

so it can't uninstall the version that's already on the classpath

micha16:11:08

and install a different version

grant16:11:14

Ah, so my bug is calling set-env with just the added dependency. I need to conj onto the current set of deps instead. Or build a whole new pod.

micha16:11:24

a new pod is the best way

micha16:11:30

but the warning may be benign

micha16:11:36

you can also use :exclusions

micha16:11:26

well so given the problem outlined above, there are a few standard ways of handling dependency conflicts like this

grant16:11:26

As a general rule, I try not to just disregard warning, especially if I'm not 100% sure I understand exactly what is going on. 🙂

micha16:11:13

the first way is to add an explicit dependency to the second set-env! call

micha16:11:19

with the version that was already loaded

micha16:11:48

that will instruct maven to use that specific version in its calculations, overriding the transitive version

micha16:11:16

the second way is to add an :exclusions to the dependency coordinates of the second set-env! call

micha16:11:49

(set-env! :dependencies #(conj % '[foo/bar "1.2.3" :exclusions [some/dependency]]))

micha16:11:22

the third way is to make a new pod:

grant16:11:23

In my particular case, I am wanting a task that reformats code, but the cljfmt library is just a dependency of the task, not the application, so didn't want to include that dependency in the main set-env.

micha16:11:35

a pod is perfect for that

grant16:11:55

That is what it was seeming like to me.

micha16:11:44

(def p
  (make-pod
    (update-in boot.pod/env
      [:dependencies] conj '[foo/bar "1.2.3"])))

micha16:11:18

you can use all the boot show -d and boot show -p etc to inspect the pod you make, too

micha16:11:32

they take a --pods option to allow you to select your pod by name

micha16:11:55

so if you want to see the dependecy tree in your pod or something you can do that

grant16:11:29

Ah, cool, always easier to understand what's going on when you can see it.

grant16:11:17

As always, thanks for all the help Micha.

micha16:11:57

sure anytime 🙂

alandipert16:11:26

welcome to the pod, cozy in here

grant16:11:34

@micha I figured it would be obvious on the wiki, but I'm not finding it, what is the recommend way to make a task run in its own pod?

alandipert16:11:16

the general pattern is not to run the whole task in the pod, but the parts of its impl. that depend on the dep

alandipert16:11:39

i will try to find an example

grant16:11:41

Ah, so use with-call-in

alandipert16:11:38

or if your with-call-in code gets uncomfortably large, you can move the code you want to run in the pod to another namespace, usually called impl.clj or something

alandipert16:11:49

then in with-call-in, you require it and do stuff

alandipert16:11:16

usually the thing your task does is related to files, so the value you pass across the pod membrane is a path as a string, the directory where the files to do work on are

grant16:11:16

Gotcha. Makes sense I think. I know in a few minutes when it works. 🙂

alandipert16:11:58

oh i forgot, with-eval-in vs with-call-in. eval-in takes code, call-in takes a namespace-qualified symbol

alandipert16:11:12

so usually one graduates from with-eval-in to with-call-in

micha16:11:20

well they're for different purposes

grant16:11:21

Ah, eval may be the way to go then, for now.

micha16:11:38

with-call-in needs to be passed java objects as arguments

micha16:11:25

with-eval-in uses the clojure printer and reader to ship expressions and results between pods

micha16:11:04

if you need to do something involving data that can't be round tripped through the reader/printer then you would need to use with-call-in

micha16:11:31

because each pod has its own isolated clojure runtime

micha16:11:37

including all the protocols and so on

micha16:11:53

so a clojure map in one pod is just an unknown java object in another pod

micha16:11:13

and none of the protocols in the second pod are implemented on the object passed to it from the first pod

grant16:11:39

I can see how that would get confusing if you forgot to keep that in mind.

alandipert16:11:16

> · A weird imagination is most useful to gain full advantage of all the features.

alandipert16:11:41

(from man screen, also true of boot)

tcrawley17:11:28

Howdy! As a misguided public service, I'm actively looking for clojure projects that don't work under Java 9. I know of a couple in Boot - is someone already looking at those? If not, I can rake up a pile of PRs

tcrawley17:11:17

https://github.com/boot-clj/boot/issues/525 is one, but I know boot.pods will puke on dynapath once we get past that one

tcrawley17:11:13

s/PRs/issues/, more likely

micha17:11:42

@tcrawley sweet! yeah, probably should start getting things ready for java 9 eh?

tcrawley17:11:13

you have until July (or later, if the schedule slips again), but I'm trying to make sure we're not all caught with our pants down

tcrawley17:11:59

I'm using https://github.com/tobias/clojure-java-9/issues as a central point to track issues

micha17:11:01

how do you feel about the modules jigsaw stuff?

micha17:11:09

think it's going to be useful?

tcrawley17:11:31

well, I haven't looked at it beyond "this breaks clojure"

tcrawley17:11:46

once things get stable there, I'll look at how useful modules actually are

micha17:11:59

oh i didn't know it interferes with clojure

tcrawley17:11:58

clojure itself has one issue with reflection (http://dev.clojure.org/jira/browse/CLJ-2066), and lein and boot won't be able to load from the bootclasspath any longer (I'll file a boot issue for that in the next few minutes)

monjohn22:11:07

Hey Bootonnieres! I am trying to get started with Boot by converting a pretty simple leiningen app, but any commanding is giving me this error:

monjohn22:11:12

clojure.lang.ExceptionInfo: org.clojure data: {:file "/var/folders/4d/ylhwc8zs44x2g6z9s3wf32hc0000gp/T/boot.user9194257774879762845.clj", :line 5} java.lang.ClassNotFoundException: org.clojure ... boot.main/-main/fn main.clj: 196 boot.main/-main main.clj: 196 ... boot.App.runBoot App.java: 399 boot.App.main App.java: 488 ... Boot.main Boot.java: 258

micha22:11:04

@monjohn can you paste the build.boot file you're using?

micha22:11:33

looks like you need to quote the dependencies?

micha22:11:45

or is the paste swallowing the single quote

micha22:11:07

(set-env!
  ...
  :dependencies '[[...

micha22:11:26

set-env! is a function, it's not a macro

micha22:11:44

so its arguments will be evaluated

micha22:11:56

and org.clojure/clojure isn't a var

micha22:11:05

that's why you get that error

monjohn22:11:13

@micha That did it! I really thought that I had fixed that before. But I guess I hadn’t. Thanks!