nim-lang / atlas

The Atlas Package cloner. It manages an isolated workspace that contains projects and dependencies.
MIT License
99 stars 14 forks source link

Implement better "vendor" style workspace setup #104

Open elcritch opened 9 months ago

elcritch commented 9 months ago

Myself and several others have used the "vendoring" style where a sub-directory is used as the Atlas workspace. This is a very common pattern for many language package managers like Npm or Elixir's mix and each project can have it's own versions checked out. Golang also uses a vendor directory for project specific deps pinning in addition to it's global GOPATH workspace.

For many projects it's convenient to setup the main parent repo as a Nim project that also contains the configs to install dependencies for that project rather than needing to create an explicit workspace. Often this is most useful for folks who want to clone a repo, install the deps locally and try out a project. This is pretty big for people who see a Nim project and just want to "try it out". Though this can be handy for a user who has a workspace but doesn't want to pollute it with some project's dependencies before they check it out. Lastly, it also enables a smooth transition path for Status project which use the nimbus-build-system that uses git submodules in a vendor folder.

The previous implementation of this in Atlas was very hacky and searched directy subdirectories in the current folder for workspaces in normal workspaces weren't found. That's problematic for lots of reasons and caused issues with normal atlas workspaces containing other workspaces. However, there should be a couple of solutions to enabling a vendoring style setup with Atlas properly.

Here's a couple of feature goals:

Here's a few approaches that have come up in a previous PR and I've thought of trying:

  1. an atlas.config project config file which could specify a default vendored workspace subdirectory in addition to other per-project configs
  2. explicit atlas.vendor file that just contains the path to a vendor folder (similar to some of git's setups)
  3. an option in a atlas.workspace configuration that specifies a vendored workspace
  4. just train users to use atlas --workspace=./vendor xyz
  5. modification of previous where a flag like -l uses a pre-defined folder like vendor as the workspace, similar to the atlas -g support for global

I'm partial towards either option 1 or option 5 of having an atlas.config or a -l local option, respectively. They're both explicit.

Having a workspace config in the current project seems sort of confusing with Atlas's standard usage. The atlas.vendor link file are sort of annoying in Nimble and Git.

Araq commented 9 months ago

I don't disagree with what you said but keep in mind that every single project/dependency can be in a custom directory and atlas.workspace remembers. Thus sharing of a project between workspaces is possible (but currently has no CLI support). Likewise instead of thinking about this problem as "project X + workspace full of deps" think of it as "workspace with project X + custom location for its dependencies".

elcritch commented 9 months ago

that every single project/dependency can be in a custom directory and atlas.workspace remembers

I'll keep it in mind. Though hopefully these wouldn't be mixed.

Likewise instead of thinking about this problem as "project X + workspace full of deps" think of it as "workspace with project X + custom location for its dependencies".

Yes, that's a good point. I've gone back and forth between setting up an atlas.workspace in the project folder with deps=vendor, and doing the vendor/atlas.workspace. Setting up "project X" with an atlas.workspace (option 3 above) works well. Either way I think of them as "default workspaces".

However, it'd be nice in that scenario to use project X's "default" workspace only if there's no parent workspace. That would allow one to use the project inside a normal workspace. I think that'd require a setting in atlas.workspace like isDefaultWorkspace=true or similar.

Does that seem last setup seem reasonable to you?

Araq commented 9 months ago

Does that seem last setup seem reasonable to you?

I don't understand it. What is a "parent" workspace? These cannot be nested currently.

elcritch commented 9 months ago

I don't understand it. What is a "parent" workspace? These cannot be nested currently.

Why couldn't a workspace be nested? Atlas should find the closest workspace and just use that. They're not nested in the sense that it does anything special. At least one person noted in the issues on here that they used nested workspaces. I've also done nested workspace just to reuse a folder layout I already had, but wanted workspaces in them too.

The main proposal I'm suggesting here is to add support for a special case nested workspace for dealing with projects that want to define a "default" workspace.

Here's the driving usage scenarios:

  1. ProjFoo has a default workspace defined in it's main repo. Some random user can clone the project and do a atlas install projFoo && nim buildAndRun to run the project. Users might do all dev this way, or delete it. Either way it's self contained and replaces the current nimble install projFoo && nimble buildAndRun process. Also, the repo can setup .gitignore so this leaves the git repo in a clean state. Unfortunately anything more complex like atlas init --deps=./deps && atlas install && nim buildAndRun seems to lead to users having issues.

  2. More advanced users of ProjFoo may prefer to work on the project along with other projects in a shared workspace. However if they use atlas inside the workspace/projectFoo project folder then Atlas would pickup the default workspace at workspace/projectFoo/atlas.workspace. The user could use atlas --workspace ../ xyz but that gets tedious to type for the 100th time. Although adding a shortcut for it like atlas -w ../ xyz might be sufficient.

Both of these scenarios will probably be fairly common. Being able to support either setup without friction will make usage experience nicer for either usage scenario.

It might seem a bit overkill, but they'll very likely be very common patterns. That's especially true when you're jumping around a bunch of repos.