Unified · Split
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | use git_hash::ObjectId; | 3 | use git_hash::ObjectId; |
| 4 | use git_ref::FullNameRef; | 4 | use git_ref::FullNameRef; |
| 5 | 5 | ||
| 6 | use crate::easy::Head; | 6 | use crate::{easy, easy::Head, ext::ReferenceExt}; |
| 7 | 7 | ||
| 8 | pub enum Kind { | 8 | pub enum Kind { |
| 9 | /// The existing reference the symbolic HEAD points to. | 9 | /// The existing reference the symbolic HEAD points to. |
| @@ -35,6 +35,18 @@ impl<'repo, A> Head<'repo, A> { · 25 unmodified lines | |||
| 35 | } | 35 | } |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | impl<'repo, A> Head<'repo, A> | ||
| 39 | where | ||
| 40 | A: easy::Access + Sized, | ||
| 41 | { | ||
| 42 | pub fn into_reference(self) -> easy::Reference<'repo, A> { | ||
| 43 | match self.kind { | ||
| 44 | Kind::Symbolic(r) => r.attach(self.access), | ||
| 45 | _ => panic!("BUG: Expected head to be a born symbolic reference"), | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 38 | pub mod peel { | 50 | pub mod peel { |
| 39 | use git_hash::ObjectId; | 51 | use git_hash::ObjectId; |
| 40 | 52 | ||
| @@ -0,0 +1,44 @@ | |||
| 1 | use std::{cell::RefMut, ops::DerefMut}; | ||
| 2 | |||
| 3 | use git_ref::file::ReferenceExt; | ||
| 4 | |||
| 5 | use crate::{easy, easy::Reference}; | ||
| 6 | |||
| 7 | pub struct Buffer<'a, 'repo, A> { | ||
| 8 | reference: &'a Reference<'repo, A>, | ||
| 9 | buf: RefMut<'repo, Vec<u8>>, | ||
| 10 | } | ||
| 11 | |||
| 12 | #[derive(Debug, thiserror::Error)] | ||
| 13 | pub enum Error { | ||
| 14 | #[error(transparent)] | ||
| 15 | Io(#[from] std::io::Error), | ||
| 16 | #[error(transparent)] | ||
| 17 | BorrowRepo(#[from] easy::borrow::repo::Error), | ||
| 18 | } | ||
| 19 | |||
| 20 | impl<'a, 'repo, A> Buffer<'a, 'repo, A> | ||
| 21 | where | ||
| 22 | A: easy::Access + Sized, | ||
| 23 | { | ||
| 24 | pub fn reverse_iter(&mut self) -> Result<Option<git_ref::file::log::iter::Reverse<'_, std::fs::File>>, Error> { | ||
| 25 | let buf = self.buf.deref_mut(); | ||
| 26 | buf.resize(512, 0); | ||
| 27 | Ok(self | ||
| 28 | .reference | ||
| 29 | .inner | ||
| 30 | .log_iter_rev(&self.reference.access.repo()?.refs, buf)?) | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | impl<'repo, A> Reference<'repo, A> | ||
| 35 | where | ||
| 36 | A: easy::Access + Sized, | ||
| 37 | { | ||
| 38 | pub fn log(&self) -> Result<Buffer<'_, 'repo, A>, easy::borrow::state::Error> { | ||
| 39 | Ok(Buffer { | ||
| 40 | reference: self, | ||
| 41 | buf: self.access.state().try_borrow_mut_buf()?, | ||
| 42 | }) | ||
| 43 | } | ||
| 44 | } | ||
| @@ -83,50 +83,7 @@ where · 82 unmodified lines | |||
| 83 | } | 83 | } |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | pub mod log { | 86 | pub mod log; |
| 87 | use crate::easy; | ||
| 88 | use crate::easy::Reference; | ||
| 89 | use git_ref::file::ReferenceExt; | ||
| 90 | use std::cell::RefMut; | ||
| 91 | use std::ops::DerefMut; | ||
| 92 | |||
| 93 | pub struct Buffer<'a, 'repo, A> { | ||
| 94 | reference: &'a Reference<'repo, A>, | ||
| 95 | buf: RefMut<'repo, Vec<u8>>, | ||
| 96 | } | ||
| 97 | |||
| 98 | #[derive(Debug, thiserror::Error)] | ||
| 99 | pub enum Error { | ||
| 100 | #[error(transparent)] | ||
| 101 | Io(#[from] std::io::Error), | ||
| 102 | #[error(transparent)] | ||
| 103 | BorrowRepo(#[from] easy::borrow::repo::Error), | ||
| 104 | } | ||
| 105 | |||
| 106 | impl<'a, 'repo, A> Buffer<'a, 'repo, A> | ||
| 107 | where | ||
| 108 | A: easy::Access + Sized, | ||
| 109 | { | ||
| 110 | pub fn reverse_iter(&mut self) -> Result<Option<git_ref::file::log::iter::Reverse<'_, std::fs::File>>, Error> { | ||
| 111 | Ok(self | ||
| 112 | .reference | ||
| 113 | .inner | ||
| 114 | .log_iter_rev(&self.reference.access.repo()?.refs, self.buf.deref_mut())?) | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | impl<'repo, A> Reference<'repo, A> | ||
| 119 | where | ||
| 120 | A: easy::Access + Sized, | ||
| 121 | { | ||
| 122 | pub fn log(&self) -> Result<Buffer<'_, 'repo, A>, easy::borrow::state::Error> { | ||
| 123 | Ok(Buffer { | ||
| 124 | reference: self, | ||
| 125 | buf: self.access.state().try_borrow_mut_buf()?, | ||
| 126 | }) | ||
| 127 | } | ||
| 128 | } | ||
| 129 | } | ||
| 130 | 87 | ||
| 131 | pub mod find { | 88 | pub mod find { |
| 132 | use crate::easy; | 89 | use crate::easy; |
| @@ -21,28 +21,36 @@ mod commit { · 20 unmodified lines | |||
| 21 | use git_testtools::hex_to_id; | 21 | use git_testtools::hex_to_id; |
| 22 | 22 | ||
| 23 | #[test] | 23 | #[test] |
| 24 | fn single_line_initial_commit_empty_tree_ref_nonexisting() { | 24 | fn single_line_initial_commit_empty_tree_ref_nonexisting() -> crate::Result { |
| 25 | let tmp = tempfile::tempdir().unwrap(); | 25 | let tmp = tempfile::tempdir()?; |
| 26 | let repo = git::init_bare(&tmp).unwrap().into_easy(); | 26 | let repo = git::init(&tmp)?.into_easy(); |
| 27 | let empty_tree_id = repo.write_object(&git::objs::Tree::empty().into()).unwrap(); | 27 | let empty_tree_id = repo.write_object(&git::objs::Tree::empty().into())?; |
| 28 | let author = git::actor::Signature::empty(); | 28 | let author = git::actor::Signature::empty(); |
| 29 | let commit_id = repo | 29 | let commit_id = repo.commit( |
| 30 | .commit( | 30 | "HEAD", |
| 31 | "HEAD", | 31 | "initial", |
| 32 | "initial", | 32 | author.clone(), |
| 33 | author.clone(), | 33 | author, |
| 34 | author, | 34 | empty_tree_id, |
| 35 | empty_tree_id, | 35 | git::commit::NO_PARENT_IDS, |
| 36 | git::commit::NO_PARENT_IDS, | 36 | )?; |
| 37 | ) | ||
| 38 | .unwrap(); | ||
| 39 | assert_eq!( | 37 | assert_eq!( |
| 40 | commit_id, | 38 | commit_id, |
| 41 | hex_to_id("302ea5640358f98ba23cda66c1e664a6f274643f"), | 39 | hex_to_id("302ea5640358f98ba23cda66c1e664a6f274643f"), |
| 42 | "the commit id is stable" | 40 | "the commit id is stable" |
| 43 | ); | 41 | ); |
| 44 | 42 | ||
| 45 | // TODO: check reflog | 43 | let head = repo.head()?.into_reference(); |
| 44 | assert_eq!( | ||
| 45 | head.log()? | ||
| 46 | .reverse_iter()? | ||
| 47 | .expect("log present") | ||
| 48 | .next() | ||
| 49 | .expect("one line")?? | ||
| 50 | .message, | ||
| 51 | "commit (initial): initial" | ||
| 52 | ); | ||
| 53 | Ok(()) | ||
| 46 | } | 54 | } |
| 47 | 55 | ||
| 48 | #[test] | 56 | #[test] |
| @@ -96,19 +104,15 @@ mod commit { · 47 unmodified lines | |||
| 96 | let current_commit = branch.peel_to_id_in_place().unwrap(); | 104 | let current_commit = branch.peel_to_id_in_place().unwrap(); |
| 97 | assert_eq!(current_commit, second_commit_id, "the commit was set"); | 105 | assert_eq!(current_commit, second_commit_id, "the commit was set"); |
| 98 | 106 | ||
| 107 | let mut log = branch.log().unwrap(); | ||
| 108 | let mut log_iter = log.reverse_iter().unwrap().expect("log present"); | ||
| 99 | assert_eq!( | 109 | assert_eq!( |
| 100 | branch | 110 | log_iter.next().expect("one line").unwrap().unwrap().message, |
| 101 | .log() | ||
| 102 | .unwrap() | ||
| 103 | .reverse_iter() | ||
| 104 | .unwrap() | ||
| 105 | .expect("log present") | ||
| 106 | .next() | ||
| 107 | .expect("one line") | ||
| 108 | .unwrap() | ||
| 109 | .unwrap() | ||
| 110 | .message, | ||
| 111 | "commit: committing into a new branch creates it" | 111 | "commit: committing into a new branch creates it" |
| 112 | ); | 112 | ); |
| 113 | assert!( | ||
| 114 | log_iter.next().is_none(), | ||
| 115 | "there is only one log line in the new branch" | ||
| 116 | ); | ||
| 113 | } | 117 | } |
| 114 | } | 118 | } |