-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dependency managament #208
Comments
@candid82 -- Thanks for moving this to a ticket and the initial proposal. I think this proposal can be made to work. I like the idea of keeping it simple, explicit and possibly pluggable (which would mean that extending it possibly doesn't require extending the base language). I have a quick curiosity -- the It would be cool if this use case was also supported: In a given script:
(ns com.test.my-script
(:require [com.test.deps]
[com.test.common.foo :as foo]))
(println (foo/bar))
(ns com.test.deps)
(ns-sources
{"com.test1.common.*" {:url "/var/lib/joker/test1/common"}}) With the above pattern, the deps / sources for a given project can be managed in a single location. It seems like the design you propose supports this. |
@charlesg3, yes, I also thought about transitive dependencies a bit more and that led to some clarifications on |
In addition, I think |
Good point on the transitive dependencies. Seems like a good candidate for a test case. In terms of caching, I am thinking that files which need to be retrieved will be stored in Once a simple http endpoint is supported it's easy enough to get files from public github repos through the same interface (and likewise from S3 where you can get a public file). On the other hand, where I'm really wanting to take this is hosting the library on a private github repo. This isn't too much extra work, but there are a few gotchas that I'd like to throw out there so that we both like the final result. Perhaps this is supported by the pluggable portion. I'll note that if I have a repo (e.g. "screen-blend") under my org
In any case, some feedback on how much should be contained in the map of parameters vs embedding in a longer string. In any case, I like where this is headed. I think I'll start a branch and see where things take me. |
With the current way to manage dependencies, it means that the order matters for what versions you're going to get in case of conflicts. That's fine when you pin a version, since you clearly want the version that you pinned. But when two transitive dependencies conflict, without you knowing, the order in which you depend on them could affect the version you get. Maven has this behavior currently, where it grabs the first one and the order matters. Some other tools I've seen do it where it just errors, and you are forced to pin the conflicting dependency. That makes what versions is being used very explicit. But you can eventually forget to unpin, and mean that as you upgrade dependencies, you force them to use an old version of their dependency. Similarly, it can give the false impression that your code depend on that, when it is only a transitive dependency. That said, some tools fix that by having a separate place where you simply define versions to pin on conflict, separate from versions you directly depend on. What tools.deps do to improve on both the above strategies, is that it always chooses the latest version in the case of conflicts. Though the pinned version (version you directly depend on) always win if there is one. So its either the version you directly depend on, or the latest version of all conflicting dependencies. I think what tool.deps does is best personally. It means that order doesn't matter, so you're not confused about why one order works and another doesn't, or how adding an unrelated dependency somehow broke another. And if the latest version is backward incompatible with the library using the older one, you can fix it by pinning it, and depending on the older version yourself. The only challenge is do all URL type have a way to know which is "latest" ? I think tools.deps has a version number logic for maven, and I'm not sure what it does for shas on github, it might look at which commit comes after. Now for local files, or files in S3, Joker would need to come up with a strategy for that, should a joker script declare a version? Or could file-creation time be used? Or is it the person declaring the dependency that should provide a version like:
Reading the resolve-deps doc for tools.deps might be a good source of inspiration as well: https://clojure.org/reference/deps_and_cli#_resolve_deps |
See #205 for some context.
Joker currently supports undocumented
--classpath
command line parameter (and correspondingJOKER_CLASSPATH
environment variable). It works the same way as Java's classpath and provides a way to use shared "libraries". There is a number of issues with classpath approach though:Ideally, Joker's dependency management system should be
I tentatively proposed
:from <url>
option for(require)
, but @charlesg3 brought up a valid concern about this approach:To address the above concern, I think Joker should allow to declare all dependencies in one place, similarly to
deps.end
or lein'sproject.clj
, except it should be part of the source code.Here is how it could work.
There is
*ns-sources*
built-in var. It's a map where keys are namespace names (possibly with wildcards) and values are "sources", which are instructions on how and where to load those namespaces from. For example:The types of different urls have been borrowed from node.js's npm.
When Joker needs to load a namespace (i.e. while executing
(require ...)
), it first consults ns-sources map. If the namespace's name matches one of the keys, Joker will try to load the namespace from the corresponding source. Except for the simplest case of local file system urls, the loaded namespaces will have to be cached somewhere. The list of supported urls could be extended in the future, or perhaps the loading mechanism could be made pluggable. For example, user could provide their own loading function in addition to the url. In addition to*ns-sources*
var, there should be(ns-sources <map>)
function to conveniently set the var. That would normally be the first statement in a Joker script. For example:The text was updated successfully, but these errors were encountered: