mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat(pkg): add --force flag to skip hash verification on upgrade, install, and delete
When upgrading yazi across versions, the content hash computation may change, causing false "You have modified the contents" errors on packages the user never touched. This leaves users unable to upgrade, install, or delete any managed package without manually deleting each one first. Add a --force/-f flag to `ya pkg upgrade`, `ya pkg install`, and `ya pkg delete` that skips the hash_check, allowing the operation to proceed. A warning is printed when the check is skipped. The error message now also suggests --force as a remedy. Closes #2735, #3291
This commit is contained in:
parent
a246e9c7c0
commit
c11064c3aa
9 changed files with 45 additions and 26 deletions
|
|
@ -77,17 +77,27 @@ pub(super) enum CommandPkg {
|
|||
Delete {
|
||||
/// Packages to delete.
|
||||
#[arg(index = 1, num_args = 1..)]
|
||||
ids: Vec<String>,
|
||||
ids: Vec<String>,
|
||||
/// Force delete, skipping local modification checks.
|
||||
#[arg(short, long)]
|
||||
force: bool,
|
||||
},
|
||||
/// Install all packages.
|
||||
Install,
|
||||
Install {
|
||||
/// Force install, skipping local modification checks.
|
||||
#[arg(short, long)]
|
||||
force: bool,
|
||||
},
|
||||
/// List all packages.
|
||||
List,
|
||||
/// Upgrade all packages.
|
||||
Upgrade {
|
||||
/// Packages to upgrade, upgrade all if unspecified.
|
||||
#[arg(index = 1, num_args = 0..)]
|
||||
ids: Vec<String>,
|
||||
ids: Vec<String>,
|
||||
/// Force upgrade, skipping local modification checks.
|
||||
#[arg(short, long)]
|
||||
force: bool,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,10 +78,10 @@ async fn run() -> anyhow::Result<()> {
|
|||
let mut pkg = package::Package::load().await?;
|
||||
match cmd {
|
||||
CommandPkg::Add { ids } => pkg.add_many(&ids).await?,
|
||||
CommandPkg::Delete { ids } => pkg.delete_many(&ids).await?,
|
||||
CommandPkg::Install => pkg.install().await?,
|
||||
CommandPkg::Delete { ids, force } => pkg.delete_many(&ids, force).await?,
|
||||
CommandPkg::Install { force } => pkg.install(force).await?,
|
||||
CommandPkg::List => pkg.print()?,
|
||||
CommandPkg::Upgrade { ids } => pkg.upgrade_many(&ids).await?,
|
||||
CommandPkg::Upgrade { ids, force } => pkg.upgrade_many(&ids, force).await?,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use super::{Dependency, Git};
|
|||
use crate::shared::must_exists;
|
||||
|
||||
impl Dependency {
|
||||
pub(super) async fn add(&mut self) -> Result<()> {
|
||||
pub(super) async fn add(&mut self, force: bool) -> Result<()> {
|
||||
self.header("Upgrading package `{name}`")?;
|
||||
|
||||
let path = self.local();
|
||||
|
|
@ -14,7 +14,7 @@ impl Dependency {
|
|||
Git::clone(&self.remote(), &path).await?;
|
||||
};
|
||||
|
||||
self.deploy().await?;
|
||||
self.deploy(force).await?;
|
||||
self.rev = Git::revision(&path).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use super::Dependency;
|
|||
use crate::shared::{maybe_exists, remove_sealed};
|
||||
|
||||
impl Dependency {
|
||||
pub(super) async fn delete(&self) -> Result<()> {
|
||||
pub(super) async fn delete(&self, force: bool) -> Result<()> {
|
||||
self.header("Deleting package `{name}`")?;
|
||||
|
||||
let dir = self.target();
|
||||
|
|
@ -14,7 +14,11 @@ impl Dependency {
|
|||
return Ok(outln!("Not found, skipping")?);
|
||||
}
|
||||
|
||||
self.hash_check().await?;
|
||||
if force {
|
||||
outln!("Warning: skipping local modification check for `{}`", self.name)?;
|
||||
} else {
|
||||
self.hash_check().await?;
|
||||
}
|
||||
self.delete_assets().await?;
|
||||
self.delete_sources().await?;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use super::Dependency;
|
|||
use crate::shared::{copy_and_seal, maybe_exists};
|
||||
|
||||
impl Dependency {
|
||||
pub(super) async fn deploy(&mut self) -> Result<()> {
|
||||
pub(super) async fn deploy(&mut self, force: bool) -> Result<()> {
|
||||
let from = self.local().join(&self.child);
|
||||
|
||||
self.header("Deploying package `{name}`")?;
|
||||
|
|
@ -17,7 +17,11 @@ impl Dependency {
|
|||
let to = self.target();
|
||||
let exists = maybe_exists(&to).await;
|
||||
if exists {
|
||||
self.hash_check().await?;
|
||||
if force {
|
||||
outln!("Warning: skipping local modification check for `{}`", self.name)?;
|
||||
} else {
|
||||
self.hash_check().await?;
|
||||
}
|
||||
}
|
||||
|
||||
Local::regular(&to).create_dir_all().await?;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ impl Dependency {
|
|||
if self.hash != self.hash().await? {
|
||||
bail!(
|
||||
"You have modified the contents of the `{}` {}. For safety, the operation has been aborted.
|
||||
Please manually delete it from `{}` and re-run the command.",
|
||||
Please manually delete it from `{}` and re-run the command.
|
||||
If you have not modified this package, re-run the command with --force to skip this check.",
|
||||
self.name,
|
||||
if self.is_flavor { "flavor" } else { "plugin" },
|
||||
self.target().display()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use super::{Dependency, Git};
|
|||
use crate::shared::must_exists;
|
||||
|
||||
impl Dependency {
|
||||
pub(super) async fn install(&mut self) -> Result<()> {
|
||||
pub(super) async fn install(&mut self, force: bool) -> Result<()> {
|
||||
self.header("Fetching package `{name}`")?;
|
||||
|
||||
let path = self.local();
|
||||
|
|
@ -18,7 +18,7 @@ impl Dependency {
|
|||
Git::checkout(&path, self.rev.trim_start_matches('=')).await?;
|
||||
}
|
||||
|
||||
self.deploy().await?;
|
||||
self.deploy(force).await?;
|
||||
if self.rev.is_empty() {
|
||||
self.rev = Git::revision(&path).await?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,19 +28,19 @@ impl Package {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn delete_many(&mut self, uses: &[String]) -> Result<()> {
|
||||
pub(crate) async fn delete_many(&mut self, uses: &[String], force: bool) -> Result<()> {
|
||||
for u in uses {
|
||||
let r = self.delete(u).await;
|
||||
let r = self.delete(u, force).await;
|
||||
self.save().await?;
|
||||
r?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn install(&mut self) -> Result<()> {
|
||||
pub(crate) async fn install(&mut self, force: bool) -> Result<()> {
|
||||
macro_rules! go {
|
||||
($dep:expr) => {
|
||||
let r = $dep.install().await;
|
||||
let r = $dep.install(force).await;
|
||||
self.save().await?;
|
||||
r?;
|
||||
};
|
||||
|
|
@ -55,11 +55,11 @@ impl Package {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn upgrade_many(&mut self, uses: &[String]) -> Result<()> {
|
||||
pub(crate) async fn upgrade_many(&mut self, uses: &[String], force: bool) -> Result<()> {
|
||||
macro_rules! go {
|
||||
($dep:expr) => {
|
||||
if uses.is_empty() || uses.contains(&$dep.r#use) {
|
||||
let r = $dep.upgrade().await;
|
||||
let r = $dep.upgrade(force).await;
|
||||
self.save().await?;
|
||||
r?;
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ impl Package {
|
|||
)
|
||||
}
|
||||
|
||||
dep.add().await?;
|
||||
dep.add(false).await?;
|
||||
if dep.is_flavor {
|
||||
self.flavors.push(dep);
|
||||
} else {
|
||||
|
|
@ -116,12 +116,12 @@ impl Package {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete(&mut self, r#use: &str) -> Result<()> {
|
||||
async fn delete(&mut self, r#use: &str, force: bool) -> Result<()> {
|
||||
let Some(dep) = self.identical(&Dependency::from_str(r#use)?).cloned() else {
|
||||
bail!("`{}` was not found in package.toml", r#use)
|
||||
};
|
||||
|
||||
dep.delete().await?;
|
||||
dep.delete(force).await?;
|
||||
if dep.is_flavor {
|
||||
self.flavors.retain(|d| !d.identical(&dep));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use anyhow::Result;
|
|||
use super::Dependency;
|
||||
|
||||
impl Dependency {
|
||||
pub(super) async fn upgrade(&mut self) -> Result<()> {
|
||||
if self.rev.starts_with('=') { Ok(()) } else { self.add().await }
|
||||
pub(super) async fn upgrade(&mut self, force: bool) -> Result<()> {
|
||||
if self.rev.starts_with('=') { Ok(()) } else { self.add(force).await }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue