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