upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-07-19 22:28:15 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2024-07-19 22:28:15 +0100
commit118d3d86efe155ee6525aba60711e100636a6646 (patch)
tree28ec40ed687cd564c8b0dba65333b30fd22af549 /src
parent29a093993ce7d0210ac39ceb1a25acc9350492e7 (diff)
feat: intergrate `fetch` into `init`
as part of a project to use fetch and the stored cache everywhere
Diffstat (limited to 'src')
-rw-r--r--src/repo_ref.rs103
-rw-r--r--src/sub_commands/init.rs49
2 files changed, 43 insertions, 109 deletions
diff --git a/src/repo_ref.rs b/src/repo_ref.rs
index 5d754f2..a1ef11a 100644
--- a/src/repo_ref.rs
+++ b/src/repo_ref.rs
@@ -6,17 +6,12 @@ use std::{
6}; 6};
7 7
8use anyhow::{bail, Context, Result}; 8use anyhow::{bail, Context, Result};
9use nostr::{ 9use nostr::{nips::nip01::Coordinate, FromBech32, PublicKey, Tag, TagStandard, ToBech32};
10 nips::{nip01::Coordinate, nip19::Nip19},
11 FromBech32, PublicKey, Tag, TagStandard, ToBech32,
12};
13use nostr_sdk::{Kind, NostrSigner, Timestamp}; 10use nostr_sdk::{Kind, NostrSigner, Timestamp};
14use serde::{Deserialize, Serialize}; 11use serde::{Deserialize, Serialize};
15 12
16#[cfg(not(test))] 13#[cfg(not(test))]
17use crate::client::Client; 14use crate::client::Client;
18#[cfg(test)]
19use crate::client::MockConnect;
20use crate::{ 15use crate::{
21 cli_interactor::{Interactor, InteractorPrompt, PromptInputParms}, 16 cli_interactor::{Interactor, InteractorPrompt, PromptInputParms},
22 client::{get_event_from_global_cache, get_events_from_cache, sign_event, Connect}, 17 client::{get_event_from_global_cache, get_events_from_cache, sign_event, Connect},
@@ -224,6 +219,15 @@ pub async fn get_repo_coordinates(
224 #[cfg(test)] client: &crate::client::MockConnect, 219 #[cfg(test)] client: &crate::client::MockConnect,
225 #[cfg(not(test))] client: &Client, 220 #[cfg(not(test))] client: &Client,
226) -> Result<HashSet<Coordinate>> { 221) -> Result<HashSet<Coordinate>> {
222 try_and_get_repo_coordinates(git_repo, client, true).await
223}
224
225pub async fn try_and_get_repo_coordinates(
226 git_repo: &Repo,
227 #[cfg(test)] client: &crate::client::MockConnect,
228 #[cfg(not(test))] client: &Client,
229 prompt_user: bool,
230) -> Result<HashSet<Coordinate>> {
227 let mut repo_coordinates = HashSet::new(); 231 let mut repo_coordinates = HashSet::new();
228 232
229 if let Some(repo_override) = git_repo.get_git_config_item("nostr.repo", Some(false))? { 233 if let Some(repo_override) = git_repo.get_git_config_item("nostr.repo", Some(false))? {
@@ -319,6 +323,9 @@ pub async fn get_repo_coordinates(
319 } 323 }
320 324
321 if repo_coordinates.is_empty() { 325 if repo_coordinates.is_empty() {
326 if !prompt_user {
327 bail!("couldn't find repo coordinates in git config nostr.repo or in maintainers.yaml");
328 }
322 // TODO: present list of events filter by root_commit 329 // TODO: present list of events filter by root_commit
323 // TODO: fallback to search based on identifier 330 // TODO: fallback to search based on identifier
324 let c = ask_for_naddr()?; 331 let c = ask_for_naddr()?;
@@ -343,90 +350,6 @@ fn ask_for_naddr() -> Result<Coordinate> {
343 }) 350 })
344} 351}
345 352
346pub async fn fetch(
347 git_repo: &Repo,
348 root_commit: String,
349 #[cfg(test)] client: &MockConnect,
350 #[cfg(not(test))] client: &Client,
351 // TODO: more rubust way of finding repo events
352 fallback_relays: Vec<String>,
353 prompt_for_nevent_if_cant_event: bool,
354) -> Result<RepoRef> {
355 let repo_config = get_repo_config_from_yaml(git_repo);
356
357 // TODO: check events only from maintainers. get relay list of maintainters.
358 // check those relays.
359
360 let mut repo_event_filter = nostr::Filter::default()
361 .kind(nostr::Kind::Custom(REPO_REF_KIND))
362 .reference(root_commit);
363
364 let mut relays = fallback_relays;
365 if let Ok(repo_config) = repo_config {
366 repo_event_filter =
367 repo_event_filter.authors(extract_pks(repo_config.maintainers.clone())?);
368 relays = repo_config.relays.clone();
369 }
370
371 let event = loop {
372 let events: Vec<nostr::Event> = client
373 .get_events(relays.clone(), vec![repo_event_filter.clone()])
374 .await?;
375
376 // TODO: if maintainers.yaml isn't present, as the user to select from the
377 // pubkeys they want to use. could use WoT as an indicator as well as the repo
378 // and user name.
379
380 // TODO: if maintainers.yaml isn't present, save the selected repo pubkey
381 // somewhere within .git folder for future use and seek to get that next time
382 if let Some(event) = events
383 .iter()
384 .filter(|e| e.kind.as_u16() == REPO_REF_KIND)
385 .max_by_key(|e| e.created_at)
386 {
387 break event.clone();
388 }
389 if !prompt_for_nevent_if_cant_event {
390 bail!("cannot find repo event");
391 }
392 println!("cannot find repo event");
393 loop {
394 let bech32 = Interactor::default()
395 .input(PromptInputParms::default().with_prompt("repository naddr or nevent"))?;
396 if let Ok(nip19) = Nip19::from_bech32(bech32) {
397 repo_event_filter =
398 nostr::Filter::default().kind(nostr::Kind::Custom(REPO_REF_KIND));
399 match nip19 {
400 Nip19::Coordinate(c) => {
401 repo_event_filter = repo_event_filter
402 .identifier(c.identifier)
403 .author(c.public_key);
404 for r in c.relays {
405 relays.push(r);
406 }
407 }
408 Nip19::Event(n) => {
409 if let Some(author) = n.author {
410 repo_event_filter = repo_event_filter.id(n.event_id).author(author);
411 }
412 for r in n.relays {
413 relays.push(r);
414 }
415 }
416 Nip19::EventId(id) => repo_event_filter = repo_event_filter.id(id),
417 _ => (),
418 }
419 } else {
420 println!("not a valid nevent or naddr");
421 continue;
422 }
423 break;
424 }
425 };
426
427 RepoRef::try_from(event.clone()).context("cannot parse event as repo reference")
428}
429
430#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)] 353#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
431pub struct RepoConfigYaml { 354pub struct RepoConfigYaml {
432 pub identifier: Option<String>, 355 pub identifier: Option<String>,
diff --git a/src/sub_commands/init.rs b/src/sub_commands/init.rs
index e46bf74..2a97779 100644
--- a/src/sub_commands/init.rs
+++ b/src/sub_commands/init.rs
@@ -11,12 +11,12 @@ use crate::client::Client;
11use crate::client::MockConnect; 11use crate::client::MockConnect;
12use crate::{ 12use crate::{
13 cli_interactor::{Interactor, InteractorPrompt, PromptInputParms}, 13 cli_interactor::{Interactor, InteractorPrompt, PromptInputParms},
14 client::Connect, 14 client::{fetching_with_report, get_repo_ref_from_cache, Connect},
15 git::{Repo, RepoActions}, 15 git::{Repo, RepoActions},
16 login, 16 login,
17 repo_ref::{ 17 repo_ref::{
18 self, extract_pks, get_repo_config_from_yaml, save_repo_config_to_yaml, RepoRef, 18 extract_pks, get_repo_config_from_yaml, save_repo_config_to_yaml,
19 REPO_REF_KIND, 19 try_and_get_repo_coordinates, RepoRef, REPO_REF_KIND,
20 }, 20 },
21 Cli, 21 Cli,
22}; 22};
@@ -66,6 +66,21 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
66 #[cfg(test)] 66 #[cfg(test)]
67 let mut client = <MockConnect as std::default::Default>::default(); 67 let mut client = <MockConnect as std::default::Default>::default();
68 68
69 let repo_coordinates = if let Ok(repo_coordinates) =
70 try_and_get_repo_coordinates(&git_repo, &client, false).await
71 {
72 Some(repo_coordinates)
73 } else {
74 None
75 };
76
77 let repo_ref = if let Some(repo_coordinates) = repo_coordinates {
78 fetching_with_report(git_repo_path, &client, &repo_coordinates).await?;
79 Some(get_repo_ref_from_cache(git_repo_path, &repo_coordinates).await?)
80 } else {
81 None
82 };
83
69 let (signer, user_ref) = login::launch( 84 let (signer, user_ref) = login::launch(
70 &git_repo, 85 &git_repo,
71 &cli_args.bunker_uri, 86 &cli_args.bunker_uri,
@@ -77,20 +92,6 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
77 ) 92 )
78 .await?; 93 .await?;
79 94
80 let repo_ref = if let Ok(rep_ref) = repo_ref::fetch(
81 &git_repo,
82 root_commit.to_string(),
83 &client,
84 user_ref.relays.write(),
85 false,
86 )
87 .await
88 {
89 Some(rep_ref)
90 } else {
91 None
92 };
93
94 let repo_config_result = get_repo_config_from_yaml(&git_repo); 95 let repo_config_result = get_repo_config_from_yaml(&git_repo);
95 // TODO: check for other claims 96 // TODO: check for other claims
96 97
@@ -115,7 +116,8 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
115 .with_default(if let Some(repo_ref) = &repo_ref { 116 .with_default(if let Some(repo_ref) = &repo_ref {
116 repo_ref.identifier.clone() 117 repo_ref.identifier.clone()
117 } else { 118 } else {
118 name.clone() 119 let fallback = name
120 .clone()
119 .replace(' ', "-") 121 .replace(' ', "-")
120 .chars() 122 .chars()
121 .map(|c| { 123 .map(|c| {
@@ -125,7 +127,16 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
125 '-' 127 '-'
126 } 128 }
127 }) 129 })
128 .collect() 130 .collect();
131 if let Ok(config) = &repo_config_result {
132 if let Some(identifier) = &config.identifier {
133 identifier.to_string()
134 } else {
135 fallback
136 }
137 } else {
138 fallback
139 }
129 }), 140 }),
130 )?, 141 )?,
131 }; 142 };