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 4fccd2fe 2023-03-08 thomas #include "got_compat.h"
21 8b925c6c 2022-07-16 thomas #include <sys/queue.h>
22 d06b3506 2022-07-04 thomas #include <sys/time.h>
23 c0768b0f 2018-06-10 stsp #include <sys/types.h>
24 5de5890b 2018-10-18 stsp #include <sys/stat.h>
25 33ad4cbe 2019-05-12 jcs #include <sys/wait.h>
27 5c860e29 2018-03-12 stsp #include <err.h>
28 5c860e29 2018-03-12 stsp #include <errno.h>
29 12463d8b 2019-12-13 stsp #include <fcntl.h>
30 12ce7a6c 2019-08-12 stsp #include <limits.h>
31 5c860e29 2018-03-12 stsp #include <locale.h>
32 818c7501 2019-07-11 stsp #include <ctype.h>
33 99437157 2018-11-11 stsp #include <signal.h>
34 5c860e29 2018-03-12 stsp #include <stdio.h>
35 5c860e29 2018-03-12 stsp #include <stdlib.h>
36 5c860e29 2018-03-12 stsp #include <string.h>
37 5c860e29 2018-03-12 stsp #include <unistd.h>
38 c09a553d 2018-03-12 stsp #include <libgen.h>
39 c0768b0f 2018-06-10 stsp #include <time.h>
40 33ad4cbe 2019-05-12 jcs #include <paths.h>
41 6841bf13 2019-11-29 kn #include <regex.h>
42 83cd27f8 2020-01-13 stsp #include <getopt.h>
44 53ccebc2 2019-07-30 stsp #include "got_version.h"
45 f42b1b34 2018-03-12 stsp #include "got_error.h"
46 f42b1b34 2018-03-12 stsp #include "got_object.h"
47 5261c201 2018-04-01 stsp #include "got_reference.h"
48 f42b1b34 2018-03-12 stsp #include "got_repository.h"
49 1dd54920 2019-05-11 stsp #include "got_path.h"
50 e6209546 2019-08-22 stsp #include "got_cancel.h"
51 c09a553d 2018-03-12 stsp #include "got_worktree.h"
52 79109fed 2018-03-27 stsp #include "got_diff.h"
53 372ccdbb 2018-06-10 stsp #include "got_commit_graph.h"
54 6f23baec 2020-03-18 stsp #include "got_fetch.h"
55 f8a36e22 2021-08-26 stsp #include "got_send.h"
56 404c43c4 2018-06-21 stsp #include "got_blame.h"
57 63219cd2 2019-01-04 stsp #include "got_privsep.h"
58 793c30b5 2019-05-13 stsp #include "got_opentemp.h"
59 50b0790e 2020-09-11 stsp #include "got_gotconfig.h"
60 d65a88a2 2021-09-05 stsp #include "got_dial.h"
61 069bbb86 2022-03-07 thomas #include "got_patch.h"
62 871bd038 2022-07-03 thomas #include "got_sigs.h"
63 871bd038 2022-07-03 thomas #include "got_date.h"
64 9139e004 2023-07-17 thomas #include "got_keyword.h"
66 5c860e29 2018-03-12 stsp #ifndef nitems
67 5c860e29 2018-03-12 stsp #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
70 a8938c43 2024-03-19 thomas #ifndef GOT_DEFAULT_EDITOR
71 a8938c43 2024-03-19 thomas #define GOT_DEFAULT_EDITOR "/usr/bin/vi"
74 99437157 2018-11-11 stsp static volatile sig_atomic_t sigint_received;
75 99437157 2018-11-11 stsp static volatile sig_atomic_t sigpipe_received;
78 99437157 2018-11-11 stsp catch_sigint(int signo)
80 99437157 2018-11-11 stsp sigint_received = 1;
84 99437157 2018-11-11 stsp catch_sigpipe(int signo)
86 99437157 2018-11-11 stsp sigpipe_received = 1;
90 8cfb4057 2019-07-09 stsp struct got_cmd {
91 820059fa 2020-09-25 stsp const char *cmd_name;
92 d7d4f210 2018-03-12 stsp const struct got_error *(*cmd_main)(int, char *[]);
93 1b6b95a8 2018-03-12 stsp void (*cmd_usage)(void);
94 97b3a7be 2019-07-09 stsp const char *cmd_alias;
97 6879ba42 2020-10-01 naddy __dead static void usage(int, int);
98 6becd179 2024-06-03 thomas __dead static void usage_init(void);
99 3ce1b845 2019-07-15 stsp __dead static void usage_import(void);
100 93658fb9 2020-03-18 stsp __dead static void usage_clone(void);
101 7848a0e1 2020-03-19 stsp __dead static void usage_fetch(void);
102 2ab43947 2020-03-18 stsp __dead static void usage_checkout(void);
103 507dc3bb 2018-12-29 stsp __dead static void usage_update(void);
104 4ed7e80c 2018-05-20 stsp __dead static void usage_log(void);
105 4ed7e80c 2018-05-20 stsp __dead static void usage_diff(void);
106 404c43c4 2018-06-21 stsp __dead static void usage_blame(void);
107 5de5890b 2018-10-18 stsp __dead static void usage_tree(void);
108 6bad629b 2019-02-04 stsp __dead static void usage_status(void);
109 d0eebce4 2019-03-11 stsp __dead static void usage_ref(void);
110 4e759de4 2019-06-26 stsp __dead static void usage_branch(void);
111 8e7bd50a 2019-08-22 stsp __dead static void usage_tag(void);
112 d00136be 2019-03-26 stsp __dead static void usage_add(void);
113 648e4ef7 2019-07-09 stsp __dead static void usage_remove(void);
114 069bbb86 2022-03-07 thomas __dead static void usage_patch(void);
115 a129376b 2019-03-28 stsp __dead static void usage_revert(void);
116 c4296144 2019-05-09 stsp __dead static void usage_commit(void);
117 f8a36e22 2021-08-26 stsp __dead static void usage_send(void);
118 234035bc 2019-06-01 stsp __dead static void usage_cherrypick(void);
119 5ef14e63 2019-06-02 stsp __dead static void usage_backout(void);
120 818c7501 2019-07-11 stsp __dead static void usage_rebase(void);
121 0ebf8283 2019-07-24 stsp __dead static void usage_histedit(void);
122 2822a352 2019-10-15 stsp __dead static void usage_integrate(void);
123 10604dce 2021-09-24 thomas __dead static void usage_merge(void);
124 715dc77e 2019-08-03 stsp __dead static void usage_stage(void);
125 ad493afc 2019-08-03 stsp __dead static void usage_unstage(void);
126 01073a5d 2019-08-22 stsp __dead static void usage_cat(void);
127 b2118c49 2020-07-28 stsp __dead static void usage_info(void);
129 6becd179 2024-06-03 thomas static const struct got_error* cmd_init(int, char *[]);
130 3ce1b845 2019-07-15 stsp static const struct got_error* cmd_import(int, char *[]);
131 93658fb9 2020-03-18 stsp static const struct got_error* cmd_clone(int, char *[]);
132 7848a0e1 2020-03-19 stsp static const struct got_error* cmd_fetch(int, char *[]);
133 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_checkout(int, char *[]);
134 507dc3bb 2018-12-29 stsp static const struct got_error* cmd_update(int, char *[]);
135 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_log(int, char *[]);
136 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_diff(int, char *[]);
137 404c43c4 2018-06-21 stsp static const struct got_error* cmd_blame(int, char *[]);
138 5de5890b 2018-10-18 stsp static const struct got_error* cmd_tree(int, char *[]);
139 4ed7e80c 2018-05-20 stsp static const struct got_error* cmd_status(int, char *[]);
140 d0eebce4 2019-03-11 stsp static const struct got_error* cmd_ref(int, char *[]);
141 4e759de4 2019-06-26 stsp static const struct got_error* cmd_branch(int, char *[]);
142 8e7bd50a 2019-08-22 stsp static const struct got_error* cmd_tag(int, char *[]);
143 d00136be 2019-03-26 stsp static const struct got_error* cmd_add(int, char *[]);
144 648e4ef7 2019-07-09 stsp static const struct got_error* cmd_remove(int, char *[]);
145 069bbb86 2022-03-07 thomas static const struct got_error* cmd_patch(int, char *[]);
146 a129376b 2019-03-28 stsp static const struct got_error* cmd_revert(int, char *[]);
147 c4296144 2019-05-09 stsp static const struct got_error* cmd_commit(int, char *[]);
148 f8a36e22 2021-08-26 stsp static const struct got_error* cmd_send(int, char *[]);
149 234035bc 2019-06-01 stsp static const struct got_error* cmd_cherrypick(int, char *[]);
150 5ef14e63 2019-06-02 stsp static const struct got_error* cmd_backout(int, char *[]);
151 818c7501 2019-07-11 stsp static const struct got_error* cmd_rebase(int, char *[]);
152 0ebf8283 2019-07-24 stsp static const struct got_error* cmd_histedit(int, char *[]);
153 2822a352 2019-10-15 stsp static const struct got_error* cmd_integrate(int, char *[]);
154 10604dce 2021-09-24 thomas static const struct got_error* cmd_merge(int, char *[]);
155 715dc77e 2019-08-03 stsp static const struct got_error* cmd_stage(int, char *[]);
156 ad493afc 2019-08-03 stsp static const struct got_error* cmd_unstage(int, char *[]);
157 01073a5d 2019-08-22 stsp static const struct got_error* cmd_cat(int, char *[]);
158 b2118c49 2020-07-28 stsp static const struct got_error* cmd_info(int, char *[]);
160 641a8ee6 2022-02-16 thomas static const struct got_cmd got_commands[] = {
161 6becd179 2024-06-03 thomas { "init", cmd_init, usage_init, "" },
162 bc26cce8 2019-08-04 stsp { "import", cmd_import, usage_import, "im" },
163 93658fb9 2020-03-18 stsp { "clone", cmd_clone, usage_clone, "cl" },
164 7848a0e1 2020-03-19 stsp { "fetch", cmd_fetch, usage_fetch, "fe" },
165 2ab43947 2020-03-18 stsp { "checkout", cmd_checkout, usage_checkout, "co" },
166 97b3a7be 2019-07-09 stsp { "update", cmd_update, usage_update, "up" },
167 97b3a7be 2019-07-09 stsp { "log", cmd_log, usage_log, "" },
168 bc26cce8 2019-08-04 stsp { "diff", cmd_diff, usage_diff, "di" },
169 bc26cce8 2019-08-04 stsp { "blame", cmd_blame, usage_blame, "bl" },
170 bc26cce8 2019-08-04 stsp { "tree", cmd_tree, usage_tree, "tr" },
171 97b3a7be 2019-07-09 stsp { "status", cmd_status, usage_status, "st" },
172 97b3a7be 2019-07-09 stsp { "ref", cmd_ref, usage_ref, "" },
173 97b3a7be 2019-07-09 stsp { "branch", cmd_branch, usage_branch, "br" },
174 8e7bd50a 2019-08-22 stsp { "tag", cmd_tag, usage_tag, "" },
175 97b3a7be 2019-07-09 stsp { "add", cmd_add, usage_add, "" },
176 648e4ef7 2019-07-09 stsp { "remove", cmd_remove, usage_remove, "rm" },
177 069bbb86 2022-03-07 thomas { "patch", cmd_patch, usage_patch, "pa" },
178 97b3a7be 2019-07-09 stsp { "revert", cmd_revert, usage_revert, "rv" },
179 97b3a7be 2019-07-09 stsp { "commit", cmd_commit, usage_commit, "ci" },
180 f8a36e22 2021-08-26 stsp { "send", cmd_send, usage_send, "se" },
181 016477fd 2019-07-09 stsp { "cherrypick", cmd_cherrypick, usage_cherrypick, "cy" },
182 97b3a7be 2019-07-09 stsp { "backout", cmd_backout, usage_backout, "bo" },
183 818c7501 2019-07-11 stsp { "rebase", cmd_rebase, usage_rebase, "rb" },
184 0ebf8283 2019-07-24 stsp { "histedit", cmd_histedit, usage_histedit, "he" },
185 2822a352 2019-10-15 stsp { "integrate", cmd_integrate, usage_integrate,"ig" },
186 10604dce 2021-09-24 thomas { "merge", cmd_merge, usage_merge, "mg" },
187 715dc77e 2019-08-03 stsp { "stage", cmd_stage, usage_stage, "sg" },
188 ad493afc 2019-08-03 stsp { "unstage", cmd_unstage, usage_unstage, "ug" },
189 01073a5d 2019-08-22 stsp { "cat", cmd_cat, usage_cat, "" },
190 b2118c49 2020-07-28 stsp { "info", cmd_info, usage_info, "" },
193 ce5b7c56 2019-07-09 stsp static void
194 6879ba42 2020-10-01 naddy list_commands(FILE *fp)
198 6879ba42 2020-10-01 naddy fprintf(fp, "commands:");
199 ce5b7c56 2019-07-09 stsp for (i = 0; i < nitems(got_commands); i++) {
200 641a8ee6 2022-02-16 thomas const struct got_cmd *cmd = &got_commands[i];
201 6879ba42 2020-10-01 naddy fprintf(fp, " %s", cmd->cmd_name);
203 6879ba42 2020-10-01 naddy fputc('\n', fp);
206 ff69268e 2020-12-13 stsp __dead static void
207 ff69268e 2020-12-13 stsp option_conflict(char a, char b)
209 ff69268e 2020-12-13 stsp errx(1, "-%c and -%c options are mutually exclusive", a, b);
213 5c860e29 2018-03-12 stsp main(int argc, char *argv[])
215 641a8ee6 2022-02-16 thomas const struct got_cmd *cmd;
218 53ccebc2 2019-07-30 stsp int hflag = 0, Vflag = 0;
219 641a8ee6 2022-02-16 thomas static const struct option longopts[] = {
220 62d463ca 2020-10-20 naddy { "version", no_argument, NULL, 'V' },
221 62d463ca 2020-10-20 naddy { NULL, 0, NULL, 0 }
224 289e3cbf 2019-02-04 stsp setlocale(LC_CTYPE, "");
226 6586ea88 2020-01-13 stsp while ((ch = getopt_long(argc, argv, "+hV", longopts, NULL)) != -1) {
227 5c860e29 2018-03-12 stsp switch (ch) {
235 6879ba42 2020-10-01 naddy usage(hflag, 1);
236 5c860e29 2018-03-12 stsp /* NOTREACHED */
240 5c860e29 2018-03-12 stsp argc -= optind;
241 5c860e29 2018-03-12 stsp argv += optind;
242 9814e6a3 2020-09-27 naddy optind = 1;
243 9814e6a3 2020-09-27 naddy optreset = 1;
245 53ccebc2 2019-07-30 stsp if (Vflag) {
246 53ccebc2 2019-07-30 stsp got_version_print_str();
250 5c860e29 2018-03-12 stsp if (argc <= 0)
251 6879ba42 2020-10-01 naddy usage(hflag, hflag ? 0 : 1);
253 99437157 2018-11-11 stsp signal(SIGINT, catch_sigint);
254 99437157 2018-11-11 stsp signal(SIGPIPE, catch_sigpipe);
256 5c860e29 2018-03-12 stsp for (i = 0; i < nitems(got_commands); i++) {
257 d7d4f210 2018-03-12 stsp const struct got_error *error;
259 5c860e29 2018-03-12 stsp cmd = &got_commands[i];
261 97b3a7be 2019-07-09 stsp if (strcmp(cmd->cmd_name, argv[0]) != 0 &&
262 97b3a7be 2019-07-09 stsp strcmp(cmd->cmd_alias, argv[0]) != 0)
266 641a8ee6 2022-02-16 thomas cmd->cmd_usage();
268 641a8ee6 2022-02-16 thomas error = cmd->cmd_main(argc, argv);
269 f8afbdc8 2019-11-08 stsp if (error && error->code != GOT_ERR_CANCELLED &&
270 f8afbdc8 2019-11-08 stsp error->code != GOT_ERR_PRIVSEP_EXIT &&
271 f8afbdc8 2019-11-08 stsp !(sigpipe_received &&
272 70015d7a 2019-11-08 stsp error->code == GOT_ERR_ERRNO && errno == EPIPE) &&
273 70015d7a 2019-11-08 stsp !(sigint_received &&
274 70015d7a 2019-11-08 stsp error->code == GOT_ERR_ERRNO && errno == EINTR)) {
275 4d0b6596 2023-04-14 thomas fflush(stdout);
276 d7d4f210 2018-03-12 stsp fprintf(stderr, "%s: %s\n", getprogname(), error->msg);
283 20ecf764 2018-03-12 stsp fprintf(stderr, "%s: unknown command '%s'\n", getprogname(), argv[0]);
284 6879ba42 2020-10-01 naddy list_commands(stderr);
288 4ed7e80c 2018-05-20 stsp __dead static void
289 6879ba42 2020-10-01 naddy usage(int hflag, int status)
291 6879ba42 2020-10-01 naddy FILE *fp = (status == 0) ? stdout : stderr;
293 0a58e722 2022-10-04 thomas fprintf(fp, "usage: %s [-hV] command [arg ...]\n",
294 53ccebc2 2019-07-30 stsp getprogname());
296 6879ba42 2020-10-01 naddy list_commands(fp);
297 6879ba42 2020-10-01 naddy exit(status);
300 0266afb7 2019-01-04 stsp static const struct got_error *
301 0ee7065d 2019-05-13 stsp get_editor(char **abspath)
303 0ee7065d 2019-05-13 stsp const struct got_error *err = NULL;
304 e2ba3d07 2019-05-13 stsp const char *editor;
306 8920fa04 2019-08-18 stsp *abspath = NULL;
308 e2ba3d07 2019-05-13 stsp editor = getenv("VISUAL");
309 e2ba3d07 2019-05-13 stsp if (editor == NULL)
310 e2ba3d07 2019-05-13 stsp editor = getenv("EDITOR");
312 0ee7065d 2019-05-13 stsp if (editor) {
313 0ee7065d 2019-05-13 stsp err = got_path_find_prog(abspath, editor);
315 0ee7065d 2019-05-13 stsp return err;
318 0ee7065d 2019-05-13 stsp if (*abspath == NULL) {
319 a8938c43 2024-03-19 thomas *abspath = strdup(GOT_DEFAULT_EDITOR);
320 0ee7065d 2019-05-13 stsp if (*abspath == NULL)
321 0ee7065d 2019-05-13 stsp return got_error_from_errno("strdup");
324 e2ba3d07 2019-05-13 stsp return NULL;
327 e2ba3d07 2019-05-13 stsp static const struct got_error *
328 d0eebce4 2019-03-11 stsp apply_unveil(const char *repo_path, int repo_read_only,
329 c530dc23 2019-07-23 stsp const char *worktree_path)
331 163ce85a 2019-05-13 stsp const struct got_error *err;
333 37c06ea4 2019-07-15 stsp #ifdef PROFILE
334 37c06ea4 2019-07-15 stsp if (unveil("gmon.out", "rwc") != 0)
335 37c06ea4 2019-07-15 stsp return got_error_from_errno2("unveil", "gmon.out");
337 d0eebce4 2019-03-11 stsp if (repo_path && unveil(repo_path, repo_read_only ? "r" : "rwc") != 0)
338 638f9024 2019-05-13 stsp return got_error_from_errno2("unveil", repo_path);
340 0266afb7 2019-01-04 stsp if (worktree_path && unveil(worktree_path, "rwc") != 0)
341 638f9024 2019-05-13 stsp return got_error_from_errno2("unveil", worktree_path);
343 bb63914a 2020-02-17 stsp if (unveil(GOT_TMPDIR_STR, "rwc") != 0)
344 bb63914a 2020-02-17 stsp return got_error_from_errno2("unveil", GOT_TMPDIR_STR);
346 163ce85a 2019-05-13 stsp err = got_privsep_unveil_exec_helpers();
347 163ce85a 2019-05-13 stsp if (err != NULL)
348 163ce85a 2019-05-13 stsp return err;
350 0266afb7 2019-01-04 stsp if (unveil(NULL, NULL) != 0)
351 638f9024 2019-05-13 stsp return got_error_from_errno("unveil");
353 0266afb7 2019-01-04 stsp return NULL;
356 3ce1b845 2019-07-15 stsp __dead static void
357 6becd179 2024-06-03 thomas usage_init(void)
359 6becd179 2024-06-03 thomas fprintf(stderr, "usage: %s init [-b branch] repository-path\n",
360 6becd179 2024-06-03 thomas getprogname());
364 6becd179 2024-06-03 thomas static const struct got_error *
365 6becd179 2024-06-03 thomas cmd_init(int argc, char *argv[])
367 6becd179 2024-06-03 thomas const struct got_error *error = NULL;
368 6becd179 2024-06-03 thomas const char *head_name = NULL;
369 6becd179 2024-06-03 thomas char *repo_path = NULL;
372 6becd179 2024-06-03 thomas while ((ch = getopt(argc, argv, "b:")) != -1) {
373 6becd179 2024-06-03 thomas switch (ch) {
374 6becd179 2024-06-03 thomas case 'b':
375 6becd179 2024-06-03 thomas head_name = optarg;
378 6becd179 2024-06-03 thomas usage_init();
379 6becd179 2024-06-03 thomas /* NOTREACHED */
383 6becd179 2024-06-03 thomas argc -= optind;
384 6becd179 2024-06-03 thomas argv += optind;
386 6becd179 2024-06-03 thomas #ifndef PROFILE
387 6becd179 2024-06-03 thomas if (pledge("stdio rpath wpath cpath unveil", NULL) == -1)
388 6becd179 2024-06-03 thomas err(1, "pledge");
390 6becd179 2024-06-03 thomas if (argc != 1)
391 6becd179 2024-06-03 thomas usage_init();
393 6becd179 2024-06-03 thomas repo_path = strdup(argv[0]);
394 6becd179 2024-06-03 thomas if (repo_path == NULL)
395 6becd179 2024-06-03 thomas return got_error_from_errno("strdup");
397 6becd179 2024-06-03 thomas got_path_strip_trailing_slashes(repo_path);
399 6becd179 2024-06-03 thomas error = got_path_mkdir(repo_path);
400 6becd179 2024-06-03 thomas if (error &&
401 6becd179 2024-06-03 thomas !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
402 6becd179 2024-06-03 thomas goto done;
404 6becd179 2024-06-03 thomas error = apply_unveil(repo_path, 0, NULL);
405 6becd179 2024-06-03 thomas if (error)
406 6becd179 2024-06-03 thomas goto done;
408 6becd179 2024-06-03 thomas error = got_repo_init(repo_path, head_name);
410 6becd179 2024-06-03 thomas free(repo_path);
411 6becd179 2024-06-03 thomas return error;
414 6becd179 2024-06-03 thomas __dead static void
415 3ce1b845 2019-07-15 stsp usage_import(void)
417 d6506a3d 2022-08-16 thomas fprintf(stderr, "usage: %s import [-b branch] [-I pattern] [-m message] "
418 d6506a3d 2022-08-16 thomas "[-r repository-path] directory\n", getprogname());
422 ef20f542 2022-06-26 thomas static int
423 3ce1b845 2019-07-15 stsp spawn_editor(const char *editor, const char *file)
426 3ce1b845 2019-07-15 stsp sig_t sighup, sigint, sigquit;
427 3ce1b845 2019-07-15 stsp int st = -1;
429 3ce1b845 2019-07-15 stsp sighup = signal(SIGHUP, SIG_IGN);
430 3ce1b845 2019-07-15 stsp sigint = signal(SIGINT, SIG_IGN);
431 3ce1b845 2019-07-15 stsp sigquit = signal(SIGQUIT, SIG_IGN);
433 3ce1b845 2019-07-15 stsp switch (pid = fork()) {
435 3ce1b845 2019-07-15 stsp goto doneediting;
437 3ce1b845 2019-07-15 stsp execl(editor, editor, file, (char *)NULL);
438 3ce1b845 2019-07-15 stsp _exit(127);
441 3ce1b845 2019-07-15 stsp while (waitpid(pid, &st, 0) == -1)
442 3ce1b845 2019-07-15 stsp if (errno != EINTR)
445 3ce1b845 2019-07-15 stsp doneediting:
446 3ce1b845 2019-07-15 stsp (void)signal(SIGHUP, sighup);
447 3ce1b845 2019-07-15 stsp (void)signal(SIGINT, sigint);
448 3ce1b845 2019-07-15 stsp (void)signal(SIGQUIT, sigquit);
450 3ce1b845 2019-07-15 stsp if (!WIFEXITED(st)) {
451 3ce1b845 2019-07-15 stsp errno = EINTR;
455 3ce1b845 2019-07-15 stsp return WEXITSTATUS(st);
458 3ce1b845 2019-07-15 stsp static const struct got_error *
459 64a300dd 2023-02-17 thomas read_logmsg(char **logmsg, size_t *len, FILE *fp, size_t filesize)
461 75a8c854 2023-02-17 thomas const struct got_error *err = NULL;
462 75a8c854 2023-02-17 thomas char *line = NULL;
463 75a8c854 2023-02-17 thomas size_t linesize = 0;
465 75a8c854 2023-02-17 thomas *logmsg = NULL;
466 75a8c854 2023-02-17 thomas *len = 0;
468 75a8c854 2023-02-17 thomas if (fseeko(fp, 0L, SEEK_SET) == -1)
469 75a8c854 2023-02-17 thomas return got_error_from_errno("fseeko");
471 75a8c854 2023-02-17 thomas *logmsg = malloc(filesize + 1);
472 75a8c854 2023-02-17 thomas if (*logmsg == NULL)
473 75a8c854 2023-02-17 thomas return got_error_from_errno("malloc");
474 75a8c854 2023-02-17 thomas (*logmsg)[0] = '\0';
476 75a8c854 2023-02-17 thomas while (getline(&line, &linesize, fp) != -1) {
477 64a300dd 2023-02-17 thomas if (line[0] == '#' || (*len == 0 && line[0] == '\n'))
478 75a8c854 2023-02-17 thomas continue; /* remove comments and leading empty lines */
479 75a8c854 2023-02-17 thomas *len = strlcat(*logmsg, line, filesize + 1);
480 75a8c854 2023-02-17 thomas if (*len >= filesize + 1) {
481 75a8c854 2023-02-17 thomas err = got_error(GOT_ERR_NO_SPACE);
482 75a8c854 2023-02-17 thomas goto done;
485 75a8c854 2023-02-17 thomas if (ferror(fp)) {
486 75a8c854 2023-02-17 thomas err = got_ferror(fp, GOT_ERR_IO);
487 75a8c854 2023-02-17 thomas goto done;
490 75a8c854 2023-02-17 thomas while (*len > 0 && (*logmsg)[*len - 1] == '\n') {
491 75a8c854 2023-02-17 thomas (*logmsg)[*len - 1] = '\0';
492 75a8c854 2023-02-17 thomas (*len)--;
495 75a8c854 2023-02-17 thomas free(line);
496 75a8c854 2023-02-17 thomas if (err) {
497 75a8c854 2023-02-17 thomas free(*logmsg);
498 75a8c854 2023-02-17 thomas *logmsg = NULL;
499 75a8c854 2023-02-17 thomas *len = 0;
501 75a8c854 2023-02-17 thomas return err;
504 75a8c854 2023-02-17 thomas static const struct got_error *
505 3ce1b845 2019-07-15 stsp edit_logmsg(char **logmsg, const char *editor, const char *logmsg_path,
506 28cf319f 2021-01-28 stsp const char *initial_content, size_t initial_content_len,
507 28cf319f 2021-01-28 stsp int require_modification)
509 3ce1b845 2019-07-15 stsp const struct got_error *err = NULL;
510 3ce1b845 2019-07-15 stsp struct stat st, st2;
511 bfa12d5e 2020-09-26 stsp FILE *fp = NULL;
512 83389425 2023-02-17 thomas size_t logmsg_len;
514 3ce1b845 2019-07-15 stsp *logmsg = NULL;
516 3ce1b845 2019-07-15 stsp if (stat(logmsg_path, &st) == -1)
517 3ce1b845 2019-07-15 stsp return got_error_from_errno2("stat", logmsg_path);
519 3ce1b845 2019-07-15 stsp if (spawn_editor(editor, logmsg_path) == -1)
520 3ce1b845 2019-07-15 stsp return got_error_from_errno("failed spawning editor");
522 088f4d22 2023-02-17 thomas if (require_modification) {
523 088f4d22 2023-02-17 thomas struct timespec timeout;
525 088f4d22 2023-02-17 thomas timeout.tv_sec = 0;
526 088f4d22 2023-02-17 thomas timeout.tv_nsec = 1;
527 088f4d22 2023-02-17 thomas nanosleep(&timeout, NULL);
530 3ce1b845 2019-07-15 stsp if (stat(logmsg_path, &st2) == -1)
531 b40793ac 2023-07-17 thomas return got_error_from_errno2("stat", logmsg_path);
533 088f4d22 2023-02-17 thomas if (require_modification && st.st_size == st2.st_size &&
534 088f4d22 2023-02-17 thomas timespeccmp(&st.st_mtim, &st2.st_mtim, ==))
535 3ce1b845 2019-07-15 stsp return got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
536 3ce1b845 2019-07-15 stsp "no changes made to commit message, aborting");
538 c56c5d8a 2021-12-31 thomas fp = fopen(logmsg_path, "re");
539 3ce1b845 2019-07-15 stsp if (fp == NULL) {
540 3ce1b845 2019-07-15 stsp err = got_error_from_errno("fopen");
544 83389425 2023-02-17 thomas /* strip comments and leading/trailing newlines */
545 64a300dd 2023-02-17 thomas err = read_logmsg(logmsg, &logmsg_len, fp, st2.st_size);
547 75a8c854 2023-02-17 thomas goto done;
548 75a8c854 2023-02-17 thomas if (logmsg_len == 0) {
549 3ce1b845 2019-07-15 stsp err = got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
550 3ce1b845 2019-07-15 stsp "commit message cannot be empty, aborting");
554 bfa12d5e 2020-09-26 stsp if (fp && fclose(fp) == EOF && err == NULL)
555 bfa12d5e 2020-09-26 stsp err = got_error_from_errno("fclose");
557 3ce1b845 2019-07-15 stsp free(*logmsg);
558 3ce1b845 2019-07-15 stsp *logmsg = NULL;
560 3ce1b845 2019-07-15 stsp return err;
563 3ce1b845 2019-07-15 stsp static const struct got_error *
564 ef293bdd 2019-10-21 stsp collect_import_msg(char **logmsg, char **logmsg_path, const char *editor,
565 ef293bdd 2019-10-21 stsp const char *path_dir, const char *branch_name)
567 ef293bdd 2019-10-21 stsp char *initial_content = NULL;
568 3ce1b845 2019-07-15 stsp const struct got_error *err = NULL;
569 1601cb9f 2020-09-11 naddy int initial_content_len;
570 97972933 2020-09-11 stsp int fd = -1;
572 1601cb9f 2020-09-11 naddy initial_content_len = asprintf(&initial_content,
573 3ce1b845 2019-07-15 stsp "\n# %s to be imported to branch %s\n", path_dir,
574 1601cb9f 2020-09-11 naddy branch_name);
575 1601cb9f 2020-09-11 naddy if (initial_content_len == -1)
576 3ce1b845 2019-07-15 stsp return got_error_from_errno("asprintf");
578 bb63914a 2020-02-17 stsp err = got_opentemp_named_fd(logmsg_path, &fd,
579 fc2a50f2 2022-11-01 thomas GOT_TMPDIR_STR "/got-importmsg", "");
583 97972933 2020-09-11 stsp if (write(fd, initial_content, initial_content_len) == -1) {
584 97972933 2020-09-11 stsp err = got_error_from_errno2("write", *logmsg_path);
585 67fdb8a7 2023-03-09 thomas goto done;
587 67fdb8a7 2023-03-09 thomas if (close(fd) == -1) {
588 67fdb8a7 2023-03-09 thomas err = got_error_from_errno2("close", *logmsg_path);
593 bfa12d5e 2020-09-26 stsp err = edit_logmsg(logmsg, editor, *logmsg_path, initial_content,
594 0d5bb276 2020-12-15 stsp initial_content_len, 1);
596 97972933 2020-09-11 stsp if (fd != -1 && close(fd) == -1 && err == NULL)
597 97972933 2020-09-11 stsp err = got_error_from_errno2("close", *logmsg_path);
598 3ce1b845 2019-07-15 stsp free(initial_content);
600 59f86c76 2020-09-11 stsp free(*logmsg_path);
601 59f86c76 2020-09-11 stsp *logmsg_path = NULL;
603 3ce1b845 2019-07-15 stsp return err;
606 3ce1b845 2019-07-15 stsp static const struct got_error *
607 3ce1b845 2019-07-15 stsp import_progress(void *arg, const char *path)
609 3ce1b845 2019-07-15 stsp printf("A %s\n", path);
610 3ce1b845 2019-07-15 stsp return NULL;
613 ec9b5f0b 2022-07-19 thomas static const struct got_error *
614 17431c13 2022-02-12 thomas valid_author(const char *author)
616 ec9b5f0b 2022-07-19 thomas const char *email = author;
619 ec9b5f0b 2022-07-19 thomas * Git' expects the author (or committer) to be in the form
620 ec9b5f0b 2022-07-19 thomas * "name <email>", which are mostly free form (see the
621 ec9b5f0b 2022-07-19 thomas * "committer" description in git-fast-import(1)). We're only
622 ec9b5f0b 2022-07-19 thomas * doing this to avoid git's object parser breaking on commits
623 ec9b5f0b 2022-07-19 thomas * we create.
626 ec9b5f0b 2022-07-19 thomas while (*author && *author != '\n' && *author != '<' && *author != '>')
627 17431c13 2022-02-12 thomas author++;
628 3d47d5be 2022-10-31 thomas if (author != email && *author == '<' && *(author - 1) != ' ')
629 3d47d5be 2022-10-31 thomas return got_error_fmt(GOT_ERR_COMMIT_BAD_AUTHOR, "%s: space "
630 3d47d5be 2022-10-31 thomas "between author name and email required", email);
631 ec9b5f0b 2022-07-19 thomas if (*author++ != '<')
632 ec9b5f0b 2022-07-19 thomas return got_error_fmt(GOT_ERR_COMMIT_NO_EMAIL, "%s", email);
633 ec9b5f0b 2022-07-19 thomas while (*author && *author != '\n' && *author != '<' && *author != '>')
634 17431c13 2022-02-12 thomas author++;
635 ec9b5f0b 2022-07-19 thomas if (strcmp(author, ">") != 0)
636 ec9b5f0b 2022-07-19 thomas return got_error_fmt(GOT_ERR_COMMIT_NO_EMAIL, "%s", email);
637 ec9b5f0b 2022-07-19 thomas return NULL;
640 3ce1b845 2019-07-15 stsp static const struct got_error *
641 50b0790e 2020-09-11 stsp get_author(char **author, struct got_repository *repo,
642 50b0790e 2020-09-11 stsp struct got_worktree *worktree)
644 aba9c984 2019-09-08 stsp const struct got_error *err = NULL;
645 50b0790e 2020-09-11 stsp const char *got_author = NULL, *name, *email;
646 50b0790e 2020-09-11 stsp const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
648 84792843 2019-08-09 stsp *author = NULL;
650 50b0790e 2020-09-11 stsp if (worktree)
651 50b0790e 2020-09-11 stsp worktree_conf = got_worktree_get_gotconfig(worktree);
652 50b0790e 2020-09-11 stsp repo_conf = got_repo_get_gotconfig(repo);
655 50b0790e 2020-09-11 stsp * Priority of potential author information sources, from most
656 50b0790e 2020-09-11 stsp * significant to least significant:
657 50b0790e 2020-09-11 stsp * 1) work tree's .got/got.conf file
658 50b0790e 2020-09-11 stsp * 2) repository's got.conf file
659 50b0790e 2020-09-11 stsp * 3) repository's git config file
660 50b0790e 2020-09-11 stsp * 4) environment variables
661 50b0790e 2020-09-11 stsp * 5) global git config files (in user's home directory or /etc)
664 50b0790e 2020-09-11 stsp if (worktree_conf)
665 50b0790e 2020-09-11 stsp got_author = got_gotconfig_get_author(worktree_conf);
666 50b0790e 2020-09-11 stsp if (got_author == NULL)
667 50b0790e 2020-09-11 stsp got_author = got_gotconfig_get_author(repo_conf);
668 84792843 2019-08-09 stsp if (got_author == NULL) {
669 257add31 2020-09-09 stsp name = got_repo_get_gitconfig_author_name(repo);
670 257add31 2020-09-09 stsp email = got_repo_get_gitconfig_author_email(repo);
671 c9956ddf 2019-09-08 stsp if (name && email) {
672 c9956ddf 2019-09-08 stsp if (asprintf(author, "%s <%s>", name, email) == -1)
673 c9956ddf 2019-09-08 stsp return got_error_from_errno("asprintf");
674 c9956ddf 2019-09-08 stsp return NULL;
677 257add31 2020-09-09 stsp got_author = getenv("GOT_AUTHOR");
678 257add31 2020-09-09 stsp if (got_author == NULL) {
679 257add31 2020-09-09 stsp name = got_repo_get_global_gitconfig_author_name(repo);
680 257add31 2020-09-09 stsp email = got_repo_get_global_gitconfig_author_email(
682 257add31 2020-09-09 stsp if (name && email) {
683 257add31 2020-09-09 stsp if (asprintf(author, "%s <%s>", name, email)
685 257add31 2020-09-09 stsp return got_error_from_errno("asprintf");
686 257add31 2020-09-09 stsp return NULL;
688 257add31 2020-09-09 stsp /* TODO: Look up user in password database? */
689 257add31 2020-09-09 stsp return got_error(GOT_ERR_COMMIT_NO_AUTHOR);
693 aba9c984 2019-09-08 stsp *author = strdup(got_author);
694 aba9c984 2019-09-08 stsp if (*author == NULL)
695 aba9c984 2019-09-08 stsp return got_error_from_errno("strdup");
697 ec9b5f0b 2022-07-19 thomas err = valid_author(*author);
698 ec9b5f0b 2022-07-19 thomas if (err) {
699 aba9c984 2019-09-08 stsp free(*author);
700 aba9c984 2019-09-08 stsp *author = NULL;
702 aba9c984 2019-09-08 stsp return err;
705 871bd038 2022-07-03 thomas static const struct got_error *
706 871bd038 2022-07-03 thomas get_allowed_signers(char **allowed_signers, struct got_repository *repo,
707 871bd038 2022-07-03 thomas struct got_worktree *worktree)
709 871bd038 2022-07-03 thomas const char *got_allowed_signers = NULL;
710 871bd038 2022-07-03 thomas const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
712 871bd038 2022-07-03 thomas *allowed_signers = NULL;
714 871bd038 2022-07-03 thomas if (worktree)
715 871bd038 2022-07-03 thomas worktree_conf = got_worktree_get_gotconfig(worktree);
716 871bd038 2022-07-03 thomas repo_conf = got_repo_get_gotconfig(repo);
719 871bd038 2022-07-03 thomas * Priority of potential author information sources, from most
720 871bd038 2022-07-03 thomas * significant to least significant:
721 871bd038 2022-07-03 thomas * 1) work tree's .got/got.conf file
722 871bd038 2022-07-03 thomas * 2) repository's got.conf file
725 871bd038 2022-07-03 thomas if (worktree_conf)
726 871bd038 2022-07-03 thomas got_allowed_signers = got_gotconfig_get_allowed_signers_file(
727 871bd038 2022-07-03 thomas worktree_conf);
728 871bd038 2022-07-03 thomas if (got_allowed_signers == NULL)
729 871bd038 2022-07-03 thomas got_allowed_signers = got_gotconfig_get_allowed_signers_file(
730 871bd038 2022-07-03 thomas repo_conf);
732 871bd038 2022-07-03 thomas if (got_allowed_signers) {
733 871bd038 2022-07-03 thomas *allowed_signers = strdup(got_allowed_signers);
734 871bd038 2022-07-03 thomas if (*allowed_signers == NULL)
735 871bd038 2022-07-03 thomas return got_error_from_errno("strdup");
737 871bd038 2022-07-03 thomas return NULL;
740 871bd038 2022-07-03 thomas static const struct got_error *
741 871bd038 2022-07-03 thomas get_revoked_signers(char **revoked_signers, struct got_repository *repo,
742 871bd038 2022-07-03 thomas struct got_worktree *worktree)
744 871bd038 2022-07-03 thomas const char *got_revoked_signers = NULL;
745 871bd038 2022-07-03 thomas const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
747 871bd038 2022-07-03 thomas *revoked_signers = NULL;
749 871bd038 2022-07-03 thomas if (worktree)
750 871bd038 2022-07-03 thomas worktree_conf = got_worktree_get_gotconfig(worktree);
751 871bd038 2022-07-03 thomas repo_conf = got_repo_get_gotconfig(repo);
754 871bd038 2022-07-03 thomas * Priority of potential author information sources, from most
755 871bd038 2022-07-03 thomas * significant to least significant:
756 871bd038 2022-07-03 thomas * 1) work tree's .got/got.conf file
757 871bd038 2022-07-03 thomas * 2) repository's got.conf file
760 871bd038 2022-07-03 thomas if (worktree_conf)
761 871bd038 2022-07-03 thomas got_revoked_signers = got_gotconfig_get_revoked_signers_file(
762 871bd038 2022-07-03 thomas worktree_conf);
763 871bd038 2022-07-03 thomas if (got_revoked_signers == NULL)
764 871bd038 2022-07-03 thomas got_revoked_signers = got_gotconfig_get_revoked_signers_file(
765 871bd038 2022-07-03 thomas repo_conf);
767 871bd038 2022-07-03 thomas if (got_revoked_signers) {
768 871bd038 2022-07-03 thomas *revoked_signers = strdup(got_revoked_signers);
769 871bd038 2022-07-03 thomas if (*revoked_signers == NULL)
770 871bd038 2022-07-03 thomas return got_error_from_errno("strdup");
772 871bd038 2022-07-03 thomas return NULL;
775 d4becbee 2023-01-27 thomas static const char *
776 d4becbee 2023-01-27 thomas get_signer_id(struct got_repository *repo, struct got_worktree *worktree)
778 ff5e1f09 2022-07-06 thomas const char *got_signer_id = NULL;
779 ff5e1f09 2022-07-06 thomas const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
781 ff5e1f09 2022-07-06 thomas if (worktree)
782 ff5e1f09 2022-07-06 thomas worktree_conf = got_worktree_get_gotconfig(worktree);
783 ff5e1f09 2022-07-06 thomas repo_conf = got_repo_get_gotconfig(repo);
786 ff5e1f09 2022-07-06 thomas * Priority of potential author information sources, from most
787 ff5e1f09 2022-07-06 thomas * significant to least significant:
788 ff5e1f09 2022-07-06 thomas * 1) work tree's .got/got.conf file
789 ff5e1f09 2022-07-06 thomas * 2) repository's got.conf file
792 ff5e1f09 2022-07-06 thomas if (worktree_conf)
793 ff5e1f09 2022-07-06 thomas got_signer_id = got_gotconfig_get_signer_id(worktree_conf);
794 ff5e1f09 2022-07-06 thomas if (got_signer_id == NULL)
795 ff5e1f09 2022-07-06 thomas got_signer_id = got_gotconfig_get_signer_id(repo_conf);
797 d4becbee 2023-01-27 thomas return got_signer_id;
800 ff5e1f09 2022-07-06 thomas static const struct got_error *
801 c9956ddf 2019-09-08 stsp get_gitconfig_path(char **gitconfig_path)
803 c9956ddf 2019-09-08 stsp const char *homedir = getenv("HOME");
805 c9956ddf 2019-09-08 stsp *gitconfig_path = NULL;
806 c9956ddf 2019-09-08 stsp if (homedir) {
807 c9956ddf 2019-09-08 stsp if (asprintf(gitconfig_path, "%s/.gitconfig", homedir) == -1)
808 c9956ddf 2019-09-08 stsp return got_error_from_errno("asprintf");
811 c9956ddf 2019-09-08 stsp return NULL;
814 84792843 2019-08-09 stsp static const struct got_error *
815 3ce1b845 2019-07-15 stsp cmd_import(int argc, char *argv[])
817 3ce1b845 2019-07-15 stsp const struct got_error *error = NULL;
818 3ce1b845 2019-07-15 stsp char *path_dir = NULL, *repo_path = NULL, *logmsg = NULL;
819 c9956ddf 2019-09-08 stsp char *gitconfig_path = NULL, *editor = NULL, *author = NULL;
820 e9424ba1 2022-09-20 thomas const char *branch_name = NULL;
821 e9424ba1 2022-09-20 thomas char *id_str = NULL, *logmsg_path = NULL;
822 e9424ba1 2022-09-20 thomas char refname[PATH_MAX] = "refs/heads/";
823 3ce1b845 2019-07-15 stsp struct got_repository *repo = NULL;
824 3ce1b845 2019-07-15 stsp struct got_reference *branch_ref = NULL, *head_ref = NULL;
825 3ce1b845 2019-07-15 stsp struct got_object_id *new_commit_id = NULL;
826 e9424ba1 2022-09-20 thomas int ch, n = 0;
827 3ce1b845 2019-07-15 stsp struct got_pathlist_head ignores;
828 3ce1b845 2019-07-15 stsp struct got_pathlist_entry *pe;
829 ef293bdd 2019-10-21 stsp int preserve_logmsg = 0;
830 7cd52833 2022-06-23 thomas int *pack_fds = NULL;
832 3ce1b845 2019-07-15 stsp TAILQ_INIT(&ignores);
834 a0abeae5 2023-02-17 thomas #ifndef PROFILE
835 a0abeae5 2023-02-17 thomas if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd "
836 a0abeae5 2023-02-17 thomas "unveil",
837 a0abeae5 2023-02-17 thomas NULL) == -1)
838 a0abeae5 2023-02-17 thomas err(1, "pledge");
841 f7065961 2022-10-27 thomas while ((ch = getopt(argc, argv, "b:I:m:r:")) != -1) {
842 3ce1b845 2019-07-15 stsp switch (ch) {
844 3ce1b845 2019-07-15 stsp branch_name = optarg;
846 f7065961 2022-10-27 thomas case 'I':
847 f7065961 2022-10-27 thomas if (optarg[0] == '\0')
849 f7065961 2022-10-27 thomas error = got_pathlist_insert(&pe, &ignores, optarg,
851 f7065961 2022-10-27 thomas if (error)
852 f7065961 2022-10-27 thomas goto done;
855 3ce1b845 2019-07-15 stsp logmsg = strdup(optarg);
856 3ce1b845 2019-07-15 stsp if (logmsg == NULL) {
857 3ce1b845 2019-07-15 stsp error = got_error_from_errno("strdup");
862 3ce1b845 2019-07-15 stsp repo_path = realpath(optarg, NULL);
863 3ce1b845 2019-07-15 stsp if (repo_path == NULL) {
864 9ba1d308 2019-10-21 stsp error = got_error_from_errno2("realpath",
870 b2b65d18 2019-08-22 stsp usage_import();
871 3ce1b845 2019-07-15 stsp /* NOTREACHED */
875 3ce1b845 2019-07-15 stsp argc -= optind;
876 3ce1b845 2019-07-15 stsp argv += optind;
878 3ce1b845 2019-07-15 stsp if (argc != 1)
879 3ce1b845 2019-07-15 stsp usage_import();
881 3ce1b845 2019-07-15 stsp if (repo_path == NULL) {
882 3ce1b845 2019-07-15 stsp repo_path = getcwd(NULL, 0);
883 3ce1b845 2019-07-15 stsp if (repo_path == NULL)
884 3ce1b845 2019-07-15 stsp return got_error_from_errno("getcwd");
886 3ce1b845 2019-07-15 stsp got_path_strip_trailing_slashes(repo_path);
887 c9956ddf 2019-09-08 stsp error = get_gitconfig_path(&gitconfig_path);
890 7cd52833 2022-06-23 thomas error = got_repo_pack_fds_open(&pack_fds);
891 7cd52833 2022-06-23 thomas if (error != NULL)
892 7cd52833 2022-06-23 thomas goto done;
893 7cd52833 2022-06-23 thomas error = got_repo_open(&repo, repo_path, gitconfig_path, pack_fds);
894 8f9af3fc 2024-03-30 thomas if (error)
895 8f9af3fc 2024-03-30 thomas goto done;
897 8f9af3fc 2024-03-30 thomas path_dir = realpath(argv[0], NULL);
898 8f9af3fc 2024-03-30 thomas if (path_dir == NULL) {
899 8f9af3fc 2024-03-30 thomas error = got_error_from_errno2("realpath", argv[0]);
900 8f9af3fc 2024-03-30 thomas goto done;
902 8f9af3fc 2024-03-30 thomas got_path_strip_trailing_slashes(path_dir);
904 8f9af3fc 2024-03-30 thomas error = get_editor(&editor);
908 8f9af3fc 2024-03-30 thomas if (unveil(path_dir, "r") != 0) {
909 8f9af3fc 2024-03-30 thomas error = got_error_from_errno2("unveil", path_dir);
910 8f9af3fc 2024-03-30 thomas goto done;
912 8f9af3fc 2024-03-30 thomas if (unveil(editor, "x") != 0) {
913 8f9af3fc 2024-03-30 thomas error = got_error_from_errno2("unveil", editor);
914 8f9af3fc 2024-03-30 thomas goto done;
916 8f9af3fc 2024-03-30 thomas error = apply_unveil(got_repo_get_path(repo), 0, NULL);
917 8f9af3fc 2024-03-30 thomas if (error)
918 8f9af3fc 2024-03-30 thomas goto done;
920 50b0790e 2020-09-11 stsp error = get_author(&author, repo, NULL);
922 aba9c984 2019-09-08 stsp return error;
925 bd5895f3 2019-11-28 stsp * Don't let the user create a branch name with a leading '-'.
926 e560b7e0 2019-11-28 stsp * While technically a valid reference name, this case is usually
927 e560b7e0 2019-11-28 stsp * an unintended typo.
929 e9424ba1 2022-09-20 thomas if (branch_name && branch_name[0] == '-')
930 bd5895f3 2019-11-28 stsp return got_error_path(branch_name, GOT_ERR_REF_NAME_MINUS);
932 e9424ba1 2022-09-20 thomas error = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0);
933 e9424ba1 2022-09-20 thomas if (error && error->code != GOT_ERR_NOT_REF)
936 e9424ba1 2022-09-20 thomas if (branch_name)
937 e9424ba1 2022-09-20 thomas n = strlcat(refname, branch_name, sizeof(refname));
938 e9424ba1 2022-09-20 thomas else if (head_ref && got_ref_is_symbolic(head_ref))
939 e9424ba1 2022-09-20 thomas n = strlcpy(refname, got_ref_get_symref_target(head_ref),
940 e9424ba1 2022-09-20 thomas sizeof(refname));
942 e9424ba1 2022-09-20 thomas n = strlcat(refname, "main", sizeof(refname));
943 e9424ba1 2022-09-20 thomas if (n >= sizeof(refname)) {
944 e9424ba1 2022-09-20 thomas error = got_error(GOT_ERR_NO_SPACE);
945 e9424ba1 2022-09-20 thomas goto done;
948 3ce1b845 2019-07-15 stsp error = got_ref_open(&branch_ref, repo, refname, 0);
949 3ce1b845 2019-07-15 stsp if (error) {
950 3ce1b845 2019-07-15 stsp if (error->code != GOT_ERR_NOT_REF)
953 3ce1b845 2019-07-15 stsp error = got_error_msg(GOT_ERR_BRANCH_EXISTS,
954 3ce1b845 2019-07-15 stsp "import target branch already exists");
958 102d840d 2023-06-22 thomas if (logmsg == NULL || *logmsg == '\0') {
959 8e158b01 2019-09-22 stsp free(logmsg);
960 ef293bdd 2019-10-21 stsp error = collect_import_msg(&logmsg, &logmsg_path, editor,
961 ef293bdd 2019-10-21 stsp path_dir, refname);
962 ef293bdd 2019-10-21 stsp if (error) {
963 ef293bdd 2019-10-21 stsp if (error->code != GOT_ERR_COMMIT_MSG_EMPTY &&
964 ef293bdd 2019-10-21 stsp logmsg_path != NULL)
965 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
970 3ce1b845 2019-07-15 stsp error = got_repo_import(&new_commit_id, path_dir, logmsg,
971 84792843 2019-08-09 stsp author, &ignores, repo, import_progress, NULL);
972 ef293bdd 2019-10-21 stsp if (error) {
973 ef293bdd 2019-10-21 stsp if (logmsg_path)
974 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
978 3ce1b845 2019-07-15 stsp error = got_ref_alloc(&branch_ref, refname, new_commit_id);
979 ef293bdd 2019-10-21 stsp if (error) {
980 ef293bdd 2019-10-21 stsp if (logmsg_path)
981 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
985 3ce1b845 2019-07-15 stsp error = got_ref_write(branch_ref, repo);
986 ef293bdd 2019-10-21 stsp if (error) {
987 ef293bdd 2019-10-21 stsp if (logmsg_path)
988 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
992 3ce1b845 2019-07-15 stsp error = got_object_id_str(&id_str, new_commit_id);
993 ef293bdd 2019-10-21 stsp if (error) {
994 ef293bdd 2019-10-21 stsp if (logmsg_path)
995 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
999 3ce1b845 2019-07-15 stsp error = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0);
1000 3ce1b845 2019-07-15 stsp if (error) {
1001 ef293bdd 2019-10-21 stsp if (error->code != GOT_ERR_NOT_REF) {
1002 ef293bdd 2019-10-21 stsp if (logmsg_path)
1003 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1004 3ce1b845 2019-07-15 stsp goto done;
1007 3ce1b845 2019-07-15 stsp error = got_ref_alloc_symref(&head_ref, GOT_REF_HEAD,
1008 3ce1b845 2019-07-15 stsp branch_ref);
1009 ef293bdd 2019-10-21 stsp if (error) {
1010 ef293bdd 2019-10-21 stsp if (logmsg_path)
1011 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1012 3ce1b845 2019-07-15 stsp goto done;
1015 3ce1b845 2019-07-15 stsp error = got_ref_write(head_ref, repo);
1016 ef293bdd 2019-10-21 stsp if (error) {
1017 ef293bdd 2019-10-21 stsp if (logmsg_path)
1018 ef293bdd 2019-10-21 stsp preserve_logmsg = 1;
1019 3ce1b845 2019-07-15 stsp goto done;
1023 3ce1b845 2019-07-15 stsp printf("Created branch %s with commit %s\n",
1024 3ce1b845 2019-07-15 stsp got_ref_get_name(branch_ref), id_str);
1026 7cd52833 2022-06-23 thomas if (pack_fds) {
1027 7cd52833 2022-06-23 thomas const struct got_error *pack_err =
1028 7cd52833 2022-06-23 thomas got_repo_pack_fds_close(pack_fds);
1029 7cd52833 2022-06-23 thomas if (error == NULL)
1030 7cd52833 2022-06-23 thomas error = pack_err;
1032 e9e79470 2023-04-14 thomas if (repo) {
1033 e9e79470 2023-04-14 thomas const struct got_error *close_err = got_repo_close(repo);
1034 e9e79470 2023-04-14 thomas if (error == NULL)
1035 e9e79470 2023-04-14 thomas error = close_err;
1037 ef293bdd 2019-10-21 stsp if (preserve_logmsg) {
1038 ef293bdd 2019-10-21 stsp fprintf(stderr, "%s: log message preserved in %s\n",
1039 ef293bdd 2019-10-21 stsp getprogname(), logmsg_path);
1040 ef293bdd 2019-10-21 stsp } else if (logmsg_path && unlink(logmsg_path) == -1 && error == NULL)
1041 ef293bdd 2019-10-21 stsp error = got_error_from_errno2("unlink", logmsg_path);
1042 8e158b01 2019-09-22 stsp free(logmsg);
1043 ef293bdd 2019-10-21 stsp free(logmsg_path);
1044 2c7829a4 2019-06-17 stsp free(repo_path);
1045 3ce1b845 2019-07-15 stsp free(editor);
1046 3ce1b845 2019-07-15 stsp free(new_commit_id);
1047 3ce1b845 2019-07-15 stsp free(id_str);
1048 aba9c984 2019-09-08 stsp free(author);
1049 c9956ddf 2019-09-08 stsp free(gitconfig_path);
1050 3ce1b845 2019-07-15 stsp if (branch_ref)
1051 3ce1b845 2019-07-15 stsp got_ref_close(branch_ref);
1052 3ce1b845 2019-07-15 stsp if (head_ref)
1053 3ce1b845 2019-07-15 stsp got_ref_close(head_ref);
1054 2c7829a4 2019-06-17 stsp return error;
1057 93658fb9 2020-03-18 stsp __dead static void
1058 93658fb9 2020-03-18 stsp usage_clone(void)
1060 d6506a3d 2022-08-16 thomas fprintf(stderr, "usage: %s clone [-almqv] [-b branch] [-R reference] "
1061 d6506a3d 2022-08-16 thomas "repository-URL [directory]\n", getprogname());
1065 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg {
1066 892ac3b6 2020-03-18 stsp char last_scaled_size[FMT_SCALED_STRSIZE];
1067 892ac3b6 2020-03-18 stsp int last_p_indexed;
1068 892ac3b6 2020-03-18 stsp int last_p_resolved;
1069 68999b92 2020-03-18 stsp int verbosity;
1071 04d9a9ec 2020-09-24 stsp struct got_repository *repo;
1073 04d9a9ec 2020-09-24 stsp int create_configs;
1074 04d9a9ec 2020-09-24 stsp int configs_created;
1076 04d9a9ec 2020-09-24 stsp struct got_pathlist_head *symrefs;
1077 04d9a9ec 2020-09-24 stsp struct got_pathlist_head *wanted_branches;
1078 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs;
1079 04d9a9ec 2020-09-24 stsp const char *proto;
1080 04d9a9ec 2020-09-24 stsp const char *host;
1081 04d9a9ec 2020-09-24 stsp const char *port;
1082 04d9a9ec 2020-09-24 stsp const char *remote_repo_path;
1083 04d9a9ec 2020-09-24 stsp const char *git_url;
1084 04d9a9ec 2020-09-24 stsp int fetch_all_branches;
1085 04d9a9ec 2020-09-24 stsp int mirror_references;
1086 04d9a9ec 2020-09-24 stsp } config_info;
1089 04d9a9ec 2020-09-24 stsp /* XXX forward declaration */
1090 93658fb9 2020-03-18 stsp static const struct got_error *
1091 04d9a9ec 2020-09-24 stsp create_config_files(const char *proto, const char *host, const char *port,
1092 04d9a9ec 2020-09-24 stsp const char *remote_repo_path, const char *git_url, int fetch_all_branches,
1093 04d9a9ec 2020-09-24 stsp int mirror_references, struct got_pathlist_head *symrefs,
1094 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_branches,
1095 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, struct got_repository *repo);
1097 04d9a9ec 2020-09-24 stsp static const struct got_error *
1098 baa9fea0 2020-03-18 stsp fetch_progress(void *arg, const char *message, off_t packfile_size,
1099 668a20f6 2020-03-18 stsp int nobj_total, int nobj_indexed, int nobj_loose, int nobj_resolved)
1101 04d9a9ec 2020-09-24 stsp const struct got_error *err = NULL;
1102 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg *a = arg;
1103 892ac3b6 2020-03-18 stsp char scaled_size[FMT_SCALED_STRSIZE];
1104 892ac3b6 2020-03-18 stsp int p_indexed, p_resolved;
1105 892ac3b6 2020-03-18 stsp int print_size = 0, print_indexed = 0, print_resolved = 0;
1108 04d9a9ec 2020-09-24 stsp * In order to allow a failed clone to be resumed with 'got fetch'
1109 04d9a9ec 2020-09-24 stsp * we try to create configuration files as soon as possible.
1110 04d9a9ec 2020-09-24 stsp * Once the server has sent information about its default branch
1111 04d9a9ec 2020-09-24 stsp * we have all required information.
1113 04d9a9ec 2020-09-24 stsp if (a->create_configs && !a->configs_created &&
1114 04d9a9ec 2020-09-24 stsp !TAILQ_EMPTY(a->config_info.symrefs)) {
1115 04d9a9ec 2020-09-24 stsp err = create_config_files(a->config_info.proto,
1116 62d463ca 2020-10-20 naddy a->config_info.host, a->config_info.port,
1117 62d463ca 2020-10-20 naddy a->config_info.remote_repo_path,
1118 62d463ca 2020-10-20 naddy a->config_info.git_url,
1119 62d463ca 2020-10-20 naddy a->config_info.fetch_all_branches,
1120 62d463ca 2020-10-20 naddy a->config_info.mirror_references,
1121 62d463ca 2020-10-20 naddy a->config_info.symrefs,
1122 99495ddb 2021-01-10 stsp a->config_info.wanted_branches,
1123 99495ddb 2021-01-10 stsp a->config_info.wanted_refs, a->repo);
1125 04d9a9ec 2020-09-24 stsp return err;
1126 04d9a9ec 2020-09-24 stsp a->configs_created = 1;
1129 68999b92 2020-03-18 stsp if (a->verbosity < 0)
1130 68999b92 2020-03-18 stsp return NULL;
1132 fd843b58 2020-03-18 stsp if (message && message[0] != '\0') {
1133 d2cdc636 2020-03-18 stsp printf("\rserver: %s", message);
1134 892ac3b6 2020-03-18 stsp fflush(stdout);
1135 12d1281e 2020-03-19 stsp return NULL;
1138 b2409d58 2020-03-18 stsp if (packfile_size > 0 || nobj_indexed > 0) {
1139 892ac3b6 2020-03-18 stsp if (fmt_scaled(packfile_size, scaled_size) == 0 &&
1140 892ac3b6 2020-03-18 stsp (a->last_scaled_size[0] == '\0' ||
1141 892ac3b6 2020-03-18 stsp strcmp(scaled_size, a->last_scaled_size)) != 0) {
1142 892ac3b6 2020-03-18 stsp print_size = 1;
1143 892ac3b6 2020-03-18 stsp if (strlcpy(a->last_scaled_size, scaled_size,
1144 892ac3b6 2020-03-18 stsp FMT_SCALED_STRSIZE) >= FMT_SCALED_STRSIZE)
1145 892ac3b6 2020-03-18 stsp return got_error(GOT_ERR_NO_SPACE);
1147 61cc1a7a 2020-03-18 stsp if (nobj_indexed > 0) {
1148 892ac3b6 2020-03-18 stsp p_indexed = (nobj_indexed * 100) / nobj_total;
1149 892ac3b6 2020-03-18 stsp if (p_indexed != a->last_p_indexed) {
1150 892ac3b6 2020-03-18 stsp a->last_p_indexed = p_indexed;
1151 892ac3b6 2020-03-18 stsp print_indexed = 1;
1152 892ac3b6 2020-03-18 stsp print_size = 1;
1155 61cc1a7a 2020-03-18 stsp if (nobj_resolved > 0) {
1156 892ac3b6 2020-03-18 stsp p_resolved = (nobj_resolved * 100) /
1157 892ac3b6 2020-03-18 stsp (nobj_total - nobj_loose);
1158 892ac3b6 2020-03-18 stsp if (p_resolved != a->last_p_resolved) {
1159 892ac3b6 2020-03-18 stsp a->last_p_resolved = p_resolved;
1160 892ac3b6 2020-03-18 stsp print_resolved = 1;
1161 892ac3b6 2020-03-18 stsp print_indexed = 1;
1162 892ac3b6 2020-03-18 stsp print_size = 1;
1167 892ac3b6 2020-03-18 stsp if (print_size || print_indexed || print_resolved)
1168 892ac3b6 2020-03-18 stsp printf("\r");
1169 892ac3b6 2020-03-18 stsp if (print_size)
1170 d2f35ef7 2022-02-13 thomas printf("%*s fetched", FMT_SCALED_STRSIZE - 2, scaled_size);
1171 d715f13e 2020-03-19 stsp if (print_indexed)
1172 892ac3b6 2020-03-18 stsp printf("; indexing %d%%", p_indexed);
1173 d715f13e 2020-03-19 stsp if (print_resolved)
1174 892ac3b6 2020-03-18 stsp printf("; resolving deltas %d%%", p_resolved);
1175 892ac3b6 2020-03-18 stsp if (print_size || print_indexed || print_resolved)
1176 892ac3b6 2020-03-18 stsp fflush(stdout);
1178 531c3985 2020-03-18 stsp return NULL;
1181 531c3985 2020-03-18 stsp static const struct got_error *
1182 04d9a9ec 2020-09-24 stsp create_symref(const char *refname, struct got_reference *target_ref,
1183 04d9a9ec 2020-09-24 stsp int verbosity, struct got_repository *repo)
1185 4ba14133 2020-03-20 stsp const struct got_error *err;
1186 04d9a9ec 2020-09-24 stsp struct got_reference *head_symref;
1188 04d9a9ec 2020-09-24 stsp err = got_ref_alloc_symref(&head_symref, refname, target_ref);
1190 4ba14133 2020-03-20 stsp return err;
1192 04d9a9ec 2020-09-24 stsp err = got_ref_write(head_symref, repo);
1193 6338a6a1 2020-03-21 stsp if (err == NULL && verbosity > 0) {
1194 6338a6a1 2020-03-21 stsp printf("Created reference %s: %s\n", GOT_REF_HEAD,
1195 6338a6a1 2020-03-21 stsp got_ref_get_name(target_ref));
1197 04d9a9ec 2020-09-24 stsp got_ref_close(head_symref);
1198 4ba14133 2020-03-20 stsp return err;
1201 4ba14133 2020-03-20 stsp static const struct got_error *
1202 41b0de12 2020-03-21 stsp list_remote_refs(struct got_pathlist_head *symrefs,
1203 41b0de12 2020-03-21 stsp struct got_pathlist_head *refs)
1205 41b0de12 2020-03-21 stsp const struct got_error *err;
1206 41b0de12 2020-03-21 stsp struct got_pathlist_entry *pe;
1208 41b0de12 2020-03-21 stsp TAILQ_FOREACH(pe, symrefs, entry) {
1209 41b0de12 2020-03-21 stsp const char *refname = pe->path;
1210 41b0de12 2020-03-21 stsp const char *targetref = pe->data;
1212 41b0de12 2020-03-21 stsp printf("%s: %s\n", refname, targetref);
1215 41b0de12 2020-03-21 stsp TAILQ_FOREACH(pe, refs, entry) {
1216 41b0de12 2020-03-21 stsp const char *refname = pe->path;
1217 41b0de12 2020-03-21 stsp struct got_object_id *id = pe->data;
1218 41b0de12 2020-03-21 stsp char *id_str;
1220 41b0de12 2020-03-21 stsp err = got_object_id_str(&id_str, id);
1222 41b0de12 2020-03-21 stsp return err;
1223 41b0de12 2020-03-21 stsp printf("%s: %s\n", refname, id_str);
1224 41b0de12 2020-03-21 stsp free(id_str);
1227 41b0de12 2020-03-21 stsp return NULL;
1230 6338a6a1 2020-03-21 stsp static const struct got_error *
1231 6338a6a1 2020-03-21 stsp create_ref(const char *refname, struct got_object_id *id,
1232 6338a6a1 2020-03-21 stsp int verbosity, struct got_repository *repo)
1234 6338a6a1 2020-03-21 stsp const struct got_error *err = NULL;
1235 6338a6a1 2020-03-21 stsp struct got_reference *ref;
1236 6338a6a1 2020-03-21 stsp char *id_str;
1238 6338a6a1 2020-03-21 stsp err = got_object_id_str(&id_str, id);
1240 6338a6a1 2020-03-21 stsp return err;
1242 6338a6a1 2020-03-21 stsp err = got_ref_alloc(&ref, refname, id);
1244 6338a6a1 2020-03-21 stsp goto done;
1246 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
1247 6338a6a1 2020-03-21 stsp got_ref_close(ref);
1249 6338a6a1 2020-03-21 stsp if (err == NULL && verbosity >= 0)
1250 6338a6a1 2020-03-21 stsp printf("Created reference %s: %s\n", refname, id_str);
1252 6338a6a1 2020-03-21 stsp free(id_str);
1253 6338a6a1 2020-03-21 stsp return err;
1256 0e4002ca 2020-03-21 stsp static int
1257 0e4002ca 2020-03-21 stsp match_wanted_ref(const char *refname, const char *wanted_ref)
1259 0e4002ca 2020-03-21 stsp if (strncmp(refname, "refs/", 5) != 0)
1261 0e4002ca 2020-03-21 stsp refname += 5;
1264 0e4002ca 2020-03-21 stsp * Prevent fetching of references that won't make any
1265 0e4002ca 2020-03-21 stsp * sense outside of the remote repository's context.
1267 0e4002ca 2020-03-21 stsp if (strncmp(refname, "got/", 4) == 0)
1269 0e4002ca 2020-03-21 stsp if (strncmp(refname, "remotes/", 8) == 0)
1272 0e4002ca 2020-03-21 stsp if (strncmp(wanted_ref, "refs/", 5) == 0)
1273 0e4002ca 2020-03-21 stsp wanted_ref += 5;
1275 0e4002ca 2020-03-21 stsp /* Allow prefix match. */
1276 0e4002ca 2020-03-21 stsp if (got_path_is_child(refname, wanted_ref, strlen(wanted_ref)))
1279 0e4002ca 2020-03-21 stsp /* Allow exact match. */
1280 0e4002ca 2020-03-21 stsp return (strcmp(refname, wanted_ref) == 0);
1283 0e4002ca 2020-03-21 stsp static int
1284 0e4002ca 2020-03-21 stsp is_wanted_ref(struct got_pathlist_head *wanted_refs, const char *refname)
1286 0e4002ca 2020-03-21 stsp struct got_pathlist_entry *pe;
1288 0e4002ca 2020-03-21 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1289 0e4002ca 2020-03-21 stsp if (match_wanted_ref(refname, pe->path))
1296 41b0de12 2020-03-21 stsp static const struct got_error *
1297 0e4002ca 2020-03-21 stsp create_wanted_ref(const char *refname, struct got_object_id *id,
1298 0e4002ca 2020-03-21 stsp const char *remote_repo_name, int verbosity, struct got_repository *repo)
1300 0e4002ca 2020-03-21 stsp const struct got_error *err;
1301 0e4002ca 2020-03-21 stsp char *remote_refname;
1303 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
1304 0e4002ca 2020-03-21 stsp refname += 5;
1306 0e4002ca 2020-03-21 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
1307 0e4002ca 2020-03-21 stsp remote_repo_name, refname) == -1)
1308 0e4002ca 2020-03-21 stsp return got_error_from_errno("asprintf");
1310 0e4002ca 2020-03-21 stsp err = create_ref(remote_refname, id, verbosity, repo);
1311 0e4002ca 2020-03-21 stsp free(remote_refname);
1312 7c0b7f42 2020-09-24 stsp return err;
1315 7c0b7f42 2020-09-24 stsp static const struct got_error *
1316 7c0b7f42 2020-09-24 stsp create_gotconfig(const char *proto, const char *host, const char *port,
1317 15d3c221 2021-01-05 stsp const char *remote_repo_path, const char *default_branch,
1318 0c8b29c5 2021-01-05 stsp int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1319 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, int mirror_references,
1320 99495ddb 2021-01-10 stsp struct got_repository *repo)
1322 7c0b7f42 2020-09-24 stsp const struct got_error *err = NULL;
1323 7c0b7f42 2020-09-24 stsp char *gotconfig_path = NULL;
1324 7c0b7f42 2020-09-24 stsp char *gotconfig = NULL;
1325 7c0b7f42 2020-09-24 stsp FILE *gotconfig_file = NULL;
1326 15d3c221 2021-01-05 stsp const char *branchname = NULL;
1327 99495ddb 2021-01-10 stsp char *branches = NULL, *refs = NULL;
1328 7c0b7f42 2020-09-24 stsp ssize_t n;
1330 0c8b29c5 2021-01-05 stsp if (!fetch_all_branches && !TAILQ_EMPTY(wanted_branches)) {
1331 132af4a5 2021-01-05 stsp struct got_pathlist_entry *pe;
1332 132af4a5 2021-01-05 stsp TAILQ_FOREACH(pe, wanted_branches, entry) {
1334 132af4a5 2021-01-05 stsp branchname = pe->path;
1335 132af4a5 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1336 132af4a5 2021-01-05 stsp branchname += 11;
1337 132af4a5 2021-01-05 stsp if (asprintf(&s, "%s\"%s\" ",
1338 132af4a5 2021-01-05 stsp branches ? branches : "", branchname) == -1) {
1339 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1340 132af4a5 2021-01-05 stsp goto done;
1342 132af4a5 2021-01-05 stsp free(branches);
1343 132af4a5 2021-01-05 stsp branches = s;
1345 0c8b29c5 2021-01-05 stsp } else if (!fetch_all_branches && default_branch) {
1346 15d3c221 2021-01-05 stsp branchname = default_branch;
1347 15d3c221 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1348 15d3c221 2021-01-05 stsp branchname += 11;
1349 132af4a5 2021-01-05 stsp if (asprintf(&branches, "\"%s\" ", branchname) == -1) {
1350 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1351 132af4a5 2021-01-05 stsp goto done;
1354 99495ddb 2021-01-10 stsp if (!TAILQ_EMPTY(wanted_refs)) {
1355 99495ddb 2021-01-10 stsp struct got_pathlist_entry *pe;
1356 99495ddb 2021-01-10 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1358 99495ddb 2021-01-10 stsp const char *refname = pe->path;
1359 99495ddb 2021-01-10 stsp if (strncmp(refname, "refs/", 5) == 0)
1360 99495ddb 2021-01-10 stsp branchname += 5;
1361 99495ddb 2021-01-10 stsp if (asprintf(&s, "%s\"%s\" ",
1362 99495ddb 2021-01-10 stsp refs ? refs : "", refname) == -1) {
1363 99495ddb 2021-01-10 stsp err = got_error_from_errno("asprintf");
1364 99495ddb 2021-01-10 stsp goto done;
1366 99495ddb 2021-01-10 stsp free(refs);
1371 7c0b7f42 2020-09-24 stsp /* Create got.conf(5). */
1372 7c0b7f42 2020-09-24 stsp gotconfig_path = got_repo_get_path_gotconfig(repo);
1373 7c0b7f42 2020-09-24 stsp if (gotconfig_path == NULL) {
1374 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("got_repo_get_path_gotconfig");
1375 7c0b7f42 2020-09-24 stsp goto done;
1377 c56c5d8a 2021-12-31 thomas gotconfig_file = fopen(gotconfig_path, "ae");
1378 7c0b7f42 2020-09-24 stsp if (gotconfig_file == NULL) {
1379 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fopen", gotconfig_path);
1380 7c0b7f42 2020-09-24 stsp goto done;
1382 7c0b7f42 2020-09-24 stsp if (asprintf(&gotconfig,
1383 7c0b7f42 2020-09-24 stsp "remote \"%s\" {\n"
1384 7c0b7f42 2020-09-24 stsp "\tserver %s\n"
1385 7c0b7f42 2020-09-24 stsp "\tprotocol %s\n"
1387 7c0b7f42 2020-09-24 stsp "\trepository \"%s\"\n"
1393 7c0b7f42 2020-09-24 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, host, proto,
1394 7c0b7f42 2020-09-24 stsp port ? "\tport " : "", port ? port : "", port ? "\n" : "",
1395 132af4a5 2021-01-05 stsp remote_repo_path, branches ? "\tbranch { " : "",
1396 b6b86fd1 2022-08-30 thomas branches ? branches : "", branches ? "}\n" : "",
1397 b6b86fd1 2022-08-30 thomas refs ? "\treference { " : "", refs ? refs : "", refs ? "}\n" : "",
1398 459c9b5d 2022-07-03 thomas mirror_references ? "\tmirror_references yes\n" : "",
1399 25eb5847 2022-07-03 thomas fetch_all_branches ? "\tfetch_all_branches yes\n" : "") == -1) {
1400 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1401 7c0b7f42 2020-09-24 stsp goto done;
1403 7c0b7f42 2020-09-24 stsp n = fwrite(gotconfig, 1, strlen(gotconfig), gotconfig_file);
1404 7c0b7f42 2020-09-24 stsp if (n != strlen(gotconfig)) {
1405 7c0b7f42 2020-09-24 stsp err = got_ferror(gotconfig_file, GOT_ERR_IO);
1406 7c0b7f42 2020-09-24 stsp goto done;
1410 7c0b7f42 2020-09-24 stsp if (gotconfig_file && fclose(gotconfig_file) == EOF && err == NULL)
1411 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fclose", gotconfig_path);
1412 7c0b7f42 2020-09-24 stsp free(gotconfig_path);
1413 132af4a5 2021-01-05 stsp free(branches);
1414 7c0b7f42 2020-09-24 stsp return err;
1417 7c0b7f42 2020-09-24 stsp static const struct got_error *
1418 04d9a9ec 2020-09-24 stsp create_gitconfig(const char *git_url, const char *default_branch,
1419 132af4a5 2021-01-05 stsp int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1420 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, int mirror_references,
1421 99495ddb 2021-01-10 stsp struct got_repository *repo)
1423 7c0b7f42 2020-09-24 stsp const struct got_error *err = NULL;
1424 7c0b7f42 2020-09-24 stsp char *gitconfig_path = NULL;
1425 7c0b7f42 2020-09-24 stsp char *gitconfig = NULL;
1426 7c0b7f42 2020-09-24 stsp FILE *gitconfig_file = NULL;
1427 99495ddb 2021-01-10 stsp char *branches = NULL, *refs = NULL;
1428 56d0a753 2021-01-20 stsp const char *branchname;
1429 7c0b7f42 2020-09-24 stsp ssize_t n;
1431 7c0b7f42 2020-09-24 stsp /* Create a config file Git can understand. */
1432 7c0b7f42 2020-09-24 stsp gitconfig_path = got_repo_get_path_gitconfig(repo);
1433 7c0b7f42 2020-09-24 stsp if (gitconfig_path == NULL) {
1434 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("got_repo_get_path_gitconfig");
1435 7c0b7f42 2020-09-24 stsp goto done;
1437 c56c5d8a 2021-12-31 thomas gitconfig_file = fopen(gitconfig_path, "ae");
1438 7c0b7f42 2020-09-24 stsp if (gitconfig_file == NULL) {
1439 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fopen", gitconfig_path);
1440 7c0b7f42 2020-09-24 stsp goto done;
1442 56d0a753 2021-01-20 stsp if (fetch_all_branches) {
1443 56d0a753 2021-01-20 stsp if (mirror_references) {
1444 56d0a753 2021-01-20 stsp if (asprintf(&branches,
1445 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/*:refs/heads/*\n") == -1) {
1446 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1447 56d0a753 2021-01-20 stsp goto done;
1449 56d0a753 2021-01-20 stsp } else if (asprintf(&branches,
1450 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/*:refs/remotes/%s/*\n",
1451 7c0b7f42 2020-09-24 stsp GOT_FETCH_DEFAULT_REMOTE_NAME) == -1) {
1452 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1453 7c0b7f42 2020-09-24 stsp goto done;
1455 132af4a5 2021-01-05 stsp } else if (!TAILQ_EMPTY(wanted_branches)) {
1456 132af4a5 2021-01-05 stsp struct got_pathlist_entry *pe;
1457 132af4a5 2021-01-05 stsp TAILQ_FOREACH(pe, wanted_branches, entry) {
1459 132af4a5 2021-01-05 stsp branchname = pe->path;
1460 132af4a5 2021-01-05 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1461 132af4a5 2021-01-05 stsp branchname += 11;
1462 56d0a753 2021-01-20 stsp if (mirror_references) {
1463 56d0a753 2021-01-20 stsp if (asprintf(&s,
1464 56d0a753 2021-01-20 stsp "%s\tfetch = refs/heads/%s:refs/heads/%s\n",
1465 56d0a753 2021-01-20 stsp branches ? branches : "",
1466 56d0a753 2021-01-20 stsp branchname, branchname) == -1) {
1467 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1468 56d0a753 2021-01-20 stsp goto done;
1470 56d0a753 2021-01-20 stsp } else if (asprintf(&s,
1471 56d0a753 2021-01-20 stsp "%s\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1472 132af4a5 2021-01-05 stsp branches ? branches : "",
1473 132af4a5 2021-01-05 stsp branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1474 132af4a5 2021-01-05 stsp branchname) == -1) {
1475 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1476 132af4a5 2021-01-05 stsp goto done;
1478 132af4a5 2021-01-05 stsp free(branches);
1479 132af4a5 2021-01-05 stsp branches = s;
1483 7c0b7f42 2020-09-24 stsp * If the server specified a default branch, use just that one.
1484 7c0b7f42 2020-09-24 stsp * Otherwise fall back to fetching all branches on next fetch.
1486 04d9a9ec 2020-09-24 stsp if (default_branch) {
1487 04d9a9ec 2020-09-24 stsp branchname = default_branch;
1488 7c0b7f42 2020-09-24 stsp if (strncmp(branchname, "refs/heads/", 11) == 0)
1489 7c0b7f42 2020-09-24 stsp branchname += 11;
1491 7c0b7f42 2020-09-24 stsp branchname = "*"; /* fall back to all branches */
1492 56d0a753 2021-01-20 stsp if (mirror_references) {
1493 56d0a753 2021-01-20 stsp if (asprintf(&branches,
1494 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/%s:refs/heads/%s\n",
1495 56d0a753 2021-01-20 stsp branchname, branchname) == -1) {
1496 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1497 56d0a753 2021-01-20 stsp goto done;
1499 56d0a753 2021-01-20 stsp } else if (asprintf(&branches,
1500 56d0a753 2021-01-20 stsp "\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1501 7c0b7f42 2020-09-24 stsp branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1502 7c0b7f42 2020-09-24 stsp branchname) == -1) {
1503 7c0b7f42 2020-09-24 stsp err = got_error_from_errno("asprintf");
1504 7c0b7f42 2020-09-24 stsp goto done;
1507 56d0a753 2021-01-20 stsp if (!TAILQ_EMPTY(wanted_refs)) {
1508 99495ddb 2021-01-10 stsp struct got_pathlist_entry *pe;
1509 99495ddb 2021-01-10 stsp TAILQ_FOREACH(pe, wanted_refs, entry) {
1511 99495ddb 2021-01-10 stsp const char *refname = pe->path;
1512 99495ddb 2021-01-10 stsp if (strncmp(refname, "refs/", 5) == 0)
1513 99495ddb 2021-01-10 stsp refname += 5;
1514 56d0a753 2021-01-20 stsp if (mirror_references) {
1515 56d0a753 2021-01-20 stsp if (asprintf(&s,
1516 56d0a753 2021-01-20 stsp "%s\tfetch = refs/%s:refs/%s\n",
1517 56d0a753 2021-01-20 stsp refs ? refs : "", refname, refname) == -1) {
1518 56d0a753 2021-01-20 stsp err = got_error_from_errno("asprintf");
1519 56d0a753 2021-01-20 stsp goto done;
1521 56d0a753 2021-01-20 stsp } else if (asprintf(&s,
1522 56d0a753 2021-01-20 stsp "%s\tfetch = refs/%s:refs/remotes/%s/%s\n",
1523 99495ddb 2021-01-10 stsp refs ? refs : "",
1524 99495ddb 2021-01-10 stsp refname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1525 99495ddb 2021-01-10 stsp refname) == -1) {
1526 99495ddb 2021-01-10 stsp err = got_error_from_errno("asprintf");
1527 99495ddb 2021-01-10 stsp goto done;
1529 99495ddb 2021-01-10 stsp free(refs);
1534 132af4a5 2021-01-05 stsp if (asprintf(&gitconfig,
1535 132af4a5 2021-01-05 stsp "[remote \"%s\"]\n"
1536 132af4a5 2021-01-05 stsp "\turl = %s\n"
1539 56d0a753 2021-01-20 stsp "\tfetch = refs/tags/*:refs/tags/*\n",
1540 132af4a5 2021-01-05 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, git_url, branches ? branches : "",
1541 56d0a753 2021-01-20 stsp refs ? refs : "") == -1) {
1542 132af4a5 2021-01-05 stsp err = got_error_from_errno("asprintf");
1543 132af4a5 2021-01-05 stsp goto done;
1545 7c0b7f42 2020-09-24 stsp n = fwrite(gitconfig, 1, strlen(gitconfig), gitconfig_file);
1546 7c0b7f42 2020-09-24 stsp if (n != strlen(gitconfig)) {
1547 7c0b7f42 2020-09-24 stsp err = got_ferror(gitconfig_file, GOT_ERR_IO);
1548 7c0b7f42 2020-09-24 stsp goto done;
1551 7c0b7f42 2020-09-24 stsp if (gitconfig_file && fclose(gitconfig_file) == EOF && err == NULL)
1552 7c0b7f42 2020-09-24 stsp err = got_error_from_errno2("fclose", gitconfig_path);
1553 7c0b7f42 2020-09-24 stsp free(gitconfig_path);
1554 132af4a5 2021-01-05 stsp free(branches);
1555 0e4002ca 2020-03-21 stsp return err;
1558 0e4002ca 2020-03-21 stsp static const struct got_error *
1559 04d9a9ec 2020-09-24 stsp create_config_files(const char *proto, const char *host, const char *port,
1560 04d9a9ec 2020-09-24 stsp const char *remote_repo_path, const char *git_url, int fetch_all_branches,
1561 04d9a9ec 2020-09-24 stsp int mirror_references, struct got_pathlist_head *symrefs,
1562 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_branches,
1563 99495ddb 2021-01-10 stsp struct got_pathlist_head *wanted_refs, struct got_repository *repo)
1565 04d9a9ec 2020-09-24 stsp const struct got_error *err = NULL;
1566 04d9a9ec 2020-09-24 stsp const char *default_branch = NULL;
1567 04d9a9ec 2020-09-24 stsp struct got_pathlist_entry *pe;
1570 04d9a9ec 2020-09-24 stsp * If we asked for a set of wanted branches then use the first
1571 04d9a9ec 2020-09-24 stsp * one of those.
1573 62d463ca 2020-10-20 naddy if (!TAILQ_EMPTY(wanted_branches)) {
1574 04d9a9ec 2020-09-24 stsp pe = TAILQ_FIRST(wanted_branches);
1575 04d9a9ec 2020-09-24 stsp default_branch = pe->path;
1577 04d9a9ec 2020-09-24 stsp /* First HEAD ref listed by server is the default branch. */
1578 04d9a9ec 2020-09-24 stsp TAILQ_FOREACH(pe, symrefs, entry) {
1579 04d9a9ec 2020-09-24 stsp const char *refname = pe->path;
1580 04d9a9ec 2020-09-24 stsp const char *target = pe->data;
1582 04d9a9ec 2020-09-24 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
1585 04d9a9ec 2020-09-24 stsp default_branch = target;
1590 04d9a9ec 2020-09-24 stsp /* Create got.conf(5). */
1591 04d9a9ec 2020-09-24 stsp err = create_gotconfig(proto, host, port, remote_repo_path,
1592 0c8b29c5 2021-01-05 stsp default_branch, fetch_all_branches, wanted_branches,
1593 99495ddb 2021-01-10 stsp wanted_refs, mirror_references, repo);
1595 04d9a9ec 2020-09-24 stsp return err;
1597 04d9a9ec 2020-09-24 stsp /* Create a config file Git can understand. */
1598 04d9a9ec 2020-09-24 stsp return create_gitconfig(git_url, default_branch, fetch_all_branches,
1599 99495ddb 2021-01-10 stsp wanted_branches, wanted_refs, mirror_references, repo);
1602 04d9a9ec 2020-09-24 stsp static const struct got_error *
1603 93658fb9 2020-03-18 stsp cmd_clone(int argc, char *argv[])
1605 39c64a6a 2020-03-18 stsp const struct got_error *error = NULL;
1606 9df6f38b 2020-03-18 stsp const char *uri, *dirname;
1607 09838ffc 2020-03-18 stsp char *proto, *host, *port, *repo_name, *server_path;
1608 d9b4d0c0 2020-03-18 stsp char *default_destdir = NULL, *id_str = NULL;
1609 a9c2d4c2 2020-09-24 stsp const char *repo_path;
1610 bb64b798 2020-03-18 stsp struct got_repository *repo = NULL;
1611 0e4002ca 2020-03-21 stsp struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
1612 d9b4d0c0 2020-03-18 stsp struct got_pathlist_entry *pe;
1613 d9b4d0c0 2020-03-18 stsp struct got_object_id *pack_hash = NULL;
1614 9c52365f 2020-03-21 stsp int ch, fetchfd = -1, fetchstatus;
1615 9c52365f 2020-03-21 stsp pid_t fetchpid = -1;
1616 892ac3b6 2020-03-18 stsp struct got_fetch_progress_arg fpa;
1617 b46f3e71 2020-03-18 stsp char *git_url = NULL;
1618 659e7fbd 2020-03-20 stsp int verbosity = 0, fetch_all_branches = 0, mirror_references = 0;
1619 7abf1863 2023-02-20 thomas int bflag = 0, list_refs_only = 0;
1620 7cd52833 2022-06-23 thomas int *pack_fds = NULL;
1622 d9b4d0c0 2020-03-18 stsp TAILQ_INIT(&refs);
1623 d9b4d0c0 2020-03-18 stsp TAILQ_INIT(&symrefs);
1624 4ba14133 2020-03-20 stsp TAILQ_INIT(&wanted_branches);
1625 0e4002ca 2020-03-21 stsp TAILQ_INIT(&wanted_refs);
1627 f7065961 2022-10-27 thomas while ((ch = getopt(argc, argv, "ab:lmqR:v")) != -1) {
1628 93658fb9 2020-03-18 stsp switch (ch) {
1630 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
1633 4ba14133 2020-03-20 stsp error = got_pathlist_append(&wanted_branches,
1634 4ba14133 2020-03-20 stsp optarg, NULL);
1635 4ba14133 2020-03-20 stsp if (error)
1636 4ba14133 2020-03-20 stsp return error;
1637 7abf1863 2023-02-20 thomas bflag = 1;
1640 41b0de12 2020-03-21 stsp list_refs_only = 1;
1643 469dd726 2020-03-20 stsp mirror_references = 1;
1646 68999b92 2020-03-18 stsp verbosity = -1;
1649 0e4002ca 2020-03-21 stsp error = got_pathlist_append(&wanted_refs,
1650 0e4002ca 2020-03-21 stsp optarg, NULL);
1651 0e4002ca 2020-03-21 stsp if (error)
1652 0e4002ca 2020-03-21 stsp return error;
1654 f7065961 2022-10-27 thomas case 'v':
1655 f7065961 2022-10-27 thomas if (verbosity < 0)
1656 f7065961 2022-10-27 thomas verbosity = 0;
1657 f7065961 2022-10-27 thomas else if (verbosity < 3)
1658 f7065961 2022-10-27 thomas verbosity++;
1661 93658fb9 2020-03-18 stsp usage_clone();
1665 93658fb9 2020-03-18 stsp argc -= optind;
1666 93658fb9 2020-03-18 stsp argv += optind;
1668 4ba14133 2020-03-20 stsp if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
1669 ff69268e 2020-12-13 stsp option_conflict('a', 'b');
1670 41b0de12 2020-03-21 stsp if (list_refs_only) {
1671 41b0de12 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_branches))
1672 ff69268e 2020-12-13 stsp option_conflict('l', 'b');
1673 41b0de12 2020-03-21 stsp if (fetch_all_branches)
1674 ff69268e 2020-12-13 stsp option_conflict('l', 'a');
1675 41b0de12 2020-03-21 stsp if (mirror_references)
1676 ff69268e 2020-12-13 stsp option_conflict('l', 'm');
1677 0e4002ca 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_refs))
1678 ff69268e 2020-12-13 stsp option_conflict('l', 'R');
1681 93658fb9 2020-03-18 stsp uri = argv[0];
1683 9df6f38b 2020-03-18 stsp if (argc == 1)
1684 93658fb9 2020-03-18 stsp dirname = NULL;
1685 9df6f38b 2020-03-18 stsp else if (argc == 2)
1686 93658fb9 2020-03-18 stsp dirname = argv[1];
1688 93658fb9 2020-03-18 stsp usage_clone();
1690 5e5da8c4 2021-09-05 stsp error = got_dial_parse_uri(&proto, &host, &port, &server_path,
1691 4dbec0a8 2020-08-27 stsp &repo_name, uri);
1692 39c64a6a 2020-03-18 stsp if (error)
1693 09f63084 2020-03-20 stsp goto done;
1695 09f63084 2020-03-20 stsp if (asprintf(&git_url, "%s://%s%s%s%s%s", proto,
1696 09f63084 2020-03-20 stsp host, port ? ":" : "", port ? port : "",
1697 09f63084 2020-03-20 stsp server_path[0] != '/' ? "/" : "", server_path) == -1) {
1698 09f63084 2020-03-20 stsp error = got_error_from_errno("asprintf");
1699 09838ffc 2020-03-18 stsp goto done;
1702 39c64a6a 2020-03-18 stsp if (strcmp(proto, "git") == 0) {
1703 b46f3e71 2020-03-18 stsp #ifndef PROFILE
1704 39c64a6a 2020-03-18 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1705 39c64a6a 2020-03-18 stsp "sendfd dns inet unveil", NULL) == -1)
1706 39c64a6a 2020-03-18 stsp err(1, "pledge");
1708 39c64a6a 2020-03-18 stsp } else if (strcmp(proto, "git+ssh") == 0 ||
1709 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "ssh") == 0 ||
1710 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "git+http") == 0 ||
1711 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "http") == 0 ||
1712 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "git+https") == 0 ||
1713 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "https") == 0) {
1714 b46f3e71 2020-03-18 stsp #ifndef PROFILE
1715 39c64a6a 2020-03-18 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1716 39c64a6a 2020-03-18 stsp "sendfd unveil", NULL) == -1)
1717 39c64a6a 2020-03-18 stsp err(1, "pledge");
1720 39c64a6a 2020-03-18 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
1721 39c64a6a 2020-03-18 stsp goto done;
1723 bb64b798 2020-03-18 stsp if (dirname == NULL) {
1724 bb64b798 2020-03-18 stsp if (asprintf(&default_destdir, "%s.git", repo_name) == -1) {
1725 39c64a6a 2020-03-18 stsp error = got_error_from_errno("asprintf");
1726 bb64b798 2020-03-18 stsp goto done;
1728 bb64b798 2020-03-18 stsp repo_path = default_destdir;
1730 bb64b798 2020-03-18 stsp repo_path = dirname;
1732 41b0de12 2020-03-21 stsp if (!list_refs_only) {
1733 41b0de12 2020-03-21 stsp error = got_path_mkdir(repo_path);
1734 2751fe64 2020-09-24 stsp if (error &&
1735 2751fe64 2020-09-24 stsp (!(error->code == GOT_ERR_ERRNO && errno == EISDIR) &&
1736 2751fe64 2020-09-24 stsp !(error->code == GOT_ERR_ERRNO && errno == EEXIST)))
1737 41b0de12 2020-03-21 stsp goto done;
1738 2751fe64 2020-09-24 stsp if (!got_path_dir_is_empty(repo_path)) {
1739 2751fe64 2020-09-24 stsp error = got_error_path(repo_path,
1740 2751fe64 2020-09-24 stsp GOT_ERR_DIR_NOT_EMPTY);
1741 41b0de12 2020-03-21 stsp goto done;
1745 d65a88a2 2021-09-05 stsp error = got_dial_apply_unveil(proto);
1746 d65a88a2 2021-09-05 stsp if (error)
1747 d65a88a2 2021-09-05 stsp goto done;
1749 f535bcd4 2020-09-30 stsp error = apply_unveil(repo_path, 0, NULL);
1750 ee448f5f 2020-03-18 stsp if (error)
1751 ee448f5f 2020-03-18 stsp goto done;
1753 f79e6490 2020-04-19 stsp if (verbosity >= 0)
1754 6df5d941 2022-11-18 thomas printf("Connecting to %s\n", git_url);
1756 9c52365f 2020-03-21 stsp error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
1757 9c52365f 2020-03-21 stsp server_path, verbosity);
1758 39c64a6a 2020-03-18 stsp if (error)
1759 bb64b798 2020-03-18 stsp goto done;
1761 a6955b87 2024-04-25 thomas.ad #ifndef PROFILE
1762 a6955b87 2024-04-25 thomas.ad if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd",
1763 a6955b87 2024-04-25 thomas.ad NULL) == -1)
1764 a6955b87 2024-04-25 thomas.ad err(1, "pledge");
1765 a6955b87 2024-04-25 thomas.ad #endif
1766 2751fe64 2020-09-24 stsp if (!list_refs_only) {
1767 e9424ba1 2022-09-20 thomas error = got_repo_init(repo_path, NULL);
1768 2751fe64 2020-09-24 stsp if (error)
1769 2751fe64 2020-09-24 stsp goto done;
1770 7cd52833 2022-06-23 thomas error = got_repo_pack_fds_open(&pack_fds);
1771 7cd52833 2022-06-23 thomas if (error != NULL)
1772 7cd52833 2022-06-23 thomas goto done;
1773 7cd52833 2022-06-23 thomas error = got_repo_open(&repo, repo_path, NULL, pack_fds);
1774 2751fe64 2020-09-24 stsp if (error)
1775 2751fe64 2020-09-24 stsp goto done;
1778 892ac3b6 2020-03-18 stsp fpa.last_scaled_size[0] = '\0';
1779 892ac3b6 2020-03-18 stsp fpa.last_p_indexed = -1;
1780 892ac3b6 2020-03-18 stsp fpa.last_p_resolved = -1;
1781 68999b92 2020-03-18 stsp fpa.verbosity = verbosity;
1782 04d9a9ec 2020-09-24 stsp fpa.create_configs = 1;
1783 04d9a9ec 2020-09-24 stsp fpa.configs_created = 0;
1784 04d9a9ec 2020-09-24 stsp fpa.repo = repo;
1785 04d9a9ec 2020-09-24 stsp fpa.config_info.symrefs = &symrefs;
1786 04d9a9ec 2020-09-24 stsp fpa.config_info.wanted_branches = &wanted_branches;
1787 99495ddb 2021-01-10 stsp fpa.config_info.wanted_refs = &wanted_refs;
1788 04d9a9ec 2020-09-24 stsp fpa.config_info.proto = proto;
1789 04d9a9ec 2020-09-24 stsp fpa.config_info.host = host;
1790 04d9a9ec 2020-09-24 stsp fpa.config_info.port = port;
1791 04d9a9ec 2020-09-24 stsp fpa.config_info.remote_repo_path = server_path;
1792 04d9a9ec 2020-09-24 stsp fpa.config_info.git_url = git_url;
1793 04d9a9ec 2020-09-24 stsp fpa.config_info.fetch_all_branches = fetch_all_branches;
1794 04d9a9ec 2020-09-24 stsp fpa.config_info.mirror_references = mirror_references;
1795 7848a0e1 2020-03-19 stsp error = got_fetch_pack(&pack_hash, &refs, &symrefs,
1796 469dd726 2020-03-20 stsp GOT_FETCH_DEFAULT_REMOTE_NAME, mirror_references,
1797 0e4002ca 2020-03-21 stsp fetch_all_branches, &wanted_branches, &wanted_refs,
1798 7abf1863 2023-02-20 thomas list_refs_only, verbosity, fetchfd, repo, NULL, NULL, bflag,
1799 0e4002ca 2020-03-21 stsp fetch_progress, &fpa);
1800 39c64a6a 2020-03-18 stsp if (error)
1801 d9b4d0c0 2020-03-18 stsp goto done;
1803 41b0de12 2020-03-21 stsp if (list_refs_only) {
1804 41b0de12 2020-03-21 stsp error = list_remote_refs(&symrefs, &refs);
1805 41b0de12 2020-03-21 stsp goto done;
1808 c3741b51 2021-12-31 thomas if (pack_hash == NULL) {
1809 c3741b51 2021-12-31 thomas error = got_error_fmt(GOT_ERR_FETCH_FAILED, "%s",
1810 c3741b51 2021-12-31 thomas "server sent an empty pack file");
1811 c3741b51 2021-12-31 thomas goto done;
1813 39c64a6a 2020-03-18 stsp error = got_object_id_str(&id_str, pack_hash);
1814 39c64a6a 2020-03-18 stsp if (error)
1815 d9b4d0c0 2020-03-18 stsp goto done;
1816 68999b92 2020-03-18 stsp if (verbosity >= 0)
1817 e69674d8 2020-03-19 stsp printf("\nFetched %s.pack\n", id_str);
1818 d9b4d0c0 2020-03-18 stsp free(id_str);
1820 d9b4d0c0 2020-03-18 stsp /* Set up references provided with the pack file. */
1821 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &refs, entry) {
1822 d9b4d0c0 2020-03-18 stsp const char *refname = pe->path;
1823 d9b4d0c0 2020-03-18 stsp struct got_object_id *id = pe->data;
1824 7ebc0570 2020-03-18 stsp char *remote_refname;
1826 0e4002ca 2020-03-21 stsp if (is_wanted_ref(&wanted_refs, refname) &&
1827 0e4002ca 2020-03-21 stsp !mirror_references) {
1828 0e4002ca 2020-03-21 stsp error = create_wanted_ref(refname, id,
1829 0e4002ca 2020-03-21 stsp GOT_FETCH_DEFAULT_REMOTE_NAME,
1830 0e4002ca 2020-03-21 stsp verbosity - 1, repo);
1831 0e4002ca 2020-03-21 stsp if (error)
1832 0e4002ca 2020-03-21 stsp goto done;
1836 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity - 1, repo);
1837 39c64a6a 2020-03-18 stsp if (error)
1838 d9b4d0c0 2020-03-18 stsp goto done;
1840 469dd726 2020-03-20 stsp if (mirror_references)
1843 7ebc0570 2020-03-18 stsp if (strncmp("refs/heads/", refname, 11) != 0)
1846 7ebc0570 2020-03-18 stsp if (asprintf(&remote_refname,
1847 7ebc0570 2020-03-18 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1848 7ebc0570 2020-03-18 stsp refname + 11) == -1) {
1849 7ebc0570 2020-03-18 stsp error = got_error_from_errno("asprintf");
1850 7ebc0570 2020-03-18 stsp goto done;
1852 6338a6a1 2020-03-21 stsp error = create_ref(remote_refname, id, verbosity - 1, repo);
1853 f298ae0f 2020-03-25 stsp free(remote_refname);
1854 39c64a6a 2020-03-18 stsp if (error)
1855 d9b4d0c0 2020-03-18 stsp goto done;
1858 d9b4d0c0 2020-03-18 stsp /* Set the HEAD reference if the server provided one. */
1859 d9b4d0c0 2020-03-18 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
1860 659e7fbd 2020-03-20 stsp struct got_reference *target_ref;
1861 d9b4d0c0 2020-03-18 stsp const char *refname = pe->path;
1862 d9b4d0c0 2020-03-18 stsp const char *target = pe->data;
1863 f298ae0f 2020-03-25 stsp char *remote_refname = NULL, *remote_target = NULL;
1865 d9b4d0c0 2020-03-18 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
1868 39c64a6a 2020-03-18 stsp error = got_ref_open(&target_ref, repo, target, 0);
1869 39c64a6a 2020-03-18 stsp if (error) {
1870 55330abe 2020-03-20 stsp if (error->code == GOT_ERR_NOT_REF) {
1871 55330abe 2020-03-20 stsp error = NULL;
1874 d9b4d0c0 2020-03-18 stsp goto done;
1877 04d9a9ec 2020-09-24 stsp error = create_symref(refname, target_ref, verbosity, repo);
1878 f298ae0f 2020-03-25 stsp got_ref_close(target_ref);
1879 f298ae0f 2020-03-25 stsp if (error)
1880 f298ae0f 2020-03-25 stsp goto done;
1882 f298ae0f 2020-03-25 stsp if (mirror_references)
1885 f298ae0f 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
1888 f298ae0f 2020-03-25 stsp if (asprintf(&remote_refname,
1889 f298ae0f 2020-03-25 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1890 f298ae0f 2020-03-25 stsp refname) == -1) {
1891 f298ae0f 2020-03-25 stsp error = got_error_from_errno("asprintf");
1892 f298ae0f 2020-03-25 stsp goto done;
1894 f298ae0f 2020-03-25 stsp if (asprintf(&remote_target,
1895 f298ae0f 2020-03-25 stsp "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1896 f298ae0f 2020-03-25 stsp target + 11) == -1) {
1897 f298ae0f 2020-03-25 stsp error = got_error_from_errno("asprintf");
1898 f298ae0f 2020-03-25 stsp free(remote_refname);
1899 f298ae0f 2020-03-25 stsp goto done;
1901 f298ae0f 2020-03-25 stsp error = got_ref_open(&target_ref, repo, remote_target, 0);
1902 f298ae0f 2020-03-25 stsp if (error) {
1903 f298ae0f 2020-03-25 stsp free(remote_refname);
1904 f298ae0f 2020-03-25 stsp free(remote_target);
1905 f298ae0f 2020-03-25 stsp if (error->code == GOT_ERR_NOT_REF) {
1906 f298ae0f 2020-03-25 stsp error = NULL;
1909 f298ae0f 2020-03-25 stsp goto done;
1911 04d9a9ec 2020-09-24 stsp error = create_symref(remote_refname, target_ref,
1912 04d9a9ec 2020-09-24 stsp verbosity - 1, repo);
1913 f298ae0f 2020-03-25 stsp free(remote_refname);
1914 f298ae0f 2020-03-25 stsp free(remote_target);
1915 d9b4d0c0 2020-03-18 stsp got_ref_close(target_ref);
1916 39c64a6a 2020-03-18 stsp if (error)
1917 d9b4d0c0 2020-03-18 stsp goto done;
1919 4ba14133 2020-03-20 stsp if (pe == NULL) {
1921 4ba14133 2020-03-20 stsp * We failed to set the HEAD reference. If we asked for
1922 4ba14133 2020-03-20 stsp * a set of wanted branches use the first of one of those
1923 4ba14133 2020-03-20 stsp * which could be fetched instead.
1925 62d463ca 2020-10-20 naddy TAILQ_FOREACH(pe, &wanted_branches, entry) {
1926 4ba14133 2020-03-20 stsp const char *target = pe->path;
1927 4ba14133 2020-03-20 stsp struct got_reference *target_ref;
1929 4ba14133 2020-03-20 stsp error = got_ref_open(&target_ref, repo, target, 0);
1930 4ba14133 2020-03-20 stsp if (error) {
1931 4ba14133 2020-03-20 stsp if (error->code == GOT_ERR_NOT_REF) {
1932 4ba14133 2020-03-20 stsp error = NULL;
1935 4ba14133 2020-03-20 stsp goto done;
1938 04d9a9ec 2020-09-24 stsp error = create_symref(GOT_REF_HEAD, target_ref,
1939 04d9a9ec 2020-09-24 stsp verbosity, repo);
1940 4ba14133 2020-03-20 stsp got_ref_close(target_ref);
1941 4ba14133 2020-03-20 stsp if (error)
1942 4ba14133 2020-03-20 stsp goto done;
1946 c22ed3f5 2022-11-08 thomas if (!fpa.configs_created && pe != NULL) {
1947 c22ed3f5 2022-11-08 thomas error = create_config_files(fpa.config_info.proto,
1948 c22ed3f5 2022-11-08 thomas fpa.config_info.host, fpa.config_info.port,
1949 c22ed3f5 2022-11-08 thomas fpa.config_info.remote_repo_path,
1950 c22ed3f5 2022-11-08 thomas fpa.config_info.git_url,
1951 c22ed3f5 2022-11-08 thomas fpa.config_info.fetch_all_branches,
1952 c22ed3f5 2022-11-08 thomas fpa.config_info.mirror_references,
1953 c22ed3f5 2022-11-08 thomas fpa.config_info.symrefs,
1954 c22ed3f5 2022-11-08 thomas fpa.config_info.wanted_branches,
1955 c22ed3f5 2022-11-08 thomas fpa.config_info.wanted_refs, fpa.repo);
1956 c22ed3f5 2022-11-08 thomas if (error)
1957 c22ed3f5 2022-11-08 thomas goto done;
1961 d715f13e 2020-03-19 stsp if (verbosity >= 0)
1962 469dd726 2020-03-20 stsp printf("Created %s repository '%s'\n",
1963 469dd726 2020-03-20 stsp mirror_references ? "mirrored" : "cloned", repo_path);
1965 7cd52833 2022-06-23 thomas if (pack_fds) {
1966 7cd52833 2022-06-23 thomas const struct got_error *pack_err =
1967 7cd52833 2022-06-23 thomas got_repo_pack_fds_close(pack_fds);
1968 7cd52833 2022-06-23 thomas if (error == NULL)
1969 7cd52833 2022-06-23 thomas error = pack_err;
1971 9c52365f 2020-03-21 stsp if (fetchpid > 0) {
1972 9c52365f 2020-03-21 stsp if (kill(fetchpid, SIGTERM) == -1)
1973 9c52365f 2020-03-21 stsp error = got_error_from_errno("kill");
1974 9c52365f 2020-03-21 stsp if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
1975 9c52365f 2020-03-21 stsp error = got_error_from_errno("waitpid");
1977 39c64a6a 2020-03-18 stsp if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
1978 39c64a6a 2020-03-18 stsp error = got_error_from_errno("close");
1979 1d0f4054 2021-06-17 stsp if (repo) {
1980 1d0f4054 2021-06-17 stsp const struct got_error *close_err = got_repo_close(repo);
1981 1d0f4054 2021-06-17 stsp if (error == NULL)
1982 1d0f4054 2021-06-17 stsp error = close_err;
1984 21c2d8be 2023-01-10 thomas got_pathlist_free(&refs, GOT_PATHLIST_FREE_ALL);
1985 21c2d8be 2023-01-10 thomas got_pathlist_free(&symrefs, GOT_PATHLIST_FREE_ALL);
1986 21c2d8be 2023-01-10 thomas got_pathlist_free(&wanted_branches, GOT_PATHLIST_FREE_NONE);
1987 21c2d8be 2023-01-10 thomas got_pathlist_free(&wanted_refs, GOT_PATHLIST_FREE_NONE);
1988 d9b4d0c0 2020-03-18 stsp free(pack_hash);
1989 09838ffc 2020-03-18 stsp free(proto);
1990 09838ffc 2020-03-18 stsp free(host);
1991 09838ffc 2020-03-18 stsp free(port);
1992 09838ffc 2020-03-18 stsp free(server_path);
1993 09838ffc 2020-03-18 stsp free(repo_name);
1994 bb64b798 2020-03-18 stsp free(default_destdir);
1995 b46f3e71 2020-03-18 stsp free(git_url);
1996 39c64a6a 2020-03-18 stsp return error;
1999 7848a0e1 2020-03-19 stsp static const struct got_error *
2000 7848a0e1 2020-03-19 stsp update_ref(struct got_reference *ref, struct got_object_id *new_id,
2001 db6d8ad8 2020-03-21 stsp int replace_tags, int verbosity, struct got_repository *repo)
2003 7848a0e1 2020-03-19 stsp const struct got_error *err = NULL;
2004 7848a0e1 2020-03-19 stsp char *new_id_str = NULL;
2005 7848a0e1 2020-03-19 stsp struct got_object_id *old_id = NULL;
2007 7848a0e1 2020-03-19 stsp err = got_object_id_str(&new_id_str, new_id);
2009 7848a0e1 2020-03-19 stsp goto done;
2011 db6d8ad8 2020-03-21 stsp if (!replace_tags &&
2012 db6d8ad8 2020-03-21 stsp strncmp(got_ref_get_name(ref), "refs/tags/", 10) == 0) {
2013 88609724 2020-03-21 stsp err = got_ref_resolve(&old_id, repo, ref);
2015 88609724 2020-03-21 stsp goto done;
2016 88609724 2020-03-21 stsp if (got_object_id_cmp(old_id, new_id) == 0)
2017 88609724 2020-03-21 stsp goto done;
2018 db6d8ad8 2020-03-21 stsp if (verbosity >= 0) {
2019 db6d8ad8 2020-03-21 stsp printf("Rejecting update of existing tag %s: %s\n",
2020 db6d8ad8 2020-03-21 stsp got_ref_get_name(ref), new_id_str);
2022 db6d8ad8 2020-03-21 stsp goto done;
2025 7848a0e1 2020-03-19 stsp if (got_ref_is_symbolic(ref)) {
2026 688f11b3 2020-03-21 stsp if (verbosity >= 0) {
2027 e8a967e0 2020-03-21 stsp printf("Replacing reference %s: %s\n",
2028 6338a6a1 2020-03-21 stsp got_ref_get_name(ref),
2029 6338a6a1 2020-03-21 stsp got_ref_get_symref_target(ref));
2031 e8a967e0 2020-03-21 stsp err = got_ref_change_symref_to_ref(ref, new_id);
2033 7848a0e1 2020-03-19 stsp goto done;
2034 e8a967e0 2020-03-21 stsp err = got_ref_write(ref, repo);
2036 e8a967e0 2020-03-21 stsp goto done;
2038 7848a0e1 2020-03-19 stsp err = got_ref_resolve(&old_id, repo, ref);
2040 7848a0e1 2020-03-19 stsp goto done;
2041 6338a6a1 2020-03-21 stsp if (got_object_id_cmp(old_id, new_id) == 0)
2042 6338a6a1 2020-03-21 stsp goto done;
2044 6338a6a1 2020-03-21 stsp err = got_ref_change_ref(ref, new_id);
2046 6338a6a1 2020-03-21 stsp goto done;
2047 6338a6a1 2020-03-21 stsp err = got_ref_write(ref, repo);
2049 6338a6a1 2020-03-21 stsp goto done;
2052 6338a6a1 2020-03-21 stsp if (verbosity >= 0)
2053 f4d0e3fb 2020-05-15 stsp printf("Updated %s: %s\n", got_ref_get_name(ref),
2054 6338a6a1 2020-03-21 stsp new_id_str);
2056 7848a0e1 2020-03-19 stsp free(old_id);
2057 7848a0e1 2020-03-19 stsp free(new_id_str);
2058 7848a0e1 2020-03-19 stsp return err;
2061 f1bcca34 2020-03-25 stsp static const struct got_error *
2062 f1bcca34 2020-03-25 stsp update_symref(const char *refname, struct got_reference *target_ref,
2063 f1bcca34 2020-03-25 stsp int verbosity, struct got_repository *repo)
2065 f1bcca34 2020-03-25 stsp const struct got_error *err = NULL, *unlock_err;
2066 f1bcca34 2020-03-25 stsp struct got_reference *symref;
2067 bcf34b0e 2020-03-26 stsp int symref_is_locked = 0;
2069 f1bcca34 2020-03-25 stsp err = got_ref_open(&symref, repo, refname, 1);
2070 bcf34b0e 2020-03-26 stsp if (err) {
2071 bcf34b0e 2020-03-26 stsp if (err->code != GOT_ERR_NOT_REF)
2072 bcf34b0e 2020-03-26 stsp return err;
2073 bcf34b0e 2020-03-26 stsp err = got_ref_alloc_symref(&symref, refname, target_ref);
2075 bcf34b0e 2020-03-26 stsp goto done;
2077 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
2079 bcf34b0e 2020-03-26 stsp goto done;
2081 bcf34b0e 2020-03-26 stsp if (verbosity >= 0)
2082 bcf34b0e 2020-03-26 stsp printf("Created reference %s: %s\n",
2083 bcf34b0e 2020-03-26 stsp got_ref_get_name(symref),
2084 bcf34b0e 2020-03-26 stsp got_ref_get_symref_target(symref));
2086 bcf34b0e 2020-03-26 stsp symref_is_locked = 1;
2088 bcf34b0e 2020-03-26 stsp if (strcmp(got_ref_get_symref_target(symref),
2089 bcf34b0e 2020-03-26 stsp got_ref_get_name(target_ref)) == 0)
2090 bcf34b0e 2020-03-26 stsp goto done;
2092 bcf34b0e 2020-03-26 stsp err = got_ref_change_symref(symref,
2093 bcf34b0e 2020-03-26 stsp got_ref_get_name(target_ref));
2095 bcf34b0e 2020-03-26 stsp goto done;
2097 bcf34b0e 2020-03-26 stsp err = got_ref_write(symref, repo);
2099 bcf34b0e 2020-03-26 stsp goto done;
2101 bcf34b0e 2020-03-26 stsp if (verbosity >= 0)
2102 f4d0e3fb 2020-05-15 stsp printf("Updated %s: %s\n", got_ref_get_name(symref),
2103 bcf34b0e 2020-03-26 stsp got_ref_get_symref_target(symref));
2107 bcf34b0e 2020-03-26 stsp if (symref_is_locked) {
2108 bcf34b0e 2020-03-26 stsp unlock_err = got_ref_unlock(symref);
2109 bcf34b0e 2020-03-26 stsp if (unlock_err && err == NULL)
2110 bcf34b0e 2020-03-26 stsp err = unlock_err;
2112 f1bcca34 2020-03-25 stsp got_ref_close(symref);
2113 f1bcca34 2020-03-25 stsp return err;
2116 2ab43947 2020-03-18 stsp __dead static void
2117 7848a0e1 2020-03-19 stsp usage_fetch(void)
2119 d6506a3d 2022-08-16 thomas fprintf(stderr, "usage: %s fetch [-adlqtvX] [-b branch] "
2120 d6506a3d 2022-08-16 thomas "[-R reference] [-r repository-path] [remote-repository]\n",
2121 13f12b09 2020-03-21 stsp getprogname());
2125 7848a0e1 2020-03-19 stsp static const struct got_error *
2126 3789fd73 2020-03-26 stsp delete_missing_ref(struct got_reference *ref,
2127 688f11b3 2020-03-21 stsp int verbosity, struct got_repository *repo)
2129 f21ec2f0 2020-03-21 stsp const struct got_error *err = NULL;
2130 3789fd73 2020-03-26 stsp struct got_object_id *id = NULL;
2131 3789fd73 2020-03-26 stsp char *id_str = NULL;
2133 3789fd73 2020-03-26 stsp if (got_ref_is_symbolic(ref)) {
2134 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
2136 3789fd73 2020-03-26 stsp return err;
2137 3789fd73 2020-03-26 stsp if (verbosity >= 0) {
2138 f9d54ee6 2021-07-16 stsp printf("Deleted %s: %s\n",
2139 3789fd73 2020-03-26 stsp got_ref_get_name(ref),
2140 3789fd73 2020-03-26 stsp got_ref_get_symref_target(ref));
2143 3789fd73 2020-03-26 stsp err = got_ref_resolve(&id, repo, ref);
2145 3789fd73 2020-03-26 stsp return err;
2146 3789fd73 2020-03-26 stsp err = got_object_id_str(&id_str, id);
2148 3789fd73 2020-03-26 stsp goto done;
2150 3789fd73 2020-03-26 stsp err = got_ref_delete(ref, repo);
2152 3789fd73 2020-03-26 stsp goto done;
2153 3789fd73 2020-03-26 stsp if (verbosity >= 0) {
2154 f9d54ee6 2021-07-16 stsp printf("Deleted %s: %s\n",
2155 3789fd73 2020-03-26 stsp got_ref_get_name(ref), id_str);
2160 3789fd73 2020-03-26 stsp free(id_str);
2161 a66a4a50 2023-02-03 thomas return err;
2164 3789fd73 2020-03-26 stsp static const struct got_error *
2165 3789fd73 2020-03-26 stsp delete_missing_refs(struct got_pathlist_head *their_refs,
2166 50b0790e 2020-09-11 stsp struct got_pathlist_head *their_symrefs,
2167 50b0790e 2020-09-11 stsp const struct got_remote_repo *remote,
2168 3789fd73 2020-03-26 stsp int verbosity, struct got_repository *repo)
2170 3789fd73 2020-03-26 stsp const struct got_error *err = NULL, *unlock_err;
2171 f21ec2f0 2020-03-21 stsp struct got_reflist_head my_refs;
2172 f21ec2f0 2020-03-21 stsp struct got_reflist_entry *re;
2173 f21ec2f0 2020-03-21 stsp struct got_pathlist_entry *pe;
2174 3789fd73 2020-03-26 stsp char *remote_namespace = NULL;
2175 3789fd73 2020-03-26 stsp char *local_refname = NULL;
2177 d9dff0e5 2020-12-26 stsp TAILQ_INIT(&my_refs);
2179 3789fd73 2020-03-26 stsp if (asprintf(&remote_namespace, "refs/remotes/%s/", remote->name)
2181 3789fd73 2020-03-26 stsp return got_error_from_errno("asprintf");
2183 f21ec2f0 2020-03-21 stsp err = got_ref_list(&my_refs, repo, NULL, got_ref_cmp_by_name, NULL);
2185 3789fd73 2020-03-26 stsp goto done;
2187 d9dff0e5 2020-12-26 stsp TAILQ_FOREACH(re, &my_refs, entry) {
2188 f21ec2f0 2020-03-21 stsp const char *refname = got_ref_get_name(re->ref);
2189 1b796c3f 2021-09-11 stsp const char *their_refname;
2191 1b796c3f 2021-09-11 stsp if (remote->mirror_references) {
2192 1b796c3f 2021-09-11 stsp their_refname = refname;
2194 3789fd73 2020-03-26 stsp if (strncmp(refname, remote_namespace,
2195 3789fd73 2020-03-26 stsp strlen(remote_namespace)) == 0) {
2196 3789fd73 2020-03-26 stsp if (strcmp(refname + strlen(remote_namespace),
2197 3789fd73 2020-03-26 stsp GOT_REF_HEAD) == 0)
2199 3789fd73 2020-03-26 stsp if (asprintf(&local_refname, "refs/heads/%s",
2200 3789fd73 2020-03-26 stsp refname + strlen(remote_namespace)) == -1) {
2201 3789fd73 2020-03-26 stsp err = got_error_from_errno("asprintf");
2202 3789fd73 2020-03-26 stsp goto done;
2204 3789fd73 2020-03-26 stsp } else if (strncmp(refname, "refs/tags/", 10) != 0)
2207 1b796c3f 2021-09-11 stsp their_refname = local_refname;
2210 f21ec2f0 2020-03-21 stsp TAILQ_FOREACH(pe, their_refs, entry) {
2211 1b796c3f 2021-09-11 stsp if (strcmp(their_refname, pe->path) == 0)
2214 f21ec2f0 2020-03-21 stsp if (pe != NULL)
2217 3789fd73 2020-03-26 stsp TAILQ_FOREACH(pe, their_symrefs, entry) {
2218 1b796c3f 2021-09-11 stsp if (strcmp(their_refname, pe->path) == 0)
2221 3789fd73 2020-03-26 stsp if (pe != NULL)
2224 3789fd73 2020-03-26 stsp err = delete_missing_ref(re->ref, verbosity, repo);
2228 3789fd73 2020-03-26 stsp if (local_refname) {
2229 3789fd73 2020-03-26 stsp struct got_reference *ref;
2230 3789fd73 2020-03-26 stsp err = got_ref_open(&ref, repo, local_refname, 1);
2231 3789fd73 2020-03-26 stsp if (err) {
2232 3789fd73 2020-03-26 stsp if (err->code != GOT_ERR_NOT_REF)
2234 3789fd73 2020-03-26 stsp free(local_refname);
2235 3789fd73 2020-03-26 stsp local_refname = NULL;
2238 3789fd73 2020-03-26 stsp err = delete_missing_ref(ref, verbosity, repo);
2241 3789fd73 2020-03-26 stsp unlock_err = got_ref_unlock(ref);
2242 3789fd73 2020-03-26 stsp got_ref_close(ref);
2243 3789fd73 2020-03-26 stsp if (unlock_err && err == NULL) {
2244 3789fd73 2020-03-26 stsp err = unlock_err;
2248 3789fd73 2020-03-26 stsp free(local_refname);
2249 3789fd73 2020-03-26 stsp local_refname = NULL;
2253 c639c920 2022-10-12 thomas got_ref_list_free(&my_refs);
2254 3789fd73 2020-03-26 stsp free(remote_namespace);
2255 3789fd73 2020-03-26 stsp free(local_refname);
2256 0e4002ca 2020-03-21 stsp return err;
2259 0e4002ca 2020-03-21 stsp static const struct got_error *
2260 0e4002ca 2020-03-21 stsp update_wanted_ref(const char *refname, struct got_object_id *id,
2261 0e4002ca 2020-03-21 stsp const char *remote_repo_name, int verbosity, struct got_repository *repo)
2263 9f142382 2020-03-21 stsp const struct got_error *err, *unlock_err;
2264 0e4002ca 2020-03-21 stsp char *remote_refname;
2265 0e4002ca 2020-03-21 stsp struct got_reference *ref;
2267 0e4002ca 2020-03-21 stsp if (strncmp("refs/", refname, 5) == 0)
2268 0e4002ca 2020-03-21 stsp refname += 5;
2270 0e4002ca 2020-03-21 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2271 0e4002ca 2020-03-21 stsp remote_repo_name, refname) == -1)
2272 0e4002ca 2020-03-21 stsp return got_error_from_errno("asprintf");
2274 9f142382 2020-03-21 stsp err = got_ref_open(&ref, repo, remote_refname, 1);
2275 0e4002ca 2020-03-21 stsp if (err) {
2276 0e4002ca 2020-03-21 stsp if (err->code != GOT_ERR_NOT_REF)
2277 0e4002ca 2020-03-21 stsp goto done;
2278 0e4002ca 2020-03-21 stsp err = create_ref(remote_refname, id, verbosity, repo);
2280 0e4002ca 2020-03-21 stsp err = update_ref(ref, id, 0, verbosity, repo);
2281 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2282 9f142382 2020-03-21 stsp if (unlock_err && err == NULL)
2283 9f142382 2020-03-21 stsp err = unlock_err;
2284 0e4002ca 2020-03-21 stsp got_ref_close(ref);
2287 0e4002ca 2020-03-21 stsp free(remote_refname);
2288 161728eb 2021-07-24 stsp return err;
2291 161728eb 2021-07-24 stsp static const struct got_error *
2292 161728eb 2021-07-24 stsp delete_ref(struct got_repository *repo, struct got_reference *ref)
2294 161728eb 2021-07-24 stsp const struct got_error *err = NULL;
2295 161728eb 2021-07-24 stsp struct got_object_id *id = NULL;
2296 161728eb 2021-07-24 stsp char *id_str = NULL;
2297 161728eb 2021-07-24 stsp const char *target;
2299 161728eb 2021-07-24 stsp if (got_ref_is_symbolic(ref)) {
2300 161728eb 2021-07-24 stsp target = got_ref_get_symref_target(ref);
2302 161728eb 2021-07-24 stsp err = got_ref_resolve(&id, repo, ref);
2304 161728eb 2021-07-24 stsp goto done;
2305 161728eb 2021-07-24 stsp err = got_object_id_str(&id_str, id);
2307 161728eb 2021-07-24 stsp goto done;
2308 161728eb 2021-07-24 stsp target = id_str;
2311 161728eb 2021-07-24 stsp err = got_ref_delete(ref, repo);
2313 161728eb 2021-07-24 stsp goto done;
2315 161728eb 2021-07-24 stsp printf("Deleted %s: %s\n", got_ref_get_name(ref), target);
2318 161728eb 2021-07-24 stsp free(id_str);
2319 f21ec2f0 2020-03-21 stsp return err;
2322 f21ec2f0 2020-03-21 stsp static const struct got_error *
2323 161728eb 2021-07-24 stsp delete_refs_for_remote(struct got_repository *repo, const char *remote_name)
2325 161728eb 2021-07-24 stsp const struct got_error *err = NULL;
2326 161728eb 2021-07-24 stsp struct got_reflist_head refs;
2327 161728eb 2021-07-24 stsp struct got_reflist_entry *re;
2328 161728eb 2021-07-24 stsp char *prefix;
2330 161728eb 2021-07-24 stsp TAILQ_INIT(&refs);
2332 161728eb 2021-07-24 stsp if (asprintf(&prefix, "refs/remotes/%s", remote_name) == -1) {
2333 161728eb 2021-07-24 stsp err = got_error_from_errno("asprintf");
2334 161728eb 2021-07-24 stsp goto done;
2336 161728eb 2021-07-24 stsp err = got_ref_list(&refs, repo, prefix, got_ref_cmp_by_name, NULL);
2338 161728eb 2021-07-24 stsp goto done;
2340 161728eb 2021-07-24 stsp TAILQ_FOREACH(re, &refs, entry)
2341 161728eb 2021-07-24 stsp delete_ref(repo, re->ref);
2343 161728eb 2021-07-24 stsp got_ref_list_free(&refs);
2344 161728eb 2021-07-24 stsp return err;
2347 161728eb 2021-07-24 stsp static const struct got_error *
2348 7848a0e1 2020-03-19 stsp cmd_fetch(int argc, char *argv[])
2350 9f142382 2020-03-21 stsp const struct got_error *error = NULL, *unlock_err;
2351 7848a0e1 2020-03-19 stsp char *cwd = NULL, *repo_path = NULL;
2352 7848a0e1 2020-03-19 stsp const char *remote_name;
2353 7848a0e1 2020-03-19 stsp char *proto = NULL, *host = NULL, *port = NULL;
2354 7848a0e1 2020-03-19 stsp char *repo_name = NULL, *server_path = NULL;
2355 11024cb9 2023-09-05 thomas const struct got_remote_repo *remotes;
2356 11024cb9 2023-09-05 thomas struct got_remote_repo *remote = NULL;
2357 7848a0e1 2020-03-19 stsp int nremotes;
2358 7848a0e1 2020-03-19 stsp char *id_str = NULL;
2359 7848a0e1 2020-03-19 stsp struct got_repository *repo = NULL;
2360 7848a0e1 2020-03-19 stsp struct got_worktree *worktree = NULL;
2361 50b0790e 2020-09-11 stsp const struct got_gotconfig *repo_conf = NULL, *worktree_conf = NULL;
2362 0e4002ca 2020-03-21 stsp struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
2363 23668511 2023-09-05 thomas char *head_refname = NULL;
2364 7848a0e1 2020-03-19 stsp struct got_pathlist_entry *pe;
2365 7abf1863 2023-02-20 thomas struct got_reflist_head remote_refs;
2366 7abf1863 2023-02-20 thomas struct got_reflist_entry *re;
2367 7848a0e1 2020-03-19 stsp struct got_object_id *pack_hash = NULL;
2368 9c52365f 2020-03-21 stsp int i, ch, fetchfd = -1, fetchstatus;
2369 9c52365f 2020-03-21 stsp pid_t fetchpid = -1;
2370 7848a0e1 2020-03-19 stsp struct got_fetch_progress_arg fpa;
2371 41b0de12 2020-03-21 stsp int verbosity = 0, fetch_all_branches = 0, list_refs_only = 0;
2372 161728eb 2021-07-24 stsp int delete_refs = 0, replace_tags = 0, delete_remote = 0;
2373 9d0a7ee3 2023-02-07 thomas int *pack_fds = NULL, have_bflag = 0;
2374 7abf1863 2023-02-20 thomas const char *remote_head = NULL, *worktree_branch = NULL;
2376 7848a0e1 2020-03-19 stsp TAILQ_INIT(&refs);
2377 7848a0e1 2020-03-19 stsp TAILQ_INIT(&symrefs);
2378 7abf1863 2023-02-20 thomas TAILQ_INIT(&remote_refs);
2379 4ba14133 2020-03-20 stsp TAILQ_INIT(&wanted_branches);
2380 0e4002ca 2020-03-21 stsp TAILQ_INIT(&wanted_refs);
2382 f7065961 2022-10-27 thomas while ((ch = getopt(argc, argv, "ab:dlqR:r:tvX")) != -1) {
2383 7848a0e1 2020-03-19 stsp switch (ch) {
2385 659e7fbd 2020-03-20 stsp fetch_all_branches = 1;
2388 4ba14133 2020-03-20 stsp error = got_pathlist_append(&wanted_branches,
2389 4ba14133 2020-03-20 stsp optarg, NULL);
2390 4ba14133 2020-03-20 stsp if (error)
2391 4ba14133 2020-03-20 stsp return error;
2392 9d0a7ee3 2023-02-07 thomas have_bflag = 1;
2395 f21ec2f0 2020-03-21 stsp delete_refs = 1;
2398 41b0de12 2020-03-21 stsp list_refs_only = 1;
2400 f7065961 2022-10-27 thomas case 'q':
2401 f7065961 2022-10-27 thomas verbosity = -1;
2403 f7065961 2022-10-27 thomas case 'R':
2404 f7065961 2022-10-27 thomas error = got_pathlist_append(&wanted_refs,
2405 f7065961 2022-10-27 thomas optarg, NULL);
2406 f7065961 2022-10-27 thomas if (error)
2407 f7065961 2022-10-27 thomas return error;
2410 7848a0e1 2020-03-19 stsp repo_path = realpath(optarg, NULL);
2411 7848a0e1 2020-03-19 stsp if (repo_path == NULL)
2412 7848a0e1 2020-03-19 stsp return got_error_from_errno2("realpath",
2414 7848a0e1 2020-03-19 stsp got_path_strip_trailing_slashes(repo_path);
2417 db6d8ad8 2020-03-21 stsp replace_tags = 1;
2420 7848a0e1 2020-03-19 stsp if (verbosity < 0)
2421 7848a0e1 2020-03-19 stsp verbosity = 0;
2422 7848a0e1 2020-03-19 stsp else if (verbosity < 3)
2423 7848a0e1 2020-03-19 stsp verbosity++;
2426 161728eb 2021-07-24 stsp delete_remote = 1;
2429 7848a0e1 2020-03-19 stsp usage_fetch();
2433 7848a0e1 2020-03-19 stsp argc -= optind;
2434 7848a0e1 2020-03-19 stsp argv += optind;
2436 4ba14133 2020-03-20 stsp if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
2437 ff69268e 2020-12-13 stsp option_conflict('a', 'b');
2438 41b0de12 2020-03-21 stsp if (list_refs_only) {
2439 41b0de12 2020-03-21 stsp if (!TAILQ_EMPTY(&wanted_branches))
2440 ff69268e 2020-12-13 stsp option_conflict('l', 'b');
2441 ff69268e 2020-12-13 stsp if (fetch_all_branches)
2442 ff69268e 2020-12-13 stsp option_conflict('l', 'a');
2443 f21ec2f0 2020-03-21 stsp if (delete_refs)
2444 ff69268e 2020-12-13 stsp option_conflict('l', 'd');
2445 161728eb 2021-07-24 stsp if (delete_remote)
2446 161728eb 2021-07-24 stsp option_conflict('l', 'X');
2448 161728eb 2021-07-24 stsp if (delete_remote) {
2449 161728eb 2021-07-24 stsp if (fetch_all_branches)
2450 161728eb 2021-07-24 stsp option_conflict('X', 'a');
2451 161728eb 2021-07-24 stsp if (!TAILQ_EMPTY(&wanted_branches))
2452 161728eb 2021-07-24 stsp option_conflict('X', 'b');
2453 161728eb 2021-07-24 stsp if (delete_refs)
2454 161728eb 2021-07-24 stsp option_conflict('X', 'd');
2455 161728eb 2021-07-24 stsp if (replace_tags)
2456 161728eb 2021-07-24 stsp option_conflict('X', 't');
2457 161728eb 2021-07-24 stsp if (!TAILQ_EMPTY(&wanted_refs))
2458 161728eb 2021-07-24 stsp option_conflict('X', 'R');
2461 161728eb 2021-07-24 stsp if (argc == 0) {
2462 161728eb 2021-07-24 stsp if (delete_remote)
2463 161728eb 2021-07-24 stsp errx(1, "-X option requires a remote name");
2464 7848a0e1 2020-03-19 stsp remote_name = GOT_FETCH_DEFAULT_REMOTE_NAME;
2465 161728eb 2021-07-24 stsp } else if (argc == 1)
2466 7848a0e1 2020-03-19 stsp remote_name = argv[0];
2468 7848a0e1 2020-03-19 stsp usage_fetch();
2470 7848a0e1 2020-03-19 stsp cwd = getcwd(NULL, 0);
2471 7848a0e1 2020-03-19 stsp if (cwd == NULL) {
2472 7848a0e1 2020-03-19 stsp error = got_error_from_errno("getcwd");
2473 7848a0e1 2020-03-19 stsp goto done;
2476 7cd52833 2022-06-23 thomas error = got_repo_pack_fds_open(&pack_fds);
2477 7cd52833 2022-06-23 thomas if (error != NULL)
2478 7cd52833 2022-06-23 thomas goto done;
2480 7848a0e1 2020-03-19 stsp if (repo_path == NULL) {
2481 ad10f64e 2023-07-19 thomas error = got_worktree_open(&worktree, cwd, GOT_WORKTREE_GOT_DIR);
2482 7848a0e1 2020-03-19 stsp if (error && error->code != GOT_ERR_NOT_WORKTREE)
2483 7848a0e1 2020-03-19 stsp goto done;
2485 7848a0e1 2020-03-19 stsp error = NULL;
2486 7848a0e1 2020-03-19 stsp if (worktree) {
2487 7848a0e1 2020-03-19 stsp repo_path =
2488 7848a0e1 2020-03-19 stsp strdup(got_worktree_get_repo_path(worktree));
2489 7848a0e1 2020-03-19 stsp if (repo_path == NULL)
2490 7848a0e1 2020-03-19 stsp error = got_error_from_errno("strdup");
2491 7848a0e1 2020-03-19 stsp if (error)
2492 7848a0e1 2020-03-19 stsp goto done;
2494 7848a0e1 2020-03-19 stsp repo_path = strdup(cwd);
2495 7848a0e1 2020-03-19 stsp if (repo_path == NULL) {
2496 7848a0e1 2020-03-19 stsp error = got_error_from_errno("strdup");
2497 7848a0e1 2020-03-19 stsp goto done;
2502 7cd52833 2022-06-23 thomas error = got_repo_open(&repo, repo_path, NULL, pack_fds);
2503 7848a0e1 2020-03-19 stsp if (error)
2504 7848a0e1 2020-03-19 stsp goto done;
2506 161728eb 2021-07-24 stsp if (delete_remote) {
2507 161728eb 2021-07-24 stsp error = delete_refs_for_remote(repo, remote_name);
2508 161728eb 2021-07-24 stsp goto done; /* nothing else to do */
2511 50b0790e 2020-09-11 stsp if (worktree) {
2512 50b0790e 2020-09-11 stsp worktree_conf = got_worktree_get_gotconfig(worktree);
2513 50b0790e 2020-09-11 stsp if (worktree_conf) {
2514 50b0790e 2020-09-11 stsp got_gotconfig_get_remotes(&nremotes, &remotes,
2515 50b0790e 2020-09-11 stsp worktree_conf);
2516 50b0790e 2020-09-11 stsp for (i = 0; i < nremotes; i++) {
2517 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2518 11024cb9 2023-09-05 thomas error = got_repo_remote_repo_dup(&remote,
2519 11024cb9 2023-09-05 thomas &remotes[i]);
2520 11024cb9 2023-09-05 thomas if (error)
2521 11024cb9 2023-09-05 thomas goto done;
2527 50b0790e 2020-09-11 stsp if (remote == NULL) {
2528 50b0790e 2020-09-11 stsp repo_conf = got_repo_get_gotconfig(repo);
2529 50b0790e 2020-09-11 stsp if (repo_conf) {
2530 50b0790e 2020-09-11 stsp got_gotconfig_get_remotes(&nremotes, &remotes,
2531 50b0790e 2020-09-11 stsp repo_conf);
2532 50b0790e 2020-09-11 stsp for (i = 0; i < nremotes; i++) {
2533 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2534 11024cb9 2023-09-05 thomas error = got_repo_remote_repo_dup(&remote,
2535 11024cb9 2023-09-05 thomas &remotes[i]);
2536 11024cb9 2023-09-05 thomas if (error)
2537 11024cb9 2023-09-05 thomas goto done;
2543 50b0790e 2020-09-11 stsp if (remote == NULL) {
2544 257add31 2020-09-09 stsp got_repo_get_gitconfig_remotes(&nremotes, &remotes, repo);
2545 257add31 2020-09-09 stsp for (i = 0; i < nremotes; i++) {
2546 54eb00d5 2020-10-20 stsp if (strcmp(remotes[i].name, remote_name) == 0) {
2547 11024cb9 2023-09-05 thomas error = got_repo_remote_repo_dup(&remote,
2548 11024cb9 2023-09-05 thomas &remotes[i]);
2549 11024cb9 2023-09-05 thomas if (error)
2550 11024cb9 2023-09-05 thomas goto done;
2555 50b0790e 2020-09-11 stsp if (remote == NULL) {
2556 50b0790e 2020-09-11 stsp error = got_error_path(remote_name, GOT_ERR_NO_REMOTE);
2557 50b0790e 2020-09-11 stsp goto done;
2560 0c8b29c5 2021-01-05 stsp if (TAILQ_EMPTY(&wanted_branches)) {
2561 0c8b29c5 2021-01-05 stsp if (!fetch_all_branches)
2562 0c8b29c5 2021-01-05 stsp fetch_all_branches = remote->fetch_all_branches;
2563 6480c871 2021-08-30 stsp for (i = 0; i < remote->nfetch_branches; i++) {
2564 c0ce8a2b 2023-01-14 thomas error = got_pathlist_append(&wanted_branches,
2565 6480c871 2021-08-30 stsp remote->fetch_branches[i], NULL);
2566 8d0dceb3 2023-02-07 thomas if (error)
2567 8d0dceb3 2023-02-07 thomas goto done;
2570 99495ddb 2021-01-10 stsp if (TAILQ_EMPTY(&wanted_refs)) {
2571 6480c871 2021-08-30 stsp for (i = 0; i < remote->nfetch_refs; i++) {
2572 c0ce8a2b 2023-01-14 thomas error = got_pathlist_append(&wanted_refs,
2573 6480c871 2021-08-30 stsp remote->fetch_refs[i], NULL);
2574 c0ce8a2b 2023-01-14 thomas if (error)
2575 c0ce8a2b 2023-01-14 thomas goto done;
2579 5e5da8c4 2021-09-05 stsp error = got_dial_parse_uri(&proto, &host, &port, &server_path,
2580 6480c871 2021-08-30 stsp &repo_name, remote->fetch_url);
2581 7848a0e1 2020-03-19 stsp if (error)
2582 7848a0e1 2020-03-19 stsp goto done;
2584 7848a0e1 2020-03-19 stsp if (strcmp(proto, "git") == 0) {
2585 7848a0e1 2020-03-19 stsp #ifndef PROFILE
2586 7848a0e1 2020-03-19 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2587 7848a0e1 2020-03-19 stsp "sendfd dns inet unveil", NULL) == -1)
2588 7848a0e1 2020-03-19 stsp err(1, "pledge");
2590 7848a0e1 2020-03-19 stsp } else if (strcmp(proto, "git+ssh") == 0 ||
2591 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "ssh") == 0 ||
2592 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "git+http") == 0 ||
2593 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "http") == 0 ||
2594 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "git+https") == 0 ||
2595 37e7d69e 2024-04-25 thomas.ad strcmp(proto, "https") == 0) {
2596 7848a0e1 2020-03-19 stsp #ifndef PROFILE
2597 7848a0e1 2020-03-19 stsp if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2598 7848a0e1 2020-03-19 stsp "sendfd unveil", NULL) == -1)
2599 7848a0e1 2020-03-19 stsp err(1, "pledge");
2602 7848a0e1 2020-03-19 stsp error = got_error_path(proto, GOT_ERR_BAD_PROTO);
2603 7848a0e1 2020-03-19 stsp goto done;
2606 d65a88a2 2021-09-05 stsp error = got_dial_apply_unveil(proto);
2607 d65a88a2 2021-09-05 stsp if (error)
2608 d65a88a2 2021-09-05 stsp goto done;
2610 7848a0e1 2020-03-19 stsp error = apply_unveil(got_repo_get_path(repo), 0, NULL);
2611 7848a0e1 2020-03-19 stsp if (error)
2612 7848a0e1 2020-03-19 stsp goto done;
2614 23668511 2023-09-05 thomas if (worktree) {
2615 23668511 2023-09-05 thomas head_refname = strdup(got_worktree_get_head_ref_name(worktree));
2616 23668511 2023-09-05 thomas if (head_refname == NULL) {
2617 23668511 2023-09-05 thomas error = got_error_from_errno("strdup");
2618 23668511 2023-09-05 thomas goto done;
2621 23668511 2023-09-05 thomas /* Release work tree lock. */
2622 23668511 2023-09-05 thomas got_worktree_close(worktree);
2623 23668511 2023-09-05 thomas worktree = NULL;
2626 6df5d941 2022-11-18 thomas if (verbosity >= 0) {
2627 6df5d941 2022-11-18 thomas printf("Connecting to \"%s\" %s://%s%s%s%s%s\n",
2628 6df5d941 2022-11-18 thomas remote->name, proto, host,
2629 6df5d941 2022-11-18 thomas port ? ":" : "", port ? port : "",
2630 6df5d941 2022-11-18 thomas *server_path == '/' ? "" : "/", server_path);
2633 9c52365f 2020-03-21 stsp error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
2634 9c52365f 2020-03-21 stsp server_path, verbosity);
2635 7848a0e1 2020-03-19 stsp if (error)
2636 7848a0e1 2020-03-19 stsp goto done;
2637 a6955b87 2024-04-25 thomas.ad #ifndef PROFILE
2638 a6955b87 2024-04-25 thomas.ad if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd",
2639 a6955b87 2024-04-25 thomas.ad NULL) == -1)
2640 a6955b87 2024-04-25 thomas.ad err(1, "pledge");
2641 a6955b87 2024-04-25 thomas.ad #endif
2642 7abf1863 2023-02-20 thomas if (!have_bflag) {
2644 7abf1863 2023-02-20 thomas * If set, get this remote's HEAD ref target so
2645 7abf1863 2023-02-20 thomas * if it has changed on the server we can fetch it.
2647 7abf1863 2023-02-20 thomas error = got_ref_list(&remote_refs, repo, "refs/remotes",
2648 7abf1863 2023-02-20 thomas got_ref_cmp_by_name, repo);
2649 7abf1863 2023-02-20 thomas if (error)
2650 7abf1863 2023-02-20 thomas goto done;
2652 7abf1863 2023-02-20 thomas TAILQ_FOREACH(re, &remote_refs, entry) {
2653 7abf1863 2023-02-20 thomas const char *remote_refname, *remote_target;
2654 7abf1863 2023-02-20 thomas size_t remote_name_len;
2656 7abf1863 2023-02-20 thomas if (!got_ref_is_symbolic(re->ref))
2657 7abf1863 2023-02-20 thomas continue;
2659 7abf1863 2023-02-20 thomas remote_name_len = strlen(remote->name);
2660 7abf1863 2023-02-20 thomas remote_refname = got_ref_get_name(re->ref);
2662 7abf1863 2023-02-20 thomas /* we only want refs/remotes/$remote->name/HEAD */
2663 7abf1863 2023-02-20 thomas if (strncmp(remote_refname + 13, remote->name,
2664 7abf1863 2023-02-20 thomas remote_name_len) != 0)
2665 7abf1863 2023-02-20 thomas continue;
2667 7abf1863 2023-02-20 thomas if (strcmp(remote_refname + remote_name_len + 14,
2668 7abf1863 2023-02-20 thomas GOT_REF_HEAD) != 0)
2669 7abf1863 2023-02-20 thomas continue;
2672 7abf1863 2023-02-20 thomas * Take the name itself because we already
2673 7abf1863 2023-02-20 thomas * only match with refs/heads/ in fetch_pack().
2675 7abf1863 2023-02-20 thomas remote_target = got_ref_get_symref_target(re->ref);
2676 7abf1863 2023-02-20 thomas remote_head = remote_target + remote_name_len + 14;
2680 23668511 2023-09-05 thomas if (head_refname &&
2681 23668511 2023-09-05 thomas strncmp(head_refname, "refs/heads/", 11) == 0)
2682 23668511 2023-09-05 thomas worktree_branch = head_refname;
2685 7848a0e1 2020-03-19 stsp fpa.last_scaled_size[0] = '\0';
2686 7848a0e1 2020-03-19 stsp fpa.last_p_indexed = -1;
2687 7848a0e1 2020-03-19 stsp fpa.last_p_resolved = -1;
2688 7848a0e1 2020-03-19 stsp fpa.verbosity = verbosity;
2689 04d9a9ec 2020-09-24 stsp fpa.repo = repo;
2690 04d9a9ec 2020-09-24 stsp fpa.create_configs = 0;
2691 04d9a9ec 2020-09-24 stsp fpa.configs_created = 0;
2692 04d9a9ec 2020-09-24 stsp memset(&fpa.config_info, 0, sizeof(fpa.config_info));
2694 7848a0e1 2020-03-19 stsp error = got_fetch_pack(&pack_hash, &refs, &symrefs, remote->name,
2695 4ba14133 2020-03-20 stsp remote->mirror_references, fetch_all_branches, &wanted_branches,
2696 0e4002ca 2020-03-21 stsp &wanted_refs, list_refs_only, verbosity, fetchfd, repo,
2697 7abf1863 2023-02-20 thomas worktree_branch, remote_head, have_bflag, fetch_progress, &fpa);
2698 7848a0e1 2020-03-19 stsp if (error)
2699 7848a0e1 2020-03-19 stsp goto done;
2701 41b0de12 2020-03-21 stsp if (list_refs_only) {
2702 41b0de12 2020-03-21 stsp error = list_remote_refs(&symrefs, &refs);
2703 41b0de12 2020-03-21 stsp goto done;
2706 7848a0e1 2020-03-19 stsp if (pack_hash == NULL) {
2707 7848a0e1 2020-03-19 stsp if (verbosity >= 0)
2708 7848a0e1 2020-03-19 stsp printf("Already up-to-date\n");
2709 bcf34b0e 2020-03-26 stsp } else if (verbosity >= 0) {
2710 984065c8 2020-03-19 stsp error = got_object_id_str(&id_str, pack_hash);
2711 984065c8 2020-03-19 stsp if (error)
2712 984065c8 2020-03-19 stsp goto done;
2713 e69674d8 2020-03-19 stsp printf("\nFetched %s.pack\n", id_str);
2714 984065c8 2020-03-19 stsp free(id_str);
2715 984065c8 2020-03-19 stsp id_str = NULL;
2718 7848a0e1 2020-03-19 stsp /* Update references provided with the pack file. */
2719 7848a0e1 2020-03-19 stsp TAILQ_FOREACH(pe, &refs, entry) {
2720 7848a0e1 2020-03-19 stsp const char *refname = pe->path;
2721 7848a0e1 2020-03-19 stsp struct got_object_id *id = pe->data;
2722 7848a0e1 2020-03-19 stsp struct got_reference *ref;
2723 7848a0e1 2020-03-19 stsp char *remote_refname;
2725 0e4002ca 2020-03-21 stsp if (is_wanted_ref(&wanted_refs, refname) &&
2726 0e4002ca 2020-03-21 stsp !remote->mirror_references) {
2727 0e4002ca 2020-03-21 stsp error = update_wanted_ref(refname, id,
2728 0e4002ca 2020-03-21 stsp remote->name, verbosity, repo);
2729 0e4002ca 2020-03-21 stsp if (error)
2730 0e4002ca 2020-03-21 stsp goto done;
2734 1510c839 2020-03-20 stsp if (remote->mirror_references ||
2735 1510c839 2020-03-20 stsp strncmp("refs/tags/", refname, 10) == 0) {
2736 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, refname, 1);
2737 7848a0e1 2020-03-19 stsp if (error) {
2738 7848a0e1 2020-03-19 stsp if (error->code != GOT_ERR_NOT_REF)
2739 7848a0e1 2020-03-19 stsp goto done;
2740 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity,
2742 7848a0e1 2020-03-19 stsp if (error)
2743 7848a0e1 2020-03-19 stsp goto done;
2745 db6d8ad8 2020-03-21 stsp error = update_ref(ref, id, replace_tags,
2746 db6d8ad8 2020-03-21 stsp verbosity, repo);
2747 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2748 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2749 9f142382 2020-03-21 stsp error = unlock_err;
2750 7848a0e1 2020-03-19 stsp got_ref_close(ref);
2751 7848a0e1 2020-03-19 stsp if (error)
2752 7848a0e1 2020-03-19 stsp goto done;
2754 7848a0e1 2020-03-19 stsp } else if (strncmp("refs/heads/", refname, 11) == 0) {
2755 7848a0e1 2020-03-19 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2756 7848a0e1 2020-03-19 stsp remote_name, refname + 11) == -1) {
2757 7848a0e1 2020-03-19 stsp error = got_error_from_errno("asprintf");
2758 7848a0e1 2020-03-19 stsp goto done;
2761 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, remote_refname, 1);
2762 7848a0e1 2020-03-19 stsp if (error) {
2763 7848a0e1 2020-03-19 stsp if (error->code != GOT_ERR_NOT_REF)
2764 7848a0e1 2020-03-19 stsp goto done;
2765 b6b86fd1 2022-08-30 thomas error = create_ref(remote_refname, id,
2766 688f11b3 2020-03-21 stsp verbosity, repo);
2767 7848a0e1 2020-03-19 stsp if (error)
2768 7848a0e1 2020-03-19 stsp goto done;
2770 db6d8ad8 2020-03-21 stsp error = update_ref(ref, id, replace_tags,
2771 db6d8ad8 2020-03-21 stsp verbosity, repo);
2772 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2773 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2774 9f142382 2020-03-21 stsp error = unlock_err;
2775 7848a0e1 2020-03-19 stsp got_ref_close(ref);
2776 7848a0e1 2020-03-19 stsp if (error)
2777 7848a0e1 2020-03-19 stsp goto done;
2780 2ec30c80 2020-03-20 stsp /* Also create a local branch if none exists yet. */
2781 9f142382 2020-03-21 stsp error = got_ref_open(&ref, repo, refname, 1);
2782 2ec30c80 2020-03-20 stsp if (error) {
2783 2ec30c80 2020-03-20 stsp if (error->code != GOT_ERR_NOT_REF)
2784 2ec30c80 2020-03-20 stsp goto done;
2785 6338a6a1 2020-03-21 stsp error = create_ref(refname, id, verbosity,
2787 2ec30c80 2020-03-20 stsp if (error)
2788 2ec30c80 2020-03-20 stsp goto done;
2790 9f142382 2020-03-21 stsp unlock_err = got_ref_unlock(ref);
2791 9f142382 2020-03-21 stsp if (unlock_err && error == NULL)
2792 9f142382 2020-03-21 stsp error = unlock_err;
2793 2ec30c80 2020-03-20 stsp got_ref_close(ref);
2797 f1bcca34 2020-03-25 stsp if (delete_refs) {
2798 3789fd73 2020-03-26 stsp error = delete_missing_refs(&refs, &symrefs, remote,
2799 3789fd73 2020-03-26 stsp verbosity, repo);
2800 f1bcca34 2020-03-25 stsp if (error)
2801 f1bcca34 2020-03-25 stsp goto done;
2804 f1bcca34 2020-03-25 stsp if (!remote->mirror_references) {
2805 f1bcca34 2020-03-25 stsp /* Update remote HEAD reference if the server provided one. */
2806 f1bcca34 2020-03-25 stsp TAILQ_FOREACH(pe, &symrefs, entry) {
2807 f1bcca34 2020-03-25 stsp struct got_reference *target_ref;
2808 f1bcca34 2020-03-25 stsp const char *refname = pe->path;
2809 f1bcca34 2020-03-25 stsp const char *target = pe->data;
2810 f1bcca34 2020-03-25 stsp char *remote_refname = NULL, *remote_target = NULL;
2812 f1bcca34 2020-03-25 stsp if (strcmp(refname, GOT_REF_HEAD) != 0)
2815 f1bcca34 2020-03-25 stsp if (strncmp("refs/heads/", target, 11) != 0)
2818 f1bcca34 2020-03-25 stsp if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2819 f1bcca34 2020-03-25 stsp remote->name, refname) == -1) {
2820 f1bcca34 2020-03-25 stsp error = got_error_from_errno("asprintf");
2821 f1bcca34 2020-03-25 stsp goto done;
2823 f1bcca34 2020-03-25 stsp if (asprintf(&remote_target, "refs/remotes/%s/%s",
2824 f1bcca34 2020-03-25 stsp remote->name, target + 11) == -1) {
2825 f1bcca34 2020-03-25 stsp error = got_error_from_errno("asprintf");
2826 f1bcca34 2020-03-25 stsp free(remote_refname);
2827 f1bcca34 2020-03-25 stsp goto done;
2830 f1bcca34 2020-03-25 stsp error = got_ref_open(&target_ref, repo, remote_target,
2832 f1bcca34 2020-03-25 stsp if (error) {
2833 f1bcca34 2020-03-25 stsp free(remote_refname);
2834 f1bcca34 2020-03-25 stsp free(remote_target);
2835 f1bcca34 2020-03-25 stsp if (error->code == GOT_ERR_NOT_REF) {
2836 f1bcca34 2020-03-25 stsp error = NULL;
2839 f1bcca34 2020-03-25 stsp goto done;
2841 f1bcca34 2020-03-25 stsp error = update_symref(remote_refname, target_ref,
2842 f1bcca34 2020-03-25 stsp verbosity, repo);
2843 f1bcca34 2020-03-25 stsp free(remote_refname);
2844 f1bcca34 2020-03-25 stsp free(remote_target);
2845 f1bcca34 2020-03-25 stsp got_ref_close(target_ref);
2846 f1bcca34 2020-03-25 stsp if (error)
2847 f1bcca34 2020-03-25 stsp goto done;
2851 9c52365f 2020-03-21 stsp if (fetchpid > 0) {
2852 9c52365f 2020-03-21 stsp if (kill(fetchpid, SIGTERM) == -1)
2853 9c52365f 2020-03-21 stsp error = got_error_from_errno("kill");
2854 9c52365f 2020-03-21 stsp if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
2855 9c52365f 2020-03-21 stsp error = got_error_from_errno("waitpid");
2857 7848a0e1 2020-03-19 stsp if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
2858 7848a0e1 2020-03-19 stsp error = got_error_from_errno("close");
2859 1d0f4054 2021-06-17 stsp if (repo) {
2860 1d0f4054 2021-06-17 stsp const struct got_error *close_err = got_repo_close(repo);
2861 1d0f4054 2021-06-17 stsp if (error == NULL)
2862 1d0f4054 2021-06-17 stsp error = close_err;
2864 7848a0e1 2020-03-19 stsp if (worktree)
2865 7848a0e1 2020-03-19 stsp got_worktree_close(worktree);
2866 7cd52833 2022-06-23 thomas if (pack_fds) {
2867 7cd52833 2022-06-23 thomas const struct got_error *pack_err =
2868 7cd52833 2022-06-23 thomas got_repo_pack_fds_close(pack_fds);
2869 7cd52833 2022-06-23 thomas if (error == NULL)
2870 7cd52833 2022-06-23 thomas error = pack_err;
2872 21c2d8be 2023-01-10 thomas got_pathlist_free(&refs, GOT_PATHLIST_FREE_ALL);
2873 21c2d8be 2023-01-10 thomas got_pathlist_free(&symrefs, GOT_PATHLIST_FREE_ALL);
2874 21c2d8be 2023-01-10 thomas got_pathlist_free(&wanted_branches, GOT_PATHLIST_FREE_NONE);
2875 21c2d8be 2023-01-10 thomas got_pathlist_free(&wanted_refs, GOT_PATHLIST_FREE_NONE);
2876 7abf1863 2023-02-20 thomas got_ref_list_free(&remote_refs);
2877 11024cb9 2023-09-05 thomas got_repo_free_remote_repo_data(remote);
2878 11024cb9 2023-09-05 thomas free(remote);
2879 23668511 2023-09-05 thomas free(head_refname);
2880 7848a0e1 2020-03-19 stsp free(id_str);
2881 7848a0e1 2020-03-19 stsp free(cwd);
2882 7848a0e1 2020-03-19 stsp free(repo_path);
2883 7848a0e1 2020-03-19 stsp free(pack_hash);
2884 7848a0e1 2020-03-19 stsp free(proto);
2885 7848a0e1 2020-03-19 stsp free(host);
2886 7848a0e1 2020-03-19 stsp free(port);
2887 7848a0e1 2020-03-19 stsp free(server_path);
2888 7848a0e1 2020-03-19 stsp free(repo_name);
2889 7848a0e1 2020-03-19 stsp return error;
2893 7848a0e1 2020-03-19 stsp __dead static void
2894 2ab43947 2020-03-18 stsp usage_checkout(void)
2896 d6506a3d 2022-08-16 thomas fprintf(stderr, "usage: %s checkout [-Eq] [-b branch] [-c commit] "
2897 d6506a3d 2022-08-16 thomas "[-p path-prefix] repository-path [work-tree-path]\n",
2898 4ad4a1ec 2021-09-13 tracey getprogname());
2902 2ab43947 2020-03-18 stsp static void
2903 2ab43947 2020-03-18 stsp show_worktree_base_ref_warning(void)
2905 2ab43947 2020-03-18 stsp fprintf(stderr, "%s: warning: could not create a reference "
2906 2ab43947 2020-03-18 stsp "to the work tree's base commit; the commit could be "
2907 e6786710 2021-07-03 stsp "garbage-collected by Git or 'gotadmin cleanup'; making the "
2908 e6786710 2021-07-03 stsp "repository writable and running 'got update' will prevent this\n",
2909 2ab43947 2020-03-18 stsp getprogname());
2912 2ab43947 2020-03-18 stsp struct got_checkout_progress_arg {
2913 2ab43947 2020-03-18 stsp const char *worktree_path;
2914 2ab43947 2020-03-18 stsp int had_base_commit_ref_error;
2915 4ad4a1ec 2021-09-13 tracey int verbosity;
2918 2ab43947 2020-03-18 stsp static const struct got_error *
2919 2ab43947 2020-03-18 stsp checkout_progress(void *arg, unsigned char status, const char *path)
2921 2ab43947 2020-03-18 stsp struct got_checkout_progress_arg *a = arg;
2923 2ab43947 2020-03-18 stsp /* Base commit bump happens silently. */
2924 2ab43947 2020-03-18 stsp if (status == GOT_STATUS_BUMP_BASE)
2925 2ab43947 2020-03-18 stsp return NULL;
2927 2ab43947 2020-03-18 stsp if (status == GOT_STATUS_BASE_REF_ERR) {
2928 2ab43947 2020-03-18 stsp a->had_base_commit_ref_error = 1;
2929 2ab43947 2020-03-18 stsp return NULL;
2932 2ab43947 2020-03-18 stsp while (path[0] == '/')
2935 4ad4a1ec 2021-09-13 tracey if (a->verbosity >= 0)
2936 4ad4a1ec 2021-09-13 tracey printf("%c %s/%s\n", status, a->worktree_path, path);
2938 2ab43947 2020-03-18 stsp return NULL;
2941 2ab43947 2020-03-18 stsp static const struct got_error *
2942 2ab43947 2020-03-18 stsp check_cancelled(void *arg)
2944 2ab43947 2020-03-18 stsp if (sigint_received || sigpipe_received)
2945 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_CANCELLED);
2946 2ab43947 2020-03-18 stsp return NULL;
2949 2ab43947 2020-03-18 stsp static const struct got_error *
2950 2ab43947 2020-03-18 stsp check_linear_ancestry(struct got_object_id *commit_id,
2951 2ab43947 2020-03-18 stsp struct got_object_id *base_commit_id, int allow_forwards_in_time_only,
2952 2ab43947 2020-03-18 stsp struct got_repository *repo)
2954 2ab43947 2020-03-18 stsp const struct got_error *err = NULL;
2955 2ab43947 2020-03-18 stsp struct got_object_id *yca_id;
2957 2ab43947 2020-03-18 stsp err = got_commit_graph_find_youngest_common_ancestor(&yca_id,
2958 807c60e9 2024-03-30 thomas commit_id, base_commit_id, 1, 0, repo, check_cancelled, NULL);
2960 2ab43947 2020-03-18 stsp return err;
2962 2ab43947 2020-03-18 stsp if (yca_id == NULL)
2963 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2966 2ab43947 2020-03-18 stsp * Require a straight line of history between the target commit
2967 2ab43947 2020-03-18 stsp * and the work tree's base commit.
2969 2ab43947 2020-03-18 stsp * Non-linear situations such as this require a rebase:
2971 2ab43947 2020-03-18 stsp * (commit) D F (base_commit)
2979 2ab43947 2020-03-18 stsp * 'got update' only handles linear cases:
2980 2ab43947 2020-03-18 stsp * Update forwards in time: A (base/yca) - B - C - D (commit)
2981 2ab43947 2020-03-18 stsp * Update backwards in time: D (base) - C - B - A (commit/yca)
2983 2ab43947 2020-03-18 stsp if (allow_forwards_in_time_only) {
2984 2ab43947 2020-03-18 stsp if (got_object_id_cmp(base_commit_id, yca_id) != 0)
2985 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);
2986 2ab43947 2020-03-18 stsp } else if (got_object_id_cmp(commit_id, yca_id) != 0 &&
2987 2ab43947 2020-03-18 stsp got_object_id_cmp(base_commit_id, yca_id) != 0)
2988 2ab43947 2020-03-18 stsp return got_error(GOT_ERR_ANCESTRY);