reference.c (2273B)
1 #include "git/reference.h" 2 3 #include <assert.h> 4 #include <err.h> 5 #include <git2/object.h> 6 #include <git2/oid.h> 7 #include <git2/refs.h> 8 #include <git2/types.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <time.h> 12 13 #include "git/internal.h" 14 15 GitReference* gitreference_create(git_repository* repo, 16 git_reference* git_ref) { 17 assert(repo != NULL); 18 assert(git_ref != NULL); 19 // Resolve git_ref to a direct reference. 20 if (git_reference_type(git_ref) == GIT_REFERENCE_SYMBOLIC) { 21 git_reference* direct_ref = NULL; 22 int error = git_reference_resolve(&direct_ref, git_ref); 23 if (error == GIT_ENOTFOUND) { 24 git_reference_free(git_ref); 25 return NULL; 26 } else if (error < 0) { 27 errx(1, "git_reference_resolve"); 28 } 29 git_reference_free(git_ref); 30 git_ref = direct_ref; 31 } 32 if (!git_ref || !git_reference_target(git_ref)) { 33 git_reference_free(git_ref); 34 return NULL; 35 } 36 37 GitReference* ref = ecalloc(1, sizeof(GitReference)); 38 39 // Set type. 40 if (git_reference_is_branch(git_ref)) { 41 ref->type = kReftypeBranch; 42 } else if (git_reference_is_tag(git_ref)) { 43 ref->type = kReftypeTag; 44 } else { 45 errx(1, "not a branch or tag"); 46 } 47 48 // Set shorthand. 49 const char* shorthand = git_reference_shorthand(git_ref); 50 ref->shorthand = shorthand ? estrdup(shorthand) : NULL; 51 52 // Create a GitCommit from the object. 53 git_object* obj = NULL; 54 if (git_reference_peel(&obj, git_ref, GIT_OBJECT_ANY) != 0) { 55 errx(1, "git_reference_peel"); 56 } 57 const git_oid* id = git_object_id(obj); 58 ref->commit = gitcommit_create(id, repo); 59 git_object_free(obj); 60 61 git_reference_free(git_ref); 62 return ref; 63 } 64 65 void gitreference_free(GitReference* ref) { 66 if (!ref) { 67 return; 68 } 69 free(ref->shorthand); 70 gitcommit_free(ref->commit); 71 free(ref); 72 } 73 74 int gitreference_compare(const void* a, const void* b) { 75 GitReference* r1 = *(GitReference**)a; 76 GitReference* r2 = *(GitReference**)b; 77 int r = (r1->type == kReftypeTag) - (r2->type == kReftypeTag); 78 if (r != 0) { 79 return r; 80 } 81 82 time_t t1 = r1->commit->author_time; 83 time_t t2 = r2->commit->author_time; 84 if (t1 > t2) { 85 return -1; 86 } 87 if (t1 < t2) { 88 return 1; 89 } 90 return strcmp(r1->shorthand, r2->shorthand); 91 }