asyncgit 0.2.1

allow using git2 in a asynchronous context
Documentation
use super::utils::repo;
use git2::{Commit, Error, Oid};
use scopetime::scope_time;

///
#[derive(Debug)]
pub struct CommitInfo {
    ///
    pub message: String,
    ///
    pub time: i64,
    ///
    pub author: String,
    ///
    pub hash: String,
}

///
pub fn get_commits_info(
    repo_path: &str,
    ids: &[Oid],
) -> Result<Vec<CommitInfo>, Error> {
    scope_time!("get_commits_info");

    let repo = repo(repo_path);

    let commits = ids.iter().map(|id| repo.find_commit(*id).unwrap());

    let res = commits
        .map(|c: Commit| {
            let message = get_message(&c);
            let author = if let Some(name) = c.author().name() {
                String::from(name)
            } else {
                String::from("<unknown>")
            };
            CommitInfo {
                message,
                author,
                time: c.time().seconds(),
                hash: c.id().to_string(),
            }
        })
        .collect::<Vec<_>>();

    Ok(res)
}

fn get_message(c: &Commit) -> String {
    if let Some(msg) = c.message() {
        limit_str(msg, 50)
    } else {
        String::from("<unknown>")
    }
}

fn limit_str(s: &str, limit: usize) -> String {
    if let Some(first) = s.lines().next() {
        first.chars().take(limit).collect::<String>()
    } else {
        String::new()
    }
}

#[cfg(test)]
mod tests {

    use super::get_commits_info;
    use crate::sync::{
        commit, stage_add_file, tests::repo_init_empty,
    };
    use std::{
        fs::File,
        io::{Error, Write},
        path::Path,
    };

    #[test]
    fn test_log() -> Result<(), Error> {
        let file_path = Path::new("foo");
        let (_td, repo) = repo_init_empty();
        let root = repo.path().parent().unwrap();
        let repo_path = root.as_os_str().to_str().unwrap();

        File::create(&root.join(file_path))?.write_all(b"a")?;
        stage_add_file(repo_path, file_path);
        let c1 = commit(repo_path, "commit1").unwrap();
        File::create(&root.join(file_path))?.write_all(b"a")?;
        stage_add_file(repo_path, file_path);
        let c2 = commit(repo_path, "commit2").unwrap();

        let res = get_commits_info(repo_path, &vec![c2, c1]).unwrap();

        assert_eq!(res.len(), 2);
        assert_eq!(res[0].message.as_str(), "commit2");
        assert_eq!(res[0].author.as_str(), "name");
        assert_eq!(res[1].message.as_str(), "commit1");

        Ok(())
    }
}