Blame


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