Provide world Git identity, reflog fallback, object inspection, and which (T73)

This commit is contained in:
2026-11-08 02:28:34 +00:00
parent 1892642d8e
commit fdda49394f
11 changed files with 450 additions and 30 deletions
+44 -20
View File
@@ -57,30 +57,54 @@ pub(crate) struct BranchDeleted {
pub reference: String,
}
/// Reflogs require an identity, but switching branches must not require configuring one.
/// With no repository identity, leave reflogs untouched and report that explicitly; never invent an author.
/// Reflog-only writes use a fallback identity when the repository has none.
pub(crate) fn reflog_signature(repo: &gix::Repository) -> Result<gix::actor::Signature> {
if let Some(signature) = repo
.committer()
.transpose()
.map_err(|e| error("reflog identity", e))?
{
return signature
.to_owned()
.map_err(|e| error("reflog identity", e));
}
let config = repo.config_snapshot();
let name = std::env::var("GIT_COMMITTER_NAME")
.ok()
.or_else(|| config.string("user.name").map(|s| s.to_string()))
.or_else(|| std::env::var("USER").ok())
.unwrap_or_else(|| "Sausage".into());
let email = std::env::var("GIT_COMMITTER_EMAIL")
.ok()
.or_else(|| config.string("user.email").map(|s| s.to_string()))
.unwrap_or_else(|| {
format!(
"{}@{}",
std::env::var("USER").unwrap_or_else(|_| "sausage".into()),
std::env::var("HOSTNAME").unwrap_or_else(|_| "localhost".into())
)
});
let seconds = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
Ok(gix::actor::Signature {
name: name.into(),
email: email.into(),
time: gix::date::Time::new(seconds, 0),
})
}
/// Publish references and their reflog entries without requiring a commit identity.
pub(crate) fn edit_refs(
repo: &gix::Repository,
edits: Vec<gix::refs::transaction::RefEdit>,
) -> Result<Vec<String>> {
let committer = repo
.committer()
.transpose()
.map_err(|e| error("reflog identity", e))?;
if let Some(committer) = committer {
repo.edit_references_as(edits, Some(committer))
.map_err(|e| error("checkout refs", e))?;
Ok(Vec::new())
} else {
let mut local = repo.clone();
local.refs.write_reflog = gix::refs::store::WriteReflog::Disable;
local
.edit_references_as(edits, None)
.map_err(|e| error("checkout refs", e))?;
Ok(vec![
"reflog not written: no repository committer identity configured".into(),
])
}
let signature = reflog_signature(repo)?;
let mut time = Default::default();
repo.edit_references_as(edits, Some(signature.to_ref(&mut time)))
.map_err(|e| error("checkout refs", e))?;
Ok(Vec::new())
}
pub(crate) fn branch_name(name: &str) -> Result<String> {