Blame


1 2df845d5 2023-07-07 op /*
2 2df845d5 2023-07-07 op * Copyright (c) 2023 Omar Polo <op@openbsd.org>
3 2df845d5 2023-07-07 op *
4 2df845d5 2023-07-07 op * Permission to use, copy, modify, and distribute this software for any
5 2df845d5 2023-07-07 op * purpose with or without fee is hereby granted, provided that the above
6 2df845d5 2023-07-07 op * copyright notice and this permission notice appear in all copies.
7 2df845d5 2023-07-07 op *
8 2df845d5 2023-07-07 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 2df845d5 2023-07-07 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 2df845d5 2023-07-07 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 2df845d5 2023-07-07 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 2df845d5 2023-07-07 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 2df845d5 2023-07-07 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 2df845d5 2023-07-07 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 2df845d5 2023-07-07 op */
16 2df845d5 2023-07-07 op
17 2df845d5 2023-07-07 op #include <sys/queue.h>
18 2df845d5 2023-07-07 op #include <sys/types.h>
19 2df845d5 2023-07-07 op
20 2df845d5 2023-07-07 op #include <ctype.h>
21 2df845d5 2023-07-07 op #include <limits.h>
22 2df845d5 2023-07-07 op #include <sha1.h>
23 2df845d5 2023-07-07 op #include <sha2.h>
24 2df845d5 2023-07-07 op #include <stdint.h>
25 2df845d5 2023-07-07 op #include <stdio.h>
26 2df845d5 2023-07-07 op #include <stdlib.h>
27 2df845d5 2023-07-07 op #include <string.h>
28 2df845d5 2023-07-07 op #include <time.h>
29 2df845d5 2023-07-07 op
30 2df845d5 2023-07-07 op #include "got_error.h"
31 2df845d5 2023-07-07 op #include "got_cancel.h"
32 2df845d5 2023-07-07 op #include "got_reference.h"
33 2df845d5 2023-07-07 op #include "got_repository_admin.h" /* XXX for pack_progress */
34 2df845d5 2023-07-07 op #include "got_object.h"
35 2df845d5 2023-07-07 op #include "got_opentemp.h"
36 2df845d5 2023-07-07 op #include "got_repository_dump.h"
37 2df845d5 2023-07-07 op
38 2df845d5 2023-07-07 op #include "got_lib_delta.h"
39 2df845d5 2023-07-07 op #include "got_lib_object.h"
40 2df845d5 2023-07-07 op #include "got_lib_object_idset.h"
41 2df845d5 2023-07-07 op #include "got_lib_ratelimit.h"
42 2df845d5 2023-07-07 op #include "got_lib_pack_create.h"
43 2df845d5 2023-07-07 op
44 2df845d5 2023-07-07 op #define GIT_BUNDLE_SIGNATURE_V2 "# v2 git bundle"
45 2df845d5 2023-07-07 op
46 2df845d5 2023-07-07 op struct idvec {
47 2df845d5 2023-07-07 op struct got_object_id **ids;
48 2df845d5 2023-07-07 op size_t len;
49 2df845d5 2023-07-07 op size_t size;
50 2df845d5 2023-07-07 op };
51 2df845d5 2023-07-07 op
52 2df845d5 2023-07-07 op static const struct got_error *
53 2df845d5 2023-07-07 op idvec_push(struct idvec *v, struct got_object_id *id)
54 2df845d5 2023-07-07 op {
55 2df845d5 2023-07-07 op size_t newsize;
56 2df845d5 2023-07-07 op void *t;
57 2df845d5 2023-07-07 op
58 2df845d5 2023-07-07 op if (v->len == v->size) {
59 2df845d5 2023-07-07 op newsize = v->size + 8;
60 2df845d5 2023-07-07 op t = reallocarray(v->ids, newsize, sizeof(*v->ids));
61 2df845d5 2023-07-07 op if (t == NULL)
62 2df845d5 2023-07-07 op return got_error_from_errno("reallocarray");
63 2df845d5 2023-07-07 op v->ids = t;
64 2df845d5 2023-07-07 op v->size = newsize;
65 2df845d5 2023-07-07 op }
66 2df845d5 2023-07-07 op
67 2df845d5 2023-07-07 op v->ids[v->len++] = id;
68 2df845d5 2023-07-07 op return NULL;
69 2df845d5 2023-07-07 op }
70 2df845d5 2023-07-07 op
71 2df845d5 2023-07-07 op static void
72 2df845d5 2023-07-07 op idvec_free(struct idvec *v)
73 2df845d5 2023-07-07 op {
74 2df845d5 2023-07-07 op size_t i;
75 2df845d5 2023-07-07 op
76 2df845d5 2023-07-07 op for (i = 0; i < v->len; ++i)
77 2df845d5 2023-07-07 op free(v->ids[i]);
78 2df845d5 2023-07-07 op free(v->ids);
79 2df845d5 2023-07-07 op }
80 2df845d5 2023-07-07 op
81 2df845d5 2023-07-07 op const struct got_error *
82 2df845d5 2023-07-07 op got_repo_dump(FILE *out, struct got_reflist_head *include_refs,
83 2df845d5 2023-07-07 op struct got_reflist_head *exclude_refs, struct got_repository *repo,
84 2df845d5 2023-07-07 op got_pack_progress_cb progress_cb, void *progress_arg,
85 2df845d5 2023-07-07 op got_cancel_cb cancel_cb, void *cancel_arg)
86 2df845d5 2023-07-07 op {
87 2df845d5 2023-07-07 op const struct got_error *err = NULL;
88 2df845d5 2023-07-07 op struct got_ratelimit rl;
89 2df845d5 2023-07-07 op uint8_t packsha[SHA1_DIGEST_LENGTH];
90 2df845d5 2023-07-07 op FILE *delta_cache = NULL;
91 2df845d5 2023-07-07 op struct got_reflist_entry *e;
92 2df845d5 2023-07-07 op struct got_object_id *id = NULL;
93 2df845d5 2023-07-07 op struct got_commit_object *commit = NULL;
94 2df845d5 2023-07-07 op struct idvec ours, theirs;
95 2df845d5 2023-07-07 op char *nl, *s, *hex, *logmsg = NULL;
96 2df845d5 2023-07-07 op const char *refname;
97 2df845d5 2023-07-07 op int r;
98 2df845d5 2023-07-07 op
99 2df845d5 2023-07-07 op got_ratelimit_init(&rl, 0, 500);
100 2df845d5 2023-07-07 op
101 2df845d5 2023-07-07 op memset(&ours, 0, sizeof(ours));
102 2df845d5 2023-07-07 op memset(&theirs, 0, sizeof(theirs));
103 2df845d5 2023-07-07 op
104 2df845d5 2023-07-07 op r = fprintf(out, "%s\n", GIT_BUNDLE_SIGNATURE_V2);
105 2df845d5 2023-07-07 op if (r != strlen(GIT_BUNDLE_SIGNATURE_V2) + 1)
106 2df845d5 2023-07-07 op return got_ferror(out, GOT_ERR_IO);
107 2df845d5 2023-07-07 op
108 2df845d5 2023-07-07 op TAILQ_FOREACH(e, exclude_refs, entry) {
109 2df845d5 2023-07-07 op err = got_ref_resolve(&id, repo, e->ref);
110 2df845d5 2023-07-07 op if (err)
111 2df845d5 2023-07-07 op goto done;
112 2df845d5 2023-07-07 op
113 2df845d5 2023-07-07 op idvec_push(&theirs, id);
114 2df845d5 2023-07-07 op if (err)
115 2df845d5 2023-07-07 op goto done;
116 2df845d5 2023-07-07 op
117 2df845d5 2023-07-07 op err = got_object_open_as_commit(&commit, repo, id);
118 2df845d5 2023-07-07 op if (err)
119 2df845d5 2023-07-07 op goto done;
120 2df845d5 2023-07-07 op
121 2df845d5 2023-07-07 op err = got_object_commit_get_logmsg(&logmsg, commit);
122 2df845d5 2023-07-07 op if (err)
123 2df845d5 2023-07-07 op goto done;
124 2df845d5 2023-07-07 op
125 2df845d5 2023-07-07 op s = logmsg;
126 2df845d5 2023-07-07 op while (isspace((unsigned char)*s))
127 2df845d5 2023-07-07 op s++;
128 2df845d5 2023-07-07 op nl = strchr(s, '\n');
129 2df845d5 2023-07-07 op if (nl)
130 2df845d5 2023-07-07 op *nl = '\0';
131 2df845d5 2023-07-07 op
132 2df845d5 2023-07-07 op err = got_object_id_str(&hex, id);
133 2df845d5 2023-07-07 op if (err)
134 2df845d5 2023-07-07 op goto done;
135 2df845d5 2023-07-07 op fprintf(out, "-%s %s\n", hex, s);
136 2df845d5 2023-07-07 op free(hex);
137 2df845d5 2023-07-07 op
138 2df845d5 2023-07-07 op got_object_commit_close(commit);
139 2df845d5 2023-07-07 op commit = NULL;
140 2df845d5 2023-07-07 op
141 2df845d5 2023-07-07 op free(logmsg);
142 2df845d5 2023-07-07 op logmsg = NULL;
143 2df845d5 2023-07-07 op }
144 2df845d5 2023-07-07 op
145 2df845d5 2023-07-07 op TAILQ_FOREACH(e, include_refs, entry) {
146 2df845d5 2023-07-07 op err = got_ref_resolve(&id, repo, e->ref);
147 2df845d5 2023-07-07 op if (err)
148 2df845d5 2023-07-07 op goto done;
149 2df845d5 2023-07-07 op
150 2df845d5 2023-07-07 op err = idvec_push(&ours, id);
151 2df845d5 2023-07-07 op if (err)
152 2df845d5 2023-07-07 op goto done;
153 2df845d5 2023-07-07 op
154 2df845d5 2023-07-07 op refname = got_ref_get_name(e->ref);
155 2df845d5 2023-07-07 op
156 2df845d5 2023-07-07 op err = got_object_id_str(&hex, id);
157 2df845d5 2023-07-07 op if (err)
158 2df845d5 2023-07-07 op goto done;
159 2df845d5 2023-07-07 op fprintf(out, "%s %s\n", hex, refname);
160 2df845d5 2023-07-07 op free(hex);
161 2df845d5 2023-07-07 op }
162 2df845d5 2023-07-07 op
163 2df845d5 2023-07-07 op if (fputc('\n', out) == EOF || fflush(out) == EOF) {
164 2df845d5 2023-07-07 op err = got_ferror(out, GOT_ERR_IO);
165 2df845d5 2023-07-07 op goto done;
166 2df845d5 2023-07-07 op }
167 2df845d5 2023-07-07 op
168 2df845d5 2023-07-07 op delta_cache = got_opentemp();
169 2df845d5 2023-07-07 op if (delta_cache == NULL) {
170 2df845d5 2023-07-07 op err = got_error_from_errno("got_opentemp");
171 2df845d5 2023-07-07 op goto done;
172 2df845d5 2023-07-07 op }
173 2df845d5 2023-07-07 op
174 2df845d5 2023-07-07 op err = got_pack_create(&packsha[0], fileno(out), delta_cache,
175 2df845d5 2023-07-07 op theirs.ids, theirs.len, ours.ids, ours.len,
176 2df845d5 2023-07-07 op repo, 0, 0, 0, progress_cb, progress_arg, &rl,
177 2df845d5 2023-07-07 op cancel_cb, cancel_arg);
178 2df845d5 2023-07-07 op
179 2df845d5 2023-07-07 op done:
180 2df845d5 2023-07-07 op idvec_free(&ours);
181 2df845d5 2023-07-07 op idvec_free(&theirs);
182 2df845d5 2023-07-07 op if (commit)
183 2df845d5 2023-07-07 op got_object_commit_close(commit);
184 2df845d5 2023-07-07 op if (delta_cache && fclose(delta_cache) == EOF && err == NULL)
185 2df845d5 2023-07-07 op err = got_error_from_errno("fclose");
186 2df845d5 2023-07-07 op return err;
187 2df845d5 2023-07-07 op }