Blame


1 e6bcace5 2021-06-22 stsp /*
2 e6bcace5 2021-06-22 stsp * Copyright (c) 2020 Ori Bernstein
3 e6bcace5 2021-06-22 stsp * Copyright (c) 2021 Stefan Sperling <stsp@openbsd.org>
4 e6bcace5 2021-06-22 stsp *
5 e6bcace5 2021-06-22 stsp * Permission to use, copy, modify, and distribute this software for any
6 e6bcace5 2021-06-22 stsp * purpose with or without fee is hereby granted, provided that the above
7 e6bcace5 2021-06-22 stsp * copyright notice and this permission notice appear in all copies.
8 e6bcace5 2021-06-22 stsp *
9 e6bcace5 2021-06-22 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 e6bcace5 2021-06-22 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 e6bcace5 2021-06-22 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 e6bcace5 2021-06-22 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 e6bcace5 2021-06-22 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 e6bcace5 2021-06-22 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 e6bcace5 2021-06-22 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 e6bcace5 2021-06-22 stsp */
17 e6bcace5 2021-06-22 stsp
18 08736cf9 2021-06-23 stsp #include <sys/types.h>
19 e6bcace5 2021-06-22 stsp #include <sys/queue.h>
20 f8b19efd 2021-10-13 stsp #include <sys/tree.h>
21 08736cf9 2021-06-23 stsp #include <sys/uio.h>
22 e6bcace5 2021-06-22 stsp #include <sys/stat.h>
23 211cfef0 2022-01-05 stsp #include <sys/time.h>
24 e6bcace5 2021-06-22 stsp
25 e3f86256 2022-02-18 naddy #include <endian.h>
26 08736cf9 2021-06-23 stsp #include <stdint.h>
27 05118f5a 2021-06-22 stsp #include <imsg.h>
28 e6bcace5 2021-06-22 stsp #include <stdio.h>
29 e6bcace5 2021-06-22 stsp #include <stdlib.h>
30 e6bcace5 2021-06-22 stsp #include <string.h>
31 e6bcace5 2021-06-22 stsp #include <sha1.h>
32 211cfef0 2022-01-05 stsp #include <time.h>
33 bfc73a47 2022-03-19 naddy #include <unistd.h>
34 e6bcace5 2021-06-22 stsp #include <limits.h>
35 e6bcace5 2021-06-22 stsp #include <zlib.h>
36 e6bcace5 2021-06-22 stsp
37 e6bcace5 2021-06-22 stsp #include "got_error.h"
38 e6bcace5 2021-06-22 stsp #include "got_cancel.h"
39 e6bcace5 2021-06-22 stsp #include "got_object.h"
40 f8b19efd 2021-10-13 stsp #include "got_path.h"
41 05118f5a 2021-06-22 stsp #include "got_reference.h"
42 05118f5a 2021-06-22 stsp #include "got_repository_admin.h"
43 08347b73 2021-10-14 stsp #include "got_opentemp.h"
44 e6bcace5 2021-06-22 stsp
45 e6bcace5 2021-06-22 stsp #include "got_lib_deltify.h"
46 e6bcace5 2021-06-22 stsp #include "got_lib_delta.h"
47 e6bcace5 2021-06-22 stsp #include "got_lib_object.h"
48 e6bcace5 2021-06-22 stsp #include "got_lib_object_idset.h"
49 05118f5a 2021-06-22 stsp #include "got_lib_object_cache.h"
50 e6bcace5 2021-06-22 stsp #include "got_lib_deflate.h"
51 e6bcace5 2021-06-22 stsp #include "got_lib_pack.h"
52 05118f5a 2021-06-22 stsp #include "got_lib_privsep.h"
53 05118f5a 2021-06-22 stsp #include "got_lib_repository.h"
54 211cfef0 2022-01-05 stsp #include "got_lib_ratelimit.h"
55 2d9e6abf 2022-05-04 stsp #include "got_lib_inflate.h"
56 e6bcace5 2021-06-22 stsp
57 74881701 2021-10-15 stsp #ifndef MIN
58 74881701 2021-10-15 stsp #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
59 74881701 2021-10-15 stsp #endif
60 74881701 2021-10-15 stsp
61 e6bcace5 2021-06-22 stsp #ifndef MAX
62 e6bcace5 2021-06-22 stsp #define MAX(_a,_b) ((_a) > (_b) ? (_a) : (_b))
63 e6bcace5 2021-06-22 stsp #endif
64 e6bcace5 2021-06-22 stsp
65 70f8f24d 2022-04-14 stsp #ifndef nitems
66 70f8f24d 2022-04-14 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
67 70f8f24d 2022-04-14 stsp #endif
68 70f8f24d 2022-04-14 stsp
69 e6bcace5 2021-06-22 stsp struct got_pack_meta {
70 e6bcace5 2021-06-22 stsp struct got_object_id id;
71 e6bcace5 2021-06-22 stsp char *path;
72 e6bcace5 2021-06-22 stsp int obj_type;
73 600b755e 2021-10-14 stsp off_t size;
74 e6bcace5 2021-06-22 stsp time_t mtime;
75 e6bcace5 2021-06-22 stsp
76 e6bcace5 2021-06-22 stsp /* The best delta we picked */
77 e6bcace5 2021-06-22 stsp struct got_pack_meta *head;
78 e6bcace5 2021-06-22 stsp struct got_pack_meta *prev;
79 2d9e6abf 2022-05-04 stsp unsigned char *delta_buf; /* if encoded in memory (compressed) */
80 2d9e6abf 2022-05-04 stsp off_t delta_offset; /* offset in delta cache file (compressed) */
81 5060d5a1 2022-01-10 stsp off_t delta_len; /* encoded delta length */
82 2d9e6abf 2022-05-04 stsp off_t delta_compressed_len; /* encoded+compressed delta length */
83 e6bcace5 2021-06-22 stsp int nchain;
84 e6bcace5 2021-06-22 stsp
85 67fd6849 2022-02-13 stsp int have_reused_delta;
86 67fd6849 2022-02-13 stsp off_t reused_delta_offset; /* offset of delta in reused pack file */
87 67fd6849 2022-02-13 stsp struct got_object_id *base_obj_id;
88 67fd6849 2022-02-13 stsp
89 e6bcace5 2021-06-22 stsp /* Only used for delta window */
90 e6bcace5 2021-06-22 stsp struct got_delta_table *dtab;
91 e6bcace5 2021-06-22 stsp
92 e6bcace5 2021-06-22 stsp /* Only used for writing offset deltas */
93 e6bcace5 2021-06-22 stsp off_t off;
94 e6bcace5 2021-06-22 stsp };
95 e6bcace5 2021-06-22 stsp
96 e6bcace5 2021-06-22 stsp struct got_pack_metavec {
97 e6bcace5 2021-06-22 stsp struct got_pack_meta **meta;
98 e6bcace5 2021-06-22 stsp int nmeta;
99 e6bcace5 2021-06-22 stsp int metasz;
100 e6bcace5 2021-06-22 stsp };
101 e6bcace5 2021-06-22 stsp
102 e6bcace5 2021-06-22 stsp static const struct got_error *
103 e6bcace5 2021-06-22 stsp alloc_meta(struct got_pack_meta **new, struct got_object_id *id,
104 e6bcace5 2021-06-22 stsp const char *path, int obj_type, time_t mtime)
105 e6bcace5 2021-06-22 stsp {
106 e6bcace5 2021-06-22 stsp const struct got_error *err = NULL;
107 e6bcace5 2021-06-22 stsp struct got_pack_meta *m;
108 e6bcace5 2021-06-22 stsp
109 e6bcace5 2021-06-22 stsp *new = NULL;
110 e6bcace5 2021-06-22 stsp
111 e6bcace5 2021-06-22 stsp m = calloc(1, sizeof(*m));
112 e6bcace5 2021-06-22 stsp if (m == NULL)
113 1d19226a 2021-10-13 stsp return got_error_from_errno("calloc");
114 e6bcace5 2021-06-22 stsp
115 e6bcace5 2021-06-22 stsp memcpy(&m->id, id, sizeof(m->id));
116 e6bcace5 2021-06-22 stsp
117 e6bcace5 2021-06-22 stsp m->path = strdup(path);
118 e6bcace5 2021-06-22 stsp if (m->path == NULL) {
119 e6bcace5 2021-06-22 stsp err = got_error_from_errno("strdup");
120 e6bcace5 2021-06-22 stsp free(m);
121 e6bcace5 2021-06-22 stsp return err;
122 e6bcace5 2021-06-22 stsp }
123 e6bcace5 2021-06-22 stsp
124 e6bcace5 2021-06-22 stsp m->obj_type = obj_type;
125 e6bcace5 2021-06-22 stsp m->mtime = mtime;
126 e6bcace5 2021-06-22 stsp *new = m;
127 e6bcace5 2021-06-22 stsp return NULL;
128 e6bcace5 2021-06-22 stsp }
129 e6bcace5 2021-06-22 stsp
130 e6bcace5 2021-06-22 stsp static void
131 e6bcace5 2021-06-22 stsp clear_meta(struct got_pack_meta *meta)
132 e6bcace5 2021-06-22 stsp {
133 e6bcace5 2021-06-22 stsp if (meta == NULL)
134 e6bcace5 2021-06-22 stsp return;
135 e6bcace5 2021-06-22 stsp free(meta->path);
136 e6bcace5 2021-06-22 stsp meta->path = NULL;
137 5060d5a1 2022-01-10 stsp free(meta->delta_buf);
138 5060d5a1 2022-01-10 stsp meta->delta_buf = NULL;
139 67fd6849 2022-02-13 stsp free(meta->base_obj_id);
140 67fd6849 2022-02-13 stsp meta->base_obj_id = NULL;
141 e6bcace5 2021-06-22 stsp }
142 e6bcace5 2021-06-22 stsp
143 e6bcace5 2021-06-22 stsp static void
144 e6bcace5 2021-06-22 stsp free_nmeta(struct got_pack_meta **meta, int nmeta)
145 e6bcace5 2021-06-22 stsp {
146 e6bcace5 2021-06-22 stsp int i;
147 e6bcace5 2021-06-22 stsp
148 e6bcace5 2021-06-22 stsp for (i = 0; i < nmeta; i++)
149 e6bcace5 2021-06-22 stsp clear_meta(meta[i]);
150 e6bcace5 2021-06-22 stsp free(meta);
151 e6bcace5 2021-06-22 stsp }
152 e6bcace5 2021-06-22 stsp
153 e6bcace5 2021-06-22 stsp static int
154 e6bcace5 2021-06-22 stsp delta_order_cmp(const void *pa, const void *pb)
155 e6bcace5 2021-06-22 stsp {
156 e6bcace5 2021-06-22 stsp struct got_pack_meta *a, *b;
157 e6bcace5 2021-06-22 stsp int cmp;
158 e6bcace5 2021-06-22 stsp
159 e6bcace5 2021-06-22 stsp a = *(struct got_pack_meta **)pa;
160 e6bcace5 2021-06-22 stsp b = *(struct got_pack_meta **)pb;
161 e6bcace5 2021-06-22 stsp
162 e6bcace5 2021-06-22 stsp if (a->obj_type != b->obj_type)
163 e6bcace5 2021-06-22 stsp return a->obj_type - b->obj_type;
164 e6bcace5 2021-06-22 stsp cmp = strcmp(a->path, b->path);
165 e6bcace5 2021-06-22 stsp if (cmp != 0)
166 e6bcace5 2021-06-22 stsp return cmp;
167 611e8e31 2022-05-01 stsp if (a->mtime < b->mtime)
168 611e8e31 2022-05-01 stsp return -1;
169 611e8e31 2022-05-01 stsp if (a->mtime > b->mtime)
170 611e8e31 2022-05-01 stsp return 1;
171 e6bcace5 2021-06-22 stsp return got_object_id_cmp(&a->id, &b->id);
172 e6bcace5 2021-06-22 stsp }
173 e6bcace5 2021-06-22 stsp
174 5060d5a1 2022-01-10 stsp static off_t
175 e6bcace5 2021-06-22 stsp delta_size(struct got_delta_instruction *deltas, int ndeltas)
176 e6bcace5 2021-06-22 stsp {
177 5060d5a1 2022-01-10 stsp int i;
178 5060d5a1 2022-01-10 stsp off_t size = 32;
179 e6bcace5 2021-06-22 stsp for (i = 0; i < ndeltas; i++) {
180 e6bcace5 2021-06-22 stsp if (deltas[i].copy)
181 e6bcace5 2021-06-22 stsp size += GOT_DELTA_SIZE_SHIFT;
182 e6bcace5 2021-06-22 stsp else
183 e6bcace5 2021-06-22 stsp size += deltas[i].len + 1;
184 e6bcace5 2021-06-22 stsp }
185 e6bcace5 2021-06-22 stsp return size;
186 5060d5a1 2022-01-10 stsp }
187 5060d5a1 2022-01-10 stsp
188 5060d5a1 2022-01-10 stsp static const struct got_error *
189 5060d5a1 2022-01-10 stsp append(unsigned char **p, size_t *len, off_t *sz, void *seg, int nseg)
190 5060d5a1 2022-01-10 stsp {
191 5060d5a1 2022-01-10 stsp char *n;
192 5060d5a1 2022-01-10 stsp
193 5060d5a1 2022-01-10 stsp if (*len + nseg >= *sz) {
194 5060d5a1 2022-01-10 stsp while (*len + nseg >= *sz)
195 5060d5a1 2022-01-10 stsp *sz += *sz / 2;
196 5060d5a1 2022-01-10 stsp n = realloc(*p, *sz);
197 5060d5a1 2022-01-10 stsp if (n == NULL)
198 5060d5a1 2022-01-10 stsp return got_error_from_errno("realloc");
199 5060d5a1 2022-01-10 stsp *p = n;
200 5060d5a1 2022-01-10 stsp }
201 5060d5a1 2022-01-10 stsp memcpy(*p + *len, seg, nseg);
202 5060d5a1 2022-01-10 stsp *len += nseg;
203 5060d5a1 2022-01-10 stsp return NULL;
204 5060d5a1 2022-01-10 stsp }
205 5060d5a1 2022-01-10 stsp
206 5060d5a1 2022-01-10 stsp static const struct got_error *
207 5060d5a1 2022-01-10 stsp encode_delta_in_mem(struct got_pack_meta *m, struct got_raw_object *o,
208 5060d5a1 2022-01-10 stsp struct got_delta_instruction *deltas, int ndeltas,
209 5060d5a1 2022-01-10 stsp off_t delta_size, off_t base_size)
210 5060d5a1 2022-01-10 stsp {
211 5060d5a1 2022-01-10 stsp const struct got_error *err;
212 5060d5a1 2022-01-10 stsp unsigned char buf[16], *bp;
213 5060d5a1 2022-01-10 stsp int i, j;
214 2d9e6abf 2022-05-04 stsp size_t len = 0, compressed_len;
215 2d9e6abf 2022-05-04 stsp off_t bufsize = delta_size;
216 5060d5a1 2022-01-10 stsp off_t n;
217 5060d5a1 2022-01-10 stsp struct got_delta_instruction *d;
218 2d9e6abf 2022-05-04 stsp uint8_t *delta_buf;
219 5060d5a1 2022-01-10 stsp
220 2d9e6abf 2022-05-04 stsp delta_buf = malloc(bufsize);
221 2d9e6abf 2022-05-04 stsp if (delta_buf == NULL)
222 2d9e6abf 2022-05-04 stsp return got_error_from_errno("malloc");
223 5060d5a1 2022-01-10 stsp
224 5060d5a1 2022-01-10 stsp /* base object size */
225 5060d5a1 2022-01-10 stsp buf[0] = base_size & GOT_DELTA_SIZE_VAL_MASK;
226 5060d5a1 2022-01-10 stsp n = base_size >> GOT_DELTA_SIZE_SHIFT;
227 5060d5a1 2022-01-10 stsp for (i = 1; n > 0; i++) {
228 5060d5a1 2022-01-10 stsp buf[i - 1] |= GOT_DELTA_SIZE_MORE;
229 5060d5a1 2022-01-10 stsp buf[i] = n & GOT_DELTA_SIZE_VAL_MASK;
230 5060d5a1 2022-01-10 stsp n >>= GOT_DELTA_SIZE_SHIFT;
231 5060d5a1 2022-01-10 stsp }
232 2d9e6abf 2022-05-04 stsp err = append(&delta_buf, &len, &bufsize, buf, i);
233 5060d5a1 2022-01-10 stsp if (err)
234 2d9e6abf 2022-05-04 stsp goto done;
235 5060d5a1 2022-01-10 stsp
236 5060d5a1 2022-01-10 stsp /* target object size */
237 5060d5a1 2022-01-10 stsp buf[0] = o->size & GOT_DELTA_SIZE_VAL_MASK;
238 5060d5a1 2022-01-10 stsp n = o->size >> GOT_DELTA_SIZE_SHIFT;
239 5060d5a1 2022-01-10 stsp for (i = 1; n > 0; i++) {
240 5060d5a1 2022-01-10 stsp buf[i - 1] |= GOT_DELTA_SIZE_MORE;
241 5060d5a1 2022-01-10 stsp buf[i] = n & GOT_DELTA_SIZE_VAL_MASK;
242 5060d5a1 2022-01-10 stsp n >>= GOT_DELTA_SIZE_SHIFT;
243 5060d5a1 2022-01-10 stsp }
244 2d9e6abf 2022-05-04 stsp err = append(&delta_buf, &len, &bufsize, buf, i);
245 5060d5a1 2022-01-10 stsp if (err)
246 2d9e6abf 2022-05-04 stsp goto done;
247 5060d5a1 2022-01-10 stsp
248 5060d5a1 2022-01-10 stsp for (j = 0; j < ndeltas; j++) {
249 5060d5a1 2022-01-10 stsp d = &deltas[j];
250 5060d5a1 2022-01-10 stsp if (d->copy) {
251 5060d5a1 2022-01-10 stsp n = d->offset;
252 5060d5a1 2022-01-10 stsp bp = &buf[1];
253 5060d5a1 2022-01-10 stsp buf[0] = GOT_DELTA_BASE_COPY;
254 5060d5a1 2022-01-10 stsp for (i = 0; i < 4; i++) {
255 5060d5a1 2022-01-10 stsp /* DELTA_COPY_OFF1 ... DELTA_COPY_OFF4 */
256 5060d5a1 2022-01-10 stsp buf[0] |= 1 << i;
257 5060d5a1 2022-01-10 stsp *bp++ = n & 0xff;
258 5060d5a1 2022-01-10 stsp n >>= 8;
259 5060d5a1 2022-01-10 stsp if (n == 0)
260 5060d5a1 2022-01-10 stsp break;
261 5060d5a1 2022-01-10 stsp }
262 5060d5a1 2022-01-10 stsp
263 5060d5a1 2022-01-10 stsp n = d->len;
264 5060d5a1 2022-01-10 stsp if (n != GOT_DELTA_COPY_DEFAULT_LEN) {
265 5060d5a1 2022-01-10 stsp /* DELTA_COPY_LEN1 ... DELTA_COPY_LEN3 */
266 5060d5a1 2022-01-10 stsp for (i = 0; i < 3 && n > 0; i++) {
267 5060d5a1 2022-01-10 stsp buf[0] |= 1 << (i + 4);
268 5060d5a1 2022-01-10 stsp *bp++ = n & 0xff;
269 5060d5a1 2022-01-10 stsp n >>= 8;
270 5060d5a1 2022-01-10 stsp }
271 5060d5a1 2022-01-10 stsp }
272 2d9e6abf 2022-05-04 stsp err = append(&delta_buf, &len, &bufsize,
273 5060d5a1 2022-01-10 stsp buf, bp - buf);
274 5060d5a1 2022-01-10 stsp if (err)
275 2d9e6abf 2022-05-04 stsp goto done;
276 5060d5a1 2022-01-10 stsp } else if (o->f == NULL) {
277 5060d5a1 2022-01-10 stsp n = 0;
278 5060d5a1 2022-01-10 stsp while (n != d->len) {
279 5060d5a1 2022-01-10 stsp buf[0] = (d->len - n < 127) ? d->len - n : 127;
280 2d9e6abf 2022-05-04 stsp err = append(&delta_buf, &len, &bufsize,
281 5060d5a1 2022-01-10 stsp buf, 1);
282 5060d5a1 2022-01-10 stsp if (err)
283 2d9e6abf 2022-05-04 stsp goto done;
284 2d9e6abf 2022-05-04 stsp err = append(&delta_buf, &len, &bufsize,
285 5060d5a1 2022-01-10 stsp o->data + o->hdrlen + d->offset + n,
286 5060d5a1 2022-01-10 stsp buf[0]);
287 5060d5a1 2022-01-10 stsp if (err)
288 2d9e6abf 2022-05-04 stsp goto done;
289 5060d5a1 2022-01-10 stsp n += buf[0];
290 5060d5a1 2022-01-10 stsp }
291 5060d5a1 2022-01-10 stsp } else {
292 5060d5a1 2022-01-10 stsp char content[128];
293 5060d5a1 2022-01-10 stsp size_t r;
294 2d9e6abf 2022-05-04 stsp if (fseeko(o->f, o->hdrlen + d->offset, SEEK_SET) == -1) {
295 2d9e6abf 2022-05-04 stsp err = got_error_from_errno("fseeko");
296 2d9e6abf 2022-05-04 stsp goto done;
297 2d9e6abf 2022-05-04 stsp }
298 5060d5a1 2022-01-10 stsp n = 0;
299 5060d5a1 2022-01-10 stsp while (n != d->len) {
300 5060d5a1 2022-01-10 stsp buf[0] = (d->len - n < 127) ? d->len - n : 127;
301 2d9e6abf 2022-05-04 stsp err = append(&delta_buf, &len, &bufsize,
302 5060d5a1 2022-01-10 stsp buf, 1);
303 5060d5a1 2022-01-10 stsp if (err)
304 2d9e6abf 2022-05-04 stsp goto done;
305 5060d5a1 2022-01-10 stsp r = fread(content, 1, buf[0], o->f);
306 2d9e6abf 2022-05-04 stsp if (r != buf[0]) {
307 2d9e6abf 2022-05-04 stsp err = got_ferror(o->f, GOT_ERR_IO);
308 2d9e6abf 2022-05-04 stsp goto done;
309 2d9e6abf 2022-05-04 stsp }
310 2d9e6abf 2022-05-04 stsp err = append(&delta_buf, &len, &bufsize,
311 5060d5a1 2022-01-10 stsp content, buf[0]);
312 5060d5a1 2022-01-10 stsp if (err)
313 2d9e6abf 2022-05-04 stsp goto done;
314 5060d5a1 2022-01-10 stsp n += buf[0];
315 5060d5a1 2022-01-10 stsp }
316 5060d5a1 2022-01-10 stsp }
317 5060d5a1 2022-01-10 stsp }
318 5060d5a1 2022-01-10 stsp
319 2d9e6abf 2022-05-04 stsp err = got_deflate_to_mem_mmap(&m->delta_buf, &compressed_len,
320 2d9e6abf 2022-05-04 stsp NULL, NULL, delta_buf, 0, len);
321 2d9e6abf 2022-05-04 stsp if (err)
322 2d9e6abf 2022-05-04 stsp goto done;
323 2d9e6abf 2022-05-04 stsp
324 5060d5a1 2022-01-10 stsp m->delta_len = len;
325 2d9e6abf 2022-05-04 stsp m->delta_compressed_len = compressed_len;
326 2d9e6abf 2022-05-04 stsp done:
327 2d9e6abf 2022-05-04 stsp free(delta_buf);
328 2d9e6abf 2022-05-04 stsp return err;
329 e6bcace5 2021-06-22 stsp }
330 e6bcace5 2021-06-22 stsp
331 74881701 2021-10-15 stsp static const struct got_error *
332 74881701 2021-10-15 stsp encode_delta(struct got_pack_meta *m, struct got_raw_object *o,
333 74881701 2021-10-15 stsp struct got_delta_instruction *deltas, int ndeltas,
334 a319ca8c 2021-10-15 stsp off_t base_size, FILE *f)
335 a319ca8c 2021-10-15 stsp {
336 2d9e6abf 2022-05-04 stsp const struct got_error *err;
337 a319ca8c 2021-10-15 stsp unsigned char buf[16], *bp;
338 a319ca8c 2021-10-15 stsp int i, j;
339 a319ca8c 2021-10-15 stsp off_t n;
340 2d9e6abf 2022-05-04 stsp struct got_deflate_buf zb;
341 a319ca8c 2021-10-15 stsp struct got_delta_instruction *d;
342 2d9e6abf 2022-05-04 stsp off_t delta_len = 0, compressed_len = 0;
343 a319ca8c 2021-10-15 stsp
344 2d9e6abf 2022-05-04 stsp err = got_deflate_init(&zb, NULL, GOT_DEFLATE_BUFSIZE);
345 2d9e6abf 2022-05-04 stsp if (err)
346 2d9e6abf 2022-05-04 stsp return err;
347 2d9e6abf 2022-05-04 stsp
348 a319ca8c 2021-10-15 stsp /* base object size */
349 a319ca8c 2021-10-15 stsp buf[0] = base_size & GOT_DELTA_SIZE_VAL_MASK;
350 a319ca8c 2021-10-15 stsp n = base_size >> GOT_DELTA_SIZE_SHIFT;
351 a319ca8c 2021-10-15 stsp for (i = 1; n > 0; i++) {
352 a319ca8c 2021-10-15 stsp buf[i - 1] |= GOT_DELTA_SIZE_MORE;
353 a319ca8c 2021-10-15 stsp buf[i] = n & GOT_DELTA_SIZE_VAL_MASK;
354 a319ca8c 2021-10-15 stsp n >>= GOT_DELTA_SIZE_SHIFT;
355 a319ca8c 2021-10-15 stsp }
356 a319ca8c 2021-10-15 stsp
357 2d9e6abf 2022-05-04 stsp err = got_deflate_append_to_file_mmap(&zb, &compressed_len,
358 2d9e6abf 2022-05-04 stsp buf, 0, i, f, NULL);
359 2d9e6abf 2022-05-04 stsp if (err)
360 2d9e6abf 2022-05-04 stsp goto done;
361 2d9e6abf 2022-05-04 stsp delta_len += i;
362 2d9e6abf 2022-05-04 stsp
363 a319ca8c 2021-10-15 stsp /* target object size */
364 a319ca8c 2021-10-15 stsp buf[0] = o->size & GOT_DELTA_SIZE_VAL_MASK;
365 a319ca8c 2021-10-15 stsp n = o->size >> GOT_DELTA_SIZE_SHIFT;
366 a319ca8c 2021-10-15 stsp for (i = 1; n > 0; i++) {
367 a319ca8c 2021-10-15 stsp buf[i - 1] |= GOT_DELTA_SIZE_MORE;
368 a319ca8c 2021-10-15 stsp buf[i] = n & GOT_DELTA_SIZE_VAL_MASK;
369 a319ca8c 2021-10-15 stsp n >>= GOT_DELTA_SIZE_SHIFT;
370 a319ca8c 2021-10-15 stsp }
371 a319ca8c 2021-10-15 stsp
372 2d9e6abf 2022-05-04 stsp err = got_deflate_append_to_file_mmap(&zb, &compressed_len,
373 2d9e6abf 2022-05-04 stsp buf, 0, i, f, NULL);
374 2d9e6abf 2022-05-04 stsp if (err)
375 2d9e6abf 2022-05-04 stsp goto done;
376 2d9e6abf 2022-05-04 stsp delta_len += i;
377 2d9e6abf 2022-05-04 stsp
378 a319ca8c 2021-10-15 stsp for (j = 0; j < ndeltas; j++) {
379 a319ca8c 2021-10-15 stsp d = &deltas[j];
380 a319ca8c 2021-10-15 stsp if (d->copy) {
381 a319ca8c 2021-10-15 stsp n = d->offset;
382 a319ca8c 2021-10-15 stsp bp = &buf[1];
383 a319ca8c 2021-10-15 stsp buf[0] = GOT_DELTA_BASE_COPY;
384 a319ca8c 2021-10-15 stsp for (i = 0; i < 4; i++) {
385 a319ca8c 2021-10-15 stsp /* DELTA_COPY_OFF1 ... DELTA_COPY_OFF4 */
386 a319ca8c 2021-10-15 stsp buf[0] |= 1 << i;
387 a319ca8c 2021-10-15 stsp *bp++ = n & 0xff;
388 a319ca8c 2021-10-15 stsp n >>= 8;
389 a319ca8c 2021-10-15 stsp if (n == 0)
390 a319ca8c 2021-10-15 stsp break;
391 a319ca8c 2021-10-15 stsp }
392 a319ca8c 2021-10-15 stsp n = d->len;
393 a319ca8c 2021-10-15 stsp if (n != GOT_DELTA_COPY_DEFAULT_LEN) {
394 a319ca8c 2021-10-15 stsp /* DELTA_COPY_LEN1 ... DELTA_COPY_LEN3 */
395 a319ca8c 2021-10-15 stsp for (i = 0; i < 3 && n > 0; i++) {
396 a319ca8c 2021-10-15 stsp buf[0] |= 1 << (i + 4);
397 a319ca8c 2021-10-15 stsp *bp++ = n & 0xff;
398 a319ca8c 2021-10-15 stsp n >>= 8;
399 a319ca8c 2021-10-15 stsp }
400 a319ca8c 2021-10-15 stsp }
401 2d9e6abf 2022-05-04 stsp err = got_deflate_append_to_file_mmap(&zb,
402 2d9e6abf 2022-05-04 stsp &compressed_len, buf, 0, bp - buf, f, NULL);
403 2d9e6abf 2022-05-04 stsp if (err)
404 2d9e6abf 2022-05-04 stsp goto done;
405 2d9e6abf 2022-05-04 stsp delta_len += (bp - buf);
406 64a8571e 2022-01-07 stsp } else if (o->f == NULL) {
407 64a8571e 2022-01-07 stsp n = 0;
408 64a8571e 2022-01-07 stsp while (n != d->len) {
409 64a8571e 2022-01-07 stsp buf[0] = (d->len - n < 127) ? d->len - n : 127;
410 2d9e6abf 2022-05-04 stsp err = got_deflate_append_to_file_mmap(&zb,
411 2d9e6abf 2022-05-04 stsp &compressed_len, buf, 0, 1, f, NULL);
412 2d9e6abf 2022-05-04 stsp if (err)
413 2d9e6abf 2022-05-04 stsp goto done;
414 2d9e6abf 2022-05-04 stsp delta_len++;
415 2d9e6abf 2022-05-04 stsp err = got_deflate_append_to_file_mmap(&zb,
416 2d9e6abf 2022-05-04 stsp &compressed_len,
417 2d9e6abf 2022-05-04 stsp o->data + o->hdrlen + d->offset + n, 0,
418 2d9e6abf 2022-05-04 stsp buf[0], f, NULL);
419 2d9e6abf 2022-05-04 stsp if (err)
420 2d9e6abf 2022-05-04 stsp goto done;
421 2d9e6abf 2022-05-04 stsp delta_len += buf[0];
422 64a8571e 2022-01-07 stsp n += buf[0];
423 64a8571e 2022-01-07 stsp }
424 a319ca8c 2021-10-15 stsp } else {
425 a319ca8c 2021-10-15 stsp char content[128];
426 a319ca8c 2021-10-15 stsp size_t r;
427 2d9e6abf 2022-05-04 stsp if (fseeko(o->f, o->hdrlen + d->offset, SEEK_SET) == -1) {
428 2d9e6abf 2022-05-04 stsp err = got_error_from_errno("fseeko");
429 2d9e6abf 2022-05-04 stsp goto done;
430 2d9e6abf 2022-05-04 stsp }
431 a319ca8c 2021-10-15 stsp n = 0;
432 a319ca8c 2021-10-15 stsp while (n != d->len) {
433 a319ca8c 2021-10-15 stsp buf[0] = (d->len - n < 127) ? d->len - n : 127;
434 2d9e6abf 2022-05-04 stsp err = got_deflate_append_to_file_mmap(&zb,
435 2d9e6abf 2022-05-04 stsp &compressed_len, buf, 0, 1, f, NULL);
436 2d9e6abf 2022-05-04 stsp if (err)
437 2d9e6abf 2022-05-04 stsp goto done;
438 2d9e6abf 2022-05-04 stsp delta_len++;
439 a319ca8c 2021-10-15 stsp r = fread(content, 1, buf[0], o->f);
440 2d9e6abf 2022-05-04 stsp if (r != buf[0]) {
441 2d9e6abf 2022-05-04 stsp err = got_ferror(o->f, GOT_ERR_IO);
442 2d9e6abf 2022-05-04 stsp goto done;
443 2d9e6abf 2022-05-04 stsp }
444 2d9e6abf 2022-05-04 stsp err = got_deflate_append_to_file_mmap(&zb,
445 2d9e6abf 2022-05-04 stsp &compressed_len, content, 0, buf[0], f,
446 2d9e6abf 2022-05-04 stsp NULL);
447 2d9e6abf 2022-05-04 stsp if (err)
448 2d9e6abf 2022-05-04 stsp goto done;
449 2d9e6abf 2022-05-04 stsp delta_len += buf[0];
450 a319ca8c 2021-10-15 stsp n += buf[0];
451 a319ca8c 2021-10-15 stsp }
452 a319ca8c 2021-10-15 stsp }
453 a319ca8c 2021-10-15 stsp }
454 e6bcace5 2021-06-22 stsp
455 2d9e6abf 2022-05-04 stsp err = got_deflate_flush(&zb, f, NULL, &compressed_len);
456 2d9e6abf 2022-05-04 stsp if (err)
457 2d9e6abf 2022-05-04 stsp goto done;
458 2d9e6abf 2022-05-04 stsp
459 2d9e6abf 2022-05-04 stsp /* sanity check */
460 2d9e6abf 2022-05-04 stsp if (compressed_len != ftello(f) - m->delta_offset) {
461 2d9e6abf 2022-05-04 stsp err = got_error(GOT_ERR_COMPRESSION);
462 2d9e6abf 2022-05-04 stsp goto done;
463 2d9e6abf 2022-05-04 stsp }
464 2d9e6abf 2022-05-04 stsp
465 2d9e6abf 2022-05-04 stsp m->delta_len = delta_len;
466 2d9e6abf 2022-05-04 stsp m->delta_compressed_len = compressed_len;
467 2d9e6abf 2022-05-04 stsp done:
468 2d9e6abf 2022-05-04 stsp got_deflate_end(&zb);
469 2d9e6abf 2022-05-04 stsp return err;
470 a319ca8c 2021-10-15 stsp }
471 211cfef0 2022-01-05 stsp
472 211cfef0 2022-01-05 stsp static const struct got_error *
473 211cfef0 2022-01-05 stsp report_progress(got_pack_progress_cb progress_cb, void *progress_arg,
474 b8af7c06 2022-03-15 stsp struct got_ratelimit *rl, int ncolored, int nfound, int ntrees,
475 b8af7c06 2022-03-15 stsp off_t packfile_size, int ncommits, int nobj_total, int obj_deltify,
476 b8af7c06 2022-03-15 stsp int nobj_written)
477 211cfef0 2022-01-05 stsp {
478 211cfef0 2022-01-05 stsp const struct got_error *err;
479 211cfef0 2022-01-05 stsp int elapsed;
480 211cfef0 2022-01-05 stsp
481 211cfef0 2022-01-05 stsp if (progress_cb == NULL)
482 211cfef0 2022-01-05 stsp return NULL;
483 211cfef0 2022-01-05 stsp
484 211cfef0 2022-01-05 stsp err = got_ratelimit_check(&elapsed, rl);
485 211cfef0 2022-01-05 stsp if (err || !elapsed)
486 211cfef0 2022-01-05 stsp return err;
487 a319ca8c 2021-10-15 stsp
488 b8af7c06 2022-03-15 stsp return progress_cb(progress_arg, ncolored, nfound, ntrees,
489 b8af7c06 2022-03-15 stsp packfile_size, ncommits, nobj_total, obj_deltify, nobj_written);
490 211cfef0 2022-01-05 stsp }
491 a319ca8c 2021-10-15 stsp
492 e6bcace5 2021-06-22 stsp static const struct got_error *
493 67fd6849 2022-02-13 stsp add_meta(struct got_pack_meta *m, struct got_pack_metavec *v)
494 67fd6849 2022-02-13 stsp {
495 67fd6849 2022-02-13 stsp if (v->nmeta == v->metasz){
496 67fd6849 2022-02-13 stsp size_t newsize = 2 * v->metasz;
497 67fd6849 2022-02-13 stsp struct got_pack_meta **new;
498 67fd6849 2022-02-13 stsp new = reallocarray(v->meta, newsize, sizeof(*new));
499 67fd6849 2022-02-13 stsp if (new == NULL)
500 67fd6849 2022-02-13 stsp return got_error_from_errno("reallocarray");
501 67fd6849 2022-02-13 stsp v->meta = new;
502 67fd6849 2022-02-13 stsp v->metasz = newsize;
503 67fd6849 2022-02-13 stsp }
504 67fd6849 2022-02-13 stsp
505 67fd6849 2022-02-13 stsp v->meta[v->nmeta++] = m;
506 67fd6849 2022-02-13 stsp return NULL;
507 67fd6849 2022-02-13 stsp }
508 67fd6849 2022-02-13 stsp
509 67fd6849 2022-02-13 stsp static const struct got_error *
510 67fd6849 2022-02-13 stsp reuse_delta(int idx, struct got_pack_meta *m, struct got_pack_metavec *v,
511 67fd6849 2022-02-13 stsp struct got_object_idset *idset, struct got_pack *pack,
512 67fd6849 2022-02-13 stsp struct got_packidx *packidx, int delta_cache_fd,
513 67fd6849 2022-02-13 stsp struct got_repository *repo)
514 67fd6849 2022-02-13 stsp {
515 67fd6849 2022-02-13 stsp const struct got_error *err = NULL;
516 67fd6849 2022-02-13 stsp struct got_pack_meta *base = NULL;
517 67fd6849 2022-02-13 stsp struct got_object_id *base_obj_id = NULL;
518 2d9e6abf 2022-05-04 stsp off_t delta_len = 0, delta_compressed_len = 0;
519 2d9e6abf 2022-05-04 stsp off_t delta_offset = 0, delta_cache_offset = 0;
520 67fd6849 2022-02-13 stsp uint64_t base_size, result_size;
521 67fd6849 2022-02-13 stsp
522 67fd6849 2022-02-13 stsp if (m->have_reused_delta)
523 67fd6849 2022-02-13 stsp return NULL;
524 67fd6849 2022-02-13 stsp
525 67fd6849 2022-02-13 stsp err = got_object_read_raw_delta(&base_size, &result_size, &delta_len,
526 2d9e6abf 2022-05-04 stsp &delta_compressed_len, &delta_offset, &delta_cache_offset,
527 2d9e6abf 2022-05-04 stsp &base_obj_id, delta_cache_fd, packidx, idx, &m->id, repo);
528 67fd6849 2022-02-13 stsp if (err)
529 67fd6849 2022-02-13 stsp return err;
530 67fd6849 2022-02-13 stsp
531 67fd6849 2022-02-13 stsp if (delta_offset + delta_len < delta_offset)
532 67fd6849 2022-02-13 stsp return got_error(GOT_ERR_BAD_PACKFILE);
533 67fd6849 2022-02-13 stsp
534 67fd6849 2022-02-13 stsp base = got_object_idset_get(idset, base_obj_id);
535 67fd6849 2022-02-13 stsp if (base == NULL)
536 67fd6849 2022-02-13 stsp goto done;
537 67fd6849 2022-02-13 stsp
538 67fd6849 2022-02-13 stsp m->delta_len = delta_len;
539 2d9e6abf 2022-05-04 stsp m->delta_compressed_len = delta_compressed_len;
540 67fd6849 2022-02-13 stsp m->delta_offset = delta_cache_offset;
541 67fd6849 2022-02-13 stsp m->prev = base;
542 67fd6849 2022-02-13 stsp m->size = result_size;
543 67fd6849 2022-02-13 stsp m->have_reused_delta = 1;
544 67fd6849 2022-02-13 stsp m->reused_delta_offset = delta_offset;
545 67fd6849 2022-02-13 stsp m->base_obj_id = base_obj_id;
546 67fd6849 2022-02-13 stsp base_obj_id = NULL;
547 67fd6849 2022-02-13 stsp err = add_meta(m, v);
548 67fd6849 2022-02-13 stsp done:
549 67fd6849 2022-02-13 stsp free(base_obj_id);
550 67fd6849 2022-02-13 stsp return err;
551 67fd6849 2022-02-13 stsp }
552 67fd6849 2022-02-13 stsp
553 67fd6849 2022-02-13 stsp static const struct got_error *
554 67fd6849 2022-02-13 stsp find_pack_for_reuse(struct got_packidx **best_packidx,
555 67fd6849 2022-02-13 stsp struct got_repository *repo)
556 67fd6849 2022-02-13 stsp {
557 9b576444 2022-03-14 stsp const struct got_error *err = NULL;
558 67fd6849 2022-02-13 stsp struct got_pathlist_entry *pe;
559 67fd6849 2022-02-13 stsp const char *best_packidx_path = NULL;
560 67fd6849 2022-02-13 stsp int nobj_max = 0;
561 67fd6849 2022-02-13 stsp
562 67fd6849 2022-02-13 stsp *best_packidx = NULL;
563 67fd6849 2022-02-13 stsp
564 9b576444 2022-03-14 stsp TAILQ_FOREACH(pe, &repo->packidx_paths, entry) {
565 67fd6849 2022-02-13 stsp const char *path_packidx = pe->path;
566 67fd6849 2022-02-13 stsp struct got_packidx *packidx;
567 67fd6849 2022-02-13 stsp int nobj;
568 67fd6849 2022-02-13 stsp
569 67fd6849 2022-02-13 stsp err = got_repo_get_packidx(&packidx, path_packidx, repo);
570 67fd6849 2022-02-13 stsp if (err)
571 67fd6849 2022-02-13 stsp break;
572 67fd6849 2022-02-13 stsp
573 67fd6849 2022-02-13 stsp nobj = be32toh(packidx->hdr.fanout_table[0xff]);
574 67fd6849 2022-02-13 stsp if (nobj > nobj_max) {
575 67fd6849 2022-02-13 stsp best_packidx_path = path_packidx;
576 67fd6849 2022-02-13 stsp nobj_max = nobj;
577 67fd6849 2022-02-13 stsp }
578 67fd6849 2022-02-13 stsp }
579 67fd6849 2022-02-13 stsp
580 67fd6849 2022-02-13 stsp if (best_packidx_path) {
581 67fd6849 2022-02-13 stsp err = got_repo_get_packidx(best_packidx, best_packidx_path,
582 67fd6849 2022-02-13 stsp repo);
583 67fd6849 2022-02-13 stsp }
584 67fd6849 2022-02-13 stsp
585 67fd6849 2022-02-13 stsp return err;
586 67fd6849 2022-02-13 stsp }
587 67fd6849 2022-02-13 stsp
588 67fd6849 2022-02-13 stsp struct search_deltas_arg {
589 67fd6849 2022-02-13 stsp struct got_packidx *packidx;
590 67fd6849 2022-02-13 stsp struct got_pack *pack;
591 67fd6849 2022-02-13 stsp struct got_object_idset *idset;
592 67fd6849 2022-02-13 stsp struct got_pack_metavec *v;
593 67fd6849 2022-02-13 stsp int delta_cache_fd;
594 67fd6849 2022-02-13 stsp struct got_repository *repo;
595 67fd6849 2022-02-13 stsp got_pack_progress_cb progress_cb;
596 67fd6849 2022-02-13 stsp void *progress_arg;
597 67fd6849 2022-02-13 stsp struct got_ratelimit *rl;
598 67fd6849 2022-02-13 stsp got_cancel_cb cancel_cb;
599 67fd6849 2022-02-13 stsp void *cancel_arg;
600 b8af7c06 2022-03-15 stsp int ncolored;
601 b8af7c06 2022-03-15 stsp int nfound;
602 b8af7c06 2022-03-15 stsp int ntrees;
603 67fd6849 2022-02-13 stsp int ncommits;
604 67fd6849 2022-02-13 stsp };
605 67fd6849 2022-02-13 stsp
606 67fd6849 2022-02-13 stsp static const struct got_error *
607 67fd6849 2022-02-13 stsp search_delta_for_object(struct got_object_id *id, void *data, void *arg)
608 67fd6849 2022-02-13 stsp {
609 67fd6849 2022-02-13 stsp const struct got_error *err;
610 67fd6849 2022-02-13 stsp struct got_pack_meta *m = data;
611 67fd6849 2022-02-13 stsp struct search_deltas_arg *a = arg;
612 67fd6849 2022-02-13 stsp int obj_idx;
613 67fd6849 2022-02-13 stsp struct got_object *obj = NULL;
614 67fd6849 2022-02-13 stsp
615 67fd6849 2022-02-13 stsp if (a->cancel_cb) {
616 67fd6849 2022-02-13 stsp err = (*a->cancel_cb)(a->cancel_arg);
617 67fd6849 2022-02-13 stsp if (err)
618 67fd6849 2022-02-13 stsp return err;
619 67fd6849 2022-02-13 stsp }
620 67fd6849 2022-02-13 stsp
621 67fd6849 2022-02-13 stsp if (!got_repo_check_packidx_bloom_filter(a->repo,
622 67fd6849 2022-02-13 stsp a->packidx->path_packidx, id))
623 67fd6849 2022-02-13 stsp return NULL;
624 67fd6849 2022-02-13 stsp
625 67fd6849 2022-02-13 stsp obj_idx = got_packidx_get_object_idx(a->packidx, id);
626 67fd6849 2022-02-13 stsp if (obj_idx == -1)
627 67fd6849 2022-02-13 stsp return NULL;
628 67fd6849 2022-02-13 stsp
629 67fd6849 2022-02-13 stsp /* TODO:
630 67fd6849 2022-02-13 stsp * Opening and closing an object just to check its flags
631 67fd6849 2022-02-13 stsp * is a bit expensive. We could have an imsg which requests
632 67fd6849 2022-02-13 stsp * plain type/size information for an object without doing
633 67fd6849 2022-02-13 stsp * work such as traversing the object's entire delta chain
634 67fd6849 2022-02-13 stsp * to find the base object type, and other such info which
635 67fd6849 2022-02-13 stsp * we don't really need here.
636 67fd6849 2022-02-13 stsp */
637 67fd6849 2022-02-13 stsp err = got_object_open_from_packfile(&obj, &m->id, a->pack,
638 67fd6849 2022-02-13 stsp a->packidx, obj_idx, a->repo);
639 67fd6849 2022-02-13 stsp if (err)
640 67fd6849 2022-02-13 stsp return err;
641 67fd6849 2022-02-13 stsp
642 67fd6849 2022-02-13 stsp if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) {
643 67fd6849 2022-02-13 stsp reuse_delta(obj_idx, m, a->v, a->idset, a->pack, a->packidx,
644 67fd6849 2022-02-13 stsp a->delta_cache_fd, a->repo);
645 67fd6849 2022-02-13 stsp if (err)
646 67fd6849 2022-02-13 stsp goto done;
647 67fd6849 2022-02-13 stsp err = report_progress(a->progress_cb, a->progress_arg, a->rl,
648 b8af7c06 2022-03-15 stsp a->ncolored, a->nfound, a->ntrees, 0L, a->ncommits,
649 b8af7c06 2022-03-15 stsp got_object_idset_num_elements(a->idset), a->v->nmeta, 0);
650 67fd6849 2022-02-13 stsp }
651 67fd6849 2022-02-13 stsp done:
652 67fd6849 2022-02-13 stsp got_object_close(obj);
653 67fd6849 2022-02-13 stsp return err;
654 67fd6849 2022-02-13 stsp }
655 67fd6849 2022-02-13 stsp
656 67fd6849 2022-02-13 stsp static const struct got_error *
657 67fd6849 2022-02-13 stsp search_deltas(struct got_pack_metavec *v, struct got_object_idset *idset,
658 b8af7c06 2022-03-15 stsp int delta_cache_fd, int ncolored, int nfound, int ntrees, int ncommits,
659 b8af7c06 2022-03-15 stsp struct got_repository *repo,
660 67fd6849 2022-02-13 stsp got_pack_progress_cb progress_cb, void *progress_arg,
661 67fd6849 2022-02-13 stsp struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
662 67fd6849 2022-02-13 stsp {
663 67fd6849 2022-02-13 stsp const struct got_error *err = NULL;
664 67fd6849 2022-02-13 stsp char *path_packfile = NULL;
665 67fd6849 2022-02-13 stsp struct got_packidx *packidx;
666 67fd6849 2022-02-13 stsp struct got_pack *pack;
667 67fd6849 2022-02-13 stsp struct search_deltas_arg sda;
668 67fd6849 2022-02-13 stsp
669 67fd6849 2022-02-13 stsp err = find_pack_for_reuse(&packidx, repo);
670 67fd6849 2022-02-13 stsp if (err)
671 67fd6849 2022-02-13 stsp return err;
672 67fd6849 2022-02-13 stsp
673 67fd6849 2022-02-13 stsp if (packidx == NULL)
674 67fd6849 2022-02-13 stsp return NULL;
675 67fd6849 2022-02-13 stsp
676 67fd6849 2022-02-13 stsp err = got_packidx_get_packfile_path(&path_packfile,
677 67fd6849 2022-02-13 stsp packidx->path_packidx);
678 67fd6849 2022-02-13 stsp if (err)
679 67fd6849 2022-02-13 stsp return err;
680 67fd6849 2022-02-13 stsp
681 67fd6849 2022-02-13 stsp pack = got_repo_get_cached_pack(repo, path_packfile);
682 67fd6849 2022-02-13 stsp if (pack == NULL) {
683 67fd6849 2022-02-13 stsp err = got_repo_cache_pack(&pack, repo, path_packfile, packidx);
684 67fd6849 2022-02-13 stsp if (err)
685 67fd6849 2022-02-13 stsp goto done;
686 67fd6849 2022-02-13 stsp }
687 67fd6849 2022-02-13 stsp
688 67fd6849 2022-02-13 stsp sda.packidx = packidx;
689 67fd6849 2022-02-13 stsp sda.pack = pack;
690 67fd6849 2022-02-13 stsp sda.idset = idset;
691 67fd6849 2022-02-13 stsp sda.v = v;
692 67fd6849 2022-02-13 stsp sda.delta_cache_fd = delta_cache_fd;
693 67fd6849 2022-02-13 stsp sda.repo = repo;
694 67fd6849 2022-02-13 stsp sda.progress_cb = progress_cb;
695 67fd6849 2022-02-13 stsp sda.progress_arg = progress_arg;
696 67fd6849 2022-02-13 stsp sda.rl = rl;
697 67fd6849 2022-02-13 stsp sda.cancel_cb = cancel_cb;
698 67fd6849 2022-02-13 stsp sda.cancel_arg = cancel_arg;
699 b8af7c06 2022-03-15 stsp sda.ncolored = ncolored;
700 b8af7c06 2022-03-15 stsp sda.nfound = nfound;
701 b8af7c06 2022-03-15 stsp sda.ntrees = ntrees;
702 67fd6849 2022-02-13 stsp sda.ncommits = ncommits;
703 67fd6849 2022-02-13 stsp err = got_object_idset_for_each(idset, search_delta_for_object, &sda);
704 67fd6849 2022-02-13 stsp done:
705 67fd6849 2022-02-13 stsp free(path_packfile);
706 67fd6849 2022-02-13 stsp return err;
707 67fd6849 2022-02-13 stsp }
708 67fd6849 2022-02-13 stsp
709 67fd6849 2022-02-13 stsp static const struct got_error *
710 b8af7c06 2022-03-15 stsp pick_deltas(struct got_pack_meta **meta, int nmeta, int ncolored,
711 b8af7c06 2022-03-15 stsp int nfound, int ntrees, int ncommits, int nreused, FILE *delta_cache,
712 b8af7c06 2022-03-15 stsp struct got_repository *repo,
713 05118f5a 2021-06-22 stsp got_pack_progress_cb progress_cb, void *progress_arg,
714 211cfef0 2022-01-05 stsp struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
715 e6bcace5 2021-06-22 stsp {
716 e6bcace5 2021-06-22 stsp const struct got_error *err = NULL;
717 e6bcace5 2021-06-22 stsp struct got_pack_meta *m = NULL, *base = NULL;
718 e6bcace5 2021-06-22 stsp struct got_raw_object *raw = NULL, *base_raw = NULL;
719 74881701 2021-10-15 stsp struct got_delta_instruction *deltas = NULL, *best_deltas = NULL;
720 5060d5a1 2022-01-10 stsp int i, j, ndeltas, best_ndeltas;
721 5060d5a1 2022-01-10 stsp off_t size, best_size;
722 4f4d853e 2021-10-24 stsp const int max_base_candidates = 3;
723 402a5ec1 2022-01-10 stsp size_t delta_memsize = 0;
724 402a5ec1 2022-01-10 stsp const size_t max_delta_memsize = 25 * GOT_DELTA_RESULT_SIZE_CACHED_MAX;
725 cc7a354a 2021-10-15 stsp int outfd = -1;
726 e6bcace5 2021-06-22 stsp
727 e6bcace5 2021-06-22 stsp qsort(meta, nmeta, sizeof(struct got_pack_meta *), delta_order_cmp);
728 e6bcace5 2021-06-22 stsp for (i = 0; i < nmeta; i++) {
729 e6bcace5 2021-06-22 stsp if (cancel_cb) {
730 e6bcace5 2021-06-22 stsp err = (*cancel_cb)(cancel_arg);
731 e6bcace5 2021-06-22 stsp if (err)
732 e6bcace5 2021-06-22 stsp break;
733 e6bcace5 2021-06-22 stsp }
734 211cfef0 2022-01-05 stsp err = report_progress(progress_cb, progress_arg, rl,
735 b8af7c06 2022-03-15 stsp ncolored, nfound, ntrees, 0L, ncommits, nreused + nmeta,
736 b8af7c06 2022-03-15 stsp nreused + i, 0);
737 211cfef0 2022-01-05 stsp if (err)
738 211cfef0 2022-01-05 stsp goto done;
739 e6bcace5 2021-06-22 stsp m = meta[i];
740 e6bcace5 2021-06-22 stsp
741 e6bcace5 2021-06-22 stsp if (m->obj_type == GOT_OBJ_TYPE_COMMIT ||
742 e6bcace5 2021-06-22 stsp m->obj_type == GOT_OBJ_TYPE_TAG)
743 e6bcace5 2021-06-22 stsp continue;
744 e6bcace5 2021-06-22 stsp
745 94dac27c 2021-10-15 stsp err = got_object_raw_open(&raw, &outfd, repo, &m->id);
746 e6bcace5 2021-06-22 stsp if (err)
747 e6bcace5 2021-06-22 stsp goto done;
748 600b755e 2021-10-14 stsp m->size = raw->size;
749 e6bcace5 2021-06-22 stsp
750 64a8571e 2022-01-07 stsp if (raw->f == NULL) {
751 64a8571e 2022-01-07 stsp err = got_deltify_init_mem(&m->dtab, raw->data,
752 64a8571e 2022-01-07 stsp raw->hdrlen, raw->size + raw->hdrlen);
753 64a8571e 2022-01-07 stsp } else {
754 64a8571e 2022-01-07 stsp err = got_deltify_init(&m->dtab, raw->f, raw->hdrlen,
755 64a8571e 2022-01-07 stsp raw->size + raw->hdrlen);
756 64a8571e 2022-01-07 stsp }
757 e6bcace5 2021-06-22 stsp if (err)
758 e6bcace5 2021-06-22 stsp goto done;
759 e6bcace5 2021-06-22 stsp
760 e6bcace5 2021-06-22 stsp if (i > max_base_candidates) {
761 e6bcace5 2021-06-22 stsp struct got_pack_meta *n = NULL;
762 e6bcace5 2021-06-22 stsp n = meta[i - (max_base_candidates + 1)];
763 e6bcace5 2021-06-22 stsp got_deltify_free(n->dtab);
764 e6bcace5 2021-06-22 stsp n->dtab = NULL;
765 e6bcace5 2021-06-22 stsp }
766 e6bcace5 2021-06-22 stsp
767 74881701 2021-10-15 stsp best_size = raw->size;
768 74881701 2021-10-15 stsp best_ndeltas = 0;
769 e6bcace5 2021-06-22 stsp for (j = MAX(0, i - max_base_candidates); j < i; j++) {
770 e6bcace5 2021-06-22 stsp if (cancel_cb) {
771 e6bcace5 2021-06-22 stsp err = (*cancel_cb)(cancel_arg);
772 e6bcace5 2021-06-22 stsp if (err)
773 e6bcace5 2021-06-22 stsp goto done;
774 e6bcace5 2021-06-22 stsp }
775 e6bcace5 2021-06-22 stsp base = meta[j];
776 e6bcace5 2021-06-22 stsp /* long chains make unpacking slow, avoid such bases */
777 22edbce7 2021-10-24 stsp if (base->nchain >= 128 ||
778 e6bcace5 2021-06-22 stsp base->obj_type != m->obj_type)
779 e6bcace5 2021-06-22 stsp continue;
780 e6bcace5 2021-06-22 stsp
781 d3c116bf 2021-10-15 stsp err = got_object_raw_open(&base_raw, &outfd, repo,
782 94dac27c 2021-10-15 stsp &base->id);
783 e6bcace5 2021-06-22 stsp if (err)
784 e6bcace5 2021-06-22 stsp goto done;
785 67fd6849 2022-02-13 stsp
786 64a8571e 2022-01-07 stsp if (raw->f == NULL && base_raw->f == NULL) {
787 64a8571e 2022-01-07 stsp err = got_deltify_mem_mem(&deltas, &ndeltas,
788 64a8571e 2022-01-07 stsp raw->data, raw->hdrlen,
789 64a8571e 2022-01-07 stsp raw->size + raw->hdrlen,
790 64a8571e 2022-01-07 stsp base->dtab, base_raw->data,
791 64a8571e 2022-01-07 stsp base_raw->hdrlen,
792 64a8571e 2022-01-07 stsp base_raw->size + base_raw->hdrlen);
793 64a8571e 2022-01-07 stsp } else if (raw->f == NULL) {
794 64a8571e 2022-01-07 stsp err = got_deltify_mem_file(&deltas, &ndeltas,
795 64a8571e 2022-01-07 stsp raw->data, raw->hdrlen,
796 64a8571e 2022-01-07 stsp raw->size + raw->hdrlen,
797 64a8571e 2022-01-07 stsp base->dtab, base_raw->f,
798 64a8571e 2022-01-07 stsp base_raw->hdrlen,
799 64a8571e 2022-01-07 stsp base_raw->size + base_raw->hdrlen);
800 64a8571e 2022-01-07 stsp } else if (base_raw->f == NULL) {
801 64a8571e 2022-01-07 stsp err = got_deltify_file_mem(&deltas, &ndeltas,
802 64a8571e 2022-01-07 stsp raw->f, raw->hdrlen,
803 64a8571e 2022-01-07 stsp raw->size + raw->hdrlen,
804 64a8571e 2022-01-07 stsp base->dtab, base_raw->data,
805 64a8571e 2022-01-07 stsp base_raw->hdrlen,
806 64a8571e 2022-01-07 stsp base_raw->size + base_raw->hdrlen);
807 64a8571e 2022-01-07 stsp } else {
808 64a8571e 2022-01-07 stsp err = got_deltify(&deltas, &ndeltas,
809 64a8571e 2022-01-07 stsp raw->f, raw->hdrlen,
810 64a8571e 2022-01-07 stsp raw->size + raw->hdrlen,
811 64a8571e 2022-01-07 stsp base->dtab, base_raw->f, base_raw->hdrlen,
812 64a8571e 2022-01-07 stsp base_raw->size + base_raw->hdrlen);
813 64a8571e 2022-01-07 stsp }
814 e6bcace5 2021-06-22 stsp got_object_raw_close(base_raw);
815 e6bcace5 2021-06-22 stsp base_raw = NULL;
816 e6bcace5 2021-06-22 stsp if (err)
817 e6bcace5 2021-06-22 stsp goto done;
818 e6bcace5 2021-06-22 stsp
819 e6bcace5 2021-06-22 stsp size = delta_size(deltas, ndeltas);
820 74881701 2021-10-15 stsp if (size + 32 < best_size){
821 e6bcace5 2021-06-22 stsp /*
822 e6bcace5 2021-06-22 stsp * if we already picked a best delta,
823 e6bcace5 2021-06-22 stsp * replace it.
824 e6bcace5 2021-06-22 stsp */
825 74881701 2021-10-15 stsp best_size = size;
826 74881701 2021-10-15 stsp free(best_deltas);
827 74881701 2021-10-15 stsp best_deltas = deltas;
828 74881701 2021-10-15 stsp best_ndeltas = ndeltas;
829 74881701 2021-10-15 stsp deltas = NULL;
830 e6bcace5 2021-06-22 stsp m->nchain = base->nchain + 1;
831 e6bcace5 2021-06-22 stsp m->prev = base;
832 e6bcace5 2021-06-22 stsp m->head = base->head;
833 e6bcace5 2021-06-22 stsp if (m->head == NULL)
834 e6bcace5 2021-06-22 stsp m->head = base;
835 e6bcace5 2021-06-22 stsp } else {
836 e6bcace5 2021-06-22 stsp free(deltas);
837 e6bcace5 2021-06-22 stsp deltas = NULL;
838 e6bcace5 2021-06-22 stsp ndeltas = 0;
839 e6bcace5 2021-06-22 stsp }
840 e6bcace5 2021-06-22 stsp }
841 e6bcace5 2021-06-22 stsp
842 74881701 2021-10-15 stsp if (best_ndeltas > 0) {
843 402a5ec1 2022-01-10 stsp if (best_size <= GOT_DELTA_RESULT_SIZE_CACHED_MAX &&
844 402a5ec1 2022-01-10 stsp delta_memsize + best_size <= max_delta_memsize) {
845 402a5ec1 2022-01-10 stsp delta_memsize += best_size;
846 5060d5a1 2022-01-10 stsp err = encode_delta_in_mem(m, raw, best_deltas,
847 5060d5a1 2022-01-10 stsp best_ndeltas, best_size, m->prev->size);
848 5060d5a1 2022-01-10 stsp } else {
849 5060d5a1 2022-01-10 stsp m->delta_offset = ftello(delta_cache);
850 5060d5a1 2022-01-10 stsp err = encode_delta(m, raw, best_deltas,
851 5060d5a1 2022-01-10 stsp best_ndeltas, m->prev->size, delta_cache);
852 5060d5a1 2022-01-10 stsp }
853 74881701 2021-10-15 stsp free(best_deltas);
854 74881701 2021-10-15 stsp best_deltas = NULL;
855 74881701 2021-10-15 stsp best_ndeltas = 0;
856 74881701 2021-10-15 stsp if (err)
857 74881701 2021-10-15 stsp goto done;
858 74881701 2021-10-15 stsp }
859 74881701 2021-10-15 stsp
860 e6bcace5 2021-06-22 stsp got_object_raw_close(raw);
861 e6bcace5 2021-06-22 stsp raw = NULL;
862 e6bcace5 2021-06-22 stsp }
863 e6bcace5 2021-06-22 stsp done:
864 e6bcace5 2021-06-22 stsp for (i = MAX(0, nmeta - max_base_candidates); i < nmeta; i++) {
865 e6bcace5 2021-06-22 stsp got_deltify_free(meta[i]->dtab);
866 e6bcace5 2021-06-22 stsp meta[i]->dtab = NULL;
867 e6bcace5 2021-06-22 stsp }
868 e6bcace5 2021-06-22 stsp if (raw)
869 e6bcace5 2021-06-22 stsp got_object_raw_close(raw);
870 e6bcace5 2021-06-22 stsp if (base_raw)
871 e6bcace5 2021-06-22 stsp got_object_raw_close(base_raw);
872 cc7a354a 2021-10-15 stsp if (outfd != -1 && close(outfd) == -1 && err == NULL)
873 cc7a354a 2021-10-15 stsp err = got_error_from_errno("close");
874 74881701 2021-10-15 stsp free(deltas);
875 74881701 2021-10-15 stsp free(best_deltas);
876 e6bcace5 2021-06-22 stsp return err;
877 e6bcace5 2021-06-22 stsp }
878 e6bcace5 2021-06-22 stsp
879 e6bcace5 2021-06-22 stsp static const struct got_error *
880 05118f5a 2021-06-22 stsp search_packidx(int *found, struct got_object_id *id,
881 05118f5a 2021-06-22 stsp struct got_repository *repo)
882 05118f5a 2021-06-22 stsp {
883 05118f5a 2021-06-22 stsp const struct got_error *err = NULL;
884 05118f5a 2021-06-22 stsp struct got_packidx *packidx = NULL;
885 05118f5a 2021-06-22 stsp int idx;
886 05118f5a 2021-06-22 stsp
887 05118f5a 2021-06-22 stsp *found = 0;
888 05118f5a 2021-06-22 stsp
889 05118f5a 2021-06-22 stsp err = got_repo_search_packidx(&packidx, &idx, repo, id);
890 05118f5a 2021-06-22 stsp if (err == NULL)
891 05118f5a 2021-06-22 stsp *found = 1; /* object is already packed */
892 05118f5a 2021-06-22 stsp else if (err->code == GOT_ERR_NO_OBJ)
893 05118f5a 2021-06-22 stsp err = NULL;
894 05118f5a 2021-06-22 stsp return err;
895 05118f5a 2021-06-22 stsp }
896 05118f5a 2021-06-22 stsp
897 05118f5a 2021-06-22 stsp static const struct got_error *
898 67fd6849 2022-02-13 stsp add_object(int want_meta, struct got_object_idset *idset,
899 e6bcace5 2021-06-22 stsp struct got_object_id *id, const char *path, int obj_type,
900 6863cbf9 2022-03-21 stsp time_t mtime, int loose_obj_only, struct got_repository *repo,
901 6863cbf9 2022-03-21 stsp int *ncolored, int *nfound, int *ntrees,
902 6863cbf9 2022-03-21 stsp got_pack_progress_cb progress_cb, void *progress_arg,
903 6863cbf9 2022-03-21 stsp struct got_ratelimit *rl)
904 e6bcace5 2021-06-22 stsp {
905 e6bcace5 2021-06-22 stsp const struct got_error *err;
906 67fd6849 2022-02-13 stsp struct got_pack_meta *m = NULL;
907 e6bcace5 2021-06-22 stsp
908 05118f5a 2021-06-22 stsp if (loose_obj_only) {
909 05118f5a 2021-06-22 stsp int is_packed;
910 05118f5a 2021-06-22 stsp err = search_packidx(&is_packed, id, repo);
911 05118f5a 2021-06-22 stsp if (err)
912 05118f5a 2021-06-22 stsp return err;
913 cdeb891a 2022-03-21 stsp if (is_packed && want_meta)
914 05118f5a 2021-06-22 stsp return NULL;
915 05118f5a 2021-06-22 stsp }
916 05118f5a 2021-06-22 stsp
917 67fd6849 2022-02-13 stsp if (want_meta) {
918 67fd6849 2022-02-13 stsp err = alloc_meta(&m, id, path, obj_type, mtime);
919 6863cbf9 2022-03-21 stsp if (err)
920 6863cbf9 2022-03-21 stsp return err;
921 6863cbf9 2022-03-21 stsp
922 6863cbf9 2022-03-21 stsp (*nfound)++;
923 6863cbf9 2022-03-21 stsp err = report_progress(progress_cb, progress_arg, rl,
924 6863cbf9 2022-03-21 stsp *ncolored, *nfound, *ntrees, 0L, 0, 0, 0, 0);
925 bb6672b6 2022-04-14 tb if (err) {
926 bb6672b6 2022-04-14 tb clear_meta(m);
927 bb6672b6 2022-04-14 tb free(m);
928 67fd6849 2022-02-13 stsp return err;
929 bb6672b6 2022-04-14 tb }
930 e6bcace5 2021-06-22 stsp }
931 e6bcace5 2021-06-22 stsp
932 bb6672b6 2022-04-14 tb err = got_object_idset_add(idset, id, m);
933 bb6672b6 2022-04-14 tb if (err) {
934 bb6672b6 2022-04-14 tb clear_meta(m);
935 bb6672b6 2022-04-14 tb free(m);
936 bb6672b6 2022-04-14 tb }
937 bb6672b6 2022-04-14 tb return err;
938 e6bcace5 2021-06-22 stsp }
939 e6bcace5 2021-06-22 stsp
940 e6bcace5 2021-06-22 stsp static const struct got_error *
941 67fd6849 2022-02-13 stsp load_tree_entries(struct got_object_id_queue *ids, int want_meta,
942 2f8438b0 2022-05-04 stsp struct got_object_idset *idset, struct got_object_idset *idset_exclude,
943 2f8438b0 2022-05-04 stsp struct got_object_id *tree_id,
944 e6bcace5 2021-06-22 stsp const char *dpath, time_t mtime, struct got_repository *repo,
945 b8af7c06 2022-03-15 stsp int loose_obj_only, int *ncolored, int *nfound, int *ntrees,
946 b8af7c06 2022-03-15 stsp got_pack_progress_cb progress_cb, void *progress_arg,
947 b8af7c06 2022-03-15 stsp struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
948 e6bcace5 2021-06-22 stsp {
949 e6bcace5 2021-06-22 stsp const struct got_error *err;
950 e6bcace5 2021-06-22 stsp struct got_tree_object *tree;
951 e6bcace5 2021-06-22 stsp char *p = NULL;
952 e6bcace5 2021-06-22 stsp int i;
953 e6bcace5 2021-06-22 stsp
954 e6bcace5 2021-06-22 stsp err = got_object_open_as_tree(&tree, repo, tree_id);
955 b8af7c06 2022-03-15 stsp if (err)
956 b8af7c06 2022-03-15 stsp return err;
957 b8af7c06 2022-03-15 stsp
958 b8af7c06 2022-03-15 stsp (*ntrees)++;
959 b8af7c06 2022-03-15 stsp err = report_progress(progress_cb, progress_arg, rl,
960 b8af7c06 2022-03-15 stsp *ncolored, *nfound, *ntrees, 0L, 0, 0, 0, 0);
961 e6bcace5 2021-06-22 stsp if (err)
962 e6bcace5 2021-06-22 stsp return err;
963 e6bcace5 2021-06-22 stsp
964 e6bcace5 2021-06-22 stsp for (i = 0; i < got_object_tree_get_nentries(tree); i++) {
965 e6bcace5 2021-06-22 stsp struct got_tree_entry *e = got_object_tree_get_entry(tree, i);
966 e6bcace5 2021-06-22 stsp struct got_object_id *id = got_tree_entry_get_id(e);
967 e6bcace5 2021-06-22 stsp mode_t mode = got_tree_entry_get_mode(e);
968 e6bcace5 2021-06-22 stsp
969 e6bcace5 2021-06-22 stsp if (cancel_cb) {
970 e6bcace5 2021-06-22 stsp err = (*cancel_cb)(cancel_arg);
971 e6bcace5 2021-06-22 stsp if (err)
972 e6bcace5 2021-06-22 stsp break;
973 e6bcace5 2021-06-22 stsp }
974 e6bcace5 2021-06-22 stsp
975 3af9de88 2021-09-22 stsp if (got_object_tree_entry_is_submodule(e) ||
976 2f8438b0 2022-05-04 stsp got_object_idset_contains(idset, id) ||
977 2f8438b0 2022-05-04 stsp got_object_idset_contains(idset_exclude, id))
978 e6bcace5 2021-06-22 stsp continue;
979 e6bcace5 2021-06-22 stsp
980 e6bcace5 2021-06-22 stsp if (asprintf(&p, "%s%s%s", dpath, dpath[0] != '\0' ? "/" : "",
981 e6bcace5 2021-06-22 stsp got_tree_entry_get_name(e)) == -1) {
982 e6bcace5 2021-06-22 stsp err = got_error_from_errno("asprintf");
983 e6bcace5 2021-06-22 stsp break;
984 e6bcace5 2021-06-22 stsp }
985 e6bcace5 2021-06-22 stsp
986 e6bcace5 2021-06-22 stsp if (S_ISDIR(mode)) {
987 e6bcace5 2021-06-22 stsp struct got_object_qid *qid;
988 e6bcace5 2021-06-22 stsp err = got_object_qid_alloc(&qid, id);
989 e6bcace5 2021-06-22 stsp if (err)
990 e6bcace5 2021-06-22 stsp break;
991 dbdddfee 2021-06-23 naddy STAILQ_INSERT_TAIL(ids, qid, entry);
992 3af9de88 2021-09-22 stsp } else if (S_ISREG(mode) || S_ISLNK(mode)) {
993 2f8438b0 2022-05-04 stsp err = add_object(want_meta,
994 2f8438b0 2022-05-04 stsp want_meta ? idset : idset_exclude, id, p,
995 6863cbf9 2022-03-21 stsp GOT_OBJ_TYPE_BLOB, mtime, loose_obj_only, repo,
996 6863cbf9 2022-03-21 stsp ncolored, nfound, ntrees,
997 6863cbf9 2022-03-21 stsp progress_cb, progress_arg, rl);
998 b8af7c06 2022-03-15 stsp if (err)
999 b8af7c06 2022-03-15 stsp break;
1000 e6bcace5 2021-06-22 stsp }
1001 e6bcace5 2021-06-22 stsp free(p);
1002 e6bcace5 2021-06-22 stsp p = NULL;
1003 e6bcace5 2021-06-22 stsp }
1004 e6bcace5 2021-06-22 stsp
1005 e6bcace5 2021-06-22 stsp got_object_tree_close(tree);
1006 e6bcace5 2021-06-22 stsp free(p);
1007 e6bcace5 2021-06-22 stsp return err;
1008 e6bcace5 2021-06-22 stsp }
1009 e6bcace5 2021-06-22 stsp
1010 e6bcace5 2021-06-22 stsp static const struct got_error *
1011 67fd6849 2022-02-13 stsp load_tree(int want_meta, struct got_object_idset *idset,
1012 2f8438b0 2022-05-04 stsp struct got_object_idset *idset_exclude,
1013 e6bcace5 2021-06-22 stsp struct got_object_id *tree_id, const char *dpath, time_t mtime,
1014 b8af7c06 2022-03-15 stsp struct got_repository *repo, int loose_obj_only,
1015 b8af7c06 2022-03-15 stsp int *ncolored, int *nfound, int *ntrees,
1016 b8af7c06 2022-03-15 stsp got_pack_progress_cb progress_cb, void *progress_arg,
1017 b8af7c06 2022-03-15 stsp struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
1018 e6bcace5 2021-06-22 stsp {
1019 e6bcace5 2021-06-22 stsp const struct got_error *err = NULL;
1020 e6bcace5 2021-06-22 stsp struct got_object_id_queue tree_ids;
1021 e6bcace5 2021-06-22 stsp struct got_object_qid *qid;
1022 e6bcace5 2021-06-22 stsp
1023 2f8438b0 2022-05-04 stsp if (got_object_idset_contains(idset, tree_id) ||
1024 2f8438b0 2022-05-04 stsp got_object_idset_contains(idset_exclude, tree_id))
1025 e6bcace5 2021-06-22 stsp return NULL;
1026 e6bcace5 2021-06-22 stsp
1027 e6bcace5 2021-06-22 stsp err = got_object_qid_alloc(&qid, tree_id);
1028 e6bcace5 2021-06-22 stsp if (err)
1029 e6bcace5 2021-06-22 stsp return err;
1030 e6bcace5 2021-06-22 stsp
1031 dbdddfee 2021-06-23 naddy STAILQ_INIT(&tree_ids);
1032 dbdddfee 2021-06-23 naddy STAILQ_INSERT_TAIL(&tree_ids, qid, entry);
1033 e6bcace5 2021-06-22 stsp
1034 dbdddfee 2021-06-23 naddy while (!STAILQ_EMPTY(&tree_ids)) {
1035 e6bcace5 2021-06-22 stsp if (cancel_cb) {
1036 e6bcace5 2021-06-22 stsp err = (*cancel_cb)(cancel_arg);
1037 e6bcace5 2021-06-22 stsp if (err)
1038 e6bcace5 2021-06-22 stsp break;
1039 e6bcace5 2021-06-22 stsp }
1040 e6bcace5 2021-06-22 stsp
1041 dbdddfee 2021-06-23 naddy qid = STAILQ_FIRST(&tree_ids);
1042 dbdddfee 2021-06-23 naddy STAILQ_REMOVE_HEAD(&tree_ids, entry);
1043 e6bcace5 2021-06-22 stsp
1044 2f8438b0 2022-05-04 stsp if (got_object_idset_contains(idset, &qid->id) ||
1045 2f8438b0 2022-05-04 stsp got_object_idset_contains(idset_exclude, &qid->id)) {
1046 e6bcace5 2021-06-22 stsp got_object_qid_free(qid);
1047 e6bcace5 2021-06-22 stsp continue;
1048 e6bcace5 2021-06-22 stsp }
1049 e6bcace5 2021-06-22 stsp
1050 2f8438b0 2022-05-04 stsp err = add_object(want_meta, want_meta ? idset : idset_exclude,
1051 2f8438b0 2022-05-04 stsp &qid->id, dpath, GOT_OBJ_TYPE_TREE,
1052 2f8438b0 2022-05-04 stsp mtime, loose_obj_only, repo,
1053 6863cbf9 2022-03-21 stsp ncolored, nfound, ntrees, progress_cb, progress_arg, rl);
1054 e6bcace5 2021-06-22 stsp if (err) {
1055 e6bcace5 2021-06-22 stsp got_object_qid_free(qid);
1056 e6bcace5 2021-06-22 stsp break;
1057 e6bcace5 2021-06-22 stsp }
1058 e6bcace5 2021-06-22 stsp
1059 2f8438b0 2022-05-04 stsp err = load_tree_entries(&tree_ids, want_meta, idset,
1060 2f8438b0 2022-05-04 stsp idset_exclude, &qid->id,
1061 b8af7c06 2022-03-15 stsp dpath, mtime, repo, loose_obj_only, ncolored, nfound,
1062 b8af7c06 2022-03-15 stsp ntrees, progress_cb, progress_arg, rl,
1063 b8af7c06 2022-03-15 stsp cancel_cb, cancel_arg);
1064 e6bcace5 2021-06-22 stsp got_object_qid_free(qid);
1065 e6bcace5 2021-06-22 stsp if (err)
1066 e6bcace5 2021-06-22 stsp break;
1067 e6bcace5 2021-06-22 stsp }
1068 e6bcace5 2021-06-22 stsp
1069 e6bcace5 2021-06-22 stsp got_object_id_queue_free(&tree_ids);
1070 e6bcace5 2021-06-22 stsp return err;
1071 e6bcace5 2021-06-22 stsp }
1072 e6bcace5 2021-06-22 stsp
1073 e6bcace5 2021-06-22 stsp static const struct got_error *
1074 67fd6849 2022-02-13 stsp load_commit(int want_meta, struct got_object_idset *idset,
1075 2f8438b0 2022-05-04 stsp struct got_object_idset *idset_exclude,
1076 05118f5a 2021-06-22 stsp struct got_object_id *id, struct got_repository *repo, int loose_obj_only,
1077 b8af7c06 2022-03-15 stsp int *ncolored, int *nfound, int *ntrees,
1078 b8af7c06 2022-03-15 stsp got_pack_progress_cb progress_cb, void *progress_arg,
1079 b8af7c06 2022-03-15 stsp struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
1080 e6bcace5 2021-06-22 stsp {
1081 e6bcace5 2021-06-22 stsp const struct got_error *err;
1082 e6bcace5 2021-06-22 stsp struct got_commit_object *commit;
1083 e6bcace5 2021-06-22 stsp
1084 2f8438b0 2022-05-04 stsp if (got_object_idset_contains(idset, id) ||
1085 2f8438b0 2022-05-04 stsp got_object_idset_contains(idset_exclude, id))
1086 e6bcace5 2021-06-22 stsp return NULL;
1087 05118f5a 2021-06-22 stsp
1088 05118f5a 2021-06-22 stsp if (loose_obj_only) {
1089 05118f5a 2021-06-22 stsp int is_packed;
1090 05118f5a 2021-06-22 stsp err = search_packidx(&is_packed, id, repo);
1091 05118f5a 2021-06-22 stsp if (err)
1092 05118f5a 2021-06-22 stsp return err;
1093 cdeb891a 2022-03-21 stsp if (is_packed && want_meta)
1094 05118f5a 2021-06-22 stsp return NULL;
1095 05118f5a 2021-06-22 stsp }
1096 e6bcace5 2021-06-22 stsp
1097 e6bcace5 2021-06-22 stsp err = got_object_open_as_commit(&commit, repo, id);
1098 e6bcace5 2021-06-22 stsp if (err)
1099 e6bcace5 2021-06-22 stsp return err;
1100 e6bcace5 2021-06-22 stsp
1101 2f8438b0 2022-05-04 stsp err = add_object(want_meta, want_meta ? idset : idset_exclude,
1102 2f8438b0 2022-05-04 stsp id, "", GOT_OBJ_TYPE_COMMIT,
1103 05118f5a 2021-06-22 stsp got_object_commit_get_committer_time(commit),
1104 6863cbf9 2022-03-21 stsp loose_obj_only, repo,
1105 6863cbf9 2022-03-21 stsp ncolored, nfound, ntrees, progress_cb, progress_arg, rl);
1106 e6bcace5 2021-06-22 stsp if (err)
1107 e6bcace5 2021-06-22 stsp goto done;
1108 b8af7c06 2022-03-15 stsp
1109 2f8438b0 2022-05-04 stsp err = load_tree(want_meta, idset, idset_exclude,
1110 2f8438b0 2022-05-04 stsp got_object_commit_get_tree_id(commit),
1111 05118f5a 2021-06-22 stsp "", got_object_commit_get_committer_time(commit),
1112 b8af7c06 2022-03-15 stsp repo, loose_obj_only, ncolored, nfound, ntrees,
1113 b8af7c06 2022-03-15 stsp progress_cb, progress_arg, rl, cancel_cb, cancel_arg);
1114 e6bcace5 2021-06-22 stsp done:
1115 e6bcace5 2021-06-22 stsp got_object_commit_close(commit);
1116 e6bcace5 2021-06-22 stsp return err;
1117 e6bcace5 2021-06-22 stsp }
1118 e6bcace5 2021-06-22 stsp
1119 05118f5a 2021-06-22 stsp static const struct got_error *
1120 67fd6849 2022-02-13 stsp load_tag(int want_meta, struct got_object_idset *idset,
1121 2f8438b0 2022-05-04 stsp struct got_object_idset *idset_exclude,
1122 05118f5a 2021-06-22 stsp struct got_object_id *id, struct got_repository *repo, int loose_obj_only,
1123 b8af7c06 2022-03-15 stsp int *ncolored, int *nfound, int *ntrees,
1124 b8af7c06 2022-03-15 stsp got_pack_progress_cb progress_cb, void *progress_arg,
1125 b8af7c06 2022-03-15 stsp struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
1126 05118f5a 2021-06-22 stsp {
1127 05118f5a 2021-06-22 stsp const struct got_error *err;
1128 05118f5a 2021-06-22 stsp struct got_tag_object *tag = NULL;
1129 05118f5a 2021-06-22 stsp
1130 2f8438b0 2022-05-04 stsp if (got_object_idset_contains(idset, id) ||
1131 2f8438b0 2022-05-04 stsp got_object_idset_contains(idset_exclude, id))
1132 05118f5a 2021-06-22 stsp return NULL;
1133 05118f5a 2021-06-22 stsp
1134 05118f5a 2021-06-22 stsp if (loose_obj_only) {
1135 05118f5a 2021-06-22 stsp int is_packed;
1136 05118f5a 2021-06-22 stsp err = search_packidx(&is_packed, id, repo);
1137 05118f5a 2021-06-22 stsp if (err)
1138 05118f5a 2021-06-22 stsp return err;
1139 cdeb891a 2022-03-21 stsp if (is_packed && want_meta)
1140 05118f5a 2021-06-22 stsp return NULL;
1141 05118f5a 2021-06-22 stsp }
1142 05118f5a 2021-06-22 stsp
1143 05118f5a 2021-06-22 stsp err = got_object_open_as_tag(&tag, repo, id);
1144 05118f5a 2021-06-22 stsp if (err)
1145 05118f5a 2021-06-22 stsp return err;
1146 05118f5a 2021-06-22 stsp
1147 2f8438b0 2022-05-04 stsp err = add_object(want_meta, want_meta ? idset : idset_exclude,
1148 2f8438b0 2022-05-04 stsp id, "", GOT_OBJ_TYPE_TAG,
1149 6863cbf9 2022-03-21 stsp got_object_tag_get_tagger_time(tag), loose_obj_only, repo,
1150 6863cbf9 2022-03-21 stsp ncolored, nfound, ntrees, progress_cb, progress_arg, rl);
1151 05118f5a 2021-06-22 stsp if (err)
1152 05118f5a 2021-06-22 stsp goto done;
1153 05118f5a 2021-06-22 stsp
1154 05118f5a 2021-06-22 stsp switch (got_object_tag_get_object_type(tag)) {
1155 05118f5a 2021-06-22 stsp case GOT_OBJ_TYPE_COMMIT:
1156 2f8438b0 2022-05-04 stsp err = load_commit(want_meta, idset, idset_exclude,
1157 b8af7c06 2022-03-15 stsp got_object_tag_get_object_id(tag), repo, loose_obj_only,
1158 b8af7c06 2022-03-15 stsp ncolored, nfound, ntrees, progress_cb, progress_arg, rl,
1159 b8af7c06 2022-03-15 stsp cancel_cb, cancel_arg);
1160 05118f5a 2021-06-22 stsp break;
1161 05118f5a 2021-06-22 stsp case GOT_OBJ_TYPE_TREE:
1162 2f8438b0 2022-05-04 stsp err = load_tree(want_meta, idset, idset_exclude,
1163 67fd6849 2022-02-13 stsp got_object_tag_get_object_id(tag), "",
1164 b8af7c06 2022-03-15 stsp got_object_tag_get_tagger_time(tag), repo, loose_obj_only,
1165 b8af7c06 2022-03-15 stsp ncolored, nfound, ntrees, progress_cb, progress_arg, rl,
1166 b8af7c06 2022-03-15 stsp cancel_cb, cancel_arg);
1167 05118f5a 2021-06-22 stsp break;
1168 05118f5a 2021-06-22 stsp default:
1169 05118f5a 2021-06-22 stsp break;
1170 05118f5a 2021-06-22 stsp }
1171 05118f5a 2021-06-22 stsp
1172 05118f5a 2021-06-22 stsp done:
1173 05118f5a 2021-06-22 stsp got_object_tag_close(tag);
1174 05118f5a 2021-06-22 stsp return err;
1175 05118f5a 2021-06-22 stsp }
1176 05118f5a 2021-06-22 stsp
1177 e6bcace5 2021-06-22 stsp enum findtwixt_color {
1178 e6bcace5 2021-06-22 stsp COLOR_KEEP = 0,
1179 e6bcace5 2021-06-22 stsp COLOR_DROP,
1180 e6bcace5 2021-06-22 stsp COLOR_BLANK,
1181 70f8f24d 2022-04-14 stsp COLOR_SKIP,
1182 e6bcace5 2021-06-22 stsp };
1183 70f8f24d 2022-04-14 stsp
1184 e6bcace5 2021-06-22 stsp static const int findtwixt_colors[] = {
1185 e6bcace5 2021-06-22 stsp COLOR_KEEP,
1186 e6bcace5 2021-06-22 stsp COLOR_DROP,
1187 70f8f24d 2022-04-14 stsp COLOR_BLANK,
1188 70f8f24d 2022-04-14 stsp COLOR_SKIP,
1189 e6bcace5 2021-06-22 stsp };
1190 e6bcace5 2021-06-22 stsp
1191 e6bcace5 2021-06-22 stsp static const struct got_error *
1192 70f8f24d 2022-04-14 stsp paint_commit(struct got_object_qid *qid, int color)
1193 e6bcace5 2021-06-22 stsp {
1194 70f8f24d 2022-04-14 stsp if (color < 0 || color >= nitems(findtwixt_colors))
1195 70f8f24d 2022-04-14 stsp return got_error(GOT_ERR_RANGE);
1196 e6bcace5 2021-06-22 stsp
1197 e6bcace5 2021-06-22 stsp qid->data = (void *)&findtwixt_colors[color];
1198 e6bcace5 2021-06-22 stsp return NULL;
1199 e6bcace5 2021-06-22 stsp }
1200 e6bcace5 2021-06-22 stsp
1201 e6bcace5 2021-06-22 stsp static const struct got_error *
1202 70f8f24d 2022-04-14 stsp queue_commit_id(struct got_object_id_queue *ids, struct got_object_id *id,
1203 70f8f24d 2022-04-14 stsp int color, struct got_repository *repo)
1204 e6bcace5 2021-06-22 stsp {
1205 70f8f24d 2022-04-14 stsp const struct got_error *err;
1206 e6bcace5 2021-06-22 stsp struct got_object_qid *qid;
1207 e6bcace5 2021-06-22 stsp
1208 e6bcace5 2021-06-22 stsp err = got_object_qid_alloc(&qid, id);
1209 e6bcace5 2021-06-22 stsp if (err)
1210 e6bcace5 2021-06-22 stsp return err;
1211 e6bcace5 2021-06-22 stsp
1212 70f8f24d 2022-04-14 stsp STAILQ_INSERT_TAIL(ids, qid, entry);
1213 70f8f24d 2022-04-14 stsp return paint_commit(qid, color);
1214 e6bcace5 2021-06-22 stsp }
1215 e6bcace5 2021-06-22 stsp
1216 e6bcace5 2021-06-22 stsp struct append_id_arg {
1217 e6bcace5 2021-06-22 stsp struct got_object_id **array;
1218 e6bcace5 2021-06-22 stsp int idx;
1219 70f8f24d 2022-04-14 stsp struct got_object_idset *drop;
1220 70f8f24d 2022-04-14 stsp struct got_object_idset *skip;
1221 e6bcace5 2021-06-22 stsp };
1222 e6bcace5 2021-06-22 stsp
1223 e6bcace5 2021-06-22 stsp static const struct got_error *
1224 e6bcace5 2021-06-22 stsp append_id(struct got_object_id *id, void *data, void *arg)
1225 e6bcace5 2021-06-22 stsp {
1226 e6bcace5 2021-06-22 stsp struct append_id_arg *a = arg;
1227 e6bcace5 2021-06-22 stsp
1228 70f8f24d 2022-04-14 stsp if (got_object_idset_contains(a->skip, id) ||
1229 70f8f24d 2022-04-14 stsp got_object_idset_contains(a->drop, id))
1230 70f8f24d 2022-04-14 stsp return NULL;
1231 70f8f24d 2022-04-14 stsp
1232 70f8f24d 2022-04-14 stsp a->array[++a->idx] = got_object_id_dup(id);
1233 e6bcace5 2021-06-22 stsp if (a->array[a->idx] == NULL)
1234 e6bcace5 2021-06-22 stsp return got_error_from_errno("got_object_id_dup");
1235 e6bcace5 2021-06-22 stsp
1236 e6bcace5 2021-06-22 stsp return NULL;
1237 29e0594f 2022-04-09 stsp }
1238 29e0594f 2022-04-09 stsp
1239 29e0594f 2022-04-09 stsp static const struct got_error *
1240 29e0594f 2022-04-09 stsp queue_commit_or_tag_id(struct got_object_id *id, int color,
1241 29e0594f 2022-04-09 stsp struct got_object_id_queue *ids, struct got_repository *repo)
1242 29e0594f 2022-04-09 stsp {
1243 29e0594f 2022-04-09 stsp const struct got_error *err;
1244 29e0594f 2022-04-09 stsp struct got_tag_object *tag = NULL;
1245 29e0594f 2022-04-09 stsp int obj_type;
1246 29e0594f 2022-04-09 stsp
1247 29e0594f 2022-04-09 stsp err = got_object_get_type(&obj_type, repo, id);
1248 29e0594f 2022-04-09 stsp if (err)
1249 29e0594f 2022-04-09 stsp return err;
1250 29e0594f 2022-04-09 stsp
1251 29e0594f 2022-04-09 stsp if (obj_type == GOT_OBJ_TYPE_TAG) {
1252 29e0594f 2022-04-09 stsp err = got_object_open_as_tag(&tag, repo, id);
1253 29e0594f 2022-04-09 stsp if (err)
1254 29e0594f 2022-04-09 stsp return err;
1255 29e0594f 2022-04-09 stsp obj_type = got_object_tag_get_object_type(tag);
1256 29e0594f 2022-04-09 stsp id = got_object_tag_get_object_id(tag);
1257 29e0594f 2022-04-09 stsp }
1258 29e0594f 2022-04-09 stsp
1259 29e0594f 2022-04-09 stsp if (obj_type == GOT_OBJ_TYPE_COMMIT) {
1260 29e0594f 2022-04-09 stsp err = queue_commit_id(ids, id, color, repo);
1261 29e0594f 2022-04-09 stsp if (err)
1262 29e0594f 2022-04-09 stsp goto done;
1263 29e0594f 2022-04-09 stsp }
1264 29e0594f 2022-04-09 stsp done:
1265 29e0594f 2022-04-09 stsp if (tag)
1266 29e0594f 2022-04-09 stsp got_object_tag_close(tag);
1267 29e0594f 2022-04-09 stsp return err;
1268 e6bcace5 2021-06-22 stsp }
1269 e6bcace5 2021-06-22 stsp
1270 e6bcace5 2021-06-22 stsp static const struct got_error *
1271 70f8f24d 2022-04-14 stsp paint_commits(int *ncolored, struct got_object_id_queue *ids, int nids,
1272 14dbbf48 2022-04-10 stsp struct got_object_idset *keep, struct got_object_idset *drop,
1273 70f8f24d 2022-04-14 stsp struct got_object_idset *skip, struct got_repository *repo,
1274 b8af7c06 2022-03-15 stsp got_pack_progress_cb progress_cb, void *progress_arg,
1275 b8af7c06 2022-03-15 stsp struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
1276 e6bcace5 2021-06-22 stsp {
1277 e6bcace5 2021-06-22 stsp const struct got_error *err = NULL;
1278 14dbbf48 2022-04-10 stsp struct got_commit_object *commit = NULL;
1279 70f8f24d 2022-04-14 stsp const struct got_object_id_queue *parents;
1280 e6bcace5 2021-06-22 stsp struct got_object_qid *qid;
1281 70f8f24d 2022-04-14 stsp int nqueued = nids, nskip = 0;
1282 e6bcace5 2021-06-22 stsp
1283 70f8f24d 2022-04-14 stsp while (!STAILQ_EMPTY(ids) && nskip != nqueued) {
1284 70f8f24d 2022-04-14 stsp int color;
1285 03c03172 2022-04-10 stsp
1286 57bc7b6d 2022-04-10 stsp if (cancel_cb) {
1287 57bc7b6d 2022-04-10 stsp err = cancel_cb(cancel_arg);
1288 57bc7b6d 2022-04-10 stsp if (err)
1289 14dbbf48 2022-04-10 stsp break;
1290 57bc7b6d 2022-04-10 stsp }
1291 57bc7b6d 2022-04-10 stsp
1292 14dbbf48 2022-04-10 stsp qid = STAILQ_FIRST(ids);
1293 70f8f24d 2022-04-14 stsp STAILQ_REMOVE_HEAD(ids, entry);
1294 70f8f24d 2022-04-14 stsp nqueued--;
1295 70f8f24d 2022-04-14 stsp color = *((int *)qid->data);
1296 70f8f24d 2022-04-14 stsp if (color == COLOR_SKIP)
1297 70f8f24d 2022-04-14 stsp nskip--;
1298 e6bcace5 2021-06-22 stsp
1299 d7b5a0e8 2022-04-20 stsp if (got_object_idset_contains(skip, &qid->id)) {
1300 70f8f24d 2022-04-14 stsp got_object_qid_free(qid);
1301 70f8f24d 2022-04-14 stsp continue;
1302 70f8f24d 2022-04-14 stsp }
1303 b8af7c06 2022-03-15 stsp
1304 70f8f24d 2022-04-14 stsp switch (color) {
1305 70f8f24d 2022-04-14 stsp case COLOR_KEEP:
1306 d7b5a0e8 2022-04-20 stsp if (got_object_idset_contains(keep, &qid->id)) {
1307 70f8f24d 2022-04-14 stsp got_object_qid_free(qid);
1308 70f8f24d 2022-04-14 stsp continue;
1309 70f8f24d 2022-04-14 stsp }
1310 d7b5a0e8 2022-04-20 stsp if (got_object_idset_contains(drop, &qid->id)) {
1311 70f8f24d 2022-04-14 stsp err = paint_commit(qid, COLOR_SKIP);
1312 70f8f24d 2022-04-14 stsp if (err)
1313 70f8f24d 2022-04-14 stsp goto done;
1314 70f8f24d 2022-04-14 stsp nskip++;
1315 70f8f24d 2022-04-14 stsp } else
1316 70f8f24d 2022-04-14 stsp (*ncolored)++;
1317 d7b5a0e8 2022-04-20 stsp err = got_object_idset_add(keep, &qid->id, NULL);
1318 70f8f24d 2022-04-14 stsp if (err)
1319 70f8f24d 2022-04-14 stsp goto done;
1320 70f8f24d 2022-04-14 stsp break;
1321 70f8f24d 2022-04-14 stsp case COLOR_DROP:
1322 d7b5a0e8 2022-04-20 stsp if (got_object_idset_contains(drop, &qid->id)) {
1323 70f8f24d 2022-04-14 stsp got_object_qid_free(qid);
1324 70f8f24d 2022-04-14 stsp continue;
1325 70f8f24d 2022-04-14 stsp }
1326 d7b5a0e8 2022-04-20 stsp if (got_object_idset_contains(keep, &qid->id)) {
1327 70f8f24d 2022-04-14 stsp err = paint_commit(qid, COLOR_SKIP);
1328 70f8f24d 2022-04-14 stsp if (err)
1329 70f8f24d 2022-04-14 stsp goto done;
1330 70f8f24d 2022-04-14 stsp nskip++;
1331 70f8f24d 2022-04-14 stsp } else
1332 70f8f24d 2022-04-14 stsp (*ncolored)++;
1333 d7b5a0e8 2022-04-20 stsp err = got_object_idset_add(drop, &qid->id, NULL);
1334 70f8f24d 2022-04-14 stsp if (err)
1335 70f8f24d 2022-04-14 stsp goto done;
1336 70f8f24d 2022-04-14 stsp break;
1337 70f8f24d 2022-04-14 stsp case COLOR_SKIP:
1338 d7b5a0e8 2022-04-20 stsp if (!got_object_idset_contains(skip, &qid->id)) {
1339 d7b5a0e8 2022-04-20 stsp err = got_object_idset_add(skip, &qid->id,
1340 d7b5a0e8 2022-04-20 stsp NULL);
1341 70f8f24d 2022-04-14 stsp if (err)
1342 70f8f24d 2022-04-14 stsp goto done;
1343 70f8f24d 2022-04-14 stsp }
1344 70f8f24d 2022-04-14 stsp break;
1345 70f8f24d 2022-04-14 stsp default:
1346 70f8f24d 2022-04-14 stsp /* should not happen */
1347 70f8f24d 2022-04-14 stsp err = got_error_fmt(GOT_ERR_NOT_IMPL,
1348 70f8f24d 2022-04-14 stsp "%s invalid commit color %d", __func__, color);
1349 70f8f24d 2022-04-14 stsp goto done;
1350 70f8f24d 2022-04-14 stsp }
1351 70f8f24d 2022-04-14 stsp
1352 b8af7c06 2022-03-15 stsp err = report_progress(progress_cb, progress_arg, rl,
1353 b8af7c06 2022-03-15 stsp *ncolored, 0, 0, 0L, 0, 0, 0, 0);
1354 b8af7c06 2022-03-15 stsp if (err)
1355 14dbbf48 2022-04-10 stsp break;
1356 e6bcace5 2021-06-22 stsp
1357 e6bcace5 2021-06-22 stsp
1358 d7b5a0e8 2022-04-20 stsp err = got_object_open_as_commit(&commit, repo, &qid->id);
1359 70f8f24d 2022-04-14 stsp if (err)
1360 70f8f24d 2022-04-14 stsp break;
1361 e6bcace5 2021-06-22 stsp
1362 70f8f24d 2022-04-14 stsp parents = got_object_commit_get_parent_ids(commit);
1363 70f8f24d 2022-04-14 stsp if (parents) {
1364 70f8f24d 2022-04-14 stsp struct got_object_qid *pid;
1365 70f8f24d 2022-04-14 stsp color = *((int *)qid->data);
1366 70f8f24d 2022-04-14 stsp STAILQ_FOREACH(pid, parents, entry) {
1367 d7b5a0e8 2022-04-20 stsp err = queue_commit_id(ids, &pid->id, color,
1368 70f8f24d 2022-04-14 stsp repo);
1369 70f8f24d 2022-04-14 stsp if (err)
1370 70f8f24d 2022-04-14 stsp break;
1371 70f8f24d 2022-04-14 stsp nqueued++;
1372 70f8f24d 2022-04-14 stsp if (color == COLOR_SKIP)
1373 70f8f24d 2022-04-14 stsp nskip++;
1374 e6bcace5 2021-06-22 stsp }
1375 e6bcace5 2021-06-22 stsp }
1376 e6bcace5 2021-06-22 stsp
1377 70f8f24d 2022-04-14 stsp got_object_commit_close(commit);
1378 70f8f24d 2022-04-14 stsp commit = NULL;
1379 e6bcace5 2021-06-22 stsp got_object_qid_free(qid);
1380 e6bcace5 2021-06-22 stsp }
1381 70f8f24d 2022-04-14 stsp done:
1382 14dbbf48 2022-04-10 stsp if (commit)
1383 14dbbf48 2022-04-10 stsp got_object_commit_close(commit);
1384 14dbbf48 2022-04-10 stsp return err;
1385 14dbbf48 2022-04-10 stsp }
1386 14dbbf48 2022-04-10 stsp
1387 14dbbf48 2022-04-10 stsp static const struct got_error *
1388 14dbbf48 2022-04-10 stsp findtwixt(struct got_object_id ***res, int *nres, int *ncolored,
1389 14dbbf48 2022-04-10 stsp struct got_object_id **head, int nhead,
1390 14dbbf48 2022-04-10 stsp struct got_object_id **tail, int ntail,
1391 14dbbf48 2022-04-10 stsp struct got_repository *repo,
1392 14dbbf48 2022-04-10 stsp got_pack_progress_cb progress_cb, void *progress_arg,
1393 14dbbf48 2022-04-10 stsp struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
1394 14dbbf48 2022-04-10 stsp {
1395 14dbbf48 2022-04-10 stsp const struct got_error *err = NULL;
1396 14dbbf48 2022-04-10 stsp struct got_object_id_queue ids;
1397 70f8f24d 2022-04-14 stsp struct got_object_idset *keep, *drop, *skip = NULL;
1398 14dbbf48 2022-04-10 stsp int i, nkeep;
1399 14dbbf48 2022-04-10 stsp
1400 14dbbf48 2022-04-10 stsp STAILQ_INIT(&ids);
1401 14dbbf48 2022-04-10 stsp *res = NULL;
1402 14dbbf48 2022-04-10 stsp *nres = 0;
1403 14dbbf48 2022-04-10 stsp *ncolored = 0;
1404 14dbbf48 2022-04-10 stsp
1405 14dbbf48 2022-04-10 stsp keep = got_object_idset_alloc();
1406 14dbbf48 2022-04-10 stsp if (keep == NULL)
1407 14dbbf48 2022-04-10 stsp return got_error_from_errno("got_object_idset_alloc");
1408 14dbbf48 2022-04-10 stsp
1409 14dbbf48 2022-04-10 stsp drop = got_object_idset_alloc();
1410 14dbbf48 2022-04-10 stsp if (drop == NULL) {
1411 14dbbf48 2022-04-10 stsp err = got_error_from_errno("got_object_idset_alloc");
1412 14dbbf48 2022-04-10 stsp goto done;
1413 14dbbf48 2022-04-10 stsp }
1414 14dbbf48 2022-04-10 stsp
1415 70f8f24d 2022-04-14 stsp skip = got_object_idset_alloc();
1416 70f8f24d 2022-04-14 stsp if (skip == NULL) {
1417 70f8f24d 2022-04-14 stsp err = got_error_from_errno("got_object_idset_alloc");
1418 70f8f24d 2022-04-14 stsp goto done;
1419 70f8f24d 2022-04-14 stsp }
1420 70f8f24d 2022-04-14 stsp
1421 14dbbf48 2022-04-10 stsp for (i = 0; i < nhead; i++) {
1422 14dbbf48 2022-04-10 stsp struct got_object_id *id = head[i];
1423 14dbbf48 2022-04-10 stsp if (id == NULL)
1424 14dbbf48 2022-04-10 stsp continue;
1425 fbafdecf 2022-04-10 stsp err = queue_commit_or_tag_id(id, COLOR_KEEP, &ids, repo);
1426 14dbbf48 2022-04-10 stsp if (err)
1427 14dbbf48 2022-04-10 stsp goto done;
1428 14dbbf48 2022-04-10 stsp }
1429 14dbbf48 2022-04-10 stsp
1430 14dbbf48 2022-04-10 stsp for (i = 0; i < ntail; i++) {
1431 14dbbf48 2022-04-10 stsp struct got_object_id *id = tail[i];
1432 14dbbf48 2022-04-10 stsp if (id == NULL)
1433 14dbbf48 2022-04-10 stsp continue;
1434 14dbbf48 2022-04-10 stsp err = queue_commit_or_tag_id(id, COLOR_DROP, &ids, repo);
1435 14dbbf48 2022-04-10 stsp if (err)
1436 14dbbf48 2022-04-10 stsp goto done;
1437 14dbbf48 2022-04-10 stsp }
1438 14dbbf48 2022-04-10 stsp
1439 70f8f24d 2022-04-14 stsp err = paint_commits(ncolored, &ids, nhead + ntail,
1440 70f8f24d 2022-04-14 stsp keep, drop, skip, repo, progress_cb, progress_arg, rl,
1441 70f8f24d 2022-04-14 stsp cancel_cb, cancel_arg);
1442 14dbbf48 2022-04-10 stsp if (err)
1443 14dbbf48 2022-04-10 stsp goto done;
1444 14dbbf48 2022-04-10 stsp
1445 e6bcace5 2021-06-22 stsp nkeep = got_object_idset_num_elements(keep);
1446 e6bcace5 2021-06-22 stsp if (nkeep > 0) {
1447 e6bcace5 2021-06-22 stsp struct append_id_arg arg;
1448 e6bcace5 2021-06-22 stsp arg.array = calloc(nkeep, sizeof(struct got_object_id *));
1449 e6bcace5 2021-06-22 stsp if (arg.array == NULL) {
1450 e6bcace5 2021-06-22 stsp err = got_error_from_errno("calloc");
1451 e6bcace5 2021-06-22 stsp goto done;
1452 e6bcace5 2021-06-22 stsp }
1453 70f8f24d 2022-04-14 stsp arg.idx = -1;
1454 70f8f24d 2022-04-14 stsp arg.skip = skip;
1455 70f8f24d 2022-04-14 stsp arg.drop = drop;
1456 e6bcace5 2021-06-22 stsp err = got_object_idset_for_each(keep, append_id, &arg);
1457 e6bcace5 2021-06-22 stsp if (err) {
1458 e6bcace5 2021-06-22 stsp free(arg.array);
1459 e6bcace5 2021-06-22 stsp goto done;
1460 e6bcace5 2021-06-22 stsp }
1461 e6bcace5 2021-06-22 stsp *res = arg.array;
1462 70f8f24d 2022-04-14 stsp *nres = arg.idx + 1;
1463 e6bcace5 2021-06-22 stsp }
1464 e6bcace5 2021-06-22 stsp done:
1465 e6bcace5 2021-06-22 stsp got_object_idset_free(keep);
1466 e6bcace5 2021-06-22 stsp got_object_idset_free(drop);
1467 70f8f24d 2022-04-14 stsp if (skip)
1468 70f8f24d 2022-04-14 stsp got_object_idset_free(skip);
1469 e6bcace5 2021-06-22 stsp got_object_id_queue_free(&ids);
1470 e6bcace5 2021-06-22 stsp return err;
1471 e6bcace5 2021-06-22 stsp }
1472 e6bcace5 2021-06-22 stsp
1473 e6bcace5 2021-06-22 stsp static const struct got_error *
1474 b8af7c06 2022-03-15 stsp load_object_ids(int *ncolored, int *nfound, int *ntrees,
1475 b8af7c06 2022-03-15 stsp struct got_object_idset *idset, struct got_object_id **theirs, int ntheirs,
1476 e6bcace5 2021-06-22 stsp struct got_object_id **ours, int nours, struct got_repository *repo,
1477 b8af7c06 2022-03-15 stsp int loose_obj_only, got_pack_progress_cb progress_cb, void *progress_arg,
1478 b8af7c06 2022-03-15 stsp struct got_ratelimit *rl, got_cancel_cb cancel_cb, void *cancel_arg)
1479 e6bcace5 2021-06-22 stsp {
1480 e6bcace5 2021-06-22 stsp const struct got_error *err = NULL;
1481 e6bcace5 2021-06-22 stsp struct got_object_id **ids = NULL;
1482 05118f5a 2021-06-22 stsp int i, nobj = 0, obj_type;
1483 2f8438b0 2022-05-04 stsp struct got_object_idset *idset_exclude;
1484 2f8438b0 2022-05-04 stsp
1485 2f8438b0 2022-05-04 stsp idset_exclude = got_object_idset_alloc();
1486 2f8438b0 2022-05-04 stsp if (idset_exclude == NULL)
1487 2f8438b0 2022-05-04 stsp return got_error_from_errno("got_object_idset_alloc");
1488 e6bcace5 2021-06-22 stsp
1489 b8af7c06 2022-03-15 stsp *ncolored = 0;
1490 b8af7c06 2022-03-15 stsp *nfound = 0;
1491 b8af7c06 2022-03-15 stsp *ntrees = 0;
1492 b8af7c06 2022-03-15 stsp
1493 b8af7c06 2022-03-15 stsp err = findtwixt(&ids, &nobj, ncolored, ours, nours, theirs, ntheirs,
1494 b8af7c06 2022-03-15 stsp repo, progress_cb, progress_arg, rl, cancel_cb, cancel_arg);
1495 e6bcace5 2021-06-22 stsp if (err || nobj == 0)
1496 e6bcace5 2021-06-22 stsp goto done;
1497 e6bcace5 2021-06-22 stsp
1498 e6bcace5 2021-06-22 stsp for (i = 0; i < ntheirs; i++) {
1499 05118f5a 2021-06-22 stsp struct got_object_id *id = theirs[i];
1500 05118f5a 2021-06-22 stsp if (id == NULL)
1501 05118f5a 2021-06-22 stsp continue;
1502 05118f5a 2021-06-22 stsp err = got_object_get_type(&obj_type, repo, id);
1503 05118f5a 2021-06-22 stsp if (err)
1504 05118f5a 2021-06-22 stsp return err;
1505 9d34261e 2022-04-07 stsp if (obj_type == GOT_OBJ_TYPE_COMMIT) {
1506 2f8438b0 2022-05-04 stsp err = load_commit(0, idset, idset_exclude, id, repo,
1507 9d34261e 2022-04-07 stsp loose_obj_only, ncolored, nfound, ntrees,
1508 9d34261e 2022-04-07 stsp progress_cb, progress_arg, rl,
1509 9d34261e 2022-04-07 stsp cancel_cb, cancel_arg);
1510 07165b17 2021-07-01 stsp if (err)
1511 07165b17 2021-07-01 stsp goto done;
1512 9d34261e 2022-04-07 stsp } else if (obj_type == GOT_OBJ_TYPE_TAG) {
1513 2f8438b0 2022-05-04 stsp err = load_tag(0, idset, idset_exclude, id, repo,
1514 9d34261e 2022-04-07 stsp loose_obj_only, ncolored, nfound, ntrees,
1515 9d34261e 2022-04-07 stsp progress_cb, progress_arg, rl,
1516 9d34261e 2022-04-07 stsp cancel_cb, cancel_arg);
1517 9d34261e 2022-04-07 stsp if (err)
1518 9d34261e 2022-04-07 stsp goto done;
1519 9d34261e 2022-04-07 stsp }
1520 05118f5a 2021-06-22 stsp }
1521 05118f5a 2021-06-22 stsp
1522 eca70f98 2021-09-03 stsp for (i = 0; i < nobj; i++) {
1523 2f8438b0 2022-05-04 stsp err = load_commit(1, idset, idset_exclude,
1524 2f8438b0 2022-05-04 stsp ids[i], repo, loose_obj_only, ncolored, nfound, ntrees,
1525 2f8438b0 2022-05-04 stsp progress_cb, progress_arg, rl, cancel_cb, cancel_arg);
1526 eca70f98 2021-09-03 stsp if (err)
1527 eca70f98 2021-09-03 stsp goto done;
1528 eca70f98 2021-09-03 stsp }
1529 eca70f98 2021-09-03 stsp
1530 05118f5a 2021-06-22 stsp for (i = 0; i < nours; i++) {
1531 05118f5a 2021-06-22 stsp struct got_object_id *id = ours[i];
1532 67fd6849 2022-02-13 stsp struct got_pack_meta *m;
1533 05118f5a 2021-06-22 stsp if (id == NULL)
1534 05118f5a 2021-06-22 stsp continue;
1535 67fd6849 2022-02-13 stsp m = got_object_idset_get(idset, id);
1536 67fd6849 2022-02-13 stsp if (m == NULL) {
1537 07165b17 2021-07-01 stsp err = got_object_get_type(&obj_type, repo, id);
1538 07165b17 2021-07-01 stsp if (err)
1539 07165b17 2021-07-01 stsp goto done;
1540 07165b17 2021-07-01 stsp } else
1541 67fd6849 2022-02-13 stsp obj_type = m->obj_type;
1542 05118f5a 2021-06-22 stsp if (obj_type != GOT_OBJ_TYPE_TAG)
1543 05118f5a 2021-06-22 stsp continue;
1544 2f8438b0 2022-05-04 stsp err = load_tag(1, idset, idset_exclude, id, repo,
1545 2f8438b0 2022-05-04 stsp loose_obj_only, ncolored, nfound, ntrees,
1546 2f8438b0 2022-05-04 stsp progress_cb, progress_arg, rl, cancel_cb, cancel_arg);
1547 05118f5a 2021-06-22 stsp if (err)
1548 e6bcace5 2021-06-22 stsp goto done;
1549 e6bcace5 2021-06-22 stsp }
1550 e6bcace5 2021-06-22 stsp done:
1551 e6bcace5 2021-06-22 stsp for (i = 0; i < nobj; i++) {
1552 e6bcace5 2021-06-22 stsp free(ids[i]);
1553 e6bcace5 2021-06-22 stsp }
1554 e6bcace5 2021-06-22 stsp free(ids);
1555 2f8438b0 2022-05-04 stsp got_object_idset_free(idset_exclude);
1556 e6bcace5 2021-06-22 stsp return err;
1557 e6bcace5 2021-06-22 stsp }
1558 e6bcace5 2021-06-22 stsp
1559 e6bcace5 2021-06-22 stsp const struct got_error *
1560 2d9e6abf 2022-05-04 stsp hwrite(FILE *f, void *buf, off_t len, SHA1_CTX *ctx)
1561 e6bcace5 2021-06-22 stsp {
1562 e6bcace5 2021-06-22 stsp size_t n;
1563 e6bcace5 2021-06-22 stsp
1564 e6bcace5 2021-06-22 stsp SHA1Update(ctx, buf, len);
1565 e6bcace5 2021-06-22 stsp n = fwrite(buf, 1, len, f);
1566 e6bcace5 2021-06-22 stsp if (n != len)
1567 e6bcace5 2021-06-22 stsp return got_ferror(f, GOT_ERR_IO);
1568 2d9e6abf 2022-05-04 stsp return NULL;
1569 2d9e6abf 2022-05-04 stsp }
1570 2d9e6abf 2022-05-04 stsp
1571 2d9e6abf 2022-05-04 stsp const struct got_error *
1572 2d9e6abf 2022-05-04 stsp hcopy(FILE *fsrc, FILE *fdst, off_t len, SHA1_CTX *ctx)
1573 2d9e6abf 2022-05-04 stsp {
1574 2d9e6abf 2022-05-04 stsp unsigned char buf[65536];
1575 2d9e6abf 2022-05-04 stsp off_t remain = len;
1576 2d9e6abf 2022-05-04 stsp size_t n;
1577 2d9e6abf 2022-05-04 stsp
1578 2d9e6abf 2022-05-04 stsp while (remain > 0) {
1579 2d9e6abf 2022-05-04 stsp size_t copylen = MIN(sizeof(buf), remain);
1580 2d9e6abf 2022-05-04 stsp n = fread(buf, 1, copylen, fsrc);
1581 2d9e6abf 2022-05-04 stsp if (n != copylen)
1582 2d9e6abf 2022-05-04 stsp return got_ferror(fsrc, GOT_ERR_IO);
1583 2d9e6abf 2022-05-04 stsp SHA1Update(ctx, buf, copylen);
1584 2d9e6abf 2022-05-04 stsp n = fwrite(buf, 1, copylen, fdst);
1585 2d9e6abf 2022-05-04 stsp if (n != copylen)
1586 2d9e6abf 2022-05-04 stsp return got_ferror(fdst, GOT_ERR_IO);
1587 2d9e6abf 2022-05-04 stsp remain -= copylen;
1588 2d9e6abf 2022-05-04 stsp }
1589 2d9e6abf 2022-05-04 stsp
1590 e6bcace5 2021-06-22 stsp return NULL;
1591 e6bcace5 2021-06-22 stsp }
1592 e6bcace5 2021-06-22 stsp
1593 e6bcace5 2021-06-22 stsp static void
1594 e6bcace5 2021-06-22 stsp putbe32(char *b, uint32_t n)
1595 e6bcace5 2021-06-22 stsp {
1596 e6bcace5 2021-06-22 stsp b[0] = n >> 24;
1597 e6bcace5 2021-06-22 stsp b[1] = n >> 16;
1598 e6bcace5 2021-06-22 stsp b[2] = n >> 8;
1599 e6bcace5 2021-06-22 stsp b[3] = n >> 0;
1600 e6bcace5 2021-06-22 stsp }
1601 e6bcace5 2021-06-22 stsp
1602 e6bcace5 2021-06-22 stsp static int
1603 e6bcace5 2021-06-22 stsp write_order_cmp(const void *pa, const void *pb)
1604 e6bcace5 2021-06-22 stsp {
1605 e6bcace5 2021-06-22 stsp struct got_pack_meta *a, *b, *ahd, *bhd;
1606 e6bcace5 2021-06-22 stsp
1607 e6bcace5 2021-06-22 stsp a = *(struct got_pack_meta **)pa;
1608 e6bcace5 2021-06-22 stsp b = *(struct got_pack_meta **)pb;
1609 e6bcace5 2021-06-22 stsp ahd = (a->head == NULL) ? a : a->head;
1610 e6bcace5 2021-06-22 stsp bhd = (b->head == NULL) ? b : b->head;
1611 611e8e31 2022-05-01 stsp if (bhd->mtime < ahd->mtime)
1612 611e8e31 2022-05-01 stsp return -1;
1613 611e8e31 2022-05-01 stsp if (bhd->mtime > ahd->mtime)
1614 611e8e31 2022-05-01 stsp return 1;
1615 611e8e31 2022-05-01 stsp if (bhd < ahd)
1616 611e8e31 2022-05-01 stsp return -1;
1617 611e8e31 2022-05-01 stsp if (bhd > ahd)
1618 611e8e31 2022-05-01 stsp return 1;
1619 e6bcace5 2021-06-22 stsp if (a->nchain != b->nchain)
1620 e6bcace5 2021-06-22 stsp return a->nchain - b->nchain;
1621 611e8e31 2022-05-01 stsp if (a->mtime < b->mtime)
1622 611e8e31 2022-05-01 stsp return -1;
1623 611e8e31 2022-05-01 stsp if (a->mtime > b->mtime)
1624 611e8e31 2022-05-01 stsp return 1;
1625 611e8e31 2022-05-01 stsp return got_object_id_cmp(&a->id, &b->id);
1626 e6bcace5 2021-06-22 stsp }
1627 e6bcace5 2021-06-22 stsp
1628 67fd6849 2022-02-13 stsp static int
1629 67fd6849 2022-02-13 stsp reuse_write_order_cmp(const void *pa, const void *pb)
1630 67fd6849 2022-02-13 stsp {
1631 67fd6849 2022-02-13 stsp struct got_pack_meta *a, *b;
1632 67fd6849 2022-02-13 stsp
1633 67fd6849 2022-02-13 stsp a = *(struct got_pack_meta **)pa;
1634 67fd6849 2022-02-13 stsp b = *(struct got_pack_meta **)pb;
1635 67fd6849 2022-02-13 stsp
1636 67fd6849 2022-02-13 stsp if (a->reused_delta_offset < b->reused_delta_offset)
1637 67fd6849 2022-02-13 stsp return -1;
1638 67fd6849 2022-02-13 stsp if (a->reused_delta_offset > b->reused_delta_offset)
1639 67fd6849 2022-02-13 stsp return 1;
1640 67fd6849 2022-02-13 stsp return 0;
1641 67fd6849 2022-02-13 stsp }
1642 67fd6849 2022-02-13 stsp
1643 e6bcace5 2021-06-22 stsp static const struct got_error *
1644 e6bcace5 2021-06-22 stsp packhdr(int *hdrlen, char *hdr, size_t bufsize, int obj_type, size_t len)
1645 e6bcace5 2021-06-22 stsp {
1646 e6bcace5 2021-06-22 stsp size_t i;
1647 e6bcace5 2021-06-22 stsp
1648 e6bcace5 2021-06-22 stsp *hdrlen = 0;
1649 e6bcace5 2021-06-22 stsp
1650 e6bcace5 2021-06-22 stsp hdr[0] = obj_type << 4;
1651 e6bcace5 2021-06-22 stsp hdr[0] |= len & 0xf;
1652 e6bcace5 2021-06-22 stsp len >>= 4;
1653 e6bcace5 2021-06-22 stsp for (i = 1; len != 0; i++){
1654 e6bcace5 2021-06-22 stsp if (i >= bufsize)
1655 e6bcace5 2021-06-22 stsp return got_error(GOT_ERR_NO_SPACE);
1656 e6bcace5 2021-06-22 stsp hdr[i - 1] |= GOT_DELTA_SIZE_MORE;
1657 e6bcace5 2021-06-22 stsp hdr[i] = len & GOT_DELTA_SIZE_VAL_MASK;
1658 e6bcace5 2021-06-22 stsp len >>= GOT_DELTA_SIZE_SHIFT;
1659 e6bcace5 2021-06-22 stsp }
1660 e6bcace5 2021-06-22 stsp
1661 e6bcace5 2021-06-22 stsp *hdrlen = i;
1662 e6bcace5 2021-06-22 stsp return NULL;
1663 e6bcace5 2021-06-22 stsp }
1664 e6bcace5 2021-06-22 stsp
1665 e6bcace5 2021-06-22 stsp static int
1666 e6bcace5 2021-06-22 stsp packoff(char *hdr, off_t off)
1667 e6bcace5 2021-06-22 stsp {
1668 e6bcace5 2021-06-22 stsp int i, j;
1669 e6bcace5 2021-06-22 stsp char rbuf[8];
1670 e6bcace5 2021-06-22 stsp
1671 e6bcace5 2021-06-22 stsp rbuf[0] = off & GOT_DELTA_SIZE_VAL_MASK;
1672 e6bcace5 2021-06-22 stsp for (i = 1; (off >>= GOT_DELTA_SIZE_SHIFT) != 0; i++) {
1673 e6bcace5 2021-06-22 stsp rbuf[i] = (--off & GOT_DELTA_SIZE_VAL_MASK) |
1674 e6bcace5 2021-06-22 stsp GOT_DELTA_SIZE_MORE;
1675 e6bcace5 2021-06-22 stsp }
1676 e6bcace5 2021-06-22 stsp
1677 e6bcace5 2021-06-22 stsp j = 0;
1678 e6bcace5 2021-06-22 stsp while (i > 0)
1679 e6bcace5 2021-06-22 stsp hdr[j++] = rbuf[--i];
1680 e6bcace5 2021-06-22 stsp return j;
1681 e6bcace5 2021-06-22 stsp }
1682 e6bcace5 2021-06-22 stsp
1683 e6bcace5 2021-06-22 stsp static const struct got_error *
1684 5060d5a1 2022-01-10 stsp deltahdr(off_t *packfile_size, SHA1_CTX *ctx, FILE *packfile,
1685 67fd6849 2022-02-13 stsp struct got_pack_meta *m)
1686 5060d5a1 2022-01-10 stsp {
1687 5060d5a1 2022-01-10 stsp const struct got_error *err;
1688 5060d5a1 2022-01-10 stsp char buf[32];
1689 5060d5a1 2022-01-10 stsp int nh;
1690 5060d5a1 2022-01-10 stsp
1691 67fd6849 2022-02-13 stsp if (m->prev->off != 0) {
1692 5060d5a1 2022-01-10 stsp err = packhdr(&nh, buf, sizeof(buf),
1693 5060d5a1 2022-01-10 stsp GOT_OBJ_TYPE_OFFSET_DELTA, m->delta_len);
1694 5060d5a1 2022-01-10 stsp if (err)
1695 5060d5a1 2022-01-10 stsp return err;
1696 5060d5a1 2022-01-10 stsp nh += packoff(buf + nh, m->off - m->prev->off);
1697 5060d5a1 2022-01-10 stsp err = hwrite(packfile, buf, nh, ctx);
1698 5060d5a1 2022-01-10 stsp if (err)
1699 5060d5a1 2022-01-10 stsp return err;
1700 5060d5a1 2022-01-10 stsp *packfile_size += nh;
1701 5060d5a1 2022-01-10 stsp } else {
1702 5060d5a1 2022-01-10 stsp err = packhdr(&nh, buf, sizeof(buf),
1703 5060d5a1 2022-01-10 stsp GOT_OBJ_TYPE_REF_DELTA, m->delta_len);
1704 5060d5a1 2022-01-10 stsp if (err)
1705 5060d5a1 2022-01-10 stsp return err;
1706 5060d5a1 2022-01-10 stsp err = hwrite(packfile, buf, nh, ctx);
1707 5060d5a1 2022-01-10 stsp if (err)
1708 5060d5a1 2022-01-10 stsp return err;
1709 5060d5a1 2022-01-10 stsp *packfile_size += nh;
1710 5060d5a1 2022-01-10 stsp err = hwrite(packfile, m->prev->id.sha1,
1711 5060d5a1 2022-01-10 stsp sizeof(m->prev->id.sha1), ctx);
1712 5060d5a1 2022-01-10 stsp if (err)
1713 5060d5a1 2022-01-10 stsp return err;
1714 5060d5a1 2022-01-10 stsp *packfile_size += sizeof(m->prev->id.sha1);
1715 5060d5a1 2022-01-10 stsp }
1716 5060d5a1 2022-01-10 stsp
1717 5060d5a1 2022-01-10 stsp return NULL;
1718 5060d5a1 2022-01-10 stsp }
1719 5060d5a1 2022-01-10 stsp
1720 5060d5a1 2022-01-10 stsp static const struct got_error *
1721 67fd6849 2022-02-13 stsp write_packed_object(off_t *packfile_size, FILE *packfile,
1722 67fd6849 2022-02-13 stsp FILE *delta_cache, struct got_pack_meta *m, int *outfd,
1723 67fd6849 2022-02-13 stsp SHA1_CTX *ctx, struct got_repository *repo)
1724 67fd6849 2022-02-13 stsp {
1725 67fd6849 2022-02-13 stsp const struct got_error *err = NULL;
1726 67fd6849 2022-02-13 stsp struct got_deflate_checksum csum;
1727 67fd6849 2022-02-13 stsp char buf[32];
1728 67fd6849 2022-02-13 stsp int nh;
1729 67fd6849 2022-02-13 stsp struct got_raw_object *raw = NULL;
1730 67fd6849 2022-02-13 stsp off_t outlen;
1731 67fd6849 2022-02-13 stsp
1732 67fd6849 2022-02-13 stsp csum.output_sha1 = ctx;
1733 67fd6849 2022-02-13 stsp csum.output_crc = NULL;
1734 67fd6849 2022-02-13 stsp
1735 67fd6849 2022-02-13 stsp m->off = ftello(packfile);
1736 67fd6849 2022-02-13 stsp if (m->delta_len == 0) {
1737 67fd6849 2022-02-13 stsp err = got_object_raw_open(&raw, outfd, repo, &m->id);
1738 67fd6849 2022-02-13 stsp if (err)
1739 67fd6849 2022-02-13 stsp goto done;
1740 67fd6849 2022-02-13 stsp err = packhdr(&nh, buf, sizeof(buf),
1741 67fd6849 2022-02-13 stsp m->obj_type, raw->size);
1742 67fd6849 2022-02-13 stsp if (err)
1743 67fd6849 2022-02-13 stsp goto done;
1744 67fd6849 2022-02-13 stsp err = hwrite(packfile, buf, nh, ctx);
1745 67fd6849 2022-02-13 stsp if (err)
1746 67fd6849 2022-02-13 stsp goto done;
1747 67fd6849 2022-02-13 stsp *packfile_size += nh;
1748 67fd6849 2022-02-13 stsp if (raw->f == NULL) {
1749 67fd6849 2022-02-13 stsp err = got_deflate_to_file_mmap(&outlen,
1750 67fd6849 2022-02-13 stsp raw->data + raw->hdrlen, 0, raw->size,
1751 67fd6849 2022-02-13 stsp packfile, &csum);
1752 67fd6849 2022-02-13 stsp if (err)
1753 67fd6849 2022-02-13 stsp goto done;
1754 67fd6849 2022-02-13 stsp } else {
1755 67fd6849 2022-02-13 stsp if (fseeko(raw->f, raw->hdrlen, SEEK_SET)
1756 67fd6849 2022-02-13 stsp == -1) {
1757 67fd6849 2022-02-13 stsp err = got_error_from_errno("fseeko");
1758 67fd6849 2022-02-13 stsp goto done;
1759 67fd6849 2022-02-13 stsp }
1760 67fd6849 2022-02-13 stsp err = got_deflate_to_file(&outlen, raw->f,
1761 67fd6849 2022-02-13 stsp raw->size, packfile, &csum);
1762 67fd6849 2022-02-13 stsp if (err)
1763 67fd6849 2022-02-13 stsp goto done;
1764 67fd6849 2022-02-13 stsp }
1765 67fd6849 2022-02-13 stsp *packfile_size += outlen;
1766 67fd6849 2022-02-13 stsp got_object_raw_close(raw);
1767 67fd6849 2022-02-13 stsp raw = NULL;
1768 67fd6849 2022-02-13 stsp } else if (m->delta_buf) {
1769 67fd6849 2022-02-13 stsp err = deltahdr(packfile_size, ctx, packfile, m);
1770 67fd6849 2022-02-13 stsp if (err)
1771 67fd6849 2022-02-13 stsp goto done;
1772 2d9e6abf 2022-05-04 stsp err = hwrite(packfile, m->delta_buf,
1773 2d9e6abf 2022-05-04 stsp m->delta_compressed_len, ctx);
1774 67fd6849 2022-02-13 stsp if (err)
1775 67fd6849 2022-02-13 stsp goto done;
1776 2d9e6abf 2022-05-04 stsp *packfile_size += m->delta_compressed_len;
1777 67fd6849 2022-02-13 stsp free(m->delta_buf);
1778 67fd6849 2022-02-13 stsp m->delta_buf = NULL;
1779 67fd6849 2022-02-13 stsp } else {
1780 67fd6849 2022-02-13 stsp if (fseeko(delta_cache, m->delta_offset, SEEK_SET)
1781 67fd6849 2022-02-13 stsp == -1) {
1782 67fd6849 2022-02-13 stsp err = got_error_from_errno("fseeko");
1783 67fd6849 2022-02-13 stsp goto done;
1784 67fd6849 2022-02-13 stsp }
1785 67fd6849 2022-02-13 stsp err = deltahdr(packfile_size, ctx, packfile, m);
1786 67fd6849 2022-02-13 stsp if (err)
1787 67fd6849 2022-02-13 stsp goto done;
1788 2d9e6abf 2022-05-04 stsp err = hcopy(delta_cache, packfile,
1789 2d9e6abf 2022-05-04 stsp m->delta_compressed_len, ctx);
1790 67fd6849 2022-02-13 stsp if (err)
1791 67fd6849 2022-02-13 stsp goto done;
1792 2d9e6abf 2022-05-04 stsp *packfile_size += m->delta_compressed_len;
1793 67fd6849 2022-02-13 stsp }
1794 67fd6849 2022-02-13 stsp done:
1795 67fd6849 2022-02-13 stsp if (raw)
1796 67fd6849 2022-02-13 stsp got_object_raw_close(raw);
1797 67fd6849 2022-02-13 stsp return err;
1798 67fd6849 2022-02-13 stsp }
1799 67fd6849 2022-02-13 stsp
1800 67fd6849 2022-02-13 stsp static const struct got_error *
1801 74881701 2021-10-15 stsp genpack(uint8_t *pack_sha1, FILE *packfile, FILE *delta_cache,
1802 67fd6849 2022-02-13 stsp struct got_pack_meta **deltify, int ndeltify,
1803 67fd6849 2022-02-13 stsp struct got_pack_meta **reuse, int nreuse,
1804 b8af7c06 2022-03-15 stsp int ncolored, int nfound, int ntrees, int nours,
1805 b8af7c06 2022-03-15 stsp struct got_repository *repo,
1806 05118f5a 2021-06-22 stsp got_pack_progress_cb progress_cb, void *progress_arg,
1807 211cfef0 2022-01-05 stsp struct got_ratelimit *rl,
1808 05118f5a 2021-06-22 stsp got_cancel_cb cancel_cb, void *cancel_arg)
1809 e6bcace5 2021-06-22 stsp {
1810 e6bcace5 2021-06-22 stsp const struct got_error *err = NULL;
1811 67fd6849 2022-02-13 stsp int i;
1812 e6bcace5 2021-06-22 stsp SHA1_CTX ctx;
1813 e6bcace5 2021-06-22 stsp struct got_pack_meta *m;
1814 08347b73 2021-10-14 stsp char buf[32];
1815 72840534 2022-01-19 stsp size_t n;
1816 67fd6849 2022-02-13 stsp off_t packfile_size = 0;
1817 cc7a354a 2021-10-15 stsp int outfd = -1;
1818 e6bcace5 2021-06-22 stsp
1819 e6bcace5 2021-06-22 stsp SHA1Init(&ctx);
1820 e6bcace5 2021-06-22 stsp
1821 e6bcace5 2021-06-22 stsp err = hwrite(packfile, "PACK", 4, &ctx);
1822 e6bcace5 2021-06-22 stsp if (err)
1823 e6bcace5 2021-06-22 stsp return err;
1824 e6bcace5 2021-06-22 stsp putbe32(buf, GOT_PACKFILE_VERSION);
1825 e6bcace5 2021-06-22 stsp err = hwrite(packfile, buf, 4, &ctx);
1826 e6bcace5 2021-06-22 stsp if (err)
1827 e6bcace5 2021-06-22 stsp goto done;
1828 67fd6849 2022-02-13 stsp putbe32(buf, ndeltify + nreuse);
1829 e6bcace5 2021-06-22 stsp err = hwrite(packfile, buf, 4, &ctx);
1830 e6bcace5 2021-06-22 stsp if (err)
1831 e6bcace5 2021-06-22 stsp goto done;
1832 67fd6849 2022-02-13 stsp
1833 67fd6849 2022-02-13 stsp qsort(deltify, ndeltify, sizeof(struct got_pack_meta *),
1834 67fd6849 2022-02-13 stsp write_order_cmp);
1835 67fd6849 2022-02-13 stsp for (i = 0; i < ndeltify; i++) {
1836 211cfef0 2022-01-05 stsp err = report_progress(progress_cb, progress_arg, rl,
1837 b8af7c06 2022-03-15 stsp ncolored, nfound, ntrees, packfile_size, nours,
1838 b8af7c06 2022-03-15 stsp ndeltify + nreuse, ndeltify + nreuse, i);
1839 211cfef0 2022-01-05 stsp if (err)
1840 211cfef0 2022-01-05 stsp goto done;
1841 67fd6849 2022-02-13 stsp m = deltify[i];
1842 67fd6849 2022-02-13 stsp err = write_packed_object(&packfile_size, packfile,
1843 67fd6849 2022-02-13 stsp delta_cache, m, &outfd, &ctx, repo);
1844 67fd6849 2022-02-13 stsp if (err)
1845 67fd6849 2022-02-13 stsp goto done;
1846 e6bcace5 2021-06-22 stsp }
1847 67fd6849 2022-02-13 stsp
1848 67fd6849 2022-02-13 stsp qsort(reuse, nreuse, sizeof(struct got_pack_meta *),
1849 67fd6849 2022-02-13 stsp reuse_write_order_cmp);
1850 67fd6849 2022-02-13 stsp for (i = 0; i < nreuse; i++) {
1851 67fd6849 2022-02-13 stsp err = report_progress(progress_cb, progress_arg, rl,
1852 b8af7c06 2022-03-15 stsp ncolored, nfound, ntrees, packfile_size, nours,
1853 b8af7c06 2022-03-15 stsp ndeltify + nreuse, ndeltify + nreuse, ndeltify + i);
1854 67fd6849 2022-02-13 stsp if (err)
1855 67fd6849 2022-02-13 stsp goto done;
1856 67fd6849 2022-02-13 stsp m = reuse[i];
1857 67fd6849 2022-02-13 stsp err = write_packed_object(&packfile_size, packfile,
1858 67fd6849 2022-02-13 stsp delta_cache, m, &outfd, &ctx, repo);
1859 67fd6849 2022-02-13 stsp if (err)
1860 67fd6849 2022-02-13 stsp goto done;
1861 67fd6849 2022-02-13 stsp }
1862 67fd6849 2022-02-13 stsp
1863 e6bcace5 2021-06-22 stsp SHA1Final(pack_sha1, &ctx);
1864 e6bcace5 2021-06-22 stsp n = fwrite(pack_sha1, 1, SHA1_DIGEST_LENGTH, packfile);
1865 e6bcace5 2021-06-22 stsp if (n != SHA1_DIGEST_LENGTH)
1866 e6bcace5 2021-06-22 stsp err = got_ferror(packfile, GOT_ERR_IO);
1867 05118f5a 2021-06-22 stsp packfile_size += SHA1_DIGEST_LENGTH;
1868 dc7edd42 2021-08-22 stsp packfile_size += sizeof(struct got_packfile_hdr);
1869 211cfef0 2022-01-05 stsp if (progress_cb) {
1870 b8af7c06 2022-03-15 stsp err = progress_cb(progress_arg, ncolored, nfound, ntrees,
1871 b8af7c06 2022-03-15 stsp packfile_size, nours, ndeltify + nreuse,
1872 b8af7c06 2022-03-15 stsp ndeltify + nreuse, ndeltify + nreuse);
1873 211cfef0 2022-01-05 stsp if (err)
1874 211cfef0 2022-01-05 stsp goto done;
1875 211cfef0 2022-01-05 stsp }
1876 e6bcace5 2021-06-22 stsp done:
1877 cc7a354a 2021-10-15 stsp if (outfd != -1 && close(outfd) == -1 && err == NULL)
1878 cc7a354a 2021-10-15 stsp err = got_error_from_errno("close");
1879 e6bcace5 2021-06-22 stsp return err;
1880 67fd6849 2022-02-13 stsp }
1881 67fd6849 2022-02-13 stsp
1882 67fd6849 2022-02-13 stsp static const struct got_error *
1883 67fd6849 2022-02-13 stsp add_meta_idset_cb(struct got_object_id *id, void *data, void *arg)
1884 67fd6849 2022-02-13 stsp {
1885 67fd6849 2022-02-13 stsp struct got_pack_meta *m = data;
1886 67fd6849 2022-02-13 stsp struct got_pack_metavec *v = arg;
1887 f5e78e05 2022-05-04 stsp
1888 f5e78e05 2022-05-04 stsp if (m->have_reused_delta)
1889 f5e78e05 2022-05-04 stsp return NULL;
1890 67fd6849 2022-02-13 stsp
1891 67fd6849 2022-02-13 stsp return add_meta(m, v);
1892 67fd6849 2022-02-13 stsp }
1893 67fd6849 2022-02-13 stsp
1894 e6bcace5 2021-06-22 stsp const struct got_error *
1895 e6bcace5 2021-06-22 stsp got_pack_create(uint8_t *packsha1, FILE *packfile,
1896 e6bcace5 2021-06-22 stsp struct got_object_id **theirs, int ntheirs,
1897 e6bcace5 2021-06-22 stsp struct got_object_id **ours, int nours,
1898 f8a36e22 2021-08-26 stsp struct got_repository *repo, int loose_obj_only, int allow_empty,
1899 05118f5a 2021-06-22 stsp got_pack_progress_cb progress_cb, void *progress_arg,
1900 05118f5a 2021-06-22 stsp got_cancel_cb cancel_cb, void *cancel_arg)
1901 e6bcace5 2021-06-22 stsp {
1902 e6bcace5 2021-06-22 stsp const struct got_error *err;
1903 67fd6849 2022-02-13 stsp int delta_cache_fd = -1;
1904 74881701 2021-10-15 stsp FILE *delta_cache = NULL;
1905 67fd6849 2022-02-13 stsp struct got_object_idset *idset;
1906 211cfef0 2022-01-05 stsp struct got_ratelimit rl;
1907 67fd6849 2022-02-13 stsp struct got_pack_metavec deltify, reuse;
1908 b8af7c06 2022-03-15 stsp int ncolored = 0, nfound = 0, ntrees = 0;
1909 f5e78e05 2022-05-04 stsp size_t ndeltify;
1910 e6bcace5 2021-06-22 stsp
1911 67fd6849 2022-02-13 stsp memset(&deltify, 0, sizeof(deltify));
1912 67fd6849 2022-02-13 stsp memset(&reuse, 0, sizeof(reuse));
1913 67fd6849 2022-02-13 stsp
1914 211cfef0 2022-01-05 stsp got_ratelimit_init(&rl, 0, 500);
1915 211cfef0 2022-01-05 stsp
1916 67fd6849 2022-02-13 stsp idset = got_object_idset_alloc();
1917 67fd6849 2022-02-13 stsp if (idset == NULL)
1918 67fd6849 2022-02-13 stsp return got_error_from_errno("got_object_idset_alloc");
1919 67fd6849 2022-02-13 stsp
1920 b8af7c06 2022-03-15 stsp err = load_object_ids(&ncolored, &nfound, &ntrees, idset, theirs,
1921 b8af7c06 2022-03-15 stsp ntheirs, ours, nours, repo, loose_obj_only,
1922 b8af7c06 2022-03-15 stsp progress_cb, progress_arg, &rl, cancel_cb, cancel_arg);
1923 e6bcace5 2021-06-22 stsp if (err)
1924 e6bcace5 2021-06-22 stsp return err;
1925 e6bcace5 2021-06-22 stsp
1926 28526235 2022-02-13 stsp if (progress_cb) {
1927 b8af7c06 2022-03-15 stsp err = progress_cb(progress_arg, ncolored, nfound, ntrees,
1928 b8af7c06 2022-03-15 stsp 0L, nours, got_object_idset_num_elements(idset), 0, 0);
1929 28526235 2022-02-13 stsp if (err)
1930 28526235 2022-02-13 stsp goto done;
1931 28526235 2022-02-13 stsp }
1932 28526235 2022-02-13 stsp
1933 67fd6849 2022-02-13 stsp if (got_object_idset_num_elements(idset) == 0 && !allow_empty) {
1934 05118f5a 2021-06-22 stsp err = got_error(GOT_ERR_CANNOT_PACK);
1935 05118f5a 2021-06-22 stsp goto done;
1936 05118f5a 2021-06-22 stsp }
1937 74881701 2021-10-15 stsp
1938 67fd6849 2022-02-13 stsp delta_cache_fd = got_opentempfd();
1939 67fd6849 2022-02-13 stsp if (delta_cache_fd == -1) {
1940 74881701 2021-10-15 stsp err = got_error_from_errno("got_opentemp");
1941 74881701 2021-10-15 stsp goto done;
1942 74881701 2021-10-15 stsp }
1943 74881701 2021-10-15 stsp
1944 67fd6849 2022-02-13 stsp reuse.metasz = 64;
1945 67fd6849 2022-02-13 stsp reuse.meta = calloc(reuse.metasz,
1946 67fd6849 2022-02-13 stsp sizeof(struct got_pack_meta *));
1947 67fd6849 2022-02-13 stsp if (reuse.meta == NULL) {
1948 67fd6849 2022-02-13 stsp err = got_error_from_errno("calloc");
1949 67fd6849 2022-02-13 stsp goto done;
1950 67fd6849 2022-02-13 stsp }
1951 67fd6849 2022-02-13 stsp
1952 b8af7c06 2022-03-15 stsp err = search_deltas(&reuse, idset, delta_cache_fd, ncolored, nfound,
1953 b8af7c06 2022-03-15 stsp ntrees, nours, repo, progress_cb, progress_arg, &rl,
1954 b8af7c06 2022-03-15 stsp cancel_cb, cancel_arg);
1955 67fd6849 2022-02-13 stsp if (err)
1956 67fd6849 2022-02-13 stsp goto done;
1957 67fd6849 2022-02-13 stsp
1958 67fd6849 2022-02-13 stsp delta_cache = fdopen(delta_cache_fd, "a+");
1959 67fd6849 2022-02-13 stsp if (delta_cache == NULL) {
1960 67fd6849 2022-02-13 stsp err = got_error_from_errno("fdopen");
1961 67fd6849 2022-02-13 stsp goto done;
1962 67fd6849 2022-02-13 stsp }
1963 67fd6849 2022-02-13 stsp delta_cache_fd = -1;
1964 67fd6849 2022-02-13 stsp
1965 67fd6849 2022-02-13 stsp if (fseeko(delta_cache, 0L, SEEK_END) == -1) {
1966 67fd6849 2022-02-13 stsp err = got_error_from_errno("fseeko");
1967 67fd6849 2022-02-13 stsp goto done;
1968 67fd6849 2022-02-13 stsp }
1969 67fd6849 2022-02-13 stsp
1970 f5e78e05 2022-05-04 stsp ndeltify = got_object_idset_num_elements(idset) - reuse.nmeta;
1971 f5e78e05 2022-05-04 stsp if (ndeltify > 0) {
1972 f5e78e05 2022-05-04 stsp deltify.meta = calloc(ndeltify, sizeof(struct got_pack_meta *));
1973 f5e78e05 2022-05-04 stsp if (deltify.meta == NULL) {
1974 f5e78e05 2022-05-04 stsp err = got_error_from_errno("calloc");
1975 f5e78e05 2022-05-04 stsp goto done;
1976 f5e78e05 2022-05-04 stsp }
1977 f5e78e05 2022-05-04 stsp deltify.metasz = ndeltify;
1978 67fd6849 2022-02-13 stsp
1979 f5e78e05 2022-05-04 stsp err = got_object_idset_for_each(idset, add_meta_idset_cb,
1980 f5e78e05 2022-05-04 stsp &deltify);
1981 f8a36e22 2021-08-26 stsp if (err)
1982 f8a36e22 2021-08-26 stsp goto done;
1983 f5e78e05 2022-05-04 stsp if (deltify.nmeta > 0) {
1984 f5e78e05 2022-05-04 stsp err = pick_deltas(deltify.meta, deltify.nmeta,
1985 f5e78e05 2022-05-04 stsp ncolored, nfound, ntrees, nours, reuse.nmeta,
1986 f5e78e05 2022-05-04 stsp delta_cache, repo, progress_cb, progress_arg, &rl,
1987 f5e78e05 2022-05-04 stsp cancel_cb, cancel_arg);
1988 f5e78e05 2022-05-04 stsp if (err)
1989 f5e78e05 2022-05-04 stsp goto done;
1990 f5e78e05 2022-05-04 stsp }
1991 f8a36e22 2021-08-26 stsp }
1992 e6bcace5 2021-06-22 stsp
1993 2d9e6abf 2022-05-04 stsp if (fflush(delta_cache) == EOF) {
1994 2d9e6abf 2022-05-04 stsp err = got_error_from_errno("fflush");
1995 2d9e6abf 2022-05-04 stsp goto done;
1996 2d9e6abf 2022-05-04 stsp }
1997 67fd6849 2022-02-13 stsp err = genpack(packsha1, packfile, delta_cache, deltify.meta,
1998 b8af7c06 2022-03-15 stsp deltify.nmeta, reuse.meta, reuse.nmeta, ncolored, nfound, ntrees,
1999 b8af7c06 2022-03-15 stsp nours, repo, progress_cb, progress_arg, &rl,
2000 b8af7c06 2022-03-15 stsp cancel_cb, cancel_arg);
2001 e6bcace5 2021-06-22 stsp if (err)
2002 e6bcace5 2021-06-22 stsp goto done;
2003 e6bcace5 2021-06-22 stsp done:
2004 67fd6849 2022-02-13 stsp free_nmeta(deltify.meta, deltify.nmeta);
2005 67fd6849 2022-02-13 stsp free_nmeta(reuse.meta, reuse.nmeta);
2006 67fd6849 2022-02-13 stsp got_object_idset_free(idset);
2007 67fd6849 2022-02-13 stsp if (delta_cache_fd != -1 && close(delta_cache_fd) == -1 && err == NULL)
2008 67fd6849 2022-02-13 stsp err = got_error_from_errno("close");
2009 74881701 2021-10-15 stsp if (delta_cache && fclose(delta_cache) == EOF && err == NULL)
2010 74881701 2021-10-15 stsp err = got_error_from_errno("fclose");
2011 e6bcace5 2021-06-22 stsp return err;
2012 e6bcace5 2021-06-22 stsp }