feat: yazi-cli: support different Git hosting services

This commit is contained in:
dm9pZCAq 2024-10-02 20:54:26 +03:00
parent dcbe7873cd
commit 9782c0fa8f
3 changed files with 40 additions and 27 deletions

View file

@ -8,7 +8,7 @@ const TRACKER: &str = "DO_NOT_MODIFY_ANYTHING_IN_THIS_DIRECTORY";
impl Package { impl Package {
pub(super) async fn deploy(&mut self) -> Result<()> { pub(super) async fn deploy(&mut self) -> Result<()> {
let Some(name) = self.name().map(ToOwned::to_owned) else { bail!("Invalid package url") }; let name = self.name().to_owned();
let from = self.local().join(&self.child); let from = self.local().join(&self.child);
self.header("Deploying package `{name}`")?; self.header("Deploying package `{name}`")?;

View file

@ -1,49 +1,64 @@
use std::{borrow::Cow, io::BufWriter, path::PathBuf}; use std::{borrow::Cow, io::BufWriter, path::PathBuf};
use anyhow::Result; use anyhow::{Context, Result};
use md5::{Digest, Md5}; use md5::{Digest, Md5};
use yazi_shared::Xdg; use yazi_shared::Xdg;
pub(crate) struct Package { pub(crate) struct Package {
pub(crate) repo: String, pub(crate) host: String,
pub(crate) owner: String,
pub(crate) repo_name: String,
pub(crate) child: String, pub(crate) child: String,
pub(crate) rev: String, pub(crate) rev: String,
pub(super) is_flavor: bool, pub(super) is_flavor: bool,
} }
impl Package { impl Package {
pub(super) fn new(url: &str, rev: Option<&str>) -> Self { pub(super) fn new(url: &str, rev: Option<&str>) -> Result<Self> {
let mut parts = url.splitn(2, ':'); let mut parts = url.splitn(2, ':');
let mut repo = parts.next().unwrap_or_default().to_owned(); let mut repo_part = parts.next().unwrap_or_default().to_owned();
let child = if let Some(s) = parts.next() { let child = if let Some(s) = parts.next() {
format!("{s}.yazi") format!("{s}.yazi")
} else { } else {
repo.push_str(".yazi"); repo_part.push_str(".yazi");
String::new() String::new()
}; };
Self { repo, child, rev: rev.unwrap_or_default().to_owned(), is_flavor: false } let mut repo = repo_part.rsplit('/');
let repo_name = repo.next().context("failed to get repo name")?.to_owned();
let owner = repo.next().context("failed to get repo owner")?.to_owned();
let host = repo.next().unwrap_or("github.com").to_owned();
Ok(Self {
repo_name,
owner,
host,
child,
rev: rev.unwrap_or_default().to_owned(),
is_flavor: false,
})
} }
#[inline] #[inline]
pub(super) fn use_(&self) -> Cow<str> { pub(super) fn use_(&self) -> Cow<str> {
if self.child.is_empty() { if self.child.is_empty() {
self.repo.trim_end_matches(".yazi").into() format!("{}/{}/{}", self.host, self.owner, self.repo_name.trim_end_matches(".yazi")).into()
} else { } else {
format!("{}:{}", self.repo, self.child.trim_end_matches(".yazi")).into() format!(
"{}/{}/{}:{}",
self.host,
self.owner,
self.repo_name,
self.child.trim_end_matches(".yazi")
)
.into()
} }
} }
#[inline] #[inline]
pub(super) fn name(&self) -> Option<&str> { pub(super) fn name(&self) -> &str {
let s = if self.child.is_empty() { if self.child.is_empty() { self.repo_name.as_str() } else { self.child.as_str() }
self.repo.split('/').last().filter(|s| !s.is_empty())
} else {
Some(self.child.as_str())
};
s.filter(|s| s.bytes().all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'z' | b'-' | b'.')))
} }
#[inline] #[inline]
@ -55,8 +70,7 @@ impl Package {
#[inline] #[inline]
pub(super) fn remote(&self) -> String { pub(super) fn remote(&self) -> String {
// Support more Git hosting services in the future format!("https://{}/{}/{}.git", self.host, self.owner, self.repo_name)
format!("https://github.com/{}.git", self.repo)
} }
pub(super) fn header(&self, s: &str) -> Result<()> { pub(super) fn header(&self, s: &str) -> Result<()> {
@ -68,7 +82,7 @@ impl Package {
SetAttributes(Attribute::Reverse.into()), SetAttributes(Attribute::Reverse.into()),
SetAttributes(Attribute::Bold.into()), SetAttributes(Attribute::Bold.into()),
Print(" "), Print(" "),
Print(s.replacen("{name}", self.name().unwrap_or_default(), 1)), Print(s.replacen("{name}", self.name(), 1)),
Print(" "), Print(" "),
SetAttributes(Attribute::Reset.into()), SetAttributes(Attribute::Reset.into()),
Print("\n\n"), Print("\n\n"),

View file

@ -34,8 +34,8 @@ impl Package {
} }
pub(crate) async fn add_to_config(use_: &str) -> Result<()> { pub(crate) async fn add_to_config(use_: &str) -> Result<()> {
let mut package = Self::new(use_, None); let mut package = Self::new(use_, None).context("Invalid package `use`")?;
let Some(name) = package.name() else { bail!("Invalid package `use`") }; let name = package.name();
let path = Xdg::config_dir().join("package.toml"); let path = Xdg::config_dir().join("package.toml");
let mut doc = Self::ensure_config(&fs::read_to_string(&path).await.unwrap_or_default())?; let mut doc = Self::ensure_config(&fs::read_to_string(&path).await.unwrap_or_default())?;
@ -76,7 +76,7 @@ impl Package {
let use_ = dep.get("use").and_then(|d| d.as_str()).context("Missing `use` field")?; let use_ = dep.get("use").and_then(|d| d.as_str()).context("Missing `use` field")?;
let rev = dep.get("rev").and_then(|d| d.as_str()); let rev = dep.get("rev").and_then(|d| d.as_str());
let mut package = Package::new(use_, rev); let mut package = Package::new(use_, rev)?;
if upgrade { if upgrade {
package.upgrade().await?; package.upgrade().await?;
} else { } else {
@ -144,10 +144,9 @@ impl Package {
fn ensure_unique(doc: &DocumentMut, name: &str) -> Result<()> { fn ensure_unique(doc: &DocumentMut, name: &str) -> Result<()> {
#[inline] #[inline]
fn same(v: &Value, name: &str) -> bool { fn same(v: &Value, name: &str) -> bool {
v.as_inline_table() v.as_inline_table().and_then(|t| t.get("use")).and_then(|v| v.as_str()).is_some_and(|s| {
.and_then(|t| t.get("use")) if let Ok(pkg) = Package::new(s, None) { pkg.name() == name } else { false }
.and_then(|v| v.as_str()) })
.is_some_and(|s| Package::new(s, None).name() == Some(name))
} }
if doc["plugin"]["deps"].as_array().unwrap().into_iter().any(|v| same(v, name)) { if doc["plugin"]["deps"].as_array().unwrap().into_iter().any(|v| same(v, name)) {