started work on git module.

This commit is contained in:
Gabe Venberg 2024-02-10 23:18:01 -06:00
parent 437a4bfa13
commit d113289fd2
5 changed files with 65 additions and 12 deletions

8
Cargo.lock generated
View file

@ -284,9 +284,9 @@ dependencies = [
[[package]] [[package]]
name = "git2" name = "git2"
version = "0.18.1" version = "0.18.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbf97ba92db08df386e10c8ede66a2a0369bd277090afd8710e19e38de9ec0cd" checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd"
dependencies = [ dependencies = [
"bitflags 2.4.2", "bitflags 2.4.2",
"libc", "libc",
@ -377,9 +377,9 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]] [[package]]
name = "libgit2-sys" name = "libgit2-sys"
version = "0.16.1+1.7.1" version = "0.16.2+1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2a2bb3680b094add03bb3732ec520ece34da31a8cd2d633d1389d0f0fb60d0c" checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",

View file

@ -12,7 +12,7 @@ description = "Utility to modify commit timestamps of a git repository"
chrono = "0.4.33" chrono = "0.4.33"
chrono-tz = "0.8.5" chrono-tz = "0.8.5"
clap = { version = "4.4.18", features = ["derive"] } clap = { version = "4.4.18", features = ["derive"] }
git2 = "0.18.1" git2 = "0.18.2"
iana-time-zone = "0.1.60" iana-time-zone = "0.1.60"
itertools = "0.12.1" itertools = "0.12.1"
once_cell = "1.19.0" once_cell = "1.19.0"

47
src/git.rs Normal file
View file

@ -0,0 +1,47 @@
use chrono::Duration;
use git2::{Commit, Repository};
use itertools::Itertools;
use thiserror::Error;
use crate::time::{distribute_across_ranges_with_jitter, TimeRange};
#[derive(Debug, Error)]
pub(crate) enum GitErrors {
#[error("end is not a parent of start")]
NotAParent,
#[error("{0} is not a commit hash in the repo")]
NotACommit(String),
}
/// find the number of commits between start and end,
/// where end is a parent commit of start
fn get_no_of_commits(start: &Commit, end: &Commit) -> Result<u32, GitErrors> {
match start.parent_ids().find_position(|sha| sha == &end.id()) {
Some(tuple) => Ok(tuple.0.try_into().expect("commit has over 2^32 parents")),
None => Err(GitErrors::NotAParent),
}
}
// will need to do an in memory rebase, ammending each commit with a new signature.
pub fn rebase_commits_across_timerange<Tz: chrono::TimeZone>(
repo: &Repository,
start_sha: &str,
end_sha: &str,
ranges: &[TimeRange<Tz>],
max_jitter: &Duration,
) -> Result<(), GitErrors> {
let start_commit = if let Ok(commit) = repo.find_commit_by_prefix(start_sha) {
commit
} else {
return Err(GitErrors::NotACommit(start_sha.to_string()));
};
let end_commit = if let Ok(commit) = repo.find_commit_by_prefix(end_sha) {
commit
} else {
return Err(GitErrors::NotACommit(end_sha.to_string()));
};
let num_commits = get_no_of_commits(&start_commit, &end_commit)?;
let times = distribute_across_ranges_with_jitter(ranges, num_commits, max_jitter);
todo!()
}

View file

@ -1,5 +1,6 @@
mod args; mod args;
mod err; mod err;
mod git;
mod time; mod time;
use chrono::prelude::*; use chrono::prelude::*;
@ -9,13 +10,19 @@ use clap::Parser;
fn main() { fn main() {
let cli = args::Cli::parse(); let cli = args::Cli::parse();
println!("{:#?}", cli); println!("{:#?}", cli);
let start_time = match cli.timezone { let tz = cli
Some(tz) => tz.from_local_datetime(&cli.start_time).unwrap(), .timezone
None => get_local_timezone() .unwrap_or_else(|| get_local_timezone().expect("Could not get local timezone"));
.expect("Could not get local timezone") let start_time = tz.from_local_datetime(&cli.start_time).unwrap();
.from_local_datetime(&cli.start_time) let end_time = if let Some(time) = cli.end_time {
.unwrap(), tz.from_local_datetime(&time).unwrap()
} else {
Utc::now().with_timezone(&tz)
}; };
println!(
"start_time = {:#?}, end_time = {:#?}, tz = {:#?}",
start_time, end_time, tz
)
} }
fn get_local_timezone() -> Result<Tz, String> { fn get_local_timezone() -> Result<Tz, String> {

View file

@ -9,7 +9,6 @@ pub struct TimeRange<Tz: chrono::TimeZone> {
} }
impl<Tz: chrono::TimeZone> TimeRange<Tz> { impl<Tz: chrono::TimeZone> TimeRange<Tz> {
/// whether a time instance lies within the time range /// whether a time instance lies within the time range
pub fn is_in_range<Otz: chrono::TimeZone>(&self, other: &DateTime<Otz>) -> bool { pub fn is_in_range<Otz: chrono::TimeZone>(&self, other: &DateTime<Otz>) -> bool {
(self.start <= *other) && (other <= &self.end) (self.start <= *other) && (other <= &self.end)