Instead of first searching for a project directory and then calling devbox.Open on that path, add a devbox.Find method that performs the search and open as a single step.
Keeping Find a distinct function from Open makes it clearer when we're recursively searching for a config vs. not.
Find can just try reading a potential config file path instead of performing a separate os.Stat. This halves the number of system calls at startup and eliminates any potential races between the call to os.Stat and os.Open.
// Open loads a Devbox config from a file or project directory.
// For use with `devbox -c some/dir <subcmd>`.
func Open(path string) (*Config, error)
// Find is like [Open] except it recursively searches up the directory tree.
// For use with `devbox <subcmd>` (without a `-c` flag).
func Find(path string) (*Config, error)
Changes to user error messages:
$ devbox add go
-Error: No devbox.json found in this directory, or any parent directories. Did you run `devbox init` yet?
+Error: no devbox.json found in the current directory (or any parent directories). Did you run `devbox init` yet?
$ devbox -c badpath add go
-Error: stat /var/folders/79/1yc1ywp10w9f2xnr_rpp_ff00000gn/T/tmp.bU25JVWovO/badpath: no such file or directory
+
+Error: the devbox config path "badpath" does not exist.
$ mkdir child
$ devbox -c child add go
-Error: No devbox.json found in child. Did you run `devbox init` yet?
+Error: no devbox.json found in "child". Did you run `devbox init` yet?
Instead of first searching for a project directory and then calling
devbox.Open
on that path, add adevbox.Find
method that performs the search and open as a single step.Find
a distinct function fromOpen
makes it clearer when we're recursively searching for a config vs. not.Find
can just try reading a potential config file path instead of performing a separateos.Stat
. This halves the number of system calls at startup and eliminates any potential races between the call toos.Stat
andos.Open
.Changes to user error messages: