Skip to content

Commit

Permalink
feat: get mise sync python --uv to work (#3706)
Browse files Browse the repository at this point in the history
* Revert "fix: disable reverse uv syncing (#3704)"

This reverts commit d2b175e.

* feat: get `mise sync python --uv`
  • Loading branch information
jdx authored Dec 19, 2024
1 parent d2b175e commit c48b6f3
Show file tree
Hide file tree
Showing 18 changed files with 1,125 additions and 52 deletions.
19 changes: 10 additions & 9 deletions Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ include = [
"/src/plugins/core/assets/**",
"/aqua-registry/pkgs/**/registry.yaml",
]
rust-version = "1.79"
build = "build.rs"
rust-version = "1.82"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down Expand Up @@ -78,7 +78,7 @@ git2 = "<1"
glob = "0.3"
globset = "0.4"
heck = "0.5"
home = "= 0.5.9" # TODO: bump this when we can bump msrv
home = "0.5"
humantime = "2"
indenter = "0.3"
indexmap = { version = "2", features = ["serde"] }
Expand Down
2 changes: 1 addition & 1 deletion docs/cli/sync/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Get tool versions from pyenv

### `--uv`

Sync tool versions from uv
Sync tool versions with uv (2-way sync)

Examples:

Expand Down
File renamed without changes.
File renamed without changes.
8 changes: 8 additions & 0 deletions e2e/sync/test_sync_python_uv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

assert "mise use -g uv python@3.11.3"
assert "mise x -- uv python install 3.11.1"
export UV_PYTHON_DOWNLOADS=never
assert "mise sync python --uv"
assert "mise x python@3.11.1 -- python -V" "Python 3.11.1"
assert "mise x -- uv run -p 3.11.3 -- python -V" "Python 3.11.3"
2 changes: 1 addition & 1 deletion mise.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,7 @@ This won't overwrite any existing installs but will overwrite any existing symli
$ uv run -p 3.10.0 -- python -V - uses mise-provided python
"
flag "--pyenv" help="Get tool versions from pyenv"
flag "--uv" help="Sync tool versions from uv"
flag "--uv" help="Sync tool versions with uv (2-way sync)"
}
cmd "ruby" help="Symlinks all ruby tool versions from an external tool into mise" {
after_long_help r"Examples:
Expand Down
4 changes: 2 additions & 2 deletions src/backend/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ impl Backend for CargoBackend {
if let Some(bin) = opts.get("bin") {
cmd = cmd.arg(format!("--bin={bin}"));
}
if !opts
if opts
.get("locked")
.is_some_and(|v| v.to_lowercase() == "false")
.is_none_or(|v| v.to_lowercase() != "false")
{
cmd = cmd.arg("--locked");
}
Expand Down
60 changes: 29 additions & 31 deletions src/cli/sync/python.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use eyre::Result;
use itertools::sorted;
use std::env::consts::{ARCH, OS};

use crate::env::PYENV_ROOT;
use crate::{backend, config, dirs, env, file};
Expand All @@ -16,7 +17,7 @@ pub struct SyncPython {
#[clap(long)]
pyenv: bool,

/// Sync tool versions from uv
/// Sync tool versions with uv (2-way sync)
#[clap(long)]
uv: bool,
}
Expand Down Expand Up @@ -79,36 +80,33 @@ impl SyncPython {
}
}

// TODO: disable reverse syncing until there is a way to deal with these 2 files that uv needs:
// ❯ diff -rq uv mise
// Only in uv/lib/python3.11: EXTERNALLY-MANAGED
// Files uv/lib/python3.11/_sysconfigdata__darwin_darwin.py and mise/lib/python3.11/_sysconfigdata__darwin_darwin.py differ
// See https://github.com/jdx/mise/issues/3654
//let subdirs = file::dir_subdirs(&installed_python_versions_path)?;
//for v in sorted(subdirs) {
// if v.starts_with(".") {
// continue;
// }
// let src = installed_python_versions_path.join(&v);
// if src.is_symlink() {
// continue;
// }
// // ~/.local/share/uv/python/cpython-3.10.16-macos-aarch64-none
// // ~/.local/share/uv/python/cpython-3.13.0-linux-x86_64-gnu
// let os = OS;
// let arch = if cfg!(target_arch = "x86_64") {
// "x86_64-gnu"
// } else if cfg!(target_arch = "aarch64") {
// "aarch64-none"
// } else {
// ARCH
// };
// let dst = uv_versions_path.join(format!("cpython-{v}-{os}-{arch}"));
// if !dst.exists() {
// file::make_symlink(&src, &dst)?;
// miseprintln!("Synced python@{v} from mise to uv");
// }
//}
let subdirs = file::dir_subdirs(&installed_python_versions_path)?;
for v in sorted(subdirs) {
if v.starts_with(".") {
continue;
}
let src = installed_python_versions_path.join(&v);
if src.is_symlink() {
continue;
}
// ~/.local/share/uv/python/cpython-3.10.16-macos-aarch64-none
// ~/.local/share/uv/python/cpython-3.13.0-linux-x86_64-gnu
let os = OS;
let arch = if cfg!(target_arch = "x86_64") {
"x86_64-gnu"
} else if cfg!(target_arch = "aarch64") {
"aarch64-none"
} else {
ARCH
};
let dst = uv_versions_path.join(format!("cpython-{v}-{os}-{arch}"));
if !dst.exists() {
// TODO: uv doesn't support symlinked dirs
// https://github.com/astral-sh/uv/blob/e65a273f1b6b7c3ab129d902e93adeda4da20636/crates/uv-python/src/managed.rs#L196
file::clone_dir(&src, &dst)?;
miseprintln!("Synced python@{v} from mise to uv");
}
}
Ok(())
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,17 @@ pub fn desymlink_path(p: &Path) -> PathBuf {
}
}

