Skip to content

Commit dafe686

Browse files
committed
feat: handle ReflogLookup::Date
Handles the missing Date based reflog lookup. The target date is compared against the signature time field
1 parent db5c9cf commit dafe686

File tree

3 files changed

+75
-12
lines changed

3 files changed

+75
-12
lines changed

gix-date/src/lib.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ pub mod time;
1515

1616
///
1717
pub mod parse;
18+
19+
use crate::time::Sign;
1820
pub use parse::function::parse;
21+
use std::ops::Sub;
1922

2023
/// A timestamp with timezone.
2124
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
@@ -29,6 +32,24 @@ pub struct Time {
2932
pub sign: time::Sign,
3033
}
3134

35+
impl Sub for Time {
36+
type Output = i64;
37+
38+
fn sub(self, rhs: Self) -> Self::Output {
39+
self.total() - rhs.total()
40+
}
41+
}
42+
43+
impl Time {
44+
fn total(&self) -> i64 {
45+
if self.sign == Sign::Minus {
46+
self.seconds - self.offset as i64
47+
} else {
48+
self.seconds + self.offset as i64
49+
}
50+
}
51+
}
52+
3253
/// The amount of seconds since unix epoch.
3354
///
3455
/// Note that negative dates represent times before the unix epoch.

gix/src/revision/spec/parse/delegate/revision.rs

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,51 @@ impl delegate::Revision for Delegate<'_> {
106106
fn reflog(&mut self, query: ReflogLookup) -> Option<()> {
107107
self.unset_disambiguate_call();
108108
match query {
109-
ReflogLookup::Date(_date) => {
110-
// TODO: actually do this - this should be possible now despite incomplete date parsing
111-
self.err.push(Error::Planned {
112-
dependency: "remote handling and ref-specs are fleshed out more",
113-
});
114-
None
109+
ReflogLookup::Date(date) => {
110+
let r = match &mut self.refs[self.idx] {
111+
Some(r) => r.clone().attach(self.repo),
112+
val @ None => match self.repo.head().map(crate::Head::try_into_referent) {
113+
Ok(Some(r)) => {
114+
*val = Some(r.clone().detach());
115+
r
116+
}
117+
Ok(None) => {
118+
self.err.push(Error::UnbornHeadsHaveNoRefLog);
119+
return None;
120+
}
121+
Err(err) => {
122+
self.err.push(err.into());
123+
return None;
124+
}
125+
},
126+
};
127+
128+
let mut platform = r.log_iter();
129+
match platform.rev().ok().flatten() {
130+
Some(it) => match it
131+
.filter_map(Result::ok)
132+
.min_by_key(|l| (date - l.signature.time).abs())
133+
{
134+
Some(closest_line) => {
135+
self.objs[self.idx]
136+
.get_or_insert_with(HashSet::default)
137+
.insert(closest_line.new_oid);
138+
Some(())
139+
}
140+
None => {
141+
// do we need an another error variant?
142+
self.err.push(Error::SingleNotFound);
143+
None
144+
}
145+
},
146+
None => {
147+
self.err.push(Error::MissingRefLog {
148+
reference: r.name().as_bstr().into(),
149+
action: "lookup entry",
150+
});
151+
None
152+
}
153+
}
115154
}
116155
ReflogLookup::Entry(no) => {
117156
let r = match &mut self.refs[self.idx] {

gix/tests/gix/revision/spec/from_bytes/reflog.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use gix::{
22
prelude::ObjectIdExt,
3-
revision::{spec::parse::Error, Spec},
3+
revision::Spec,
44
};
55

66
use crate::{
@@ -78,10 +78,13 @@ fn by_index() {
7878
}
7979

8080
#[test]
81-
fn by_date_is_planned_until_git_date_crate_is_implements_parsing() {
81+
fn by_date() {
8282
let repo = repo("complex_graph").unwrap();
83-
assert!(matches!(
84-
parse_spec_no_baseline("main@{1979-02-26 18:30:00}", &repo).unwrap_err(),
85-
Error::Planned { .. }
86-
));
83+
84+
let spec = parse_spec_no_baseline("main@{1979-02-26 18:30:00}", &repo).unwrap();
85+
86+
assert_eq!(
87+
spec,
88+
Spec::from_id(hex_to_id("9f9eac6bd1cd4b4cc6a494f044b28c985a22972b").attach(&repo))
89+
);
8790
}

0 commit comments

Comments
 (0)