]> git.proxmox.com Git - libgit2.git/blob - examples/common.c
Add ci
[libgit2.git] / examples / common.c
1 /*
2 * Utilities library for libgit2 examples
3 *
4 * Written by the libgit2 contributors
5 *
6 * To the extent possible under law, the author(s) have dedicated all copyright
7 * and related and neighboring rights to this software to the public domain
8 * worldwide. This software is distributed without any warranty.
9 *
10 * You should have received a copy of the CC0 Public Domain Dedication along
11 * with this software. If not, see
12 * <http://creativecommons.org/publicdomain/zero/1.0/>.
13 */
14
15
16 #include "common.h"
17
18 #ifndef _WIN32
19 # include <unistd.h>
20 #endif
21 #include <errno.h>
22
23 void check_lg2(int error, const char *message, const char *extra)
24 {
25 const git_error *lg2err;
26 const char *lg2msg = "", *lg2spacer = "";
27
28 if (!error)
29 return;
30
31 if ((lg2err = git_error_last()) != NULL && lg2err->message != NULL) {
32 lg2msg = lg2err->message;
33 lg2spacer = " - ";
34 }
35
36 if (extra)
37 fprintf(stderr, "%s '%s' [%d]%s%s\n",
38 message, extra, error, lg2spacer, lg2msg);
39 else
40 fprintf(stderr, "%s [%d]%s%s\n",
41 message, error, lg2spacer, lg2msg);
42
43 exit(1);
44 }
45
46 void fatal(const char *message, const char *extra)
47 {
48 if (extra)
49 fprintf(stderr, "%s %s\n", message, extra);
50 else
51 fprintf(stderr, "%s\n", message);
52
53 exit(1);
54 }
55
56 int diff_output(
57 const git_diff_delta *d,
58 const git_diff_hunk *h,
59 const git_diff_line *l,
60 void *p)
61 {
62 FILE *fp = (FILE*)p;
63
64 (void)d; (void)h;
65
66 if (!fp)
67 fp = stdout;
68
69 if (l->origin == GIT_DIFF_LINE_CONTEXT ||
70 l->origin == GIT_DIFF_LINE_ADDITION ||
71 l->origin == GIT_DIFF_LINE_DELETION)
72 fputc(l->origin, fp);
73
74 fwrite(l->content, 1, l->content_len, fp);
75
76 return 0;
77 }
78
79 void treeish_to_tree(
80 git_tree **out, git_repository *repo, const char *treeish)
81 {
82 git_object *obj = NULL;
83
84 check_lg2(
85 git_revparse_single(&obj, repo, treeish),
86 "looking up object", treeish);
87
88 check_lg2(
89 git_object_peel((git_object **)out, obj, GIT_OBJECT_TREE),
90 "resolving object to tree", treeish);
91
92 git_object_free(obj);
93 }
94
95 void *xrealloc(void *oldp, size_t newsz)
96 {
97 void *p = realloc(oldp, newsz);
98 if (p == NULL) {
99 fprintf(stderr, "Cannot allocate memory, exiting.\n");
100 exit(1);
101 }
102 return p;
103 }
104
105 int resolve_refish(git_annotated_commit **commit, git_repository *repo, const char *refish)
106 {
107 git_reference *ref;
108 git_object *obj;
109 int err = 0;
110
111 assert(commit != NULL);
112
113 err = git_reference_dwim(&ref, repo, refish);
114 if (err == GIT_OK) {
115 git_annotated_commit_from_ref(commit, repo, ref);
116 git_reference_free(ref);
117 return 0;
118 }
119
120 err = git_revparse_single(&obj, repo, refish);
121 if (err == GIT_OK) {
122 err = git_annotated_commit_lookup(commit, repo, git_object_id(obj));
123 git_object_free(obj);
124 }
125
126 return err;
127 }
128
129 static int readline(char **out)
130 {
131 int c, error = 0, length = 0, allocated = 0;
132 char *line = NULL;
133
134 errno = 0;
135
136 while ((c = getchar()) != EOF) {
137 if (length == allocated) {
138 allocated += 16;
139
140 if ((line = realloc(line, allocated)) == NULL) {
141 error = -1;
142 goto error;
143 }
144 }
145
146 if (c == '\n')
147 break;
148
149 line[length++] = c;
150 }
151
152 if (errno != 0) {
153 error = -1;
154 goto error;
155 }
156
157 line[length] = '\0';
158 *out = line;
159 line = NULL;
160 error = length;
161 error:
162 free(line);
163 return error;
164 }
165
166 static int ask(char **out, const char *prompt, char optional)
167 {
168 printf("%s ", prompt);
169 fflush(stdout);
170
171 if (!readline(out) && !optional) {
172 fprintf(stderr, "Could not read response: %s", strerror(errno));
173 return -1;
174 }
175
176 return 0;
177 }
178
179 int cred_acquire_cb(git_credential **out,
180 const char *url,
181 const char *username_from_url,
182 unsigned int allowed_types,
183 void *payload)
184 {
185 char *username = NULL, *password = NULL, *privkey = NULL, *pubkey = NULL;
186 int error = 1;
187
188 UNUSED(url);
189 UNUSED(payload);
190
191 if (username_from_url) {
192 if ((username = strdup(username_from_url)) == NULL)
193 goto out;
194 } else if ((error = ask(&username, "Username:", 0)) < 0) {
195 goto out;
196 }
197
198 if (allowed_types & GIT_CREDENTIAL_SSH_KEY) {
199 int n;
200
201 if ((error = ask(&privkey, "SSH Key:", 0)) < 0 ||
202 (error = ask(&password, "Password:", 1)) < 0)
203 goto out;
204
205 if ((n = snprintf(NULL, 0, "%s.pub", privkey)) < 0 ||
206 (pubkey = malloc(n + 1)) == NULL ||
207 (n = snprintf(pubkey, n + 1, "%s.pub", privkey)) < 0)
208 goto out;
209
210 error = git_credential_ssh_key_new(out, username, pubkey, privkey, password);
211 } else if (allowed_types & GIT_CREDENTIAL_USERPASS_PLAINTEXT) {
212 if ((error = ask(&password, "Password:", 1)) < 0)
213 goto out;
214
215 error = git_credential_userpass_plaintext_new(out, username, password);
216 } else if (allowed_types & GIT_CREDENTIAL_USERNAME) {
217 error = git_credential_username_new(out, username);
218 }
219
220 out:
221 free(username);
222 free(password);
223 free(privkey);
224 free(pubkey);
225 return error;
226 }
227
228 char *read_file(const char *path)
229 {
230 ssize_t total = 0;
231 char *buf = NULL;
232 struct stat st;
233 int fd = -1;
234
235 if ((fd = open(path, O_RDONLY)) < 0 || fstat(fd, &st) < 0)
236 goto out;
237
238 if ((buf = malloc(st.st_size + 1)) == NULL)
239 goto out;
240
241 while (total < st.st_size) {
242 ssize_t bytes = read(fd, buf + total, st.st_size - total);
243 if (bytes <= 0) {
244 if (errno == EAGAIN || errno == EINTR)
245 continue;
246 free(buf);
247 buf = NULL;
248 goto out;
249 }
250 total += bytes;
251 }
252
253 buf[total] = '\0';
254
255 out:
256 if (fd >= 0)
257 close(fd);
258 return buf;
259 }
260