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.rs137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/git.rs b/src/git.rs
index f9121f2..281f00c 100644
--- a/src/git.rs
+++ b/src/git.rs
@@ -33,6 +33,7 @@ pub trait RepoActions {
33 fn get_checked_out_branch_name(&self) -> Result<String>; 33 fn get_checked_out_branch_name(&self) -> Result<String>;
34 fn get_tip_of_local_branch(&self, branch_name: &str) -> Result<Sha1Hash>; 34 fn get_tip_of_local_branch(&self, branch_name: &str) -> Result<Sha1Hash>;
35 fn get_root_commit(&self, branch_name: &str) -> Result<Sha1Hash>; 35 fn get_root_commit(&self, branch_name: &str) -> Result<Sha1Hash>;
36 fn does_commit_exist(&self, commit: &str) -> Result<bool>;
36 fn get_head_commit(&self) -> Result<Sha1Hash>; 37 fn get_head_commit(&self) -> Result<Sha1Hash>;
37 fn get_commit_parent(&self, commit: &Sha1Hash) -> Result<Sha1Hash>; 38 fn get_commit_parent(&self, commit: &Sha1Hash) -> Result<Sha1Hash>;
38 fn get_commits_ahead_behind( 39 fn get_commits_ahead_behind(
@@ -41,6 +42,8 @@ pub trait RepoActions {
41 latest_commit: &Sha1Hash, 42 latest_commit: &Sha1Hash,
42 ) -> Result<(Vec<Sha1Hash>, Vec<Sha1Hash>)>; 43 ) -> Result<(Vec<Sha1Hash>, Vec<Sha1Hash>)>;
43 fn make_patch_from_commit(&self, commit: &Sha1Hash) -> Result<String>; 44 fn make_patch_from_commit(&self, commit: &Sha1Hash) -> Result<String>;
45 fn checkout(&self, ref_name: &str) -> Result<()>;
46 fn create_branch_at_commit(&self, branch_name: &str, commit: &str) -> Result<()>;
44} 47}
45 48
46impl RepoActions for Repo { 49impl RepoActions for Repo {
@@ -118,6 +121,14 @@ impl RepoActions for Repo {
118 )) 121 ))
119 } 122 }
120 123
124 fn does_commit_exist(&self, commit: &str) -> Result<bool> {
125 if let Ok(c) = self.git_repo.find_commit(Oid::from_str(commit)?) {
126 Ok(true)
127 } else {
128 Ok(false)
129 }
130 }
131
121 fn get_head_commit(&self) -> Result<Sha1Hash> { 132 fn get_head_commit(&self) -> Result<Sha1Hash> {
122 let head = self 133 let head = self
123 .git_repo 134 .git_repo
@@ -213,6 +224,31 @@ impl RepoActions for Repo {
213 }); 224 });
214 Ok((ahead, behind)) 225 Ok((ahead, behind))
215 } 226 }
227
228 fn checkout(&self, ref_name: &str) -> Result<()> {
229 let (object, reference) = self.git_repo.revparse_ext(ref_name)?;
230
231 self.git_repo.checkout_tree(&object, None)?;
232
233 match reference {
234 // gref is an actual reference like branches or tags
235 Some(gref) => self.git_repo.set_head(gref.name().unwrap()),
236 // this is a commit, not a reference
237 None => self.git_repo.set_head_detached(object.id()),
238 }?;
239 Ok(())
240 }
241
242 fn create_branch_at_commit(&self, branch_name: &str, commit: &str) -> Result<()> {
243 self.git_repo
244 .branch(
245 branch_name,
246 &self.git_repo.find_commit(Oid::from_str(commit)?)?,
247 false,
248 )
249 .context("branch could not be created")?;
250 Ok(())
251 }
216} 252}
217 253
218fn oid_to_u8_20_bytes(oid: &Oid) -> [u8; 20] { 254fn oid_to_u8_20_bytes(oid: &Oid) -> [u8; 20] {
@@ -272,6 +308,42 @@ mod tests {
272 Ok(()) 308 Ok(())
273 } 309 }
274 310
311 mod does_commit_exist {
312 use super::*;
313
314 #[test]
315 fn existing_commits_results_in_true() -> Result<()> {
316 let test_repo = GitTestRepo::default();
317 let oid = test_repo.populate()?;
318 let git_repo = Repo::from_path(&test_repo.dir)?;
319
320 assert!(git_repo.does_commit_exist(&"431b84edc0d2fa118d63faa3c2db9c73d630a5ae")?);
321 Ok(())
322 }
323
324 #[test]
325 fn correctly_formatted_hash_that_doesnt_correspond_to_an_existing_commit_results_in_false()
326 -> Result<()> {
327 let test_repo = GitTestRepo::default();
328 let oid = test_repo.populate()?;
329 let git_repo = Repo::from_path(&test_repo.dir)?;
330
331 assert!(!git_repo.does_commit_exist(&"000004edc0d2fa118d63faa3c2db9c73d630a5ae")?);
332 Ok(())
333 }
334
335 #[test]
336 fn incorrectly_formatted_hash_that_doesnt_correspond_to_an_existing_commit_results_in_error()
337 -> Result<()> {
338 let test_repo = GitTestRepo::default();
339 let oid = test_repo.populate()?;
340 let git_repo = Repo::from_path(&test_repo.dir)?;
341
342 assert!(!git_repo.does_commit_exist(&"00").is_err());
343 Ok(())
344 }
345 }
346
275 mod make_patch_from_commit { 347 mod make_patch_from_commit {
276 use super::*; 348 use super::*;
277 #[test] 349 #[test]
@@ -521,4 +593,69 @@ mod tests {
521 } 593 }
522 } 594 }
523 } 595 }
596
597 mod create_branch_at_commit {
598 use super::*;
599 #[test]
600 fn doesnt_error() -> Result<()> {
601 let test_repo = GitTestRepo::default();
602 test_repo.populate()?;
603 // create feature branch and add 2 commits
604 test_repo.create_branch("feature")?;
605 test_repo.checkout("feature")?;
606 std::fs::write(test_repo.dir.join("t3.md"), "some content")?;
607 let ahead_1_oid = test_repo.stage_and_commit("add t3.md")?;
608 std::fs::write(test_repo.dir.join("t4.md"), "some content")?;
609 test_repo.stage_and_commit("add t4.md")?;
610
611 let git_repo = Repo::from_path(&test_repo.dir)?;
612
613 let branch_name = "test-name-1";
614 git_repo.create_branch_at_commit(branch_name, &ahead_1_oid.to_string())?;
615
616 Ok(())
617 }
618
619 #[test]
620 fn branch_gets_created() -> Result<()> {
621 let test_repo = GitTestRepo::default();
622 test_repo.populate()?;
623 // create feature branch and add 2 commits
624 test_repo.create_branch("feature")?;
625 test_repo.checkout("feature")?;
626 std::fs::write(test_repo.dir.join("t3.md"), "some content")?;
627 let ahead_1_oid = test_repo.stage_and_commit("add t3.md")?;
628 std::fs::write(test_repo.dir.join("t4.md"), "some content")?;
629 test_repo.stage_and_commit("add t4.md")?;
630
631 let git_repo = Repo::from_path(&test_repo.dir)?;
632
633 let branch_name = "test-name-1";
634 git_repo.create_branch_at_commit(branch_name, &ahead_1_oid.to_string())?;
635
636 assert!(test_repo.checkout(&branch_name).is_ok());
637 Ok(())
638 }
639
640 #[test]
641 fn branch_created_with_correct_commit() -> Result<()> {
642 let test_repo = GitTestRepo::default();
643 test_repo.populate()?;
644 // create feature branch and add 2 commits
645 test_repo.create_branch("feature")?;
646 test_repo.checkout("feature")?;
647 std::fs::write(test_repo.dir.join("t3.md"), "some content")?;
648 let ahead_1_oid = test_repo.stage_and_commit("add t3.md")?;
649 std::fs::write(test_repo.dir.join("t4.md"), "some content")?;
650 test_repo.stage_and_commit("add t4.md")?;
651
652 let git_repo = Repo::from_path(&test_repo.dir)?;
653
654 let branch_name = "test-name-1";
655 git_repo.create_branch_at_commit(branch_name, &ahead_1_oid.to_string())?;
656
657 assert_eq!(test_repo.checkout(&branch_name)?, ahead_1_oid);
658 Ok(())
659 }
660 }
524} 661}