radicle-heartwood-lfs/radicle-cli/src/project.rs

85 lines
2.8 KiB
Rust

use radicle::prelude::*;
use crate::git;
use radicle::git::RefStr;
use radicle::node::tracking::Scope;
use radicle::node::{Handle, NodeId};
use radicle::Node;
/// Setup a project remote and tracking branch.
pub struct SetupRemote<'a> {
/// The project id.
pub rid: Id,
/// Whether or not to setup a remote tracking branch.
pub tracking: Option<BranchName>,
/// Whether or not to fetch the remote immediately.
pub fetch: bool,
/// The repository in which to setup the remote.
pub repo: &'a git::Repository,
}
impl<'a> SetupRemote<'a> {
/// Run the setup for the given peer.
pub fn run(
&self,
name: impl AsRef<RefStr>,
node: NodeId,
) -> anyhow::Result<(git::Remote, Option<BranchName>)> {
let remote_url = radicle::git::Url::from(self.rid).with_namespace(node);
let remote_name = name.as_ref();
if git::is_remote(self.repo, remote_name)? {
anyhow::bail!("remote `{remote_name}` already exists");
}
let remote =
radicle::git::configure_remote(self.repo, remote_name, &remote_url, &remote_url)?;
let mut remote = git::Remote::try_from(remote)?;
// Fetch the refs into the working copy.
if self.fetch {
remote.fetch::<&str>(&[], None, None)?;
}
// Setup remote-tracking branch.
if let Some(branch) = &self.tracking {
let tracking_branch = remote_name.join(branch);
let local_branch = radicle::git::refs::workdir::branch(tracking_branch.as_refstr());
radicle::git::set_upstream(self.repo, remote_name, &tracking_branch, local_branch)?;
return Ok((remote, Some(tracking_branch)));
}
Ok((remote, None))
}
}
/// Track a repository by first trying to track through the node, and if the node isn't running,
/// by updating the tracking database directly.
pub fn track(
rid: Id,
scope: Scope,
node: &mut Node,
profile: &Profile,
) -> Result<bool, anyhow::Error> {
match node.seed(rid, scope) {
Ok(updated) => Ok(updated),
Err(e) if e.is_connection_err() => {
let mut config = profile.tracking_mut()?;
config.track_repo(&rid, scope).map_err(|e| e.into())
}
Err(e) => Err(e.into()),
}
}
/// Untrack a repository by first trying to untrack through the node, and if the node isn't running,
/// by updating the tracking database directly.
pub fn untrack(rid: Id, node: &mut Node, profile: &Profile) -> Result<bool, anyhow::Error> {
match node.unseed(rid) {
Ok(updated) => Ok(updated),
Err(e) if e.is_connection_err() => {
let mut config = profile.tracking_mut()?;
config.untrack_repo(&rid).map_err(|e| e.into())
}
Err(e) => Err(e.into()),
}
}