run more tests in sha256 mode
[got.git] / got / got.c
blobeedba272792e095dfe5a62504a47e88c579c69c8
1 /*
2 * Copyright (c) 2017 Martin Pieuchot <mpi@openbsd.org>
3 * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
4 * Copyright (c) 2020 Ori Bernstein <ori@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/queue.h>
20 #include <sys/time.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/wait.h>
25 #include <err.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <limits.h>
29 #include <locale.h>
30 #include <ctype.h>
31 #include <sha1.h>
32 #include <sha2.h>
33 #include <signal.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <libgen.h>
39 #include <time.h>
40 #include <paths.h>
41 #include <regex.h>
42 #include <getopt.h>
43 #include <util.h>
45 #include "got_version.h"
46 #include "got_error.h"
47 #include "got_object.h"
48 #include "got_reference.h"
49 #include "got_repository.h"
50 #include "got_path.h"
51 #include "got_cancel.h"
52 #include "got_worktree.h"
53 #include "got_diff.h"
54 #include "got_commit_graph.h"
55 #include "got_fetch.h"
56 #include "got_send.h"
57 #include "got_blame.h"
58 #include "got_privsep.h"
59 #include "got_opentemp.h"
60 #include "got_gotconfig.h"
61 #include "got_dial.h"
62 #include "got_patch.h"
63 #include "got_sigs.h"
64 #include "got_date.h"
65 #include "got_keyword.h"
67 #ifndef nitems
68 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
69 #endif
71 #ifndef GOT_DEFAULT_EDITOR
72 #define GOT_DEFAULT_EDITOR "/usr/bin/vi"
73 #endif
75 static volatile sig_atomic_t sigint_received;
76 static volatile sig_atomic_t sigpipe_received;
78 static void
79 catch_sigint(int signo)
81 sigint_received = 1;
84 static void
85 catch_sigpipe(int signo)
87 sigpipe_received = 1;
91 struct got_cmd {
92 const char *cmd_name;
93 const struct got_error *(*cmd_main)(int, char *[]);
94 void (*cmd_usage)(void);
95 const char *cmd_alias;
98 __dead static void usage(int, int);
99 __dead static void usage_init(void);
100 __dead static void usage_import(void);
101 __dead static void usage_clone(void);
102 __dead static void usage_fetch(void);
103 __dead static void usage_checkout(void);
104 __dead static void usage_update(void);
105 __dead static void usage_log(void);
106 __dead static void usage_diff(void);
107 __dead static void usage_blame(void);
108 __dead static void usage_tree(void);
109 __dead static void usage_status(void);
110 __dead static void usage_ref(void);
111 __dead static void usage_branch(void);
112 __dead static void usage_tag(void);
113 __dead static void usage_add(void);
114 __dead static void usage_remove(void);
115 __dead static void usage_patch(void);
116 __dead static void usage_revert(void);
117 __dead static void usage_commit(void);
118 __dead static void usage_send(void);
119 __dead static void usage_cherrypick(void);
120 __dead static void usage_backout(void);
121 __dead static void usage_rebase(void);
122 __dead static void usage_histedit(void);
123 __dead static void usage_integrate(void);
124 __dead static void usage_merge(void);
125 __dead static void usage_stage(void);
126 __dead static void usage_unstage(void);
127 __dead static void usage_cat(void);
128 __dead static void usage_info(void);
130 static const struct got_error* cmd_init(int, char *[]);
131 static const struct got_error* cmd_import(int, char *[]);
132 static const struct got_error* cmd_clone(int, char *[]);
133 static const struct got_error* cmd_fetch(int, char *[]);
134 static const struct got_error* cmd_checkout(int, char *[]);
135 static const struct got_error* cmd_update(int, char *[]);
136 static const struct got_error* cmd_log(int, char *[]);
137 static const struct got_error* cmd_diff(int, char *[]);
138 static const struct got_error* cmd_blame(int, char *[]);
139 static const struct got_error* cmd_tree(int, char *[]);
140 static const struct got_error* cmd_status(int, char *[]);
141 static const struct got_error* cmd_ref(int, char *[]);
142 static const struct got_error* cmd_branch(int, char *[]);
143 static const struct got_error* cmd_tag(int, char *[]);
144 static const struct got_error* cmd_add(int, char *[]);
145 static const struct got_error* cmd_remove(int, char *[]);
146 static const struct got_error* cmd_patch(int, char *[]);
147 static const struct got_error* cmd_revert(int, char *[]);
148 static const struct got_error* cmd_commit(int, char *[]);
149 static const struct got_error* cmd_send(int, char *[]);
150 static const struct got_error* cmd_cherrypick(int, char *[]);
151 static const struct got_error* cmd_backout(int, char *[]);
152 static const struct got_error* cmd_rebase(int, char *[]);
153 static const struct got_error* cmd_histedit(int, char *[]);
154 static const struct got_error* cmd_integrate(int, char *[]);
155 static const struct got_error* cmd_merge(int, char *[]);
156 static const struct got_error* cmd_stage(int, char *[]);
157 static const struct got_error* cmd_unstage(int, char *[]);
158 static const struct got_error* cmd_cat(int, char *[]);
159 static const struct got_error* cmd_info(int, char *[]);
161 static const struct got_cmd got_commands[] = {
162 { "init", cmd_init, usage_init, "" },
163 { "import", cmd_import, usage_import, "im" },
164 { "clone", cmd_clone, usage_clone, "cl" },
165 { "fetch", cmd_fetch, usage_fetch, "fe" },
166 { "checkout", cmd_checkout, usage_checkout, "co" },
167 { "update", cmd_update, usage_update, "up" },
168 { "log", cmd_log, usage_log, "" },
169 { "diff", cmd_diff, usage_diff, "di" },
170 { "blame", cmd_blame, usage_blame, "bl" },
171 { "tree", cmd_tree, usage_tree, "tr" },
172 { "status", cmd_status, usage_status, "st" },
173 { "ref", cmd_ref, usage_ref, "" },
174 { "branch", cmd_branch, usage_branch, "br" },
175 { "tag", cmd_tag, usage_tag, "" },
176 { "add", cmd_add, usage_add, "" },
177 { "remove", cmd_remove, usage_remove, "rm" },
178 { "patch", cmd_patch, usage_patch, "pa" },
179 { "revert", cmd_revert, usage_revert, "rv" },
180 { "commit", cmd_commit, usage_commit, "ci" },
181 { "send", cmd_send, usage_send, "se" },
182 { "cherrypick", cmd_cherrypick, usage_cherrypick, "cy" },
183 { "backout", cmd_backout, usage_backout, "bo" },
184 { "rebase", cmd_rebase, usage_rebase, "rb" },
185 { "histedit", cmd_histedit, usage_histedit, "he" },
186 { "integrate", cmd_integrate, usage_integrate,"ig" },
187 { "merge", cmd_merge, usage_merge, "mg" },
188 { "stage", cmd_stage, usage_stage, "sg" },
189 { "unstage", cmd_unstage, usage_unstage, "ug" },
190 { "cat", cmd_cat, usage_cat, "" },
191 { "info", cmd_info, usage_info, "" },
194 static void
195 list_commands(FILE *fp)
197 size_t i;
199 fprintf(fp, "commands:");
200 for (i = 0; i < nitems(got_commands); i++) {
201 const struct got_cmd *cmd = &got_commands[i];
202 fprintf(fp, " %s", cmd->cmd_name);
204 fputc('\n', fp);
207 __dead static void
208 option_conflict(char a, char b)
210 errx(1, "-%c and -%c options are mutually exclusive", a, b);
214 main(int argc, char *argv[])
216 const struct got_cmd *cmd;
217 size_t i;
218 int ch;
219 int hflag = 0, Vflag = 0;
220 static const struct option longopts[] = {
221 { "version", no_argument, NULL, 'V' },
222 { NULL, 0, NULL, 0 }
225 setlocale(LC_CTYPE, "");
227 while ((ch = getopt_long(argc, argv, "+hV", longopts, NULL)) != -1) {
228 switch (ch) {
229 case 'h':
230 hflag = 1;
231 break;
232 case 'V':
233 Vflag = 1;
234 break;
235 default:
236 usage(hflag, 1);
237 /* NOTREACHED */
241 argc -= optind;
242 argv += optind;
243 optind = 1;
244 optreset = 1;
246 if (Vflag) {
247 got_version_print_str();
248 return 0;
251 if (argc <= 0)
252 usage(hflag, hflag ? 0 : 1);
254 signal(SIGINT, catch_sigint);
255 signal(SIGPIPE, catch_sigpipe);
257 for (i = 0; i < nitems(got_commands); i++) {
258 const struct got_error *error;
260 cmd = &got_commands[i];
262 if (strcmp(cmd->cmd_name, argv[0]) != 0 &&
263 strcmp(cmd->cmd_alias, argv[0]) != 0)
264 continue;
266 if (hflag)
267 cmd->cmd_usage();
269 error = cmd->cmd_main(argc, argv);
270 if (error && error->code != GOT_ERR_CANCELLED &&
271 error->code != GOT_ERR_PRIVSEP_EXIT &&
272 !(sigpipe_received &&
273 error->code == GOT_ERR_ERRNO && errno == EPIPE) &&
274 !(sigint_received &&
275 error->code == GOT_ERR_ERRNO && errno == EINTR)) {
276 fflush(stdout);
277 fprintf(stderr, "%s: %s\n", getprogname(), error->msg);
278 return 1;
281 return 0;
284 fprintf(stderr, "%s: unknown command '%s'\n", getprogname(), argv[0]);
285 list_commands(stderr);
286 return 1;
289 __dead static void
290 usage(int hflag, int status)
292 FILE *fp = (status == 0) ? stdout : stderr;
294 fprintf(fp, "usage: %s [-hV] command [arg ...]\n",
295 getprogname());
296 if (hflag)
297 list_commands(fp);
298 exit(status);
301 static const struct got_error *
302 get_editor(char **abspath)
304 const struct got_error *err = NULL;
305 const char *editor;
307 *abspath = NULL;
309 editor = getenv("VISUAL");
310 if (editor == NULL)
311 editor = getenv("EDITOR");
313 if (editor) {
314 err = got_path_find_prog(abspath, editor);
315 if (err)
316 return err;
319 if (*abspath == NULL) {
320 *abspath = strdup(GOT_DEFAULT_EDITOR);
321 if (*abspath == NULL)
322 return got_error_from_errno("strdup");
325 return NULL;
328 static const struct got_error *
329 apply_unveil(const char *repo_path, int repo_read_only,
330 const char *worktree_path)
332 const struct got_error *err;
334 #ifdef PROFILE
335 if (unveil("gmon.out", "rwc") != 0)
336 return got_error_from_errno2("unveil", "gmon.out");
337 #endif
338 if (repo_path && unveil(repo_path, repo_read_only ? "r" : "rwc") != 0)
339 return got_error_from_errno2("unveil", repo_path);
341 if (worktree_path && unveil(worktree_path, "rwc") != 0)
342 return got_error_from_errno2("unveil", worktree_path);
344 if (unveil(GOT_TMPDIR_STR, "rwc") != 0)
345 return got_error_from_errno2("unveil", GOT_TMPDIR_STR);
347 err = got_privsep_unveil_exec_helpers();
348 if (err != NULL)
349 return err;
351 if (unveil(NULL, NULL) != 0)
352 return got_error_from_errno("unveil");
354 return NULL;
357 __dead static void
358 usage_init(void)
360 fprintf(stderr, "usage: %s init [-A hashing-algorithm] [-b branch]"
361 " repository-path\n",
362 getprogname());
363 exit(1);
366 static const struct got_error *
367 cmd_init(int argc, char *argv[])
369 const struct got_error *error = NULL;
370 const char *head_name = NULL;
371 char *repo_path = NULL;
372 enum got_hash_algorithm algo = GOT_HASH_SHA1;
373 int ch;
375 while ((ch = getopt(argc, argv, "A:b:")) != -1) {
376 switch (ch) {
377 case 'A':
378 if (!strcmp(optarg, "sha1"))
379 algo = GOT_HASH_SHA1;
380 else if (!strcmp(optarg, "sha256"))
381 algo = GOT_HASH_SHA256;
382 else
383 return got_error_path(optarg,
384 GOT_ERR_OBJECT_FORMAT);
385 break;
386 case 'b':
387 head_name = optarg;
388 break;
389 default:
390 usage_init();
391 /* NOTREACHED */
395 argc -= optind;
396 argv += optind;
398 #ifndef PROFILE
399 if (pledge("stdio rpath wpath cpath unveil", NULL) == -1)
400 err(1, "pledge");
401 #endif
402 if (argc != 1)
403 usage_init();
405 repo_path = strdup(argv[0]);
406 if (repo_path == NULL)
407 return got_error_from_errno("strdup");
409 got_path_strip_trailing_slashes(repo_path);
411 error = got_path_mkdir(repo_path);
412 if (error &&
413 !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
414 goto done;
416 error = apply_unveil(repo_path, 0, NULL);
417 if (error)
418 goto done;
420 error = got_repo_init(repo_path, head_name, algo);
421 done:
422 free(repo_path);
423 return error;
426 __dead static void
427 usage_import(void)
429 fprintf(stderr, "usage: %s import [-b branch] [-I pattern] [-m message] "
430 "[-r repository-path] directory\n", getprogname());
431 exit(1);
434 static int
435 spawn_editor(const char *editor, const char *file)
437 pid_t pid;
438 sig_t sighup, sigint, sigquit;
439 int st = -1;
441 sighup = signal(SIGHUP, SIG_IGN);
442 sigint = signal(SIGINT, SIG_IGN);
443 sigquit = signal(SIGQUIT, SIG_IGN);
445 switch (pid = fork()) {
446 case -1:
447 goto doneediting;
448 case 0:
449 execl(editor, editor, file, (char *)NULL);
450 _exit(127);
453 while (waitpid(pid, &st, 0) == -1)
454 if (errno != EINTR)
455 break;
457 doneediting:
458 (void)signal(SIGHUP, sighup);
459 (void)signal(SIGINT, sigint);
460 (void)signal(SIGQUIT, sigquit);
462 if (!WIFEXITED(st)) {
463 errno = EINTR;
464 return -1;
467 return WEXITSTATUS(st);
470 static const struct got_error *
471 read_logmsg(char **logmsg, size_t *len, FILE *fp, size_t filesize)
473 const struct got_error *err = NULL;
474 char *line = NULL;
475 size_t linesize = 0;
477 *logmsg = NULL;
478 *len = 0;
480 if (fseeko(fp, 0L, SEEK_SET) == -1)
481 return got_error_from_errno("fseeko");
483 *logmsg = malloc(filesize + 1);
484 if (*logmsg == NULL)
485 return got_error_from_errno("malloc");
486 (*logmsg)[0] = '\0';
488 while (getline(&line, &linesize, fp) != -1) {
489 if (line[0] == '#' || (*len == 0 && line[0] == '\n'))
490 continue; /* remove comments and leading empty lines */
491 *len = strlcat(*logmsg, line, filesize + 1);
492 if (*len >= filesize + 1) {
493 err = got_error(GOT_ERR_NO_SPACE);
494 goto done;
497 if (ferror(fp)) {
498 err = got_ferror(fp, GOT_ERR_IO);
499 goto done;
502 while (*len > 0 && (*logmsg)[*len - 1] == '\n') {
503 (*logmsg)[*len - 1] = '\0';
504 (*len)--;
506 done:
507 free(line);
508 if (err) {
509 free(*logmsg);
510 *logmsg = NULL;
511 *len = 0;
513 return err;
516 static const struct got_error *
517 edit_logmsg(char **logmsg, const char *editor, const char *logmsg_path,
518 const char *initial_content, size_t initial_content_len,
519 int require_modification)
521 const struct got_error *err = NULL;
522 struct stat st, st2;
523 FILE *fp = NULL;
524 size_t logmsg_len;
526 *logmsg = NULL;
528 if (stat(logmsg_path, &st) == -1)
529 return got_error_from_errno2("stat", logmsg_path);
531 if (spawn_editor(editor, logmsg_path) == -1)
532 return got_error_from_errno("failed spawning editor");
534 if (require_modification) {
535 struct timespec timeout;
537 timeout.tv_sec = 0;
538 timeout.tv_nsec = 1;
539 nanosleep(&timeout, NULL);
542 if (stat(logmsg_path, &st2) == -1)
543 return got_error_from_errno2("stat", logmsg_path);
545 if (require_modification && st.st_size == st2.st_size &&
546 timespeccmp(&st.st_mtim, &st2.st_mtim, ==))
547 return got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
548 "no changes made to commit message, aborting");
550 fp = fopen(logmsg_path, "re");
551 if (fp == NULL) {
552 err = got_error_from_errno("fopen");
553 goto done;
556 /* strip comments and leading/trailing newlines */
557 err = read_logmsg(logmsg, &logmsg_len, fp, st2.st_size);
558 if (err)
559 goto done;
560 if (logmsg_len == 0) {
561 err = got_error_msg(GOT_ERR_COMMIT_MSG_EMPTY,
562 "commit message cannot be empty, aborting");
563 goto done;
565 done:
566 if (fp && fclose(fp) == EOF && err == NULL)
567 err = got_error_from_errno("fclose");
568 if (err) {
569 free(*logmsg);
570 *logmsg = NULL;
572 return err;
575 static const struct got_error *
576 collect_import_msg(char **logmsg, char **logmsg_path, const char *editor,
577 const char *path_dir, const char *branch_name)
579 char *initial_content = NULL;
580 const struct got_error *err = NULL;
581 int initial_content_len;
582 int fd = -1;
584 initial_content_len = asprintf(&initial_content,
585 "\n# %s to be imported to branch %s\n", path_dir,
586 branch_name);
587 if (initial_content_len == -1)
588 return got_error_from_errno("asprintf");
590 err = got_opentemp_named_fd(logmsg_path, &fd,
591 GOT_TMPDIR_STR "/got-importmsg", "");
592 if (err)
593 goto done;
595 if (write(fd, initial_content, initial_content_len) == -1) {
596 err = got_error_from_errno2("write", *logmsg_path);
597 goto done;
599 if (close(fd) == -1) {
600 err = got_error_from_errno2("close", *logmsg_path);
601 goto done;
603 fd = -1;
605 err = edit_logmsg(logmsg, editor, *logmsg_path, initial_content,
606 initial_content_len, 1);
607 done:
608 if (fd != -1 && close(fd) == -1 && err == NULL)
609 err = got_error_from_errno2("close", *logmsg_path);
610 free(initial_content);
611 if (err) {
612 free(*logmsg_path);
613 *logmsg_path = NULL;
615 return err;
618 static const struct got_error *
619 import_progress(void *arg, const char *path)
621 printf("A %s\n", path);
622 return NULL;
625 static const struct got_error *
626 valid_author(const char *author)
628 const char *email = author;
631 * Git' expects the author (or committer) to be in the form
632 * "name <email>", which are mostly free form (see the
633 * "committer" description in git-fast-import(1)). We're only
634 * doing this to avoid git's object parser breaking on commits
635 * we create.
638 while (*author && *author != '\n' && *author != '<' && *author != '>')
639 author++;
640 if (author != email && *author == '<' && *(author - 1) != ' ')
641 return got_error_fmt(GOT_ERR_COMMIT_BAD_AUTHOR, "%s: space "
642 "between author name and email required", email);
643 if (*author++ != '<')
644 return got_error_fmt(GOT_ERR_COMMIT_NO_EMAIL, "%s", email);
645 while (*author && *author != '\n' && *author != '<' && *author != '>')
646 author++;
647 if (strcmp(author, ">") != 0)
648 return got_error_fmt(GOT_ERR_COMMIT_NO_EMAIL, "%s", email);
649 return NULL;
652 static const struct got_error *
653 get_author(char **author, struct got_repository *repo,
654 struct got_worktree *worktree)
656 const struct got_error *err = NULL;
657 const char *got_author = NULL, *name, *email;
658 const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
660 *author = NULL;
662 if (worktree)
663 worktree_conf = got_worktree_get_gotconfig(worktree);
664 repo_conf = got_repo_get_gotconfig(repo);
667 * Priority of potential author information sources, from most
668 * significant to least significant:
669 * 1) work tree's .got/got.conf file
670 * 2) repository's got.conf file
671 * 3) repository's git config file
672 * 4) environment variables
673 * 5) global git config files (in user's home directory or /etc)
676 if (worktree_conf)
677 got_author = got_gotconfig_get_author(worktree_conf);
678 if (got_author == NULL)
679 got_author = got_gotconfig_get_author(repo_conf);
680 if (got_author == NULL) {
681 name = got_repo_get_gitconfig_author_name(repo);
682 email = got_repo_get_gitconfig_author_email(repo);
683 if (name && email) {
684 if (asprintf(author, "%s <%s>", name, email) == -1)
685 return got_error_from_errno("asprintf");
686 return NULL;
689 got_author = getenv("GOT_AUTHOR");
690 if (got_author == NULL) {
691 name = got_repo_get_global_gitconfig_author_name(repo);
692 email = got_repo_get_global_gitconfig_author_email(
693 repo);
694 if (name && email) {
695 if (asprintf(author, "%s <%s>", name, email)
696 == -1)
697 return got_error_from_errno("asprintf");
698 return NULL;
700 /* TODO: Look up user in password database? */
701 return got_error(GOT_ERR_COMMIT_NO_AUTHOR);
705 *author = strdup(got_author);
706 if (*author == NULL)
707 return got_error_from_errno("strdup");
709 err = valid_author(*author);
710 if (err) {
711 free(*author);
712 *author = NULL;
714 return err;
717 static const struct got_error *
718 get_allowed_signers(char **allowed_signers, struct got_repository *repo,
719 struct got_worktree *worktree)
721 const char *got_allowed_signers = NULL;
722 const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
724 *allowed_signers = NULL;
726 if (worktree)
727 worktree_conf = got_worktree_get_gotconfig(worktree);
728 repo_conf = got_repo_get_gotconfig(repo);
731 * Priority of potential author information sources, from most
732 * significant to least significant:
733 * 1) work tree's .got/got.conf file
734 * 2) repository's got.conf file
737 if (worktree_conf)
738 got_allowed_signers = got_gotconfig_get_allowed_signers_file(
739 worktree_conf);
740 if (got_allowed_signers == NULL)
741 got_allowed_signers = got_gotconfig_get_allowed_signers_file(
742 repo_conf);
744 if (got_allowed_signers) {
745 *allowed_signers = strdup(got_allowed_signers);
746 if (*allowed_signers == NULL)
747 return got_error_from_errno("strdup");
749 return NULL;
752 static const struct got_error *
753 get_revoked_signers(char **revoked_signers, struct got_repository *repo,
754 struct got_worktree *worktree)
756 const char *got_revoked_signers = NULL;
757 const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
759 *revoked_signers = NULL;
761 if (worktree)
762 worktree_conf = got_worktree_get_gotconfig(worktree);
763 repo_conf = got_repo_get_gotconfig(repo);
766 * Priority of potential author information sources, from most
767 * significant to least significant:
768 * 1) work tree's .got/got.conf file
769 * 2) repository's got.conf file
772 if (worktree_conf)
773 got_revoked_signers = got_gotconfig_get_revoked_signers_file(
774 worktree_conf);
775 if (got_revoked_signers == NULL)
776 got_revoked_signers = got_gotconfig_get_revoked_signers_file(
777 repo_conf);
779 if (got_revoked_signers) {
780 *revoked_signers = strdup(got_revoked_signers);
781 if (*revoked_signers == NULL)
782 return got_error_from_errno("strdup");
784 return NULL;
787 static const char *
788 get_signer_id(struct got_repository *repo, struct got_worktree *worktree)
790 const char *got_signer_id = NULL;
791 const struct got_gotconfig *worktree_conf = NULL, *repo_conf = NULL;
793 if (worktree)
794 worktree_conf = got_worktree_get_gotconfig(worktree);
795 repo_conf = got_repo_get_gotconfig(repo);
798 * Priority of potential author information sources, from most
799 * significant to least significant:
800 * 1) work tree's .got/got.conf file
801 * 2) repository's got.conf file
804 if (worktree_conf)
805 got_signer_id = got_gotconfig_get_signer_id(worktree_conf);
806 if (got_signer_id == NULL)
807 got_signer_id = got_gotconfig_get_signer_id(repo_conf);
809 return got_signer_id;
812 static const struct got_error *
813 get_gitconfig_path(char **gitconfig_path)
815 const char *homedir = getenv("HOME");
817 *gitconfig_path = NULL;
818 if (homedir) {
819 if (asprintf(gitconfig_path, "%s/.gitconfig", homedir) == -1)
820 return got_error_from_errno("asprintf");
823 return NULL;
826 static const struct got_error *
827 cmd_import(int argc, char *argv[])
829 const struct got_error *error = NULL;
830 char *path_dir = NULL, *repo_path = NULL, *logmsg = NULL;
831 char *gitconfig_path = NULL, *editor = NULL, *author = NULL;
832 const char *branch_name = NULL;
833 char *id_str = NULL, *logmsg_path = NULL;
834 char refname[PATH_MAX] = "refs/heads/";
835 struct got_repository *repo = NULL;
836 struct got_reference *branch_ref = NULL, *head_ref = NULL;
837 struct got_object_id *new_commit_id = NULL;
838 int ch, n = 0;
839 struct got_pathlist_head ignores;
840 struct got_pathlist_entry *pe;
841 int preserve_logmsg = 0;
842 int *pack_fds = NULL;
844 TAILQ_INIT(&ignores);
846 #ifndef PROFILE
847 if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd "
848 "unveil",
849 NULL) == -1)
850 err(1, "pledge");
851 #endif
853 while ((ch = getopt(argc, argv, "b:I:m:r:")) != -1) {
854 switch (ch) {
855 case 'b':
856 branch_name = optarg;
857 break;
858 case 'I':
859 if (optarg[0] == '\0')
860 break;
861 error = got_pathlist_insert(&pe, &ignores, optarg,
862 NULL);
863 if (error)
864 goto done;
865 break;
866 case 'm':
867 logmsg = strdup(optarg);
868 if (logmsg == NULL) {
869 error = got_error_from_errno("strdup");
870 goto done;
872 break;
873 case 'r':
874 repo_path = realpath(optarg, NULL);
875 if (repo_path == NULL) {
876 error = got_error_from_errno2("realpath",
877 optarg);
878 goto done;
880 break;
881 default:
882 usage_import();
883 /* NOTREACHED */
887 argc -= optind;
888 argv += optind;
890 if (argc != 1)
891 usage_import();
893 if (repo_path == NULL) {
894 repo_path = getcwd(NULL, 0);
895 if (repo_path == NULL)
896 return got_error_from_errno("getcwd");
898 got_path_strip_trailing_slashes(repo_path);
899 error = get_gitconfig_path(&gitconfig_path);
900 if (error)
901 goto done;
902 error = got_repo_pack_fds_open(&pack_fds);
903 if (error != NULL)
904 goto done;
905 error = got_repo_open(&repo, repo_path, gitconfig_path, pack_fds);
906 if (error)
907 goto done;
909 path_dir = realpath(argv[0], NULL);
910 if (path_dir == NULL) {
911 error = got_error_from_errno2("realpath", argv[0]);
912 goto done;
914 got_path_strip_trailing_slashes(path_dir);
916 error = get_editor(&editor);
917 if (error)
918 goto done;
920 if (unveil(path_dir, "r") != 0) {
921 error = got_error_from_errno2("unveil", path_dir);
922 goto done;
924 if (unveil(editor, "x") != 0) {
925 error = got_error_from_errno2("unveil", editor);
926 goto done;
928 error = apply_unveil(got_repo_get_path(repo), 0, NULL);
929 if (error)
930 goto done;
932 error = get_author(&author, repo, NULL);
933 if (error)
934 return error;
937 * Don't let the user create a branch name with a leading '-'.
938 * While technically a valid reference name, this case is usually
939 * an unintended typo.
941 if (branch_name && branch_name[0] == '-')
942 return got_error_path(branch_name, GOT_ERR_REF_NAME_MINUS);
944 error = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0);
945 if (error && error->code != GOT_ERR_NOT_REF)
946 goto done;
948 if (branch_name)
949 n = strlcat(refname, branch_name, sizeof(refname));
950 else if (head_ref && got_ref_is_symbolic(head_ref))
951 n = strlcpy(refname, got_ref_get_symref_target(head_ref),
952 sizeof(refname));
953 else
954 n = strlcat(refname, "main", sizeof(refname));
955 if (n >= sizeof(refname)) {
956 error = got_error(GOT_ERR_NO_SPACE);
957 goto done;
960 error = got_ref_open(&branch_ref, repo, refname, 0);
961 if (error) {
962 if (error->code != GOT_ERR_NOT_REF)
963 goto done;
964 } else {
965 error = got_error_msg(GOT_ERR_BRANCH_EXISTS,
966 "import target branch already exists");
967 goto done;
970 if (logmsg == NULL || *logmsg == '\0') {
971 free(logmsg);
972 error = collect_import_msg(&logmsg, &logmsg_path, editor,
973 path_dir, refname);
974 if (error) {
975 if (error->code != GOT_ERR_COMMIT_MSG_EMPTY &&
976 logmsg_path != NULL)
977 preserve_logmsg = 1;
978 goto done;
982 error = got_repo_import(&new_commit_id, path_dir, logmsg,
983 author, &ignores, repo, import_progress, NULL);
984 if (error) {
985 if (logmsg_path)
986 preserve_logmsg = 1;
987 goto done;
990 error = got_ref_alloc(&branch_ref, refname, new_commit_id);
991 if (error) {
992 if (logmsg_path)
993 preserve_logmsg = 1;
994 goto done;
997 error = got_ref_write(branch_ref, repo);
998 if (error) {
999 if (logmsg_path)
1000 preserve_logmsg = 1;
1001 goto done;
1004 error = got_object_id_str(&id_str, new_commit_id);
1005 if (error) {
1006 if (logmsg_path)
1007 preserve_logmsg = 1;
1008 goto done;
1011 error = got_ref_open(&head_ref, repo, GOT_REF_HEAD, 0);
1012 if (error) {
1013 if (error->code != GOT_ERR_NOT_REF) {
1014 if (logmsg_path)
1015 preserve_logmsg = 1;
1016 goto done;
1019 error = got_ref_alloc_symref(&head_ref, GOT_REF_HEAD,
1020 branch_ref);
1021 if (error) {
1022 if (logmsg_path)
1023 preserve_logmsg = 1;
1024 goto done;
1027 error = got_ref_write(head_ref, repo);
1028 if (error) {
1029 if (logmsg_path)
1030 preserve_logmsg = 1;
1031 goto done;
1035 printf("Created branch %s with commit %s\n",
1036 got_ref_get_name(branch_ref), id_str);
1037 done:
1038 if (pack_fds) {
1039 const struct got_error *pack_err =
1040 got_repo_pack_fds_close(pack_fds);
1041 if (error == NULL)
1042 error = pack_err;
1044 if (repo) {
1045 const struct got_error *close_err = got_repo_close(repo);
1046 if (error == NULL)
1047 error = close_err;
1049 if (preserve_logmsg) {
1050 fprintf(stderr, "%s: log message preserved in %s\n",
1051 getprogname(), logmsg_path);
1052 } else if (logmsg_path && unlink(logmsg_path) == -1 && error == NULL)
1053 error = got_error_from_errno2("unlink", logmsg_path);
1054 free(logmsg);
1055 free(logmsg_path);
1056 free(repo_path);
1057 free(editor);
1058 free(new_commit_id);
1059 free(id_str);
1060 free(author);
1061 free(gitconfig_path);
1062 if (branch_ref)
1063 got_ref_close(branch_ref);
1064 if (head_ref)
1065 got_ref_close(head_ref);
1066 return error;
1069 __dead static void
1070 usage_clone(void)
1072 fprintf(stderr, "usage: %s clone [-almqv] [-b branch] [-R reference] "
1073 "repository-URL [directory]\n", getprogname());
1074 exit(1);
1077 struct got_fetch_progress_arg {
1078 char last_scaled_size[FMT_SCALED_STRSIZE];
1079 int last_p_indexed;
1080 int last_p_resolved;
1081 int verbosity;
1083 struct got_repository *repo;
1085 int create_configs;
1086 int configs_created;
1087 struct {
1088 struct got_pathlist_head *symrefs;
1089 struct got_pathlist_head *wanted_branches;
1090 struct got_pathlist_head *wanted_refs;
1091 const char *proto;
1092 const char *host;
1093 const char *port;
1094 const char *remote_repo_path;
1095 const char *git_url;
1096 int fetch_all_branches;
1097 int mirror_references;
1098 } config_info;
1101 /* XXX forward declaration */
1102 static const struct got_error *
1103 create_config_files(const char *proto, const char *host, const char *port,
1104 const char *remote_repo_path, const char *git_url, int fetch_all_branches,
1105 int mirror_references, struct got_pathlist_head *symrefs,
1106 struct got_pathlist_head *wanted_branches,
1107 struct got_pathlist_head *wanted_refs, struct got_repository *repo);
1109 static const struct got_error *
1110 fetch_progress(void *arg, const char *message, off_t packfile_size,
1111 int nobj_total, int nobj_indexed, int nobj_loose, int nobj_resolved)
1113 const struct got_error *err = NULL;
1114 struct got_fetch_progress_arg *a = arg;
1115 char scaled_size[FMT_SCALED_STRSIZE];
1116 int p_indexed, p_resolved;
1117 int print_size = 0, print_indexed = 0, print_resolved = 0;
1120 * In order to allow a failed clone to be resumed with 'got fetch'
1121 * we try to create configuration files as soon as possible.
1122 * Once the server has sent information about its default branch
1123 * we have all required information.
1125 if (a->create_configs && !a->configs_created &&
1126 !TAILQ_EMPTY(a->config_info.symrefs)) {
1127 err = create_config_files(a->config_info.proto,
1128 a->config_info.host, a->config_info.port,
1129 a->config_info.remote_repo_path,
1130 a->config_info.git_url,
1131 a->config_info.fetch_all_branches,
1132 a->config_info.mirror_references,
1133 a->config_info.symrefs,
1134 a->config_info.wanted_branches,
1135 a->config_info.wanted_refs, a->repo);
1136 if (err)
1137 return err;
1138 a->configs_created = 1;
1141 if (a->verbosity < 0)
1142 return NULL;
1144 if (message && message[0] != '\0') {
1145 printf("\rserver: %s", message);
1146 fflush(stdout);
1147 return NULL;
1150 if (packfile_size > 0 || nobj_indexed > 0) {
1151 if (fmt_scaled(packfile_size, scaled_size) == 0 &&
1152 (a->last_scaled_size[0] == '\0' ||
1153 strcmp(scaled_size, a->last_scaled_size)) != 0) {
1154 print_size = 1;
1155 if (strlcpy(a->last_scaled_size, scaled_size,
1156 FMT_SCALED_STRSIZE) >= FMT_SCALED_STRSIZE)
1157 return got_error(GOT_ERR_NO_SPACE);
1159 if (nobj_indexed > 0) {
1160 p_indexed = (nobj_indexed * 100) / nobj_total;
1161 if (p_indexed != a->last_p_indexed) {
1162 a->last_p_indexed = p_indexed;
1163 print_indexed = 1;
1164 print_size = 1;
1167 if (nobj_resolved > 0) {
1168 p_resolved = (nobj_resolved * 100) /
1169 (nobj_total - nobj_loose);
1170 if (p_resolved != a->last_p_resolved) {
1171 a->last_p_resolved = p_resolved;
1172 print_resolved = 1;
1173 print_indexed = 1;
1174 print_size = 1;
1179 if (print_size || print_indexed || print_resolved)
1180 printf("\r");
1181 if (print_size)
1182 printf("%*s fetched", FMT_SCALED_STRSIZE - 2, scaled_size);
1183 if (print_indexed)
1184 printf("; indexing %d%%", p_indexed);
1185 if (print_resolved)
1186 printf("; resolving deltas %d%%", p_resolved);
1187 if (print_size || print_indexed || print_resolved)
1188 fflush(stdout);
1190 return NULL;
1193 static const struct got_error *
1194 create_symref(const char *refname, struct got_reference *target_ref,
1195 int verbosity, struct got_repository *repo)
1197 const struct got_error *err;
1198 struct got_reference *head_symref;
1200 err = got_ref_alloc_symref(&head_symref, refname, target_ref);
1201 if (err)
1202 return err;
1204 err = got_ref_write(head_symref, repo);
1205 if (err == NULL && verbosity > 0) {
1206 printf("Created reference %s: %s\n", GOT_REF_HEAD,
1207 got_ref_get_name(target_ref));
1209 got_ref_close(head_symref);
1210 return err;
1213 static const struct got_error *
1214 list_remote_refs(struct got_pathlist_head *symrefs,
1215 struct got_pathlist_head *refs)
1217 const struct got_error *err;
1218 struct got_pathlist_entry *pe;
1220 TAILQ_FOREACH(pe, symrefs, entry) {
1221 const char *refname = pe->path;
1222 const char *targetref = pe->data;
1224 printf("%s: %s\n", refname, targetref);
1227 TAILQ_FOREACH(pe, refs, entry) {
1228 const char *refname = pe->path;
1229 struct got_object_id *id = pe->data;
1230 char *id_str;
1232 err = got_object_id_str(&id_str, id);
1233 if (err)
1234 return err;
1235 printf("%s: %s\n", refname, id_str);
1236 free(id_str);
1239 return NULL;
1242 static const struct got_error *
1243 create_ref(const char *refname, struct got_object_id *id,
1244 int verbosity, struct got_repository *repo)
1246 const struct got_error *err = NULL;
1247 struct got_reference *ref;
1248 char *id_str;
1250 err = got_object_id_str(&id_str, id);
1251 if (err)
1252 return err;
1254 err = got_ref_alloc(&ref, refname, id);
1255 if (err)
1256 goto done;
1258 err = got_ref_write(ref, repo);
1259 got_ref_close(ref);
1261 if (err == NULL && verbosity >= 0)
1262 printf("Created reference %s: %s\n", refname, id_str);
1263 done:
1264 free(id_str);
1265 return err;
1268 static int
1269 match_wanted_ref(const char *refname, const char *wanted_ref)
1271 if (strncmp(refname, "refs/", 5) != 0)
1272 return 0;
1273 refname += 5;
1276 * Prevent fetching of references that won't make any
1277 * sense outside of the remote repository's context.
1279 if (strncmp(refname, "got/", 4) == 0)
1280 return 0;
1281 if (strncmp(refname, "remotes/", 8) == 0)
1282 return 0;
1284 if (strncmp(wanted_ref, "refs/", 5) == 0)
1285 wanted_ref += 5;
1287 /* Allow prefix match. */
1288 if (got_path_is_child(refname, wanted_ref, strlen(wanted_ref)))
1289 return 1;
1291 /* Allow exact match. */
1292 return (strcmp(refname, wanted_ref) == 0);
1295 static int
1296 is_wanted_ref(struct got_pathlist_head *wanted_refs, const char *refname)
1298 struct got_pathlist_entry *pe;
1300 TAILQ_FOREACH(pe, wanted_refs, entry) {
1301 if (match_wanted_ref(refname, pe->path))
1302 return 1;
1305 return 0;
1308 static const struct got_error *
1309 create_wanted_ref(const char *refname, struct got_object_id *id,
1310 const char *remote_repo_name, int verbosity, struct got_repository *repo)
1312 const struct got_error *err;
1313 char *remote_refname;
1315 if (strncmp("refs/", refname, 5) == 0)
1316 refname += 5;
1318 if (asprintf(&remote_refname, "refs/remotes/%s/%s",
1319 remote_repo_name, refname) == -1)
1320 return got_error_from_errno("asprintf");
1322 err = create_ref(remote_refname, id, verbosity, repo);
1323 free(remote_refname);
1324 return err;
1327 static const struct got_error *
1328 create_gotconfig(const char *proto, const char *host, const char *port,
1329 const char *remote_repo_path, const char *default_branch,
1330 int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1331 struct got_pathlist_head *wanted_refs, int mirror_references,
1332 struct got_repository *repo)
1334 const struct got_error *err = NULL;
1335 char *gotconfig_path = NULL;
1336 char *gotconfig = NULL;
1337 FILE *gotconfig_file = NULL;
1338 const char *branchname = NULL;
1339 char *branches = NULL, *refs = NULL;
1340 ssize_t n;
1342 if (!fetch_all_branches && !TAILQ_EMPTY(wanted_branches)) {
1343 struct got_pathlist_entry *pe;
1344 TAILQ_FOREACH(pe, wanted_branches, entry) {
1345 char *s;
1346 branchname = pe->path;
1347 if (strncmp(branchname, "refs/heads/", 11) == 0)
1348 branchname += 11;
1349 if (asprintf(&s, "%s\"%s\" ",
1350 branches ? branches : "", branchname) == -1) {
1351 err = got_error_from_errno("asprintf");
1352 goto done;
1354 free(branches);
1355 branches = s;
1357 } else if (!fetch_all_branches && default_branch) {
1358 branchname = default_branch;
1359 if (strncmp(branchname, "refs/heads/", 11) == 0)
1360 branchname += 11;
1361 if (asprintf(&branches, "\"%s\" ", branchname) == -1) {
1362 err = got_error_from_errno("asprintf");
1363 goto done;
1366 if (!TAILQ_EMPTY(wanted_refs)) {
1367 struct got_pathlist_entry *pe;
1368 TAILQ_FOREACH(pe, wanted_refs, entry) {
1369 char *s;
1370 const char *refname = pe->path;
1371 if (strncmp(refname, "refs/", 5) == 0)
1372 branchname += 5;
1373 if (asprintf(&s, "%s\"%s\" ",
1374 refs ? refs : "", refname) == -1) {
1375 err = got_error_from_errno("asprintf");
1376 goto done;
1378 free(refs);
1379 refs = s;
1383 /* Create got.conf(5). */
1384 gotconfig_path = got_repo_get_path_gotconfig(repo);
1385 if (gotconfig_path == NULL) {
1386 err = got_error_from_errno("got_repo_get_path_gotconfig");
1387 goto done;
1389 gotconfig_file = fopen(gotconfig_path, "ae");
1390 if (gotconfig_file == NULL) {
1391 err = got_error_from_errno2("fopen", gotconfig_path);
1392 goto done;
1394 if (asprintf(&gotconfig,
1395 "remote \"%s\" {\n"
1396 "\tserver %s\n"
1397 "\tprotocol %s\n"
1398 "%s%s%s"
1399 "\trepository \"%s\"\n"
1400 "%s%s%s"
1401 "%s%s%s"
1402 "%s"
1403 "%s"
1404 "}\n",
1405 GOT_FETCH_DEFAULT_REMOTE_NAME, host, proto,
1406 port ? "\tport " : "", port ? port : "", port ? "\n" : "",
1407 remote_repo_path, branches ? "\tbranch { " : "",
1408 branches ? branches : "", branches ? "}\n" : "",
1409 refs ? "\treference { " : "", refs ? refs : "", refs ? "}\n" : "",
1410 mirror_references ? "\tmirror_references yes\n" : "",
1411 fetch_all_branches ? "\tfetch_all_branches yes\n" : "") == -1) {
1412 err = got_error_from_errno("asprintf");
1413 goto done;
1415 n = fwrite(gotconfig, 1, strlen(gotconfig), gotconfig_file);
1416 if (n != strlen(gotconfig)) {
1417 err = got_ferror(gotconfig_file, GOT_ERR_IO);
1418 goto done;
1421 done:
1422 if (gotconfig_file && fclose(gotconfig_file) == EOF && err == NULL)
1423 err = got_error_from_errno2("fclose", gotconfig_path);
1424 free(gotconfig_path);
1425 free(branches);
1426 return err;
1429 static const struct got_error *
1430 create_gitconfig(const char *git_url, const char *default_branch,
1431 int fetch_all_branches, struct got_pathlist_head *wanted_branches,
1432 struct got_pathlist_head *wanted_refs, int mirror_references,
1433 struct got_repository *repo)
1435 const struct got_error *err = NULL;
1436 char *gitconfig_path = NULL;
1437 char *gitconfig = NULL;
1438 FILE *gitconfig_file = NULL;
1439 char *branches = NULL, *refs = NULL;
1440 const char *branchname;
1441 ssize_t n;
1443 /* Create a config file Git can understand. */
1444 gitconfig_path = got_repo_get_path_gitconfig(repo);
1445 if (gitconfig_path == NULL) {
1446 err = got_error_from_errno("got_repo_get_path_gitconfig");
1447 goto done;
1449 gitconfig_file = fopen(gitconfig_path, "ae");
1450 if (gitconfig_file == NULL) {
1451 err = got_error_from_errno2("fopen", gitconfig_path);
1452 goto done;
1454 if (fetch_all_branches) {
1455 if (mirror_references) {
1456 if (asprintf(&branches,
1457 "\tfetch = refs/heads/*:refs/heads/*\n") == -1) {
1458 err = got_error_from_errno("asprintf");
1459 goto done;
1461 } else if (asprintf(&branches,
1462 "\tfetch = refs/heads/*:refs/remotes/%s/*\n",
1463 GOT_FETCH_DEFAULT_REMOTE_NAME) == -1) {
1464 err = got_error_from_errno("asprintf");
1465 goto done;
1467 } else if (!TAILQ_EMPTY(wanted_branches)) {
1468 struct got_pathlist_entry *pe;
1469 TAILQ_FOREACH(pe, wanted_branches, entry) {
1470 char *s;
1471 branchname = pe->path;
1472 if (strncmp(branchname, "refs/heads/", 11) == 0)
1473 branchname += 11;
1474 if (mirror_references) {
1475 if (asprintf(&s,
1476 "%s\tfetch = refs/heads/%s:refs/heads/%s\n",
1477 branches ? branches : "",
1478 branchname, branchname) == -1) {
1479 err = got_error_from_errno("asprintf");
1480 goto done;
1482 } else if (asprintf(&s,
1483 "%s\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1484 branches ? branches : "",
1485 branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1486 branchname) == -1) {
1487 err = got_error_from_errno("asprintf");
1488 goto done;
1490 free(branches);
1491 branches = s;
1493 } else {
1495 * If the server specified a default branch, use just that one.
1496 * Otherwise fall back to fetching all branches on next fetch.
1498 if (default_branch) {
1499 branchname = default_branch;
1500 if (strncmp(branchname, "refs/heads/", 11) == 0)
1501 branchname += 11;
1502 } else
1503 branchname = "*"; /* fall back to all branches */
1504 if (mirror_references) {
1505 if (asprintf(&branches,
1506 "\tfetch = refs/heads/%s:refs/heads/%s\n",
1507 branchname, branchname) == -1) {
1508 err = got_error_from_errno("asprintf");
1509 goto done;
1511 } else if (asprintf(&branches,
1512 "\tfetch = refs/heads/%s:refs/remotes/%s/%s\n",
1513 branchname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1514 branchname) == -1) {
1515 err = got_error_from_errno("asprintf");
1516 goto done;
1519 if (!TAILQ_EMPTY(wanted_refs)) {
1520 struct got_pathlist_entry *pe;
1521 TAILQ_FOREACH(pe, wanted_refs, entry) {
1522 char *s;
1523 const char *refname = pe->path;
1524 if (strncmp(refname, "refs/", 5) == 0)
1525 refname += 5;
1526 if (mirror_references) {
1527 if (asprintf(&s,
1528 "%s\tfetch = refs/%s:refs/%s\n",
1529 refs ? refs : "", refname, refname) == -1) {
1530 err = got_error_from_errno("asprintf");
1531 goto done;
1533 } else if (asprintf(&s,
1534 "%s\tfetch = refs/%s:refs/remotes/%s/%s\n",
1535 refs ? refs : "",
1536 refname, GOT_FETCH_DEFAULT_REMOTE_NAME,
1537 refname) == -1) {
1538 err = got_error_from_errno("asprintf");
1539 goto done;
1541 free(refs);
1542 refs = s;
1546 if (asprintf(&gitconfig,
1547 "[remote \"%s\"]\n"
1548 "\turl = %s\n"
1549 "%s"
1550 "%s"
1551 "\tfetch = refs/tags/*:refs/tags/*\n",
1552 GOT_FETCH_DEFAULT_REMOTE_NAME, git_url, branches ? branches : "",
1553 refs ? refs : "") == -1) {
1554 err = got_error_from_errno("asprintf");
1555 goto done;
1557 n = fwrite(gitconfig, 1, strlen(gitconfig), gitconfig_file);
1558 if (n != strlen(gitconfig)) {
1559 err = got_ferror(gitconfig_file, GOT_ERR_IO);
1560 goto done;
1562 done:
1563 if (gitconfig_file && fclose(gitconfig_file) == EOF && err == NULL)
1564 err = got_error_from_errno2("fclose", gitconfig_path);
1565 free(gitconfig_path);
1566 free(branches);
1567 return err;
1570 static const struct got_error *
1571 create_config_files(const char *proto, const char *host, const char *port,
1572 const char *remote_repo_path, const char *git_url, int fetch_all_branches,
1573 int mirror_references, struct got_pathlist_head *symrefs,
1574 struct got_pathlist_head *wanted_branches,
1575 struct got_pathlist_head *wanted_refs, struct got_repository *repo)
1577 const struct got_error *err = NULL;
1578 const char *default_branch = NULL;
1579 struct got_pathlist_entry *pe;
1582 * If we asked for a set of wanted branches then use the first
1583 * one of those.
1585 if (!TAILQ_EMPTY(wanted_branches)) {
1586 pe = TAILQ_FIRST(wanted_branches);
1587 default_branch = pe->path;
1588 } else {
1589 /* First HEAD ref listed by server is the default branch. */
1590 TAILQ_FOREACH(pe, symrefs, entry) {
1591 const char *refname = pe->path;
1592 const char *target = pe->data;
1594 if (strcmp(refname, GOT_REF_HEAD) != 0)
1595 continue;
1597 default_branch = target;
1598 break;
1602 /* Create got.conf(5). */
1603 err = create_gotconfig(proto, host, port, remote_repo_path,
1604 default_branch, fetch_all_branches, wanted_branches,
1605 wanted_refs, mirror_references, repo);
1606 if (err)
1607 return err;
1609 /* Create a config file Git can understand. */
1610 return create_gitconfig(git_url, default_branch, fetch_all_branches,
1611 wanted_branches, wanted_refs, mirror_references, repo);
1614 static const struct got_error *
1615 cmd_clone(int argc, char *argv[])
1617 const struct got_error *error = NULL;
1618 const char *uri, *dirname;
1619 char *proto, *host, *port, *repo_name, *server_path;
1620 char *default_destdir = NULL, *id_str = NULL;
1621 const char *repo_path;
1622 struct got_repository *repo = NULL;
1623 struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
1624 struct got_pathlist_entry *pe;
1625 struct got_object_id *pack_hash = NULL;
1626 int ch, fetchfd = -1, fetchstatus;
1627 pid_t fetchpid = -1;
1628 struct got_fetch_progress_arg fpa;
1629 char *git_url = NULL;
1630 int verbosity = 0, fetch_all_branches = 0, mirror_references = 0;
1631 int bflag = 0, list_refs_only = 0;
1632 int *pack_fds = NULL;
1634 TAILQ_INIT(&refs);
1635 TAILQ_INIT(&symrefs);
1636 TAILQ_INIT(&wanted_branches);
1637 TAILQ_INIT(&wanted_refs);
1639 while ((ch = getopt(argc, argv, "ab:lmqR:v")) != -1) {
1640 switch (ch) {
1641 case 'a':
1642 fetch_all_branches = 1;
1643 break;
1644 case 'b':
1645 error = got_pathlist_append(&wanted_branches,
1646 optarg, NULL);
1647 if (error)
1648 return error;
1649 bflag = 1;
1650 break;
1651 case 'l':
1652 list_refs_only = 1;
1653 break;
1654 case 'm':
1655 mirror_references = 1;
1656 break;
1657 case 'q':
1658 verbosity = -1;
1659 break;
1660 case 'R':
1661 error = got_pathlist_append(&wanted_refs,
1662 optarg, NULL);
1663 if (error)
1664 return error;
1665 break;
1666 case 'v':
1667 if (verbosity < 0)
1668 verbosity = 0;
1669 else if (verbosity < 3)
1670 verbosity++;
1671 break;
1672 default:
1673 usage_clone();
1674 break;
1677 argc -= optind;
1678 argv += optind;
1680 if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
1681 option_conflict('a', 'b');
1682 if (list_refs_only) {
1683 if (!TAILQ_EMPTY(&wanted_branches))
1684 option_conflict('l', 'b');
1685 if (fetch_all_branches)
1686 option_conflict('l', 'a');
1687 if (mirror_references)
1688 option_conflict('l', 'm');
1689 if (!TAILQ_EMPTY(&wanted_refs))
1690 option_conflict('l', 'R');
1693 uri = argv[0];
1695 if (argc == 1)
1696 dirname = NULL;
1697 else if (argc == 2)
1698 dirname = argv[1];
1699 else
1700 usage_clone();
1702 error = got_dial_parse_uri(&proto, &host, &port, &server_path,
1703 &repo_name, uri);
1704 if (error)
1705 goto done;
1707 if (asprintf(&git_url, "%s://%s%s%s%s%s", proto,
1708 host, port ? ":" : "", port ? port : "",
1709 server_path[0] != '/' ? "/" : "", server_path) == -1) {
1710 error = got_error_from_errno("asprintf");
1711 goto done;
1714 if (strcmp(proto, "git") == 0) {
1715 #ifndef PROFILE
1716 if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1717 "sendfd dns inet unveil", NULL) == -1)
1718 err(1, "pledge");
1719 #endif
1720 } else if (strcmp(proto, "git+ssh") == 0 ||
1721 strcmp(proto, "ssh") == 0 ||
1722 strcmp(proto, "git+http") == 0 ||
1723 strcmp(proto, "http") == 0 ||
1724 strcmp(proto, "git+https") == 0 ||
1725 strcmp(proto, "https") == 0) {
1726 #ifndef PROFILE
1727 if (pledge("stdio rpath wpath cpath fattr flock proc exec "
1728 "sendfd unveil", NULL) == -1)
1729 err(1, "pledge");
1730 #endif
1731 } else {
1732 error = got_error_path(proto, GOT_ERR_BAD_PROTO);
1733 goto done;
1735 if (dirname == NULL) {
1736 if (asprintf(&default_destdir, "%s.git", repo_name) == -1) {
1737 error = got_error_from_errno("asprintf");
1738 goto done;
1740 repo_path = default_destdir;
1741 } else
1742 repo_path = dirname;
1744 if (!list_refs_only) {
1745 error = got_path_mkdir(repo_path);
1746 if (error &&
1747 (!(error->code == GOT_ERR_ERRNO && errno == EISDIR) &&
1748 !(error->code == GOT_ERR_ERRNO && errno == EEXIST)))
1749 goto done;
1750 if (!got_path_dir_is_empty(repo_path)) {
1751 error = got_error_path(repo_path,
1752 GOT_ERR_DIR_NOT_EMPTY);
1753 goto done;
1757 error = got_dial_apply_unveil(proto);
1758 if (error)
1759 goto done;
1761 error = apply_unveil(repo_path, 0, NULL);
1762 if (error)
1763 goto done;
1765 if (verbosity >= 0)
1766 printf("Connecting to %s\n", git_url);
1768 error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
1769 server_path, verbosity);
1770 if (error)
1771 goto done;
1773 #ifndef PROFILE
1774 if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd",
1775 NULL) == -1)
1776 err(1, "pledge");
1777 #endif
1778 if (!list_refs_only) {
1779 error = got_repo_init(repo_path, NULL, GOT_HASH_SHA1);
1780 if (error)
1781 goto done;
1782 error = got_repo_pack_fds_open(&pack_fds);
1783 if (error != NULL)
1784 goto done;
1785 error = got_repo_open(&repo, repo_path, NULL, pack_fds);
1786 if (error)
1787 goto done;
1790 fpa.last_scaled_size[0] = '\0';
1791 fpa.last_p_indexed = -1;
1792 fpa.last_p_resolved = -1;
1793 fpa.verbosity = verbosity;
1794 fpa.create_configs = 1;
1795 fpa.configs_created = 0;
1796 fpa.repo = repo;
1797 fpa.config_info.symrefs = &symrefs;
1798 fpa.config_info.wanted_branches = &wanted_branches;
1799 fpa.config_info.wanted_refs = &wanted_refs;
1800 fpa.config_info.proto = proto;
1801 fpa.config_info.host = host;
1802 fpa.config_info.port = port;
1803 fpa.config_info.remote_repo_path = server_path;
1804 fpa.config_info.git_url = git_url;
1805 fpa.config_info.fetch_all_branches = fetch_all_branches;
1806 fpa.config_info.mirror_references = mirror_references;
1807 error = got_fetch_pack(&pack_hash, &refs, &symrefs,
1808 GOT_FETCH_DEFAULT_REMOTE_NAME, mirror_references,
1809 fetch_all_branches, &wanted_branches, &wanted_refs,
1810 list_refs_only, verbosity, fetchfd, repo, NULL, NULL, bflag,
1811 fetch_progress, &fpa);
1812 if (error)
1813 goto done;
1815 if (list_refs_only) {
1816 error = list_remote_refs(&symrefs, &refs);
1817 goto done;
1820 if (pack_hash == NULL) {
1821 error = got_error_fmt(GOT_ERR_FETCH_FAILED, "%s",
1822 "server sent an empty pack file");
1823 goto done;
1825 error = got_object_id_str(&id_str, pack_hash);
1826 if (error)
1827 goto done;
1828 if (verbosity >= 0)
1829 printf("\nFetched %s.pack\n", id_str);
1830 free(id_str);
1832 /* Set up references provided with the pack file. */
1833 TAILQ_FOREACH(pe, &refs, entry) {
1834 const char *refname = pe->path;
1835 struct got_object_id *id = pe->data;
1836 char *remote_refname;
1838 if (is_wanted_ref(&wanted_refs, refname) &&
1839 !mirror_references) {
1840 error = create_wanted_ref(refname, id,
1841 GOT_FETCH_DEFAULT_REMOTE_NAME,
1842 verbosity - 1, repo);
1843 if (error)
1844 goto done;
1845 continue;
1848 error = create_ref(refname, id, verbosity - 1, repo);
1849 if (error)
1850 goto done;
1852 if (mirror_references)
1853 continue;
1855 if (strncmp("refs/heads/", refname, 11) != 0)
1856 continue;
1858 if (asprintf(&remote_refname,
1859 "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1860 refname + 11) == -1) {
1861 error = got_error_from_errno("asprintf");
1862 goto done;
1864 error = create_ref(remote_refname, id, verbosity - 1, repo);
1865 free(remote_refname);
1866 if (error)
1867 goto done;
1870 /* Set the HEAD reference if the server provided one. */
1871 TAILQ_FOREACH(pe, &symrefs, entry) {
1872 struct got_reference *target_ref;
1873 const char *refname = pe->path;
1874 const char *target = pe->data;
1875 char *remote_refname = NULL, *remote_target = NULL;
1877 if (strcmp(refname, GOT_REF_HEAD) != 0)
1878 continue;
1880 error = got_ref_open(&target_ref, repo, target, 0);
1881 if (error) {
1882 if (error->code == GOT_ERR_NOT_REF) {
1883 error = NULL;
1884 continue;
1886 goto done;
1889 error = create_symref(refname, target_ref, verbosity, repo);
1890 got_ref_close(target_ref);
1891 if (error)
1892 goto done;
1894 if (mirror_references)
1895 continue;
1897 if (strncmp("refs/heads/", target, 11) != 0)
1898 continue;
1900 if (asprintf(&remote_refname,
1901 "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1902 refname) == -1) {
1903 error = got_error_from_errno("asprintf");
1904 goto done;
1906 if (asprintf(&remote_target,
1907 "refs/remotes/%s/%s", GOT_FETCH_DEFAULT_REMOTE_NAME,
1908 target + 11) == -1) {
1909 error = got_error_from_errno("asprintf");
1910 free(remote_refname);
1911 goto done;
1913 error = got_ref_open(&target_ref, repo, remote_target, 0);
1914 if (error) {
1915 free(remote_refname);
1916 free(remote_target);
1917 if (error->code == GOT_ERR_NOT_REF) {
1918 error = NULL;
1919 continue;
1921 goto done;
1923 error = create_symref(remote_refname, target_ref,
1924 verbosity - 1, repo);
1925 free(remote_refname);
1926 free(remote_target);
1927 got_ref_close(target_ref);
1928 if (error)
1929 goto done;
1931 if (pe == NULL) {
1933 * We failed to set the HEAD reference. If we asked for
1934 * a set of wanted branches use the first of one of those
1935 * which could be fetched instead.
1937 TAILQ_FOREACH(pe, &wanted_branches, entry) {
1938 const char *target = pe->path;
1939 struct got_reference *target_ref;
1941 error = got_ref_open(&target_ref, repo, target, 0);
1942 if (error) {
1943 if (error->code == GOT_ERR_NOT_REF) {
1944 error = NULL;
1945 continue;
1947 goto done;
1950 error = create_symref(GOT_REF_HEAD, target_ref,
1951 verbosity, repo);
1952 got_ref_close(target_ref);
1953 if (error)
1954 goto done;
1955 break;
1958 if (!fpa.configs_created && pe != NULL) {
1959 error = create_config_files(fpa.config_info.proto,
1960 fpa.config_info.host, fpa.config_info.port,
1961 fpa.config_info.remote_repo_path,
1962 fpa.config_info.git_url,
1963 fpa.config_info.fetch_all_branches,
1964 fpa.config_info.mirror_references,
1965 fpa.config_info.symrefs,
1966 fpa.config_info.wanted_branches,
1967 fpa.config_info.wanted_refs, fpa.repo);
1968 if (error)
1969 goto done;
1973 if (verbosity >= 0)
1974 printf("Created %s repository '%s'\n",
1975 mirror_references ? "mirrored" : "cloned", repo_path);
1976 done:
1977 if (pack_fds) {
1978 const struct got_error *pack_err =
1979 got_repo_pack_fds_close(pack_fds);
1980 if (error == NULL)
1981 error = pack_err;
1983 if (fetchpid > 0) {
1984 if (kill(fetchpid, SIGTERM) == -1)
1985 error = got_error_from_errno("kill");
1986 if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
1987 error = got_error_from_errno("waitpid");
1989 if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
1990 error = got_error_from_errno("close");
1991 if (repo) {
1992 const struct got_error *close_err = got_repo_close(repo);
1993 if (error == NULL)
1994 error = close_err;
1996 got_pathlist_free(&refs, GOT_PATHLIST_FREE_ALL);
1997 got_pathlist_free(&symrefs, GOT_PATHLIST_FREE_ALL);
1998 got_pathlist_free(&wanted_branches, GOT_PATHLIST_FREE_NONE);
1999 got_pathlist_free(&wanted_refs, GOT_PATHLIST_FREE_NONE);
2000 free(pack_hash);
2001 free(proto);
2002 free(host);
2003 free(port);
2004 free(server_path);
2005 free(repo_name);
2006 free(default_destdir);
2007 free(git_url);
2008 return error;
2011 static const struct got_error *
2012 update_ref(struct got_reference *ref, struct got_object_id *new_id,
2013 int replace_tags, int verbosity, struct got_repository *repo)
2015 const struct got_error *err = NULL;
2016 char *new_id_str = NULL;
2017 struct got_object_id *old_id = NULL;
2019 err = got_object_id_str(&new_id_str, new_id);
2020 if (err)
2021 goto done;
2023 if (!replace_tags &&
2024 strncmp(got_ref_get_name(ref), "refs/tags/", 10) == 0) {
2025 err = got_ref_resolve(&old_id, repo, ref);
2026 if (err)
2027 goto done;
2028 if (got_object_id_cmp(old_id, new_id) == 0)
2029 goto done;
2030 if (verbosity >= 0) {
2031 printf("Rejecting update of existing tag %s: %s\n",
2032 got_ref_get_name(ref), new_id_str);
2034 goto done;
2037 if (got_ref_is_symbolic(ref)) {
2038 if (verbosity >= 0) {
2039 printf("Replacing reference %s: %s\n",
2040 got_ref_get_name(ref),
2041 got_ref_get_symref_target(ref));
2043 err = got_ref_change_symref_to_ref(ref, new_id);
2044 if (err)
2045 goto done;
2046 err = got_ref_write(ref, repo);
2047 if (err)
2048 goto done;
2049 } else {
2050 err = got_ref_resolve(&old_id, repo, ref);
2051 if (err)
2052 goto done;
2053 if (got_object_id_cmp(old_id, new_id) == 0)
2054 goto done;
2056 err = got_ref_change_ref(ref, new_id);
2057 if (err)
2058 goto done;
2059 err = got_ref_write(ref, repo);
2060 if (err)
2061 goto done;
2064 if (verbosity >= 0)
2065 printf("Updated %s: %s\n", got_ref_get_name(ref),
2066 new_id_str);
2067 done:
2068 free(old_id);
2069 free(new_id_str);
2070 return err;
2073 static const struct got_error *
2074 update_symref(const char *refname, struct got_reference *target_ref,
2075 int verbosity, struct got_repository *repo)
2077 const struct got_error *err = NULL, *unlock_err;
2078 struct got_reference *symref;
2079 int symref_is_locked = 0;
2081 err = got_ref_open(&symref, repo, refname, 1);
2082 if (err) {
2083 if (err->code != GOT_ERR_NOT_REF)
2084 return err;
2085 err = got_ref_alloc_symref(&symref, refname, target_ref);
2086 if (err)
2087 goto done;
2089 err = got_ref_write(symref, repo);
2090 if (err)
2091 goto done;
2093 if (verbosity >= 0)
2094 printf("Created reference %s: %s\n",
2095 got_ref_get_name(symref),
2096 got_ref_get_symref_target(symref));
2097 } else {
2098 symref_is_locked = 1;
2100 if (strcmp(got_ref_get_symref_target(symref),
2101 got_ref_get_name(target_ref)) == 0)
2102 goto done;
2104 err = got_ref_change_symref(symref,
2105 got_ref_get_name(target_ref));
2106 if (err)
2107 goto done;
2109 err = got_ref_write(symref, repo);
2110 if (err)
2111 goto done;
2113 if (verbosity >= 0)
2114 printf("Updated %s: %s\n", got_ref_get_name(symref),
2115 got_ref_get_symref_target(symref));
2118 done:
2119 if (symref_is_locked) {
2120 unlock_err = got_ref_unlock(symref);
2121 if (unlock_err && err == NULL)
2122 err = unlock_err;
2124 got_ref_close(symref);
2125 return err;
2128 __dead static void
2129 usage_fetch(void)
2131 fprintf(stderr, "usage: %s fetch [-adlqtvX] [-b branch] "
2132 "[-R reference] [-r repository-path] [remote-repository]\n",
2133 getprogname());
2134 exit(1);
2137 static const struct got_error *
2138 delete_missing_ref(struct got_reference *ref,
2139 int verbosity, struct got_repository *repo)
2141 const struct got_error *err = NULL;
2142 struct got_object_id *id = NULL;
2143 char *id_str = NULL;
2145 if (got_ref_is_symbolic(ref)) {
2146 err = got_ref_delete(ref, repo);
2147 if (err)
2148 return err;
2149 if (verbosity >= 0) {
2150 printf("Deleted %s: %s\n",
2151 got_ref_get_name(ref),
2152 got_ref_get_symref_target(ref));
2154 } else {
2155 err = got_ref_resolve(&id, repo, ref);
2156 if (err)
2157 return err;
2158 err = got_object_id_str(&id_str, id);
2159 if (err)
2160 goto done;
2162 err = got_ref_delete(ref, repo);
2163 if (err)
2164 goto done;
2165 if (verbosity >= 0) {
2166 printf("Deleted %s: %s\n",
2167 got_ref_get_name(ref), id_str);
2170 done:
2171 free(id);
2172 free(id_str);
2173 return err;
2176 static const struct got_error *
2177 delete_missing_refs(struct got_pathlist_head *their_refs,
2178 struct got_pathlist_head *their_symrefs,
2179 const struct got_remote_repo *remote,
2180 int verbosity, struct got_repository *repo)
2182 const struct got_error *err = NULL, *unlock_err;
2183 struct got_reflist_head my_refs;
2184 struct got_reflist_entry *re;
2185 struct got_pathlist_entry *pe;
2186 char *remote_namespace = NULL;
2187 char *local_refname = NULL;
2189 TAILQ_INIT(&my_refs);
2191 if (asprintf(&remote_namespace, "refs/remotes/%s/", remote->name)
2192 == -1)
2193 return got_error_from_errno("asprintf");
2195 err = got_ref_list(&my_refs, repo, NULL, got_ref_cmp_by_name, NULL);
2196 if (err)
2197 goto done;
2199 TAILQ_FOREACH(re, &my_refs, entry) {
2200 const char *refname = got_ref_get_name(re->ref);
2201 const char *their_refname;
2203 if (remote->mirror_references) {
2204 their_refname = refname;
2205 } else {
2206 if (strncmp(refname, remote_namespace,
2207 strlen(remote_namespace)) == 0) {
2208 if (strcmp(refname + strlen(remote_namespace),
2209 GOT_REF_HEAD) == 0)
2210 continue;
2211 if (asprintf(&local_refname, "refs/heads/%s",
2212 refname + strlen(remote_namespace)) == -1) {
2213 err = got_error_from_errno("asprintf");
2214 goto done;
2216 } else if (strncmp(refname, "refs/tags/", 10) != 0)
2217 continue;
2219 their_refname = local_refname;
2222 TAILQ_FOREACH(pe, their_refs, entry) {
2223 if (strcmp(their_refname, pe->path) == 0)
2224 break;
2226 if (pe != NULL)
2227 continue;
2229 TAILQ_FOREACH(pe, their_symrefs, entry) {
2230 if (strcmp(their_refname, pe->path) == 0)
2231 break;
2233 if (pe != NULL)
2234 continue;
2236 err = delete_missing_ref(re->ref, verbosity, repo);
2237 if (err)
2238 break;
2240 if (local_refname) {
2241 struct got_reference *ref;
2242 err = got_ref_open(&ref, repo, local_refname, 1);
2243 if (err) {
2244 if (err->code != GOT_ERR_NOT_REF)
2245 break;
2246 free(local_refname);
2247 local_refname = NULL;
2248 continue;
2250 err = delete_missing_ref(ref, verbosity, repo);
2251 if (err)
2252 break;
2253 unlock_err = got_ref_unlock(ref);
2254 got_ref_close(ref);
2255 if (unlock_err && err == NULL) {
2256 err = unlock_err;
2257 break;
2260 free(local_refname);
2261 local_refname = NULL;
2264 done:
2265 got_ref_list_free(&my_refs);
2266 free(remote_namespace);
2267 free(local_refname);
2268 return err;
2271 static const struct got_error *
2272 update_wanted_ref(const char *refname, struct got_object_id *id,
2273 const char *remote_repo_name, int verbosity, struct got_repository *repo)
2275 const struct got_error *err, *unlock_err;
2276 char *remote_refname;
2277 struct got_reference *ref;
2279 if (strncmp("refs/", refname, 5) == 0)
2280 refname += 5;
2282 if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2283 remote_repo_name, refname) == -1)
2284 return got_error_from_errno("asprintf");
2286 err = got_ref_open(&ref, repo, remote_refname, 1);
2287 if (err) {
2288 if (err->code != GOT_ERR_NOT_REF)
2289 goto done;
2290 err = create_ref(remote_refname, id, verbosity, repo);
2291 } else {
2292 err = update_ref(ref, id, 0, verbosity, repo);
2293 unlock_err = got_ref_unlock(ref);
2294 if (unlock_err && err == NULL)
2295 err = unlock_err;
2296 got_ref_close(ref);
2298 done:
2299 free(remote_refname);
2300 return err;
2303 static const struct got_error *
2304 delete_ref(struct got_repository *repo, struct got_reference *ref)
2306 const struct got_error *err = NULL;
2307 struct got_object_id *id = NULL;
2308 char *id_str = NULL;
2309 const char *target;
2311 if (got_ref_is_symbolic(ref)) {
2312 target = got_ref_get_symref_target(ref);
2313 } else {
2314 err = got_ref_resolve(&id, repo, ref);
2315 if (err)
2316 goto done;
2317 err = got_object_id_str(&id_str, id);
2318 if (err)
2319 goto done;
2320 target = id_str;
2323 err = got_ref_delete(ref, repo);
2324 if (err)
2325 goto done;
2327 printf("Deleted %s: %s\n", got_ref_get_name(ref), target);
2328 done:
2329 free(id);
2330 free(id_str);
2331 return err;
2334 static const struct got_error *
2335 delete_refs_for_remote(struct got_repository *repo, const char *remote_name)
2337 const struct got_error *err = NULL;
2338 struct got_reflist_head refs;
2339 struct got_reflist_entry *re;
2340 char *prefix;
2342 TAILQ_INIT(&refs);
2344 if (asprintf(&prefix, "refs/remotes/%s", remote_name) == -1) {
2345 err = got_error_from_errno("asprintf");
2346 goto done;
2348 err = got_ref_list(&refs, repo, prefix, got_ref_cmp_by_name, NULL);
2349 if (err)
2350 goto done;
2352 TAILQ_FOREACH(re, &refs, entry)
2353 delete_ref(repo, re->ref);
2354 done:
2355 got_ref_list_free(&refs);
2356 return err;
2359 static const struct got_error *
2360 cmd_fetch(int argc, char *argv[])
2362 const struct got_error *error = NULL, *unlock_err;
2363 char *cwd = NULL, *repo_path = NULL;
2364 const char *remote_name;
2365 char *proto = NULL, *host = NULL, *port = NULL;
2366 char *repo_name = NULL, *server_path = NULL;
2367 const struct got_remote_repo *remotes;
2368 struct got_remote_repo *remote = NULL;
2369 int nremotes;
2370 char *id_str = NULL;
2371 struct got_repository *repo = NULL;
2372 struct got_worktree *worktree = NULL;
2373 const struct got_gotconfig *repo_conf = NULL, *worktree_conf = NULL;
2374 struct got_pathlist_head refs, symrefs, wanted_branches, wanted_refs;
2375 char *head_refname = NULL;
2376 struct got_pathlist_entry *pe;
2377 struct got_reflist_head remote_refs;
2378 struct got_reflist_entry *re;
2379 struct got_object_id *pack_hash = NULL;
2380 int i, ch, fetchfd = -1, fetchstatus;
2381 pid_t fetchpid = -1;
2382 struct got_fetch_progress_arg fpa;
2383 int verbosity = 0, fetch_all_branches = 0, list_refs_only = 0;
2384 int delete_refs = 0, replace_tags = 0, delete_remote = 0;
2385 int *pack_fds = NULL, have_bflag = 0;
2386 const char *remote_head = NULL, *worktree_branch = NULL;
2388 TAILQ_INIT(&refs);
2389 TAILQ_INIT(&symrefs);
2390 TAILQ_INIT(&remote_refs);
2391 TAILQ_INIT(&wanted_branches);
2392 TAILQ_INIT(&wanted_refs);
2394 while ((ch = getopt(argc, argv, "ab:dlqR:r:tvX")) != -1) {
2395 switch (ch) {
2396 case 'a':
2397 fetch_all_branches = 1;
2398 break;
2399 case 'b':
2400 error = got_pathlist_append(&wanted_branches,
2401 optarg, NULL);
2402 if (error)
2403 return error;
2404 have_bflag = 1;
2405 break;
2406 case 'd':
2407 delete_refs = 1;
2408 break;
2409 case 'l':
2410 list_refs_only = 1;
2411 break;
2412 case 'q':
2413 verbosity = -1;
2414 break;
2415 case 'R':
2416 error = got_pathlist_append(&wanted_refs,
2417 optarg, NULL);
2418 if (error)
2419 return error;
2420 break;
2421 case 'r':
2422 repo_path = realpath(optarg, NULL);
2423 if (repo_path == NULL)
2424 return got_error_from_errno2("realpath",
2425 optarg);
2426 got_path_strip_trailing_slashes(repo_path);
2427 break;
2428 case 't':
2429 replace_tags = 1;
2430 break;
2431 case 'v':
2432 if (verbosity < 0)
2433 verbosity = 0;
2434 else if (verbosity < 3)
2435 verbosity++;
2436 break;
2437 case 'X':
2438 delete_remote = 1;
2439 break;
2440 default:
2441 usage_fetch();
2442 break;
2445 argc -= optind;
2446 argv += optind;
2448 if (fetch_all_branches && !TAILQ_EMPTY(&wanted_branches))
2449 option_conflict('a', 'b');
2450 if (list_refs_only) {
2451 if (!TAILQ_EMPTY(&wanted_branches))
2452 option_conflict('l', 'b');
2453 if (fetch_all_branches)
2454 option_conflict('l', 'a');
2455 if (delete_refs)
2456 option_conflict('l', 'd');
2457 if (delete_remote)
2458 option_conflict('l', 'X');
2460 if (delete_remote) {
2461 if (fetch_all_branches)
2462 option_conflict('X', 'a');
2463 if (!TAILQ_EMPTY(&wanted_branches))
2464 option_conflict('X', 'b');
2465 if (delete_refs)
2466 option_conflict('X', 'd');
2467 if (replace_tags)
2468 option_conflict('X', 't');
2469 if (!TAILQ_EMPTY(&wanted_refs))
2470 option_conflict('X', 'R');
2473 if (argc == 0) {
2474 if (delete_remote)
2475 errx(1, "-X option requires a remote name");
2476 remote_name = GOT_FETCH_DEFAULT_REMOTE_NAME;
2477 } else if (argc == 1)
2478 remote_name = argv[0];
2479 else
2480 usage_fetch();
2482 cwd = getcwd(NULL, 0);
2483 if (cwd == NULL) {
2484 error = got_error_from_errno("getcwd");
2485 goto done;
2488 error = got_repo_pack_fds_open(&pack_fds);
2489 if (error != NULL)
2490 goto done;
2492 if (repo_path == NULL) {
2493 error = got_worktree_open(&worktree, cwd, GOT_WORKTREE_GOT_DIR);
2494 if (error && error->code != GOT_ERR_NOT_WORKTREE)
2495 goto done;
2496 else
2497 error = NULL;
2498 if (worktree) {
2499 repo_path =
2500 strdup(got_worktree_get_repo_path(worktree));
2501 if (repo_path == NULL)
2502 error = got_error_from_errno("strdup");
2503 if (error)
2504 goto done;
2505 } else {
2506 repo_path = strdup(cwd);
2507 if (repo_path == NULL) {
2508 error = got_error_from_errno("strdup");
2509 goto done;
2514 error = got_repo_open(&repo, repo_path, NULL, pack_fds);
2515 if (error)
2516 goto done;
2518 if (delete_remote) {
2519 error = delete_refs_for_remote(repo, remote_name);
2520 goto done; /* nothing else to do */
2523 if (worktree) {
2524 worktree_conf = got_worktree_get_gotconfig(worktree);
2525 if (worktree_conf) {
2526 got_gotconfig_get_remotes(&nremotes, &remotes,
2527 worktree_conf);
2528 for (i = 0; i < nremotes; i++) {
2529 if (strcmp(remotes[i].name, remote_name) == 0) {
2530 error = got_repo_remote_repo_dup(&remote,
2531 &remotes[i]);
2532 if (error)
2533 goto done;
2534 break;
2539 if (remote == NULL) {
2540 repo_conf = got_repo_get_gotconfig(repo);
2541 if (repo_conf) {
2542 got_gotconfig_get_remotes(&nremotes, &remotes,
2543 repo_conf);
2544 for (i = 0; i < nremotes; i++) {
2545 if (strcmp(remotes[i].name, remote_name) == 0) {
2546 error = got_repo_remote_repo_dup(&remote,
2547 &remotes[i]);
2548 if (error)
2549 goto done;
2550 break;
2555 if (remote == NULL) {
2556 got_repo_get_gitconfig_remotes(&nremotes, &remotes, repo);
2557 for (i = 0; i < nremotes; i++) {
2558 if (strcmp(remotes[i].name, remote_name) == 0) {
2559 error = got_repo_remote_repo_dup(&remote,
2560 &remotes[i]);
2561 if (error)
2562 goto done;
2563 break;
2567 if (remote == NULL) {
2568 error = got_error_path(remote_name, GOT_ERR_NO_REMOTE);
2569 goto done;
2572 if (TAILQ_EMPTY(&wanted_branches)) {
2573 if (!fetch_all_branches)
2574 fetch_all_branches = remote->fetch_all_branches;
2575 for (i = 0; i < remote->nfetch_branches; i++) {
2576 error = got_pathlist_append(&wanted_branches,
2577 remote->fetch_branches[i], NULL);
2578 if (error)
2579 goto done;
2582 if (TAILQ_EMPTY(&wanted_refs)) {
2583 for (i = 0; i < remote->nfetch_refs; i++) {
2584 error = got_pathlist_append(&wanted_refs,
2585 remote->fetch_refs[i], NULL);
2586 if (error)
2587 goto done;
2591 error = got_dial_parse_uri(&proto, &host, &port, &server_path,
2592 &repo_name, remote->fetch_url);
2593 if (error)
2594 goto done;
2596 if (strcmp(proto, "git") == 0) {
2597 #ifndef PROFILE
2598 if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2599 "sendfd dns inet unveil", NULL) == -1)
2600 err(1, "pledge");
2601 #endif
2602 } else if (strcmp(proto, "git+ssh") == 0 ||
2603 strcmp(proto, "ssh") == 0 ||
2604 strcmp(proto, "git+http") == 0 ||
2605 strcmp(proto, "http") == 0 ||
2606 strcmp(proto, "git+https") == 0 ||
2607 strcmp(proto, "https") == 0) {
2608 #ifndef PROFILE
2609 if (pledge("stdio rpath wpath cpath fattr flock proc exec "
2610 "sendfd unveil", NULL) == -1)
2611 err(1, "pledge");
2612 #endif
2613 } else {
2614 error = got_error_path(proto, GOT_ERR_BAD_PROTO);
2615 goto done;
2618 error = got_dial_apply_unveil(proto);
2619 if (error)
2620 goto done;
2622 error = apply_unveil(got_repo_get_path(repo), 0, NULL);
2623 if (error)
2624 goto done;
2626 if (worktree) {
2627 head_refname = strdup(got_worktree_get_head_ref_name(worktree));
2628 if (head_refname == NULL) {
2629 error = got_error_from_errno("strdup");
2630 goto done;
2633 /* Release work tree lock. */
2634 got_worktree_close(worktree);
2635 worktree = NULL;
2638 if (verbosity >= 0) {
2639 printf("Connecting to \"%s\" %s://%s%s%s%s%s\n",
2640 remote->name, proto, host,
2641 port ? ":" : "", port ? port : "",
2642 *server_path == '/' ? "" : "/", server_path);
2645 error = got_fetch_connect(&fetchpid, &fetchfd, proto, host, port,
2646 server_path, verbosity);
2647 if (error)
2648 goto done;
2649 #ifndef PROFILE
2650 if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd",
2651 NULL) == -1)
2652 err(1, "pledge");
2653 #endif
2654 if (!have_bflag) {
2656 * If set, get this remote's HEAD ref target so
2657 * if it has changed on the server we can fetch it.
2659 error = got_ref_list(&remote_refs, repo, "refs/remotes",
2660 got_ref_cmp_by_name, repo);
2661 if (error)
2662 goto done;
2664 TAILQ_FOREACH(re, &remote_refs, entry) {
2665 const char *remote_refname, *remote_target;
2666 size_t remote_name_len;
2668 if (!got_ref_is_symbolic(re->ref))
2669 continue;
2671 remote_name_len = strlen(remote->name);
2672 remote_refname = got_ref_get_name(re->ref);
2674 /* we only want refs/remotes/$remote->name/HEAD */
2675 if (strncmp(remote_refname + 13, remote->name,
2676 remote_name_len) != 0)
2677 continue;
2679 if (strcmp(remote_refname + remote_name_len + 14,
2680 GOT_REF_HEAD) != 0)
2681 continue;
2684 * Take the name itself because we already
2685 * only match with refs/heads/ in fetch_pack().
2687 remote_target = got_ref_get_symref_target(re->ref);
2688 remote_head = remote_target + remote_name_len + 14;
2689 break;
2692 if (head_refname &&
2693 strncmp(head_refname, "refs/heads/", 11) == 0)
2694 worktree_branch = head_refname;
2697 fpa.last_scaled_size[0] = '\0';
2698 fpa.last_p_indexed = -1;
2699 fpa.last_p_resolved = -1;
2700 fpa.verbosity = verbosity;
2701 fpa.repo = repo;
2702 fpa.create_configs = 0;
2703 fpa.configs_created = 0;
2704 memset(&fpa.config_info, 0, sizeof(fpa.config_info));
2706 error = got_fetch_pack(&pack_hash, &refs, &symrefs, remote->name,
2707 remote->mirror_references, fetch_all_branches, &wanted_branches,
2708 &wanted_refs, list_refs_only, verbosity, fetchfd, repo,
2709 worktree_branch, remote_head, have_bflag, fetch_progress, &fpa);
2710 if (error)
2711 goto done;
2713 if (list_refs_only) {
2714 error = list_remote_refs(&symrefs, &refs);
2715 goto done;
2718 if (pack_hash == NULL) {
2719 if (verbosity >= 0)
2720 printf("Already up-to-date\n");
2721 } else if (verbosity >= 0) {
2722 error = got_object_id_str(&id_str, pack_hash);
2723 if (error)
2724 goto done;
2725 printf("\nFetched %s.pack\n", id_str);
2726 free(id_str);
2727 id_str = NULL;
2730 /* Update references provided with the pack file. */
2731 TAILQ_FOREACH(pe, &refs, entry) {
2732 const char *refname = pe->path;
2733 struct got_object_id *id = pe->data;
2734 struct got_reference *ref;
2735 char *remote_refname;
2737 if (is_wanted_ref(&wanted_refs, refname) &&
2738 !remote->mirror_references) {
2739 error = update_wanted_ref(refname, id,
2740 remote->name, verbosity, repo);
2741 if (error)
2742 goto done;
2743 continue;
2746 if (remote->mirror_references ||
2747 strncmp("refs/tags/", refname, 10) == 0) {
2748 error = got_ref_open(&ref, repo, refname, 1);
2749 if (error) {
2750 if (error->code != GOT_ERR_NOT_REF)
2751 goto done;
2752 error = create_ref(refname, id, verbosity,
2753 repo);
2754 if (error)
2755 goto done;
2756 } else {
2757 error = update_ref(ref, id, replace_tags,
2758 verbosity, repo);
2759 unlock_err = got_ref_unlock(ref);
2760 if (unlock_err && error == NULL)
2761 error = unlock_err;
2762 got_ref_close(ref);
2763 if (error)
2764 goto done;
2766 } else if (strncmp("refs/heads/", refname, 11) == 0) {
2767 if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2768 remote_name, refname + 11) == -1) {
2769 error = got_error_from_errno("asprintf");
2770 goto done;
2773 error = got_ref_open(&ref, repo, remote_refname, 1);
2774 if (error) {
2775 if (error->code != GOT_ERR_NOT_REF)
2776 goto done;
2777 error = create_ref(remote_refname, id,
2778 verbosity, repo);
2779 if (error)
2780 goto done;
2781 } else {
2782 error = update_ref(ref, id, replace_tags,
2783 verbosity, repo);
2784 unlock_err = got_ref_unlock(ref);
2785 if (unlock_err && error == NULL)
2786 error = unlock_err;
2787 got_ref_close(ref);
2788 if (error)
2789 goto done;
2792 /* Also create a local branch if none exists yet. */
2793 error = got_ref_open(&ref, repo, refname, 1);
2794 if (error) {
2795 if (error->code != GOT_ERR_NOT_REF)
2796 goto done;
2797 error = create_ref(refname, id, verbosity,
2798 repo);
2799 if (error)
2800 goto done;
2801 } else {
2802 unlock_err = got_ref_unlock(ref);
2803 if (unlock_err && error == NULL)
2804 error = unlock_err;
2805 got_ref_close(ref);
2809 if (delete_refs) {
2810 error = delete_missing_refs(&refs, &symrefs, remote,
2811 verbosity, repo);
2812 if (error)
2813 goto done;
2816 if (!remote->mirror_references) {
2817 /* Update remote HEAD reference if the server provided one. */
2818 TAILQ_FOREACH(pe, &symrefs, entry) {
2819 struct got_reference *target_ref;
2820 const char *refname = pe->path;
2821 const char *target = pe->data;
2822 char *remote_refname = NULL, *remote_target = NULL;
2824 if (strcmp(refname, GOT_REF_HEAD) != 0)
2825 continue;
2827 if (strncmp("refs/heads/", target, 11) != 0)
2828 continue;
2830 if (asprintf(&remote_refname, "refs/remotes/%s/%s",
2831 remote->name, refname) == -1) {
2832 error = got_error_from_errno("asprintf");
2833 goto done;
2835 if (asprintf(&remote_target, "refs/remotes/%s/%s",
2836 remote->name, target + 11) == -1) {
2837 error = got_error_from_errno("asprintf");
2838 free(remote_refname);
2839 goto done;
2842 error = got_ref_open(&target_ref, repo, remote_target,
2844 if (error) {
2845 free(remote_refname);
2846 free(remote_target);
2847 if (error->code == GOT_ERR_NOT_REF) {
2848 error = NULL;
2849 continue;
2851 goto done;
2853 error = update_symref(remote_refname, target_ref,
2854 verbosity, repo);
2855 free(remote_refname);
2856 free(remote_target);
2857 got_ref_close(target_ref);
2858 if (error)
2859 goto done;
2862 done:
2863 if (fetchpid > 0) {
2864 if (kill(fetchpid, SIGTERM) == -1)
2865 error = got_error_from_errno("kill");
2866 if (waitpid(fetchpid, &fetchstatus, 0) == -1 && error == NULL)
2867 error = got_error_from_errno("waitpid");
2869 if (fetchfd != -1 && close(fetchfd) == -1 && error == NULL)
2870 error = got_error_from_errno("close");
2871 if (repo) {
2872 const struct got_error *close_err = got_repo_close(repo);
2873 if (error == NULL)
2874 error = close_err;
2876 if (worktree)
2877 got_worktree_close(worktree);
2878 if (pack_fds) {
2879 const struct got_error *pack_err =
2880 got_repo_pack_fds_close(pack_fds);
2881 if (error == NULL)
2882 error = pack_err;
2884 got_pathlist_free(&refs, GOT_PATHLIST_FREE_ALL);
2885 got_pathlist_free(&symrefs, GOT_PATHLIST_FREE_ALL);
2886 got_pathlist_free(&wanted_branches, GOT_PATHLIST_FREE_NONE);
2887 got_pathlist_free(&wanted_refs, GOT_PATHLIST_FREE_NONE);
2888 got_ref_list_free(&remote_refs);
2889 got_repo_free_remote_repo_data(remote);
2890 free(remote);
2891 free(head_refname);
2892 free(id_str);
2893 free(cwd);
2894 free(repo_path);
2895 free(pack_hash);
2896 free(proto);
2897 free(host);
2898 free(port);
2899 free(server_path);
2900 free(repo_name);
2901 return error;
2905 __dead static void
2906 usage_checkout(void)
2908 fprintf(stderr, "usage: %s checkout [-Eq] [-b branch] [-c commit] "
2909 "[-p path-prefix] repository-path [work-tree-path]\n",
2910 getprogname());
2911 exit(1);
2914 static void
2915 show_worktree_base_ref_warning(void)
2917 fprintf(stderr, "%s: warning: could not create a reference "
2918 "to the work tree's base commit; the commit could be "
2919 "garbage-collected by Git or 'gotadmin cleanup'; making the "
2920 "repository writable and running 'got update' will prevent this\n",
2921 getprogname());
2924 struct got_checkout_progress_arg {
2925 const char *worktree_path;
2926 int had_base_commit_ref_error;
2927 int verbosity;
2930 static const struct got_error *
2931 checkout_progress(void *arg, unsigned char status, const char *path)
2933 struct got_checkout_progress_arg *a = arg;
2935 /* Base commit bump happens silently. */
2936 if (status == GOT_STATUS_BUMP_BASE)
2937 return NULL;
2939 if (status == GOT_STATUS_BASE_REF_ERR) {
2940 a->had_base_commit_ref_error = 1;
2941 return NULL;
2944 while (path[0] == '/')
2945 path++;
2947 if (a->verbosity >= 0)
2948 printf("%c %s/%s\n", status, a->worktree_path, path);
2950 return NULL;
2953 static const struct got_error *
2954 check_cancelled(void *arg)
2956 if (sigint_received || sigpipe_received)
2957 return got_error(GOT_ERR_CANCELLED);
2958 return NULL;
2961 static const struct got_error *
2962 check_linear_ancestry(struct got_object_id *commit_id,
2963 struct got_object_id *base_commit_id, int allow_forwards_in_time_only,
2964 struct got_repository *repo)
2966 const struct got_error *err = NULL;
2967 struct got_object_id *yca_id;
2969 err = got_commit_graph_find_youngest_common_ancestor(&yca_id,
2970 commit_id, base_commit_id, 1, 0, repo, check_cancelled, NULL);
2971 if (err)
2972 return err;
2974 if (yca_id == NULL)
2975 return got_error(GOT_ERR_ANCESTRY);
2978 * Require a straight line of history between the target commit
2979 * and the work tree's base commit.
2981 * Non-linear situations such as this require a rebase:
2983 * (commit) D F (base_commit)
2984 * \ /
2985 * C E
2986 * \ /
2987 * B (yca)
2991 * 'got update' only handles linear cases:
2992 * Update forwards in time: A (base/yca) - B - C - D (commit)
2993 * Update backwards in time: D (base) - C - B - A (commit/yca)
2995 if (allow_forwards_in_time_only) {
2996 if (got_object_id_cmp(base_commit_id, yca_id) != 0)
2997 return got_error(GOT_ERR_ANCESTRY);
2998 } else if (got_object_id_cmp(commit_id, yca_id) != 0 &&
2999 got_object_id_cmp(base_commit_id, yca_id) != 0)
3000 return got_error(GOT_ERR_ANCESTRY);
3002 free(yca_id);
3003 return NULL;
3006 static const struct got_error *
3007 check_same_branch(struct got_object_id *commit_id,
3008 struct got_reference *head_ref, struct got_repository *repo)
3010 const struct got_error *err = NULL;
3011 struct got_commit_graph *graph = NULL;
3012 struct got_object_id *head_commit_id = NULL;
3014 err = got_ref_resolve(&head_commit_id, repo, head_ref);
3015 if (err)
3016 goto done;
3018 if (got_object_id_cmp(head_commit_id, commit_id) == 0)
3019 goto done;
3021 err = got_commit_graph_open(&graph, "/", 1);
3022 if (err)
3023 goto done;
3025 err = got_commit_graph_bfsort(graph, head_commit_id, repo,
3026 check_cancelled, NULL);
3027 if (err)
3028 goto done;
3030 for (;;) {
3031 struct got_object_id id;
3033 err = got_commit_graph_iter_next(&id, graph, repo,
3034 check_cancelled, NULL);
3035 if (err) {
3036 if (err->code == GOT_ERR_ITER_COMPLETED)
3037 err = got_error(GOT_ERR_ANCESTRY);
3038 break;
3041 if (got_object_id_cmp(&id, commit_id) == 0)
3042 break;
3044 done:
3045 if (graph)
3046 got_commit_graph_close(graph);
3047 free(head_commit_id);
3048 return err;
3051 static const struct got_error *
3052 checkout_ancestry_error(struct got_reference *ref, const char *commit_id_str)
3054 static char msg[512];
3055 const char *branch_name;
3057 if (got_ref_is_symbolic(ref))
3058 branch_name = got_ref_get_symref_target(ref);
3059 else
3060 branch_name = got_ref_get_name(ref);
3062 if (strncmp("refs/heads/", branch_name, 11) == 0)
3063 branch_name += 11;
3065 snprintf(msg, sizeof(msg),
3066 "target commit is not contained in branch '%s'; "
3067 "the branch to use must be specified with -b; "
3068 "if necessary a new branch can be created for "
3069 "this commit with 'got branch -c %s BRANCH_NAME'",
3070 branch_name, commit_id_str);
3072 return got_error_msg(GOT_ERR_ANCESTRY, msg);
3075 static const struct got_error *
3076 cmd_checkout(int argc, char *argv[])
3078 const struct got_error *close_err, *error = NULL;
3079 struct got_repository *repo = NULL;
3080 struct got_reference *head_ref = NULL, *ref = NULL;
3081 struct got_worktree *worktree = NULL;
3082 char *repo_path = NULL;
3083 char *worktree_path = NULL;
3084 const char *path_prefix = "";
3085 const char *branch_name = GOT_REF_HEAD, *refname = NULL;
3086 char *commit_id_str = NULL, *keyword_idstr = NULL;
3087 struct got_object_id *commit_id = NULL;
3088 char *cwd = NULL;
3089 int ch, same_path_prefix, allow_nonempty = 0, verbosity = 0;
3090 struct got_pathlist_head paths;
3091 struct got_checkout_progress_arg cpa;
3092 int *pack_fds = NULL;
3094 TAILQ_INIT(&paths);
3096 #ifndef PROFILE
3097 if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd "
3098 "unveil", NULL) == -1)
3099 err(1, "pledge");
3100 #endif
3102 while ((ch = getopt(argc, argv, "b:c:Ep:q")) != -1) {
3103 switch (ch) {
3104 case 'b':
3105 branch_name = optarg;
3106 break;
3107 case 'c':
3108 commit_id_str = strdup(optarg);
3109 if (commit_id_str == NULL)
3110 return got_error_from_errno("strdup");
3111 break;
3112 case 'E':
3113 allow_nonempty = 1;
3114 break;
3115 case 'p':
3116 path_prefix = optarg;
3117 break;
3118 case 'q':
3119 verbosity = -1;
3120 break;
3121 default:
3122 usage_checkout();
3123 /* NOTREACHED */
3127 argc -= optind;
3128 argv += optind;
3130 if (argc == 1) {
3131 char *base, *dotgit;
3132 const char *path;
3133 repo_path = realpath(argv[0], NULL);
3134 if (repo_path == NULL)
3135 return got_error_from_errno2("realpath", argv[0]);
3136 cwd = getcwd(NULL, 0);
3137 if (cwd == NULL) {
3138 error = got_error_from_errno("getcwd");
3139 goto done;
3141 if (path_prefix[0])
3142 path = path_prefix;
3143 else
3144 path = repo_path;
3145 error = got_path_basename(&base, path);
3146 if (error)
3147 goto done;
3148 dotgit = strstr(base, ".git");
3149 if (dotgit)
3150 *dotgit = '\0';
3151 if (asprintf(&worktree_path, "%s/%s", cwd, base) == -1) {
3152 error = got_error_from_errno("asprintf");
3153 free(base);
3154 goto done;
3156 free(base);
3157 } else if (argc == 2) {
3158 repo_path = realpath(argv[0], NULL);
3159 if (repo_path == NULL) {
3160 error = got_error_from_errno2("realpath", argv[0]);
3161 goto done;
3163 worktree_path = realpath(argv[1], NULL);
3164 if (worktree_path == NULL) {
3165 if (errno != ENOENT) {
3166 error = got_error_from_errno2("realpath",
3167 argv[1]);
3168 goto done;
3170 worktree_path = strdup(argv[1]);
3171 if (worktree_path == NULL) {
3172 error = got_error_from_errno("strdup");
3173 goto done;
3176 } else
3177 usage_checkout();
3179 got_path_strip_trailing_slashes(repo_path);
3180 got_path_strip_trailing_slashes(worktree_path);
3182 if (got_path_is_child(worktree_path, repo_path, strlen(repo_path)) ||
3183 got_path_is_child(repo_path, worktree_path,
3184 strlen(worktree_path))) {
3185 error = got_error_fmt(GOT_ERR_BAD_PATH,
3186 "work tree and repository paths may not overlap: %s",
3187 worktree_path);
3188 goto done;
3191 error = got_repo_pack_fds_open(&pack_fds);
3192 if (error != NULL)
3193 goto done;
3195 error = got_repo_open(&repo, repo_path, NULL, pack_fds);
3196 if (error != NULL)
3197 goto done;
3199 /* Pre-create work tree path for unveil(2) */
3200 error = got_path_mkdir(worktree_path);
3201 if (error) {
3202 if (!(error->code == GOT_ERR_ERRNO && errno == EISDIR) &&
3203 !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
3204 goto done;
3205 if (!allow_nonempty &&
3206 !got_path_dir_is_empty(worktree_path)) {
3207 error = got_error_path(worktree_path,
3208 GOT_ERR_DIR_NOT_EMPTY);
3209 goto done;
3213 error = apply_unveil(got_repo_get_path(repo), 0, worktree_path);
3214 if (error)
3215 goto done;
3217 error = got_ref_open(&head_ref, repo, branch_name, 0);
3218 if (error != NULL)
3219 goto done;
3221 error = got_worktree_init(worktree_path, head_ref, path_prefix,
3222 GOT_WORKTREE_GOT_DIR, repo);
3223 if (error != NULL && !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
3224 goto done;
3226 error = got_worktree_open(&worktree, worktree_path,
3227 GOT_WORKTREE_GOT_DIR);
3228 if (error != NULL)
3229 goto done;
3231 error = got_worktree_match_path_prefix(&same_path_prefix, worktree,
3232 path_prefix);
3233 if (error != NULL)
3234 goto done;
3235 if (!same_path_prefix) {
3236 error = got_error(GOT_ERR_PATH_PREFIX);
3237 goto done;
3240 if (commit_id_str) {
3241 struct got_reflist_head refs;
3242 TAILQ_INIT(&refs);
3243 error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name,
3244 NULL);
3245 if (error)
3246 goto done;
3248 error = got_keyword_to_idstr(&keyword_idstr, commit_id_str,
3249 repo, worktree);
3250 if (error != NULL)
3251 goto done;
3252 if (keyword_idstr != NULL) {
3253 free(commit_id_str);
3254 commit_id_str = keyword_idstr;
3257 error = got_repo_match_object_id(&commit_id, NULL,
3258 commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo);
3259 got_ref_list_free(&refs);
3260 if (error)
3261 goto done;
3262 error = check_linear_ancestry(commit_id,
3263 got_worktree_get_base_commit_id(worktree), 0, repo);
3264 if (error != NULL) {
3265 if (error->code == GOT_ERR_ANCESTRY) {
3266 error = checkout_ancestry_error(
3267 head_ref, commit_id_str);
3269 goto done;
3271 error = check_same_branch(commit_id, head_ref, repo);
3272 if (error) {
3273 if (error->code == GOT_ERR_ANCESTRY) {
3274 error = checkout_ancestry_error(
3275 head_ref, commit_id_str);
3277 goto done;
3279 error = got_worktree_set_base_commit_id(worktree, repo,
3280 commit_id);
3281 if (error)
3282 goto done;
3283 /* Expand potentially abbreviated commit ID string. */
3284 free(commit_id_str);
3285 error = got_object_id_str(&commit_id_str, commit_id);
3286 if (error)
3287 goto done;
3288 } else {
3289 commit_id = got_object_id_dup(
3290 got_worktree_get_base_commit_id(worktree));
3291 if (commit_id == NULL) {
3292 error = got_error_from_errno("got_object_id_dup");
3293 goto done;
3295 error = got_object_id_str(&commit_id_str, commit_id);
3296 if (error)
3297 goto done;
3300 error = got_pathlist_append(&paths, "", NULL);
3301 if (error)
3302 goto done;
3303 cpa.worktree_path = worktree_path;
3304 cpa.had_base_commit_ref_error = 0;
3305 cpa.verbosity = verbosity;
3306 error = got_worktree_checkout_files(worktree, &paths, repo,
3307 checkout_progress, &cpa, check_cancelled, NULL);
3308 if (error != NULL)
3309 goto done;
3311 if (got_ref_is_symbolic(head_ref)) {
3312 error = got_ref_resolve_symbolic(&ref, repo, head_ref);
3313 if (error)
3314 goto done;
3315 refname = got_ref_get_name(ref);
3316 } else
3317 refname = got_ref_get_name(head_ref);
3318 printf("Checked out %s: %s\n", refname, commit_id_str);
3319 printf("Now shut up and hack\n");
3320 if (cpa.had_base_commit_ref_error)
3321 show_worktree_base_ref_warning();
3322 done:
3323 if (pack_fds) {
3324 const struct got_error *pack_err =
3325 got_repo_pack_fds_close(pack_fds);
3326 if (error == NULL)
3327 error = pack_err;
3329 if (head_ref)
3330 got_ref_close(head_ref);
3331 if (ref)
3332 got_ref_close(ref);
3333 if (repo) {
3334 close_err = got_repo_close(repo);
3335 if (error == NULL)
3336 error = close_err;
3338 if (worktree != NULL) {
3339 close_err = got_worktree_close(worktree);
3340 if (error == NULL)
3341 error = close_err;
3343 got_pathlist_free(&paths, GOT_PATHLIST_FREE_NONE);
3344 free(commit_id_str);
3345 free(commit_id);
3346 free(repo_path);
3347 free(worktree_path);
3348 free(cwd);
3349 return error;
3352 struct got_update_progress_arg {
3353 int did_something;
3354 int conflicts;
3355 int obstructed;
3356 int not_updated;
3357 int missing;
3358 int not_deleted;
3359 int unversioned;
3360 int verbosity;
3363 static void
3364 print_update_progress_stats(struct got_update_progress_arg *upa)
3366 if (!upa->did_something)
3367 return;
3369 if (upa->conflicts > 0)
3370 printf("Files with new merge conflicts: %d\n", upa->conflicts);
3371 if (upa->obstructed > 0)
3372 printf("File paths obstructed by a non-regular file: %d\n",
3373 upa->obstructed);
3374 if (upa->not_updated > 0)
3375 printf("Files not updated because of existing merge "
3376 "conflicts: %d\n", upa->not_updated);
3380 * The meaning of some status codes differs between merge-style operations and
3381 * update operations. For example, the ! status code means "file was missing"
3382 * if changes were merged into the work tree, and "missing file was restored"
3383 * if the work tree was updated. This function should be used by any operation
3384 * which merges changes into the work tree without updating the work tree.
3386 static void
3387 print_merge_progress_stats(struct got_update_progress_arg *upa)
3389 if (!upa->did_something)
3390 return;
3392 if (upa->conflicts > 0)
3393 printf("Files with new merge conflicts: %d\n", upa->conflicts);
3394 if (upa->obstructed > 0)
3395 printf("File paths obstructed by a non-regular file: %d\n",
3396 upa->obstructed);
3397 if (upa->missing > 0)
3398 printf("Files which had incoming changes but could not be "
3399 "found in the work tree: %d\n", upa->missing);
3400 if (upa->not_deleted > 0)
3401 printf("Files not deleted due to differences in deleted "
3402 "content: %d\n", upa->not_deleted);
3403 if (upa->unversioned > 0)
3404 printf("Files not merged because an unversioned file was "
3405 "found in the work tree: %d\n", upa->unversioned);
3408 __dead static void
3409 usage_update(void)
3411 fprintf(stderr, "usage: %s update [-q] [-b branch] [-c commit] "
3412 "[path ...]\n", getprogname());
3413 exit(1);
3416 static const struct got_error *
3417 update_progress(void *arg, unsigned char status, const char *path)
3419 struct got_update_progress_arg *upa = arg;
3421 if (status == GOT_STATUS_EXISTS ||
3422 status == GOT_STATUS_BASE_REF_ERR)
3423 return NULL;
3425 upa->did_something = 1;
3427 /* Base commit bump happens silently. */
3428 if (status == GOT_STATUS_BUMP_BASE)
3429 return NULL;
3431 if (status == GOT_STATUS_CONFLICT)
3432 upa->conflicts++;
3433 if (status == GOT_STATUS_OBSTRUCTED)
3434 upa->obstructed++;
3435 if (status == GOT_STATUS_CANNOT_UPDATE)
3436 upa->not_updated++;
3437 if (status == GOT_STATUS_MISSING)
3438 upa->missing++;
3439 if (status == GOT_STATUS_CANNOT_DELETE)
3440 upa->not_deleted++;
3441 if (status == GOT_STATUS_UNVERSIONED)
3442 upa->unversioned++;
3444 while (path[0] == '/')
3445 path++;
3446 if (upa->verbosity >= 0)
3447 printf("%c %s\n", status, path);
3449 return NULL;
3452 static const struct got_error *
3453 switch_head_ref(struct got_reference *head_ref,
3454 struct got_object_id *commit_id, struct got_worktree *worktree,
3455 struct got_repository *repo)
3457 const struct got_error *err = NULL;
3458 char *base_id_str;
3459 int ref_has_moved = 0;
3461 /* Trivial case: switching between two different references. */
3462 if (strcmp(got_ref_get_name(head_ref),
3463 got_worktree_get_head_ref_name(worktree)) != 0) {
3464 printf("Switching work tree from %s to %s\n",
3465 got_worktree_get_head_ref_name(worktree),
3466 got_ref_get_name(head_ref));
3467 return got_worktree_set_head_ref(worktree, head_ref);
3470 err = check_linear_ancestry(commit_id,
3471 got_worktree_get_base_commit_id(worktree), 0, repo);
3472 if (err) {
3473 if (err->code != GOT_ERR_ANCESTRY)
3474 return err;
3475 ref_has_moved = 1;
3477 if (!ref_has_moved)
3478 return NULL;
3480 /* Switching to a rebased branch with the same reference name. */
3481 err = got_object_id_str(&base_id_str,
3482 got_worktree_get_base_commit_id(worktree));
3483 if (err)
3484 return err;
3485 printf("Reference %s now points at a different branch\n",
3486 got_worktree_get_head_ref_name(worktree));
3487 printf("Switching work tree from %s to %s\n", base_id_str,
3488 got_worktree_get_head_ref_name(worktree));
3489 return NULL;
3492 static const struct got_error *
3493 check_rebase_or_histedit_in_progress(struct got_worktree *worktree)
3495 const struct got_error *err;
3496 int in_progress;
3498 err = got_worktree_rebase_in_progress(&in_progress, worktree);
3499 if (err)
3500 return err;
3501 if (in_progress)
3502 return got_error(GOT_ERR_REBASING);
3504 err = got_worktree_histedit_in_progress(&in_progress, worktree);
3505 if (err)
3506 return err;
3507 if (in_progress)
3508 return got_error(GOT_ERR_HISTEDIT_BUSY);
3510 return NULL;
3513 static const struct got_error *
3514 check_merge_in_progress(struct got_worktree *worktree,
3515 struct got_repository *repo)
3517 const struct got_error *err;
3518 int in_progress;
3520 err = got_worktree_merge_in_progress(&in_progress, worktree, repo);
3521 if (err)
3522 return err;
3523 if (in_progress)
3524 return got_error(GOT_ERR_MERGE_BUSY);
3526 return NULL;
3529 static const struct got_error *
3530 get_worktree_paths_from_argv(struct got_pathlist_head *paths, int argc,
3531 char *argv[], struct got_worktree *worktree)
3533 const struct got_error *err = NULL;
3534 char *path;
3535 struct got_pathlist_entry *new;
3536 int i;
3538 if (argc == 0) {
3539 path = strdup("");
3540 if (path == NULL)
3541 return got_error_from_errno("strdup");
3542 return got_pathlist_append(paths, path, NULL);
3545 for (i = 0; i < argc; i++) {
3546 err = got_worktree_resolve_path(&path, worktree, argv[i]);
3547 if (err)
3548 break;
3549 err = got_pathlist_insert(&new, paths, path, NULL);
3550 if (err || new == NULL /* duplicate */) {
3551 free(path);
3552 if (err)
3553 break;
3557 return err;
3560 static const struct got_error *
3561 wrap_not_worktree_error(const struct got_error *orig_err,
3562 const char *cmdname, const char *path)
3564 const struct got_error *err;
3565 struct got_repository *repo;
3566 static char msg[512];
3567 int *pack_fds = NULL;
3569 err = got_repo_pack_fds_open(&pack_fds);
3570 if (err)
3571 return err;
3573 err = got_repo_open(&repo, path, NULL, pack_fds);
3574 if (err)
3575 return orig_err;
3577 snprintf(msg, sizeof(msg),
3578 "'got %s' needs a work tree in addition to a git repository\n"
3579 "Work trees can be checked out from this Git repository with "
3580 "'got checkout'.\n"
3581 "The got(1) manual page contains more information.", cmdname);
3582 err = got_error_msg(GOT_ERR_NOT_WORKTREE, msg);
3583 if (repo) {
3584 const struct got_error *close_err = got_repo_close(repo);
3585 if (err == NULL)
3586 err = close_err;
3588 if (pack_fds) {
3589 const struct got_error *pack_err =
3590 got_repo_pack_fds_close(pack_fds);
3591 if (err == NULL)
3592 err = pack_err;
3594 return err;
3597 static const struct got_error *
3598 cmd_update(int argc, char *argv[])
3600 const struct got_error *close_err, *error = NULL;
3601 struct got_repository *repo = NULL;
3602 struct got_worktree *worktree = NULL;
3603 char *worktree_path = NULL;
3604 struct got_object_id *commit_id = NULL;
3605 char *commit_id_str = NULL;
3606 const char *branch_name = NULL;
3607 struct got_reference *head_ref = NULL;
3608 struct got_pathlist_head paths;
3609 struct got_pathlist_entry *pe;
3610 int ch, verbosity = 0;
3611 struct got_update_progress_arg upa;
3612 int *pack_fds = NULL;
3614 TAILQ_INIT(&paths);
3616 #ifndef PROFILE
3617 if (pledge("stdio rpath wpath cpath fattr flock proc exec sendfd "
3618 "unveil", NULL) == -1)
3619 err(1, "pledge");
3620 #endif
3622 while ((ch = getopt(argc, argv, "b:c:q")) != -1) {
3623 switch (ch) {
3624 case 'b':
3625 branch_name = optarg;
3626 break;
3627 case 'c':
3628 commit_id_str = strdup(optarg);
3629 if (commit_id_str == NULL)
3630 return got_error_from_errno("strdup");
3631 break;
3632 case 'q':
3633 verbosity = -1;
3634 break;
3635 default:
3636 usage_update();
3637 /* NOTREACHED */
3641 argc -= optind;
3642 argv += optind;
3644 worktree_path = getcwd(NULL, 0);
3645 if (worktree_path == NULL) {
3646 error = got_error_from_errno("getcwd");
3647 goto done;
3650 error = got_repo_pack_fds_open(&pack_fds);
3651 if (error != NULL)
3652 goto done;
3654 error = got_worktree_open(&worktree, worktree_path,
3655 GOT_WORKTREE_GOT_DIR);
3656 if (error) {
3657 if (error->code == GOT_ERR_NOT_WORKTREE)
3658 error = wrap_not_worktree_error(error, "update",
3659 worktree_path);
3660 goto done;
3663 error = check_rebase_or_histedit_in_progress(worktree);
3664 if (error)
3665 goto done;
3667 error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
3668 NULL, pack_fds);
3669 if (error != NULL)
3670 goto done;
3672 error = apply_unveil(got_repo_get_path(repo), 0,
3673 got_worktree_get_root_path(worktree));
3674 if (error)
3675 goto done;
3677 error = check_merge_in_progress(worktree, repo);
3678 if (error)
3679 goto done;
3681 error = get_worktree_paths_from_argv(&paths, argc, argv, worktree);
3682 if (error)
3683 goto done;
3685 error = got_ref_open(&head_ref, repo, branch_name ? branch_name :
3686 got_worktree_get_head_ref_name(worktree), 0);
3687 if (error != NULL)
3688 goto done;
3689 if (commit_id_str == NULL) {
3690 error = got_ref_resolve(&commit_id, repo, head_ref);
3691 if (error != NULL)
3692 goto done;
3693 error = got_object_id_str(&commit_id_str, commit_id);
3694 if (error != NULL)
3695 goto done;
3696 } else {
3697 struct got_reflist_head refs;
3698 char *keyword_idstr = NULL;
3700 TAILQ_INIT(&refs);
3702 error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name,
3703 NULL);
3704 if (error)
3705 goto done;
3707 error = got_keyword_to_idstr(&keyword_idstr, commit_id_str,
3708 repo, worktree);
3709 if (error != NULL)
3710 goto done;
3711 if (keyword_idstr != NULL) {
3712 free(commit_id_str);
3713 commit_id_str = keyword_idstr;
3716 error = got_repo_match_object_id(&commit_id, NULL,
3717 commit_id_str, GOT_OBJ_TYPE_COMMIT, &refs, repo);
3718 got_ref_list_free(&refs);
3719 free(commit_id_str);
3720 commit_id_str = NULL;
3721 if (error)
3722 goto done;
3723 error = got_object_id_str(&commit_id_str, commit_id);
3724 if (error)
3725 goto done;
3728 if (branch_name) {
3729 struct got_object_id *head_commit_id;
3730 TAILQ_FOREACH(pe, &paths, entry) {
3731 if (pe->path_len == 0)
3732 continue;
3733 error = got_error_msg(GOT_ERR_BAD_PATH,
3734 "switching between branches requires that "
3735 "the entire work tree gets updated");
3736 goto done;
3738 error = got_ref_resolve(&head_commit_id, repo, head_ref);
3739 if (error)
3740 goto done;
3741 error = check_linear_ancestry(commit_id, head_commit_id, 0,
3742 repo);
3743 free(head_commit_id);
3744 if (error != NULL)
3745 goto done;
3746 error = check_same_branch(commit_id, head_ref, repo);
3747 if (error)
3748 goto done;
3749 error = switch_head_ref(head_ref, commit_id, worktree, repo);
3750 if (error)
3751 goto done;
3752 } else {
3753 error = check_linear_ancestry(commit_id,
3754 got_worktree_get_base_commit_id(worktree), 0, repo);
3755 if (error != NULL) {
3756 if (error->code == GOT_ERR_ANCESTRY)
3757 error = got_error(GOT_ERR_BRANCH_MOVED);
3758 goto done;
3760 error = check_same_branch(commit_id, head_ref, repo);
3761 if (error)
3762 goto done;
3765 if (got_object_id_cmp(got_worktree_get_base_commit_id(worktree),
3766 commit_id) != 0) {
3767 error = got_worktree_set_base_commit_id(worktree, repo,
3768 commit_id);
3769 if (error)
3770 goto done;
3773 memset(&upa, 0, sizeof(upa));
3774 upa.verbosity = verbosity;
3775 error = got_worktree_checkout_files(worktree, &paths, repo,
3776 update_progress, &upa, check_cancelled, NULL);
3777 if (error != NULL)
3778 goto done;
3780 if (upa.did_something) {
3781 printf("Updated to %s: %s\n",
3782 got_worktree_get_head_ref_name(worktree), commit_id_str);
3783 } else
3784 printf("Already up-to-date\n");
3786 print_update_progress_stats(&upa);
3787 done:
3788 if (pack_fds) {
3789 const struct got_error *pack_err =
3790 got_repo_pack_fds_close(pack_fds);
3791 if (error == NULL)
3792 error = pack_err;
3794 if (repo) {
3795 close_err = got_repo_close(repo);
3796 if (error == NULL)
3797 error = close_err;
3799 if (worktree != NULL) {
3800 close_err = got_worktree_close(worktree);
3801 if (error == NULL)
3802 error = close_err;
3804 if (head_ref != NULL)
3805 got_ref_close(head_ref);
3806 free(worktree_path);
3807 got_pathlist_free(&paths, GOT_PATHLIST_FREE_PATH);
3808 free(commit_id);
3809 free(commit_id_str);
3810 return error;
3813 static const struct got_error *
3814 diff_blobs(struct got_object_id *blob_id1, struct got_object_id *blob_id2,
3815 const char *path, int diff_context, int ignore_whitespace,
3816 int force_text_diff, struct got_diffstat_cb_arg *dsa,
3817 struct got_repository *repo, FILE *outfile)
3819 const struct got_error *err = NULL;
3820 struct got_blob_object *blob1 = NULL, *blob2 = NULL;
3821 FILE *f1 = NULL, *f2 = NULL;
3822 int fd1 = -1, fd2 = -1;
3824 fd1 = got_opentempfd();
3825 if (fd1 == -1)
3826 return got_error_from_errno("got_opentempfd");
3827 fd2 = got_opentempfd();
3828 if (fd2 == -1) {
3829 err = got_error_from_errno("got_opentempfd");
3830 goto done;
3833 if (blob_id1) {
3834 err = got_object_open_as_blob(&blob1, repo, blob_id1, 8192,
3835 fd1);
3836 if (err)
3837 goto done;
3840 err = got_object_open_as_blob(&blob2, repo, blob_id2, 8192, fd2);
3841 if (err)
3842 goto done;
3844 f1 = got_opentemp();
3845 if (f1 == NULL) {
3846 err = got_error_from_errno("got_opentemp");
3847 goto done;
3849 f2 = got_opentemp();
3850 if (f2 == NULL) {
3851 err = got_error_from_errno("got_opentemp");
3852 goto done;
3855 while (path[0] == '/')
3856 path++;
3857 err = got_diff_blob(NULL, NULL, blob1, blob2, f1, f2, path, path,
3858 GOT_DIFF_ALGORITHM_PATIENCE, diff_context, ignore_whitespace,
3859 force_text_diff, dsa, outfile);
3860 done:
3861 if (fd1 != -1 && close(fd1) == -1 && err == NULL)
3862 err = got_error_from_errno("close");
3863 if (blob1)
3864 got_object_blob_close(blob1);
3865 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
3866 err = got_error_from_errno("close");
3867 if (blob2)
3868 got_object_blob_close(blob2);
3869 if (f1 && fclose(f1) == EOF && err == NULL)
3870 err = got_error_from_errno("fclose");
3871 if (f2 && fclose(f2) == EOF && err == NULL)
3872 err = got_error_from_errno("fclose");
3873 return err;
3876 static const struct got_error *
3877 diff_trees(struct got_object_id *tree_id1, struct got_object_id *tree_id2,
3878 const char *path, int diff_context, int ignore_whitespace,
3879 int force_text_diff, struct got_diffstat_cb_arg *dsa,
3880 struct got_repository *repo, FILE *outfile)
3882 const struct got_error *err = NULL;
3883 struct got_tree_object *tree1 = NULL, *tree2 = NULL;
3884 struct got_diff_blob_output_unidiff_arg arg;
3885 FILE *f1 = NULL, *f2 = NULL;
3886 int fd1 = -1, fd2 = -1;
3888 if (tree_id1) {
3889 err = got_object_open_as_tree(&tree1, repo, tree_id1);
3890 if (err)
3891 goto done;
3892 fd1 = got_opentempfd();
3893 if (fd1 == -1) {
3894 err = got_error_from_errno("got_opentempfd");
3895 goto done;
3899 err = got_object_open_as_tree(&tree2, repo, tree_id2);
3900 if (err)
3901 goto done;
3903 f1 = got_opentemp();
3904 if (f1 == NULL) {
3905 err = got_error_from_errno("got_opentemp");
3906 goto done;
3909 f2 = got_opentemp();
3910 if (f2 == NULL) {
3911 err = got_error_from_errno("got_opentemp");
3912 goto done;
3914 fd2 = got_opentempfd();
3915 if (fd2 == -1) {
3916 err = got_error_from_errno("got_opentempfd");
3917 goto done;
3919 arg.diff_context = diff_context;
3920 arg.ignore_whitespace = ignore_whitespace;
3921 arg.force_text_diff = force_text_diff;
3922 arg.diffstat = dsa;
3923 arg.diff_algo = GOT_DIFF_ALGORITHM_PATIENCE;
3924 arg.outfile = outfile;
3925 arg.lines = NULL;
3926 arg.nlines = 0;
3927 while (path[0] == '/')
3928 path++;
3929 err = got_diff_tree(tree1, tree2, f1, f2, fd1, fd2, path, path, repo,
3930 got_diff_blob_output_unidiff, &arg, 1);
3931 done:
3932 if (tree1)
3933 got_object_tree_close(tree1);
3934 if (tree2)
3935 got_object_tree_close(tree2);
3936 if (f1 && fclose(f1) == EOF && err == NULL)
3937 err = got_error_from_errno("fclose");
3938 if (f2 && fclose(f2) == EOF && err == NULL)
3939 err = got_error_from_errno("fclose");
3940 if (fd1 != -1 && close(fd1) == -1 && err == NULL)
3941 err = got_error_from_errno("close");
3942 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
3943 err = got_error_from_errno("close");
3944 return err;
3947 static const struct got_error *
3948 get_changed_paths(struct got_pathlist_head *paths,
3949 struct got_commit_object *commit, struct got_repository *repo,
3950 struct got_diffstat_cb_arg *dsa)
3952 const struct got_error *err = NULL;
3953 struct got_object_id *tree_id1 = NULL, *tree_id2 = NULL;
3954 struct got_tree_object *tree1 = NULL, *tree2 = NULL;
3955 struct got_object_qid *qid;
3956 got_diff_blob_cb cb = got_diff_tree_collect_changed_paths;
3957 FILE *f1 = NULL, *f2 = NULL;
3958 int fd1 = -1, fd2 = -1;
3960 if (dsa) {
3961 cb = got_diff_tree_compute_diffstat;
3963 f1 = got_opentemp();
3964 if (f1 == NULL) {
3965 err = got_error_from_errno("got_opentemp");
3966 goto done;
3968 f2 = got_opentemp();
3969 if (f2 == NULL) {
3970 err = got_error_from_errno("got_opentemp");
3971 goto done;
3973 fd1 = got_opentempfd();
3974 if (fd1 == -1) {
3975 err = got_error_from_errno("got_opentempfd");
3976 goto done;
3978 fd2 = got_opentempfd();
3979 if (fd2 == -1) {
3980 err = got_error_from_errno("got_opentempfd");
3981 goto done;
3985 qid = STAILQ_FIRST(got_object_commit_get_parent_ids(commit));
3986 if (qid != NULL) {
3987 struct got_commit_object *pcommit;
3988 err = got_object_open_as_commit(&pcommit, repo,
3989 &qid->id);
3990 if (err)
3991 return err;
3993 tree_id1 = got_object_id_dup(
3994 got_object_commit_get_tree_id(pcommit));
3995 if (tree_id1 == NULL) {
3996 got_object_commit_close(pcommit);
3997 return got_error_from_errno("got_object_id_dup");
3999 got_object_commit_close(pcommit);
4003 if (tree_id1) {
4004 err = got_object_open_as_tree(&tree1, repo, tree_id1);
4005 if (err)
4006 goto done;
4009 tree_id2 = got_object_commit_get_tree_id(commit);
4010 err = got_object_open_as_tree(&tree2, repo, tree_id2);
4011 if (err)
4012 goto done;
4014 err = got_diff_tree(tree1, tree2, f1, f2, fd1, fd2, "", "", repo,
4015 cb, dsa ? (void *)dsa : paths, dsa ? 1 : 0);
4016 done:
4017 if (tree1)
4018 got_object_tree_close(tree1);
4019 if (tree2)
4020 got_object_tree_close(tree2);
4021 if (fd1 != -1 && close(fd1) == -1 && err == NULL)
4022 err = got_error_from_errno("close");
4023 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
4024 err = got_error_from_errno("close");
4025 if (f1 && fclose(f1) == EOF && err == NULL)
4026 err = got_error_from_errno("fclose");
4027 if (f2 && fclose(f2) == EOF && err == NULL)
4028 err = got_error_from_errno("fclose");
4029 free(tree_id1);
4030 return err;
4033 static const struct got_error *
4034 print_patch(struct got_commit_object *commit, struct got_object_id *id,
4035 const char *path, int diff_context, struct got_diffstat_cb_arg *dsa,
4036 struct got_repository *repo, FILE *outfile)
4038 const struct got_error *err = NULL;
4039 struct got_commit_object *pcommit = NULL;
4040 char *id_str1 = NULL, *id_str2 = NULL;
4041 struct got_object_id *obj_id1 = NULL, *obj_id2 = NULL;
4042 struct got_object_qid *qid;
4044 qid = STAILQ_FIRST(got_object_commit_get_parent_ids(commit));
4045 if (qid != NULL) {
4046 err = got_object_open_as_commit(&pcommit, repo,
4047 &qid->id);
4048 if (err)
4049 return err;
4050 err = got_object_id_str(&id_str1, &qid->id);
4051 if (err)
4052 goto done;
4055 err = got_object_id_str(&id_str2, id);
4056 if (err)
4057 goto done;
4059 if (path && path[0] != '\0') {
4060 int obj_type;
4061 err = got_object_id_by_path(&obj_id2, repo, commit, path);
4062 if (err)
4063 goto done;
4064 if (pcommit) {
4065 err = got_object_id_by_path(&obj_id1, repo,
4066 pcommit, path);
4067 if (err) {
4068 if (err->code != GOT_ERR_NO_TREE_ENTRY) {
4069 free(obj_id2);
4070 goto done;
4074 err = got_object_get_type(&obj_type, repo, obj_id2);
4075 if (err) {
4076 free(obj_id2);
4077 goto done;
4079 fprintf(outfile,
4080 "diff %s %s\n", id_str1 ? id_str1 : "/dev/null", id_str2);
4081 fprintf(outfile, "commit - %s\n",
4082 id_str1 ? id_str1 : "/dev/null");
4083 fprintf(outfile, "commit + %s\n", id_str2);
4084 switch (obj_type) {
4085 case GOT_OBJ_TYPE_BLOB:
4086 err = diff_blobs(obj_id1, obj_id2, path, diff_context,
4087 0, 0, dsa, repo, outfile);
4088 break;
4089 case GOT_OBJ_TYPE_TREE:
4090 err = diff_trees(obj_id1, obj_id2, path, diff_context,
4091 0, 0, dsa, repo, outfile);
4092 break;
4093 default:
4094 err = got_error(GOT_ERR_OBJ_TYPE);
4095 break;
4097 free(obj_id1);
4098 free(obj_id2);
4099 } else {
4100 obj_id2 = got_object_commit_get_tree_id(commit);
4101 if (pcommit)
4102 obj_id1 = got_object_commit_get_tree_id(pcommit);
4103 fprintf(outfile,
4104 "diff %s %s\n", id_str1 ? id_str1 : "/dev/null", id_str2);
4105 fprintf(outfile, "commit - %s\n",
4106 id_str1 ? id_str1 : "/dev/null");
4107 fprintf(outfile, "commit + %s\n", id_str2);
4108 err = diff_trees(obj_id1, obj_id2, "", diff_context, 0, 0,
4109 dsa, repo, outfile);
4111 done:
4112 free(id_str1);
4113 free(id_str2);
4114 if (pcommit)
4115 got_object_commit_close(pcommit);
4116 return err;
4119 static char *
4120 get_datestr(time_t *time, char *datebuf)
4122 struct tm mytm, *tm;
4123 char *p, *s;
4125 tm = gmtime_r(time, &mytm);
4126 if (tm == NULL)
4127 return NULL;
4128 s = asctime_r(tm, datebuf);
4129 if (s == NULL)
4130 return NULL;
4131 p = strchr(s, '\n');
4132 if (p)
4133 *p = '\0';
4134 return s;
4137 static const struct got_error *
4138 match_commit(int *have_match, struct got_object_id *id,
4139 struct got_commit_object *commit, regex_t *regex)
4141 const struct got_error *err = NULL;
4142 regmatch_t regmatch;
4143 char *id_str = NULL, *logmsg = NULL;
4145 *have_match = 0;
4147 err = got_object_id_str(&id_str, id);
4148 if (err)
4149 return err;
4151 err = got_object_commit_get_logmsg(&logmsg, commit);
4152 if (err)
4153 goto done;
4155 if (regexec(regex, got_object_commit_get_author(commit), 1,
4156 &regmatch, 0) == 0 ||
4157 regexec(regex, got_object_commit_get_committer(commit), 1,
4158 &regmatch, 0) == 0 ||
4159 regexec(regex, id_str, 1, &regmatch, 0) == 0 ||
4160 regexec(regex, logmsg, 1, &regmatch, 0) == 0)
4161 *have_match = 1;
4162 done:
4163 free(id_str);
4164 free(logmsg);
4165 return err;
4168 static void
4169 match_changed_paths(int *have_match, struct got_pathlist_head *changed_paths,
4170 regex_t *regex)
4172 regmatch_t regmatch;
4173 struct got_pathlist_entry *pe;
4175 *have_match = 0;
4177 TAILQ_FOREACH(pe, changed_paths, entry) {
4178 if (regexec(regex, pe->path, 1, &regmatch, 0) == 0) {
4179 *have_match = 1;
4180 break;
4185 static const struct got_error *
4186 match_patch(int *have_match, struct got_commit_object *commit,
4187 struct got_object_id *id, const char *path, int diff_context,
4188 struct got_repository *repo, regex_t *regex, FILE *f)
4190 const struct got_error *err = NULL;
4191 char *line = NULL;
4192 size_t linesize = 0;
4193 regmatch_t regmatch;
4195 *have_match = 0;
4197 err = got_opentemp_truncate(f);
4198 if (err)
4199 return err;
4201 err = print_patch(commit, id, path, diff_context, NULL, repo, f);
4202 if (err)
4203 goto done;
4205 if (fseeko(f, 0L, SEEK_SET) == -1) {
4206 err = got_error_from_errno("fseeko");
4207 goto done;
4210 while (getline(&line, &linesize, f) != -1) {
4211 if (regexec(regex, line, 1, &regmatch, 0) == 0) {
4212 *have_match = 1;
4213 break;
4216 done:
4217 free(line);
4218 return err;
4221 #define GOT_COMMIT_SEP_STR "-----------------------------------------------\n"
4223 static const struct got_error*
4224 build_refs_str(char **refs_str, struct got_reflist_head *refs,
4225 struct got_object_id *id, struct got_repository *repo,
4226 int local_only)
4228 static const struct got_error *err = NULL;
4229 struct got_reflist_entry *re;
4230 char *s;
4231 const char *name;
4233 *refs_str = NULL;
4235 TAILQ_FOREACH(re, refs, entry) {
4236 struct got_tag_object *tag = NULL;
4237 struct got_object_id *ref_id;
4238 int cmp;
4240 name = got_ref_get_name(re->ref);
4241 if (strcmp(name, GOT_REF_HEAD) == 0)
4242 continue;
4243 if (strncmp(name, "refs/", 5) == 0)
4244 name += 5;
4245 if (strncmp(name, "got/", 4) == 0)
4246 continue;
4247 if (strncmp(name, "heads/", 6) == 0)
4248 name += 6;
4249 if (strncmp(name, "remotes/", 8) == 0) {
4250 if (local_only)
4251 continue;
4252 name += 8;
4253 s = strstr(name, "/" GOT_REF_HEAD);
4254 if (s != NULL && strcmp(s, "/" GOT_REF_HEAD) == 0)
4255 continue;
4257 err = got_ref_resolve(&ref_id, repo, re->ref);
4258 if (err)
4259 break;
4260 if (strncmp(name, "tags/", 5) == 0) {
4261 err = got_object_open_as_tag(&tag, repo, ref_id);
4262 if (err) {
4263 if (err->code != GOT_ERR_OBJ_TYPE) {
4264 free(ref_id);
4265 break;
4267 /* Ref points at something other than a tag. */
4268 err = NULL;
4269 tag = NULL;
4272 cmp = got_object_id_cmp(tag ?
4273 got_object_tag_get_object_id(tag) : ref_id, id);
4274 free(ref_id);
4275 if (tag)
4276 got_object_tag_close(tag);
4277 if (cmp != 0)
4278 continue;
4279 s = *refs_str;
4280 if (asprintf(refs_str, "%s%s%s", s ? s : "",
4281 s ? ", " : "", name) == -1) {
4282 err = got_error_from_errno("asprintf");
4283 free(s);
4284 *refs_str = NULL;
4285 break;
4287 free(s);
4290 return err;
4293 static const struct got_error *
4294 print_commit_oneline(struct got_commit_object *commit, struct got_object_id *id,
4295 struct got_repository *repo, struct got_reflist_object_id_map *refs_idmap)
4297 const struct got_error *err = NULL;
4298 char *ref_str = NULL, *id_str = NULL, *logmsg0 = NULL;
4299 char *comma, *s, *nl;
4300 struct got_reflist_head *refs;
4301 char datebuf[12]; /* YYYY-MM-DD + SPACE + NUL */
4302 struct tm tm;
4303 time_t committer_time;
4305 refs = got_reflist_object_id_map_lookup(refs_idmap, id);
4306 if (refs) {
4307 err = build_refs_str(&ref_str, refs, id, repo, 1);
4308 if (err)
4309 return err;
4311 /* Display the first matching ref only. */
4312 if (ref_str && (comma = strchr(ref_str, ',')) != NULL)
4313 *comma = '\0';
4316 if (ref_str == NULL) {
4317 err = got_object_id_str(&id_str, id);
4318 if (err)
4319 return err;
4322 committer_time = got_object_commit_get_committer_time(commit);
4323 if (gmtime_r(&committer_time, &tm) == NULL) {
4324 err = got_error_from_errno("gmtime_r");
4325 goto done;
4327 if (strftime(datebuf, sizeof(datebuf), "%F ", &tm) == 0) {
4328 err = got_error(GOT_ERR_NO_SPACE);
4329 goto done;
4332 err = got_object_commit_get_logmsg(&logmsg0, commit);
4333 if (err)
4334 goto done;
4336 s = logmsg0;
4337 while (isspace((unsigned char)s[0]))
4338 s++;
4340 nl = strchr(s, '\n');
4341 if (nl) {
4342 *nl = '\0';
4345 if (ref_str)
4346 printf("%s%-7s %s\n", datebuf, ref_str, s);
4347 else
4348 printf("%s%.7s %s\n", datebuf, id_str, s);
4350 if (fflush(stdout) != 0 && err == NULL)
4351 err = got_error_from_errno("fflush");
4352 done:
4353 free(id_str);
4354 free(ref_str);
4355 free(logmsg0);
4356 return err;
4359 static const struct got_error *
4360 print_diffstat(struct got_diffstat_cb_arg *dsa, const char *header)
4362 struct got_pathlist_entry *pe;
4364 if (header != NULL)
4365 printf("%s\n", header);
4367 TAILQ_FOREACH(pe, dsa->paths, entry) {
4368 struct got_diff_changed_path *cp = pe->data;
4369 int pad = dsa->max_path_len - pe->path_len + 1;
4371 printf(" %c %s%*c | %*d+ %*d-\n", cp->status, pe->path, pad,
4372 ' ', dsa->add_cols + 1, cp->add, dsa->rm_cols + 1, cp->rm);
4374 printf("\n%d file%s changed, %d insertion%s(+), %d deletion%s(-)\n\n",
4375 dsa->nfiles, dsa->nfiles > 1 ? "s" : "", dsa->ins,
4376 dsa->ins != 1 ? "s" : "", dsa->del, dsa->del != 1 ? "s" : "");
4378 if (fflush(stdout) != 0)
4379 return got_error_from_errno("fflush");
4381 return NULL;
4384 static const struct got_error *
4385 printfile(FILE *f)
4387 char buf[8192];
4388 size_t r;
4390 if (fseeko(f, 0L, SEEK_SET) == -1)
4391 return got_error_from_errno("fseek");
4393 for (;;) {
4394 r = fread(buf, 1, sizeof(buf), f);
4395 if (r == 0) {
4396 if (ferror(f))
4397 return got_error_from_errno("fread");
4398 if (feof(f))
4399 break;
4401 if (fwrite(buf, 1, r, stdout) != r)
4402 return got_ferror(stdout, GOT_ERR_IO);
4405 return NULL;
4408 static const struct got_error *
4409 print_commit(struct got_commit_object *commit, struct got_object_id *id,
4410 struct got_repository *repo, const char *path,
4411 struct got_pathlist_head *changed_paths,
4412 struct got_diffstat_cb_arg *diffstat, int show_patch, int diff_context,
4413 struct got_reflist_object_id_map *refs_idmap, const char *custom_refs_str,
4414 const char *prefix)
4416 const struct got_error *err = NULL;
4417 FILE *f = NULL;
4418 char *id_str, *datestr, *logmsg0, *logmsg, *line;
4419 char datebuf[26];
4420 time_t committer_time;
4421 const char *author, *committer;
4422 char *refs_str = NULL;
4424 err = got_object_id_str(&id_str, id);
4425 if (err)
4426 return err;
4428 if (custom_refs_str == NULL) {
4429 struct got_reflist_head *refs;
4430 refs = got_reflist_object_id_map_lookup(refs_idmap, id);
4431 if (refs) {
4432 err = build_refs_str(&refs_str, refs, id, repo, 0);
4433 if (err)
4434 goto done;
4438 printf(GOT_COMMIT_SEP_STR);
4439 if (custom_refs_str)
4440 printf("%s %s (%s)\n", prefix ? prefix : "commit", id_str,
4441 custom_refs_str);
4442 else
4443 printf("%s %s%s%s%s\n", prefix ? prefix : "commit", id_str,
4444 refs_str ? " (" : "", refs_str ? refs_str : "",
4445 refs_str ? ")" : "");
4446 free(id_str);
4447 id_str = NULL;
4448 free(refs_str);
4449 refs_str = NULL;
4450 printf("from: %s\n", got_object_commit_get_author(commit));
4451 author = got_object_commit_get_author(commit);
4452 committer = got_object_commit_get_committer(commit);
4453 if (strcmp(author, committer) != 0)
4454 printf("via: %s\n", committer);
4455 committer_time = got_object_commit_get_committer_time(commit);
4456 datestr = get_datestr(&committer_time, datebuf);
4457 if (datestr)
4458 printf("date: %s UTC\n", datestr);
4459 if (got_object_commit_get_nparents(commit) > 1) {
4460 const struct got_object_id_queue *parent_ids;
4461 struct got_object_qid *qid;
4462 int n = 1;
4463 parent_ids = got_object_commit_get_parent_ids(commit);
4464 STAILQ_FOREACH(qid, parent_ids, entry) {
4465 err = got_object_id_str(&id_str, &qid->id);
4466 if (err)
4467 goto done;
4468 printf("parent %d: %s\n", n++, id_str);
4469 free(id_str);
4470 id_str = NULL;
4474 err = got_object_commit_get_logmsg(&logmsg0, commit);
4475 if (err)