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 c0768b0f 2018-06-10 stsp #include <sys/types.h>
21 5de5890b 2018-10-18 stsp #include <sys/stat.h>
22 3c45a30a 2019-05-12 jcs #include <sys/param.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 99437157 2018-11-11 stsp #include <signal.h>
32 5c860e29 2018-03-12 stsp #include <stdio.h>
33 5c860e29 2018-03-12 stsp #include <stdlib.h>
34 5c860e29 2018-03-12 stsp #include <string.h>
35 5c860e29 2018-03-12 stsp #include <unistd.h>
36 c09a553d 2018-03-12 stsp #include <libgen.h>
37 c0768b0f 2018-06-10 stsp #include <time.h>
38 33ad4cbe 2019-05-12 jcs #include <paths.h>
39 6841bf13 2019-11-29 kn #include <regex.h>
40 83cd27f8 2020-01-13 stsp #include <getopt.h>
41 d2cdc636 2020-03-18 stsp #include <util.h>
43 53ccebc2 2019-07-30 stsp #include "got_version.h"
44 f42b1b34 2018-03-12 stsp #include "got_error.h"
45 f42b1b34 2018-03-12 stsp #include "got_object.h"
46 5261c201 2018-04-01 stsp #include "got_reference.h"
47 f42b1b34 2018-03-12 stsp #include "got_repository.h"
48 1dd54920 2019-05-11 stsp #include "got_path.h"
49 e6209546 2019-08-22 stsp #include "got_cancel.h"
50 c09a553d 2018-03-12 stsp #include "got_worktree.h"
51 79109fed 2018-03-27 stsp #include "got_diff.h"
52 372ccdbb 2018-06-10 stsp #include "got_commit_graph.h"
53 6f23baec 2020-03-18 stsp #include "got_fetch.h"
54 f8a36e22 2021-08-26 stsp #include "got_send.h"
55 404c43c4 2018-06-21 stsp #include "got_blame.h"
56 63219cd2 2019-01-04 stsp #include "got_privsep.h"
57 793c30b5 2019-05-13 stsp #include "got_opentemp.h"
58 50b0790e 2020-09-11 stsp #include "got_gotconfig.h"
60 5c860e29 2018-03-12 stsp #ifndef nitems
61 5c860e29 2018-03-12 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
64 99437157 2018-11-11 stsp static volatile sig_atomic_t sigint_received;
65 99437157 2018-11-11 stsp static volatile sig_atomic_t sigpipe_received;
68 99437157 2018-11-11 stsp catch_sigint(int signo)
70 99437157 2018-11-11 stsp sigint_received = 1;
74 99437157 2018-11-11 stsp catch_sigpipe(int signo)
76 99437157 2018-11-11 stsp sigpipe_received = 1;
80 8cfb4057 2019-07-09 stsp struct got_cmd {
81 820059fa 2020-09-25 stsp const char *cmd_name;
82 d7d4f210 2018-03-12 stsp const struct got_error *(*cmd_main)(int, char *[]);
83 1b6b95a8 2018-03-12 stsp void (*cmd_usage)(void);
84 97b3a7be 2019-07-09 stsp const char *cmd_alias;
87 6879ba42 2020-10-01 naddy __dead static void usage(int, int);
88 2c7829a4 2019-06-17 stsp __dead static void usage_init(void);
89 3ce1b845 2019-07-15 stsp __dead static void usage_import(void);
90 93658fb9 2020-03-18 stsp __dead static void usage_clone(void);
91 7848a0e1 2020-03-19 stsp __dead static void usage_fetch(void);
92 2ab43947 2020-03-18 stsp __dead static void usage_checkout(void);
93 507dc3bb 2018-12-29 stsp __dead static void usage_update(void);
94 4ed7e80c 2018-05-20 stsp __dead static void usage_log(void);
95 4ed7e80c 2018-05-20 stsp __dead static void usage_diff(void);
96 404c43c4 2018-06-21 stsp __dead static void usage_blame(void);
97 5de5890b 2018-10-18 stsp __dead static void usage_tree(void);
98 6bad629b 2019-02-04 stsp __dead static void usage_status(void);
99 d0eebce4 2019-03-11 stsp __dead static void usage_ref(void);
100 4e759de4 2019-06-26 stsp __dead static void usage_branch(void);
101 8e7bd50a 2019-08-22 stsp __dead static void usage_tag(void);
102 d00136be 2019-03-26 stsp __dead static void usage_add(void);
103 648e4ef7 2019-07-09 stsp __dead static void usage_remove(void);
104 a129376b 2019-03-28 stsp __dead static void usage_revert(void);
105 c4296144 2019-05-09 stsp __dead static void usage_commit(void);
106 f8a36e22 2021-08-26 stsp __dead static void usage_send(void);
107 234035bc 2019-06-01 stsp __dead static void usage_cherrypick(void);
108 5ef14e63 2019-06-02 stsp __dead static void usage_backout(void);
109 818c7501 2019-07-11 stsp __dead static void usage_rebase(void);
110 0ebf8283 2019-07-24 stsp __dead static void usage_histedit(void);
111 2822a352 2019-10-15 stsp __dead static void usage_integrate(void);
112 715dc77e 2019-08-03 stsp __dead static void usage_stage(void);
113 ad493afc 2019-08-03 stsp __dead static void usage_unstage(void);
114 01073a5d 2019-08-22 stsp __dead static void usage_cat(void);
115 b2118c49 2020-07-28 stsp __dead static void usage_info(void);
117 2c7829a4 2019-06-17 stsp static const struct got_error* cmd_init(int, char *[]);
118 3ce1b845 2019-07-15 stsp static const struct got_error* cmd_import(int, char *[]);
119 93658fb9 2020-03-18 stsp static const struct got_error* cmd_clone(int, char *[]);
120 7848a0e1 2020-03-19 stsp static const struct got_error* cmd_fetch(int, char *[]);
121 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_checkout(int, char *[]);
122 507dc3bb 2018-12-29 stsp static const struct got_error* cmd_update(int, char *[]);
123 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_log(int, char *[]);
124 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_diff(int, char *[]);
125 404c43c4 2018-06-21 stsp static const struct got_error* cmd_blame(int, char *[]);
126 5de5890b 2018-10-18 stsp static const struct got_error* cmd_tree(int, char *[]);
127 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_status(int, char *[]);
128 d0eebce4 2019-03-11 stsp static const struct got_error* cmd_ref(int, char *[]);
129 4e759de4 2019-06-26 stsp static const struct got_error* cmd_branch(int, char *[]);
130 8e7bd50a 2019-08-22 stsp static const struct got_error* cmd_tag(int, char *[]);
131 d00136be 2019-03-26 stsp static const struct got_error* cmd_add(int, char *[]);
132 648e4ef7 2019-07-09 stsp static const struct got_error* cmd_remove(int, char *[]);
133 a129376b 2019-03-28 stsp static const struct got_error* cmd_revert(int, char *[]);
134 c4296144 2019-05-09 stsp static const struct got_error* cmd_commit(int, char *[]);
135 f8a36e22 2021-08-26 stsp static const struct got_error* cmd_send(int, char *[]);
136 234035bc 2019-06-01 stsp static const struct got_error* cmd_cherrypick(int, char *[]);
137 5ef14e63 2019-06-02 stsp static const struct got_error* cmd_backout(int, char *[]);
138 818c7501 2019-07-11 stsp static const struct got_error* cmd_rebase(int, char *[]);
139 0ebf8283 2019-07-24 stsp static const struct got_error* cmd_histedit(int, char *[]);
140 2822a352 2019-10-15 stsp static const struct got_error* cmd_integrate(int, char *[]);
141 715dc77e 2019-08-03 stsp static const struct got_error* cmd_stage(int, char *[]);
142 ad493afc 2019-08-03 stsp static const struct got_error* cmd_unstage(int, char *[]);
143 01073a5d 2019-08-22 stsp static const struct got_error* cmd_cat(int, char *[]);
144 b2118c49 2020-07-28 stsp static const struct got_error* cmd_info(int, char *[]);
146 8cfb4057 2019-07-09 stsp static struct got_cmd got_commands[] = {
147 b2118c49 2020-07-28 stsp { "init", cmd_init, usage_init, "" },
148 bc26cce8 2019-08-04 stsp { "import", cmd_import, usage_import, "im" },
149 93658fb9 2020-03-18 stsp { "clone", cmd_clone, usage_clone, "cl" },
150 7848a0e1 2020-03-19 stsp { "fetch", cmd_fetch, usage_fetch, "fe" },
151 2ab43947 2020-03-18 stsp { "checkout", cmd_checkout, usage_checkout, "co" },
152 97b3a7be 2019-07-09 stsp { "update", cmd_update, usage_update, "up" },
153 97b3a7be 2019-07-09 stsp { "log", cmd_log, usage_log, "" },
154 bc26cce8 2019-08-04 stsp { "diff", cmd_diff, usage_diff, "di" },
155 bc26cce8 2019-08-04 stsp { "blame", cmd_blame, usage_blame, "bl" },
156 bc26cce8 2019-08-04 stsp { "tree", cmd_tree, usage_tree, "tr" },
157 97b3a7be 2019-07-09 stsp { "status", cmd_status, usage_status, "st" },
158 97b3a7be 2019-07-09 stsp { "ref", cmd_ref, usage_ref, "" },
159 97b3a7be 2019-07-09 stsp { "branch", cmd_branch, usage_branch, "br" },
160 8e7bd50a 2019-08-22 stsp { "tag", cmd_tag, usage_tag, "" },
161 97b3a7be 2019-07-09 stsp { "add", cmd_add, usage_add, "" },
162 648e4ef7 2019-07-09 stsp { "remove", cmd_remove, usage_remove, "rm" },
163 97b3a7be 2019-07-09 stsp { "revert", cmd_revert, usage_revert, "rv" },
164 97b3a7be 2019-07-09 stsp { "commit", cmd_commit, usage_commit, "ci" },
165 f8a36e22 2021-08-26 stsp { "send", cmd_send, usage_send, "se" },
166 016477fd 2019-07-09 stsp { "cherrypick", cmd_cherrypick, usage_cherrypick, "cy" },
167 97b3a7be 2019-07-09 stsp { "backout", cmd_backout, usage_backout, "bo" },
168 818c7501 2019-07-11 stsp { "rebase", cmd_rebase, usage_rebase, "rb" },
169 0ebf8283 2019-07-24 stsp { "histedit", cmd_histedit, usage_histedit, "he" },
170 2822a352 2019-10-15 stsp { "integrate", cmd_integrate, usage_integrate,"ig" },
171 715dc77e 2019-08-03 stsp { "stage", cmd_stage, usage_stage, "sg" },
172 ad493afc 2019-08-03 stsp { "unstage", cmd_unstage, usage_unstage, "ug" },
173 01073a5d 2019-08-22 stsp { "cat", cmd_cat, usage_cat, "" },
174 b2118c49 2020-07-28 stsp { "info", cmd_info, usage_info, "" },
177 ce5b7c56 2019-07-09 stsp static void
178 6879ba42 2020-10-01 naddy list_commands(FILE *fp)
182 6879ba42 2020-10-01 naddy fprintf(fp, "commands:");
183 ce5b7c56 2019-07-09 stsp for (i = 0; i < nitems(got_commands); i++) {
184 ce5b7c56 2019-07-09 stsp struct got_cmd *cmd = &got_commands[i];
185 6879ba42 2020-10-01 naddy fprintf(fp, " %s", cmd->cmd_name);
187 6879ba42 2020-10-01 naddy fputc('\n', fp);
190 ff69268e 2020-12-13 stsp __dead static void
191 ff69268e 2020-12-13 stsp option_conflict(char a, char b)
193 ff69268e 2020-12-13 stsp errx(1, "-%c and -%c options are mutually exclusive", a, b);
197 5c860e29 2018-03-12 stsp main(int argc, char *argv[])
199 8cfb4057 2019-07-09 stsp struct got_cmd *cmd;
202 53ccebc2 2019-07-30 stsp int hflag = 0, Vflag = 0;
203 83cd27f8 2020-01-13 stsp static struct option longopts[] = {
204 62d463ca 2020-10-20 naddy { "version", no_argument, NULL, 'V' },
205 62d463ca 2020-10-20 naddy { NULL, 0, NULL, 0 }
208 289e3cbf 2019-02-04 stsp setlocale(LC_CTYPE, "");
210 6586ea88 2020-01-13 stsp while ((ch = getopt_long(argc, argv, "+hV", longopts, NULL)) != -1) {
211 5c860e29 2018-03-12 stsp switch (ch) {
219 6879ba42 2020-10-01 naddy usage(hflag, 1);
220 5c860e29 2018-03-12 stsp /* NOTREACHED */
224 5c860e29 2018-03-12 stsp argc -= optind;
225 5c860e29 2018-03-12 stsp argv += optind;
226 9814e6a3 2020-09-27 naddy optind = 1;
227 9814e6a3 2020-09-27 naddy optreset = 1;
229 53ccebc2 2019-07-30 stsp if (Vflag) {
230 53ccebc2 2019-07-30 stsp got_version_print_str();
234 5c860e29 2018-03-12 stsp if (argc <= 0)
235 6879ba42 2020-10-01 naddy usage(hflag, hflag ? 0 : 1);
237 99437157 2018-11-11 stsp signal(SIGINT, catch_sigint);
238 99437157 2018-11-11 stsp signal(SIGPIPE, catch_sigpipe);
240 5c860e29 2018-03-12 stsp for (i = 0; i < nitems(got_commands); i++) {
241 d7d4f210 2018-03-12 stsp const struct got_error *error;
243 5c860e29 2018-03-12 stsp cmd = &got_commands[i];
245 97b3a7be 2019-07-09 stsp if (strcmp(cmd->cmd_name, argv[0]) != 0 &&
246 97b3a7be 2019-07-09 stsp strcmp(cmd->cmd_alias, argv[0]) != 0)
250 1b6b95a8 2018-03-12 stsp got_commands[i].cmd_usage();
252 d7d4f210 2018-03-12 stsp error = got_commands[i].cmd_main(argc, argv);
253 f8afbdc8 2019-11-08 stsp if (error && error->code != GOT_ERR_CANCELLED &&
254 f8afbdc8 2019-11-08 stsp error->code != GOT_ERR_PRIVSEP_EXIT &&
255 f8afbdc8 2019-11-08 stsp !(sigpipe_received &&
256 70015d7a 2019-11-08 stsp error->code == GOT_ERR_ERRNO && errno == EPIPE) &&
257 70015d7a 2019-11-08 stsp !(sigint_received &&
258 70015d7a 2019-11-08 stsp error->code == GOT_ERR_ERRNO && errno == EINTR)) {
259 d7d4f210 2018-03-12 stsp fprintf(stderr, "%s: %s\n", getprogname(), error->msg);
266 20ecf764 2018-03-12 stsp fprintf(stderr, "%s: unknown command '%s'\n", getprogname(), argv[0]);
267 6879ba42 2020-10-01 naddy list_commands(stderr);
271 4ed7e80c 2018-05-20 stsp __dead static void
272 6879ba42 2020-10-01 naddy usage(int hflag, int status)
274 6879ba42 2020-10-01 naddy FILE *fp = (status == 0) ? stdout : stderr;
276 6879ba42 2020-10-01 naddy fprintf(fp, "usage: %s [-h] [-V | --version] command [arg ...]\n",
277 53ccebc2 2019-07-30 stsp getprogname());
279 6879ba42 2020-10-01 naddy list_commands(fp);
280 6879ba42 2020-10-01 naddy exit(status);
283 0266afb7 2019-01-04 stsp static const struct got_error *
284 0ee7065d 2019-05-13 stsp get_editor(char **abspath)
286 0ee7065d 2019-05-13 stsp const struct got_error *err = NULL;
287 e2ba3d07 2019-05-13 stsp const char *editor;
289 8920fa04 2019-08-18 stsp *abspath = NULL;
291 e2ba3d07 2019-05-13 stsp editor = getenv("VISUAL");
292 e2ba3d07 2019-05-13 stsp if (editor == NULL)
293 e2ba3d07 2019-05-13 stsp editor = getenv("EDITOR");
295 0ee7065d 2019-05-13 stsp if (editor) {
296 0ee7065d 2019-05-13 stsp err = got_path_find_prog(abspath, editor);
298 0ee7065d 2019-05-13 stsp return err;
301 0ee7065d 2019-05-13 stsp if (*abspath == NULL) {
302 0ee7065d 2019-05-13 stsp *abspath = strdup("/bin/ed");
303 0ee7065d 2019-05-13 stsp if (*abspath == NULL)
304 0ee7065d 2019-05-13 stsp return got_error_from_errno("strdup");
307 e2ba3d07 2019-05-13 stsp return NULL;
310 e2ba3d07 2019-05-13 stsp static const struct got_error *
311 d0eebce4 2019-03-11 stsp apply_unveil(const char *repo_path, int repo_read_only,
312 c530dc23 2019-07-23 stsp const char *worktree_path)
314 163ce85a 2019-05-13 stsp const struct got_error *err;
316 37c06ea4 2019-07-15 stsp #ifdef PROFILE
317 37c06ea4 2019-07-15 stsp if (unveil("gmon.out", "rwc") != 0)
318 37c06ea4 2019-07-15 stsp return got_error_from_errno2("unveil", "gmon.out");
320 d0eebce4 2019-03-11 stsp if (repo_path && unveil(repo_path, repo_read_only ? "r" : "rwc") != 0)
321 638f9024 2019-05-13 stsp return got_error_from_errno2("unveil", repo_path);
323 0266afb7 2019-01-04 stsp if (worktree_path && unveil(worktree_path, "rwc") != 0)
324 638f9024 2019-05-13 stsp return got_error_from_errno2("unveil", worktree_path);
326 bb63914a 2020-02-17 stsp if (unveil(GOT_TMPDIR_STR, "rwc") != 0)
327 bb63914a 2020-02-17 stsp return got_error_from_errno2("unveil", GOT_TMPDIR_STR);
329 163ce85a 2019-05-13 stsp err = got_privsep_unveil_exec_helpers();
330 163ce85a 2019-05-13 stsp if (err != NULL)
331 163ce85a 2019-05-13 stsp return err;
333 0266afb7 2019-01-04 stsp if (unveil(NULL, NULL) != 0)
334 638f9024 2019-05-13 stsp return got_error_from_errno("unveil");
336 0266afb7 2019-01-04 stsp return NULL;
339 2c7829a4 2019-06-17 stsp __dead static void
340 2c7829a4 2019-06-17 stsp usage_init(void)
342 09ea71ba 2019-07-27 stsp fprintf(stderr, "usage: %s init repository-path\n", getprogname());
346 2c7829a4 2019-06-17 stsp static const struct got_error *
347 2c7829a4 2019-06-17 stsp cmd_init(int argc, char *argv[])
349 2c7829a4 2019-06-17 stsp const struct got_error *error = NULL;
350 2c7829a4 2019-06-17 stsp char *repo_path = NULL;
353 2c7829a4 2019-06-17 stsp while ((ch = getopt(argc, argv, "")) != -1) {
354 2c7829a4 2019-06-17 stsp switch (ch) {
356 2c7829a4 2019-06-17 stsp usage_init();
357 2c7829a4 2019-06-17 stsp /* NOTREACHED */
361 2c7829a4 2019-06-17 stsp argc -= optind;
362 2c7829a4 2019-06-17 stsp argv += optind;
364 2c7829a4 2019-06-17 stsp #ifndef PROFILE
365 2c7829a4 2019-06-17 stsp if (pledge("stdio rpath wpath cpath unveil", NULL) == -1)
366 2c7829a4 2019-06-17 stsp err(1, "pledge");
368 2c7829a4 2019-06-17 stsp if (argc != 1)
369 bc20e173 2019-06-17 stsp usage_init();
371 2c7829a4 2019-06-17 stsp repo_path = strdup(argv[0]);
372 2c7829a4 2019-06-17 stsp if (repo_path == NULL)
373 2c7829a4 2019-06-17 stsp return got_error_from_errno("strdup");
375 2c7829a4 2019-06-17 stsp got_path_strip_trailing_slashes(repo_path);
377 2c7829a4 2019-06-17 stsp error = got_path_mkdir(repo_path);
378 2c7829a4 2019-06-17 stsp if (error &&
379 2c7829a4 2019-06-17 stsp !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
382 c530dc23 2019-07-23 stsp error = apply_unveil(repo_path, 0, NULL);
386 2c7829a4 2019-06-17 stsp error = got_repo_init(repo_path);
388 3ce1b845 2019-07-15 stsp free(repo_path);
389 3ce1b845 2019-07-15 stsp return error;
392 3ce1b845 2019-07-15 stsp __dead static void
393 3ce1b845 2019-07-15 stsp usage_import(void)
395 3ce1b845 2019-07-15 stsp fprintf(stderr, "usage: %s import [-b branch] [-m message] "
396 3ce1b845 2019-07-15 stsp "[-r repository-path] [-I pattern] path\n", getprogname());
401 3ce1b845 2019-07-15 stsp spawn_editor(const char *editor, const char *file)
404 3ce1b845 2019-07-15 stsp sig_t sighup, sigint, sigquit;
405 3ce1b845 2019-07-15 stsp int st = -1;
407 3ce1b845 2019-07-15 stsp sighup = signal(SIGHUP, SIG_IGN);
408 3ce1b845 2019-07-15 stsp sigint = signal(SIGINT, SIG_IGN);
409 3ce1b845 2019-07-15 stsp sigquit = signal(SIGQUIT, SIG_IGN);
411 3ce1b845 2019-07-15 stsp switch (pid = fork()) {
413 3ce1b845 2019-07-15 stsp goto doneediting;
415 3ce1b845 2019-07-15 stsp execl(editor, editor, file, (char *)NULL);
416 3ce1b845 2019-07-15 stsp _exit(127);
419 3ce1b845 2019-07-15 stsp while (waitpid(pid, &st, 0) == -1)
420 3ce1b845 2019-07-15 stsp if (errno != EINTR)
423 3ce1b845 2019-07-15 stsp doneediting:
424 3ce1b845 2019-07-15 stsp (void)signal(SIGHUP, sighup);
425 3ce1b845 2019-07-15 stsp (void)signal(SIGINT, sigint);
426 3ce1b845 2019-07-15 stsp (void)signal(SIGQUIT, sigquit);
428 3ce1b845 2019-07-15 stsp if (!WIFEXITED(st)) {
429 3ce1b845 2019-07-15 stsp errno = EINTR;
433 3ce1b845 2019-07-15 stsp return WEXITSTATUS(st);
436 3ce1b845 2019-07-15 stsp static const struct got_error *
437 3ce1b845 2019-07-15 stsp edit_logmsg(char **logmsg, const char *editor, const char *logmsg_path,
438 28cf319f 2021-01-28 stsp const char *initial_content, size_t initial_content_len,
439 28cf319f 2021-01-28 stsp int require_modification)
441 3ce1b845 2019-07-15 stsp const struct got_error *err = NULL;
442 bfa12d5e 2020-09-26 stsp char *line = NULL;
443 bfa12d5e 2020-09-26 stsp size_t linesize = 0;
444 bfa12d5e 2020-09-26 stsp ssize_t linelen;
445 3ce1b845 2019-07-15 stsp struct stat st, st2;
446 bfa12d5e 2020-09-26 stsp FILE *fp = NULL;
447 bfa12d5e 2020-09-26 stsp size_t len, logmsg_len;
448 bfa12d5e 2020-09-26 stsp char *initial_content_stripped = NULL, *buf = NULL, *s;
450 3ce1b845 2019-07-15 stsp *logmsg = NULL;
452 3ce1b845 2019-07-15 stsp if (stat(logmsg_path, &st) == -1)
453 3ce1b845 2019-07-15 stsp return got_error_from_errno2("stat", logmsg_path);
455 3ce1b845 2019-07-15 stsp if (spawn_editor(editor, logmsg_path) == -1)
456 3ce1b845 2019-07-15 stsp return got_error_from_errno("failed spawning editor");
458 3ce1b845 2019-07-15 stsp if (stat(logmsg_path, &st2) == -1)
459 3ce1b845 2019-07-15 stsp return got_error_from_errno("stat");
461 28cf319f 2021-01-28 stsp if (require_modification &&
462 28cf319f 2021-01-28 stsp st.st_mtime == st2.st_mtime && st.st_size == st2.st_size)
463 3ce1b845 2019-07-15 stsp return got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
464 3ce1b845 2019-07-15 stsp "no changes made to commit message, aborting");
467 bfa12d5e 2020-09-26 stsp * Set up a stripped version of the initial content without comments
468 bfa12d5e 2020-09-26 stsp * and blank lines. We need this in order to check if the message
469 bfa12d5e 2020-09-26 stsp * has in fact been edited.
471 bfa12d5e 2020-09-26 stsp initial_content_stripped = malloc(initial_content_len + 1);
472 bfa12d5e 2020-09-26 stsp if (initial_content_stripped == NULL)
473 bfa12d5e 2020-09-26 stsp return got_error_from_errno("malloc");
474 bfa12d5e 2020-09-26 stsp initial_content_stripped[0] = '\0';
476 bfa12d5e 2020-09-26 stsp buf = strdup(initial_content);
477 bfa12d5e 2020-09-26 stsp if (buf == NULL) {
478 bfa12d5e 2020-09-26 stsp err = got_error_from_errno("strdup");
483 bfa12d5e 2020-09-26 stsp while ((line = strsep(&s, "\n")) != NULL) {
484 bfa12d5e 2020-09-26 stsp if ((line[0] == '#' || (len == 0 && line[0] == '\n')))
485 bfa12d5e 2020-09-26 stsp continue; /* remove comments and leading empty lines */
486 bfa12d5e 2020-09-26 stsp len = strlcat(initial_content_stripped, line,
487 bfa12d5e 2020-09-26 stsp initial_content_len + 1);
488 bfa12d5e 2020-09-26 stsp if (len >= initial_content_len + 1) {
489 bfa12d5e 2020-09-26 stsp err = got_error(GOT_ERR_NO_SPACE);
493 bfa12d5e 2020-09-26 stsp while (len > 0 && initial_content_stripped[len - 1] == '\n') {
494 bfa12d5e 2020-09-26 stsp initial_content_stripped[len - 1] = '\0';
498 bfa12d5e 2020-09-26 stsp logmsg_len = st2.st_size;
499 bfa12d5e 2020-09-26 stsp *logmsg = malloc(logmsg_len + 1);
500 3ce1b845 2019-07-15 stsp if (*logmsg == NULL)
501 3ce1b845 2019-07-15 stsp return got_error_from_errno("malloc");
502 3ce1b845 2019-07-15 stsp (*logmsg)[0] = '\0';
504 3ce1b845 2019-07-15 stsp fp = fopen(logmsg_path, "r");
505 3ce1b845 2019-07-15 stsp if (fp == NULL) {
506 3ce1b845 2019-07-15 stsp err = got_error_from_errno("fopen");
511 bfa12d5e 2020-09-26 stsp while ((linelen = getline(&line, &linesize, fp)) != -1) {
512 bfa12d5e 2020-09-26 stsp if ((line[0] == '#' || (len == 0 && line[0] == '\n')))
513 3ce1b845 2019-07-15 stsp continue; /* remove comments and leading empty lines */
514 bfa12d5e 2020-09-26 stsp len = strlcat(*logmsg, line, logmsg_len + 1);
515 bfa12d5e 2020-09-26 stsp if (len >= logmsg_len + 1) {
516 bfa12d5e 2020-09-26 stsp err = got_error(GOT_ERR_NO_SPACE);
520 bfa12d5e 2020-09-26 stsp free(line);
521 bfa12d5e 2020-09-26 stsp if (ferror(fp)) {
522 bfa12d5e 2020-09-26 stsp err = got_ferror(fp, GOT_ERR_IO);
525 3ce1b845 2019-07-15 stsp while (len > 0 && (*logmsg)[len - 1] == '\n') {
526 3ce1b845 2019-07-15 stsp (*logmsg)[len - 1] = '\0';
530 bfa12d5e 2020-09-26 stsp if (len == 0) {
531 3ce1b845 2019-07-15 stsp err = got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
532 3ce1b845 2019-07-15 stsp "commit message cannot be empty, aborting");
535 28cf319f 2021-01-28 stsp if (require_modification &&
536 28cf319f 2021-01-28 stsp strcmp(*logmsg, initial_content_stripped) == 0)
537 bfa12d5e 2020-09-26 stsp err = got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
538 bfa12d5e 2020-09-26 stsp "no changes made to commit message, aborting");
540 bfa12d5e 2020-09-26 stsp free(initial_content_stripped);
542 bfa12d5e 2020-09-26 stsp if (fp && fclose(fp) == EOF && err == NULL)
543 bfa12d5e 2020-09-26 stsp err = got_error_from_errno("fclose");
545 3ce1b845 2019-07-15 stsp free(*logmsg);
546 3ce1b845 2019-07-15 stsp *logmsg = NULL;
548 3ce1b845 2019-07-15 stsp return err;
551 3ce1b845 2019-07-15 stsp static const struct got_error *
552 ef293bdd 2019-10-21 stsp collect_import_msg(char **logmsg, char **logmsg_path, const char *editor,
553 ef293bdd 2019-10-21 stsp const char *path_dir, const char *branch_name)
555 ef293bdd 2019-10-21 stsp char *initial_content = NULL;
556 3ce1b845 2019-07-15 stsp const struct got_error *err = NULL;
557 1601cb9f 2020-09-11 naddy int initial_content_len;
558 97972933 2020-09-11 stsp int fd = -1;
560 1601cb9f 2020-09-11 naddy initial_content_len = asprintf(&initial_content,
561 3ce1b845 2019-07-15 stsp "\n# %s to be imported to branch %s\n", path_dir,
562 1601cb9f 2020-09-11 naddy branch_name);
563 1601cb9f 2020-09-11 naddy if (initial_content_len == -1)
564 3ce1b845 2019-07-15 stsp return got_error_from_errno("asprintf");
566 bb63914a 2020-02-17 stsp err = got_opentemp_named_fd(logmsg_path, &fd,
567 bb63914a 2020-02-17 stsp GOT_TMPDIR_STR "/got-importmsg");
571 97972933 2020-09-11 stsp if (write(fd, initial_content, initial_content_len) == -1) {
572 97972933 2020-09-11 stsp err = got_error_from_errno2("write", *logmsg_path);
576 bfa12d5e 2020-09-26 stsp err = edit_logmsg(logmsg, editor, *logmsg_path, initial_content,
577 0d5bb276 2020-12-15 stsp initial_content_len, 1);
579 97972933 2020-09-11 stsp if (fd != -1 && close(fd) == -1 && err == NULL)
580 97972933 2020-09-11 stsp err = got_error_from_errno2("close", *logmsg_path);
581 3ce1b845 2019-07-15 stsp free(initial_content);
583 59f86c76 2020-09-11 stsp free(*logmsg_path);
584 59f86c76 2020-09-11 stsp *logmsg_path = NULL;
586 3ce1b845 2019-07-15 stsp return err;
589 3ce1b845 2019-07-15 stsp static const struct got_error *
590 3ce1b845 2019-07-15 stsp import_progress(void *arg, const char *path)
592 3ce1b845 2019-07-15 stsp printf("A %s\n", path);
593 3ce1b845 2019-07-15 stsp return NULL;
596 3ce1b845 2019-07-15 stsp static const struct got_error *
597 50b0790e 2020-09-11 stsp get_author(char **author, struct got_repository *repo,
598 50b0790e 2020-09-11 stsp struct got_worktree *worktree)
600 aba9c984 2019-09-08 stsp const struct got_error *err = NULL;
601 50b0790e 2020-09-11 stsp const char *got_author = NULL, *name, *email;
602 50b0790e 2020-09-11 stsp const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
604 84792843 2019-08-09 stsp *author = NULL;
606 50b0790e 2020-09-11 stsp if (worktree)
607 50b0790e 2020-09-11 stsp worktree_conf = got_worktree_get_gotconfig(worktree);
608 50b0790e 2020-09-11 stsp repo_conf = got_repo_get_gotconfig(repo);
611 50b0790e 2020-09-11 stsp * Priority of potential author information sources, from most
612 50b0790e 2020-09-11 stsp * significant to least significant:
613 50b0790e 2020-09-11 stsp * 1) work tree's .got/got.conf file
614 50b0790e 2020-09-11 stsp * 2) repository's got.conf file
615 50b0790e 2020-09-11 stsp * 3) repository's git config file
616 50b0790e 2020-09-11 stsp * 4) environment variables
617 50b0790e 2020-09-11 stsp * 5) global git config files (in user's home directory or /etc)
620 50b0790e 2020-09-11 stsp if (worktree_conf)
621 50b0790e 2020-09-11 stsp got_author = got_gotconfig_get_author(worktree_conf);
622 50b0790e 2020-09-11 stsp if (got_author == NULL)
623 50b0790e 2020-09-11 stsp got_author = got_gotconfig_get_author(repo_conf);
624 84792843 2019-08-09 stsp if (got_author == NULL) {
625 257add31 2020-09-09 stsp name = got_repo_get_gitconfig_author_name(repo);
626 257add31 2020-09-09 stsp email = got_repo_get_gitconfig_author_email(repo);
627 c9956ddf 2019-09-08 stsp if (name && email) {
628 c9956ddf 2019-09-08 stsp if (asprintf(author, "%s <%s>", name, email) == -1)
629 c9956ddf 2019-09-08 stsp return got_error_from_errno("asprintf");
630 c9956ddf 2019-09-08 stsp return NULL;
633 257add31 2020-09-09 stsp got_author = getenv("GOT_AUTHOR");
634 257add31 2020-09-09 stsp if (got_author == NULL) {
635 257add31 2020-09-09 stsp name = got_repo_get_global_gitconfig_author_name(repo);
636 257add31 2020-09-09 stsp email = got_repo_get_global_gitconfig_author_email(
638 257add31 2020-09-09 stsp if (name && email) {
639 257add31 2020-09-09 stsp if (asprintf(author, "%s <%s>", name, email)
641 257add31 2020-09-09 stsp return got_error_from_errno("asprintf");
642 257add31 2020-09-09 stsp return NULL;
644 257add31 2020-09-09 stsp /* TODO: Look up user in password database? */
645 257add31 2020-09-09 stsp return got_error(GOT_ERR_COMMIT_NO_AUTHOR);
649 aba9c984 2019-09-08 stsp *author = strdup(got_author);
650 aba9c984 2019-09-08 stsp if (*author == NULL)
651 aba9c984 2019-09-08 stsp return got_error_from_errno("strdup");
654 84792843 2019-08-09 stsp * Really dumb email address check; we're only doing this to
655 84792843 2019-08-09 stsp * avoid git's object parser breaking on commits we create.
657 84792843 2019-08-09 stsp while (*got_author && *got_author != '<')
658 84792843 2019-08-09 stsp got_author++;
659 aba9c984 2019-09-08 stsp if (*got_author != '<') {
660 aba9c984 2019-09-08 stsp err = got_error(GOT_ERR_COMMIT_NO_EMAIL);
663 84792843 2019-08-09 stsp while (*got_author && *got_author != '@')
664 84792843 2019-08-09 stsp got_author++;
665 aba9c984 2019-09-08 stsp if (*got_author != '@') {
666 aba9c984 2019-09-08 stsp err = got_error(GOT_ERR_COMMIT_NO_EMAIL);
669 84792843 2019-08-09 stsp while (*got_author && *got_author != '>')
670 84792843 2019-08-09 stsp got_author++;
671 84792843 2019-08-09 stsp if (*got_author != '>')
672 aba9c984 2019-09-08 stsp err = got_error(GOT_ERR_COMMIT_NO_EMAIL);
675 aba9c984 2019-09-08 stsp free(*author);
676 aba9c984 2019-09-08 stsp *author = NULL;
678 aba9c984 2019-09-08 stsp return err;
681 c9956ddf 2019-09-08 stsp static const struct got_error *
682 c9956ddf 2019-09-08 stsp get_gitconfig_path(char **gitconfig_path)
684 c9956ddf 2019-09-08 stsp const char *homedir = getenv("HOME");
686 c9956ddf 2019-09-08 stsp *gitconfig_path = NULL;
687 c9956ddf 2019-09-08 stsp if (homedir) {
688 c9956ddf 2019-09-08 stsp if (asprintf(gitconfig_path, "%s/.gitconfig", homedir) == -1)
689 c9956ddf 2019-09-08 stsp return got_error_from_errno("asprintf");
692 c9956ddf 2019-09-08 stsp return NULL;
695 84792843 2019-08-09 stsp static const struct got_error *
696 3ce1b845 2019-07-15 stsp cmd_import(int argc, char *argv[])
698 3ce1b845 2019-07-15 stsp const struct got_error *error = NULL;
699 3ce1b845 2019-07-15 stsp char *path_dir = NULL, *repo_path = NULL, *logmsg = NULL;
700 c9956ddf 2019-09-08 stsp char *gitconfig_path = NULL, *editor = NULL, *author = NULL;
701 5d67f40d 2019-11-08 stsp const char *branch_name = "main";
702 ef293bdd 2019-10-21 stsp char *refname = NULL, *id_str = NULL, *logmsg_path = NULL;
703 3ce1b845 2019-07-15 stsp struct got_repository *repo = NULL;
704 3ce1b845 2019-07-15 stsp struct got_reference *branch_ref = NULL, *head_ref = NULL;
705 3ce1b845 2019-07-15 stsp struct got_object_id *new_commit_id = NULL;
707 3ce1b845 2019-07-15 stsp struct got_pathlist_head ignores;
708 3ce1b845 2019-07-15 stsp struct got_pathlist_entry *pe;
709 ef293bdd 2019-10-21 stsp int preserve_logmsg = 0;
711 3ce1b845 2019-07-15 stsp TAILQ_INIT(&ignores);
713 3ce1b845 2019-07-15 stsp while ((ch = getopt(argc, argv, "b:m:r:I:")) != -1) {
714 3ce1b845 2019-07-15 stsp switch (ch) {
716 3ce1b845 2019-07-15 stsp branch_name = optarg;
719 3ce1b845 2019-07-15 stsp logmsg = strdup(optarg);
720 3ce1b845 2019-07-15 stsp if (logmsg == NULL) {
721 3ce1b845 2019-07-15 stsp error = got_error_from_errno("strdup");
726 3ce1b845 2019-07-15 stsp repo_path = realpath(optarg, NULL);
727 3ce1b845 2019-07-15 stsp if (repo_path == NULL) {
728 9ba1d308 2019-10-21 stsp error = got_error_from_errno2("realpath",
734 3ce1b845 2019-07-15 stsp if (optarg[0] == '\0')
736 3ce1b845 2019-07-15 stsp error = got_pathlist_insert(&pe, &ignores, optarg,
742 b2b65d18 2019-08-22 stsp usage_import();
743 3ce1b845 2019-07-15 stsp /* NOTREACHED */
747 3ce1b845 2019-07-15 stsp argc -= optind;
748 3ce1b845 2019-07-15 stsp argv += optind;
750 3ce1b845 2019-07-15 stsp #ifndef PROFILE
751 aba9c984 2019-09-08 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd "
753 3ce1b845 2019-07-15 stsp NULL) == -1)
754 3ce1b845 2019-07-15 stsp err(1, "pledge");
756 3ce1b845 2019-07-15 stsp if (argc != 1)
757 3ce1b845 2019-07-15 stsp usage_import();
759 3ce1b845 2019-07-15 stsp if (repo_path == NULL) {
760 3ce1b845 2019-07-15 stsp repo_path = getcwd(NULL, 0);
761 3ce1b845 2019-07-15 stsp if (repo_path == NULL)
762 3ce1b845 2019-07-15 stsp return got_error_from_errno("getcwd");
764 3ce1b845 2019-07-15 stsp got_path_strip_trailing_slashes(repo_path);
765 c9956ddf 2019-09-08 stsp error = get_gitconfig_path(&gitconfig_path);
768 c9956ddf 2019-09-08 stsp error = got_repo_open(&repo, repo_path, gitconfig_path);
772 50b0790e 2020-09-11 stsp error = get_author(&author, repo, NULL);
774 aba9c984 2019-09-08 stsp return error;
777 bd5895f3 2019-11-28 stsp * Don't let the user create a branch name with a leading '-'.
778 e560b7e0 2019-11-28 stsp * While technically a valid reference name, this case is usually
779 e560b7e0 2019-11-28 stsp * an unintended typo.
781 bd5895f3 2019-11-28 stsp if (branch_name[0] == '-')
782 bd5895f3 2019-11-28 stsp return got_error_path(branch_name, GOT_ERR_REF_NAME_MINUS);
784 3ce1b845 2019-07-15 stsp if (asprintf(&refname, "refs/heads/%s", branch_name) == -1) {
785 3ce1b845 2019-07-15 stsp error = got_error_from_errno("asprintf");
789 3ce1b845 2019-07-15 stsp error = got_ref_open(&branch_ref, repo, refname, 0);
790 3ce1b845 2019-07-15 stsp if (error) {
791 3ce1b845 2019-07-15 stsp if (error->code != GOT_ERR_NOT_REF)
794 3ce1b845 2019-07-15 stsp error = got_error_msg(GOT_ERR_BRANCH_EXISTS,
795 3ce1b845 2019-07-15 stsp "import target branch already exists");
799 3ce1b845 2019-07-15 stsp path_dir = realpath(argv[0], NULL);
800 3ce1b845 2019-07-15 stsp if (path_dir == NULL) {
801 9ba1d308 2019-10-21 stsp error = got_error_from_errno2("realpath", argv[0]);
804 3ce1b845 2019-07-15 stsp got_path_strip_trailing_slashes(path_dir);
807 3ce1b845 2019-07-15 stsp * unveil(2) traverses exec(2); if an editor is used we have
808 3ce1b845 2019-07-15 stsp * to apply unveil after the log message has been written.
810 3ce1b845 2019-07-15 stsp if (logmsg == NULL || strlen(logmsg) == 0) {
811 3ce1b845 2019-07-15 stsp error = get_editor(&editor);
814 8e158b01 2019-09-22 stsp free(logmsg);
815 ef293bdd 2019-10-21 stsp error = collect_import_msg(&logmsg, &logmsg_path, editor,
816 ef293bdd 2019-10-21 stsp path_dir, refname);
817 ef293bdd 2019-10-21 stsp if (error) {
818 ef293bdd 2019-10-21 stsp if (error->code != GOT_ERR_COMMIT_MSG_EMPTY &&
819 ef293bdd 2019-10-21 stsp logmsg_path != NULL)
820 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
825 ef293bdd 2019-10-21 stsp if (unveil(path_dir, "r") != 0) {
826 ef293bdd 2019-10-21 stsp error = got_error_from_errno2("unveil", path_dir);
827 ef293bdd 2019-10-21 stsp if (logmsg_path)
828 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
832 ef293bdd 2019-10-21 stsp error = apply_unveil(got_repo_get_path(repo), 0, NULL);
833 ef293bdd 2019-10-21 stsp if (error) {
834 ef293bdd 2019-10-21 stsp if (logmsg_path)
835 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
839 3ce1b845 2019-07-15 stsp error = got_repo_import(&new_commit_id, path_dir, logmsg,
840 84792843 2019-08-09 stsp author, &ignores, repo, import_progress, NULL);
841 ef293bdd 2019-10-21 stsp if (error) {
842 ef293bdd 2019-10-21 stsp if (logmsg_path)
843 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
847 3ce1b845 2019-07-15 stsp error = got_ref_alloc(&branch_ref, refname, new_commit_id);
848 ef293bdd 2019-10-21 stsp if (error) {
849 ef293bdd 2019-10-21 stsp if (logmsg_path)
850 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
854 3ce1b845 2019-07-15 stsp error = got_ref_write(branch_ref, repo);
855 ef293bdd 2019-10-21 stsp if (error) {
856 ef293bdd 2019-10-21 stsp if (logmsg_path)
857 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
861 3ce1b845 2019-07-15 stsp error = got_object_id_str(&id_str, new_commit_id);
862 ef293bdd 2019-10-21 stsp if (error) {
863 ef293bdd 2019-10-21 stsp if (logmsg_path)
864 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
868 3ce1b845 2019-07-15 stsp error = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0);
869 3ce1b845 2019-07-15 stsp if (error) {
870 ef293bdd 2019-10-21 stsp if (error->code != GOT_ERR_NOT_REF) {
871 ef293bdd 2019-10-21 stsp if (logmsg_path)
872 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
876 3ce1b845 2019-07-15 stsp error = got_ref_alloc_symref(&head_ref, GOT_REF_HEAD,
877 3ce1b845 2019-07-15 stsp branch_ref);
878 ef293bdd 2019-10-21 stsp if (error) {
879 ef293bdd 2019-10-21 stsp if (logmsg_path)
880 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
884 3ce1b845 2019-07-15 stsp error = got_ref_write(head_ref, repo);
885 ef293bdd 2019-10-21 stsp if (error) {
886 ef293bdd 2019-10-21 stsp if (logmsg_path)
887 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
892 3ce1b845 2019-07-15 stsp printf("Created branch %s with commit %s\n",
893 3ce1b845 2019-07-15 stsp got_ref_get_name(branch_ref), id_str);
895 ef293bdd 2019-10-21 stsp if (preserve_logmsg) {
896 ef293bdd 2019-10-21 stsp fprintf(stderr, "%s: log message preserved in %s\n",
897 ef293bdd 2019-10-21 stsp getprogname(), logmsg_path);
898 ef293bdd 2019-10-21 stsp } else if (logmsg_path && unlink(logmsg_path) == -1 && error == NULL)
899 ef293bdd 2019-10-21 stsp error = got_error_from_errno2("unlink", logmsg_path);
900 8e158b01 2019-09-22 stsp free(logmsg);
901 ef293bdd 2019-10-21 stsp free(logmsg_path);
902 2c7829a4 2019-06-17 stsp free(repo_path);
903 3ce1b845 2019-07-15 stsp free(editor);
904 3ce1b845 2019-07-15 stsp free(refname);
905 3ce1b845 2019-07-15 stsp free(new_commit_id);
906 3ce1b845 2019-07-15 stsp free(id_str);
907 aba9c984 2019-09-08 stsp free(author);
908 c9956ddf 2019-09-08 stsp free(gitconfig_path);
909 3ce1b845 2019-07-15 stsp if (branch_ref)
910 3ce1b845 2019-07-15 stsp got_ref_close(branch_ref);
911 3ce1b845 2019-07-15 stsp if (head_ref)
912 3ce1b845 2019-07-15 stsp got_ref_close(head_ref);
913 2c7829a4 2019-06-17 stsp return error;
916 93658fb9 2020-03-18 stsp __dead static void
917 93658fb9 2020-03-18 stsp usage_clone(void)
919 13f12b09 2020-03-21 stsp fprintf(stderr, "usage: %s clone [-a] [-b branch] [-l] [-m] [-q] [-v] "
920 0e4002ca 2020-03-21 stsp "[-R reference] repository-url [directory]\n", getprogname());
924 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg {
925 892ac3b6 2020-03-18 stsp char last_scaled_size[FMT_SCALED_STRSIZE];
926 892ac3b6 2020-03-18 stsp int last_p_indexed;
927 892ac3b6 2020-03-18 stsp int last_p_resolved;
928 68999b92 2020-03-18 stsp int verbosity;
930 04d9a9ec 2020-09-24 stsp struct got_repository *repo;
932 04d9a9ec 2020-09-24 stsp int create_configs;
933 04d9a9ec 2020-09-24 stsp int configs_created;
935 04d9a9ec 2020-09-24 stsp struct got_pathlist_head *symrefs;
936 04d9a9ec 2020-09-24 stsp struct got_pathlist_head *wanted_branches;
937 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs;
938 04d9a9ec 2020-09-24 stsp const char *proto;
939 04d9a9ec 2020-09-24 stsp const char *host;
940 04d9a9ec 2020-09-24 stsp const char *port;
941 04d9a9ec 2020-09-24 stsp const char *remote_repo_path;
942 04d9a9ec 2020-09-24 stsp const char *git_url;
943 04d9a9ec 2020-09-24 stsp int fetch_all_branches;
944 04d9a9ec 2020-09-24 stsp int mirror_references;
945 04d9a9ec 2020-09-24 stsp } config_info;
948 04d9a9ec 2020-09-24 stsp /* XXX forward declaration */
949 93658fb9 2020-03-18 stsp static const struct got_error *
950 04d9a9ec 2020-09-24 stsp create_config_files(const char *proto, const char *host, const char *port,
951 04d9a9ec 2020-09-24 stsp const char *remote_repo_path, const char *git_url, int fetch_all_branches,
952 04d9a9ec 2020-09-24 stsp int mirror_references, struct got_pathlist_head *symrefs,
953 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_branches,
954 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, struct got_repository *repo);
956 04d9a9ec 2020-09-24 stsp static const struct got_error *
957 baa9fea0 2020-03-18 stsp fetch_progress(void *arg, const char *message, off_t packfile_size,
958 668a20f6 2020-03-18 stsp int nobj_total, int nobj_indexed, int nobj_loose, int nobj_resolved)
960 04d9a9ec 2020-09-24 stsp const struct got_error *err = NULL;
961 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg *a = arg;
962 892ac3b6 2020-03-18 stsp char scaled_size[FMT_SCALED_STRSIZE];
963 892ac3b6 2020-03-18 stsp int p_indexed, p_resolved;
964 892ac3b6 2020-03-18 stsp int print_size = 0, print_indexed = 0, print_resolved = 0;
967 04d9a9ec 2020-09-24 stsp * In order to allow a failed clone to be resumed with 'got fetch'
968 04d9a9ec 2020-09-24 stsp * we try to create configuration files as soon as possible.
969 04d9a9ec 2020-09-24 stsp * Once the server has sent information about its default branch
970 04d9a9ec 2020-09-24 stsp * we have all required information.
972 04d9a9ec 2020-09-24 stsp if (a->create_configs && !a->configs_created &&
973 04d9a9ec 2020-09-24 stsp !TAILQ_EMPTY(a->config_info.symrefs)) {
974 04d9a9ec 2020-09-24 stsp err = create_config_files(a->config_info.proto,
975 62d463ca 2020-10-20 naddy a->config_info.host, a->config_info.port,
976 62d463ca 2020-10-20 naddy a->config_info.remote_repo_path,
977 62d463ca 2020-10-20 naddy a->config_info.git_url,
978 62d463ca 2020-10-20 naddy a->config_info.fetch_all_branches,
979 62d463ca 2020-10-20 naddy a->config_info.mirror_references,
980 62d463ca 2020-10-20 naddy a->config_info.symrefs,
981 99495ddb 2021-01-10 stsp a->config_info.wanted_branches,
982 99495ddb 2021-01-10 stsp a->config_info.wanted_refs, a->repo);
984 04d9a9ec 2020-09-24 stsp return err;
985 04d9a9ec 2020-09-24 stsp a->configs_created = 1;
988 68999b92 2020-03-18 stsp if (a->verbosity < 0)
989 68999b92 2020-03-18 stsp return NULL;
991 fd843b58 2020-03-18 stsp if (message && message[0] != '\0') {
992 d2cdc636 2020-03-18 stsp printf("\rserver: %s", message);
993 892ac3b6 2020-03-18 stsp fflush(stdout);
994 12d1281e 2020-03-19 stsp return NULL;
997 b2409d58 2020-03-18 stsp if (packfile_size > 0 || nobj_indexed > 0) {
998 892ac3b6 2020-03-18 stsp if (fmt_scaled(packfile_size, scaled_size) == 0 &&
999 892ac3b6 2020-03-18 stsp (a->last_scaled_size[0] == '\0' ||
1000 892ac3b6 2020-03-18 stsp strcmp(scaled_size, a->last_scaled_size)) != 0) {
1001 892ac3b6 2020-03-18 stsp print_size = 1;
1002 892ac3b6 2020-03-18 stsp if (strlcpy(a->last_scaled_size, scaled_size,
1003 892ac3b6 2020-03-18 stsp FMT_SCALED_STRSIZE) >= FMT_SCALED_STRSIZE)
1004 892ac3b6 2020-03-18 stsp return got_error(GOT_ERR_NO_SPACE);
1006 61cc1a7a 2020-03-18 stsp if (nobj_indexed > 0) {
1007 892ac3b6 2020-03-18 stsp p_indexed = (nobj_indexed * 100) / nobj_total;
1008 892ac3b6 2020-03-18 stsp if (p_indexed != a->last_p_indexed) {
1009 892ac3b6 2020-03-18 stsp a->last_p_indexed = p_indexed;
1010 892ac3b6 2020-03-18 stsp print_indexed = 1;
1011 892ac3b6 2020-03-18 stsp print_size = 1;
1014 61cc1a7a 2020-03-18 stsp if (nobj_resolved > 0) {
1015 892ac3b6 2020-03-18 stsp p_resolved = (nobj_resolved * 100) /
1016 892ac3b6 2020-03-18 stsp (nobj_total - nobj_loose);
1017 892ac3b6 2020-03-18 stsp if (p_resolved != a->last_p_resolved) {
1018 892ac3b6 2020-03-18 stsp a->last_p_resolved = p_resolved;
1019 892ac3b6 2020-03-18 stsp print_resolved = 1;
1020 892ac3b6 2020-03-18 stsp print_indexed = 1;
1021 892ac3b6 2020-03-18 stsp print_size = 1;
1026 892ac3b6 2020-03-18 stsp if (print_size || print_indexed || print_resolved)
1027 892ac3b6 2020-03-18 stsp printf("\r");
1028 892ac3b6 2020-03-18 stsp if (print_size)
1029 892ac3b6 2020-03-18 stsp printf("%*s fetched", FMT_SCALED_STRSIZE, scaled_size);
1030 d715f13e 2020-03-19 stsp if (print_indexed)
1031 892ac3b6 2020-03-18 stsp printf("; indexing %d%%", p_indexed);
1032 d715f13e 2020-03-19 stsp if (print_resolved)
1033 892ac3b6 2020-03-18 stsp printf("; resolving deltas %d%%", p_resolved);
1034 892ac3b6 2020-03-18 stsp if (print_size || print_indexed || print_resolved)
1035 892ac3b6 2020-03-18 stsp fflush(stdout);
1037 531c3985 2020-03-18 stsp return NULL;
1040 531c3985 2020-03-18 stsp static const struct got_error *
1041 04d9a9ec 2020-09-24 stsp create_symref(const char *refname, struct got_reference *target_ref,
1042 04d9a9ec 2020-09-24 stsp int verbosity, struct got_repository *repo)
1044 4ba14133 2020-03-20 stsp const struct got_error *err;
1045 04d9a9ec 2020-09-24 stsp struct got_reference *head_symref;
1047 04d9a9ec 2020-09-24 stsp err = got_ref_alloc_symref(&head_symref, refname, target_ref);
1049 4ba14133 2020-03-20 stsp return err;
1051 04d9a9ec 2020-09-24 stsp err = got_ref_write(head_symref, repo);
1052 6338a6a1 2020-03-21 stsp if (err == NULL && verbosity > 0) {
1053 6338a6a1 2020-03-21 stsp printf("Created reference %s: %s\n", GOT_REF_HEAD,
1054 6338a6a1 2020-03-21 stsp got_ref_get_name(target_ref));
1056 04d9a9ec 2020-09-24 stsp got_ref_close(head_symref);
1057 4ba14133 2020-03-20 stsp return err;
1060 4ba14133 2020-03-20 stsp static const struct got_error *
1061 41b0de12 2020-03-21 stsp list_remote_refs(struct got_pathlist_head *symrefs,
1062 41b0de12 2020-03-21 stsp struct got_pathlist_head *refs)
1064 41b0de12 2020-03-21 stsp const struct got_error *err;
1065 41b0de12 2020-03-21 stsp struct got_pathlist_entry *pe;
1067 41b0de12 2020-03-21 stsp TAILQ_FOREACH(pe, symrefs, entry) {
1068 41b0de12 2020-03-21 stsp const char *refname = pe->path;
1069 41b0de12 2020-03-21 stsp const char *targetref = pe->data;
1071 41b0de12 2020-03-21 stsp printf("%s: %s\n", refname, targetref);
1074 41b0de12 2020-03-21 stsp TAILQ_FOREACH(pe, refs, entry) {
1075 41b0de12 2020-03-21 stsp const char *refname = pe->path;
1076 41b0de12 2020-03-21 stsp struct got_object_id *id = pe->data;
1077 41b0de12 2020-03-21 stsp char *id_str;
1079 41b0de12 2020-03-21 stsp err = got_object_id_str(&id_str, id);
1081 41b0de12 2020-03-21 stsp return err;
1082 41b0de12 2020-03-21 stsp printf("%s: %s\n", refname, id_str);
1083 41b0de12 2020-03-21 stsp free(id_str);
1086 41b0de12 2020-03-21 stsp return NULL;
1089 6338a6a1 2020-03-21 stsp static const struct got_error *
1090 6338a6a1 2020-03-21 stsp create_ref(const char *refname, struct got_object_id *id,
1091 6338a6a1 2020-03-21 stsp int verbosity, struct got_repository *repo)
1093 6338a6a1 2020-03-21 stsp const struct got_error *err = NULL;
1094 6338a6a1 2020-03-21 stsp struct got_reference *ref;
1095 6338a6a1 2020-03-21 stsp char *id_str;
1097 6338a6a1 2020-03-21 stsp err = got_object_id_str(&id_str, id);
1099 6338a6a1 2020-03-21 stsp return err;
1101 6338a6a1 2020-03-21 stsp err = got_ref_alloc(&ref, refname, id);
1103 6338a6a1 2020-03-21 stsp goto done;
1105 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
1106 6338a6a1 2020-03-21 stsp got_ref_close(ref);
1108 6338a6a1 2020-03-21 stsp if (err == NULL && verbosity >= 0)
1109 6338a6a1 2020-03-21 stsp printf("Created reference %s: %s\n", refname, id_str);
1111 6338a6a1 2020-03-21 stsp free(id_str);
1112 6338a6a1 2020-03-21 stsp return err;
1115 0e4002ca 2020-03-21 stsp static int
1116 0e4002ca 2020-03-21 stsp match_wanted_ref(const char *refname, const char *wanted_ref)
1118 0e4002ca 2020-03-21 stsp if (strncmp(refname, "refs/", 5) != 0)
1120 0e4002ca 2020-03-21 stsp refname += 5;
1123 0e4002ca 2020-03-21 stsp * Prevent fetching of references that won't make any
1124 0e4002ca 2020-03-21 stsp * sense outside of the remote repository's context.
1126 0e4002ca 2020-03-21 stsp if (strncmp(refname, "got/", 4) == 0)
1128 0e4002ca 2020-03-21 stsp if (strncmp(refname, "remotes/", 8) == 0)
1131 0e4002ca 2020-03-21 stsp if (strncmp(wanted_ref, "refs/", 5) == 0)
1132 0e4002ca 2020-03-21 stsp wanted_ref += 5;
1134 0e4002ca 2020-03-21 stsp /* Allow prefix match. */
1135 0e4002ca 2020-03-21 stsp if (got_path_is_child(refname, wanted_ref, strlen(wanted_ref)))
1138 0e4002ca 2020-03-21 stsp /* Allow exact match. */
1139 0e4002ca 2020-03-21 stsp return (strcmp(refname, wanted_ref) == 0);
1142 0e4002ca 2020-03-21 stsp static int
1143 0e4002ca 2020-03-21 stsp is_wanted_ref(struct got_pathlist_head *wanted_refs, const char *refname)
1145 0e4002ca 2020-03-21 stsp struct got_pathlist_entry *pe;
1147 0e4002ca 2020-03-21 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1148 0e4002ca 2020-03-21 stsp if (match_wanted_ref(refname, pe->path))
1155 41b0de12 2020-03-21 stsp static const struct got_error *
1156 0e4002ca 2020-03-21 stsp create_wanted_ref(const char *refname, struct got_object_id *id,
1157 0e4002ca 2020-03-21 stsp const char *remote_repo_name, int verbosity, struct got_repository *repo)
1159 0e4002ca 2020-03-21 stsp const struct got_error *err;
1160 0e4002ca 2020-03-21 stsp char *remote_refname;
1162 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
1163 0e4002ca 2020-03-21 stsp refname += 5;
1165 0e4002ca 2020-03-21 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
1166 0e4002ca 2020-03-21 stsp remote_repo_name, refname) == -1)
1167 0e4002ca 2020-03-21 stsp return got_error_from_errno("asprintf");
1169 0e4002ca 2020-03-21 stsp err = create_ref(remote_refname, id, verbosity, repo);
1170 0e4002ca 2020-03-21 stsp free(remote_refname);
1171 7c0b7f42 2020-09-24 stsp return err;
1174 7c0b7f42 2020-09-24 stsp static const struct got_error *
1175 7c0b7f42 2020-09-24 stsp create_gotconfig(const char *proto, const char *host, const char *port,
1176 15d3c221 2021-01-05 stsp const char *remote_repo_path, const char *default_branch,
1177 0c8b29c5 2021-01-05 stsp int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1178 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, int mirror_references,
1179 99495ddb 2021-01-10 stsp struct got_repository *repo)
1181 7c0b7f42 2020-09-24 stsp const struct got_error *err = NULL;
1182 7c0b7f42 2020-09-24 stsp char *gotconfig_path = NULL;
1183 7c0b7f42 2020-09-24 stsp char *gotconfig = NULL;
1184 7c0b7f42 2020-09-24 stsp FILE *gotconfig_file = NULL;
1185 15d3c221 2021-01-05 stsp const char *branchname = NULL;
1186 99495ddb 2021-01-10 stsp char *branches = NULL, *refs = NULL;
1187 7c0b7f42 2020-09-24 stsp ssize_t n;
1189 0c8b29c5 2021-01-05 stsp if (!fetch_all_branches && !TAILQ_EMPTY(wanted_branches)) {
1190 132af4a5 2021-01-05 stsp struct got_pathlist_entry *pe;
1191 132af4a5 2021-01-05 stsp TAILQ_FOREACH(pe, wanted_branches, entry) {
1193 132af4a5 2021-01-05 stsp branchname = pe->path;
1194 132af4a5 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1195 132af4a5 2021-01-05 stsp branchname += 11;
1196 132af4a5 2021-01-05 stsp if (asprintf(&s, "%s\"%s\" ",
1197 132af4a5 2021-01-05 stsp branches ? branches : "", branchname) == -1) {
1198 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1199 132af4a5 2021-01-05 stsp goto done;
1201 132af4a5 2021-01-05 stsp free(branches);
1202 132af4a5 2021-01-05 stsp branches = s;
1204 0c8b29c5 2021-01-05 stsp } else if (!fetch_all_branches && default_branch) {
1205 15d3c221 2021-01-05 stsp branchname = default_branch;
1206 15d3c221 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1207 15d3c221 2021-01-05 stsp branchname += 11;
1208 132af4a5 2021-01-05 stsp if (asprintf(&branches, "\"%s\" ", branchname) == -1) {
1209 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1210 132af4a5 2021-01-05 stsp goto done;
1213 99495ddb 2021-01-10 stsp if (!TAILQ_EMPTY(wanted_refs)) {
1214 99495ddb 2021-01-10 stsp struct got_pathlist_entry *pe;
1215 99495ddb 2021-01-10 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1217 99495ddb 2021-01-10 stsp const char *refname = pe->path;
1218 99495ddb 2021-01-10 stsp if (strncmp(refname, "refs/", 5) == 0)
1219 99495ddb 2021-01-10 stsp branchname += 5;
1220 99495ddb 2021-01-10 stsp if (asprintf(&s, "%s\"%s\" ",
1221 99495ddb 2021-01-10 stsp refs ? refs : "", refname) == -1) {
1222 99495ddb 2021-01-10 stsp err = got_error_from_errno("asprintf");
1223 99495ddb 2021-01-10 stsp goto done;
1225 99495ddb 2021-01-10 stsp free(refs);
1230 7c0b7f42 2020-09-24 stsp /* Create got.conf(5). */
1231 7c0b7f42 2020-09-24 stsp gotconfig_path = got_repo_get_path_gotconfig(repo);
1232 7c0b7f42 2020-09-24 stsp if (gotconfig_path == NULL) {
1233 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("got_repo_get_path_gotconfig");
1234 7c0b7f42 2020-09-24 stsp goto done;
1236 7c0b7f42 2020-09-24 stsp gotconfig_file = fopen(gotconfig_path, "a");
1237 7c0b7f42 2020-09-24 stsp if (gotconfig_file == NULL) {
1238 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fopen", gotconfig_path);
1239 7c0b7f42 2020-09-24 stsp goto done;
1241 7c0b7f42 2020-09-24 stsp if (asprintf(&gotconfig,
1242 7c0b7f42 2020-09-24 stsp "remote \"%s\" {\n"
1243 7c0b7f42 2020-09-24 stsp "\tserver %s\n"
1244 7c0b7f42 2020-09-24 stsp "\tprotocol %s\n"
1246 7c0b7f42 2020-09-24 stsp "\trepository \"%s\"\n"
1252 7c0b7f42 2020-09-24 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, host, proto,
1253 7c0b7f42 2020-09-24 stsp port ? "\tport " : "", port ? port : "", port ? "\n" : "",
1254 132af4a5 2021-01-05 stsp remote_repo_path, branches ? "\tbranch { " : "",
1255 132af4a5 2021-01-05 stsp branches ? branches : "", branches ? "}\n" : "",
1256 99495ddb 2021-01-10 stsp refs ? "\treference { " : "", refs ? refs : "", refs ? "}\n" : "",
1257 0c8b29c5 2021-01-05 stsp mirror_references ? "\tmirror-references yes\n" : "",
1258 0c8b29c5 2021-01-05 stsp fetch_all_branches ? "\tfetch-all-branches yes\n" : "") == -1) {
1259 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1260 7c0b7f42 2020-09-24 stsp goto done;
1262 7c0b7f42 2020-09-24 stsp n = fwrite(gotconfig, 1, strlen(gotconfig), gotconfig_file);
1263 7c0b7f42 2020-09-24 stsp if (n != strlen(gotconfig)) {
1264 7c0b7f42 2020-09-24 stsp err = got_ferror(gotconfig_file, GOT_ERR_IO);
1265 7c0b7f42 2020-09-24 stsp goto done;
1269 7c0b7f42 2020-09-24 stsp if (gotconfig_file && fclose(gotconfig_file) == EOF && err == NULL)
1270 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fclose", gotconfig_path);
1271 7c0b7f42 2020-09-24 stsp free(gotconfig_path);
1272 132af4a5 2021-01-05 stsp free(branches);
1273 7c0b7f42 2020-09-24 stsp return err;
1276 7c0b7f42 2020-09-24 stsp static const struct got_error *
1277 04d9a9ec 2020-09-24 stsp create_gitconfig(const char *git_url, const char *default_branch,
1278 132af4a5 2021-01-05 stsp int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1279 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, int mirror_references,
1280 99495ddb 2021-01-10 stsp struct got_repository *repo)
1282 7c0b7f42 2020-09-24 stsp const struct got_error *err = NULL;
1283 7c0b7f42 2020-09-24 stsp char *gitconfig_path = NULL;
1284 7c0b7f42 2020-09-24 stsp char *gitconfig = NULL;
1285 7c0b7f42 2020-09-24 stsp FILE *gitconfig_file = NULL;
1286 99495ddb 2021-01-10 stsp char *branches = NULL, *refs = NULL;
1287 56d0a753 2021-01-20 stsp const char *branchname;
1288 7c0b7f42 2020-09-24 stsp ssize_t n;
1290 7c0b7f42 2020-09-24 stsp /* Create a config file Git can understand. */
1291 7c0b7f42 2020-09-24 stsp gitconfig_path = got_repo_get_path_gitconfig(repo);
1292 7c0b7f42 2020-09-24 stsp if (gitconfig_path == NULL) {
1293 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("got_repo_get_path_gitconfig");
1294 7c0b7f42 2020-09-24 stsp goto done;
1296 7c0b7f42 2020-09-24 stsp gitconfig_file = fopen(gitconfig_path, "a");
1297 7c0b7f42 2020-09-24 stsp if (gitconfig_file == NULL) {
1298 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fopen", gitconfig_path);
1299 7c0b7f42 2020-09-24 stsp goto done;
1301 56d0a753 2021-01-20 stsp if (fetch_all_branches) {
1302 56d0a753 2021-01-20 stsp if (mirror_references) {
1303 56d0a753 2021-01-20 stsp if (asprintf(&branches,
1304 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/*:refs/heads/*\n") == -1) {
1305 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1306 56d0a753 2021-01-20 stsp goto done;
1308 56d0a753 2021-01-20 stsp } else if (asprintf(&branches,
1309 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/*:refs/remotes/%s/*\n",
1310 7c0b7f42 2020-09-24 stsp GOT_FETCH_DEFAULT_REMOTE_NAME) == -1) {
1311 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1312 7c0b7f42 2020-09-24 stsp goto done;
1314 132af4a5 2021-01-05 stsp } else if (!TAILQ_EMPTY(wanted_branches)) {
1315 132af4a5 2021-01-05 stsp struct got_pathlist_entry *pe;
1316 132af4a5 2021-01-05 stsp TAILQ_FOREACH(pe, wanted_branches, entry) {
1318 132af4a5 2021-01-05 stsp branchname = pe->path;
1319 132af4a5 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1320 132af4a5 2021-01-05 stsp branchname += 11;
1321 56d0a753 2021-01-20 stsp if (mirror_references) {
1322 56d0a753 2021-01-20 stsp if (asprintf(&s,
1323 56d0a753 2021-01-20 stsp "%s\tfetch = refs/heads/%s:refs/heads/%s\n",
1324 56d0a753 2021-01-20 stsp branches ? branches : "",
1325 56d0a753 2021-01-20 stsp branchname, branchname) == -1) {
1326 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1327 56d0a753 2021-01-20 stsp goto done;
1329 56d0a753 2021-01-20 stsp } else if (asprintf(&s,
1330 56d0a753 2021-01-20 stsp "%s\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1331 132af4a5 2021-01-05 stsp branches ? branches : "",
1332 132af4a5 2021-01-05 stsp branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1333 132af4a5 2021-01-05 stsp branchname) == -1) {
1334 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1335 132af4a5 2021-01-05 stsp goto done;
1337 132af4a5 2021-01-05 stsp free(branches);
1338 132af4a5 2021-01-05 stsp branches = s;
1342 7c0b7f42 2020-09-24 stsp * If the server specified a default branch, use just that one.
1343 7c0b7f42 2020-09-24 stsp * Otherwise fall back to fetching all branches on next fetch.
1345 04d9a9ec 2020-09-24 stsp if (default_branch) {
1346 04d9a9ec 2020-09-24 stsp branchname = default_branch;
1347 7c0b7f42 2020-09-24 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1348 7c0b7f42 2020-09-24 stsp branchname += 11;
1350 7c0b7f42 2020-09-24 stsp branchname = "*"; /* fall back to all branches */
1351 56d0a753 2021-01-20 stsp if (mirror_references) {
1352 56d0a753 2021-01-20 stsp if (asprintf(&branches,
1353 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/%s:refs/heads/%s\n",
1354 56d0a753 2021-01-20 stsp branchname, branchname) == -1) {
1355 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1356 56d0a753 2021-01-20 stsp goto done;
1358 56d0a753 2021-01-20 stsp } else if (asprintf(&branches,
1359 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1360 7c0b7f42 2020-09-24 stsp branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1361 7c0b7f42 2020-09-24 stsp branchname) == -1) {
1362 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1363 7c0b7f42 2020-09-24 stsp goto done;
1366 56d0a753 2021-01-20 stsp if (!TAILQ_EMPTY(wanted_refs)) {
1367 99495ddb 2021-01-10 stsp struct got_pathlist_entry *pe;
1368 99495ddb 2021-01-10 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1370 99495ddb 2021-01-10 stsp const char *refname = pe->path;
1371 99495ddb 2021-01-10 stsp if (strncmp(refname, "refs/", 5) == 0)
1372 99495ddb 2021-01-10 stsp refname += 5;
1373 56d0a753 2021-01-20 stsp if (mirror_references) {
1374 56d0a753 2021-01-20 stsp if (asprintf(&s,
1375 56d0a753 2021-01-20 stsp "%s\tfetch = refs/%s:refs/%s\n",
1376 56d0a753 2021-01-20 stsp refs ? refs : "", refname, refname) == -1) {
1377 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1378 56d0a753 2021-01-20 stsp goto done;
1380 56d0a753 2021-01-20 stsp } else if (asprintf(&s,
1381 56d0a753 2021-01-20 stsp "%s\tfetch = refs/%s:refs/remotes/%s/%s\n",
1382 99495ddb 2021-01-10 stsp refs ? refs : "",
1383 99495ddb 2021-01-10 stsp refname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1384 99495ddb 2021-01-10 stsp refname) == -1) {
1385 99495ddb 2021-01-10 stsp err = got_error_from_errno("asprintf");
1386 99495ddb 2021-01-10 stsp goto done;
1388 99495ddb 2021-01-10 stsp free(refs);
1393 132af4a5 2021-01-05 stsp if (asprintf(&gitconfig,
1394 132af4a5 2021-01-05 stsp "[remote \"%s\"]\n"
1395 132af4a5 2021-01-05 stsp "\turl = %s\n"
1398 56d0a753 2021-01-20 stsp "\tfetch = refs/tags/*:refs/tags/*\n",
1399 132af4a5 2021-01-05 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, git_url, branches ? branches : "",
1400 56d0a753 2021-01-20 stsp refs ? refs : "") == -1) {
1401 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1402 132af4a5 2021-01-05 stsp goto done;
1404 7c0b7f42 2020-09-24 stsp n = fwrite(gitconfig, 1, strlen(gitconfig), gitconfig_file);
1405 7c0b7f42 2020-09-24 stsp if (n != strlen(gitconfig)) {
1406 7c0b7f42 2020-09-24 stsp err = got_ferror(gitconfig_file, GOT_ERR_IO);
1407 7c0b7f42 2020-09-24 stsp goto done;
1410 7c0b7f42 2020-09-24 stsp if (gitconfig_file && fclose(gitconfig_file) == EOF && err == NULL)
1411 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fclose", gitconfig_path);
1412 7c0b7f42 2020-09-24 stsp free(gitconfig_path);
1413 132af4a5 2021-01-05 stsp free(branches);
1414 0e4002ca 2020-03-21 stsp return err;
1417 0e4002ca 2020-03-21 stsp static const struct got_error *
1418 04d9a9ec 2020-09-24 stsp create_config_files(const char *proto, const char *host, const char *port,
1419 04d9a9ec 2020-09-24 stsp const char *remote_repo_path, const char *git_url, int fetch_all_branches,
1420 04d9a9ec 2020-09-24 stsp int mirror_references, struct got_pathlist_head *symrefs,
1421 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_branches,
1422 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, struct got_repository *repo)
1424 04d9a9ec 2020-09-24 stsp const struct got_error *err = NULL;
1425 04d9a9ec 2020-09-24 stsp const char *default_branch = NULL;
1426 04d9a9ec 2020-09-24 stsp struct got_pathlist_entry *pe;
1429 04d9a9ec 2020-09-24 stsp * If we asked for a set of wanted branches then use the first
1430 04d9a9ec 2020-09-24 stsp * one of those.
1432 62d463ca 2020-10-20 naddy if (!TAILQ_EMPTY(wanted_branches)) {
1433 04d9a9ec 2020-09-24 stsp pe = TAILQ_FIRST(wanted_branches);
1434 04d9a9ec 2020-09-24 stsp default_branch = pe->path;
1436 04d9a9ec 2020-09-24 stsp /* First HEAD ref listed by server is the default branch. */
1437 04d9a9ec 2020-09-24 stsp TAILQ_FOREACH(pe, symrefs, entry) {
1438 04d9a9ec 2020-09-24 stsp const char *refname = pe->path;
1439 04d9a9ec 2020-09-24 stsp const char *target = pe->data;
1441 04d9a9ec 2020-09-24 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
1444 04d9a9ec 2020-09-24 stsp default_branch = target;
1449 04d9a9ec 2020-09-24 stsp /* Create got.conf(5). */
1450 04d9a9ec 2020-09-24 stsp err = create_gotconfig(proto, host, port, remote_repo_path,
1451 0c8b29c5 2021-01-05 stsp default_branch, fetch_all_branches, wanted_branches,
1452 99495ddb 2021-01-10 stsp wanted_refs, mirror_references, repo);
1454 04d9a9ec 2020-09-24 stsp return err;
1456 04d9a9ec 2020-09-24 stsp /* Create a config file Git can understand. */
1457 04d9a9ec 2020-09-24 stsp return create_gitconfig(git_url, default_branch, fetch_all_branches,
1458 99495ddb 2021-01-10 stsp wanted_branches, wanted_refs, mirror_references, repo);
1461 04d9a9ec 2020-09-24 stsp static const struct got_error *
1462 93658fb9 2020-03-18 stsp cmd_clone(int argc, char *argv[])
1464 39c64a6a 2020-03-18 stsp const struct got_error *error = NULL;
1465 9df6f38b 2020-03-18 stsp const char *uri, *dirname;
1466 09838ffc 2020-03-18 stsp char *proto, *host, *port, *repo_name, *server_path;
1467 d9b4d0c0 2020-03-18 stsp char *default_destdir = NULL, *id_str = NULL;
1468 a9c2d4c2 2020-09-24 stsp const char *repo_path;
1469 bb64b798 2020-03-18 stsp struct got_repository *repo = NULL;
1470 0e4002ca 2020-03-21 stsp struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
1471 d9b4d0c0 2020-03-18 stsp struct got_pathlist_entry *pe;
1472 d9b4d0c0 2020-03-18 stsp struct got_object_id *pack_hash = NULL;
1473 9c52365f 2020-03-21 stsp int ch, fetchfd = -1, fetchstatus;
1474 9c52365f 2020-03-21 stsp pid_t fetchpid = -1;
1475 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg fpa;
1476 b46f3e71 2020-03-18 stsp char *git_url = NULL;
1477 659e7fbd 2020-03-20 stsp int verbosity = 0, fetch_all_branches = 0, mirror_references = 0;
1478 41b0de12 2020-03-21 stsp int list_refs_only = 0;
1480 d9b4d0c0 2020-03-18 stsp TAILQ_INIT(&refs);
1481 d9b4d0c0 2020-03-18 stsp TAILQ_INIT(&symrefs);
1482 4ba14133 2020-03-20 stsp TAILQ_INIT(&wanted_branches);
1483 0e4002ca 2020-03-21 stsp TAILQ_INIT(&wanted_refs);
1485 0e4002ca 2020-03-21 stsp while ((ch = getopt(argc, argv, "ab:lmvqR:")) != -1) {
1486 93658fb9 2020-03-18 stsp switch (ch) {
1488 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
1491 4ba14133 2020-03-20 stsp error = got_pathlist_append(&wanted_branches,
1492 4ba14133 2020-03-20 stsp optarg, NULL);
1493 4ba14133 2020-03-20 stsp if (error)
1494 4ba14133 2020-03-20 stsp return error;
1497 41b0de12 2020-03-21 stsp list_refs_only = 1;
1500 469dd726 2020-03-20 stsp mirror_references = 1;
1503 68999b92 2020-03-18 stsp if (verbosity < 0)
1504 68999b92 2020-03-18 stsp verbosity = 0;
1505 68999b92 2020-03-18 stsp else if (verbosity < 3)
1506 68999b92 2020-03-18 stsp verbosity++;
1509 68999b92 2020-03-18 stsp verbosity = -1;
1512 0e4002ca 2020-03-21 stsp error = got_pathlist_append(&wanted_refs,
1513 0e4002ca 2020-03-21 stsp optarg, NULL);
1514 0e4002ca 2020-03-21 stsp if (error)
1515 0e4002ca 2020-03-21 stsp return error;
1518 93658fb9 2020-03-18 stsp usage_clone();
1522 93658fb9 2020-03-18 stsp argc -= optind;
1523 93658fb9 2020-03-18 stsp argv += optind;
1525 4ba14133 2020-03-20 stsp if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
1526 ff69268e 2020-12-13 stsp option_conflict('a', 'b');
1527 41b0de12 2020-03-21 stsp if (list_refs_only) {
1528 41b0de12 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_branches))
1529 ff69268e 2020-12-13 stsp option_conflict('l', 'b');
1530 41b0de12 2020-03-21 stsp if (fetch_all_branches)
1531 ff69268e 2020-12-13 stsp option_conflict('l', 'a');
1532 41b0de12 2020-03-21 stsp if (mirror_references)
1533 ff69268e 2020-12-13 stsp option_conflict('l', 'm');
1534 0e4002ca 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_refs))
1535 ff69268e 2020-12-13 stsp option_conflict('l', 'R');
1538 93658fb9 2020-03-18 stsp uri = argv[0];
1540 9df6f38b 2020-03-18 stsp if (argc == 1)
1541 93658fb9 2020-03-18 stsp dirname = NULL;
1542 9df6f38b 2020-03-18 stsp else if (argc == 2)
1543 93658fb9 2020-03-18 stsp dirname = argv[1];
1545 93658fb9 2020-03-18 stsp usage_clone();
1547 39c64a6a 2020-03-18 stsp error = got_fetch_parse_uri(&proto, &host, &port, &server_path,
1548 4dbec0a8 2020-08-27 stsp &repo_name, uri);
1549 39c64a6a 2020-03-18 stsp if (error)
1550 09f63084 2020-03-20 stsp goto done;
1552 09f63084 2020-03-20 stsp if (asprintf(&git_url, "%s://%s%s%s%s%s", proto,
1553 09f63084 2020-03-20 stsp host, port ? ":" : "", port ? port : "",
1554 09f63084 2020-03-20 stsp server_path[0] != '/' ? "/" : "", server_path) == -1) {
1555 09f63084 2020-03-20 stsp error = got_error_from_errno("asprintf");
1556 09838ffc 2020-03-18 stsp goto done;
1559 39c64a6a 2020-03-18 stsp if (strcmp(proto, "git") == 0) {
1560 b46f3e71 2020-03-18 stsp #ifndef PROFILE
1561 39c64a6a 2020-03-18 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1562 39c64a6a 2020-03-18 stsp "sendfd dns inet unveil", NULL) == -1)
1563 39c64a6a 2020-03-18 stsp err(1, "pledge");
1565 39c64a6a 2020-03-18 stsp } else if (strcmp(proto, "git+ssh") == 0 ||
1566 39c64a6a 2020-03-18 stsp strcmp(proto, "ssh") == 0) {
1567 b46f3e71 2020-03-18 stsp #ifndef PROFILE
1568 39c64a6a 2020-03-18 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1569 39c64a6a 2020-03-18 stsp "sendfd unveil", NULL) == -1)
1570 39c64a6a 2020-03-18 stsp err(1, "pledge");
1572 39c64a6a 2020-03-18 stsp } else if (strcmp(proto, "http") == 0 ||
1573 39c64a6a 2020-03-18 stsp strcmp(proto, "git+http") == 0) {
1574 39c64a6a 2020-03-18 stsp error = got_error_path(proto, GOT_ERR_NOT_IMPL);
1575 39c64a6a 2020-03-18 stsp goto done;
1577 39c64a6a 2020-03-18 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
1578 39c64a6a 2020-03-18 stsp goto done;
1580 bb64b798 2020-03-18 stsp if (dirname == NULL) {
1581 bb64b798 2020-03-18 stsp if (asprintf(&default_destdir, "%s.git", repo_name) == -1) {
1582 39c64a6a 2020-03-18 stsp error = got_error_from_errno("asprintf");
1583 bb64b798 2020-03-18 stsp goto done;
1585 bb64b798 2020-03-18 stsp repo_path = default_destdir;
1587 bb64b798 2020-03-18 stsp repo_path = dirname;
1589 41b0de12 2020-03-21 stsp if (!list_refs_only) {
1590 41b0de12 2020-03-21 stsp error = got_path_mkdir(repo_path);
1591 2751fe64 2020-09-24 stsp if (error &&
1592 2751fe64 2020-09-24 stsp (!(error->code == GOT_ERR_ERRNO && errno == EISDIR) &&
1593 2751fe64 2020-09-24 stsp !(error->code == GOT_ERR_ERRNO && errno == EEXIST)))
1594 41b0de12 2020-03-21 stsp goto done;
1595 2751fe64 2020-09-24 stsp if (!got_path_dir_is_empty(repo_path)) {
1596 2751fe64 2020-09-24 stsp error = got_error_path(repo_path,
1597 2751fe64 2020-09-24 stsp GOT_ERR_DIR_NOT_EMPTY);
1598 41b0de12 2020-03-21 stsp goto done;
1602 ee448f5f 2020-03-18 stsp if (strcmp(proto, "git+ssh") == 0 || strcmp(proto, "ssh") == 0) {
1603 ee448f5f 2020-03-18 stsp if (unveil(GOT_FETCH_PATH_SSH, "x") != 0) {
1604 ee448f5f 2020-03-18 stsp error = got_error_from_errno2("unveil",
1605 ee448f5f 2020-03-18 stsp GOT_FETCH_PATH_SSH);
1606 ee448f5f 2020-03-18 stsp goto done;
1609 f535bcd4 2020-09-30 stsp error = apply_unveil(repo_path, 0, NULL);
1610 ee448f5f 2020-03-18 stsp if (error)
1611 ee448f5f 2020-03-18 stsp goto done;
1613 f79e6490 2020-04-19 stsp if (verbosity >= 0)
1614 f79e6490 2020-04-19 stsp printf("Connecting to %s%s%s\n", host,
1615 f79e6490 2020-04-19 stsp port ? ":" : "", port ? port : "");
1617 9c52365f 2020-03-21 stsp error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
1618 9c52365f 2020-03-21 stsp server_path, verbosity);
1619 39c64a6a 2020-03-18 stsp if (error)
1620 bb64b798 2020-03-18 stsp goto done;
1622 2751fe64 2020-09-24 stsp if (!list_refs_only) {
1623 2751fe64 2020-09-24 stsp error = got_repo_init(repo_path);
1624 2751fe64 2020-09-24 stsp if (error)
1625 2751fe64 2020-09-24 stsp goto done;
1626 2751fe64 2020-09-24 stsp error = got_repo_open(&repo, repo_path, NULL);
1627 2751fe64 2020-09-24 stsp if (error)
1628 2751fe64 2020-09-24 stsp goto done;
1631 892ac3b6 2020-03-18 stsp fpa.last_scaled_size[0] = '\0';
1632 892ac3b6 2020-03-18 stsp fpa.last_p_indexed = -1;
1633 892ac3b6 2020-03-18 stsp fpa.last_p_resolved = -1;
1634 68999b92 2020-03-18 stsp fpa.verbosity = verbosity;
1635 04d9a9ec 2020-09-24 stsp fpa.create_configs = 1;
1636 04d9a9ec 2020-09-24 stsp fpa.configs_created = 0;
1637 04d9a9ec 2020-09-24 stsp fpa.repo = repo;
1638 04d9a9ec 2020-09-24 stsp fpa.config_info.symrefs = &symrefs;
1639 04d9a9ec 2020-09-24 stsp fpa.config_info.wanted_branches = &wanted_branches;
1640 99495ddb 2021-01-10 stsp fpa.config_info.wanted_refs = &wanted_refs;
1641 04d9a9ec 2020-09-24 stsp fpa.config_info.proto = proto;
1642 04d9a9ec 2020-09-24 stsp fpa.config_info.host = host;
1643 04d9a9ec 2020-09-24 stsp fpa.config_info.port = port;
1644 04d9a9ec 2020-09-24 stsp fpa.config_info.remote_repo_path = server_path;
1645 04d9a9ec 2020-09-24 stsp fpa.config_info.git_url = git_url;
1646 04d9a9ec 2020-09-24 stsp fpa.config_info.fetch_all_branches = fetch_all_branches;
1647 04d9a9ec 2020-09-24 stsp fpa.config_info.mirror_references = mirror_references;
1648 7848a0e1 2020-03-19 stsp error = got_fetch_pack(&pack_hash, &refs, &symrefs,
1649 469dd726 2020-03-20 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, mirror_references,
1650 0e4002ca 2020-03-21 stsp fetch_all_branches, &wanted_branches, &wanted_refs,
1651 0e4002ca 2020-03-21 stsp list_refs_only, verbosity, fetchfd, repo,
1652 0e4002ca 2020-03-21 stsp fetch_progress, &fpa);
1653 39c64a6a 2020-03-18 stsp if (error)
1654 d9b4d0c0 2020-03-18 stsp goto done;
1656 41b0de12 2020-03-21 stsp if (list_refs_only) {
1657 41b0de12 2020-03-21 stsp error = list_remote_refs(&symrefs, &refs);
1658 41b0de12 2020-03-21 stsp goto done;
1661 39c64a6a 2020-03-18 stsp error = got_object_id_str(&id_str, pack_hash);
1662 39c64a6a 2020-03-18 stsp if (error)
1663 d9b4d0c0 2020-03-18 stsp goto done;
1664 68999b92 2020-03-18 stsp if (verbosity >= 0)
1665 e69674d8 2020-03-19 stsp printf("\nFetched %s.pack\n", id_str);
1666 d9b4d0c0 2020-03-18 stsp free(id_str);
1668 d9b4d0c0 2020-03-18 stsp /* Set up references provided with the pack file. */
1669 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &refs, entry) {
1670 d9b4d0c0 2020-03-18 stsp const char *refname = pe->path;
1671 d9b4d0c0 2020-03-18 stsp struct got_object_id *id = pe->data;
1672 7ebc0570 2020-03-18 stsp char *remote_refname;
1674 0e4002ca 2020-03-21 stsp if (is_wanted_ref(&wanted_refs, refname) &&
1675 0e4002ca 2020-03-21 stsp !mirror_references) {
1676 0e4002ca 2020-03-21 stsp error = create_wanted_ref(refname, id,
1677 0e4002ca 2020-03-21 stsp GOT_FETCH_DEFAULT_REMOTE_NAME,
1678 0e4002ca 2020-03-21 stsp verbosity - 1, repo);
1679 0e4002ca 2020-03-21 stsp if (error)
1680 0e4002ca 2020-03-21 stsp goto done;
1684 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity - 1, repo);
1685 39c64a6a 2020-03-18 stsp if (error)
1686 d9b4d0c0 2020-03-18 stsp goto done;
1688 469dd726 2020-03-20 stsp if (mirror_references)
1691 7ebc0570 2020-03-18 stsp if (strncmp("refs/heads/", refname, 11) != 0)
1694 7ebc0570 2020-03-18 stsp if (asprintf(&remote_refname,
1695 7ebc0570 2020-03-18 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1696 7ebc0570 2020-03-18 stsp refname + 11) == -1) {
1697 7ebc0570 2020-03-18 stsp error = got_error_from_errno("asprintf");
1698 7ebc0570 2020-03-18 stsp goto done;
1700 6338a6a1 2020-03-21 stsp error = create_ref(remote_refname, id, verbosity - 1, repo);
1701 f298ae0f 2020-03-25 stsp free(remote_refname);
1702 39c64a6a 2020-03-18 stsp if (error)
1703 d9b4d0c0 2020-03-18 stsp goto done;
1706 d9b4d0c0 2020-03-18 stsp /* Set the HEAD reference if the server provided one. */
1707 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
1708 659e7fbd 2020-03-20 stsp struct got_reference *target_ref;
1709 d9b4d0c0 2020-03-18 stsp const char *refname = pe->path;
1710 d9b4d0c0 2020-03-18 stsp const char *target = pe->data;
1711 f298ae0f 2020-03-25 stsp char *remote_refname = NULL, *remote_target = NULL;
1713 d9b4d0c0 2020-03-18 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
1716 39c64a6a 2020-03-18 stsp error = got_ref_open(&target_ref, repo, target, 0);
1717 39c64a6a 2020-03-18 stsp if (error) {
1718 55330abe 2020-03-20 stsp if (error->code == GOT_ERR_NOT_REF) {
1719 55330abe 2020-03-20 stsp error = NULL;
1722 d9b4d0c0 2020-03-18 stsp goto done;
1725 04d9a9ec 2020-09-24 stsp error = create_symref(refname, target_ref, verbosity, repo);
1726 f298ae0f 2020-03-25 stsp got_ref_close(target_ref);
1727 f298ae0f 2020-03-25 stsp if (error)
1728 f298ae0f 2020-03-25 stsp goto done;
1730 f298ae0f 2020-03-25 stsp if (mirror_references)
1733 f298ae0f 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
1736 f298ae0f 2020-03-25 stsp if (asprintf(&remote_refname,
1737 f298ae0f 2020-03-25 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1738 f298ae0f 2020-03-25 stsp refname) == -1) {
1739 f298ae0f 2020-03-25 stsp error = got_error_from_errno("asprintf");
1740 f298ae0f 2020-03-25 stsp goto done;
1742 f298ae0f 2020-03-25 stsp if (asprintf(&remote_target,
1743 f298ae0f 2020-03-25 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1744 f298ae0f 2020-03-25 stsp target + 11) == -1) {
1745 f298ae0f 2020-03-25 stsp error = got_error_from_errno("asprintf");
1746 f298ae0f 2020-03-25 stsp free(remote_refname);
1747 f298ae0f 2020-03-25 stsp goto done;
1749 f298ae0f 2020-03-25 stsp error = got_ref_open(&target_ref, repo, remote_target, 0);
1750 f298ae0f 2020-03-25 stsp if (error) {
1751 f298ae0f 2020-03-25 stsp free(remote_refname);
1752 f298ae0f 2020-03-25 stsp free(remote_target);
1753 f298ae0f 2020-03-25 stsp if (error->code == GOT_ERR_NOT_REF) {
1754 f298ae0f 2020-03-25 stsp error = NULL;
1757 f298ae0f 2020-03-25 stsp goto done;
1759 04d9a9ec 2020-09-24 stsp error = create_symref(remote_refname, target_ref,
1760 04d9a9ec 2020-09-24 stsp verbosity - 1, repo);
1761 f298ae0f 2020-03-25 stsp free(remote_refname);
1762 f298ae0f 2020-03-25 stsp free(remote_target);
1763 d9b4d0c0 2020-03-18 stsp got_ref_close(target_ref);
1764 39c64a6a 2020-03-18 stsp if (error)
1765 d9b4d0c0 2020-03-18 stsp goto done;
1767 4ba14133 2020-03-20 stsp if (pe == NULL) {
1769 4ba14133 2020-03-20 stsp * We failed to set the HEAD reference. If we asked for
1770 4ba14133 2020-03-20 stsp * a set of wanted branches use the first of one of those
1771 4ba14133 2020-03-20 stsp * which could be fetched instead.
1773 62d463ca 2020-10-20 naddy TAILQ_FOREACH(pe, &wanted_branches, entry) {
1774 4ba14133 2020-03-20 stsp const char *target = pe->path;
1775 4ba14133 2020-03-20 stsp struct got_reference *target_ref;
1777 4ba14133 2020-03-20 stsp error = got_ref_open(&target_ref, repo, target, 0);
1778 4ba14133 2020-03-20 stsp if (error) {
1779 4ba14133 2020-03-20 stsp if (error->code == GOT_ERR_NOT_REF) {
1780 4ba14133 2020-03-20 stsp error = NULL;
1783 4ba14133 2020-03-20 stsp goto done;
1786 04d9a9ec 2020-09-24 stsp error = create_symref(GOT_REF_HEAD, target_ref,
1787 04d9a9ec 2020-09-24 stsp verbosity, repo);
1788 4ba14133 2020-03-20 stsp got_ref_close(target_ref);
1789 4ba14133 2020-03-20 stsp if (error)
1790 4ba14133 2020-03-20 stsp goto done;
1795 d715f13e 2020-03-19 stsp if (verbosity >= 0)
1796 469dd726 2020-03-20 stsp printf("Created %s repository '%s'\n",
1797 469dd726 2020-03-20 stsp mirror_references ? "mirrored" : "cloned", repo_path);
1799 9c52365f 2020-03-21 stsp if (fetchpid > 0) {
1800 9c52365f 2020-03-21 stsp if (kill(fetchpid, SIGTERM) == -1)
1801 9c52365f 2020-03-21 stsp error = got_error_from_errno("kill");
1802 9c52365f 2020-03-21 stsp if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
1803 9c52365f 2020-03-21 stsp error = got_error_from_errno("waitpid");
1805 39c64a6a 2020-03-18 stsp if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
1806 39c64a6a 2020-03-18 stsp error = got_error_from_errno("close");
1807 1d0f4054 2021-06-17 stsp if (repo) {
1808 1d0f4054 2021-06-17 stsp const struct got_error *close_err = got_repo_close(repo);
1809 1d0f4054 2021-06-17 stsp if (error == NULL)
1810 1d0f4054 2021-06-17 stsp error = close_err;
1812 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &refs, entry) {
1813 d9b4d0c0 2020-03-18 stsp free((void *)pe->path);
1814 d9b4d0c0 2020-03-18 stsp free(pe->data);
1816 d9b4d0c0 2020-03-18 stsp got_pathlist_free(&refs);
1817 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
1818 d9b4d0c0 2020-03-18 stsp free((void *)pe->path);
1819 d9b4d0c0 2020-03-18 stsp free(pe->data);
1821 d9b4d0c0 2020-03-18 stsp got_pathlist_free(&symrefs);
1822 4ba14133 2020-03-20 stsp got_pathlist_free(&wanted_branches);
1823 0e4002ca 2020-03-21 stsp got_pathlist_free(&wanted_refs);
1824 d9b4d0c0 2020-03-18 stsp free(pack_hash);
1825 09838ffc 2020-03-18 stsp free(proto);
1826 09838ffc 2020-03-18 stsp free(host);
1827 09838ffc 2020-03-18 stsp free(port);
1828 09838ffc 2020-03-18 stsp free(server_path);
1829 09838ffc 2020-03-18 stsp free(repo_name);
1830 bb64b798 2020-03-18 stsp free(default_destdir);
1831 b46f3e71 2020-03-18 stsp free(git_url);
1832 39c64a6a 2020-03-18 stsp return error;
1835 7848a0e1 2020-03-19 stsp static const struct got_error *
1836 7848a0e1 2020-03-19 stsp update_ref(struct got_reference *ref, struct got_object_id *new_id,
1837 db6d8ad8 2020-03-21 stsp int replace_tags, int verbosity, struct got_repository *repo)
1839 7848a0e1 2020-03-19 stsp const struct got_error *err = NULL;
1840 7848a0e1 2020-03-19 stsp char *new_id_str = NULL;
1841 7848a0e1 2020-03-19 stsp struct got_object_id *old_id = NULL;
1843 7848a0e1 2020-03-19 stsp err = got_object_id_str(&new_id_str, new_id);
1845 7848a0e1 2020-03-19 stsp goto done;
1847 db6d8ad8 2020-03-21 stsp if (!replace_tags &&
1848 db6d8ad8 2020-03-21 stsp strncmp(got_ref_get_name(ref), "refs/tags/", 10) == 0) {
1849 88609724 2020-03-21 stsp err = got_ref_resolve(&old_id, repo, ref);
1851 88609724 2020-03-21 stsp goto done;
1852 88609724 2020-03-21 stsp if (got_object_id_cmp(old_id, new_id) == 0)
1853 88609724 2020-03-21 stsp goto done;
1854 db6d8ad8 2020-03-21 stsp if (verbosity >= 0) {
1855 db6d8ad8 2020-03-21 stsp printf("Rejecting update of existing tag %s: %s\n",
1856 db6d8ad8 2020-03-21 stsp got_ref_get_name(ref), new_id_str);
1858 db6d8ad8 2020-03-21 stsp goto done;
1861 7848a0e1 2020-03-19 stsp if (got_ref_is_symbolic(ref)) {
1862 688f11b3 2020-03-21 stsp if (verbosity >= 0) {
1863 e8a967e0 2020-03-21 stsp printf("Replacing reference %s: %s\n",
1864 6338a6a1 2020-03-21 stsp got_ref_get_name(ref),
1865 6338a6a1 2020-03-21 stsp got_ref_get_symref_target(ref));
1867 e8a967e0 2020-03-21 stsp err = got_ref_change_symref_to_ref(ref, new_id);
1869 7848a0e1 2020-03-19 stsp goto done;
1870 e8a967e0 2020-03-21 stsp err = got_ref_write(ref, repo);
1872 e8a967e0 2020-03-21 stsp goto done;
1874 7848a0e1 2020-03-19 stsp err = got_ref_resolve(&old_id, repo, ref);
1876 7848a0e1 2020-03-19 stsp goto done;
1877 6338a6a1 2020-03-21 stsp if (got_object_id_cmp(old_id, new_id) == 0)
1878 6338a6a1 2020-03-21 stsp goto done;
1880 6338a6a1 2020-03-21 stsp err = got_ref_change_ref(ref, new_id);
1882 6338a6a1 2020-03-21 stsp goto done;
1883 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
1885 6338a6a1 2020-03-21 stsp goto done;
1888 6338a6a1 2020-03-21 stsp if (verbosity >= 0)
1889 f4d0e3fb 2020-05-15 stsp printf("Updated %s: %s\n", got_ref_get_name(ref),
1890 6338a6a1 2020-03-21 stsp new_id_str);
1892 7848a0e1 2020-03-19 stsp free(old_id);
1893 7848a0e1 2020-03-19 stsp free(new_id_str);
1894 7848a0e1 2020-03-19 stsp return err;
1897 f1bcca34 2020-03-25 stsp static const struct got_error *
1898 f1bcca34 2020-03-25 stsp update_symref(const char *refname, struct got_reference *target_ref,
1899 f1bcca34 2020-03-25 stsp int verbosity, struct got_repository *repo)
1901 f1bcca34 2020-03-25 stsp const struct got_error *err = NULL, *unlock_err;
1902 f1bcca34 2020-03-25 stsp struct got_reference *symref;
1903 bcf34b0e 2020-03-26 stsp int symref_is_locked = 0;
1905 f1bcca34 2020-03-25 stsp err = got_ref_open(&symref, repo, refname, 1);
1906 bcf34b0e 2020-03-26 stsp if (err) {
1907 bcf34b0e 2020-03-26 stsp if (err->code != GOT_ERR_NOT_REF)
1908 bcf34b0e 2020-03-26 stsp return err;
1909 bcf34b0e 2020-03-26 stsp err = got_ref_alloc_symref(&symref, refname, target_ref);
1911 bcf34b0e 2020-03-26 stsp goto done;
1913 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
1915 bcf34b0e 2020-03-26 stsp goto done;
1917 bcf34b0e 2020-03-26 stsp if (verbosity >= 0)
1918 bcf34b0e 2020-03-26 stsp printf("Created reference %s: %s\n",
1919 bcf34b0e 2020-03-26 stsp got_ref_get_name(symref),
1920 bcf34b0e 2020-03-26 stsp got_ref_get_symref_target(symref));
1922 bcf34b0e 2020-03-26 stsp symref_is_locked = 1;
1924 bcf34b0e 2020-03-26 stsp if (strcmp(got_ref_get_symref_target(symref),
1925 bcf34b0e 2020-03-26 stsp got_ref_get_name(target_ref)) == 0)
1926 bcf34b0e 2020-03-26 stsp goto done;
1928 bcf34b0e 2020-03-26 stsp err = got_ref_change_symref(symref,
1929 bcf34b0e 2020-03-26 stsp got_ref_get_name(target_ref));
1931 bcf34b0e 2020-03-26 stsp goto done;
1933 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
1935 bcf34b0e 2020-03-26 stsp goto done;
1937 bcf34b0e 2020-03-26 stsp if (verbosity >= 0)
1938 f4d0e3fb 2020-05-15 stsp printf("Updated %s: %s\n", got_ref_get_name(symref),
1939 bcf34b0e 2020-03-26 stsp got_ref_get_symref_target(symref));
1943 bcf34b0e 2020-03-26 stsp if (symref_is_locked) {
1944 bcf34b0e 2020-03-26 stsp unlock_err = got_ref_unlock(symref);
1945 bcf34b0e 2020-03-26 stsp if (unlock_err && err == NULL)
1946 bcf34b0e 2020-03-26 stsp err = unlock_err;
1948 f1bcca34 2020-03-25 stsp got_ref_close(symref);
1949 f1bcca34 2020-03-25 stsp return err;
1952 2ab43947 2020-03-18 stsp __dead static void
1953 7848a0e1 2020-03-19 stsp usage_fetch(void)
1955 f21ec2f0 2020-03-21 stsp fprintf(stderr, "usage: %s fetch [-a] [-b branch] [-d] [-l] "
1956 161728eb 2021-07-24 stsp "[-r repository-path] [-t] [-q] [-v] [-R reference] [-X] "
1957 0e4002ca 2020-03-21 stsp "[remote-repository-name]\n",
1958 13f12b09 2020-03-21 stsp getprogname());
1962 7848a0e1 2020-03-19 stsp static const struct got_error *
1963 3789fd73 2020-03-26 stsp delete_missing_ref(struct got_reference *ref,
1964 688f11b3 2020-03-21 stsp int verbosity, struct got_repository *repo)
1966 f21ec2f0 2020-03-21 stsp const struct got_error *err = NULL;
1967 3789fd73 2020-03-26 stsp struct got_object_id *id = NULL;
1968 3789fd73 2020-03-26 stsp char *id_str = NULL;
1970 3789fd73 2020-03-26 stsp if (got_ref_is_symbolic(ref)) {
1971 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
1973 3789fd73 2020-03-26 stsp return err;
1974 3789fd73 2020-03-26 stsp if (verbosity >= 0) {
1975 f9d54ee6 2021-07-16 stsp printf("Deleted %s: %s\n",
1976 3789fd73 2020-03-26 stsp got_ref_get_name(ref),
1977 3789fd73 2020-03-26 stsp got_ref_get_symref_target(ref));
1980 3789fd73 2020-03-26 stsp err = got_ref_resolve(&id, repo, ref);
1982 3789fd73 2020-03-26 stsp return err;
1983 3789fd73 2020-03-26 stsp err = got_object_id_str(&id_str, id);
1985 3789fd73 2020-03-26 stsp goto done;
1987 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
1989 3789fd73 2020-03-26 stsp goto done;
1990 3789fd73 2020-03-26 stsp if (verbosity >= 0) {
1991 f9d54ee6 2021-07-16 stsp printf("Deleted %s: %s\n",
1992 3789fd73 2020-03-26 stsp got_ref_get_name(ref), id_str);
1997 3789fd73 2020-03-26 stsp free(id_str);
1998 3789fd73 2020-03-26 stsp return NULL;
2001 3789fd73 2020-03-26 stsp static const struct got_error *
2002 3789fd73 2020-03-26 stsp delete_missing_refs(struct got_pathlist_head *their_refs,
2003 50b0790e 2020-09-11 stsp struct got_pathlist_head *their_symrefs,
2004 50b0790e 2020-09-11 stsp const struct got_remote_repo *remote,
2005 3789fd73 2020-03-26 stsp int verbosity, struct got_repository *repo)
2007 3789fd73 2020-03-26 stsp const struct got_error *err = NULL, *unlock_err;
2008 f21ec2f0 2020-03-21 stsp struct got_reflist_head my_refs;
2009 f21ec2f0 2020-03-21 stsp struct got_reflist_entry *re;
2010 f21ec2f0 2020-03-21 stsp struct got_pathlist_entry *pe;
2011 3789fd73 2020-03-26 stsp char *remote_namespace = NULL;
2012 3789fd73 2020-03-26 stsp char *local_refname = NULL;
2014 d9dff0e5 2020-12-26 stsp TAILQ_INIT(&my_refs);
2016 3789fd73 2020-03-26 stsp if (asprintf(&remote_namespace, "refs/remotes/%s/", remote->name)
2018 3789fd73 2020-03-26 stsp return got_error_from_errno("asprintf");
2020 f21ec2f0 2020-03-21 stsp err = got_ref_list(&my_refs, repo, NULL, got_ref_cmp_by_name, NULL);
2022 3789fd73 2020-03-26 stsp goto done;
2024 d9dff0e5 2020-12-26 stsp TAILQ_FOREACH(re, &my_refs, entry) {
2025 f21ec2f0 2020-03-21 stsp const char *refname = got_ref_get_name(re->ref);
2027 3789fd73 2020-03-26 stsp if (!remote->mirror_references) {
2028 3789fd73 2020-03-26 stsp if (strncmp(refname, remote_namespace,
2029 3789fd73 2020-03-26 stsp strlen(remote_namespace)) == 0) {
2030 3789fd73 2020-03-26 stsp if (strcmp(refname + strlen(remote_namespace),
2031 3789fd73 2020-03-26 stsp GOT_REF_HEAD) == 0)
2033 3789fd73 2020-03-26 stsp if (asprintf(&local_refname, "refs/heads/%s",
2034 3789fd73 2020-03-26 stsp refname + strlen(remote_namespace)) == -1) {
2035 3789fd73 2020-03-26 stsp err = got_error_from_errno("asprintf");
2036 3789fd73 2020-03-26 stsp goto done;
2038 3789fd73 2020-03-26 stsp } else if (strncmp(refname, "refs/tags/", 10) != 0)
2042 f21ec2f0 2020-03-21 stsp TAILQ_FOREACH(pe, their_refs, entry) {
2043 3789fd73 2020-03-26 stsp if (strcmp(local_refname, pe->path) == 0)
2046 f21ec2f0 2020-03-21 stsp if (pe != NULL)
2049 3789fd73 2020-03-26 stsp TAILQ_FOREACH(pe, their_symrefs, entry) {
2050 3789fd73 2020-03-26 stsp if (strcmp(local_refname, pe->path) == 0)
2053 3789fd73 2020-03-26 stsp if (pe != NULL)
2056 3789fd73 2020-03-26 stsp err = delete_missing_ref(re->ref, verbosity, repo);
2060 3789fd73 2020-03-26 stsp if (local_refname) {
2061 3789fd73 2020-03-26 stsp struct got_reference *ref;
2062 3789fd73 2020-03-26 stsp err = got_ref_open(&ref, repo, local_refname, 1);
2063 3789fd73 2020-03-26 stsp if (err) {
2064 3789fd73 2020-03-26 stsp if (err->code != GOT_ERR_NOT_REF)
2066 3789fd73 2020-03-26 stsp free(local_refname);
2067 3789fd73 2020-03-26 stsp local_refname = NULL;
2070 3789fd73 2020-03-26 stsp err = delete_missing_ref(ref, verbosity, repo);
2073 3789fd73 2020-03-26 stsp unlock_err = got_ref_unlock(ref);
2074 3789fd73 2020-03-26 stsp got_ref_close(ref);
2075 3789fd73 2020-03-26 stsp if (unlock_err && err == NULL) {
2076 3789fd73 2020-03-26 stsp err = unlock_err;
2080 3789fd73 2020-03-26 stsp free(local_refname);
2081 3789fd73 2020-03-26 stsp local_refname = NULL;
2085 3789fd73 2020-03-26 stsp free(remote_namespace);
2086 3789fd73 2020-03-26 stsp free(local_refname);
2087 0e4002ca 2020-03-21 stsp return err;
2090 0e4002ca 2020-03-21 stsp static const struct got_error *
2091 0e4002ca 2020-03-21 stsp update_wanted_ref(const char *refname, struct got_object_id *id,
2092 0e4002ca 2020-03-21 stsp const char *remote_repo_name, int verbosity, struct got_repository *repo)
2094 9f142382 2020-03-21 stsp const struct got_error *err, *unlock_err;
2095 0e4002ca 2020-03-21 stsp char *remote_refname;
2096 0e4002ca 2020-03-21 stsp struct got_reference *ref;
2098 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
2099 0e4002ca 2020-03-21 stsp refname += 5;
2101 0e4002ca 2020-03-21 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2102 0e4002ca 2020-03-21 stsp remote_repo_name, refname) == -1)
2103 0e4002ca 2020-03-21 stsp return got_error_from_errno("asprintf");
2105 9f142382 2020-03-21 stsp err = got_ref_open(&ref, repo, remote_refname, 1);
2106 0e4002ca 2020-03-21 stsp if (err) {
2107 0e4002ca 2020-03-21 stsp if (err->code != GOT_ERR_NOT_REF)
2108 0e4002ca 2020-03-21 stsp goto done;
2109 0e4002ca 2020-03-21 stsp err = create_ref(remote_refname, id, verbosity, repo);
2111 0e4002ca 2020-03-21 stsp err = update_ref(ref, id, 0, verbosity, repo);
2112 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2113 9f142382 2020-03-21 stsp if (unlock_err && err == NULL)
2114 9f142382 2020-03-21 stsp err = unlock_err;
2115 0e4002ca 2020-03-21 stsp got_ref_close(ref);
2118 0e4002ca 2020-03-21 stsp free(remote_refname);
2119 161728eb 2021-07-24 stsp return err;
2122 161728eb 2021-07-24 stsp static const struct got_error *
2123 161728eb 2021-07-24 stsp delete_ref(struct got_repository *repo, struct got_reference *ref)
2125 161728eb 2021-07-24 stsp const struct got_error *err = NULL;
2126 161728eb 2021-07-24 stsp struct got_object_id *id = NULL;
2127 161728eb 2021-07-24 stsp char *id_str = NULL;
2128 161728eb 2021-07-24 stsp const char *target;
2130 161728eb 2021-07-24 stsp if (got_ref_is_symbolic(ref)) {
2131 161728eb 2021-07-24 stsp target = got_ref_get_symref_target(ref);
2133 161728eb 2021-07-24 stsp err = got_ref_resolve(&id, repo, ref);
2135 161728eb 2021-07-24 stsp goto done;
2136 161728eb 2021-07-24 stsp err = got_object_id_str(&id_str, id);
2138 161728eb 2021-07-24 stsp goto done;
2139 161728eb 2021-07-24 stsp target = id_str;
2142 161728eb 2021-07-24 stsp err = got_ref_delete(ref, repo);
2144 161728eb 2021-07-24 stsp goto done;
2146 161728eb 2021-07-24 stsp printf("Deleted %s: %s\n", got_ref_get_name(ref), target);
2149 161728eb 2021-07-24 stsp free(id_str);
2150 f21ec2f0 2020-03-21 stsp return err;
2153 f21ec2f0 2020-03-21 stsp static const struct got_error *
2154 161728eb 2021-07-24 stsp delete_refs_for_remote(struct got_repository *repo, const char *remote_name)
2156 161728eb 2021-07-24 stsp const struct got_error *err = NULL;
2157 161728eb 2021-07-24 stsp struct got_reflist_head refs;
2158 161728eb 2021-07-24 stsp struct got_reflist_entry *re;
2159 161728eb 2021-07-24 stsp char *prefix;
2161 161728eb 2021-07-24 stsp TAILQ_INIT(&refs);
2163 161728eb 2021-07-24 stsp if (asprintf(&prefix, "refs/remotes/%s", remote_name) == -1) {
2164 161728eb 2021-07-24 stsp err = got_error_from_errno("asprintf");
2165 161728eb 2021-07-24 stsp goto done;
2167 161728eb 2021-07-24 stsp err = got_ref_list(&refs, repo, prefix, got_ref_cmp_by_name, NULL);
2169 161728eb 2021-07-24 stsp goto done;
2171 161728eb 2021-07-24 stsp TAILQ_FOREACH(re, &refs, entry)
2172 161728eb 2021-07-24 stsp delete_ref(repo, re->ref);
2174 161728eb 2021-07-24 stsp got_ref_list_free(&refs);
2175 161728eb 2021-07-24 stsp return err;
2178 161728eb 2021-07-24 stsp static const struct got_error *
2179 7848a0e1 2020-03-19 stsp cmd_fetch(int argc, char *argv[])
2181 9f142382 2020-03-21 stsp const struct got_error *error = NULL, *unlock_err;
2182 7848a0e1 2020-03-19 stsp char *cwd = NULL, *repo_path = NULL;
2183 7848a0e1 2020-03-19 stsp const char *remote_name;
2184 7848a0e1 2020-03-19 stsp char *proto = NULL, *host = NULL, *port = NULL;
2185 7848a0e1 2020-03-19 stsp char *repo_name = NULL, *server_path = NULL;
2186 50b0790e 2020-09-11 stsp const struct got_remote_repo *remotes, *remote = NULL;
2187 7848a0e1 2020-03-19 stsp int nremotes;
2188 7848a0e1 2020-03-19 stsp char *id_str = NULL;
2189 7848a0e1 2020-03-19 stsp struct got_repository *repo = NULL;
2190 7848a0e1 2020-03-19 stsp struct got_worktree *worktree = NULL;
2191 50b0790e 2020-09-11 stsp const struct got_gotconfig *repo_conf = NULL, *worktree_conf = NULL;
2192 0e4002ca 2020-03-21 stsp struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
2193 7848a0e1 2020-03-19 stsp struct got_pathlist_entry *pe;
2194 7848a0e1 2020-03-19 stsp struct got_object_id *pack_hash = NULL;
2195 9c52365f 2020-03-21 stsp int i, ch, fetchfd = -1, fetchstatus;
2196 9c52365f 2020-03-21 stsp pid_t fetchpid = -1;
2197 7848a0e1 2020-03-19 stsp struct got_fetch_progress_arg fpa;
2198 41b0de12 2020-03-21 stsp int verbosity = 0, fetch_all_branches = 0, list_refs_only = 0;
2199 161728eb 2021-07-24 stsp int delete_refs = 0, replace_tags = 0, delete_remote = 0;
2201 7848a0e1 2020-03-19 stsp TAILQ_INIT(&refs);
2202 7848a0e1 2020-03-19 stsp TAILQ_INIT(&symrefs);
2203 4ba14133 2020-03-20 stsp TAILQ_INIT(&wanted_branches);
2204 0e4002ca 2020-03-21 stsp TAILQ_INIT(&wanted_refs);
2206 161728eb 2021-07-24 stsp while ((ch = getopt(argc, argv, "ab:dlr:tvqR:X")) != -1) {
2207 7848a0e1 2020-03-19 stsp switch (ch) {
2209 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
2212 4ba14133 2020-03-20 stsp error = got_pathlist_append(&wanted_branches,
2213 4ba14133 2020-03-20 stsp optarg, NULL);
2214 4ba14133 2020-03-20 stsp if (error)
2215 4ba14133 2020-03-20 stsp return error;
2218 f21ec2f0 2020-03-21 stsp delete_refs = 1;
2221 41b0de12 2020-03-21 stsp list_refs_only = 1;
2224 7848a0e1 2020-03-19 stsp repo_path = realpath(optarg, NULL);
2225 7848a0e1 2020-03-19 stsp if (repo_path == NULL)
2226 7848a0e1 2020-03-19 stsp return got_error_from_errno2("realpath",
2228 7848a0e1 2020-03-19 stsp got_path_strip_trailing_slashes(repo_path);
2231 db6d8ad8 2020-03-21 stsp replace_tags = 1;
2234 7848a0e1 2020-03-19 stsp if (verbosity < 0)
2235 7848a0e1 2020-03-19 stsp verbosity = 0;
2236 7848a0e1 2020-03-19 stsp else if (verbosity < 3)
2237 7848a0e1 2020-03-19 stsp verbosity++;
2240 7848a0e1 2020-03-19 stsp verbosity = -1;
2243 0e4002ca 2020-03-21 stsp error = got_pathlist_append(&wanted_refs,
2244 0e4002ca 2020-03-21 stsp optarg, NULL);
2245 0e4002ca 2020-03-21 stsp if (error)
2246 0e4002ca 2020-03-21 stsp return error;
2249 161728eb 2021-07-24 stsp delete_remote = 1;
2252 7848a0e1 2020-03-19 stsp usage_fetch();
2256 7848a0e1 2020-03-19 stsp argc -= optind;
2257 7848a0e1 2020-03-19 stsp argv += optind;
2259 4ba14133 2020-03-20 stsp if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
2260 ff69268e 2020-12-13 stsp option_conflict('a', 'b');
2261 41b0de12 2020-03-21 stsp if (list_refs_only) {
2262 41b0de12 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_branches))
2263 ff69268e 2020-12-13 stsp option_conflict('l', 'b');
2264 ff69268e 2020-12-13 stsp if (fetch_all_branches)
2265 ff69268e 2020-12-13 stsp option_conflict('l', 'a');
2266 f21ec2f0 2020-03-21 stsp if (delete_refs)
2267 ff69268e 2020-12-13 stsp option_conflict('l', 'd');
2268 161728eb 2021-07-24 stsp if (delete_remote)
2269 161728eb 2021-07-24 stsp option_conflict('l', 'X');
2271 161728eb 2021-07-24 stsp if (delete_remote) {
2272 161728eb 2021-07-24 stsp if (fetch_all_branches)
2273 161728eb 2021-07-24 stsp option_conflict('X', 'a');
2274 161728eb 2021-07-24 stsp if (!TAILQ_EMPTY(&wanted_branches))
2275 161728eb 2021-07-24 stsp option_conflict('X', 'b');
2276 161728eb 2021-07-24 stsp if (delete_refs)
2277 161728eb 2021-07-24 stsp option_conflict('X', 'd');
2278 161728eb 2021-07-24 stsp if (replace_tags)
2279 161728eb 2021-07-24 stsp option_conflict('X', 't');
2280 161728eb 2021-07-24 stsp if (!TAILQ_EMPTY(&wanted_refs))
2281 161728eb 2021-07-24 stsp option_conflict('X', 'R');
2284 161728eb 2021-07-24 stsp if (argc == 0) {
2285 161728eb 2021-07-24 stsp if (delete_remote)
2286 161728eb 2021-07-24 stsp errx(1, "-X option requires a remote name");
2287 7848a0e1 2020-03-19 stsp remote_name = GOT_FETCH_DEFAULT_REMOTE_NAME;
2288 161728eb 2021-07-24 stsp } else if (argc == 1)
2289 7848a0e1 2020-03-19 stsp remote_name = argv[0];
2291 7848a0e1 2020-03-19 stsp usage_fetch();
2293 7848a0e1 2020-03-19 stsp cwd = getcwd(NULL, 0);
2294 7848a0e1 2020-03-19 stsp if (cwd == NULL) {
2295 7848a0e1 2020-03-19 stsp error = got_error_from_errno("getcwd");
2296 7848a0e1 2020-03-19 stsp goto done;
2299 7848a0e1 2020-03-19 stsp if (repo_path == NULL) {
2300 7848a0e1 2020-03-19 stsp error = got_worktree_open(&worktree, cwd);
2301 7848a0e1 2020-03-19 stsp if (error && error->code != GOT_ERR_NOT_WORKTREE)
2302 7848a0e1 2020-03-19 stsp goto done;
2304 7848a0e1 2020-03-19 stsp error = NULL;
2305 7848a0e1 2020-03-19 stsp if (worktree) {
2306 7848a0e1 2020-03-19 stsp repo_path =
2307 7848a0e1 2020-03-19 stsp strdup(got_worktree_get_repo_path(worktree));
2308 7848a0e1 2020-03-19 stsp if (repo_path == NULL)
2309 7848a0e1 2020-03-19 stsp error = got_error_from_errno("strdup");
2310 7848a0e1 2020-03-19 stsp if (error)
2311 7848a0e1 2020-03-19 stsp goto done;
2313 7848a0e1 2020-03-19 stsp repo_path = strdup(cwd);
2314 7848a0e1 2020-03-19 stsp if (repo_path == NULL) {
2315 7848a0e1 2020-03-19 stsp error = got_error_from_errno("strdup");
2316 7848a0e1 2020-03-19 stsp goto done;
2321 7848a0e1 2020-03-19 stsp error = got_repo_open(&repo, repo_path, NULL);
2322 7848a0e1 2020-03-19 stsp if (error)
2323 7848a0e1 2020-03-19 stsp goto done;
2325 161728eb 2021-07-24 stsp if (delete_remote) {
2326 161728eb 2021-07-24 stsp error = delete_refs_for_remote(repo, remote_name);
2327 161728eb 2021-07-24 stsp goto done; /* nothing else to do */
2330 50b0790e 2020-09-11 stsp if (worktree) {
2331 50b0790e 2020-09-11 stsp worktree_conf = got_worktree_get_gotconfig(worktree);
2332 50b0790e 2020-09-11 stsp if (worktree_conf) {
2333 50b0790e 2020-09-11 stsp got_gotconfig_get_remotes(&nremotes, &remotes,
2334 50b0790e 2020-09-11 stsp worktree_conf);
2335 50b0790e 2020-09-11 stsp for (i = 0; i < nremotes; i++) {
2336 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2337 54eb00d5 2020-10-20 stsp remote = &remotes[i];
2343 50b0790e 2020-09-11 stsp if (remote == NULL) {
2344 50b0790e 2020-09-11 stsp repo_conf = got_repo_get_gotconfig(repo);
2345 50b0790e 2020-09-11 stsp if (repo_conf) {
2346 50b0790e 2020-09-11 stsp got_gotconfig_get_remotes(&nremotes, &remotes,
2347 50b0790e 2020-09-11 stsp repo_conf);
2348 50b0790e 2020-09-11 stsp for (i = 0; i < nremotes; i++) {
2349 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2350 54eb00d5 2020-10-20 stsp remote = &remotes[i];
2356 50b0790e 2020-09-11 stsp if (remote == NULL) {
2357 257add31 2020-09-09 stsp got_repo_get_gitconfig_remotes(&nremotes, &remotes, repo);
2358 257add31 2020-09-09 stsp for (i = 0; i < nremotes; i++) {
2359 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2360 54eb00d5 2020-10-20 stsp remote = &remotes[i];
2365 50b0790e 2020-09-11 stsp if (remote == NULL) {
2366 50b0790e 2020-09-11 stsp error = got_error_path(remote_name, GOT_ERR_NO_REMOTE);
2367 50b0790e 2020-09-11 stsp goto done;
2370 0c8b29c5 2021-01-05 stsp if (TAILQ_EMPTY(&wanted_branches)) {
2371 0c8b29c5 2021-01-05 stsp if (!fetch_all_branches)
2372 0c8b29c5 2021-01-05 stsp fetch_all_branches = remote->fetch_all_branches;
2373 6480c871 2021-08-30 stsp for (i = 0; i < remote->nfetch_branches; i++) {
2374 b8adfa55 2020-09-25 stsp got_pathlist_append(&wanted_branches,
2375 6480c871 2021-08-30 stsp remote->fetch_branches[i], NULL);
2378 99495ddb 2021-01-10 stsp if (TAILQ_EMPTY(&wanted_refs)) {
2379 6480c871 2021-08-30 stsp for (i = 0; i < remote->nfetch_refs; i++) {
2380 99495ddb 2021-01-10 stsp got_pathlist_append(&wanted_refs,
2381 6480c871 2021-08-30 stsp remote->fetch_refs[i], NULL);
2385 7848a0e1 2020-03-19 stsp error = got_fetch_parse_uri(&proto, &host, &port, &server_path,
2386 6480c871 2021-08-30 stsp &repo_name, remote->fetch_url);
2387 7848a0e1 2020-03-19 stsp if (error)
2388 7848a0e1 2020-03-19 stsp goto done;
2390 7848a0e1 2020-03-19 stsp if (strcmp(proto, "git") == 0) {
2391 7848a0e1 2020-03-19 stsp #ifndef PROFILE
2392 7848a0e1 2020-03-19 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2393 7848a0e1 2020-03-19 stsp "sendfd dns inet unveil", NULL) == -1)
2394 7848a0e1 2020-03-19 stsp err(1, "pledge");
2396 7848a0e1 2020-03-19 stsp } else if (strcmp(proto, "git+ssh") == 0 ||
2397 7848a0e1 2020-03-19 stsp strcmp(proto, "ssh") == 0) {
2398 7848a0e1 2020-03-19 stsp #ifndef PROFILE
2399 7848a0e1 2020-03-19 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2400 7848a0e1 2020-03-19 stsp "sendfd unveil", NULL) == -1)
2401 7848a0e1 2020-03-19 stsp err(1, "pledge");
2403 7848a0e1 2020-03-19 stsp } else if (strcmp(proto, "http") == 0 ||
2404 7848a0e1 2020-03-19 stsp strcmp(proto, "git+http") == 0) {
2405 7848a0e1 2020-03-19 stsp error = got_error_path(proto, GOT_ERR_NOT_IMPL);
2406 7848a0e1 2020-03-19 stsp goto done;
2408 7848a0e1 2020-03-19 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
2409 7848a0e1 2020-03-19 stsp goto done;
2412 7848a0e1 2020-03-19 stsp if (strcmp(proto, "git+ssh") == 0 || strcmp(proto, "ssh") == 0) {
2413 7848a0e1 2020-03-19 stsp if (unveil(GOT_FETCH_PATH_SSH, "x") != 0) {
2414 7848a0e1 2020-03-19 stsp error = got_error_from_errno2("unveil",
2415 7848a0e1 2020-03-19 stsp GOT_FETCH_PATH_SSH);
2416 7848a0e1 2020-03-19 stsp goto done;
2419 7848a0e1 2020-03-19 stsp error = apply_unveil(got_repo_get_path(repo), 0, NULL);
2420 7848a0e1 2020-03-19 stsp if (error)
2421 7848a0e1 2020-03-19 stsp goto done;
2423 f79e6490 2020-04-19 stsp if (verbosity >= 0)
2424 f79e6490 2020-04-19 stsp printf("Connecting to \"%s\" %s%s%s\n", remote->name, host,
2425 f79e6490 2020-04-19 stsp port ? ":" : "", port ? port : "");
2427 9c52365f 2020-03-21 stsp error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
2428 9c52365f 2020-03-21 stsp server_path, verbosity);
2429 7848a0e1 2020-03-19 stsp if (error)
2430 7848a0e1 2020-03-19 stsp goto done;
2432 7848a0e1 2020-03-19 stsp fpa.last_scaled_size[0] = '\0';
2433 7848a0e1 2020-03-19 stsp fpa.last_p_indexed = -1;
2434 7848a0e1 2020-03-19 stsp fpa.last_p_resolved = -1;
2435 7848a0e1 2020-03-19 stsp fpa.verbosity = verbosity;
2436 04d9a9ec 2020-09-24 stsp fpa.repo = repo;
2437 04d9a9ec 2020-09-24 stsp fpa.create_configs = 0;
2438 04d9a9ec 2020-09-24 stsp fpa.configs_created = 0;
2439 04d9a9ec 2020-09-24 stsp memset(&fpa.config_info, 0, sizeof(fpa.config_info));
2440 7848a0e1 2020-03-19 stsp error = got_fetch_pack(&pack_hash, &refs, &symrefs, remote->name,
2441 4ba14133 2020-03-20 stsp remote->mirror_references, fetch_all_branches, &wanted_branches,
2442 0e4002ca 2020-03-21 stsp &wanted_refs, list_refs_only, verbosity, fetchfd, repo,
2443 0e4002ca 2020-03-21 stsp fetch_progress, &fpa);
2444 7848a0e1 2020-03-19 stsp if (error)
2445 7848a0e1 2020-03-19 stsp goto done;
2447 41b0de12 2020-03-21 stsp if (list_refs_only) {
2448 41b0de12 2020-03-21 stsp error = list_remote_refs(&symrefs, &refs);
2449 41b0de12 2020-03-21 stsp goto done;
2452 7848a0e1 2020-03-19 stsp if (pack_hash == NULL) {
2453 7848a0e1 2020-03-19 stsp if (verbosity >= 0)
2454 7848a0e1 2020-03-19 stsp printf("Already up-to-date\n");
2455 bcf34b0e 2020-03-26 stsp } else if (verbosity >= 0) {
2456 984065c8 2020-03-19 stsp error = got_object_id_str(&id_str, pack_hash);
2457 984065c8 2020-03-19 stsp if (error)
2458 984065c8 2020-03-19 stsp goto done;
2459 e69674d8 2020-03-19 stsp printf("\nFetched %s.pack\n", id_str);
2460 984065c8 2020-03-19 stsp free(id_str);
2461 984065c8 2020-03-19 stsp id_str = NULL;
2464 7848a0e1 2020-03-19 stsp /* Update references provided with the pack file. */
2465 7848a0e1 2020-03-19 stsp TAILQ_FOREACH(pe, &refs, entry) {
2466 7848a0e1 2020-03-19 stsp const char *refname = pe->path;
2467 7848a0e1 2020-03-19 stsp struct got_object_id *id = pe->data;
2468 7848a0e1 2020-03-19 stsp struct got_reference *ref;
2469 7848a0e1 2020-03-19 stsp char *remote_refname;
2471 0e4002ca 2020-03-21 stsp if (is_wanted_ref(&wanted_refs, refname) &&
2472 0e4002ca 2020-03-21 stsp !remote->mirror_references) {
2473 0e4002ca 2020-03-21 stsp error = update_wanted_ref(refname, id,
2474 0e4002ca 2020-03-21 stsp remote->name, verbosity, repo);
2475 0e4002ca 2020-03-21 stsp if (error)
2476 0e4002ca 2020-03-21 stsp goto done;
2480 1510c839 2020-03-20 stsp if (remote->mirror_references ||
2481 1510c839 2020-03-20 stsp strncmp("refs/tags/", refname, 10) == 0) {
2482 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, refname, 1);
2483 7848a0e1 2020-03-19 stsp if (error) {
2484 7848a0e1 2020-03-19 stsp if (error->code != GOT_ERR_NOT_REF)
2485 7848a0e1 2020-03-19 stsp goto done;
2486 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity,
2488 7848a0e1 2020-03-19 stsp if (error)
2489 7848a0e1 2020-03-19 stsp goto done;
2491 db6d8ad8 2020-03-21 stsp error = update_ref(ref, id, replace_tags,
2492 db6d8ad8 2020-03-21 stsp verbosity, repo);
2493 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2494 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2495 9f142382 2020-03-21 stsp error = unlock_err;
2496 7848a0e1 2020-03-19 stsp got_ref_close(ref);
2497 7848a0e1 2020-03-19 stsp if (error)
2498 7848a0e1 2020-03-19 stsp goto done;
2500 7848a0e1 2020-03-19 stsp } else if (strncmp("refs/heads/", refname, 11) == 0) {
2501 7848a0e1 2020-03-19 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2502 7848a0e1 2020-03-19 stsp remote_name, refname + 11) == -1) {
2503 7848a0e1 2020-03-19 stsp error = got_error_from_errno("asprintf");
2504 7848a0e1 2020-03-19 stsp goto done;
2507 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, remote_refname, 1);
2508 7848a0e1 2020-03-19 stsp if (error) {
2509 7848a0e1 2020-03-19 stsp if (error->code != GOT_ERR_NOT_REF)
2510 7848a0e1 2020-03-19 stsp goto done;
2511 6338a6a1 2020-03-21 stsp error = create_ref(remote_refname, id,
2512 688f11b3 2020-03-21 stsp verbosity, repo);
2513 7848a0e1 2020-03-19 stsp if (error)
2514 7848a0e1 2020-03-19 stsp goto done;
2516 db6d8ad8 2020-03-21 stsp error = update_ref(ref, id, replace_tags,
2517 db6d8ad8 2020-03-21 stsp verbosity, repo);
2518 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2519 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2520 9f142382 2020-03-21 stsp error = unlock_err;
2521 7848a0e1 2020-03-19 stsp got_ref_close(ref);
2522 7848a0e1 2020-03-19 stsp if (error)
2523 7848a0e1 2020-03-19 stsp goto done;
2526 2ec30c80 2020-03-20 stsp /* Also create a local branch if none exists yet. */
2527 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, refname, 1);
2528 2ec30c80 2020-03-20 stsp if (error) {
2529 2ec30c80 2020-03-20 stsp if (error->code != GOT_ERR_NOT_REF)
2530 2ec30c80 2020-03-20 stsp goto done;
2531 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity,
2533 2ec30c80 2020-03-20 stsp if (error)
2534 2ec30c80 2020-03-20 stsp goto done;
2536 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2537 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2538 9f142382 2020-03-21 stsp error = unlock_err;
2539 2ec30c80 2020-03-20 stsp got_ref_close(ref);
2543 f1bcca34 2020-03-25 stsp if (delete_refs) {
2544 3789fd73 2020-03-26 stsp error = delete_missing_refs(&refs, &symrefs, remote,
2545 3789fd73 2020-03-26 stsp verbosity, repo);
2546 f1bcca34 2020-03-25 stsp if (error)
2547 f1bcca34 2020-03-25 stsp goto done;
2550 f1bcca34 2020-03-25 stsp if (!remote->mirror_references) {
2551 f1bcca34 2020-03-25 stsp /* Update remote HEAD reference if the server provided one. */
2552 f1bcca34 2020-03-25 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
2553 f1bcca34 2020-03-25 stsp struct got_reference *target_ref;
2554 f1bcca34 2020-03-25 stsp const char *refname = pe->path;
2555 f1bcca34 2020-03-25 stsp const char *target = pe->data;
2556 f1bcca34 2020-03-25 stsp char *remote_refname = NULL, *remote_target = NULL;
2558 f1bcca34 2020-03-25 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
2561 f1bcca34 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
2564 f1bcca34 2020-03-25 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2565 f1bcca34 2020-03-25 stsp remote->name, refname) == -1) {
2566 f1bcca34 2020-03-25 stsp error = got_error_from_errno("asprintf");
2567 f1bcca34 2020-03-25 stsp goto done;
2569 f1bcca34 2020-03-25 stsp if (asprintf(&remote_target, "refs/remotes/%s/%s",
2570 f1bcca34 2020-03-25 stsp remote->name, target + 11) == -1) {
2571 f1bcca34 2020-03-25 stsp error = got_error_from_errno("asprintf");
2572 f1bcca34 2020-03-25 stsp free(remote_refname);
2573 f1bcca34 2020-03-25 stsp goto done;
2576 f1bcca34 2020-03-25 stsp error = got_ref_open(&target_ref, repo, remote_target,
2578 f1bcca34 2020-03-25 stsp if (error) {
2579 f1bcca34 2020-03-25 stsp free(remote_refname);
2580 f1bcca34 2020-03-25 stsp free(remote_target);
2581 f1bcca34 2020-03-25 stsp if (error->code == GOT_ERR_NOT_REF) {
2582 f1bcca34 2020-03-25 stsp error = NULL;
2585 f1bcca34 2020-03-25 stsp goto done;
2587 f1bcca34 2020-03-25 stsp error = update_symref(remote_refname, target_ref,
2588 f1bcca34 2020-03-25 stsp verbosity, repo);
2589 f1bcca34 2020-03-25 stsp free(remote_refname);
2590 f1bcca34 2020-03-25 stsp free(remote_target);
2591 f1bcca34 2020-03-25 stsp got_ref_close(target_ref);
2592 f1bcca34 2020-03-25 stsp if (error)
2593 f1bcca34 2020-03-25 stsp goto done;
2597 9c52365f 2020-03-21 stsp if (fetchpid > 0) {
2598 9c52365f 2020-03-21 stsp if (kill(fetchpid, SIGTERM) == -1)
2599 9c52365f 2020-03-21 stsp error = got_error_from_errno("kill");
2600 9c52365f 2020-03-21 stsp if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
2601 9c52365f 2020-03-21 stsp error = got_error_from_errno("waitpid");
2603 7848a0e1 2020-03-19 stsp if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
2604 7848a0e1 2020-03-19 stsp error = got_error_from_errno("close");
2605 1d0f4054 2021-06-17 stsp if (repo) {
2606 1d0f4054 2021-06-17 stsp const struct got_error *close_err = got_repo_close(repo);
2607 1d0f4054 2021-06-17 stsp if (error == NULL)
2608 1d0f4054 2021-06-17 stsp error = close_err;
2610 7848a0e1 2020-03-19 stsp if (worktree)
2611 7848a0e1 2020-03-19 stsp got_worktree_close(worktree);
2612 7848a0e1 2020-03-19 stsp TAILQ_FOREACH(pe, &refs, entry) {
2613 7848a0e1 2020-03-19 stsp free((void *)pe->path);
2614 7848a0e1 2020-03-19 stsp free(pe->data);
2616 7848a0e1 2020-03-19 stsp got_pathlist_free(&refs);
2617 7848a0e1 2020-03-19 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
2618 7848a0e1 2020-03-19 stsp free((void *)pe->path);
2619 7848a0e1 2020-03-19 stsp free(pe->data);
2621 7848a0e1 2020-03-19 stsp got_pathlist_free(&symrefs);
2622 4ba14133 2020-03-20 stsp got_pathlist_free(&wanted_branches);
2623 0e4002ca 2020-03-21 stsp got_pathlist_free(&wanted_refs);
2624 7848a0e1 2020-03-19 stsp free(id_str);
2625 7848a0e1 2020-03-19 stsp free(cwd);
2626 7848a0e1 2020-03-19 stsp free(repo_path);
2627 7848a0e1 2020-03-19 stsp free(pack_hash);
2628 7848a0e1 2020-03-19 stsp free(proto);
2629 7848a0e1 2020-03-19 stsp free(host);
2630 7848a0e1 2020-03-19 stsp free(port);
2631 7848a0e1 2020-03-19 stsp free(server_path);
2632 7848a0e1 2020-03-19 stsp free(repo_name);
2633 7848a0e1 2020-03-19 stsp return error;
2637 7848a0e1 2020-03-19 stsp __dead static void
2638 2ab43947 2020-03-18 stsp usage_checkout(void)
2640 2ab43947 2020-03-18 stsp fprintf(stderr, "usage: %s checkout [-E] [-b branch] [-c commit] "
2641 2ab43947 2020-03-18 stsp "[-p prefix] repository-path [worktree-path]\n", getprogname());
2645 2ab43947 2020-03-18 stsp static void
2646 2ab43947 2020-03-18 stsp show_worktree_base_ref_warning(void)
2648 2ab43947 2020-03-18 stsp fprintf(stderr, "%s: warning: could not create a reference "
2649 2ab43947 2020-03-18 stsp "to the work tree's base commit; the commit could be "
2650 e6786710 2021-07-03 stsp "garbage-collected by Git or 'gotadmin cleanup'; making the "
2651 e6786710 2021-07-03 stsp "repository writable and running 'got update' will prevent this\n",
2652 2ab43947 2020-03-18 stsp getprogname());
2655 2ab43947 2020-03-18 stsp struct got_checkout_progress_arg {
2656 2ab43947 2020-03-18 stsp const char *worktree_path;
2657 2ab43947 2020-03-18 stsp int had_base_commit_ref_error;
2660 2ab43947 2020-03-18 stsp static const struct got_error *
2661 2ab43947 2020-03-18 stsp checkout_progress(void *arg, unsigned char status, const char *path)
2663 2ab43947 2020-03-18 stsp struct got_checkout_progress_arg *a = arg;
2665 2ab43947 2020-03-18 stsp /* Base commit bump happens silently. */
2666 2ab43947 2020-03-18 stsp if (status == GOT_STATUS_BUMP_BASE)
2667 2ab43947 2020-03-18 stsp return NULL;
2669 2ab43947 2020-03-18 stsp if (status == GOT_STATUS_BASE_REF_ERR) {
2670 2ab43947 2020-03-18 stsp a->had_base_commit_ref_error = 1;
2671 2ab43947 2020-03-18 stsp return NULL;
2674 2ab43947 2020-03-18 stsp while (path[0] == '/')
2677 2ab43947 2020-03-18 stsp printf("%c %s/%s\n", status, a->worktree_path, path);
2678 2ab43947 2020-03-18 stsp return NULL;
2681 2ab43947 2020-03-18 stsp static const struct got_error *
2682 2ab43947 2020-03-18 stsp check_cancelled(void *arg)
2684 2ab43947 2020-03-18 stsp if (sigint_received || sigpipe_received)
2685 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_CANCELLED);
2686 2ab43947 2020-03-18 stsp return NULL;
2689 2ab43947 2020-03-18 stsp static const struct got_error *
2690 2ab43947 2020-03-18 stsp check_linear_ancestry(struct got_object_id *commit_id,
2691 2ab43947 2020-03-18 stsp struct got_object_id *base_commit_id, int allow_forwards_in_time_only,
2692 2ab43947 2020-03-18 stsp struct got_repository *repo)
2694 2ab43947 2020-03-18 stsp const struct got_error *err = NULL;
2695 2ab43947 2020-03-18 stsp struct got_object_id *yca_id;
2697 2ab43947 2020-03-18 stsp err = got_commit_graph_find_youngest_common_ancestor(&yca_id,
2698 2ab43947 2020-03-18 stsp commit_id, base_commit_id, repo, check_cancelled, NULL);
2700 2ab43947 2020-03-18 stsp return err;
2702 2ab43947 2020-03-18 stsp if (yca_id == NULL)
2703 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2706 2ab43947 2020-03-18 stsp * Require a straight line of history between the target commit
2707 2ab43947 2020-03-18 stsp * and the work tree's base commit.
2709 2ab43947 2020-03-18 stsp * Non-linear situations such as this require a rebase:
2711 2ab43947 2020-03-18 stsp * (commit) D F (base_commit)
2719 2ab43947 2020-03-18 stsp * 'got update' only handles linear cases:
2720 2ab43947 2020-03-18 stsp * Update forwards in time: A (base/yca) - B - C - D (commit)
2721 2ab43947 2020-03-18 stsp * Update backwards in time: D (base) - C - B - A (commit/yca)
2723 2ab43947 2020-03-18 stsp if (allow_forwards_in_time_only) {
2724 2ab43947 2020-03-18 stsp if (got_object_id_cmp(base_commit_id, yca_id) != 0)
2725 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2726 2ab43947 2020-03-18 stsp } else if (got_object_id_cmp(commit_id, yca_id) != 0 &&
2727 2ab43947 2020-03-18 stsp got_object_id_cmp(base_commit_id, yca_id) != 0)
2728 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2730 2ab43947 2020-03-18 stsp free(yca_id);
2731 2ab43947 2020-03-18 stsp return NULL;
2734 2ab43947 2020-03-18 stsp static const struct got_error *
2735 2ab43947 2020-03-18 stsp check_same_branch(struct got_object_id *commit_id,
2736 2ab43947 2020-03-18 stsp struct got_reference *head_ref, struct got_object_id *yca_id,
2737 2ab43947 2020-03-18 stsp struct got_repository *repo)
2739 2ab43947 2020-03-18 stsp const struct got_error *err = NULL;
2740 2ab43947 2020-03-18 stsp struct got_commit_graph *graph = NULL;
2741 2ab43947 2020-03-18 stsp struct got_object_id *head_commit_id = NULL;
2742 2ab43947 2020-03-18 stsp int is_same_branch = 0;
2744 2ab43947 2020-03-18 stsp err = got_ref_resolve(&head_commit_id, repo, head_ref);
2746 2ab43947 2020-03-18 stsp goto done;
2748 2ab43947 2020-03-18 stsp if (got_object_id_cmp(head_commit_id, commit_id) == 0) {
2749 2ab43947 2020-03-18 stsp is_same_branch = 1;
2750 2ab43947 2020-03-18 stsp goto done;
2752 2ab43947 2020-03-18 stsp if (yca_id && got_object_id_cmp(commit_id, yca_id) == 0) {
2753 2ab43947 2020-03-18 stsp is_same_branch = 1;
2754 2ab43947 2020-03-18 stsp goto done;
2757 2ab43947 2020-03-18 stsp err = got_commit_graph_open(&graph, "/", 1);
2759 2ab43947 2020-03-18 stsp goto done;
2761 2ab43947 2020-03-18 stsp err = got_commit_graph_iter_start(graph, head_commit_id, repo,
2762 2ab43947 2020-03-18 stsp check_cancelled, NULL);
2764 2ab43947 2020-03-18 stsp goto done;
2766 2ab43947 2020-03-18 stsp for (;;) {
2767 2ab43947 2020-03-18 stsp struct got_object_id *id;
2768 2ab43947 2020-03-18 stsp err = got_commit_graph_iter_next(&id, graph, repo,
2769 2ab43947 2020-03-18 stsp check_cancelled, NULL);
2770 2ab43947 2020-03-18 stsp if (err) {
2771 2ab43947 2020-03-18 stsp if (err->code == GOT_ERR_ITER_COMPLETED)
2772 2ab43947 2020-03-18 stsp err = NULL;
2777 2ab43947 2020-03-18 stsp if (yca_id && got_object_id_cmp(id, yca_id) == 0)
2779 2ab43947 2020-03-18 stsp if (got_object_id_cmp(id, commit_id) == 0) {
2780 2ab43947 2020-03-18 stsp is_same_branch = 1;
2786 2ab43947 2020-03-18 stsp if (graph)
2787 2ab43947 2020-03-18 stsp got_commit_graph_close(graph);
2788 2ab43947 2020-03-18 stsp free(head_commit_id);
2789 2ab43947 2020-03-18 stsp if (!err && !is_same_branch)
2790 2ab43947 2020-03-18 stsp err = got_error(GOT_ERR_ANCESTRY);
2791 2ab43947 2020-03-18 stsp return err;
2794 4ed7e80c 2018-05-20 stsp static const struct got_error *
2795 4b6c9460 2020-03-05 stsp checkout_ancestry_error(struct got_reference *ref, const char *commit_id_str)
2797 4b6c9460 2020-03-05 stsp static char msg[512];
2798 4b6c9460 2020-03-05 stsp const char *branch_name;
2800 4b6c9460 2020-03-05 stsp if (got_ref_is_symbolic(ref))
2801 4b6c9460 2020-03-05 stsp branch_name = got_ref_get_symref_target(ref);
2803 4b6c9460 2020-03-05 stsp branch_name = got_ref_get_name(ref);
2805 4b6c9460 2020-03-05 stsp if (strncmp("refs/heads/", branch_name, 11) == 0)
2806 4b6c9460 2020-03-05 stsp branch_name += 11;
2808 4b6c9460 2020-03-05 stsp snprintf(msg, sizeof(msg),
2809 4b6c9460 2020-03-05 stsp "target commit is not contained in branch '%s'; "
2810 4b6c9460 2020-03-05 stsp "the branch to use must be specified with -b; "
2811 4b6c9460 2020-03-05 stsp "if necessary a new branch can be created for "
2812 4b6c9460 2020-03-05 stsp "this commit with 'got branch -c %s BRANCH_NAME'",
2813 4b6c9460 2020-03-05 stsp branch_name, commit_id_str);
2815 4b6c9460 2020-03-05 stsp return got_error_msg(GOT_ERR_ANCESTRY, msg);
2818 4b6c9460 2020-03-05 stsp static const struct got_error *
2819 c09a553d 2018-03-12 stsp cmd_checkout(int argc, char *argv[])
2821 c09a553d 2018-03-12 stsp const struct got_error *error = NULL;
2822 c09a553d 2018-03-12 stsp struct got_repository *repo = NULL;
2823 c09a553d 2018-03-12 stsp struct got_reference *head_ref = NULL;
2824 c09a553d 2018-03-12 stsp struct got_worktree *worktree = NULL;
2825 c09a553d 2018-03-12 stsp char *repo_path = NULL;
2826 c09a553d 2018-03-12 stsp char *worktree_path = NULL;
2827 0bb8a95e 2018-03-12 stsp const char *path_prefix = "";
2828 08573d5b 2019-05-14 stsp const char *branch_name = GOT_REF_HEAD;
2829 8069f636 2019-01-12 stsp char *commit_id_str = NULL;
2830 f0207f6a 2020-10-19 stsp char *cwd = NULL;
2831 bb51a5b4 2020-01-13 stsp int ch, same_path_prefix, allow_nonempty = 0;
2832 f2ea84fa 2019-07-27 stsp struct got_pathlist_head paths;
2833 7f47418f 2019-12-20 stsp struct got_checkout_progress_arg cpa;
2835 f2ea84fa 2019-07-27 stsp TAILQ_INIT(&paths);
2837 bb51a5b4 2020-01-13 stsp while ((ch = getopt(argc, argv, "b:c:Ep:")) != -1) {
2838 0bb8a95e 2018-03-12 stsp switch (ch) {
2840 08573d5b 2019-05-14 stsp branch_name = optarg;
2843 8069f636 2019-01-12 stsp commit_id_str = strdup(optarg);
2844 8069f636 2019-01-12 stsp if (commit_id_str == NULL)
2845 638f9024 2019-05-13 stsp return got_error_from_errno("strdup");
2848 bb51a5b4 2020-01-13 stsp allow_nonempty = 1;
2851 0bb8a95e 2018-03-12 stsp path_prefix = optarg;
2854 2deda0b9 2019-03-07 stsp usage_checkout();
2855 0bb8a95e 2018-03-12 stsp /* NOTREACHED */
2859 0bb8a95e 2018-03-12 stsp argc -= optind;
2860 0bb8a95e 2018-03-12 stsp argv += optind;
2862 6715a751 2018-03-16 stsp #ifndef PROFILE
2863 68ed9ba5 2019-02-10 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd "
2864 68ed9ba5 2019-02-10 stsp "unveil", NULL) == -1)
2865 c09a553d 2018-03-12 stsp err(1, "pledge");
2867 0bb8a95e 2018-03-12 stsp if (argc == 1) {
2868 c47340da 2020-09-20 stsp char *base, *dotgit;
2869 f0207f6a 2020-10-19 stsp const char *path;
2870 76089277 2018-04-01 stsp repo_path = realpath(argv[0], NULL);
2871 76089277 2018-04-01 stsp if (repo_path == NULL)
2872 638f9024 2019-05-13 stsp return got_error_from_errno2("realpath", argv[0]);
2873 c09a553d 2018-03-12 stsp cwd = getcwd(NULL, 0);
2874 76089277 2018-04-01 stsp if (cwd == NULL) {
2875 638f9024 2019-05-13 stsp error = got_error_from_errno("getcwd");
2876 76089277 2018-04-01 stsp goto done;
2878 c47340da 2020-09-20 stsp if (path_prefix[0])
2879 f0207f6a 2020-10-19 stsp path = path_prefix;
2881 f0207f6a 2020-10-19 stsp path = repo_path;
2882 f0207f6a 2020-10-19 stsp error = got_path_basename(&base, path);
2883 f0207f6a 2020-10-19 stsp if (error)
2884 c47340da 2020-09-20 stsp goto done;
2885 c09a553d 2018-03-12 stsp dotgit = strstr(base, ".git");
2886 c09a553d 2018-03-12 stsp if (dotgit)
2887 c09a553d 2018-03-12 stsp *dotgit = '\0';
2888 c09a553d 2018-03-12 stsp if (asprintf(&worktree_path, "%s/%s", cwd, base) == -1) {
2889 638f9024 2019-05-13 stsp error = got_error_from_errno("asprintf");
2890 f0207f6a 2020-10-19 stsp free(base);
2891 76089277 2018-04-01 stsp goto done;
2893 f0207f6a 2020-10-19 stsp free(base);
2894 0bb8a95e 2018-03-12 stsp } else if (argc == 2) {
2895 76089277 2018-04-01 stsp repo_path = realpath(argv[0], NULL);
2896 76089277 2018-04-01 stsp if (repo_path == NULL) {
2897 638f9024 2019-05-13 stsp error = got_error_from_errno2("realpath", argv[0]);
2898 76089277 2018-04-01 stsp goto done;
2900 f7b38925 2018-04-01 stsp worktree_path = realpath(argv[1], NULL);
2901 76089277 2018-04-01 stsp if (worktree_path == NULL) {
2902 b4b3a7dd 2019-07-22 stsp if (errno != ENOENT) {
2903 b4b3a7dd 2019-07-22 stsp error = got_error_from_errno2("realpath",
2905 b4b3a7dd 2019-07-22 stsp goto done;
2907 b4b3a7dd 2019-07-22 stsp worktree_path = strdup(argv[1]);
2908 b4b3a7dd 2019-07-22 stsp if (worktree_path == NULL) {
2909 b4b3a7dd 2019-07-22 stsp error = got_error_from_errno("strdup");
2910 b4b3a7dd 2019-07-22 stsp goto done;
2914 c09a553d 2018-03-12 stsp usage_checkout();
2916 7fbaa4f3 2019-05-11 stsp got_path_strip_trailing_slashes(repo_path);
2917 72151b04 2019-05-11 stsp got_path_strip_trailing_slashes(worktree_path);
2919 c9956ddf 2019-09-08 stsp error = got_repo_open(&repo, repo_path, NULL);
2920 c09a553d 2018-03-12 stsp if (error != NULL)
2921 c02c541e 2019-03-29 stsp goto done;
2923 c530dc23 2019-07-23 stsp /* Pre-create work tree path for unveil(2) */
2924 c530dc23 2019-07-23 stsp error = got_path_mkdir(worktree_path);
2925 c530dc23 2019-07-23 stsp if (error) {
2926 80c1b583 2019-08-07 stsp if (!(error->code == GOT_ERR_ERRNO && errno == EISDIR) &&
2927 80c1b583 2019-08-07 stsp !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
2928 c530dc23 2019-07-23 stsp goto done;
2929 bb51a5b4 2020-01-13 stsp if (!allow_nonempty &&
2930 bb51a5b4 2020-01-13 stsp !got_path_dir_is_empty(worktree_path)) {
2931 c530dc23 2019-07-23 stsp error = got_error_path(worktree_path,
2932 c530dc23 2019-07-23 stsp GOT_ERR_DIR_NOT_EMPTY);
2933 c530dc23 2019-07-23 stsp goto done;
2937 c530dc23 2019-07-23 stsp error = apply_unveil(got_repo_get_path(repo), 0, worktree_path);
2938 c02c541e 2019-03-29 stsp if (error)
2939 c09a553d 2018-03-12 stsp goto done;
2941 08573d5b 2019-05-14 stsp error = got_ref_open(&head_ref, repo, branch_name, 0);
2942 c09a553d 2018-03-12 stsp if (error != NULL)
2943 c09a553d 2018-03-12 stsp goto done;
2945 0bb8a95e 2018-03-12 stsp error = got_worktree_init(worktree_path, head_ref, path_prefix, repo);
2946 d70b8e30 2018-12-27 stsp if (error != NULL && !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
2947 c09a553d 2018-03-12 stsp goto done;
2949 c09a553d 2018-03-12 stsp error = got_worktree_open(&worktree, worktree_path);
2950 c09a553d 2018-03-12 stsp if (error != NULL)
2951 c09a553d 2018-03-12 stsp goto done;
2953 e5dc7198 2018-12-29 stsp error = got_worktree_match_path_prefix(&same_path_prefix, worktree,
2954 e5dc7198 2018-12-29 stsp path_prefix);
2955 e5dc7198 2018-12-29 stsp if (error != NULL)
2956 e5dc7198 2018-12-29 stsp goto done;
2957 e5dc7198 2018-12-29 stsp if (!same_path_prefix) {
2958 49520a32 2018-12-29 stsp error = got_error(GOT_ERR_PATH_PREFIX);
2959 49520a32 2018-12-29 stsp goto done;
2962 8069f636 2019-01-12 stsp if (commit_id_str) {
2963 04f57cb3 2019-07-25 stsp struct got_object_id *commit_id;
2964 84de9106 2020-12-26 stsp struct got_reflist_head refs;
2965 d9dff0e5 2020-12-26 stsp TAILQ_INIT(&refs);
2966 84de9106 2020-12-26 stsp error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name,
2968 84de9106 2020-12-26 stsp if (error)
2969 84de9106 2020-12-26 stsp goto done;
2970 71a27632 2020-01-15 stsp error = got_repo_match_object_id(&commit_id, NULL,
2971 84de9106 2020-12-26 stsp commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo);
2972 84de9106 2020-12-26 stsp got_ref_list_free(&refs);
2973 30837e32 2019-07-25 stsp if (error)
2974 8069f636 2019-01-12 stsp goto done;
2975 024e9686 2019-05-14 stsp error = check_linear_ancestry(commit_id,
2976 3aef623b 2019-10-15 stsp got_worktree_get_base_commit_id(worktree), 0, repo);
2977 8069f636 2019-01-12 stsp if (error != NULL) {
2978 8069f636 2019-01-12 stsp free(commit_id);
2979 4b6c9460 2020-03-05 stsp if (error->code == GOT_ERR_ANCESTRY) {
2980 4b6c9460 2020-03-05 stsp error = checkout_ancestry_error(
2981 4b6c9460 2020-03-05 stsp head_ref, commit_id_str);
2983 8069f636 2019-01-12 stsp goto done;
2985 a51a74b3 2019-07-27 stsp error = check_same_branch(commit_id, head_ref, NULL, repo);
2986 4b6c9460 2020-03-05 stsp if (error) {
2987 4b6c9460 2020-03-05 stsp if (error->code == GOT_ERR_ANCESTRY) {
2988 4b6c9460 2020-03-05 stsp error = checkout_ancestry_error(
2989 4b6c9460 2020-03-05 stsp head_ref, commit_id_str);
2991 45d344f6 2019-05-14 stsp goto done;
2993 8069f636 2019-01-12 stsp error = got_worktree_set_base_commit_id(worktree, repo,