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 5822e79e 2023-02-23 op #include <sha2.h>
33 99437157 2018-11-11 stsp #include <signal.h>
34 5c860e29 2018-03-12 stsp #include <stdio.h>
35 5c860e29 2018-03-12 stsp #include <stdlib.h>
36 5c860e29 2018-03-12 stsp #include <string.h>
37 5c860e29 2018-03-12 stsp #include <unistd.h>
38 c09a553d 2018-03-12 stsp #include <libgen.h>
39 c0768b0f 2018-06-10 stsp #include <time.h>
40 33ad4cbe 2019-05-12 jcs #include <paths.h>
41 6841bf13 2019-11-29 kn #include <regex.h>
42 83cd27f8 2020-01-13 stsp #include <getopt.h>
43 d2cdc636 2020-03-18 stsp #include <util.h>
45 53ccebc2 2019-07-30 stsp #include "got_version.h"
46 f42b1b34 2018-03-12 stsp #include "got_error.h"
47 f42b1b34 2018-03-12 stsp #include "got_object.h"
48 5261c201 2018-04-01 stsp #include "got_reference.h"
49 f42b1b34 2018-03-12 stsp #include "got_repository.h"
50 1dd54920 2019-05-11 stsp #include "got_path.h"
51 e6209546 2019-08-22 stsp #include "got_cancel.h"
52 c09a553d 2018-03-12 stsp #include "got_worktree.h"
53 79109fed 2018-03-27 stsp #include "got_diff.h"
54 372ccdbb 2018-06-10 stsp #include "got_commit_graph.h"
55 6f23baec 2020-03-18 stsp #include "got_fetch.h"
56 f8a36e22 2021-08-26 stsp #include "got_send.h"
57 404c43c4 2018-06-21 stsp #include "got_blame.h"
58 63219cd2 2019-01-04 stsp #include "got_privsep.h"
59 793c30b5 2019-05-13 stsp #include "got_opentemp.h"
60 50b0790e 2020-09-11 stsp #include "got_gotconfig.h"
61 d65a88a2 2021-09-05 stsp #include "got_dial.h"
62 e9ce266e 2022-03-07 op #include "got_patch.h"
63 4d5ee956 2022-07-02 jrick #include "got_sigs.h"
64 4d5ee956 2022-07-02 jrick #include "got_date.h"
65 fd7552d2 2023-07-17 mark #include "got_keyword.h"
67 5c860e29 2018-03-12 stsp #ifndef nitems
68 5c860e29 2018-03-12 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
71 9c177e8d 2024-03-18 op #ifndef GOT_DEFAULT_EDITOR
72 9c177e8d 2024-03-18 op #define GOT_DEFAULT_EDITOR "/usr/bin/vi"
75 99437157 2018-11-11 stsp static volatile sig_atomic_t sigint_received;
76 99437157 2018-11-11 stsp static volatile sig_atomic_t sigpipe_received;
79 99437157 2018-11-11 stsp catch_sigint(int signo)
81 99437157 2018-11-11 stsp sigint_received = 1;
85 99437157 2018-11-11 stsp catch_sigpipe(int signo)
87 99437157 2018-11-11 stsp sigpipe_received = 1;
91 8cfb4057 2019-07-09 stsp struct got_cmd {
92 820059fa 2020-09-25 stsp const char *cmd_name;
93 d7d4f210 2018-03-12 stsp const struct got_error *(*cmd_main)(int, char *[]);
94 1b6b95a8 2018-03-12 stsp void (*cmd_usage)(void);
95 97b3a7be 2019-07-09 stsp const char *cmd_alias;
98 6879ba42 2020-10-01 naddy __dead static void usage(int, int);
99 433eb77d 2024-06-03 stsp __dead static void usage_init(void);
100 3ce1b845 2019-07-15 stsp __dead static void usage_import(void);
101 93658fb9 2020-03-18 stsp __dead static void usage_clone(void);
102 7848a0e1 2020-03-19 stsp __dead static void usage_fetch(void);
103 2ab43947 2020-03-18 stsp __dead static void usage_checkout(void);
104 507dc3bb 2018-12-29 stsp __dead static void usage_update(void);
105 4ed7e80c 2018-05-20 stsp __dead static void usage_log(void);
106 4ed7e80c 2018-05-20 stsp __dead static void usage_diff(void);
107 404c43c4 2018-06-21 stsp __dead static void usage_blame(void);
108 5de5890b 2018-10-18 stsp __dead static void usage_tree(void);
109 6bad629b 2019-02-04 stsp __dead static void usage_status(void);
110 d0eebce4 2019-03-11 stsp __dead static void usage_ref(void);
111 4e759de4 2019-06-26 stsp __dead static void usage_branch(void);
112 8e7bd50a 2019-08-22 stsp __dead static void usage_tag(void);
113 d00136be 2019-03-26 stsp __dead static void usage_add(void);
114 648e4ef7 2019-07-09 stsp __dead static void usage_remove(void);
115 e9ce266e 2022-03-07 op __dead static void usage_patch(void);
116 a129376b 2019-03-28 stsp __dead static void usage_revert(void);
117 c4296144 2019-05-09 stsp __dead static void usage_commit(void);
118 f8a36e22 2021-08-26 stsp __dead static void usage_send(void);
119 234035bc 2019-06-01 stsp __dead static void usage_cherrypick(void);
120 5ef14e63 2019-06-02 stsp __dead static void usage_backout(void);
121 818c7501 2019-07-11 stsp __dead static void usage_rebase(void);
122 0ebf8283 2019-07-24 stsp __dead static void usage_histedit(void);
123 2822a352 2019-10-15 stsp __dead static void usage_integrate(void);
124 f259c4c1 2021-09-24 stsp __dead static void usage_merge(void);
125 715dc77e 2019-08-03 stsp __dead static void usage_stage(void);
126 ad493afc 2019-08-03 stsp __dead static void usage_unstage(void);
127 01073a5d 2019-08-22 stsp __dead static void usage_cat(void);
128 b2118c49 2020-07-28 stsp __dead static void usage_info(void);
130 433eb77d 2024-06-03 stsp static const struct got_error* cmd_init(int, char *[]);
131 3ce1b845 2019-07-15 stsp static const struct got_error* cmd_import(int, char *[]);
132 93658fb9 2020-03-18 stsp static const struct got_error* cmd_clone(int, char *[]);
133 7848a0e1 2020-03-19 stsp static const struct got_error* cmd_fetch(int, char *[]);
134 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_checkout(int, char *[]);
135 507dc3bb 2018-12-29 stsp static const struct got_error* cmd_update(int, char *[]);
136 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_log(int, char *[]);
137 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_diff(int, char *[]);
138 404c43c4 2018-06-21 stsp static const struct got_error* cmd_blame(int, char *[]);
139 5de5890b 2018-10-18 stsp static const struct got_error* cmd_tree(int, char *[]);
140 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_status(int, char *[]);
141 d0eebce4 2019-03-11 stsp static const struct got_error* cmd_ref(int, char *[]);
142 4e759de4 2019-06-26 stsp static const struct got_error* cmd_branch(int, char *[]);
143 8e7bd50a 2019-08-22 stsp static const struct got_error* cmd_tag(int, char *[]);
144 d00136be 2019-03-26 stsp static const struct got_error* cmd_add(int, char *[]);
145 648e4ef7 2019-07-09 stsp static const struct got_error* cmd_remove(int, char *[]);
146 e9ce266e 2022-03-07 op static const struct got_error* cmd_patch(int, char *[]);
147 a129376b 2019-03-28 stsp static const struct got_error* cmd_revert(int, char *[]);
148 c4296144 2019-05-09 stsp static const struct got_error* cmd_commit(int, char *[]);
149 f8a36e22 2021-08-26 stsp static const struct got_error* cmd_send(int, char *[]);
150 234035bc 2019-06-01 stsp static const struct got_error* cmd_cherrypick(int, char *[]);
151 5ef14e63 2019-06-02 stsp static const struct got_error* cmd_backout(int, char *[]);
152 818c7501 2019-07-11 stsp static const struct got_error* cmd_rebase(int, char *[]);
153 0ebf8283 2019-07-24 stsp static const struct got_error* cmd_histedit(int, char *[]);
154 2822a352 2019-10-15 stsp static const struct got_error* cmd_integrate(int, char *[]);
155 f259c4c1 2021-09-24 stsp static const struct got_error* cmd_merge(int, char *[]);
156 715dc77e 2019-08-03 stsp static const struct got_error* cmd_stage(int, char *[]);
157 ad493afc 2019-08-03 stsp static const struct got_error* cmd_unstage(int, char *[]);
158 01073a5d 2019-08-22 stsp static const struct got_error* cmd_cat(int, char *[]);
159 b2118c49 2020-07-28 stsp static const struct got_error* cmd_info(int, char *[]);
161 3e166534 2022-02-16 naddy static const struct got_cmd got_commands[] = {
162 433eb77d 2024-06-03 stsp { "init", cmd_init, usage_init, "" },
163 bc26cce8 2019-08-04 stsp { "import", cmd_import, usage_import, "im" },
164 93658fb9 2020-03-18 stsp { "clone", cmd_clone, usage_clone, "cl" },
165 7848a0e1 2020-03-19 stsp { "fetch", cmd_fetch, usage_fetch, "fe" },
166 2ab43947 2020-03-18 stsp { "checkout", cmd_checkout, usage_checkout, "co" },
167 97b3a7be 2019-07-09 stsp { "update", cmd_update, usage_update, "up" },
168 97b3a7be 2019-07-09 stsp { "log", cmd_log, usage_log, "" },
169 bc26cce8 2019-08-04 stsp { "diff", cmd_diff, usage_diff, "di" },
170 bc26cce8 2019-08-04 stsp { "blame", cmd_blame, usage_blame, "bl" },
171 bc26cce8 2019-08-04 stsp { "tree", cmd_tree, usage_tree, "tr" },
172 97b3a7be 2019-07-09 stsp { "status", cmd_status, usage_status, "st" },
173 97b3a7be 2019-07-09 stsp { "ref", cmd_ref, usage_ref, "" },
174 97b3a7be 2019-07-09 stsp { "branch", cmd_branch, usage_branch, "br" },
175 8e7bd50a 2019-08-22 stsp { "tag", cmd_tag, usage_tag, "" },
176 97b3a7be 2019-07-09 stsp { "add", cmd_add, usage_add, "" },
177 648e4ef7 2019-07-09 stsp { "remove", cmd_remove, usage_remove, "rm" },
178 e9ce266e 2022-03-07 op { "patch", cmd_patch, usage_patch, "pa" },
179 97b3a7be 2019-07-09 stsp { "revert", cmd_revert, usage_revert, "rv" },
180 97b3a7be 2019-07-09 stsp { "commit", cmd_commit, usage_commit, "ci" },
181 f8a36e22 2021-08-26 stsp { "send", cmd_send, usage_send, "se" },
182 016477fd 2019-07-09 stsp { "cherrypick", cmd_cherrypick, usage_cherrypick, "cy" },
183 97b3a7be 2019-07-09 stsp { "backout", cmd_backout, usage_backout, "bo" },
184 818c7501 2019-07-11 stsp { "rebase", cmd_rebase, usage_rebase, "rb" },
185 0ebf8283 2019-07-24 stsp { "histedit", cmd_histedit, usage_histedit, "he" },
186 2822a352 2019-10-15 stsp { "integrate", cmd_integrate, usage_integrate,"ig" },
187 f259c4c1 2021-09-24 stsp { "merge", cmd_merge, usage_merge, "mg" },
188 715dc77e 2019-08-03 stsp { "stage", cmd_stage, usage_stage, "sg" },
189 ad493afc 2019-08-03 stsp { "unstage", cmd_unstage, usage_unstage, "ug" },
190 01073a5d 2019-08-22 stsp { "cat", cmd_cat, usage_cat, "" },
191 b2118c49 2020-07-28 stsp { "info", cmd_info, usage_info, "" },
194 ce5b7c56 2019-07-09 stsp static void
195 6879ba42 2020-10-01 naddy list_commands(FILE *fp)
199 6879ba42 2020-10-01 naddy fprintf(fp, "commands:");
200 ce5b7c56 2019-07-09 stsp for (i = 0; i < nitems(got_commands); i++) {
201 3e166534 2022-02-16 naddy const struct got_cmd *cmd = &got_commands[i];
202 6879ba42 2020-10-01 naddy fprintf(fp, " %s", cmd->cmd_name);
204 6879ba42 2020-10-01 naddy fputc('\n', fp);
207 ff69268e 2020-12-13 stsp __dead static void
208 ff69268e 2020-12-13 stsp option_conflict(char a, char b)
210 ff69268e 2020-12-13 stsp errx(1, "-%c and -%c options are mutually exclusive", a, b);
214 5c860e29 2018-03-12 stsp main(int argc, char *argv[])
216 3e166534 2022-02-16 naddy const struct got_cmd *cmd;
219 53ccebc2 2019-07-30 stsp int hflag = 0, Vflag = 0;
220 3e166534 2022-02-16 naddy static const struct option longopts[] = {
221 62d463ca 2020-10-20 naddy { "version", no_argument, NULL, 'V' },
222 62d463ca 2020-10-20 naddy { NULL, 0, NULL, 0 }
225 289e3cbf 2019-02-04 stsp setlocale(LC_CTYPE, "");
227 6586ea88 2020-01-13 stsp while ((ch = getopt_long(argc, argv, "+hV", longopts, NULL)) != -1) {
228 5c860e29 2018-03-12 stsp switch (ch) {
236 6879ba42 2020-10-01 naddy usage(hflag, 1);
237 5c860e29 2018-03-12 stsp /* NOTREACHED */
241 5c860e29 2018-03-12 stsp argc -= optind;
242 5c860e29 2018-03-12 stsp argv += optind;
243 9814e6a3 2020-09-27 naddy optind = 1;
244 9814e6a3 2020-09-27 naddy optreset = 1;
246 53ccebc2 2019-07-30 stsp if (Vflag) {
247 53ccebc2 2019-07-30 stsp got_version_print_str();
251 5c860e29 2018-03-12 stsp if (argc <= 0)
252 6879ba42 2020-10-01 naddy usage(hflag, hflag ? 0 : 1);
254 99437157 2018-11-11 stsp signal(SIGINT, catch_sigint);
255 99437157 2018-11-11 stsp signal(SIGPIPE, catch_sigpipe);
257 5c860e29 2018-03-12 stsp for (i = 0; i < nitems(got_commands); i++) {
258 d7d4f210 2018-03-12 stsp const struct got_error *error;
260 5c860e29 2018-03-12 stsp cmd = &got_commands[i];
262 97b3a7be 2019-07-09 stsp if (strcmp(cmd->cmd_name, argv[0]) != 0 &&
263 97b3a7be 2019-07-09 stsp strcmp(cmd->cmd_alias, argv[0]) != 0)
267 3e166534 2022-02-16 naddy cmd->cmd_usage();
269 3e166534 2022-02-16 naddy error = cmd->cmd_main(argc, argv);
270 f8afbdc8 2019-11-08 stsp if (error && error->code != GOT_ERR_CANCELLED &&
271 f8afbdc8 2019-11-08 stsp error->code != GOT_ERR_PRIVSEP_EXIT &&
272 f8afbdc8 2019-11-08 stsp !(sigpipe_received &&
273 70015d7a 2019-11-08 stsp error->code == GOT_ERR_ERRNO && errno == EPIPE) &&
274 70015d7a 2019-11-08 stsp !(sigint_received &&
275 70015d7a 2019-11-08 stsp error->code == GOT_ERR_ERRNO && errno == EINTR)) {
276 8cdd2318 2023-04-13 op fflush(stdout);
277 d7d4f210 2018-03-12 stsp fprintf(stderr, "%s: %s\n", getprogname(), error->msg);
284 20ecf764 2018-03-12 stsp fprintf(stderr, "%s: unknown command '%s'\n", getprogname(), argv[0]);
285 6879ba42 2020-10-01 naddy list_commands(stderr);
289 4ed7e80c 2018-05-20 stsp __dead static void
290 6879ba42 2020-10-01 naddy usage(int hflag, int status)
292 6879ba42 2020-10-01 naddy FILE *fp = (status == 0) ? stdout : stderr;
294 6a0a1bd4 2022-10-04 op fprintf(fp, "usage: %s [-hV] command [arg ...]\n",
295 53ccebc2 2019-07-30 stsp getprogname());
297 6879ba42 2020-10-01 naddy list_commands(fp);
298 6879ba42 2020-10-01 naddy exit(status);
301 0266afb7 2019-01-04 stsp static const struct got_error *
302 0ee7065d 2019-05-13 stsp get_editor(char **abspath)
304 0ee7065d 2019-05-13 stsp const struct got_error *err = NULL;
305 e2ba3d07 2019-05-13 stsp const char *editor;
307 8920fa04 2019-08-18 stsp *abspath = NULL;
309 e2ba3d07 2019-05-13 stsp editor = getenv("VISUAL");
310 e2ba3d07 2019-05-13 stsp if (editor == NULL)
311 e2ba3d07 2019-05-13 stsp editor = getenv("EDITOR");
313 0ee7065d 2019-05-13 stsp if (editor) {
314 0ee7065d 2019-05-13 stsp err = got_path_find_prog(abspath, editor);
316 0ee7065d 2019-05-13 stsp return err;
319 0ee7065d 2019-05-13 stsp if (*abspath == NULL) {
320 9c177e8d 2024-03-18 op *abspath = strdup(GOT_DEFAULT_EDITOR);
321 0ee7065d 2019-05-13 stsp if (*abspath == NULL)
322 0ee7065d 2019-05-13 stsp return got_error_from_errno("strdup");
325 e2ba3d07 2019-05-13 stsp return NULL;
328 e2ba3d07 2019-05-13 stsp static const struct got_error *
329 d0eebce4 2019-03-11 stsp apply_unveil(const char *repo_path, int repo_read_only,
330 c530dc23 2019-07-23 stsp const char *worktree_path)
332 163ce85a 2019-05-13 stsp const struct got_error *err;
334 37c06ea4 2019-07-15 stsp #ifdef PROFILE
335 37c06ea4 2019-07-15 stsp if (unveil("gmon.out", "rwc") != 0)
336 37c06ea4 2019-07-15 stsp return got_error_from_errno2("unveil", "gmon.out");
338 d0eebce4 2019-03-11 stsp if (repo_path && unveil(repo_path, repo_read_only ? "r" : "rwc") != 0)
339 638f9024 2019-05-13 stsp return got_error_from_errno2("unveil", repo_path);
341 0266afb7 2019-01-04 stsp if (worktree_path && unveil(worktree_path, "rwc") != 0)
342 638f9024 2019-05-13 stsp return got_error_from_errno2("unveil", worktree_path);
344 bb63914a 2020-02-17 stsp if (unveil(GOT_TMPDIR_STR, "rwc") != 0)
345 bb63914a 2020-02-17 stsp return got_error_from_errno2("unveil", GOT_TMPDIR_STR);
347 163ce85a 2019-05-13 stsp err = got_privsep_unveil_exec_helpers();
348 163ce85a 2019-05-13 stsp if (err != NULL)
349 163ce85a 2019-05-13 stsp return err;
351 0266afb7 2019-01-04 stsp if (unveil(NULL, NULL) != 0)
352 638f9024 2019-05-13 stsp return got_error_from_errno("unveil");
354 0266afb7 2019-01-04 stsp return NULL;
357 3ce1b845 2019-07-15 stsp __dead static void
358 433eb77d 2024-06-03 stsp usage_init(void)
360 433eb77d 2024-06-03 stsp fprintf(stderr, "usage: %s init [-b branch] repository-path\n",
361 433eb77d 2024-06-03 stsp getprogname());
365 433eb77d 2024-06-03 stsp static const struct got_error *
366 433eb77d 2024-06-03 stsp cmd_init(int argc, char *argv[])
368 433eb77d 2024-06-03 stsp const struct got_error *error = NULL;
369 433eb77d 2024-06-03 stsp const char *head_name = NULL;
370 433eb77d 2024-06-03 stsp char *repo_path = NULL;
373 433eb77d 2024-06-03 stsp while ((ch = getopt(argc, argv, "b:")) != -1) {
374 433eb77d 2024-06-03 stsp switch (ch) {
376 433eb77d 2024-06-03 stsp head_name = optarg;
379 433eb77d 2024-06-03 stsp usage_init();
380 433eb77d 2024-06-03 stsp /* NOTREACHED */
384 433eb77d 2024-06-03 stsp argc -= optind;
385 433eb77d 2024-06-03 stsp argv += optind;
387 433eb77d 2024-06-03 stsp #ifndef PROFILE
388 433eb77d 2024-06-03 stsp if (pledge("stdio rpath wpath cpath unveil", NULL) == -1)
389 433eb77d 2024-06-03 stsp err(1, "pledge");
391 433eb77d 2024-06-03 stsp if (argc != 1)
392 433eb77d 2024-06-03 stsp usage_init();
394 433eb77d 2024-06-03 stsp repo_path = strdup(argv[0]);
395 433eb77d 2024-06-03 stsp if (repo_path == NULL)
396 433eb77d 2024-06-03 stsp return got_error_from_errno("strdup");
398 433eb77d 2024-06-03 stsp got_path_strip_trailing_slashes(repo_path);
400 433eb77d 2024-06-03 stsp error = got_path_mkdir(repo_path);
401 433eb77d 2024-06-03 stsp if (error &&
402 433eb77d 2024-06-03 stsp !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
405 433eb77d 2024-06-03 stsp error = apply_unveil(repo_path, 0, NULL);
409 433eb77d 2024-06-03 stsp error = got_repo_init(repo_path, head_name);
411 433eb77d 2024-06-03 stsp free(repo_path);
412 433eb77d 2024-06-03 stsp return error;
415 433eb77d 2024-06-03 stsp __dead static void
416 3ce1b845 2019-07-15 stsp usage_import(void)
418 827a167b 2022-08-16 stsp fprintf(stderr, "usage: %s import [-b branch] [-I pattern] [-m message] "
419 827a167b 2022-08-16 stsp "[-r repository-path] directory\n", getprogname());
424 3ce1b845 2019-07-15 stsp spawn_editor(const char *editor, const char *file)
427 3ce1b845 2019-07-15 stsp sig_t sighup, sigint, sigquit;
428 3ce1b845 2019-07-15 stsp int st = -1;
430 3ce1b845 2019-07-15 stsp sighup = signal(SIGHUP, SIG_IGN);
431 3ce1b845 2019-07-15 stsp sigint = signal(SIGINT, SIG_IGN);
432 3ce1b845 2019-07-15 stsp sigquit = signal(SIGQUIT, SIG_IGN);
434 3ce1b845 2019-07-15 stsp switch (pid = fork()) {
436 3ce1b845 2019-07-15 stsp goto doneediting;
438 3ce1b845 2019-07-15 stsp execl(editor, editor, file, (char *)NULL);
439 3ce1b845 2019-07-15 stsp _exit(127);
442 3ce1b845 2019-07-15 stsp while (waitpid(pid, &st, 0) == -1)
443 3ce1b845 2019-07-15 stsp if (errno != EINTR)
446 3ce1b845 2019-07-15 stsp doneediting:
447 3ce1b845 2019-07-15 stsp (void)signal(SIGHUP, sighup);
448 3ce1b845 2019-07-15 stsp (void)signal(SIGINT, sigint);
449 3ce1b845 2019-07-15 stsp (void)signal(SIGQUIT, sigquit);
451 3ce1b845 2019-07-15 stsp if (!WIFEXITED(st)) {
452 3ce1b845 2019-07-15 stsp errno = EINTR;
456 3ce1b845 2019-07-15 stsp return WEXITSTATUS(st);
459 3ce1b845 2019-07-15 stsp static const struct got_error *
460 ccc835f1 2023-02-10 mark read_logmsg(char **logmsg, size_t *len, FILE *fp, size_t filesize)
462 91a3781a 2023-02-09 stsp const struct got_error *err = NULL;
463 91a3781a 2023-02-09 stsp char *line = NULL;
464 91a3781a 2023-02-09 stsp size_t linesize = 0;
466 91a3781a 2023-02-09 stsp *logmsg = NULL;
469 91a3781a 2023-02-09 stsp if (fseeko(fp, 0L, SEEK_SET) == -1)
470 91a3781a 2023-02-09 stsp return got_error_from_errno("fseeko");
472 91a3781a 2023-02-09 stsp *logmsg = malloc(filesize + 1);
473 91a3781a 2023-02-09 stsp if (*logmsg == NULL)
474 91a3781a 2023-02-09 stsp return got_error_from_errno("malloc");
475 91a3781a 2023-02-09 stsp (*logmsg)[0] = '\0';
477 91a3781a 2023-02-09 stsp while (getline(&line, &linesize, fp) != -1) {
478 ccc835f1 2023-02-10 mark if (line[0] == '#' || (*len == 0 && line[0] == '\n'))
479 91a3781a 2023-02-09 stsp continue; /* remove comments and leading empty lines */
480 91a3781a 2023-02-09 stsp *len = strlcat(*logmsg, line, filesize + 1);
481 91a3781a 2023-02-09 stsp if (*len >= filesize + 1) {
482 91a3781a 2023-02-09 stsp err = got_error(GOT_ERR_NO_SPACE);
486 91a3781a 2023-02-09 stsp if (ferror(fp)) {
487 91a3781a 2023-02-09 stsp err = got_ferror(fp, GOT_ERR_IO);
491 91a3781a 2023-02-09 stsp while (*len > 0 && (*logmsg)[*len - 1] == '\n') {
492 91a3781a 2023-02-09 stsp (*logmsg)[*len - 1] = '\0';
496 91a3781a 2023-02-09 stsp free(line);
498 91a3781a 2023-02-09 stsp free(*logmsg);
499 91a3781a 2023-02-09 stsp *logmsg = NULL;
502 91a3781a 2023-02-09 stsp return err;
505 91a3781a 2023-02-09 stsp static const struct got_error *
506 3ce1b845 2019-07-15 stsp edit_logmsg(char **logmsg, const char *editor, const char *logmsg_path,
507 28cf319f 2021-01-28 stsp const char *initial_content, size_t initial_content_len,
508 28cf319f 2021-01-28 stsp int require_modification)
510 3ce1b845 2019-07-15 stsp const struct got_error *err = NULL;
511 3ce1b845 2019-07-15 stsp struct stat st, st2;
512 bfa12d5e 2020-09-26 stsp FILE *fp = NULL;
513 93436ccd 2023-02-10 mark size_t logmsg_len;
515 3ce1b845 2019-07-15 stsp *logmsg = NULL;
517 3ce1b845 2019-07-15 stsp if (stat(logmsg_path, &st) == -1)
518 3ce1b845 2019-07-15 stsp return got_error_from_errno2("stat", logmsg_path);
520 3ce1b845 2019-07-15 stsp if (spawn_editor(editor, logmsg_path) == -1)
521 3ce1b845 2019-07-15 stsp return got_error_from_errno("failed spawning editor");
523 faf054c3 2023-02-10 stsp if (require_modification) {
524 faf054c3 2023-02-10 stsp struct timespec timeout;
526 faf054c3 2023-02-10 stsp timeout.tv_sec = 0;
527 faf054c3 2023-02-10 stsp timeout.tv_nsec = 1;
528 faf054c3 2023-02-10 stsp nanosleep(&timeout, NULL);
531 3ce1b845 2019-07-15 stsp if (stat(logmsg_path, &st2) == -1)
532 1494a06e 2023-07-14 naddy return got_error_from_errno2("stat", logmsg_path);
534 faf054c3 2023-02-10 stsp if (require_modification && st.st_size == st2.st_size &&
535 faf054c3 2023-02-10 stsp timespeccmp(&st.st_mtim, &st2.st_mtim, ==))
536 3ce1b845 2019-07-15 stsp return got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
537 3ce1b845 2019-07-15 stsp "no changes made to commit message, aborting");
539 00fe21f2 2021-12-31 stsp fp = fopen(logmsg_path, "re");
540 3ce1b845 2019-07-15 stsp if (fp == NULL) {
541 3ce1b845 2019-07-15 stsp err = got_error_from_errno("fopen");
545 93436ccd 2023-02-10 mark /* strip comments and leading/trailing newlines */
546 ccc835f1 2023-02-10 mark err = read_logmsg(logmsg, &logmsg_len, fp, st2.st_size);
549 91a3781a 2023-02-09 stsp if (logmsg_len == 0) {
550 3ce1b845 2019-07-15 stsp err = got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
551 3ce1b845 2019-07-15 stsp "commit message cannot be empty, aborting");
555 bfa12d5e 2020-09-26 stsp if (fp && fclose(fp) == EOF && err == NULL)
556 bfa12d5e 2020-09-26 stsp err = got_error_from_errno("fclose");
558 3ce1b845 2019-07-15 stsp free(*logmsg);
559 3ce1b845 2019-07-15 stsp *logmsg = NULL;
561 3ce1b845 2019-07-15 stsp return err;
564 3ce1b845 2019-07-15 stsp static const struct got_error *
565 ef293bdd 2019-10-21 stsp collect_import_msg(char **logmsg, char **logmsg_path, const char *editor,
566 ef293bdd 2019-10-21 stsp const char *path_dir, const char *branch_name)
568 ef293bdd 2019-10-21 stsp char *initial_content = NULL;
569 3ce1b845 2019-07-15 stsp const struct got_error *err = NULL;
570 1601cb9f 2020-09-11 naddy int initial_content_len;
571 97972933 2020-09-11 stsp int fd = -1;
573 1601cb9f 2020-09-11 naddy initial_content_len = asprintf(&initial_content,
574 3ce1b845 2019-07-15 stsp "\n# %s to be imported to branch %s\n", path_dir,
575 1601cb9f 2020-09-11 naddy branch_name);
576 1601cb9f 2020-09-11 naddy if (initial_content_len == -1)
577 3ce1b845 2019-07-15 stsp return got_error_from_errno("asprintf");
579 bb63914a 2020-02-17 stsp err = got_opentemp_named_fd(logmsg_path, &fd,
580 b90054ed 2022-11-01 stsp GOT_TMPDIR_STR "/got-importmsg", "");
584 97972933 2020-09-11 stsp if (write(fd, initial_content, initial_content_len) == -1) {
585 97972933 2020-09-11 stsp err = got_error_from_errno2("write", *logmsg_path);
586 66993e59 2023-03-08 Todd.Mill goto done;
588 66993e59 2023-03-08 Todd.Mill if (close(fd) == -1) {
589 66993e59 2023-03-08 Todd.Mill err = got_error_from_errno2("close", *logmsg_path);
592 66993e59 2023-03-08 Todd.Mill fd = -1;
594 bfa12d5e 2020-09-26 stsp err = edit_logmsg(logmsg, editor, *logmsg_path, initial_content,
595 0d5bb276 2020-12-15 stsp initial_content_len, 1);
597 97972933 2020-09-11 stsp if (fd != -1 && close(fd) == -1 && err == NULL)
598 97972933 2020-09-11 stsp err = got_error_from_errno2("close", *logmsg_path);
599 3ce1b845 2019-07-15 stsp free(initial_content);
601 59f86c76 2020-09-11 stsp free(*logmsg_path);
602 59f86c76 2020-09-11 stsp *logmsg_path = NULL;
604 3ce1b845 2019-07-15 stsp return err;
607 3ce1b845 2019-07-15 stsp static const struct got_error *
608 3ce1b845 2019-07-15 stsp import_progress(void *arg, const char *path)
610 3ce1b845 2019-07-15 stsp printf("A %s\n", path);
611 3ce1b845 2019-07-15 stsp return NULL;
614 cf208ddd 2022-07-19 op static const struct got_error *
615 1d918cf9 2022-02-06 op valid_author(const char *author)
617 cf208ddd 2022-07-19 op const char *email = author;
620 cf208ddd 2022-07-19 op * Git' expects the author (or committer) to be in the form
621 cf208ddd 2022-07-19 op * "name <email>", which are mostly free form (see the
622 cf208ddd 2022-07-19 op * "committer" description in git-fast-import(1)). We're only
623 cf208ddd 2022-07-19 op * doing this to avoid git's object parser breaking on commits
627 cf208ddd 2022-07-19 op while (*author && *author != '\n' && *author != '<' && *author != '>')
629 21f07726 2022-10-31 stsp if (author != email && *author == '<' && *(author - 1) != ' ')
630 21f07726 2022-10-31 stsp return got_error_fmt(GOT_ERR_COMMIT_BAD_AUTHOR, "%s: space "
631 21f07726 2022-10-31 stsp "between author name and email required", email);
632 cf208ddd 2022-07-19 op if (*author++ != '<')
633 cf208ddd 2022-07-19 op return got_error_fmt(GOT_ERR_COMMIT_NO_EMAIL, "%s", email);
634 cf208ddd 2022-07-19 op while (*author && *author != '\n' && *author != '<' && *author != '>')
636 cf208ddd 2022-07-19 op if (strcmp(author, ">") != 0)
637 cf208ddd 2022-07-19 op return got_error_fmt(GOT_ERR_COMMIT_NO_EMAIL, "%s", email);
641 3ce1b845 2019-07-15 stsp static const struct got_error *
642 50b0790e 2020-09-11 stsp get_author(char **author, struct got_repository *repo,
643 50b0790e 2020-09-11 stsp struct got_worktree *worktree)
645 aba9c984 2019-09-08 stsp const struct got_error *err = NULL;
646 50b0790e 2020-09-11 stsp const char *got_author = NULL, *name, *email;
647 50b0790e 2020-09-11 stsp const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
649 84792843 2019-08-09 stsp *author = NULL;
651 50b0790e 2020-09-11 stsp if (worktree)
652 50b0790e 2020-09-11 stsp worktree_conf = got_worktree_get_gotconfig(worktree);
653 50b0790e 2020-09-11 stsp repo_conf = got_repo_get_gotconfig(repo);
656 50b0790e 2020-09-11 stsp * Priority of potential author information sources, from most
657 50b0790e 2020-09-11 stsp * significant to least significant:
658 50b0790e 2020-09-11 stsp * 1) work tree's .got/got.conf file
659 50b0790e 2020-09-11 stsp * 2) repository's got.conf file
660 50b0790e 2020-09-11 stsp * 3) repository's git config file
661 50b0790e 2020-09-11 stsp * 4) environment variables
662 50b0790e 2020-09-11 stsp * 5) global git config files (in user's home directory or /etc)
665 50b0790e 2020-09-11 stsp if (worktree_conf)
666 50b0790e 2020-09-11 stsp got_author = got_gotconfig_get_author(worktree_conf);
667 50b0790e 2020-09-11 stsp if (got_author == NULL)
668 50b0790e 2020-09-11 stsp got_author = got_gotconfig_get_author(repo_conf);
669 84792843 2019-08-09 stsp if (got_author == NULL) {
670 257add31 2020-09-09 stsp name = got_repo_get_gitconfig_author_name(repo);
671 257add31 2020-09-09 stsp email = got_repo_get_gitconfig_author_email(repo);
672 c9956ddf 2019-09-08 stsp if (name && email) {
673 c9956ddf 2019-09-08 stsp if (asprintf(author, "%s <%s>", name, email) == -1)
674 c9956ddf 2019-09-08 stsp return got_error_from_errno("asprintf");
675 c9956ddf 2019-09-08 stsp return NULL;
678 257add31 2020-09-09 stsp got_author = getenv("GOT_AUTHOR");
679 257add31 2020-09-09 stsp if (got_author == NULL) {
680 257add31 2020-09-09 stsp name = got_repo_get_global_gitconfig_author_name(repo);
681 257add31 2020-09-09 stsp email = got_repo_get_global_gitconfig_author_email(
683 257add31 2020-09-09 stsp if (name && email) {
684 257add31 2020-09-09 stsp if (asprintf(author, "%s <%s>", name, email)
686 257add31 2020-09-09 stsp return got_error_from_errno("asprintf");
687 257add31 2020-09-09 stsp return NULL;
689 257add31 2020-09-09 stsp /* TODO: Look up user in password database? */
690 257add31 2020-09-09 stsp return got_error(GOT_ERR_COMMIT_NO_AUTHOR);
694 aba9c984 2019-09-08 stsp *author = strdup(got_author);
695 aba9c984 2019-09-08 stsp if (*author == NULL)
696 aba9c984 2019-09-08 stsp return got_error_from_errno("strdup");
698 cf208ddd 2022-07-19 op err = valid_author(*author);
700 aba9c984 2019-09-08 stsp free(*author);
701 aba9c984 2019-09-08 stsp *author = NULL;
703 aba9c984 2019-09-08 stsp return err;
706 4d5ee956 2022-07-02 jrick static const struct got_error *
707 4d5ee956 2022-07-02 jrick get_allowed_signers(char **allowed_signers, struct got_repository *repo,
708 4d5ee956 2022-07-02 jrick struct got_worktree *worktree)
710 4d5ee956 2022-07-02 jrick const char *got_allowed_signers = NULL;
711 4d5ee956 2022-07-02 jrick const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
713 4d5ee956 2022-07-02 jrick *allowed_signers = NULL;
715 4d5ee956 2022-07-02 jrick if (worktree)
716 4d5ee956 2022-07-02 jrick worktree_conf = got_worktree_get_gotconfig(worktree);
717 4d5ee956 2022-07-02 jrick repo_conf = got_repo_get_gotconfig(repo);
720 4d5ee956 2022-07-02 jrick * Priority of potential author information sources, from most
721 4d5ee956 2022-07-02 jrick * significant to least significant:
722 4d5ee956 2022-07-02 jrick * 1) work tree's .got/got.conf file
723 4d5ee956 2022-07-02 jrick * 2) repository's got.conf file
726 4d5ee956 2022-07-02 jrick if (worktree_conf)
727 4d5ee956 2022-07-02 jrick got_allowed_signers = got_gotconfig_get_allowed_signers_file(
728 4d5ee956 2022-07-02 jrick worktree_conf);
729 4d5ee956 2022-07-02 jrick if (got_allowed_signers == NULL)
730 4d5ee956 2022-07-02 jrick got_allowed_signers = got_gotconfig_get_allowed_signers_file(
731 4d5ee956 2022-07-02 jrick repo_conf);
733 4d5ee956 2022-07-02 jrick if (got_allowed_signers) {
734 4d5ee956 2022-07-02 jrick *allowed_signers = strdup(got_allowed_signers);
735 4d5ee956 2022-07-02 jrick if (*allowed_signers == NULL)
736 4d5ee956 2022-07-02 jrick return got_error_from_errno("strdup");
738 4d5ee956 2022-07-02 jrick return NULL;
741 4d5ee956 2022-07-02 jrick static const struct got_error *
742 4d5ee956 2022-07-02 jrick get_revoked_signers(char **revoked_signers, struct got_repository *repo,
743 4d5ee956 2022-07-02 jrick struct got_worktree *worktree)
745 4d5ee956 2022-07-02 jrick const char *got_revoked_signers = NULL;
746 4d5ee956 2022-07-02 jrick const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
748 4d5ee956 2022-07-02 jrick *revoked_signers = NULL;
750 4d5ee956 2022-07-02 jrick if (worktree)
751 4d5ee956 2022-07-02 jrick worktree_conf = got_worktree_get_gotconfig(worktree);
752 4d5ee956 2022-07-02 jrick repo_conf = got_repo_get_gotconfig(repo);
755 4d5ee956 2022-07-02 jrick * Priority of potential author information sources, from most
756 4d5ee956 2022-07-02 jrick * significant to least significant:
757 4d5ee956 2022-07-02 jrick * 1) work tree's .got/got.conf file
758 4d5ee956 2022-07-02 jrick * 2) repository's got.conf file
761 4d5ee956 2022-07-02 jrick if (worktree_conf)
762 4d5ee956 2022-07-02 jrick got_revoked_signers = got_gotconfig_get_revoked_signers_file(
763 4d5ee956 2022-07-02 jrick worktree_conf);
764 4d5ee956 2022-07-02 jrick if (got_revoked_signers == NULL)
765 4d5ee956 2022-07-02 jrick got_revoked_signers = got_gotconfig_get_revoked_signers_file(
766 4d5ee956 2022-07-02 jrick repo_conf);
768 4d5ee956 2022-07-02 jrick if (got_revoked_signers) {
769 4d5ee956 2022-07-02 jrick *revoked_signers = strdup(got_revoked_signers);
770 4d5ee956 2022-07-02 jrick if (*revoked_signers == NULL)
771 4d5ee956 2022-07-02 jrick return got_error_from_errno("strdup");
773 4d5ee956 2022-07-02 jrick return NULL;
776 a003d518 2023-01-26 op static const char *
777 a003d518 2023-01-26 op get_signer_id(struct got_repository *repo, struct got_worktree *worktree)
779 d68f2c0e 2022-07-05 jrick const char *got_signer_id = NULL;
780 d68f2c0e 2022-07-05 jrick const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
782 d68f2c0e 2022-07-05 jrick if (worktree)
783 d68f2c0e 2022-07-05 jrick worktree_conf = got_worktree_get_gotconfig(worktree);
784 d68f2c0e 2022-07-05 jrick repo_conf = got_repo_get_gotconfig(repo);
787 d68f2c0e 2022-07-05 jrick * Priority of potential author information sources, from most
788 d68f2c0e 2022-07-05 jrick * significant to least significant:
789 d68f2c0e 2022-07-05 jrick * 1) work tree's .got/got.conf file
790 d68f2c0e 2022-07-05 jrick * 2) repository's got.conf file
793 d68f2c0e 2022-07-05 jrick if (worktree_conf)
794 d68f2c0e 2022-07-05 jrick got_signer_id = got_gotconfig_get_signer_id(worktree_conf);
795 d68f2c0e 2022-07-05 jrick if (got_signer_id == NULL)
796 d68f2c0e 2022-07-05 jrick got_signer_id = got_gotconfig_get_signer_id(repo_conf);
798 a003d518 2023-01-26 op return got_signer_id;
801 d68f2c0e 2022-07-05 jrick static const struct got_error *
802 c9956ddf 2019-09-08 stsp get_gitconfig_path(char **gitconfig_path)
804 c9956ddf 2019-09-08 stsp const char *homedir = getenv("HOME");
806 c9956ddf 2019-09-08 stsp *gitconfig_path = NULL;
807 c9956ddf 2019-09-08 stsp if (homedir) {
808 c9956ddf 2019-09-08 stsp if (asprintf(gitconfig_path, "%s/.gitconfig", homedir) == -1)
809 c9956ddf 2019-09-08 stsp return got_error_from_errno("asprintf");
812 c9956ddf 2019-09-08 stsp return NULL;
815 84792843 2019-08-09 stsp static const struct got_error *
816 3ce1b845 2019-07-15 stsp cmd_import(int argc, char *argv[])
818 3ce1b845 2019-07-15 stsp const struct got_error *error = NULL;
819 3ce1b845 2019-07-15 stsp char *path_dir = NULL, *repo_path = NULL, *logmsg = NULL;
820 c9956ddf 2019-09-08 stsp char *gitconfig_path = NULL, *editor = NULL, *author = NULL;
821 6f04a73d 2022-09-20 mark const char *branch_name = NULL;
822 6f04a73d 2022-09-20 mark char *id_str = NULL, *logmsg_path = NULL;
823 6f04a73d 2022-09-20 mark char refname[PATH_MAX] = "refs/heads/";
824 3ce1b845 2019-07-15 stsp struct got_repository *repo = NULL;
825 3ce1b845 2019-07-15 stsp struct got_reference *branch_ref = NULL, *head_ref = NULL;
826 3ce1b845 2019-07-15 stsp struct got_object_id *new_commit_id = NULL;
827 6f04a73d 2022-09-20 mark int ch, n = 0;
828 3ce1b845 2019-07-15 stsp struct got_pathlist_head ignores;
829 3ce1b845 2019-07-15 stsp struct got_pathlist_entry *pe;
830 ef293bdd 2019-10-21 stsp int preserve_logmsg = 0;
831 0ae84acc 2022-06-15 tracey int *pack_fds = NULL;
833 3ce1b845 2019-07-15 stsp TAILQ_INIT(&ignores);
835 1fa0d17d 2023-02-13 op #ifndef PROFILE
836 1fa0d17d 2023-02-13 op if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd "
839 1fa0d17d 2023-02-13 op err(1, "pledge");
842 6f319063 2022-10-27 stsp while ((ch = getopt(argc, argv, "b:I:m:r:")) != -1) {
843 3ce1b845 2019-07-15 stsp switch (ch) {
845 3ce1b845 2019-07-15 stsp branch_name = optarg;
848 6f319063 2022-10-27 stsp if (optarg[0] == '\0')
850 6f319063 2022-10-27 stsp error = got_pathlist_insert(&pe, &ignores, optarg,
856 3ce1b845 2019-07-15 stsp logmsg = strdup(optarg);
857 3ce1b845 2019-07-15 stsp if (logmsg == NULL) {
858 3ce1b845 2019-07-15 stsp error = got_error_from_errno("strdup");
863 3ce1b845 2019-07-15 stsp repo_path = realpath(optarg, NULL);
864 3ce1b845 2019-07-15 stsp if (repo_path == NULL) {
865 9ba1d308 2019-10-21 stsp error = got_error_from_errno2("realpath",
871 b2b65d18 2019-08-22 stsp usage_import();
872 3ce1b845 2019-07-15 stsp /* NOTREACHED */
876 3ce1b845 2019-07-15 stsp argc -= optind;
877 3ce1b845 2019-07-15 stsp argv += optind;
879 3ce1b845 2019-07-15 stsp if (argc != 1)
880 3ce1b845 2019-07-15 stsp usage_import();
882 3ce1b845 2019-07-15 stsp if (repo_path == NULL) {
883 3ce1b845 2019-07-15 stsp repo_path = getcwd(NULL, 0);
884 3ce1b845 2019-07-15 stsp if (repo_path == NULL)
885 3ce1b845 2019-07-15 stsp return got_error_from_errno("getcwd");
887 3ce1b845 2019-07-15 stsp got_path_strip_trailing_slashes(repo_path);
888 c9956ddf 2019-09-08 stsp error = get_gitconfig_path(&gitconfig_path);
891 0ae84acc 2022-06-15 tracey error = got_repo_pack_fds_open(&pack_fds);
892 0ae84acc 2022-06-15 tracey if (error != NULL)
893 0ae84acc 2022-06-15 tracey goto done;
894 0ae84acc 2022-06-15 tracey error = got_repo_open(&repo, repo_path, gitconfig_path, pack_fds);
898 2f40f7d2 2024-03-28 stsp path_dir = realpath(argv[0], NULL);
899 2f40f7d2 2024-03-28 stsp if (path_dir == NULL) {
900 2f40f7d2 2024-03-28 stsp error = got_error_from_errno2("realpath", argv[0]);
903 2f40f7d2 2024-03-28 stsp got_path_strip_trailing_slashes(path_dir);
905 2f40f7d2 2024-03-28 stsp error = get_editor(&editor);
909 2f40f7d2 2024-03-28 stsp if (unveil(path_dir, "r") != 0) {
910 2f40f7d2 2024-03-28 stsp error = got_error_from_errno2("unveil", path_dir);
913 2f40f7d2 2024-03-28 stsp if (unveil(editor, "x") != 0) {
914 2f40f7d2 2024-03-28 stsp error = got_error_from_errno2("unveil", editor);
917 2f40f7d2 2024-03-28 stsp error = apply_unveil(got_repo_get_path(repo), 0, NULL);
921 50b0790e 2020-09-11 stsp error = get_author(&author, repo, NULL);
923 aba9c984 2019-09-08 stsp return error;
926 bd5895f3 2019-11-28 stsp * Don't let the user create a branch name with a leading '-'.
927 e560b7e0 2019-11-28 stsp * While technically a valid reference name, this case is usually
928 e560b7e0 2019-11-28 stsp * an unintended typo.
930 6f04a73d 2022-09-20 mark if (branch_name && branch_name[0] == '-')
931 bd5895f3 2019-11-28 stsp return got_error_path(branch_name, GOT_ERR_REF_NAME_MINUS);
933 6f04a73d 2022-09-20 mark error = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0);
934 6f04a73d 2022-09-20 mark if (error && error->code != GOT_ERR_NOT_REF)
937 6f04a73d 2022-09-20 mark if (branch_name)
938 6f04a73d 2022-09-20 mark n = strlcat(refname, branch_name, sizeof(refname));
939 6f04a73d 2022-09-20 mark else if (head_ref && got_ref_is_symbolic(head_ref))
940 6f04a73d 2022-09-20 mark n = strlcpy(refname, got_ref_get_symref_target(head_ref),
941 6f04a73d 2022-09-20 mark sizeof(refname));
943 6f04a73d 2022-09-20 mark n = strlcat(refname, "main", sizeof(refname));
944 6f04a73d 2022-09-20 mark if (n >= sizeof(refname)) {
945 6f04a73d 2022-09-20 mark error = got_error(GOT_ERR_NO_SPACE);
949 3ce1b845 2019-07-15 stsp error = got_ref_open(&branch_ref, repo, refname, 0);
950 3ce1b845 2019-07-15 stsp if (error) {
951 3ce1b845 2019-07-15 stsp if (error->code != GOT_ERR_NOT_REF)
954 3ce1b845 2019-07-15 stsp error = got_error_msg(GOT_ERR_BRANCH_EXISTS,
955 3ce1b845 2019-07-15 stsp "import target branch already exists");
959 4448825a 2023-06-16 op if (logmsg == NULL || *logmsg == '\0') {
960 8e158b01 2019-09-22 stsp free(logmsg);
961 ef293bdd 2019-10-21 stsp error = collect_import_msg(&logmsg, &logmsg_path, editor,
962 ef293bdd 2019-10-21 stsp path_dir, refname);
963 ef293bdd 2019-10-21 stsp if (error) {
964 ef293bdd 2019-10-21 stsp if (error->code != GOT_ERR_COMMIT_MSG_EMPTY &&
965 ef293bdd 2019-10-21 stsp logmsg_path != NULL)
966 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
971 3ce1b845 2019-07-15 stsp error = got_repo_import(&new_commit_id, path_dir, logmsg,
972 84792843 2019-08-09 stsp author, &ignores, repo, import_progress, NULL);
973 ef293bdd 2019-10-21 stsp if (error) {
974 ef293bdd 2019-10-21 stsp if (logmsg_path)
975 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
979 3ce1b845 2019-07-15 stsp error = got_ref_alloc(&branch_ref, refname, new_commit_id);
980 ef293bdd 2019-10-21 stsp if (error) {
981 ef293bdd 2019-10-21 stsp if (logmsg_path)
982 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
986 3ce1b845 2019-07-15 stsp error = got_ref_write(branch_ref, repo);
987 ef293bdd 2019-10-21 stsp if (error) {
988 ef293bdd 2019-10-21 stsp if (logmsg_path)
989 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
993 3ce1b845 2019-07-15 stsp error = got_object_id_str(&id_str, new_commit_id);
994 ef293bdd 2019-10-21 stsp if (error) {
995 ef293bdd 2019-10-21 stsp if (logmsg_path)
996 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1000 3ce1b845 2019-07-15 stsp error = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0);
1001 3ce1b845 2019-07-15 stsp if (error) {
1002 ef293bdd 2019-10-21 stsp if (error->code != GOT_ERR_NOT_REF) {
1003 ef293bdd 2019-10-21 stsp if (logmsg_path)
1004 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1005 3ce1b845 2019-07-15 stsp goto done;
1008 3ce1b845 2019-07-15 stsp error = got_ref_alloc_symref(&head_ref, GOT_REF_HEAD,
1009 3ce1b845 2019-07-15 stsp branch_ref);
1010 ef293bdd 2019-10-21 stsp if (error) {
1011 ef293bdd 2019-10-21 stsp if (logmsg_path)
1012 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1013 3ce1b845 2019-07-15 stsp goto done;
1016 3ce1b845 2019-07-15 stsp error = got_ref_write(head_ref, repo);
1017 ef293bdd 2019-10-21 stsp if (error) {
1018 ef293bdd 2019-10-21 stsp if (logmsg_path)
1019 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1020 3ce1b845 2019-07-15 stsp goto done;
1024 3ce1b845 2019-07-15 stsp printf("Created branch %s with commit %s\n",
1025 3ce1b845 2019-07-15 stsp got_ref_get_name(branch_ref), id_str);
1027 0ae84acc 2022-06-15 tracey if (pack_fds) {
1028 0ae84acc 2022-06-15 tracey const struct got_error *pack_err =
1029 0ae84acc 2022-06-15 tracey got_repo_pack_fds_close(pack_fds);
1030 0ae84acc 2022-06-15 tracey if (error == NULL)
1031 0ae84acc 2022-06-15 tracey error = pack_err;
1034 7755e2f8 2023-04-07 op const struct got_error *close_err = got_repo_close(repo);
1035 7755e2f8 2023-04-07 op if (error == NULL)
1036 7755e2f8 2023-04-07 op error = close_err;
1038 ef293bdd 2019-10-21 stsp if (preserve_logmsg) {
1039 ef293bdd 2019-10-21 stsp fprintf(stderr, "%s: log message preserved in %s\n",
1040 ef293bdd 2019-10-21 stsp getprogname(), logmsg_path);
1041 ef293bdd 2019-10-21 stsp } else if (logmsg_path && unlink(logmsg_path) == -1 && error == NULL)
1042 ef293bdd 2019-10-21 stsp error = got_error_from_errno2("unlink", logmsg_path);
1043 8e158b01 2019-09-22 stsp free(logmsg);
1044 ef293bdd 2019-10-21 stsp free(logmsg_path);
1045 2c7829a4 2019-06-17 stsp free(repo_path);
1046 3ce1b845 2019-07-15 stsp free(editor);
1047 3ce1b845 2019-07-15 stsp free(new_commit_id);
1048 3ce1b845 2019-07-15 stsp free(id_str);
1049 aba9c984 2019-09-08 stsp free(author);
1050 c9956ddf 2019-09-08 stsp free(gitconfig_path);
1051 3ce1b845 2019-07-15 stsp if (branch_ref)
1052 3ce1b845 2019-07-15 stsp got_ref_close(branch_ref);
1053 3ce1b845 2019-07-15 stsp if (head_ref)
1054 3ce1b845 2019-07-15 stsp got_ref_close(head_ref);
1055 2c7829a4 2019-06-17 stsp return error;
1058 93658fb9 2020-03-18 stsp __dead static void
1059 93658fb9 2020-03-18 stsp usage_clone(void)
1061 827a167b 2022-08-16 stsp fprintf(stderr, "usage: %s clone [-almqv] [-b branch] [-R reference] "
1062 827a167b 2022-08-16 stsp "repository-URL [directory]\n", getprogname());
1066 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg {
1067 892ac3b6 2020-03-18 stsp char last_scaled_size[FMT_SCALED_STRSIZE];
1068 892ac3b6 2020-03-18 stsp int last_p_indexed;
1069 892ac3b6 2020-03-18 stsp int last_p_resolved;
1070 68999b92 2020-03-18 stsp int verbosity;
1072 04d9a9ec 2020-09-24 stsp struct got_repository *repo;
1074 04d9a9ec 2020-09-24 stsp int create_configs;
1075 04d9a9ec 2020-09-24 stsp int configs_created;
1077 04d9a9ec 2020-09-24 stsp struct got_pathlist_head *symrefs;
1078 04d9a9ec 2020-09-24 stsp struct got_pathlist_head *wanted_branches;
1079 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs;
1080 04d9a9ec 2020-09-24 stsp const char *proto;
1081 04d9a9ec 2020-09-24 stsp const char *host;
1082 04d9a9ec 2020-09-24 stsp const char *port;
1083 04d9a9ec 2020-09-24 stsp const char *remote_repo_path;
1084 04d9a9ec 2020-09-24 stsp const char *git_url;
1085 04d9a9ec 2020-09-24 stsp int fetch_all_branches;
1086 04d9a9ec 2020-09-24 stsp int mirror_references;
1087 04d9a9ec 2020-09-24 stsp } config_info;
1090 04d9a9ec 2020-09-24 stsp /* XXX forward declaration */
1091 93658fb9 2020-03-18 stsp static const struct got_error *
1092 04d9a9ec 2020-09-24 stsp create_config_files(const char *proto, const char *host, const char *port,
1093 04d9a9ec 2020-09-24 stsp const char *remote_repo_path, const char *git_url, int fetch_all_branches,
1094 04d9a9ec 2020-09-24 stsp int mirror_references, struct got_pathlist_head *symrefs,
1095 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_branches,
1096 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, struct got_repository *repo);
1098 04d9a9ec 2020-09-24 stsp static const struct got_error *
1099 baa9fea0 2020-03-18 stsp fetch_progress(void *arg, const char *message, off_t packfile_size,
1100 668a20f6 2020-03-18 stsp int nobj_total, int nobj_indexed, int nobj_loose, int nobj_resolved)
1102 04d9a9ec 2020-09-24 stsp const struct got_error *err = NULL;
1103 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg *a = arg;
1104 892ac3b6 2020-03-18 stsp char scaled_size[FMT_SCALED_STRSIZE];
1105 892ac3b6 2020-03-18 stsp int p_indexed, p_resolved;
1106 892ac3b6 2020-03-18 stsp int print_size = 0, print_indexed = 0, print_resolved = 0;
1109 04d9a9ec 2020-09-24 stsp * In order to allow a failed clone to be resumed with 'got fetch'
1110 04d9a9ec 2020-09-24 stsp * we try to create configuration files as soon as possible.
1111 04d9a9ec 2020-09-24 stsp * Once the server has sent information about its default branch
1112 04d9a9ec 2020-09-24 stsp * we have all required information.
1114 04d9a9ec 2020-09-24 stsp if (a->create_configs && !a->configs_created &&
1115 04d9a9ec 2020-09-24 stsp !TAILQ_EMPTY(a->config_info.symrefs)) {
1116 04d9a9ec 2020-09-24 stsp err = create_config_files(a->config_info.proto,
1117 62d463ca 2020-10-20 naddy a->config_info.host, a->config_info.port,
1118 62d463ca 2020-10-20 naddy a->config_info.remote_repo_path,
1119 62d463ca 2020-10-20 naddy a->config_info.git_url,
1120 62d463ca 2020-10-20 naddy a->config_info.fetch_all_branches,
1121 62d463ca 2020-10-20 naddy a->config_info.mirror_references,
1122 62d463ca 2020-10-20 naddy a->config_info.symrefs,
1123 99495ddb 2021-01-10 stsp a->config_info.wanted_branches,
1124 99495ddb 2021-01-10 stsp a->config_info.wanted_refs, a->repo);
1126 04d9a9ec 2020-09-24 stsp return err;
1127 04d9a9ec 2020-09-24 stsp a->configs_created = 1;
1130 68999b92 2020-03-18 stsp if (a->verbosity < 0)
1131 68999b92 2020-03-18 stsp return NULL;
1133 fd843b58 2020-03-18 stsp if (message && message[0] != '\0') {
1134 d2cdc636 2020-03-18 stsp printf("\rserver: %s", message);
1135 892ac3b6 2020-03-18 stsp fflush(stdout);
1136 12d1281e 2020-03-19 stsp return NULL;
1139 b2409d58 2020-03-18 stsp if (packfile_size > 0 || nobj_indexed > 0) {
1140 892ac3b6 2020-03-18 stsp if (fmt_scaled(packfile_size, scaled_size) == 0 &&
1141 892ac3b6 2020-03-18 stsp (a->last_scaled_size[0] == '\0' ||
1142 892ac3b6 2020-03-18 stsp strcmp(scaled_size, a->last_scaled_size)) != 0) {
1143 892ac3b6 2020-03-18 stsp print_size = 1;
1144 892ac3b6 2020-03-18 stsp if (strlcpy(a->last_scaled_size, scaled_size,
1145 892ac3b6 2020-03-18 stsp FMT_SCALED_STRSIZE) >= FMT_SCALED_STRSIZE)
1146 892ac3b6 2020-03-18 stsp return got_error(GOT_ERR_NO_SPACE);
1148 61cc1a7a 2020-03-18 stsp if (nobj_indexed > 0) {
1149 892ac3b6 2020-03-18 stsp p_indexed = (nobj_indexed * 100) / nobj_total;
1150 892ac3b6 2020-03-18 stsp if (p_indexed != a->last_p_indexed) {
1151 892ac3b6 2020-03-18 stsp a->last_p_indexed = p_indexed;
1152 892ac3b6 2020-03-18 stsp print_indexed = 1;
1153 892ac3b6 2020-03-18 stsp print_size = 1;
1156 61cc1a7a 2020-03-18 stsp if (nobj_resolved > 0) {
1157 892ac3b6 2020-03-18 stsp p_resolved = (nobj_resolved * 100) /
1158 892ac3b6 2020-03-18 stsp (nobj_total - nobj_loose);
1159 892ac3b6 2020-03-18 stsp if (p_resolved != a->last_p_resolved) {
1160 892ac3b6 2020-03-18 stsp a->last_p_resolved = p_resolved;
1161 892ac3b6 2020-03-18 stsp print_resolved = 1;
1162 892ac3b6 2020-03-18 stsp print_indexed = 1;
1163 892ac3b6 2020-03-18 stsp print_size = 1;
1168 892ac3b6 2020-03-18 stsp if (print_size || print_indexed || print_resolved)
1169 892ac3b6 2020-03-18 stsp printf("\r");
1170 892ac3b6 2020-03-18 stsp if (print_size)
1171 b5934965 2022-02-12 naddy printf("%*s fetched", FMT_SCALED_STRSIZE - 2, scaled_size);
1172 d715f13e 2020-03-19 stsp if (print_indexed)
1173 892ac3b6 2020-03-18 stsp printf("; indexing %d%%", p_indexed);
1174 d715f13e 2020-03-19 stsp if (print_resolved)
1175 892ac3b6 2020-03-18 stsp printf("; resolving deltas %d%%", p_resolved);
1176 892ac3b6 2020-03-18 stsp if (print_size || print_indexed || print_resolved)
1177 892ac3b6 2020-03-18 stsp fflush(stdout);
1179 531c3985 2020-03-18 stsp return NULL;
1182 531c3985 2020-03-18 stsp static const struct got_error *
1183 04d9a9ec 2020-09-24 stsp create_symref(const char *refname, struct got_reference *target_ref,
1184 04d9a9ec 2020-09-24 stsp int verbosity, struct got_repository *repo)
1186 4ba14133 2020-03-20 stsp const struct got_error *err;
1187 04d9a9ec 2020-09-24 stsp struct got_reference *head_symref;
1189 04d9a9ec 2020-09-24 stsp err = got_ref_alloc_symref(&head_symref, refname, target_ref);
1191 4ba14133 2020-03-20 stsp return err;
1193 04d9a9ec 2020-09-24 stsp err = got_ref_write(head_symref, repo);
1194 6338a6a1 2020-03-21 stsp if (err == NULL && verbosity > 0) {
1195 6338a6a1 2020-03-21 stsp printf("Created reference %s: %s\n", GOT_REF_HEAD,
1196 6338a6a1 2020-03-21 stsp got_ref_get_name(target_ref));
1198 04d9a9ec 2020-09-24 stsp got_ref_close(head_symref);
1199 4ba14133 2020-03-20 stsp return err;
1202 4ba14133 2020-03-20 stsp static const struct got_error *
1203 41b0de12 2020-03-21 stsp list_remote_refs(struct got_pathlist_head *symrefs,
1204 41b0de12 2020-03-21 stsp struct got_pathlist_head *refs)
1206 41b0de12 2020-03-21 stsp const struct got_error *err;
1207 41b0de12 2020-03-21 stsp struct got_pathlist_entry *pe;
1209 41b0de12 2020-03-21 stsp TAILQ_FOREACH(pe, symrefs, entry) {
1210 41b0de12 2020-03-21 stsp const char *refname = pe->path;
1211 41b0de12 2020-03-21 stsp const char *targetref = pe->data;
1213 41b0de12 2020-03-21 stsp printf("%s: %s\n", refname, targetref);
1216 41b0de12 2020-03-21 stsp TAILQ_FOREACH(pe, refs, entry) {
1217 41b0de12 2020-03-21 stsp const char *refname = pe->path;
1218 41b0de12 2020-03-21 stsp struct got_object_id *id = pe->data;
1219 41b0de12 2020-03-21 stsp char *id_str;
1221 41b0de12 2020-03-21 stsp err = got_object_id_str(&id_str, id);
1223 41b0de12 2020-03-21 stsp return err;
1224 41b0de12 2020-03-21 stsp printf("%s: %s\n", refname, id_str);
1225 41b0de12 2020-03-21 stsp free(id_str);
1228 41b0de12 2020-03-21 stsp return NULL;
1231 6338a6a1 2020-03-21 stsp static const struct got_error *
1232 6338a6a1 2020-03-21 stsp create_ref(const char *refname, struct got_object_id *id,
1233 6338a6a1 2020-03-21 stsp int verbosity, struct got_repository *repo)
1235 6338a6a1 2020-03-21 stsp const struct got_error *err = NULL;
1236 6338a6a1 2020-03-21 stsp struct got_reference *ref;
1237 6338a6a1 2020-03-21 stsp char *id_str;
1239 6338a6a1 2020-03-21 stsp err = got_object_id_str(&id_str, id);
1241 6338a6a1 2020-03-21 stsp return err;
1243 6338a6a1 2020-03-21 stsp err = got_ref_alloc(&ref, refname, id);
1245 6338a6a1 2020-03-21 stsp goto done;
1247 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
1248 6338a6a1 2020-03-21 stsp got_ref_close(ref);
1250 6338a6a1 2020-03-21 stsp if (err == NULL && verbosity >= 0)
1251 6338a6a1 2020-03-21 stsp printf("Created reference %s: %s\n", refname, id_str);
1253 6338a6a1 2020-03-21 stsp free(id_str);
1254 6338a6a1 2020-03-21 stsp return err;
1257 0e4002ca 2020-03-21 stsp static int
1258 0e4002ca 2020-03-21 stsp match_wanted_ref(const char *refname, const char *wanted_ref)
1260 0e4002ca 2020-03-21 stsp if (strncmp(refname, "refs/", 5) != 0)
1262 0e4002ca 2020-03-21 stsp refname += 5;
1265 0e4002ca 2020-03-21 stsp * Prevent fetching of references that won't make any
1266 0e4002ca 2020-03-21 stsp * sense outside of the remote repository's context.
1268 0e4002ca 2020-03-21 stsp if (strncmp(refname, "got/", 4) == 0)
1270 0e4002ca 2020-03-21 stsp if (strncmp(refname, "remotes/", 8) == 0)
1273 0e4002ca 2020-03-21 stsp if (strncmp(wanted_ref, "refs/", 5) == 0)
1274 0e4002ca 2020-03-21 stsp wanted_ref += 5;
1276 0e4002ca 2020-03-21 stsp /* Allow prefix match. */
1277 0e4002ca 2020-03-21 stsp if (got_path_is_child(refname, wanted_ref, strlen(wanted_ref)))
1280 0e4002ca 2020-03-21 stsp /* Allow exact match. */
1281 0e4002ca 2020-03-21 stsp return (strcmp(refname, wanted_ref) == 0);
1284 0e4002ca 2020-03-21 stsp static int
1285 0e4002ca 2020-03-21 stsp is_wanted_ref(struct got_pathlist_head *wanted_refs, const char *refname)
1287 0e4002ca 2020-03-21 stsp struct got_pathlist_entry *pe;
1289 0e4002ca 2020-03-21 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1290 0e4002ca 2020-03-21 stsp if (match_wanted_ref(refname, pe->path))
1297 41b0de12 2020-03-21 stsp static const struct got_error *
1298 0e4002ca 2020-03-21 stsp create_wanted_ref(const char *refname, struct got_object_id *id,
1299 0e4002ca 2020-03-21 stsp const char *remote_repo_name, int verbosity, struct got_repository *repo)
1301 0e4002ca 2020-03-21 stsp const struct got_error *err;
1302 0e4002ca 2020-03-21 stsp char *remote_refname;
1304 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
1305 0e4002ca 2020-03-21 stsp refname += 5;
1307 0e4002ca 2020-03-21 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
1308 0e4002ca 2020-03-21 stsp remote_repo_name, refname) == -1)
1309 0e4002ca 2020-03-21 stsp return got_error_from_errno("asprintf");
1311 0e4002ca 2020-03-21 stsp err = create_ref(remote_refname, id, verbosity, repo);
1312 0e4002ca 2020-03-21 stsp free(remote_refname);
1313 7c0b7f42 2020-09-24 stsp return err;
1316 7c0b7f42 2020-09-24 stsp static const struct got_error *
1317 7c0b7f42 2020-09-24 stsp create_gotconfig(const char *proto, const char *host, const char *port,
1318 15d3c221 2021-01-05 stsp const char *remote_repo_path, const char *default_branch,
1319 0c8b29c5 2021-01-05 stsp int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1320 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, int mirror_references,
1321 99495ddb 2021-01-10 stsp struct got_repository *repo)
1323 7c0b7f42 2020-09-24 stsp const struct got_error *err = NULL;
1324 7c0b7f42 2020-09-24 stsp char *gotconfig_path = NULL;
1325 7c0b7f42 2020-09-24 stsp char *gotconfig = NULL;
1326 7c0b7f42 2020-09-24 stsp FILE *gotconfig_file = NULL;
1327 15d3c221 2021-01-05 stsp const char *branchname = NULL;
1328 99495ddb 2021-01-10 stsp char *branches = NULL, *refs = NULL;
1329 7c0b7f42 2020-09-24 stsp ssize_t n;
1331 0c8b29c5 2021-01-05 stsp if (!fetch_all_branches && !TAILQ_EMPTY(wanted_branches)) {
1332 132af4a5 2021-01-05 stsp struct got_pathlist_entry *pe;
1333 132af4a5 2021-01-05 stsp TAILQ_FOREACH(pe, wanted_branches, entry) {
1335 132af4a5 2021-01-05 stsp branchname = pe->path;
1336 132af4a5 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1337 132af4a5 2021-01-05 stsp branchname += 11;
1338 132af4a5 2021-01-05 stsp if (asprintf(&s, "%s\"%s\" ",
1339 132af4a5 2021-01-05 stsp branches ? branches : "", branchname) == -1) {
1340 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1341 132af4a5 2021-01-05 stsp goto done;
1343 132af4a5 2021-01-05 stsp free(branches);
1344 132af4a5 2021-01-05 stsp branches = s;
1346 0c8b29c5 2021-01-05 stsp } else if (!fetch_all_branches && default_branch) {
1347 15d3c221 2021-01-05 stsp branchname = default_branch;
1348 15d3c221 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1349 15d3c221 2021-01-05 stsp branchname += 11;
1350 132af4a5 2021-01-05 stsp if (asprintf(&branches, "\"%s\" ", branchname) == -1) {
1351 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1352 132af4a5 2021-01-05 stsp goto done;
1355 99495ddb 2021-01-10 stsp if (!TAILQ_EMPTY(wanted_refs)) {
1356 99495ddb 2021-01-10 stsp struct got_pathlist_entry *pe;
1357 99495ddb 2021-01-10 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1359 99495ddb 2021-01-10 stsp const char *refname = pe->path;
1360 99495ddb 2021-01-10 stsp if (strncmp(refname, "refs/", 5) == 0)
1361 99495ddb 2021-01-10 stsp branchname += 5;
1362 99495ddb 2021-01-10 stsp if (asprintf(&s, "%s\"%s\" ",
1363 99495ddb 2021-01-10 stsp refs ? refs : "", refname) == -1) {
1364 99495ddb 2021-01-10 stsp err = got_error_from_errno("asprintf");
1365 99495ddb 2021-01-10 stsp goto done;
1367 99495ddb 2021-01-10 stsp free(refs);
1372 7c0b7f42 2020-09-24 stsp /* Create got.conf(5). */
1373 7c0b7f42 2020-09-24 stsp gotconfig_path = got_repo_get_path_gotconfig(repo);
1374 7c0b7f42 2020-09-24 stsp if (gotconfig_path == NULL) {
1375 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("got_repo_get_path_gotconfig");
1376 7c0b7f42 2020-09-24 stsp goto done;
1378 00fe21f2 2021-12-31 stsp gotconfig_file = fopen(gotconfig_path, "ae");
1379 7c0b7f42 2020-09-24 stsp if (gotconfig_file == NULL) {
1380 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fopen", gotconfig_path);
1381 7c0b7f42 2020-09-24 stsp goto done;
1383 7c0b7f42 2020-09-24 stsp if (asprintf(&gotconfig,
1384 7c0b7f42 2020-09-24 stsp "remote \"%s\" {\n"
1385 7c0b7f42 2020-09-24 stsp "\tserver %s\n"
1386 7c0b7f42 2020-09-24 stsp "\tprotocol %s\n"
1388 7c0b7f42 2020-09-24 stsp "\trepository \"%s\"\n"
1394 7c0b7f42 2020-09-24 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, host, proto,
1395 7c0b7f42 2020-09-24 stsp port ? "\tport " : "", port ? port : "", port ? "\n" : "",
1396 132af4a5 2021-01-05 stsp remote_repo_path, branches ? "\tbranch { " : "",
1397 5e91dae4 2022-08-30 stsp branches ? branches : "", branches ? "}\n" : "",
1398 5e91dae4 2022-08-30 stsp refs ? "\treference { " : "", refs ? refs : "", refs ? "}\n" : "",
1399 26e6f38e 2022-07-03 stsp mirror_references ? "\tmirror_references yes\n" : "",
1400 f1bf60d1 2022-07-03 stsp fetch_all_branches ? "\tfetch_all_branches yes\n" : "") == -1) {
1401 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1402 7c0b7f42 2020-09-24 stsp goto done;
1404 7c0b7f42 2020-09-24 stsp n = fwrite(gotconfig, 1, strlen(gotconfig), gotconfig_file);
1405 7c0b7f42 2020-09-24 stsp if (n != strlen(gotconfig)) {
1406 7c0b7f42 2020-09-24 stsp err = got_ferror(gotconfig_file, GOT_ERR_IO);
1407 7c0b7f42 2020-09-24 stsp goto done;
1411 7c0b7f42 2020-09-24 stsp if (gotconfig_file && fclose(gotconfig_file) == EOF && err == NULL)
1412 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fclose", gotconfig_path);
1413 7c0b7f42 2020-09-24 stsp free(gotconfig_path);
1414 132af4a5 2021-01-05 stsp free(branches);
1415 7c0b7f42 2020-09-24 stsp return err;
1418 7c0b7f42 2020-09-24 stsp static const struct got_error *
1419 04d9a9ec 2020-09-24 stsp create_gitconfig(const char *git_url, const char *default_branch,
1420 132af4a5 2021-01-05 stsp int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1421 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, int mirror_references,
1422 99495ddb 2021-01-10 stsp struct got_repository *repo)
1424 7c0b7f42 2020-09-24 stsp const struct got_error *err = NULL;
1425 7c0b7f42 2020-09-24 stsp char *gitconfig_path = NULL;
1426 7c0b7f42 2020-09-24 stsp char *gitconfig = NULL;
1427 7c0b7f42 2020-09-24 stsp FILE *gitconfig_file = NULL;
1428 99495ddb 2021-01-10 stsp char *branches = NULL, *refs = NULL;
1429 56d0a753 2021-01-20 stsp const char *branchname;
1430 7c0b7f42 2020-09-24 stsp ssize_t n;
1432 7c0b7f42 2020-09-24 stsp /* Create a config file Git can understand. */
1433 7c0b7f42 2020-09-24 stsp gitconfig_path = got_repo_get_path_gitconfig(repo);
1434 7c0b7f42 2020-09-24 stsp if (gitconfig_path == NULL) {
1435 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("got_repo_get_path_gitconfig");
1436 7c0b7f42 2020-09-24 stsp goto done;
1438 00fe21f2 2021-12-31 stsp gitconfig_file = fopen(gitconfig_path, "ae");
1439 7c0b7f42 2020-09-24 stsp if (gitconfig_file == NULL) {
1440 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fopen", gitconfig_path);
1441 7c0b7f42 2020-09-24 stsp goto done;
1443 56d0a753 2021-01-20 stsp if (fetch_all_branches) {
1444 56d0a753 2021-01-20 stsp if (mirror_references) {
1445 56d0a753 2021-01-20 stsp if (asprintf(&branches,
1446 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/*:refs/heads/*\n") == -1) {
1447 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1448 56d0a753 2021-01-20 stsp goto done;
1450 56d0a753 2021-01-20 stsp } else if (asprintf(&branches,
1451 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/*:refs/remotes/%s/*\n",
1452 7c0b7f42 2020-09-24 stsp GOT_FETCH_DEFAULT_REMOTE_NAME) == -1) {
1453 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1454 7c0b7f42 2020-09-24 stsp goto done;
1456 132af4a5 2021-01-05 stsp } else if (!TAILQ_EMPTY(wanted_branches)) {
1457 132af4a5 2021-01-05 stsp struct got_pathlist_entry *pe;
1458 132af4a5 2021-01-05 stsp TAILQ_FOREACH(pe, wanted_branches, entry) {
1460 132af4a5 2021-01-05 stsp branchname = pe->path;
1461 132af4a5 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1462 132af4a5 2021-01-05 stsp branchname += 11;
1463 56d0a753 2021-01-20 stsp if (mirror_references) {
1464 56d0a753 2021-01-20 stsp if (asprintf(&s,
1465 56d0a753 2021-01-20 stsp "%s\tfetch = refs/heads/%s:refs/heads/%s\n",
1466 56d0a753 2021-01-20 stsp branches ? branches : "",
1467 56d0a753 2021-01-20 stsp branchname, branchname) == -1) {
1468 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1469 56d0a753 2021-01-20 stsp goto done;
1471 56d0a753 2021-01-20 stsp } else if (asprintf(&s,
1472 56d0a753 2021-01-20 stsp "%s\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1473 132af4a5 2021-01-05 stsp branches ? branches : "",
1474 132af4a5 2021-01-05 stsp branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1475 132af4a5 2021-01-05 stsp branchname) == -1) {
1476 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1477 132af4a5 2021-01-05 stsp goto done;
1479 132af4a5 2021-01-05 stsp free(branches);
1480 132af4a5 2021-01-05 stsp branches = s;
1484 7c0b7f42 2020-09-24 stsp * If the server specified a default branch, use just that one.
1485 7c0b7f42 2020-09-24 stsp * Otherwise fall back to fetching all branches on next fetch.
1487 04d9a9ec 2020-09-24 stsp if (default_branch) {
1488 04d9a9ec 2020-09-24 stsp branchname = default_branch;
1489 7c0b7f42 2020-09-24 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1490 7c0b7f42 2020-09-24 stsp branchname += 11;
1492 7c0b7f42 2020-09-24 stsp branchname = "*"; /* fall back to all branches */
1493 56d0a753 2021-01-20 stsp if (mirror_references) {
1494 56d0a753 2021-01-20 stsp if (asprintf(&branches,
1495 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/%s:refs/heads/%s\n",
1496 56d0a753 2021-01-20 stsp branchname, branchname) == -1) {
1497 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1498 56d0a753 2021-01-20 stsp goto done;
1500 56d0a753 2021-01-20 stsp } else if (asprintf(&branches,
1501 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1502 7c0b7f42 2020-09-24 stsp branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1503 7c0b7f42 2020-09-24 stsp branchname) == -1) {
1504 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1505 7c0b7f42 2020-09-24 stsp goto done;
1508 56d0a753 2021-01-20 stsp if (!TAILQ_EMPTY(wanted_refs)) {
1509 99495ddb 2021-01-10 stsp struct got_pathlist_entry *pe;
1510 99495ddb 2021-01-10 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1512 99495ddb 2021-01-10 stsp const char *refname = pe->path;
1513 99495ddb 2021-01-10 stsp if (strncmp(refname, "refs/", 5) == 0)
1514 99495ddb 2021-01-10 stsp refname += 5;
1515 56d0a753 2021-01-20 stsp if (mirror_references) {
1516 56d0a753 2021-01-20 stsp if (asprintf(&s,
1517 56d0a753 2021-01-20 stsp "%s\tfetch = refs/%s:refs/%s\n",
1518 56d0a753 2021-01-20 stsp refs ? refs : "", refname, refname) == -1) {
1519 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1520 56d0a753 2021-01-20 stsp goto done;
1522 56d0a753 2021-01-20 stsp } else if (asprintf(&s,
1523 56d0a753 2021-01-20 stsp "%s\tfetch = refs/%s:refs/remotes/%s/%s\n",
1524 99495ddb 2021-01-10 stsp refs ? refs : "",
1525 99495ddb 2021-01-10 stsp refname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1526 99495ddb 2021-01-10 stsp refname) == -1) {
1527 99495ddb 2021-01-10 stsp err = got_error_from_errno("asprintf");
1528 99495ddb 2021-01-10 stsp goto done;
1530 99495ddb 2021-01-10 stsp free(refs);
1535 132af4a5 2021-01-05 stsp if (asprintf(&gitconfig,
1536 132af4a5 2021-01-05 stsp "[remote \"%s\"]\n"
1537 132af4a5 2021-01-05 stsp "\turl = %s\n"
1540 56d0a753 2021-01-20 stsp "\tfetch = refs/tags/*:refs/tags/*\n",
1541 132af4a5 2021-01-05 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, git_url, branches ? branches : "",
1542 56d0a753 2021-01-20 stsp refs ? refs : "") == -1) {
1543 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1544 132af4a5 2021-01-05 stsp goto done;
1546 7c0b7f42 2020-09-24 stsp n = fwrite(gitconfig, 1, strlen(gitconfig), gitconfig_file);
1547 7c0b7f42 2020-09-24 stsp if (n != strlen(gitconfig)) {
1548 7c0b7f42 2020-09-24 stsp err = got_ferror(gitconfig_file, GOT_ERR_IO);
1549 7c0b7f42 2020-09-24 stsp goto done;
1552 7c0b7f42 2020-09-24 stsp if (gitconfig_file && fclose(gitconfig_file) == EOF && err == NULL)
1553 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fclose", gitconfig_path);
1554 7c0b7f42 2020-09-24 stsp free(gitconfig_path);
1555 132af4a5 2021-01-05 stsp free(branches);
1556 0e4002ca 2020-03-21 stsp return err;
1559 0e4002ca 2020-03-21 stsp static const struct got_error *
1560 04d9a9ec 2020-09-24 stsp create_config_files(const char *proto, const char *host, const char *port,
1561 04d9a9ec 2020-09-24 stsp const char *remote_repo_path, const char *git_url, int fetch_all_branches,
1562 04d9a9ec 2020-09-24 stsp int mirror_references, struct got_pathlist_head *symrefs,
1563 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_branches,
1564 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, struct got_repository *repo)
1566 04d9a9ec 2020-09-24 stsp const struct got_error *err = NULL;
1567 04d9a9ec 2020-09-24 stsp const char *default_branch = NULL;
1568 04d9a9ec 2020-09-24 stsp struct got_pathlist_entry *pe;
1571 04d9a9ec 2020-09-24 stsp * If we asked for a set of wanted branches then use the first
1572 04d9a9ec 2020-09-24 stsp * one of those.
1574 62d463ca 2020-10-20 naddy if (!TAILQ_EMPTY(wanted_branches)) {
1575 04d9a9ec 2020-09-24 stsp pe = TAILQ_FIRST(wanted_branches);
1576 04d9a9ec 2020-09-24 stsp default_branch = pe->path;
1578 04d9a9ec 2020-09-24 stsp /* First HEAD ref listed by server is the default branch. */
1579 04d9a9ec 2020-09-24 stsp TAILQ_FOREACH(pe, symrefs, entry) {
1580 04d9a9ec 2020-09-24 stsp const char *refname = pe->path;
1581 04d9a9ec 2020-09-24 stsp const char *target = pe->data;
1583 04d9a9ec 2020-09-24 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
1586 04d9a9ec 2020-09-24 stsp default_branch = target;
1591 04d9a9ec 2020-09-24 stsp /* Create got.conf(5). */
1592 04d9a9ec 2020-09-24 stsp err = create_gotconfig(proto, host, port, remote_repo_path,
1593 0c8b29c5 2021-01-05 stsp default_branch, fetch_all_branches, wanted_branches,
1594 99495ddb 2021-01-10 stsp wanted_refs, mirror_references, repo);
1596 04d9a9ec 2020-09-24 stsp return err;
1598 04d9a9ec 2020-09-24 stsp /* Create a config file Git can understand. */
1599 04d9a9ec 2020-09-24 stsp return create_gitconfig(git_url, default_branch, fetch_all_branches,
1600 99495ddb 2021-01-10 stsp wanted_branches, wanted_refs, mirror_references, repo);
1603 04d9a9ec 2020-09-24 stsp static const struct got_error *
1604 93658fb9 2020-03-18 stsp cmd_clone(int argc, char *argv[])
1606 39c64a6a 2020-03-18 stsp const struct got_error *error = NULL;
1607 9df6f38b 2020-03-18 stsp const char *uri, *dirname;
1608 09838ffc 2020-03-18 stsp char *proto, *host, *port, *repo_name, *server_path;
1609 d9b4d0c0 2020-03-18 stsp char *default_destdir = NULL, *id_str = NULL;
1610 a9c2d4c2 2020-09-24 stsp const char *repo_path;
1611 bb64b798 2020-03-18 stsp struct got_repository *repo = NULL;
1612 0e4002ca 2020-03-21 stsp struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
1613 d9b4d0c0 2020-03-18 stsp struct got_pathlist_entry *pe;
1614 d9b4d0c0 2020-03-18 stsp struct got_object_id *pack_hash = NULL;
1615 9c52365f 2020-03-21 stsp int ch, fetchfd = -1, fetchstatus;
1616 9c52365f 2020-03-21 stsp pid_t fetchpid = -1;
1617 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg fpa;
1618 b46f3e71 2020-03-18 stsp char *git_url = NULL;
1619 659e7fbd 2020-03-20 stsp int verbosity = 0, fetch_all_branches = 0, mirror_references = 0;
1620 118a625d 2023-02-18 mark int bflag = 0, list_refs_only = 0;
1621 0ae84acc 2022-06-15 tracey int *pack_fds = NULL;
1623 d9b4d0c0 2020-03-18 stsp TAILQ_INIT(&refs);
1624 d9b4d0c0 2020-03-18 stsp TAILQ_INIT(&symrefs);
1625 4ba14133 2020-03-20 stsp TAILQ_INIT(&wanted_branches);
1626 0e4002ca 2020-03-21 stsp TAILQ_INIT(&wanted_refs);
1628 6f319063 2022-10-27 stsp while ((ch = getopt(argc, argv, "ab:lmqR:v")) != -1) {
1629 93658fb9 2020-03-18 stsp switch (ch) {
1631 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
1634 4ba14133 2020-03-20 stsp error = got_pathlist_append(&wanted_branches,
1635 4ba14133 2020-03-20 stsp optarg, NULL);
1636 4ba14133 2020-03-20 stsp if (error)
1637 4ba14133 2020-03-20 stsp return error;
1638 118a625d 2023-02-18 mark bflag = 1;
1641 41b0de12 2020-03-21 stsp list_refs_only = 1;
1644 469dd726 2020-03-20 stsp mirror_references = 1;
1647 68999b92 2020-03-18 stsp verbosity = -1;
1650 0e4002ca 2020-03-21 stsp error = got_pathlist_append(&wanted_refs,
1651 0e4002ca 2020-03-21 stsp optarg, NULL);
1652 0e4002ca 2020-03-21 stsp if (error)
1653 0e4002ca 2020-03-21 stsp return error;
1656 6f319063 2022-10-27 stsp if (verbosity < 0)
1657 6f319063 2022-10-27 stsp verbosity = 0;
1658 6f319063 2022-10-27 stsp else if (verbosity < 3)
1659 6f319063 2022-10-27 stsp verbosity++;
1662 93658fb9 2020-03-18 stsp usage_clone();
1666 93658fb9 2020-03-18 stsp argc -= optind;
1667 93658fb9 2020-03-18 stsp argv += optind;
1669 4ba14133 2020-03-20 stsp if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
1670 ff69268e 2020-12-13 stsp option_conflict('a', 'b');
1671 41b0de12 2020-03-21 stsp if (list_refs_only) {
1672 41b0de12 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_branches))
1673 ff69268e 2020-12-13 stsp option_conflict('l', 'b');
1674 41b0de12 2020-03-21 stsp if (fetch_all_branches)
1675 ff69268e 2020-12-13 stsp option_conflict('l', 'a');
1676 41b0de12 2020-03-21 stsp if (mirror_references)
1677 ff69268e 2020-12-13 stsp option_conflict('l', 'm');
1678 0e4002ca 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_refs))
1679 ff69268e 2020-12-13 stsp option_conflict('l', 'R');
1682 93658fb9 2020-03-18 stsp uri = argv[0];
1684 9df6f38b 2020-03-18 stsp if (argc == 1)
1685 93658fb9 2020-03-18 stsp dirname = NULL;
1686 9df6f38b 2020-03-18 stsp else if (argc == 2)
1687 93658fb9 2020-03-18 stsp dirname = argv[1];
1689 93658fb9 2020-03-18 stsp usage_clone();
1691 5e5da8c4 2021-09-05 stsp error = got_dial_parse_uri(&proto, &host, &port, &server_path,
1692 4dbec0a8 2020-08-27 stsp &repo_name, uri);
1693 39c64a6a 2020-03-18 stsp if (error)
1694 09f63084 2020-03-20 stsp goto done;
1696 09f63084 2020-03-20 stsp if (asprintf(&git_url, "%s://%s%s%s%s%s", proto,
1697 09f63084 2020-03-20 stsp host, port ? ":" : "", port ? port : "",
1698 09f63084 2020-03-20 stsp server_path[0] != '/' ? "/" : "", server_path) == -1) {
1699 09f63084 2020-03-20 stsp error = got_error_from_errno("asprintf");
1700 09838ffc 2020-03-18 stsp goto done;
1703 39c64a6a 2020-03-18 stsp if (strcmp(proto, "git") == 0) {
1704 b46f3e71 2020-03-18 stsp #ifndef PROFILE
1705 39c64a6a 2020-03-18 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1706 39c64a6a 2020-03-18 stsp "sendfd dns inet unveil", NULL) == -1)
1707 39c64a6a 2020-03-18 stsp err(1, "pledge");
1709 39c64a6a 2020-03-18 stsp } else if (strcmp(proto, "git+ssh") == 0 ||
1710 ced242c2 2024-04-14 me strcmp(proto, "ssh") == 0 ||
1711 ced242c2 2024-04-14 me strcmp(proto, "git+http") == 0 ||
1712 ced242c2 2024-04-14 me strcmp(proto, "http") == 0 ||
1713 ced242c2 2024-04-14 me strcmp(proto, "git+https") == 0 ||
1714 ced242c2 2024-04-14 me strcmp(proto, "https") == 0) {
1715 b46f3e71 2020-03-18 stsp #ifndef PROFILE
1716 39c64a6a 2020-03-18 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1717 39c64a6a 2020-03-18 stsp "sendfd unveil", NULL) == -1)
1718 39c64a6a 2020-03-18 stsp err(1, "pledge");
1721 39c64a6a 2020-03-18 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
1722 39c64a6a 2020-03-18 stsp goto done;
1724 bb64b798 2020-03-18 stsp if (dirname == NULL) {
1725 bb64b798 2020-03-18 stsp if (asprintf(&default_destdir, "%s.git", repo_name) == -1) {
1726 39c64a6a 2020-03-18 stsp error = got_error_from_errno("asprintf");
1727 bb64b798 2020-03-18 stsp goto done;
1729 bb64b798 2020-03-18 stsp repo_path = default_destdir;
1731 bb64b798 2020-03-18 stsp repo_path = dirname;
1733 41b0de12 2020-03-21 stsp if (!list_refs_only) {
1734 41b0de12 2020-03-21 stsp error = got_path_mkdir(repo_path);
1735 2751fe64 2020-09-24 stsp if (error &&
1736 2751fe64 2020-09-24 stsp (!(error->code == GOT_ERR_ERRNO && errno == EISDIR) &&
1737 2751fe64 2020-09-24 stsp !(error->code == GOT_ERR_ERRNO && errno == EEXIST)))
1738 41b0de12 2020-03-21 stsp goto done;
1739 2751fe64 2020-09-24 stsp if (!got_path_dir_is_empty(repo_path)) {
1740 2751fe64 2020-09-24 stsp error = got_error_path(repo_path,
1741 2751fe64 2020-09-24 stsp GOT_ERR_DIR_NOT_EMPTY);
1742 41b0de12 2020-03-21 stsp goto done;
1746 d65a88a2 2021-09-05 stsp error = got_dial_apply_unveil(proto);
1747 d65a88a2 2021-09-05 stsp if (error)
1748 d65a88a2 2021-09-05 stsp goto done;
1750 f535bcd4 2020-09-30 stsp error = apply_unveil(repo_path, 0, NULL);
1751 ee448f5f 2020-03-18 stsp if (error)
1752 ee448f5f 2020-03-18 stsp goto done;
1754 f79e6490 2020-04-19 stsp if (verbosity >= 0)
1755 0deb9607 2022-11-18 op printf("Connecting to %s\n", git_url);
1757 9c52365f 2020-03-21 stsp error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
1758 9c52365f 2020-03-21 stsp server_path, verbosity);
1759 39c64a6a 2020-03-18 stsp if (error)
1760 bb64b798 2020-03-18 stsp goto done;
1762 72cc612f 2024-04-14 stsp #ifndef PROFILE
1763 72cc612f 2024-04-14 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd",
1764 72cc612f 2024-04-14 stsp NULL) == -1)
1765 72cc612f 2024-04-14 stsp err(1, "pledge");
1767 2751fe64 2020-09-24 stsp if (!list_refs_only) {
1768 6f04a73d 2022-09-20 mark error = got_repo_init(repo_path, NULL);
1769 2751fe64 2020-09-24 stsp if (error)
1770 2751fe64 2020-09-24 stsp goto done;
1771 0ae84acc 2022-06-15 tracey error = got_repo_pack_fds_open(&pack_fds);
1772 0ae84acc 2022-06-15 tracey if (error != NULL)
1773 0ae84acc 2022-06-15 tracey goto done;
1774 0ae84acc 2022-06-15 tracey error = got_repo_open(&repo, repo_path, NULL, pack_fds);
1775 2751fe64 2020-09-24 stsp if (error)
1776 2751fe64 2020-09-24 stsp goto done;
1779 892ac3b6 2020-03-18 stsp fpa.last_scaled_size[0] = '\0';
1780 892ac3b6 2020-03-18 stsp fpa.last_p_indexed = -1;
1781 892ac3b6 2020-03-18 stsp fpa.last_p_resolved = -1;
1782 68999b92 2020-03-18 stsp fpa.verbosity = verbosity;
1783 04d9a9ec 2020-09-24 stsp fpa.create_configs = 1;
1784 04d9a9ec 2020-09-24 stsp fpa.configs_created = 0;
1785 04d9a9ec 2020-09-24 stsp fpa.repo = repo;
1786 04d9a9ec 2020-09-24 stsp fpa.config_info.symrefs = &symrefs;
1787 04d9a9ec 2020-09-24 stsp fpa.config_info.wanted_branches = &wanted_branches;
1788 99495ddb 2021-01-10 stsp fpa.config_info.wanted_refs = &wanted_refs;
1789 04d9a9ec 2020-09-24 stsp fpa.config_info.proto = proto;
1790 04d9a9ec 2020-09-24 stsp fpa.config_info.host = host;
1791 04d9a9ec 2020-09-24 stsp fpa.config_info.port = port;
1792 04d9a9ec 2020-09-24 stsp fpa.config_info.remote_repo_path = server_path;
1793 04d9a9ec 2020-09-24 stsp fpa.config_info.git_url = git_url;
1794 04d9a9ec 2020-09-24 stsp fpa.config_info.fetch_all_branches = fetch_all_branches;
1795 04d9a9ec 2020-09-24 stsp fpa.config_info.mirror_references = mirror_references;
1796 7848a0e1 2020-03-19 stsp error = got_fetch_pack(&pack_hash, &refs, &symrefs,
1797 469dd726 2020-03-20 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, mirror_references,
1798 0e4002ca 2020-03-21 stsp fetch_all_branches, &wanted_branches, &wanted_refs,
1799 118a625d 2023-02-18 mark list_refs_only, verbosity, fetchfd, repo, NULL, NULL, bflag,
1800 0e4002ca 2020-03-21 stsp fetch_progress, &fpa);
1801 39c64a6a 2020-03-18 stsp if (error)
1802 d9b4d0c0 2020-03-18 stsp goto done;
1804 41b0de12 2020-03-21 stsp if (list_refs_only) {
1805 41b0de12 2020-03-21 stsp error = list_remote_refs(&symrefs, &refs);
1806 41b0de12 2020-03-21 stsp goto done;
1809 8a4f8535 2021-12-27 stsp if (pack_hash == NULL) {
1810 8a4f8535 2021-12-27 stsp error = got_error_fmt(GOT_ERR_FETCH_FAILED, "%s",
1811 8a4f8535 2021-12-27 stsp "server sent an empty pack file");
1812 8a4f8535 2021-12-27 stsp goto done;
1814 39c64a6a 2020-03-18 stsp error = got_object_id_str(&id_str, pack_hash);
1815 39c64a6a 2020-03-18 stsp if (error)
1816 d9b4d0c0 2020-03-18 stsp goto done;
1817 68999b92 2020-03-18 stsp if (verbosity >= 0)
1818 e69674d8 2020-03-19 stsp printf("\nFetched %s.pack\n", id_str);
1819 d9b4d0c0 2020-03-18 stsp free(id_str);
1821 d9b4d0c0 2020-03-18 stsp /* Set up references provided with the pack file. */
1822 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &refs, entry) {
1823 d9b4d0c0 2020-03-18 stsp const char *refname = pe->path;
1824 d9b4d0c0 2020-03-18 stsp struct got_object_id *id = pe->data;
1825 7ebc0570 2020-03-18 stsp char *remote_refname;
1827 0e4002ca 2020-03-21 stsp if (is_wanted_ref(&wanted_refs, refname) &&
1828 0e4002ca 2020-03-21 stsp !mirror_references) {
1829 0e4002ca 2020-03-21 stsp error = create_wanted_ref(refname, id,
1830 0e4002ca 2020-03-21 stsp GOT_FETCH_DEFAULT_REMOTE_NAME,
1831 0e4002ca 2020-03-21 stsp verbosity - 1, repo);
1832 0e4002ca 2020-03-21 stsp if (error)
1833 0e4002ca 2020-03-21 stsp goto done;
1837 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity - 1, repo);
1838 39c64a6a 2020-03-18 stsp if (error)
1839 d9b4d0c0 2020-03-18 stsp goto done;
1841 469dd726 2020-03-20 stsp if (mirror_references)
1844 7ebc0570 2020-03-18 stsp if (strncmp("refs/heads/", refname, 11) != 0)
1847 7ebc0570 2020-03-18 stsp if (asprintf(&remote_refname,
1848 7ebc0570 2020-03-18 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1849 7ebc0570 2020-03-18 stsp refname + 11) == -1) {
1850 7ebc0570 2020-03-18 stsp error = got_error_from_errno("asprintf");
1851 7ebc0570 2020-03-18 stsp goto done;
1853 6338a6a1 2020-03-21 stsp error = create_ref(remote_refname, id, verbosity - 1, repo);
1854 f298ae0f 2020-03-25 stsp free(remote_refname);
1855 39c64a6a 2020-03-18 stsp if (error)
1856 d9b4d0c0 2020-03-18 stsp goto done;
1859 d9b4d0c0 2020-03-18 stsp /* Set the HEAD reference if the server provided one. */
1860 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
1861 659e7fbd 2020-03-20 stsp struct got_reference *target_ref;
1862 d9b4d0c0 2020-03-18 stsp const char *refname = pe->path;
1863 d9b4d0c0 2020-03-18 stsp const char *target = pe->data;
1864 f298ae0f 2020-03-25 stsp char *remote_refname = NULL, *remote_target = NULL;
1866 d9b4d0c0 2020-03-18 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
1869 39c64a6a 2020-03-18 stsp error = got_ref_open(&target_ref, repo, target, 0);
1870 39c64a6a 2020-03-18 stsp if (error) {
1871 55330abe 2020-03-20 stsp if (error->code == GOT_ERR_NOT_REF) {
1872 55330abe 2020-03-20 stsp error = NULL;
1875 d9b4d0c0 2020-03-18 stsp goto done;
1878 04d9a9ec 2020-09-24 stsp error = create_symref(refname, target_ref, verbosity, repo);
1879 f298ae0f 2020-03-25 stsp got_ref_close(target_ref);
1880 f298ae0f 2020-03-25 stsp if (error)
1881 f298ae0f 2020-03-25 stsp goto done;
1883 f298ae0f 2020-03-25 stsp if (mirror_references)
1886 f298ae0f 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
1889 f298ae0f 2020-03-25 stsp if (asprintf(&remote_refname,
1890 f298ae0f 2020-03-25 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1891 f298ae0f 2020-03-25 stsp refname) == -1) {
1892 f298ae0f 2020-03-25 stsp error = got_error_from_errno("asprintf");
1893 f298ae0f 2020-03-25 stsp goto done;
1895 f298ae0f 2020-03-25 stsp if (asprintf(&remote_target,
1896 f298ae0f 2020-03-25 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1897 f298ae0f 2020-03-25 stsp target + 11) == -1) {
1898 f298ae0f 2020-03-25 stsp error = got_error_from_errno("asprintf");
1899 f298ae0f 2020-03-25 stsp free(remote_refname);
1900 f298ae0f 2020-03-25 stsp goto done;
1902 f298ae0f 2020-03-25 stsp error = got_ref_open(&target_ref, repo, remote_target, 0);
1903 f298ae0f 2020-03-25 stsp if (error) {
1904 f298ae0f 2020-03-25 stsp free(remote_refname);
1905 f298ae0f 2020-03-25 stsp free(remote_target);
1906 f298ae0f 2020-03-25 stsp if (error->code == GOT_ERR_NOT_REF) {
1907 f298ae0f 2020-03-25 stsp error = NULL;
1910 f298ae0f 2020-03-25 stsp goto done;
1912 04d9a9ec 2020-09-24 stsp error = create_symref(remote_refname, target_ref,
1913 04d9a9ec 2020-09-24 stsp verbosity - 1, repo);
1914 f298ae0f 2020-03-25 stsp free(remote_refname);
1915 f298ae0f 2020-03-25 stsp free(remote_target);
1916 d9b4d0c0 2020-03-18 stsp got_ref_close(target_ref);
1917 39c64a6a 2020-03-18 stsp if (error)
1918 d9b4d0c0 2020-03-18 stsp goto done;
1920 4ba14133 2020-03-20 stsp if (pe == NULL) {
1922 4ba14133 2020-03-20 stsp * We failed to set the HEAD reference. If we asked for
1923 4ba14133 2020-03-20 stsp * a set of wanted branches use the first of one of those
1924 4ba14133 2020-03-20 stsp * which could be fetched instead.
1926 62d463ca 2020-10-20 naddy TAILQ_FOREACH(pe, &wanted_branches, entry) {
1927 4ba14133 2020-03-20 stsp const char *target = pe->path;
1928 4ba14133 2020-03-20 stsp struct got_reference *target_ref;
1930 4ba14133 2020-03-20 stsp error = got_ref_open(&target_ref, repo, target, 0);
1931 4ba14133 2020-03-20 stsp if (error) {
1932 4ba14133 2020-03-20 stsp if (error->code == GOT_ERR_NOT_REF) {
1933 4ba14133 2020-03-20 stsp error = NULL;
1936 4ba14133 2020-03-20 stsp goto done;
1939 04d9a9ec 2020-09-24 stsp error = create_symref(GOT_REF_HEAD, target_ref,
1940 04d9a9ec 2020-09-24 stsp verbosity, repo);
1941 4ba14133 2020-03-20 stsp got_ref_close(target_ref);
1942 4ba14133 2020-03-20 stsp if (error)
1943 4ba14133 2020-03-20 stsp goto done;
1947 c9f1ac46 2022-11-08 stsp if (!fpa.configs_created && pe != NULL) {
1948 c9f1ac46 2022-11-08 stsp error = create_config_files(fpa.config_info.proto,
1949 c9f1ac46 2022-11-08 stsp fpa.config_info.host, fpa.config_info.port,
1950 c9f1ac46 2022-11-08 stsp fpa.config_info.remote_repo_path,
1951 c9f1ac46 2022-11-08 stsp fpa.config_info.git_url,
1952 c9f1ac46 2022-11-08 stsp fpa.config_info.fetch_all_branches,
1953 c9f1ac46 2022-11-08 stsp fpa.config_info.mirror_references,
1954 c9f1ac46 2022-11-08 stsp fpa.config_info.symrefs,
1955 c9f1ac46 2022-11-08 stsp fpa.config_info.wanted_branches,
1956 c9f1ac46 2022-11-08 stsp fpa.config_info.wanted_refs, fpa.repo);
1957 c9f1ac46 2022-11-08 stsp if (error)
1958 c9f1ac46 2022-11-08 stsp goto done;
1962 d715f13e 2020-03-19 stsp if (verbosity >= 0)
1963 469dd726 2020-03-20 stsp printf("Created %s repository '%s'\n",
1964 469dd726 2020-03-20 stsp mirror_references ? "mirrored" : "cloned", repo_path);
1966 0ae84acc 2022-06-15 tracey if (pack_fds) {
1967 0ae84acc 2022-06-15 tracey const struct got_error *pack_err =
1968 0ae84acc 2022-06-15 tracey got_repo_pack_fds_close(pack_fds);
1969 0ae84acc 2022-06-15 tracey if (error == NULL)
1970 0ae84acc 2022-06-15 tracey error = pack_err;
1972 9c52365f 2020-03-21 stsp if (fetchpid > 0) {
1973 9c52365f 2020-03-21 stsp if (kill(fetchpid, SIGTERM) == -1)
1974 9c52365f 2020-03-21 stsp error = got_error_from_errno("kill");
1975 9c52365f 2020-03-21 stsp if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
1976 9c52365f 2020-03-21 stsp error = got_error_from_errno("waitpid");
1978 39c64a6a 2020-03-18 stsp if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
1979 39c64a6a 2020-03-18 stsp error = got_error_from_errno("close");
1980 1d0f4054 2021-06-17 stsp if (repo) {
1981 1d0f4054 2021-06-17 stsp const struct got_error *close_err = got_repo_close(repo);
1982 1d0f4054 2021-06-17 stsp if (error == NULL)
1983 1d0f4054 2021-06-17 stsp error = close_err;
1985 d8bacb93 2023-01-10 mark got_pathlist_free(&refs, GOT_PATHLIST_FREE_ALL);
1986 d8bacb93 2023-01-10 mark got_pathlist_free(&symrefs, GOT_PATHLIST_FREE_ALL);
1987 d8bacb93 2023-01-10 mark got_pathlist_free(&wanted_branches, GOT_PATHLIST_FREE_NONE);
1988 d8bacb93 2023-01-10 mark got_pathlist_free(&wanted_refs, GOT_PATHLIST_FREE_NONE);
1989 d9b4d0c0 2020-03-18 stsp free(pack_hash);
1990 09838ffc 2020-03-18 stsp free(proto);
1991 09838ffc 2020-03-18 stsp free(host);
1992 09838ffc 2020-03-18 stsp free(port);
1993 09838ffc 2020-03-18 stsp free(server_path);
1994 09838ffc 2020-03-18 stsp free(repo_name);
1995 bb64b798 2020-03-18 stsp free(default_destdir);
1996 b46f3e71 2020-03-18 stsp free(git_url);
1997 39c64a6a 2020-03-18 stsp return error;
2000 7848a0e1 2020-03-19 stsp static const struct got_error *
2001 7848a0e1 2020-03-19 stsp update_ref(struct got_reference *ref, struct got_object_id *new_id,
2002 db6d8ad8 2020-03-21 stsp int replace_tags, int verbosity, struct got_repository *repo)
2004 7848a0e1 2020-03-19 stsp const struct got_error *err = NULL;
2005 7848a0e1 2020-03-19 stsp char *new_id_str = NULL;
2006 7848a0e1 2020-03-19 stsp struct got_object_id *old_id = NULL;
2008 7848a0e1 2020-03-19 stsp err = got_object_id_str(&new_id_str, new_id);
2010 7848a0e1 2020-03-19 stsp goto done;
2012 db6d8ad8 2020-03-21 stsp if (!replace_tags &&
2013 db6d8ad8 2020-03-21 stsp strncmp(got_ref_get_name(ref), "refs/tags/", 10) == 0) {
2014 88609724 2020-03-21 stsp err = got_ref_resolve(&old_id, repo, ref);
2016 88609724 2020-03-21 stsp goto done;
2017 88609724 2020-03-21 stsp if (got_object_id_cmp(old_id, new_id) == 0)
2018 88609724 2020-03-21 stsp goto done;
2019 db6d8ad8 2020-03-21 stsp if (verbosity >= 0) {
2020 db6d8ad8 2020-03-21 stsp printf("Rejecting update of existing tag %s: %s\n",
2021 db6d8ad8 2020-03-21 stsp got_ref_get_name(ref), new_id_str);
2023 db6d8ad8 2020-03-21 stsp goto done;
2026 7848a0e1 2020-03-19 stsp if (got_ref_is_symbolic(ref)) {
2027 688f11b3 2020-03-21 stsp if (verbosity >= 0) {
2028 e8a967e0 2020-03-21 stsp printf("Replacing reference %s: %s\n",
2029 6338a6a1 2020-03-21 stsp got_ref_get_name(ref),
2030 6338a6a1 2020-03-21 stsp got_ref_get_symref_target(ref));
2032 e8a967e0 2020-03-21 stsp err = got_ref_change_symref_to_ref(ref, new_id);
2034 7848a0e1 2020-03-19 stsp goto done;
2035 e8a967e0 2020-03-21 stsp err = got_ref_write(ref, repo);
2037 e8a967e0 2020-03-21 stsp goto done;
2039 7848a0e1 2020-03-19 stsp err = got_ref_resolve(&old_id, repo, ref);
2041 7848a0e1 2020-03-19 stsp goto done;
2042 6338a6a1 2020-03-21 stsp if (got_object_id_cmp(old_id, new_id) == 0)
2043 6338a6a1 2020-03-21 stsp goto done;
2045 6338a6a1 2020-03-21 stsp err = got_ref_change_ref(ref, new_id);
2047 6338a6a1 2020-03-21 stsp goto done;
2048 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
2050 6338a6a1 2020-03-21 stsp goto done;
2053 6338a6a1 2020-03-21 stsp if (verbosity >= 0)
2054 f4d0e3fb 2020-05-15 stsp printf("Updated %s: %s\n", got_ref_get_name(ref),
2055 6338a6a1 2020-03-21 stsp new_id_str);
2057 7848a0e1 2020-03-19 stsp free(old_id);
2058 7848a0e1 2020-03-19 stsp free(new_id_str);
2059 7848a0e1 2020-03-19 stsp return err;
2062 f1bcca34 2020-03-25 stsp static const struct got_error *
2063 f1bcca34 2020-03-25 stsp update_symref(const char *refname, struct got_reference *target_ref,
2064 f1bcca34 2020-03-25 stsp int verbosity, struct got_repository *repo)
2066 f1bcca34 2020-03-25 stsp const struct got_error *err = NULL, *unlock_err;
2067 f1bcca34 2020-03-25 stsp struct got_reference *symref;
2068 bcf34b0e 2020-03-26 stsp int symref_is_locked = 0;
2070 f1bcca34 2020-03-25 stsp err = got_ref_open(&symref, repo, refname, 1);
2071 bcf34b0e 2020-03-26 stsp if (err) {
2072 bcf34b0e 2020-03-26 stsp if (err->code != GOT_ERR_NOT_REF)
2073 bcf34b0e 2020-03-26 stsp return err;
2074 bcf34b0e 2020-03-26 stsp err = got_ref_alloc_symref(&symref, refname, target_ref);
2076 bcf34b0e 2020-03-26 stsp goto done;
2078 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
2080 bcf34b0e 2020-03-26 stsp goto done;
2082 bcf34b0e 2020-03-26 stsp if (verbosity >= 0)
2083 bcf34b0e 2020-03-26 stsp printf("Created reference %s: %s\n",
2084 bcf34b0e 2020-03-26 stsp got_ref_get_name(symref),
2085 bcf34b0e 2020-03-26 stsp got_ref_get_symref_target(symref));
2087 bcf34b0e 2020-03-26 stsp symref_is_locked = 1;
2089 bcf34b0e 2020-03-26 stsp if (strcmp(got_ref_get_symref_target(symref),
2090 bcf34b0e 2020-03-26 stsp got_ref_get_name(target_ref)) == 0)
2091 bcf34b0e 2020-03-26 stsp goto done;
2093 bcf34b0e 2020-03-26 stsp err = got_ref_change_symref(symref,
2094 bcf34b0e 2020-03-26 stsp got_ref_get_name(target_ref));
2096 bcf34b0e 2020-03-26 stsp goto done;
2098 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
2100 bcf34b0e 2020-03-26 stsp goto done;
2102 bcf34b0e 2020-03-26 stsp if (verbosity >= 0)
2103 f4d0e3fb 2020-05-15 stsp printf("Updated %s: %s\n", got_ref_get_name(symref),
2104 bcf34b0e 2020-03-26 stsp got_ref_get_symref_target(symref));
2108 bcf34b0e 2020-03-26 stsp if (symref_is_locked) {
2109 bcf34b0e 2020-03-26 stsp unlock_err = got_ref_unlock(symref);
2110 bcf34b0e 2020-03-26 stsp if (unlock_err && err == NULL)
2111 bcf34b0e 2020-03-26 stsp err = unlock_err;
2113 f1bcca34 2020-03-25 stsp got_ref_close(symref);
2114 f1bcca34 2020-03-25 stsp return err;
2117 2ab43947 2020-03-18 stsp __dead static void
2118 7848a0e1 2020-03-19 stsp usage_fetch(void)
2120 827a167b 2022-08-16 stsp fprintf(stderr, "usage: %s fetch [-adlqtvX] [-b branch] "
2121 827a167b 2022-08-16 stsp "[-R reference] [-r repository-path] [remote-repository]\n",
2122 13f12b09 2020-03-21 stsp getprogname());
2126 7848a0e1 2020-03-19 stsp static const struct got_error *
2127 3789fd73 2020-03-26 stsp delete_missing_ref(struct got_reference *ref,
2128 688f11b3 2020-03-21 stsp int verbosity, struct got_repository *repo)
2130 f21ec2f0 2020-03-21 stsp const struct got_error *err = NULL;
2131 3789fd73 2020-03-26 stsp struct got_object_id *id = NULL;
2132 3789fd73 2020-03-26 stsp char *id_str = NULL;
2134 3789fd73 2020-03-26 stsp if (got_ref_is_symbolic(ref)) {
2135 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
2137 3789fd73 2020-03-26 stsp return err;
2138 3789fd73 2020-03-26 stsp if (verbosity >= 0) {
2139 f9d54ee6 2021-07-16 stsp printf("Deleted %s: %s\n",
2140 3789fd73 2020-03-26 stsp got_ref_get_name(ref),
2141 3789fd73 2020-03-26 stsp got_ref_get_symref_target(ref));
2144 3789fd73 2020-03-26 stsp err = got_ref_resolve(&id, repo, ref);
2146 3789fd73 2020-03-26 stsp return err;
2147 3789fd73 2020-03-26 stsp err = got_object_id_str(&id_str, id);
2149 3789fd73 2020-03-26 stsp goto done;
2151 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
2153 3789fd73 2020-03-26 stsp goto done;
2154 3789fd73 2020-03-26 stsp if (verbosity >= 0) {
2155 f9d54ee6 2021-07-16 stsp printf("Deleted %s: %s\n",
2156 3789fd73 2020-03-26 stsp got_ref_get_name(ref), id_str);
2161 3789fd73 2020-03-26 stsp free(id_str);
2162 c33c3763 2023-02-03 mark return err;
2165 3789fd73 2020-03-26 stsp static const struct got_error *
2166 3789fd73 2020-03-26 stsp delete_missing_refs(struct got_pathlist_head *their_refs,
2167 50b0790e 2020-09-11 stsp struct got_pathlist_head *their_symrefs,
2168 50b0790e 2020-09-11 stsp const struct got_remote_repo *remote,
2169 3789fd73 2020-03-26 stsp int verbosity, struct got_repository *repo)
2171 3789fd73 2020-03-26 stsp const struct got_error *err = NULL, *unlock_err;
2172 f21ec2f0 2020-03-21 stsp struct got_reflist_head my_refs;
2173 f21ec2f0 2020-03-21 stsp struct got_reflist_entry *re;
2174 f21ec2f0 2020-03-21 stsp struct got_pathlist_entry *pe;
2175 3789fd73 2020-03-26 stsp char *remote_namespace = NULL;
2176 3789fd73 2020-03-26 stsp char *local_refname = NULL;
2178 d9dff0e5 2020-12-26 stsp TAILQ_INIT(&my_refs);
2180 3789fd73 2020-03-26 stsp if (asprintf(&remote_namespace, "refs/remotes/%s/", remote->name)
2182 3789fd73 2020-03-26 stsp return got_error_from_errno("asprintf");
2184 f21ec2f0 2020-03-21 stsp err = got_ref_list(&my_refs, repo, NULL, got_ref_cmp_by_name, NULL);
2186 3789fd73 2020-03-26 stsp goto done;
2188 d9dff0e5 2020-12-26 stsp TAILQ_FOREACH(re, &my_refs, entry) {
2189 f21ec2f0 2020-03-21 stsp const char *refname = got_ref_get_name(re->ref);
2190 1b796c3f 2021-09-11 stsp const char *their_refname;
2192 1b796c3f 2021-09-11 stsp if (remote->mirror_references) {
2193 1b796c3f 2021-09-11 stsp their_refname = refname;
2195 3789fd73 2020-03-26 stsp if (strncmp(refname, remote_namespace,
2196 3789fd73 2020-03-26 stsp strlen(remote_namespace)) == 0) {
2197 3789fd73 2020-03-26 stsp if (strcmp(refname + strlen(remote_namespace),
2198 3789fd73 2020-03-26 stsp GOT_REF_HEAD) == 0)
2200 3789fd73 2020-03-26 stsp if (asprintf(&local_refname, "refs/heads/%s",
2201 3789fd73 2020-03-26 stsp refname + strlen(remote_namespace)) == -1) {
2202 3789fd73 2020-03-26 stsp err = got_error_from_errno("asprintf");
2203 3789fd73 2020-03-26 stsp goto done;
2205 3789fd73 2020-03-26 stsp } else if (strncmp(refname, "refs/tags/", 10) != 0)
2208 1b796c3f 2021-09-11 stsp their_refname = local_refname;
2211 f21ec2f0 2020-03-21 stsp TAILQ_FOREACH(pe, their_refs, entry) {
2212 1b796c3f 2021-09-11 stsp if (strcmp(their_refname, pe->path) == 0)
2215 f21ec2f0 2020-03-21 stsp if (pe != NULL)
2218 3789fd73 2020-03-26 stsp TAILQ_FOREACH(pe, their_symrefs, entry) {
2219 1b796c3f 2021-09-11 stsp if (strcmp(their_refname, pe->path) == 0)
2222 3789fd73 2020-03-26 stsp if (pe != NULL)
2225 3789fd73 2020-03-26 stsp err = delete_missing_ref(re->ref, verbosity, repo);
2229 3789fd73 2020-03-26 stsp if (local_refname) {
2230 3789fd73 2020-03-26 stsp struct got_reference *ref;
2231 3789fd73 2020-03-26 stsp err = got_ref_open(&ref, repo, local_refname, 1);
2232 3789fd73 2020-03-26 stsp if (err) {
2233 3789fd73 2020-03-26 stsp if (err->code != GOT_ERR_NOT_REF)
2235 3789fd73 2020-03-26 stsp free(local_refname);
2236 3789fd73 2020-03-26 stsp local_refname = NULL;
2239 3789fd73 2020-03-26 stsp err = delete_missing_ref(ref, verbosity, repo);
2242 3789fd73 2020-03-26 stsp unlock_err = got_ref_unlock(ref);
2243 3789fd73 2020-03-26 stsp got_ref_close(ref);
2244 3789fd73 2020-03-26 stsp if (unlock_err && err == NULL) {
2245 3789fd73 2020-03-26 stsp err = unlock_err;
2249 3789fd73 2020-03-26 stsp free(local_refname);
2250 3789fd73 2020-03-26 stsp local_refname = NULL;
2254 0e51642e 2022-10-12 stsp got_ref_list_free(&my_refs);
2255 3789fd73 2020-03-26 stsp free(remote_namespace);
2256 3789fd73 2020-03-26 stsp free(local_refname);
2257 0e4002ca 2020-03-21 stsp return err;
2260 0e4002ca 2020-03-21 stsp static const struct got_error *
2261 0e4002ca 2020-03-21 stsp update_wanted_ref(const char *refname, struct got_object_id *id,
2262 0e4002ca 2020-03-21 stsp const char *remote_repo_name, int verbosity, struct got_repository *repo)
2264 9f142382 2020-03-21 stsp const struct got_error *err, *unlock_err;
2265 0e4002ca 2020-03-21 stsp char *remote_refname;
2266 0e4002ca 2020-03-21 stsp struct got_reference *ref;
2268 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
2269 0e4002ca 2020-03-21 stsp refname += 5;
2271 0e4002ca 2020-03-21 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2272 0e4002ca 2020-03-21 stsp remote_repo_name, refname) == -1)
2273 0e4002ca 2020-03-21 stsp return got_error_from_errno("asprintf");
2275 9f142382 2020-03-21 stsp err = got_ref_open(&ref, repo, remote_refname, 1);
2276 0e4002ca 2020-03-21 stsp if (err) {
2277 0e4002ca 2020-03-21 stsp if (err->code != GOT_ERR_NOT_REF)
2278 0e4002ca 2020-03-21 stsp goto done;
2279 0e4002ca 2020-03-21 stsp err = create_ref(remote_refname, id, verbosity, repo);
2281 0e4002ca 2020-03-21 stsp err = update_ref(ref, id, 0, verbosity, repo);
2282 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2283 9f142382 2020-03-21 stsp if (unlock_err && err == NULL)
2284 9f142382 2020-03-21 stsp err = unlock_err;
2285 0e4002ca 2020-03-21 stsp got_ref_close(ref);
2288 0e4002ca 2020-03-21 stsp free(remote_refname);
2289 161728eb 2021-07-24 stsp return err;
2292 161728eb 2021-07-24 stsp static const struct got_error *
2293 161728eb 2021-07-24 stsp delete_ref(struct got_repository *repo, struct got_reference *ref)
2295 161728eb 2021-07-24 stsp const struct got_error *err = NULL;
2296 161728eb 2021-07-24 stsp struct got_object_id *id = NULL;
2297 161728eb 2021-07-24 stsp char *id_str = NULL;
2298 161728eb 2021-07-24 stsp const char *target;
2300 161728eb 2021-07-24 stsp if (got_ref_is_symbolic(ref)) {
2301 161728eb 2021-07-24 stsp target = got_ref_get_symref_target(ref);
2303 161728eb 2021-07-24 stsp err = got_ref_resolve(&id, repo, ref);
2305 161728eb 2021-07-24 stsp goto done;
2306 161728eb 2021-07-24 stsp err = got_object_id_str(&id_str, id);
2308 161728eb 2021-07-24 stsp goto done;
2309 161728eb 2021-07-24 stsp target = id_str;
2312 161728eb 2021-07-24 stsp err = got_ref_delete(ref, repo);
2314 161728eb 2021-07-24 stsp goto done;
2316 161728eb 2021-07-24 stsp printf("Deleted %s: %s\n", got_ref_get_name(ref), target);
2319 161728eb 2021-07-24 stsp free(id_str);
2320 f21ec2f0 2020-03-21 stsp return err;
2323 f21ec2f0 2020-03-21 stsp static const struct got_error *
2324 161728eb 2021-07-24 stsp delete_refs_for_remote(struct got_repository *repo, const char *remote_name)
2326 161728eb 2021-07-24 stsp const struct got_error *err = NULL;
2327 161728eb 2021-07-24 stsp struct got_reflist_head refs;
2328 161728eb 2021-07-24 stsp struct got_reflist_entry *re;
2329 161728eb 2021-07-24 stsp char *prefix;
2331 161728eb 2021-07-24 stsp TAILQ_INIT(&refs);
2333 161728eb 2021-07-24 stsp if (asprintf(&prefix, "refs/remotes/%s", remote_name) == -1) {
2334 161728eb 2021-07-24 stsp err = got_error_from_errno("asprintf");
2335 161728eb 2021-07-24 stsp goto done;
2337 161728eb 2021-07-24 stsp err = got_ref_list(&refs, repo, prefix, got_ref_cmp_by_name, NULL);
2339 161728eb 2021-07-24 stsp goto done;
2341 161728eb 2021-07-24 stsp TAILQ_FOREACH(re, &refs, entry)
2342 161728eb 2021-07-24 stsp delete_ref(repo, re->ref);
2344 161728eb 2021-07-24 stsp got_ref_list_free(&refs);
2345 161728eb 2021-07-24 stsp return err;
2348 161728eb 2021-07-24 stsp static const struct got_error *
2349 7848a0e1 2020-03-19 stsp cmd_fetch(int argc, char *argv[])
2351 9f142382 2020-03-21 stsp const struct got_error *error = NULL, *unlock_err;
2352 7848a0e1 2020-03-19 stsp char *cwd = NULL, *repo_path = NULL;
2353 7848a0e1 2020-03-19 stsp const char *remote_name;
2354 7848a0e1 2020-03-19 stsp char *proto = NULL, *host = NULL, *port = NULL;
2355 7848a0e1 2020-03-19 stsp char *repo_name = NULL, *server_path = NULL;
2356 db82695e 2023-09-05 stsp const struct got_remote_repo *remotes;
2357 db82695e 2023-09-05 stsp struct got_remote_repo *remote = NULL;
2358 7848a0e1 2020-03-19 stsp int nremotes;
2359 7848a0e1 2020-03-19 stsp char *id_str = NULL;
2360 7848a0e1 2020-03-19 stsp struct got_repository *repo = NULL;
2361 7848a0e1 2020-03-19 stsp struct got_worktree *worktree = NULL;
2362 50b0790e 2020-09-11 stsp const struct got_gotconfig *repo_conf = NULL, *worktree_conf = NULL;
2363 0e4002ca 2020-03-21 stsp struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
2364 48d13ac6 2023-09-05 stsp char *head_refname = NULL;
2365 7848a0e1 2020-03-19 stsp struct got_pathlist_entry *pe;
2366 118a625d 2023-02-18 mark struct got_reflist_head remote_refs;
2367 118a625d 2023-02-18 mark struct got_reflist_entry *re;
2368 7848a0e1 2020-03-19 stsp struct got_object_id *pack_hash = NULL;
2369 9c52365f 2020-03-21 stsp int i, ch, fetchfd = -1, fetchstatus;
2370 9c52365f 2020-03-21 stsp pid_t fetchpid = -1;
2371 7848a0e1 2020-03-19 stsp struct got_fetch_progress_arg fpa;
2372 41b0de12 2020-03-21 stsp int verbosity = 0, fetch_all_branches = 0, list_refs_only = 0;
2373 161728eb 2021-07-24 stsp int delete_refs = 0, replace_tags = 0, delete_remote = 0;
2374 188f8dcf 2023-02-07 stsp int *pack_fds = NULL, have_bflag = 0;
2375 118a625d 2023-02-18 mark const char *remote_head = NULL, *worktree_branch = NULL;
2377 7848a0e1 2020-03-19 stsp TAILQ_INIT(&refs);
2378 7848a0e1 2020-03-19 stsp TAILQ_INIT(&symrefs);
2379 118a625d 2023-02-18 mark TAILQ_INIT(&remote_refs);
2380 4ba14133 2020-03-20 stsp TAILQ_INIT(&wanted_branches);
2381 0e4002ca 2020-03-21 stsp TAILQ_INIT(&wanted_refs);
2383 6f319063 2022-10-27 stsp while ((ch = getopt(argc, argv, "ab:dlqR:r:tvX")) != -1) {
2384 7848a0e1 2020-03-19 stsp switch (ch) {
2386 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
2389 4ba14133 2020-03-20 stsp error = got_pathlist_append(&wanted_branches,
2390 4ba14133 2020-03-20 stsp optarg, NULL);
2391 4ba14133 2020-03-20 stsp if (error)
2392 4ba14133 2020-03-20 stsp return error;
2393 188f8dcf 2023-02-07 stsp have_bflag = 1;
2396 f21ec2f0 2020-03-21 stsp delete_refs = 1;
2399 41b0de12 2020-03-21 stsp list_refs_only = 1;
2402 6f319063 2022-10-27 stsp verbosity = -1;
2405 6f319063 2022-10-27 stsp error = got_pathlist_append(&wanted_refs,
2406 6f319063 2022-10-27 stsp optarg, NULL);
2407 6f319063 2022-10-27 stsp if (error)
2408 6f319063 2022-10-27 stsp return error;
2411 7848a0e1 2020-03-19 stsp repo_path = realpath(optarg, NULL);
2412 7848a0e1 2020-03-19 stsp if (repo_path == NULL)
2413 7848a0e1 2020-03-19 stsp return got_error_from_errno2("realpath",
2415 7848a0e1 2020-03-19 stsp got_path_strip_trailing_slashes(repo_path);
2418 db6d8ad8 2020-03-21 stsp replace_tags = 1;
2421 7848a0e1 2020-03-19 stsp if (verbosity < 0)
2422 7848a0e1 2020-03-19 stsp verbosity = 0;
2423 7848a0e1 2020-03-19 stsp else if (verbosity < 3)
2424 7848a0e1 2020-03-19 stsp verbosity++;
2427 161728eb 2021-07-24 stsp delete_remote = 1;
2430 7848a0e1 2020-03-19 stsp usage_fetch();
2434 7848a0e1 2020-03-19 stsp argc -= optind;
2435 7848a0e1 2020-03-19 stsp argv += optind;
2437 4ba14133 2020-03-20 stsp if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
2438 ff69268e 2020-12-13 stsp option_conflict('a', 'b');
2439 41b0de12 2020-03-21 stsp if (list_refs_only) {
2440 41b0de12 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_branches))
2441 ff69268e 2020-12-13 stsp option_conflict('l', 'b');
2442 ff69268e 2020-12-13 stsp if (fetch_all_branches)
2443 ff69268e 2020-12-13 stsp option_conflict('l', 'a');
2444 f21ec2f0 2020-03-21 stsp if (delete_refs)
2445 ff69268e 2020-12-13 stsp option_conflict('l', 'd');
2446 161728eb 2021-07-24 stsp if (delete_remote)
2447 161728eb 2021-07-24 stsp option_conflict('l', 'X');
2449 161728eb 2021-07-24 stsp if (delete_remote) {
2450 161728eb 2021-07-24 stsp if (fetch_all_branches)
2451 161728eb 2021-07-24 stsp option_conflict('X', 'a');
2452 161728eb 2021-07-24 stsp if (!TAILQ_EMPTY(&wanted_branches))
2453 161728eb 2021-07-24 stsp option_conflict('X', 'b');
2454 161728eb 2021-07-24 stsp if (delete_refs)
2455 161728eb 2021-07-24 stsp option_conflict('X', 'd');
2456 161728eb 2021-07-24 stsp if (replace_tags)
2457 161728eb 2021-07-24 stsp option_conflict('X', 't');
2458 161728eb 2021-07-24 stsp if (!TAILQ_EMPTY(&wanted_refs))
2459 161728eb 2021-07-24 stsp option_conflict('X', 'R');
2462 161728eb 2021-07-24 stsp if (argc == 0) {
2463 161728eb 2021-07-24 stsp if (delete_remote)
2464 161728eb 2021-07-24 stsp errx(1, "-X option requires a remote name");
2465 7848a0e1 2020-03-19 stsp remote_name = GOT_FETCH_DEFAULT_REMOTE_NAME;
2466 161728eb 2021-07-24 stsp } else if (argc == 1)
2467 7848a0e1 2020-03-19 stsp remote_name = argv[0];
2469 7848a0e1 2020-03-19 stsp usage_fetch();
2471 7848a0e1 2020-03-19 stsp cwd = getcwd(NULL, 0);
2472 7848a0e1 2020-03-19 stsp if (cwd == NULL) {
2473 7848a0e1 2020-03-19 stsp error = got_error_from_errno("getcwd");
2474 7848a0e1 2020-03-19 stsp goto done;
2477 0ae84acc 2022-06-15 tracey error = got_repo_pack_fds_open(&pack_fds);
2478 0ae84acc 2022-06-15 tracey if (error != NULL)
2479 0ae84acc 2022-06-15 tracey goto done;
2481 7848a0e1 2020-03-19 stsp if (repo_path == NULL) {
2482 df6221c7 2023-07-19 stsp error = got_worktree_open(&worktree, cwd, GOT_WORKTREE_GOT_DIR);
2483 7848a0e1 2020-03-19 stsp if (error && error->code != GOT_ERR_NOT_WORKTREE)
2484 7848a0e1 2020-03-19 stsp goto done;
2486 7848a0e1 2020-03-19 stsp error = NULL;
2487 7848a0e1 2020-03-19 stsp if (worktree) {
2488 7848a0e1 2020-03-19 stsp repo_path =
2489 7848a0e1 2020-03-19 stsp strdup(got_worktree_get_repo_path(worktree));
2490 7848a0e1 2020-03-19 stsp if (repo_path == NULL)
2491 7848a0e1 2020-03-19 stsp error = got_error_from_errno("strdup");
2492 7848a0e1 2020-03-19 stsp if (error)
2493 7848a0e1 2020-03-19 stsp goto done;
2495 7848a0e1 2020-03-19 stsp repo_path = strdup(cwd);
2496 7848a0e1 2020-03-19 stsp if (repo_path == NULL) {
2497 7848a0e1 2020-03-19 stsp error = got_error_from_errno("strdup");
2498 7848a0e1 2020-03-19 stsp goto done;
2503 0ae84acc 2022-06-15 tracey error = got_repo_open(&repo, repo_path, NULL, pack_fds);
2504 7848a0e1 2020-03-19 stsp if (error)
2505 7848a0e1 2020-03-19 stsp goto done;
2507 161728eb 2021-07-24 stsp if (delete_remote) {
2508 161728eb 2021-07-24 stsp error = delete_refs_for_remote(repo, remote_name);
2509 161728eb 2021-07-24 stsp goto done; /* nothing else to do */
2512 50b0790e 2020-09-11 stsp if (worktree) {
2513 50b0790e 2020-09-11 stsp worktree_conf = got_worktree_get_gotconfig(worktree);
2514 50b0790e 2020-09-11 stsp if (worktree_conf) {
2515 50b0790e 2020-09-11 stsp got_gotconfig_get_remotes(&nremotes, &remotes,
2516 50b0790e 2020-09-11 stsp worktree_conf);
2517 50b0790e 2020-09-11 stsp for (i = 0; i < nremotes; i++) {
2518 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2519 db82695e 2023-09-05 stsp error = got_repo_remote_repo_dup(&remote,
2520 db82695e 2023-09-05 stsp &remotes[i]);
2521 db82695e 2023-09-05 stsp if (error)
2522 db82695e 2023-09-05 stsp goto done;
2528 50b0790e 2020-09-11 stsp if (remote == NULL) {
2529 50b0790e 2020-09-11 stsp repo_conf = got_repo_get_gotconfig(repo);
2530 50b0790e 2020-09-11 stsp if (repo_conf) {
2531 50b0790e 2020-09-11 stsp got_gotconfig_get_remotes(&nremotes, &remotes,
2532 50b0790e 2020-09-11 stsp repo_conf);
2533 50b0790e 2020-09-11 stsp for (i = 0; i < nremotes; i++) {
2534 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2535 db82695e 2023-09-05 stsp error = got_repo_remote_repo_dup(&remote,
2536 db82695e 2023-09-05 stsp &remotes[i]);
2537 db82695e 2023-09-05 stsp if (error)
2538 db82695e 2023-09-05 stsp goto done;
2544 50b0790e 2020-09-11 stsp if (remote == NULL) {
2545 257add31 2020-09-09 stsp got_repo_get_gitconfig_remotes(&nremotes, &remotes, repo);
2546 257add31 2020-09-09 stsp for (i = 0; i < nremotes; i++) {
2547 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2548 db82695e 2023-09-05 stsp error = got_repo_remote_repo_dup(&remote,
2549 db82695e 2023-09-05 stsp &remotes[i]);
2550 db82695e 2023-09-05 stsp if (error)
2551 db82695e 2023-09-05 stsp goto done;
2556 50b0790e 2020-09-11 stsp if (remote == NULL) {
2557 50b0790e 2020-09-11 stsp error = got_error_path(remote_name, GOT_ERR_NO_REMOTE);
2558 50b0790e 2020-09-11 stsp goto done;
2561 0c8b29c5 2021-01-05 stsp if (TAILQ_EMPTY(&wanted_branches)) {
2562 0c8b29c5 2021-01-05 stsp if (!fetch_all_branches)
2563 0c8b29c5 2021-01-05 stsp fetch_all_branches = remote->fetch_all_branches;
2564 6480c871 2021-08-30 stsp for (i = 0; i < remote->nfetch_branches; i++) {
2565 38ef2333 2023-01-10 mark error = got_pathlist_append(&wanted_branches,
2566 6480c871 2021-08-30 stsp remote->fetch_branches[i], NULL);
2567 ccbbf026 2023-02-06 stsp if (error)
2568 ccbbf026 2023-02-06 stsp goto done;
2571 99495ddb 2021-01-10 stsp if (TAILQ_EMPTY(&wanted_refs)) {
2572 6480c871 2021-08-30 stsp for (i = 0; i < remote->nfetch_refs; i++) {
2573 38ef2333 2023-01-10 mark error = got_pathlist_append(&wanted_refs,
2574 6480c871 2021-08-30 stsp remote->fetch_refs[i], NULL);
2575 38ef2333 2023-01-10 mark if (error)
2576 38ef2333 2023-01-10 mark goto done;
2580 5e5da8c4 2021-09-05 stsp error = got_dial_parse_uri(&proto, &host, &port, &server_path,
2581 6480c871 2021-08-30 stsp &repo_name, remote->fetch_url);
2582 7848a0e1 2020-03-19 stsp if (error)
2583 7848a0e1 2020-03-19 stsp goto done;
2585 7848a0e1 2020-03-19 stsp if (strcmp(proto, "git") == 0) {
2586 7848a0e1 2020-03-19 stsp #ifndef PROFILE
2587 7848a0e1 2020-03-19 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2588 7848a0e1 2020-03-19 stsp "sendfd dns inet unveil", NULL) == -1)
2589 7848a0e1 2020-03-19 stsp err(1, "pledge");
2591 7848a0e1 2020-03-19 stsp } else if (strcmp(proto, "git+ssh") == 0 ||
2592 ced242c2 2024-04-14 me strcmp(proto, "ssh") == 0 ||
2593 ced242c2 2024-04-14 me strcmp(proto, "git+http") == 0 ||
2594 ced242c2 2024-04-14 me strcmp(proto, "http") == 0 ||
2595 ced242c2 2024-04-14 me strcmp(proto, "git+https") == 0 ||
2596 ced242c2 2024-04-14 me strcmp(proto, "https") == 0) {
2597 7848a0e1 2020-03-19 stsp #ifndef PROFILE
2598 7848a0e1 2020-03-19 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2599 7848a0e1 2020-03-19 stsp "sendfd unveil", NULL) == -1)
2600 7848a0e1 2020-03-19 stsp err(1, "pledge");
2603 7848a0e1 2020-03-19 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
2604 7848a0e1 2020-03-19 stsp goto done;
2607 d65a88a2 2021-09-05 stsp error = got_dial_apply_unveil(proto);
2608 d65a88a2 2021-09-05 stsp if (error)
2609 d65a88a2 2021-09-05 stsp goto done;
2611 7848a0e1 2020-03-19 stsp error = apply_unveil(got_repo_get_path(repo), 0, NULL);
2612 7848a0e1 2020-03-19 stsp if (error)
2613 7848a0e1 2020-03-19 stsp goto done;
2615 48d13ac6 2023-09-05 stsp if (worktree) {
2616 48d13ac6 2023-09-05 stsp head_refname = strdup(got_worktree_get_head_ref_name(worktree));
2617 48d13ac6 2023-09-05 stsp if (head_refname == NULL) {
2618 48d13ac6 2023-09-05 stsp error = got_error_from_errno("strdup");
2619 48d13ac6 2023-09-05 stsp goto done;
2622 48d13ac6 2023-09-05 stsp /* Release work tree lock. */
2623 48d13ac6 2023-09-05 stsp got_worktree_close(worktree);
2624 48d13ac6 2023-09-05 stsp worktree = NULL;
2627 0deb9607 2022-11-18 op if (verbosity >= 0) {
2628 0deb9607 2022-11-18 op printf("Connecting to \"%s\" %s://%s%s%s%s%s\n",
2629 0deb9607 2022-11-18 op remote->name, proto, host,
2630 0deb9607 2022-11-18 op port ? ":" : "", port ? port : "",
2631 0deb9607 2022-11-18 op *server_path == '/' ? "" : "/", server_path);
2634 9c52365f 2020-03-21 stsp error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
2635 9c52365f 2020-03-21 stsp server_path, verbosity);
2636 7848a0e1 2020-03-19 stsp if (error)
2637 7848a0e1 2020-03-19 stsp goto done;
2638 72cc612f 2024-04-14 stsp #ifndef PROFILE
2639 72cc612f 2024-04-14 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd",
2640 72cc612f 2024-04-14 stsp NULL) == -1)
2641 72cc612f 2024-04-14 stsp err(1, "pledge");
2643 118a625d 2023-02-18 mark if (!have_bflag) {
2645 118a625d 2023-02-18 mark * If set, get this remote's HEAD ref target so
2646 118a625d 2023-02-18 mark * if it has changed on the server we can fetch it.
2648 118a625d 2023-02-18 mark error = got_ref_list(&remote_refs, repo, "refs/remotes",
2649 118a625d 2023-02-18 mark got_ref_cmp_by_name, repo);
2650 118a625d 2023-02-18 mark if (error)
2651 118a625d 2023-02-18 mark goto done;
2653 118a625d 2023-02-18 mark TAILQ_FOREACH(re, &remote_refs, entry) {
2654 118a625d 2023-02-18 mark const char *remote_refname, *remote_target;
2655 118a625d 2023-02-18 mark size_t remote_name_len;
2657 118a625d 2023-02-18 mark if (!got_ref_is_symbolic(re->ref))
2660 118a625d 2023-02-18 mark remote_name_len = strlen(remote->name);
2661 118a625d 2023-02-18 mark remote_refname = got_ref_get_name(re->ref);
2663 118a625d 2023-02-18 mark /* we only want refs/remotes/$remote->name/HEAD */
2664 118a625d 2023-02-18 mark if (strncmp(remote_refname + 13, remote->name,
2665 118a625d 2023-02-18 mark remote_name_len) != 0)
2668 118a625d 2023-02-18 mark if (strcmp(remote_refname + remote_name_len + 14,
2669 118a625d 2023-02-18 mark GOT_REF_HEAD) != 0)
2673 118a625d 2023-02-18 mark * Take the name itself because we already
2674 118a625d 2023-02-18 mark * only match with refs/heads/ in fetch_pack().
2676 118a625d 2023-02-18 mark remote_target = got_ref_get_symref_target(re->ref);
2677 118a625d 2023-02-18 mark remote_head = remote_target + remote_name_len + 14;
2681 48d13ac6 2023-09-05 stsp if (head_refname &&
2682 48d13ac6 2023-09-05 stsp strncmp(head_refname, "refs/heads/", 11) == 0)
2683 48d13ac6 2023-09-05 stsp worktree_branch = head_refname;
2686 7848a0e1 2020-03-19 stsp fpa.last_scaled_size[0] = '\0';
2687 7848a0e1 2020-03-19 stsp fpa.last_p_indexed = -1;
2688 7848a0e1 2020-03-19 stsp fpa.last_p_resolved = -1;
2689 7848a0e1 2020-03-19 stsp fpa.verbosity = verbosity;
2690 04d9a9ec 2020-09-24 stsp fpa.repo = repo;
2691 04d9a9ec 2020-09-24 stsp fpa.create_configs = 0;
2692 04d9a9ec 2020-09-24 stsp fpa.configs_created = 0;
2693 04d9a9ec 2020-09-24 stsp memset(&fpa.config_info, 0, sizeof(fpa.config_info));
2695 7848a0e1 2020-03-19 stsp error = got_fetch_pack(&pack_hash, &refs, &symrefs, remote->name,
2696 4ba14133 2020-03-20 stsp remote->mirror_references, fetch_all_branches, &wanted_branches,
2697 0e4002ca 2020-03-21 stsp &wanted_refs, list_refs_only, verbosity, fetchfd, repo,
2698 118a625d 2023-02-18 mark worktree_branch, remote_head, have_bflag, fetch_progress, &fpa);
2699 7848a0e1 2020-03-19 stsp if (error)
2700 7848a0e1 2020-03-19 stsp goto done;
2702 41b0de12 2020-03-21 stsp if (list_refs_only) {
2703 41b0de12 2020-03-21 stsp error = list_remote_refs(&symrefs, &refs);
2704 41b0de12 2020-03-21 stsp goto done;
2707 7848a0e1 2020-03-19 stsp if (pack_hash == NULL) {
2708 7848a0e1 2020-03-19 stsp if (verbosity >= 0)
2709 7848a0e1 2020-03-19 stsp printf("Already up-to-date\n");
2710 bcf34b0e 2020-03-26 stsp } else if (verbosity >= 0) {
2711 984065c8 2020-03-19 stsp error = got_object_id_str(&id_str, pack_hash);
2712 984065c8 2020-03-19 stsp if (error)
2713 984065c8 2020-03-19 stsp goto done;
2714 e69674d8 2020-03-19 stsp printf("\nFetched %s.pack\n", id_str);
2715 984065c8 2020-03-19 stsp free(id_str);
2716 984065c8 2020-03-19 stsp id_str = NULL;
2719 7848a0e1 2020-03-19 stsp /* Update references provided with the pack file. */
2720 7848a0e1 2020-03-19 stsp TAILQ_FOREACH(pe, &refs, entry) {
2721 7848a0e1 2020-03-19 stsp const char *refname = pe->path;
2722 7848a0e1 2020-03-19 stsp struct got_object_id *id = pe->data;
2723 7848a0e1 2020-03-19 stsp struct got_reference *ref;
2724 7848a0e1 2020-03-19 stsp char *remote_refname;
2726 0e4002ca 2020-03-21 stsp if (is_wanted_ref(&wanted_refs, refname) &&
2727 0e4002ca 2020-03-21 stsp !remote->mirror_references) {
2728 0e4002ca 2020-03-21 stsp error = update_wanted_ref(refname, id,
2729 0e4002ca 2020-03-21 stsp remote->name, verbosity, repo);
2730 0e4002ca 2020-03-21 stsp if (error)
2731 0e4002ca 2020-03-21 stsp goto done;
2735 1510c839 2020-03-20 stsp if (remote->mirror_references ||
2736 1510c839 2020-03-20 stsp strncmp("refs/tags/", refname, 10) == 0) {
2737 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, refname, 1);
2738 7848a0e1 2020-03-19 stsp if (error) {
2739 7848a0e1 2020-03-19 stsp if (error->code != GOT_ERR_NOT_REF)
2740 7848a0e1 2020-03-19 stsp goto done;
2741 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity,
2743 7848a0e1 2020-03-19 stsp if (error)
2744 7848a0e1 2020-03-19 stsp goto done;
2746 db6d8ad8 2020-03-21 stsp error = update_ref(ref, id, replace_tags,
2747 db6d8ad8 2020-03-21 stsp verbosity, repo);
2748 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2749 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2750 9f142382 2020-03-21 stsp error = unlock_err;
2751 7848a0e1 2020-03-19 stsp got_ref_close(ref);
2752 7848a0e1 2020-03-19 stsp if (error)
2753 7848a0e1 2020-03-19 stsp goto done;
2755 7848a0e1 2020-03-19 stsp } else if (strncmp("refs/heads/", refname, 11) == 0) {
2756 7848a0e1 2020-03-19 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2757 7848a0e1 2020-03-19 stsp remote_name, refname + 11) == -1) {
2758 7848a0e1 2020-03-19 stsp error = got_error_from_errno("asprintf");
2759 7848a0e1 2020-03-19 stsp goto done;
2762 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, remote_refname, 1);
2763 7848a0e1 2020-03-19 stsp if (error) {
2764 7848a0e1 2020-03-19 stsp if (error->code != GOT_ERR_NOT_REF)
2765 7848a0e1 2020-03-19 stsp goto done;
2766 5e91dae4 2022-08-30 stsp error = create_ref(remote_refname, id,
2767 688f11b3 2020-03-21 stsp verbosity, repo);
2768 7848a0e1 2020-03-19 stsp if (error)
2769 7848a0e1 2020-03-19 stsp goto done;
2771 db6d8ad8 2020-03-21 stsp error = update_ref(ref, id, replace_tags,
2772 db6d8ad8 2020-03-21 stsp verbosity, repo);
2773 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2774 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2775 9f142382 2020-03-21 stsp error = unlock_err;
2776 7848a0e1 2020-03-19 stsp got_ref_close(ref);
2777 7848a0e1 2020-03-19 stsp if (error)
2778 7848a0e1 2020-03-19 stsp goto done;
2781 2ec30c80 2020-03-20 stsp /* Also create a local branch if none exists yet. */
2782 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, refname, 1);
2783 2ec30c80 2020-03-20 stsp if (error) {
2784 2ec30c80 2020-03-20 stsp if (error->code != GOT_ERR_NOT_REF)
2785 2ec30c80 2020-03-20 stsp goto done;
2786 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity,
2788 2ec30c80 2020-03-20 stsp if (error)
2789 2ec30c80 2020-03-20 stsp goto done;
2791 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2792 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2793 9f142382 2020-03-21 stsp error = unlock_err;
2794 2ec30c80 2020-03-20 stsp got_ref_close(ref);
2798 f1bcca34 2020-03-25 stsp if (delete_refs) {
2799 3789fd73 2020-03-26 stsp error = delete_missing_refs(&refs, &symrefs, remote,
2800 3789fd73 2020-03-26 stsp verbosity, repo);
2801 f1bcca34 2020-03-25 stsp if (error)
2802 f1bcca34 2020-03-25 stsp goto done;
2805 f1bcca34 2020-03-25 stsp if (!remote->mirror_references) {
2806 f1bcca34 2020-03-25 stsp /* Update remote HEAD reference if the server provided one. */
2807 f1bcca34 2020-03-25 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
2808 f1bcca34 2020-03-25 stsp struct got_reference *target_ref;
2809 f1bcca34 2020-03-25 stsp const char *refname = pe->path;
2810 f1bcca34 2020-03-25 stsp const char *target = pe->data;
2811 f1bcca34 2020-03-25 stsp char *remote_refname = NULL, *remote_target = NULL;
2813 f1bcca34 2020-03-25 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
2816 f1bcca34 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
2819 f1bcca34 2020-03-25 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2820 f1bcca34 2020-03-25 stsp remote->name, refname) == -1) {
2821 f1bcca34 2020-03-25 stsp error = got_error_from_errno("asprintf");
2822 f1bcca34 2020-03-25 stsp goto done;
2824 f1bcca34 2020-03-25 stsp if (asprintf(&remote_target, "refs/remotes/%s/%s",
2825 f1bcca34 2020-03-25 stsp remote->name, target + 11) == -1) {
2826 f1bcca34 2020-03-25 stsp error = got_error_from_errno("asprintf");
2827 f1bcca34 2020-03-25 stsp free(remote_refname);
2828 f1bcca34 2020-03-25 stsp goto done;
2831 f1bcca34 2020-03-25 stsp error = got_ref_open(&target_ref, repo, remote_target,
2833 f1bcca34 2020-03-25 stsp if (error) {
2834 f1bcca34 2020-03-25 stsp free(remote_refname);
2835 f1bcca34 2020-03-25 stsp free(remote_target);
2836 f1bcca34 2020-03-25 stsp if (error->code == GOT_ERR_NOT_REF) {
2837 f1bcca34 2020-03-25 stsp error = NULL;
2840 f1bcca34 2020-03-25 stsp goto done;
2842 f1bcca34 2020-03-25 stsp error = update_symref(remote_refname, target_ref,
2843 f1bcca34 2020-03-25 stsp verbosity, repo);
2844 f1bcca34 2020-03-25 stsp free(remote_refname);
2845 f1bcca34 2020-03-25 stsp free(remote_target);
2846 f1bcca34 2020-03-25 stsp got_ref_close(target_ref);
2847 f1bcca34 2020-03-25 stsp if (error)
2848 f1bcca34 2020-03-25 stsp goto done;
2852 9c52365f 2020-03-21 stsp if (fetchpid > 0) {
2853 9c52365f 2020-03-21 stsp if (kill(fetchpid, SIGTERM) == -1)
2854 9c52365f 2020-03-21 stsp error = got_error_from_errno("kill");
2855 9c52365f 2020-03-21 stsp if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
2856 9c52365f 2020-03-21 stsp error = got_error_from_errno("waitpid");
2858 7848a0e1 2020-03-19 stsp if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
2859 7848a0e1 2020-03-19 stsp error = got_error_from_errno("close");
2860 1d0f4054 2021-06-17 stsp if (repo) {
2861 1d0f4054 2021-06-17 stsp const struct got_error *close_err = got_repo_close(repo);
2862 1d0f4054 2021-06-17 stsp if (error == NULL)
2863 1d0f4054 2021-06-17 stsp error = close_err;
2865 7848a0e1 2020-03-19 stsp if (worktree)
2866 7848a0e1 2020-03-19 stsp got_worktree_close(worktree);
2867 0ae84acc 2022-06-15 tracey if (pack_fds) {
2868 0ae84acc 2022-06-15 tracey const struct got_error *pack_err =
2869 0ae84acc 2022-06-15 tracey got_repo_pack_fds_close(pack_fds);
2870 0ae84acc 2022-06-15 tracey if (error == NULL)
2871 0ae84acc 2022-06-15 tracey error = pack_err;
2873 d8bacb93 2023-01-10 mark got_pathlist_free(&refs, GOT_PATHLIST_FREE_ALL);
2874 d8bacb93 2023-01-10 mark got_pathlist_free(&symrefs, GOT_PATHLIST_FREE_ALL);
2875 d8bacb93 2023-01-10 mark got_pathlist_free(&wanted_branches, GOT_PATHLIST_FREE_NONE);
2876 d8bacb93 2023-01-10 mark got_pathlist_free(&wanted_refs, GOT_PATHLIST_FREE_NONE);
2877 118a625d 2023-02-18 mark got_ref_list_free(&remote_refs);
2878 db82695e 2023-09-05 stsp got_repo_free_remote_repo_data(remote);
2879 db82695e 2023-09-05 stsp free(remote);
2880 48d13ac6 2023-09-05 stsp free(head_refname);
2881 7848a0e1 2020-03-19 stsp free(id_str);
2882 7848a0e1 2020-03-19 stsp free(cwd);
2883 7848a0e1 2020-03-19 stsp free(repo_path);
2884 7848a0e1 2020-03-19 stsp free(pack_hash);
2885 7848a0e1 2020-03-19 stsp free(proto);
2886 7848a0e1 2020-03-19 stsp free(host);
2887 7848a0e1 2020-03-19 stsp free(port);
2888 7848a0e1 2020-03-19 stsp free(server_path);
2889 7848a0e1 2020-03-19 stsp free(repo_name);
2890 7848a0e1 2020-03-19 stsp return error;
2894 7848a0e1 2020-03-19 stsp __dead static void
2895 2ab43947 2020-03-18 stsp usage_checkout(void)
2897 827a167b 2022-08-16 stsp fprintf(stderr, "usage: %s checkout [-Eq] [-b branch] [-c commit] "
2898 827a167b 2022-08-16 stsp "[-p path-prefix] repository-path [work-tree-path]\n",
2899 4ad4a1ec 2021-09-13 tracey getprogname());
2903 2ab43947 2020-03-18 stsp static void
2904 2ab43947 2020-03-18 stsp show_worktree_base_ref_warning(void)
2906 2ab43947 2020-03-18 stsp fprintf(stderr, "%s: warning: could not create a reference "
2907 2ab43947 2020-03-18 stsp "to the work tree's base commit; the commit could be "
2908 e6786710 2021-07-03 stsp "garbage-collected by Git or 'gotadmin cleanup'; making the "
2909 e6786710 2021-07-03 stsp "repository writable and running 'got update' will prevent this\n",
2910 2ab43947 2020-03-18 stsp getprogname());
2913 2ab43947 2020-03-18 stsp struct got_checkout_progress_arg {
2914 2ab43947 2020-03-18 stsp const char *worktree_path;
2915 2ab43947 2020-03-18 stsp int had_base_commit_ref_error;
2916 4ad4a1ec 2021-09-13 tracey int verbosity;
2919 2ab43947 2020-03-18 stsp static const struct got_error *
2920 2ab43947 2020-03-18 stsp checkout_progress(void *arg, unsigned char status, const char *path)
2922 2ab43947 2020-03-18 stsp struct got_checkout_progress_arg *a = arg;
2924 2ab43947 2020-03-18 stsp /* Base commit bump happens silently. */
2925 2ab43947 2020-03-18 stsp if (status == GOT_STATUS_BUMP_BASE)
2926 2ab43947 2020-03-18 stsp return NULL;
2928 2ab43947 2020-03-18 stsp if (status == GOT_STATUS_BASE_REF_ERR) {
2929 2ab43947 2020-03-18 stsp a->had_base_commit_ref_error = 1;
2930 2ab43947 2020-03-18 stsp return NULL;
2933 2ab43947 2020-03-18 stsp while (path[0] == '/')
2936 4ad4a1ec 2021-09-13 tracey if (a->verbosity >= 0)
2937 4ad4a1ec 2021-09-13 tracey printf("%c %s/%s\n", status, a->worktree_path, path);
2939 2ab43947 2020-03-18 stsp return NULL;
2942 2ab43947 2020-03-18 stsp static const struct got_error *
2943 2ab43947 2020-03-18 stsp check_cancelled(void *arg)
2945 2ab43947 2020-03-18 stsp if (sigint_received || sigpipe_received)
2946 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_CANCELLED);
2947 2ab43947 2020-03-18 stsp return NULL;
2950 2ab43947 2020-03-18 stsp static const struct got_error *
2951 2ab43947 2020-03-18 stsp check_linear_ancestry(struct got_object_id *commit_id,
2952 2ab43947 2020-03-18 stsp struct got_object_id *base_commit_id, int allow_forwards_in_time_only,
2953 2ab43947 2020-03-18 stsp struct got_repository *repo)
2955 2ab43947 2020-03-18 stsp const struct got_error *err = NULL;
2956 2ab43947 2020-03-18 stsp struct got_object_id *yca_id;
2958 2ab43947 2020-03-18 stsp err = got_commit_graph_find_youngest_common_ancestor(&yca_id,
2959 e12cc036 2024-03-27 stsp commit_id, base_commit_id, 1, 0, repo, check_cancelled, NULL);
2961 2ab43947 2020-03-18 stsp return err;
2963 2ab43947 2020-03-18 stsp if (yca_id == NULL)
2964 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2967 2ab43947 2020-03-18 stsp * Require a straight line of history between the target commit
2968 2ab43947 2020-03-18 stsp * and the work tree's base commit.
2970 2ab43947 2020-03-18 stsp * Non-linear situations such as this require a rebase:
2972 2ab43947 2020-03-18 stsp * (commit) D F (base_commit)
2980 2ab43947 2020-03-18 stsp * 'got update' only handles linear cases:
2981 2ab43947 2020-03-18 stsp * Update forwards in time: A (base/yca) - B - C - D (commit)
2982 2ab43947 2020-03-18 stsp * Update backwards in time: D (base) - C - B - A (commit/yca)
2984 2ab43947 2020-03-18 stsp if (allow_forwards_in_time_only) {
2985 2ab43947 2020-03-18 stsp if (got_object_id_cmp(base_commit_id, yca_id) != 0)
2986 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2987 2ab43947 2020-03-18 stsp } else if (got_object_id_cmp(commit_id, yca_id) != 0 &&
2988 2ab43947 2020-03-18 stsp got_object_id_cmp(base_commit_id, yca_id) != 0)
2989 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2991 2ab43947 2020-03-18 stsp free(yca_id);
2992 2ab43947 2020-03-18 stsp return NULL;
2995 2ab43947 2020-03-18 stsp static const struct got_error *
2996 2ab43947 2020-03-18 stsp check_same_branch(struct got_object_id *commit_id,
2997 ad575c3a 2023-05-25 stsp struct got_reference *head_ref, struct got_repository *repo)
2999 2ab43947 2020-03-18 stsp const struct got_error *err = NULL;
3000 2ab43947 2020-03-18 stsp struct got_commit_graph *graph = NULL;
3001 2ab43947 2020-03-18 stsp struct got_object_id *head_commit_id = NULL;
3003 2ab43947 2020-03-18 stsp err = got_ref_resolve(&head_commit_id, repo, head_ref);
3005 2ab43947 2020-03-18 stsp goto done;
3007 ad575c3a 2023-05-25 stsp if (got_object_id_cmp(head_commit_id, commit_id) == 0)
3008 2ab43947 2020-03-18 stsp goto done;
3010 2ab43947 2020-03-18 stsp err = got_commit_graph_open(&graph, "/", 1);
3012 2ab43947 2020-03-18 stsp goto done;
3014 98297eed 2024-03-27 stsp err = got_commit_graph_bfsort(graph, head_commit_id, repo,
3015 2ab43947 2020-03-18 stsp check_cancelled, NULL);
3017 2ab43947 2020-03-18 stsp goto done;
3019 2ab43947 2020-03-18 stsp for (;;) {
3020 d9787ed8 2022-09-10 op struct got_object_id id;
3022 2ab43947 2020-03-18 stsp err = got_commit_graph_iter_next(&id, graph, repo,
3023 2ab43947 2020-03-18 stsp check_cancelled, NULL);
3024 2ab43947 2020-03-18 stsp if (err) {
3025 2ab43947 2020-03-18 stsp if (err->code == GOT_ERR_ITER_COMPLETED)
3026 ad575c3a 2023-05-25 stsp err = got_error(GOT_ERR_ANCESTRY);
3030 ad575c3a 2023-05-25 stsp if (got_object_id_cmp(&id, commit_id) == 0)
3034 2ab43947 2020-03-18 stsp if (graph)
3035 2ab43947 2020-03-18 stsp got_commit_graph_close(graph);
3036 2ab43947 2020-03-18 stsp free(head_commit_id);
3037 2ab43947 2020-03-18 stsp return err;
3040 4ed7e80c 2018-05-20 stsp static const struct got_error *
3041 4b6c9460 2020-03-05 stsp checkout_ancestry_error(struct got_reference *ref, const char *commit_id_str)
3043 4b6c9460 2020-03-05 stsp static char msg[512];
3044 4b6c9460 2020-03-05 stsp const char *branch_name;
3046 4b6c9460 2020-03-05 stsp if (got_ref_is_symbolic(ref))
3047 4b6c9460 2020-03-05 stsp branch_name = got_ref_get_symref_target(ref);
3049 4b6c9460 2020-03-05 stsp branch_name = got_ref_get_name(ref);
3051 4b6c9460 2020-03-05 stsp if (strncmp("refs/heads/", branch_name, 11) == 0)
3052 4b6c9460 2020-03-05 stsp branch_name += 11;
3054 4b6c9460 2020-03-05 stsp snprintf(msg, sizeof(msg),
3055 4b6c9460 2020-03-05 stsp "target commit is not contained in branch '%s'; "
3056 4b6c9460 2020-03-05 stsp "the branch to use must be specified with -b; "
3057 4b6c9460 2020-03-05 stsp "if necessary a new branch can be created for "
3058 4b6c9460 2020-03-05 stsp "this commit with 'got branch -c %s BRANCH_NAME'",
3059 4b6c9460 2020-03-05 stsp branch_name, commit_id_str);
3061 4b6c9460 2020-03-05 stsp return got_error_msg(GOT_ERR_ANCESTRY, msg);
3064 4b6c9460 2020-03-05 stsp static const struct got_error *
3065 c09a553d 2018-03-12 stsp cmd_checkout(int argc, char *argv[])
3067 d0bb0ed6 2023-12-03 mark const struct got_error *close_err, *error = NULL;
3068 c09a553d 2018-03-12 stsp struct got_repository *repo = NULL;
3069 08e5873e 2021-09-14 stsp struct got_reference *head_ref = NULL, *ref = NULL;
3070 c09a553d 2018-03-12 stsp struct got_worktree *worktree = NULL;
3071 c09a553d 2018-03-12 stsp char *repo_path = NULL;