commit.c (3990B)
1 #include "git/commit.h" 2 3 #include <assert.h> 4 #include <err.h> 5 #include <git2/commit.h> 6 #include <git2/diff.h> 7 #include <git2/oid.h> 8 #include <git2/patch.h> 9 #include <git2/tree.h> 10 #include <git2/types.h> 11 #include <stdlib.h> 12 13 #include "git/internal.h" 14 15 GitCommit* gitcommit_create(const git_oid* oid, git_repository* repo) { 16 assert(oid != NULL); 17 assert(repo != NULL); 18 GitCommit* commit = ecalloc(1, sizeof(GitCommit)); 19 git_commit* gcommit = NULL; 20 if (git_commit_lookup(&gcommit, repo, oid)) { 21 errx(1, "git_commit_lookup"); 22 } 23 24 // Get OID, parent OID. 25 git_oid_tostr(commit->oid, sizeof(commit->oid), git_commit_id(gcommit)); 26 if (git_commit_parentcount(gcommit) > 0) { 27 git_oid_tostr(commit->parentoid, sizeof(commit->parentoid), 28 git_commit_parent_id(gcommit, 0)); 29 } else { 30 commit->parentoid[0] = '\0'; 31 } 32 33 // Set commit summary, message. 34 const char* summary = git_commit_summary(gcommit); 35 commit->summary = summary ? estrdup(summary) : NULL; 36 const char* message = git_commit_message(gcommit); 37 commit->message = message ? estrdup(message) : NULL; 38 39 // Get commit time, tz offset. 40 commit->commit_time = git_commit_time(gcommit); 41 commit->commit_timezone_offset = git_commit_time_offset(gcommit); 42 43 // Get author info. 44 const git_signature* author = git_commit_author(gcommit); 45 commit->author_name = author->name ? estrdup(author->name) : NULL; 46 commit->author_email = author->email ? estrdup(author->email) : NULL; 47 commit->author_time = author->when.time; 48 commit->author_timezone_offset = author->when.offset; 49 50 // Look up commit tree. 51 git_tree* commit_tree = NULL; 52 if (git_tree_lookup(&commit_tree, repo, git_commit_tree_id(gcommit))) { 53 errx(1, "git_tree_lookup"); 54 } 55 56 // Look up parent tree, if there is a parent commit. 57 git_commit* parent = NULL; 58 git_tree* parent_tree = NULL; 59 if (!git_commit_parent(&parent, gcommit, 0)) { 60 if (git_tree_lookup(&parent_tree, repo, git_commit_tree_id(parent))) { 61 errx(1, "git_tree_lookup"); 62 } 63 git_commit_free(parent); 64 } 65 66 // Compute the diff. 67 git_diff* diff = NULL; 68 git_diff_options opts; 69 git_diff_options_init(&opts, GIT_DIFF_OPTIONS_VERSION); 70 opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH | GIT_DIFF_IGNORE_SUBMODULES | 71 GIT_DIFF_INCLUDE_TYPECHANGE; 72 if (git_diff_tree_to_tree(&diff, repo, parent_tree, commit_tree, &opts)) { 73 errx(1, "git_diff_tree_to_tree"); 74 } 75 git_tree_free(commit_tree); 76 git_tree_free(parent_tree); 77 78 git_diff_find_options fopts; 79 if (git_diff_find_options_init(&fopts, GIT_DIFF_FIND_OPTIONS_VERSION)) { 80 errx(1, "git_diff_find_init_options"); 81 } 82 83 /* find renames and copies, exact matches (no heuristic) for renames. */ 84 fopts.flags |= GIT_DIFF_FIND_RENAMES | GIT_DIFF_FIND_COPIES | 85 GIT_DIFF_FIND_EXACT_MATCH_ONLY; 86 if (git_diff_find_similar(diff, &fopts)) { 87 errx(1, "git_diff_find_similar"); 88 } 89 90 // Add deltas. 91 commit->addcount = 0; 92 commit->delcount = 0; 93 size_t deltas_len = git_diff_num_deltas(diff); 94 commit->deltas = ecalloc(deltas_len, sizeof(GitDelta*)); 95 size_t deltas_out_count = 0; 96 for (size_t i = 0; i < deltas_len; i++) { 97 git_patch* patch = NULL; 98 if (git_patch_from_diff(&patch, diff, i)) { 99 continue; 100 } 101 102 // Hand ownership of patch to delta. 103 GitDelta* delta = gitdelta_create(patch); 104 if (delta) { 105 commit->deltas[deltas_out_count++] = delta; 106 commit->addcount += delta->addcount; 107 commit->delcount += delta->delcount; 108 } 109 } 110 commit->deltas_len = deltas_out_count; 111 commit->filecount = deltas_len; 112 113 git_diff_free(diff); 114 git_commit_free(gcommit); 115 return commit; 116 } 117 118 void gitcommit_free(GitCommit* commit) { 119 if (!commit) { 120 return; 121 } 122 free(commit->summary); 123 free(commit->message); 124 free(commit->author_name); 125 free(commit->author_email); 126 for (size_t i = 0; i < commit->deltas_len; i++) { 127 gitdelta_free(commit->deltas[i]); 128 } 129 free(commit->deltas); 130 free(commit); 131 }