Skip to content

Commit

Permalink
feat: handle ReflogLookup::Date
Browse files Browse the repository at this point in the history
Handles the missing Date based reflog lookup. The target date is compared against the signature time field
  • Loading branch information
dvtkrlbs committed Oct 24, 2024
1 parent db5c9cf commit dafe686
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 12 deletions.
21 changes: 21 additions & 0 deletions gix-date/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ pub mod time;

///
pub mod parse;

use crate::time::Sign;
pub use parse::function::parse;
use std::ops::Sub;

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

impl Sub for Time {
type Output = i64;

fn sub(self, rhs: Self) -> Self::Output {
self.total() - rhs.total()
}
}

impl Time {
fn total(&self) -> i64 {
if self.sign == Sign::Minus {
self.seconds - self.offset as i64
} else {
self.seconds + self.offset as i64
}
}
}

/// The amount of seconds since unix epoch.
///
/// Note that negative dates represent times before the unix epoch.
Expand Down
51 changes: 45 additions & 6 deletions gix/src/revision/spec/parse/delegate/revision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,51 @@ impl delegate::Revision for Delegate<'_> {
fn reflog(&mut self, query: ReflogLookup) -> Option<()> {
self.unset_disambiguate_call();
match query {
ReflogLookup::Date(_date) => {
// TODO: actually do this - this should be possible now despite incomplete date parsing
self.err.push(Error::Planned {
dependency: "remote handling and ref-specs are fleshed out more",
});
None
ReflogLookup::Date(date) => {
let r = match &mut self.refs[self.idx] {
Some(r) => r.clone().attach(self.repo),
val @ None => match self.repo.head().map(crate::Head::try_into_referent) {
Ok(Some(r)) => {
*val = Some(r.clone().detach());
r
}
Ok(None) => {
self.err.push(Error::UnbornHeadsHaveNoRefLog);
return None;
}
Err(err) => {
self.err.push(err.into());
return None;
}
},
};

let mut platform = r.log_iter();
match platform.rev().ok().flatten() {
Some(it) => match it
.filter_map(Result::ok)
.min_by_key(|l| (date - l.signature.time).abs())
{
Some(closest_line) => {
self.objs[self.idx]
.get_or_insert_with(HashSet::default)
.insert(closest_line.new_oid);
Some(())
}
None => {
// do we need an another error variant?
self.err.push(Error::SingleNotFound);
None
}
},
None => {
self.err.push(Error::MissingRefLog {
reference: r.name().as_bstr().into(),
action: "lookup entry",
});
None
}
}
}
ReflogLookup::Entry(no) => {
let r = match &mut self.refs[self.idx] {
Expand Down
15 changes: 9 additions & 6 deletions gix/tests/gix/revision/spec/from_bytes/reflog.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use gix::{
prelude::ObjectIdExt,
revision::{spec::parse::Error, Spec},
revision::Spec,
};

use crate::{
Expand Down Expand Up @@ -78,10 +78,13 @@ fn by_index() {
}

#[test]
fn by_date_is_planned_until_git_date_crate_is_implements_parsing() {
fn by_date() {
let repo = repo("complex_graph").unwrap();
assert!(matches!(
parse_spec_no_baseline("main@{1979-02-26 18:30:00}", &repo).unwrap_err(),
Error::Planned { .. }
));

let spec = parse_spec_no_baseline("main@{1979-02-26 18:30:00}", &repo).unwrap();

assert_eq!(
spec,
Spec::from_id(hex_to_id("9f9eac6bd1cd4b4cc6a494f044b28c985a22972b").attach(&repo))
);
}

0 comments on commit dafe686

Please sign in to comment.