Finally, I created a working version using libgit2. Carlos Martín Nieto pointed in the right direction, the following example works great with libgit2 0.16. It took me some time to study the general.c I found in the libgit2-examples repository on github. git revwalk was exactly what I was looking for.
I noted that git adds an newline at the end of my commit messages, probably because I'm always using nano
to write them, so I don't printf out the last character in my example code.
If anyone reads this and has the same problem as I had, here's the working code:
#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;
}
Thanks!