получить список авторов в репозитории git эффективно с помощью libgit2 - PullRequest
1 голос
/ 29 февраля 2020

Мне нужно получить список авторов для репозитория git, как git shortlog -s делает в командной строке.

То, что я делаю в настоящее время и работает, это сделать revwalk ( просматривая все ревизии) и собирая список авторов для всех коммитов по одному, но это довольно медленно, особенно по сравнению с командой git командной строки.

Я использую ржавчину, но Я ожидаю, что решение похоже на C или другой язык привязки к libgit2.

Это мой текущий, работающий, но медленный код:

        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 Хорошо, если в режиме релиза с ржавчиной это заметно быстрее. Я до сих пор не знаю, есть ли более эффективный способ.

Ответы [ 2 ]

2 голосов
/ 29 февраля 2020

Общий алгоритм хорош: он должен пройти каждый коммит, чтобы собрать все имена авторов, нет никакого способа обойти его.

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.

2 голосов
/ 29 февраля 2020

К сожалению, не существует более эффективного способа, если только вы не знаете что-то о структуре хранилища (например, когда все коммиты перед определенным пунктом сделаны определенным пользователем). Если вы хотите знать что-то о каждом коммите, вы должны обязательно пройти через каждый коммит. Git не предоставляет кеш для этой информации, поэтому требуется просмотр истории.

libgit2, будучи немного более обобщенным c, может не иметь возможности использовать те же оптимизации, что и Git само по себе, но в целом алгоритм тот же.

...