Skip to content

Commit 38fa3c4

Browse files
committed
feat: yazi-cli: support different Git hosting services
1 parent e1773b1 commit 38fa3c4

File tree

3 files changed

+40
-27
lines changed

3 files changed

+40
-27
lines changed

yazi-cli/src/package/deploy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const TRACKER: &str = "DO_NOT_MODIFY_ANYTHING_IN_THIS_DIRECTORY";
88

99
impl Package {
1010
pub(super) async fn deploy(&mut self) -> Result<()> {
11-
let Some(name) = self.name().map(ToOwned::to_owned) else { bail!("Invalid package url") };
11+
let name = self.name().to_owned();
1212
let from = self.local().join(&self.child);
1313

1414
self.header("Deploying package `{name}`")?;

yazi-cli/src/package/package.rs

+33-19
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,64 @@
11
use std::{borrow::Cow, io::BufWriter, path::PathBuf};
22

3-
use anyhow::Result;
3+
use anyhow::{Context, Result};
44
use md5::{Digest, Md5};
55
use yazi_shared::Xdg;
66

77
pub(crate) struct Package {
8-
pub(crate) repo: String,
8+
pub(crate) host: String,
9+
pub(crate) owner: String,
10+
pub(crate) repo_name: String,
911
pub(crate) child: String,
1012
pub(crate) rev: String,
1113
pub(super) is_flavor: bool,
1214
}
1315

1416
impl Package {
15-
pub(super) fn new(url: &str, rev: Option<&str>) -> Self {
17+
pub(super) fn new(url: &str, rev: Option<&str>) -> Result<Self> {
1618
let mut parts = url.splitn(2, ':');
1719

18-
let mut repo = parts.next().unwrap_or_default().to_owned();
20+
let mut repo_part = parts.next().unwrap_or_default().to_owned();
1921
let child = if let Some(s) = parts.next() {
2022
format!("{s}.yazi")
2123
} else {
22-
repo.push_str(".yazi");
24+
repo_part.push_str(".yazi");
2325
String::new()
2426
};
2527

26-
Self { repo, child, rev: rev.unwrap_or_default().to_owned(), is_flavor: false }
28+
let mut repo = repo_part.rsplit('/');
29+
let repo_name = repo.next().context("failed to get repo name")?.to_owned();
30+
let owner = repo.next().context("failed to get repo owner")?.to_owned();
31+
let host = repo.next().unwrap_or("github.com").to_owned();
32+
33+
Ok(Self {
34+
repo_name,
35+
owner,
36+
host,
37+
child,
38+
rev: rev.unwrap_or_default().to_owned(),
39+
is_flavor: false,
40+
})
2741
}
2842

2943
#[inline]
3044
pub(super) fn use_(&self) -> Cow<str> {
3145
if self.child.is_empty() {
32-
self.repo.trim_end_matches(".yazi").into()
46+
format!("{}/{}/{}", self.host, self.owner, self.repo_name.trim_end_matches(".yazi")).into()
3347
} else {
34-
format!("{}:{}", self.repo, self.child.trim_end_matches(".yazi")).into()
48+
format!(
49+
"{}/{}/{}:{}",
50+
self.host,
51+
self.owner,
52+
self.repo_name,
53+
self.child.trim_end_matches(".yazi")
54+
)
55+
.into()
3556
}
3657
}
3758

3859
#[inline]
39-
pub(super) fn name(&self) -> Option<&str> {
40-
let s = if self.child.is_empty() {
41-
self.repo.split('/').last().filter(|s| !s.is_empty())
42-
} else {
43-
Some(self.child.as_str())
44-
};
45-
46-
s.filter(|s| s.bytes().all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'z' | b'-' | b'.')))
60+
pub(super) fn name(&self) -> &str {
61+
if self.child.is_empty() { self.repo_name.as_str() } else { self.child.as_str() }
4762
}
4863

4964
#[inline]
@@ -55,8 +70,7 @@ impl Package {
5570

5671
#[inline]
5772
pub(super) fn remote(&self) -> String {
58-
// Support more Git hosting services in the future
59-
format!("https://github.com/{}.git", self.repo)
73+
format!("https://{}/{}/{}.git", self.host, self.owner, self.repo_name)
6074
}
6175

6276
pub(super) fn header(&self, s: &str) -> Result<()> {
@@ -68,7 +82,7 @@ impl Package {
6882
SetAttributes(Attribute::Reverse.into()),
6983
SetAttributes(Attribute::Bold.into()),
7084
Print(" "),
71-
Print(s.replacen("{name}", self.name().unwrap_or_default(), 1)),
85+
Print(s.replacen("{name}", self.name(), 1)),
7286
Print(" "),
7387
SetAttributes(Attribute::Reset.into()),
7488
Print("\n\n"),

yazi-cli/src/package/parser.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ impl Package {
3434
}
3535

3636
pub(crate) async fn add_to_config(use_: &str) -> Result<()> {
37-
let mut package = Self::new(use_, None);
38-
let Some(name) = package.name() else { bail!("Invalid package `use`") };
37+
let mut package = Self::new(use_, None).context("Invalid package `use`")?;
38+
let name = package.name();
3939

4040
let path = Xdg::config_dir().join("package.toml");
4141
let mut doc = Self::ensure_config(&fs::read_to_string(&path).await.unwrap_or_default())?;
@@ -76,7 +76,7 @@ impl Package {
7676
let use_ = dep.get("use").and_then(|d| d.as_str()).context("Missing `use` field")?;
7777
let rev = dep.get("rev").and_then(|d| d.as_str());
7878

79-
let mut package = Package::new(use_, rev);
79+
let mut package = Package::new(use_, rev)?;
8080
if upgrade {
8181
package.upgrade().await?;
8282
} else {
@@ -144,10 +144,9 @@ impl Package {
144144
fn ensure_unique(doc: &DocumentMut, name: &str) -> Result<()> {
145145
#[inline]
146146
fn same(v: &Value, name: &str) -> bool {
147-
v.as_inline_table()
148-
.and_then(|t| t.get("use"))
149-
.and_then(|v| v.as_str())
150-
.is_some_and(|s| Package::new(s, None).name() == Some(name))
147+
v.as_inline_table().and_then(|t| t.get("use")).and_then(|v| v.as_str()).is_some_and(|s| {
148+
if let Ok(pkg) = Package::new(s, None) { pkg.name() == name } else { false }
149+
})
151150
}
152151

153152
if doc["plugin"]["deps"].as_array().unwrap().into_iter().any(|v| same(v, name)) {

0 commit comments

Comments
 (0)