This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-10-25
Channels
- # aws (1)
- # beginners (6)
- # boot (403)
- # boulder-clojurians (1)
- # clojure (28)
- # clojure-china (1)
- # clojure-ecuador (2)
- # clojure-ukraine (2)
- # clojurescript (27)
- # clojurex (5)
- # core-async (7)
- # cursive (5)
- # datomic (4)
- # hoplon (160)
- # ldnclj (2)
- # ldnproclodo (2)
- # lein-figwheel (2)
- # om (182)
- # onyx (1)
- # re-frame (1)
- # reagent (40)
- # spacemacs (15)
i am concerned boot is building itself, it's not supposed to be a build tool
just kidding, great work @martinklepsch 😉
@micha: the idea was to also run the pretty printed script
are you doing some work on boot today?
cool, then I won’t feel as bad for asking stuff on sundays 😉
you can have boot.properties in the cwd, in a parent directory if it's a git repo, and in BOOT_HOME/boot.properties
it processes them in order, merging the properties, BOOT_HOME, then git project, then cwd
I had this idea yesterday of a higher order task that executes some other tasks with a scoped fileset, e.g. only stuff in boot/worker/
I got pretty far with an approach only using fileset https://gist.github.com/martinklepsch/6ff00508cc49158f270b
Not sure if that’s a total mess or not but it felt pretty sweet to just derive all from fileset
what for?
if I have :source-paths #{“boot”}
I could do something like this:
(with-dir
:dir (-> settings :pod :dir)
:task (comp (pom) (aot :all true) (jar :file "boot-pod.jar")))
map of stuff — what’s being passed as :dir
is ”pod/src/“
i wonder if the "env' should be a fileset instead of an atom
am i on a different page?
@alandipert: I had that thought too
what about a pod with a fileset in it
if you're not running it in the main thread then it's just a function in a pod which we already have
well you can alraedy run functions in pods, the main thread is the place where you can mutate the state of the build jvm environment
i guess no matter what there needs to be a calling environment
we can add more things to the "world" inside the env/fileset, but there still needs to be something that takes that as an argument
the issue I have with set-env! is that it feels unintuitive how it affects watching etc. tasks that set-env! some paths don’t compose very well with watching
that’s why I was looking into scoping while fileset is being passed around
sounds awesome
you mentioned removing things from classpath isn’t possible, can you think of another approach that would allow temporary scoping as it would be needed in the with dirs task?
couldn’t you just have filtered deps before creating the pod?
becaus that gives the user power to hide things they don't want to be in the pod or whatever
> well you can alraedy run functions in pods, the main thread is the place where you can mutate the state of the build jvm environment > which is where tasks are useful can you elaborate on that? what are the useful bits about mutating the state of the build env? for building a jar I wouldn’t need this right?
you definitely can't remove classes from the classpath once they're loaded in a classloader
you can remove directories though, but only because of some clever things in the watcher
when you remove a directory from the env it just uses the watcher to remove files from the fixed directories the classloader was created with
I’m thinking I could make a pod, give it a dir I created as classpath + required deps + fileset and then it gives me a fileset back
isolation
I want to run tasks in the pod pom, jar etc
aren’t tasks functions once the factory fn is called?
I can return the fileset from the pod and call the next handler myself (I think ..)
yeah coming to think the same
problem: we have 5 libs. we want to have a boot watch build-all install
like thing that builds libs whose files have changed and installs them.
It felt really enabling to program things with values/fileset, I hope we can have more of that and less of set-env!
I think I’ll go with the stupid non-watch supporting way for now, wanted to do the fileset patch stuff today too 😄
@micha: do you have the with-env macro handy?
how does boot/boot/project.clj
synchronize things if it doesn’t depend on anything?
@micha: the barbarywatchservice thing — is that still only for Java 6?
yeah, was just wondering if it’s for java 6 compat
ok cool
regarding boot/boot/project.clj again: I see a jar is made but it doesn’t depend on anything, is this really just supposed to be an empty jar?
[#"^(?!boot\.repl-server).*$”]
— this means all but boot.repl-server right?
we need that for the aot task 😉
heard about that but is it any good?
like in the project.clj there i have to later remove things that got included that should have been
but then I need to list all the things
meh, some option like :exclude
would be way more user friendly
agree about regexes but just a set with ns that shouldn’t get aot'd
can’t follow?
@micha: true but all that requires me to pull in c.t.n and that seems overkill for saying “all but these"
not saying it’s hard or impossible it’s just not what I consider “user-friendly"
I’m thinking it would be cool to move more towards things operating on a fileset. Pods could setup isolated envs based on those and some other params and then outside of pods we can combine filesets again and work with them as regular values. There’s not so much stuff in boot.core that would actually be useful if you’re just operating on filesets.
we can no?
ah, yeah
@micha: in that branch I just pushed to boot build-lib
fails because nrepl-server gets aot’d but when I just to boot core
it works fine
not sure what’s going on there
I assume set-env!
doesn’t reset classpath and some other build step has :aot all
@micha: do you see a way around unnecessary fs operations without blob ids of previous file? you think it’s ok to assume if lastmod of blobfile equals lastmod of tmpfile they’re the same?
(commit! [this]
(util/with-let [{:keys [dirs tree blob]} this]
(apply file/empty-dir! (map file dirs))
(doseq [[p tmpf] tree]
(let [srcf (io/file blob (id tmpf))]
(file/copy-with-lastmod srcf (file tmpf))))))
Also what you you think about storing blob ids instead of last id. With something like this we could very easily lookup previous versions, potentially we could even store the same ids and have “generations”.
With that we could super easily create a previous fileset from the current. (at least for files that are still present)
i wasn't suggesting storing "last id", but rather storing the current state of the filesystem
@micha: I know what you were suggesting but I don’t see much drawbacks with storing that information in the fileset itself. Also where exactly would we store the filesystem state? How would we have access to it when commit!
is called?
storing it in the fileset itself would defeat the purpose, because the fileset is immutable, and the underlying filesystem that we want to keep a record of is not
so when commit! runs it compares the cached state against the fileset, does a diff to get the patch, and then applies the changes
basically the tmpdir namespace needs to hold onto the fileset that was used in the latest commit! call
then when commit! is called again with a different fileset it can compare the two and make a path
@micha: it would only store state of the blob store part of the filesystem which could be considered immutable to some extent?
It would certainly be a straightforward approach I’m just thinking embedding this information in the fileset keeps more doors open (e.g. parallel tasks)
What do you think about my point that blob storage is (mostly) immutable?
but if you keep the information about the hard links that are supposed to be on the disk in the fileset it would be useless
I’m really only suggesting to make TmpFiles contain ids
instead of id
— nothing else added
for one it would be useful in that step, we could just check if last two ids of tmpfile match.
two most recent
if you want to keep a history you can, because you can hold onto a fileset if you want to, and put them in a vector or whatevee
for removing stale things we would still use file-seq
and delete the ones not in fileset
listing files is very fast
but making them is not (cheap). also deleting is probably still more expensive than ls.
the advantage would solely be to have one datastructure that provides a datastructure->filesystem abstraction that could be used in any context and does not rely on global state
but it only stores hashes/just strings
the key element is that the actual classpath (which will be populated with hard links) is global singleton and mutable
in the context of boot the point is to do global stateful things but the general idea of fileset has nothing to do with classpath, that’s just how boot uses it
commit! is classpath only because dirs are on classpath, not because it has inherently something to do with classpath?
anyways, I’ll try to come up with something more tangible and then we can discuss further
I think my main point is: fileset is so awesome it should be usable as a library too. global state to make patches makes that harder
thanks for the discussion ✌️
i feel like the problem(s) boot (and the fileset, tmpdirs, etc) are trying to solve is not stated clearly and the current implementation details are clouding and skewing our understanding (at least mine, but it seems im not alone).
of course micha you have quite a clear picture in mind and you keep trying to explain that picture from many different angles but somehow it's not permeating into other's minds easily
@martinklepsch: if the fileset would be a library of its own, how would you describe what problem is it solving? what would be its interface boundary?
micha: im not suggesting any specific action now. i just made an observation, hoping it inspires u, martin, deraen and other core contributors.
i was just re-reading the "Development Process" of the C4.1 (Collective Code Construction Contract -- http://rfc.zeromq.org/spec:22) yesterday and i noticed an interesting point in it: > Users SHALL NOT log feature requests, ideas, suggestions, or any solutions to problems that are not explicitly documented and provable. they way you (micha) argue follows this principles already, i just thought it's useful to make it explicit that "formally agreeing on a problem definition" first might help discussions a lot.
and i see the way martin & deraen is handling the github issues are very much inline with c4 too
@micha: awesome!
@micha: ^ playing around further with the idea I came to the conclusion that really all that’s needed is some “staging area” like concept. added a prototype like thing here: https://github.com/boot-clj/boot/commit/83e6761feb0b47bd7d7be0952dab7203b7703d7c — what do you think?
(haven’t tested this very much yet so may explode)
there are the files bar
and baz
that will need to be fished out via a scan of the filessytem
and then foo
would need to be added, again by scanning the filesystem to make sure it's not there already and pointing to the right place
@micha: first of all thanks for your patience :)
What you're saying boils down to: if you commit the fileset with an earlier state it will not properly change the filesystem to match the fileset contents - is that right?
therefore we must conclude that what commit!
does cannot depend on the history of what was done to any individual fileset object
so this means that some oracle type authority needs to hold the state in an atom or something that is mutable
if i understand the goal correctly we want to avoid messing around in the filesystem because IO is slow
this means that we need a different place that can hold the info that describes the filesystem
but when commit!
is called, it simply compares the fileset in boot.tmpdir/state
with the new fileset
since the filesystem can only be modified via commit!
, we know that the fileset in state
describes the filesystem fully and accurately
I see your point about the stage thing now. :D
after the comparison and after the filesystem links are all correct, commit!
updates state
, (reset! state fs)
Wondering if it could still be used as an optimization. If no stage is given the filesystem state would be read from the filesystem. Would need to test how fast that would actually be to see if it makes sense at all.
@micha: with the atom approach - what would I do if I want to mess with two file sets simultaneously
that complicates things, but you can just have a map in state
where the keys are the fileset dirs
if you were going to allow multiple filesets simultaneously you'd need to make sure that no fileset could be created with an underlying dir that is shared with any other fileset
so you can use the dirs as a key in the state atom and the value is the current filesystem
Yeah, nesting things by dir makes sense, I think that removes my main concern
@micha sorry it took me so long to accept the global state thing, somehow thought it could be done w/o but you're right it's not possible unless we construct a complete filesystem from scratch by looking at the filesystem
Thanks for talking me through it, I hope you didn't gain to much gray hair 😄
Now bed time, have a nice evening!