From a0dca8186bdef76e09e9c388d7f85839e85ce8db Mon Sep 17 00:00:00 2001 From: Katharina Fey Date: Mon, 22 Jun 2020 16:33:28 +0200 Subject: git: refactoring git module to have a unified actions API --- src/git/log.rs | 57 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 23 deletions(-) (limited to 'src/git/log.rs') diff --git a/src/git/log.rs b/src/git/log.rs index 97101cf..c8f4aa3 100644 --- a/src/git/log.rs +++ b/src/git/log.rs @@ -1,7 +1,7 @@ //! libgit2 log parsing -use crate::git::{self, tree::FileNode}; -use git2::{Oid, Repository}; +use crate::git::{tree::FileNode, Repo}; +use git2::Oid; use std::collections::{BTreeMap, BTreeSet}; /// A file-commit referenced graph thing @@ -17,8 +17,11 @@ use std::collections::{BTreeMap, BTreeSet}; /// change" and it will tell you (sort of). #[derive(Debug, Default)] pub(crate) struct CommitGraph { + /// The correct order of commits in the log order: Vec, - file_refs: BTreeMap>, + /// List of all files, and the commits in which they were touched + file_refs: BTreeMap>, + /// Map of commit IDs to metadata commit_refs: BTreeMap, } @@ -31,19 +34,19 @@ pub(crate) struct CommitNode { time: i64, } -fn build_diff_log(repo: &Repository, log: Vec<(String, Vec)>) -> Vec { +fn build_diff_log(repo: &Repo, log: Vec<(String, Vec)>) -> Vec { todo!() } /// Walk through all commits from a given ref and build a commit graph -pub(crate) fn create_commit_log(id: String, repo: &Repository) -> CommitGraph { - let mut walker = repo.revwalk().unwrap(); - walker.push(Oid::from_str(id.as_str()).unwrap()).unwrap(); +pub(crate) fn create_commit_log(rev: String, repo: &Repo) -> CommitGraph { + let mut walker = repo.get_inner().revwalk().unwrap(); + walker.push(Oid::from_str(rev.as_str()).unwrap()).unwrap(); let mut commits = walker .into_iter() .map(|oid| { let oid = oid.unwrap(); - repo.find_commit(oid).unwrap() + repo.get_inner().find_commit(oid).unwrap() }) .collect::>(); commits.reverse(); @@ -52,7 +55,7 @@ pub(crate) fn create_commit_log(id: String, repo: &Repository) -> CommitGraph { .into_iter() .map(|commit| { let id = format!("{}", commit.id()); - (id.clone(), git::repo::get_tree(&repo, id.as_str())) + (id.clone(), repo.get_tree(id.as_str())) }) .collect(); @@ -64,43 +67,51 @@ pub(crate) fn create_commit_log(id: String, repo: &Repository) -> CommitGraph { let (commit_refs, file_refs) = log.into_iter().fold( (BTreeMap::new(), BTreeMap::new()), |(mut cm, mut fm), (cid, current)| { + let commit_id = format!("{}", cid); + let d = repo + .get_inner() .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())); + + // Store the commit to preserve order + order.push(commit_id.clone()); + + // For each file, store this commit as one that touched it + let touches = d.deltas().fold(BTreeSet::new(), |mut set, delta| { + let file_id = format!("{}", delta.new_file().id()); + fm.entry(file_id.clone()) + .or_insert(vec![]) + .push(commit_id.clone()); + set.insert(file_id); set }); - order.push(cid.clone()); - fm.insert(cid.clone(), files.clone()); - + // From the commit, build a metadata object let commit_u = repo + .get_inner() .find_commit(Oid::from_str(cid.as_str()).unwrap()) .unwrap(); let author_u = commit_u.author(); let commit = CommitNode { - id: cid.clone(), + id: commit_id, message: commit_u.message().unwrap().to_owned(), author: format!("{} {}", author_u.name().unwrap(), author_u.email().unwrap()), - touches: files, + touches, time: author_u.when().seconds(), }; + // Insert the metadata object cm.insert(cid.clone(), commit); + // We pass both the modified maps into the next commit (cm, fm) }, ); - let graph = CommitGraph { + CommitGraph { order, file_refs, commit_refs, - }; - - dbg!(graph); - - // let diffs = build_diff_log(&repo, log); - todo!() + } } -- cgit v1.2.3