使用 libgit2 高效地获取 git 存储库中的作者列表
get the list of authors in a git repository efficiently with libgit2
我需要获取 git 存储库的作者列表,就像 git shortlog -s
在命令行中所做的那样。
我目前正在做的工作是进行一次 revwalk(遍历所有修订)并一次收集所有提交的作者列表,但这非常慢,尤其是与到命令行 git 命令。
我正在使用 Rust,但我希望解决方案在 C 或其他绑定到 lib 的语言中类似git2。
这是我当前工作但速度较慢的代码:
let repo = Repository::open(&git_path)?;
let mut revwalk = repo.revwalk()?;
revwalk.push_head()?;
let mut authors: Vec<String> = revwalk
.map(|r| {
let oid = r?;
repo.find_commit(oid)
})
.filter_map(|c| match c {
Ok(commit) => Some(commit),
Err(e) => {
println!("Error walking the revisions {}, skipping", e);
None
}
})
.fold(HashSet::new(), |mut sofar, cur| {
if let Some(name) = cur.author().name() {
sofar.insert(name.to_string());
}
sofar
})
.into_iter()
.collect();
authors.sort();
EDIT 好的,在发布模式下使用 Rust 构建时速度明显更快。我仍然想知道是否还有更有效的方法。
不幸的是,没有更有效的方法,除非您对存储库结构有所了解(例如,特定点之前的所有提交都是由特定用户进行的)。如果您想了解有关每个提交的信息,则必须遍历每个提交。 Git 不提供此信息的缓存,因此需要遍历历史记录。
libgit2 更通用一些,可能无法利用与 Git 本身相同的优化,但整体算法是相同的。
通用算法已尽善尽美:您必须遍历每次提交才能收集所有作者姓名,没有办法绕过它。
Nitpick:您正在为每个提交的作者姓名分配 String
。首先检查名称是否已经在集合中可能会更快,它仅适用于 &str
(!sofar.contains(name)
).
在夜间,您可以将 sofar.insert(name.to_string());
更改为 sofar.get_or_insert_with(name, str::to_string);
。 get_or_insert_with
将只执行一次查找,而不是使用 contains
/insert
对执行两次查找。
我需要获取 git 存储库的作者列表,就像 git shortlog -s
在命令行中所做的那样。
我目前正在做的工作是进行一次 revwalk(遍历所有修订)并一次收集所有提交的作者列表,但这非常慢,尤其是与到命令行 git 命令。
我正在使用 Rust,但我希望解决方案在 C 或其他绑定到 lib 的语言中类似git2。
这是我当前工作但速度较慢的代码:
let repo = Repository::open(&git_path)?;
let mut revwalk = repo.revwalk()?;
revwalk.push_head()?;
let mut authors: Vec<String> = revwalk
.map(|r| {
let oid = r?;
repo.find_commit(oid)
})
.filter_map(|c| match c {
Ok(commit) => Some(commit),
Err(e) => {
println!("Error walking the revisions {}, skipping", e);
None
}
})
.fold(HashSet::new(), |mut sofar, cur| {
if let Some(name) = cur.author().name() {
sofar.insert(name.to_string());
}
sofar
})
.into_iter()
.collect();
authors.sort();
EDIT 好的,在发布模式下使用 Rust 构建时速度明显更快。我仍然想知道是否还有更有效的方法。
不幸的是,没有更有效的方法,除非您对存储库结构有所了解(例如,特定点之前的所有提交都是由特定用户进行的)。如果您想了解有关每个提交的信息,则必须遍历每个提交。 Git 不提供此信息的缓存,因此需要遍历历史记录。
libgit2 更通用一些,可能无法利用与 Git 本身相同的优化,但整体算法是相同的。
通用算法已尽善尽美:您必须遍历每次提交才能收集所有作者姓名,没有办法绕过它。
Nitpick:您正在为每个提交的作者姓名分配 String
。首先检查名称是否已经在集合中可能会更快,它仅适用于 &str
(!sofar.contains(name)
).
在夜间,您可以将 sofar.insert(name.to_string());
更改为 sofar.get_or_insert_with(name, str::to_string);
。 get_or_insert_with
将只执行一次查找,而不是使用 contains
/insert
对执行两次查找。