Proposal: programmatic access to the exact Mix.install/2 installation folder

27 views
Skip to first unread message

thibaut...@gmail.com

unread,
Sep 25, 2021, 11:23:30 AM9/25/21
to elixir-lang-core
Hello,

Currently, Mix.install/2 installs the dependencies specified by the user under a folder whose name is built based on 3 elements:
  • an install root (e.g. ~/Library/Caches/mix/installs), optionally overridable via MIX_INSTALL_DIR env variable 
  • the version of elixir and erlang 
  • the MD5 of the list of dependencies the user specifies 
Related code is here: https://github.com/elixir-lang/elixir/blob/dc879df77dacce967db9f10dc1a35ff2f93e05c2/lib/mix/lib/mix.ex#L652-L662.

The resulting folder name is logged on screen if you pass “verbose: true” as an option to Mix.install/2, and typically looks like this:

/Users/thbar/Library/Caches/mix/installs/elixir-1.12.2-erts-12.0.3/00a28e7d30445de698241d077372c9cc

My understanding is that this folder name is not exposed currently to the user. This makes it hard to refer programmatically to resources (e.g. copy files from there to somewhere else).

In particular, javascript resources (packaged via Hex.pm e.g. https://preview.hex.pm/preview/phoenix_live_view/0.16.4/show/priv/static/phoenix_live_view.js) could be referenced from single-file scripts, either using esbuild (https://github.com/wojtekmach/mix_install_examples/pull/3/files) or directly referencing those files (e.g. copying the files to some specific location like mentioned in https://github.com/phoenixframework/phoenix/blob/master/installer/templates/phx_static/app.js).

I am proposing to save the `dir` variable (folder computed in the code quoted at the top of the proposal) and expose it to the user.

I do not know where exactly the state could be saved if this idea is accepted (maybe something like `Mix.State.put(:installed, deps)`, but I do not know this part well enough yet).

Thanks for reading, and let me know what you think!

-- Thibaut

José Valim

unread,
Sep 25, 2021, 11:29:19 AM9/25/21
to elixir-l...@googlegroups.com
My biggest concern about exposing those is that Mix.install/2's are cached and, if we expose the directory, people can write to it and then we will end-up with state in those.

On the positive side, all of the files you referenced so far seem to be in priv, which means you can do `Application.app_dir(:some_app, "priv")` to access them. Could that work?

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/98e31be3-d2af-4754-9464-86d102aa8c32n%40googlegroups.com.

thibaut...@gmail.com

unread,
Sep 25, 2021, 3:37:35 PM9/25/21
to elixir-lang-core
My biggest concern about exposing those is that Mix.install/2's are cached and, if we expose the directory, people can write to it and then we will end-up with state in those.
On the positive side, all of the files you referenced so far seem to be in priv, which means you can do `Application.app_dir(:some_app, "priv")` to access them. Could that work?

Thanks for the suggestion ; it is a good one and esbuild is able to find the resources apparently!

Application.put_env(:esbuild, :default,
  args: ~w(app.js --bundle --target=es2016 --outdir=../priv/static/assets),
  cd: Path.expand("assets", __DIR__),
  env: %{"NODE_PATH" => Path.expand(Application.app_dir(:phoenix, "../../../../deps"))}
)

This is great, it gives full esbuild support within Mix.install/2, without the risks you described.

Thanks for the answer!

-- Thibaut
Reply all
Reply to author
Forward
0 new messages