git_zero_server/receive/
ancestry.rs1use git_zero_core::{Error, ObjectFormat, ObjectId, ObjectKind, Result};
3
4pub struct Ancestry {
8 format: ObjectFormat,
9 target: Option<ObjectId>,
10 remaining: u64,
11}
12
13impl Ancestry {
14 pub const fn new(format: ObjectFormat, max_visits: u64) -> Self {
15 Self {
16 format,
17 target: None,
18 remaining: max_visits,
19 }
20 }
21
22 pub fn start(&mut self, old: ObjectId) -> Result<()> {
24 self.target = None;
25 if self.remaining == 0 {
26 return Err(Error::LimitExceeded);
27 }
28 if old.format() != self.format || old.is_zero() {
29 return Err(Error::InvalidObjectId);
30 }
31 self.target = Some(old);
32 Ok(())
33 }
34
35 pub fn visit(&mut self, id: ObjectId, kind: ObjectKind) -> Result<bool> {
38 let target = self.target.ok_or(Error::InvalidRequest)?;
39 if self.remaining == 0 {
40 return Err(Error::LimitExceeded);
41 }
42 if id.format() != self.format || id.is_zero() {
43 return Err(Error::InvalidObjectId);
44 }
45 if kind != ObjectKind::Commit {
46 return Err(Error::InvalidObject);
47 }
48 self.remaining -= 1;
49 let found = target == id;
50 if found {
51 self.target = None;
52 }
53 Ok(found)
54 }
55}