From 367cb0b2358be04d18dfea963d1c42044893e3b4 Mon Sep 17 00:00:00 2001 From: Katharina Fey Date: Mon, 22 Jun 2020 10:17:52 +0200 Subject: git/log: adding a lot of parsing code to make libgit2 useful --- src/git/log.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/src/git/log.rs b/src/git/log.rs index dab9e69..97101cf 100644 --- a/src/git/log.rs +++ b/src/git/log.rs @@ -15,18 +15,20 @@ use std::collections::{BTreeMap, BTreeSet}; /// heavily parse the log. This type here is the result of this /// parsing: you can ask it smart questions like "when did this file /// change" and it will tell you (sort of). -#[derive(Default)] +#[derive(Debug, Default)] pub(crate) struct CommitGraph { order: Vec, file_refs: BTreeMap>, commit_refs: BTreeMap, } +#[derive(Debug)] pub(crate) struct CommitNode { id: String, author: String, + message: String, touches: BTreeSet, - date: String, + time: i64, } fn build_diff_log(repo: &Repository, log: Vec<(String, Vec)>) -> Vec { @@ -37,25 +39,68 @@ fn build_diff_log(repo: &Repository, log: Vec<(String, Vec)>) -> Vec CommitGraph { let mut walker = repo.revwalk().unwrap(); walker.push(Oid::from_str(id.as_str()).unwrap()).unwrap(); - let mut v = walker + let mut commits = walker .into_iter() .map(|oid| { let oid = oid.unwrap(); repo.find_commit(oid).unwrap() }) .collect::>(); - v.reverse(); + commits.reverse(); - let log: Vec<_> = v + let mut initial: Vec<(_, _)> = commits .into_iter() .map(|commit| { let id = format!("{}", commit.id()); - let tree_u = git::repo::get_tree(&repo, id.as_str()); - let tree = git::tree::parse_tree(tree_u, &repo); - (id, tree.flatten()) + (id.clone(), git::repo::get_tree(&repo, id.as_str())) }) .collect(); - let diffs = build_diff_log(&repo, log); + // split off rest of the diffs and dissolve the len(1) vec + let log = initial.split_off(1); + let previous = initial.remove(0).1; + + let mut order = vec![]; + let (commit_refs, file_refs) = log.into_iter().fold( + (BTreeMap::new(), BTreeMap::new()), + |(mut cm, mut fm), (cid, current)| { + let d = repo + .diff_tree_to_tree(Some(&previous), Some(¤t), None) + .unwrap(); + let files = d.deltas().fold(BTreeSet::new(), |mut set, delta| { + set.insert(format!("{}", delta.new_file().id())); + set + }); + + order.push(cid.clone()); + fm.insert(cid.clone(), files.clone()); + + let commit_u = repo + .find_commit(Oid::from_str(cid.as_str()).unwrap()) + .unwrap(); + let author_u = commit_u.author(); + let commit = CommitNode { + id: cid.clone(), + message: commit_u.message().unwrap().to_owned(), + author: format!("{} {}", author_u.name().unwrap(), author_u.email().unwrap()), + touches: files, + time: author_u.when().seconds(), + }; + + cm.insert(cid.clone(), commit); + + (cm, fm) + }, + ); + + let graph = CommitGraph { + order, + file_refs, + commit_refs, + }; + + dbg!(graph); + + // let diffs = build_diff_log(&repo, log); todo!() } -- cgit v1.2.3