Respect author-date for setting up completely static commmit graphs

This updates to a yet-to-be-released version of `gix` to be able to
leverage full local-time support thanks to the usage of `jiff`.

This means we can now rely on the local `now()` that `gix` signatures
come with, which naturally respect environment variables that help
to make commits statically known.

For the running Tauri application this won't have an effect as it won't
inherit environment variables, but the CLI will be different in that regard.
This commit is contained in:
Sebastian Thiel 2024-07-30 09:47:29 +02:00
parent f4504b78d3
commit 76d687b55c
No known key found for this signature in database
GPG Key ID: 9CB5EE7895E8268B
4 changed files with 606 additions and 244 deletions

782
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@ resolver = "2"
[workspace.dependencies] [workspace.dependencies]
# Add the `tracing` or `tracing-detail` features to see more of gitoxide in the logs. Useful to see which programs it invokes. # Add the `tracing` or `tracing-detail` features to see more of gitoxide in the logs. Useful to see which programs it invokes.
gix = { version = "0.64", default-features = false, features = [] } gix = { git = "https://github.com/Byron/gitoxide", rev = "1d37bf6a773d56eea9003aa626ced413e8e0eaa3", default-features = false, features = [] }
git2 = { version = "0.18.3", features = [ git2 = { version = "0.18.3", features = [
"vendored-openssl", "vendored-openssl",
"vendored-libgit2", "vendored-libgit2",

View File

@ -2,13 +2,39 @@
set -eu -o pipefail set -eu -o pipefail
CLI=${1:?The first argument is the GitButler CLI} CLI=${1:?The first argument is the GitButler CLI}
function tick () {
if test -z "${tick+set}"; then
tick=1675176957
else
tick=$(($tick + 60))
fi
GIT_COMMITTER_DATE="$tick +0100"
GIT_AUTHOR_DATE="$tick +0100"
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
}
tick
git init remote git init remote
(cd remote (cd remote
echo first > file echo first > file
git add . && git commit -m "init" git add . && git commit -m "init"
) )
export GITBUTLER_CLI_DATA_DIR=./git/gitbutler/app-data git clone remote single-branch-no-vbranch
git clone remote single-branch-no-vbranch-one-commit
(cd single-branch-no-vbranch-one-commit
echo change >> file && git add . && git commit -m "local change"
)
git clone remote single-branch-no-vbranch-multi-remote
(cd single-branch-no-vbranch-multi-remote
git remote add other-origin ../remote
git fetch other-origin
)
export GITBUTLER_CLI_DATA_DIR=./user/gitbutler/app-data
git clone remote one-vbranch-on-integration git clone remote one-vbranch-on-integration
(cd one-vbranch-on-integration (cd one-vbranch-on-integration
$CLI project add --switch-to-integration "$(git rev-parse --symbolic-full-name @{u})" $CLI project add --switch-to-integration "$(git rev-parse --symbolic-full-name @{u})"

View File

@ -447,17 +447,18 @@ impl RepoActionsExt for CommandContext {
fn signatures(&self) -> Result<(git2::Signature, git2::Signature)> { fn signatures(&self) -> Result<(git2::Signature, git2::Signature)> {
let repo = gix::open(self.repository().path())?; let repo = gix::open(self.repository().path())?;
let default_actor = gix::actor::SignatureRef { let author = repo
name: GITBUTLER_INTEGRATION_COMMIT_AUTHOR_NAME.into(), .author()
email: GITBUTLER_INTEGRATION_COMMIT_AUTHOR_EMAIL.into(), .transpose()?
time: Default::default(), .unwrap_or_else(|| default_actor_with_commit_time("GIT_AUTHOR_DATE"));
};
let author = repo.author().transpose()?.unwrap_or(default_actor);
let config: Config = self.repository().into(); let config: Config = self.repository().into();
let committer = if config.user_real_comitter()? { let committer = if config.user_real_comitter()? {
repo.committer().transpose()?.unwrap_or(default_actor) repo.committer()
.transpose()?
.unwrap_or_else(|| default_actor_with_commit_time("GIT_COMMITTER_DATE"))
} else { } else {
default_actor default_actor_with_commit_time("GIT_COMMITTER_DATE")
}; };
Ok(( Ok((
@ -467,10 +468,28 @@ impl RepoActionsExt for CommandContext {
} }
} }
fn default_actor_with_commit_time(
overriding_variable_name: &str,
) -> gix::actor::SignatureRef<'static> {
gix::actor::SignatureRef {
name: GITBUTLER_INTEGRATION_COMMIT_AUTHOR_NAME.into(),
email: GITBUTLER_INTEGRATION_COMMIT_AUTHOR_EMAIL.into(),
time: std::env::var(overriding_variable_name)
.ok()
.and_then(|time| gix::date::parse(&time, Some(std::time::SystemTime::now())).ok())
.unwrap_or_else(|| gix::date::Time::now_local_or_utc()),
}
}
/// Convert `actor` to a `git2` representation or fail if that's not possible.
/// Note that the current time as provided by `gix` is also use as it
/// respects the `GIT_AUTHOR|COMMITTER_DATE` environment variables.
fn actor_to_git2_signature( fn actor_to_git2_signature(
actor: gix::actor::SignatureRef<'_>, actor: gix::actor::SignatureRef<'_>,
) -> Result<git2::Signature<'static>> { ) -> Result<git2::Signature<'static>> {
Ok(git2::Signature::now( let offset_in_minutes = actor.time.offset / 60;
let time = git2::Time::new(actor.time.seconds, offset_in_minutes);
Ok(git2::Signature::new(
actor actor
.name .name
.to_str() .to_str()
@ -479,6 +498,7 @@ fn actor_to_git2_signature(
.email .email
.to_str() .to_str()
.with_context(|| format!("Could not process actor email: {}", actor.email))?, .with_context(|| format!("Could not process actor email: {}", actor.email))?,
&time,
)?) )?)
} }