Skip to content

Commit

Permalink
Merge branch 'main' into feat/repodata
Browse files Browse the repository at this point in the history
  • Loading branch information
olivier-lacroix authored Aug 12, 2024
2 parents db009a4 + 3a6b694 commit 712af8c
Show file tree
Hide file tree
Showing 2 changed files with 254 additions and 0 deletions.
252 changes: 252 additions & 0 deletions docs/design_proposals/pixi_global_manifest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
# Pixi Global Manifest

## Motivation

`pixi global` is currently limited to imperatively managing CLI packages.
The next iteration of this feature should fulfill the following needs:

- Shareable global environments.
- Managing complex environments with multiple packages as dependencies
- Flexible exposure of binaries

## Design Considerations

There are a few things we wanted to keep in mind in the design:

1. **User-friendliness**: Pixi is a user focused tool that goes beyond developers. The feature should have good error reporting and helpful documentation from the start.
2. **Keep it simple**: The CLI should be all you strictly need to interact with global environments.
3. **Unsurprising**: Simple commands should behave similar to traditional package managers.
4. **Human Readable**: Any file created by this feature should be human-readable and modifiable.

## Manifest

The global environments and exposed will be managed by a human-readable manifest.
This manifest will stick to conventions set by `pixi.toml` where possible.
Among other things it will be written in the TOML format, be named `pixi-global.toml` and be placed at `~/.pixi/manifests/pixi-global.toml`.
The motivation for the location is discussed [further below](#multiple-manifests)

```toml title="pixi-global.toml"
# The name of the environment is `python`
# It will expose python, python3 and python3.11, but not pip
[envs.python.dependencies]
python = "3.11.*"
pip = "*"

[envs.python.exposed]
python = "python"
python3 = "python3"
"python3.11" = "python3.11"

# The name of the environment is `python_3_10`
# It will expose python3.10
[envs.python_3_10.dependencies]
python = "3.10.*"

[envs.python_3_10.exposed]
"python3.10" = "python"

```

## CLI

Install one or more packages `PACKAGE` and expose their binaries.
If `--environment` has been given, all packages will be installed in the same environment.
If the environment already exists, the command will return with an error.
`--expose` can be given if `--environment` is given as well or if only a single `PACKAGE` will be installed.
The syntax for `MAPPING` is `exposed_name=binary_name`, so for example `python3.10=python`.

```
pixi global install [--expose MAPPING] [--environment ENV] <PACKAGE>...
```

Remove environments `ENV`.
```
pixi global uninstall <ENV>...
```

Update `PACKAGE` if `--package` is given. If not, all packages in environments `ENV` will be updated.
If the update leads to binaries being removed, it will offer to remove the mappings.
If the user declines the update process will stop.
If the update leads to binaries being added, it will offer for each binary individually to expose it.
`--assume-yes` will assume yes as answer for every question that would otherwise be asked interactively.
```
pixi global update [--package PACKAGE] [--assume-yes] <ENV>...
```

Add one or more packages `PACKAGE` into an existing environment `ENV`.
If environment `ENV` does not exist, it will return with an error.
Without `--expose` no binary will be exposed.
If you don't mention a spec like `python=3.8.*`, the spec will be unconstrained with `*`.
The syntax for `MAPPING` is `exposed_name=binary_name`, so for example `python3.10=python`.

```
pixi global add --environment ENV [--expose MAPPING] <PACKAGE>...
```

Remove package `PACKAGE` from environment `ENV`.
If that was the last package remove the whole environment and print that information in the console.
If this leads to binaries being removed, it will offer to remove the mappings.
If the user declines the remove process will stop.
```
pixi global remove --environment ENV PACKAGE
```

Add one or more `MAPPING` for environment `ENV` which describe which binaries are exposed.
The syntax for `MAPPING` is `exposed_name=binary_name`, so for example `python3.10=python`.
```
pixi global expose add --environment ENV <MAPPING>...
```

Remove one or more exposed `BINARY` from environment `ENV`
```
pixi global expose remove --environment ENV <BINARY>...
```

Ensure that the environments on the machine reflect the state in the manifest.
The manifest is the single source of truth.
Only if there's no manifest, will the data from existing environments be used to create a manifest.
`pixi global sync` is implied by most other `pixi global` commands.

```
pixi global sync
```

List all environments, their specs and exposed binaries
```
pixi global list
```


### Simple workflow

Create environment `python`, install package `python=3.10.*` and expose all binaries of that package
```
pixi global install python=3.10.*
```

Update all packages in environment `python`
```
pixi global update python
```

Remove environment `python`
```
pixi global uninstall python
```

Create environment `python` and `pip`, install corresponding packages and expose all binaries of that packages
```
pixi global install python pip
```

Remove environments `python` and `pip`
```
pixi global uninstall python pip
```

Create environment `python-pip`, install `python` and `pip` in the same environment and expose all binaries of these packages
```
pixi global install --environment python-pip python pip
```


### Adding dependencies

Create environment `python`, install package `python` and expose all binaries of that package.
Then add package `hypercorn` to environment `python` but doesn't expose its binaries.

```
pixi global install python
pixi global add --environment python hypercorn
```

Update package `cryptography` (a dependency of `hypercorn`) to `43.0.0` in environment `python`

```
pixi update --environment python cryptography=43.0.0
```

Then remove `hypercorn` again.
```
pixi global remove --environment python hypercorn
```


### Specifying which binaries to expose

Make a new environment `python_3_10` with package `python=3.10` and expose the `python` executable as `python3.10`.
```
pixi global install --environment python_3_10 --expose "python3.10=python" python=3.10
```

Now `python3.10` is available.


Run the following in order to expose `python` from environment `python_3_10` as `python310` instead.

```
pixi global expose remove --environment python_3_10 python3.10
pixi global expose add --environment python_3_10 "python310=python"
```

Now `python310` is available, but `python3.10` isn't anymore.


### Syncing

Most `pixi global` sub commands imply a `pixi global sync`.

- Users should be able to change the manifest by hand (creating or modifying (adding or removing))
- Users should be able to "export" their existing environments into the manifest, if non-existing.
- The manifest is always "in sync" after `install`/`remove`/`inject`/`other global command`.


First time, clean computer.
Running the following creates manifest and `~/.pixi/envs/python`.
```
pixi global install python
```

Delete `~/.pixi` and syncing, should add environment `python` again as described in the manifest
```
rm `~/.pixi/envs`
pixi global sync
```

If there's no manifest, but existing environments, pixi will create a manifest that matches your current environments.
It is to be decided whether the user should be asked if they want an empty manifest instead, or if it should always import the data from the environments.
```
rm <manifest>
pixi global sync
```

If we remove the python environment from the manifest, running `pixi global sync` will also remove the `~/.pixi/envs/python` environment from the file system.
```
vim <manifest>
pixi global sync
```

## Open Questions

### Should we version the manifest?

Something like:

```
[manifest]
version = 1
```

We still have to figure out which existing programs do something similar and how they benefit from it.

### Multiple manifests

We could go for one default manifest, but also parse other manifests in the same directory.
In order to modify those with the `CLI` one would have to add an option `--manifest` to select the correct one.

- pixi-global.toml: Default
- pixi-global-company-tools.toml
- pixi-global-from-my-dotfiles.toml

It is unclear whether the first implementation already needs to support this.
At the very least we should put the manifest into its own folder like `~/.pixi/global/manifests/pixi-global.toml`
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ nav:
- Multi Platform: features/multi_platform_configuration.md
- Multi Environment: features/multi_environment.md
- Lockfile: features/lockfile.md
- Design Proposals:
- Pixi Global Manifest: design_proposals/pixi_global_manifest.md
- Advanced:
- Authentication: advanced/authentication.md
- Info Command: advanced/explain_info_command.md
Expand Down

0 comments on commit 712af8c

Please sign in to comment.