]>
Commit | Line | Data |
---|---|---|
66902d47 | 1 | /* |
6cb831bd | 2 | * Utilities library for libgit2 examples |
66902d47 | 3 | * |
6cb831bd BS |
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/>. | |
66902d47 RB |
13 | */ |
14 | ||
ac3d33df | 15 | |
66902d47 RB |
16 | #include "common.h" |
17 | ||
0c9c969a UG |
18 | #ifndef _WIN32 |
19 | # include <unistd.h> | |
20 | #endif | |
21 | #include <errno.h> | |
22 | ||
66902d47 RB |
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 | ||
ac3d33df | 31 | if ((lg2err = git_error_last()) != NULL && lg2err->message != NULL) { |
66902d47 RB |
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 | ||
66902d47 RB |
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 | { | |
300f4412 | 62 | FILE *fp = (FILE*)p; |
66902d47 RB |
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( | |
ac3d33df | 89 | git_object_peel((git_object **)out, obj, GIT_OBJECT_TREE), |
66902d47 RB |
90 | "resolving object to tree", treeish); |
91 | ||
92 | git_object_free(obj); | |
93 | } | |
94 | ||
eae0bfdc PP |
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 | ||
ac3d33df JK |
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 | } | |
0c9c969a UG |
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 |