-
Notifications
You must be signed in to change notification settings - Fork 34
A minimal packaging/dependency proposal #114
Description
I'm putting this idea forward here as one idea for a way to consider for simple dependencies (vs vendoring everything). Hopefully community discussion can help evolve the idea or lead to even better ideas.
What I tried to solve:
- An easy way to codify a list of dependencies and their versions
- An easy/repeatable way to install those dependencies into a project's
wren_modules - A way to do this without introducing too many further dependencies (bash, Python, etc)... which meant it had to be as much pure Wren as possible.
I just needed the bare minimum that would allow students to install Wren dependencies needed to run Wren tests for Exercism. I started out vendoring libraries but that was proving quite problematic and frustrating to maintain.
What I didn't try to solve:
- Dependencies that have further dependencies. (though these could all be specified and commented in a single project level package.wren)
- Providing any type of separate executable other than the
package.wrenitself... - Dynamically updating the
package.wrenfile via some sort of utility... right now it's all hand maintained. - Upgrading dependencies. (though wipe/reinstall isn't hard)
- Network access of any type (it just uses
gitto fetch needed dependencies - which must be git repos)
Obviously one could imagine a super complex system here akin to npm/yarn, but I was going for something much simpler... it's currently less than 100 total lines of Wren code.
The idea, a package.wren file to express simple first-tier dependencies of a package. This file is of course pure Wren. One could imagine additional getters (or perhaps attributes?) to express details of the package.
import "wren-package/package" for WrenPackage, Dependency
class Package is WrenPackage {
construct new() {}
name { "wren-test-runner" }
dependencies {
return [
Depencency.new("wren-testie", "0.1.0", "https://github.com/joshgoebel/wren-testie.git")
]
}
}
// this allows for installation, query, etc, just by running the package file
Package.new().default()Then you simply run the package ./package.wren to get information about it...
Usage:
./package.wren install
wren-test-runner dependencies:
- wren-testie 0.1.0
Or ask it to install itself:
- installing wren-testie 0.1.0
- [R] git clone -q https://github.com/joshgoebel/wren-testie.git wren_modules/wren-testie
- [R] git checkout --detach 0.1.0
HEAD is now at 921b912 show variety
* 1 dependency(s). All good.
This idea has already been implemented via wren-package and is in use in the real world of Exercism. It currently works with wren-console. Right now the big missing wren-cli pieces I see preventing something like this are:
Process.exit(enh) add OS / Process.exit #74Process.exec(enh) adds Process.exec(cmd, [args], [cwd],[env]) #94- Bug with directory creation IO: Directory.create defaulting mode 0 results in no permissions #115
node_modulescan only resolve to a single directory making a "global" + local installation of packages impossible (this quite limits the usefulness I think) Related: [RFC] ~/.wren directory #78
It seems the most natural thing would be to install a packager globally and then use it locally with projects... ie the packager might live in $HOME/wren_modules and then your project's dependencies in $HOME/projects/sample/wren_modules. It seems very natural that the package manager itself needs to be installed globally, outside the scope of your project... I guess I'm also very used to how the JavaScript ecosystem (and others) do this. I actually set things up this way without even thinking about it then was bummed when it failed - and had to go add support for resolving imports from multiple node_modules directories...
One could also imagine just compiling the package management code into the CLI as well, alleviating the need for it to be installed at all - though this makes it a lot more tied to the CLI installation.
Anyways, just food for thought.