Blame


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