mirror of
https://codeberg.org/Cyborus/forgejo-cli.git
synced 2024-11-23 10:21:48 +01:00
decouple repo info from key info
This commit is contained in:
parent
66dd7096e4
commit
51b180d4a9
3 changed files with 67 additions and 100 deletions
94
src/keys.rs
94
src/keys.rs
|
@ -42,35 +42,6 @@ impl KeyInfo {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_current(&self) -> eyre::Result<(HostInfo<'_>, RepoInfo)> {
|
||||
let repo = git2::Repository::open(".")?;
|
||||
let remote_url = get_remote(&repo)?;
|
||||
let login_info = self.get_login(&remote_url)?;
|
||||
|
||||
let mut path = remote_url
|
||||
.path_segments()
|
||||
.ok_or_else(|| eyre!("bad path"))?
|
||||
.collect::<Vec<_>>();
|
||||
let repo_name = path
|
||||
.pop()
|
||||
.ok_or_else(|| eyre!("path does not have repo name"))?
|
||||
.to_string();
|
||||
let owner = path
|
||||
.pop()
|
||||
.ok_or_else(|| eyre!("path does not have owner name"))?
|
||||
.to_string();
|
||||
let base_path = path.join("/");
|
||||
|
||||
let mut url = remote_url;
|
||||
url.set_path(&base_path);
|
||||
let host_info = HostInfo { url, login_info };
|
||||
let repo_info = RepoInfo {
|
||||
owner,
|
||||
name: repo_name,
|
||||
};
|
||||
Ok((host_info, repo_info))
|
||||
}
|
||||
|
||||
pub fn get_login(&self, url: &Url) -> eyre::Result<&LoginInfo> {
|
||||
let host_str = url
|
||||
.host_str()
|
||||
|
@ -87,59 +58,10 @@ impl KeyInfo {
|
|||
.ok_or_else(|| eyre!("not signed in to {domain}"))?;
|
||||
Ok(login_info)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HostInfo<'a> {
|
||||
url: Url,
|
||||
login_info: &'a LoginInfo,
|
||||
}
|
||||
|
||||
impl<'a> HostInfo<'a> {
|
||||
pub fn api(&self) -> Result<forgejo_api::Forgejo, forgejo_api::ForgejoError> {
|
||||
self.login_info.api_for(self.url())
|
||||
pub fn get_api(&self, url: &Url) -> eyre::Result<forgejo_api::Forgejo> {
|
||||
self.get_login(url)?.api_for(url).map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
|
||||
pub fn username(&self) -> &'a str {
|
||||
&self.login_info.name
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RepoInfo {
|
||||
owner: String,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl RepoInfo {
|
||||
pub fn owner(&self) -> &str {
|
||||
&self.owner
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
fn repo_from_url(url: &Url) -> eyre::Result<&str> {
|
||||
let mut iter = url
|
||||
.path_segments()
|
||||
.ok_or_else(|| eyre!("failed to get path from url"))?;
|
||||
soft_assert::soft_assert!(
|
||||
matches!(iter.next(), Some(_)),
|
||||
Err(eyre!("path should have 2 segments, has none"))
|
||||
);
|
||||
let repo = iter
|
||||
.next()
|
||||
.ok_or_else(|| eyre!("path should have 2 segments, has only 1"))?;
|
||||
let repo = repo.strip_suffix(".git").unwrap_or(repo);
|
||||
soft_assert::soft_assert!(
|
||||
matches!(iter.next(), None),
|
||||
Err(eyre!("path should have 2 segments, has more"))
|
||||
);
|
||||
Ok(repo)
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Default)]
|
||||
|
@ -161,15 +83,3 @@ impl LoginInfo {
|
|||
forgejo_api::Forgejo::new(&self.key, url.clone())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_remote(repo: &git2::Repository) -> eyre::Result<Url> {
|
||||
let head = repo.head()?;
|
||||
let branch_name = head.name().ok_or_else(|| eyre!("branch name not UTF-8"))?;
|
||||
let remote_name = repo.branch_upstream_remote(branch_name)?;
|
||||
let remote_name = remote_name
|
||||
.as_str()
|
||||
.ok_or_else(|| eyre!("remote name not UTF-8"))?;
|
||||
let remote = repo.find_remote(remote_name)?;
|
||||
let url = Url::parse(std::str::from_utf8(remote.url_bytes())?)?;
|
||||
Ok(url)
|
||||
}
|
||||
|
|
|
@ -39,13 +39,13 @@ async fn main() -> eyre::Result<()> {
|
|||
Command::Repo(repo_subcommand) => repo_subcommand.run(&keys).await?,
|
||||
Command::User { host } => {
|
||||
let host = host.map(|host| Url::parse(&host)).transpose()?;
|
||||
let (url, name) = match host {
|
||||
Some(url) => (keys.get_login(&url)?.username(), url),
|
||||
let url = match host {
|
||||
Some(url) => url,
|
||||
None => {
|
||||
let (host, _) = keys.get_current()?;
|
||||
(host.username(), host.url().clone())
|
||||
repo::RepoInfo::get_current()?.url().clone()
|
||||
}
|
||||
};
|
||||
let name = keys.get_login(&url)?.username();
|
||||
eprintln!("currently signed in to {name}@{url}");
|
||||
}
|
||||
Command::Auth(auth_subcommand) => auth_subcommand.run(&mut keys).await?,
|
||||
|
@ -65,3 +65,4 @@ async fn readline(msg: &str) -> eyre::Result<String> {
|
|||
})
|
||||
.await?
|
||||
}
|
||||
|
||||
|
|
64
src/repo.rs
64
src/repo.rs
|
@ -1,6 +1,62 @@
|
|||
use clap::Subcommand;
|
||||
use forgejo_api::CreateRepoOption;
|
||||
use url::Url;
|
||||
use eyre::eyre;
|
||||
|
||||
pub struct RepoInfo {
|
||||
owner: String,
|
||||
name: String,
|
||||
url: Url,
|
||||
}
|
||||
|
||||
impl RepoInfo {
|
||||
pub fn get_current() -> eyre::Result<Self> {
|
||||
let repo = git2::Repository::open(".")?;
|
||||
let url = get_remote(&repo)?;
|
||||
|
||||
let mut path = url
|
||||
.path_segments()
|
||||
.ok_or_else(|| eyre!("bad path"))?;
|
||||
let owner = path
|
||||
.next()
|
||||
.ok_or_else(|| eyre!("path does not have owner name"))?
|
||||
.to_string();
|
||||
let name = path
|
||||
.next()
|
||||
.ok_or_else(|| eyre!("path does not have repo name"))?
|
||||
.to_string();
|
||||
|
||||
let repo_info = RepoInfo {
|
||||
owner,
|
||||
name,
|
||||
url,
|
||||
};
|
||||
Ok(repo_info)
|
||||
}
|
||||
pub fn owner(&self) -> &str {
|
||||
&self.owner
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn url(&self) -> &Url {
|
||||
&self.url
|
||||
}
|
||||
}
|
||||
|
||||
fn get_remote(repo: &git2::Repository) -> eyre::Result<Url> {
|
||||
let head = repo.head()?;
|
||||
let branch_name = head.name().ok_or_else(|| eyre!("branch name not UTF-8"))?;
|
||||
let remote_name = repo.branch_upstream_remote(branch_name)?;
|
||||
let remote_name = remote_name
|
||||
.as_str()
|
||||
.ok_or_else(|| eyre!("remote name not UTF-8"))?;
|
||||
let remote = repo.find_remote(remote_name)?;
|
||||
let url = Url::parse(std::str::from_utf8(remote.url_bytes())?)?;
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Clone, Debug)]
|
||||
pub enum RepoCommand {
|
||||
|
@ -73,8 +129,8 @@ impl RepoCommand {
|
|||
}
|
||||
}
|
||||
RepoCommand::Info => {
|
||||
let (host, repo) = keys.get_current()?;
|
||||
let api = host.api()?;
|
||||
let repo = RepoInfo::get_current()?;
|
||||
let api = keys.get_api(repo.url())?;
|
||||
let repo = api.get_repo(repo.owner(), repo.name()).await?;
|
||||
match repo {
|
||||
Some(repo) => {
|
||||
|
@ -84,8 +140,8 @@ impl RepoCommand {
|
|||
}
|
||||
}
|
||||
RepoCommand::Browse => {
|
||||
let (host, repo) = keys.get_current()?;
|
||||
let mut url = host.url().clone();
|
||||
let repo = RepoInfo::get_current()?;
|
||||
let mut url = repo.url().clone();
|
||||
let new_path = format!(
|
||||
"{}/{}/{}",
|
||||
url.path().strip_suffix("/").unwrap_or(url.path()),
|
||||
|
|
Loading…
Reference in a new issue