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

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

View file

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