mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 21:35:00 +00:00
Merge 51bd377d94
into f609e1ddaf
This commit is contained in:
commit
c85c31d735
6 changed files with 277 additions and 138 deletions
|
@ -58,6 +58,15 @@ pub enum ListFormat {
|
||||||
Json,
|
Json,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Copy, clap::ValueEnum)]
|
||||||
|
pub enum SelfUpdateFormat {
|
||||||
|
/// Output plain text messages.
|
||||||
|
#[default]
|
||||||
|
Text,
|
||||||
|
/// Output result as JSON.
|
||||||
|
Json,
|
||||||
|
}
|
||||||
|
|
||||||
fn extra_name_with_clap_error(arg: &str) -> Result<ExtraName> {
|
fn extra_name_with_clap_error(arg: &str) -> Result<ExtraName> {
|
||||||
ExtraName::from_str(arg).map_err(|_err| {
|
ExtraName::from_str(arg).map_err(|_err| {
|
||||||
anyhow!(
|
anyhow!(
|
||||||
|
@ -651,6 +660,10 @@ pub struct SelfUpdateArgs {
|
||||||
/// Run without performing the update.
|
/// Run without performing the update.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub dry_run: bool,
|
pub dry_run: bool,
|
||||||
|
|
||||||
|
/// The format in which the result would be displayed.
|
||||||
|
#[arg(long, value_enum, default_value_t = SelfUpdateFormat::default())]
|
||||||
|
pub output_format: SelfUpdateFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use std::fmt::Write;
|
use std::fmt::{Display, Write};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use axoupdater::{AxoUpdater, AxoupdateError, UpdateRequest};
|
use axoupdater::{AxoUpdater, AxoupdateError, UpdateRequest, Version};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
|
use serde::{Serialize, Serializer};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
use uv_cli::SelfUpdateFormat;
|
||||||
use uv_client::WrappedReqwestError;
|
use uv_client::WrappedReqwestError;
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
|
|
||||||
|
@ -12,27 +14,204 @@ use crate::commands::ExitStatus;
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
use crate::settings::NetworkSettings;
|
use crate::settings::NetworkSettings;
|
||||||
|
|
||||||
|
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
|
struct VersionWrapper(Version);
|
||||||
|
|
||||||
|
impl Display for VersionWrapper {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Version> for VersionWrapper {
|
||||||
|
fn from(value: Version) -> VersionWrapper {
|
||||||
|
VersionWrapper(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for VersionWrapper {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.0.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(tag = "result", rename_all = "kebab-case")]
|
||||||
|
enum SelfUpdateOutput {
|
||||||
|
Offline,
|
||||||
|
ExternallyInstalled,
|
||||||
|
MultipleInstallations {
|
||||||
|
current: String,
|
||||||
|
other: String,
|
||||||
|
},
|
||||||
|
#[serde(rename = "github-rate-limit-exceeded")]
|
||||||
|
GitHubRateLimitExceeded,
|
||||||
|
OnLatest {
|
||||||
|
version: String,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
dry_run: bool,
|
||||||
|
},
|
||||||
|
WouldUpdate {
|
||||||
|
from: String,
|
||||||
|
to: String,
|
||||||
|
},
|
||||||
|
Updated {
|
||||||
|
from: Option<VersionWrapper>,
|
||||||
|
to: VersionWrapper,
|
||||||
|
tag: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SelfUpdateOutput {
|
||||||
|
fn exit_status(&self) -> ExitStatus {
|
||||||
|
match self {
|
||||||
|
Self::Offline => ExitStatus::Failure,
|
||||||
|
Self::ExternallyInstalled => ExitStatus::Error,
|
||||||
|
Self::MultipleInstallations { .. } => ExitStatus::Error,
|
||||||
|
Self::GitHubRateLimitExceeded => ExitStatus::Error,
|
||||||
|
Self::WouldUpdate { .. } => ExitStatus::Success,
|
||||||
|
Self::Updated { .. } => ExitStatus::Success,
|
||||||
|
Self::OnLatest { .. } => ExitStatus::Success,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Attempt to update the uv binary.
|
/// Attempt to update the uv binary.
|
||||||
pub(crate) async fn self_update(
|
pub(crate) async fn self_update(
|
||||||
version: Option<String>,
|
version: Option<String>,
|
||||||
token: Option<String>,
|
token: Option<String>,
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
|
output_format: SelfUpdateFormat,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
network_settings: NetworkSettings,
|
network_settings: NetworkSettings,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
if network_settings.connectivity.is_offline() {
|
let output = self_update_impl(
|
||||||
writeln!(
|
version,
|
||||||
printer.stderr(),
|
token,
|
||||||
"{}",
|
dry_run,
|
||||||
format_args!(
|
output_format,
|
||||||
concat!(
|
printer,
|
||||||
"{}{} Self-update is not possible because network connectivity is disabled (i.e., with `--offline`)"
|
network_settings,
|
||||||
),
|
)
|
||||||
"error".red().bold(),
|
.await?;
|
||||||
":".bold()
|
let exit_status = output.exit_status();
|
||||||
|
|
||||||
|
if matches!(output_format, SelfUpdateFormat::Json) {
|
||||||
|
writeln!(printer.stdout(), "{}", serde_json::to_string(&output)?)?;
|
||||||
|
return Ok(exit_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = match output {
|
||||||
|
SelfUpdateOutput::Offline => format!(
|
||||||
|
concat!(
|
||||||
|
"{}{} Self-update is not possible because network connectivity is disabled (i.e., with `--offline`)"
|
||||||
|
),
|
||||||
|
"error".red().bold(),
|
||||||
|
":".bold()
|
||||||
|
),
|
||||||
|
SelfUpdateOutput::ExternallyInstalled => format!(
|
||||||
|
concat!(
|
||||||
|
"{}{} Self-update is only available for uv binaries installed via the standalone installation scripts.",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"If you installed uv with pip, brew, or another package manager, update uv with `pip install --upgrade`, `brew upgrade`, or similar."
|
||||||
|
),
|
||||||
|
"error".red().bold(),
|
||||||
|
":".bold()
|
||||||
|
),
|
||||||
|
SelfUpdateOutput::MultipleInstallations { current, other } => format!(
|
||||||
|
concat!(
|
||||||
|
"{}{} Self-update is only available for uv binaries installed via the standalone installation scripts.",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"The current executable is at `{}` but the standalone installer was used to install uv to `{}`. Are multiple copies of uv installed?"
|
||||||
|
),
|
||||||
|
"error".red().bold(),
|
||||||
|
":".bold(),
|
||||||
|
current.bold().cyan(),
|
||||||
|
other.bold().cyan()
|
||||||
|
),
|
||||||
|
SelfUpdateOutput::GitHubRateLimitExceeded => format!(
|
||||||
|
"{}{} GitHub API rate limit exceeded. Please provide a GitHub token via the {} option.",
|
||||||
|
"error".red().bold(),
|
||||||
|
":".bold(),
|
||||||
|
"`--token`".green().bold()
|
||||||
|
),
|
||||||
|
|
||||||
|
SelfUpdateOutput::OnLatest { version, dry_run } => {
|
||||||
|
if dry_run {
|
||||||
|
format!(
|
||||||
|
"You're on the latest version of uv ({})",
|
||||||
|
format!("v{version}").bold().white()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"{}{} You're on the latest version of uv ({})",
|
||||||
|
"success".green().bold(),
|
||||||
|
":".bold(),
|
||||||
|
format!("v{version}").bold().cyan()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfUpdateOutput::WouldUpdate { from, to } => {
|
||||||
|
let to = if to == "latest" {
|
||||||
|
"the latest version".to_string()
|
||||||
|
} else {
|
||||||
|
format!("v{to}")
|
||||||
|
};
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"Would update uv from {} to {}",
|
||||||
|
format!("v{from}").bold().white(),
|
||||||
|
to.bold().white(),
|
||||||
)
|
)
|
||||||
)?;
|
}
|
||||||
return Ok(ExitStatus::Failure);
|
|
||||||
|
SelfUpdateOutput::Updated { from, to, tag } => {
|
||||||
|
let direction = if from.as_ref().is_some_and(|from| *from > to) {
|
||||||
|
"Downgraded"
|
||||||
|
} else {
|
||||||
|
"Upgraded"
|
||||||
|
};
|
||||||
|
|
||||||
|
let version_information = if let Some(from) = from {
|
||||||
|
format!(
|
||||||
|
"from {} to {}",
|
||||||
|
format!("v{from}").bold().cyan(),
|
||||||
|
format!("v{to}").bold().cyan(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!("to {}", format!("v{to}").bold().cyan())
|
||||||
|
};
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"{}{} {direction} uv {}! {}",
|
||||||
|
"success".green().bold(),
|
||||||
|
":".bold(),
|
||||||
|
version_information,
|
||||||
|
format!("https://github.com/astral-sh/uv/releases/tag/{tag}").cyan()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
writeln!(printer.stderr(), "{message}")?;
|
||||||
|
Ok(exit_status)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn self_update_impl(
|
||||||
|
version: Option<String>,
|
||||||
|
token: Option<String>,
|
||||||
|
dry_run: bool,
|
||||||
|
output_format: SelfUpdateFormat,
|
||||||
|
printer: Printer,
|
||||||
|
network_settings: NetworkSettings,
|
||||||
|
) -> Result<SelfUpdateOutput> {
|
||||||
|
if network_settings.connectivity.is_offline() {
|
||||||
|
return Ok(SelfUpdateOutput::Offline);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut updater = AxoUpdater::new_for("uv");
|
let mut updater = AxoUpdater::new_for("uv");
|
||||||
|
@ -46,21 +225,7 @@ pub(crate) async fn self_update(
|
||||||
// uv was likely installed via a package manager.
|
// uv was likely installed via a package manager.
|
||||||
let Ok(updater) = updater.load_receipt() else {
|
let Ok(updater) = updater.load_receipt() else {
|
||||||
debug!("No receipt found; assuming uv was installed via a package manager");
|
debug!("No receipt found; assuming uv was installed via a package manager");
|
||||||
writeln!(
|
return Ok(SelfUpdateOutput::ExternallyInstalled);
|
||||||
printer.stderr(),
|
|
||||||
"{}",
|
|
||||||
format_args!(
|
|
||||||
concat!(
|
|
||||||
"{}{} Self-update is only available for uv binaries installed via the standalone installation scripts.",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"If you installed uv with pip, brew, or another package manager, update uv with `pip install --upgrade`, `brew upgrade`, or similar."
|
|
||||||
),
|
|
||||||
"error".red().bold(),
|
|
||||||
":".bold()
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
return Ok(ExitStatus::Error);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// If we know what our version is, ignore whatever the receipt thinks it is!
|
// If we know what our version is, ignore whatever the receipt thinks it is!
|
||||||
|
@ -78,35 +243,24 @@ pub(crate) async fn self_update(
|
||||||
let current_exe = std::env::current_exe()?;
|
let current_exe = std::env::current_exe()?;
|
||||||
let receipt_prefix = updater.install_prefix_root()?;
|
let receipt_prefix = updater.install_prefix_root()?;
|
||||||
|
|
||||||
|
return Ok(SelfUpdateOutput::MultipleInstallations {
|
||||||
|
current: current_exe.simplified_display().to_string(),
|
||||||
|
other: receipt_prefix.simplified_display().to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(output_format, SelfUpdateFormat::Text) {
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"{}",
|
"{}",
|
||||||
format_args!(
|
format_args!(
|
||||||
concat!(
|
"{}{} Checking for updates...",
|
||||||
"{}{} Self-update is only available for uv binaries installed via the standalone installation scripts.",
|
"info".cyan().bold(),
|
||||||
"\n",
|
":".bold()
|
||||||
"\n",
|
|
||||||
"The current executable is at `{}` but the standalone installer was used to install uv to `{}`. Are multiple copies of uv installed?"
|
|
||||||
),
|
|
||||||
"error".red().bold(),
|
|
||||||
":".bold(),
|
|
||||||
current_exe.simplified_display().bold().cyan(),
|
|
||||||
receipt_prefix.simplified_display().bold().cyan()
|
|
||||||
)
|
)
|
||||||
)?;
|
)?;
|
||||||
return Ok(ExitStatus::Error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"{}",
|
|
||||||
format_args!(
|
|
||||||
"{}{} Checking for updates...",
|
|
||||||
"info".cyan().bold(),
|
|
||||||
":".bold()
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let update_request = if let Some(version) = version {
|
let update_request = if let Some(version) = version {
|
||||||
UpdateRequest::SpecificTag(version)
|
UpdateRequest::SpecificTag(version)
|
||||||
} else {
|
} else {
|
||||||
|
@ -118,108 +272,49 @@ pub(crate) async fn self_update(
|
||||||
if dry_run {
|
if dry_run {
|
||||||
// TODO(charlie): `updater.fetch_release` isn't public, so we can't say what the latest
|
// TODO(charlie): `updater.fetch_release` isn't public, so we can't say what the latest
|
||||||
// version is.
|
// version is.
|
||||||
if updater.is_update_needed().await? {
|
return if updater.is_update_needed().await? {
|
||||||
let version = match update_request {
|
let version = match update_request {
|
||||||
UpdateRequest::Latest | UpdateRequest::LatestMaybePrerelease => {
|
UpdateRequest::Latest | UpdateRequest::LatestMaybePrerelease => {
|
||||||
"the latest version".to_string()
|
"latest".to_string()
|
||||||
}
|
}
|
||||||
UpdateRequest::SpecificTag(version) | UpdateRequest::SpecificVersion(version) => {
|
UpdateRequest::SpecificTag(version) | UpdateRequest::SpecificVersion(version) => {
|
||||||
format!("v{version}")
|
version
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
Ok(SelfUpdateOutput::WouldUpdate {
|
||||||
"Would update uv from {} to {}",
|
from: env!("CARGO_PKG_VERSION").to_string(),
|
||||||
format!("v{}", env!("CARGO_PKG_VERSION")).bold().white(),
|
to: version,
|
||||||
version.bold().white(),
|
})
|
||||||
)?;
|
|
||||||
} else {
|
} else {
|
||||||
writeln!(
|
Ok(SelfUpdateOutput::OnLatest {
|
||||||
printer.stderr(),
|
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||||
"{}",
|
dry_run: true,
|
||||||
format_args!(
|
})
|
||||||
"You're on the latest version of uv ({})",
|
};
|
||||||
format!("v{}", env!("CARGO_PKG_VERSION")).bold().white()
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
return Ok(ExitStatus::Success);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the updater. This involves a network request, since we need to determine the latest
|
// Run the updater. This involves a network request, since we need to determine the latest
|
||||||
// available version of uv.
|
// available version of uv.
|
||||||
match updater.run().await {
|
match updater.run().await {
|
||||||
Ok(Some(result)) => {
|
Ok(Some(result)) => Ok(SelfUpdateOutput::Updated {
|
||||||
let direction = if result
|
from: result.old_version.map(VersionWrapper),
|
||||||
.old_version
|
to: result.new_version.into(),
|
||||||
.as_ref()
|
tag: result.new_version_tag,
|
||||||
.is_some_and(|old_version| *old_version > result.new_version)
|
}),
|
||||||
{
|
Ok(None) => Ok(SelfUpdateOutput::OnLatest {
|
||||||
"Downgraded"
|
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||||
} else {
|
dry_run: false,
|
||||||
"Upgraded"
|
}),
|
||||||
};
|
Err(err) => match err {
|
||||||
|
AxoupdateError::Reqwest(err) => {
|
||||||
let version_information = if let Some(old_version) = result.old_version {
|
|
||||||
format!(
|
|
||||||
"from {} to {}",
|
|
||||||
format!("v{old_version}").bold().cyan(),
|
|
||||||
format!("v{}", result.new_version).bold().cyan(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!("to {}", format!("v{}", result.new_version).bold().cyan())
|
|
||||||
};
|
|
||||||
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"{}",
|
|
||||||
format_args!(
|
|
||||||
"{}{} {direction} uv {}! {}",
|
|
||||||
"success".green().bold(),
|
|
||||||
":".bold(),
|
|
||||||
version_information,
|
|
||||||
format!(
|
|
||||||
"https://github.com/astral-sh/uv/releases/tag/{}",
|
|
||||||
result.new_version_tag
|
|
||||||
)
|
|
||||||
.cyan()
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
Ok(None) => {
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"{}",
|
|
||||||
format_args!(
|
|
||||||
"{}{} You're on the latest version of uv ({})",
|
|
||||||
"success".green().bold(),
|
|
||||||
":".bold(),
|
|
||||||
format!("v{}", env!("CARGO_PKG_VERSION")).bold().cyan()
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
return if let AxoupdateError::Reqwest(err) = err {
|
|
||||||
if err.status() == Some(http::StatusCode::FORBIDDEN) && token.is_none() {
|
if err.status() == Some(http::StatusCode::FORBIDDEN) && token.is_none() {
|
||||||
writeln!(
|
Ok(SelfUpdateOutput::GitHubRateLimitExceeded)
|
||||||
printer.stderr(),
|
|
||||||
"{}",
|
|
||||||
format_args!(
|
|
||||||
"{}{} GitHub API rate limit exceeded. Please provide a GitHub token via the {} option.",
|
|
||||||
"error".red().bold(),
|
|
||||||
":".bold(),
|
|
||||||
"`--token`".green().bold()
|
|
||||||
)
|
|
||||||
)?;
|
|
||||||
Ok(ExitStatus::Error)
|
|
||||||
} else {
|
} else {
|
||||||
Err(WrappedReqwestError::from(err).into())
|
Err(WrappedReqwestError::from(err).into())
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
Err(err.into())
|
_ => Err(err.into()),
|
||||||
};
|
},
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ExitStatus::Success)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1076,12 +1076,14 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
target_version,
|
target_version,
|
||||||
token,
|
token,
|
||||||
dry_run,
|
dry_run,
|
||||||
|
output_format,
|
||||||
}),
|
}),
|
||||||
}) => {
|
}) => {
|
||||||
commands::self_update(
|
commands::self_update(
|
||||||
target_version,
|
target_version,
|
||||||
token,
|
token,
|
||||||
dry_run,
|
dry_run,
|
||||||
|
output_format,
|
||||||
printer,
|
printer,
|
||||||
globals.network_settings,
|
globals.network_settings,
|
||||||
)
|
)
|
||||||
|
|
|
@ -400,6 +400,15 @@ impl TestContext {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a filter that filters out version fields in `self version`'s JSON output.
|
||||||
|
pub fn with_filtered_version_fields(mut self) -> Self {
|
||||||
|
self.filters.push((
|
||||||
|
r#""(version|from|to)":"[^"]+""#.to_string(),
|
||||||
|
r#""$1":"<version>""#.to_string(),
|
||||||
|
));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Clear filters on `TestContext`.
|
/// Clear filters on `TestContext`.
|
||||||
pub fn clear_filters(mut self) -> Self {
|
pub fn clear_filters(mut self) -> Self {
|
||||||
self.filters.clear();
|
self.filters.clear();
|
||||||
|
|
|
@ -57,3 +57,18 @@ fn test_self_update_offline_error() {
|
||||||
error: Self-update is not possible because network connectivity is disabled (i.e., with `--offline`)
|
error: Self-update is not possible because network connectivity is disabled (i.e., with `--offline`)
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_self_update_offline_json() {
|
||||||
|
let context = TestContext::new("3.12");
|
||||||
|
|
||||||
|
uv_snapshot!(context.self_update().arg("--offline").arg("--output-format=json"),
|
||||||
|
@r#"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
{"result":"offline"}
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
|
@ -5226,7 +5226,12 @@ uv self update [OPTIONS] [TARGET_VERSION]
|
||||||
<p>May also be set with the <code>UV_NO_PROGRESS</code> environment variable.</p></dd><dt id="uv-self-update--no-python-downloads"><a href="#uv-self-update--no-python-downloads"><code>--no-python-downloads</code></a></dt><dd><p>Disable automatic downloads of Python.</p>
|
<p>May also be set with the <code>UV_NO_PROGRESS</code> environment variable.</p></dd><dt id="uv-self-update--no-python-downloads"><a href="#uv-self-update--no-python-downloads"><code>--no-python-downloads</code></a></dt><dd><p>Disable automatic downloads of Python.</p>
|
||||||
</dd><dt id="uv-self-update--offline"><a href="#uv-self-update--offline"><code>--offline</code></a></dt><dd><p>Disable network access.</p>
|
</dd><dt id="uv-self-update--offline"><a href="#uv-self-update--offline"><code>--offline</code></a></dt><dd><p>Disable network access.</p>
|
||||||
<p>When disabled, uv will only use locally cached data and locally available files.</p>
|
<p>When disabled, uv will only use locally cached data and locally available files.</p>
|
||||||
<p>May also be set with the <code>UV_OFFLINE</code> environment variable.</p></dd><dt id="uv-self-update--project"><a href="#uv-self-update--project"><code>--project</code></a> <i>project</i></dt><dd><p>Run the command within the given project directory.</p>
|
<p>May also be set with the <code>UV_OFFLINE</code> environment variable.</p></dd><dt id="uv-self-update--output-format"><a href="#uv-self-update--output-format"><code>--output-format</code></a> <i>output-format</i></dt><dd><p>The format in which the result would be displayed</p>
|
||||||
|
<p>[default: text]</p><p>Possible values:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>text</code>: Output plain text messages</li>
|
||||||
|
<li><code>json</code>: Output result as JSON</li>
|
||||||
|
</ul></dd><dt id="uv-self-update--project"><a href="#uv-self-update--project"><code>--project</code></a> <i>project</i></dt><dd><p>Run the command within the given project directory.</p>
|
||||||
<p>All <code>pyproject.toml</code>, <code>uv.toml</code>, and <code>.python-version</code> files will be discovered by walking up the directory tree from the project root, as will the project's virtual environment (<code>.venv</code>).</p>
|
<p>All <code>pyproject.toml</code>, <code>uv.toml</code>, and <code>.python-version</code> files will be discovered by walking up the directory tree from the project root, as will the project's virtual environment (<code>.venv</code>).</p>
|
||||||
<p>Other command-line arguments (such as relative paths) will be resolved relative to the current working directory.</p>
|
<p>Other command-line arguments (such as relative paths) will be resolved relative to the current working directory.</p>
|
||||||
<p>See <code>--directory</code> to change the working directory entirely.</p>
|
<p>See <code>--directory</code> to change the working directory entirely.</p>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue