Unified · Split
| @@ -1388,6 +1388,7 @@ dependencies = [ · 1387 unmodified lines | |||
| 1388 | "git-object", | 1388 | "git-object", |
| 1389 | "git-repository", | 1389 | "git-repository", |
| 1390 | "git-testtools", | 1390 | "git-testtools", |
| 1391 | "hash_hasher", | ||
| 1391 | "quick-error", | 1392 | "quick-error", |
| 1392 | "serde", | 1393 | "serde", |
| 1393 | ] | 1394 | ] |
| @@ -18,9 +18,10 @@ serde1 = [ "serde", "git-hash/serde1", "git-object/serde1" ] · 17 unmodified lines | |||
| 18 | [dependencies] | 18 | [dependencies] |
| 19 | git-hash = { version = "^0.9.1", path = "../git-hash" } | 19 | git-hash = { version = "^0.9.1", path = "../git-hash" } |
| 20 | git-object = { version = "^0.17.0", path = "../git-object" } | 20 | git-object = { version = "^0.17.0", path = "../git-object" } |
| 21 | hash_hasher = "2.0.3" | ||
| 21 | quick-error = "2.0.0" | 22 | quick-error = "2.0.0" |
| 22 | serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] } | 23 | serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] } |
| 23 | 24 | ||
| 24 | [dev-dependencies] | 25 | [dev-dependencies] |
| 25 | git-testtools = { path = "../tests/tools" } | 26 | git-testtools = { path = "../tests/tools" } |
| 26 | git-repository = { version = "^0.15.0", path = "../git-repository", default-features = false } | 27 | git-repository = { version = "^0.15.0", path = "../git-repository", default-features = false, features = ["unstable"] } |
| @@ -47,24 +47,29 @@ impl<'a> Display for Outcome<'a> { · 46 unmodified lines | |||
| 47 | } | 47 | } |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | pub type Error = (); | ||
| 51 | |||
| 52 | pub(crate) mod function { | 50 | pub(crate) mod function { |
| 53 | use super::{Error, Outcome}; | 51 | use super::Outcome; |
| 54 | use git_hash::{oid, ObjectId}; | 52 | use git_hash::{oid, ObjectId}; |
| 55 | use git_object::bstr::BStr; | 53 | use git_object::bstr::BStr; |
| 54 | use git_object::CommitRefIter; | ||
| 56 | use std::borrow::Cow; | 55 | use std::borrow::Cow; |
| 57 | use std::collections::HashMap; | 56 | use std::collections::{HashMap, VecDeque}; |
| 57 | use std::iter::FromIterator; | ||
| 58 | 58 | ||
| 59 | #[allow(clippy::result_unit_err)] | 59 | #[allow(clippy::result_unit_err)] |
| 60 | pub fn describe<'a>( | 60 | pub fn describe<'a, Find, E>( |
| 61 | commit: &oid, | 61 | commit: &oid, |
| 62 | find: Find, | ||
| 62 | hex_len: usize, | 63 | hex_len: usize, |
| 63 | name_set: &HashMap<ObjectId, Cow<'a, BStr>>, | 64 | name_set: &HashMap<ObjectId, Cow<'a, BStr>>, |
| 64 | ) -> Result<Option<Outcome<'a>>, Error> { | 65 | ) -> Result<Option<Outcome<'a>>, E> |
| 66 | where | ||
| 67 | Find: for<'b> FnMut(&oid, &'b mut Vec<u8>) -> Result<CommitRefIter<'b>, E>, | ||
| 68 | E: std::error::Error + Send + Sync + 'static, | ||
| 69 | { | ||
| 65 | if let Some(name) = name_set.get(commit) { | 70 | if let Some(name) = name_set.get(commit) { |
| 66 | return Ok(Some(Outcome { | 71 | return Ok(Some(Outcome { |
| 67 | name: name.to_owned(), | 72 | name: name.clone(), |
| 68 | id: commit.to_owned(), | 73 | id: commit.to_owned(), |
| 69 | hex_len, | 74 | hex_len, |
| 70 | depth: 0, | 75 | depth: 0, |
| @@ -72,6 +77,39 @@ pub(crate) mod function { · 1 unmodified line | |||
| 72 | dirty_suffix: None, | 77 | dirty_suffix: None, |
| 73 | })); | 78 | })); |
| 74 | } | 79 | } |
| 80 | let mut queue = VecDeque::from_iter(Some(commit.to_owned())); | ||
| 81 | let mut candidates = Vec::new(); | ||
| 82 | let mut seen_commits = 0; | ||
| 83 | let mut gave_up_on_commit = None; | ||
| 84 | let mut seen = hash_hasher::HashedSet::default(); | ||
| 85 | |||
| 86 | const MAX_CANDIDATES: usize = std::mem::size_of::<usize>() * 8; | ||
| 87 | while let Some(commit) = queue.pop_front() { | ||
| 88 | seen_commits += 1; | ||
| 89 | assert!(seen.insert(commit), "BUG: shouldn't ever see dupes here"); | ||
| 90 | if let Some(name) = name_set.get(&commit) { | ||
| 91 | if candidates.len() < MAX_CANDIDATES { | ||
| 92 | candidates.push(Candidate { | ||
| 93 | name: name.clone(), | ||
| 94 | depth: seen_commits - 1, | ||
| 95 | identity_bit: 1 << candidates.len(), | ||
| 96 | order: candidates.len(), | ||
| 97 | }); | ||
| 98 | } else { | ||
| 99 | gave_up_on_commit = Some(commit); | ||
| 100 | break; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 75 | todo!("actually search for it") | 104 | todo!("actually search for it") |
| 76 | } | 105 | } |
| 106 | |||
| 107 | struct Candidate<'a> { | ||
| 108 | name: Cow<'a, BStr>, | ||
| 109 | depth: usize, | ||
| 110 | /// A single bit identifying this candidate uniquely in a bitset | ||
| 111 | identity_bit: usize, | ||
| 112 | /// The order at which we found the candidate, first one has order = 0 | ||
| 113 | order: usize, | ||
| 114 | } | ||
| 77 | } | 115 | } |
| @@ -1,4 +1,5 @@ | |||
| 1 | use git_object::bstr::ByteSlice; | 1 | use git_object::bstr::ByteSlice; |
| 2 | use git_repository::odb::FindExt; | ||
| 2 | use git_revision::describe; | 3 | use git_revision::describe; |
| 3 | use git_testtools::hex_to_id; | 4 | use git_testtools::hex_to_id; |
| 4 | use std::borrow::Cow; | 5 | use std::borrow::Cow; |
| @@ -49,6 +50,7 @@ fn typical_usecases() { · 44 unmodified lines | |||
| 49 | let hex_len = 7; | 50 | let hex_len = 7; |
| 50 | let res = git_revision::describe( | 51 | let res = git_revision::describe( |
| 51 | &commit.id, | 52 | &commit.id, |
| 53 | |_, _| Err(std::io::Error::new(std::io::ErrorKind::Other, "shouldn't be called")), | ||
| 52 | hex_len, | 54 | hex_len, |
| 53 | &vec![(commit.id, name.clone())].into_iter().collect(), | 55 | &vec![(commit.id, name.clone())].into_iter().collect(), |
| 54 | ) | 56 | ) |
| @@ -70,6 +72,7 @@ fn typical_usecases() { · 15 unmodified lines | |||
| 70 | let name = Cow::Borrowed(b"at-c5".as_bstr()); | 72 | let name = Cow::Borrowed(b"at-c5".as_bstr()); |
| 71 | let res = git_revision::describe( | 73 | let res = git_revision::describe( |
| 72 | &commit.id, | 74 | &commit.id, |
| 75 | |id, buf| repo.objects.find_commit_iter(id, buf), | ||
| 73 | hex_len, | 76 | hex_len, |
| 74 | &vec![(hex_to_id("efd9a841189668f1bab5b8ebade9cd0a1b139a37"), name.clone())] | 77 | &vec![(hex_to_id("efd9a841189668f1bab5b8ebade9cd0a1b139a37"), name.clone())] |
| 75 | .into_iter() | 78 | .into_iter() |