Skip to content

Commit

Permalink
refactor: Make self-update a compile time feature (prefix-dev#2213)
Browse files Browse the repository at this point in the history
Co-authored-by: Hofer-Julian <[email protected]>
  • Loading branch information
freundTech and Hofer-Julian authored Oct 11, 2024
1 parent c88db3e commit ddc54f7
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 57 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ jobs:
cargo build
--locked
--profile $CARGO_PROFILE
--features self_update
${{ steps.build-options.outputs.CARGO_BUILD_OPTIONS}}
- name: Build on Windows
Expand All @@ -271,6 +272,7 @@ jobs:
cargo build
--locked
--profile $env:CARGO_PROFILE
--features self_update
${{ steps.build-options.outputs.CARGO_BUILD_OPTIONS}}
- name: Set binary name & path
Expand Down
2 changes: 0 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ reqwest-middleware = "0.3.0"
reqwest-retry = "0.5.0"
rlimit = "0.10.1"
rstest = "0.19.0"
same-file = "1.0.6"
self-replace = "1.3.7"
serde = "1.0.198"
serde-untagged = "0.1.5"
Expand Down Expand Up @@ -159,6 +158,7 @@ rustls-tls = [
"rattler/rustls-tls",
"pixi_utils/rustls-tls",
]
self_update = []
slow_integration_tests = []

[dependencies]
Expand All @@ -184,7 +184,6 @@ crossbeam-channel = { workspace = true }
csv = { workspace = true }
deno_task_shell = { workspace = true }
dialoguer = { workspace = true }
dirs = { workspace = true }
distribution-filename = { workspace = true }
distribution-types = { workspace = true }
dunce = { workspace = true }
Expand Down Expand Up @@ -246,7 +245,6 @@ reqwest = { workspace = true, features = [
] }
reqwest-middleware = { workspace = true }
rlimit = { workspace = true }
same-file = { workspace = true }
self-replace = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ pixi self-update --version x.y.z
```

!!! note
If you've used a package manager like `brew`, `mamba`, `conda`, `paru` etc. to install `pixi`.
It's preferable to use the built-in update mechanism. e.g. `brew upgrade pixi`.
If you've used a package manager like `brew`, `mamba`, `conda`, `paru` etc. to install `pixi`
you must use the built-in update mechanism. e.g. `brew upgrade pixi`.

## Uninstall

Expand Down
52 changes: 52 additions & 0 deletions docs/packaging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
part: pixi
title: Packaging pixi
description: How to package pixi for distribution with another package manager?
---
This is a guide for distribution maintainers wanting to package pixi for a different package manager.
Users of pixi can ignore this page.

## Building

Pixi is written in Rust and compiled using Cargo, which are needed as compile-time dependencies.
At runtime pixi needs no dependencies in other than the runtime it was compiled against (`libc`, ...).

To build pixi run
```shell
cargo build --locked --profile dist
```
Instead of using the predefined `dist` profile, which is optimized for binary size, you can also pass other options to
let cargo optimize the binary for other metrics.

### Build-time Options

Pixi provides some compile-time options, which can influence the build

#### TLS

By default, pixi is built with Rustls TLS implementation. You can compile pixi using the platform native TLS implementation
using by adding `--no-default-features --feature native-tls` to the build command. Note that this might add additional
runtime dependencies, such as OpenSSL on Linux.

#### Self-Update

Pixi has a self-update functionality. When pixi is installed using another package manager one usually doesn't want pixi
to try to update itself and instead let it be updated by the package manager.
For this reason the self-update feature is disabled by default. It can be enabled by adding `--feature self_update` to
the build command.

When the self-update feature is disabled and a user tries to run `pixi self-update` an error message is displayed. This
message can be customized by setting the `PIXI_SELF_UPDATE_DISABLED_MESSAGE` environment variable at build time to point
the user to the package manager they should be using to update pixi.
```shell
PIXI_SELF_UPDATE_DISABLED_MESSAGE="`self-update` has been disabled for this build. Run `brew upgrade pixi` instead" cargo build --locked --profile dist
```

## Shell completion

After building pixi you can generate shell autocompletion scripts by running
```shell
pixi completion --shell <SHELL>
```
and saving the output to a file.
Currently supported shells are `bash`, `elvish`, `fish`, `nushell`, `powershell` and `zsh`.
7 changes: 2 additions & 5 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -698,19 +698,16 @@ pixi search -c robostack --platform linux-64 "plotjuggler*"

## `self-update`

Update pixi to the latest version or a specific version. If the pixi binary is not found in the default location (e.g.
`~/.pixi/bin/pixi`), pixi won't update to prevent breaking the current installation (Homebrew, etc.). The behaviour can be
overridden with the `--force` flag
Update pixi to the latest version or a specific version. If pixi was installed using another package manager this feature might not
be available and pixi should be updated using the package manager used to install it.

##### Options

- `--version <VERSION>`: The desired version (to downgrade or upgrade to). Update to the latest version if not specified.
- `--force`: Force the update even if the pixi binary is not found in the default location.

```shell
pixi self-update
pixi self-update --version 0.13.0
pixi self-update --force
```

## `info`
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ nav:
- CLI: reference/cli.md
- Misc:
- Pixi vision: vision.md
- Packaging: packaging.md
- Community: Community.md
- FAQ: FAQ.md

Expand Down
4 changes: 4 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ pub enum Command {
Info(info::Args),
Upload(upload::Args),
Search(search::Args),
#[cfg_attr(not(feature = "self_update"), clap(hide = true))]
SelfUpdate(self_update::Args),
Clean(clean::Args),
Completion(completion::Args),
Expand Down Expand Up @@ -272,7 +273,10 @@ pub async fn execute_command(command: Command) -> miette::Result<()> {
Command::Search(cmd) => search::execute(cmd).await,
Command::Project(cmd) => project::execute(cmd).await,
Command::Remove(cmd) => remove::execute(cmd).await,
#[cfg(feature = "self_update")]
Command::SelfUpdate(cmd) => self_update::execute(cmd).await,
#[cfg(not(feature = "self_update"))]
Command::SelfUpdate(cmd) => self_update::execute_stub(cmd).await,
Command::List(cmd) => list::execute(cmd).await,
Command::Tree(cmd) => tree::execute(cmd).await,
Command::Update(cmd) => update::execute(cmd).await,
Expand Down
50 changes: 5 additions & 45 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use std::{
env,
io::{Seek, Write},
};
use std::io::{Seek, Write};

use flate2::read::GzDecoder;
use tar::Archive;
Expand All @@ -12,19 +9,11 @@ use reqwest::Client;
use serde::Deserialize;

/// Update pixi to the latest version or a specific version.
///
/// If the pixi binary is not found in the default location
/// (e.g. `~/.pixi/bin/pixi`), pixi won't updated to prevent breaking the current installation (Homebrew, etc).
/// The behaviour can be overridden with the `--force` flag.
#[derive(Debug, clap::Parser)]
pub struct Args {
/// The desired version (to downgrade or upgrade to). Update to the latest version if not specified.
#[clap(long)]
version: Option<String>,

/// Force the update even if the pixi binary is not found in the default location.
#[clap(long)]
force: bool,
}

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -66,25 +55,6 @@ fn default_archive_name() -> Option<String> {
}

pub async fn execute(args: Args) -> miette::Result<()> {
// If args.force is false and pixi is not installed in the default location, stop here.
match (args.force, is_pixi_binary_default_location()) {
(false, false) => {
miette::bail!(
"pixi is not installed in the default location:
- Default pixi location: {}
- Pixi location detected: {}
It can happen when pixi has been installed via a dedicated package manager (such as Homebrew on macOS).
You can always use `pixi self-update --force` to force the update.",
default_pixi_binary_path().to_str().expect("Could not convert the default pixi binary path to a string"),
env::current_exe().expect("Failed to retrieve the current pixi binary path").to_str().expect("Could not convert the current pixi binary path to a string")
);
}
(false, true) => {}
(true, _) => {}
}

// Retrieve the target version information from github.
let target_version_json = match retrieve_target_version(&args.version).await {
Ok(target_version_json) => target_version_json,
Expand Down Expand Up @@ -242,19 +212,9 @@ fn pixi_binary_name() -> String {
format!("pixi{}", std::env::consts::EXE_SUFFIX)
}

fn default_pixi_binary_path() -> std::path::PathBuf {
dirs::home_dir()
.expect("Could not find the home directory")
.join(".pixi")
.join("bin")
.join(pixi_binary_name())
}

// check current binary is in the default pixi location
fn is_pixi_binary_default_location() -> bool {
same_file::is_same_file(
std::env::current_exe().expect("Failed to retrieve the current pixi binary path"),
default_pixi_binary_path(),
pub async fn execute_stub(_: Args) -> miette::Result<()> {
let message = option_env!("PIXI_SELF_UPDATE_DISABLED_MESSAGE");
miette::bail!(
message.unwrap_or("This version of pixi was built without self-update support. Please use your package manager to update pixi.")
)
.unwrap_or(false)
}

0 comments on commit ddc54f7

Please sign in to comment.