1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use git2::{Repository, Revwalk};
use regex::Regex;
use std::collections::HashMap;

lazy_static! {
    static ref RE_SUMMARY: Regex = Regex::new(r":(.*?):(.*)").unwrap();

    static ref EMOJIES: HashMap<&'static str, &'static str> = {
        let mut m = HashMap::new();
        // You can use gen_code.js to generate this
        m.insert("hammer", "🔨");
        m.insert("art", "🎨");
        m.insert("zap", "⚡️");
        m.insert("fire", "🔥");
        m.insert("bug", "🐛");
        m.insert("ambulance", "🚑");
        m.insert("sparkles", "✨");
        m.insert("memo", "📝");
        m.insert("rocket", "🚀");
        m.insert("lipstick", "💄");
        m.insert("tada", "🎉");
        m.insert("white_check_mark", "✅");
        m.insert("lock", "🔒");
        m.insert("apple", "🍎");
        m.insert("penguin", "🐧");
        m.insert("checkered_flag", "🏁");
        m.insert("robot", "🤖");
        m.insert("green_apple", "🍏");
        m.insert("bookmark", "🔖");
        m.insert("rotating_light", "🚨");
        m.insert("construction", "🚧");
        m.insert("green_heart", "💚");
        m.insert("arrow_down", "⬇️");
        m.insert("arrow_up", "⬆️");
        m.insert("pushpin", "📌");
        m.insert("construction_worker", "👷");
        m.insert("chart_with_upwards_trend", "📈");
        m.insert("recycle", "♻️");
        m.insert("whale", "🐳");
        m.insert("heavy_plus_sign", "➕");
        m.insert("heavy_minus_sign", "➖");
        m.insert("wrench", "🔧");
        m.insert("globe_with_meridians", "🌐");
        m.insert("pencil2", "✏️");
        m.insert("hankey", "💩");
        m.insert("rewind", "⏪");
        m.insert("twisted_rightwards_arrows", "🔀");
        m.insert("package", "📦");
        m.insert("alien", "👽");
        m.insert("truck", "🚚");
        m.insert("page_facing_up", "📄");
        m.insert("boom", "💥");
        m.insert("bento", "🍱");
        m.insert("ok_hand", "👌");
        m.insert("wheelchair", "♿️");
        m.insert("bulb", "💡");
        m.insert("beers", "🍻");
        m.insert("speech_balloon", "💬");
        m.insert("card_file_box", "🗃");
        m.insert("loud_sound", "🔊");
        m.insert("mute", "🔇");
        m.insert("busts_in_silhouette", "👥");
        m.insert("children_crossing", "🚸");
        m.insert("building_construction", "🏗");
        m.insert("iphone", "📱");
        m.insert("clown_face", "🤡");
        m.insert("egg", "🥚");
        m.insert("see_no_evil", "🙈");
        m.insert("camera_flash", "📸");
        m.insert("alembic", "⚗");
        m.insert("mag", "🔍");
        m.insert("wheel_of_dharma", "☸️");
        m.insert("label", "🏷️");
        m
    };
}

#[derive(Debug, Eq, PartialEq, Serialize, Clone)]
pub struct Commit {
    pub hash: String,
    pub summary: String, // TODO: try to convert this so str
    pub author: String,
    pub emoji_code: String,
    pub emoji: String,
}

impl Commit {
    pub fn new(hash: String, summary: &str, author: &str, emoji_code: &str) -> Commit {
        Commit {
            hash,
            summary: summary.to_string(),
            author: author.to_string(),
            emoji_code: emoji_code.to_string(),
            emoji: EMOJIES.get(emoji_code).unwrap_or(&emoji_code).to_string(),
        }
    }

    pub fn from_git2(commit: &git2::Commit) -> Option<Commit> {
        // author
        let author = commit.author();
        let author = author.name().or_else(|| author.email()).unwrap_or("");

        // hash (full, since git2r doesn't support shorthash yet )
        let hash = format!("{}", commit.id());

        // summary and new commit
        let summary = commit.summary().unwrap_or("");
        match RE_SUMMARY.captures(summary) {
            None => None,
            Some(captures) => {
                let emoji_code = captures.get(1).unwrap().as_str();
                let summary = captures.get(2).unwrap().as_str().trim();

                Some(Commit::new(hash, summary, author, emoji_code))
            }
        }
    }

    pub fn from_revwalk(repository: &Repository, revwalk: &mut Revwalk) -> Vec<Commit> {
        revwalk
            .filter_map(|oid| repository.find_commit(oid.unwrap()).ok())
            .filter_map(|raw_commit| Commit::from_git2(&raw_commit))
            .collect()
    }
}