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>
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.
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.
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>
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>
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"
65 5c860e29 2018-03-12 stsp #ifndef nitems
66 5c860e29 2018-03-12 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
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;
73 99437157 2018-11-11 stsp catch_sigint(int signo)
75 99437157 2018-11-11 stsp sigint_received = 1;
79 99437157 2018-11-11 stsp catch_sigpipe(int signo)
81 99437157 2018-11-11 stsp sigpipe_received = 1;
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;
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);
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 *[]);
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, "" },
185 ce5b7c56 2019-07-09 stsp static void
186 6879ba42 2020-10-01 naddy list_commands(FILE *fp)
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);
195 6879ba42 2020-10-01 naddy fputc('\n', fp);
198 ff69268e 2020-12-13 stsp __dead static void
199 ff69268e 2020-12-13 stsp option_conflict(char a, char b)
201 ff69268e 2020-12-13 stsp errx(1, "-%c and -%c options are mutually exclusive", a, b);
205 5c860e29 2018-03-12 stsp main(int argc, char *argv[])
207 3e166534 2022-02-16 naddy const struct got_cmd *cmd;
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 }
216 289e3cbf 2019-02-04 stsp setlocale(LC_CTYPE, "");
218 6586ea88 2020-01-13 stsp while ((ch = getopt_long(argc, argv, "+hV", longopts, NULL)) != -1) {
219 5c860e29 2018-03-12 stsp switch (ch) {
227 6879ba42 2020-10-01 naddy usage(hflag, 1);
228 5c860e29 2018-03-12 stsp /* NOTREACHED */
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;
237 53ccebc2 2019-07-30 stsp if (Vflag) {
238 53ccebc2 2019-07-30 stsp got_version_print_str();
242 5c860e29 2018-03-12 stsp if (argc <= 0)
243 6879ba42 2020-10-01 naddy usage(hflag, hflag ? 0 : 1);
245 99437157 2018-11-11 stsp signal(SIGINT, catch_sigint);
246 99437157 2018-11-11 stsp signal(SIGPIPE, catch_sigpipe);
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;
251 5c860e29 2018-03-12 stsp cmd = &got_commands[i];
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)
258 3e166534 2022-02-16 naddy cmd->cmd_usage();
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);
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);
279 4ed7e80c 2018-05-20 stsp __dead static void
280 6879ba42 2020-10-01 naddy usage(int hflag, int status)
282 6879ba42 2020-10-01 naddy FILE *fp = (status == 0) ? stdout : stderr;
284 6a0a1bd4 2022-10-04 op fprintf(fp, "usage: %s [-hV] command [arg ...]\n",
285 53ccebc2 2019-07-30 stsp getprogname());
287 6879ba42 2020-10-01 naddy list_commands(fp);
288 6879ba42 2020-10-01 naddy exit(status);
291 0266afb7 2019-01-04 stsp static const struct got_error *
292 0ee7065d 2019-05-13 stsp get_editor(char **abspath)
294 0ee7065d 2019-05-13 stsp const struct got_error *err = NULL;
295 e2ba3d07 2019-05-13 stsp const char *editor;
297 8920fa04 2019-08-18 stsp *abspath = NULL;
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");
303 0ee7065d 2019-05-13 stsp if (editor) {
304 0ee7065d 2019-05-13 stsp err = got_path_find_prog(abspath, editor);
306 0ee7065d 2019-05-13 stsp return err;
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");
315 e2ba3d07 2019-05-13 stsp return NULL;
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)
322 163ce85a 2019-05-13 stsp const struct got_error *err;
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");
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);
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);
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);
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;
341 0266afb7 2019-01-04 stsp if (unveil(NULL, NULL) != 0)
342 638f9024 2019-05-13 stsp return got_error_from_errno("unveil");
344 0266afb7 2019-01-04 stsp return NULL;
347 3ce1b845 2019-07-15 stsp __dead static void
348 3ce1b845 2019-07-15 stsp usage_import(void)
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());
356 3ce1b845 2019-07-15 stsp spawn_editor(const char *editor, const char *file)
359 3ce1b845 2019-07-15 stsp sig_t sighup, sigint, sigquit;
360 3ce1b845 2019-07-15 stsp int st = -1;
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);
366 3ce1b845 2019-07-15 stsp switch (pid = fork()) {
368 3ce1b845 2019-07-15 stsp goto doneediting;
370 3ce1b845 2019-07-15 stsp execl(editor, editor, file, (char *)NULL);
371 3ce1b845 2019-07-15 stsp _exit(127);
374 3ce1b845 2019-07-15 stsp while (waitpid(pid, &st, 0) == -1)
375 3ce1b845 2019-07-15 stsp if (errno != EINTR)
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);
383 3ce1b845 2019-07-15 stsp if (!WIFEXITED(st)) {
384 3ce1b845 2019-07-15 stsp errno = EINTR;
388 3ce1b845 2019-07-15 stsp return WEXITSTATUS(st);
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)
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;
404 3ce1b845 2019-07-15 stsp *logmsg = NULL;
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);
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");
412 3ce1b845 2019-07-15 stsp if (stat(logmsg_path, &st2) == -1)
413 3ce1b845 2019-07-15 stsp return got_error_from_errno("stat");
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");
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.
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';
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");
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);
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';
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';
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");
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);
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);
479 3ce1b845 2019-07-15 stsp while (len > 0 && (*logmsg)[len - 1] == '\n') {
480 3ce1b845 2019-07-15 stsp (*logmsg)[len - 1] = '\0';
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");
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");
494 bfa12d5e 2020-09-26 stsp free(initial_content_stripped);
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");
499 3ce1b845 2019-07-15 stsp free(*logmsg);
500 3ce1b845 2019-07-15 stsp *logmsg = NULL;
502 3ce1b845 2019-07-15 stsp return err;
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)
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;
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");
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", "");
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);
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);
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);
537 59f86c76 2020-09-11 stsp free(*logmsg_path);
538 59f86c76 2020-09-11 stsp *logmsg_path = NULL;
540 3ce1b845 2019-07-15 stsp return err;
543 3ce1b845 2019-07-15 stsp static const struct got_error *
544 3ce1b845 2019-07-15 stsp import_progress(void *arg, const char *path)
546 3ce1b845 2019-07-15 stsp printf("A %s\n", path);
547 3ce1b845 2019-07-15 stsp return NULL;
550 cf208ddd 2022-07-19 op static const struct got_error *
551 1d918cf9 2022-02-06 op valid_author(const char *author)
553 cf208ddd 2022-07-19 op const char *email = author;
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
563 cf208ddd 2022-07-19 op while (*author && *author != '\n' && *author != '<' && *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 != '>')
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);
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)
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;
585 84792843 2019-08-09 stsp *author = NULL;
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);
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)
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;
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(
619 257add31 2020-09-09 stsp if (name && email) {
620 257add31 2020-09-09 stsp if (asprintf(author, "%s <%s>", name, email)
622 257add31 2020-09-09 stsp return got_error_from_errno("asprintf");
623 257add31 2020-09-09 stsp return NULL;
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);
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");
634 cf208ddd 2022-07-19 op err = valid_author(*author);
636 aba9c984 2019-09-08 stsp free(*author);
637 aba9c984 2019-09-08 stsp *author = NULL;
639 aba9c984 2019-09-08 stsp return err;
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)
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;
649 4d5ee956 2022-07-02 jrick *allowed_signers = NULL;
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);
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
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);
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");
674 4d5ee956 2022-07-02 jrick return NULL;
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)
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;
684 4d5ee956 2022-07-02 jrick *revoked_signers = NULL;
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);
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
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);
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");
709 4d5ee956 2022-07-02 jrick return NULL;
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)
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;
719 d68f2c0e 2022-07-05 jrick *signer_id = NULL;
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);
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
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);
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");
742 d68f2c0e 2022-07-05 jrick return NULL;
745 d68f2c0e 2022-07-05 jrick static const struct got_error *
746 c9956ddf 2019-09-08 stsp get_gitconfig_path(char **gitconfig_path)
748 c9956ddf 2019-09-08 stsp const char *homedir = getenv("HOME");
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");
756 c9956ddf 2019-09-08 stsp return NULL;
759 84792843 2019-08-09 stsp static const struct got_error *
760 3ce1b845 2019-07-15 stsp cmd_import(int argc, char *argv[])
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;
777 3ce1b845 2019-07-15 stsp TAILQ_INIT(&ignores);
779 6f319063 2022-10-27 stsp while ((ch = getopt(argc, argv, "b:I:m:r:")) != -1) {
780 3ce1b845 2019-07-15 stsp switch (ch) {
782 3ce1b845 2019-07-15 stsp branch_name = optarg;
785 6f319063 2022-10-27 stsp if (optarg[0] == '\0')
787 6f319063 2022-10-27 stsp error = got_pathlist_insert(&pe, &ignores, optarg,
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");
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",
808 b2b65d18 2019-08-22 stsp usage_import();
809 3ce1b845 2019-07-15 stsp /* NOTREACHED */
813 3ce1b845 2019-07-15 stsp argc -= optind;
814 3ce1b845 2019-07-15 stsp argv += optind;
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 "
819 3ce1b845 2019-07-15 stsp NULL) == -1)
820 3ce1b845 2019-07-15 stsp err(1, "pledge");
822 3ce1b845 2019-07-15 stsp if (argc != 1)
823 3ce1b845 2019-07-15 stsp usage_import();
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");
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);
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);
841 50b0790e 2020-09-11 stsp error = get_author(&author, repo, NULL);
843 aba9c984 2019-09-08 stsp return error;
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.
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);
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)
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));
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);
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)
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");
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]);
884 3ce1b845 2019-07-15 stsp got_path_strip_trailing_slashes(path_dir);
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.
890 3ce1b845 2019-07-15 stsp if (logmsg == NULL || strlen(logmsg) == 0) {
891 3ce1b845 2019-07-15 stsp error = get_editor(&editor);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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);
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;
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;
1001 93658fb9 2020-03-18 stsp __dead static void
1002 93658fb9 2020-03-18 stsp usage_clone(void)
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());
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;
1015 04d9a9ec 2020-09-24 stsp struct got_repository *repo;
1017 04d9a9ec 2020-09-24 stsp int create_configs;
1018 04d9a9ec 2020-09-24 stsp int configs_created;
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;
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);
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)
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;
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.
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);
1069 04d9a9ec 2020-09-24 stsp return err;
1070 04d9a9ec 2020-09-24 stsp a->configs_created = 1;
1073 68999b92 2020-03-18 stsp if (a->verbosity < 0)
1074 68999b92 2020-03-18 stsp return NULL;
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;
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);
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;
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;
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);
1122 531c3985 2020-03-18 stsp return NULL;
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)
1129 4ba14133 2020-03-20 stsp const struct got_error *err;
1130 04d9a9ec 2020-09-24 stsp struct got_reference *head_symref;
1132 04d9a9ec 2020-09-24 stsp err = got_ref_alloc_symref(&head_symref, refname, target_ref);
1134 4ba14133 2020-03-20 stsp return err;
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));
1141 04d9a9ec 2020-09-24 stsp got_ref_close(head_symref);
1142 4ba14133 2020-03-20 stsp return err;
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)
1149 41b0de12 2020-03-21 stsp const struct got_error *err;
1150 41b0de12 2020-03-21 stsp struct got_pathlist_entry *pe;
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;
1156 41b0de12 2020-03-21 stsp printf("%s: %s\n", refname, targetref);
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;
1164 41b0de12 2020-03-21 stsp err = got_object_id_str(&id_str, id);
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);
1171 41b0de12 2020-03-21 stsp return NULL;
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)
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;
1182 6338a6a1 2020-03-21 stsp err = got_object_id_str(&id_str, id);
1184 6338a6a1 2020-03-21 stsp return err;
1186 6338a6a1 2020-03-21 stsp err = got_ref_alloc(&ref, refname, id);
1188 6338a6a1 2020-03-21 stsp goto done;
1190 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
1191 6338a6a1 2020-03-21 stsp got_ref_close(ref);
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);
1196 6338a6a1 2020-03-21 stsp free(id_str);
1197 6338a6a1 2020-03-21 stsp return err;
1200 0e4002ca 2020-03-21 stsp static int
1201 0e4002ca 2020-03-21 stsp match_wanted_ref(const char *refname, const char *wanted_ref)
1203 0e4002ca 2020-03-21 stsp if (strncmp(refname, "refs/", 5) != 0)
1205 0e4002ca 2020-03-21 stsp refname += 5;
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.
1211 0e4002ca 2020-03-21 stsp if (strncmp(refname, "got/", 4) == 0)
1213 0e4002ca 2020-03-21 stsp if (strncmp(refname, "remotes/", 8) == 0)
1216 0e4002ca 2020-03-21 stsp if (strncmp(wanted_ref, "refs/", 5) == 0)
1217 0e4002ca 2020-03-21 stsp wanted_ref += 5;
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)))
1223 0e4002ca 2020-03-21 stsp /* Allow exact match. */
1224 0e4002ca 2020-03-21 stsp return (strcmp(refname, wanted_ref) == 0);
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)
1230 0e4002ca 2020-03-21 stsp struct got_pathlist_entry *pe;
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))
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)
1244 0e4002ca 2020-03-21 stsp const struct got_error *err;
1245 0e4002ca 2020-03-21 stsp char *remote_refname;
1247 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
1248 0e4002ca 2020-03-21 stsp refname += 5;
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");
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;
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)
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;
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) {
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;
1286 132af4a5 2021-01-05 stsp free(branches);
1287 132af4a5 2021-01-05 stsp branches = s;
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;
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) {
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;
1310 99495ddb 2021-01-10 stsp free(refs);
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;
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;
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"
1331 7c0b7f42 2020-09-24 stsp "\trepository \"%s\"\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;
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;
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;
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)
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;
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;
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;
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;
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;
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) {
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;
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;
1422 132af4a5 2021-01-05 stsp free(branches);
1423 132af4a5 2021-01-05 stsp branches = s;
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.
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;
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;
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;
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) {
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;
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;
1473 99495ddb 2021-01-10 stsp free(refs);
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"
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;
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;
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;
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)
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;
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.
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;
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;
1526 04d9a9ec 2020-09-24 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
1529 04d9a9ec 2020-09-24 stsp default_branch = target;
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);
1539 04d9a9ec 2020-09-24 stsp return err;
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);
1546 04d9a9ec 2020-09-24 stsp static const struct got_error *
1547 93658fb9 2020-03-18 stsp cmd_clone(int argc, char *argv[])
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;
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);
1571 6f319063 2022-10-27 stsp while ((ch = getopt(argc, argv, "ab:lmqR:v")) != -1) {
1572 93658fb9 2020-03-18 stsp switch (ch) {
1574 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
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;
1583 41b0de12 2020-03-21 stsp list_refs_only = 1;
1586 469dd726 2020-03-20 stsp mirror_references = 1;
1589 68999b92 2020-03-18 stsp verbosity = -1;
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;
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++;
1604 93658fb9 2020-03-18 stsp usage_clone();
1608 93658fb9 2020-03-18 stsp argc -= optind;
1609 93658fb9 2020-03-18 stsp argv += optind;
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');
1624 93658fb9 2020-03-18 stsp uri = argv[0];
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];
1631 93658fb9 2020-03-18 stsp usage_clone();
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;
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;
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");
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");
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;
1663 39c64a6a 2020-03-18 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
1664 39c64a6a 2020-03-18 stsp goto done;
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;
1671 bb64b798 2020-03-18 stsp repo_path = default_destdir;
1673 bb64b798 2020-03-18 stsp repo_path = dirname;
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;
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;
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;
1696 f79e6490 2020-04-19 stsp if (verbosity >= 0)
1697 0deb9607 2022-11-18 op printf("Connecting to %s\n", git_url);
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;
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;
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;
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;
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;
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);
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;
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;
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;
1778 469dd726 2020-03-20 stsp if (mirror_references)
1781 7ebc0570 2020-03-18 stsp if (strncmp("refs/heads/", refname, 11) != 0)
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;
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;
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;
1803 d9b4d0c0 2020-03-18 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
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;
1812 d9b4d0c0 2020-03-18 stsp goto done;
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;
1820 f298ae0f 2020-03-25 stsp if (mirror_references)
1823 f298ae0f 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
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;
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;
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;
1847 f298ae0f 2020-03-25 stsp goto done;
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;
1857 4ba14133 2020-03-20 stsp if (pe == NULL) {
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.
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;
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;
1873 4ba14133 2020-03-20 stsp goto done;
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;
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;
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);
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;
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");
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;
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);
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);
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;
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)
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;
1953 7848a0e1 2020-03-19 stsp err = got_object_id_str(&new_id_str, new_id);
1955 7848a0e1 2020-03-19 stsp goto done;
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);
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);
1968 db6d8ad8 2020-03-21 stsp goto done;
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));
1977 e8a967e0 2020-03-21 stsp err = got_ref_change_symref_to_ref(ref, new_id);
1979 7848a0e1 2020-03-19 stsp goto done;
1980 e8a967e0 2020-03-21 stsp err = got_ref_write(ref, repo);
1982 e8a967e0 2020-03-21 stsp goto done;
1984 7848a0e1 2020-03-19 stsp err = got_ref_resolve(&old_id, repo, ref);
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;
1990 6338a6a1 2020-03-21 stsp err = got_ref_change_ref(ref, new_id);
1992 6338a6a1 2020-03-21 stsp goto done;
1993 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
1995 6338a6a1 2020-03-21 stsp goto done;
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);
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;
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)
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;
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);
2021 bcf34b0e 2020-03-26 stsp goto done;
2023 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
2025 bcf34b0e 2020-03-26 stsp goto done;
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));
2032 bcf34b0e 2020-03-26 stsp symref_is_locked = 1;
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;
2038 bcf34b0e 2020-03-26 stsp err = got_ref_change_symref(symref,
2039 bcf34b0e 2020-03-26 stsp got_ref_get_name(target_ref));
2041 bcf34b0e 2020-03-26 stsp goto done;
2043 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
2045 bcf34b0e 2020-03-26 stsp goto done;
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));
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;
2058 f1bcca34 2020-03-25 stsp got_ref_close(symref);
2059 f1bcca34 2020-03-25 stsp return err;
2062 2ab43947 2020-03-18 stsp __dead static void
2063 7848a0e1 2020-03-19 stsp usage_fetch(void)
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());
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)
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;
2079 3789fd73 2020-03-26 stsp if (got_ref_is_symbolic(ref)) {
2080 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
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));
2089 3789fd73 2020-03-26 stsp err = got_ref_resolve(&id, repo, ref);
2091 3789fd73 2020-03-26 stsp return err;
2092 3789fd73 2020-03-26 stsp err = got_object_id_str(&id_str, id);
2094 3789fd73 2020-03-26 stsp goto done;
2096 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
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);
2106 3789fd73 2020-03-26 stsp free(id_str);
2107 3789fd73 2020-03-26 stsp return NULL;
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)
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;
2123 d9dff0e5 2020-12-26 stsp TAILQ_INIT(&my_refs);
2125 3789fd73 2020-03-26 stsp if (asprintf(&remote_namespace, "refs/remotes/%s/", remote->name)
2127 3789fd73 2020-03-26 stsp return got_error_from_errno("asprintf");
2129 f21ec2f0 2020-03-21 stsp err = got_ref_list(&my_refs, repo, NULL, got_ref_cmp_by_name, NULL);
2131 3789fd73 2020-03-26 stsp goto done;
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;
2137 1b796c3f 2021-09-11 stsp if (remote->mirror_references) {
2138 1b796c3f 2021-09-11 stsp their_refname = refname;
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)
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;
2150 3789fd73 2020-03-26 stsp } else if (strncmp(refname, "refs/tags/", 10) != 0)
2153 1b796c3f 2021-09-11 stsp their_refname = local_refname;
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)
2160 f21ec2f0 2020-03-21 stsp if (pe != NULL)
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)
2167 3789fd73 2020-03-26 stsp if (pe != NULL)
2170 3789fd73 2020-03-26 stsp err = delete_missing_ref(re->ref, verbosity, repo);
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)
2180 3789fd73 2020-03-26 stsp free(local_refname);
2181 3789fd73 2020-03-26 stsp local_refname = NULL;
2184 3789fd73 2020-03-26 stsp err = delete_missing_ref(ref, verbosity, repo);
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;
2194 3789fd73 2020-03-26 stsp free(local_refname);
2195 3789fd73 2020-03-26 stsp local_refname = NULL;
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;
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)
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;
2213 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
2214 0e4002ca 2020-03-21 stsp refname += 5;
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");
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);
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);
2233 0e4002ca 2020-03-21 stsp free(remote_refname);
2234 161728eb 2021-07-24 stsp return err;
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)
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;
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);
2248 161728eb 2021-07-24 stsp err = got_ref_resolve(&id, repo, ref);
2250 161728eb 2021-07-24 stsp goto done;
2251 161728eb 2021-07-24 stsp err = got_object_id_str(&id_str, id);
2253 161728eb 2021-07-24 stsp goto done;
2254 161728eb 2021-07-24 stsp target = id_str;
2257 161728eb 2021-07-24 stsp err = got_ref_delete(ref, repo);
2259 161728eb 2021-07-24 stsp goto done;
2261 161728eb 2021-07-24 stsp printf("Deleted %s: %s\n", got_ref_get_name(ref), target);
2264 161728eb 2021-07-24 stsp free(id_str);
2265 f21ec2f0 2020-03-21 stsp return err;
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)
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;
2276 161728eb 2021-07-24 stsp TAILQ_INIT(&refs);
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;
2282 161728eb 2021-07-24 stsp err = got_ref_list(&refs, repo, prefix, got_ref_cmp_by_name, NULL);
2284 161728eb 2021-07-24 stsp goto done;
2286 161728eb 2021-07-24 stsp TAILQ_FOREACH(re, &refs, entry)
2287 161728eb 2021-07-24 stsp delete_ref(repo, re->ref);
2289 161728eb 2021-07-24 stsp got_ref_list_free(&refs);
2290 161728eb 2021-07-24 stsp return err;
2293 161728eb 2021-07-24 stsp static const struct got_error *
2294 7848a0e1 2020-03-19 stsp cmd_fetch(int argc, char *argv[])
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;
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);
2322 6f319063 2022-10-27 stsp while ((ch = getopt(argc, argv, "ab:dlqR:r:tvX")) != -1) {
2323 7848a0e1 2020-03-19 stsp switch (ch) {
2325 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
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;
2334 f21ec2f0 2020-03-21 stsp delete_refs = 1;
2337 41b0de12 2020-03-21 stsp list_refs_only = 1;
2340 6f319063 2022-10-27 stsp verbosity = -1;
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;
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",
2353 7848a0e1 2020-03-19 stsp got_path_strip_trailing_slashes(repo_path);
2356 db6d8ad8 2020-03-21 stsp replace_tags = 1;
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++;
2365 161728eb 2021-07-24 stsp delete_remote = 1;
2368 7848a0e1 2020-03-19 stsp usage_fetch();
2372 7848a0e1 2020-03-19 stsp argc -= optind;
2373 7848a0e1 2020-03-19 stsp argv += optind;
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');
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');
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];
2407 7848a0e1 2020-03-19 stsp usage_fetch();
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;
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;
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;
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;
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;
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;
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 */
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];
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];
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];
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;
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);
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);
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;
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");
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");
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;
2528 7848a0e1 2020-03-19 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
2529 7848a0e1 2020-03-19 stsp goto done;
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;
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;
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);
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;
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;
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;
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;
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;
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;
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,
2608 7848a0e1 2020-03-19 stsp if (error)
2609 7848a0e1 2020-03-19 stsp goto done;
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;
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;
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;
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;
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,
2653 2ec30c80 2020-03-20 stsp if (error)
2654 2ec30c80 2020-03-20 stsp goto done;
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);
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;
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;
2678 f1bcca34 2020-03-25 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
2681 f1bcca34 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
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;
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;
2696 f1bcca34 2020-03-25 stsp error = got_ref_open(&target_ref, repo, remote_target,
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;
2705 f1bcca34 2020-03-25 stsp goto done;
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;
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");
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;
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;
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);
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);
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;
2763 7848a0e1 2020-03-19 stsp __dead static void
2764 2ab43947 2020-03-18 stsp usage_checkout(void)
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());
2772 2ab43947 2020-03-18 stsp static void
2773 2ab43947 2020-03-18 stsp show_worktree_base_ref_warning(void)
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());
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;
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)
2791 2ab43947 2020-03-18 stsp struct got_checkout_progress_arg *a = arg;
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;
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;
2802 2ab43947 2020-03-18 stsp while (path[0] == '/')
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);
2808 2ab43947 2020-03-18 stsp return NULL;
2811 2ab43947 2020-03-18 stsp static const struct got_error *
2812 2ab43947 2020-03-18 stsp check_cancelled(void *arg)
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;
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)
2824 2ab43947 2020-03-18 stsp const struct got_error *err = NULL;
2825 2ab43947 2020-03-18 stsp struct got_object_id *yca_id;
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);
2830 2ab43947 2020-03-18 stsp return err;
2832 2ab43947 2020-03-18 stsp if (yca_id == NULL)
2833 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
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.
2839 2ab43947 2020-03-18 stsp * Non-linear situations such as this require a rebase:
2841 2ab43947 2020-03-18 stsp * (commit) D F (base_commit)
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)
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);
2860 2ab43947 2020-03-18 stsp free(yca_id);
2861 2ab43947 2020-03-18 stsp return NULL;
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)
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;
2874 2ab43947 2020-03-18 stsp err = got_ref_resolve(&head_commit_id, repo, head_ref);
2876 2ab43947 2020-03-18 stsp goto done;
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;
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;
2887 2ab43947 2020-03-18 stsp err = got_commit_graph_open(&graph, "/", 1);
2889 2ab43947 2020-03-18 stsp goto done;
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);
2894 2ab43947 2020-03-18 stsp goto done;
2896 2ab43947 2020-03-18 stsp for (;;) {
2897 d9787ed8 2022-09-10 op struct got_object_id id;
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;
2907 d9787ed8 2022-09-10 op if (yca_id && got_object_id_cmp(&id, yca_id) == 0)
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;
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;
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)
2926 4b6c9460 2020-03-05 stsp static char msg[512];
2927 4b6c9460 2020-03-05 stsp const char *branch_name;
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);
2932 4b6c9460 2020-03-05 stsp branch_name = got_ref_get_name(ref);
2934 4b6c9460 2020-03-05 stsp if (strncmp("refs/heads/", branch_name, 11) == 0)
2935 4b6c9460 2020-03-05 stsp branch_name += 11;
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);
2944 4b6c9460 2020-03-05 stsp return got_error_msg(GOT_ERR_ANCESTRY, msg);
2947 4b6c9460 2020-03-05 stsp static const struct got_error *
2948 c09a553d 2018-03-12 stsp cmd_checkout(int argc, char *argv[])
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;
2966 f2ea84fa 2019-07-27 stsp TAILQ_INIT(&paths);
2968 4ad4a1ec 2021-09-13 tracey while ((ch = getopt(argc, argv, "b:c:Ep:q")) != -1) {
2969 0bb8a95e 2018-03-12 stsp switch (ch) {
2971 08573d5b 2019-05-14 stsp branch_name = optarg;
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");
2979 bb51a5b4 2020-01-13 stsp allow_nonempty = 1;
2982 0bb8a95e 2018-03-12 stsp path_prefix = optarg;
2984 4ad4a1ec 2021-09-13 tracey case 'q':
2985 4ad4a1ec 2021-09-13 tracey verbosity = -1;
2988 2deda0b9 2019-03-07 stsp usage_checkout();
2989 0bb8a95e 2018-03-12 stsp /* NOTREACHED */
2993 0bb8a95e 2018-03-12 stsp argc -= optind;
2994 0bb8a95e 2018-03-12 stsp argv += optind;
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");
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;
3012 c47340da 2020-09-20 stsp if (path_prefix[0])
3013 f0207f6a 2020-10-19 stsp path = path_prefix;
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;
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;
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",
3039 b4b3a7dd 2019-07-22 stsp goto done;
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;
3048 c09a553d 2018-03-12 stsp usage_checkout();
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);
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;
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;
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);