GCC Code Coverage Report


src/
File: src/examples/signature_extract.c
Date: 2026-03-31 17:48:22
Lines:
0/62
0.0%
Functions:
0/4
0.0%
Branches:
0/48
0.0%

Line Branch Exec Source
1 #include <git2.h>
2 #include <glib.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include "examples/signature_extract.h"
7
8 #define GET_CWD getcwd
9
10 /**
11 * Private helper method for error message output
12 *
13 * @param error Error code
14 * @param message Custom message for error
15 */
16
17 static void log_git_error(int error, const char* message) {
18 if (error < 0) {
19 const git_error* e = giterr_last();
20 g_printerr("Error %d: %s - %s\n", error, message,
21 e ? e->message : "Unknown");
22 }
23 }
24
25 /**
26 * Gets the Git Repository Path for the current working directory.
27 *
28 * @return The cwd git repository path. Returns NULL on failure.
29 */
30 char* find_git_repo_path(void) {
31 git_buf repo_path_buf = {0};
32 char* repo_path = NULL;
33 char cwd[1024];
34
35 if (!GET_CWD(cwd, sizeof(cwd))) {
36 perror("Could not get current working directory");
37 return NULL;
38 }
39
40 int error = git_repository_discover(&repo_path_buf, cwd, 1, NULL);
41 if (error < 0) {
42 log_git_error(error, "Failed to discover repository");
43 git_buf_dispose(&repo_path_buf);
44 return NULL;
45 }
46
47 repo_path = malloc(repo_path_buf.size + 1);
48 if (repo_path) {
49 g_strlcpy(repo_path, repo_path_buf.ptr, repo_path_buf.size + 1);
50 repo_path[repo_path_buf.size] = '\0';
51 }
52
53 git_buf_dispose(&repo_path_buf);
54 return repo_path;
55 }
56
57 /**
58 * Gets the SHA string of the commit that HEAD points to. AKA the
59 * most recent commit.
60 *
61 * @param repo A previously opened git_repository object.
62 * @return A dynamically allocated 40-character string with the SHA,
63 * which the caller must free. Returns NULL on failure.
64 */
65 char* get_head_commit_sha(git_repository* repo) {
66 if (!repo) {
67 g_printerr("Error: get_head_commit_sha called with NULL repository.\n");
68 return NULL;
69 }
70
71 git_oid oid;
72 char* sha_string = NULL;
73
74 int error = git_reference_name_to_id(&oid, repo, "HEAD");
75 if (error < 0) {
76 log_git_error(error, "Failed to resolve HEAD to a commit");
77 return NULL;
78 }
79
80 sha_string = malloc(GIT_OID_HEXSZ + 1);
81 if (sha_string) {
82 git_oid_tostr(sha_string, GIT_OID_HEXSZ + 1, &oid);
83 }
84
85 return sha_string;
86 }
87
88 /**
89 * Gets the GPG Signature for the git commit given.
90 *
91 * @param repo_path A path to the git repository for the commit
92 * @param commit_sha The sha for the commit we want to check
93 * @return A GPG Signature. Returns NULL on failure.
94 */
95 // NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
96 char* signature_extract(const char* repo_path, const char* commit_sha) {
97 git_repository* repo = NULL;
98 git_oid oid;
99 git_buf signature_buf = {0};
100 git_buf signed_data_buf = {0};
101 char* signature_string = NULL;
102
103 // Gets the Git Repository Object (repo)
104 int error = git_repository_open(&repo, repo_path);
105 if (error < 0) {
106 log_git_error(error, "Failed to open repository");
107 return NULL;
108 }
109
110 // Gets the Git Object ID
111 error = git_oid_fromstr(&oid, commit_sha); // Git Object ID
112 if (error < 0) {
113 log_git_error(error, "Failed to parse commit SHA");
114 git_repository_free(repo);
115 return NULL;
116 }
117
118 // Extracts GPG Signature
119 error = git_commit_extract_signature(&signature_buf, &signed_data_buf, repo,
120 &oid, NULL);
121 if (error == GIT_ENOTFOUND) {
122 g_printerr("No GPG signature found on commit %s\n", commit_sha);
123
124 } else if (error < 0) {
125 log_git_error(error, "Failed to extract signature");
126 } else {
127 signature_string = malloc(signature_buf.size + 1);
128 if (signature_string) {
129 g_strlcpy(signature_string, signature_buf.ptr,
130 signature_buf.size + 1);
131 }
132 }
133
134 git_buf_dispose(&signature_buf);
135 git_buf_dispose(&signed_data_buf);
136 git_repository_free(repo);
137
138 return signature_string;
139 }
140