From 5ac09c580272d5116c2f57b4370e274b204f21bb Mon Sep 17 00:00:00 2001
From: DanConwayDev
Date: Mon, 18 Nov 2024 16:39:47 +0000
Subject: [PATCH] feat(blossom): blossom as remote via external bin
following conversations with
nostr:npub1elta7cneng3w8p9y4dw633qzdjr4kyvaparuyuttyrx6e8xp7xnq32cume
this minimum viable attempt at adapting git-remote-nostr so that his
approach / work on git via blossom can be intergrated.
it requires 2 binaries in PATH called:
1. git-remote-blossom-fetch which must take multiple commit ids as
`--input` args and either write an errot to `stderr` or return a
success code after downloading and adding missing state data related
to these commit ids into the local .git folder.
2. git-remote-blossom-push which must take multiple commit ids as
`--input` args and either write an errot to `stderr` or upload
downloading and uploading any missing state data to (a) blossom
server(s) in a way that is retrievable by the fetch binary.
this is just an untested starting point.
---
src/bin/git_remote_nostr/fetch.rs | 30 ++++++++++++++++++++++++++++++
src/bin/git_remote_nostr/list.rs | 24 +++++++++++++++++++++++-
src/bin/git_remote_nostr/push.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++---
src/lib/repo_state.rs | 1 +
4 files changed, 98 insertions(+), 4 deletions(-)
diff --git a/src/bin/git_remote_nostr/fetch.rs b/src/bin/git_remote_nostr/fetch.rs
index a972a2f..df2158b 100644
--- a/src/bin/git_remote_nostr/fetch.rs
+++ b/src/bin/git_remote_nostr/fetch.rs
@@ -2,6 +2,7 @@ use core::str;
use std::{
collections::HashMap,
io::Stdin,
+ process::Command,
sync::{Arc, Mutex},
time::Instant,
};
@@ -171,6 +172,10 @@ pub fn fetch_from_git_server(
return Ok(());
}
+ if git_server_url == "blossom" {
+ return fetch_from_blossom(oids, term);
+ }
+
let server_url = git_server_url.parse::
let protocols_to_attempt = get_read_protocols_to_try(git_repo, &server_url, decoded_nostr_url);
@@ -228,6 +233,31 @@ pub fn fetch_from_git_server(
}
}
+fn fetch_from_blossom(oids: &[String], term: &console::Term) -> Result<()> {
+ term.write_line("fetching over blossom...")?;
+ let args: Vec
+ .iter()
+ .flat_map(|value| vec!["--input".to_string(), value.clone()])
+ .collect();
+ let res = Command::new("git-remote-blossom-fetch").args(args).output();
+ match res {
+ Ok(output) => {
+ if output.status.success() {
+ term.write_line("fetch: succeeded over blossom")?;
+ } else {
+ let error = String::from_utf8_lossy(&output.stderr).to_string();
+ term.write_line(format!("fetch: failed over blossom: {}", &error).as_str())?;
+ bail!(error);
+ }
+ }
+ Err(error) => {
+ term.write_line(format!("fetch: failed over blossom: {error}").as_str())?;
+ bail!(error);
+ }
+ }
+ Ok(())
+}
+
#[allow(clippy::cast_precision_loss)]
#[allow(clippy::float_cmp)]
#[allow(clippy::needless_pass_by_value)]
diff --git a/src/bin/git_remote_nostr/list.rs b/src/bin/git_remote_nostr/list.rs
index 92faa6b..b556897 100644
--- a/src/bin/git_remote_nostr/list.rs
+++ b/src/bin/git_remote_nostr/list.rs
@@ -14,6 +14,7 @@ use ngit::{
git_events::event_to_cover_letter,
login::get_curent_user,
repo_ref,
+ repo_state::RepoState,
};
use nostr_sdk::hashes::sha1::Hash as Sha1Hash;
use repo_ref::RepoRef;
@@ -43,11 +44,20 @@ pub async fn run_list(
let term = console::Term::stderr();
- let remote_states = list_from_remotes(&term, git_repo, &repo_ref.git_server, decoded_nostr_url);
+ let remote_states = list_from_remotes(
+ &term,
+ git_repo,
+ &repo_ref.git_server,
+ decoded_nostr_url,
+ &nostr_state,
+ );
let mut state = if let Some(nostr_state) = nostr_state {
for (name, value) in &nostr_state.state {
for (url, remote_state) in &remote_states {
+ if url == "blossom" {
+ continue;
+ }
let remote_name = get_short_git_server_name(git_repo, url);
if let Some(remote_value) = remote_state.get(name) {
if value.ne(remote_value) {
@@ -179,10 +189,22 @@ pub fn list_from_remotes(
git_repo: &Repo,
git_servers: &Vec
decoded_nostr_url: &NostrUrlDecoded, // Add this parameter
+ nostr_state: &Option
) -> HashMap
let mut remote_states = HashMap::new();
let mut errors = HashMap::new();
for url in git_servers {
+ if url == "blossom" {
+ remote_states.insert(
+ "blossom".to_string(),
+ if let Some(nostr_state) = nostr_state {
+ nostr_state.state.clone()
+ } else {
+ HashMap::new()
+ },
+ );
+ continue;
+ }
match list_from_remote(term, git_repo, url, decoded_nostr_url) {
Err(error) => {
errors.insert(url, error);
diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs
index db86c04..2bc1cb1 100644
--- a/src/bin/git_remote_nostr/push.rs
+++ b/src/bin/git_remote_nostr/push.rs
@@ -2,6 +2,7 @@ use core::str;
use std::{
collections::{HashMap, HashSet},
io::Stdin,
+ process::Command,
sync::{Arc, Mutex},
time::Instant,
};
@@ -72,13 +73,23 @@ pub async fn run_push(
let term = console::Term::stderr();
+ let nostr_state = get_state_from_cache(git_repo.get_path()?, repo_ref).await;
+
let list_outputs = match list_outputs {
Some(outputs) => outputs,
- _ => list_from_remotes(&term, git_repo, &repo_ref.git_server, decoded_nostr_url),
+ _ => list_from_remotes(
+ &term,
+ git_repo,
+ &repo_ref.git_server,
+ decoded_nostr_url,
+ &if let Ok(nostr_state) = &nostr_state {
+ Some(nostr_state.clone())
+ } else {
+ None
+ },
+ ),
};
- let nostr_state = get_state_from_cache(git_repo.get_path()?, repo_ref).await;
-
let existing_state = {
// if no state events - create from first git server listed
if let Ok(nostr_state) = &nostr_state {
@@ -352,7 +363,12 @@ fn push_to_remote(
remote_refspecs: &[String],
term: &Term,
) -> Result<()> {
+ if git_server_url == "blossom" {
+ return push_to_blossom(remote_refspecs, term);
+ }
+
let server_url = git_server_url.parse::
+
let protocols_to_attempt = get_write_protocols_to_try(git_repo, &server_url, decoded_nostr_url);
let mut failed_protocols = vec![];
@@ -398,6 +414,31 @@ fn push_to_remote(
}
}
+fn push_to_blossom(remote_refspecs: &[String], term: &console::Term) -> Result<()> {
+ term.write_line("push: to blossom...")?;
+ let args: Vec
+ .iter()
+ .flat_map(|value| vec!["--input".to_string(), value.clone()])
+ .collect();
+ let res = Command::new("git-remote-blossom-push").args(args).output();
+ match res {
+ Ok(output) => {
+ if output.status.success() {
+ term.write_line("push: succeeded over blossom")?;
+ } else {
+ let error = String::from_utf8_lossy(&output.stderr).to_string();
+ term.write_line(format!("push: failed over blossom: {}", &error).as_str())?;
+ bail!(error);
+ }
+ }
+ Err(error) => {
+ term.write_line(format!("push: failed over blossom: {error}").as_str())?;
+ bail!(error);
+ }
+ }
+ Ok(())
+}
+
fn push_to_remote_url(
git_repo: &Repo,
git_server_url: &str,
diff --git a/src/lib/repo_state.rs b/src/lib/repo_state.rs
index c3a7606..ccd317a 100644
--- a/src/lib/repo_state.rs
+++ b/src/lib/repo_state.rs
@@ -3,6 +3,7 @@ use std::collections::HashMap;
use anyhow::{Context, Result};
use git2::Oid;
+#[derive(Clone)]
pub struct RepoState {
pub identifier: String,
pub state: HashMap
--
libgit2 1.8.1