Blame


1 5c860e29 2018-03-12 stsp /*
2 f42b1b34 2018-03-12 stsp * Copyright (c) 2017 Martin Pieuchot <mpi@openbsd.org>
3 5aa81393 2020-01-06 stsp * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
4 93658fb9 2020-03-18 stsp * Copyright (c) 2020 Ori Bernstein <ori@openbsd.org>
5 5c860e29 2018-03-12 stsp *
6 5c860e29 2018-03-12 stsp * Permission to use, copy, modify, and distribute this software for any
7 5c860e29 2018-03-12 stsp * purpose with or without fee is hereby granted, provided that the above
8 5c860e29 2018-03-12 stsp * copyright notice and this permission notice appear in all copies.
9 5c860e29 2018-03-12 stsp *
10 5c860e29 2018-03-12 stsp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 5c860e29 2018-03-12 stsp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 5c860e29 2018-03-12 stsp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 5c860e29 2018-03-12 stsp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 5c860e29 2018-03-12 stsp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 5c860e29 2018-03-12 stsp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 5c860e29 2018-03-12 stsp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 5c860e29 2018-03-12 stsp */
18 4fccd2fe 2023-03-08 thomas
19 4fccd2fe 2023-03-08 thomas #include "got_compat.h"
20 5c860e29 2018-03-12 stsp
21 8b925c6c 2022-07-16 thomas #include <sys/queue.h>
22 d06b3506 2022-07-04 thomas #include <sys/time.h>
23 c0768b0f 2018-06-10 stsp #include <sys/types.h>
24 5de5890b 2018-10-18 stsp #include <sys/stat.h>
25 33ad4cbe 2019-05-12 jcs #include <sys/wait.h>
26 f42b1b34 2018-03-12 stsp
27 5c860e29 2018-03-12 stsp #include <err.h>
28 5c860e29 2018-03-12 stsp #include <errno.h>
29 12463d8b 2019-12-13 stsp #include <fcntl.h>
30 12ce7a6c 2019-08-12 stsp #include <limits.h>
31 5c860e29 2018-03-12 stsp #include <locale.h>
32 818c7501 2019-07-11 stsp #include <ctype.h>
33 99437157 2018-11-11 stsp #include <signal.h>
34 5c860e29 2018-03-12 stsp #include <stdio.h>
35 5c860e29 2018-03-12 stsp #include <stdlib.h>
36 5c860e29 2018-03-12 stsp #include <string.h>
37 5c860e29 2018-03-12 stsp #include <unistd.h>
38 c09a553d 2018-03-12 stsp #include <libgen.h>
39 c0768b0f 2018-06-10 stsp #include <time.h>
40 33ad4cbe 2019-05-12 jcs #include <paths.h>
41 6841bf13 2019-11-29 kn #include <regex.h>
42 83cd27f8 2020-01-13 stsp #include <getopt.h>
43 5c860e29 2018-03-12 stsp
44 53ccebc2 2019-07-30 stsp #include "got_version.h"
45 f42b1b34 2018-03-12 stsp #include "got_error.h"
46 f42b1b34 2018-03-12 stsp #include "got_object.h"
47 5261c201 2018-04-01 stsp #include "got_reference.h"
48 f42b1b34 2018-03-12 stsp #include "got_repository.h"
49 1dd54920 2019-05-11 stsp #include "got_path.h"
50 e6209546 2019-08-22 stsp #include "got_cancel.h"
51 c09a553d 2018-03-12 stsp #include "got_worktree.h"
52 79109fed 2018-03-27 stsp #include "got_diff.h"
53 372ccdbb 2018-06-10 stsp #include "got_commit_graph.h"
54 6f23baec 2020-03-18 stsp #include "got_fetch.h"
55 f8a36e22 2021-08-26 stsp #include "got_send.h"
56 404c43c4 2018-06-21 stsp #include "got_blame.h"
57 63219cd2 2019-01-04 stsp #include "got_privsep.h"
58 793c30b5 2019-05-13 stsp #include "got_opentemp.h"
59 50b0790e 2020-09-11 stsp #include "got_gotconfig.h"
60 d65a88a2 2021-09-05 stsp #include "got_dial.h"
61 069bbb86 2022-03-07 thomas #include "got_patch.h"
62 871bd038 2022-07-03 thomas #include "got_sigs.h"
63 871bd038 2022-07-03 thomas #include "got_date.h"
64 9139e004 2023-07-17 thomas #include "got_keyword.h"
65 5c860e29 2018-03-12 stsp
66 5c860e29 2018-03-12 stsp #ifndef nitems
67 5c860e29 2018-03-12 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
68 a8938c43 2024-03-19 thomas #endif
69 a8938c43 2024-03-19 thomas
70 a8938c43 2024-03-19 thomas #ifndef GOT_DEFAULT_EDITOR
71 a8938c43 2024-03-19 thomas #define GOT_DEFAULT_EDITOR "/usr/bin/vi"
72 5c860e29 2018-03-12 stsp #endif
73 99437157 2018-11-11 stsp
74 99437157 2018-11-11 stsp static volatile sig_atomic_t sigint_received;
75 99437157 2018-11-11 stsp static volatile sig_atomic_t sigpipe_received;
76 99437157 2018-11-11 stsp
77 99437157 2018-11-11 stsp static void
78 99437157 2018-11-11 stsp catch_sigint(int signo)
79 99437157 2018-11-11 stsp {
80 99437157 2018-11-11 stsp sigint_received = 1;
81 99437157 2018-11-11 stsp }
82 99437157 2018-11-11 stsp
83 99437157 2018-11-11 stsp static void
84 99437157 2018-11-11 stsp catch_sigpipe(int signo)
85 99437157 2018-11-11 stsp {
86 99437157 2018-11-11 stsp sigpipe_received = 1;
87 99437157 2018-11-11 stsp }
88 5c860e29 2018-03-12 stsp
89 99437157 2018-11-11 stsp
90 8cfb4057 2019-07-09 stsp struct got_cmd {
91 820059fa 2020-09-25 stsp const char *cmd_name;
92 d7d4f210 2018-03-12 stsp const struct got_error *(*cmd_main)(int, char *[]);
93 1b6b95a8 2018-03-12 stsp void (*cmd_usage)(void);
94 97b3a7be 2019-07-09 stsp const char *cmd_alias;
95 5c860e29 2018-03-12 stsp };
96 5c860e29 2018-03-12 stsp
97 6879ba42 2020-10-01 naddy __dead static void usage(int, int);
98 6becd179 2024-06-03 thomas __dead static void usage_init(void);
99 3ce1b845 2019-07-15 stsp __dead static void usage_import(void);
100 93658fb9 2020-03-18 stsp __dead static void usage_clone(void);
101 7848a0e1 2020-03-19 stsp __dead static void usage_fetch(void);
102 2ab43947 2020-03-18 stsp __dead static void usage_checkout(void);
103 507dc3bb 2018-12-29 stsp __dead static void usage_update(void);
104 4ed7e80c 2018-05-20 stsp __dead static void usage_log(void);
105 4ed7e80c 2018-05-20 stsp __dead static void usage_diff(void);
106 404c43c4 2018-06-21 stsp __dead static void usage_blame(void);
107 5de5890b 2018-10-18 stsp __dead static void usage_tree(void);
108 6bad629b 2019-02-04 stsp __dead static void usage_status(void);
109 d0eebce4 2019-03-11 stsp __dead static void usage_ref(void);
110 4e759de4 2019-06-26 stsp __dead static void usage_branch(void);
111 8e7bd50a 2019-08-22 stsp __dead static void usage_tag(void);
112 d00136be 2019-03-26 stsp __dead static void usage_add(void);
113 648e4ef7 2019-07-09 stsp __dead static void usage_remove(void);
114 069bbb86 2022-03-07 thomas __dead static void usage_patch(void);
115 a129376b 2019-03-28 stsp __dead static void usage_revert(void);
116 c4296144 2019-05-09 stsp __dead static void usage_commit(void);
117 f8a36e22 2021-08-26 stsp __dead static void usage_send(void);
118 234035bc 2019-06-01 stsp __dead static void usage_cherrypick(void);
119 5ef14e63 2019-06-02 stsp __dead static void usage_backout(void);
120 818c7501 2019-07-11 stsp __dead static void usage_rebase(void);
121 0ebf8283 2019-07-24 stsp __dead static void usage_histedit(void);
122 2822a352 2019-10-15 stsp __dead static void usage_integrate(void);
123 10604dce 2021-09-24 thomas __dead static void usage_merge(void);
124 715dc77e 2019-08-03 stsp __dead static void usage_stage(void);
125 ad493afc 2019-08-03 stsp __dead static void usage_unstage(void);
126 01073a5d 2019-08-22 stsp __dead static void usage_cat(void);
127 b2118c49 2020-07-28 stsp __dead static void usage_info(void);
128 5c860e29 2018-03-12 stsp
129 6becd179 2024-06-03 thomas static const struct got_error* cmd_init(int, char *[]);
130 3ce1b845 2019-07-15 stsp static const struct got_error* cmd_import(int, char *[]);
131 93658fb9 2020-03-18 stsp static const struct got_error* cmd_clone(int, char *[]);
132 7848a0e1 2020-03-19 stsp static const struct got_error* cmd_fetch(int, char *[]);
133 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_checkout(int, char *[]);
134 507dc3bb 2018-12-29 stsp static const struct got_error* cmd_update(int, char *[]);
135 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_log(int, char *[]);
136 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_diff(int, char *[]);
137 404c43c4 2018-06-21 stsp static const struct got_error* cmd_blame(int, char *[]);
138 5de5890b 2018-10-18 stsp static const struct got_error* cmd_tree(int, char *[]);
139 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_status(int, char *[]);
140 d0eebce4 2019-03-11 stsp static const struct got_error* cmd_ref(int, char *[]);
141 4e759de4 2019-06-26 stsp static const struct got_error* cmd_branch(int, char *[]);
142 8e7bd50a 2019-08-22 stsp static const struct got_error* cmd_tag(int, char *[]);
143 d00136be 2019-03-26 stsp static const struct got_error* cmd_add(int, char *[]);
144 648e4ef7 2019-07-09 stsp static const struct got_error* cmd_remove(int, char *[]);
145 069bbb86 2022-03-07 thomas static const struct got_error* cmd_patch(int, char *[]);
146 a129376b 2019-03-28 stsp static const struct got_error* cmd_revert(int, char *[]);
147 c4296144 2019-05-09 stsp static const struct got_error* cmd_commit(int, char *[]);
148 f8a36e22 2021-08-26 stsp static const struct got_error* cmd_send(int, char *[]);
149 234035bc 2019-06-01 stsp static const struct got_error* cmd_cherrypick(int, char *[]);
150 5ef14e63 2019-06-02 stsp static const struct got_error* cmd_backout(int, char *[]);
151 818c7501 2019-07-11 stsp static const struct got_error* cmd_rebase(int, char *[]);
152 0ebf8283 2019-07-24 stsp static const struct got_error* cmd_histedit(int, char *[]);
153 2822a352 2019-10-15 stsp static const struct got_error* cmd_integrate(int, char *[]);
154 10604dce 2021-09-24 thomas static const struct got_error* cmd_merge(int, char *[]);
155 715dc77e 2019-08-03 stsp static const struct got_error* cmd_stage(int, char *[]);
156 ad493afc 2019-08-03 stsp static const struct got_error* cmd_unstage(int, char *[]);
157 01073a5d 2019-08-22 stsp static const struct got_error* cmd_cat(int, char *[]);
158 b2118c49 2020-07-28 stsp static const struct got_error* cmd_info(int, char *[]);
159 5c860e29 2018-03-12 stsp
160 641a8ee6 2022-02-16 thomas static const struct got_cmd got_commands[] = {
161 6becd179 2024-06-03 thomas { "init", cmd_init, usage_init, "" },
162 bc26cce8 2019-08-04 stsp { "import", cmd_import, usage_import, "im" },
163 93658fb9 2020-03-18 stsp { "clone", cmd_clone, usage_clone, "cl" },
164 7848a0e1 2020-03-19 stsp { "fetch", cmd_fetch, usage_fetch, "fe" },
165 2ab43947 2020-03-18 stsp { "checkout", cmd_checkout, usage_checkout, "co" },
166 97b3a7be 2019-07-09 stsp { "update", cmd_update, usage_update, "up" },
167 97b3a7be 2019-07-09 stsp { "log", cmd_log, usage_log, "" },
168 bc26cce8 2019-08-04 stsp { "diff", cmd_diff, usage_diff, "di" },
169 bc26cce8 2019-08-04 stsp { "blame", cmd_blame, usage_blame, "bl" },
170 bc26cce8 2019-08-04 stsp { "tree", cmd_tree, usage_tree, "tr" },
171 97b3a7be 2019-07-09 stsp { "status", cmd_status, usage_status, "st" },
172 97b3a7be 2019-07-09 stsp { "ref", cmd_ref, usage_ref, "" },
173 97b3a7be 2019-07-09 stsp { "branch", cmd_branch, usage_branch, "br" },
174 8e7bd50a 2019-08-22 stsp { "tag", cmd_tag, usage_tag, "" },
175 97b3a7be 2019-07-09 stsp { "add", cmd_add, usage_add, "" },
176 648e4ef7 2019-07-09 stsp { "remove", cmd_remove, usage_remove, "rm" },
177 069bbb86 2022-03-07 thomas { "patch", cmd_patch, usage_patch, "pa" },
178 97b3a7be 2019-07-09 stsp { "revert", cmd_revert, usage_revert, "rv" },
179 97b3a7be 2019-07-09 stsp { "commit", cmd_commit, usage_commit, "ci" },
180 f8a36e22 2021-08-26 stsp { "send", cmd_send, usage_send, "se" },
181 016477fd 2019-07-09 stsp { "cherrypick", cmd_cherrypick, usage_cherrypick, "cy" },
182 97b3a7be 2019-07-09 stsp { "backout", cmd_backout, usage_backout, "bo" },
183 818c7501 2019-07-11 stsp { "rebase", cmd_rebase, usage_rebase, "rb" },
184 0ebf8283 2019-07-24 stsp { "histedit", cmd_histedit, usage_histedit, "he" },
185 2822a352 2019-10-15 stsp { "integrate", cmd_integrate, usage_integrate,"ig" },
186 10604dce 2021-09-24 thomas { "merge", cmd_merge, usage_merge, "mg" },
187 715dc77e 2019-08-03 stsp { "stage", cmd_stage, usage_stage, "sg" },
188 ad493afc 2019-08-03 stsp { "unstage", cmd_unstage, usage_unstage, "ug" },
189 01073a5d 2019-08-22 stsp { "cat", cmd_cat, usage_cat, "" },
190 b2118c49 2020-07-28 stsp { "info", cmd_info, usage_info, "" },
191 5c860e29 2018-03-12 stsp };
192 ce5b7c56 2019-07-09 stsp
193 ce5b7c56 2019-07-09 stsp static void
194 6879ba42 2020-10-01 naddy list_commands(FILE *fp)
195 ce5b7c56 2019-07-09 stsp {
196 6059809a 2020-12-17 stsp size_t i;
197 ce5b7c56 2019-07-09 stsp
198 6879ba42 2020-10-01 naddy fprintf(fp, "commands:");
199 ce5b7c56 2019-07-09 stsp for (i = 0; i < nitems(got_commands); i++) {
200 641a8ee6 2022-02-16 thomas const struct got_cmd *cmd = &got_commands[i];
201 6879ba42 2020-10-01 naddy fprintf(fp, " %s", cmd->cmd_name);
202 ce5b7c56 2019-07-09 stsp }
203 6879ba42 2020-10-01 naddy fputc('\n', fp);
204 ce5b7c56 2019-07-09 stsp }
205 5c860e29 2018-03-12 stsp
206 ff69268e 2020-12-13 stsp __dead static void
207 ff69268e 2020-12-13 stsp option_conflict(char a, char b)
208 ff69268e 2020-12-13 stsp {
209 ff69268e 2020-12-13 stsp errx(1, "-%c and -%c options are mutually exclusive", a, b);
210 ff69268e 2020-12-13 stsp }
211 ff69268e 2020-12-13 stsp
212 5c860e29 2018-03-12 stsp int
213 5c860e29 2018-03-12 stsp main(int argc, char *argv[])
214 5c860e29 2018-03-12 stsp {
215 641a8ee6 2022-02-16 thomas const struct got_cmd *cmd;
216 6059809a 2020-12-17 stsp size_t i;
217 5c860e29 2018-03-12 stsp int ch;
218 53ccebc2 2019-07-30 stsp int hflag = 0, Vflag = 0;
219 641a8ee6 2022-02-16 thomas static const struct option longopts[] = {
220 62d463ca 2020-10-20 naddy { "version", no_argument, NULL, 'V' },
221 62d463ca 2020-10-20 naddy { NULL, 0, NULL, 0 }
222 83cd27f8 2020-01-13 stsp };
223 5c860e29 2018-03-12 stsp
224 289e3cbf 2019-02-04 stsp setlocale(LC_CTYPE, "");
225 5c860e29 2018-03-12 stsp
226 6586ea88 2020-01-13 stsp while ((ch = getopt_long(argc, argv, "+hV", longopts, NULL)) != -1) {
227 5c860e29 2018-03-12 stsp switch (ch) {
228 1b6b95a8 2018-03-12 stsp case 'h':
229 1b6b95a8 2018-03-12 stsp hflag = 1;
230 53ccebc2 2019-07-30 stsp break;
231 53ccebc2 2019-07-30 stsp case 'V':
232 53ccebc2 2019-07-30 stsp Vflag = 1;
233 1b6b95a8 2018-03-12 stsp break;
234 5c860e29 2018-03-12 stsp default:
235 6879ba42 2020-10-01 naddy usage(hflag, 1);
236 5c860e29 2018-03-12 stsp /* NOTREACHED */
237 5c860e29 2018-03-12 stsp }
238 5c860e29 2018-03-12 stsp }
239 5c860e29 2018-03-12 stsp
240 5c860e29 2018-03-12 stsp argc -= optind;
241 5c860e29 2018-03-12 stsp argv += optind;
242 9814e6a3 2020-09-27 naddy optind = 1;
243 9814e6a3 2020-09-27 naddy optreset = 1;
244 53ccebc2 2019-07-30 stsp
245 53ccebc2 2019-07-30 stsp if (Vflag) {
246 53ccebc2 2019-07-30 stsp got_version_print_str();
247 6879ba42 2020-10-01 naddy return 0;
248 53ccebc2 2019-07-30 stsp }
249 5c860e29 2018-03-12 stsp
250 5c860e29 2018-03-12 stsp if (argc <= 0)
251 6879ba42 2020-10-01 naddy usage(hflag, hflag ? 0 : 1);
252 5c860e29 2018-03-12 stsp
253 99437157 2018-11-11 stsp signal(SIGINT, catch_sigint);
254 99437157 2018-11-11 stsp signal(SIGPIPE, catch_sigpipe);
255 99437157 2018-11-11 stsp
256 5c860e29 2018-03-12 stsp for (i = 0; i < nitems(got_commands); i++) {
257 d7d4f210 2018-03-12 stsp const struct got_error *error;
258 d7d4f210 2018-03-12 stsp
259 5c860e29 2018-03-12 stsp cmd = &got_commands[i];
260 5c860e29 2018-03-12 stsp
261 97b3a7be 2019-07-09 stsp if (strcmp(cmd->cmd_name, argv[0]) != 0 &&
262 97b3a7be 2019-07-09 stsp strcmp(cmd->cmd_alias, argv[0]) != 0)
263 5c860e29 2018-03-12 stsp continue;
264 5c860e29 2018-03-12 stsp
265 1b6b95a8 2018-03-12 stsp if (hflag)
266 641a8ee6 2022-02-16 thomas cmd->cmd_usage();
267 1b6b95a8 2018-03-12 stsp
268 641a8ee6 2022-02-16 thomas error = cmd->cmd_main(argc, argv);
269 f8afbdc8 2019-11-08 stsp if (error && error->code != GOT_ERR_CANCELLED &&
270 f8afbdc8 2019-11-08 stsp error->code != GOT_ERR_PRIVSEP_EXIT &&
271 f8afbdc8 2019-11-08 stsp !(sigpipe_received &&
272 70015d7a 2019-11-08 stsp error->code == GOT_ERR_ERRNO && errno == EPIPE) &&
273 70015d7a 2019-11-08 stsp !(sigint_received &&
274 70015d7a 2019-11-08 stsp error->code == GOT_ERR_ERRNO && errno == EINTR)) {
275 4d0b6596 2023-04-14 thomas fflush(stdout);
276 d7d4f210 2018-03-12 stsp fprintf(stderr, "%s: %s\n", getprogname(), error->msg);
277 d7d4f210 2018-03-12 stsp return 1;
278 d7d4f210 2018-03-12 stsp }
279 d7d4f210 2018-03-12 stsp
280 d7d4f210 2018-03-12 stsp return 0;
281 5c860e29 2018-03-12 stsp }
282 5c860e29 2018-03-12 stsp
283 20ecf764 2018-03-12 stsp fprintf(stderr, "%s: unknown command '%s'\n", getprogname(), argv[0]);
284 6879ba42 2020-10-01 naddy list_commands(stderr);
285 5c860e29 2018-03-12 stsp return 1;
286 5c860e29 2018-03-12 stsp }
287 5c860e29 2018-03-12 stsp
288 4ed7e80c 2018-05-20 stsp __dead static void
289 6879ba42 2020-10-01 naddy usage(int hflag, int status)
290 5c860e29 2018-03-12 stsp {
291 6879ba42 2020-10-01 naddy FILE *fp = (status == 0) ? stdout : stderr;
292 6879ba42 2020-10-01 naddy
293 0a58e722 2022-10-04 thomas fprintf(fp, "usage: %s [-hV] command [arg ...]\n",
294 53ccebc2 2019-07-30 stsp getprogname());
295 ce5b7c56 2019-07-09 stsp if (hflag)
296 6879ba42 2020-10-01 naddy list_commands(fp);
297 6879ba42 2020-10-01 naddy exit(status);
298 5c860e29 2018-03-12 stsp }
299 5c860e29 2018-03-12 stsp
300 0266afb7 2019-01-04 stsp static const struct got_error *
301 0ee7065d 2019-05-13 stsp get_editor(char **abspath)
302 e2ba3d07 2019-05-13 stsp {
303 0ee7065d 2019-05-13 stsp const struct got_error *err = NULL;
304 e2ba3d07 2019-05-13 stsp const char *editor;
305 8920fa04 2019-08-18 stsp
306 8920fa04 2019-08-18 stsp *abspath = NULL;
307 e2ba3d07 2019-05-13 stsp
308 e2ba3d07 2019-05-13 stsp editor = getenv("VISUAL");
309 e2ba3d07 2019-05-13 stsp if (editor == NULL)
310 e2ba3d07 2019-05-13 stsp editor = getenv("EDITOR");
311 e2ba3d07 2019-05-13 stsp
312 0ee7065d 2019-05-13 stsp if (editor) {
313 0ee7065d 2019-05-13 stsp err = got_path_find_prog(abspath, editor);
314 0ee7065d 2019-05-13 stsp if (err)
315 0ee7065d 2019-05-13 stsp return err;
316 0ee7065d 2019-05-13 stsp }
317 e2ba3d07 2019-05-13 stsp
318 0ee7065d 2019-05-13 stsp if (*abspath == NULL) {
319 a8938c43 2024-03-19 thomas *abspath = strdup(GOT_DEFAULT_EDITOR);
320 0ee7065d 2019-05-13 stsp if (*abspath == NULL)
321 0ee7065d 2019-05-13 stsp return got_error_from_errno("strdup");
322 0ee7065d 2019-05-13 stsp }
323 0ee7065d 2019-05-13 stsp
324 e2ba3d07 2019-05-13 stsp return NULL;
325 e2ba3d07 2019-05-13 stsp }
326 e2ba3d07 2019-05-13 stsp
327 e2ba3d07 2019-05-13 stsp static const struct got_error *
328 d0eebce4 2019-03-11 stsp apply_unveil(const char *repo_path, int repo_read_only,
329 c530dc23 2019-07-23 stsp const char *worktree_path)
330 0266afb7 2019-01-04 stsp {
331 163ce85a 2019-05-13 stsp const struct got_error *err;
332 0266afb7 2019-01-04 stsp
333 37c06ea4 2019-07-15 stsp #ifdef PROFILE
334 37c06ea4 2019-07-15 stsp if (unveil("gmon.out", "rwc") != 0)
335 37c06ea4 2019-07-15 stsp return got_error_from_errno2("unveil", "gmon.out");
336 37c06ea4 2019-07-15 stsp #endif
337 d0eebce4 2019-03-11 stsp if (repo_path && unveil(repo_path, repo_read_only ? "r" : "rwc") != 0)
338 638f9024 2019-05-13 stsp return got_error_from_errno2("unveil", repo_path);
339 0266afb7 2019-01-04 stsp
340 0266afb7 2019-01-04 stsp if (worktree_path && unveil(worktree_path, "rwc") != 0)
341 638f9024 2019-05-13 stsp return got_error_from_errno2("unveil", worktree_path);
342 0266afb7 2019-01-04 stsp
343 bb63914a 2020-02-17 stsp if (unveil(GOT_TMPDIR_STR, "rwc") != 0)
344 bb63914a 2020-02-17 stsp return got_error_from_errno2("unveil", GOT_TMPDIR_STR);
345 0266afb7 2019-01-04 stsp
346 163ce85a 2019-05-13 stsp err = got_privsep_unveil_exec_helpers();
347 163ce85a 2019-05-13 stsp if (err != NULL)
348 163ce85a 2019-05-13 stsp return err;
349 0266afb7 2019-01-04 stsp
350 0266afb7 2019-01-04 stsp if (unveil(NULL, NULL) != 0)
351 638f9024 2019-05-13 stsp return got_error_from_errno("unveil");
352 0266afb7 2019-01-04 stsp
353 0266afb7 2019-01-04 stsp return NULL;
354 3ce1b845 2019-07-15 stsp }
355 3ce1b845 2019-07-15 stsp
356 3ce1b845 2019-07-15 stsp __dead static void
357 6becd179 2024-06-03 thomas usage_init(void)
358 6becd179 2024-06-03 thomas {
359 6becd179 2024-06-03 thomas fprintf(stderr, "usage: %s init [-b branch] repository-path\n",
360 6becd179 2024-06-03 thomas getprogname());
361 6becd179 2024-06-03 thomas exit(1);
362 6becd179 2024-06-03 thomas }
363 6becd179 2024-06-03 thomas
364 6becd179 2024-06-03 thomas static const struct got_error *
365 6becd179 2024-06-03 thomas cmd_init(int argc, char *argv[])
366 6becd179 2024-06-03 thomas {
367 6becd179 2024-06-03 thomas const struct got_error *error = NULL;
368 6becd179 2024-06-03 thomas const char *head_name = NULL;
369 6becd179 2024-06-03 thomas char *repo_path = NULL;
370 6becd179 2024-06-03 thomas int ch;
371 6becd179 2024-06-03 thomas
372 6becd179 2024-06-03 thomas while ((ch = getopt(argc, argv, "b:")) != -1) {
373 6becd179 2024-06-03 thomas switch (ch) {
374 6becd179 2024-06-03 thomas case 'b':
375 6becd179 2024-06-03 thomas head_name = optarg;
376 6becd179 2024-06-03 thomas break;
377 6becd179 2024-06-03 thomas default:
378 6becd179 2024-06-03 thomas usage_init();
379 6becd179 2024-06-03 thomas /* NOTREACHED */
380 6becd179 2024-06-03 thomas }
381 6becd179 2024-06-03 thomas }
382 6becd179 2024-06-03 thomas
383 6becd179 2024-06-03 thomas argc -= optind;
384 6becd179 2024-06-03 thomas argv += optind;
385 6becd179 2024-06-03 thomas
386 6becd179 2024-06-03 thomas #ifndef PROFILE
387 6becd179 2024-06-03 thomas if (pledge("stdio rpath wpath cpath unveil", NULL) == -1)
388 6becd179 2024-06-03 thomas err(1, "pledge");
389 6becd179 2024-06-03 thomas #endif
390 6becd179 2024-06-03 thomas if (argc != 1)
391 6becd179 2024-06-03 thomas usage_init();
392 6becd179 2024-06-03 thomas
393 6becd179 2024-06-03 thomas repo_path = strdup(argv[0]);
394 6becd179 2024-06-03 thomas if (repo_path == NULL)
395 6becd179 2024-06-03 thomas return got_error_from_errno("strdup");
396 6becd179 2024-06-03 thomas
397 6becd179 2024-06-03 thomas got_path_strip_trailing_slashes(repo_path);
398 6becd179 2024-06-03 thomas
399 6becd179 2024-06-03 thomas error = got_path_mkdir(repo_path);
400 6becd179 2024-06-03 thomas if (error &&
401 6becd179 2024-06-03 thomas !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
402 6becd179 2024-06-03 thomas goto done;
403 6becd179 2024-06-03 thomas
404 6becd179 2024-06-03 thomas error = apply_unveil(repo_path, 0, NULL);
405 6becd179 2024-06-03 thomas if (error)
406 6becd179 2024-06-03 thomas goto done;
407 6becd179 2024-06-03 thomas
408 6becd179 2024-06-03 thomas error = got_repo_init(repo_path, head_name);
409 6becd179 2024-06-03 thomas done:
410 6becd179 2024-06-03 thomas free(repo_path);
411 6becd179 2024-06-03 thomas return error;
412 6becd179 2024-06-03 thomas }
413 6becd179 2024-06-03 thomas
414 6becd179 2024-06-03 thomas __dead static void
415 3ce1b845 2019-07-15 stsp usage_import(void)
416 3ce1b845 2019-07-15 stsp {
417 d6506a3d 2022-08-16 thomas fprintf(stderr, "usage: %s import [-b branch] [-I pattern] [-m message] "
418 d6506a3d 2022-08-16 thomas "[-r repository-path] directory\n", getprogname());
419 3ce1b845 2019-07-15 stsp exit(1);
420 3ce1b845 2019-07-15 stsp }
421 3ce1b845 2019-07-15 stsp
422 ef20f542 2022-06-26 thomas static int
423 3ce1b845 2019-07-15 stsp spawn_editor(const char *editor, const char *file)
424 3ce1b845 2019-07-15 stsp {
425 3ce1b845 2019-07-15 stsp pid_t pid;
426 3ce1b845 2019-07-15 stsp sig_t sighup, sigint, sigquit;
427 3ce1b845 2019-07-15 stsp int st = -1;
428 3ce1b845 2019-07-15 stsp
429 3ce1b845 2019-07-15 stsp sighup = signal(SIGHUP, SIG_IGN);
430 3ce1b845 2019-07-15 stsp sigint = signal(SIGINT, SIG_IGN);
431 3ce1b845 2019-07-15 stsp sigquit = signal(SIGQUIT, SIG_IGN);
432 3ce1b845 2019-07-15 stsp
433 3ce1b845 2019-07-15 stsp switch (pid = fork()) {
434 3ce1b845 2019-07-15 stsp case -1:
435 3ce1b845 2019-07-15 stsp goto doneediting;
436 3ce1b845 2019-07-15 stsp case 0:
437 3ce1b845 2019-07-15 stsp execl(editor, editor, file, (char *)NULL);
438 3ce1b845 2019-07-15 stsp _exit(127);
439 3ce1b845 2019-07-15 stsp }
440 3ce1b845 2019-07-15 stsp
441 3ce1b845 2019-07-15 stsp while (waitpid(pid, &st, 0) == -1)
442 3ce1b845 2019-07-15 stsp if (errno != EINTR)
443 3ce1b845 2019-07-15 stsp break;
444 3ce1b845 2019-07-15 stsp
445 3ce1b845 2019-07-15 stsp doneediting:
446 3ce1b845 2019-07-15 stsp (void)signal(SIGHUP, sighup);
447 3ce1b845 2019-07-15 stsp (void)signal(SIGINT, sigint);
448 3ce1b845 2019-07-15 stsp (void)signal(SIGQUIT, sigquit);
449 3ce1b845 2019-07-15 stsp
450 3ce1b845 2019-07-15 stsp if (!WIFEXITED(st)) {
451 3ce1b845 2019-07-15 stsp errno = EINTR;
452 3ce1b845 2019-07-15 stsp return -1;
453 3ce1b845 2019-07-15 stsp }
454 3ce1b845 2019-07-15 stsp
455 3ce1b845 2019-07-15 stsp return WEXITSTATUS(st);
456 3ce1b845 2019-07-15 stsp }
457 3ce1b845 2019-07-15 stsp
458 3ce1b845 2019-07-15 stsp static const struct got_error *
459 64a300dd 2023-02-17 thomas read_logmsg(char **logmsg, size_t *len, FILE *fp, size_t filesize)
460 75a8c854 2023-02-17 thomas {
461 75a8c854 2023-02-17 thomas const struct got_error *err = NULL;
462 75a8c854 2023-02-17 thomas char *line = NULL;
463 75a8c854 2023-02-17 thomas size_t linesize = 0;
464 75a8c854 2023-02-17 thomas
465 75a8c854 2023-02-17 thomas *logmsg = NULL;
466 75a8c854 2023-02-17 thomas *len = 0;
467 75a8c854 2023-02-17 thomas
468 75a8c854 2023-02-17 thomas if (fseeko(fp, 0L, SEEK_SET) == -1)
469 75a8c854 2023-02-17 thomas return got_error_from_errno("fseeko");
470 75a8c854 2023-02-17 thomas
471 75a8c854 2023-02-17 thomas *logmsg = malloc(filesize + 1);
472 75a8c854 2023-02-17 thomas if (*logmsg == NULL)
473 75a8c854 2023-02-17 thomas return got_error_from_errno("malloc");
474 75a8c854 2023-02-17 thomas (*logmsg)[0] = '\0';
475 75a8c854 2023-02-17 thomas
476 75a8c854 2023-02-17 thomas while (getline(&line, &linesize, fp) != -1) {
477 64a300dd 2023-02-17 thomas if (line[0] == '#' || (*len == 0 && line[0] == '\n'))
478 75a8c854 2023-02-17 thomas continue; /* remove comments and leading empty lines */
479 75a8c854 2023-02-17 thomas *len = strlcat(*logmsg, line, filesize + 1);
480 75a8c854 2023-02-17 thomas if (*len >= filesize + 1) {
481 75a8c854 2023-02-17 thomas err = got_error(GOT_ERR_NO_SPACE);
482 75a8c854 2023-02-17 thomas goto done;
483 75a8c854 2023-02-17 thomas }
484 75a8c854 2023-02-17 thomas }
485 75a8c854 2023-02-17 thomas if (ferror(fp)) {
486 75a8c854 2023-02-17 thomas err = got_ferror(fp, GOT_ERR_IO);
487 75a8c854 2023-02-17 thomas goto done;
488 75a8c854 2023-02-17 thomas }
489 75a8c854 2023-02-17 thomas
490 75a8c854 2023-02-17 thomas while (*len > 0 && (*logmsg)[*len - 1] == '\n') {
491 75a8c854 2023-02-17 thomas (*logmsg)[*len - 1] = '\0';
492 75a8c854 2023-02-17 thomas (*len)--;
493 75a8c854 2023-02-17 thomas }
494 75a8c854 2023-02-17 thomas done:
495 75a8c854 2023-02-17 thomas free(line);
496 75a8c854 2023-02-17 thomas if (err) {
497 75a8c854 2023-02-17 thomas free(*logmsg);
498 75a8c854 2023-02-17 thomas *logmsg = NULL;
499 75a8c854 2023-02-17 thomas *len = 0;
500 75a8c854 2023-02-17 thomas }
501 75a8c854 2023-02-17 thomas return err;
502 75a8c854 2023-02-17 thomas }
503 75a8c854 2023-02-17 thomas
504 75a8c854 2023-02-17 thomas static const struct got_error *
505 3ce1b845 2019-07-15 stsp edit_logmsg(char **logmsg, const char *editor, const char *logmsg_path,
506 28cf319f 2021-01-28 stsp const char *initial_content, size_t initial_content_len,
507 28cf319f 2021-01-28 stsp int require_modification)
508 3ce1b845 2019-07-15 stsp {
509 3ce1b845 2019-07-15 stsp const struct got_error *err = NULL;
510 3ce1b845 2019-07-15 stsp struct stat st, st2;
511 bfa12d5e 2020-09-26 stsp FILE *fp = NULL;
512 83389425 2023-02-17 thomas size_t logmsg_len;
513 3ce1b845 2019-07-15 stsp
514 3ce1b845 2019-07-15 stsp *logmsg = NULL;
515 3ce1b845 2019-07-15 stsp
516 3ce1b845 2019-07-15 stsp if (stat(logmsg_path, &st) == -1)
517 3ce1b845 2019-07-15 stsp return got_error_from_errno2("stat", logmsg_path);
518 3ce1b845 2019-07-15 stsp
519 3ce1b845 2019-07-15 stsp if (spawn_editor(editor, logmsg_path) == -1)
520 3ce1b845 2019-07-15 stsp return got_error_from_errno("failed spawning editor");
521 3ce1b845 2019-07-15 stsp
522 088f4d22 2023-02-17 thomas if (require_modification) {
523 088f4d22 2023-02-17 thomas struct timespec timeout;
524 088f4d22 2023-02-17 thomas
525 088f4d22 2023-02-17 thomas timeout.tv_sec = 0;
526 088f4d22 2023-02-17 thomas timeout.tv_nsec = 1;
527 088f4d22 2023-02-17 thomas nanosleep(&timeout, NULL);
528 088f4d22 2023-02-17 thomas }
529 088f4d22 2023-02-17 thomas
530 3ce1b845 2019-07-15 stsp if (stat(logmsg_path, &st2) == -1)
531 b40793ac 2023-07-17 thomas return got_error_from_errno2("stat", logmsg_path);
532 3ce1b845 2019-07-15 stsp
533 088f4d22 2023-02-17 thomas if (require_modification && st.st_size == st2.st_size &&
534 088f4d22 2023-02-17 thomas timespeccmp(&st.st_mtim, &st2.st_mtim, ==))
535 3ce1b845 2019-07-15 stsp return got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
536 3ce1b845 2019-07-15 stsp "no changes made to commit message, aborting");
537 bfa12d5e 2020-09-26 stsp
538 c56c5d8a 2021-12-31 thomas fp = fopen(logmsg_path, "re");
539 3ce1b845 2019-07-15 stsp if (fp == NULL) {
540 3ce1b845 2019-07-15 stsp err = got_error_from_errno("fopen");
541 3ce1b845 2019-07-15 stsp goto done;
542 3ce1b845 2019-07-15 stsp }
543 bfa12d5e 2020-09-26 stsp
544 83389425 2023-02-17 thomas /* strip comments and leading/trailing newlines */
545 64a300dd 2023-02-17 thomas err = read_logmsg(logmsg, &logmsg_len, fp, st2.st_size);
546 75a8c854 2023-02-17 thomas if (err)
547 75a8c854 2023-02-17 thomas goto done;
548 75a8c854 2023-02-17 thomas if (logmsg_len == 0) {
549 3ce1b845 2019-07-15 stsp err = got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
550 3ce1b845 2019-07-15 stsp "commit message cannot be empty, aborting");
551 bfa12d5e 2020-09-26 stsp goto done;
552 bfa12d5e 2020-09-26 stsp }
553 3ce1b845 2019-07-15 stsp done:
554 bfa12d5e 2020-09-26 stsp if (fp && fclose(fp) == EOF && err == NULL)
555 bfa12d5e 2020-09-26 stsp err = got_error_from_errno("fclose");
556 3ce1b845 2019-07-15 stsp if (err) {
557 3ce1b845 2019-07-15 stsp free(*logmsg);
558 3ce1b845 2019-07-15 stsp *logmsg = NULL;
559 3ce1b845 2019-07-15 stsp }
560 3ce1b845 2019-07-15 stsp return err;
561 3ce1b845 2019-07-15 stsp }
562 3ce1b845 2019-07-15 stsp
563 3ce1b845 2019-07-15 stsp static const struct got_error *
564 ef293bdd 2019-10-21 stsp collect_import_msg(char **logmsg, char **logmsg_path, const char *editor,
565 ef293bdd 2019-10-21 stsp const char *path_dir, const char *branch_name)
566 3ce1b845 2019-07-15 stsp {
567 ef293bdd 2019-10-21 stsp char *initial_content = NULL;
568 3ce1b845 2019-07-15 stsp const struct got_error *err = NULL;
569 1601cb9f 2020-09-11 naddy int initial_content_len;
570 97972933 2020-09-11 stsp int fd = -1;
571 3ce1b845 2019-07-15 stsp
572 1601cb9f 2020-09-11 naddy initial_content_len = asprintf(&initial_content,
573 3ce1b845 2019-07-15 stsp "\n# %s to be imported to branch %s\n", path_dir,
574 1601cb9f 2020-09-11 naddy branch_name);
575 1601cb9f 2020-09-11 naddy if (initial_content_len == -1)
576 3ce1b845 2019-07-15 stsp return got_error_from_errno("asprintf");
577 3ce1b845 2019-07-15 stsp
578 bb63914a 2020-02-17 stsp err = got_opentemp_named_fd(logmsg_path, &fd,
579 fc2a50f2 2022-11-01 thomas GOT_TMPDIR_STR "/got-importmsg", "");
580 3ce1b845 2019-07-15 stsp if (err)
581 3ce1b845 2019-07-15 stsp goto done;
582 3ce1b845 2019-07-15 stsp
583 97972933 2020-09-11 stsp if (write(fd, initial_content, initial_content_len) == -1) {
584 97972933 2020-09-11 stsp err = got_error_from_errno2("write", *logmsg_path);
585 67fdb8a7 2023-03-09 thomas goto done;
586 67fdb8a7 2023-03-09 thomas }
587 67fdb8a7 2023-03-09 thomas if (close(fd) == -1) {
588 67fdb8a7 2023-03-09 thomas err = got_error_from_errno2("close", *logmsg_path);
589 97972933 2020-09-11 stsp goto done;
590 97972933 2020-09-11 stsp }
591 67fdb8a7 2023-03-09 thomas fd = -1;
592 3ce1b845 2019-07-15 stsp
593 bfa12d5e 2020-09-26 stsp err = edit_logmsg(logmsg, editor, *logmsg_path, initial_content,
594 0d5bb276 2020-12-15 stsp initial_content_len, 1);
595 3ce1b845 2019-07-15 stsp done:
596 97972933 2020-09-11 stsp if (fd != -1 && close(fd) == -1 && err == NULL)
597 97972933 2020-09-11 stsp err = got_error_from_errno2("close", *logmsg_path);
598 3ce1b845 2019-07-15 stsp free(initial_content);
599 59f86c76 2020-09-11 stsp if (err) {
600 59f86c76 2020-09-11 stsp free(*logmsg_path);
601 59f86c76 2020-09-11 stsp *logmsg_path = NULL;
602 59f86c76 2020-09-11 stsp }
603 3ce1b845 2019-07-15 stsp return err;
604 3ce1b845 2019-07-15 stsp }
605 3ce1b845 2019-07-15 stsp
606 3ce1b845 2019-07-15 stsp static const struct got_error *
607 3ce1b845 2019-07-15 stsp import_progress(void *arg, const char *path)
608 3ce1b845 2019-07-15 stsp {
609 3ce1b845 2019-07-15 stsp printf("A %s\n", path);
610 3ce1b845 2019-07-15 stsp return NULL;
611 17431c13 2022-02-12 thomas }
612 17431c13 2022-02-12 thomas
613 ec9b5f0b 2022-07-19 thomas static const struct got_error *
614 17431c13 2022-02-12 thomas valid_author(const char *author)
615 17431c13 2022-02-12 thomas {
616 ec9b5f0b 2022-07-19 thomas const char *email = author;
617 ec9b5f0b 2022-07-19 thomas
618 17431c13 2022-02-12 thomas /*
619 ec9b5f0b 2022-07-19 thomas * Git' expects the author (or committer) to be in the form
620 ec9b5f0b 2022-07-19 thomas * "name <email>", which are mostly free form (see the
621 ec9b5f0b 2022-07-19 thomas * "committer" description in git-fast-import(1)). We're only
622 ec9b5f0b 2022-07-19 thomas * doing this to avoid git's object parser breaking on commits
623 ec9b5f0b 2022-07-19 thomas * we create.
624 17431c13 2022-02-12 thomas */
625 ec9b5f0b 2022-07-19 thomas
626 ec9b5f0b 2022-07-19 thomas while (*author && *author != '\n' && *author != '<' && *author != '>')
627 17431c13 2022-02-12 thomas author++;
628 3d47d5be 2022-10-31 thomas if (author != email && *author == '<' && *(author - 1) != ' ')
629 3d47d5be 2022-10-31 thomas return got_error_fmt(GOT_ERR_COMMIT_BAD_AUTHOR, "%s: space "
630 3d47d5be 2022-10-31 thomas "between author name and email required", email);
631 ec9b5f0b 2022-07-19 thomas if (*author++ != '<')
632 ec9b5f0b 2022-07-19 thomas return got_error_fmt(GOT_ERR_COMMIT_NO_EMAIL, "%s", email);
633 ec9b5f0b 2022-07-19 thomas while (*author && *author != '\n' && *author != '<' && *author != '>')
634 17431c13 2022-02-12 thomas author++;
635 ec9b5f0b 2022-07-19 thomas if (strcmp(author, ">") != 0)
636 ec9b5f0b 2022-07-19 thomas return got_error_fmt(GOT_ERR_COMMIT_NO_EMAIL, "%s", email);
637 ec9b5f0b 2022-07-19 thomas return NULL;
638 3ce1b845 2019-07-15 stsp }
639 3ce1b845 2019-07-15 stsp
640 3ce1b845 2019-07-15 stsp static const struct got_error *
641 50b0790e 2020-09-11 stsp get_author(char **author, struct got_repository *repo,
642 50b0790e 2020-09-11 stsp struct got_worktree *worktree)
643 84792843 2019-08-09 stsp {
644 aba9c984 2019-09-08 stsp const struct got_error *err = NULL;
645 50b0790e 2020-09-11 stsp const char *got_author = NULL, *name, *email;
646 50b0790e 2020-09-11 stsp const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
647 84792843 2019-08-09 stsp
648 84792843 2019-08-09 stsp *author = NULL;
649 aba9c984 2019-09-08 stsp
650 50b0790e 2020-09-11 stsp if (worktree)
651 50b0790e 2020-09-11 stsp worktree_conf = got_worktree_get_gotconfig(worktree);
652 50b0790e 2020-09-11 stsp repo_conf = got_repo_get_gotconfig(repo);
653 50b0790e 2020-09-11 stsp
654 50b0790e 2020-09-11 stsp /*
655 50b0790e 2020-09-11 stsp * Priority of potential author information sources, from most
656 50b0790e 2020-09-11 stsp * significant to least significant:
657 50b0790e 2020-09-11 stsp * 1) work tree's .got/got.conf file
658 50b0790e 2020-09-11 stsp * 2) repository's got.conf file
659 50b0790e 2020-09-11 stsp * 3) repository's git config file
660 50b0790e 2020-09-11 stsp * 4) environment variables
661 50b0790e 2020-09-11 stsp * 5) global git config files (in user's home directory or /etc)
662 50b0790e 2020-09-11 stsp */
663 50b0790e 2020-09-11 stsp
664 50b0790e 2020-09-11 stsp if (worktree_conf)
665 50b0790e 2020-09-11 stsp got_author = got_gotconfig_get_author(worktree_conf);
666 50b0790e 2020-09-11 stsp if (got_author == NULL)
667 50b0790e 2020-09-11 stsp got_author = got_gotconfig_get_author(repo_conf);
668 84792843 2019-08-09 stsp if (got_author == NULL) {
669 257add31 2020-09-09 stsp name = got_repo_get_gitconfig_author_name(repo);
670 257add31 2020-09-09 stsp email = got_repo_get_gitconfig_author_email(repo);
671 c9956ddf 2019-09-08 stsp if (name && email) {
672 c9956ddf 2019-09-08 stsp if (asprintf(author, "%s <%s>", name, email) == -1)
673 c9956ddf 2019-09-08 stsp return got_error_from_errno("asprintf");
674 c9956ddf 2019-09-08 stsp return NULL;
675 c9956ddf 2019-09-08 stsp }
676 257add31 2020-09-09 stsp
677 257add31 2020-09-09 stsp got_author = getenv("GOT_AUTHOR");
678 257add31 2020-09-09 stsp if (got_author == NULL) {
679 257add31 2020-09-09 stsp name = got_repo_get_global_gitconfig_author_name(repo);
680 257add31 2020-09-09 stsp email = got_repo_get_global_gitconfig_author_email(
681 257add31 2020-09-09 stsp repo);
682 257add31 2020-09-09 stsp if (name && email) {
683 257add31 2020-09-09 stsp if (asprintf(author, "%s <%s>", name, email)
684 257add31 2020-09-09 stsp == -1)
685 257add31 2020-09-09 stsp return got_error_from_errno("asprintf");
686 257add31 2020-09-09 stsp return NULL;
687 257add31 2020-09-09 stsp }
688 257add31 2020-09-09 stsp /* TODO: Look up user in password database? */
689 257add31 2020-09-09 stsp return got_error(GOT_ERR_COMMIT_NO_AUTHOR);
690 257add31 2020-09-09 stsp }
691 84792843 2019-08-09 stsp }
692 84792843 2019-08-09 stsp
693 aba9c984 2019-09-08 stsp *author = strdup(got_author);
694 aba9c984 2019-09-08 stsp if (*author == NULL)
695 aba9c984 2019-09-08 stsp return got_error_from_errno("strdup");
696 84792843 2019-08-09 stsp
697 ec9b5f0b 2022-07-19 thomas err = valid_author(*author);
698 ec9b5f0b 2022-07-19 thomas if (err) {
699 aba9c984 2019-09-08 stsp free(*author);
700 aba9c984 2019-09-08 stsp *author = NULL;
701 aba9c984 2019-09-08 stsp }
702 aba9c984 2019-09-08 stsp return err;
703 871bd038 2022-07-03 thomas }
704 871bd038 2022-07-03 thomas
705 871bd038 2022-07-03 thomas static const struct got_error *
706 871bd038 2022-07-03 thomas get_allowed_signers(char **allowed_signers, struct got_repository *repo,
707 871bd038 2022-07-03 thomas struct got_worktree *worktree)
708 871bd038 2022-07-03 thomas {
709 871bd038 2022-07-03 thomas const char *got_allowed_signers = NULL;
710 871bd038 2022-07-03 thomas const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
711 871bd038 2022-07-03 thomas
712 871bd038 2022-07-03 thomas *allowed_signers = NULL;
713 871bd038 2022-07-03 thomas
714 871bd038 2022-07-03 thomas if (worktree)
715 871bd038 2022-07-03 thomas worktree_conf = got_worktree_get_gotconfig(worktree);
716 871bd038 2022-07-03 thomas repo_conf = got_repo_get_gotconfig(repo);
717 871bd038 2022-07-03 thomas
718 871bd038 2022-07-03 thomas /*
719 871bd038 2022-07-03 thomas * Priority of potential author information sources, from most
720 871bd038 2022-07-03 thomas * significant to least significant:
721 871bd038 2022-07-03 thomas * 1) work tree's .got/got.conf file
722 871bd038 2022-07-03 thomas * 2) repository's got.conf file
723 871bd038 2022-07-03 thomas */
724 871bd038 2022-07-03 thomas
725 871bd038 2022-07-03 thomas if (worktree_conf)
726 871bd038 2022-07-03 thomas got_allowed_signers = got_gotconfig_get_allowed_signers_file(
727 871bd038 2022-07-03 thomas worktree_conf);
728 871bd038 2022-07-03 thomas if (got_allowed_signers == NULL)
729 871bd038 2022-07-03 thomas got_allowed_signers = got_gotconfig_get_allowed_signers_file(
730 871bd038 2022-07-03 thomas repo_conf);
731 871bd038 2022-07-03 thomas
732 871bd038 2022-07-03 thomas if (got_allowed_signers) {
733 871bd038 2022-07-03 thomas *allowed_signers = strdup(got_allowed_signers);
734 871bd038 2022-07-03 thomas if (*allowed_signers == NULL)
735 871bd038 2022-07-03 thomas return got_error_from_errno("strdup");
736 871bd038 2022-07-03 thomas }
737 871bd038 2022-07-03 thomas return NULL;
738 871bd038 2022-07-03 thomas }
739 871bd038 2022-07-03 thomas
740 871bd038 2022-07-03 thomas static const struct got_error *
741 871bd038 2022-07-03 thomas get_revoked_signers(char **revoked_signers, struct got_repository *repo,
742 871bd038 2022-07-03 thomas struct got_worktree *worktree)
743 871bd038 2022-07-03 thomas {
744 871bd038 2022-07-03 thomas const char *got_revoked_signers = NULL;
745 871bd038 2022-07-03 thomas const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
746 871bd038 2022-07-03 thomas
747 871bd038 2022-07-03 thomas *revoked_signers = NULL;
748 871bd038 2022-07-03 thomas
749 871bd038 2022-07-03 thomas if (worktree)
750 871bd038 2022-07-03 thomas worktree_conf = got_worktree_get_gotconfig(worktree);
751 871bd038 2022-07-03 thomas repo_conf = got_repo_get_gotconfig(repo);
752 871bd038 2022-07-03 thomas
753 871bd038 2022-07-03 thomas /*
754 871bd038 2022-07-03 thomas * Priority of potential author information sources, from most
755 871bd038 2022-07-03 thomas * significant to least significant:
756 871bd038 2022-07-03 thomas * 1) work tree's .got/got.conf file
757 871bd038 2022-07-03 thomas * 2) repository's got.conf file
758 871bd038 2022-07-03 thomas */
759 871bd038 2022-07-03 thomas
760 871bd038 2022-07-03 thomas if (worktree_conf)
761 871bd038 2022-07-03 thomas got_revoked_signers = got_gotconfig_get_revoked_signers_file(
762 871bd038 2022-07-03 thomas worktree_conf);
763 871bd038 2022-07-03 thomas if (got_revoked_signers == NULL)
764 871bd038 2022-07-03 thomas got_revoked_signers = got_gotconfig_get_revoked_signers_file(
765 871bd038 2022-07-03 thomas repo_conf);
766 871bd038 2022-07-03 thomas
767 871bd038 2022-07-03 thomas if (got_revoked_signers) {
768 871bd038 2022-07-03 thomas *revoked_signers = strdup(got_revoked_signers);
769 871bd038 2022-07-03 thomas if (*revoked_signers == NULL)
770 871bd038 2022-07-03 thomas return got_error_from_errno("strdup");
771 871bd038 2022-07-03 thomas }
772 871bd038 2022-07-03 thomas return NULL;
773 c9956ddf 2019-09-08 stsp }
774 c9956ddf 2019-09-08 stsp
775 d4becbee 2023-01-27 thomas static const char *
776 d4becbee 2023-01-27 thomas get_signer_id(struct got_repository *repo, struct got_worktree *worktree)
777 ff5e1f09 2022-07-06 thomas {
778 ff5e1f09 2022-07-06 thomas const char *got_signer_id = NULL;
779 ff5e1f09 2022-07-06 thomas const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
780 ff5e1f09 2022-07-06 thomas
781 ff5e1f09 2022-07-06 thomas if (worktree)
782 ff5e1f09 2022-07-06 thomas worktree_conf = got_worktree_get_gotconfig(worktree);
783 ff5e1f09 2022-07-06 thomas repo_conf = got_repo_get_gotconfig(repo);
784 ff5e1f09 2022-07-06 thomas
785 ff5e1f09 2022-07-06 thomas /*
786 ff5e1f09 2022-07-06 thomas * Priority of potential author information sources, from most
787 ff5e1f09 2022-07-06 thomas * significant to least significant:
788 ff5e1f09 2022-07-06 thomas * 1) work tree's .got/got.conf file
789 ff5e1f09 2022-07-06 thomas * 2) repository's got.conf file
790 ff5e1f09 2022-07-06 thomas */
791 ff5e1f09 2022-07-06 thomas
792 ff5e1f09 2022-07-06 thomas if (worktree_conf)
793 ff5e1f09 2022-07-06 thomas got_signer_id = got_gotconfig_get_signer_id(worktree_conf);
794 ff5e1f09 2022-07-06 thomas if (got_signer_id == NULL)
795 ff5e1f09 2022-07-06 thomas got_signer_id = got_gotconfig_get_signer_id(repo_conf);
796 ff5e1f09 2022-07-06 thomas
797 d4becbee 2023-01-27 thomas return got_signer_id;
798 ff5e1f09 2022-07-06 thomas }
799 ff5e1f09 2022-07-06 thomas
800 ff5e1f09 2022-07-06 thomas static const struct got_error *
801 c9956ddf 2019-09-08 stsp get_gitconfig_path(char **gitconfig_path)
802 c9956ddf 2019-09-08 stsp {
803 c9956ddf 2019-09-08 stsp const char *homedir = getenv("HOME");
804 c9956ddf 2019-09-08 stsp
805 c9956ddf 2019-09-08 stsp *gitconfig_path = NULL;
806 c9956ddf 2019-09-08 stsp if (homedir) {
807 c9956ddf 2019-09-08 stsp if (asprintf(gitconfig_path, "%s/.gitconfig", homedir) == -1)
808 c9956ddf 2019-09-08 stsp return got_error_from_errno("asprintf");
809 c9956ddf 2019-09-08 stsp
810 c9956ddf 2019-09-08 stsp }
811 c9956ddf 2019-09-08 stsp return NULL;
812 84792843 2019-08-09 stsp }
813 84792843 2019-08-09 stsp
814 84792843 2019-08-09 stsp static const struct got_error *
815 3ce1b845 2019-07-15 stsp cmd_import(int argc, char *argv[])
816 3ce1b845 2019-07-15 stsp {
817 3ce1b845 2019-07-15 stsp const struct got_error *error = NULL;
818 3ce1b845 2019-07-15 stsp char *path_dir = NULL, *repo_path = NULL, *logmsg = NULL;
819 c9956ddf 2019-09-08 stsp char *gitconfig_path = NULL, *editor = NULL, *author = NULL;
820 e9424ba1 2022-09-20 thomas const char *branch_name = NULL;
821 e9424ba1 2022-09-20 thomas char *id_str = NULL, *logmsg_path = NULL;
822 e9424ba1 2022-09-20 thomas char refname[PATH_MAX] = "refs/heads/";
823 3ce1b845 2019-07-15 stsp struct got_repository *repo = NULL;
824 3ce1b845 2019-07-15 stsp struct got_reference *branch_ref = NULL, *head_ref = NULL;
825 3ce1b845 2019-07-15 stsp struct got_object_id *new_commit_id = NULL;
826 e9424ba1 2022-09-20 thomas int ch, n = 0;
827 3ce1b845 2019-07-15 stsp struct got_pathlist_head ignores;
828 3ce1b845 2019-07-15 stsp struct got_pathlist_entry *pe;
829 ef293bdd 2019-10-21 stsp int preserve_logmsg = 0;
830 7cd52833 2022-06-23 thomas int *pack_fds = NULL;
831 3ce1b845 2019-07-15 stsp
832 3ce1b845 2019-07-15 stsp TAILQ_INIT(&ignores);
833 a0abeae5 2023-02-17 thomas
834 a0abeae5 2023-02-17 thomas #ifndef PROFILE
835 a0abeae5 2023-02-17 thomas if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd "
836 a0abeae5 2023-02-17 thomas "unveil",
837 a0abeae5 2023-02-17 thomas NULL) == -1)
838 a0abeae5 2023-02-17 thomas err(1, "pledge");
839 a0abeae5 2023-02-17 thomas #endif
840 3ce1b845 2019-07-15 stsp
841 f7065961 2022-10-27 thomas while ((ch = getopt(argc, argv, "b:I:m:r:")) != -1) {
842 3ce1b845 2019-07-15 stsp switch (ch) {
843 3ce1b845 2019-07-15 stsp case 'b':
844 3ce1b845 2019-07-15 stsp branch_name = optarg;
845 3ce1b845 2019-07-15 stsp break;
846 f7065961 2022-10-27 thomas case 'I':
847 f7065961 2022-10-27 thomas if (optarg[0] == '\0')
848 f7065961 2022-10-27 thomas break;
849 f7065961 2022-10-27 thomas error = got_pathlist_insert(&pe, &ignores, optarg,
850 f7065961 2022-10-27 thomas NULL);
851 f7065961 2022-10-27 thomas if (error)
852 f7065961 2022-10-27 thomas goto done;
853 f7065961 2022-10-27 thomas break;
854 3ce1b845 2019-07-15 stsp case 'm':
855 3ce1b845 2019-07-15 stsp logmsg = strdup(optarg);
856 3ce1b845 2019-07-15 stsp if (logmsg == NULL) {
857 3ce1b845 2019-07-15 stsp error = got_error_from_errno("strdup");
858 3ce1b845 2019-07-15 stsp goto done;
859 3ce1b845 2019-07-15 stsp }
860 3ce1b845 2019-07-15 stsp break;
861 3ce1b845 2019-07-15 stsp case 'r':
862 3ce1b845 2019-07-15 stsp repo_path = realpath(optarg, NULL);
863 3ce1b845 2019-07-15 stsp if (repo_path == NULL) {
864 9ba1d308 2019-10-21 stsp error = got_error_from_errno2("realpath",
865 9ba1d308 2019-10-21 stsp optarg);
866 3ce1b845 2019-07-15 stsp goto done;
867 3ce1b845 2019-07-15 stsp }
868 3ce1b845 2019-07-15 stsp break;
869 3ce1b845 2019-07-15 stsp default:
870 b2b65d18 2019-08-22 stsp usage_import();
871 3ce1b845 2019-07-15 stsp /* NOTREACHED */
872 3ce1b845 2019-07-15 stsp }
873 3ce1b845 2019-07-15 stsp }
874 3ce1b845 2019-07-15 stsp
875 3ce1b845 2019-07-15 stsp argc -= optind;
876 3ce1b845 2019-07-15 stsp argv += optind;
877 3ce1b845 2019-07-15 stsp
878 3ce1b845 2019-07-15 stsp if (argc != 1)
879 3ce1b845 2019-07-15 stsp usage_import();
880 2c7829a4 2019-06-17 stsp
881 3ce1b845 2019-07-15 stsp if (repo_path == NULL) {
882 3ce1b845 2019-07-15 stsp repo_path = getcwd(NULL, 0);
883 3ce1b845 2019-07-15 stsp if (repo_path == NULL)
884 3ce1b845 2019-07-15 stsp return got_error_from_errno("getcwd");
885 3ce1b845 2019-07-15 stsp }
886 3ce1b845 2019-07-15 stsp got_path_strip_trailing_slashes(repo_path);
887 c9956ddf 2019-09-08 stsp error = get_gitconfig_path(&gitconfig_path);
888 c9956ddf 2019-09-08 stsp if (error)
889 c9956ddf 2019-09-08 stsp goto done;
890 7cd52833 2022-06-23 thomas error = got_repo_pack_fds_open(&pack_fds);
891 7cd52833 2022-06-23 thomas if (error != NULL)
892 7cd52833 2022-06-23 thomas goto done;
893 7cd52833 2022-06-23 thomas error = got_repo_open(&repo, repo_path, gitconfig_path, pack_fds);
894 8f9af3fc 2024-03-30 thomas if (error)
895 8f9af3fc 2024-03-30 thomas goto done;
896 8f9af3fc 2024-03-30 thomas
897 8f9af3fc 2024-03-30 thomas path_dir = realpath(argv[0], NULL);
898 8f9af3fc 2024-03-30 thomas if (path_dir == NULL) {
899 8f9af3fc 2024-03-30 thomas error = got_error_from_errno2("realpath", argv[0]);
900 8f9af3fc 2024-03-30 thomas goto done;
901 8f9af3fc 2024-03-30 thomas }
902 8f9af3fc 2024-03-30 thomas got_path_strip_trailing_slashes(path_dir);
903 8f9af3fc 2024-03-30 thomas
904 8f9af3fc 2024-03-30 thomas error = get_editor(&editor);
905 3ce1b845 2019-07-15 stsp if (error)
906 3ce1b845 2019-07-15 stsp goto done;
907 aba9c984 2019-09-08 stsp
908 8f9af3fc 2024-03-30 thomas if (unveil(path_dir, "r") != 0) {
909 8f9af3fc 2024-03-30 thomas error = got_error_from_errno2("unveil", path_dir);
910 8f9af3fc 2024-03-30 thomas goto done;
911 8f9af3fc 2024-03-30 thomas }
912 8f9af3fc 2024-03-30 thomas if (unveil(editor, "x") != 0) {
913 8f9af3fc 2024-03-30 thomas error = got_error_from_errno2("unveil", editor);
914 8f9af3fc 2024-03-30 thomas goto done;
915 8f9af3fc 2024-03-30 thomas }
916 8f9af3fc 2024-03-30 thomas error = apply_unveil(got_repo_get_path(repo), 0, NULL);
917 8f9af3fc 2024-03-30 thomas if (error)
918 8f9af3fc 2024-03-30 thomas goto done;
919 8f9af3fc 2024-03-30 thomas
920 50b0790e 2020-09-11 stsp error = get_author(&author, repo, NULL);
921 aba9c984 2019-09-08 stsp if (error)
922 aba9c984 2019-09-08 stsp return error;
923 e560b7e0 2019-11-28 stsp
924 e560b7e0 2019-11-28 stsp /*
925 bd5895f3 2019-11-28 stsp * Don't let the user create a branch name with a leading '-'.
926 e560b7e0 2019-11-28 stsp * While technically a valid reference name, this case is usually
927 e560b7e0 2019-11-28 stsp * an unintended typo.
928 e560b7e0 2019-11-28 stsp */
929 e9424ba1 2022-09-20 thomas if (branch_name && branch_name[0] == '-')
930 bd5895f3 2019-11-28 stsp return got_error_path(branch_name, GOT_ERR_REF_NAME_MINUS);
931 3ce1b845 2019-07-15 stsp
932 e9424ba1 2022-09-20 thomas error = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0);
933 e9424ba1 2022-09-20 thomas if (error && error->code != GOT_ERR_NOT_REF)
934 3ce1b845 2019-07-15 stsp goto done;
935 e9424ba1 2022-09-20 thomas
936 e9424ba1 2022-09-20 thomas if (branch_name)
937 e9424ba1 2022-09-20 thomas n = strlcat(refname, branch_name, sizeof(refname));
938 e9424ba1 2022-09-20 thomas else if (head_ref && got_ref_is_symbolic(head_ref))
939 e9424ba1 2022-09-20 thomas n = strlcpy(refname, got_ref_get_symref_target(head_ref),
940 e9424ba1 2022-09-20 thomas sizeof(refname));
941 e9424ba1 2022-09-20 thomas else
942 e9424ba1 2022-09-20 thomas n = strlcat(refname, "main", sizeof(refname));
943 e9424ba1 2022-09-20 thomas if (n >= sizeof(refname)) {
944 e9424ba1 2022-09-20 thomas error = got_error(GOT_ERR_NO_SPACE);
945 e9424ba1 2022-09-20 thomas goto done;
946 3ce1b845 2019-07-15 stsp }
947 3ce1b845 2019-07-15 stsp
948 3ce1b845 2019-07-15 stsp error = got_ref_open(&branch_ref, repo, refname, 0);
949 3ce1b845 2019-07-15 stsp if (error) {
950 3ce1b845 2019-07-15 stsp if (error->code != GOT_ERR_NOT_REF)
951 3ce1b845 2019-07-15 stsp goto done;
952 3ce1b845 2019-07-15 stsp } else {
953 3ce1b845 2019-07-15 stsp error = got_error_msg(GOT_ERR_BRANCH_EXISTS,
954 3ce1b845 2019-07-15 stsp "import target branch already exists");
955 3ce1b845 2019-07-15 stsp goto done;
956 3ce1b845 2019-07-15 stsp }
957 3ce1b845 2019-07-15 stsp
958 102d840d 2023-06-22 thomas if (logmsg == NULL || *logmsg == '\0') {
959 8e158b01 2019-09-22 stsp free(logmsg);
960 ef293bdd 2019-10-21 stsp error = collect_import_msg(&logmsg, &logmsg_path, editor,
961 ef293bdd 2019-10-21 stsp path_dir, refname);
962 ef293bdd 2019-10-21 stsp if (error) {
963 ef293bdd 2019-10-21 stsp if (error->code != GOT_ERR_COMMIT_MSG_EMPTY &&
964 ef293bdd 2019-10-21 stsp logmsg_path != NULL)
965 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
966 3ce1b845 2019-07-15 stsp goto done;
967 ef293bdd 2019-10-21 stsp }
968 3ce1b845 2019-07-15 stsp }
969 3ce1b845 2019-07-15 stsp
970 3ce1b845 2019-07-15 stsp error = got_repo_import(&new_commit_id, path_dir, logmsg,
971 84792843 2019-08-09 stsp author, &ignores, repo, import_progress, NULL);
972 ef293bdd 2019-10-21 stsp if (error) {
973 ef293bdd 2019-10-21 stsp if (logmsg_path)
974 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
975 3ce1b845 2019-07-15 stsp goto done;
976 ef293bdd 2019-10-21 stsp }
977 3ce1b845 2019-07-15 stsp
978 3ce1b845 2019-07-15 stsp error = got_ref_alloc(&branch_ref, refname, new_commit_id);
979 ef293bdd 2019-10-21 stsp if (error) {
980 ef293bdd 2019-10-21 stsp if (logmsg_path)
981 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
982 3ce1b845 2019-07-15 stsp goto done;
983 ef293bdd 2019-10-21 stsp }
984 3ce1b845 2019-07-15 stsp
985 3ce1b845 2019-07-15 stsp error = got_ref_write(branch_ref, repo);
986 ef293bdd 2019-10-21 stsp if (error) {
987 ef293bdd 2019-10-21 stsp if (logmsg_path)
988 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
989 3ce1b845 2019-07-15 stsp goto done;
990 ef293bdd 2019-10-21 stsp }
991 3ce1b845 2019-07-15 stsp
992 3ce1b845 2019-07-15 stsp error = got_object_id_str(&id_str, new_commit_id);
993 ef293bdd 2019-10-21 stsp if (error) {
994 ef293bdd 2019-10-21 stsp if (logmsg_path)
995 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
996 3ce1b845 2019-07-15 stsp goto done;
997 ef293bdd 2019-10-21 stsp }
998 3ce1b845 2019-07-15 stsp
999 3ce1b845 2019-07-15 stsp error = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0);
1000 3ce1b845 2019-07-15 stsp if (error) {
1001 ef293bdd 2019-10-21 stsp if (error->code != GOT_ERR_NOT_REF) {
1002 ef293bdd 2019-10-21 stsp if (logmsg_path)
1003 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1004 3ce1b845 2019-07-15 stsp goto done;
1005 ef293bdd 2019-10-21 stsp }
1006 3ce1b845 2019-07-15 stsp
1007 3ce1b845 2019-07-15 stsp error = got_ref_alloc_symref(&head_ref, GOT_REF_HEAD,
1008 3ce1b845 2019-07-15 stsp branch_ref);
1009 ef293bdd 2019-10-21 stsp if (error) {
1010 ef293bdd 2019-10-21 stsp if (logmsg_path)
1011 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1012 3ce1b845 2019-07-15 stsp goto done;
1013 ef293bdd 2019-10-21 stsp }
1014 3ce1b845 2019-07-15 stsp
1015 3ce1b845 2019-07-15 stsp error = got_ref_write(head_ref, repo);
1016 ef293bdd 2019-10-21 stsp if (error) {
1017 ef293bdd 2019-10-21 stsp if (logmsg_path)
1018 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1019 3ce1b845 2019-07-15 stsp goto done;
1020 ef293bdd 2019-10-21 stsp }
1021 3ce1b845 2019-07-15 stsp }
1022 3ce1b845 2019-07-15 stsp
1023 3ce1b845 2019-07-15 stsp printf("Created branch %s with commit %s\n",
1024 3ce1b845 2019-07-15 stsp got_ref_get_name(branch_ref), id_str);
1025 2c7829a4 2019-06-17 stsp done:
1026 7cd52833 2022-06-23 thomas if (pack_fds) {
1027 7cd52833 2022-06-23 thomas const struct got_error *pack_err =
1028 7cd52833 2022-06-23 thomas got_repo_pack_fds_close(pack_fds);
1029 7cd52833 2022-06-23 thomas if (error == NULL)
1030 7cd52833 2022-06-23 thomas error = pack_err;
1031 e9e79470 2023-04-14 thomas }
1032 e9e79470 2023-04-14 thomas if (repo) {
1033 e9e79470 2023-04-14 thomas const struct got_error *close_err = got_repo_close(repo);
1034 e9e79470 2023-04-14 thomas if (error == NULL)
1035 e9e79470 2023-04-14 thomas error = close_err;
1036 7cd52833 2022-06-23 thomas }
1037 ef293bdd 2019-10-21 stsp if (preserve_logmsg) {
1038 ef293bdd 2019-10-21 stsp fprintf(stderr, "%s: log message preserved in %s\n",
1039 ef293bdd 2019-10-21 stsp getprogname(), logmsg_path);
1040 ef293bdd 2019-10-21 stsp } else if (logmsg_path && unlink(logmsg_path) == -1 && error == NULL)
1041 ef293bdd 2019-10-21 stsp error = got_error_from_errno2("unlink", logmsg_path);
1042 8e158b01 2019-09-22 stsp free(logmsg);
1043 ef293bdd 2019-10-21 stsp free(logmsg_path);
1044 2c7829a4 2019-06-17 stsp free(repo_path);
1045 3ce1b845 2019-07-15 stsp free(editor);
1046 3ce1b845 2019-07-15 stsp free(new_commit_id);
1047 3ce1b845 2019-07-15 stsp free(id_str);
1048 aba9c984 2019-09-08 stsp free(author);
1049 c9956ddf 2019-09-08 stsp free(gitconfig_path);
1050 3ce1b845 2019-07-15 stsp if (branch_ref)
1051 3ce1b845 2019-07-15 stsp got_ref_close(branch_ref);
1052 3ce1b845 2019-07-15 stsp if (head_ref)
1053 3ce1b845 2019-07-15 stsp got_ref_close(head_ref);
1054 2c7829a4 2019-06-17 stsp return error;
1055 93658fb9 2020-03-18 stsp }
1056 93658fb9 2020-03-18 stsp
1057 93658fb9 2020-03-18 stsp __dead static void
1058 93658fb9 2020-03-18 stsp usage_clone(void)
1059 93658fb9 2020-03-18 stsp {
1060 d6506a3d 2022-08-16 thomas fprintf(stderr, "usage: %s clone [-almqv] [-b branch] [-R reference] "
1061 d6506a3d 2022-08-16 thomas "repository-URL [directory]\n", getprogname());
1062 93658fb9 2020-03-18 stsp exit(1);
1063 93658fb9 2020-03-18 stsp }
1064 892ac3b6 2020-03-18 stsp
1065 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg {
1066 892ac3b6 2020-03-18 stsp char last_scaled_size[FMT_SCALED_STRSIZE];
1067 892ac3b6 2020-03-18 stsp int last_p_indexed;
1068 892ac3b6 2020-03-18 stsp int last_p_resolved;
1069 68999b92 2020-03-18 stsp int verbosity;
1070 04d9a9ec 2020-09-24 stsp
1071 04d9a9ec 2020-09-24 stsp struct got_repository *repo;
1072 04d9a9ec 2020-09-24 stsp
1073 04d9a9ec 2020-09-24 stsp int create_configs;
1074 04d9a9ec 2020-09-24 stsp int configs_created;
1075 04d9a9ec 2020-09-24 stsp struct {
1076 04d9a9ec 2020-09-24 stsp struct got_pathlist_head *symrefs;
1077 04d9a9ec 2020-09-24 stsp struct got_pathlist_head *wanted_branches;
1078 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs;
1079 04d9a9ec 2020-09-24 stsp const char *proto;
1080 04d9a9ec 2020-09-24 stsp const char *host;
1081 04d9a9ec 2020-09-24 stsp const char *port;
1082 04d9a9ec 2020-09-24 stsp const char *remote_repo_path;
1083 04d9a9ec 2020-09-24 stsp const char *git_url;
1084 04d9a9ec 2020-09-24 stsp int fetch_all_branches;
1085 04d9a9ec 2020-09-24 stsp int mirror_references;
1086 04d9a9ec 2020-09-24 stsp } config_info;
1087 892ac3b6 2020-03-18 stsp };
1088 93658fb9 2020-03-18 stsp
1089 04d9a9ec 2020-09-24 stsp /* XXX forward declaration */
1090 93658fb9 2020-03-18 stsp static const struct got_error *
1091 04d9a9ec 2020-09-24 stsp create_config_files(const char *proto, const char *host, const char *port,
1092 04d9a9ec 2020-09-24 stsp const char *remote_repo_path, const char *git_url, int fetch_all_branches,
1093 04d9a9ec 2020-09-24 stsp int mirror_references, struct got_pathlist_head *symrefs,
1094 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_branches,
1095 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, struct got_repository *repo);
1096 04d9a9ec 2020-09-24 stsp
1097 04d9a9ec 2020-09-24 stsp static const struct got_error *
1098 baa9fea0 2020-03-18 stsp fetch_progress(void *arg, const char *message, off_t packfile_size,
1099 668a20f6 2020-03-18 stsp int nobj_total, int nobj_indexed, int nobj_loose, int nobj_resolved)
1100 531c3985 2020-03-18 stsp {
1101 04d9a9ec 2020-09-24 stsp const struct got_error *err = NULL;
1102 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg *a = arg;
1103 892ac3b6 2020-03-18 stsp char scaled_size[FMT_SCALED_STRSIZE];
1104 892ac3b6 2020-03-18 stsp int p_indexed, p_resolved;
1105 892ac3b6 2020-03-18 stsp int print_size = 0, print_indexed = 0, print_resolved = 0;
1106 04d9a9ec 2020-09-24 stsp
1107 04d9a9ec 2020-09-24 stsp /*
1108 04d9a9ec 2020-09-24 stsp * In order to allow a failed clone to be resumed with 'got fetch'
1109 04d9a9ec 2020-09-24 stsp * we try to create configuration files as soon as possible.
1110 04d9a9ec 2020-09-24 stsp * Once the server has sent information about its default branch
1111 04d9a9ec 2020-09-24 stsp * we have all required information.
1112 04d9a9ec 2020-09-24 stsp */
1113 04d9a9ec 2020-09-24 stsp if (a->create_configs && !a->configs_created &&
1114 04d9a9ec 2020-09-24 stsp !TAILQ_EMPTY(a->config_info.symrefs)) {
1115 04d9a9ec 2020-09-24 stsp err = create_config_files(a->config_info.proto,
1116 62d463ca 2020-10-20 naddy a->config_info.host, a->config_info.port,
1117 62d463ca 2020-10-20 naddy a->config_info.remote_repo_path,
1118 62d463ca 2020-10-20 naddy a->config_info.git_url,
1119 62d463ca 2020-10-20 naddy a->config_info.fetch_all_branches,
1120 62d463ca 2020-10-20 naddy a->config_info.mirror_references,
1121 62d463ca 2020-10-20 naddy a->config_info.symrefs,
1122 99495ddb 2021-01-10 stsp a->config_info.wanted_branches,
1123 99495ddb 2021-01-10 stsp a->config_info.wanted_refs, a->repo);
1124 04d9a9ec 2020-09-24 stsp if (err)
1125 04d9a9ec 2020-09-24 stsp return err;
1126 04d9a9ec 2020-09-24 stsp a->configs_created = 1;
1127 04d9a9ec 2020-09-24 stsp }
1128 b2409d58 2020-03-18 stsp
1129 68999b92 2020-03-18 stsp if (a->verbosity < 0)
1130 68999b92 2020-03-18 stsp return NULL;
1131 68999b92 2020-03-18 stsp
1132 fd843b58 2020-03-18 stsp if (message && message[0] != '\0') {
1133 d2cdc636 2020-03-18 stsp printf("\rserver: %s", message);
1134 892ac3b6 2020-03-18 stsp fflush(stdout);
1135 12d1281e 2020-03-19 stsp return NULL;
1136 b2409d58 2020-03-18 stsp }
1137 b2409d58 2020-03-18 stsp
1138 b2409d58 2020-03-18 stsp if (packfile_size > 0 || nobj_indexed > 0) {
1139 892ac3b6 2020-03-18 stsp if (fmt_scaled(packfile_size, scaled_size) == 0 &&
1140 892ac3b6 2020-03-18 stsp (a->last_scaled_size[0] == '\0' ||
1141 892ac3b6 2020-03-18 stsp strcmp(scaled_size, a->last_scaled_size)) != 0) {
1142 892ac3b6 2020-03-18 stsp print_size = 1;
1143 892ac3b6 2020-03-18 stsp if (strlcpy(a->last_scaled_size, scaled_size,
1144 892ac3b6 2020-03-18 stsp FMT_SCALED_STRSIZE) >= FMT_SCALED_STRSIZE)
1145 892ac3b6 2020-03-18 stsp return got_error(GOT_ERR_NO_SPACE);
1146 892ac3b6 2020-03-18 stsp }
1147 61cc1a7a 2020-03-18 stsp if (nobj_indexed > 0) {
1148 892ac3b6 2020-03-18 stsp p_indexed = (nobj_indexed * 100) / nobj_total;
1149 892ac3b6 2020-03-18 stsp if (p_indexed != a->last_p_indexed) {
1150 892ac3b6 2020-03-18 stsp a->last_p_indexed = p_indexed;
1151 892ac3b6 2020-03-18 stsp print_indexed = 1;
1152 892ac3b6 2020-03-18 stsp print_size = 1;
1153 892ac3b6 2020-03-18 stsp }
1154 61cc1a7a 2020-03-18 stsp }
1155 61cc1a7a 2020-03-18 stsp if (nobj_resolved > 0) {
1156 892ac3b6 2020-03-18 stsp p_resolved = (nobj_resolved * 100) /
1157 892ac3b6 2020-03-18 stsp (nobj_total - nobj_loose);
1158 892ac3b6 2020-03-18 stsp if (p_resolved != a->last_p_resolved) {
1159 892ac3b6 2020-03-18 stsp a->last_p_resolved = p_resolved;
1160 892ac3b6 2020-03-18 stsp print_resolved = 1;
1161 892ac3b6 2020-03-18 stsp print_indexed = 1;
1162 892ac3b6 2020-03-18 stsp print_size = 1;
1163 892ac3b6 2020-03-18 stsp }
1164 61cc1a7a 2020-03-18 stsp }
1165 3168e5da 2020-09-10 stsp
1166 d2cdc636 2020-03-18 stsp }
1167 892ac3b6 2020-03-18 stsp if (print_size || print_indexed || print_resolved)
1168 892ac3b6 2020-03-18 stsp printf("\r");
1169 892ac3b6 2020-03-18 stsp if (print_size)
1170 d2f35ef7 2022-02-13 thomas printf("%*s fetched", FMT_SCALED_STRSIZE - 2, scaled_size);
1171 d715f13e 2020-03-19 stsp if (print_indexed)
1172 892ac3b6 2020-03-18 stsp printf("; indexing %d%%", p_indexed);
1173 d715f13e 2020-03-19 stsp if (print_resolved)
1174 892ac3b6 2020-03-18 stsp printf("; resolving deltas %d%%", p_resolved);
1175 892ac3b6 2020-03-18 stsp if (print_size || print_indexed || print_resolved)
1176 892ac3b6 2020-03-18 stsp fflush(stdout);
1177 892ac3b6 2020-03-18 stsp
1178 531c3985 2020-03-18 stsp return NULL;
1179 531c3985 2020-03-18 stsp }
1180 531c3985 2020-03-18 stsp
1181 531c3985 2020-03-18 stsp static const struct got_error *
1182 04d9a9ec 2020-09-24 stsp create_symref(const char *refname, struct got_reference *target_ref,
1183 04d9a9ec 2020-09-24 stsp int verbosity, struct got_repository *repo)
1184 4ba14133 2020-03-20 stsp {
1185 4ba14133 2020-03-20 stsp const struct got_error *err;
1186 04d9a9ec 2020-09-24 stsp struct got_reference *head_symref;
1187 4ba14133 2020-03-20 stsp
1188 04d9a9ec 2020-09-24 stsp err = got_ref_alloc_symref(&head_symref, refname, target_ref);
1189 4ba14133 2020-03-20 stsp if (err)
1190 4ba14133 2020-03-20 stsp return err;
1191 4ba14133 2020-03-20 stsp
1192 04d9a9ec 2020-09-24 stsp err = got_ref_write(head_symref, repo);
1193 6338a6a1 2020-03-21 stsp if (err == NULL && verbosity > 0) {
1194 6338a6a1 2020-03-21 stsp printf("Created reference %s: %s\n", GOT_REF_HEAD,
1195 6338a6a1 2020-03-21 stsp got_ref_get_name(target_ref));
1196 6338a6a1 2020-03-21 stsp }
1197 04d9a9ec 2020-09-24 stsp got_ref_close(head_symref);
1198 4ba14133 2020-03-20 stsp return err;
1199 4ba14133 2020-03-20 stsp }
1200 4ba14133 2020-03-20 stsp
1201 4ba14133 2020-03-20 stsp static const struct got_error *
1202 41b0de12 2020-03-21 stsp list_remote_refs(struct got_pathlist_head *symrefs,
1203 41b0de12 2020-03-21 stsp struct got_pathlist_head *refs)
1204 41b0de12 2020-03-21 stsp {
1205 41b0de12 2020-03-21 stsp const struct got_error *err;
1206 41b0de12 2020-03-21 stsp struct got_pathlist_entry *pe;
1207 41b0de12 2020-03-21 stsp
1208 41b0de12 2020-03-21 stsp TAILQ_FOREACH(pe, symrefs, entry) {
1209 41b0de12 2020-03-21 stsp const char *refname = pe->path;
1210 41b0de12 2020-03-21 stsp const char *targetref = pe->data;
1211 41b0de12 2020-03-21 stsp
1212 41b0de12 2020-03-21 stsp printf("%s: %s\n", refname, targetref);
1213 41b0de12 2020-03-21 stsp }
1214 41b0de12 2020-03-21 stsp
1215 41b0de12 2020-03-21 stsp TAILQ_FOREACH(pe, refs, entry) {
1216 41b0de12 2020-03-21 stsp const char *refname = pe->path;
1217 41b0de12 2020-03-21 stsp struct got_object_id *id = pe->data;
1218 41b0de12 2020-03-21 stsp char *id_str;
1219 41b0de12 2020-03-21 stsp
1220 41b0de12 2020-03-21 stsp err = got_object_id_str(&id_str, id);
1221 41b0de12 2020-03-21 stsp if (err)
1222 41b0de12 2020-03-21 stsp return err;
1223 41b0de12 2020-03-21 stsp printf("%s: %s\n", refname, id_str);
1224 41b0de12 2020-03-21 stsp free(id_str);
1225 41b0de12 2020-03-21 stsp }
1226 41b0de12 2020-03-21 stsp
1227 41b0de12 2020-03-21 stsp return NULL;
1228 6338a6a1 2020-03-21 stsp }
1229 6338a6a1 2020-03-21 stsp
1230 6338a6a1 2020-03-21 stsp static const struct got_error *
1231 6338a6a1 2020-03-21 stsp create_ref(const char *refname, struct got_object_id *id,
1232 6338a6a1 2020-03-21 stsp int verbosity, struct got_repository *repo)
1233 6338a6a1 2020-03-21 stsp {
1234 6338a6a1 2020-03-21 stsp const struct got_error *err = NULL;
1235 6338a6a1 2020-03-21 stsp struct got_reference *ref;
1236 6338a6a1 2020-03-21 stsp char *id_str;
1237 6338a6a1 2020-03-21 stsp
1238 6338a6a1 2020-03-21 stsp err = got_object_id_str(&id_str, id);
1239 6338a6a1 2020-03-21 stsp if (err)
1240 6338a6a1 2020-03-21 stsp return err;
1241 6338a6a1 2020-03-21 stsp
1242 6338a6a1 2020-03-21 stsp err = got_ref_alloc(&ref, refname, id);
1243 6338a6a1 2020-03-21 stsp if (err)
1244 6338a6a1 2020-03-21 stsp goto done;
1245 6338a6a1 2020-03-21 stsp
1246 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
1247 6338a6a1 2020-03-21 stsp got_ref_close(ref);
1248 6338a6a1 2020-03-21 stsp
1249 6338a6a1 2020-03-21 stsp if (err == NULL && verbosity >= 0)
1250 6338a6a1 2020-03-21 stsp printf("Created reference %s: %s\n", refname, id_str);
1251 6338a6a1 2020-03-21 stsp done:
1252 6338a6a1 2020-03-21 stsp free(id_str);
1253 6338a6a1 2020-03-21 stsp return err;
1254 0e4002ca 2020-03-21 stsp }
1255 0e4002ca 2020-03-21 stsp
1256 0e4002ca 2020-03-21 stsp static int
1257 0e4002ca 2020-03-21 stsp match_wanted_ref(const char *refname, const char *wanted_ref)
1258 0e4002ca 2020-03-21 stsp {
1259 0e4002ca 2020-03-21 stsp if (strncmp(refname, "refs/", 5) != 0)
1260 0e4002ca 2020-03-21 stsp return 0;
1261 0e4002ca 2020-03-21 stsp refname += 5;
1262 0e4002ca 2020-03-21 stsp
1263 0e4002ca 2020-03-21 stsp /*
1264 0e4002ca 2020-03-21 stsp * Prevent fetching of references that won't make any
1265 0e4002ca 2020-03-21 stsp * sense outside of the remote repository's context.
1266 0e4002ca 2020-03-21 stsp */
1267 0e4002ca 2020-03-21 stsp if (strncmp(refname, "got/", 4) == 0)
1268 0e4002ca 2020-03-21 stsp return 0;
1269 0e4002ca 2020-03-21 stsp if (strncmp(refname, "remotes/", 8) == 0)
1270 0e4002ca 2020-03-21 stsp return 0;
1271 0e4002ca 2020-03-21 stsp
1272 0e4002ca 2020-03-21 stsp if (strncmp(wanted_ref, "refs/", 5) == 0)
1273 0e4002ca 2020-03-21 stsp wanted_ref += 5;
1274 0e4002ca 2020-03-21 stsp
1275 0e4002ca 2020-03-21 stsp /* Allow prefix match. */
1276 0e4002ca 2020-03-21 stsp if (got_path_is_child(refname, wanted_ref, strlen(wanted_ref)))
1277 0e4002ca 2020-03-21 stsp return 1;
1278 0e4002ca 2020-03-21 stsp
1279 0e4002ca 2020-03-21 stsp /* Allow exact match. */
1280 0e4002ca 2020-03-21 stsp return (strcmp(refname, wanted_ref) == 0);
1281 41b0de12 2020-03-21 stsp }
1282 41b0de12 2020-03-21 stsp
1283 0e4002ca 2020-03-21 stsp static int
1284 0e4002ca 2020-03-21 stsp is_wanted_ref(struct got_pathlist_head *wanted_refs, const char *refname)
1285 0e4002ca 2020-03-21 stsp {
1286 0e4002ca 2020-03-21 stsp struct got_pathlist_entry *pe;
1287 0e4002ca 2020-03-21 stsp
1288 0e4002ca 2020-03-21 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1289 0e4002ca 2020-03-21 stsp if (match_wanted_ref(refname, pe->path))
1290 0e4002ca 2020-03-21 stsp return 1;
1291 0e4002ca 2020-03-21 stsp }
1292 0e4002ca 2020-03-21 stsp
1293 0e4002ca 2020-03-21 stsp return 0;
1294 0e4002ca 2020-03-21 stsp }
1295 0e4002ca 2020-03-21 stsp
1296 41b0de12 2020-03-21 stsp static const struct got_error *
1297 0e4002ca 2020-03-21 stsp create_wanted_ref(const char *refname, struct got_object_id *id,
1298 0e4002ca 2020-03-21 stsp const char *remote_repo_name, int verbosity, struct got_repository *repo)
1299 0e4002ca 2020-03-21 stsp {
1300 0e4002ca 2020-03-21 stsp const struct got_error *err;
1301 0e4002ca 2020-03-21 stsp char *remote_refname;
1302 0e4002ca 2020-03-21 stsp
1303 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
1304 0e4002ca 2020-03-21 stsp refname += 5;
1305 0e4002ca 2020-03-21 stsp
1306 0e4002ca 2020-03-21 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
1307 0e4002ca 2020-03-21 stsp remote_repo_name, refname) == -1)
1308 0e4002ca 2020-03-21 stsp return got_error_from_errno("asprintf");
1309 0e4002ca 2020-03-21 stsp
1310 0e4002ca 2020-03-21 stsp err = create_ref(remote_refname, id, verbosity, repo);
1311 0e4002ca 2020-03-21 stsp free(remote_refname);
1312 7c0b7f42 2020-09-24 stsp return err;
1313 7c0b7f42 2020-09-24 stsp }
1314 7c0b7f42 2020-09-24 stsp
1315 7c0b7f42 2020-09-24 stsp static const struct got_error *
1316 7c0b7f42 2020-09-24 stsp create_gotconfig(const char *proto, const char *host, const char *port,
1317 15d3c221 2021-01-05 stsp const char *remote_repo_path, const char *default_branch,
1318 0c8b29c5 2021-01-05 stsp int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1319 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, int mirror_references,
1320 99495ddb 2021-01-10 stsp struct got_repository *repo)
1321 7c0b7f42 2020-09-24 stsp {
1322 7c0b7f42 2020-09-24 stsp const struct got_error *err = NULL;
1323 7c0b7f42 2020-09-24 stsp char *gotconfig_path = NULL;
1324 7c0b7f42 2020-09-24 stsp char *gotconfig = NULL;
1325 7c0b7f42 2020-09-24 stsp FILE *gotconfig_file = NULL;
1326 15d3c221 2021-01-05 stsp const char *branchname = NULL;
1327 99495ddb 2021-01-10 stsp char *branches = NULL, *refs = NULL;
1328 7c0b7f42 2020-09-24 stsp ssize_t n;
1329 7c0b7f42 2020-09-24 stsp
1330 0c8b29c5 2021-01-05 stsp if (!fetch_all_branches && !TAILQ_EMPTY(wanted_branches)) {
1331 132af4a5 2021-01-05 stsp struct got_pathlist_entry *pe;
1332 132af4a5 2021-01-05 stsp TAILQ_FOREACH(pe, wanted_branches, entry) {
1333 132af4a5 2021-01-05 stsp char *s;
1334 132af4a5 2021-01-05 stsp branchname = pe->path;
1335 132af4a5 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1336 132af4a5 2021-01-05 stsp branchname += 11;
1337 132af4a5 2021-01-05 stsp if (asprintf(&s, "%s\"%s\" ",
1338 132af4a5 2021-01-05 stsp branches ? branches : "", branchname) == -1) {
1339 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1340 132af4a5 2021-01-05 stsp goto done;
1341 132af4a5 2021-01-05 stsp }
1342 132af4a5 2021-01-05 stsp free(branches);
1343 132af4a5 2021-01-05 stsp branches = s;
1344 132af4a5 2021-01-05 stsp }
1345 0c8b29c5 2021-01-05 stsp } else if (!fetch_all_branches && default_branch) {
1346 15d3c221 2021-01-05 stsp branchname = default_branch;
1347 15d3c221 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1348 15d3c221 2021-01-05 stsp branchname += 11;
1349 132af4a5 2021-01-05 stsp if (asprintf(&branches, "\"%s\" ", branchname) == -1) {
1350 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1351 132af4a5 2021-01-05 stsp goto done;
1352 99495ddb 2021-01-10 stsp }
1353 99495ddb 2021-01-10 stsp }
1354 99495ddb 2021-01-10 stsp if (!TAILQ_EMPTY(wanted_refs)) {
1355 99495ddb 2021-01-10 stsp struct got_pathlist_entry *pe;
1356 99495ddb 2021-01-10 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1357 99495ddb 2021-01-10 stsp char *s;
1358 99495ddb 2021-01-10 stsp const char *refname = pe->path;
1359 99495ddb 2021-01-10 stsp if (strncmp(refname, "refs/", 5) == 0)
1360 99495ddb 2021-01-10 stsp branchname += 5;
1361 99495ddb 2021-01-10 stsp if (asprintf(&s, "%s\"%s\" ",
1362 99495ddb 2021-01-10 stsp refs ? refs : "", refname) == -1) {
1363 99495ddb 2021-01-10 stsp err = got_error_from_errno("asprintf");
1364 99495ddb 2021-01-10 stsp goto done;
1365 99495ddb 2021-01-10 stsp }
1366 99495ddb 2021-01-10 stsp free(refs);
1367 99495ddb 2021-01-10 stsp refs = s;
1368 132af4a5 2021-01-05 stsp }
1369 15d3c221 2021-01-05 stsp }
1370 15d3c221 2021-01-05 stsp
1371 7c0b7f42 2020-09-24 stsp /* Create got.conf(5). */
1372 7c0b7f42 2020-09-24 stsp gotconfig_path = got_repo_get_path_gotconfig(repo);
1373 7c0b7f42 2020-09-24 stsp if (gotconfig_path == NULL) {
1374 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("got_repo_get_path_gotconfig");
1375 7c0b7f42 2020-09-24 stsp goto done;
1376 7c0b7f42 2020-09-24 stsp }
1377 c56c5d8a 2021-12-31 thomas gotconfig_file = fopen(gotconfig_path, "ae");
1378 7c0b7f42 2020-09-24 stsp if (gotconfig_file == NULL) {
1379 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fopen", gotconfig_path);
1380 7c0b7f42 2020-09-24 stsp goto done;
1381 7c0b7f42 2020-09-24 stsp }
1382 7c0b7f42 2020-09-24 stsp if (asprintf(&gotconfig,
1383 7c0b7f42 2020-09-24 stsp "remote \"%s\" {\n"
1384 7c0b7f42 2020-09-24 stsp "\tserver %s\n"
1385 7c0b7f42 2020-09-24 stsp "\tprotocol %s\n"
1386 7c0b7f42 2020-09-24 stsp "%s%s%s"
1387 7c0b7f42 2020-09-24 stsp "\trepository \"%s\"\n"
1388 15d3c221 2021-01-05 stsp "%s%s%s"
1389 99495ddb 2021-01-10 stsp "%s%s%s"
1390 7c0b7f42 2020-09-24 stsp "%s"
1391 0c8b29c5 2021-01-05 stsp "%s"
1392 7c0b7f42 2020-09-24 stsp "}\n",
1393 7c0b7f42 2020-09-24 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, host, proto,
1394 7c0b7f42 2020-09-24 stsp port ? "\tport " : "", port ? port : "", port ? "\n" : "",
1395 132af4a5 2021-01-05 stsp remote_repo_path, branches ? "\tbranch { " : "",
1396 b6b86fd1 2022-08-30 thomas branches ? branches : "", branches ? "}\n" : "",
1397 b6b86fd1 2022-08-30 thomas refs ? "\treference { " : "", refs ? refs : "", refs ? "}\n" : "",
1398 459c9b5d 2022-07-03 thomas mirror_references ? "\tmirror_references yes\n" : "",
1399 25eb5847 2022-07-03 thomas fetch_all_branches ? "\tfetch_all_branches yes\n" : "") == -1) {
1400 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1401 7c0b7f42 2020-09-24 stsp goto done;
1402 7c0b7f42 2020-09-24 stsp }
1403 7c0b7f42 2020-09-24 stsp n = fwrite(gotconfig, 1, strlen(gotconfig), gotconfig_file);
1404 7c0b7f42 2020-09-24 stsp if (n != strlen(gotconfig)) {
1405 7c0b7f42 2020-09-24 stsp err = got_ferror(gotconfig_file, GOT_ERR_IO);
1406 7c0b7f42 2020-09-24 stsp goto done;
1407 7c0b7f42 2020-09-24 stsp }
1408 7c0b7f42 2020-09-24 stsp
1409 7c0b7f42 2020-09-24 stsp done:
1410 7c0b7f42 2020-09-24 stsp if (gotconfig_file && fclose(gotconfig_file) == EOF && err == NULL)
1411 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fclose", gotconfig_path);
1412 7c0b7f42 2020-09-24 stsp free(gotconfig_path);
1413 132af4a5 2021-01-05 stsp free(branches);
1414 7c0b7f42 2020-09-24 stsp return err;
1415 7c0b7f42 2020-09-24 stsp }
1416 7c0b7f42 2020-09-24 stsp
1417 7c0b7f42 2020-09-24 stsp static const struct got_error *
1418 04d9a9ec 2020-09-24 stsp create_gitconfig(const char *git_url, const char *default_branch,
1419 132af4a5 2021-01-05 stsp int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1420 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, int mirror_references,
1421 99495ddb 2021-01-10 stsp struct got_repository *repo)
1422 7c0b7f42 2020-09-24 stsp {
1423 7c0b7f42 2020-09-24 stsp const struct got_error *err = NULL;
1424 7c0b7f42 2020-09-24 stsp char *gitconfig_path = NULL;
1425 7c0b7f42 2020-09-24 stsp char *gitconfig = NULL;
1426 7c0b7f42 2020-09-24 stsp FILE *gitconfig_file = NULL;
1427 99495ddb 2021-01-10 stsp char *branches = NULL, *refs = NULL;
1428 56d0a753 2021-01-20 stsp const char *branchname;
1429 7c0b7f42 2020-09-24 stsp ssize_t n;
1430 7c0b7f42 2020-09-24 stsp
1431 7c0b7f42 2020-09-24 stsp /* Create a config file Git can understand. */
1432 7c0b7f42 2020-09-24 stsp gitconfig_path = got_repo_get_path_gitconfig(repo);
1433 7c0b7f42 2020-09-24 stsp if (gitconfig_path == NULL) {
1434 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("got_repo_get_path_gitconfig");
1435 7c0b7f42 2020-09-24 stsp goto done;
1436 7c0b7f42 2020-09-24 stsp }
1437 c56c5d8a 2021-12-31 thomas gitconfig_file = fopen(gitconfig_path, "ae");
1438 7c0b7f42 2020-09-24 stsp if (gitconfig_file == NULL) {
1439 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fopen", gitconfig_path);
1440 7c0b7f42 2020-09-24 stsp goto done;
1441 7c0b7f42 2020-09-24 stsp }
1442 56d0a753 2021-01-20 stsp if (fetch_all_branches) {
1443 56d0a753 2021-01-20 stsp if (mirror_references) {
1444 56d0a753 2021-01-20 stsp if (asprintf(&branches,
1445 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/*:refs/heads/*\n") == -1) {
1446 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1447 56d0a753 2021-01-20 stsp goto done;
1448 56d0a753 2021-01-20 stsp }
1449 56d0a753 2021-01-20 stsp } else if (asprintf(&branches,
1450 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/*:refs/remotes/%s/*\n",
1451 7c0b7f42 2020-09-24 stsp GOT_FETCH_DEFAULT_REMOTE_NAME) == -1) {
1452 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1453 7c0b7f42 2020-09-24 stsp goto done;
1454 132af4a5 2021-01-05 stsp }
1455 132af4a5 2021-01-05 stsp } else if (!TAILQ_EMPTY(wanted_branches)) {
1456 132af4a5 2021-01-05 stsp struct got_pathlist_entry *pe;
1457 132af4a5 2021-01-05 stsp TAILQ_FOREACH(pe, wanted_branches, entry) {
1458 132af4a5 2021-01-05 stsp char *s;
1459 132af4a5 2021-01-05 stsp branchname = pe->path;
1460 132af4a5 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1461 132af4a5 2021-01-05 stsp branchname += 11;
1462 56d0a753 2021-01-20 stsp if (mirror_references) {
1463 56d0a753 2021-01-20 stsp if (asprintf(&s,
1464 56d0a753 2021-01-20 stsp "%s\tfetch = refs/heads/%s:refs/heads/%s\n",
1465 56d0a753 2021-01-20 stsp branches ? branches : "",
1466 56d0a753 2021-01-20 stsp branchname, branchname) == -1) {
1467 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1468 56d0a753 2021-01-20 stsp goto done;
1469 56d0a753 2021-01-20 stsp }
1470 56d0a753 2021-01-20 stsp } else if (asprintf(&s,
1471 56d0a753 2021-01-20 stsp "%s\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1472 132af4a5 2021-01-05 stsp branches ? branches : "",
1473 132af4a5 2021-01-05 stsp branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1474 132af4a5 2021-01-05 stsp branchname) == -1) {
1475 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1476 132af4a5 2021-01-05 stsp goto done;
1477 132af4a5 2021-01-05 stsp }
1478 132af4a5 2021-01-05 stsp free(branches);
1479 132af4a5 2021-01-05 stsp branches = s;
1480 7c0b7f42 2020-09-24 stsp }
1481 7c0b7f42 2020-09-24 stsp } else {
1482 7c0b7f42 2020-09-24 stsp /*
1483 7c0b7f42 2020-09-24 stsp * If the server specified a default branch, use just that one.
1484 7c0b7f42 2020-09-24 stsp * Otherwise fall back to fetching all branches on next fetch.
1485 7c0b7f42 2020-09-24 stsp */
1486 04d9a9ec 2020-09-24 stsp if (default_branch) {
1487 04d9a9ec 2020-09-24 stsp branchname = default_branch;
1488 7c0b7f42 2020-09-24 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1489 7c0b7f42 2020-09-24 stsp branchname += 11;
1490 7c0b7f42 2020-09-24 stsp } else
1491 7c0b7f42 2020-09-24 stsp branchname = "*"; /* fall back to all branches */
1492 56d0a753 2021-01-20 stsp if (mirror_references) {
1493 56d0a753 2021-01-20 stsp if (asprintf(&branches,
1494 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/%s:refs/heads/%s\n",
1495 56d0a753 2021-01-20 stsp branchname, branchname) == -1) {
1496 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1497 56d0a753 2021-01-20 stsp goto done;
1498 56d0a753 2021-01-20 stsp }
1499 56d0a753 2021-01-20 stsp } else if (asprintf(&branches,
1500 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1501 7c0b7f42 2020-09-24 stsp branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1502 7c0b7f42 2020-09-24 stsp branchname) == -1) {
1503 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1504 7c0b7f42 2020-09-24 stsp goto done;
1505 99495ddb 2021-01-10 stsp }
1506 99495ddb 2021-01-10 stsp }
1507 56d0a753 2021-01-20 stsp if (!TAILQ_EMPTY(wanted_refs)) {
1508 99495ddb 2021-01-10 stsp struct got_pathlist_entry *pe;
1509 99495ddb 2021-01-10 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1510 99495ddb 2021-01-10 stsp char *s;
1511 99495ddb 2021-01-10 stsp const char *refname = pe->path;
1512 99495ddb 2021-01-10 stsp if (strncmp(refname, "refs/", 5) == 0)
1513 99495ddb 2021-01-10 stsp refname += 5;
1514 56d0a753 2021-01-20 stsp if (mirror_references) {
1515 56d0a753 2021-01-20 stsp if (asprintf(&s,
1516 56d0a753 2021-01-20 stsp "%s\tfetch = refs/%s:refs/%s\n",
1517 56d0a753 2021-01-20 stsp refs ? refs : "", refname, refname) == -1) {
1518 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1519 56d0a753 2021-01-20 stsp goto done;
1520 56d0a753 2021-01-20 stsp }
1521 56d0a753 2021-01-20 stsp } else if (asprintf(&s,
1522 56d0a753 2021-01-20 stsp "%s\tfetch = refs/%s:refs/remotes/%s/%s\n",
1523 99495ddb 2021-01-10 stsp refs ? refs : "",
1524 99495ddb 2021-01-10 stsp refname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1525 99495ddb 2021-01-10 stsp refname) == -1) {
1526 99495ddb 2021-01-10 stsp err = got_error_from_errno("asprintf");
1527 99495ddb 2021-01-10 stsp goto done;
1528 99495ddb 2021-01-10 stsp }
1529 99495ddb 2021-01-10 stsp free(refs);
1530 99495ddb 2021-01-10 stsp refs = s;
1531 7c0b7f42 2020-09-24 stsp }
1532 132af4a5 2021-01-05 stsp }
1533 99495ddb 2021-01-10 stsp
1534 132af4a5 2021-01-05 stsp if (asprintf(&gitconfig,
1535 132af4a5 2021-01-05 stsp "[remote \"%s\"]\n"
1536 132af4a5 2021-01-05 stsp "\turl = %s\n"
1537 132af4a5 2021-01-05 stsp "%s"
1538 99495ddb 2021-01-10 stsp "%s"
1539 56d0a753 2021-01-20 stsp "\tfetch = refs/tags/*:refs/tags/*\n",
1540 132af4a5 2021-01-05 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, git_url, branches ? branches : "",
1541 56d0a753 2021-01-20 stsp refs ? refs : "") == -1) {
1542 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1543 132af4a5 2021-01-05 stsp goto done;
1544 7c0b7f42 2020-09-24 stsp }
1545 7c0b7f42 2020-09-24 stsp n = fwrite(gitconfig, 1, strlen(gitconfig), gitconfig_file);
1546 7c0b7f42 2020-09-24 stsp if (n != strlen(gitconfig)) {
1547 7c0b7f42 2020-09-24 stsp err = got_ferror(gitconfig_file, GOT_ERR_IO);
1548 7c0b7f42 2020-09-24 stsp goto done;
1549 7c0b7f42 2020-09-24 stsp }
1550 7c0b7f42 2020-09-24 stsp done:
1551 7c0b7f42 2020-09-24 stsp if (gitconfig_file && fclose(gitconfig_file) == EOF && err == NULL)
1552 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fclose", gitconfig_path);
1553 7c0b7f42 2020-09-24 stsp free(gitconfig_path);
1554 132af4a5 2021-01-05 stsp free(branches);
1555 0e4002ca 2020-03-21 stsp return err;
1556 0e4002ca 2020-03-21 stsp }
1557 0e4002ca 2020-03-21 stsp
1558 0e4002ca 2020-03-21 stsp static const struct got_error *
1559 04d9a9ec 2020-09-24 stsp create_config_files(const char *proto, const char *host, const char *port,
1560 04d9a9ec 2020-09-24 stsp const char *remote_repo_path, const char *git_url, int fetch_all_branches,
1561 04d9a9ec 2020-09-24 stsp int mirror_references, struct got_pathlist_head *symrefs,
1562 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_branches,
1563 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, struct got_repository *repo)
1564 04d9a9ec 2020-09-24 stsp {
1565 04d9a9ec 2020-09-24 stsp const struct got_error *err = NULL;
1566 04d9a9ec 2020-09-24 stsp const char *default_branch = NULL;
1567 04d9a9ec 2020-09-24 stsp struct got_pathlist_entry *pe;
1568 04d9a9ec 2020-09-24 stsp
1569 04d9a9ec 2020-09-24 stsp /*
1570 04d9a9ec 2020-09-24 stsp * If we asked for a set of wanted branches then use the first
1571 04d9a9ec 2020-09-24 stsp * one of those.
1572 04d9a9ec 2020-09-24 stsp */
1573 62d463ca 2020-10-20 naddy if (!TAILQ_EMPTY(wanted_branches)) {
1574 04d9a9ec 2020-09-24 stsp pe = TAILQ_FIRST(wanted_branches);
1575 04d9a9ec 2020-09-24 stsp default_branch = pe->path;
1576 04d9a9ec 2020-09-24 stsp } else {
1577 04d9a9ec 2020-09-24 stsp /* First HEAD ref listed by server is the default branch. */
1578 04d9a9ec 2020-09-24 stsp TAILQ_FOREACH(pe, symrefs, entry) {
1579 04d9a9ec 2020-09-24 stsp const char *refname = pe->path;
1580 04d9a9ec 2020-09-24 stsp const char *target = pe->data;
1581 04d9a9ec 2020-09-24 stsp
1582 04d9a9ec 2020-09-24 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
1583 04d9a9ec 2020-09-24 stsp continue;
1584 04d9a9ec 2020-09-24 stsp
1585 04d9a9ec 2020-09-24 stsp default_branch = target;
1586 04d9a9ec 2020-09-24 stsp break;
1587 04d9a9ec 2020-09-24 stsp }
1588 04d9a9ec 2020-09-24 stsp }
1589 04d9a9ec 2020-09-24 stsp
1590 04d9a9ec 2020-09-24 stsp /* Create got.conf(5). */
1591 04d9a9ec 2020-09-24 stsp err = create_gotconfig(proto, host, port, remote_repo_path,
1592 0c8b29c5 2021-01-05 stsp default_branch, fetch_all_branches, wanted_branches,
1593 99495ddb 2021-01-10 stsp wanted_refs, mirror_references, repo);
1594 04d9a9ec 2020-09-24 stsp if (err)
1595 04d9a9ec 2020-09-24 stsp return err;
1596 04d9a9ec 2020-09-24 stsp
1597 04d9a9ec 2020-09-24 stsp /* Create a config file Git can understand. */
1598 04d9a9ec 2020-09-24 stsp return create_gitconfig(git_url, default_branch, fetch_all_branches,
1599 99495ddb 2021-01-10 stsp wanted_branches, wanted_refs, mirror_references, repo);
1600 04d9a9ec 2020-09-24 stsp }
1601 04d9a9ec 2020-09-24 stsp
1602 04d9a9ec 2020-09-24 stsp static const struct got_error *
1603 93658fb9 2020-03-18 stsp cmd_clone(int argc, char *argv[])
1604 93658fb9 2020-03-18 stsp {
1605 39c64a6a 2020-03-18 stsp const struct got_error *error = NULL;
1606 9df6f38b 2020-03-18 stsp const char *uri, *dirname;
1607 09838ffc 2020-03-18 stsp char *proto, *host, *port, *repo_name, *server_path;
1608 d9b4d0c0 2020-03-18 stsp char *default_destdir = NULL, *id_str = NULL;
1609 a9c2d4c2 2020-09-24 stsp const char *repo_path;
1610 bb64b798 2020-03-18 stsp struct got_repository *repo = NULL;
1611 0e4002ca 2020-03-21 stsp struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
1612 d9b4d0c0 2020-03-18 stsp struct got_pathlist_entry *pe;
1613 d9b4d0c0 2020-03-18 stsp struct got_object_id *pack_hash = NULL;
1614 9c52365f 2020-03-21 stsp int ch, fetchfd = -1, fetchstatus;
1615 9c52365f 2020-03-21 stsp pid_t fetchpid = -1;
1616 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg fpa;
1617 b46f3e71 2020-03-18 stsp char *git_url = NULL;
1618 659e7fbd 2020-03-20 stsp int verbosity = 0, fetch_all_branches = 0, mirror_references = 0;
1619 7abf1863 2023-02-20 thomas int bflag = 0, list_refs_only = 0;
1620 7cd52833 2022-06-23 thomas int *pack_fds = NULL;
1621 93658fb9 2020-03-18 stsp
1622 d9b4d0c0 2020-03-18 stsp TAILQ_INIT(&refs);
1623 d9b4d0c0 2020-03-18 stsp TAILQ_INIT(&symrefs);
1624 4ba14133 2020-03-20 stsp TAILQ_INIT(&wanted_branches);
1625 0e4002ca 2020-03-21 stsp TAILQ_INIT(&wanted_refs);
1626 d9b4d0c0 2020-03-18 stsp
1627 f7065961 2022-10-27 thomas while ((ch = getopt(argc, argv, "ab:lmqR:v")) != -1) {
1628 93658fb9 2020-03-18 stsp switch (ch) {
1629 659e7fbd 2020-03-20 stsp case 'a':
1630 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
1631 4ba14133 2020-03-20 stsp break;
1632 4ba14133 2020-03-20 stsp case 'b':
1633 4ba14133 2020-03-20 stsp error = got_pathlist_append(&wanted_branches,
1634 4ba14133 2020-03-20 stsp optarg, NULL);
1635 4ba14133 2020-03-20 stsp if (error)
1636 4ba14133 2020-03-20 stsp return error;
1637 7abf1863 2023-02-20 thomas bflag = 1;
1638 659e7fbd 2020-03-20 stsp break;
1639 41b0de12 2020-03-21 stsp case 'l':
1640 41b0de12 2020-03-21 stsp list_refs_only = 1;
1641 41b0de12 2020-03-21 stsp break;
1642 469dd726 2020-03-20 stsp case 'm':
1643 469dd726 2020-03-20 stsp mirror_references = 1;
1644 469dd726 2020-03-20 stsp break;
1645 68999b92 2020-03-18 stsp case 'q':
1646 68999b92 2020-03-18 stsp verbosity = -1;
1647 68999b92 2020-03-18 stsp break;
1648 0e4002ca 2020-03-21 stsp case 'R':
1649 0e4002ca 2020-03-21 stsp error = got_pathlist_append(&wanted_refs,
1650 0e4002ca 2020-03-21 stsp optarg, NULL);
1651 0e4002ca 2020-03-21 stsp if (error)
1652 0e4002ca 2020-03-21 stsp return error;
1653 0e4002ca 2020-03-21 stsp break;
1654 f7065961 2022-10-27 thomas case 'v':
1655 f7065961 2022-10-27 thomas if (verbosity < 0)
1656 f7065961 2022-10-27 thomas verbosity = 0;
1657 f7065961 2022-10-27 thomas else if (verbosity < 3)
1658 f7065961 2022-10-27 thomas verbosity++;
1659 f7065961 2022-10-27 thomas break;
1660 93658fb9 2020-03-18 stsp default:
1661 93658fb9 2020-03-18 stsp usage_clone();
1662 93658fb9 2020-03-18 stsp break;
1663 93658fb9 2020-03-18 stsp }
1664 93658fb9 2020-03-18 stsp }
1665 93658fb9 2020-03-18 stsp argc -= optind;
1666 93658fb9 2020-03-18 stsp argv += optind;
1667 39c64a6a 2020-03-18 stsp
1668 4ba14133 2020-03-20 stsp if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
1669 ff69268e 2020-12-13 stsp option_conflict('a', 'b');
1670 41b0de12 2020-03-21 stsp if (list_refs_only) {
1671 41b0de12 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_branches))
1672 ff69268e 2020-12-13 stsp option_conflict('l', 'b');
1673 41b0de12 2020-03-21 stsp if (fetch_all_branches)
1674 ff69268e 2020-12-13 stsp option_conflict('l', 'a');
1675 41b0de12 2020-03-21 stsp if (mirror_references)
1676 ff69268e 2020-12-13 stsp option_conflict('l', 'm');
1677 0e4002ca 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_refs))
1678 ff69268e 2020-12-13 stsp option_conflict('l', 'R');
1679 41b0de12 2020-03-21 stsp }
1680 4ba14133 2020-03-20 stsp
1681 93658fb9 2020-03-18 stsp uri = argv[0];
1682 9df6f38b 2020-03-18 stsp
1683 9df6f38b 2020-03-18 stsp if (argc == 1)
1684 93658fb9 2020-03-18 stsp dirname = NULL;
1685 9df6f38b 2020-03-18 stsp else if (argc == 2)
1686 93658fb9 2020-03-18 stsp dirname = argv[1];
1687 93658fb9 2020-03-18 stsp else
1688 93658fb9 2020-03-18 stsp usage_clone();
1689 09838ffc 2020-03-18 stsp
1690 5e5da8c4 2021-09-05 stsp error = got_dial_parse_uri(&proto, &host, &port, &server_path,
1691 4dbec0a8 2020-08-27 stsp &repo_name, uri);
1692 39c64a6a 2020-03-18 stsp if (error)
1693 09f63084 2020-03-20 stsp goto done;
1694 09f63084 2020-03-20 stsp
1695 09f63084 2020-03-20 stsp if (asprintf(&git_url, "%s://%s%s%s%s%s", proto,
1696 09f63084 2020-03-20 stsp host, port ? ":" : "", port ? port : "",
1697 09f63084 2020-03-20 stsp server_path[0] != '/' ? "/" : "", server_path) == -1) {
1698 09f63084 2020-03-20 stsp error = got_error_from_errno("asprintf");
1699 09838ffc 2020-03-18 stsp goto done;
1700 09f63084 2020-03-20 stsp }
1701 09838ffc 2020-03-18 stsp
1702 39c64a6a 2020-03-18 stsp if (strcmp(proto, "git") == 0) {
1703 b46f3e71 2020-03-18 stsp #ifndef PROFILE
1704 39c64a6a 2020-03-18 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1705 39c64a6a 2020-03-18 stsp "sendfd dns inet unveil", NULL) == -1)
1706 39c64a6a 2020-03-18 stsp err(1, "pledge");
1707 b46f3e71 2020-03-18 stsp #endif
1708 39c64a6a 2020-03-18 stsp } else if (strcmp(proto, "git+ssh") == 0 ||
1709 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "ssh") == 0 ||
1710 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "git+http") == 0 ||
1711 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "http") == 0 ||
1712 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "git+https") == 0 ||
1713 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "https") == 0) {
1714 b46f3e71 2020-03-18 stsp #ifndef PROFILE
1715 39c64a6a 2020-03-18 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1716 39c64a6a 2020-03-18 stsp "sendfd unveil", NULL) == -1)
1717 39c64a6a 2020-03-18 stsp err(1, "pledge");
1718 b46f3e71 2020-03-18 stsp #endif
1719 39c64a6a 2020-03-18 stsp } else {
1720 39c64a6a 2020-03-18 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
1721 39c64a6a 2020-03-18 stsp goto done;
1722 39c64a6a 2020-03-18 stsp }
1723 bb64b798 2020-03-18 stsp if (dirname == NULL) {
1724 bb64b798 2020-03-18 stsp if (asprintf(&default_destdir, "%s.git", repo_name) == -1) {
1725 39c64a6a 2020-03-18 stsp error = got_error_from_errno("asprintf");
1726 bb64b798 2020-03-18 stsp goto done;
1727 bb64b798 2020-03-18 stsp }
1728 bb64b798 2020-03-18 stsp repo_path = default_destdir;
1729 bb64b798 2020-03-18 stsp } else
1730 bb64b798 2020-03-18 stsp repo_path = dirname;
1731 bb64b798 2020-03-18 stsp
1732 41b0de12 2020-03-21 stsp if (!list_refs_only) {
1733 41b0de12 2020-03-21 stsp error = got_path_mkdir(repo_path);
1734 2751fe64 2020-09-24 stsp if (error &&
1735 2751fe64 2020-09-24 stsp (!(error->code == GOT_ERR_ERRNO && errno == EISDIR) &&
1736 2751fe64 2020-09-24 stsp !(error->code == GOT_ERR_ERRNO && errno == EEXIST)))
1737 41b0de12 2020-03-21 stsp goto done;
1738 2751fe64 2020-09-24 stsp if (!got_path_dir_is_empty(repo_path)) {
1739 2751fe64 2020-09-24 stsp error = got_error_path(repo_path,
1740 2751fe64 2020-09-24 stsp GOT_ERR_DIR_NOT_EMPTY);
1741 41b0de12 2020-03-21 stsp goto done;
1742 2751fe64 2020-09-24 stsp }
1743 41b0de12 2020-03-21 stsp }
1744 bb64b798 2020-03-18 stsp
1745 d65a88a2 2021-09-05 stsp error = got_dial_apply_unveil(proto);
1746 d65a88a2 2021-09-05 stsp if (error)
1747 d65a88a2 2021-09-05 stsp goto done;
1748 d65a88a2 2021-09-05 stsp
1749 f535bcd4 2020-09-30 stsp error = apply_unveil(repo_path, 0, NULL);
1750 ee448f5f 2020-03-18 stsp if (error)
1751 ee448f5f 2020-03-18 stsp goto done;
1752 f79e6490 2020-04-19 stsp
1753 f79e6490 2020-04-19 stsp if (verbosity >= 0)
1754 6df5d941 2022-11-18 thomas printf("Connecting to %s\n", git_url);
1755 ee448f5f 2020-03-18 stsp
1756 9c52365f 2020-03-21 stsp error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
1757 9c52365f 2020-03-21 stsp server_path, verbosity);
1758 39c64a6a 2020-03-18 stsp if (error)
1759 bb64b798 2020-03-18 stsp goto done;
1760 bb64b798 2020-03-18 stsp
1761 a6955b87 2024-04-25 thomas.ad #ifndef PROFILE
1762 a6955b87 2024-04-25 thomas.ad if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd",
1763 a6955b87 2024-04-25 thomas.ad NULL) == -1)
1764 a6955b87 2024-04-25 thomas.ad err(1, "pledge");
1765 a6955b87 2024-04-25 thomas.ad #endif
1766 2751fe64 2020-09-24 stsp if (!list_refs_only) {
1767 e9424ba1 2022-09-20 thomas error = got_repo_init(repo_path, NULL);
1768 2751fe64 2020-09-24 stsp if (error)
1769 2751fe64 2020-09-24 stsp goto done;
1770 7cd52833 2022-06-23 thomas error = got_repo_pack_fds_open(&pack_fds);
1771 7cd52833 2022-06-23 thomas if (error != NULL)
1772 7cd52833 2022-06-23 thomas goto done;
1773 7cd52833 2022-06-23 thomas error = got_repo_open(&repo, repo_path, NULL, pack_fds);
1774 2751fe64 2020-09-24 stsp if (error)
1775 2751fe64 2020-09-24 stsp goto done;
1776 2751fe64 2020-09-24 stsp }
1777 2751fe64 2020-09-24 stsp
1778 892ac3b6 2020-03-18 stsp fpa.last_scaled_size[0] = '\0';
1779 892ac3b6 2020-03-18 stsp fpa.last_p_indexed = -1;
1780 892ac3b6 2020-03-18 stsp fpa.last_p_resolved = -1;
1781 68999b92 2020-03-18 stsp fpa.verbosity = verbosity;
1782 04d9a9ec 2020-09-24 stsp fpa.create_configs = 1;
1783 04d9a9ec 2020-09-24 stsp fpa.configs_created = 0;
1784 04d9a9ec 2020-09-24 stsp fpa.repo = repo;
1785 04d9a9ec 2020-09-24 stsp fpa.config_info.symrefs = &symrefs;
1786 04d9a9ec 2020-09-24 stsp fpa.config_info.wanted_branches = &wanted_branches;
1787 99495ddb 2021-01-10 stsp fpa.config_info.wanted_refs = &wanted_refs;
1788 04d9a9ec 2020-09-24 stsp fpa.config_info.proto = proto;
1789 04d9a9ec 2020-09-24 stsp fpa.config_info.host = host;
1790 04d9a9ec 2020-09-24 stsp fpa.config_info.port = port;
1791 04d9a9ec 2020-09-24 stsp fpa.config_info.remote_repo_path = server_path;
1792 04d9a9ec 2020-09-24 stsp fpa.config_info.git_url = git_url;
1793 04d9a9ec 2020-09-24 stsp fpa.config_info.fetch_all_branches = fetch_all_branches;
1794 04d9a9ec 2020-09-24 stsp fpa.config_info.mirror_references = mirror_references;
1795 7848a0e1 2020-03-19 stsp error = got_fetch_pack(&pack_hash, &refs, &symrefs,
1796 469dd726 2020-03-20 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, mirror_references,
1797 0e4002ca 2020-03-21 stsp fetch_all_branches, &wanted_branches, &wanted_refs,
1798 7abf1863 2023-02-20 thomas list_refs_only, verbosity, fetchfd, repo, NULL, NULL, bflag,
1799 0e4002ca 2020-03-21 stsp fetch_progress, &fpa);
1800 39c64a6a 2020-03-18 stsp if (error)
1801 d9b4d0c0 2020-03-18 stsp goto done;
1802 d9b4d0c0 2020-03-18 stsp
1803 41b0de12 2020-03-21 stsp if (list_refs_only) {
1804 41b0de12 2020-03-21 stsp error = list_remote_refs(&symrefs, &refs);
1805 41b0de12 2020-03-21 stsp goto done;
1806 41b0de12 2020-03-21 stsp }
1807 41b0de12 2020-03-21 stsp
1808 c3741b51 2021-12-31 thomas if (pack_hash == NULL) {
1809 c3741b51 2021-12-31 thomas error = got_error_fmt(GOT_ERR_FETCH_FAILED, "%s",
1810 c3741b51 2021-12-31 thomas "server sent an empty pack file");
1811 c3741b51 2021-12-31 thomas goto done;
1812 c3741b51 2021-12-31 thomas }
1813 39c64a6a 2020-03-18 stsp error = got_object_id_str(&id_str, pack_hash);
1814 39c64a6a 2020-03-18 stsp if (error)
1815 d9b4d0c0 2020-03-18 stsp goto done;
1816 68999b92 2020-03-18 stsp if (verbosity >= 0)
1817 e69674d8 2020-03-19 stsp printf("\nFetched %s.pack\n", id_str);
1818 d9b4d0c0 2020-03-18 stsp free(id_str);
1819 d9b4d0c0 2020-03-18 stsp
1820 d9b4d0c0 2020-03-18 stsp /* Set up references provided with the pack file. */
1821 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &refs, entry) {
1822 d9b4d0c0 2020-03-18 stsp const char *refname = pe->path;
1823 d9b4d0c0 2020-03-18 stsp struct got_object_id *id = pe->data;
1824 7ebc0570 2020-03-18 stsp char *remote_refname;
1825 0e4002ca 2020-03-21 stsp
1826 0e4002ca 2020-03-21 stsp if (is_wanted_ref(&wanted_refs, refname) &&
1827 0e4002ca 2020-03-21 stsp !mirror_references) {
1828 0e4002ca 2020-03-21 stsp error = create_wanted_ref(refname, id,
1829 0e4002ca 2020-03-21 stsp GOT_FETCH_DEFAULT_REMOTE_NAME,
1830 0e4002ca 2020-03-21 stsp verbosity - 1, repo);
1831 0e4002ca 2020-03-21 stsp if (error)
1832 0e4002ca 2020-03-21 stsp goto done;
1833 0e4002ca 2020-03-21 stsp continue;
1834 0e4002ca 2020-03-21 stsp }
1835 668a20f6 2020-03-18 stsp
1836 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity - 1, repo);
1837 39c64a6a 2020-03-18 stsp if (error)
1838 d9b4d0c0 2020-03-18 stsp goto done;
1839 d9b4d0c0 2020-03-18 stsp
1840 469dd726 2020-03-20 stsp if (mirror_references)
1841 469dd726 2020-03-20 stsp continue;
1842 469dd726 2020-03-20 stsp
1843 7ebc0570 2020-03-18 stsp if (strncmp("refs/heads/", refname, 11) != 0)
1844 7ebc0570 2020-03-18 stsp continue;
1845 7ebc0570 2020-03-18 stsp
1846 7ebc0570 2020-03-18 stsp if (asprintf(&remote_refname,
1847 7ebc0570 2020-03-18 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1848 7ebc0570 2020-03-18 stsp refname + 11) == -1) {
1849 7ebc0570 2020-03-18 stsp error = got_error_from_errno("asprintf");
1850 7ebc0570 2020-03-18 stsp goto done;
1851 7ebc0570 2020-03-18 stsp }
1852 6338a6a1 2020-03-21 stsp error = create_ref(remote_refname, id, verbosity - 1, repo);
1853 f298ae0f 2020-03-25 stsp free(remote_refname);
1854 39c64a6a 2020-03-18 stsp if (error)
1855 d9b4d0c0 2020-03-18 stsp goto done;
1856 d9b4d0c0 2020-03-18 stsp }
1857 d9b4d0c0 2020-03-18 stsp
1858 d9b4d0c0 2020-03-18 stsp /* Set the HEAD reference if the server provided one. */
1859 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
1860 659e7fbd 2020-03-20 stsp struct got_reference *target_ref;
1861 d9b4d0c0 2020-03-18 stsp const char *refname = pe->path;
1862 d9b4d0c0 2020-03-18 stsp const char *target = pe->data;
1863 f298ae0f 2020-03-25 stsp char *remote_refname = NULL, *remote_target = NULL;
1864 d9b4d0c0 2020-03-18 stsp
1865 d9b4d0c0 2020-03-18 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
1866 d9b4d0c0 2020-03-18 stsp continue;
1867 d9b4d0c0 2020-03-18 stsp
1868 39c64a6a 2020-03-18 stsp error = got_ref_open(&target_ref, repo, target, 0);
1869 39c64a6a 2020-03-18 stsp if (error) {
1870 55330abe 2020-03-20 stsp if (error->code == GOT_ERR_NOT_REF) {
1871 55330abe 2020-03-20 stsp error = NULL;
1872 d9b4d0c0 2020-03-18 stsp continue;
1873 55330abe 2020-03-20 stsp }
1874 d9b4d0c0 2020-03-18 stsp goto done;
1875 d9b4d0c0 2020-03-18 stsp }
1876 d9b4d0c0 2020-03-18 stsp
1877 04d9a9ec 2020-09-24 stsp error = create_symref(refname, target_ref, verbosity, repo);
1878 f298ae0f 2020-03-25 stsp got_ref_close(target_ref);
1879 f298ae0f 2020-03-25 stsp if (error)
1880 f298ae0f 2020-03-25 stsp goto done;
1881 f298ae0f 2020-03-25 stsp
1882 f298ae0f 2020-03-25 stsp if (mirror_references)
1883 f298ae0f 2020-03-25 stsp continue;
1884 f298ae0f 2020-03-25 stsp
1885 f298ae0f 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
1886 f298ae0f 2020-03-25 stsp continue;
1887 f298ae0f 2020-03-25 stsp
1888 f298ae0f 2020-03-25 stsp if (asprintf(&remote_refname,
1889 f298ae0f 2020-03-25 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1890 f298ae0f 2020-03-25 stsp refname) == -1) {
1891 f298ae0f 2020-03-25 stsp error = got_error_from_errno("asprintf");
1892 f298ae0f 2020-03-25 stsp goto done;
1893 f298ae0f 2020-03-25 stsp }
1894 f298ae0f 2020-03-25 stsp if (asprintf(&remote_target,
1895 f298ae0f 2020-03-25 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1896 f298ae0f 2020-03-25 stsp target + 11) == -1) {
1897 f298ae0f 2020-03-25 stsp error = got_error_from_errno("asprintf");
1898 f298ae0f 2020-03-25 stsp free(remote_refname);
1899 f298ae0f 2020-03-25 stsp goto done;
1900 f298ae0f 2020-03-25 stsp }
1901 f298ae0f 2020-03-25 stsp error = got_ref_open(&target_ref, repo, remote_target, 0);
1902 f298ae0f 2020-03-25 stsp if (error) {
1903 f298ae0f 2020-03-25 stsp free(remote_refname);
1904 f298ae0f 2020-03-25 stsp free(remote_target);
1905 f298ae0f 2020-03-25 stsp if (error->code == GOT_ERR_NOT_REF) {
1906 f298ae0f 2020-03-25 stsp error = NULL;
1907 f298ae0f 2020-03-25 stsp continue;
1908 f298ae0f 2020-03-25 stsp }
1909 f298ae0f 2020-03-25 stsp goto done;
1910 f298ae0f 2020-03-25 stsp }
1911 04d9a9ec 2020-09-24 stsp error = create_symref(remote_refname, target_ref,
1912 04d9a9ec 2020-09-24 stsp verbosity - 1, repo);
1913 f298ae0f 2020-03-25 stsp free(remote_refname);
1914 f298ae0f 2020-03-25 stsp free(remote_target);
1915 d9b4d0c0 2020-03-18 stsp got_ref_close(target_ref);
1916 39c64a6a 2020-03-18 stsp if (error)
1917 d9b4d0c0 2020-03-18 stsp goto done;
1918 4ba14133 2020-03-20 stsp }
1919 4ba14133 2020-03-20 stsp if (pe == NULL) {
1920 4ba14133 2020-03-20 stsp /*
1921 4ba14133 2020-03-20 stsp * We failed to set the HEAD reference. If we asked for
1922 4ba14133 2020-03-20 stsp * a set of wanted branches use the first of one of those
1923 4ba14133 2020-03-20 stsp * which could be fetched instead.
1924 4ba14133 2020-03-20 stsp */
1925 62d463ca 2020-10-20 naddy TAILQ_FOREACH(pe, &wanted_branches, entry) {
1926 4ba14133 2020-03-20 stsp const char *target = pe->path;
1927 4ba14133 2020-03-20 stsp struct got_reference *target_ref;
1928 d9b4d0c0 2020-03-18 stsp
1929 4ba14133 2020-03-20 stsp error = got_ref_open(&target_ref, repo, target, 0);
1930 4ba14133 2020-03-20 stsp if (error) {
1931 4ba14133 2020-03-20 stsp if (error->code == GOT_ERR_NOT_REF) {
1932 4ba14133 2020-03-20 stsp error = NULL;
1933 4ba14133 2020-03-20 stsp continue;
1934 4ba14133 2020-03-20 stsp }
1935 4ba14133 2020-03-20 stsp goto done;
1936 4ba14133 2020-03-20 stsp }
1937 4ba14133 2020-03-20 stsp
1938 04d9a9ec 2020-09-24 stsp error = create_symref(GOT_REF_HEAD, target_ref,
1939 04d9a9ec 2020-09-24 stsp verbosity, repo);
1940 4ba14133 2020-03-20 stsp got_ref_close(target_ref);
1941 4ba14133 2020-03-20 stsp if (error)
1942 4ba14133 2020-03-20 stsp goto done;
1943 4ba14133 2020-03-20 stsp break;
1944 c22ed3f5 2022-11-08 thomas }
1945 c22ed3f5 2022-11-08 thomas
1946 c22ed3f5 2022-11-08 thomas if (!fpa.configs_created && pe != NULL) {
1947 c22ed3f5 2022-11-08 thomas error = create_config_files(fpa.config_info.proto,
1948 c22ed3f5 2022-11-08 thomas fpa.config_info.host, fpa.config_info.port,
1949 c22ed3f5 2022-11-08 thomas fpa.config_info.remote_repo_path,
1950 c22ed3f5 2022-11-08 thomas fpa.config_info.git_url,
1951 c22ed3f5 2022-11-08 thomas fpa.config_info.fetch_all_branches,
1952 c22ed3f5 2022-11-08 thomas fpa.config_info.mirror_references,
1953 c22ed3f5 2022-11-08 thomas fpa.config_info.symrefs,
1954 c22ed3f5 2022-11-08 thomas fpa.config_info.wanted_branches,
1955 c22ed3f5 2022-11-08 thomas fpa.config_info.wanted_refs, fpa.repo);
1956 c22ed3f5 2022-11-08 thomas if (error)
1957 c22ed3f5 2022-11-08 thomas goto done;
1958 4ba14133 2020-03-20 stsp }
1959 659e7fbd 2020-03-20 stsp }
1960 659e7fbd 2020-03-20 stsp
1961 d715f13e 2020-03-19 stsp if (verbosity >= 0)
1962 469dd726 2020-03-20 stsp printf("Created %s repository '%s'\n",
1963 469dd726 2020-03-20 stsp mirror_references ? "mirrored" : "cloned", repo_path);
1964 09838ffc 2020-03-18 stsp done:
1965 7cd52833 2022-06-23 thomas if (pack_fds) {
1966 7cd52833 2022-06-23 thomas const struct got_error *pack_err =
1967 7cd52833 2022-06-23 thomas got_repo_pack_fds_close(pack_fds);
1968 7cd52833 2022-06-23 thomas if (error == NULL)
1969 7cd52833 2022-06-23 thomas error = pack_err;
1970 7cd52833 2022-06-23 thomas }
1971 9c52365f 2020-03-21 stsp if (fetchpid > 0) {
1972 9c52365f 2020-03-21 stsp if (kill(fetchpid, SIGTERM) == -1)
1973 9c52365f 2020-03-21 stsp error = got_error_from_errno("kill");
1974 9c52365f 2020-03-21 stsp if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
1975 9c52365f 2020-03-21 stsp error = got_error_from_errno("waitpid");
1976 9c52365f 2020-03-21 stsp }
1977 39c64a6a 2020-03-18 stsp if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
1978 39c64a6a 2020-03-18 stsp error = got_error_from_errno("close");
1979 1d0f4054 2021-06-17 stsp if (repo) {
1980 1d0f4054 2021-06-17 stsp const struct got_error *close_err = got_repo_close(repo);
1981 1d0f4054 2021-06-17 stsp if (error == NULL)
1982 1d0f4054 2021-06-17 stsp error = close_err;
1983 d9b4d0c0 2020-03-18 stsp }
1984 21c2d8be 2023-01-10 thomas got_pathlist_free(&refs, GOT_PATHLIST_FREE_ALL);
1985 21c2d8be 2023-01-10 thomas got_pathlist_free(&symrefs, GOT_PATHLIST_FREE_ALL);
1986 21c2d8be 2023-01-10 thomas got_pathlist_free(&wanted_branches, GOT_PATHLIST_FREE_NONE);
1987 21c2d8be 2023-01-10 thomas got_pathlist_free(&wanted_refs, GOT_PATHLIST_FREE_NONE);
1988 d9b4d0c0 2020-03-18 stsp free(pack_hash);
1989 09838ffc 2020-03-18 stsp free(proto);
1990 09838ffc 2020-03-18 stsp free(host);
1991 09838ffc 2020-03-18 stsp free(port);
1992 09838ffc 2020-03-18 stsp free(server_path);
1993 09838ffc 2020-03-18 stsp free(repo_name);
1994 bb64b798 2020-03-18 stsp free(default_destdir);
1995 b46f3e71 2020-03-18 stsp free(git_url);
1996 39c64a6a 2020-03-18 stsp return error;
1997 7848a0e1 2020-03-19 stsp }
1998 7848a0e1 2020-03-19 stsp
1999 7848a0e1 2020-03-19 stsp static const struct got_error *
2000 7848a0e1 2020-03-19 stsp update_ref(struct got_reference *ref, struct got_object_id *new_id,
2001 db6d8ad8 2020-03-21 stsp int replace_tags, int verbosity, struct got_repository *repo)
2002 7848a0e1 2020-03-19 stsp {
2003 7848a0e1 2020-03-19 stsp const struct got_error *err = NULL;
2004 7848a0e1 2020-03-19 stsp char *new_id_str = NULL;
2005 7848a0e1 2020-03-19 stsp struct got_object_id *old_id = NULL;
2006 7848a0e1 2020-03-19 stsp
2007 7848a0e1 2020-03-19 stsp err = got_object_id_str(&new_id_str, new_id);
2008 7848a0e1 2020-03-19 stsp if (err)
2009 7848a0e1 2020-03-19 stsp goto done;
2010 7848a0e1 2020-03-19 stsp
2011 db6d8ad8 2020-03-21 stsp if (!replace_tags &&
2012 db6d8ad8 2020-03-21 stsp strncmp(got_ref_get_name(ref), "refs/tags/", 10) == 0) {
2013 88609724 2020-03-21 stsp err = got_ref_resolve(&old_id, repo, ref);
2014 88609724 2020-03-21 stsp if (err)
2015 88609724 2020-03-21 stsp goto done;
2016 88609724 2020-03-21 stsp if (got_object_id_cmp(old_id, new_id) == 0)
2017 88609724 2020-03-21 stsp goto done;
2018 db6d8ad8 2020-03-21 stsp if (verbosity >= 0) {
2019 db6d8ad8 2020-03-21 stsp printf("Rejecting update of existing tag %s: %s\n",
2020 db6d8ad8 2020-03-21 stsp got_ref_get_name(ref), new_id_str);
2021 db6d8ad8 2020-03-21 stsp }
2022 db6d8ad8 2020-03-21 stsp goto done;
2023 db6d8ad8 2020-03-21 stsp }
2024 db6d8ad8 2020-03-21 stsp
2025 7848a0e1 2020-03-19 stsp if (got_ref_is_symbolic(ref)) {
2026 688f11b3 2020-03-21 stsp if (verbosity >= 0) {
2027 e8a967e0 2020-03-21 stsp printf("Replacing reference %s: %s\n",
2028 6338a6a1 2020-03-21 stsp got_ref_get_name(ref),
2029 6338a6a1 2020-03-21 stsp got_ref_get_symref_target(ref));
2030 688f11b3 2020-03-21 stsp }
2031 e8a967e0 2020-03-21 stsp err = got_ref_change_symref_to_ref(ref, new_id);
2032 7848a0e1 2020-03-19 stsp if (err)
2033 7848a0e1 2020-03-19 stsp goto done;
2034 e8a967e0 2020-03-21 stsp err = got_ref_write(ref, repo);
2035 e8a967e0 2020-03-21 stsp if (err)
2036 e8a967e0 2020-03-21 stsp goto done;
2037 7848a0e1 2020-03-19 stsp } else {
2038 7848a0e1 2020-03-19 stsp err = got_ref_resolve(&old_id, repo, ref);
2039 7848a0e1 2020-03-19 stsp if (err)
2040 7848a0e1 2020-03-19 stsp goto done;
2041 6338a6a1 2020-03-21 stsp if (got_object_id_cmp(old_id, new_id) == 0)
2042 6338a6a1 2020-03-21 stsp goto done;
2043 6338a6a1 2020-03-21 stsp
2044 6338a6a1 2020-03-21 stsp err = got_ref_change_ref(ref, new_id);
2045 6338a6a1 2020-03-21 stsp if (err)
2046 6338a6a1 2020-03-21 stsp goto done;
2047 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
2048 6338a6a1 2020-03-21 stsp if (err)
2049 6338a6a1 2020-03-21 stsp goto done;
2050 7848a0e1 2020-03-19 stsp }
2051 6338a6a1 2020-03-21 stsp
2052 6338a6a1 2020-03-21 stsp if (verbosity >= 0)
2053 f4d0e3fb 2020-05-15 stsp printf("Updated %s: %s\n", got_ref_get_name(ref),
2054 6338a6a1 2020-03-21 stsp new_id_str);
2055 7848a0e1 2020-03-19 stsp done:
2056 7848a0e1 2020-03-19 stsp free(old_id);
2057 7848a0e1 2020-03-19 stsp free(new_id_str);
2058 7848a0e1 2020-03-19 stsp return err;
2059 2ab43947 2020-03-18 stsp }
2060 f1bcca34 2020-03-25 stsp
2061 f1bcca34 2020-03-25 stsp static const struct got_error *
2062 f1bcca34 2020-03-25 stsp update_symref(const char *refname, struct got_reference *target_ref,
2063 f1bcca34 2020-03-25 stsp int verbosity, struct got_repository *repo)
2064 f1bcca34 2020-03-25 stsp {
2065 f1bcca34 2020-03-25 stsp const struct got_error *err = NULL, *unlock_err;
2066 f1bcca34 2020-03-25 stsp struct got_reference *symref;
2067 bcf34b0e 2020-03-26 stsp int symref_is_locked = 0;
2068 f1bcca34 2020-03-25 stsp
2069 f1bcca34 2020-03-25 stsp err = got_ref_open(&symref, repo, refname, 1);
2070 bcf34b0e 2020-03-26 stsp if (err) {
2071 bcf34b0e 2020-03-26 stsp if (err->code != GOT_ERR_NOT_REF)
2072 bcf34b0e 2020-03-26 stsp return err;
2073 bcf34b0e 2020-03-26 stsp err = got_ref_alloc_symref(&symref, refname, target_ref);
2074 bcf34b0e 2020-03-26 stsp if (err)
2075 bcf34b0e 2020-03-26 stsp goto done;
2076 2ab43947 2020-03-18 stsp
2077 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
2078 bcf34b0e 2020-03-26 stsp if (err)
2079 bcf34b0e 2020-03-26 stsp goto done;
2080 f1bcca34 2020-03-25 stsp
2081 bcf34b0e 2020-03-26 stsp if (verbosity >= 0)
2082 bcf34b0e 2020-03-26 stsp printf("Created reference %s: %s\n",
2083 bcf34b0e 2020-03-26 stsp got_ref_get_name(symref),
2084 bcf34b0e 2020-03-26 stsp got_ref_get_symref_target(symref));
2085 bcf34b0e 2020-03-26 stsp } else {
2086 bcf34b0e 2020-03-26 stsp symref_is_locked = 1;
2087 f1bcca34 2020-03-25 stsp
2088 bcf34b0e 2020-03-26 stsp if (strcmp(got_ref_get_symref_target(symref),
2089 bcf34b0e 2020-03-26 stsp got_ref_get_name(target_ref)) == 0)
2090 bcf34b0e 2020-03-26 stsp goto done;
2091 bcf34b0e 2020-03-26 stsp
2092 bcf34b0e 2020-03-26 stsp err = got_ref_change_symref(symref,
2093 bcf34b0e 2020-03-26 stsp got_ref_get_name(target_ref));
2094 bcf34b0e 2020-03-26 stsp if (err)
2095 bcf34b0e 2020-03-26 stsp goto done;
2096 bcf34b0e 2020-03-26 stsp
2097 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
2098 bcf34b0e 2020-03-26 stsp if (err)
2099 bcf34b0e 2020-03-26 stsp goto done;
2100 bcf34b0e 2020-03-26 stsp
2101 bcf34b0e 2020-03-26 stsp if (verbosity >= 0)
2102 f4d0e3fb 2020-05-15 stsp printf("Updated %s: %s\n", got_ref_get_name(symref),
2103 bcf34b0e 2020-03-26 stsp got_ref_get_symref_target(symref));
2104 bcf34b0e 2020-03-26 stsp
2105 bcf34b0e 2020-03-26 stsp }
2106 f1bcca34 2020-03-25 stsp done:
2107 bcf34b0e 2020-03-26 stsp if (symref_is_locked) {
2108 bcf34b0e 2020-03-26 stsp unlock_err = got_ref_unlock(symref);
2109 bcf34b0e 2020-03-26 stsp if (unlock_err && err == NULL)
2110 bcf34b0e 2020-03-26 stsp err = unlock_err;
2111 bcf34b0e 2020-03-26 stsp }
2112 f1bcca34 2020-03-25 stsp got_ref_close(symref);
2113 f1bcca34 2020-03-25 stsp return err;
2114 f1bcca34 2020-03-25 stsp }
2115 f1bcca34 2020-03-25 stsp
2116 2ab43947 2020-03-18 stsp __dead static void
2117 7848a0e1 2020-03-19 stsp usage_fetch(void)
2118 7848a0e1 2020-03-19 stsp {
2119 d6506a3d 2022-08-16 thomas fprintf(stderr, "usage: %s fetch [-adlqtvX] [-b branch] "
2120 d6506a3d 2022-08-16 thomas "[-R reference] [-r repository-path] [remote-repository]\n",
2121 13f12b09 2020-03-21 stsp getprogname());
2122 7848a0e1 2020-03-19 stsp exit(1);
2123 7848a0e1 2020-03-19 stsp }
2124 7848a0e1 2020-03-19 stsp
2125 7848a0e1 2020-03-19 stsp static const struct got_error *
2126 3789fd73 2020-03-26 stsp delete_missing_ref(struct got_reference *ref,
2127 688f11b3 2020-03-21 stsp int verbosity, struct got_repository *repo)
2128 f21ec2f0 2020-03-21 stsp {
2129 f21ec2f0 2020-03-21 stsp const struct got_error *err = NULL;
2130 3789fd73 2020-03-26 stsp struct got_object_id *id = NULL;
2131 3789fd73 2020-03-26 stsp char *id_str = NULL;
2132 3789fd73 2020-03-26 stsp
2133 3789fd73 2020-03-26 stsp if (got_ref_is_symbolic(ref)) {
2134 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
2135 3789fd73 2020-03-26 stsp if (err)
2136 3789fd73 2020-03-26 stsp return err;
2137 3789fd73 2020-03-26 stsp if (verbosity >= 0) {
2138 f9d54ee6 2021-07-16 stsp printf("Deleted %s: %s\n",
2139 3789fd73 2020-03-26 stsp got_ref_get_name(ref),
2140 3789fd73 2020-03-26 stsp got_ref_get_symref_target(ref));
2141 3789fd73 2020-03-26 stsp }
2142 3789fd73 2020-03-26 stsp } else {
2143 3789fd73 2020-03-26 stsp err = got_ref_resolve(&id, repo, ref);
2144 3789fd73 2020-03-26 stsp if (err)
2145 3789fd73 2020-03-26 stsp return err;
2146 3789fd73 2020-03-26 stsp err = got_object_id_str(&id_str, id);
2147 3789fd73 2020-03-26 stsp if (err)
2148 3789fd73 2020-03-26 stsp goto done;
2149 3168e5da 2020-09-10 stsp
2150 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
2151 3789fd73 2020-03-26 stsp if (err)
2152 3789fd73 2020-03-26 stsp goto done;
2153 3789fd73 2020-03-26 stsp if (verbosity >= 0) {
2154 f9d54ee6 2021-07-16 stsp printf("Deleted %s: %s\n",
2155 3789fd73 2020-03-26 stsp got_ref_get_name(ref), id_str);
2156 3789fd73 2020-03-26 stsp }
2157 3789fd73 2020-03-26 stsp }
2158 3789fd73 2020-03-26 stsp done:
2159 3789fd73 2020-03-26 stsp free(id);
2160 3789fd73 2020-03-26 stsp free(id_str);
2161 a66a4a50 2023-02-03 thomas return err;
2162 3789fd73 2020-03-26 stsp }
2163 3789fd73 2020-03-26 stsp
2164 3789fd73 2020-03-26 stsp static const struct got_error *
2165 3789fd73 2020-03-26 stsp delete_missing_refs(struct got_pathlist_head *their_refs,
2166 50b0790e 2020-09-11 stsp struct got_pathlist_head *their_symrefs,
2167 50b0790e 2020-09-11 stsp const struct got_remote_repo *remote,
2168 3789fd73 2020-03-26 stsp int verbosity, struct got_repository *repo)
2169 3789fd73 2020-03-26 stsp {
2170 3789fd73 2020-03-26 stsp const struct got_error *err = NULL, *unlock_err;
2171 f21ec2f0 2020-03-21 stsp struct got_reflist_head my_refs;
2172 f21ec2f0 2020-03-21 stsp struct got_reflist_entry *re;
2173 f21ec2f0 2020-03-21 stsp struct got_pathlist_entry *pe;
2174 3789fd73 2020-03-26 stsp char *remote_namespace = NULL;
2175 3789fd73 2020-03-26 stsp char *local_refname = NULL;
2176 f21ec2f0 2020-03-21 stsp
2177 d9dff0e5 2020-12-26 stsp TAILQ_INIT(&my_refs);
2178 f21ec2f0 2020-03-21 stsp
2179 3789fd73 2020-03-26 stsp if (asprintf(&remote_namespace, "refs/remotes/%s/", remote->name)
2180 3789fd73 2020-03-26 stsp == -1)
2181 3789fd73 2020-03-26 stsp return got_error_from_errno("asprintf");
2182 3789fd73 2020-03-26 stsp
2183 f21ec2f0 2020-03-21 stsp err = got_ref_list(&my_refs, repo, NULL, got_ref_cmp_by_name, NULL);
2184 f21ec2f0 2020-03-21 stsp if (err)
2185 3789fd73 2020-03-26 stsp goto done;
2186 f21ec2f0 2020-03-21 stsp
2187 d9dff0e5 2020-12-26 stsp TAILQ_FOREACH(re, &my_refs, entry) {
2188 f21ec2f0 2020-03-21 stsp const char *refname = got_ref_get_name(re->ref);
2189 1b796c3f 2021-09-11 stsp const char *their_refname;
2190 f21ec2f0 2020-03-21 stsp
2191 1b796c3f 2021-09-11 stsp if (remote->mirror_references) {
2192 1b796c3f 2021-09-11 stsp their_refname = refname;
2193 1b796c3f 2021-09-11 stsp } else {
2194 3789fd73 2020-03-26 stsp if (strncmp(refname, remote_namespace,
2195 3789fd73 2020-03-26 stsp strlen(remote_namespace)) == 0) {
2196 3789fd73 2020-03-26 stsp if (strcmp(refname + strlen(remote_namespace),
2197 3789fd73 2020-03-26 stsp GOT_REF_HEAD) == 0)
2198 3789fd73 2020-03-26 stsp continue;
2199 3789fd73 2020-03-26 stsp if (asprintf(&local_refname, "refs/heads/%s",
2200 3789fd73 2020-03-26 stsp refname + strlen(remote_namespace)) == -1) {
2201 3789fd73 2020-03-26 stsp err = got_error_from_errno("asprintf");
2202 3789fd73 2020-03-26 stsp goto done;
2203 3789fd73 2020-03-26 stsp }
2204 3789fd73 2020-03-26 stsp } else if (strncmp(refname, "refs/tags/", 10) != 0)
2205 3789fd73 2020-03-26 stsp continue;
2206 f21ec2f0 2020-03-21 stsp
2207 1b796c3f 2021-09-11 stsp their_refname = local_refname;
2208 1b796c3f 2021-09-11 stsp }
2209 b6b86fd1 2022-08-30 thomas
2210 f21ec2f0 2020-03-21 stsp TAILQ_FOREACH(pe, their_refs, entry) {
2211 1b796c3f 2021-09-11 stsp if (strcmp(their_refname, pe->path) == 0)
2212 f21ec2f0 2020-03-21 stsp break;
2213 f21ec2f0 2020-03-21 stsp }
2214 f21ec2f0 2020-03-21 stsp if (pe != NULL)
2215 f21ec2f0 2020-03-21 stsp continue;
2216 f21ec2f0 2020-03-21 stsp
2217 3789fd73 2020-03-26 stsp TAILQ_FOREACH(pe, their_symrefs, entry) {
2218 1b796c3f 2021-09-11 stsp if (strcmp(their_refname, pe->path) == 0)
2219 3789fd73 2020-03-26 stsp break;
2220 3789fd73 2020-03-26 stsp }
2221 3789fd73 2020-03-26 stsp if (pe != NULL)
2222 3789fd73 2020-03-26 stsp continue;
2223 f21ec2f0 2020-03-21 stsp
2224 3789fd73 2020-03-26 stsp err = delete_missing_ref(re->ref, verbosity, repo);
2225 f21ec2f0 2020-03-21 stsp if (err)
2226 f21ec2f0 2020-03-21 stsp break;
2227 3789fd73 2020-03-26 stsp
2228 3789fd73 2020-03-26 stsp if (local_refname) {
2229 3789fd73 2020-03-26 stsp struct got_reference *ref;
2230 3789fd73 2020-03-26 stsp err = got_ref_open(&ref, repo, local_refname, 1);
2231 3789fd73 2020-03-26 stsp if (err) {
2232 3789fd73 2020-03-26 stsp if (err->code != GOT_ERR_NOT_REF)
2233 3789fd73 2020-03-26 stsp break;
2234 3789fd73 2020-03-26 stsp free(local_refname);
2235 3789fd73 2020-03-26 stsp local_refname = NULL;
2236 3789fd73 2020-03-26 stsp continue;
2237 3789fd73 2020-03-26 stsp }
2238 3789fd73 2020-03-26 stsp err = delete_missing_ref(ref, verbosity, repo);
2239 3789fd73 2020-03-26 stsp if (err)
2240 3789fd73 2020-03-26 stsp break;
2241 3789fd73 2020-03-26 stsp unlock_err = got_ref_unlock(ref);
2242 3789fd73 2020-03-26 stsp got_ref_close(ref);
2243 3789fd73 2020-03-26 stsp if (unlock_err && err == NULL) {
2244 3789fd73 2020-03-26 stsp err = unlock_err;
2245 3789fd73 2020-03-26 stsp break;
2246 3789fd73 2020-03-26 stsp }
2247 3789fd73 2020-03-26 stsp
2248 3789fd73 2020-03-26 stsp free(local_refname);
2249 3789fd73 2020-03-26 stsp local_refname = NULL;
2250 6338a6a1 2020-03-21 stsp }
2251 f21ec2f0 2020-03-21 stsp }
2252 3789fd73 2020-03-26 stsp done:
2253 c639c920 2022-10-12 thomas got_ref_list_free(&my_refs);
2254 3789fd73 2020-03-26 stsp free(remote_namespace);
2255 3789fd73 2020-03-26 stsp free(local_refname);
2256 0e4002ca 2020-03-21 stsp return err;
2257 0e4002ca 2020-03-21 stsp }
2258 0e4002ca 2020-03-21 stsp
2259 0e4002ca 2020-03-21 stsp static const struct got_error *
2260 0e4002ca 2020-03-21 stsp update_wanted_ref(const char *refname, struct got_object_id *id,
2261 0e4002ca 2020-03-21 stsp const char *remote_repo_name, int verbosity, struct got_repository *repo)
2262 0e4002ca 2020-03-21 stsp {
2263 9f142382 2020-03-21 stsp const struct got_error *err, *unlock_err;
2264 0e4002ca 2020-03-21 stsp char *remote_refname;
2265 0e4002ca 2020-03-21 stsp struct got_reference *ref;
2266 0e4002ca 2020-03-21 stsp
2267 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
2268 0e4002ca 2020-03-21 stsp refname += 5;
2269 0e4002ca 2020-03-21 stsp
2270 0e4002ca 2020-03-21 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2271 0e4002ca 2020-03-21 stsp remote_repo_name, refname) == -1)
2272 0e4002ca 2020-03-21 stsp return got_error_from_errno("asprintf");
2273 f21ec2f0 2020-03-21 stsp
2274 9f142382 2020-03-21 stsp err = got_ref_open(&ref, repo, remote_refname, 1);
2275 0e4002ca 2020-03-21 stsp if (err) {
2276 0e4002ca 2020-03-21 stsp if (err->code != GOT_ERR_NOT_REF)
2277 0e4002ca 2020-03-21 stsp goto done;
2278 0e4002ca 2020-03-21 stsp err = create_ref(remote_refname, id, verbosity, repo);
2279 0e4002ca 2020-03-21 stsp } else {
2280 0e4002ca 2020-03-21 stsp err = update_ref(ref, id, 0, verbosity, repo);
2281 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2282 9f142382 2020-03-21 stsp if (unlock_err && err == NULL)
2283 9f142382 2020-03-21 stsp err = unlock_err;
2284 0e4002ca 2020-03-21 stsp got_ref_close(ref);
2285 0e4002ca 2020-03-21 stsp }
2286 0e4002ca 2020-03-21 stsp done:
2287 0e4002ca 2020-03-21 stsp free(remote_refname);
2288 161728eb 2021-07-24 stsp return err;
2289 161728eb 2021-07-24 stsp }
2290 161728eb 2021-07-24 stsp
2291 161728eb 2021-07-24 stsp static const struct got_error *
2292 161728eb 2021-07-24 stsp delete_ref(struct got_repository *repo, struct got_reference *ref)
2293 161728eb 2021-07-24 stsp {
2294 161728eb 2021-07-24 stsp const struct got_error *err = NULL;
2295 161728eb 2021-07-24 stsp struct got_object_id *id = NULL;
2296 161728eb 2021-07-24 stsp char *id_str = NULL;
2297 161728eb 2021-07-24 stsp const char *target;
2298 161728eb 2021-07-24 stsp
2299 161728eb 2021-07-24 stsp if (got_ref_is_symbolic(ref)) {
2300 161728eb 2021-07-24 stsp target = got_ref_get_symref_target(ref);
2301 161728eb 2021-07-24 stsp } else {
2302 161728eb 2021-07-24 stsp err = got_ref_resolve(&id, repo, ref);
2303 161728eb 2021-07-24 stsp if (err)
2304 161728eb 2021-07-24 stsp goto done;
2305 161728eb 2021-07-24 stsp err = got_object_id_str(&id_str, id);
2306 161728eb 2021-07-24 stsp if (err)
2307 161728eb 2021-07-24 stsp goto done;
2308 161728eb 2021-07-24 stsp target = id_str;
2309 161728eb 2021-07-24 stsp }
2310 161728eb 2021-07-24 stsp
2311 161728eb 2021-07-24 stsp err = got_ref_delete(ref, repo);
2312 161728eb 2021-07-24 stsp if (err)
2313 161728eb 2021-07-24 stsp goto done;
2314 161728eb 2021-07-24 stsp
2315 161728eb 2021-07-24 stsp printf("Deleted %s: %s\n", got_ref_get_name(ref), target);
2316 161728eb 2021-07-24 stsp done:
2317 161728eb 2021-07-24 stsp free(id);
2318 161728eb 2021-07-24 stsp free(id_str);
2319 f21ec2f0 2020-03-21 stsp return err;
2320 f21ec2f0 2020-03-21 stsp }
2321 f21ec2f0 2020-03-21 stsp
2322 f21ec2f0 2020-03-21 stsp static const struct got_error *
2323 161728eb 2021-07-24 stsp delete_refs_for_remote(struct got_repository *repo, const char *remote_name)
2324 161728eb 2021-07-24 stsp {
2325 161728eb 2021-07-24 stsp const struct got_error *err = NULL;
2326 161728eb 2021-07-24 stsp struct got_reflist_head refs;
2327 161728eb 2021-07-24 stsp struct got_reflist_entry *re;
2328 161728eb 2021-07-24 stsp char *prefix;
2329 161728eb 2021-07-24 stsp
2330 161728eb 2021-07-24 stsp TAILQ_INIT(&refs);
2331 161728eb 2021-07-24 stsp
2332 161728eb 2021-07-24 stsp if (asprintf(&prefix, "refs/remotes/%s", remote_name) == -1) {
2333 161728eb 2021-07-24 stsp err = got_error_from_errno("asprintf");
2334 161728eb 2021-07-24 stsp goto done;
2335 161728eb 2021-07-24 stsp }
2336 161728eb 2021-07-24 stsp err = got_ref_list(&refs, repo, prefix, got_ref_cmp_by_name, NULL);
2337 161728eb 2021-07-24 stsp if (err)
2338 161728eb 2021-07-24 stsp goto done;
2339 161728eb 2021-07-24 stsp
2340 161728eb 2021-07-24 stsp TAILQ_FOREACH(re, &refs, entry)
2341 161728eb 2021-07-24 stsp delete_ref(repo, re->ref);
2342 161728eb 2021-07-24 stsp done:
2343 161728eb 2021-07-24 stsp got_ref_list_free(&refs);
2344 161728eb 2021-07-24 stsp return err;
2345 161728eb 2021-07-24 stsp }
2346 161728eb 2021-07-24 stsp
2347 161728eb 2021-07-24 stsp static const struct got_error *
2348 7848a0e1 2020-03-19 stsp cmd_fetch(int argc, char *argv[])
2349 7848a0e1 2020-03-19 stsp {
2350 9f142382 2020-03-21 stsp const struct got_error *error = NULL, *unlock_err;
2351 7848a0e1 2020-03-19 stsp char *cwd = NULL, *repo_path = NULL;
2352 7848a0e1 2020-03-19 stsp const char *remote_name;
2353 7848a0e1 2020-03-19 stsp char *proto = NULL, *host = NULL, *port = NULL;
2354 7848a0e1 2020-03-19 stsp char *repo_name = NULL, *server_path = NULL;
2355 11024cb9 2023-09-05 thomas const struct got_remote_repo *remotes;
2356 11024cb9 2023-09-05 thomas struct got_remote_repo *remote = NULL;
2357 7848a0e1 2020-03-19 stsp int nremotes;
2358 7848a0e1 2020-03-19 stsp char *id_str = NULL;
2359 7848a0e1 2020-03-19 stsp struct got_repository *repo = NULL;
2360 7848a0e1 2020-03-19 stsp struct got_worktree *worktree = NULL;
2361 50b0790e 2020-09-11 stsp const struct got_gotconfig *repo_conf = NULL, *worktree_conf = NULL;
2362 0e4002ca 2020-03-21 stsp struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
2363 23668511 2023-09-05 thomas char *head_refname = NULL;
2364 7848a0e1 2020-03-19 stsp struct got_pathlist_entry *pe;
2365 7abf1863 2023-02-20 thomas struct got_reflist_head remote_refs;
2366 7abf1863 2023-02-20 thomas struct got_reflist_entry *re;
2367 7848a0e1 2020-03-19 stsp struct got_object_id *pack_hash = NULL;
2368 9c52365f 2020-03-21 stsp int i, ch, fetchfd = -1, fetchstatus;
2369 9c52365f 2020-03-21 stsp pid_t fetchpid = -1;
2370 7848a0e1 2020-03-19 stsp struct got_fetch_progress_arg fpa;
2371 41b0de12 2020-03-21 stsp int verbosity = 0, fetch_all_branches = 0, list_refs_only = 0;
2372 161728eb 2021-07-24 stsp int delete_refs = 0, replace_tags = 0, delete_remote = 0;
2373 9d0a7ee3 2023-02-07 thomas int *pack_fds = NULL, have_bflag = 0;
2374 7abf1863 2023-02-20 thomas const char *remote_head = NULL, *worktree_branch = NULL;
2375 7848a0e1 2020-03-19 stsp
2376 7848a0e1 2020-03-19 stsp TAILQ_INIT(&refs);
2377 7848a0e1 2020-03-19 stsp TAILQ_INIT(&symrefs);
2378 7abf1863 2023-02-20 thomas TAILQ_INIT(&remote_refs);
2379 4ba14133 2020-03-20 stsp TAILQ_INIT(&wanted_branches);
2380 0e4002ca 2020-03-21 stsp TAILQ_INIT(&wanted_refs);
2381 7848a0e1 2020-03-19 stsp
2382 f7065961 2022-10-27 thomas while ((ch = getopt(argc, argv, "ab:dlqR:r:tvX")) != -1) {
2383 7848a0e1 2020-03-19 stsp switch (ch) {
2384 659e7fbd 2020-03-20 stsp case 'a':
2385 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
2386 4ba14133 2020-03-20 stsp break;
2387 4ba14133 2020-03-20 stsp case 'b':
2388 4ba14133 2020-03-20 stsp error = got_pathlist_append(&wanted_branches,
2389 4ba14133 2020-03-20 stsp optarg, NULL);
2390 4ba14133 2020-03-20 stsp if (error)
2391 4ba14133 2020-03-20 stsp return error;
2392 9d0a7ee3 2023-02-07 thomas have_bflag = 1;
2393 41b0de12 2020-03-21 stsp break;
2394 f21ec2f0 2020-03-21 stsp case 'd':
2395 f21ec2f0 2020-03-21 stsp delete_refs = 1;
2396 f21ec2f0 2020-03-21 stsp break;
2397 41b0de12 2020-03-21 stsp case 'l':
2398 41b0de12 2020-03-21 stsp list_refs_only = 1;
2399 f7065961 2022-10-27 thomas break;
2400 f7065961 2022-10-27 thomas case 'q':
2401 f7065961 2022-10-27 thomas verbosity = -1;
2402 f7065961 2022-10-27 thomas break;
2403 f7065961 2022-10-27 thomas case 'R':
2404 f7065961 2022-10-27 thomas error = got_pathlist_append(&wanted_refs,
2405 f7065961 2022-10-27 thomas optarg, NULL);
2406 f7065961 2022-10-27 thomas if (error)
2407 f7065961 2022-10-27 thomas return error;
2408 659e7fbd 2020-03-20 stsp break;
2409 7848a0e1 2020-03-19 stsp case 'r':
2410 7848a0e1 2020-03-19 stsp repo_path = realpath(optarg, NULL);
2411 7848a0e1 2020-03-19 stsp if (repo_path == NULL)
2412 7848a0e1 2020-03-19 stsp return got_error_from_errno2("realpath",
2413 7848a0e1 2020-03-19 stsp optarg);
2414 7848a0e1 2020-03-19 stsp got_path_strip_trailing_slashes(repo_path);
2415 7848a0e1 2020-03-19 stsp break;
2416 db6d8ad8 2020-03-21 stsp case 't':
2417 db6d8ad8 2020-03-21 stsp replace_tags = 1;
2418 db6d8ad8 2020-03-21 stsp break;
2419 7848a0e1 2020-03-19 stsp case 'v':
2420 7848a0e1 2020-03-19 stsp if (verbosity < 0)
2421 7848a0e1 2020-03-19 stsp verbosity = 0;
2422 7848a0e1 2020-03-19 stsp else if (verbosity < 3)
2423 7848a0e1 2020-03-19 stsp verbosity++;
2424 0e4002ca 2020-03-21 stsp break;
2425 161728eb 2021-07-24 stsp case 'X':
2426 161728eb 2021-07-24 stsp delete_remote = 1;
2427 161728eb 2021-07-24 stsp break;
2428 7848a0e1 2020-03-19 stsp default:
2429 7848a0e1 2020-03-19 stsp usage_fetch();
2430 7848a0e1 2020-03-19 stsp break;
2431 7848a0e1 2020-03-19 stsp }
2432 7848a0e1 2020-03-19 stsp }
2433 7848a0e1 2020-03-19 stsp argc -= optind;
2434 7848a0e1 2020-03-19 stsp argv += optind;
2435 7848a0e1 2020-03-19 stsp
2436 4ba14133 2020-03-20 stsp if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
2437 ff69268e 2020-12-13 stsp option_conflict('a', 'b');
2438 41b0de12 2020-03-21 stsp if (list_refs_only) {
2439 41b0de12 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_branches))
2440 ff69268e 2020-12-13 stsp option_conflict('l', 'b');
2441 ff69268e 2020-12-13 stsp if (fetch_all_branches)
2442 ff69268e 2020-12-13 stsp option_conflict('l', 'a');
2443 f21ec2f0 2020-03-21 stsp if (delete_refs)
2444 ff69268e 2020-12-13 stsp option_conflict('l', 'd');
2445 161728eb 2021-07-24 stsp if (delete_remote)
2446 161728eb 2021-07-24 stsp option_conflict('l', 'X');
2447 41b0de12 2020-03-21 stsp }
2448 161728eb 2021-07-24 stsp if (delete_remote) {
2449 161728eb 2021-07-24 stsp if (fetch_all_branches)
2450 161728eb 2021-07-24 stsp option_conflict('X', 'a');
2451 161728eb 2021-07-24 stsp if (!TAILQ_EMPTY(&wanted_branches))
2452 161728eb 2021-07-24 stsp option_conflict('X', 'b');
2453 161728eb 2021-07-24 stsp if (delete_refs)
2454 161728eb 2021-07-24 stsp option_conflict('X', 'd');
2455 161728eb 2021-07-24 stsp if (replace_tags)
2456 161728eb 2021-07-24 stsp option_conflict('X', 't');
2457 161728eb 2021-07-24 stsp if (!TAILQ_EMPTY(&wanted_refs))
2458 161728eb 2021-07-24 stsp option_conflict('X', 'R');
2459 161728eb 2021-07-24 stsp }
2460 161728eb 2021-07-24 stsp
2461 161728eb 2021-07-24 stsp if (argc == 0) {
2462 161728eb 2021-07-24 stsp if (delete_remote)
2463 161728eb 2021-07-24 stsp errx(1, "-X option requires a remote name");
2464 7848a0e1 2020-03-19 stsp remote_name = GOT_FETCH_DEFAULT_REMOTE_NAME;
2465 161728eb 2021-07-24 stsp } else if (argc == 1)
2466 7848a0e1 2020-03-19 stsp remote_name = argv[0];
2467 7848a0e1 2020-03-19 stsp else
2468 7848a0e1 2020-03-19 stsp usage_fetch();
2469 7848a0e1 2020-03-19 stsp
2470 7848a0e1 2020-03-19 stsp cwd = getcwd(NULL, 0);
2471 7848a0e1 2020-03-19 stsp if (cwd == NULL) {
2472 7848a0e1 2020-03-19 stsp error = got_error_from_errno("getcwd");
2473 7848a0e1 2020-03-19 stsp goto done;
2474 7848a0e1 2020-03-19 stsp }
2475 7848a0e1 2020-03-19 stsp
2476 7cd52833 2022-06-23 thomas error = got_repo_pack_fds_open(&pack_fds);
2477 7cd52833 2022-06-23 thomas if (error != NULL)
2478 7cd52833 2022-06-23 thomas goto done;
2479 7cd52833 2022-06-23 thomas
2480 7848a0e1 2020-03-19 stsp if (repo_path == NULL) {
2481 ad10f64e 2023-07-19 thomas error = got_worktree_open(&worktree, cwd, GOT_WORKTREE_GOT_DIR);
2482 7848a0e1 2020-03-19 stsp if (error && error->code != GOT_ERR_NOT_WORKTREE)
2483 7848a0e1 2020-03-19 stsp goto done;
2484 7848a0e1 2020-03-19 stsp else
2485 7848a0e1 2020-03-19 stsp error = NULL;
2486 7848a0e1 2020-03-19 stsp if (worktree) {
2487 7848a0e1 2020-03-19 stsp repo_path =
2488 7848a0e1 2020-03-19 stsp strdup(got_worktree_get_repo_path(worktree));
2489 7848a0e1 2020-03-19 stsp if (repo_path == NULL)
2490 7848a0e1 2020-03-19 stsp error = got_error_from_errno("strdup");
2491 7848a0e1 2020-03-19 stsp if (error)
2492 7848a0e1 2020-03-19 stsp goto done;
2493 7848a0e1 2020-03-19 stsp } else {
2494 7848a0e1 2020-03-19 stsp repo_path = strdup(cwd);
2495 7848a0e1 2020-03-19 stsp if (repo_path == NULL) {
2496 7848a0e1 2020-03-19 stsp error = got_error_from_errno("strdup");
2497 7848a0e1 2020-03-19 stsp goto done;
2498 7848a0e1 2020-03-19 stsp }
2499 7848a0e1 2020-03-19 stsp }
2500 7848a0e1 2020-03-19 stsp }
2501 7848a0e1 2020-03-19 stsp
2502 7cd52833 2022-06-23 thomas error = got_repo_open(&repo, repo_path, NULL, pack_fds);
2503 7848a0e1 2020-03-19 stsp if (error)
2504 7848a0e1 2020-03-19 stsp goto done;
2505 7848a0e1 2020-03-19 stsp
2506 161728eb 2021-07-24 stsp if (delete_remote) {
2507 161728eb 2021-07-24 stsp error = delete_refs_for_remote(repo, remote_name);
2508 161728eb 2021-07-24 stsp goto done; /* nothing else to do */
2509 161728eb 2021-07-24 stsp }
2510 161728eb 2021-07-24 stsp
2511 50b0790e 2020-09-11 stsp if (worktree) {
2512 50b0790e 2020-09-11 stsp worktree_conf = got_worktree_get_gotconfig(worktree);
2513 50b0790e 2020-09-11 stsp if (worktree_conf) {
2514 50b0790e 2020-09-11 stsp got_gotconfig_get_remotes(&nremotes, &remotes,
2515 50b0790e 2020-09-11 stsp worktree_conf);
2516 50b0790e 2020-09-11 stsp for (i = 0; i < nremotes; i++) {
2517 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2518 11024cb9 2023-09-05 thomas error = got_repo_remote_repo_dup(&remote,
2519 11024cb9 2023-09-05 thomas &remotes[i]);
2520 11024cb9 2023-09-05 thomas if (error)
2521 11024cb9 2023-09-05 thomas goto done;
2522 50b0790e 2020-09-11 stsp break;
2523 54eb00d5 2020-10-20 stsp }
2524 50b0790e 2020-09-11 stsp }
2525 50b0790e 2020-09-11 stsp }
2526 7848a0e1 2020-03-19 stsp }
2527 50b0790e 2020-09-11 stsp if (remote == NULL) {
2528 50b0790e 2020-09-11 stsp repo_conf = got_repo_get_gotconfig(repo);
2529 50b0790e 2020-09-11 stsp if (repo_conf) {
2530 50b0790e 2020-09-11 stsp got_gotconfig_get_remotes(&nremotes, &remotes,
2531 50b0790e 2020-09-11 stsp repo_conf);
2532 50b0790e 2020-09-11 stsp for (i = 0; i < nremotes; i++) {
2533 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2534 11024cb9 2023-09-05 thomas error = got_repo_remote_repo_dup(&remote,
2535 11024cb9 2023-09-05 thomas &remotes[i]);
2536 11024cb9 2023-09-05 thomas if (error)
2537 11024cb9 2023-09-05 thomas goto done;
2538 50b0790e 2020-09-11 stsp break;
2539 54eb00d5 2020-10-20 stsp }
2540 50b0790e 2020-09-11 stsp }
2541 50b0790e 2020-09-11 stsp }
2542 50b0790e 2020-09-11 stsp }
2543 50b0790e 2020-09-11 stsp if (remote == NULL) {
2544 257add31 2020-09-09 stsp got_repo_get_gitconfig_remotes(&nremotes, &remotes, repo);
2545 257add31 2020-09-09 stsp for (i = 0; i < nremotes; i++) {
2546 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2547 11024cb9 2023-09-05 thomas error = got_repo_remote_repo_dup(&remote,
2548 11024cb9 2023-09-05 thomas &remotes[i]);
2549 11024cb9 2023-09-05 thomas if (error)
2550 11024cb9 2023-09-05 thomas goto done;
2551 257add31 2020-09-09 stsp break;
2552 54eb00d5 2020-10-20 stsp }
2553 257add31 2020-09-09 stsp }
2554 7848a0e1 2020-03-19 stsp }
2555 50b0790e 2020-09-11 stsp if (remote == NULL) {
2556 50b0790e 2020-09-11 stsp error = got_error_path(remote_name, GOT_ERR_NO_REMOTE);
2557 50b0790e 2020-09-11 stsp goto done;
2558 b8adfa55 2020-09-25 stsp }
2559 b8adfa55 2020-09-25 stsp
2560 0c8b29c5 2021-01-05 stsp if (TAILQ_EMPTY(&wanted_branches)) {
2561 0c8b29c5 2021-01-05 stsp if (!fetch_all_branches)
2562 0c8b29c5 2021-01-05 stsp fetch_all_branches = remote->fetch_all_branches;
2563 6480c871 2021-08-30 stsp for (i = 0; i < remote->nfetch_branches; i++) {
2564 c0ce8a2b 2023-01-14 thomas error = got_pathlist_append(&wanted_branches,
2565 6480c871 2021-08-30 stsp remote->fetch_branches[i], NULL);
2566 8d0dceb3 2023-02-07 thomas if (error)
2567 8d0dceb3 2023-02-07 thomas goto done;
2568 8d0dceb3 2023-02-07 thomas }
2569 99495ddb 2021-01-10 stsp }
2570 99495ddb 2021-01-10 stsp if (TAILQ_EMPTY(&wanted_refs)) {
2571 6480c871 2021-08-30 stsp for (i = 0; i < remote->nfetch_refs; i++) {
2572 c0ce8a2b 2023-01-14 thomas error = got_pathlist_append(&wanted_refs,
2573 6480c871 2021-08-30 stsp remote->fetch_refs[i], NULL);
2574 c0ce8a2b 2023-01-14 thomas if (error)
2575 c0ce8a2b 2023-01-14 thomas goto done;
2576 b8adfa55 2020-09-25 stsp }
2577 50b0790e 2020-09-11 stsp }
2578 7848a0e1 2020-03-19 stsp
2579 5e5da8c4 2021-09-05 stsp error = got_dial_parse_uri(&proto, &host, &port, &server_path,
2580 6480c871 2021-08-30 stsp &repo_name, remote->fetch_url);
2581 7848a0e1 2020-03-19 stsp if (error)
2582 7848a0e1 2020-03-19 stsp goto done;
2583 7848a0e1 2020-03-19 stsp
2584 7848a0e1 2020-03-19 stsp if (strcmp(proto, "git") == 0) {
2585 7848a0e1 2020-03-19 stsp #ifndef PROFILE
2586 7848a0e1 2020-03-19 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2587 7848a0e1 2020-03-19 stsp "sendfd dns inet unveil", NULL) == -1)
2588 7848a0e1 2020-03-19 stsp err(1, "pledge");
2589 7848a0e1 2020-03-19 stsp #endif
2590 7848a0e1 2020-03-19 stsp } else if (strcmp(proto, "git+ssh") == 0 ||
2591 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "ssh") == 0 ||
2592 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "git+http") == 0 ||
2593 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "http") == 0 ||
2594 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "git+https") == 0 ||
2595 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "https") == 0) {
2596 7848a0e1 2020-03-19 stsp #ifndef PROFILE
2597 7848a0e1 2020-03-19 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2598 7848a0e1 2020-03-19 stsp "sendfd unveil", NULL) == -1)
2599 7848a0e1 2020-03-19 stsp err(1, "pledge");
2600 7848a0e1 2020-03-19 stsp #endif
2601 7848a0e1 2020-03-19 stsp } else {
2602 7848a0e1 2020-03-19 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
2603 7848a0e1 2020-03-19 stsp goto done;
2604 7848a0e1 2020-03-19 stsp }
2605 7848a0e1 2020-03-19 stsp
2606 d65a88a2 2021-09-05 stsp error = got_dial_apply_unveil(proto);
2607 d65a88a2 2021-09-05 stsp if (error)
2608 d65a88a2 2021-09-05 stsp goto done;
2609 d65a88a2 2021-09-05 stsp
2610 7848a0e1 2020-03-19 stsp error = apply_unveil(got_repo_get_path(repo), 0, NULL);
2611 7848a0e1 2020-03-19 stsp if (error)
2612 7848a0e1 2020-03-19 stsp goto done;
2613 f79e6490 2020-04-19 stsp
2614 23668511 2023-09-05 thomas if (worktree) {
2615 23668511 2023-09-05 thomas head_refname = strdup(got_worktree_get_head_ref_name(worktree));
2616 23668511 2023-09-05 thomas if (head_refname == NULL) {
2617 23668511 2023-09-05 thomas error = got_error_from_errno("strdup");
2618 23668511 2023-09-05 thomas goto done;
2619 23668511 2023-09-05 thomas }
2620 23668511 2023-09-05 thomas
2621 23668511 2023-09-05 thomas /* Release work tree lock. */
2622 23668511 2023-09-05 thomas got_worktree_close(worktree);
2623 23668511 2023-09-05 thomas worktree = NULL;
2624 23668511 2023-09-05 thomas }
2625 23668511 2023-09-05 thomas
2626 6df5d941 2022-11-18 thomas if (verbosity >= 0) {
2627 6df5d941 2022-11-18 thomas printf("Connecting to \"%s\" %s://%s%s%s%s%s\n",
2628 6df5d941 2022-11-18 thomas remote->name, proto, host,
2629 6df5d941 2022-11-18 thomas port ? ":" : "", port ? port : "",
2630 6df5d941 2022-11-18 thomas *server_path == '/' ? "" : "/", server_path);
2631 6df5d941 2022-11-18 thomas }
2632 7848a0e1 2020-03-19 stsp
2633 9c52365f 2020-03-21 stsp error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
2634 9c52365f 2020-03-21 stsp server_path, verbosity);
2635 7848a0e1 2020-03-19 stsp if (error)
2636 7848a0e1 2020-03-19 stsp goto done;
2637 a6955b87 2024-04-25 thomas.ad #ifndef PROFILE
2638 a6955b87 2024-04-25 thomas.ad if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd",
2639 a6955b87 2024-04-25 thomas.ad NULL) == -1)
2640 a6955b87 2024-04-25 thomas.ad err(1, "pledge");
2641 a6955b87 2024-04-25 thomas.ad #endif
2642 7abf1863 2023-02-20 thomas if (!have_bflag) {
2643 7abf1863 2023-02-20 thomas /*
2644 7abf1863 2023-02-20 thomas * If set, get this remote's HEAD ref target so
2645 7abf1863 2023-02-20 thomas * if it has changed on the server we can fetch it.
2646 7abf1863 2023-02-20 thomas */
2647 7abf1863 2023-02-20 thomas error = got_ref_list(&remote_refs, repo, "refs/remotes",
2648 7abf1863 2023-02-20 thomas got_ref_cmp_by_name, repo);
2649 7abf1863 2023-02-20 thomas if (error)
2650 7abf1863 2023-02-20 thomas goto done;
2651 7848a0e1 2020-03-19 stsp
2652 7abf1863 2023-02-20 thomas TAILQ_FOREACH(re, &remote_refs, entry) {
2653 7abf1863 2023-02-20 thomas const char *remote_refname, *remote_target;
2654 7abf1863 2023-02-20 thomas size_t remote_name_len;
2655 7abf1863 2023-02-20 thomas
2656 7abf1863 2023-02-20 thomas if (!got_ref_is_symbolic(re->ref))
2657 7abf1863 2023-02-20 thomas continue;
2658 7abf1863 2023-02-20 thomas
2659 7abf1863 2023-02-20 thomas remote_name_len = strlen(remote->name);
2660 7abf1863 2023-02-20 thomas remote_refname = got_ref_get_name(re->ref);
2661 7abf1863 2023-02-20 thomas
2662 7abf1863 2023-02-20 thomas /* we only want refs/remotes/$remote->name/HEAD */
2663 7abf1863 2023-02-20 thomas if (strncmp(remote_refname + 13, remote->name,
2664 7abf1863 2023-02-20 thomas remote_name_len) != 0)
2665 7abf1863 2023-02-20 thomas continue;
2666 7abf1863 2023-02-20 thomas
2667 7abf1863 2023-02-20 thomas if (strcmp(remote_refname + remote_name_len + 14,
2668 7abf1863 2023-02-20 thomas GOT_REF_HEAD) != 0)
2669 7abf1863 2023-02-20 thomas continue;
2670 7abf1863 2023-02-20 thomas
2671 7abf1863 2023-02-20 thomas /*
2672 7abf1863 2023-02-20 thomas * Take the name itself because we already
2673 7abf1863 2023-02-20 thomas * only match with refs/heads/ in fetch_pack().
2674 7abf1863 2023-02-20 thomas */
2675 7abf1863 2023-02-20 thomas remote_target = got_ref_get_symref_target(re->ref);
2676 7abf1863 2023-02-20 thomas remote_head = remote_target + remote_name_len + 14;
2677 7abf1863 2023-02-20 thomas break;
2678 7abf1863 2023-02-20 thomas }
2679 7abf1863 2023-02-20 thomas
2680 23668511 2023-09-05 thomas if (head_refname &&
2681 23668511 2023-09-05 thomas strncmp(head_refname, "refs/heads/", 11) == 0)
2682 23668511 2023-09-05 thomas worktree_branch = head_refname;
2683 4c63d3a5 2023-02-07 thomas }
2684 4c63d3a5 2023-02-07 thomas
2685 7848a0e1 2020-03-19 stsp fpa.last_scaled_size[0] = '\0';
2686 7848a0e1 2020-03-19 stsp fpa.last_p_indexed = -1;
2687 7848a0e1 2020-03-19 stsp fpa.last_p_resolved = -1;
2688 7848a0e1 2020-03-19 stsp fpa.verbosity = verbosity;
2689 04d9a9ec 2020-09-24 stsp fpa.repo = repo;
2690 04d9a9ec 2020-09-24 stsp fpa.create_configs = 0;
2691 04d9a9ec 2020-09-24 stsp fpa.configs_created = 0;
2692 04d9a9ec 2020-09-24 stsp memset(&fpa.config_info, 0, sizeof(fpa.config_info));
2693 e0380e3d 2023-02-17 thomas
2694 7848a0e1 2020-03-19 stsp error = got_fetch_pack(&pack_hash, &refs, &symrefs, remote->name,
2695 4ba14133 2020-03-20 stsp remote->mirror_references, fetch_all_branches, &wanted_branches,
2696 0e4002ca 2020-03-21 stsp &wanted_refs, list_refs_only, verbosity, fetchfd, repo,
2697 7abf1863 2023-02-20 thomas worktree_branch, remote_head, have_bflag, fetch_progress, &fpa);
2698 7848a0e1 2020-03-19 stsp if (error)
2699 7848a0e1 2020-03-19 stsp goto done;
2700 7848a0e1 2020-03-19 stsp
2701 41b0de12 2020-03-21 stsp if (list_refs_only) {
2702 41b0de12 2020-03-21 stsp error = list_remote_refs(&symrefs, &refs);
2703 41b0de12 2020-03-21 stsp goto done;
2704 41b0de12 2020-03-21 stsp }
2705 41b0de12 2020-03-21 stsp
2706 7848a0e1 2020-03-19 stsp if (pack_hash == NULL) {
2707 7848a0e1 2020-03-19 stsp if (verbosity >= 0)
2708 7848a0e1 2020-03-19 stsp printf("Already up-to-date\n");
2709 bcf34b0e 2020-03-26 stsp } else if (verbosity >= 0) {
2710 984065c8 2020-03-19 stsp error = got_object_id_str(&id_str, pack_hash);
2711 984065c8 2020-03-19 stsp if (error)
2712 984065c8 2020-03-19 stsp goto done;
2713 e69674d8 2020-03-19 stsp printf("\nFetched %s.pack\n", id_str);
2714 984065c8 2020-03-19 stsp free(id_str);
2715 984065c8 2020-03-19 stsp id_str = NULL;
2716 984065c8 2020-03-19 stsp }
2717 7848a0e1 2020-03-19 stsp
2718 7848a0e1 2020-03-19 stsp /* Update references provided with the pack file. */
2719 7848a0e1 2020-03-19 stsp TAILQ_FOREACH(pe, &refs, entry) {
2720 7848a0e1 2020-03-19 stsp const char *refname = pe->path;
2721 7848a0e1 2020-03-19 stsp struct got_object_id *id = pe->data;
2722 7848a0e1 2020-03-19 stsp struct got_reference *ref;
2723 7848a0e1 2020-03-19 stsp char *remote_refname;
2724 7848a0e1 2020-03-19 stsp
2725 0e4002ca 2020-03-21 stsp if (is_wanted_ref(&wanted_refs, refname) &&
2726 0e4002ca 2020-03-21 stsp !remote->mirror_references) {
2727 0e4002ca 2020-03-21 stsp error = update_wanted_ref(refname, id,
2728 0e4002ca 2020-03-21 stsp remote->name, verbosity, repo);
2729 0e4002ca 2020-03-21 stsp if (error)
2730 0e4002ca 2020-03-21 stsp goto done;
2731 0e4002ca 2020-03-21 stsp continue;
2732 0e4002ca 2020-03-21 stsp }
2733 0e4002ca 2020-03-21 stsp
2734 1510c839 2020-03-20 stsp if (remote->mirror_references ||
2735 1510c839 2020-03-20 stsp strncmp("refs/tags/", refname, 10) == 0) {
2736 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, refname, 1);
2737 7848a0e1 2020-03-19 stsp if (error) {
2738 7848a0e1 2020-03-19 stsp if (error->code != GOT_ERR_NOT_REF)
2739 7848a0e1 2020-03-19 stsp goto done;
2740 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity,
2741 6338a6a1 2020-03-21 stsp repo);
2742 7848a0e1 2020-03-19 stsp if (error)
2743 7848a0e1 2020-03-19 stsp goto done;
2744 7848a0e1 2020-03-19 stsp } else {
2745 db6d8ad8 2020-03-21 stsp error = update_ref(ref, id, replace_tags,
2746 db6d8ad8 2020-03-21 stsp verbosity, repo);
2747 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2748 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2749 9f142382 2020-03-21 stsp error = unlock_err;
2750 7848a0e1 2020-03-19 stsp got_ref_close(ref);
2751 7848a0e1 2020-03-19 stsp if (error)
2752 7848a0e1 2020-03-19 stsp goto done;
2753 7848a0e1 2020-03-19 stsp }
2754 7848a0e1 2020-03-19 stsp } else if (strncmp("refs/heads/", refname, 11) == 0) {
2755 7848a0e1 2020-03-19 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2756 7848a0e1 2020-03-19 stsp remote_name, refname + 11) == -1) {
2757 7848a0e1 2020-03-19 stsp error = got_error_from_errno("asprintf");
2758 7848a0e1 2020-03-19 stsp goto done;
2759 7848a0e1 2020-03-19 stsp }
2760 7848a0e1 2020-03-19 stsp
2761 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, remote_refname, 1);
2762 7848a0e1 2020-03-19 stsp if (error) {
2763 7848a0e1 2020-03-19 stsp if (error->code != GOT_ERR_NOT_REF)
2764 7848a0e1 2020-03-19 stsp goto done;
2765 b6b86fd1 2022-08-30 thomas error = create_ref(remote_refname, id,
2766 688f11b3 2020-03-21 stsp verbosity, repo);
2767 7848a0e1 2020-03-19 stsp if (error)
2768 7848a0e1 2020-03-19 stsp goto done;
2769 7848a0e1 2020-03-19 stsp } else {
2770 db6d8ad8 2020-03-21 stsp error = update_ref(ref, id, replace_tags,
2771 db6d8ad8 2020-03-21 stsp verbosity, repo);
2772 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2773 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2774 9f142382 2020-03-21 stsp error = unlock_err;
2775 7848a0e1 2020-03-19 stsp got_ref_close(ref);
2776 7848a0e1 2020-03-19 stsp if (error)
2777 7848a0e1 2020-03-19 stsp goto done;
2778 7848a0e1 2020-03-19 stsp }
2779 2ec30c80 2020-03-20 stsp
2780 2ec30c80 2020-03-20 stsp /* Also create a local branch if none exists yet. */
2781 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, refname, 1);
2782 2ec30c80 2020-03-20 stsp if (error) {
2783 2ec30c80 2020-03-20 stsp if (error->code != GOT_ERR_NOT_REF)
2784 2ec30c80 2020-03-20 stsp goto done;
2785 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity,
2786 6338a6a1 2020-03-21 stsp repo);
2787 2ec30c80 2020-03-20 stsp if (error)
2788 2ec30c80 2020-03-20 stsp goto done;
2789 9f142382 2020-03-21 stsp } else {
2790 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2791 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2792 9f142382 2020-03-21 stsp error = unlock_err;
2793 2ec30c80 2020-03-20 stsp got_ref_close(ref);
2794 9f142382 2020-03-21 stsp }
2795 7848a0e1 2020-03-19 stsp }
2796 7848a0e1 2020-03-19 stsp }
2797 f1bcca34 2020-03-25 stsp if (delete_refs) {
2798 3789fd73 2020-03-26 stsp error = delete_missing_refs(&refs, &symrefs, remote,
2799 3789fd73 2020-03-26 stsp verbosity, repo);
2800 f1bcca34 2020-03-25 stsp if (error)
2801 f1bcca34 2020-03-25 stsp goto done;
2802 f1bcca34 2020-03-25 stsp }
2803 f1bcca34 2020-03-25 stsp
2804 f1bcca34 2020-03-25 stsp if (!remote->mirror_references) {
2805 f1bcca34 2020-03-25 stsp /* Update remote HEAD reference if the server provided one. */
2806 f1bcca34 2020-03-25 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
2807 f1bcca34 2020-03-25 stsp struct got_reference *target_ref;
2808 f1bcca34 2020-03-25 stsp const char *refname = pe->path;
2809 f1bcca34 2020-03-25 stsp const char *target = pe->data;
2810 f1bcca34 2020-03-25 stsp char *remote_refname = NULL, *remote_target = NULL;
2811 f1bcca34 2020-03-25 stsp
2812 f1bcca34 2020-03-25 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
2813 f1bcca34 2020-03-25 stsp continue;
2814 f1bcca34 2020-03-25 stsp
2815 f1bcca34 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
2816 f1bcca34 2020-03-25 stsp continue;
2817 f1bcca34 2020-03-25 stsp
2818 f1bcca34 2020-03-25 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2819 f1bcca34 2020-03-25 stsp remote->name, refname) == -1) {
2820 f1bcca34 2020-03-25 stsp error = got_error_from_errno("asprintf");
2821 f1bcca34 2020-03-25 stsp goto done;
2822 f1bcca34 2020-03-25 stsp }
2823 f1bcca34 2020-03-25 stsp if (asprintf(&remote_target, "refs/remotes/%s/%s",
2824 f1bcca34 2020-03-25 stsp remote->name, target + 11) == -1) {
2825 f1bcca34 2020-03-25 stsp error = got_error_from_errno("asprintf");
2826 f1bcca34 2020-03-25 stsp free(remote_refname);
2827 f1bcca34 2020-03-25 stsp goto done;
2828 f1bcca34 2020-03-25 stsp }
2829 f1bcca34 2020-03-25 stsp
2830 f1bcca34 2020-03-25 stsp error = got_ref_open(&target_ref, repo, remote_target,
2831 f1bcca34 2020-03-25 stsp 0);
2832 f1bcca34 2020-03-25 stsp if (error) {
2833 f1bcca34 2020-03-25 stsp free(remote_refname);
2834 f1bcca34 2020-03-25 stsp free(remote_target);
2835 f1bcca34 2020-03-25 stsp if (error->code == GOT_ERR_NOT_REF) {
2836 f1bcca34 2020-03-25 stsp error = NULL;
2837 f1bcca34 2020-03-25 stsp continue;
2838 f1bcca34 2020-03-25 stsp }
2839 f1bcca34 2020-03-25 stsp goto done;
2840 f1bcca34 2020-03-25 stsp }
2841 f1bcca34 2020-03-25 stsp error = update_symref(remote_refname, target_ref,
2842 f1bcca34 2020-03-25 stsp verbosity, repo);
2843 f1bcca34 2020-03-25 stsp free(remote_refname);
2844 f1bcca34 2020-03-25 stsp free(remote_target);
2845 f1bcca34 2020-03-25 stsp got_ref_close(target_ref);
2846 f1bcca34 2020-03-25 stsp if (error)
2847 f1bcca34 2020-03-25 stsp goto done;
2848 f1bcca34 2020-03-25 stsp }
2849 f1bcca34 2020-03-25 stsp }
2850 7848a0e1 2020-03-19 stsp done:
2851 9c52365f 2020-03-21 stsp if (fetchpid > 0) {
2852 9c52365f 2020-03-21 stsp if (kill(fetchpid, SIGTERM) == -1)
2853 9c52365f 2020-03-21 stsp error = got_error_from_errno("kill");
2854 9c52365f 2020-03-21 stsp if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
2855 9c52365f 2020-03-21 stsp error = got_error_from_errno("waitpid");
2856 9c52365f 2020-03-21 stsp }
2857 7848a0e1 2020-03-19 stsp if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
2858 7848a0e1 2020-03-19 stsp error = got_error_from_errno("close");
2859 1d0f4054 2021-06-17 stsp if (repo) {
2860 1d0f4054 2021-06-17 stsp const struct got_error *close_err = got_repo_close(repo);
2861 1d0f4054 2021-06-17 stsp if (error == NULL)
2862 1d0f4054 2021-06-17 stsp error = close_err;
2863 1d0f4054 2021-06-17 stsp }
2864 7848a0e1 2020-03-19 stsp if (worktree)
2865 7848a0e1 2020-03-19 stsp got_worktree_close(worktree);
2866 7cd52833 2022-06-23 thomas if (pack_fds) {
2867 7cd52833 2022-06-23 thomas const struct got_error *pack_err =
2868 7cd52833 2022-06-23 thomas got_repo_pack_fds_close(pack_fds);
2869 7cd52833 2022-06-23 thomas if (error == NULL)
2870 7cd52833 2022-06-23 thomas error = pack_err;
2871 7cd52833 2022-06-23 thomas }
2872 21c2d8be 2023-01-10 thomas got_pathlist_free(&refs, GOT_PATHLIST_FREE_ALL);
2873 21c2d8be 2023-01-10 thomas got_pathlist_free(&symrefs, GOT_PATHLIST_FREE_ALL);
2874 21c2d8be 2023-01-10 thomas got_pathlist_free(&wanted_branches, GOT_PATHLIST_FREE_NONE);
2875 21c2d8be 2023-01-10 thomas got_pathlist_free(&wanted_refs, GOT_PATHLIST_FREE_NONE);
2876 7abf1863 2023-02-20 thomas got_ref_list_free(&remote_refs);
2877 11024cb9 2023-09-05 thomas got_repo_free_remote_repo_data(remote);
2878 11024cb9 2023-09-05 thomas free(remote);
2879 23668511 2023-09-05 thomas free(head_refname);
2880 7848a0e1 2020-03-19 stsp free(id_str);
2881 7848a0e1 2020-03-19 stsp free(cwd);
2882 7848a0e1 2020-03-19 stsp free(repo_path);
2883 7848a0e1 2020-03-19 stsp free(pack_hash);
2884 7848a0e1 2020-03-19 stsp free(proto);
2885 7848a0e1 2020-03-19 stsp free(host);
2886 7848a0e1 2020-03-19 stsp free(port);
2887 7848a0e1 2020-03-19 stsp free(server_path);
2888 7848a0e1 2020-03-19 stsp free(repo_name);
2889 7848a0e1 2020-03-19 stsp return error;
2890 7848a0e1 2020-03-19 stsp }
2891 7848a0e1 2020-03-19 stsp
2892 7848a0e1 2020-03-19 stsp
2893 7848a0e1 2020-03-19 stsp __dead static void
2894 2ab43947 2020-03-18 stsp usage_checkout(void)
2895 2ab43947 2020-03-18 stsp {
2896 d6506a3d 2022-08-16 thomas fprintf(stderr, "usage: %s checkout [-Eq] [-b branch] [-c commit] "
2897 d6506a3d 2022-08-16 thomas "[-p path-prefix] repository-path [work-tree-path]\n",
2898 4ad4a1ec 2021-09-13 tracey getprogname());
2899 2ab43947 2020-03-18 stsp exit(1);
2900 2ab43947 2020-03-18 stsp }
2901 2ab43947 2020-03-18 stsp
2902 2ab43947 2020-03-18 stsp static void
2903 2ab43947 2020-03-18 stsp show_worktree_base_ref_warning(void)
2904 2ab43947 2020-03-18 stsp {
2905 2ab43947 2020-03-18 stsp fprintf(stderr, "%s: warning: could not create a reference "
2906 2ab43947 2020-03-18 stsp "to the work tree's base commit; the commit could be "
2907 e6786710 2021-07-03 stsp "garbage-collected by Git or 'gotadmin cleanup'; making the "
2908 e6786710 2021-07-03 stsp "repository writable and running 'got update' will prevent this\n",
2909 2ab43947 2020-03-18 stsp getprogname());
2910 2ab43947 2020-03-18 stsp }
2911 2ab43947 2020-03-18 stsp
2912 2ab43947 2020-03-18 stsp struct got_checkout_progress_arg {
2913 2ab43947 2020-03-18 stsp const char *worktree_path;
2914 2ab43947 2020-03-18 stsp int had_base_commit_ref_error;
2915 4ad4a1ec 2021-09-13 tracey int verbosity;
2916 2ab43947 2020-03-18 stsp };
2917 2ab43947 2020-03-18 stsp
2918 2ab43947 2020-03-18 stsp static const struct got_error *
2919 2ab43947 2020-03-18 stsp checkout_progress(void *arg, unsigned char status, const char *path)
2920 2ab43947 2020-03-18 stsp {
2921 2ab43947 2020-03-18 stsp struct got_checkout_progress_arg *a = arg;
2922 2ab43947 2020-03-18 stsp
2923 2ab43947 2020-03-18 stsp /* Base commit bump happens silently. */
2924 2ab43947 2020-03-18 stsp if (status == GOT_STATUS_BUMP_BASE)
2925 2ab43947 2020-03-18 stsp return NULL;
2926 2ab43947 2020-03-18 stsp
2927 2ab43947 2020-03-18 stsp if (status == GOT_STATUS_BASE_REF_ERR) {
2928 2ab43947 2020-03-18 stsp a->had_base_commit_ref_error = 1;
2929 2ab43947 2020-03-18 stsp return NULL;
2930 2ab43947 2020-03-18 stsp }
2931 2ab43947 2020-03-18 stsp
2932 2ab43947 2020-03-18 stsp while (path[0] == '/')
2933 2ab43947 2020-03-18 stsp path++;
2934 2ab43947 2020-03-18 stsp
2935 4ad4a1ec 2021-09-13 tracey if (a->verbosity >= 0)
2936 4ad4a1ec 2021-09-13 tracey printf("%c %s/%s\n", status, a->worktree_path, path);
2937 4ad4a1ec 2021-09-13 tracey
2938 2ab43947 2020-03-18 stsp return NULL;
2939 2ab43947 2020-03-18 stsp }
2940 2ab43947 2020-03-18 stsp
2941 2ab43947 2020-03-18 stsp static const struct got_error *
2942 2ab43947 2020-03-18 stsp check_cancelled(void *arg)
2943 2ab43947 2020-03-18 stsp {
2944 2ab43947 2020-03-18 stsp if (sigint_received || sigpipe_received)
2945 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_CANCELLED);
2946 2ab43947 2020-03-18 stsp return NULL;
2947 2ab43947 2020-03-18 stsp }
2948 2ab43947 2020-03-18 stsp
2949 2ab43947 2020-03-18 stsp static const struct got_error *
2950 2ab43947 2020-03-18 stsp check_linear_ancestry(struct got_object_id *commit_id,
2951 2ab43947 2020-03-18 stsp struct got_object_id *base_commit_id, int allow_forwards_in_time_only,
2952 2ab43947 2020-03-18 stsp struct got_repository *repo)
2953 2ab43947 2020-03-18 stsp {
2954 2ab43947 2020-03-18 stsp const struct got_error *err = NULL;
2955 2ab43947 2020-03-18 stsp struct got_object_id *yca_id;
2956 2ab43947 2020-03-18 stsp
2957 2ab43947 2020-03-18 stsp err = got_commit_graph_find_youngest_common_ancestor(&yca_id,
2958 807c60e9 2024-03-30 thomas commit_id, base_commit_id, 1, 0, repo, check_cancelled, NULL);
2959 2ab43947 2020-03-18 stsp if (err)
2960 2ab43947 2020-03-18 stsp return err;
2961 2ab43947 2020-03-18 stsp
2962 2ab43947 2020-03-18 stsp if (yca_id == NULL)
2963 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2964 2ab43947 2020-03-18 stsp
2965 2ab43947 2020-03-18 stsp /*
2966 2ab43947 2020-03-18 stsp * Require a straight line of history between the target commit
2967 2ab43947 2020-03-18 stsp * and the work tree's base commit.
2968 2ab43947 2020-03-18 stsp *
2969 2ab43947 2020-03-18 stsp * Non-linear situations such as this require a rebase:
2970 2ab43947 2020-03-18 stsp *
2971 2ab43947 2020-03-18 stsp * (commit) D F (base_commit)
2972 2ab43947 2020-03-18 stsp * \ /
2973 2ab43947 2020-03-18 stsp * C E
2974 2ab43947 2020-03-18 stsp * \ /
2975 2ab43947 2020-03-18 stsp * B (yca)
2976 2ab43947 2020-03-18 stsp * |
2977 2ab43947 2020-03-18 stsp * A
2978 2ab43947 2020-03-18 stsp *
2979 2ab43947 2020-03-18 stsp * 'got update' only handles linear cases:
2980 2ab43947 2020-03-18 stsp * Update forwards in time: A (base/yca) - B - C - D (commit)
2981 2ab43947 2020-03-18 stsp * Update backwards in time: D (base) - C - B - A (commit/yca)
2982 2ab43947 2020-03-18 stsp */
2983 2ab43947 2020-03-18 stsp if (allow_forwards_in_time_only) {
2984 2ab43947 2020-03-18 stsp if (got_object_id_cmp(base_commit_id, yca_id) != 0)
2985 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2986 2ab43947 2020-03-18 stsp } else if (got_object_id_cmp(commit_id, yca_id) != 0 &&
2987 2ab43947 2020-03-18 stsp got_object_id_cmp(base_commit_id, yca_id) != 0)
2988 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2989