fix(poetry): skip if not installed with official script (#989)
* fix(poetry): skip if not installed with official script * feat(poetry): add poetry_force_self_update config option * docs: give this config a more detailed explanation --------- Co-authored-by: Steve Lau <stevelauc@outlook.com>
This commit is contained in:
@@ -103,6 +103,13 @@
|
|||||||
# enable_pipupgrade = true ###disabled by default
|
# enable_pipupgrade = true ###disabled by default
|
||||||
# pipupgrade_arguments = "-y -u --pip-path pip" ###disabled by default
|
# pipupgrade_arguments = "-y -u --pip-path pip" ###disabled by default
|
||||||
|
|
||||||
|
# For the poetry step, by default, Topgrade skips its update if poetry is not
|
||||||
|
# installed with the official script. This configuration entry forces Topgrade
|
||||||
|
# to run the update in this case.
|
||||||
|
#
|
||||||
|
# (default: false)
|
||||||
|
# poetry_force_self_update = true
|
||||||
|
|
||||||
|
|
||||||
[composer]
|
[composer]
|
||||||
# self_update = true
|
# self_update = true
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ pub struct Python {
|
|||||||
enable_pip_review_local: Option<bool>,
|
enable_pip_review_local: Option<bool>,
|
||||||
enable_pipupgrade: Option<bool>,
|
enable_pipupgrade: Option<bool>,
|
||||||
pipupgrade_arguments: Option<String>,
|
pipupgrade_arguments: Option<String>,
|
||||||
|
poetry_force_self_update: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Debug, Merge)]
|
#[derive(Deserialize, Default, Debug, Merge)]
|
||||||
@@ -1627,6 +1628,13 @@ impl Config {
|
|||||||
.and_then(|python| python.enable_pip_review_local)
|
.and_then(|python| python.enable_pip_review_local)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
pub fn poetry_force_self_update(&self) -> bool {
|
||||||
|
self.config_file
|
||||||
|
.python
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|python| python.poetry_force_self_update)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn display_time(&self) -> bool {
|
pub fn display_time(&self) -> bool {
|
||||||
self.config_file
|
self.config_file
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
|
use std::ffi::OsStr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::{env, path::Path};
|
use std::{env, path::Path};
|
||||||
@@ -1029,8 +1030,88 @@ pub fn run_lensfun_update_data(ctx: &ExecutionContext) -> Result<()> {
|
|||||||
|
|
||||||
pub fn run_poetry(ctx: &ExecutionContext) -> Result<()> {
|
pub fn run_poetry(ctx: &ExecutionContext) -> Result<()> {
|
||||||
let poetry = require("poetry")?;
|
let poetry = require("poetry")?;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn get_interpreter(poetry: &PathBuf) -> Result<PathBuf> {
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
|
let script = fs::read(poetry)?;
|
||||||
|
if let Some(r) = script.iter().position(|&b| b == b'\n') {
|
||||||
|
let first_line = &script[..r];
|
||||||
|
if first_line.starts_with(b"#!") {
|
||||||
|
return Ok(OsStr::from_bytes(&first_line[2..]).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(eyre!("Could not find shebang"))
|
||||||
|
}
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn get_interpreter(poetry: &PathBuf) -> Result<PathBuf> {
|
||||||
|
let data = fs::read(poetry)?;
|
||||||
|
|
||||||
|
// https://bitbucket.org/vinay.sajip/simple_launcher/src/master/compare_launchers.py
|
||||||
|
|
||||||
|
let pos = match data.windows(4).rposition(|b| b == b"PK\x05\x06") {
|
||||||
|
Some(i) => i,
|
||||||
|
None => return Err(eyre!("Not a ZIP archive")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let cdr_size = match data.get(pos + 12..pos + 16) {
|
||||||
|
Some(b) => u32::from_le_bytes(b.try_into().unwrap()) as usize,
|
||||||
|
None => return Err(eyre!("Invalid CDR size")),
|
||||||
|
};
|
||||||
|
let cdr_offset = match data.get(pos + 16..pos + 20) {
|
||||||
|
Some(b) => u32::from_le_bytes(b.try_into().unwrap()) as usize,
|
||||||
|
None => return Err(eyre!("Invalid CDR offset")),
|
||||||
|
};
|
||||||
|
if pos < cdr_size + cdr_offset {
|
||||||
|
return Err(eyre!("Invalid ZIP archive"));
|
||||||
|
}
|
||||||
|
let arc_pos = pos - cdr_size - cdr_offset;
|
||||||
|
let shebang = match data[..arc_pos].windows(2).rposition(|b| b == b"#!") {
|
||||||
|
Some(l) => &data[l + 2..arc_pos - 1],
|
||||||
|
None => return Err(eyre!("Could not find shebang")),
|
||||||
|
};
|
||||||
|
|
||||||
|
// shebang line is utf8
|
||||||
|
Ok(std::str::from_utf8(shebang)?.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.config().poetry_force_self_update() {
|
||||||
|
debug!("forcing poetry self update");
|
||||||
|
} else {
|
||||||
|
let interpreter = match get_interpreter(&poetry) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(SkipStep(format!("Could not find interpreter for {}: {}", poetry.display(), e)).into())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
debug!("poetry interpreter: {}", interpreter.display());
|
||||||
|
|
||||||
|
let check_official_install_script =
|
||||||
|
"import sys; from os import path; print('Y') if path.isfile(path.join(sys.prefix, 'poetry_env')) else print('N')";
|
||||||
|
let output = Command::new(&interpreter)
|
||||||
|
.args(["-c", check_official_install_script])
|
||||||
|
.output_checked_utf8()?;
|
||||||
|
let stdout = output.stdout.trim();
|
||||||
|
let official_install = match stdout {
|
||||||
|
"N" => false,
|
||||||
|
"Y" => true,
|
||||||
|
_ => unreachable!("unexpected output from `check_official_install_script`"),
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("poetry is official install: {}", official_install);
|
||||||
|
|
||||||
|
if !official_install {
|
||||||
|
return Err(SkipStep("Not installed with the official script".to_string()).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
print_separator("Poetry");
|
print_separator("Poetry");
|
||||||
ctx.run_type().execute(poetry).args(["self", "update"]).status_checked()
|
ctx.run_type()
|
||||||
|
.execute(&poetry)
|
||||||
|
.args(["self", "update"])
|
||||||
|
.status_checked()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_uv(ctx: &ExecutionContext) -> Result<()> {
|
pub fn run_uv(ctx: &ExecutionContext) -> Result<()> {
|
||||||
|
|||||||
Reference in New Issue
Block a user