Fork me on GitHub
#boot
<
2015-06-30
>
andrewmcveigh11:06:14

Is there an idiomatic way to use pods? How many/few should I use? I’m writing an internal tool (equivalent to a lein plugin) with boot tasks, with 2 unrelated namespaces that have different deps/etc. Should each use a pod? Should the tool share a pod? Does it matter?

juhoteperi12:06:28

@andrewmcveigh: Yes, they should use pods. Doesn't matter much is they use separate or shared pod. If one odesn't depend on another, should be possible and good idea to use separate pods.

andrewmcveigh12:06:22

@juhoteperi: Thanks, I have them in 2 separate pods atm. They don’t depend on each other, but one task might need to call into both.

andrewmcveigh12:06:28

I guess I should just use whatever is simpler.

frankie16:06:58

So now that 1.7 is official, is there any good resource/project that shows how migrate from cljx to cljc? Possibly with boot?

samflores17:06:57

I’m not sure boot is the cause, but I’ll ask here anyway 😛 I’m working on an app that uses the ptaoussanis/sente and everything works fine until I add core.match as a dependency. I don’t even need to use require it in any namespace. Just add the dependency.

alandipert17:06:55

@samflores: my guess is a dependency problem related to tools.analyzer, which is brought in by core.match directly and sente indirectly (through core.async)

alandipert17:06:15

@samflores: you could start with boot -d com.taoensso/sente:1.5.0 -d org.clojure/core.match:0.3.0-alpha4 show -p to see the selections maven is making for you, and pick some tactical exclusions

alandipert17:06:41

@samflores: this appears to compute: (set-env! :dependencies '[[org.clojure/core.match "0.3.0-alpha4" :exclusions [org.clojure/tools.analyzer.jvm]] [com.taoensso/sente "1.5.0"]])

samflores17:06:54

That was really a great tip. I’ve tried running boot show -p in my project directory and got the same error. Didn’t remember I could run boot without a build.boot and give it the parameters. 😄

samflores17:06:13

(inc :alandipert)

alandipert17:06:18

haha no prob

arrdem19:06:13

Okay. Howdoi boot to the head.

arrdem23:06:13

From the context of a task, can I modify other tasks options? I'm trying to build a test task which alters the pom task's version using a version parsed from the git tag. (task-options! pom {:version version}) doesn't seem to be doing it... there's magic in the pom symbol that I haven't figured out yet.

micha23:06:24

boot doesn't have a big map of configuration like that

micha23:06:50

tasks aren't really designed to be coupled like that

arrdem23:06:51

you're altering var meta

micha23:06:39

def is for side effects

micha23:06:50

we don't have an immutable map as a namespace in clojure

micha23:06:05

because we'd lose all the dynamic benefits if we did

micha23:06:13

task-options! is like def

micha23:06:43

but what are you wanting to do?

micha23:06:59

there is maybe a more direct way

micha23:06:51

nothing should be magical hopefully simple_smile

arrdem23:06:59

I have four tightly coupled lein projects that are version controlled together. At present we use https://github.com/cvillecsteele/lein-git-version to coordinate versions across the subprojects. In evaluating boot I figured it'd be a good exercise to port that sort of task to boot.

micha23:06:31

can you paste what you have?

arrdem23:06:42

(ns factual.boot-git-version
  {:boot/export-tasks true}
  (:refer-clojure :exclude [test])
  (:require [boot.pod  :as pod]
            [boot.core :as core]
            [ :as io]
            [clojure.java.shell :refer [sh]]))

(defn get-git-version
  []
  (->> (sh "git" "describe" "--match" "v*.*" "--abbrev=4" "--dirty=**DIRTY**")
       :out
       clojure.string/trim
       rest
       (apply str)))

(defn get-git-ref
  []
  (->> (sh "git" "rev-parse" "--verify" "HEAD")
       :out
       clojure.string/trim
       rest
       (apply str)))

(core/deftask git-version
  [v  version-file      bool   "Create a version statement file."
   p  version-ns-prefix string "Namespace where the version defs will be written"]
  (let [version (get-git-version)
        ref     (get-git-ref)]

    ;; If appropriate, build and install a version file
    (when version-file
      (let [temp-dir  (core/tmp-dir!)
            pname     (name (get (core/get-env core/pom) :project))
            temp-file (io/file temp-dir pname "version.clj")]

        ;; Write the file
        (spit temp-file
              (format
               (str ";; Do not edit. Generated by factual/boot-git-version.\n"
                    "(ns %s)\n"
                    "(def version \"%s\")\n"
                    "(def gitref \"%s\")\n")
               ns version ref))

        ;; Add it to the fileset
        (core/with-pre-wrap fileset
          (-> fileset
              (core/add-source temp-dir)
              (core/commit!)))))

    ;; Set the POM version
    (task-options! core/pom {:version version})))

arrdem23:06:05

fairly direct port except for the actually doing anything to the fileset bit 😛

micha23:06:19

the task should return the middleware

micha23:06:33

you might want to move the call to task-options! up to the top there

micha23:06:45

the "env" btw is not like the lein project map

micha23:06:00

the env is how the JVM environment is configured

micha23:06:08

it's part of the bootstrapping process

micha23:06:28

it contains configuration for boot's lower level bootstrapping

micha23:06:35

like maven deps, things like that

micha23:06:52

options for aether and for its own worker thread setups

micha23:06:10

tasks like the pom task are configured by currying their arguments

arrdem23:06:10

Gotcha. So those pom options are things I'm gonna have to dig off of the pom task.

micha23:06:26

or pass it to both, probably

micha23:06:40

i mean your task could set the pom task option

arrdem23:06:08

or I could just partially apply pom and return that, no?

micha23:06:33

you'd want to compose it then

micha23:06:54

(comp
  (with-pre-wrap ...)
  (pom ...))

micha23:06:04

or something

micha23:06:24

it's like ring middleware

micha23:06:55

(def wrap-foo [handler]
  (wrap-bar handler)
  (wrap-baz handler))

micha23:06:18

the wrap-bar middleware wouldn't be doing anything there

micha23:06:21

basically your task should return middleware that can be composed by the user into a pipeline

micha23:06:07

boot watch git-version aot -n my.namespace jar -m my.namespace

micha23:06:10

or something

micha23:06:21

another thng you can do is if a task almost does what you want, but for some reason isn't compatible, you can just use the underlying functions that task uses

micha23:06:24

in your own task

micha23:06:46

like if the pom task is problematic, you can probably use the functions it's using

micha23:06:52

inside your own pom task

micha23:06:05

one thing you can also do that will make it pom task agnostic:

micha23:06:25

instead of having your task compute the path to the version.clj file, you can use file extensions for this

micha23:06:55

make a file in the source that is like my/namespace/version.clj.foo

micha23:06:07

and have your task just extract that from the fileset

micha23:06:19

maybe version.clj.edn, which would be an edn template

micha23:06:58

then in your task do (->> fileset core/input-files (core/by-name ["version.clj.edn"])) to get the file

micha23:06:04

you can then write to it

micha23:06:10

this would be the idiomatic boot way

micha23:06:54

it could take that file and know the path to the generated file (i.e. remove the .edn extension or whatever)

micha23:06:21

and it would be completely decoupled from the pom configuration

micha23:06:18

the main difference between boot and lein is that in boot tasks cooperate via the fileset

micha23:06:27

and in lein they cooperate via the project map

micha23:06:46

fishing around in the pom task configuration options is like the project map pattern kinda