git-ents.gitmain
⌘K
foforge
commit 9954b29
fixup! feat: recover a document's authorship from its ref's commits
Joseph D. Carpinelli · 1 month ago

Reviews

No reviews of this commit yet — record a verdict below.

Start a review

verdict

crates/git-store/src/lib.rs @@ -256,10 +256,7 @@ value: &T, message: &str, ) -> Result<(), Error> { - if !ref_segment_ok(id) { - return Err(Error::InvalidKey(id.to_owned())); - } - self.store(&format!("{prefix}/{id}"), value, message) + self.store(&item_ref(prefix, id)?, value, message) } /// Like [`store_item`](Self::store_item), but attributing authorship to @@ -274,10 +271,7 @@ message: &str, author: (&str, &str), ) -> Result<(), Error> { - if !ref_segment_ok(id) { - return Err(Error::InvalidKey(id.to_owned())); - } - self.store_impl(&format!("{prefix}/{id}"), value, message, Some(author)) + self.store_authored(&item_ref(prefix, id)?, value, message, author) } /// Like [`store_item`](Self::store_item), but for a [`HasId`] value that @@ -372,13 +366,15 @@ let Some(tip) = self.ref_commit(refname)? else { return Ok(None); }; - let updated = self.read_authorship(&tip)?; - let mut genesis = tip; - while let Some(parent) = self.read_commit(&genesis)?.parents.into_iter().next() { - genesis = parent; + let mut commit = self.read_commit(&tip)?; + let updated = commit.author.clone(); + while let Some(parent) = commit.parents.first().copied() { + commit = self.read_commit(&parent)?; } - let created = self.read_authorship(&genesis)?; - Ok(Some(Provenance { created, updated })) + Ok(Some(Provenance { + created: commit.author, + updated, + })) } /// [`provenance`](Self::provenance) for the item `id` under the collection @@ -427,7 +423,8 @@ } } - /// Read `oid`'s tree, parents, and committer date from the durable store. + /// Read `oid`'s tree, parents, author, and committer date from the + /// durable store. fn read_commit(&self, oid: &ObjectId) -> Result<CommitFacts, Error> { let mut buffer = Vec::new(); let commit = self @@ -438,27 +435,18 @@ .committer() .map_err(|error| Error::Object(error.to_string()))? .seconds(); + let author = commit + .author() + .map_err(|error| Error::Object(error.to_string()))?; Ok(CommitFacts { tree: commit.tree(), parents: commit.parents().collect(), seconds: u64::try_from(seconds).unwrap_or(0), - }) - } - - /// Read the author stamped on `oid`'s commit header. - fn read_authorship(&self, oid: &ObjectId) -> Result<Authorship, Error> { - let mut buffer = Vec::new(); - let commit = self - .odb - .find_commit(oid, &mut buffer) - .map_err(|error| Error::Object(error.to_string()))?; - let author = commit - .author() - .map_err(|error| Error::Object(error.to_string()))?; - Ok(Authorship { - name: author.name.to_string(), - email: author.email.to_string(), - seconds: u64::try_from(author.seconds()).unwrap_or(0), + author: Authorship { + name: author.name.to_string(), + email: author.email.to_string(), + seconds: u64::try_from(author.seconds()).unwrap_or(0), + }, }) } @@ -534,6 +522,16 @@ /// contention; ordinary racing writers resolve within one or two rounds. const MAX_MERGE_RETRIES: usize = 5; +/// The ref name for item `id` under the collection namespace `prefix` +/// (`{prefix}/{id}`), rejecting an `id` that fails [`ref_segment_ok`] since it +/// becomes the ref's last path segment. +fn item_ref(prefix: &str, id: &str) -> Result<String, Error> { + if !ref_segment_ok(id) { + return Err(Error::InvalidKey(id.to_owned())); + } + Ok(format!("{prefix}/{id}")) +} + /// An author identity and date read off one of a document ref's commits — /// recovered from the commit header rather than stored in the document tree. #[derive(Debug, Clone, PartialEq, Eq)] @@ -555,11 +553,13 @@ pub updated: Authorship, } -/// The facts read off a commit: its tree, its parents, and its committer date. +/// The facts read off a commit: its tree, its parents, its author, and its +/// committer date. struct CommitFacts { tree: ObjectId, parents: Vec<ObjectId>, seconds: u64, + author: Authorship, } #[cfg(test)]