History

a step towards traversing the graph (#301)

Sebastian Thiel committed 4 years ago

Commit 48cba411 parent e22e2dd4 files · +51 −8Browse files

Unified · Split

4 files
  1. Cargo.lock +1 −0
  2. git-revision/Cargo.toml +2 −1
  3. git-revision/src/describe.rs +45 −7
  4. git-revision/tests/describe/mod.rs +3 −0
Cargo.lock+1−0
@@ -1388,6 +1388,7 @@ dependencies = [ · 1387 unmodified lines
13881388 "git-object",
13891389 "git-repository",
13901390 "git-testtools",
1391+ "hash_hasher",
13911392 "quick-error",
13921393 "serde",
13931394 ]
git-revision/Cargo.toml+2−1
@@ -18,9 +18,10 @@ serde1 = [ "serde", "git-hash/serde1", "git-object/serde1" ] · 17 unmodified lines
1818 [dependencies]
1919 git-hash = { version = "^0.9.1", path = "../git-hash" }
2020 git-object = { version = "^0.17.0", path = "../git-object" }
21+hash_hasher = "2.0.3"
2122 quick-error = "2.0.0"
2223 serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }
2324
2425 [dev-dependencies]
2526 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"] }
git-revision/src/describe.rs+45−7
@@ -47,24 +47,29 @@ impl<'a> Display for Outcome<'a> { · 46 unmodified lines
4747 }
4848 }
4949
50−pub type Error = ();
51−
5250 pub(crate) mod function {
53− use super::{Error, Outcome};
51+ use super::Outcome;
5452 use git_hash::{oid, ObjectId};
5553 use git_object::bstr::BStr;
54+ use git_object::CommitRefIter;
5655 use std::borrow::Cow;
57− use std::collections::HashMap;
56+ use std::collections::{HashMap, VecDeque};
57+ use std::iter::FromIterator;
5858
5959 #[allow(clippy::result_unit_err)]
60− pub fn describe<'a>(
60+ pub fn describe<'a, Find, E>(
6161 commit: &oid,
62+ find: Find,
6263 hex_len: usize,
6364 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+ {
6570 if let Some(name) = name_set.get(commit) {
6671 return Ok(Some(Outcome {
67− name: name.to_owned(),
72+ name: name.clone(),
6873 id: commit.to_owned(),
6974 hex_len,
7075 depth: 0,
@@ -72,6 +77,39 @@ pub(crate) mod function { · 1 unmodified line
7277 dirty_suffix: None,
7378 }));
7479 }
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+ }
75104 todo!("actually search for it")
76105 }
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+ }
77115 }
git-revision/tests/describe/mod.rs+3−0
@@ -1,4 +1,5 @@
11 use git_object::bstr::ByteSlice;
2+use git_repository::odb::FindExt;
23 use git_revision::describe;
34 use git_testtools::hex_to_id;
45 use std::borrow::Cow;
@@ -49,6 +50,7 @@ fn typical_usecases() { · 44 unmodified lines
4950 let hex_len = 7;
5051 let res = git_revision::describe(
5152 &commit.id,
53+ |_, _| Err(std::io::Error::new(std::io::ErrorKind::Other, "shouldn't be called")),
5254 hex_len,
5355 &vec![(commit.id, name.clone())].into_iter().collect(),
5456 )
@@ -70,6 +72,7 @@ fn typical_usecases() { · 15 unmodified lines
7072 let name = Cow::Borrowed(b"at-c5".as_bstr());
7173 let res = git_revision::describe(
7274 &commit.id,
75+ |id, buf| repo.objects.find_commit_iter(id, buf),
7376 hex_len,
7477 &vec![(hex_to_id("efd9a841189668f1bab5b8ebade9cd0a1b139a37"), name.clone())]
7578 .into_iter()

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t