rad: preparation for the rad remote commands
This commits introduces just a couple of helper functions in order to work with the `rad remote *` commands. Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
This commit is contained in:
parent
442e8a7128
commit
0468a1a757
|
|
@ -10,12 +10,14 @@ use std::str::FromStr;
|
|||
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Context as _;
|
||||
use thiserror::Error;
|
||||
|
||||
use radicle::crypto::ssh;
|
||||
use radicle::git;
|
||||
use radicle::git::raw as git2;
|
||||
use radicle::git::{Version, VERSION_REQUIRED};
|
||||
use radicle::prelude::{Id, NodeId};
|
||||
use radicle::storage::git::transport;
|
||||
|
||||
pub use radicle::git::raw::{
|
||||
build::CheckoutBuilder, AnnotatedCommit, Commit, Direction, ErrorCode, MergeAnalysis,
|
||||
|
|
@ -60,6 +62,45 @@ impl From<String> for Rev {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum RemoteError {
|
||||
#[error("url malformed: {0}")]
|
||||
ParseUrl(#[from] transport::local::UrlError),
|
||||
#[error("remote `url` not found")]
|
||||
MissingUrl,
|
||||
#[error("remote `name` not found")]
|
||||
MissingName,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Remote<'a> {
|
||||
pub(crate) name: String,
|
||||
pub(crate) url: radicle::git::Url,
|
||||
inner: git2::Remote<'a>,
|
||||
}
|
||||
|
||||
impl Remote<'_> {
|
||||
pub fn refspecs(&self) -> git2::Refspecs {
|
||||
self.inner.refspecs()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<git2::Remote<'a>> for Remote<'a> {
|
||||
type Error = RemoteError;
|
||||
|
||||
fn try_from(value: git2::Remote<'a>) -> Result<Self, Self::Error> {
|
||||
let url = value.url().map_or(Err(RemoteError::MissingUrl), |url| {
|
||||
Ok(radicle::git::Url::from_str(url)?)
|
||||
})?;
|
||||
let name = value.name().ok_or(RemoteError::MissingName)?;
|
||||
Ok(Self {
|
||||
name: name.to_owned(),
|
||||
url,
|
||||
inner: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the git repository in the current directory.
|
||||
pub fn repository() -> Result<Repository, anyhow::Error> {
|
||||
match Repository::open(".") {
|
||||
|
|
@ -175,24 +216,27 @@ pub fn is_signing_configured(repo: &Path) -> Result<bool, anyhow::Error> {
|
|||
}
|
||||
|
||||
/// Return the list of radicle remotes for the given repository.
|
||||
pub fn remotes(repo: &git2::Repository) -> anyhow::Result<Vec<(String, NodeId)>> {
|
||||
let mut remotes = Vec::new();
|
||||
|
||||
for name in repo.remotes().iter().flatten().flatten() {
|
||||
let remote = repo.find_remote(name)?;
|
||||
for refspec in remote.refspecs() {
|
||||
if refspec.direction() != git2::Direction::Fetch {
|
||||
continue;
|
||||
}
|
||||
if let Some((peer, _)) = refspec.src().and_then(self::parse_remote) {
|
||||
remotes.push((name.to_owned(), peer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rad_remotes(repo: &git2::Repository) -> anyhow::Result<Vec<Remote>> {
|
||||
let remotes: Vec<_> = repo
|
||||
.remotes()?
|
||||
.iter()
|
||||
.filter_map(|name| {
|
||||
let remote = repo.find_remote(name?).ok()?;
|
||||
Remote::try_from(remote).ok()
|
||||
})
|
||||
.collect();
|
||||
Ok(remotes)
|
||||
}
|
||||
|
||||
/// Check if the git remote is configured for the `Repository`.
|
||||
pub fn is_remote(repo: &git2::Repository, alias: &str) -> anyhow::Result<bool> {
|
||||
match repo.find_remote(alias) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(err) if err.code() == git2::ErrorCode::NotFound => Ok(false),
|
||||
Err(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the repository's "rad" remote.
|
||||
pub fn rad_remote(repo: &Repository) -> anyhow::Result<(git2::Remote, Id)> {
|
||||
match radicle::rad::remote(repo) {
|
||||
|
|
@ -204,6 +248,15 @@ pub fn rad_remote(repo: &Repository) -> anyhow::Result<(git2::Remote, Id)> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_remote<'a>(
|
||||
repo: &'a Repository,
|
||||
name: &'a str,
|
||||
url: &'a radicle::git::Url,
|
||||
) -> anyhow::Result<Remote<'a>> {
|
||||
let remote = repo.remote(name, &url.to_string())?;
|
||||
Ok(Remote::try_from(remote)?)
|
||||
}
|
||||
|
||||
/// Setup an upstream tracking branch for the given remote and branch.
|
||||
/// Creates the tracking branch if it does not exist.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -99,6 +99,14 @@ pub fn rid(val: &OsString) -> anyhow::Result<Id> {
|
|||
Id::from_str(&val).map_err(|_| anyhow!("invalid Repository ID '{}'", val))
|
||||
}
|
||||
|
||||
pub fn pubkey(val: &OsString) -> anyhow::Result<NodeId> {
|
||||
let Ok(did) = did(val) else {
|
||||
let nid = nid(val)?;
|
||||
return Ok(nid)
|
||||
};
|
||||
Ok(did.as_key().to_owned())
|
||||
}
|
||||
|
||||
pub fn addr(val: &OsString) -> anyhow::Result<Address> {
|
||||
let val = val.to_string_lossy();
|
||||
Address::from_str(&val).map_err(|_| anyhow!("invalid address '{}'", val))
|
||||
|
|
|
|||
Loading…
Reference in New Issue