Skip to content

Commit 1bb5f7d

Browse files
committed
refactor reflog support
- deduplicate implementation - fix implementation to work just like Git does (according to their source code) - add tests
1 parent 2a9274c commit 1bb5f7d

File tree

4 files changed

+683
-84
lines changed

4 files changed

+683
-84
lines changed

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

+67-84
Original file line numberDiff line numberDiff line change
@@ -105,98 +105,81 @@ impl delegate::Revision for Delegate<'_> {
105105

106106
fn reflog(&mut self, query: ReflogLookup) -> Option<()> {
107107
self.unset_disambiguate_call();
108-
match query {
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-
};
108+
let r = match &mut self.refs[self.idx] {
109+
Some(r) => r.clone().attach(self.repo),
110+
val @ None => match self.repo.head().map(crate::Head::try_into_referent) {
111+
Ok(Some(r)) => {
112+
*val = Some(r.clone().detach());
113+
r
114+
}
115+
Ok(None) => {
116+
self.err.push(Error::UnbornHeadsHaveNoRefLog);
117+
return None;
118+
}
119+
Err(err) => {
120+
self.err.push(err.into());
121+
return None;
122+
}
123+
},
124+
};
127125

128-
let mut platform = r.log_iter();
129-
match platform.rev().ok().flatten() {
130-
Some(it) => match it
126+
let mut platform = r.log_iter();
127+
match platform.rev().ok().flatten() {
128+
Some(mut it) => match query {
129+
ReflogLookup::Date(date) => {
130+
let mut last = None;
131+
let id_to_insert = match it
131132
.filter_map(Result::ok)
132-
.min_by_key(|l| (date - l.signature.time).abs())
133+
.inspect(|d| {
134+
last = Some(if d.previous_oid.is_null() {
135+
d.new_oid
136+
} else {
137+
d.previous_oid
138+
});
139+
})
140+
.find(|l| l.signature.time.seconds <= date.seconds)
133141
{
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-
}
142+
Some(closest_line) => closest_line.new_oid,
143+
None => match last {
144+
None => {
145+
self.err.push(Error::EmptyReflog);
146+
return None;
147+
}
148+
Some(id) => id,
149+
},
150+
};
151+
self.objs[self.idx]
152+
.get_or_insert_with(HashSet::default)
153+
.insert(id_to_insert);
154+
Some(())
153155
}
154-
}
155-
ReflogLookup::Entry(no) => {
156-
let r = match &mut self.refs[self.idx] {
157-
Some(r) => r.clone().attach(self.repo),
158-
val @ None => match self.repo.head().map(crate::Head::try_into_referent) {
159-
Ok(Some(r)) => {
160-
*val = Some(r.clone().detach());
161-
r
162-
}
163-
Ok(None) => {
164-
self.err.push(Error::UnbornHeadsHaveNoRefLog);
165-
return None;
166-
}
167-
Err(err) => {
168-
self.err.push(err.into());
169-
return None;
170-
}
171-
},
172-
};
173-
let mut platform = r.log_iter();
174-
match platform.rev().ok().flatten() {
175-
Some(mut it) => match it.nth(no).and_then(Result::ok) {
176-
Some(line) => {
177-
self.objs[self.idx]
178-
.get_or_insert_with(HashSet::default)
179-
.insert(line.new_oid);
180-
Some(())
181-
}
182-
None => {
183-
let available = platform.rev().ok().flatten().map_or(0, Iterator::count);
184-
self.err.push(Error::RefLogEntryOutOfRange {
185-
reference: r.detach(),
186-
desired: no,
187-
available,
188-
});
189-
None
190-
}
191-
},
156+
ReflogLookup::Entry(no) => match it.nth(no).and_then(Result::ok) {
157+
Some(line) => {
158+
self.objs[self.idx]
159+
.get_or_insert_with(HashSet::default)
160+
.insert(line.new_oid);
161+
Some(())
162+
}
192163
None => {
193-
self.err.push(Error::MissingRefLog {
194-
reference: r.name().as_bstr().into(),
195-
action: "lookup entry",
164+
let available = platform.rev().ok().flatten().map_or(0, Iterator::count);
165+
self.err.push(Error::RefLogEntryOutOfRange {
166+
reference: r.detach(),
167+
desired: no,
168+
available,
196169
});
197170
None
198171
}
199-
}
172+
},
173+
},
174+
None => {
175+
self.err.push(Error::MissingRefLog {
176+
reference: r.name().as_bstr().into(),
177+
action: match query {
178+
ReflogLookup::Entry(_) => "lookup reflog entry by index",
179+
ReflogLookup::Date(_) => "lookup reflog entry by date",
180+
},
181+
});
182+
None
200183
}
201184
}
202185
}
Binary file not shown.

0 commit comments

Comments
 (0)