Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/dev-tools/backends/pipx.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ This relies on having `uv` (recommended) or `pipx` installed.

If you have `uv` installed, mise will use `uv tool install` under the hood and you don't need to install `pipx` to run the commands containing "pipx:".

When [`install_before`](/configuration/settings.html#install_before) is set, mise forwards the cutoff
to transitive Python dependency resolution during install. The uv install path uses uv's
`--exclude-newer` flag, and the `pipx` fallback passes pip's `--uploaded-prior-to` flag.

In case you need `pipx` for other reasons, you can install it with or without mise.
Here is how to install `pipx` with mise:

Expand Down
3 changes: 3 additions & 0 deletions docs/dev-tools/mise-lock.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,9 @@ install_before = "7d" # only resolve to versions released more than 7 days ago

This pairs well with lockfiles — use `install_before` to avoid picking up brand-new releases, and lockfiles to pin the exact versions you've vetted.

Some package-manager backends also forward this cutoff into transitive dependency resolution during
install. This includes `npm:` and `pipx:` tools.

## See Also

- [Configuration Settings](/configuration/settings) - All available settings
Expand Down
7 changes: 4 additions & 3 deletions docs/tips-and-tricks.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,10 @@ install_before = "7d" # only install versions released more than 7 days ago

Supports relative durations (`7d`, `6m`, `1y`) and absolute dates (`2024-06-01`). For most backends, this only affects fuzzy version resolution (e.g., `node@20` or `latest`) — explicitly pinned versions like `node@22.5.0` bypass the filter.

For `npm:` tools, the same cutoff is also forwarded to transitive dependency resolution during
install. Refer to the [npm backend docs](/dev-tools/backends/npm.html) for package-manager support
details.
For `npm:` and `pipx:` tools, the same cutoff is also forwarded to transitive dependency resolution
during install. Refer to the
[npm backend docs](/dev-tools/backends/npm.html) and [pipx backend docs](/dev-tools/backends/pipx.html)
for package-manager support details.

You can also set `install_before` per-tool to override the global setting:

Expand Down
3 changes: 3 additions & 0 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,9 @@ like `node@20` or `latest`. Explicitly pinned versions like `node@22.5.0` are no
allowing you to selectively use newer versions for specific tools while keeping others behind the
cutoff date.
Some package-manager backends also forward the cutoff to transitive dependency resolution during
install. This includes `npm:` and `pipx:` tools.
Can be overridden with the `--before` CLI flag or per-tool with the `install_before` tool option.
```toml
Expand Down
77 changes: 75 additions & 2 deletions src/backend/pipx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ use async_trait::async_trait;
use eyre::{Result, eyre};
use indexmap::IndexMap;
use itertools::Itertools;
use jiff::Timestamp;
use regex::Regex;
use std::collections::BTreeMap;
use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::{fmt::Debug, sync::Arc};
Expand Down Expand Up @@ -229,6 +231,7 @@ impl Backend for PIPXBackend {
ctx.pr.as_ref(),
)
.await?;
cmd = cmd.args(Self::uv_exclude_newer_args(ctx.before_date));
if let Some(args) = tv.request.options().get("uvx_args") {
cmd = cmd.args(shell_words::split(args)?);
}
Expand All @@ -244,6 +247,7 @@ impl Backend for PIPXBackend {
ctx.pr.as_ref(),
)
.await?;
cmd = cmd.args(Self::pip_uploaded_prior_to_args(ctx.before_date));
if let Some(args) = tv.request.options().get("pipx_args") {
cmd = cmd.args(shell_words::split(args)?);
}
Expand Down Expand Up @@ -288,6 +292,23 @@ pub fn install_time_option_keys() -> Vec<String> {
}

impl PIPXBackend {
fn uv_exclude_newer_args(before_date: Option<Timestamp>) -> Vec<OsString> {
match before_date {
Some(before_date) => vec!["--exclude-newer".into(), before_date.to_string().into()],
None => vec![],
}
}

fn pip_uploaded_prior_to_args(before_date: Option<Timestamp>) -> Vec<OsString> {
match before_date {
Some(before_date) => vec![
"--pip-args".into(),
format!("--uploaded-prior-to={before_date}").into(),
],
None => vec![],
}
}
Comment thread
risu729 marked this conversation as resolved.
Comment thread
greptile-apps[bot] marked this conversation as resolved.

pub fn from_arg(ba: BackendArg) -> Self {
Self {
latest_version_cache: CacheManagerBuilder::new(
Expand Down Expand Up @@ -419,10 +440,11 @@ impl PIPXBackend {
cmd = cmd.arg(arg);
}
cmd.with_pr(pr)
.env("PIPX_HOME", tv.install_path())
.env("PIPX_BIN_DIR", tv.install_path().join("bin"))
.env("PIP_INDEX_URL", Self::get_index_url()?)
.envs(ts.env_with_path_without_tools(config).await?)
.env_remove("PIPX_SHARED_LIBS")
.env("PIPX_HOME", tv.install_path())
.env("PIPX_BIN_DIR", tv.install_path().join("bin"))
.prepend_path(ts.list_paths(config).await)?
.prepend_path(vec![tv.install_path().join("bin")])?
.prepend_path(b.dependency_toolset(config).await?.list_paths(config).await)
Expand Down Expand Up @@ -640,3 +662,54 @@ fn fix_venv_python_symlink(install_path: &Path, pkg_name: &str) -> Result<()> {
fn fix_venv_python_symlink(_install_path: &Path, _pkg_name: &str) -> Result<()> {
Ok(())
}

#[cfg(test)]
mod tests {
use super::PIPXBackend;
use pretty_assertions::assert_eq;
use std::ffi::OsString;

#[test]
fn test_uv_exclude_newer_args_with_cutoff() {
let before_date = "2024-01-02T03:04:05Z".parse().unwrap();
let args = PIPXBackend::uv_exclude_newer_args(Some(before_date));

assert_eq!(
args,
vec![
OsString::from("--exclude-newer"),
OsString::from("2024-01-02T03:04:05Z"),
]
);
}

#[test]
fn test_uv_exclude_newer_args_without_cutoff() {
assert_eq!(
PIPXBackend::uv_exclude_newer_args(None),
Vec::<OsString>::new()
);
}

#[test]
fn test_pip_uploaded_prior_to_args_with_cutoff() {
let before_date = "2024-01-02T03:04:05Z".parse().unwrap();
let args = PIPXBackend::pip_uploaded_prior_to_args(Some(before_date));

assert_eq!(
args,
vec![
OsString::from("--pip-args"),
OsString::from("--uploaded-prior-to=2024-01-02T03:04:05Z"),
]
);
}

#[test]
fn test_pip_uploaded_prior_to_args_without_cutoff() {
assert_eq!(
PIPXBackend::pip_uploaded_prior_to_args(None),
Vec::<OsString>::new()
);
}
Comment thread
greptile-apps[bot] marked this conversation as resolved.
}
9 changes: 9 additions & 0 deletions src/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,15 @@ impl<'a> CmdLineRunner<'a> {
self.cmd.env(key, val);
self
}

pub fn env_remove<K>(mut self, key: K) -> Self
where
K: AsRef<OsStr>,
{
self.cmd.env_remove(key);
self
}

pub fn envs<I, K, V>(mut self, vars: I) -> Self
where
I: IntoIterator<Item = (K, V)>,
Expand Down
Loading