Blame


1 7b19e0f1 2017-11-05 stsp /*
2 7b19e0f1 2017-11-05 stsp * Copyright (c) 2017 Stefan Sperling <stsp@openbsd.org>
3 7b19e0f1 2017-11-05 stsp *
4 7b19e0f1 2017-11-05 stsp * Permission to use, copy, modify, and distribute this software for any
5 7b19e0f1 2017-11-05 stsp * purpose with or without fee is hereby granted, provided that the above
6 7b19e0f1 2017-11-05 stsp * copyright notice and this permission notice appear in all copies.
7 7b19e0f1 2017-11-05 stsp *
8 7b19e0f1 2017-11-05 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 7b19e0f1 2017-11-05 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 7b19e0f1 2017-11-05 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 7b19e0f1 2017-11-05 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 7b19e0f1 2017-11-05 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 7b19e0f1 2017-11-05 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 7b19e0f1 2017-11-05 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 7b19e0f1 2017-11-05 stsp */
16 7b19e0f1 2017-11-05 stsp
17 0ffeb3c2 2017-11-26 stsp #include <sys/stat.h>
18 d1cda826 2017-11-06 stsp #include <sys/queue.h>
19 d1cda826 2017-11-06 stsp
20 4027f31a 2017-11-04 stsp #include <stdio.h>
21 4027f31a 2017-11-04 stsp #include <stdlib.h>
22 4027f31a 2017-11-04 stsp #include <sha1.h>
23 68482ea3 2017-11-27 stsp #include <zlib.h>
24 4027f31a 2017-11-04 stsp
25 4027f31a 2017-11-04 stsp #include "got_error.h"
26 11995603 2017-11-05 stsp #include "got_object.h"
27 4027f31a 2017-11-04 stsp #include "got_refs.h"
28 4027f31a 2017-11-04 stsp #include "got_repository.h"
29 68482ea3 2017-11-27 stsp #include "got_sha1.h"
30 4027f31a 2017-11-04 stsp
31 4027f31a 2017-11-04 stsp #define RUN_TEST(expr, name) \
32 4027f31a 2017-11-04 stsp if (!(expr)) { printf("test %s failed", (name)); failure = 1; }
33 4027f31a 2017-11-04 stsp
34 4027f31a 2017-11-04 stsp #define GOT_REPO_PATH "../../../"
35 4027f31a 2017-11-04 stsp
36 bfab4d9a 2017-11-12 stsp static const struct got_error *
37 bfab4d9a 2017-11-12 stsp print_commit_object(struct got_object *, struct got_repository *);
38 1c852fbe 2017-11-12 stsp
39 1c852fbe 2017-11-12 stsp static const struct got_error *
40 bfab4d9a 2017-11-12 stsp print_parent_commits(struct got_commit_object *commit,
41 bfab4d9a 2017-11-12 stsp struct got_repository *repo)
42 bfab4d9a 2017-11-12 stsp {
43 bfab4d9a 2017-11-12 stsp struct got_parent_id *pid;
44 bfab4d9a 2017-11-12 stsp const struct got_error *err;
45 bfab4d9a 2017-11-12 stsp struct got_object *obj;
46 bfab4d9a 2017-11-12 stsp
47 bfab4d9a 2017-11-12 stsp SIMPLEQ_FOREACH(pid, &commit->parent_ids, entry) {
48 bfab4d9a 2017-11-12 stsp err = got_object_open(&obj, repo, &pid->id);
49 bfab4d9a 2017-11-12 stsp if (err != NULL)
50 bfab4d9a 2017-11-12 stsp return err;
51 bfab4d9a 2017-11-12 stsp if (obj->type != GOT_OBJ_TYPE_COMMIT)
52 bfab4d9a 2017-11-12 stsp return got_error(GOT_ERR_OBJ_TYPE);
53 bfab4d9a 2017-11-12 stsp print_commit_object(obj, repo);
54 bfab4d9a 2017-11-12 stsp got_object_close(obj);
55 bfab4d9a 2017-11-12 stsp }
56 bfab4d9a 2017-11-12 stsp
57 bfab4d9a 2017-11-12 stsp return NULL;
58 bfab4d9a 2017-11-12 stsp }
59 bfab4d9a 2017-11-12 stsp
60 bfab4d9a 2017-11-12 stsp static const struct got_error *
61 f715ca7f 2017-11-27 stsp print_tree_object(struct got_object *obj, char *parent,
62 f715ca7f 2017-11-27 stsp struct got_repository *repo)
63 0ffeb3c2 2017-11-26 stsp {
64 0ffeb3c2 2017-11-26 stsp struct got_tree_object *tree;
65 f715ca7f 2017-11-27 stsp struct got_tree_entry *te;
66 0ffeb3c2 2017-11-26 stsp const struct got_error *err;
67 f715ca7f 2017-11-27 stsp char hex[SHA1_DIGEST_STRING_LENGTH];
68 0ffeb3c2 2017-11-26 stsp
69 0ffeb3c2 2017-11-26 stsp err = got_object_tree_open(&tree, repo, obj);
70 0ffeb3c2 2017-11-26 stsp if (err != NULL)
71 0ffeb3c2 2017-11-26 stsp return err;
72 0ffeb3c2 2017-11-26 stsp
73 f715ca7f 2017-11-27 stsp SIMPLEQ_FOREACH(te, &tree->entries, entry) {
74 f715ca7f 2017-11-27 stsp struct got_object *treeobj;
75 f715ca7f 2017-11-27 stsp char *next_parent;
76 f715ca7f 2017-11-27 stsp
77 f715ca7f 2017-11-27 stsp if (!S_ISDIR(te->mode)) {
78 f715ca7f 2017-11-27 stsp printf("%s %s/%s\n",
79 f715ca7f 2017-11-27 stsp got_object_id_str(&te->id, hex, sizeof(hex)),
80 f715ca7f 2017-11-27 stsp parent, te->name);
81 f715ca7f 2017-11-27 stsp continue;
82 f715ca7f 2017-11-27 stsp }
83 f715ca7f 2017-11-27 stsp printf("%s %s/%s\n",
84 f715ca7f 2017-11-27 stsp got_object_id_str(&te->id, hex, sizeof(hex)),
85 f715ca7f 2017-11-27 stsp parent, te->name);
86 f715ca7f 2017-11-27 stsp
87 f715ca7f 2017-11-27 stsp err = got_object_open(&treeobj, repo, &te->id);
88 f715ca7f 2017-11-27 stsp if (err != NULL)
89 f715ca7f 2017-11-27 stsp break;
90 f715ca7f 2017-11-27 stsp
91 f715ca7f 2017-11-27 stsp if (treeobj->type != GOT_OBJ_TYPE_TREE) {
92 f715ca7f 2017-11-27 stsp err = got_error(GOT_ERR_OBJ_TYPE);
93 f715ca7f 2017-11-27 stsp got_object_close(treeobj);
94 f715ca7f 2017-11-27 stsp break;
95 f715ca7f 2017-11-27 stsp }
96 f715ca7f 2017-11-27 stsp
97 f715ca7f 2017-11-27 stsp if (asprintf(&next_parent, "%s/%s", parent, te->name) == -1) {
98 f715ca7f 2017-11-27 stsp err = got_error(GOT_ERR_NO_MEM);
99 f715ca7f 2017-11-27 stsp got_object_close(treeobj);
100 f715ca7f 2017-11-27 stsp break;
101 f715ca7f 2017-11-27 stsp }
102 f715ca7f 2017-11-27 stsp
103 f715ca7f 2017-11-27 stsp err = print_tree_object(treeobj, next_parent, repo);
104 f715ca7f 2017-11-27 stsp free(next_parent);
105 f715ca7f 2017-11-27 stsp if (err) {
106 f715ca7f 2017-11-27 stsp got_object_close(treeobj);
107 f715ca7f 2017-11-27 stsp break;
108 f715ca7f 2017-11-27 stsp }
109 f715ca7f 2017-11-27 stsp
110 f715ca7f 2017-11-27 stsp got_object_close(treeobj);
111 f715ca7f 2017-11-27 stsp }
112 f715ca7f 2017-11-27 stsp
113 0ffeb3c2 2017-11-26 stsp got_object_tree_close(tree);
114 f715ca7f 2017-11-27 stsp return err;
115 0ffeb3c2 2017-11-26 stsp }
116 0ffeb3c2 2017-11-26 stsp
117 0ffeb3c2 2017-11-26 stsp static const struct got_error *
118 1c852fbe 2017-11-12 stsp print_commit_object(struct got_object *obj, struct got_repository *repo)
119 1c852fbe 2017-11-12 stsp {
120 1c852fbe 2017-11-12 stsp struct got_commit_object *commit;
121 1c852fbe 2017-11-12 stsp struct got_parent_id *pid;
122 1c852fbe 2017-11-12 stsp char buf[SHA1_DIGEST_STRING_LENGTH];
123 1c852fbe 2017-11-12 stsp const struct got_error *err;
124 0ffeb3c2 2017-11-26 stsp struct got_object* treeobj;
125 1c852fbe 2017-11-12 stsp
126 1c852fbe 2017-11-12 stsp err = got_object_commit_open(&commit, repo, obj);
127 1c852fbe 2017-11-12 stsp if (err != NULL)
128 1c852fbe 2017-11-12 stsp return err;
129 1c852fbe 2017-11-12 stsp
130 1c852fbe 2017-11-12 stsp printf("tree: %s\n",
131 1c852fbe 2017-11-12 stsp got_object_id_str(&commit->tree_id, buf, sizeof(buf)));
132 1c852fbe 2017-11-12 stsp printf("parent%s: ", (commit->nparents == 1) ? "" : "s");
133 1c852fbe 2017-11-12 stsp SIMPLEQ_FOREACH(pid, &commit->parent_ids, entry) {
134 1c852fbe 2017-11-12 stsp printf("%s\n",
135 1c852fbe 2017-11-12 stsp got_object_id_str(&pid->id, buf, sizeof(buf)));
136 1c852fbe 2017-11-12 stsp }
137 1c852fbe 2017-11-12 stsp printf("author: %s\n", commit->author);
138 1c852fbe 2017-11-12 stsp printf("committer: %s\n", commit->committer);
139 1c852fbe 2017-11-12 stsp printf("log: %s\n", commit->logmsg);
140 bfab4d9a 2017-11-12 stsp
141 0ffeb3c2 2017-11-26 stsp err = got_object_open(&treeobj, repo, &commit->tree_id);
142 0ffeb3c2 2017-11-26 stsp if (err != NULL)
143 0ffeb3c2 2017-11-26 stsp return err;
144 f715ca7f 2017-11-27 stsp if (treeobj->type == GOT_OBJ_TYPE_TREE) {
145 f715ca7f 2017-11-27 stsp print_tree_object(treeobj, "", repo);
146 f715ca7f 2017-11-27 stsp printf("\n");
147 f715ca7f 2017-11-27 stsp }
148 0ffeb3c2 2017-11-26 stsp got_object_close(treeobj);
149 0ffeb3c2 2017-11-26 stsp
150 bfab4d9a 2017-11-12 stsp err = print_parent_commits(commit, repo);
151 1c852fbe 2017-11-12 stsp got_object_commit_close(commit);
152 1c852fbe 2017-11-12 stsp
153 bfab4d9a 2017-11-12 stsp return err;
154 1c852fbe 2017-11-12 stsp }
155 1c852fbe 2017-11-12 stsp
156 4027f31a 2017-11-04 stsp static int
157 bfab4d9a 2017-11-12 stsp repo_read_log(const char *repo_path)
158 11995603 2017-11-05 stsp {
159 11995603 2017-11-05 stsp const struct got_error *err;
160 11995603 2017-11-05 stsp struct got_repository *repo;
161 11995603 2017-11-05 stsp struct got_reference *head_ref;
162 11995603 2017-11-05 stsp struct got_object_id *id;
163 ab9a70b2 2017-11-06 stsp struct got_object *obj;
164 d71d75ad 2017-11-05 stsp char buf[SHA1_DIGEST_STRING_LENGTH];
165 11995603 2017-11-05 stsp int ret;
166 11995603 2017-11-05 stsp
167 11995603 2017-11-05 stsp err = got_repo_open(&repo, repo_path);
168 11995603 2017-11-05 stsp if (err != NULL || repo == NULL)
169 11995603 2017-11-05 stsp return 0;
170 11995603 2017-11-05 stsp err = got_ref_open(&head_ref, repo, GOT_REF_HEAD);
171 11995603 2017-11-05 stsp if (err != NULL || head_ref == NULL)
172 11995603 2017-11-05 stsp return 0;
173 11995603 2017-11-05 stsp err = got_ref_resolve(&id, repo, head_ref);
174 11995603 2017-11-05 stsp if (err != NULL || head_ref == NULL)
175 11995603 2017-11-05 stsp return 0;
176 d71d75ad 2017-11-05 stsp printf("HEAD is at %s\n", got_object_id_str(id, buf, sizeof(buf)));
177 ab9a70b2 2017-11-06 stsp err = got_object_open(&obj, repo, id);
178 ab9a70b2 2017-11-06 stsp if (err != NULL || obj == NULL)
179 ab9a70b2 2017-11-06 stsp return 0;
180 1c852fbe 2017-11-12 stsp if (obj->type == GOT_OBJ_TYPE_COMMIT)
181 1c852fbe 2017-11-12 stsp print_commit_object(obj, repo);
182 ab9a70b2 2017-11-06 stsp got_object_close(obj);
183 11995603 2017-11-05 stsp free(id);
184 11995603 2017-11-05 stsp got_ref_close(head_ref);
185 11995603 2017-11-05 stsp got_repo_close(repo);
186 11995603 2017-11-05 stsp return 1;
187 11995603 2017-11-05 stsp }
188 11995603 2017-11-05 stsp
189 68482ea3 2017-11-27 stsp static int
190 68482ea3 2017-11-27 stsp repo_read_blob(const char *repo_path)
191 68482ea3 2017-11-27 stsp {
192 68482ea3 2017-11-27 stsp const char *blob_sha1 = "141f5fdc96126c1f4195558560a3c915e3d9b4c3";
193 68482ea3 2017-11-27 stsp const struct got_error *err;
194 68482ea3 2017-11-27 stsp struct got_repository *repo;
195 68482ea3 2017-11-27 stsp struct got_object_id id;
196 68482ea3 2017-11-27 stsp struct got_object *obj;
197 68482ea3 2017-11-27 stsp struct got_blob_object *blob;
198 68482ea3 2017-11-27 stsp char hex[SHA1_DIGEST_STRING_LENGTH];
199 68482ea3 2017-11-27 stsp int i;
200 68482ea3 2017-11-27 stsp size_t len;
201 68482ea3 2017-11-27 stsp
202 68482ea3 2017-11-27 stsp if (!got_parse_sha1_digest(id.sha1, blob_sha1))
203 68482ea3 2017-11-27 stsp return 0;
204 68482ea3 2017-11-27 stsp
205 68482ea3 2017-11-27 stsp err = got_repo_open(&repo, repo_path);
206 68482ea3 2017-11-27 stsp if (err != NULL || repo == NULL)
207 68482ea3 2017-11-27 stsp return 0;
208 68482ea3 2017-11-27 stsp err = got_object_open(&obj, repo, &id);
209 68482ea3 2017-11-27 stsp if (err != NULL || obj == NULL)
210 68482ea3 2017-11-27 stsp return 0;
211 68482ea3 2017-11-27 stsp if (obj->type != GOT_OBJ_TYPE_BLOB)
212 68482ea3 2017-11-27 stsp return 0;
213 68482ea3 2017-11-27 stsp
214 68482ea3 2017-11-27 stsp err = got_object_blob_open(&blob, repo, obj, 64);
215 68482ea3 2017-11-27 stsp if (err != NULL)
216 68482ea3 2017-11-27 stsp return 0;
217 68482ea3 2017-11-27 stsp
218 68482ea3 2017-11-27 stsp putchar('\n');
219 68482ea3 2017-11-27 stsp do {
220 68482ea3 2017-11-27 stsp err = got_object_blob_read_block(blob, &len);
221 68482ea3 2017-11-27 stsp if (err)
222 68482ea3 2017-11-27 stsp break;
223 68482ea3 2017-11-27 stsp for (i = 0; i < len; i++)
224 68482ea3 2017-11-27 stsp putchar(blob->zb.outbuf[i]);
225 68482ea3 2017-11-27 stsp } while (len != 0);
226 68482ea3 2017-11-27 stsp putchar('\n');
227 68482ea3 2017-11-27 stsp
228 68482ea3 2017-11-27 stsp got_object_blob_close(blob);
229 68482ea3 2017-11-27 stsp got_object_close(obj);
230 7d283eee 2017-11-29 stsp got_repo_close(repo);
231 7d283eee 2017-11-29 stsp return (err == NULL);
232 7d283eee 2017-11-29 stsp }
233 7d283eee 2017-11-29 stsp
234 7d283eee 2017-11-29 stsp static int
235 7d283eee 2017-11-29 stsp repo_diff_blob(const char *repo_path)
236 7d283eee 2017-11-29 stsp {
237 7d283eee 2017-11-29 stsp const char *blob1_sha1 = "141f5fdc96126c1f4195558560a3c915e3d9b4c3";
238 7d283eee 2017-11-29 stsp const char *blob2_sha1 = "de7eb21b21c7823a753261aadf7cba35c9580fbf";
239 7d283eee 2017-11-29 stsp const struct got_error *err;
240 7d283eee 2017-11-29 stsp struct got_repository *repo;
241 7d283eee 2017-11-29 stsp struct got_object_id id1;
242 7d283eee 2017-11-29 stsp struct got_object_id id2;
243 7d283eee 2017-11-29 stsp struct got_object *obj1;
244 7d283eee 2017-11-29 stsp struct got_object *obj2;
245 7d283eee 2017-11-29 stsp struct got_blob_object *blob1;
246 7d283eee 2017-11-29 stsp struct got_blob_object *blob2;
247 7d283eee 2017-11-29 stsp char hex[SHA1_DIGEST_STRING_LENGTH];
248 7d283eee 2017-11-29 stsp int i;
249 7d283eee 2017-11-29 stsp size_t len;
250 7d283eee 2017-11-29 stsp
251 7d283eee 2017-11-29 stsp if (!got_parse_sha1_digest(id1.sha1, blob1_sha1))
252 7d283eee 2017-11-29 stsp return 0;
253 7d283eee 2017-11-29 stsp if (!got_parse_sha1_digest(id2.sha1, blob2_sha1))
254 7d283eee 2017-11-29 stsp return 0;
255 7d283eee 2017-11-29 stsp
256 7d283eee 2017-11-29 stsp err = got_repo_open(&repo, repo_path);
257 7d283eee 2017-11-29 stsp if (err != NULL || repo == NULL)
258 7d283eee 2017-11-29 stsp return 0;
259 7d283eee 2017-11-29 stsp
260 7d283eee 2017-11-29 stsp err = got_object_open(&obj1, repo, &id1);
261 7d283eee 2017-11-29 stsp if (err != NULL || obj1 == NULL)
262 7d283eee 2017-11-29 stsp return 0;
263 7d283eee 2017-11-29 stsp if (obj1->type != GOT_OBJ_TYPE_BLOB)
264 7d283eee 2017-11-29 stsp return 0;
265 7d283eee 2017-11-29 stsp err = got_object_open(&obj2, repo, &id2);
266 7d283eee 2017-11-29 stsp if (err != NULL || obj2 == NULL)
267 7d283eee 2017-11-29 stsp return 0;
268 7d283eee 2017-11-29 stsp if (obj2->type != GOT_OBJ_TYPE_BLOB)
269 7d283eee 2017-11-29 stsp return 0;
270 7d283eee 2017-11-29 stsp
271 7d283eee 2017-11-29 stsp err = got_object_blob_open(&blob1, repo, obj1, 512);
272 7d283eee 2017-11-29 stsp if (err != NULL)
273 7d283eee 2017-11-29 stsp return 0;
274 7d283eee 2017-11-29 stsp
275 7d283eee 2017-11-29 stsp err = got_object_blob_open(&blob2, repo, obj2, 512);
276 7d283eee 2017-11-29 stsp if (err != NULL)
277 7d283eee 2017-11-29 stsp return 0;
278 7d283eee 2017-11-29 stsp
279 7d283eee 2017-11-29 stsp putchar('\n');
280 7d283eee 2017-11-29 stsp got_diff_blob(blob1, blob2, repo);
281 7d283eee 2017-11-29 stsp putchar('\n');
282 7d283eee 2017-11-29 stsp
283 7d283eee 2017-11-29 stsp got_object_blob_close(blob1);
284 7d283eee 2017-11-29 stsp got_object_blob_close(blob2);
285 7d283eee 2017-11-29 stsp got_object_close(obj1);
286 7d283eee 2017-11-29 stsp got_object_close(obj2);
287 68482ea3 2017-11-27 stsp got_repo_close(repo);
288 68482ea3 2017-11-27 stsp return (err == NULL);
289 68482ea3 2017-11-27 stsp }
290 68482ea3 2017-11-27 stsp
291 4027f31a 2017-11-04 stsp int
292 4027f31a 2017-11-04 stsp main(int argc, const char *argv[])
293 4027f31a 2017-11-04 stsp {
294 4027f31a 2017-11-04 stsp int failure = 0;
295 4027f31a 2017-11-04 stsp const char *repo_path;
296 4027f31a 2017-11-04 stsp
297 4027f31a 2017-11-04 stsp if (argc == 1)
298 4027f31a 2017-11-04 stsp repo_path = GOT_REPO_PATH;
299 4027f31a 2017-11-04 stsp else if (argc == 2)
300 4027f31a 2017-11-04 stsp repo_path = argv[1];
301 4027f31a 2017-11-04 stsp else {
302 4027f31a 2017-11-04 stsp fprintf(stderr, "usage: repository_test [REPO_PATH]\n");
303 4027f31a 2017-11-04 stsp return 1;
304 4027f31a 2017-11-04 stsp }
305 4027f31a 2017-11-04 stsp
306 bfab4d9a 2017-11-12 stsp RUN_TEST(repo_read_log(repo_path), "read_log");
307 68482ea3 2017-11-27 stsp RUN_TEST(repo_read_blob(repo_path), "read_blob");
308 7d283eee 2017-11-29 stsp RUN_TEST(repo_diff_blob(repo_path), "diff_blob");
309 4027f31a 2017-11-04 stsp
310 4027f31a 2017-11-04 stsp return failure ? 1 : 0;
311 4027f31a 2017-11-04 stsp }