使用libgit2列出分支中的所有提交

时间:2013-07-29 00:18:08

标签: c git 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;
}
海湾合作委员会报告:

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标志编译。从root-commit开始,是否有可能快速完成所有提交?

更新 新代码如下所示:

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

3 个答案:

答案 0 :(得分:3)

  

我已经有了以下一些代码,但它没有编译

git_commit是一种opaque类型,这意味着您的编译器不知道它是什么,只知道它存在。因此,您无法在堆栈上分配git_commit。库会为你在堆上分配它。

您必须在代码中使用指针并将指针传递给库的函数,如its documentation及其示例links to中所示。

  

从root-commit开始,是否有可能快速完成所有提交?

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

答案 1 :(得分:3)

最后,我使用libgit2创建了一个工作版本。 CarlosMartínNieto指出了正确的方向,以下示例适用于libgit2 0.16 。我花了一些时间研究general.cgithub上的libgit2-examples存储库中找到的{{3}}。 git revwalk 正是我所寻找的。

我注意到git在我的提交消息末尾添加了一个换行符,可能是因为我总是使用nano来编写它们,所以我不打印出示例代码中的最后一个字符。 / p>

如果有人读到这个并且遇到了和我一样的问题,那么这就是工作代码:

#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;

}

谢谢!

答案 2 :(得分:0)

在上面添加Pentax的答案。如果你只是想走路&#39;头部,而不是做所有的工作,让老头到头来初始化助行器:

 git_revwalk_push(walker, &oid);

可以简单地使用:

 git_revwalk_push_head(walker);