pub fn clone_dir(from: &PathBuf, to: &PathBuf) -> Result<()> {
if cfg!(macos) {
cmd!("cp", "-cR", from, to).run()?;
} else if cfg!(windows) {
cmd!("robocopy", from, to, "/MIR").run()?;
} else {
cmd!("cp", "--reflink=auto", "-r", from, to).run()?;
}
Ok(())
}

#[cfg(test)]
mod tests {

Expand Down
4 changes: 2 additions & 2 deletions src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@ fn with_github_auth(url: &Url, mut req: RequestBuilder) -> RequestBuilder {
fn display_github_rate_limit(resp: &Response) {
let status = resp.status().as_u16();
if status == 403 || status == 429 {
if !resp
if resp
.headers()
.get("x-ratelimit-remaining")
.is_some_and(|r| r == "0")
.is_none_or(|r| r != "0")
{
return;
}
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ mod shell;
mod shims;
mod shorthands;
mod sops;
mod sysconfig;
pub(crate) mod task;
pub(crate) mod tera;
pub(crate) mod timeout;
Expand Down
31 changes: 28 additions & 3 deletions src/plugins/core/python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::http::{HTTP, HTTP_FETCH};
use crate::install_context::InstallContext;
use crate::toolset::{ToolRequest, ToolVersion, Toolset};
use crate::ui::progress_report::SingleReport;
use crate::{cmd, dirs, file, plugins};
use crate::{cmd, dirs, file, plugins, sysconfig};
use eyre::{bail, eyre};
use flate2::read::GzDecoder;
use itertools::Itertools;
Expand Down Expand Up @@ -208,8 +208,33 @@ impl PythonPlugin {
file::rename(&entry, install.join(filename))?;
}
}
#[cfg(unix)]
file::make_symlink(&install.join("bin/python3"), &install.join("bin/python"))?;

let re_digits = regex!(r"\d+");
let version_parts = tv.version.split('.').collect_vec();
let major = re_digits
.find(version_parts[0])
.and_then(|m| m.as_str().parse().ok());
let minor = re_digits
.find(version_parts[1])
.and_then(|m| m.as_str().parse().ok());
let suffix = version_parts
.get(2)
.map(|s| re_digits.replace(s, "").to_string());
if cfg!(unix) {
if let (Some(major), Some(minor), Some(suffix)) = (major, minor, suffix) {
if tv.request.options().get("patch_sysconfig") != Some(&"false".to_string()) {
sysconfig::update_sysconfig(&install, major, minor, &suffix)?;
}
} else {
debug!("failed to update sysconfig with version {}", tv.version);
}
}

if !install.join("bin").join("python").exists() {
#[cfg(unix)]
file::make_symlink(&install.join("bin/python3"), &install.join("bin/python"))?;
}

Ok(())
}

Expand Down
21 changes: 21 additions & 0 deletions src/sysconfig/LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 Astral Software Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading

0 comments on commit c48b6f3

Please sign in to comment.