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