如何将常量映射到自定义字符串

时间:2019-06-02 18:51:27

标签: git rust

我正在使用git2 crate获取git存储库上的statuses列表,这是我正在使用的代码:

use git2::{Repository, StatusOptions, StatusShow};
use std::{collections::HashMap, env};

fn main() {
    let path = env::current_dir().unwrap();
    let repo = Repository::discover(path).unwrap();
    let mut status_opt = StatusOptions::new();
    status_opt
        .show(StatusShow::IndexAndWorkdir)
        .include_untracked(true)
        .include_unmodified(false)
        .no_refresh(false);
    let status_result = repo.statuses(Some(&mut status_opt)).unwrap();

    let mut map: HashMap<git2::Status, u32> = HashMap::new();

    for status_entry in status_result.iter() {
        *map.entry(status_entry.status()).or_insert(0) += 1;
    }
    println!("{:?}", map);
}

基于当前存储库的修改,返回了git2::Status和事件的映射,但是我想向命令git status --porcelain返回类似的输出。

例如,根据存储库的更改,这是git status --porcelain的输出:

M  file_a
AM file_b
A  file_c
?? file_e
?? file_f

将输出传递到awk

$ git status --porcelain | awk -v ORS=", " 'NR>0{arr[$1]++}END{for (a in arr) print a, arr[a]}'
A 1, ?? 2, M 1, AM 1,

使用上面的Rust代码将返回:

{INDEX_NEW: 1, WT_NEW: 2, INDEX_NEW | WT_MODIFIED: 1, INDEX_MODIFIED: 1}

我想知道如何将git2::Status常量的值映射到自定义字符串(匹配porceline字符串),例如:

INDEX_NEW                -> A 
INDEX_NEW | WT_MODIFIED  -> AM
INDEX_MODIFIED           -> M
WT_NEW                   -> ??

主要是如何处理类似INDEX_NEW | WT_MODIFIED的情况,例如将映射到AM

1 个答案:

答案 0 :(得分:4)

以下代码段将您的map转换为所需的表示形式。所提供的示例将这些值集合到另一个HashMap中,并且有一个可以惊慌的手臂,但是可以随时动态转换git2::Status值(即,当您第一次遍历它们时)。

let mut output = HashMap::new();
for (key, value) in map.iter()
{
    let key = match key
    {

        s if s.contains(git2::Status::INDEX_NEW) &&
             s.contains(git2::Status::WT_MODIFIED) => "AM",
        s if s.contains(git2::Status::INDEX_NEW) => "A",
        s if s.contains(git2::Status::INDEX_MODIFIED) => "M",
        _ => panic!("Unexpected status"),
    };

    output.insert(key, value);
}

println!("{:?}", output);

如果您正在查看所选库的示例,则会发现非常相似的内容:git2-rs/examples/status.rs

有关模式匹配语法的更多信息,请参阅The Rust Programming Book