Blame


1 d71d75ad 2017-11-05 stsp /*
2 a1fd68d8 2018-01-12 stsp * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org>
3 d71d75ad 2017-11-05 stsp *
4 d71d75ad 2017-11-05 stsp * Permission to use, copy, modify, and distribute this software for any
5 d71d75ad 2017-11-05 stsp * purpose with or without fee is hereby granted, provided that the above
6 d71d75ad 2017-11-05 stsp * copyright notice and this permission notice appear in all copies.
7 d71d75ad 2017-11-05 stsp *
8 d71d75ad 2017-11-05 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 d71d75ad 2017-11-05 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 d71d75ad 2017-11-05 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 d71d75ad 2017-11-05 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 d71d75ad 2017-11-05 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 d71d75ad 2017-11-05 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 d71d75ad 2017-11-05 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 d71d75ad 2017-11-05 stsp */
16 d71d75ad 2017-11-05 stsp
17 2178c42e 2018-04-22 stsp #include <sys/types.h>
18 0ffeb3c2 2017-11-26 stsp #include <sys/stat.h>
19 d1cda826 2017-11-06 stsp #include <sys/queue.h>
20 2178c42e 2018-04-22 stsp #include <sys/uio.h>
21 2178c42e 2018-04-22 stsp #include <sys/socket.h>
22 2178c42e 2018-04-22 stsp #include <sys/wait.h>
23 876c234b 2018-09-10 stsp #include <sys/syslimits.h>
24 d1cda826 2017-11-06 stsp
25 a1fd68d8 2018-01-12 stsp #include <errno.h>
26 2178c42e 2018-04-22 stsp #include <fcntl.h>
27 d71d75ad 2017-11-05 stsp #include <stdio.h>
28 ab9a70b2 2017-11-06 stsp #include <stdlib.h>
29 ab9a70b2 2017-11-06 stsp #include <string.h>
30 2178c42e 2018-04-22 stsp #include <stdint.h>
31 d71d75ad 2017-11-05 stsp #include <sha1.h>
32 ab9a70b2 2017-11-06 stsp #include <zlib.h>
33 ab9a70b2 2017-11-06 stsp #include <ctype.h>
34 ab9a70b2 2017-11-06 stsp #include <limits.h>
35 2178c42e 2018-04-22 stsp #include <imsg.h>
36 788c352e 2018-06-16 stsp #include <time.h>
37 d71d75ad 2017-11-05 stsp
38 ab9a70b2 2017-11-06 stsp #include "got_error.h"
39 d71d75ad 2017-11-05 stsp #include "got_object.h"
40 ab9a70b2 2017-11-06 stsp #include "got_repository.h"
41 511a516b 2018-05-19 stsp #include "got_opentemp.h"
42 d71d75ad 2017-11-05 stsp
43 718b3ab0 2018-03-17 stsp #include "got_lib_sha1.h"
44 718b3ab0 2018-03-17 stsp #include "got_lib_delta.h"
45 718b3ab0 2018-03-17 stsp #include "got_lib_pack.h"
46 2178c42e 2018-04-22 stsp #include "got_lib_path.h"
47 63581804 2018-07-09 stsp #include "got_lib_inflate.h"
48 718b3ab0 2018-03-17 stsp #include "got_lib_object.h"
49 2178c42e 2018-04-22 stsp #include "got_lib_privsep.h"
50 6bef87be 2018-09-11 stsp #include "got_lib_object_idcache.h"
51 6bef87be 2018-09-11 stsp #include "got_lib_object_cache.h"
52 ad242220 2018-09-08 stsp #include "got_lib_object_parse.h"
53 7bb0daa1 2018-06-21 stsp #include "got_lib_repository.h"
54 1411938b 2018-02-12 stsp
55 ab9a70b2 2017-11-06 stsp #ifndef MIN
56 ab9a70b2 2017-11-06 stsp #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
57 ab9a70b2 2017-11-06 stsp #endif
58 ef0981d5 2018-02-12 stsp
59 a1fd68d8 2018-01-12 stsp int
60 a1fd68d8 2018-01-12 stsp got_object_id_cmp(struct got_object_id *id1, struct got_object_id *id2)
61 a1fd68d8 2018-01-12 stsp {
62 a1fd68d8 2018-01-12 stsp return memcmp(id1->sha1, id2->sha1, SHA1_DIGEST_LENGTH);
63 8bf5b3c9 2018-03-17 stsp }
64 8bf5b3c9 2018-03-17 stsp
65 8bf5b3c9 2018-03-17 stsp struct got_object_id *
66 8bf5b3c9 2018-03-17 stsp got_object_id_dup(struct got_object_id *id1)
67 8bf5b3c9 2018-03-17 stsp {
68 8bf5b3c9 2018-03-17 stsp struct got_object_id *id2;
69 8bf5b3c9 2018-03-17 stsp
70 8bf5b3c9 2018-03-17 stsp id2 = malloc(sizeof(*id2));
71 8bf5b3c9 2018-03-17 stsp if (id2 == NULL)
72 8bf5b3c9 2018-03-17 stsp return NULL;
73 8bf5b3c9 2018-03-17 stsp memcpy(id2, id1, sizeof(*id2));
74 8bf5b3c9 2018-03-17 stsp return id2;
75 3235492e 2018-04-01 stsp }
76 3235492e 2018-04-01 stsp
77 3235492e 2018-04-01 stsp struct got_object_id *
78 3235492e 2018-04-01 stsp got_object_get_id(struct got_object *obj)
79 3235492e 2018-04-01 stsp {
80 6402fb3c 2018-09-15 stsp return &obj->id;
81 bacc9935 2018-05-20 stsp }
82 bacc9935 2018-05-20 stsp
83 bacc9935 2018-05-20 stsp const struct got_error *
84 bacc9935 2018-05-20 stsp got_object_get_id_str(char **outbuf, struct got_object *obj)
85 bacc9935 2018-05-20 stsp {
86 bacc9935 2018-05-20 stsp return got_object_id_str(outbuf, &obj->id);
87 a1fd68d8 2018-01-12 stsp }
88 d71d75ad 2017-11-05 stsp
89 b107e67f 2018-01-19 stsp int
90 b107e67f 2018-01-19 stsp got_object_get_type(struct got_object *obj)
91 a1fd68d8 2018-01-12 stsp {
92 b107e67f 2018-01-19 stsp switch (obj->type) {
93 a1fd68d8 2018-01-12 stsp case GOT_OBJ_TYPE_COMMIT:
94 a1fd68d8 2018-01-12 stsp case GOT_OBJ_TYPE_TREE:
95 a1fd68d8 2018-01-12 stsp case GOT_OBJ_TYPE_BLOB:
96 b107e67f 2018-01-19 stsp case GOT_OBJ_TYPE_TAG:
97 b107e67f 2018-01-19 stsp return obj->type;
98 96f5e8b3 2018-01-23 stsp default:
99 96f5e8b3 2018-01-23 stsp abort();
100 96f5e8b3 2018-01-23 stsp break;
101 d71d75ad 2017-11-05 stsp }
102 d71d75ad 2017-11-05 stsp
103 96f5e8b3 2018-01-23 stsp /* not reached */
104 96f5e8b3 2018-01-23 stsp return 0;
105 d71d75ad 2017-11-05 stsp }
106 ab9a70b2 2017-11-06 stsp
107 ab9a70b2 2017-11-06 stsp static const struct got_error *
108 4558fcd4 2018-01-14 stsp object_path(char **path, struct got_object_id *id, struct got_repository *repo)
109 ab9a70b2 2017-11-06 stsp {
110 ab9a70b2 2017-11-06 stsp const struct got_error *err = NULL;
111 7a132809 2018-07-23 stsp char *hex = NULL;
112 d1cda826 2017-11-06 stsp char *path_objects = got_repo_get_path_objects(repo);
113 e6b1056e 2018-04-22 stsp
114 e6b1056e 2018-04-22 stsp *path = NULL;
115 ab9a70b2 2017-11-06 stsp
116 ab9a70b2 2017-11-06 stsp if (path_objects == NULL)
117 0a585a0d 2018-03-17 stsp return got_error_from_errno();
118 ab9a70b2 2017-11-06 stsp
119 ef0981d5 2018-02-12 stsp err = got_object_id_str(&hex, id);
120 ef0981d5 2018-02-12 stsp if (err)
121 7a132809 2018-07-23 stsp goto done;
122 ab9a70b2 2017-11-06 stsp
123 d1cda826 2017-11-06 stsp if (asprintf(path, "%s/%.2x/%s", path_objects,
124 d1cda826 2017-11-06 stsp id->sha1[0], hex + 2) == -1)
125 0a585a0d 2018-03-17 stsp err = got_error_from_errno();
126 ab9a70b2 2017-11-06 stsp
127 7a132809 2018-07-23 stsp done:
128 ef0981d5 2018-02-12 stsp free(hex);
129 d1cda826 2017-11-06 stsp free(path_objects);
130 d1cda826 2017-11-06 stsp return err;
131 d1cda826 2017-11-06 stsp }
132 d1cda826 2017-11-06 stsp
133 4ee4114f 2018-01-23 stsp static const struct got_error *
134 d5003b79 2018-04-22 stsp open_loose_object(int *fd, struct got_object *obj, struct got_repository *repo)
135 d1cda826 2017-11-06 stsp {
136 d1cda826 2017-11-06 stsp const struct got_error *err = NULL;
137 a1fd68d8 2018-01-12 stsp char *path;
138 6c00b545 2018-01-17 stsp
139 6c00b545 2018-01-17 stsp err = object_path(&path, &obj->id, repo);
140 d1cda826 2017-11-06 stsp if (err)
141 d1cda826 2017-11-06 stsp return err;
142 d5003b79 2018-04-22 stsp *fd = open(path, O_RDONLY | O_NOFOLLOW, GOT_DEFAULT_FILE_MODE);
143 d5003b79 2018-04-22 stsp if (*fd == -1) {
144 6c00b545 2018-01-17 stsp err = got_error_from_errno();
145 6c00b545 2018-01-17 stsp goto done;
146 a1fd68d8 2018-01-12 stsp }
147 4558fcd4 2018-01-14 stsp done:
148 4558fcd4 2018-01-14 stsp free(path);
149 2090a03d 2018-09-09 stsp return err;
150 2090a03d 2018-09-09 stsp }
151 2090a03d 2018-09-09 stsp
152 2090a03d 2018-09-09 stsp static const struct got_error *
153 2090a03d 2018-09-09 stsp get_packfile_path(char **path_packfile, struct got_packidx *packidx)
154 2090a03d 2018-09-09 stsp {
155 2090a03d 2018-09-09 stsp size_t size;
156 2090a03d 2018-09-09 stsp
157 2090a03d 2018-09-09 stsp /* Packfile path contains ".pack" instead of ".idx", so add one byte. */
158 2090a03d 2018-09-09 stsp size = strlen(packidx->path_packidx) + 2;
159 2090a03d 2018-09-09 stsp if (size < GOT_PACKFILE_NAMELEN + 1)
160 2090a03d 2018-09-09 stsp return got_error(GOT_ERR_BAD_PATH);
161 2090a03d 2018-09-09 stsp
162 2090a03d 2018-09-09 stsp *path_packfile = calloc(size, sizeof(**path_packfile));
163 2090a03d 2018-09-09 stsp if (*path_packfile == NULL)
164 2090a03d 2018-09-09 stsp return got_error_from_errno();
165 2090a03d 2018-09-09 stsp
166 2090a03d 2018-09-09 stsp /* Copy up to and excluding ".idx". */
167 2090a03d 2018-09-09 stsp if (strlcpy(*path_packfile, packidx->path_packidx,
168 2090a03d 2018-09-09 stsp size - strlen(GOT_PACKIDX_SUFFIX) - 1) >= size)
169 2090a03d 2018-09-09 stsp return got_error(GOT_ERR_NO_SPACE);
170 2090a03d 2018-09-09 stsp
171 2090a03d 2018-09-09 stsp if (strlcat(*path_packfile, GOT_PACKFILE_SUFFIX, size) >= size)
172 2090a03d 2018-09-09 stsp return got_error(GOT_ERR_NO_SPACE);
173 2090a03d 2018-09-09 stsp
174 2090a03d 2018-09-09 stsp return NULL;
175 2090a03d 2018-09-09 stsp }
176 2090a03d 2018-09-09 stsp
177 2090a03d 2018-09-09 stsp static const struct got_error *
178 2090a03d 2018-09-09 stsp open_packed_object(struct got_object **obj, struct got_object_id *id,
179 2090a03d 2018-09-09 stsp struct got_repository *repo)
180 2090a03d 2018-09-09 stsp {
181 2090a03d 2018-09-09 stsp const struct got_error *err = NULL;
182 2090a03d 2018-09-09 stsp struct got_pack *pack = NULL;
183 2090a03d 2018-09-09 stsp struct got_packidx *packidx = NULL;
184 2090a03d 2018-09-09 stsp int idx;
185 2090a03d 2018-09-09 stsp char *path_packfile;
186 2090a03d 2018-09-09 stsp
187 2090a03d 2018-09-09 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
188 2090a03d 2018-09-09 stsp if (err)
189 2090a03d 2018-09-09 stsp return err;
190 2090a03d 2018-09-09 stsp
191 2090a03d 2018-09-09 stsp err = get_packfile_path(&path_packfile, packidx);
192 2090a03d 2018-09-09 stsp if (err)
193 2090a03d 2018-09-09 stsp return err;
194 2090a03d 2018-09-09 stsp
195 2090a03d 2018-09-09 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
196 2090a03d 2018-09-09 stsp if (pack == NULL) {
197 2090a03d 2018-09-09 stsp err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
198 2090a03d 2018-09-09 stsp if (err)
199 2090a03d 2018-09-09 stsp goto done;
200 2090a03d 2018-09-09 stsp }
201 2090a03d 2018-09-09 stsp
202 876c234b 2018-09-10 stsp err = got_object_packed_read_privsep(obj, repo, pack, packidx, idx, id);
203 2090a03d 2018-09-09 stsp if (err)
204 2090a03d 2018-09-09 stsp goto done;
205 2090a03d 2018-09-09 stsp
206 2090a03d 2018-09-09 stsp err = got_repo_cache_pack(NULL, repo, (*obj)->path_packfile, packidx);
207 2090a03d 2018-09-09 stsp done:
208 2090a03d 2018-09-09 stsp free(path_packfile);
209 4558fcd4 2018-01-14 stsp return err;
210 4558fcd4 2018-01-14 stsp }
211 a1fd68d8 2018-01-12 stsp
212 4558fcd4 2018-01-14 stsp const struct got_error *
213 4558fcd4 2018-01-14 stsp got_object_open(struct got_object **obj, struct got_repository *repo,
214 4558fcd4 2018-01-14 stsp struct got_object_id *id)
215 4558fcd4 2018-01-14 stsp {
216 6c00b545 2018-01-17 stsp const struct got_error *err = NULL;
217 6c00b545 2018-01-17 stsp char *path;
218 2178c42e 2018-04-22 stsp int fd;
219 7bb0daa1 2018-06-21 stsp
220 7bb0daa1 2018-06-21 stsp *obj = got_repo_get_cached_object(repo, id);
221 7bb0daa1 2018-06-21 stsp if (*obj != NULL) {
222 7bb0daa1 2018-06-21 stsp (*obj)->refcnt++;
223 7bb0daa1 2018-06-21 stsp return NULL;
224 7bb0daa1 2018-06-21 stsp }
225 4558fcd4 2018-01-14 stsp
226 6c00b545 2018-01-17 stsp err = object_path(&path, id, repo);
227 4558fcd4 2018-01-14 stsp if (err)
228 4558fcd4 2018-01-14 stsp return err;
229 4558fcd4 2018-01-14 stsp
230 2178c42e 2018-04-22 stsp fd = open(path, O_RDONLY | O_NOFOLLOW, GOT_DEFAULT_FILE_MODE);
231 2178c42e 2018-04-22 stsp if (fd == -1) {
232 6c00b545 2018-01-17 stsp if (errno != ENOENT) {
233 6c00b545 2018-01-17 stsp err = got_error_from_errno();
234 6c00b545 2018-01-17 stsp goto done;
235 6c00b545 2018-01-17 stsp }
236 2090a03d 2018-09-09 stsp err = open_packed_object(obj, id, repo);
237 6c00b545 2018-01-17 stsp if (err)
238 6c00b545 2018-01-17 stsp goto done;
239 6c00b545 2018-01-17 stsp if (*obj == NULL)
240 6c00b545 2018-01-17 stsp err = got_error(GOT_ERR_NO_OBJ);
241 6c00b545 2018-01-17 stsp } else {
242 ad242220 2018-09-08 stsp err = got_object_read_header_privsep(obj, repo, fd);
243 6c00b545 2018-01-17 stsp if (err)
244 6c00b545 2018-01-17 stsp goto done;
245 ab9a70b2 2017-11-06 stsp memcpy((*obj)->id.sha1, id->sha1, SHA1_DIGEST_LENGTH);
246 6c00b545 2018-01-17 stsp }
247 7bb0daa1 2018-06-21 stsp
248 7bb0daa1 2018-06-21 stsp if (err == NULL) {
249 7bb0daa1 2018-06-21 stsp (*obj)->refcnt++;
250 7bb0daa1 2018-06-21 stsp err = got_repo_cache_object(repo, id, *obj);
251 7bb0daa1 2018-06-21 stsp }
252 6c00b545 2018-01-17 stsp done:
253 6c00b545 2018-01-17 stsp free(path);
254 2178c42e 2018-04-22 stsp if (fd != -1)
255 2178c42e 2018-04-22 stsp close(fd);
256 ab9a70b2 2017-11-06 stsp return err;
257 6c00b545 2018-01-17 stsp
258 ab9a70b2 2017-11-06 stsp }
259 ab9a70b2 2017-11-06 stsp
260 6dfa2fd3 2018-02-12 stsp const struct got_error *
261 6dfa2fd3 2018-02-12 stsp got_object_open_by_id_str(struct got_object **obj, struct got_repository *repo,
262 6dfa2fd3 2018-02-12 stsp const char *id_str)
263 6dfa2fd3 2018-02-12 stsp {
264 6dfa2fd3 2018-02-12 stsp struct got_object_id id;
265 6dfa2fd3 2018-02-12 stsp
266 6dfa2fd3 2018-02-12 stsp if (!got_parse_sha1_digest(id.sha1, id_str))
267 6dfa2fd3 2018-02-12 stsp return got_error(GOT_ERR_BAD_OBJ_ID_STR);
268 6dfa2fd3 2018-02-12 stsp
269 6dfa2fd3 2018-02-12 stsp return got_object_open(obj, repo, &id);
270 bff6ca00 2018-04-23 stsp }
271 bff6ca00 2018-04-23 stsp
272 bff6ca00 2018-04-23 stsp const struct got_error *
273 be6a1b5a 2018-06-11 stsp got_object_open_as_commit(struct got_commit_object **commit,
274 be6a1b5a 2018-06-11 stsp struct got_repository *repo, struct got_object_id *id)
275 be6a1b5a 2018-06-11 stsp {
276 be6a1b5a 2018-06-11 stsp const struct got_error *err;
277 be6a1b5a 2018-06-11 stsp struct got_object *obj;
278 835e0dbd 2018-06-21 stsp
279 835e0dbd 2018-06-21 stsp *commit = NULL;
280 be6a1b5a 2018-06-11 stsp
281 be6a1b5a 2018-06-11 stsp err = got_object_open(&obj, repo, id);
282 be6a1b5a 2018-06-11 stsp if (err)
283 be6a1b5a 2018-06-11 stsp return err;
284 be6a1b5a 2018-06-11 stsp if (got_object_get_type(obj) != GOT_OBJ_TYPE_COMMIT) {
285 be6a1b5a 2018-06-11 stsp err = got_error(GOT_ERR_OBJ_TYPE);
286 be6a1b5a 2018-06-11 stsp goto done;
287 be6a1b5a 2018-06-11 stsp }
288 be6a1b5a 2018-06-11 stsp
289 be6a1b5a 2018-06-11 stsp err = got_object_commit_open(commit, repo, obj);
290 be6a1b5a 2018-06-11 stsp done:
291 be6a1b5a 2018-06-11 stsp got_object_close(obj);
292 be6a1b5a 2018-06-11 stsp return err;
293 be6a1b5a 2018-06-11 stsp }
294 be6a1b5a 2018-06-11 stsp
295 be6a1b5a 2018-06-11 stsp const struct got_error *
296 dbc6a6b6 2018-07-12 stsp got_object_qid_alloc(struct got_object_qid **qid, struct got_object_id *id)
297 dbc6a6b6 2018-07-12 stsp {
298 dbc6a6b6 2018-07-12 stsp const struct got_error *err = NULL;
299 dbc6a6b6 2018-07-12 stsp
300 dbc6a6b6 2018-07-12 stsp *qid = calloc(1, sizeof(**qid));
301 dbc6a6b6 2018-07-12 stsp if (*qid == NULL)
302 dbc6a6b6 2018-07-12 stsp return got_error_from_errno();
303 dbc6a6b6 2018-07-12 stsp
304 dbc6a6b6 2018-07-12 stsp (*qid)->id = got_object_id_dup(id);
305 dbc6a6b6 2018-07-12 stsp if ((*qid)->id == NULL) {
306 dbc6a6b6 2018-07-12 stsp err = got_error_from_errno();
307 fa2f6902 2018-07-23 stsp got_object_qid_free(*qid);
308 dbc6a6b6 2018-07-12 stsp *qid = NULL;
309 dbc6a6b6 2018-07-12 stsp return err;
310 dbc6a6b6 2018-07-12 stsp }
311 dbc6a6b6 2018-07-12 stsp
312 dbc6a6b6 2018-07-12 stsp return NULL;
313 7e212e3d 2018-09-09 stsp }
314 7e212e3d 2018-09-09 stsp
315 d1cda826 2017-11-06 stsp const struct got_error *
316 d1cda826 2017-11-06 stsp got_object_commit_open(struct got_commit_object **commit,
317 d1cda826 2017-11-06 stsp struct got_repository *repo, struct got_object *obj)
318 d1cda826 2017-11-06 stsp {
319 d1cda826 2017-11-06 stsp const struct got_error *err = NULL;
320 1943de01 2018-06-22 stsp
321 1943de01 2018-06-22 stsp *commit = got_repo_get_cached_commit(repo, &obj->id);
322 1943de01 2018-06-22 stsp if (*commit != NULL) {
323 1943de01 2018-06-22 stsp (*commit)->refcnt++;
324 1943de01 2018-06-22 stsp return NULL;
325 1943de01 2018-06-22 stsp }
326 d1cda826 2017-11-06 stsp
327 d1cda826 2017-11-06 stsp if (obj->type != GOT_OBJ_TYPE_COMMIT)
328 d1cda826 2017-11-06 stsp return got_error(GOT_ERR_OBJ_TYPE);
329 d1cda826 2017-11-06 stsp
330 ea35256b 2018-03-16 stsp if (obj->flags & GOT_OBJ_FLAG_PACKED) {
331 cfd633c2 2018-09-10 stsp struct got_pack *pack;
332 cfd633c2 2018-09-10 stsp pack = got_repo_get_cached_pack(repo, obj->path_packfile);
333 cfd633c2 2018-09-10 stsp if (pack == NULL) {
334 cfd633c2 2018-09-10 stsp err = got_repo_cache_pack(&pack, repo,
335 cfd633c2 2018-09-10 stsp obj->path_packfile, NULL);
336 cfd633c2 2018-09-10 stsp if (err)
337 cfd633c2 2018-09-10 stsp return err;
338 cfd633c2 2018-09-10 stsp }
339 cfd633c2 2018-09-10 stsp err = got_object_read_packed_commit_privsep(commit, obj, pack);
340 ea35256b 2018-03-16 stsp } else {
341 d5003b79 2018-04-22 stsp int fd;
342 d5003b79 2018-04-22 stsp err = open_loose_object(&fd, obj, repo);
343 ea35256b 2018-03-16 stsp if (err)
344 ea35256b 2018-03-16 stsp return err;
345 ad242220 2018-09-08 stsp err = got_object_read_commit_privsep(commit, obj, fd, repo);
346 bff6ca00 2018-04-23 stsp close(fd);
347 ea35256b 2018-03-16 stsp }
348 1943de01 2018-06-22 stsp
349 1943de01 2018-06-22 stsp if (err == NULL) {
350 1943de01 2018-06-22 stsp (*commit)->refcnt++;
351 1943de01 2018-06-22 stsp err = got_repo_cache_commit(repo, &obj->id, *commit);
352 1943de01 2018-06-22 stsp }
353 1943de01 2018-06-22 stsp
354 d1cda826 2017-11-06 stsp return err;
355 d1cda826 2017-11-06 stsp }
356 d1cda826 2017-11-06 stsp
357 0ffeb3c2 2017-11-26 stsp const struct got_error *
358 0ffeb3c2 2017-11-26 stsp got_object_tree_open(struct got_tree_object **tree,
359 0ffeb3c2 2017-11-26 stsp struct got_repository *repo, struct got_object *obj)
360 0ffeb3c2 2017-11-26 stsp {
361 0ffeb3c2 2017-11-26 stsp const struct got_error *err = NULL;
362 f6be5c30 2018-06-22 stsp
363 f6be5c30 2018-06-22 stsp *tree = got_repo_get_cached_tree(repo, &obj->id);
364 f6be5c30 2018-06-22 stsp if (*tree != NULL) {
365 f6be5c30 2018-06-22 stsp (*tree)->refcnt++;
366 f6be5c30 2018-06-22 stsp return NULL;
367 f6be5c30 2018-06-22 stsp }
368 0ffeb3c2 2017-11-26 stsp
369 0ffeb3c2 2017-11-26 stsp if (obj->type != GOT_OBJ_TYPE_TREE)
370 0ffeb3c2 2017-11-26 stsp return got_error(GOT_ERR_OBJ_TYPE);
371 0ffeb3c2 2017-11-26 stsp
372 e0ab43e7 2018-03-16 stsp if (obj->flags & GOT_OBJ_FLAG_PACKED) {
373 e7885405 2018-09-10 stsp struct got_pack *pack;
374 e7885405 2018-09-10 stsp pack = got_repo_get_cached_pack(repo, obj->path_packfile);
375 e7885405 2018-09-10 stsp if (pack == NULL) {
376 e7885405 2018-09-10 stsp err = got_repo_cache_pack(&pack, repo,
377 e7885405 2018-09-10 stsp obj->path_packfile, NULL);
378 e7885405 2018-09-10 stsp if (err)
379 e7885405 2018-09-10 stsp return err;
380 e7885405 2018-09-10 stsp }
381 e7885405 2018-09-10 stsp err = got_object_read_packed_tree_privsep(tree, obj, pack);
382 e0ab43e7 2018-03-16 stsp } else {
383 d5003b79 2018-04-22 stsp int fd;
384 d5003b79 2018-04-22 stsp err = open_loose_object(&fd, obj, repo);
385 e0ab43e7 2018-03-16 stsp if (err)
386 e0ab43e7 2018-03-16 stsp return err;
387 ad242220 2018-09-08 stsp err = got_object_read_tree_privsep(tree, obj, fd, repo);
388 d5003b79 2018-04-22 stsp close(fd);
389 776d4d29 2018-06-17 stsp }
390 f6be5c30 2018-06-22 stsp
391 f6be5c30 2018-06-22 stsp if (err == NULL) {
392 f6be5c30 2018-06-22 stsp (*tree)->refcnt++;
393 f6be5c30 2018-06-22 stsp err = got_repo_cache_tree(repo, &obj->id, *tree);
394 f6be5c30 2018-06-22 stsp }
395 f6be5c30 2018-06-22 stsp
396 776d4d29 2018-06-17 stsp return err;
397 776d4d29 2018-06-17 stsp }
398 776d4d29 2018-06-17 stsp
399 776d4d29 2018-06-17 stsp const struct got_error *
400 776d4d29 2018-06-17 stsp got_object_open_as_tree(struct got_tree_object **tree,
401 776d4d29 2018-06-17 stsp struct got_repository *repo, struct got_object_id *id)
402 776d4d29 2018-06-17 stsp {
403 776d4d29 2018-06-17 stsp const struct got_error *err;
404 776d4d29 2018-06-17 stsp struct got_object *obj;
405 835e0dbd 2018-06-21 stsp
406 835e0dbd 2018-06-21 stsp *tree = NULL;
407 776d4d29 2018-06-17 stsp
408 776d4d29 2018-06-17 stsp err = got_object_open(&obj, repo, id);
409 776d4d29 2018-06-17 stsp if (err)
410 776d4d29 2018-06-17 stsp return err;
411 1cbc02b6 2018-06-21 stsp if (got_object_get_type(obj) != GOT_OBJ_TYPE_TREE) {
412 776d4d29 2018-06-17 stsp err = got_error(GOT_ERR_OBJ_TYPE);
413 776d4d29 2018-06-17 stsp goto done;
414 e0ab43e7 2018-03-16 stsp }
415 776d4d29 2018-06-17 stsp
416 776d4d29 2018-06-17 stsp err = got_object_tree_open(tree, repo, obj);
417 776d4d29 2018-06-17 stsp done:
418 776d4d29 2018-06-17 stsp got_object_close(obj);
419 0ffeb3c2 2017-11-26 stsp return err;
420 57efb1af 2018-04-24 stsp }
421 ff6b18f8 2018-04-24 stsp
422 883f0469 2018-06-23 stsp const struct got_tree_entries *
423 883f0469 2018-06-23 stsp got_object_tree_get_entries(struct got_tree_object *tree)
424 883f0469 2018-06-23 stsp {
425 883f0469 2018-06-23 stsp return &tree->entries;
426 883f0469 2018-06-23 stsp }
427 3840f4c9 2018-09-12 stsp
428 3840f4c9 2018-09-12 stsp static const struct got_error *
429 3840f4c9 2018-09-12 stsp read_packed_blob_privsep(size_t *size, int outfd, struct got_object *obj,
430 3840f4c9 2018-09-12 stsp struct got_pack *pack)
431 3840f4c9 2018-09-12 stsp {
432 3840f4c9 2018-09-12 stsp const struct got_error *err = NULL;
433 3840f4c9 2018-09-12 stsp int outfd_child;
434 3840f4c9 2018-09-12 stsp int basefd, accumfd; /* temporary files for delta application */
435 24140570 2018-09-09 stsp
436 3840f4c9 2018-09-12 stsp basefd = got_opentempfd();
437 3840f4c9 2018-09-12 stsp if (basefd == -1)
438 3840f4c9 2018-09-12 stsp return got_error_from_errno();
439 3840f4c9 2018-09-12 stsp accumfd = got_opentempfd();
440 3840f4c9 2018-09-12 stsp if (accumfd == -1)
441 3840f4c9 2018-09-12 stsp return got_error_from_errno();
442 3840f4c9 2018-09-12 stsp
443 3840f4c9 2018-09-12 stsp outfd_child = dup(outfd);
444 3840f4c9 2018-09-12 stsp if (outfd_child == -1)
445 3840f4c9 2018-09-12 stsp return got_error_from_errno();
446 3840f4c9 2018-09-12 stsp
447 3840f4c9 2018-09-12 stsp err = got_privsep_send_obj_req(pack->privsep_child->ibuf, -1, obj);
448 3840f4c9 2018-09-12 stsp if (err)
449 3840f4c9 2018-09-12 stsp return err;
450 3840f4c9 2018-09-12 stsp
451 3840f4c9 2018-09-12 stsp err = got_privsep_send_blob_outfd(pack->privsep_child->ibuf,
452 3840f4c9 2018-09-12 stsp outfd_child);
453 3840f4c9 2018-09-12 stsp if (err) {
454 3840f4c9 2018-09-12 stsp close(outfd_child);
455 3840f4c9 2018-09-12 stsp return err;
456 3840f4c9 2018-09-12 stsp }
457 3840f4c9 2018-09-12 stsp err = got_privsep_send_tmpfd(pack->privsep_child->ibuf,
458 3840f4c9 2018-09-12 stsp basefd);
459 3840f4c9 2018-09-12 stsp if (err) {
460 3840f4c9 2018-09-12 stsp close(basefd);
461 3840f4c9 2018-09-12 stsp close(accumfd);
462 3840f4c9 2018-09-12 stsp close(outfd_child);
463 3840f4c9 2018-09-12 stsp return err;
464 3840f4c9 2018-09-12 stsp }
465 3840f4c9 2018-09-12 stsp
466 3840f4c9 2018-09-12 stsp err = got_privsep_send_tmpfd(pack->privsep_child->ibuf,
467 3840f4c9 2018-09-12 stsp accumfd);
468 3840f4c9 2018-09-12 stsp if (err) {
469 3840f4c9 2018-09-12 stsp close(accumfd);
470 3840f4c9 2018-09-12 stsp close(outfd_child);
471 3840f4c9 2018-09-12 stsp return err;
472 3840f4c9 2018-09-12 stsp }
473 3840f4c9 2018-09-12 stsp
474 3840f4c9 2018-09-12 stsp err = got_privsep_recv_blob(size, pack->privsep_child->ibuf);
475 3840f4c9 2018-09-12 stsp if (err)
476 3840f4c9 2018-09-12 stsp return err;
477 3840f4c9 2018-09-12 stsp
478 3840f4c9 2018-09-12 stsp if (lseek(outfd, SEEK_SET, 0) == -1)
479 3840f4c9 2018-09-12 stsp err = got_error_from_errno();
480 3840f4c9 2018-09-12 stsp
481 3840f4c9 2018-09-12 stsp return err;
482 3840f4c9 2018-09-12 stsp }
483 3840f4c9 2018-09-12 stsp
484 68482ea3 2017-11-27 stsp const struct got_error *
485 68482ea3 2017-11-27 stsp got_object_blob_open(struct got_blob_object **blob,
486 68482ea3 2017-11-27 stsp struct got_repository *repo, struct got_object *obj, size_t blocksize)
487 68482ea3 2017-11-27 stsp {
488 68482ea3 2017-11-27 stsp const struct got_error *err = NULL;
489 55da3778 2018-09-10 stsp int outfd;
490 55da3778 2018-09-10 stsp size_t size;
491 55da3778 2018-09-10 stsp struct stat sb;
492 68482ea3 2017-11-27 stsp
493 68482ea3 2017-11-27 stsp if (obj->type != GOT_OBJ_TYPE_BLOB)
494 68482ea3 2017-11-27 stsp return got_error(GOT_ERR_OBJ_TYPE);
495 68482ea3 2017-11-27 stsp
496 7d283eee 2017-11-29 stsp if (blocksize < obj->hdrlen)
497 7d283eee 2017-11-29 stsp return got_error(GOT_ERR_NO_SPACE);
498 7d283eee 2017-11-29 stsp
499 68482ea3 2017-11-27 stsp *blob = calloc(1, sizeof(**blob));
500 4558fcd4 2018-01-14 stsp if (*blob == NULL)
501 0a585a0d 2018-03-17 stsp return got_error_from_errno();
502 68482ea3 2017-11-27 stsp
503 55da3778 2018-09-10 stsp outfd = got_opentempfd();
504 55da3778 2018-09-10 stsp if (outfd == -1)
505 55da3778 2018-09-10 stsp return got_error_from_errno();
506 55da3778 2018-09-10 stsp
507 062ebb78 2018-07-12 stsp (*blob)->read_buf = malloc(blocksize);
508 15c8b0e6 2018-04-24 stsp if ((*blob)->read_buf == NULL) {
509 15c8b0e6 2018-04-24 stsp err = got_error_from_errno();
510 c7254d79 2018-04-24 stsp goto done;
511 15c8b0e6 2018-04-24 stsp }
512 eb651edf 2018-02-11 stsp if (obj->flags & GOT_OBJ_FLAG_PACKED) {
513 55da3778 2018-09-10 stsp struct got_pack *pack;
514 55da3778 2018-09-10 stsp pack = got_repo_get_cached_pack(repo, obj->path_packfile);
515 55da3778 2018-09-10 stsp if (pack == NULL) {
516 55da3778 2018-09-10 stsp err = got_repo_cache_pack(&pack, repo,
517 55da3778 2018-09-10 stsp obj->path_packfile, NULL);
518 55da3778 2018-09-10 stsp if (err)
519 55da3778 2018-09-10 stsp goto done;
520 55da3778 2018-09-10 stsp }
521 3840f4c9 2018-09-12 stsp err = read_packed_blob_privsep(&size, outfd, obj, pack);
522 c7254d79 2018-04-24 stsp if (err)
523 c7254d79 2018-04-24 stsp goto done;
524 55da3778 2018-09-10 stsp obj->size = size;
525 eb651edf 2018-02-11 stsp } else {
526 55da3778 2018-09-10 stsp int infd;
527 c7254d79 2018-04-24 stsp
528 3aca5731 2018-04-24 stsp err = open_loose_object(&infd, obj, repo);
529 c7254d79 2018-04-24 stsp if (err)
530 c7254d79 2018-04-24 stsp goto done;
531 c7254d79 2018-04-24 stsp
532 ad242220 2018-09-08 stsp err = got_object_read_blob_privsep(&size, outfd, infd, repo);
533 3aca5731 2018-04-24 stsp close(infd);
534 57efb1af 2018-04-24 stsp if (err)
535 c7254d79 2018-04-24 stsp goto done;
536 3aca5731 2018-04-24 stsp
537 2967a784 2018-04-24 stsp if (size != obj->hdrlen + obj->size) {
538 1a6b3ab7 2018-04-24 stsp err = got_error(GOT_ERR_PRIVSEP_LEN);
539 2967a784 2018-04-24 stsp goto done;
540 2967a784 2018-04-24 stsp }
541 55da3778 2018-09-10 stsp }
542 2967a784 2018-04-24 stsp
543 55da3778 2018-09-10 stsp if (fstat(outfd, &sb) == -1) {
544 55da3778 2018-09-10 stsp err = got_error_from_errno();
545 55da3778 2018-09-10 stsp goto done;
546 55da3778 2018-09-10 stsp }
547 2967a784 2018-04-24 stsp
548 55da3778 2018-09-10 stsp if (sb.st_size != obj->hdrlen + obj->size) {
549 55da3778 2018-09-10 stsp err = got_error(GOT_ERR_PRIVSEP_LEN);
550 55da3778 2018-09-10 stsp goto done;
551 55da3778 2018-09-10 stsp }
552 2967a784 2018-04-24 stsp
553 55da3778 2018-09-10 stsp (*blob)->f = fdopen(outfd, "rb");
554 55da3778 2018-09-10 stsp if ((*blob)->f == NULL) {
555 55da3778 2018-09-10 stsp err = got_error_from_errno();
556 55da3778 2018-09-10 stsp close(outfd);
557 55da3778 2018-09-10 stsp goto done;
558 68482ea3 2017-11-27 stsp }
559 68482ea3 2017-11-27 stsp
560 7d283eee 2017-11-29 stsp (*blob)->hdrlen = obj->hdrlen;
561 eb651edf 2018-02-11 stsp (*blob)->blocksize = blocksize;
562 f78b0693 2017-11-29 stsp memcpy(&(*blob)->id.sha1, obj->id.sha1, SHA1_DIGEST_LENGTH);
563 7d283eee 2017-11-29 stsp
564 c7254d79 2018-04-24 stsp done:
565 55da3778 2018-09-10 stsp if (err) {
566 55da3778 2018-09-10 stsp if (*blob) {
567 55da3778 2018-09-10 stsp if ((*blob)->f)
568 55da3778 2018-09-10 stsp fclose((*blob)->f);
569 55da3778 2018-09-10 stsp free((*blob)->read_buf);
570 55da3778 2018-09-10 stsp free(*blob);
571 55da3778 2018-09-10 stsp *blob = NULL;
572 55da3778 2018-09-10 stsp } else if (outfd != -1)
573 55da3778 2018-09-10 stsp close(outfd);
574 a19581a2 2018-06-21 stsp }
575 a19581a2 2018-06-21 stsp return err;
576 a19581a2 2018-06-21 stsp }
577 a19581a2 2018-06-21 stsp
578 a19581a2 2018-06-21 stsp const struct got_error *
579 a19581a2 2018-06-21 stsp got_object_open_as_blob(struct got_blob_object **blob,
580 a19581a2 2018-06-21 stsp struct got_repository *repo, struct got_object_id *id,
581 a19581a2 2018-06-21 stsp size_t blocksize)
582 a19581a2 2018-06-21 stsp {
583 a19581a2 2018-06-21 stsp const struct got_error *err;
584 a19581a2 2018-06-21 stsp struct got_object *obj;
585 835e0dbd 2018-06-21 stsp
586 835e0dbd 2018-06-21 stsp *blob = NULL;
587 a19581a2 2018-06-21 stsp
588 a19581a2 2018-06-21 stsp err = got_object_open(&obj, repo, id);
589 a19581a2 2018-06-21 stsp if (err)
590 a19581a2 2018-06-21 stsp return err;
591 a19581a2 2018-06-21 stsp if (got_object_get_type(obj) != GOT_OBJ_TYPE_BLOB) {
592 a19581a2 2018-06-21 stsp err = got_error(GOT_ERR_OBJ_TYPE);
593 a19581a2 2018-06-21 stsp goto done;
594 c7254d79 2018-04-24 stsp }
595 a19581a2 2018-06-21 stsp
596 a19581a2 2018-06-21 stsp err = got_object_blob_open(blob, repo, obj, blocksize);
597 a19581a2 2018-06-21 stsp done:
598 a19581a2 2018-06-21 stsp got_object_close(obj);
599 68482ea3 2017-11-27 stsp return err;
600 0ffeb3c2 2017-11-26 stsp }
601 68482ea3 2017-11-27 stsp
602 68482ea3 2017-11-27 stsp void
603 68482ea3 2017-11-27 stsp got_object_blob_close(struct got_blob_object *blob)
604 68482ea3 2017-11-27 stsp {
605 15c8b0e6 2018-04-24 stsp free(blob->read_buf);
606 68482ea3 2017-11-27 stsp fclose(blob->f);
607 68482ea3 2017-11-27 stsp free(blob);
608 f934cf2c 2018-02-12 stsp }
609 f934cf2c 2018-02-12 stsp
610 f934cf2c 2018-02-12 stsp char *
611 f934cf2c 2018-02-12 stsp got_object_blob_id_str(struct got_blob_object *blob, char *buf, size_t size)
612 f934cf2c 2018-02-12 stsp {
613 f934cf2c 2018-02-12 stsp return got_sha1_digest_to_str(blob->id.sha1, buf, size);
614 f934cf2c 2018-02-12 stsp }
615 f934cf2c 2018-02-12 stsp
616 f934cf2c 2018-02-12 stsp size_t
617 f934cf2c 2018-02-12 stsp got_object_blob_get_hdrlen(struct got_blob_object *blob)
618 f934cf2c 2018-02-12 stsp {
619 f934cf2c 2018-02-12 stsp return blob->hdrlen;
620 68482ea3 2017-11-27 stsp }
621 68482ea3 2017-11-27 stsp
622 f934cf2c 2018-02-12 stsp const uint8_t *
623 f934cf2c 2018-02-12 stsp got_object_blob_get_read_buf(struct got_blob_object *blob)
624 f934cf2c 2018-02-12 stsp {
625 f934cf2c 2018-02-12 stsp return blob->read_buf;
626 f934cf2c 2018-02-12 stsp }
627 f934cf2c 2018-02-12 stsp
628 68482ea3 2017-11-27 stsp const struct got_error *
629 eb651edf 2018-02-11 stsp got_object_blob_read_block(size_t *outlenp, struct got_blob_object *blob)
630 68482ea3 2017-11-27 stsp {
631 eb651edf 2018-02-11 stsp size_t n;
632 eb651edf 2018-02-11 stsp
633 eb651edf 2018-02-11 stsp n = fread(blob->read_buf, 1, blob->blocksize, blob->f);
634 eb651edf 2018-02-11 stsp if (n == 0 && ferror(blob->f))
635 eb651edf 2018-02-11 stsp return got_ferror(blob->f, GOT_ERR_IO);
636 eb651edf 2018-02-11 stsp *outlenp = n;
637 35e9ba5d 2018-06-21 stsp return NULL;
638 35e9ba5d 2018-06-21 stsp }
639 35e9ba5d 2018-06-21 stsp
640 35e9ba5d 2018-06-21 stsp const struct got_error *
641 84451b3e 2018-07-10 stsp got_object_blob_dump_to_file(size_t *total_len, size_t *nlines,
642 84451b3e 2018-07-10 stsp FILE *outfile, struct got_blob_object *blob)
643 35e9ba5d 2018-06-21 stsp {
644 35e9ba5d 2018-06-21 stsp const struct got_error *err = NULL;
645 35e9ba5d 2018-06-21 stsp size_t len, hdrlen;
646 84451b3e 2018-07-10 stsp const uint8_t *buf;
647 84451b3e 2018-07-10 stsp int i;
648 84451b3e 2018-07-10 stsp
649 84451b3e 2018-07-10 stsp if (total_len)
650 84451b3e 2018-07-10 stsp *total_len = 0;
651 84451b3e 2018-07-10 stsp if (nlines)
652 84451b3e 2018-07-10 stsp *nlines = 0;
653 35e9ba5d 2018-06-21 stsp
654 35e9ba5d 2018-06-21 stsp hdrlen = got_object_blob_get_hdrlen(blob);
655 35e9ba5d 2018-06-21 stsp do {
656 35e9ba5d 2018-06-21 stsp err = got_object_blob_read_block(&len, blob);
657 35e9ba5d 2018-06-21 stsp if (err)
658 35e9ba5d 2018-06-21 stsp return err;
659 35e9ba5d 2018-06-21 stsp if (len == 0)
660 35e9ba5d 2018-06-21 stsp break;
661 84451b3e 2018-07-10 stsp if (total_len)
662 84451b3e 2018-07-10 stsp *total_len += len;
663 84451b3e 2018-07-10 stsp buf = got_object_blob_get_read_buf(blob);
664 84451b3e 2018-07-10 stsp if (nlines) {
665 84451b3e 2018-07-10 stsp for (i = 0; i < len; i++) {
666 84451b3e 2018-07-10 stsp if (buf[i] == '\n')
667 84451b3e 2018-07-10 stsp (*nlines)++;
668 84451b3e 2018-07-10 stsp }
669 84451b3e 2018-07-10 stsp }
670 35e9ba5d 2018-06-21 stsp /* Skip blob object header first time around. */
671 84451b3e 2018-07-10 stsp fwrite(buf + hdrlen, len - hdrlen, 1, outfile);
672 35e9ba5d 2018-06-21 stsp hdrlen = 0;
673 35e9ba5d 2018-06-21 stsp } while (len != 0);
674 35e9ba5d 2018-06-21 stsp
675 35e9ba5d 2018-06-21 stsp fflush(outfile);
676 35e9ba5d 2018-06-21 stsp rewind(outfile);
677 35e9ba5d 2018-06-21 stsp
678 776d4d29 2018-06-17 stsp return NULL;
679 776d4d29 2018-06-17 stsp }
680 776d4d29 2018-06-17 stsp
681 776d4d29 2018-06-17 stsp static struct got_tree_entry *
682 776d4d29 2018-06-17 stsp find_entry_by_name(struct got_tree_object *tree, const char *name)
683 776d4d29 2018-06-17 stsp {
684 776d4d29 2018-06-17 stsp struct got_tree_entry *te;
685 776d4d29 2018-06-17 stsp
686 883f0469 2018-06-23 stsp SIMPLEQ_FOREACH(te, &tree->entries.head, entry) {
687 776d4d29 2018-06-17 stsp if (strcmp(te->name, name) == 0)
688 776d4d29 2018-06-17 stsp return te;
689 776d4d29 2018-06-17 stsp }
690 eb651edf 2018-02-11 stsp return NULL;
691 776d4d29 2018-06-17 stsp }
692 776d4d29 2018-06-17 stsp
693 776d4d29 2018-06-17 stsp const struct got_error *
694 27d434c2 2018-09-15 stsp got_object_id_by_path(struct got_object_id **id, struct got_repository *repo,
695 776d4d29 2018-06-17 stsp struct got_object_id *commit_id, const char *path)
696 776d4d29 2018-06-17 stsp {
697 776d4d29 2018-06-17 stsp const struct got_error *err = NULL;
698 776d4d29 2018-06-17 stsp struct got_commit_object *commit = NULL;
699 776d4d29 2018-06-17 stsp struct got_tree_object *tree = NULL;
700 db37e2c0 2018-06-21 stsp struct got_tree_entry *te = NULL;
701 197aa481 2018-06-21 stsp char *seg, *s, *s0 = NULL;
702 67606321 2018-06-21 stsp size_t len = strlen(path);
703 776d4d29 2018-06-17 stsp
704 27d434c2 2018-09-15 stsp *id = NULL;
705 776d4d29 2018-06-17 stsp
706 776d4d29 2018-06-17 stsp /* We are expecting an absolute in-repository path. */
707 776d4d29 2018-06-17 stsp if (path[0] != '/')
708 776d4d29 2018-06-17 stsp return got_error(GOT_ERR_NOT_ABSPATH);
709 776d4d29 2018-06-17 stsp
710 776d4d29 2018-06-17 stsp err = got_object_open_as_commit(&commit, repo, commit_id);
711 776d4d29 2018-06-17 stsp if (err)
712 776d4d29 2018-06-17 stsp goto done;
713 776d4d29 2018-06-17 stsp
714 776d4d29 2018-06-17 stsp /* Handle opening of root of commit's tree. */
715 776d4d29 2018-06-17 stsp if (path[1] == '\0') {
716 27d434c2 2018-09-15 stsp *id = got_object_id_dup(commit->tree_id);
717 27d434c2 2018-09-15 stsp if (*id == NULL)
718 27d434c2 2018-09-15 stsp err = got_error_from_errno();
719 ca008b32 2018-07-22 stsp goto done;
720 776d4d29 2018-06-17 stsp }
721 776d4d29 2018-06-17 stsp
722 776d4d29 2018-06-17 stsp err = got_object_open_as_tree(&tree, repo, commit->tree_id);
723 776d4d29 2018-06-17 stsp if (err)
724 776d4d29 2018-06-17 stsp goto done;
725 776d4d29 2018-06-17 stsp
726 197aa481 2018-06-21 stsp s0 = strdup(path);
727 197aa481 2018-06-21 stsp if (s0 == NULL) {
728 776d4d29 2018-06-17 stsp err = got_error_from_errno();
729 776d4d29 2018-06-17 stsp goto done;
730 776d4d29 2018-06-17 stsp }
731 67606321 2018-06-21 stsp err = got_canonpath(path, s0, len + 1);
732 776d4d29 2018-06-17 stsp if (err)
733 776d4d29 2018-06-17 stsp goto done;
734 776d4d29 2018-06-17 stsp
735 197aa481 2018-06-21 stsp s = s0;
736 776d4d29 2018-06-17 stsp s++; /* skip leading '/' */
737 67606321 2018-06-21 stsp len--;
738 776d4d29 2018-06-17 stsp seg = s;
739 67606321 2018-06-21 stsp while (len > 0) {
740 776d4d29 2018-06-17 stsp struct got_tree_object *next_tree;
741 776d4d29 2018-06-17 stsp
742 776d4d29 2018-06-17 stsp if (*s != '/') {
743 776d4d29 2018-06-17 stsp s++;
744 67606321 2018-06-21 stsp len--;
745 00530cfb 2018-06-21 stsp if (*s)
746 00530cfb 2018-06-21 stsp continue;
747 776d4d29 2018-06-17 stsp }
748 776d4d29 2018-06-17 stsp
749 776d4d29 2018-06-17 stsp /* end of path segment */
750 776d4d29 2018-06-17 stsp *s = '\0';
751 776d4d29 2018-06-17 stsp
752 db37e2c0 2018-06-21 stsp te = find_entry_by_name(tree, seg);
753 db37e2c0 2018-06-21 stsp if (te == NULL) {
754 776d4d29 2018-06-17 stsp err = got_error(GOT_ERR_NO_OBJ);
755 776d4d29 2018-06-17 stsp goto done;
756 776d4d29 2018-06-17 stsp }
757 776d4d29 2018-06-17 stsp
758 67606321 2018-06-21 stsp if (len == 0)
759 67606321 2018-06-21 stsp break;
760 67606321 2018-06-21 stsp
761 776d4d29 2018-06-17 stsp seg = s + 1;
762 776d4d29 2018-06-17 stsp s++;
763 67606321 2018-06-21 stsp len--;
764 776d4d29 2018-06-17 stsp if (*s) {
765 776d4d29 2018-06-17 stsp err = got_object_open_as_tree(&next_tree, repo,
766 db37e2c0 2018-06-21 stsp te->id);
767 db37e2c0 2018-06-21 stsp te = NULL;
768 776d4d29 2018-06-17 stsp if (err)
769 776d4d29 2018-06-17 stsp goto done;
770 776d4d29 2018-06-17 stsp got_object_tree_close(tree);
771 776d4d29 2018-06-17 stsp tree = next_tree;
772 776d4d29 2018-06-17 stsp }
773 776d4d29 2018-06-17 stsp }
774 776d4d29 2018-06-17 stsp
775 27d434c2 2018-09-15 stsp if (te) {
776 27d434c2 2018-09-15 stsp *id = got_object_id_dup(te->id);
777 27d434c2 2018-09-15 stsp if (*id == NULL)
778 27d434c2 2018-09-15 stsp return got_error_from_errno();
779 27d434c2 2018-09-15 stsp } else
780 776d4d29 2018-06-17 stsp err = got_error(GOT_ERR_NO_OBJ);
781 776d4d29 2018-06-17 stsp done:
782 197aa481 2018-06-21 stsp free(s0);
783 776d4d29 2018-06-17 stsp if (commit)
784 776d4d29 2018-06-17 stsp got_object_commit_close(commit);
785 776d4d29 2018-06-17 stsp if (tree)
786 776d4d29 2018-06-17 stsp got_object_tree_close(tree);
787 776d4d29 2018-06-17 stsp return err;
788 68482ea3 2017-11-27 stsp }
789 07862c20 2018-09-15 stsp
790 07862c20 2018-09-15 stsp const struct got_error *
791 07862c20 2018-09-15 stsp got_object_tree_path_changed(int *changed,
792 07862c20 2018-09-15 stsp struct got_tree_object *tree01, struct got_tree_object *tree02,
793 07862c20 2018-09-15 stsp const char *path, struct got_repository *repo)
794 07862c20 2018-09-15 stsp {
795 07862c20 2018-09-15 stsp const struct got_error *err = NULL;
796 07862c20 2018-09-15 stsp struct got_tree_object *tree1 = NULL, *tree2 = NULL;
797 07862c20 2018-09-15 stsp struct got_tree_entry *te1 = NULL, *te2 = NULL;
798 07862c20 2018-09-15 stsp char *seg, *s, *s0 = NULL;
799 07862c20 2018-09-15 stsp size_t len = strlen(path);
800 07862c20 2018-09-15 stsp
801 07862c20 2018-09-15 stsp *changed = 0;
802 07862c20 2018-09-15 stsp
803 07862c20 2018-09-15 stsp /* We are expecting an absolute in-repository path. */
804 07862c20 2018-09-15 stsp if (path[0] != '/')
805 07862c20 2018-09-15 stsp return got_error(GOT_ERR_NOT_ABSPATH);
806 07862c20 2018-09-15 stsp
807 07862c20 2018-09-15 stsp /* We not do support comparing the root path. */
808 07862c20 2018-09-15 stsp if (path[1] == '\0')
809 07862c20 2018-09-15 stsp return got_error(GOT_ERR_BAD_PATH);
810 07862c20 2018-09-15 stsp
811 07862c20 2018-09-15 stsp s0 = strdup(path);
812 07862c20 2018-09-15 stsp if (s0 == NULL) {
813 07862c20 2018-09-15 stsp err = got_error_from_errno();
814 07862c20 2018-09-15 stsp goto done;
815 07862c20 2018-09-15 stsp }
816 07862c20 2018-09-15 stsp err = got_canonpath(path, s0, len + 1);
817 07862c20 2018-09-15 stsp if (err)
818 07862c20 2018-09-15 stsp goto done;
819 07862c20 2018-09-15 stsp
820 07862c20 2018-09-15 stsp tree1 = tree01;
821 07862c20 2018-09-15 stsp tree2 = tree02;
822 07862c20 2018-09-15 stsp s = s0;
823 07862c20 2018-09-15 stsp s++; /* skip leading '/' */
824 07862c20 2018-09-15 stsp len--;
825 07862c20 2018-09-15 stsp seg = s;
826 07862c20 2018-09-15 stsp while (len > 0) {
827 07862c20 2018-09-15 stsp struct got_tree_object *next_tree1, *next_tree2;
828 07862c20 2018-09-15 stsp
829 07862c20 2018-09-15 stsp if (*s != '/') {
830 07862c20 2018-09-15 stsp s++;
831 07862c20 2018-09-15 stsp len--;
832 07862c20 2018-09-15 stsp if (*s)
833 07862c20 2018-09-15 stsp continue;
834 07862c20 2018-09-15 stsp }
835 07862c20 2018-09-15 stsp
836 07862c20 2018-09-15 stsp /* end of path segment */
837 07862c20 2018-09-15 stsp *s = '\0';
838 07862c20 2018-09-15 stsp
839 07862c20 2018-09-15 stsp te1 = find_entry_by_name(tree1, seg);
840 07862c20 2018-09-15 stsp if (te1 == NULL) {
841 07862c20 2018-09-15 stsp err = got_error(GOT_ERR_NO_OBJ);
842 07862c20 2018-09-15 stsp goto done;
843 07862c20 2018-09-15 stsp }
844 07862c20 2018-09-15 stsp
845 07862c20 2018-09-15 stsp te2 = find_entry_by_name(tree2, seg);
846 07862c20 2018-09-15 stsp if (te2 == NULL) {
847 07862c20 2018-09-15 stsp *changed = 1;
848 07862c20 2018-09-15 stsp goto done;
849 07862c20 2018-09-15 stsp }
850 07862c20 2018-09-15 stsp
851 07862c20 2018-09-15 stsp if (te1->mode != te2->mode) {
852 07862c20 2018-09-15 stsp *changed = 1;
853 07862c20 2018-09-15 stsp goto done;
854 07862c20 2018-09-15 stsp }
855 07862c20 2018-09-15 stsp
856 07862c20 2018-09-15 stsp if (got_object_id_cmp(te1->id, te2->id) == 0) {
857 07862c20 2018-09-15 stsp *changed = 0;
858 07862c20 2018-09-15 stsp goto done;
859 07862c20 2018-09-15 stsp }
860 07862c20 2018-09-15 stsp
861 f970fa8a 2018-09-15 stsp if (len == 0) { /* final path element */
862 07862c20 2018-09-15 stsp *changed = 1;
863 07862c20 2018-09-15 stsp goto done;
864 07862c20 2018-09-15 stsp }
865 07862c20 2018-09-15 stsp
866 07862c20 2018-09-15 stsp seg = s + 1;
867 07862c20 2018-09-15 stsp s++;
868 07862c20 2018-09-15 stsp len--;
869 07862c20 2018-09-15 stsp if (*s) {
870 07862c20 2018-09-15 stsp err = got_object_open_as_tree(&next_tree1, repo,
871 07862c20 2018-09-15 stsp te1->id);
872 07862c20 2018-09-15 stsp te1 = NULL;
873 07862c20 2018-09-15 stsp if (err)
874 07862c20 2018-09-15 stsp goto done;
875 07862c20 2018-09-15 stsp tree1 = next_tree1;
876 07862c20 2018-09-15 stsp
877 07862c20 2018-09-15 stsp err = got_object_open_as_tree(&next_tree2, repo,
878 07862c20 2018-09-15 stsp te2->id);
879 07862c20 2018-09-15 stsp te2 = NULL;
880 07862c20 2018-09-15 stsp if (err)
881 07862c20 2018-09-15 stsp goto done;
882 07862c20 2018-09-15 stsp tree2 = next_tree2;
883 07862c20 2018-09-15 stsp }
884 07862c20 2018-09-15 stsp }
885 07862c20 2018-09-15 stsp done:
886 07862c20 2018-09-15 stsp free(s0);
887 07862c20 2018-09-15 stsp if (tree1 != tree01)
888 07862c20 2018-09-15 stsp got_object_tree_close(tree1);
889 07862c20 2018-09-15 stsp if (tree2 != tree02)
890 07862c20 2018-09-15 stsp got_object_tree_close(tree2);
891 07862c20 2018-09-15 stsp return err;
892 07862c20 2018-09-15 stsp }