upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/git_remote_helper.rs35
-rw-r--r--test_utils/src/git.rs6
-rw-r--r--tests/git_remote_helper.rs81
3 files changed, 114 insertions, 8 deletions
diff --git a/src/git_remote_helper.rs b/src/git_remote_helper.rs
index d0c0005..7b471b1 100644
--- a/src/git_remote_helper.rs
+++ b/src/git_remote_helper.rs
@@ -183,15 +183,36 @@ async fn list(git_repo: &Repo, repo_ref: &RepoRef, for_push: bool) -> Result<()>
183} 183}
184 184
185fn fetch(git_repo: &Repository, repo_ref: &RepoRef, stdin: &Stdin, oid: &str) -> Result<()> { 185fn fetch(git_repo: &Repository, repo_ref: &RepoRef, stdin: &Stdin, oid: &str) -> Result<()> {
186 let git_server_remote_url = repo_ref 186 let oids = get_oids_from_fetch_batch(stdin, oid)?;
187 .git_server 187
188 .first() 188 let mut errors = HashMap::new();
189 .context("no git server listed in nostr repository announcement")?; 189 for git_server_url in &repo_ref.git_server {
190 let mut git_server_remote = git_repo.remote_anonymous(git_server_remote_url)?; 190 if let Err(e) = fetch_from_git_server(git_repo, &oids, git_server_url) {
191 errors.insert(git_server_url.to_string(), e);
192 } else {
193 println!();
194 return Ok(());
195 }
196 }
197 bail!(
198 "failed to fetch objects in nostr state event from:\r\n{}",
199 errors
200 .iter()
201 .map(|(url, error)| format!("{url}: {error}"))
202 .collect::<Vec<String>>()
203 .join("\r\n")
204 );
205}
206
207fn fetch_from_git_server(
208 git_repo: &Repository,
209 oids: &[String],
210 git_server_url: &str,
211) -> Result<()> {
212 let mut git_server_remote = git_repo.remote_anonymous(git_server_url)?;
191 git_server_remote.connect(git2::Direction::Fetch)?; 213 git_server_remote.connect(git2::Direction::Fetch)?;
192 git_server_remote.download(&get_oids_from_fetch_batch(stdin, oid)?, None)?; 214 git_server_remote.download(oids, None)?;
193 git_server_remote.disconnect()?; 215 git_server_remote.disconnect()?;
194 println!();
195 Ok(()) 216 Ok(())
196} 217}
197 218
diff --git a/test_utils/src/git.rs b/test_utils/src/git.rs
index e522ffd..058eb31 100644
--- a/test_utils/src/git.rs
+++ b/test_utils/src/git.rs
@@ -154,6 +154,12 @@ impl GitTestRepo {
154 self.stage_and_commit("add t2.md") 154 self.stage_and_commit("add t2.md")
155 } 155 }
156 156
157 pub fn populate_minus_1(&self) -> Result<Oid> {
158 self.initial_commit()?;
159 fs::write(self.dir.join("t1.md"), "some content")?;
160 self.stage_and_commit("add t1.md")
161 }
162
157 pub fn populate_with_test_branch(&self) -> Result<Oid> { 163 pub fn populate_with_test_branch(&self) -> Result<Oid> {
158 self.populate()?; 164 self.populate()?;
159 self.create_branch("add-example-feature")?; 165 self.create_branch("add-example-feature")?;
diff --git a/tests/git_remote_helper.rs b/tests/git_remote_helper.rs
index 69f290a..fda393f 100644
--- a/tests/git_remote_helper.rs
+++ b/tests/git_remote_helper.rs
@@ -39,6 +39,19 @@ fn prep_git_repo() -> Result<GitTestRepo> {
39 Ok(test_repo) 39 Ok(test_repo)
40} 40}
41 41
42fn prep_git_repo_minus_1_commit() -> Result<GitTestRepo> {
43 let test_repo = GitTestRepo::without_repo_in_git_config();
44 let mut config = test_repo
45 .git_repo
46 .config()
47 .context("cannot open git config")?;
48 config.set_str("nostr.nsec", TEST_KEY_1_NSEC)?;
49 config.set_str("nostr.npub", TEST_KEY_1_NPUB)?;
50 test_repo.add_remote(NOSTR_REMOTE_NAME, &get_nostr_remote_url()?)?;
51 test_repo.populate_minus_1()?;
52 Ok(test_repo)
53}
54
42fn cli_tester(git_repo: &GitTestRepo) -> CliTester { 55fn cli_tester(git_repo: &GitTestRepo) -> CliTester {
43 CliTester::new_remote_helper_from_dir(&git_repo.dir, &get_nostr_remote_url().unwrap()) 56 CliTester::new_remote_helper_from_dir(&git_repo.dir, &get_nostr_remote_url().unwrap())
44} 57}
@@ -493,9 +506,75 @@ mod fetch {
493 506
494 #[tokio::test] 507 #[tokio::test]
495 #[serial] 508 #[serial]
496 async fn fetch_downloads_speficied_branch_ref_commits_from_git_server() -> Result<()> { 509 async fn fetch_downloads_speficied_commits_from_git_server() -> Result<()> {
497 async_run_test().await 510 async_run_test().await
498 } 511 }
512
513 mod when_first_git_server_fails_ {
514 use super::*;
515 async fn async_run_test() -> Result<()> {
516 let (state_event, source_git_repo) = generate_repo_with_state_event().await?;
517
518 let main_commit_id = source_git_repo.get_tip_of_local_branch("main")?;
519
520 let git_repo = prep_git_repo_minus_1_commit()?;
521
522 let events = vec![
523 generate_test_key_1_metadata_event("fred"),
524 generate_test_key_1_relay_list_event(),
525 generate_repo_ref_event_with_git_server(vec![
526 "./path-doesnt-exist".to_string(),
527 source_git_repo.dir.to_str().unwrap().to_string(),
528 ]),
529 state_event,
530 ];
531 // fallback (51,52) user write (53, 55) repo (55, 56) blaster (57)
532 let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = (
533 Relay::new(8051, None, None),
534 Relay::new(8052, None, None),
535 Relay::new(8053, None, None),
536 Relay::new(8055, None, None),
537 Relay::new(8056, None, None),
538 Relay::new(8057, None, None),
539 );
540 r51.events = events.clone();
541 r55.events = events;
542
543 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
544 assert!(git_repo.git_repo.find_commit(main_commit_id).is_err());
545
546 let mut p = cli_tester_after_fetch(&git_repo)?;
547 p.send_line(format!("fetch {main_commit_id} main").as_str())?;
548 p.send_line("")?;
549 p.expect("\r\n")?;
550
551 assert!(git_repo.git_repo.find_commit(main_commit_id).is_ok());
552
553 p.exit()?;
554 for p in [51, 52, 53, 55, 56, 57] {
555 relay::shutdown_relay(8000 + p)?;
556 }
557 Ok(())
558 });
559 // launch relays
560 let _ = join!(
561 r51.listen_until_close(),
562 r52.listen_until_close(),
563 r53.listen_until_close(),
564 r55.listen_until_close(),
565 r56.listen_until_close(),
566 r57.listen_until_close(),
567 );
568 cli_tester_handle.join().unwrap()?;
569 Ok(())
570 }
571
572 #[tokio::test]
573 #[serial]
574 async fn fetch_downloads_speficied_commits_from_second_git_server() -> Result<()> {
575 async_run_test().await
576 }
577 }
499} 578}
500 579
501mod push { 580mod push {