Listing all commits in a branch using libgit2
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!
I have already the following bit of code, but it doesn't compile
A git_commit
is an opaque type, which means that your compiler doesn't know what it is, only that it exists. Thus you cannot allocate a git_commit
on the stack. The library will allocate it on the heap for you.
You must use a pointer in your code and pass a pointer to that to the library's functions, as you can see in its documentation and the examples it links to.
Is there a fast possibility to walk through all the commits, beginning from the root-commit?
Those revwalk tests, demonstrating different walking strategies, may provide you with some help.