Add `rad-push`

Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
Alexis Sellier 2022-09-23 20:08:58 +02:00
parent a3bf5ab7c3
commit 51e18c27fc
No known key found for this signature in database
6 changed files with 73 additions and 9 deletions

View File

@ -23,3 +23,7 @@ path = "src/rad-auth.rs"
[[bin]] [[bin]]
name = "rad-self" name = "rad-self"
path = "src/rad-self.rs" path = "src/rad-self.rs"
[[bin]]
name = "rad-push"
path = "src/rad-push.rs"

View File

@ -0,0 +1,19 @@
use std::path::Path;
use radicle::storage::WriteStorage;
fn main() -> anyhow::Result<()> {
let cwd = Path::new(".").canonicalize()?;
let repo = radicle::git::raw::Repository::open(&cwd)?;
let profile = radicle::Profile::load()?;
let (_, id) = radicle::rad::remote(&repo)?;
let output = radicle::git::run(&cwd, &["push", "rad"])?;
println!("{}", output);
let project = profile.storage.repository(&id)?;
let sigrefs = profile.storage.sign_refs(&project, &profile.signer)?;
println!("ok: {}", sigrefs.signature);
Ok(())
}

View File

@ -1,4 +1,6 @@
use std::io;
use std::path::Path; use std::path::Path;
use std::process::Command;
use std::str::FromStr; use std::str::FromStr;
use git_ref_format as format; use git_ref_format as format;
@ -238,3 +240,25 @@ pub fn set_upstream(
Ok(()) Ok(())
} }
/// Execute a git command by spawning a child process.
pub fn run<P: AsRef<Path>, S: AsRef<std::ffi::OsStr>>(
repo: &P,
args: impl IntoIterator<Item = S>,
) -> Result<String, io::Error> {
let output = Command::new("git").current_dir(repo).args(args).output()?;
if output.status.success() {
let out = if output.stdout.is_empty() {
&output.stderr
} else {
&output.stdout
};
return Ok(String::from_utf8_lossy(out).into());
}
Err(io::Error::new(
io::ErrorKind::Other,
String::from_utf8_lossy(&output.stderr),
))
}

View File

@ -1,6 +1,7 @@
#![allow(clippy::let_unit_value)] #![allow(clippy::let_unit_value)]
use std::io; use std::io;
use std::path::Path; use std::path::Path;
use std::str::FromStr;
use thiserror::Error; use thiserror::Error;
@ -57,7 +58,7 @@ pub fn init<G: Signer, S: storage::WriteStorage>(
) )
.verified()?; .verified()?;
let (id, _, project) = doc.create(pk, "Initialize Radicle", storage)?; let (id, _, project) = doc.create(pk, "Initialize Radicle\n", storage)?;
let url = storage.url(&id); let url = storage.url(&id);
git::set_upstream( git::set_upstream(
@ -299,6 +300,18 @@ pub fn checkout<P: AsRef<Path>, S: storage::ReadStorage>(
Ok(repo) Ok(repo)
} }
/// Get the radicle ("rad") remote of a repository, and return the associated project id.
pub fn remote(repo: &git2::Repository) -> Result<(git2::Remote<'_>, Id), git2::Error> {
let remote = repo.find_remote(REMOTE_NAME)?;
let url = remote.url_bytes();
let url = git::Url::from_bytes(url).unwrap();
let path = url.path.to_string();
let id = path.split('/').last().unwrap();
let id = Id::from_str(id).unwrap();
Ok((remote, id))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::HashMap; use std::collections::HashMap;

View File

@ -91,13 +91,7 @@ impl WriteStorage for Storage {
repository: &Repository, repository: &Repository,
signer: G, signer: G,
) -> Result<SignedRefs<Verified>, Error> { ) -> Result<SignedRefs<Verified>, Error> {
let remote = signer.public_key(); repository.sign_refs(signer)
let refs = repository.references(remote)?;
let signed = refs.signed(&signer)?;
signed.save(remote, repository)?;
Ok(signed)
} }
fn fetch(&self, proj_id: &Id, remote: &Url) -> Result<Vec<RefUpdate>, FetchError> { fn fetch(&self, proj_id: &Id, remote: &Url) -> Result<Vec<RefUpdate>, FetchError> {
@ -370,6 +364,16 @@ impl Repository {
); );
Ok(remotes) Ok(remotes)
} }
pub fn sign_refs<G: Signer>(&self, signer: G) -> Result<SignedRefs<Verified>, Error> {
let remote = signer.public_key();
let refs = self.references(remote)?;
let signed = refs.signed(&signer)?;
signed.save(remote, self)?;
Ok(signed)
}
} }
impl ReadRepository for Repository { impl ReadRepository for Repository {

View File

@ -288,7 +288,7 @@ impl SignedRefs<Verified> {
Some(&sigref), Some(&sigref),
&author, &author,
&author, &author,
&format!("Update {} for {}", sigref, remote), &format!("Update signature for {}\n", remote),
&tree, &tree,
&parent.iter().collect::<Vec<&git2::Commit>>(), &parent.iter().collect::<Vec<&git2::Commit>>(),
); );