7

如何使用 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;
}

海湾合作委员会报告:

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'
4

3 回答 3

4

最后,我使用 libgit2 创建了一个工作版本。Carlos Martín Nieto 指出了正确的方向,以下示例在 libgit2 0.16上效果很好。我花了一些时间来研究我在github上的 libgit2-examples 存储库中找到的general.cgit 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;

}

谢谢!

于 2013-07-31T18:42:20.037 回答
3

我已经有以下代码,但无法编译

Agit_commit是一种不透明类型,这意味着您的编译器不知道它是什么,只知道它存在。因此,您不能git_commit在堆栈上分配 a 。该库将为您在堆上分配它。

您必须在代码中使用指针并将指向该指针的指针传递给库的函数,如您在其文档和链接到的示例中所见。

从根提交开始,是否可以快速遍历所有提交?

那些revwalk 测试,展示了不同的步行策略,可能会为您提供一些帮助。

于 2013-07-29T03:20:58.107 回答
1

添加到上面宾得的答案。如果您只是想“走”头部,而不是做所有的工作来让旧的头部初始化步行器:

 git_revwalk_push(walker, &oid);

可以简单地使用:

 git_revwalk_push_head(walker);
于 2017-01-02T12:35:43.177 回答