git_backend: return timestamps for what was actually written

Now that we return the written commit from `write_commit()`, let's
make the timestamps match what was actually written, accounting for
the whole-second precision and the adjustment we do to avoid
collisions.
This commit is contained in:
Martin von Zweigbergk 2023-05-11 16:01:09 -07:00 committed by Martin von Zweigbergk
parent a95188ddbc
commit 87a925d736
3 changed files with 28 additions and 7 deletions

View file

@ -468,7 +468,7 @@ impl Backend for GitBackend {
Ok(commit)
}
fn write_commit(&self, contents: Commit) -> BackendResult<(CommitId, Commit)> {
fn write_commit(&self, mut contents: Commit) -> BackendResult<(CommitId, Commit)> {
let locked_repo = self.repo.lock().unwrap();
let git_tree_id = validate_git_object_id(&contents.root_tree)?;
let git_tree = locked_repo
@ -546,6 +546,11 @@ impl Backend for GitBackend {
}
}
};
// Update the signatures to match the ones that were actually written to the
// object store
contents.author.timestamp.timestamp = MillisSinceEpoch(author.when().seconds() * 1000);
contents.committer.timestamp.timestamp =
MillisSinceEpoch(committer.when().seconds() * 1000);
mut_table.add_entry(id.to_bytes(), extras);
self.extra_metadata_store
.save_table(mut_table)
@ -844,7 +849,7 @@ mod tests {
fn overlapping_git_commit_id() {
let temp_dir = testutils::new_temp_dir();
let store = GitBackend::init_internal(temp_dir.path());
let commit1 = Commit {
let mut commit1 = Commit {
parents: vec![store.root_commit_id().clone()],
predecessors: vec![],
root_tree: store.empty_tree_id().clone(),
@ -853,11 +858,27 @@ mod tests {
author: create_signature(),
committer: create_signature(),
};
// libgit2 doesn't seem to preserve negative timestamps, so set it to at least 1
// second after the epoch, so the timestamp adjustment can remove 1
// second and it will still be nonnegative
commit1.committer.timestamp.timestamp = MillisSinceEpoch(1000);
let (commit_id1, mut commit2) = store.write_commit(commit1).unwrap();
commit2.predecessors.push(commit_id1.clone());
// `write_commit` should prevent the ids from being the same by changing the
// committer timestamp of the commit it actually writes.
assert_ne!(store.write_commit(commit2).unwrap().0, commit_id1);
let (commit_id2, mut actual_commit2) = store.write_commit(commit2.clone()).unwrap();
// The returned matches the ID
assert_eq!(store.read_commit(&commit_id2).unwrap(), actual_commit2);
assert_ne!(commit_id2, commit_id1);
// The committer timestamp should differ
assert_ne!(
actual_commit2.committer.timestamp.timestamp,
commit2.committer.timestamp.timestamp
);
// The rest of the commit should be the same
actual_commit2.committer.timestamp.timestamp =
commit2.committer.timestamp.timestamp.clone();
assert_eq!(actual_commit2, commit2);
}
fn git_id(commit_id: &CommitId) -> Oid {

View file

@ -44,7 +44,7 @@ fn test_initial(use_git: bool) {
name: "author name".to_string(),
email: "author email".to_string(),
timestamp: Timestamp {
timestamp: MillisSinceEpoch(100),
timestamp: MillisSinceEpoch(1000),
tz_offset: 60,
},
};
@ -52,7 +52,7 @@ fn test_initial(use_git: bool) {
name: "committer name".to_string(),
email: "committer email".to_string(),
timestamp: Timestamp {
timestamp: MillisSinceEpoch(200),
timestamp: MillisSinceEpoch(2000),
tz_offset: -60,
},
};

View file

@ -1611,10 +1611,10 @@ fn test_evaluate_expression_latest(use_git: bool) {
let mut tx = repo.start_transaction(&settings, "test");
let mut_repo = tx.mut_repo();
let mut write_commit_with_committer_timestamp = |msec| {
let mut write_commit_with_committer_timestamp = |sec: i64| {
let builder = create_random_commit(mut_repo, &settings);
let mut committer = builder.committer().clone();
committer.timestamp.timestamp = MillisSinceEpoch(msec);
committer.timestamp.timestamp = MillisSinceEpoch(sec * 1000);
builder.set_committer(committer).write().unwrap()
};
let commit1_t3 = write_commit_with_committer_timestamp(3);