Список всех коммитов в ветке с использованием libgit2

Как я могу просмотреть все коммиты ветки, используя libgit2?

У меня уже есть следующий фрагмент кода, но он не компилируется.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <git2.h>

int main(int argc, char *argv[]){
    git_repository *repo;
    git_repository_open(&repo, ".");

    git_odb *obj_db;
    obj_db = git_repository_database(repo);

    git_object commit;
    git_revparse_single(&commit, repo, "HEAD");


    git_repository_free(repo);
    return 0;
}

GCC сообщает:

log.c: In function ‘main’:
log.c:11:9: warning: assignment makes pointer from integer without a cast [enabled by default]
log.c:13:13: error: storage size of ‘commit’ isn’t known

Я скомпилировал с флагом -lgit2. Есть ли возможность быстро просмотреть все коммиты, начиная с корневого коммита?

Обновить Новый код выглядит так:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <git2.h>

int main(int argc, char *argv[]){
    git_repository *repo;
    git_repository_open(&repo, ".");

    git_odb *obj_db;
    obj_db = git_repository_database(repo);

    git_object *commit;
    git_revparse_single(&commit, repo, "HEAD");


    git_repository_free(repo);
    return 0;
}

Я получаю следующие сообщения об ошибках:

log.c:11: undefined reference to `git_repository_database'
log.c:14: undefined reference to `git_revparse_single'

person pentix    schedule 29.07.2013    source источник
comment
Убедитесь, что вы используете последнюю версию библиотеки и просматриваете документацию для этой версии. git_repository_database не существует. Предположительно, вам нужен git_repository_odb, хотя он вам не нужен для журнала. git_revparse_single был представлен в версии 0.18, что говорит о том, что в вашей системе установлена ​​древняя библиотека.   -  person Carlos Martín Nieto    schedule 29.07.2013
comment
Принятый ответ, похоже, не ограничивается одной ветвью, например, master. Возможно, git_revwalk не для этого предназначен?   -  person Fuhrmanator    schedule 10.01.2019


Ответы (3)


У меня уже есть следующий фрагмент кода, но он не компилируется

git_commit — это непрозрачный тип, что означает, что ваш компилятор не знает, что это такое, а только то, что он существует. Таким образом, вы не можете выделить git_commit в стеке. Библиотека выделит его для вас в куче.

Вы должны использовать указатель в своем коде и передавать указатель на него библиотечным функциям, как показано в его документация и примеры к нему ссылки на.

Есть ли возможность быстро просмотреть все коммиты, начиная с корневого коммита?

Эти тесты revwalk, демонстрируя различные стратегии ходьбы, может оказать вам некоторую помощь.

person Carlos Martín Nieto    schedule 29.07.2013
comment
Все равно не компилируется, используя все заголовки из примера. Флаг компилятора -lgit2, не так ли? - person pentix; 29.07.2013
comment
Он по-прежнему не компилируется -› Я почти уверен, что сообщения об ошибках могут быть очень полезны для читателя. - person nulltoken; 29.07.2013
comment
Заголовки не будут проблемой, дело в том, что вы не используете (или не использовали) указатель. Если бы вы обновили свой ответ новым кодом, возможно, мы могли бы помочь. - person Carlos Martín Nieto; 29.07.2013

Наконец, я создал рабочую версию, используя libgit2. Карлос Мартин Ньето указал правильное направление, следующий пример отлично работает с libgit2 0.16. Мне потребовалось некоторое время, чтобы изучить general.c, который я нашел в репозитории libgit2-examples на github. git revwalk был именно тем, что я искал.

Я заметил, что git добавляет новую строку в конце моих сообщений о фиксации, вероятно, потому, что я всегда использую nano для их записи, поэтому я не печатаю последний символ в своем примере кода.

Если кто-то читает это и у него такая же проблема, как у меня, вот рабочий код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <git2.h>

#define REPO ".git"

int main(void){
    git_repository *repo;
    if(git_repository_open(&repo, REPO) != GIT_SUCCESS){
        fprintf(stderr, "Failed opening repository: '%s'\n", REPO);
        return 1;
    }

    // Read HEAD on master
    char head_filepath[512];
    FILE *head_fileptr;
    char head_rev[41];

    strcpy(head_filepath, REPO);

    if(strrchr(REPO, '/') != (REPO+strlen(REPO)))
        strcat(head_filepath, "/refs/heads/master");
    else
        strcat(head_filepath, "refs/heads/master");


    if((head_fileptr = fopen(head_filepath, "r")) == NULL){
        fprintf(stderr, "Error opening '%s'\n", head_filepath);
        return 1;
    }

    if(fread(head_rev, 40, 1, head_fileptr) != 1){
        fprintf(stderr, "Error reading from '%s'\n", head_filepath);
        fclose(head_fileptr);
        return 1;
    }   

    fclose(head_fileptr);


    git_oid oid;
    git_revwalk *walker;
    git_commit *commit;

    if(git_oid_fromstr(&oid, head_rev) != GIT_SUCCESS){
        fprintf(stderr, "Invalid git object: '%s'\n", head_rev);
        return 1;
    }

    git_revwalk_new(&walker, repo);
    git_revwalk_sorting(walker, GIT_SORT_TOPOLOGICAL);
    git_revwalk_push(walker, &oid);

    const char *commit_message;
    const git_signature *commit_author;

    while(git_revwalk_next(&oid, walker) == GIT_SUCCESS) {
        if(git_commit_lookup(&commit, repo, &oid)){
            fprintf(stderr, "Failed to lookup the next object\n");
            return 1;
        }

        commit_message  = git_commit_message(commit);
        commit_author = git_commit_committer(commit);

        // Don't print the \n in the commit_message 
        printf("'%.*s' by %s <%s>\n", strlen(commit_message)-1, commit_message, commit_author->name, commit_author->email);

        git_commit_free(commit);
    }

    git_revwalk_free(walker);

    return 0;

}

Спасибо!

person pentix    schedule 31.07.2013
comment
Привет, я только что нашел это объявление и хочу сказать большое спасибо, так как у меня была точно такая же проблема. Спасибо, что поделился, добрый человек! - person There is nothing we can do; 27.04.2016
comment
Приятно слышать, что он все еще работает. После исправления этой проблемы я попытался реализовать свои вещи на другом языке, чем C. libgit2 все равно внес некоторые изменения в API, и вам действительно нужно было знать об этом, поскольку они изменили некоторые фундаментальные вещи. Также я думаю, что в то время библиотека была не очень дружелюбна к разработчикам... Рад, что смог вам помочь! - person pentix; 27.04.2016
comment
Привет еще раз, надеюсь, у тебя все хорошо. Я заметил, что ходок будет идти от ветки, скажем, A обратно к мастеру, т.е. будет перечислять в одном цикле коммиты из ветки A и мастера. Есть ли способ перечислить коммиты только из ветки A? Спасибо. - person There is nothing we can do; 05.05.2016
comment
Как говорит @Thereisnothingwecando, этот ответ не отвечает на вопрос, как он был написан. То есть он не ограничивается коммитами только в одной ветке. - person Fuhrmanator; 10.01.2019
comment
Ты не забыл позвонить git_repository_free? - person rodrigocfd; 12.06.2019

Добавление к ответу Pentax выше. Если вы просто хотите «пройтись» по голове, вместо того, чтобы выполнять всю эту работу, чтобы получить старую голову для инициализации ходока с помощью:

 git_revwalk_push(walker, &oid);

Можно было бы просто использовать:

 git_revwalk_push_head(walker);
person SteveEng    schedule 02.01.2017