fix: replace # with : to resolve the problem where certain shells recognize it as a special character (#1490)

This commit is contained in:
三咲雅 · Misaki Masa 2024-08-15 17:21:06 +08:00 committed by GitHub
parent c75960eae6
commit fc304ca043
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 61 additions and 25 deletions

View File

@ -45,6 +45,7 @@ async fn main() -> anyhow::Result<()> {
Command::Pack(cmd) => {
package::init();
package::Package::migrate().await?;
if cmd.install {
package::Package::install_from_config("plugin", false).await?;
package::Package::install_from_config("flavor", false).await?;
@ -54,8 +55,16 @@ async fn main() -> anyhow::Result<()> {
} else if cmd.upgrade {
package::Package::install_from_config("plugin", true).await?;
package::Package::install_from_config("flavor", true).await?;
} else if let Some(repo) = &cmd.add {
package::Package::add_to_config(repo).await?;
} else if let Some(mut repo) = cmd.add {
// TODO: remove this in the future
if repo.contains("#") {
repo = repo.replace("#", ":");
println!(
"WARNING: `#` has been deprecated in Yazi 0.3.1, please use `:` instead. See https://github.com/sxyazi/yazi/issues/1471 for more information."
);
}
package::Package::add_to_config(&repo).await?;
}
}
}

View File

@ -14,7 +14,7 @@ impl Package {
Git::pull(&path).await?;
};
self.commit = Git::hash(&path).await?;
self.rev = Git::hash(&path).await?;
self.deploy().await
}
}

View File

@ -15,8 +15,8 @@ impl Git {
Self::exec(|c| c.current_dir(path).arg("fetch")).await
}
pub(super) async fn checkout(path: &Path, commit: &str) -> Result<()> {
Self::exec(|c| c.current_dir(path).args(["checkout", commit])).await
pub(super) async fn checkout(path: &Path, rev: &str) -> Result<()> {
Self::exec(|c| c.current_dir(path).args(["checkout", rev])).await
}
pub(super) async fn pull(path: &Path) -> Result<()> {
@ -31,14 +31,14 @@ impl Git {
.args(["rev-parse", "--short", "HEAD"])
.output()
.await
.context("Failed to get current commit hash")?;
.context("Failed to get current revision")?;
if !output.status.success() {
bail!("Getting commit hash failed: {}", output.status);
bail!("Getting revision failed: {}", output.status);
}
Ok(strip_trailing_newline(
String::from_utf8(output.stdout).context("Failed to parse commit hash")?,
String::from_utf8(output.stdout).context("Failed to parse revision")?,
))
}

View File

@ -14,10 +14,10 @@ impl Package {
Git::fetch(&path).await?;
};
if self.commit.is_empty() {
self.commit = Git::hash(&path).await?;
if self.rev.is_empty() {
self.rev = Git::hash(&path).await?;
} else {
Git::checkout(&path, self.commit.trim_start_matches('=')).await?;
Git::checkout(&path, self.rev.trim_start_matches('=')).await?;
}
self.deploy().await

View File

@ -7,13 +7,13 @@ use yazi_shared::Xdg;
pub(crate) struct Package {
pub(crate) repo: String,
pub(crate) child: String,
pub(crate) commit: String,
pub(crate) rev: String,
pub(super) is_flavor: bool,
}
impl Package {
pub(super) fn new(url: &str, commit: Option<&str>) -> Self {
let mut parts = url.splitn(2, '#');
pub(super) fn new(url: &str, rev: Option<&str>) -> Self {
let mut parts = url.splitn(2, ':');
let mut repo = parts.next().unwrap_or_default().to_owned();
let child = if let Some(s) = parts.next() {
@ -23,7 +23,7 @@ impl Package {
String::new()
};
Self { repo, child, commit: commit.unwrap_or_default().to_owned(), is_flavor: false }
Self { repo, child, rev: rev.unwrap_or_default().to_owned(), is_flavor: false }
}
#[inline]
@ -31,7 +31,7 @@ impl Package {
if self.child.is_empty() {
self.repo.trim_end_matches(".yazi").into()
} else {
format!("{}#{}", self.repo, self.child.trim_end_matches(".yazi")).into()
format!("{}:{}", self.repo, self.child.trim_end_matches(".yazi")).into()
}
}

View File

@ -6,6 +6,33 @@ use yazi_shared::Xdg;
use super::Package;
impl Package {
// TODO: remove this in the future
pub(crate) async fn migrate() -> Result<()> {
let path = Xdg::config_dir().join("package.toml");
let mut doc = Self::ensure_config(&fs::read_to_string(&path).await.unwrap_or_default())?;
fn impl_(deps: &mut Array) -> Result<()> {
for dep in deps.iter_mut() {
let dep = dep.as_inline_table_mut().context("Dependency must be an inline table")?;
let use_ = dep.get("use").and_then(|d| d.as_str()).context("Missing `use` field")?;
if use_.contains("#") {
dep["use"] = use_.replace("#", ":").into();
}
if let Some(commit) = dep.get("commit").map(ToOwned::to_owned) {
dep.remove("commit");
dep.insert("rev", commit);
}
}
Ok(())
}
impl_(doc["plugin"]["deps"].as_array_mut().unwrap())?;
impl_(doc["flavor"]["deps"].as_array_mut().unwrap())?;
fs::write(path, doc.to_string()).await?;
Ok(())
}
pub(crate) async fn add_to_config(use_: &str) -> Result<()> {
let mut package = Self::new(use_, None);
let Some(name) = package.name() else { bail!("Invalid package `use`") };
@ -18,8 +45,8 @@ impl Package {
let mut table = InlineTable::new();
table.insert("use", package.use_().as_ref().into());
if !package.commit.is_empty() {
table.insert("commit", package.commit.into());
if !package.rev.is_empty() {
table.insert("rev", package.rev.into());
}
if package.is_flavor {
@ -47,19 +74,19 @@ impl Package {
for dep in deps.iter_mut() {
let dep = dep.as_inline_table_mut().context("Dependency must be an inline table")?;
let use_ = dep.get("use").and_then(|d| d.as_str()).context("Missing `use` field")?;
let commit = dep.get("commit").and_then(|d| d.as_str());
let rev = dep.get("rev").and_then(|d| d.as_str());
let mut package = Package::new(use_, commit);
let mut package = Package::new(use_, rev);
if upgrade {
package.upgrade().await?;
} else {
package.install().await?;
}
if package.commit.is_empty() {
dep.remove("commit");
if package.rev.is_empty() {
dep.remove("rev");
} else {
dep.insert("commit", package.commit.into());
dep.insert("rev", package.rev.into());
}
}

View File

@ -4,6 +4,6 @@ use super::Package;
impl Package {
pub(super) async fn upgrade(&mut self) -> Result<()> {
if self.commit.starts_with('=') { Ok(()) } else { self.add().await }
if self.rev.starts_with('=') { Ok(()) } else { self.add().await }
}
}

View File

@ -26,7 +26,7 @@ impl From<Cmd> for Opt {
impl Completion {
fn match_candidates(word: &str, cache: &[String]) -> Vec<String> {
let smart = word.chars().all(|c| c.is_lowercase());
let smart = !word.bytes().any(|c| c.is_ascii_uppercase());
let flow = cache.iter().try_fold(
(Vec::with_capacity(LIMIT), Vec::with_capacity(LIMIT)),