reference.c (2317B)
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 git_reference_peel(&obj, git_ref, GIT_OBJECT_ANY); 55 const git_oid* id = git_object_id(obj); 56 git_object_free(obj); 57 if (!id) { 58 errx(1, "git_object_id"); 59 } 60 ref->commit = gitcommit_create(id, repo); 61 62 git_reference_free(git_ref); 63 return ref; 64 } 65 66 void gitreference_free(GitReference* ref) { 67 if (!ref) { 68 return; 69 } 70 free(ref->shorthand); 71 ref->shorthand = NULL; 72 gitcommit_free(ref->commit); 73 ref->commit = NULL; 74 free(ref); 75 } 76 77 int gitreference_compare(const void* a, const void* b) { 78 GitReference* r1 = *(GitReference**)a; 79 GitReference* r2 = *(GitReference**)b; 80 int r = (r1->type == kReftypeTag) - (r2->type == kReftypeTag); 81 if (r != 0) { 82 return r; 83 } 84 85 time_t t1 = r1->commit->author_time; 86 time_t t2 = r2->commit->author_time; 87 if (t1 > t2) { 88 return -1; 89 } 90 if (t1 < t2) { 91 return 1; 92 } 93 return strcmp(r1->shorthand, r2->shorthand); 94 }