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
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]
git-revision/Cargo.toml+2−1
@@ -18,9 +18,10 @@ serde1 = [ "serde", "git-hash/serde1", "git-object/serde1" ] · 17 unmodified lines
18[dependencies]18[dependencies]
19git-hash = { version = "^0.9.1", path = "../git-hash" }19git-hash = { version = "^0.9.1", path = "../git-hash" }
20git-object = { version = "^0.17.0", path = "../git-object" }20git-object = { version = "^0.17.0", path = "../git-object" }
21hash_hasher = "2.0.3"
21quick-error = "2.0.0"22quick-error = "2.0.0"
22serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }23serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }
23 24
24[dev-dependencies]25[dev-dependencies]
25git-testtools = { path = "../tests/tools" }26git-testtools = { path = "../tests/tools" }
26git-repository = { version = "^0.15.0", path = "../git-repository", default-features = false }27git-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
47 }47 }
48}48}
49 49
50pub type Error = ();
51
52pub(crate) mod function {50pub(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}
git-revision/tests/describe/mod.rs+3−0
@@ -1,4 +1,5 @@
1use git_object::bstr::ByteSlice;1use git_object::bstr::ByteSlice;
2use git_repository::odb::FindExt;
2use git_revision::describe;3use git_revision::describe;
3use git_testtools::hex_to_id;4use git_testtools::hex_to_id;
4use std::borrow::Cow;5use 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()

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