Let's say you have an umbrella project and that umbrella project has a mix
task that wants to write to a tmp/ directory in the root. Well if you're me
then you just realized there's no method that gets you this exact value,
even though there are a lot of methods that get you close! Of course there
are plenty of tricks/hacks you can employ to get the value as well, but the
point of a stdlib is to give you foundational elements like this so that a
1 line doesn't get written a million times.
Alright, so here's what we have:
0. `app_path` -> `"/path/to/project/_build/shared/lib/app"`, fails on an
umbrella project
0. `apps_paths` -> `%{my_app1: "apps/my_app1", my_app2: "apps/my_app2"}`,
this is actually pretty close, but on a non-standard umbrella application
it gets really weird. Like what if you have some things in `apps/` and some
things in `applications/` due to weird legacy? Not a great solve. It's also
very strange that these are not expanded paths like many other functions?
ALSO it's not "app_path" of each of your apps, it's really just the
`umbrella_app_paths` if anything.
0. `build_path` -> `"/path/to/project/_build/shared"` or
`"/path/to/project/_build/dev"` depending on `Mix.env()`, still not very
helpful.
0. `compile_path` -> See: `build_path`
0. `config_files` -> `["/path/to/project/_build/dev/.mix/compile.lock",
"/path/to/project/config/dev.exs", "/path/to/project/config/config.exs",
"/path/to/project/mix.exs"]` Okay a step in the right direction as they're
all absolute, but only the last file is really helpful. One trick here
would be `config_files() |> List.last |> Path.dirname`, assuming the list
is always in order and mix.exs is always last.
0. `consolidation_path` -> See: `build_path`
0. `deps_path` -> `"/path/to/project/deps"` This function gets us the
closest: [x] It's absolute, [x] It's just one path, [x] It works in an
umbrella application, [x] It can be fed to `Path.dirname`, but [ ] It's not
configurable, so it's brittle
0. `deps_paths` -> `%{foo: "deps/foo", bar: "custom/path/dep"}` which
isn't even close to useful. The example on this by the way in the docs
could be significantly more informative.
0. `manifest_path` -> See: `build_path`
So in summery the closest we get is `deps_path()`, but even then it's kinda
shaky. Okay, fine so I thought to myself: How are these functions
determining where these pieces are? Well turns out most of them look in one
of two places:
0. `MIX_*` (`MIX_BUILD_PATH` for example), which isn't very helpful
0. `Mix.Project.config()`, which is a `list(map)`, where each map is a
mix project?
For example:
```
def deps_path(config \\ config()) do
System.get_env("MIX_DEPS_PATH", config[:deps_path]) |> Path.expand
end
```
Despite it being a list of maps, when you go to access a key it just looks
at the first project. In this case:
```
Mix.Project.config[:deps_path] # => "deps"
```
and then:
```
Path.expand("deps") # => "/path/to/project/deps"
```
At this point you've probably been screaming: Kurtis! Why aren't you just
using File.cwd??? Well, okay, here's why:
```
iex(1)> File.cwd
{:ok, "/path/to/project"}
```
but let's say you have a task in one of your apps that calls `File.cwd`:
```
$ mix print-working-direcotry-task
{:ok, "/path/to/project/apps/example"}
```
The same thing happens when I define the path as a property in
`config/config.exs`, despite being in the root. With that said, here's my
proposal:
```
@spec umbrella_path() :: Path.t()
def umbrella_path() do
File.cwd!
end
```
"Can't you do that yourself? By defining it in the mix.exs module?" While
you can define it alright, it's seemingly inaccessible from inside an app's
tasks.
The great thing is that initially I was worried there would be special
logic needed for when you talk about `Mix.Project.umbrella_path` inside a
app, but you'll find `Mix.Project.deps_path` returns the umbrella project's
deps path!
--
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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/elixir-lang-core/623ace74-b11c-4c47-9e13-f04b13f03c97o%40googlegroups.com.