2 * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <sys/queue.h>
38 #include "got_error.h"
39 #include "got_repository.h"
40 #include "got_reference.h"
41 #include "got_object.h"
43 #include "got_cancel.h"
44 #include "got_worktree.h"
45 #include "got_opentemp.h"
48 #include "got_lib_worktree.h"
49 #include "got_lib_sha1.h"
50 #include "got_lib_fileindex.h"
51 #include "got_lib_inflate.h"
52 #include "got_lib_delta.h"
53 #include "got_lib_object.h"
54 #include "got_lib_object_parse.h"
55 #include "got_lib_object_create.h"
56 #include "got_lib_object_idset.h"
57 #include "got_lib_diff.h"
58 #include "got_lib_gotconfig.h"
61 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
64 #define GOT_MERGE_LABEL_MERGED "merged change"
65 #define GOT_MERGE_LABEL_BASE "3-way merge base"
67 static mode_t apply_umask(mode_t);
69 static const struct got_error *
70 create_meta_file(const char *path_got, const char *name, const char *content)
72 const struct got_error *err = NULL;
75 if (asprintf(&path, "%s/%s", path_got, name) == -1)
76 return got_error_from_errno("asprintf");
78 err = got_path_create_file(path, content);
83 static const struct got_error *
84 update_meta_file(const char *path_got, const char *name, const char *content)
86 const struct got_error *err = NULL;
91 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
92 err = got_error_from_errno("asprintf");
97 err = got_opentemp_named(&tmppath, &tmpfile, path, "");
102 int len = fprintf(tmpfile, "%s\n", content);
103 if (len != strlen(content) + 1) {
104 err = got_error_from_errno2("fprintf", tmppath);
109 if (rename(tmppath, path) != 0) {
110 err = got_error_from_errno3("rename", tmppath, path);
116 if (fclose(tmpfile) == EOF && err == NULL)
117 err = got_error_from_errno2("fclose", tmppath);
122 static const struct got_error *
123 write_head_ref(const char *path_got, struct got_reference *head_ref)
125 const struct got_error *err = NULL;
128 if (got_ref_is_symbolic(head_ref)) {
129 refstr = got_ref_to_str(head_ref);
131 return got_error_from_errno("got_ref_to_str");
133 refstr = strdup(got_ref_get_name(head_ref));
135 return got_error_from_errno("strdup");
137 err = update_meta_file(path_got, GOT_WORKTREE_HEAD_REF, refstr);
142 const struct got_error *
143 got_worktree_init(const char *path, struct got_reference *head_ref,
144 const char *prefix, struct got_repository *repo)
146 const struct got_error *err = NULL;
147 struct got_object_id *commit_id = NULL;
149 uint32_t uuid_status;
151 char *path_got = NULL;
152 char *formatstr = NULL;
153 char *absprefix = NULL;
154 char *basestr = NULL;
155 char *uuidstr = NULL;
157 if (strcmp(path, got_repo_get_path(repo)) == 0) {
158 err = got_error(GOT_ERR_WORKTREE_REPO);
162 err = got_ref_resolve(&commit_id, repo, head_ref);
165 err = got_object_get_type(&obj_type, repo, commit_id);
168 if (obj_type != GOT_OBJ_TYPE_COMMIT)
169 return got_error(GOT_ERR_OBJ_TYPE);
171 if (!got_path_is_absolute(prefix)) {
172 if (asprintf(&absprefix, "/%s", prefix) == -1)
173 return got_error_from_errno("asprintf");
176 /* Create top-level directory (may already exist). */
177 if (mkdir(path, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
178 err = got_error_from_errno2("mkdir", path);
182 /* Create .got directory (may already exist). */
183 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
184 err = got_error_from_errno("asprintf");
187 if (mkdir(path_got, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
188 err = got_error_from_errno2("mkdir", path_got);
192 /* Create an empty lock file. */
193 err = create_meta_file(path_got, GOT_WORKTREE_LOCK, NULL);
197 /* Create an empty file index. */
198 err = create_meta_file(path_got, GOT_WORKTREE_FILE_INDEX, NULL);
202 /* Write the HEAD reference. */
203 err = write_head_ref(path_got, head_ref);
207 /* Record our base commit. */
208 err = got_object_id_str(&basestr, commit_id);
211 err = create_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, basestr);
215 /* Store path to repository. */
216 err = create_meta_file(path_got, GOT_WORKTREE_REPOSITORY,
217 got_repo_get_path(repo));
221 /* Store in-repository path prefix. */
222 err = create_meta_file(path_got, GOT_WORKTREE_PATH_PREFIX,
223 absprefix ? absprefix : prefix);
228 uuid_create(&uuid, &uuid_status);
229 if (uuid_status != uuid_s_ok) {
230 err = got_error_uuid(uuid_status, "uuid_create");
233 uuid_to_string(&uuid, &uuidstr, &uuid_status);
234 if (uuid_status != uuid_s_ok) {
235 err = got_error_uuid(uuid_status, "uuid_to_string");
238 err = create_meta_file(path_got, GOT_WORKTREE_UUID, uuidstr);
242 /* Stamp work tree with format file. */
243 if (asprintf(&formatstr, "%d", GOT_WORKTREE_FORMAT_VERSION) == -1) {
244 err = got_error_from_errno("asprintf");
247 err = create_meta_file(path_got, GOT_WORKTREE_FORMAT, formatstr);
261 const struct got_error *
262 got_worktree_match_path_prefix(int *match, struct got_worktree *worktree,
263 const char *path_prefix)
265 char *absprefix = NULL;
267 if (!got_path_is_absolute(path_prefix)) {
268 if (asprintf(&absprefix, "/%s", path_prefix) == -1)
269 return got_error_from_errno("asprintf");
271 *match = (strcmp(absprefix ? absprefix : path_prefix,
272 worktree->path_prefix) == 0);
278 got_worktree_get_head_ref_name(struct got_worktree *worktree)
280 return worktree->head_ref_name;
283 const struct got_error *
284 got_worktree_set_head_ref(struct got_worktree *worktree,
285 struct got_reference *head_ref)
287 const struct got_error *err = NULL;
288 char *path_got = NULL, *head_ref_name = NULL;
290 if (asprintf(&path_got, "%s/%s", worktree->root_path,
291 GOT_WORKTREE_GOT_DIR) == -1) {
292 err = got_error_from_errno("asprintf");
297 head_ref_name = strdup(got_ref_get_name(head_ref));
298 if (head_ref_name == NULL) {
299 err = got_error_from_errno("strdup");
303 err = write_head_ref(path_got, head_ref);
307 free(worktree->head_ref_name);
308 worktree->head_ref_name = head_ref_name;
316 struct got_object_id *
317 got_worktree_get_base_commit_id(struct got_worktree *worktree)
319 return worktree->base_commit_id;
322 const struct got_error *
323 got_worktree_set_base_commit_id(struct got_worktree *worktree,
324 struct got_repository *repo, struct got_object_id *commit_id)
326 const struct got_error *err;
327 struct got_object *obj = NULL;
329 char *path_got = NULL;
331 if (asprintf(&path_got, "%s/%s", worktree->root_path,
332 GOT_WORKTREE_GOT_DIR) == -1) {
333 err = got_error_from_errno("asprintf");
338 err = got_object_open(&obj, repo, commit_id);
342 if (obj->type != GOT_OBJ_TYPE_COMMIT) {
343 err = got_error(GOT_ERR_OBJ_TYPE);
347 /* Record our base commit. */
348 err = got_object_id_str(&id_str, commit_id);
351 err = update_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, id_str);
355 free(worktree->base_commit_id);
356 worktree->base_commit_id = got_object_id_dup(commit_id);
357 if (worktree->base_commit_id == NULL) {
358 err = got_error_from_errno("got_object_id_dup");
363 got_object_close(obj);
369 const struct got_gotconfig *
370 got_worktree_get_gotconfig(struct got_worktree *worktree)
372 return worktree->gotconfig;
375 static const struct got_error *
376 lock_worktree(struct got_worktree *worktree, int operation)
378 if (flock(worktree->lockfd, operation | LOCK_NB) == -1)
379 return (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
380 : got_error_from_errno2("flock",
381 got_worktree_get_root_path(worktree)));
385 static const struct got_error *
386 add_dir_on_disk(struct got_worktree *worktree, const char *path)
388 const struct got_error *err = NULL;
391 if (asprintf(&abspath, "%s/%s", worktree->root_path, path) == -1)
392 return got_error_from_errno("asprintf");
394 err = got_path_mkdir(abspath);
395 if (err && err->code == GOT_ERR_ERRNO && errno == EEXIST) {
398 if (lstat(abspath, &sb) == -1) {
399 err = got_error_from_errno2("lstat", abspath);
400 } else if (!S_ISDIR(sb.st_mode)) {
401 /* TODO directory is obstructed; do something */
402 err = got_error_path(abspath, GOT_ERR_FILE_OBSTRUCTED);
409 static const struct got_error *
410 check_file_contents_equal(int *same, FILE *f1, FILE *f2)
412 const struct got_error *err = NULL;
415 size_t flen1 = 0, flen2 = 0;
420 flen1 = fread(fbuf1, 1, sizeof(fbuf1), f1);
421 if (flen1 == 0 && ferror(f1)) {
422 err = got_error_from_errno("fread");
425 flen2 = fread(fbuf2, 1, sizeof(fbuf2), f2);
426 if (flen2 == 0 && ferror(f2)) {
427 err = got_error_from_errno("fread");
434 } else if (flen2 == 0) {
438 } else if (flen1 == flen2) {
439 if (memcmp(fbuf1, fbuf2, flen2) != 0) {
452 static const struct got_error *
453 check_files_equal(int *same, FILE *f1, FILE *f2)
460 if (fstat(fileno(f1), &sb) != 0)
461 return got_error_from_errno("fstat");
464 if (fstat(fileno(f2), &sb) != 0)
465 return got_error_from_errno("fstat");
468 if (size1 != size2) {
473 if (fseek(f1, 0L, SEEK_SET) == -1)
474 return got_ferror(f1, GOT_ERR_IO);
475 if (fseek(f2, 0L, SEEK_SET) == -1)
476 return got_ferror(f2, GOT_ERR_IO);
478 return check_file_contents_equal(same, f1, f2);
481 static const struct got_error *
482 copy_file_to_fd(off_t *outsize, FILE *f, int outfd)
490 if (fseek(f, 0L, SEEK_SET) == -1)
491 return got_ferror(f, GOT_ERR_IO);
494 flen = fread(fbuf, 1, sizeof(fbuf), f);
497 return got_error_from_errno("fread");
501 outlen = write(outfd, fbuf, flen);
503 return got_error_from_errno("write");
505 return got_error(GOT_ERR_IO);
512 static const struct got_error *
513 merge_binary_file(int *overlapcnt, int merged_fd,
514 FILE *f_deriv, FILE *f_orig, FILE *f_deriv2,
515 const char *label_deriv, const char *label_orig, const char *label_deriv2,
516 const char *ondisk_path)
518 const struct got_error *err = NULL;
519 int same_content, changed_deriv, changed_deriv2;
520 int fd_orig = -1, fd_deriv = -1, fd_deriv2 = -1;
521 off_t size_orig = 0, size_deriv = 0, size_deriv2 = 0;
522 char *path_orig = NULL, *path_deriv = NULL, *path_deriv2 = NULL;
523 char *base_path_orig = NULL, *base_path_deriv = NULL;
524 char *base_path_deriv2 = NULL;
528 err = check_files_equal(&same_content, f_deriv, f_deriv2);
533 return copy_file_to_fd(&size_deriv, f_deriv, merged_fd);
535 err = check_files_equal(&same_content, f_deriv, f_orig);
538 changed_deriv = !same_content;
539 err = check_files_equal(&same_content, f_deriv2, f_orig);
542 changed_deriv2 = !same_content;
544 if (changed_deriv && changed_deriv2) {
546 if (asprintf(&base_path_orig, "%s-orig", ondisk_path) == -1) {
547 err = got_error_from_errno("asprintf");
550 if (asprintf(&base_path_deriv, "%s-1", ondisk_path) == -1) {
551 err = got_error_from_errno("asprintf");
554 if (asprintf(&base_path_deriv2, "%s-2", ondisk_path) == -1) {
555 err = got_error_from_errno("asprintf");
558 err = got_opentemp_named_fd(&path_orig, &fd_orig,
562 err = got_opentemp_named_fd(&path_deriv, &fd_deriv,
563 base_path_deriv, "");
566 err = got_opentemp_named_fd(&path_deriv2, &fd_deriv2,
567 base_path_deriv2, "");
570 err = copy_file_to_fd(&size_orig, f_orig, fd_orig);
573 err = copy_file_to_fd(&size_deriv, f_deriv, fd_deriv);
576 err = copy_file_to_fd(&size_deriv2, f_deriv2, fd_deriv2);
579 if (dprintf(merged_fd, "Binary files differ and cannot be "
580 "merged automatically:\n") < 0) {
581 err = got_error_from_errno("dprintf");
584 if (dprintf(merged_fd, "%s%s%s\nfile %s\n",
585 GOT_DIFF_CONFLICT_MARKER_BEGIN,
586 label_deriv ? " " : "",
587 label_deriv ? label_deriv : "",
589 err = got_error_from_errno("dprintf");
593 if (dprintf(merged_fd, "%s%s%s\nfile %s\n",
594 GOT_DIFF_CONFLICT_MARKER_ORIG,
595 label_orig ? " " : "",
596 label_orig ? label_orig : "",
598 err = got_error_from_errno("dprintf");
602 if (dprintf(merged_fd, "%s\nfile %s\n%s%s%s\n",
603 GOT_DIFF_CONFLICT_MARKER_SEP,
605 GOT_DIFF_CONFLICT_MARKER_END,
606 label_deriv2 ? " " : "",
607 label_deriv2 ? label_deriv2 : "") < 0) {
608 err = got_error_from_errno("dprintf");
611 } else if (changed_deriv)
612 err = copy_file_to_fd(&size_deriv, f_deriv, merged_fd);
613 else if (changed_deriv2)
614 err = copy_file_to_fd(&size_deriv2, f_deriv2, merged_fd);
616 if (size_orig == 0 && path_orig && unlink(path_orig) == -1 &&
618 err = got_error_from_errno2("unlink", path_orig);
619 if (fd_orig != -1 && close(fd_orig) == -1 && err == NULL)
620 err = got_error_from_errno2("close", path_orig);
621 if (fd_deriv != -1 && close(fd_deriv) == -1 && err == NULL)
622 err = got_error_from_errno2("close", path_deriv);
623 if (fd_deriv2 != -1 && close(fd_deriv2) == -1 && err == NULL)
624 err = got_error_from_errno2("close", path_deriv2);
628 free(base_path_orig);
629 free(base_path_deriv);
630 free(base_path_deriv2);
635 * Perform a 3-way merge where the file f_orig acts as the common
636 * ancestor, the file f_deriv acts as the first derived version,
637 * and the file f_deriv2 acts as the second derived version.
638 * The merge result will be written to a new file at ondisk_path; any
639 * existing file at this path will be replaced.
641 static const struct got_error *
642 merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
643 FILE *f_orig, FILE *f_deriv, FILE *f_deriv2, const char *ondisk_path,
644 const char *path, uint16_t st_mode,
645 const char *label_orig, const char *label_deriv, const char *label_deriv2,
646 enum got_diff_algorithm diff_algo, struct got_repository *repo,
647 got_worktree_checkout_cb progress_cb, void *progress_arg)
649 const struct got_error *err = NULL;
651 FILE *f_merged = NULL;
652 char *merged_path = NULL, *base_path = NULL;
656 *local_changes_subsumed = 0;
658 err = got_path_dirname(&parent, ondisk_path);
662 if (asprintf(&base_path, "%s/got-merged", parent) == -1) {
663 err = got_error_from_errno("asprintf");
667 err = got_opentemp_named_fd(&merged_path, &merged_fd, base_path, "");
671 err = got_merge_diff3(&overlapcnt, merged_fd, f_deriv, f_orig,
672 f_deriv2, label_deriv, label_orig, label_deriv2, diff_algo);
674 if (err->code != GOT_ERR_FILE_BINARY)
676 err = merge_binary_file(&overlapcnt, merged_fd, f_deriv,
677 f_orig, f_deriv2, label_deriv, label_orig, label_deriv2,
683 err = (*progress_cb)(progress_arg,
684 overlapcnt > 0 ? GOT_STATUS_CONFLICT : GOT_STATUS_MERGE, path);
688 if (fsync(merged_fd) != 0) {
689 err = got_error_from_errno("fsync");
693 f_merged = fdopen(merged_fd, "r");
694 if (f_merged == NULL) {
695 err = got_error_from_errno("fdopen");
700 /* Check if a clean merge has subsumed all local changes. */
701 if (overlapcnt == 0) {
702 err = check_files_equal(local_changes_subsumed, f_deriv,
708 if (fchmod(fileno(f_merged), apply_umask(st_mode)) != 0) {
709 err = got_error_from_errno2("fchmod", merged_path);
713 if (rename(merged_path, ondisk_path) != 0) {
714 err = got_error_from_errno3("rename", merged_path,
723 if (merged_fd != -1 && close(merged_fd) == -1 && err == NULL)
724 err = got_error_from_errno("close");
725 if (f_merged && fclose(f_merged) == EOF && err == NULL)
726 err = got_error_from_errno("fclose");
733 static const struct got_error *
734 update_symlink(const char *ondisk_path, const char *target_path,
737 /* This is not atomic but matches what 'ln -sf' does. */
738 if (unlink(ondisk_path) == -1)
739 return got_error_from_errno2("unlink", ondisk_path);
740 if (symlink(target_path, ondisk_path) == -1)
741 return got_error_from_errno3("symlink", target_path,
747 * Overwrite a symlink (or a regular file in case there was a "bad" symlink)
748 * in the work tree with a file that contains conflict markers and the
749 * conflicting target paths of the original version, a "derived version"
750 * of a symlink from an incoming change, and a local version of the symlink.
752 * The original versions's target path can be NULL if it is not available,
753 * such as if both derived versions added a new symlink at the same path.
755 * The incoming derived symlink target is NULL in case the incoming change
756 * has deleted this symlink.
758 static const struct got_error *
759 install_symlink_conflict(const char *deriv_target,
760 struct got_object_id *deriv_base_commit_id, const char *orig_target,
761 const char *label_orig, const char *local_target, const char *ondisk_path)
763 const struct got_error *err;
764 char *id_str = NULL, *label_deriv = NULL, *path = NULL;
767 err = got_object_id_str(&id_str, deriv_base_commit_id);
769 return got_error_from_errno("asprintf");
771 if (asprintf(&label_deriv, "%s: commit %s",
772 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
773 err = got_error_from_errno("asprintf");
777 err = got_opentemp_named(&path, &f, "got-symlink-conflict", "");
781 if (fchmod(fileno(f), apply_umask(GOT_DEFAULT_FILE_MODE)) == -1) {
782 err = got_error_from_errno2("fchmod", path);
786 if (fprintf(f, "%s %s\n%s\n%s%s%s%s%s\n%s\n%s\n",
787 GOT_DIFF_CONFLICT_MARKER_BEGIN, label_deriv,
788 deriv_target ? deriv_target : "(symlink was deleted)",
789 orig_target ? label_orig : "",
790 orig_target ? "\n" : "",
791 orig_target ? orig_target : "",
792 orig_target ? "\n" : "",
793 GOT_DIFF_CONFLICT_MARKER_SEP,
794 local_target, GOT_DIFF_CONFLICT_MARKER_END) < 0) {
795 err = got_error_from_errno2("fprintf", path);
799 if (unlink(ondisk_path) == -1) {
800 err = got_error_from_errno2("unlink", ondisk_path);
803 if (rename(path, ondisk_path) == -1) {
804 err = got_error_from_errno3("rename", path, ondisk_path);
808 if (f != NULL && fclose(f) == EOF && err == NULL)
809 err = got_error_from_errno2("fclose", path);
816 /* forward declaration */
817 static const struct got_error *
818 merge_blob(int *, struct got_worktree *, struct got_blob_object *,
819 const char *, const char *, uint16_t, const char *,
820 struct got_blob_object *, struct got_object_id *,
821 struct got_repository *, got_worktree_checkout_cb, void *);
824 * Merge a symlink into the work tree, where blob_orig acts as the common
825 * ancestor, deriv_target is the link target of the first derived version,
826 * and the symlink on disk acts as the second derived version.
827 * Assume that contents of both blobs represent symlinks.
829 static const struct got_error *
830 merge_symlink(struct got_worktree *worktree,
831 struct got_blob_object *blob_orig, const char *ondisk_path,
832 const char *path, const char *label_orig, const char *deriv_target,
833 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
834 got_worktree_checkout_cb progress_cb, void *progress_arg)
836 const struct got_error *err = NULL;
837 char *ancestor_target = NULL;
839 ssize_t ondisk_len, deriv_len;
840 char ondisk_target[PATH_MAX];
841 int have_local_change = 0;
842 int have_incoming_change = 0;
844 if (lstat(ondisk_path, &sb) == -1)
845 return got_error_from_errno2("lstat", ondisk_path);
847 ondisk_len = readlink(ondisk_path, ondisk_target,
848 sizeof(ondisk_target));
849 if (ondisk_len == -1) {
850 err = got_error_from_errno2("readlink",
854 ondisk_target[ondisk_len] = '\0';
857 err = got_object_blob_read_to_str(&ancestor_target, blob_orig);
862 if (ancestor_target == NULL ||
863 (ondisk_len != strlen(ancestor_target) ||
864 memcmp(ondisk_target, ancestor_target, ondisk_len) != 0))
865 have_local_change = 1;
867 deriv_len = strlen(deriv_target);
868 if (ancestor_target == NULL ||
869 (deriv_len != strlen(ancestor_target) ||
870 memcmp(deriv_target, ancestor_target, deriv_len) != 0))
871 have_incoming_change = 1;
873 if (!have_local_change && !have_incoming_change) {
874 if (ancestor_target) {
875 /* Both sides made the same change. */
876 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
878 } else if (deriv_len == ondisk_len &&
879 memcmp(ondisk_target, deriv_target, deriv_len) == 0) {
880 /* Both sides added the same symlink. */
881 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
884 /* Both sides added symlinks which don't match. */
885 err = install_symlink_conflict(deriv_target,
886 deriv_base_commit_id, ancestor_target,
887 label_orig, ondisk_target, ondisk_path);
890 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
893 } else if (!have_local_change && have_incoming_change) {
894 /* Apply the incoming change. */
895 err = update_symlink(ondisk_path, deriv_target,
896 strlen(deriv_target));
899 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
900 } else if (have_local_change && have_incoming_change) {
901 if (deriv_len == ondisk_len &&
902 memcmp(deriv_target, ondisk_target, deriv_len) == 0) {
903 /* Both sides made the same change. */
904 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
907 err = install_symlink_conflict(deriv_target,
908 deriv_base_commit_id, ancestor_target, label_orig,
909 ondisk_target, ondisk_path);
912 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
918 free(ancestor_target);
922 static const struct got_error *
923 dump_symlink_target_path_to_file(FILE **outfile, const char *ondisk_path)
925 const struct got_error *err = NULL;
926 char target_path[PATH_MAX];
935 return got_error_from_errno("got_opentemp");
936 target_len = readlink(ondisk_path, target_path, sizeof(target_path));
937 if (target_len == -1) {
938 err = got_error_from_errno2("readlink", ondisk_path);
941 n = fwrite(target_path, 1, target_len, f);
942 if (n != target_len) {
943 err = got_ferror(f, GOT_ERR_IO);
946 if (fflush(f) == EOF) {
947 err = got_error_from_errno("fflush");
950 if (fseek(f, 0L, SEEK_SET) == -1) {
951 err = got_ferror(f, GOT_ERR_IO);
963 * Perform a 3-way merge where blob_orig acts as the common ancestor,
964 * blob_deriv acts as the first derived version, and the file on disk
965 * acts as the second derived version.
967 static const struct got_error *
968 merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
969 struct got_blob_object *blob_orig, const char *ondisk_path,
970 const char *path, uint16_t st_mode, const char *label_orig,
971 struct got_blob_object *blob_deriv,
972 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
973 got_worktree_checkout_cb progress_cb, void *progress_arg)
975 const struct got_error *err = NULL;
976 FILE *f_orig = NULL, *f_deriv = NULL, *f_deriv2 = NULL;
977 char *blob_orig_path = NULL;
978 char *blob_deriv_path = NULL, *base_path = NULL, *id_str = NULL;
979 char *label_deriv = NULL, *parent = NULL;
981 *local_changes_subsumed = 0;
983 err = got_path_dirname(&parent, ondisk_path);
988 if (asprintf(&base_path, "%s/got-merge-blob-orig",
990 err = got_error_from_errno("asprintf");
995 err = got_opentemp_named(&blob_orig_path, &f_orig,
999 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_orig,
1006 * No common ancestor exists. This is an "add vs add" conflict
1007 * and we simply use an empty ancestor file to make both files
1008 * appear in the merged result in their entirety.
1010 f_orig = got_opentemp();
1011 if (f_orig == NULL) {
1012 err = got_error_from_errno("got_opentemp");
1017 if (asprintf(&base_path, "%s/got-merge-blob-deriv", parent) == -1) {
1018 err = got_error_from_errno("asprintf");
1023 err = got_opentemp_named(&blob_deriv_path, &f_deriv, base_path, "");
1026 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_deriv,
1031 err = got_object_id_str(&id_str, deriv_base_commit_id);
1034 if (asprintf(&label_deriv, "%s: commit %s",
1035 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
1036 err = got_error_from_errno("asprintf");
1041 * In order the run a 3-way merge with a symlink we copy the symlink's
1042 * target path into a temporary file and use that file with diff3.
1044 if (S_ISLNK(st_mode)) {
1045 err = dump_symlink_target_path_to_file(&f_deriv2, ondisk_path);
1050 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
1052 err = got_error_from_errno2("open", ondisk_path);
1055 f_deriv2 = fdopen(fd, "r");
1056 if (f_deriv2 == NULL) {
1057 err = got_error_from_errno2("fdopen", ondisk_path);
1063 err = merge_file(local_changes_subsumed, worktree, f_orig, f_deriv,
1064 f_deriv2, ondisk_path, path, st_mode, label_orig, label_deriv,
1065 NULL, GOT_DIFF_ALGORITHM_MYERS, repo, progress_cb, progress_arg);
1067 if (f_orig && fclose(f_orig) == EOF && err == NULL)
1068 err = got_error_from_errno("fclose");
1069 if (f_deriv && fclose(f_deriv) == EOF && err == NULL)
1070 err = got_error_from_errno("fclose");
1071 if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
1072 err = got_error_from_errno("fclose");
1074 if (blob_orig_path) {
1075 unlink(blob_orig_path);
1076 free(blob_orig_path);
1078 if (blob_deriv_path) {
1079 unlink(blob_deriv_path);
1080 free(blob_deriv_path);
1088 static const struct got_error *
1089 create_fileindex_entry(struct got_fileindex_entry **new_iep,
1090 struct got_fileindex *fileindex, struct got_object_id *base_commit_id,
1091 int wt_fd, const char *path, struct got_object_id *blob_id)
1093 const struct got_error *err = NULL;
1094 struct got_fileindex_entry *new_ie;
1098 err = got_fileindex_entry_alloc(&new_ie, path);
1102 err = got_fileindex_entry_update(new_ie, wt_fd, path,
1103 blob_id->sha1, base_commit_id->sha1, 1);
1107 err = got_fileindex_entry_add(fileindex, new_ie);
1110 got_fileindex_entry_free(new_ie);
1117 get_ondisk_perms(int executable, mode_t st_mode)
1119 mode_t xbits = S_IXUSR;
1122 /* Map read bits to execute bits. */
1123 if (st_mode & S_IRGRP)
1125 if (st_mode & S_IROTH)
1127 return st_mode | xbits;
1134 apply_umask(mode_t mode)
1143 /* forward declaration */
1144 static const struct got_error *
1145 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1146 const char *path, mode_t te_mode, mode_t st_mode,
1147 struct got_blob_object *blob, int restoring_missing_file,
1148 int reverting_versioned_file, int installing_bad_symlink,
1149 int path_is_unversioned, struct got_repository *repo,
1150 got_worktree_checkout_cb progress_cb, void *progress_arg);
1153 * This function assumes that the provided symlink target points at a
1154 * safe location in the work tree!
1156 static const struct got_error *
1157 replace_existing_symlink(int *did_something, const char *ondisk_path,
1158 const char *target_path, size_t target_len)
1160 const struct got_error *err = NULL;
1162 char etarget[PATH_MAX];
1168 * "Bad" symlinks (those pointing outside the work tree or into the
1169 * .got directory) are installed in the work tree as a regular file
1170 * which contains the bad symlink target path.
1171 * The new symlink target has already been checked for safety by our
1172 * caller. If we can successfully open a regular file then we simply
1173 * replace this file with a symlink below.
1175 fd = open(ondisk_path, O_RDWR | O_EXCL | O_NOFOLLOW | O_CLOEXEC);
1177 if (!got_err_open_nofollow_on_symlink())
1178 return got_error_from_errno2("open", ondisk_path);
1180 /* We are updating an existing on-disk symlink. */
1181 elen = readlink(ondisk_path, etarget, sizeof(etarget));
1183 return got_error_from_errno2("readlink", ondisk_path);
1185 if (elen == target_len &&
1186 memcmp(etarget, target_path, target_len) == 0)
1187 return NULL; /* nothing to do */
1191 err = update_symlink(ondisk_path, target_path, target_len);
1192 if (fd != -1 && close(fd) == -1 && err == NULL)
1193 err = got_error_from_errno2("close", ondisk_path);
1197 static const struct got_error *
1198 is_bad_symlink_target(int *is_bad_symlink, const char *target_path,
1199 size_t target_len, const char *ondisk_path, const char *wtroot_path)
1201 const struct got_error *err = NULL;
1202 char canonpath[PATH_MAX];
1203 char *path_got = NULL;
1205 *is_bad_symlink = 0;
1207 if (target_len >= sizeof(canonpath)) {
1208 *is_bad_symlink = 1;
1213 * We do not use realpath(3) to resolve the symlink's target
1214 * path because we don't want to resolve symlinks recursively.
1215 * Instead we make the path absolute and then canonicalize it.
1216 * Relative symlink target lookup should begin at the directory
1217 * in which the blob object is being installed.
1219 if (!got_path_is_absolute(target_path)) {
1220 char *abspath, *parent;
1221 err = got_path_dirname(&parent, ondisk_path);
1224 if (asprintf(&abspath, "%s/%s", parent, target_path) == -1) {
1226 return got_error_from_errno("asprintf");
1229 if (strlen(abspath) >= sizeof(canonpath)) {
1230 err = got_error_path(abspath, GOT_ERR_BAD_PATH);
1234 err = got_canonpath(abspath, canonpath, sizeof(canonpath));
1239 err = got_canonpath(target_path, canonpath, sizeof(canonpath));
1244 /* Only allow symlinks pointing at paths within the work tree. */
1245 if (!got_path_is_child(canonpath, wtroot_path, strlen(wtroot_path))) {
1246 *is_bad_symlink = 1;
1250 /* Do not allow symlinks pointing into the .got directory. */
1251 if (asprintf(&path_got, "%s/%s", wtroot_path,
1252 GOT_WORKTREE_GOT_DIR) == -1)
1253 return got_error_from_errno("asprintf");
1254 if (got_path_is_child(canonpath, path_got, strlen(path_got)))
1255 *is_bad_symlink = 1;
1261 static const struct got_error *
1262 install_symlink(int *is_bad_symlink, struct got_worktree *worktree,
1263 const char *ondisk_path, const char *path, struct got_blob_object *blob,
1264 int restoring_missing_file, int reverting_versioned_file,
1265 int path_is_unversioned, int allow_bad_symlinks,
1266 struct got_repository *repo,
1267 got_worktree_checkout_cb progress_cb, void *progress_arg)
1269 const struct got_error *err = NULL;
1270 char target_path[PATH_MAX];
1271 size_t len, target_len = 0;
1272 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1273 size_t hdrlen = got_object_blob_get_hdrlen(blob);
1275 *is_bad_symlink = 0;
1278 * Blob object content specifies the target path of the link.
1279 * If a symbolic link cannot be installed we instead create
1280 * a regular file which contains the link target path stored
1281 * in the blob object.
1284 err = got_object_blob_read_block(&len, blob);
1288 if (len + target_len >= sizeof(target_path)) {
1289 /* Path too long; install as a regular file. */
1290 *is_bad_symlink = 1;
1291 got_object_blob_rewind(blob);
1292 return install_blob(worktree, ondisk_path, path,
1293 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1294 restoring_missing_file, reverting_versioned_file,
1295 1, path_is_unversioned, repo, progress_cb,
1299 /* Skip blob object header first time around. */
1300 memcpy(target_path + target_len, buf + hdrlen,
1302 target_len += len - hdrlen;
1306 target_path[target_len] = '\0';
1308 err = is_bad_symlink_target(is_bad_symlink, target_path, target_len,
1309 ondisk_path, worktree->root_path);
1313 if (*is_bad_symlink && !allow_bad_symlinks) {
1314 /* install as a regular file */
1315 got_object_blob_rewind(blob);
1316 err = install_blob(worktree, ondisk_path, path,
1317 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1318 restoring_missing_file, reverting_versioned_file, 1,
1319 path_is_unversioned, repo, progress_cb, progress_arg);
1323 if (symlink(target_path, ondisk_path) == -1) {
1324 if (errno == EEXIST) {
1325 int symlink_replaced;
1326 if (path_is_unversioned) {
1327 err = (*progress_cb)(progress_arg,
1328 GOT_STATUS_UNVERSIONED, path);
1331 err = replace_existing_symlink(&symlink_replaced,
1332 ondisk_path, target_path, target_len);
1336 if (symlink_replaced) {
1337 err = (*progress_cb)(progress_arg,
1338 reverting_versioned_file ?
1340 GOT_STATUS_UPDATE, path);
1342 err = (*progress_cb)(progress_arg,
1343 GOT_STATUS_EXISTS, path);
1346 return err; /* Nothing else to do. */
1349 if (errno == ENOENT) {
1351 err = got_path_dirname(&parent, ondisk_path);
1354 err = add_dir_on_disk(worktree, parent);
1359 * Retry, and fall through to error handling
1360 * below if this second attempt fails.
1362 if (symlink(target_path, ondisk_path) != -1) {
1363 err = NULL; /* success */
1368 /* Handle errors from first or second creation attempt. */
1369 if (errno == ENAMETOOLONG) {
1370 /* bad target path; install as a regular file */
1371 *is_bad_symlink = 1;
1372 got_object_blob_rewind(blob);
1373 err = install_blob(worktree, ondisk_path, path,
1374 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1375 restoring_missing_file, reverting_versioned_file, 1,
1376 path_is_unversioned, repo,
1377 progress_cb, progress_arg);
1378 } else if (errno == ENOTDIR) {
1379 err = got_error_path(ondisk_path,
1380 GOT_ERR_FILE_OBSTRUCTED);
1382 err = got_error_from_errno3("symlink",
1383 target_path, ondisk_path);
1385 } else if (progress_cb)
1386 err = (*progress_cb)(progress_arg, reverting_versioned_file ?
1387 GOT_STATUS_REVERT : GOT_STATUS_ADD, path);
1391 static const struct got_error *
1392 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1393 const char *path, mode_t te_mode, mode_t st_mode,
1394 struct got_blob_object *blob, int restoring_missing_file,
1395 int reverting_versioned_file, int installing_bad_symlink,
1396 int path_is_unversioned, struct got_repository *repo,
1397 got_worktree_checkout_cb progress_cb, void *progress_arg)
1399 const struct got_error *err = NULL;
1403 char *tmppath = NULL;
1406 mode = get_ondisk_perms(te_mode & S_IXUSR, GOT_DEFAULT_FILE_MODE);
1407 fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW |
1410 if (errno == ENOENT) {
1412 err = got_path_dirname(&parent, path);
1415 err = add_dir_on_disk(worktree, parent);
1419 fd = open(ondisk_path,
1420 O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC,
1423 return got_error_from_errno2("open",
1425 } else if (errno == EEXIST) {
1426 if (path_is_unversioned) {
1427 err = (*progress_cb)(progress_arg,
1428 GOT_STATUS_UNVERSIONED, path);
1431 if (!(S_ISLNK(st_mode) && S_ISREG(te_mode)) &&
1432 !S_ISREG(st_mode) && !installing_bad_symlink) {
1433 /* TODO file is obstructed; do something */
1434 err = got_error_path(ondisk_path,
1435 GOT_ERR_FILE_OBSTRUCTED);
1438 err = got_opentemp_named_fd(&tmppath, &fd,
1444 if (fchmod(fd, apply_umask(mode)) == -1) {
1445 err = got_error_from_errno2("fchmod",
1451 return got_error_from_errno2("open", ondisk_path);
1455 if (restoring_missing_file)
1456 err = (*progress_cb)(progress_arg, GOT_STATUS_MISSING,
1458 else if (reverting_versioned_file)
1459 err = (*progress_cb)(progress_arg, GOT_STATUS_REVERT,
1462 err = (*progress_cb)(progress_arg,
1463 update ? GOT_STATUS_UPDATE : GOT_STATUS_ADD, path);
1468 hdrlen = got_object_blob_get_hdrlen(blob);
1470 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1471 err = got_object_blob_read_block(&len, blob);
1475 /* Skip blob object header first time around. */
1476 ssize_t outlen = write(fd, buf + hdrlen, len - hdrlen);
1478 err = got_error_from_errno("write");
1480 } else if (outlen != len - hdrlen) {
1481 err = got_error(GOT_ERR_IO);
1488 if (fsync(fd) != 0) {
1489 err = got_error_from_errno("fsync");
1494 if (S_ISLNK(st_mode) && unlink(ondisk_path) == -1) {
1495 err = got_error_from_errno2("unlink", ondisk_path);
1498 if (rename(tmppath, ondisk_path) != 0) {
1499 err = got_error_from_errno3("rename", tmppath,
1508 if (fd != -1 && close(fd) == -1 && err == NULL)
1509 err = got_error_from_errno("close");
1510 if (tmppath != NULL && unlink(tmppath) == -1 && err == NULL)
1511 err = got_error_from_errno2("unlink", tmppath);
1517 * Upgrade STATUS_MODIFY to STATUS_CONFLICT if a
1518 * conflict marker is found in newly added lines only.
1520 static const struct got_error *
1521 get_modified_file_content_status(unsigned char *status,
1522 struct got_blob_object *blob, const char *path, struct stat *sb,
1525 const struct got_error *err = NULL;
1526 const char *markers[3] = {
1527 GOT_DIFF_CONFLICT_MARKER_BEGIN,
1528 GOT_DIFF_CONFLICT_MARKER_SEP,
1529 GOT_DIFF_CONFLICT_MARKER_END
1531 FILE *f = NULL, *f1 = NULL;
1534 size_t linesize = 0;
1538 if (*status == GOT_STATUS_MODIFY) {
1541 return got_error_from_errno("got_opentemp");
1543 f1 = got_opentemp();
1545 err = got_error_from_errno("got_opentemp");
1550 err = got_object_blob_dump_to_file(&sz1, NULL, NULL,
1556 err = got_diff_blob_file(blob, f1, sz1, NULL, ondisk_file, 1,
1557 sb, path, GOT_DIFF_ALGORITHM_MYERS, 0, 0, 0, NULL, f);
1561 if (fflush(f) == EOF) {
1562 err = got_error_from_errno("fflush");
1565 if (fseeko(f, 0L, SEEK_SET) == -1) {
1566 err = got_error_from_errno("fseek");
1571 while (*status == GOT_STATUS_MODIFY) {
1572 linelen = getline(&line, &linesize, f);
1573 if (linelen == -1) {
1576 err = got_ferror(f, GOT_ERR_IO);
1581 strncmp(line + 1, markers[i], strlen(markers[i])) == 0) {
1582 if (strcmp(markers[i], GOT_DIFF_CONFLICT_MARKER_END)
1584 *status = GOT_STATUS_CONFLICT;
1592 if (f != NULL && fclose(f) == EOF && err == NULL)
1593 err = got_error_from_errno("fclose");
1594 if (f1 != NULL && fclose(f1) == EOF && err == NULL)
1595 err = got_error_from_errno("fclose");
1601 xbit_differs(struct got_fileindex_entry *ie, uint16_t st_mode)
1603 mode_t ie_mode = got_fileindex_perms_to_st(ie);
1604 return ((ie_mode & S_IXUSR) != (st_mode & S_IXUSR));
1608 stat_info_differs(struct got_fileindex_entry *ie, struct stat *sb)
1610 return !(ie->ctime_sec == sb->st_ctim.tv_sec &&
1611 ie->ctime_nsec == sb->st_ctim.tv_nsec &&
1612 ie->mtime_sec == sb->st_mtim.tv_sec &&
1613 ie->mtime_nsec == sb->st_mtim.tv_nsec &&
1614 ie->size == (sb->st_size & 0xffffffff) &&
1615 !xbit_differs(ie, sb->st_mode));
1618 static unsigned char
1619 get_staged_status(struct got_fileindex_entry *ie)
1621 switch (got_fileindex_entry_stage_get(ie)) {
1622 case GOT_FILEIDX_STAGE_ADD:
1623 return GOT_STATUS_ADD;
1624 case GOT_FILEIDX_STAGE_DELETE:
1625 return GOT_STATUS_DELETE;
1626 case GOT_FILEIDX_STAGE_MODIFY:
1627 return GOT_STATUS_MODIFY;
1629 return GOT_STATUS_NO_CHANGE;
1633 static const struct got_error *
1634 get_symlink_modification_status(unsigned char *status,
1635 struct got_fileindex_entry *ie, const char *abspath,
1636 int dirfd, const char *de_name, struct got_blob_object *blob)
1638 const struct got_error *err = NULL;
1639 char target_path[PATH_MAX];
1640 char etarget[PATH_MAX];
1642 size_t len, target_len = 0;
1643 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1644 size_t hdrlen = got_object_blob_get_hdrlen(blob);
1646 *status = GOT_STATUS_NO_CHANGE;
1648 /* Blob object content specifies the target path of the link. */
1650 err = got_object_blob_read_block(&len, blob);
1653 if (len + target_len >= sizeof(target_path)) {
1655 * Should not happen. The blob contents were OK
1656 * when this symlink was installed.
1658 return got_error(GOT_ERR_NO_SPACE);
1661 /* Skip blob object header first time around. */
1662 memcpy(target_path + target_len, buf + hdrlen,
1664 target_len += len - hdrlen;
1668 target_path[target_len] = '\0';
1671 elen = readlinkat(dirfd, de_name, etarget, sizeof(etarget));
1673 return got_error_from_errno2("readlinkat", abspath);
1675 elen = readlink(abspath, etarget, sizeof(etarget));
1677 return got_error_from_errno2("readlink", abspath);
1680 if (elen != target_len || memcmp(etarget, target_path, target_len) != 0)
1681 *status = GOT_STATUS_MODIFY;
1686 static const struct got_error *
1687 get_file_status(unsigned char *status, struct stat *sb,
1688 struct got_fileindex_entry *ie, const char *abspath,
1689 int dirfd, const char *de_name, struct got_repository *repo)
1691 const struct got_error *err = NULL;
1692 struct got_object_id id;
1694 int fd = -1, fd1 = -1;
1697 struct got_blob_object *blob = NULL;
1699 unsigned char staged_status;
1701 staged_status = get_staged_status(ie);
1702 *status = GOT_STATUS_NO_CHANGE;
1703 memset(sb, 0, sizeof(*sb));
1706 * Whenever the caller provides a directory descriptor and a
1707 * directory entry name for the file, use them! This prevents
1708 * race conditions if filesystem paths change beneath our feet.
1711 if (fstatat(dirfd, de_name, sb, AT_SYMLINK_NOFOLLOW) == -1) {
1712 if (errno == ENOENT) {
1713 if (got_fileindex_entry_has_file_on_disk(ie))
1714 *status = GOT_STATUS_MISSING;
1716 *status = GOT_STATUS_DELETE;
1719 err = got_error_from_errno2("fstatat", abspath);
1723 fd = open(abspath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
1724 if (fd == -1 && errno != ENOENT &&
1725 !got_err_open_nofollow_on_symlink())
1726 return got_error_from_errno2("open", abspath);
1727 else if (fd == -1 && got_err_open_nofollow_on_symlink()) {
1728 if (lstat(abspath, sb) == -1)
1729 return got_error_from_errno2("lstat", abspath);
1730 } else if (fd == -1 || fstat(fd, sb) == -1) {
1731 if (errno == ENOENT) {
1732 if (got_fileindex_entry_has_file_on_disk(ie))
1733 *status = GOT_STATUS_MISSING;
1735 *status = GOT_STATUS_DELETE;
1738 err = got_error_from_errno2("fstat", abspath);
1743 if (!S_ISREG(sb->st_mode) && !S_ISLNK(sb->st_mode)) {
1744 *status = GOT_STATUS_OBSTRUCTED;
1748 if (!got_fileindex_entry_has_file_on_disk(ie)) {
1749 *status = GOT_STATUS_DELETE;
1751 } else if (!got_fileindex_entry_has_blob(ie) &&
1752 staged_status != GOT_STATUS_ADD) {
1753 *status = GOT_STATUS_ADD;
1757 if (!stat_info_differs(ie, sb))
1760 if (S_ISLNK(sb->st_mode) &&
1761 got_fileindex_entry_filetype_get(ie) != GOT_FILEIDX_MODE_SYMLINK) {
1762 *status = GOT_STATUS_MODIFY;
1766 if (staged_status == GOT_STATUS_MODIFY ||
1767 staged_status == GOT_STATUS_ADD)
1768 got_fileindex_entry_get_staged_blob_id(&id, ie);
1770 got_fileindex_entry_get_blob_id(&id, ie);
1772 fd1 = got_opentempfd();
1774 err = got_error_from_errno("got_opentempfd");
1777 err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf), fd1);
1781 if (S_ISLNK(sb->st_mode)) {
1782 err = get_symlink_modification_status(status, ie,
1783 abspath, dirfd, de_name, blob);
1788 fd = openat(dirfd, de_name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
1790 err = got_error_from_errno2("openat", abspath);
1795 f = fdopen(fd, "r");
1797 err = got_error_from_errno2("fdopen", abspath);
1801 hdrlen = got_object_blob_get_hdrlen(blob);
1803 const uint8_t *bbuf = got_object_blob_get_read_buf(blob);
1804 err = got_object_blob_read_block(&blen, blob);
1807 /* Skip length of blob object header first time around. */
1808 flen = fread(fbuf, 1, sizeof(fbuf) - hdrlen, f);
1809 if (flen == 0 && ferror(f)) {
1810 err = got_error_from_errno("fread");
1813 if (blen - hdrlen == 0) {
1815 *status = GOT_STATUS_MODIFY;
1817 } else if (flen == 0) {
1818 if (blen - hdrlen != 0)
1819 *status = GOT_STATUS_MODIFY;
1821 } else if (blen - hdrlen == flen) {
1822 /* Skip blob object header first time around. */
1823 if (memcmp(bbuf + hdrlen, fbuf, flen) != 0) {
1824 *status = GOT_STATUS_MODIFY;
1828 *status = GOT_STATUS_MODIFY;
1834 if (*status == GOT_STATUS_MODIFY) {
1836 err = get_modified_file_content_status(status, blob, ie->path,
1838 } else if (xbit_differs(ie, sb->st_mode))
1839 *status = GOT_STATUS_MODE_CHANGE;
1841 if (fd1 != -1 && close(fd1) == -1 && err == NULL)
1842 err = got_error_from_errno("close");
1844 got_object_blob_close(blob);
1845 if (f != NULL && fclose(f) == EOF && err == NULL)
1846 err = got_error_from_errno2("fclose", abspath);
1847 if (fd != -1 && close(fd) == -1 && err == NULL)
1848 err = got_error_from_errno2("close", abspath);
1853 * Update timestamps in the file index if a file is unmodified and
1854 * we had to run a full content comparison to find out.
1856 static const struct got_error *
1857 sync_timestamps(int wt_fd, const char *path, unsigned char status,
1858 struct got_fileindex_entry *ie, struct stat *sb)
1860 if (status == GOT_STATUS_NO_CHANGE && stat_info_differs(ie, sb))
1861 return got_fileindex_entry_update(ie, wt_fd, path,
1862 ie->blob_sha1, ie->commit_sha1, 1);
1867 static const struct got_error *
1868 update_blob(struct got_worktree *worktree,
1869 struct got_fileindex *fileindex, struct got_fileindex_entry *ie,
1870 struct got_tree_entry *te, const char *path,
1871 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
1874 const struct got_error *err = NULL;
1875 struct got_blob_object *blob = NULL;
1876 char *ondisk_path = NULL;
1877 unsigned char status = GOT_STATUS_NO_CHANGE;
1879 int fd1 = -1, fd2 = -1;
1881 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, path) == -1)
1882 return got_error_from_errno("asprintf");
1885 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE) {
1886 err = got_error_path(ie->path, GOT_ERR_FILE_STAGED);
1889 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
1893 if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE)
1894 sb.st_mode = got_fileindex_perms_to_st(ie);
1896 if (stat(ondisk_path, &sb) == -1) {
1897 if (errno != ENOENT) {
1898 err = got_error_from_errno2("stat",
1902 sb.st_mode = GOT_DEFAULT_FILE_MODE;
1903 status = GOT_STATUS_UNVERSIONED;
1905 if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode))
1906 status = GOT_STATUS_UNVERSIONED;
1908 status = GOT_STATUS_OBSTRUCTED;
1912 if (status == GOT_STATUS_OBSTRUCTED) {
1914 got_fileindex_entry_mark_skipped(ie);
1915 err = (*progress_cb)(progress_arg, status, path);
1918 if (status == GOT_STATUS_CONFLICT) {
1920 got_fileindex_entry_mark_skipped(ie);
1921 err = (*progress_cb)(progress_arg, GOT_STATUS_CANNOT_UPDATE,
1926 if (ie && status != GOT_STATUS_MISSING && S_ISREG(sb.st_mode) &&
1927 (S_ISLNK(te->mode) ||
1928 (te->mode & S_IXUSR) == (sb.st_mode & S_IXUSR))) {
1930 * This is a regular file or an installed bad symlink.
1931 * If the file index indicates that this file is already
1932 * up-to-date with respect to the repository we can skip
1933 * updating contents of this file.
1935 if (got_fileindex_entry_has_commit(ie) &&
1936 memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
1937 SHA1_DIGEST_LENGTH) == 0) {
1939 err = sync_timestamps(worktree->root_fd,
1940 path, status, ie, &sb);
1943 err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
1947 if (got_fileindex_entry_has_blob(ie) &&
1948 memcmp(ie->blob_sha1, te->id.sha1,
1949 SHA1_DIGEST_LENGTH) == 0) {
1950 /* Different commit but the same blob. */
1951 err = sync_timestamps(worktree->root_fd,
1952 path, status, ie, &sb);
1955 err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
1961 fd1 = got_opentempfd();
1963 err = got_error_from_errno("got_opentempfd");
1966 err = got_object_open_as_blob(&blob, repo, &te->id, 8192, fd1);
1970 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_ADD) {
1971 int update_timestamps;
1972 struct got_blob_object *blob2 = NULL;
1973 char *label_orig = NULL;
1974 if (got_fileindex_entry_has_blob(ie)) {
1975 fd2 = got_opentempfd();
1977 err = got_error_from_errno("got_opentempfd");
1980 struct got_object_id id2;
1981 got_fileindex_entry_get_blob_id(&id2, ie);
1982 err = got_object_open_as_blob(&blob2, repo, &id2, 8192,
1987 if (got_fileindex_entry_has_commit(ie)) {
1988 char id_str[SHA1_DIGEST_STRING_LENGTH];
1989 if (got_sha1_digest_to_str(ie->commit_sha1, id_str,
1990 sizeof(id_str)) == NULL) {
1991 err = got_error_path(id_str,
1992 GOT_ERR_BAD_OBJ_ID_STR);
1995 if (asprintf(&label_orig, "%s: commit %s",
1996 GOT_MERGE_LABEL_BASE, id_str) == -1) {
1997 err = got_error_from_errno("asprintf");
2001 if (S_ISLNK(te->mode) && S_ISLNK(sb.st_mode)) {
2003 err = got_object_blob_read_to_str(&link_target, blob);
2006 err = merge_symlink(worktree, blob2, ondisk_path, path,
2007 label_orig, link_target, worktree->base_commit_id,
2008 repo, progress_cb, progress_arg);
2011 err = merge_blob(&update_timestamps, worktree, blob2,
2012 ondisk_path, path, sb.st_mode, label_orig, blob,
2013 worktree->base_commit_id, repo,
2014 progress_cb, progress_arg);
2017 if (fd2 != -1 && close(fd2) == -1 && err == NULL) {
2018 err = got_error_from_errno("close");
2022 got_object_blob_close(blob2);
2026 * Do not update timestamps of files with local changes.
2027 * Otherwise, a future status walk would treat them as
2028 * unmodified files again.
2030 err = got_fileindex_entry_update(ie, worktree->root_fd, path,
2031 blob->id.sha1, worktree->base_commit_id->sha1,
2033 } else if (status == GOT_STATUS_MODE_CHANGE) {
2034 err = got_fileindex_entry_update(ie, worktree->root_fd, path,
2035 blob->id.sha1, worktree->base_commit_id->sha1, 0);
2036 } else if (status == GOT_STATUS_DELETE) {
2037 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
2040 err = got_fileindex_entry_update(ie, worktree->root_fd, path,
2041 blob->id.sha1, worktree->base_commit_id->sha1, 0);
2045 int is_bad_symlink = 0;
2046 if (S_ISLNK(te->mode)) {
2047 err = install_symlink(&is_bad_symlink, worktree,
2048 ondisk_path, path, blob,
2049 status == GOT_STATUS_MISSING, 0,
2050 status == GOT_STATUS_UNVERSIONED, 0,
2051 repo, progress_cb, progress_arg);
2053 err = install_blob(worktree, ondisk_path, path,
2054 te->mode, sb.st_mode, blob,
2055 status == GOT_STATUS_MISSING, 0, 0,
2056 status == GOT_STATUS_UNVERSIONED, repo,
2057 progress_cb, progress_arg);
2063 err = got_fileindex_entry_update(ie,
2064 worktree->root_fd, path, blob->id.sha1,
2065 worktree->base_commit_id->sha1, 1);
2067 err = create_fileindex_entry(&ie, fileindex,
2068 worktree->base_commit_id, worktree->root_fd, path,
2074 if (is_bad_symlink) {
2075 got_fileindex_entry_filetype_set(ie,
2076 GOT_FILEIDX_MODE_BAD_SYMLINK);
2080 if (fd1 != -1 && close(fd1) == -1 && err == NULL) {
2081 err = got_error_from_errno("close");
2084 got_object_blob_close(blob);
2090 static const struct got_error *
2091 remove_ondisk_file(const char *root_path, const char *path)
2093 const struct got_error *err = NULL;
2094 char *ondisk_path = NULL, *parent = NULL;
2096 if (asprintf(&ondisk_path, "%s/%s", root_path, path) == -1)
2097 return got_error_from_errno("asprintf");
2099 if (unlink(ondisk_path) == -1) {
2100 if (errno != ENOENT)
2101 err = got_error_from_errno2("unlink", ondisk_path);
2103 size_t root_len = strlen(root_path);
2104 err = got_path_dirname(&parent, ondisk_path);
2107 while (got_path_cmp(parent, root_path,
2108 strlen(parent), root_len) != 0) {
2110 ondisk_path = parent;
2112 if (rmdir(ondisk_path) == -1) {
2113 if (errno != ENOTEMPTY)
2114 err = got_error_from_errno2("rmdir",
2118 err = got_path_dirname(&parent, ondisk_path);
2129 static const struct got_error *
2130 delete_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
2131 struct got_fileindex_entry *ie, struct got_repository *repo,
2132 got_worktree_checkout_cb progress_cb, void *progress_arg)
2134 const struct got_error *err = NULL;
2135 unsigned char status;
2139 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
2140 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
2142 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, ie->path)
2144 return got_error_from_errno("asprintf");
2146 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, repo);
2150 if (S_ISLNK(sb.st_mode) && status != GOT_STATUS_NO_CHANGE) {
2151 char ondisk_target[PATH_MAX];
2152 ssize_t ondisk_len = readlink(ondisk_path, ondisk_target,
2153 sizeof(ondisk_target));
2154 if (ondisk_len == -1) {
2155 err = got_error_from_errno2("readlink", ondisk_path);
2158 ondisk_target[ondisk_len] = '\0';
2159 err = install_symlink_conflict(NULL, worktree->base_commit_id,
2160 NULL, NULL, /* XXX pass common ancestor info? */
2161 ondisk_target, ondisk_path);
2164 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
2169 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_CONFLICT ||
2170 status == GOT_STATUS_ADD) {
2171 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, ie->path);
2175 * Preserve the working file and change the deleted blob's
2176 * entry into a schedule-add entry.
2178 err = got_fileindex_entry_update(ie, worktree->root_fd,
2179 ie->path, NULL, NULL, 0);
2181 err = (*progress_cb)(progress_arg, GOT_STATUS_DELETE, ie->path);
2184 if (status == GOT_STATUS_NO_CHANGE) {
2185 err = remove_ondisk_file(worktree->root_path, ie->path);
2189 got_fileindex_entry_remove(fileindex, ie);
2196 struct diff_cb_arg {
2197 struct got_fileindex *fileindex;
2198 struct got_worktree *worktree;
2199 struct got_repository *repo;
2200 got_worktree_checkout_cb progress_cb;
2202 got_cancel_cb cancel_cb;
2206 static const struct got_error *
2207 diff_old_new(void *arg, struct got_fileindex_entry *ie,
2208 struct got_tree_entry *te, const char *parent_path)
2210 struct diff_cb_arg *a = arg;
2212 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2213 return got_error(GOT_ERR_CANCELLED);
2215 return update_blob(a->worktree, a->fileindex, ie, te,
2216 ie->path, a->repo, a->progress_cb, a->progress_arg);
2219 static const struct got_error *
2220 diff_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
2222 struct diff_cb_arg *a = arg;
2224 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2225 return got_error(GOT_ERR_CANCELLED);
2227 return delete_blob(a->worktree, a->fileindex, ie,
2228 a->repo, a->progress_cb, a->progress_arg);
2231 static const struct got_error *
2232 diff_new(void *arg, struct got_tree_entry *te, const char *parent_path)
2234 struct diff_cb_arg *a = arg;
2235 const struct got_error *err;
2238 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2239 return got_error(GOT_ERR_CANCELLED);
2241 if (got_object_tree_entry_is_submodule(te))
2244 if (asprintf(&path, "%s%s%s", parent_path,
2245 parent_path[0] ? "/" : "", te->name)
2247 return got_error_from_errno("asprintf");
2249 if (S_ISDIR(te->mode))
2250 err = add_dir_on_disk(a->worktree, path);
2252 err = update_blob(a->worktree, a->fileindex, NULL, te, path,
2253 a->repo, a->progress_cb, a->progress_arg);
2259 const struct got_error *
2260 got_worktree_get_uuid(char **uuidstr, struct got_worktree *worktree)
2262 uint32_t uuid_status;
2264 uuid_to_string(&worktree->uuid, uuidstr, &uuid_status);
2265 if (uuid_status != uuid_s_ok) {
2267 return got_error_uuid(uuid_status, "uuid_to_string");
2273 static const struct got_error *
2274 get_ref_name(char **refname, struct got_worktree *worktree, const char *prefix)
2276 const struct got_error *err = NULL;
2277 char *uuidstr = NULL;
2281 err = got_worktree_get_uuid(&uuidstr, worktree);
2285 if (asprintf(refname, "%s-%s", prefix, uuidstr) == -1) {
2286 err = got_error_from_errno("asprintf");
2293 const struct got_error *
2294 got_worktree_get_logmsg_ref_name(char **refname, struct got_worktree *worktree,
2297 return get_ref_name(refname, worktree, prefix);
2300 const struct got_error *
2301 got_worktree_get_base_ref_name(char **refname, struct got_worktree *worktree)
2303 return get_ref_name(refname, worktree, GOT_WORKTREE_BASE_REF_PREFIX);
2306 static const struct got_error *
2307 get_rebase_tmp_ref_name(char **refname, struct got_worktree *worktree)
2309 return get_ref_name(refname, worktree,
2310 GOT_WORKTREE_REBASE_TMP_REF_PREFIX);
2313 static const struct got_error *
2314 get_newbase_symref_name(char **refname, struct got_worktree *worktree)
2316 return get_ref_name(refname, worktree, GOT_WORKTREE_NEWBASE_REF_PREFIX);
2319 static const struct got_error *
2320 get_rebase_branch_symref_name(char **refname, struct got_worktree *worktree)
2322 return get_ref_name(refname, worktree,
2323 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX);
2326 static const struct got_error *
2327 get_rebase_commit_ref_name(char **refname, struct got_worktree *worktree)
2329 return get_ref_name(refname, worktree,
2330 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX);
2333 static const struct got_error *
2334 get_histedit_tmp_ref_name(char **refname, struct got_worktree *worktree)
2336 return get_ref_name(refname, worktree,
2337 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX);
2340 static const struct got_error *
2341 get_histedit_branch_symref_name(char **refname, struct got_worktree *worktree)
2343 return get_ref_name(refname, worktree,
2344 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX);
2347 static const struct got_error *
2348 get_histedit_base_commit_ref_name(char **refname, struct got_worktree *worktree)
2350 return get_ref_name(refname, worktree,
2351 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX);
2354 static const struct got_error *
2355 get_histedit_commit_ref_name(char **refname, struct got_worktree *worktree)
2357 return get_ref_name(refname, worktree,
2358 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX);
2361 const struct got_error *
2362 got_worktree_get_histedit_script_path(char **path,
2363 struct got_worktree *worktree)
2365 if (asprintf(path, "%s/%s/%s", worktree->root_path,
2366 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_HISTEDIT_SCRIPT) == -1) {
2368 return got_error_from_errno("asprintf");
2373 static const struct got_error *
2374 get_merge_branch_ref_name(char **refname, struct got_worktree *worktree)
2376 return get_ref_name(refname, worktree,
2377 GOT_WORKTREE_MERGE_BRANCH_REF_PREFIX);
2380 static const struct got_error *
2381 get_merge_commit_ref_name(char **refname, struct got_worktree *worktree)
2383 return get_ref_name(refname, worktree,
2384 GOT_WORKTREE_MERGE_COMMIT_REF_PREFIX);
2388 * Prevent Git's garbage collector from deleting our base commit by
2389 * setting a reference to our base commit's ID.
2391 static const struct got_error *
2392 ref_base_commit(struct got_worktree *worktree, struct got_repository *repo)
2394 const struct got_error *err = NULL;
2395 struct got_reference *ref = NULL;
2398 err = got_worktree_get_base_ref_name(&refname, worktree);
2402 err = got_ref_alloc(&ref, refname, worktree->base_commit_id);
2406 err = got_ref_write(ref, repo);
2414 static const struct got_error *
2415 get_fileindex_path(char **fileindex_path, struct got_worktree *worktree)
2417 const struct got_error *err = NULL;
2419 if (asprintf(fileindex_path, "%s/%s/%s", worktree->root_path,
2420 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_FILE_INDEX) == -1) {
2421 err = got_error_from_errno("asprintf");
2422 *fileindex_path = NULL;
2428 static const struct got_error *
2429 open_fileindex(struct got_fileindex **fileindex, char **fileindex_path,
2430 struct got_worktree *worktree)
2432 const struct got_error *err = NULL;
2435 *fileindex_path = NULL;
2436 *fileindex = got_fileindex_alloc();
2437 if (*fileindex == NULL)
2438 return got_error_from_errno("got_fileindex_alloc");
2440 err = get_fileindex_path(fileindex_path, worktree);
2444 index = fopen(*fileindex_path, "rbe");
2445 if (index == NULL) {
2446 if (errno != ENOENT)
2447 err = got_error_from_errno2("fopen", *fileindex_path);
2449 err = got_fileindex_read(*fileindex, index);
2450 if (fclose(index) == EOF && err == NULL)
2451 err = got_error_from_errno("fclose");
2455 free(*fileindex_path);
2456 *fileindex_path = NULL;
2457 got_fileindex_free(*fileindex);
2463 struct bump_base_commit_id_arg {
2464 struct got_object_id *base_commit_id;
2467 const char *entry_name;
2468 got_worktree_checkout_cb progress_cb;
2472 static const struct got_error *
2473 bump_base_commit_id(void *arg, struct got_fileindex_entry *ie)
2475 const struct got_error *err;
2476 struct bump_base_commit_id_arg *a = arg;
2478 if (a->entry_name) {
2479 if (strcmp(ie->path, a->path) != 0)
2481 } else if (!got_path_is_child(ie->path, a->path, a->path_len))
2484 if (got_fileindex_entry_was_skipped(ie))
2487 if (memcmp(ie->commit_sha1, a->base_commit_id->sha1,
2488 SHA1_DIGEST_LENGTH) == 0)
2491 if (a->progress_cb) {
2492 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_BUMP_BASE,
2497 memcpy(ie->commit_sha1, a->base_commit_id->sha1, SHA1_DIGEST_LENGTH);
2501 /* Bump base commit ID of all files within an updated part of the work tree. */
2502 static const struct got_error *
2503 bump_base_commit_id_everywhere(struct got_worktree *worktree,
2504 struct got_fileindex *fileindex,
2505 got_worktree_checkout_cb progress_cb, void *progress_arg)
2507 struct bump_base_commit_id_arg bbc_arg;
2509 bbc_arg.base_commit_id = worktree->base_commit_id;
2510 bbc_arg.entry_name = NULL;
2512 bbc_arg.path_len = 0;
2513 bbc_arg.progress_cb = progress_cb;
2514 bbc_arg.progress_arg = progress_arg;
2516 return got_fileindex_for_each_entry_safe(fileindex,
2517 bump_base_commit_id, &bbc_arg);
2520 static const struct got_error *
2521 sync_fileindex(struct got_fileindex *fileindex, const char *fileindex_path)
2523 const struct got_error *err = NULL;
2524 char *new_fileindex_path = NULL;
2525 FILE *new_index = NULL;
2526 struct timespec timeout;
2528 err = got_opentemp_named(&new_fileindex_path, &new_index,
2529 fileindex_path, "");
2533 err = got_fileindex_write(fileindex, new_index);
2537 if (rename(new_fileindex_path, fileindex_path) != 0) {
2538 err = got_error_from_errno3("rename", new_fileindex_path,
2540 unlink(new_fileindex_path);
2544 * Sleep for a short amount of time to ensure that files modified after
2545 * this program exits have a different time stamp from the one which
2546 * was recorded in the file index.
2549 timeout.tv_nsec = 1;
2550 nanosleep(&timeout, NULL);
2554 free(new_fileindex_path);
2558 static const struct got_error *
2559 find_tree_entry_for_checkout(int *entry_type, char **tree_relpath,
2560 struct got_object_id **tree_id, const char *wt_relpath,
2561 struct got_commit_object *base_commit, struct got_worktree *worktree,
2562 struct got_repository *repo)
2564 const struct got_error *err = NULL;
2565 struct got_object_id *id = NULL;
2566 char *in_repo_path = NULL;
2567 int is_root_wt = got_path_is_root_dir(worktree->path_prefix);
2569 *entry_type = GOT_OBJ_TYPE_ANY;
2570 *tree_relpath = NULL;
2573 if (wt_relpath[0] == '\0') {
2574 /* Check out all files within the work tree. */
2575 *entry_type = GOT_OBJ_TYPE_TREE;
2576 *tree_relpath = strdup("");
2577 if (*tree_relpath == NULL) {
2578 err = got_error_from_errno("strdup");
2581 err = got_object_id_by_path(tree_id, repo, base_commit,
2582 worktree->path_prefix);
2588 /* Check out a subset of files in the work tree. */
2590 if (asprintf(&in_repo_path, "%s%s%s", worktree->path_prefix,
2591 is_root_wt ? "" : "/", wt_relpath) == -1) {
2592 err = got_error_from_errno("asprintf");
2596 err = got_object_id_by_path(&id, repo, base_commit, in_repo_path);
2601 in_repo_path = NULL;
2603 err = got_object_get_type(entry_type, repo, id);
2607 if (*entry_type == GOT_OBJ_TYPE_BLOB) {
2608 /* Check out a single file. */
2609 if (strchr(wt_relpath, '/') == NULL) {
2610 /* Check out a single file in work tree's root dir. */
2611 in_repo_path = strdup(worktree->path_prefix);
2612 if (in_repo_path == NULL) {
2613 err = got_error_from_errno("strdup");
2616 *tree_relpath = strdup("");
2617 if (*tree_relpath == NULL) {
2618 err = got_error_from_errno("strdup");
2622 /* Check out a single file in a subdirectory. */
2623 err = got_path_dirname(tree_relpath, wt_relpath);
2626 if (asprintf(&in_repo_path, "%s%s%s",
2627 worktree->path_prefix, is_root_wt ? "" : "/",
2628 *tree_relpath) == -1) {
2629 err = got_error_from_errno("asprintf");
2633 err = got_object_id_by_path(tree_id, repo,
2634 base_commit, in_repo_path);
2636 /* Check out all files within a subdirectory. */
2637 *tree_id = got_object_id_dup(id);
2638 if (*tree_id == NULL) {
2639 err = got_error_from_errno("got_object_id_dup");
2642 *tree_relpath = strdup(wt_relpath);
2643 if (*tree_relpath == NULL) {
2644 err = got_error_from_errno("strdup");
2652 *entry_type = GOT_OBJ_TYPE_ANY;
2653 free(*tree_relpath);
2654 *tree_relpath = NULL;
2661 static const struct got_error *
2662 checkout_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
2663 const char *relpath, struct got_object_id *tree_id, const char *entry_name,
2664 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
2665 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
2667 const struct got_error *err = NULL;
2668 struct got_commit_object *commit = NULL;
2669 struct got_tree_object *tree = NULL;
2670 struct got_fileindex_diff_tree_cb diff_cb;
2671 struct diff_cb_arg arg;
2673 err = ref_base_commit(worktree, repo);
2675 if (!(err->code == GOT_ERR_ERRNO &&
2676 (errno == EACCES || errno == EROFS)))
2678 err = (*progress_cb)(progress_arg,
2679 GOT_STATUS_BASE_REF_ERR, worktree->root_path);
2684 err = got_object_open_as_commit(&commit, repo,
2685 worktree->base_commit_id);
2689 err = got_object_open_as_tree(&tree, repo, tree_id);
2694 got_object_tree_find_entry(tree, entry_name) == NULL) {
2695 err = got_error_path(entry_name, GOT_ERR_NO_TREE_ENTRY);
2699 diff_cb.diff_old_new = diff_old_new;
2700 diff_cb.diff_old = diff_old;
2701 diff_cb.diff_new = diff_new;
2702 arg.fileindex = fileindex;
2703 arg.worktree = worktree;
2705 arg.progress_cb = progress_cb;
2706 arg.progress_arg = progress_arg;
2707 arg.cancel_cb = cancel_cb;
2708 arg.cancel_arg = cancel_arg;
2709 err = got_fileindex_diff_tree(fileindex, tree, relpath,
2710 entry_name, repo, &diff_cb, &arg);
2713 got_object_tree_close(tree);
2715 got_object_commit_close(commit);
2719 const struct got_error *
2720 got_worktree_checkout_files(struct got_worktree *worktree,
2721 struct got_pathlist_head *paths, struct got_repository *repo,
2722 got_worktree_checkout_cb progress_cb, void *progress_arg,
2723 got_cancel_cb cancel_cb, void *cancel_arg)
2725 const struct got_error *err = NULL, *sync_err, *unlockerr;
2726 struct got_commit_object *commit = NULL;
2727 struct got_tree_object *tree = NULL;
2728 struct got_fileindex *fileindex = NULL;
2729 char *fileindex_path = NULL;
2730 struct got_pathlist_entry *pe;
2731 struct tree_path_data {
2732 STAILQ_ENTRY(tree_path_data) entry;
2733 struct got_object_id *tree_id;
2738 STAILQ_HEAD(tree_paths, tree_path_data) tree_paths;
2740 STAILQ_INIT(&tree_paths);
2742 err = lock_worktree(worktree, LOCK_EX);
2746 err = got_object_open_as_commit(&commit, repo,
2747 worktree->base_commit_id);
2751 /* Map all specified paths to in-repository trees. */
2752 TAILQ_FOREACH(pe, paths, entry) {
2753 tpd = malloc(sizeof(*tpd));
2755 err = got_error_from_errno("malloc");
2759 err = find_tree_entry_for_checkout(&tpd->entry_type,
2760 &tpd->relpath, &tpd->tree_id, pe->path, commit,
2767 if (tpd->entry_type == GOT_OBJ_TYPE_BLOB) {
2768 err = got_path_basename(&tpd->entry_name, pe->path);
2776 tpd->entry_name = NULL;
2778 STAILQ_INSERT_TAIL(&tree_paths, tpd, entry);
2782 * Read the file index.
2783 * Checking out files is supposed to be an idempotent operation.
2784 * If the on-disk file index is incomplete we will try to complete it.
2786 err = open_fileindex(&fileindex, &fileindex_path, worktree);
2790 tpd = STAILQ_FIRST(&tree_paths);
2791 TAILQ_FOREACH(pe, paths, entry) {
2792 struct bump_base_commit_id_arg bbc_arg;
2794 err = checkout_files(worktree, fileindex, tpd->relpath,
2795 tpd->tree_id, tpd->entry_name, repo,
2796 progress_cb, progress_arg, cancel_cb, cancel_arg);
2800 bbc_arg.base_commit_id = worktree->base_commit_id;
2801 bbc_arg.entry_name = tpd->entry_name;
2802 bbc_arg.path = pe->path;
2803 bbc_arg.path_len = pe->path_len;
2804 bbc_arg.progress_cb = progress_cb;
2805 bbc_arg.progress_arg = progress_arg;
2806 err = got_fileindex_for_each_entry_safe(fileindex,
2807 bump_base_commit_id, &bbc_arg);
2811 tpd = STAILQ_NEXT(tpd, entry);
2813 sync_err = sync_fileindex(fileindex, fileindex_path);
2814 if (sync_err && err == NULL)
2817 free(fileindex_path);
2819 got_object_tree_close(tree);
2821 got_object_commit_close(commit);
2823 got_fileindex_free(fileindex);
2824 while (!STAILQ_EMPTY(&tree_paths)) {
2825 tpd = STAILQ_FIRST(&tree_paths);
2826 STAILQ_REMOVE_HEAD(&tree_paths, entry);
2831 unlockerr = lock_worktree(worktree, LOCK_SH);
2832 if (unlockerr && err == NULL)
2837 struct merge_file_cb_arg {
2838 struct got_worktree *worktree;
2839 struct got_fileindex *fileindex;
2840 got_worktree_checkout_cb progress_cb;
2842 got_cancel_cb cancel_cb;
2844 const char *label_orig;
2845 struct got_object_id *commit_id2;
2846 int allow_bad_symlinks;
2849 static const struct got_error *
2850 merge_file_cb(void *arg, struct got_blob_object *blob1,
2851 struct got_blob_object *blob2, FILE *f1, FILE *f2,
2852 struct got_object_id *id1, struct got_object_id *id2,
2853 const char *path1, const char *path2,
2854 mode_t mode1, mode_t mode2, struct got_repository *repo)
2856 static const struct got_error *err = NULL;
2857 struct merge_file_cb_arg *a = arg;
2858 struct got_fileindex_entry *ie;
2859 char *ondisk_path = NULL;
2861 unsigned char status;
2862 int local_changes_subsumed;
2863 FILE *f_orig = NULL, *f_deriv = NULL, *f_deriv2 = NULL;
2864 char *id_str = NULL, *label_deriv2 = NULL;
2866 if (blob1 && blob2) {
2867 ie = got_fileindex_entry_get(a->fileindex, path2,
2870 return (*a->progress_cb)(a->progress_arg,
2871 GOT_STATUS_MISSING, path2);
2873 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2875 return got_error_from_errno("asprintf");
2877 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2882 if (status == GOT_STATUS_DELETE) {
2883 err = (*a->progress_cb)(a->progress_arg,
2884 GOT_STATUS_MERGE, path2);
2887 if (status != GOT_STATUS_NO_CHANGE &&
2888 status != GOT_STATUS_MODIFY &&
2889 status != GOT_STATUS_CONFLICT &&
2890 status != GOT_STATUS_ADD) {
2891 err = (*a->progress_cb)(a->progress_arg, status, path2);
2895 if (S_ISLNK(mode1) && S_ISLNK(mode2)) {
2897 err = got_object_blob_read_to_str(&link_target2, blob2);
2900 err = merge_symlink(a->worktree, blob1, ondisk_path,
2901 path2, a->label_orig, link_target2, a->commit_id2,
2902 repo, a->progress_cb, a->progress_arg);
2907 f_orig = got_opentemp();
2908 if (f_orig == NULL) {
2909 err = got_error_from_errno("got_opentemp");
2912 err = got_object_blob_dump_to_file(NULL, NULL, NULL,
2917 f_deriv2 = got_opentemp();
2918 if (f_deriv2 == NULL)
2920 err = got_object_blob_dump_to_file(NULL, NULL, NULL,
2925 fd = open(ondisk_path,
2926 O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
2928 err = got_error_from_errno2("open",
2932 f_deriv = fdopen(fd, "r");
2933 if (f_deriv == NULL) {
2934 err = got_error_from_errno2("fdopen",
2939 err = got_object_id_str(&id_str, a->commit_id2);
2942 if (asprintf(&label_deriv2, "%s: commit %s",
2943 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
2944 err = got_error_from_errno("asprintf");
2947 err = merge_file(&local_changes_subsumed, a->worktree,
2948 f_orig, f_deriv, f_deriv2, ondisk_path, path2,
2949 mode2, a->label_orig, NULL, label_deriv2,
2950 GOT_DIFF_ALGORITHM_PATIENCE, repo,
2951 a->progress_cb, a->progress_arg);
2954 ie = got_fileindex_entry_get(a->fileindex, path1,
2957 return (*a->progress_cb)(a->progress_arg,
2958 GOT_STATUS_MISSING, path1);
2960 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2962 return got_error_from_errno("asprintf");
2964 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2970 case GOT_STATUS_NO_CHANGE:
2971 err = (*a->progress_cb)(a->progress_arg,
2972 GOT_STATUS_DELETE, path1);
2975 err = remove_ondisk_file(a->worktree->root_path, path1);
2979 got_fileindex_entry_mark_deleted_from_disk(ie);
2981 case GOT_STATUS_DELETE:
2982 case GOT_STATUS_MISSING:
2983 err = (*a->progress_cb)(a->progress_arg,
2984 GOT_STATUS_DELETE, path1);
2988 got_fileindex_entry_mark_deleted_from_disk(ie);
2990 case GOT_STATUS_ADD: {
2991 struct got_object_id *id;
2995 * Delete the added file only if its content already
2996 * exists in the repository.
2998 err = got_object_blob_file_create(&id, &blob1_f,
2999 &blob1_size, path1);
3002 if (got_object_id_cmp(id, id1) == 0) {
3003 err = (*a->progress_cb)(a->progress_arg,
3004 GOT_STATUS_DELETE, path1);
3007 err = remove_ondisk_file(a->worktree->root_path,
3012 got_fileindex_entry_remove(a->fileindex,
3015 err = (*a->progress_cb)(a->progress_arg,
3016 GOT_STATUS_CANNOT_DELETE, path1);
3018 if (fclose(blob1_f) == EOF && err == NULL)
3019 err = got_error_from_errno("fclose");
3025 case GOT_STATUS_MODIFY:
3026 case GOT_STATUS_CONFLICT:
3027 err = (*a->progress_cb)(a->progress_arg,
3028 GOT_STATUS_CANNOT_DELETE, path1);
3032 case GOT_STATUS_OBSTRUCTED:
3033 err = (*a->progress_cb)(a->progress_arg, status, path1);
3041 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3043 return got_error_from_errno("asprintf");
3044 ie = got_fileindex_entry_get(a->fileindex, path2,
3047 err = get_file_status(&status, &sb, ie, ondisk_path,
3051 if (status != GOT_STATUS_NO_CHANGE &&
3052 status != GOT_STATUS_MODIFY &&
3053 status != GOT_STATUS_CONFLICT &&
3054 status != GOT_STATUS_ADD) {
3055 err = (*a->progress_cb)(a->progress_arg,
3059 if (S_ISLNK(mode2) && S_ISLNK(sb.st_mode)) {
3061 err = got_object_blob_read_to_str(&link_target2,
3065 err = merge_symlink(a->worktree, NULL,
3066 ondisk_path, path2, a->label_orig,
3067 link_target2, a->commit_id2, repo,
3068 a->progress_cb, a->progress_arg);
3070 } else if (S_ISREG(sb.st_mode)) {
3071 err = merge_blob(&local_changes_subsumed,
3072 a->worktree, NULL, ondisk_path, path2,
3073 sb.st_mode, a->label_orig, blob2,
3074 a->commit_id2, repo, a->progress_cb,
3077 err = got_error_path(ondisk_path,
3078 GOT_ERR_FILE_OBSTRUCTED);
3082 if (status == GOT_STATUS_DELETE) {
3083 err = got_fileindex_entry_update(ie,
3084 a->worktree->root_fd, path2, blob2->id.sha1,
3085 a->worktree->base_commit_id->sha1, 0);
3090 int is_bad_symlink = 0;
3091 sb.st_mode = GOT_DEFAULT_FILE_MODE;
3092 if (S_ISLNK(mode2)) {
3093 err = install_symlink(&is_bad_symlink,
3094 a->worktree, ondisk_path, path2, blob2, 0,
3095 0, 1, a->allow_bad_symlinks, repo,
3096 a->progress_cb, a->progress_arg);
3098 err = install_blob(a->worktree, ondisk_path, path2,
3099 mode2, sb.st_mode, blob2, 0, 0, 0, 1, repo,
3100 a->progress_cb, a->progress_arg);
3104 err = got_fileindex_entry_alloc(&ie, path2);
3107 err = got_fileindex_entry_update(ie,
3108 a->worktree->root_fd, path2, NULL, NULL, 1);
3110 got_fileindex_entry_free(ie);
3113 err = got_fileindex_entry_add(a->fileindex, ie);
3115 got_fileindex_entry_free(ie);
3118 if (is_bad_symlink) {
3119 got_fileindex_entry_filetype_set(ie,
3120 GOT_FILEIDX_MODE_BAD_SYMLINK);
3125 if (f_orig && fclose(f_orig) == EOF && err == NULL)
3126 err = got_error_from_errno("fclose");
3127 if (f_deriv && fclose(f_deriv) == EOF && err == NULL)
3128 err = got_error_from_errno("fclose");
3129 if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
3130 err = got_error_from_errno("fclose");
3137 static const struct got_error *
3138 check_mixed_commits(void *arg, struct got_fileindex_entry *ie)
3140 struct got_worktree *worktree = arg;
3142 /* Reject merges into a work tree with mixed base commits. */
3143 if (got_fileindex_entry_has_commit(ie) &&
3144 memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
3145 SHA1_DIGEST_LENGTH) != 0)
3146 return got_error(GOT_ERR_MIXED_COMMITS);
3151 struct check_merge_conflicts_arg {
3152 struct got_worktree *worktree;
3153 struct got_fileindex *fileindex;
3154 struct got_repository *repo;
3157 static const struct got_error *
3158 check_merge_conflicts(void *arg, struct got_blob_object *blob1,
3159 struct got_blob_object *blob2, FILE *f1, FILE *f2,
3160 struct got_object_id *id1, struct got_object_id *id2,
3161 const char *path1, const char *path2,
3162 mode_t mode1, mode_t mode2, struct got_repository *repo)
3164 const struct got_error *err = NULL;
3165 struct check_merge_conflicts_arg *a = arg;
3166 unsigned char status;
3168 struct got_fileindex_entry *ie;
3169 const char *path = path2 ? path2 : path1;
3170 struct got_object_id *id = id2 ? id2 : id1;
3176 ie = got_fileindex_entry_get(a->fileindex, path, strlen(path));
3180 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
3182 return got_error_from_errno("asprintf");
3184 /* Reject merges into a work tree with conflicted files. */
3185 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
3189 if (status == GOT_STATUS_CONFLICT)
3190 return got_error(GOT_ERR_CONFLICTS);
3195 static const struct got_error *
3196 merge_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
3197 const char *fileindex_path, struct got_object_id *commit_id1,
3198 struct got_object_id *commit_id2, struct got_repository *repo,
3199 got_worktree_checkout_cb progress_cb, void *progress_arg,
3200 got_cancel_cb cancel_cb, void *cancel_arg)
3202 const struct got_error *err = NULL, *sync_err;
3203 struct got_object_id *tree_id1 = NULL, *tree_id2 = NULL;
3204 struct got_tree_object *tree1 = NULL, *tree2 = NULL;
3205 struct got_commit_object *commit1 = NULL, *commit2 = NULL;
3206 struct check_merge_conflicts_arg cmc_arg;
3207 struct merge_file_cb_arg arg;
3208 char *label_orig = NULL;
3209 FILE *f1 = NULL, *f2 = NULL;
3210 int fd1 = -1, fd2 = -1;
3213 err = got_object_open_as_commit(&commit1, repo, commit_id1);
3216 err = got_object_id_by_path(&tree_id1, repo, commit1,
3217 worktree->path_prefix);
3218 if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
3224 err = got_object_open_as_tree(&tree1, repo, tree_id1);
3228 err = got_object_id_str(&id_str, commit_id1);
3232 if (asprintf(&label_orig, "%s: commit %s",
3233 GOT_MERGE_LABEL_BASE, id_str) == -1) {
3234 err = got_error_from_errno("asprintf");
3240 f1 = got_opentemp();
3242 err = got_error_from_errno("got_opentemp");
3247 err = got_object_open_as_commit(&commit2, repo, commit_id2);
3251 err = got_object_id_by_path(&tree_id2, repo, commit2,
3252 worktree->path_prefix);
3256 err = got_object_open_as_tree(&tree2, repo, tree_id2);
3260 f2 = got_opentemp();
3262 err = got_error_from_errno("got_opentemp");
3266 fd1 = got_opentempfd();
3268 err = got_error_from_errno("got_opentempfd");
3272 fd2 = got_opentempfd();
3274 err = got_error_from_errno("got_opentempfd");
3278 cmc_arg.worktree = worktree;
3279 cmc_arg.fileindex = fileindex;
3280 cmc_arg.repo = repo;
3281 err = got_diff_tree(tree1, tree2, f1, f2, fd1, fd2, "", "", repo,
3282 check_merge_conflicts, &cmc_arg, 0);
3286 arg.worktree = worktree;
3287 arg.fileindex = fileindex;
3288 arg.progress_cb = progress_cb;
3289 arg.progress_arg = progress_arg;
3290 arg.cancel_cb = cancel_cb;
3291 arg.cancel_arg = cancel_arg;
3292 arg.label_orig = label_orig;
3293 arg.commit_id2 = commit_id2;
3294 arg.allow_bad_symlinks = 1; /* preserve bad symlinks across merges */
3295 err = got_diff_tree(tree1, tree2, f1, f2, fd1, fd2, "", "", repo,
3296 merge_file_cb, &arg, 1);
3297 sync_err = sync_fileindex(fileindex, fileindex_path);
3298 if (sync_err && err == NULL)
3302 got_object_commit_close(commit1);
3304 got_object_commit_close(commit2);
3306 got_object_tree_close(tree1);
3308 got_object_tree_close(tree2);
3309 if (f1 && fclose(f1) == EOF && err == NULL)
3310 err = got_error_from_errno("fclose");
3311 if (f2 && fclose(f2) == EOF && err == NULL)
3312 err = got_error_from_errno("fclose");
3313 if (fd1 != -1 && close(fd1) == -1 && err == NULL)
3314 err = got_error_from_errno("close");
3315 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
3316 err = got_error_from_errno("close");
3321 const struct got_error *
3322 got_worktree_merge_files(struct got_worktree *worktree,
3323 struct got_object_id *commit_id1, struct got_object_id *commit_id2,
3324 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
3325 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
3327 const struct got_error *err, *unlockerr;
3328 char *fileindex_path = NULL;
3329 struct got_fileindex *fileindex = NULL;
3331 err = lock_worktree(worktree, LOCK_EX);
3335 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3339 err = got_fileindex_for_each_entry_safe(fileindex, check_mixed_commits,
3344 err = merge_files(worktree, fileindex, fileindex_path, commit_id1,
3345 commit_id2, repo, progress_cb, progress_arg,
3346 cancel_cb, cancel_arg);
3349 got_fileindex_free(fileindex);
3350 free(fileindex_path);
3351 unlockerr = lock_worktree(worktree, LOCK_SH);
3352 if (unlockerr && err == NULL)
3357 struct diff_dir_cb_arg {
3358 struct got_fileindex *fileindex;
3359 struct got_worktree *worktree;
3360 const char *status_path;
3361 size_t status_path_len;
3362 struct got_repository *repo;
3363 got_worktree_status_cb status_cb;
3365 got_cancel_cb cancel_cb;
3367 /* A pathlist containing per-directory pathlists of ignore patterns. */
3368 struct got_pathlist_head *ignores;
3369 int report_unchanged;
3373 static const struct got_error *
3374 report_file_status(struct got_fileindex_entry *ie, const char *abspath,
3375 int dirfd, const char *de_name,
3376 got_worktree_status_cb status_cb, void *status_arg,
3377 struct got_repository *repo, int report_unchanged)
3379 const struct got_error *err = NULL;
3380 unsigned char status = GOT_STATUS_NO_CHANGE;
3381 unsigned char staged_status;
3383 struct got_object_id blob_id, commit_id, staged_blob_id;
3384 struct got_object_id *blob_idp = NULL, *commit_idp = NULL;
3385 struct got_object_id *staged_blob_idp = NULL;
3387 staged_status = get_staged_status(ie);
3388 err = get_file_status(&status, &sb, ie, abspath, dirfd, de_name, repo);
3392 if (status == GOT_STATUS_NO_CHANGE &&
3393 staged_status == GOT_STATUS_NO_CHANGE && !report_unchanged)
3396 if (got_fileindex_entry_has_blob(ie))
3397 blob_idp = got_fileindex_entry_get_blob_id(&blob_id, ie);
3398 if (got_fileindex_entry_has_commit(ie))
3399 commit_idp = got_fileindex_entry_get_commit_id(&commit_id, ie);
3400 if (staged_status == GOT_STATUS_ADD ||
3401 staged_status == GOT_STATUS_MODIFY) {
3402 staged_blob_idp = got_fileindex_entry_get_staged_blob_id(
3403 &staged_blob_id, ie);
3406 return (*status_cb)(status_arg, status, staged_status,
3407 ie->path, blob_idp, staged_blob_idp, commit_idp, dirfd, de_name);
3410 static const struct got_error *
3411 status_old_new(void *arg, struct got_fileindex_entry *ie,
3412 struct dirent *de, const char *parent_path, int dirfd)
3414 const struct got_error *err = NULL;
3415 struct diff_dir_cb_arg *a = arg;
3418 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3419 return got_error(GOT_ERR_CANCELLED);
3421 if (got_path_cmp(parent_path, a->status_path,
3422 strlen(parent_path), a->status_path_len) != 0 &&
3423 !got_path_is_child(parent_path, a->status_path, a->status_path_len))
3426 if (parent_path[0]) {
3427 if (asprintf(&abspath, "%s/%s/%s", a->worktree->root_path,
3428 parent_path, de->d_name) == -1)
3429 return got_error_from_errno("asprintf");
3431 if (asprintf(&abspath, "%s/%s", a->worktree->root_path,
3433 return got_error_from_errno("asprintf");
3436 err = report_file_status(ie, abspath, dirfd, de->d_name,
3437 a->status_cb, a->status_arg, a->repo, a->report_unchanged);
3442 static const struct got_error *
3443 status_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
3445 struct diff_dir_cb_arg *a = arg;
3446 struct got_object_id blob_id, commit_id;
3447 unsigned char status;
3449 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3450 return got_error(GOT_ERR_CANCELLED);
3452 if (!got_path_is_child(ie->path, a->status_path, a->status_path_len))
3455 got_fileindex_entry_get_blob_id(&blob_id, ie);
3456 got_fileindex_entry_get_commit_id(&commit_id, ie);
3457 if (got_fileindex_entry_has_file_on_disk(ie))
3458 status = GOT_STATUS_MISSING;
3460 status = GOT_STATUS_DELETE;
3461 return (*a->status_cb)(a->status_arg, status, get_staged_status(ie),
3462 ie->path, &blob_id, NULL, &commit_id, -1, NULL);
3466 free_ignores(struct got_pathlist_head *ignores)
3468 struct got_pathlist_entry *pe;
3470 TAILQ_FOREACH(pe, ignores, entry) {
3471 struct got_pathlist_head *ignorelist = pe->data;
3473 got_pathlist_free(ignorelist, GOT_PATHLIST_FREE_PATH);
3475 got_pathlist_free(ignores, GOT_PATHLIST_FREE_PATH);
3478 static const struct got_error *
3479 read_ignores(struct got_pathlist_head *ignores, const char *path, FILE *f)
3481 const struct got_error *err = NULL;
3482 struct got_pathlist_entry *pe = NULL;
3483 struct got_pathlist_head *ignorelist;
3484 char *line = NULL, *pattern, *dirpath = NULL;
3485 size_t linesize = 0;
3488 ignorelist = calloc(1, sizeof(*ignorelist));
3489 if (ignorelist == NULL)
3490 return got_error_from_errno("calloc");
3491 TAILQ_INIT(ignorelist);
3493 while ((linelen = getline(&line, &linesize, f)) != -1) {
3494 if (linelen > 0 && line[linelen - 1] == '\n')
3495 line[linelen - 1] = '\0';
3497 /* Git's ignores may contain comments. */
3501 /* Git's negated patterns are not (yet?) supported. */
3505 if (asprintf(&pattern, "%s%s%s", path, path[0] ? "/" : "",
3507 err = got_error_from_errno("asprintf");
3510 err = got_pathlist_insert(NULL, ignorelist, pattern, NULL);
3515 err = got_error_from_errno("getline");
3519 dirpath = strdup(path);
3520 if (dirpath == NULL) {
3521 err = got_error_from_errno("strdup");
3524 err = got_pathlist_insert(&pe, ignores, dirpath, ignorelist);
3527 if (err || pe == NULL) {
3529 got_pathlist_free(ignorelist, GOT_PATHLIST_FREE_PATH);
3535 match_ignores(struct got_pathlist_head *ignores, const char *path)
3537 struct got_pathlist_entry *pe;
3539 /* Handle patterns which match in all directories. */
3540 TAILQ_FOREACH(pe, ignores, entry) {
3541 struct got_pathlist_head *ignorelist = pe->data;
3542 struct got_pathlist_entry *pi;
3544 TAILQ_FOREACH(pi, ignorelist, entry) {
3545 const char *p, *pattern = pi->path;
3547 if (strncmp(pattern, "**/", 3) != 0)
3552 if (fnmatch(pattern, p,
3553 FNM_PATHNAME | FNM_LEADING_DIR)) {
3554 /* Retry in next directory. */
3555 while (*p && *p != '/')
3567 * The ignores pathlist contains ignore lists from children before
3568 * parents, so we can find the most specific ignorelist by walking
3569 * ignores backwards.
3571 pe = TAILQ_LAST(ignores, got_pathlist_head);
3573 if (got_path_is_child(path, pe->path, pe->path_len)) {
3574 struct got_pathlist_head *ignorelist = pe->data;
3575 struct got_pathlist_entry *pi;
3576 TAILQ_FOREACH(pi, ignorelist, entry) {
3577 const char *pattern = pi->path;
3578 int flags = FNM_LEADING_DIR;
3579 if (strstr(pattern, "/**/") == NULL)
3580 flags |= FNM_PATHNAME;
3581 if (fnmatch(pattern, path, flags))
3586 pe = TAILQ_PREV(pe, got_pathlist_head, entry);
3592 static const struct got_error *
3593 add_ignores(struct got_pathlist_head *ignores, const char *root_path,
3594 const char *path, int dirfd, const char *ignores_filename)
3596 const struct got_error *err = NULL;
3599 FILE *ignoresfile = NULL;
3601 if (asprintf(&ignorespath, "%s/%s%s%s", root_path, path,
3602 path[0] ? "/" : "", ignores_filename) == -1)
3603 return got_error_from_errno("asprintf");
3606 fd = openat(dirfd, ignores_filename,
3607 O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
3609 if (errno != ENOENT && errno != EACCES)
3610 err = got_error_from_errno2("openat",
3613 ignoresfile = fdopen(fd, "r");
3614 if (ignoresfile == NULL)
3615 err = got_error_from_errno2("fdopen",
3619 err = read_ignores(ignores, path, ignoresfile);
3623 ignoresfile = fopen(ignorespath, "re");
3624 if (ignoresfile == NULL) {
3625 if (errno != ENOENT && errno != EACCES)
3626 err = got_error_from_errno2("fopen",
3629 err = read_ignores(ignores, path, ignoresfile);
3632 if (ignoresfile && fclose(ignoresfile) == EOF && err == NULL)
3633 err = got_error_from_errno2("fclose", path);
3634 if (fd != -1 && close(fd) == -1 && err == NULL)
3635 err = got_error_from_errno2("close", path);
3640 static const struct got_error *
3641 status_new(int *ignore, void *arg, struct dirent *de, const char *parent_path,
3644 const struct got_error *err = NULL;
3645 struct diff_dir_cb_arg *a = arg;
3651 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3652 return got_error(GOT_ERR_CANCELLED);
3654 if (parent_path[0]) {
3655 if (asprintf(&path, "%s/%s", parent_path, de->d_name) == -1)
3656 return got_error_from_errno("asprintf");
3661 if (de->d_type == DT_DIR) {
3662 if (!a->no_ignores && ignore != NULL &&
3663 match_ignores(a->ignores, path))
3665 } else if (!match_ignores(a->ignores, path) &&
3666 got_path_is_child(path, a->status_path, a->status_path_len))
3667 err = (*a->status_cb)(a->status_arg, GOT_STATUS_UNVERSIONED,
3668 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3674 static const struct got_error *
3675 status_traverse(void *arg, const char *path, int dirfd)
3677 const struct got_error *err = NULL;
3678 struct diff_dir_cb_arg *a = arg;
3683 err = add_ignores(a->ignores, a->worktree->root_path,
3684 path, dirfd, ".cvsignore");
3688 err = add_ignores(a->ignores, a->worktree->root_path, path,
3689 dirfd, ".gitignore");
3694 static const struct got_error *
3695 report_single_file_status(const char *path, const char *ondisk_path,
3696 struct got_fileindex *fileindex, got_worktree_status_cb status_cb,
3697 void *status_arg, struct got_repository *repo, int report_unchanged,
3698 struct got_pathlist_head *ignores, int no_ignores)
3700 struct got_fileindex_entry *ie;
3703 ie = got_fileindex_entry_get(fileindex, path, strlen(path));
3705 return report_file_status(ie, ondisk_path, -1, NULL,
3706 status_cb, status_arg, repo, report_unchanged);
3708 if (lstat(ondisk_path, &sb) == -1) {
3709 if (errno != ENOENT)
3710 return got_error_from_errno2("lstat", ondisk_path);
3711 return (*status_cb)(status_arg, GOT_STATUS_NONEXISTENT,
3712 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3715 if (!no_ignores && match_ignores(ignores, path))
3718 if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode))
3719 return (*status_cb)(status_arg, GOT_STATUS_UNVERSIONED,
3720 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3725 static const struct got_error *
3726 add_ignores_from_parent_paths(struct got_pathlist_head *ignores,
3727 const char *root_path, const char *path)
3729 const struct got_error *err;
3730 char *parent_path, *next_parent_path = NULL;
3732 err = add_ignores(ignores, root_path, "", -1,
3737 err = add_ignores(ignores, root_path, "", -1,
3742 err = got_path_dirname(&parent_path, path);
3744 if (err->code == GOT_ERR_BAD_PATH)
3745 return NULL; /* cannot traverse parent */
3749 err = add_ignores(ignores, root_path, parent_path, -1,
3753 err = add_ignores(ignores, root_path, parent_path, -1,
3757 err = got_path_dirname(&next_parent_path, parent_path);
3759 if (err->code == GOT_ERR_BAD_PATH)
3760 err = NULL; /* traversed everything */
3763 if (got_path_is_root_dir(parent_path))
3766 parent_path = next_parent_path;
3767 next_parent_path = NULL;
3771 free(next_parent_path);
3775 static const struct got_error *
3776 worktree_status(struct got_worktree *worktree, const char *path,
3777 struct got_fileindex *fileindex, struct got_repository *repo,
3778 got_worktree_status_cb status_cb, void *status_arg,
3779 got_cancel_cb cancel_cb, void *cancel_arg, int no_ignores,
3780 int report_unchanged)
3782 const struct got_error *err = NULL;
3784 struct got_fileindex_diff_dir_cb fdiff_cb;
3785 struct diff_dir_cb_arg arg;
3786 char *ondisk_path = NULL;
3787 struct got_pathlist_head ignores;
3788 struct got_fileindex_entry *ie;
3790 TAILQ_INIT(&ignores);
3792 if (asprintf(&ondisk_path, "%s%s%s",
3793 worktree->root_path, path[0] ? "/" : "", path) == -1)
3794 return got_error_from_errno("asprintf");
3796 ie = got_fileindex_entry_get(fileindex, path, strlen(path));
3798 err = report_single_file_status(path, ondisk_path,
3799 fileindex, status_cb, status_arg, repo,
3800 report_unchanged, &ignores, no_ignores);
3804 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
3806 if (errno != ENOTDIR && errno != ENOENT && errno != EACCES &&
3807 !got_err_open_nofollow_on_symlink())
3808 err = got_error_from_errno2("open", ondisk_path);
3811 err = add_ignores_from_parent_paths(&ignores,
3812 worktree->root_path, ondisk_path);
3816 err = report_single_file_status(path, ondisk_path,
3817 fileindex, status_cb, status_arg, repo,
3818 report_unchanged, &ignores, no_ignores);
3821 fdiff_cb.diff_old_new = status_old_new;
3822 fdiff_cb.diff_old = status_old;
3823 fdiff_cb.diff_new = status_new;
3824 fdiff_cb.diff_traverse = status_traverse;
3825 arg.fileindex = fileindex;
3826 arg.worktree = worktree;
3827 arg.status_path = path;
3828 arg.status_path_len = strlen(path);
3830 arg.status_cb = status_cb;
3831 arg.status_arg = status_arg;
3832 arg.cancel_cb = cancel_cb;
3833 arg.cancel_arg = cancel_arg;
3834 arg.report_unchanged = report_unchanged;
3835 arg.no_ignores = no_ignores;
3837 err = add_ignores_from_parent_paths(&ignores,
3838 worktree->root_path, path);
3842 arg.ignores = &ignores;
3843 err = got_fileindex_diff_dir(fileindex, fd,
3844 worktree->root_path, path, repo, &fdiff_cb, &arg);
3847 free_ignores(&ignores);
3848 if (fd != -1 && close(fd) == -1 && err == NULL)
3849 err = got_error_from_errno("close");
3854 const struct got_error *
3855 got_worktree_status(struct got_worktree *worktree,
3856 struct got_pathlist_head *paths, struct got_repository *repo,
3857 int no_ignores, got_worktree_status_cb status_cb, void *status_arg,
3858 got_cancel_cb cancel_cb, void *cancel_arg)
3860 const struct got_error *err = NULL;
3861 char *fileindex_path = NULL;
3862 struct got_fileindex *fileindex = NULL;
3863 struct got_pathlist_entry *pe;
3865 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3869 TAILQ_FOREACH(pe, paths, entry) {
3870 err = worktree_status(worktree, pe->path, fileindex, repo,
3871 status_cb, status_arg, cancel_cb, cancel_arg,
3876 free(fileindex_path);
3877 got_fileindex_free(fileindex);
3881 const struct got_error *
3882 got_worktree_resolve_path(char **wt_path, struct got_worktree *worktree,
3885 const struct got_error *err = NULL;
3886 char *resolved = NULL, *cwd = NULL, *path = NULL;
3889 char *abspath = NULL;
3890 char canonpath[PATH_MAX];
3894 cwd = getcwd(NULL, 0);
3896 return got_error_from_errno("getcwd");
3898 if (lstat(arg, &sb) == -1) {
3899 if (errno != ENOENT) {
3900 err = got_error_from_errno2("lstat", arg);
3905 if (S_ISLNK(sb.st_mode)) {
3907 * We cannot use realpath(3) with symlinks since we want to
3908 * operate on the symlink itself.
3909 * But we can make the path absolute, assuming it is relative
3910 * to the current working directory, and then canonicalize it.
3912 if (!got_path_is_absolute(arg)) {
3913 if (asprintf(&abspath, "%s/%s", cwd, arg) == -1) {
3914 err = got_error_from_errno("asprintf");
3919 err = got_canonpath(abspath ? abspath : arg, canonpath,
3923 resolved = strdup(canonpath);
3924 if (resolved == NULL) {
3925 err = got_error_from_errno("strdup");
3929 resolved = realpath(arg, NULL);
3930 if (resolved == NULL) {
3931 if (errno != ENOENT) {
3932 err = got_error_from_errno2("realpath", arg);
3935 if (asprintf(&abspath, "%s/%s", cwd, arg) == -1) {
3936 err = got_error_from_errno("asprintf");
3939 err = got_canonpath(abspath, canonpath,
3943 resolved = strdup(canonpath);
3944 if (resolved == NULL) {
3945 err = got_error_from_errno("strdup");
3951 if (strncmp(got_worktree_get_root_path(worktree), resolved,
3952 strlen(got_worktree_get_root_path(worktree)))) {
3953 err = got_error_path(resolved, GOT_ERR_BAD_PATH);
3957 if (strlen(resolved) > strlen(got_worktree_get_root_path(worktree))) {
3958 err = got_path_skip_common_ancestor(&path,
3959 got_worktree_get_root_path(worktree), resolved);
3965 err = got_error_from_errno("strdup");
3970 /* XXX status walk can't deal with trailing slash! */
3972 while (len > 0 && path[len - 1] == '/') {
3973 path[len - 1] = '\0';
3987 struct schedule_addition_args {
3988 struct got_worktree *worktree;
3989 struct got_fileindex *fileindex;
3990 got_worktree_checkout_cb progress_cb;
3992 struct got_repository *repo;
3995 static const struct got_error *
3996 schedule_addition(void *arg, unsigned char status, unsigned char staged_status,
3997 const char *relpath, struct got_object_id *blob_id,
3998 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
3999 int dirfd, const char *de_name)
4001 struct schedule_addition_args *a = arg;
4002 const struct got_error *err = NULL;
4003 struct got_fileindex_entry *ie;
4007 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
4009 return got_error_from_errno("asprintf");
4011 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
4013 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd,
4017 /* Re-adding an existing entry is a no-op. */
4018 if (status == GOT_STATUS_ADD)
4020 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
4025 if (status != GOT_STATUS_UNVERSIONED) {
4026 if (status == GOT_STATUS_NONEXISTENT)
4027 err = got_error_set_errno(ENOENT, ondisk_path);
4029 err = got_error_path(ondisk_path, GOT_ERR_FILE_STATUS);
4033 err = got_fileindex_entry_alloc(&ie, relpath);
4036 err = got_fileindex_entry_update(ie, a->worktree->root_fd,
4037 relpath, NULL, NULL, 1);
4039 got_fileindex_entry_free(ie);
4042 err = got_fileindex_entry_add(a->fileindex, ie);
4044 got_fileindex_entry_free(ie);
4051 if (status == GOT_STATUS_ADD)
4053 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_ADD, relpath);
4056 const struct got_error *
4057 got_worktree_schedule_add(struct got_worktree *worktree,
4058 struct got_pathlist_head *paths,
4059 got_worktree_checkout_cb progress_cb, void *progress_arg,
4060 struct got_repository *repo, int no_ignores)
4062 struct got_fileindex *fileindex = NULL;
4063 char *fileindex_path = NULL;
4064 const struct got_error *err = NULL, *sync_err, *unlockerr;
4065 struct got_pathlist_entry *pe;
4066 struct schedule_addition_args saa;
4068 err = lock_worktree(worktree, LOCK_EX);
4072 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4076 saa.worktree = worktree;
4077 saa.fileindex = fileindex;
4078 saa.progress_cb = progress_cb;
4079 saa.progress_arg = progress_arg;
4082 TAILQ_FOREACH(pe, paths, entry) {
4083 err = worktree_status(worktree, pe->path, fileindex, repo,
4084 schedule_addition, &saa, NULL, NULL, no_ignores, 0);
4088 sync_err = sync_fileindex(fileindex, fileindex_path);
4089 if (sync_err && err == NULL)
4092 free(fileindex_path);
4094 got_fileindex_free(fileindex);
4095 unlockerr = lock_worktree(worktree, LOCK_SH);
4096 if (unlockerr && err == NULL)
4101 struct schedule_deletion_args {
4102 struct got_worktree *worktree;
4103 struct got_fileindex *fileindex;
4104 got_worktree_delete_cb progress_cb;
4106 struct got_repository *repo;
4107 int delete_local_mods;
4109 int ignore_missing_paths;
4110 const char *status_codes;
4113 static const struct got_error *
4114 schedule_for_deletion(void *arg, unsigned char status,
4115 unsigned char staged_status, const char *relpath,
4116 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
4117 struct got_object_id *commit_id, int dirfd, const char *de_name)
4119 struct schedule_deletion_args *a = arg;
4120 const struct got_error *err = NULL;
4121 struct got_fileindex_entry *ie = NULL;
4125 if (status == GOT_STATUS_NONEXISTENT) {
4126 if (a->ignore_missing_paths)
4128 return got_error_set_errno(ENOENT, relpath);
4131 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
4133 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
4135 staged_status = get_staged_status(ie);
4136 if (staged_status != GOT_STATUS_NO_CHANGE) {
4137 if (staged_status == GOT_STATUS_DELETE)
4139 return got_error_path(relpath, GOT_ERR_FILE_STAGED);
4142 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
4144 return got_error_from_errno("asprintf");
4146 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd, de_name,
4151 if (a->status_codes) {
4152 size_t ncodes = strlen(a->status_codes);
4154 for (i = 0; i < ncodes ; i++) {
4155 if (status == a->status_codes[i])
4159 /* Do not delete files in non-matching status. */
4163 if (a->status_codes[i] != GOT_STATUS_MODIFY &&
4164 a->status_codes[i] != GOT_STATUS_MISSING) {
4165 static char msg[64];
4166 snprintf(msg, sizeof(msg),
4167 "invalid status code '%c'", a->status_codes[i]);
4168 err = got_error_msg(GOT_ERR_FILE_STATUS, msg);
4173 if (status != GOT_STATUS_NO_CHANGE) {
4174 if (status == GOT_STATUS_DELETE)
4176 if (status == GOT_STATUS_MODIFY && !a->delete_local_mods) {
4177 err = got_error_path(relpath, GOT_ERR_FILE_MODIFIED);
4180 if (status == GOT_STATUS_MISSING && !a->ignore_missing_paths) {
4181 err = got_error_set_errno(ENOENT, relpath);
4184 if (status != GOT_STATUS_MODIFY &&
4185 status != GOT_STATUS_MISSING) {
4186 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
4191 if (!a->keep_on_disk && status != GOT_STATUS_MISSING) {
4195 if (unlinkat(dirfd, de_name, 0) == -1) {
4196 err = got_error_from_errno2("unlinkat",
4200 } else if (unlink(ondisk_path) == -1) {
4201 err = got_error_from_errno2("unlink", ondisk_path);
4205 root_len = strlen(a->worktree->root_path);
4208 err = got_path_dirname(&parent, ondisk_path);
4212 ondisk_path = parent;
4213 if (rmdir(ondisk_path) == -1) {
4214 if (errno != ENOTEMPTY)
4215 err = got_error_from_errno2("rmdir",
4219 } while (got_path_cmp(ondisk_path, a->worktree->root_path,
4220 strlen(ondisk_path), root_len) != 0);
4223 got_fileindex_entry_mark_deleted_from_disk(ie);
4228 if (status == GOT_STATUS_DELETE)
4230 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE,
4231 staged_status, relpath);
4234 const struct got_error *
4235 got_worktree_schedule_delete(struct got_worktree *worktree,
4236 struct got_pathlist_head *paths, int delete_local_mods,
4237 const char *status_codes,
4238 got_worktree_delete_cb progress_cb, void *progress_arg,
4239 struct got_repository *repo, int keep_on_disk, int ignore_missing_paths)
4241 struct got_fileindex *fileindex = NULL;
4242 char *fileindex_path = NULL;
4243 const struct got_error *err = NULL, *sync_err, *unlockerr;
4244 struct got_pathlist_entry *pe;
4245 struct schedule_deletion_args sda;
4247 err = lock_worktree(worktree, LOCK_EX);
4251 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4255 sda.worktree = worktree;
4256 sda.fileindex = fileindex;
4257 sda.progress_cb = progress_cb;
4258 sda.progress_arg = progress_arg;
4260 sda.delete_local_mods = delete_local_mods;
4261 sda.keep_on_disk = keep_on_disk;
4262 sda.ignore_missing_paths = ignore_missing_paths;
4263 sda.status_codes = status_codes;
4265 TAILQ_FOREACH(pe, paths, entry) {
4266 err = worktree_status(worktree, pe->path, fileindex, repo,
4267 schedule_for_deletion, &sda, NULL, NULL, 1, 1);
4271 sync_err = sync_fileindex(fileindex, fileindex_path);
4272 if (sync_err && err == NULL)
4275 free(fileindex_path);
4277 got_fileindex_free(fileindex);
4278 unlockerr = lock_worktree(worktree, LOCK_SH);
4279 if (unlockerr && err == NULL)
4284 static const struct got_error *
4285 copy_one_line(FILE *infile, FILE *outfile, FILE *rejectfile)
4287 const struct got_error *err = NULL;
4289 size_t linesize = 0, n;
4292 linelen = getline(&line, &linesize, infile);
4293 if (linelen == -1) {
4294 if (ferror(infile)) {
4295 err = got_error_from_errno("getline");
4301 n = fwrite(line, 1, linelen, outfile);
4303 err = got_ferror(outfile, GOT_ERR_IO);
4308 n = fwrite(line, 1, linelen, rejectfile);
4310 err = got_ferror(rejectfile, GOT_ERR_IO);
4317 static const struct got_error *
4318 skip_one_line(FILE *f)
4321 size_t linesize = 0;
4324 linelen = getline(&line, &linesize, f);
4325 if (linelen == -1) {
4327 return got_error_from_errno("getline");
4334 static const struct got_error *
4335 copy_change(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
4336 int start_old, int end_old, int start_new, int end_new,
4337 FILE *outfile, FILE *rejectfile)
4339 const struct got_error *err;
4341 /* Copy old file's lines leading up to patch. */
4342 while (!feof(f1) && *line_cur1 < start_old) {
4343 err = copy_one_line(f1, outfile, NULL);
4348 /* Skip new file's lines leading up to patch. */
4349 while (!feof(f2) && *line_cur2 < start_new) {
4351 err = copy_one_line(f2, NULL, rejectfile);
4353 err = skip_one_line(f2);
4358 /* Copy patched lines. */
4359 while (!feof(f2) && *line_cur2 <= end_new) {
4360 err = copy_one_line(f2, outfile, NULL);
4365 /* Skip over old file's replaced lines. */
4366 while (!feof(f1) && *line_cur1 <= end_old) {
4368 err = copy_one_line(f1, NULL, rejectfile);
4370 err = skip_one_line(f1);
4379 static const struct got_error *
4380 copy_remaining_content(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
4381 FILE *outfile, FILE *rejectfile)
4383 const struct got_error *err;
4386 /* Copy old file's lines until EOF. */
4388 err = copy_one_line(f1, outfile, NULL);
4395 /* Copy new file's lines until EOF. */
4397 err = copy_one_line(f2, NULL, rejectfile);
4407 static const struct got_error *
4408 apply_or_reject_change(int *choice, int *nchunks_used,
4409 struct diff_result *diff_result, int n,
4410 const char *relpath, FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
4411 FILE *outfile, FILE *rejectfile, int changeno, int nchanges,
4412 got_worktree_patch_cb patch_cb, void *patch_arg)
4414 const struct got_error *err = NULL;
4415 struct diff_chunk_context cc = {};
4416 int start_old, end_old, start_new, end_new;
4418 struct diff_output_unidiff_state *diff_state;
4419 struct diff_input_info diff_info;
4422 *choice = GOT_PATCH_CHOICE_NONE;
4424 /* Get changed line numbers without context lines for copy_change(). */
4425 diff_chunk_context_load_change(&cc, NULL, diff_result, n, 0);
4426 start_old = cc.left.start;
4427 end_old = cc.left.end;
4428 start_new = cc.right.start;
4429 end_new = cc.right.end;
4431 /* Get the same change with context lines for display. */
4432 memset(&cc, 0, sizeof(cc));
4433 diff_chunk_context_load_change(&cc, nchunks_used, diff_result, n, 3);
4435 memset(&diff_info, 0, sizeof(diff_info));
4436 diff_info.left_path = relpath;
4437 diff_info.right_path = relpath;
4439 diff_state = diff_output_unidiff_state_alloc();
4440 if (diff_state == NULL)
4441 return got_error_set_errno(ENOMEM,
4442 "diff_output_unidiff_state_alloc");
4444 hunkfile = got_opentemp();
4445 if (hunkfile == NULL) {
4446 err = got_error_from_errno("got_opentemp");
4450 rc = diff_output_unidiff_chunk(NULL, hunkfile, diff_state, &diff_info,
4452 if (rc != DIFF_RC_OK) {
4453 err = got_error_set_errno(rc, "diff_output_unidiff_chunk");
4457 if (fseek(hunkfile, 0L, SEEK_SET) == -1) {
4458 err = got_ferror(hunkfile, GOT_ERR_IO);
4462 err = (*patch_cb)(choice, patch_arg, GOT_STATUS_MODIFY, relpath,
4463 hunkfile, changeno, nchanges);
4468 case GOT_PATCH_CHOICE_YES:
4469 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
4470 end_old, start_new, end_new, outfile, rejectfile);
4472 case GOT_PATCH_CHOICE_NO:
4473 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
4474 end_old, start_new, end_new, rejectfile, outfile);
4476 case GOT_PATCH_CHOICE_QUIT:
4479 err = got_error(GOT_ERR_PATCH_CHOICE);
4483 diff_output_unidiff_state_free(diff_state);
4484 if (hunkfile && fclose(hunkfile) == EOF && err == NULL)
4485 err = got_error_from_errno("fclose");
4489 struct revert_file_args {
4490 struct got_worktree *worktree;
4491 struct got_fileindex *fileindex;
4492 got_worktree_checkout_cb progress_cb;
4494 got_worktree_patch_cb patch_cb;
4496 struct got_repository *repo;
4497 int unlink_added_files;
4500 static const struct got_error *
4501 create_patched_content(char **path_outfile, int reverse_patch,
4502 struct got_object_id *blob_id, const char *path2,
4503 int dirfd2, const char *de_name2,
4504 const char *relpath, struct got_repository *repo,
4505 got_worktree_patch_cb patch_cb, void *patch_arg)
4507 const struct got_error *err, *free_err;
4508 struct got_blob_object *blob = NULL;
4509 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL;
4510 int fd = -1, fd2 = -1;
4511 char link_target[PATH_MAX];
4512 ssize_t link_len = 0;
4513 char *path1 = NULL, *id_str = NULL;
4515 struct got_diffreg_result *diffreg_result = NULL;
4516 int line_cur1 = 1, line_cur2 = 1, have_content = 0;
4517 int i = 0, n = 0, nchunks_used = 0, nchanges = 0;
4519 *path_outfile = NULL;
4521 err = got_object_id_str(&id_str, blob_id);
4526 fd2 = openat(dirfd2, de_name2,
4527 O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
4529 if (!got_err_open_nofollow_on_symlink()) {
4530 err = got_error_from_errno2("openat", path2);
4533 link_len = readlinkat(dirfd2, de_name2,
4534 link_target, sizeof(link_target));
4535 if (link_len == -1) {
4536 return got_error_from_errno2("readlinkat",
4539 sb2.st_mode = S_IFLNK;
4540 sb2.st_size = link_len;
4543 fd2 = open(path2, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
4545 if (!got_err_open_nofollow_on_symlink()) {
4546 err = got_error_from_errno2("open", path2);
4549 link_len = readlink(path2, link_target,
4550 sizeof(link_target));
4552 return got_error_from_errno2("readlink", path2);
4553 sb2.st_mode = S_IFLNK;
4554 sb2.st_size = link_len;
4558 if (fstat(fd2, &sb2) == -1) {
4559 err = got_error_from_errno2("fstat", path2);
4563 f2 = fdopen(fd2, "r");
4565 err = got_error_from_errno2("fdopen", path2);
4571 f2 = got_opentemp();
4573 err = got_error_from_errno2("got_opentemp", path2);
4576 n = fwrite(link_target, 1, link_len, f2);
4577 if (n != link_len) {
4578 err = got_ferror(f2, GOT_ERR_IO);
4581 if (fflush(f2) == EOF) {
4582 err = got_error_from_errno("fflush");
4588 fd = got_opentempfd();
4590 err = got_error_from_errno("got_opentempfd");
4594 err = got_object_open_as_blob(&blob, repo, blob_id, 8192, fd);
4598 err = got_opentemp_named(&path1, &f1, "got-patched-blob", "");
4602 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
4606 err = got_diff_files(&diffreg_result, f1, 1, id_str, f2, 1, path2,
4607 3, 0, 1, NULL, GOT_DIFF_ALGORITHM_MYERS);
4611 err = got_opentemp_named(path_outfile, &outfile, "got-patched-content",
4616 if (fseek(f1, 0L, SEEK_SET) == -1)
4617 return got_ferror(f1, GOT_ERR_IO);
4618 if (fseek(f2, 0L, SEEK_SET) == -1)
4619 return got_ferror(f2, GOT_ERR_IO);
4621 /* Count the number of actual changes in the diff result. */
4622 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
4623 struct diff_chunk_context cc = {};
4624 diff_chunk_context_load_change(&cc, &nchunks_used,
4625 diffreg_result->result, n, 0);
4628 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
4630 err = apply_or_reject_change(&choice, &nchunks_used,
4631 diffreg_result->result, n, relpath, f1, f2,
4632 &line_cur1, &line_cur2,
4633 reverse_patch ? NULL : outfile,
4634 reverse_patch ? outfile : NULL,
4635 ++i, nchanges, patch_cb, patch_arg);
4638 if (choice == GOT_PATCH_CHOICE_YES)
4640 else if (choice == GOT_PATCH_CHOICE_QUIT)
4644 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
4645 reverse_patch ? NULL : outfile,
4646 reverse_patch ? outfile : NULL);
4650 if (!S_ISLNK(sb2.st_mode)) {
4653 mode = apply_umask(sb2.st_mode);
4654 if (fchmod(fileno(outfile), mode) == -1) {
4655 err = got_error_from_errno2("fchmod", path2);
4662 if (fd != -1 && close(fd) == -1 && err == NULL)
4663 err = got_error_from_errno("close");
4665 got_object_blob_close(blob);
4666 free_err = got_diffreg_result_free(diffreg_result);
4669 if (f1 && fclose(f1) == EOF && err == NULL)
4670 err = got_error_from_errno2("fclose", path1);
4671 if (f2 && fclose(f2) == EOF && err == NULL)
4672 err = got_error_from_errno2("fclose", path2);
4673 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
4674 err = got_error_from_errno2("close", path2);
4675 if (outfile && fclose(outfile) == EOF && err == NULL)
4676 err = got_error_from_errno2("fclose", *path_outfile);
4677 if (path1 && unlink(path1) == -1 && err == NULL)
4678 err = got_error_from_errno2("unlink", path1);
4679 if (err || !have_content) {
4680 if (*path_outfile && unlink(*path_outfile) == -1 && err == NULL)
4681 err = got_error_from_errno2("unlink", *path_outfile);
4682 free(*path_outfile);
4683 *path_outfile = NULL;
4689 static const struct got_error *
4690 revert_file(void *arg, unsigned char status, unsigned char staged_status,
4691 const char *relpath, struct got_object_id *blob_id,
4692 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
4693 int dirfd, const char *de_name)
4695 struct revert_file_args *a = arg;
4696 const struct got_error *err = NULL;
4697 char *parent_path = NULL;
4698 struct got_fileindex_entry *ie;
4699 struct got_commit_object *base_commit = NULL;
4700 struct got_tree_object *tree = NULL;
4701 struct got_object_id *tree_id = NULL;
4702 const struct got_tree_entry *te = NULL;
4703 char *tree_path = NULL, *te_name;
4704 char *ondisk_path = NULL, *path_content = NULL;
4705 struct got_blob_object *blob = NULL;
4708 /* Reverting a staged deletion is a no-op. */
4709 if (status == GOT_STATUS_DELETE &&
4710 staged_status != GOT_STATUS_NO_CHANGE)
4713 if (status == GOT_STATUS_UNVERSIONED)
4714 return (*a->progress_cb)(a->progress_arg,
4715 GOT_STATUS_UNVERSIONED, relpath);
4717 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
4719 return got_error_path(relpath, GOT_ERR_BAD_PATH);
4721 /* Construct in-repository path of tree which contains this blob. */
4722 err = got_path_dirname(&parent_path, ie->path);
4724 if (err->code != GOT_ERR_BAD_PATH)
4726 parent_path = strdup("/");
4727 if (parent_path == NULL) {
4728 err = got_error_from_errno("strdup");
4732 if (got_path_is_root_dir(a->worktree->path_prefix)) {
4733 tree_path = strdup(parent_path);
4734 if (tree_path == NULL) {
4735 err = got_error_from_errno("strdup");
4739 if (got_path_is_root_dir(parent_path)) {
4740 tree_path = strdup(a->worktree->path_prefix);
4741 if (tree_path == NULL) {
4742 err = got_error_from_errno("strdup");
4746 if (asprintf(&tree_path, "%s/%s",
4747 a->worktree->path_prefix, parent_path) == -1) {
4748 err = got_error_from_errno("asprintf");
4754 err = got_object_open_as_commit(&base_commit, a->repo,
4755 a->worktree->base_commit_id);
4759 err = got_object_id_by_path(&tree_id, a->repo, base_commit, tree_path);
4761 if (!(err->code == GOT_ERR_NO_TREE_ENTRY &&
4762 (status == GOT_STATUS_ADD ||
4763 staged_status == GOT_STATUS_ADD)))
4766 err = got_object_open_as_tree(&tree, a->repo, tree_id);
4770 err = got_path_basename(&te_name, ie->path);
4774 te = got_object_tree_find_entry(tree, te_name);
4776 if (te == NULL && status != GOT_STATUS_ADD &&
4777 staged_status != GOT_STATUS_ADD) {
4778 err = got_error_path(ie->path, GOT_ERR_NO_TREE_ENTRY);
4784 case GOT_STATUS_ADD:
4786 int choice = GOT_PATCH_CHOICE_NONE;
4787 err = (*a->patch_cb)(&choice, a->patch_arg,
4788 status, ie->path, NULL, 1, 1);
4791 if (choice != GOT_PATCH_CHOICE_YES)
4794 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_REVERT,
4798 got_fileindex_entry_remove(a->fileindex, ie);
4799 if (a->unlink_added_files) {
4800 if (asprintf(&ondisk_path, "%s/%s",
4801 got_worktree_get_root_path(a->worktree),
4803 err = got_error_from_errno("asprintf");
4806 if (unlink(ondisk_path) == -1) {
4807 err = got_error_from_errno2("unlink",
4813 case GOT_STATUS_DELETE:
4815 int choice = GOT_PATCH_CHOICE_NONE;
4816 err = (*a->patch_cb)(&choice, a->patch_arg,
4817 status, ie->path, NULL, 1, 1);
4820 if (choice != GOT_PATCH_CHOICE_YES)
4824 case GOT_STATUS_MODIFY:
4825 case GOT_STATUS_MODE_CHANGE:
4826 case GOT_STATUS_CONFLICT:
4827 case GOT_STATUS_MISSING: {
4828 struct got_object_id id;
4829 if (staged_status == GOT_STATUS_ADD ||
4830 staged_status == GOT_STATUS_MODIFY)
4831 got_fileindex_entry_get_staged_blob_id(&id, ie);
4833 got_fileindex_entry_get_blob_id(&id, ie);
4834 fd = got_opentempfd();
4836 err = got_error_from_errno("got_opentempfd");
4840 err = got_object_open_as_blob(&blob, a->repo, &id, 8192, fd);
4844 if (asprintf(&ondisk_path, "%s/%s",
4845 got_worktree_get_root_path(a->worktree), relpath) == -1) {
4846 err = got_error_from_errno("asprintf");
4850 if (a->patch_cb && (status == GOT_STATUS_MODIFY ||
4851 status == GOT_STATUS_CONFLICT)) {
4852 int is_bad_symlink = 0;
4853 err = create_patched_content(&path_content, 1, &id,
4854 ondisk_path, dirfd, de_name, ie->path, a->repo,
4855 a->patch_cb, a->patch_arg);
4856 if (err || path_content == NULL)
4858 if (te && S_ISLNK(te->mode)) {
4859 if (unlink(path_content) == -1) {
4860 err = got_error_from_errno2("unlink",
4864 err = install_symlink(&is_bad_symlink,
4865 a->worktree, ondisk_path, ie->path,
4866 blob, 0, 1, 0, 0, a->repo,
4867 a->progress_cb, a->progress_arg);
4869 if (rename(path_content, ondisk_path) == -1) {
4870 err = got_error_from_errno3("rename",
4871 path_content, ondisk_path);
4876 int is_bad_symlink = 0;
4877 if (te && S_ISLNK(te->mode)) {
4878 err = install_symlink(&is_bad_symlink,
4879 a->worktree, ondisk_path, ie->path,
4880 blob, 0, 1, 0, 0, a->repo,
4881 a->progress_cb, a->progress_arg);
4883 err = install_blob(a->worktree, ondisk_path,
4885 te ? te->mode : GOT_DEFAULT_FILE_MODE,
4886 got_fileindex_perms_to_st(ie), blob,
4887 0, 1, 0, 0, a->repo,
4888 a->progress_cb, a->progress_arg);
4892 if (status == GOT_STATUS_DELETE ||
4893 status == GOT_STATUS_MODE_CHANGE) {
4894 err = got_fileindex_entry_update(ie,
4895 a->worktree->root_fd, relpath,
4897 a->worktree->base_commit_id->sha1, 1);
4901 if (is_bad_symlink) {
4902 got_fileindex_entry_filetype_set(ie,
4903 GOT_FILEIDX_MODE_BAD_SYMLINK);
4916 if (fd != -1 && close(fd) == -1 && err == NULL)
4917 err = got_error_from_errno("close");
4919 got_object_blob_close(blob);
4921 got_object_tree_close(tree);
4924 got_object_commit_close(base_commit);
4928 const struct got_error *
4929 got_worktree_revert(struct got_worktree *worktree,
4930 struct got_pathlist_head *paths,
4931 got_worktree_checkout_cb progress_cb, void *progress_arg,
4932 got_worktree_patch_cb patch_cb, void *patch_arg,
4933 struct got_repository *repo)
4935 struct got_fileindex *fileindex = NULL;
4936 char *fileindex_path = NULL;
4937 const struct got_error *err = NULL, *unlockerr = NULL;
4938 const struct got_error *sync_err = NULL;
4939 struct got_pathlist_entry *pe;
4940 struct revert_file_args rfa;
4942 err = lock_worktree(worktree, LOCK_EX);
4946 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4950 rfa.worktree = worktree;
4951 rfa.fileindex = fileindex;
4952 rfa.progress_cb = progress_cb;
4953 rfa.progress_arg = progress_arg;
4954 rfa.patch_cb = patch_cb;
4955 rfa.patch_arg = patch_arg;
4957 rfa.unlink_added_files = 0;
4958 TAILQ_FOREACH(pe, paths, entry) {
4959 err = worktree_status(worktree, pe->path, fileindex, repo,
4960 revert_file, &rfa, NULL, NULL, 1, 0);
4964 sync_err = sync_fileindex(fileindex, fileindex_path);
4965 if (sync_err && err == NULL)
4968 free(fileindex_path);
4970 got_fileindex_free(fileindex);
4971 unlockerr = lock_worktree(worktree, LOCK_SH);
4972 if (unlockerr && err == NULL)
4978 free_commitable(struct got_commitable *ct)
4981 free(ct->in_repo_path);
4982 free(ct->ondisk_path);
4984 free(ct->base_blob_id);
4985 free(ct->staged_blob_id);
4986 free(ct->base_commit_id);
4990 struct collect_commitables_arg {
4991 struct got_pathlist_head *commitable_paths;
4992 struct got_repository *repo;
4993 struct got_worktree *worktree;
4994 struct got_fileindex *fileindex;
4995 int have_staged_files;
4996 int allow_bad_symlinks;
4997 int diff_header_shown;
4998 int commit_conflicts;
5005 * Create a file which contains the target path of a symlink so we can feed
5006 * it as content to the diff engine.
5008 static const struct got_error *
5009 get_symlink_target_file(int *fd, int dirfd, const char *de_name,
5010 const char *abspath)
5012 const struct got_error *err = NULL;
5013 char target_path[PATH_MAX];
5014 ssize_t target_len, outlen;
5019 target_len = readlinkat(dirfd, de_name, target_path, PATH_MAX);
5020 if (target_len == -1)
5021 return got_error_from_errno2("readlinkat", abspath);
5023 target_len = readlink(abspath, target_path, PATH_MAX);
5024 if (target_len == -1)
5025 return got_error_from_errno2("readlink", abspath);
5028 *fd = got_opentempfd();
5030 return got_error_from_errno("got_opentempfd");
5032 outlen = write(*fd, target_path, target_len);
5034 err = got_error_from_errno("got_opentempfd");
5038 if (lseek(*fd, 0, SEEK_SET) == -1) {
5039 err = got_error_from_errno2("lseek", abspath);
5050 static const struct got_error *
5051 append_ct_diff(struct got_commitable *ct, int *diff_header_shown,
5052 FILE *diff_outfile, FILE *f1, FILE *f2, int dirfd, const char *de_name,
5053 int diff_staged, struct got_repository *repo, struct got_worktree *worktree)
5055 const struct got_error *err = NULL;
5056 struct got_blob_object *blob1 = NULL;
5057 int fd = -1, fd1 = -1, fd2 = -1;
5058 FILE *ondisk_file = NULL;
5059 char *label1 = NULL;
5063 char *id_str = NULL;
5065 memset(&sb, 0, sizeof(sb));
5068 if (ct->staged_status != GOT_STATUS_MODIFY &&
5069 ct->staged_status != GOT_STATUS_ADD &&
5070 ct->staged_status != GOT_STATUS_DELETE)
5073 if (ct->status != GOT_STATUS_MODIFY &&
5074 ct->status != GOT_STATUS_ADD &&
5075 ct->status != GOT_STATUS_DELETE &&
5076 ct->status != GOT_STATUS_CONFLICT)
5080 err = got_opentemp_truncate(f1);
5082 return got_error_from_errno("got_opentemp_truncate");
5083 err = got_opentemp_truncate(f2);
5085 return got_error_from_errno("got_opentemp_truncate");
5087 if (!*diff_header_shown) {
5088 err = got_object_id_str(&id_str, worktree->base_commit_id);
5091 fprintf(diff_outfile, "diff %s%s\n", diff_staged ? "-s " : "",
5092 got_worktree_get_root_path(worktree));
5093 fprintf(diff_outfile, "commit - %s\n", id_str);
5094 fprintf(diff_outfile, "path + %s%s\n",
5095 got_worktree_get_root_path(worktree),
5096 diff_staged ? " (staged changes)" : "");
5097 *diff_header_shown = 1;
5101 const char *label1 = NULL, *label2 = NULL;
5102 switch (ct->staged_status) {
5103 case GOT_STATUS_MODIFY:
5107 case GOT_STATUS_ADD:
5110 case GOT_STATUS_DELETE:
5114 return got_error(GOT_ERR_FILE_STATUS);
5116 fd1 = got_opentempfd();
5118 err = got_error_from_errno("got_opentempfd");
5121 fd2 = got_opentempfd();
5123 err = got_error_from_errno("got_opentempfd");
5126 err = got_diff_objects_as_blobs(NULL, NULL, f1, f2,
5127 fd1, fd2, ct->base_blob_id, ct->staged_blob_id,
5128 label1, label2, GOT_DIFF_ALGORITHM_PATIENCE, 3, 0, 0,
5129 NULL, repo, diff_outfile);
5133 fd1 = got_opentempfd();
5135 err = got_error_from_errno("got_opentempfd");
5139 if (ct->status != GOT_STATUS_ADD) {
5140 err = got_object_open_as_blob(&blob1, repo, ct->base_blob_id,
5146 if (ct->status != GOT_STATUS_DELETE) {
5148 fd = openat(dirfd, de_name,
5149 O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
5151 if (!got_err_open_nofollow_on_symlink()) {
5152 err = got_error_from_errno2("openat",
5156 err = get_symlink_target_file(&fd, dirfd,
5157 de_name, ct->ondisk_path);
5162 fd = open(ct->ondisk_path,
5163 O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
5165 if (!got_err_open_nofollow_on_symlink()) {
5166 err = got_error_from_errno2("open",
5170 err = get_symlink_target_file(&fd, dirfd,
5171 de_name, ct->ondisk_path);
5176 if (fstatat(fd, ct->ondisk_path, &sb,
5177 AT_SYMLINK_NOFOLLOW) == -1) {
5178 err = got_error_from_errno2("fstatat", ct->ondisk_path);
5181 ondisk_file = fdopen(fd, "r");
5182 if (ondisk_file == NULL) {
5183 err = got_error_from_errno2("fdopen", ct->ondisk_path);
5191 err = got_object_blob_dump_to_file(&size1, NULL, NULL,
5197 err = got_diff_blob_file(blob1, f1, size1, label1,
5198 ondisk_file ? ondisk_file : f2, f2_exists, &sb, ct->path,
5199 GOT_DIFF_ALGORITHM_PATIENCE, 3, 0, 0, NULL, diff_outfile);
5201 if (fd1 != -1 && close(fd1) == -1 && err == NULL)
5202 err = got_error_from_errno("close");
5203 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
5204 err = got_error_from_errno("close");
5206 got_object_blob_close(blob1);
5207 if (fd != -1 && close(fd) == -1 && err == NULL)
5208 err = got_error_from_errno("close");
5209 if (ondisk_file && fclose(ondisk_file) == EOF && err == NULL)
5210 err = got_error_from_errno("fclose");
5214 static const struct got_error *
5215 collect_commitables(void *arg, unsigned char status,
5216 unsigned char staged_status, const char *relpath,
5217 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
5218 struct got_object_id *commit_id, int dirfd, const char *de_name)
5220 struct collect_commitables_arg *a = arg;
5221 const struct got_error *err = NULL;
5222 struct got_commitable *ct = NULL;
5223 struct got_pathlist_entry *new = NULL;
5224 char *parent_path = NULL, *path = NULL;
5227 if (a->have_staged_files) {
5228 if (staged_status != GOT_STATUS_MODIFY &&
5229 staged_status != GOT_STATUS_ADD &&
5230 staged_status != GOT_STATUS_DELETE)
5233 if (status == GOT_STATUS_CONFLICT && !a->commit_conflicts) {
5234 printf("C %s\n", relpath);
5235 return got_error(GOT_ERR_COMMIT_CONFLICT);
5238 if (status != GOT_STATUS_MODIFY &&
5239 status != GOT_STATUS_MODE_CHANGE &&
5240 status != GOT_STATUS_ADD &&
5241 status != GOT_STATUS_DELETE &&
5242 status != GOT_STATUS_CONFLICT)
5246 if (asprintf(&path, "/%s", relpath) == -1) {
5247 err = got_error_from_errno("asprintf");
5250 if (strcmp(path, "/") == 0) {
5251 parent_path = strdup("");
5252 if (parent_path == NULL)
5253 return got_error_from_errno("strdup");
5255 err = got_path_dirname(&parent_path, path);
5260 ct = calloc(1, sizeof(*ct));
5262 err = got_error_from_errno("calloc");
5266 if (asprintf(&ct->ondisk_path, "%s/%s", a->worktree->root_path,
5268 err = got_error_from_errno("asprintf");
5272 if (staged_status == GOT_STATUS_ADD ||
5273 staged_status == GOT_STATUS_MODIFY) {
5274 struct got_fileindex_entry *ie;
5275 ie = got_fileindex_entry_get(a->fileindex, path, strlen(path));
5276 switch (got_fileindex_entry_staged_filetype_get(ie)) {
5277 case GOT_FILEIDX_MODE_REGULAR_FILE:
5278 case GOT_FILEIDX_MODE_BAD_SYMLINK:
5281 case GOT_FILEIDX_MODE_SYMLINK:
5285 err = got_error_path(path, GOT_ERR_BAD_FILETYPE);
5288 ct->mode |= got_fileindex_entry_perms_get(ie);
5289 } else if (status != GOT_STATUS_DELETE &&
5290 staged_status != GOT_STATUS_DELETE) {
5292 if (fstatat(dirfd, de_name, &sb,
5293 AT_SYMLINK_NOFOLLOW) == -1) {
5294 err = got_error_from_errno2("fstatat",
5298 } else if (lstat(ct->ondisk_path, &sb) == -1) {
5299 err = got_error_from_errno2("lstat", ct->ondisk_path);
5302 ct->mode = sb.st_mode;
5305 if (asprintf(&ct->in_repo_path, "%s%s%s", a->worktree->path_prefix,
5306 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
5308 err = got_error_from_errno("asprintf");
5312 if (S_ISLNK(ct->mode) && staged_status == GOT_STATUS_NO_CHANGE &&
5313 status == GOT_STATUS_ADD && !a->allow_bad_symlinks) {
5315 char target_path[PATH_MAX];
5317 target_len = readlink(ct->ondisk_path, target_path,
5318 sizeof(target_path));
5319 if (target_len == -1) {
5320 err = got_error_from_errno2("readlink",
5324 err = is_bad_symlink_target(&is_bad_symlink, target_path,
5325 target_len, ct->ondisk_path, a->worktree->root_path);
5328 if (is_bad_symlink) {
5329 err = got_error_path(ct->ondisk_path,
5330 GOT_ERR_BAD_SYMLINK);
5336 ct->status = status;
5337 ct->staged_status = staged_status;
5338 ct->blob_id = NULL; /* will be filled in when blob gets created */
5339 if (ct->status != GOT_STATUS_ADD &&
5340 ct->staged_status != GOT_STATUS_ADD) {
5341 ct->base_blob_id = got_object_id_dup(blob_id);
5342 if (ct->base_blob_id == NULL) {
5343 err = got_error_from_errno("got_object_id_dup");
5346 ct->base_commit_id = got_object_id_dup(commit_id);
5347 if (ct->base_commit_id == NULL) {
5348 err = got_error_from_errno("got_object_id_dup");
5352 if (ct->staged_status == GOT_STATUS_ADD ||
5353 ct->staged_status == GOT_STATUS_MODIFY) {
5354 ct->staged_blob_id = got_object_id_dup(staged_blob_id);
5355 if (ct->staged_blob_id == NULL) {
5356 err = got_error_from_errno("got_object_id_dup");
5360 ct->path = strdup(path);
5361 if (ct->path == NULL) {
5362 err = got_error_from_errno("strdup");
5365 err = got_pathlist_insert(&new, a->commitable_paths, ct->path, ct);
5369 if (a->diff_outfile && ct && new != NULL) {
5370 err = append_ct_diff(ct, &a->diff_header_shown,
5371 a->diff_outfile, a->f1, a->f2, dirfd, de_name,
5372 a->have_staged_files, a->repo, a->worktree);
5377 if (ct && (err || new == NULL))
5378 free_commitable(ct);
5384 static const struct got_error *write_tree(struct got_object_id **, int *,
5385 struct got_tree_object *, const char *, struct got_pathlist_head *,
5386 got_worktree_status_cb status_cb, void *status_arg,
5387 struct got_repository *);
5389 static const struct got_error *
5390 write_subtree(struct got_object_id **new_subtree_id, int *nentries,
5391 struct got_tree_entry *te, const char *parent_path,
5392 struct got_pathlist_head *commitable_paths,
5393 got_worktree_status_cb status_cb, void *status_arg,
5394 struct got_repository *repo)
5396 const struct got_error *err = NULL;
5397 struct got_tree_object *subtree;
5400 if (asprintf(&subpath, "%s%s%s", parent_path,
5401 got_path_is_root_dir(parent_path) ? "" : "/", te->name) == -1)
5402 return got_error_from_errno("asprintf");
5404 err = got_object_open_as_tree(&subtree, repo, &te->id);
5408 err = write_tree(new_subtree_id, nentries, subtree, subpath,
5409 commitable_paths, status_cb, status_arg, repo);
5410 got_object_tree_close(subtree);
5415 static const struct got_error *
5416 match_ct_parent_path(int *match, struct got_commitable *ct, const char *path)
5418 const struct got_error *err = NULL;
5419 char *ct_parent_path = NULL;
5423 if (strchr(ct->in_repo_path, '/') == NULL) {
5424 *match = got_path_is_root_dir(path);
5428 err = got_path_dirname(&ct_parent_path, ct->in_repo_path);
5431 *match = (strcmp(path, ct_parent_path) == 0);
5432 free(ct_parent_path);
5437 get_ct_file_mode(struct got_commitable *ct)
5439 if (S_ISLNK(ct->mode))
5442 return S_IFREG | (ct->mode & ((S_IRWXU | S_IRWXG | S_IRWXO)));
5445 static const struct got_error *
5446 alloc_modified_blob_tree_entry(struct got_tree_entry **new_te,
5447 struct got_tree_entry *te, struct got_commitable *ct)
5449 const struct got_error *err = NULL;
5453 err = got_object_tree_entry_dup(new_te, te);
5457 (*new_te)->mode = get_ct_file_mode(ct);
5459 if (ct->staged_status == GOT_STATUS_MODIFY)
5460 memcpy(&(*new_te)->id, ct->staged_blob_id,
5461 sizeof((*new_te)->id));
5463 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
5465 if (err && *new_te) {
5472 static const struct got_error *
5473 alloc_added_blob_tree_entry(struct got_tree_entry **new_te,
5474 struct got_commitable *ct)
5476 const struct got_error *err = NULL;
5477 char *ct_name = NULL;
5481 *new_te = calloc(1, sizeof(**new_te));
5482 if (*new_te == NULL)
5483 return got_error_from_errno("calloc");
5485 err = got_path_basename(&ct_name, ct->path);
5488 if (strlcpy((*new_te)->name, ct_name, sizeof((*new_te)->name)) >=
5489 sizeof((*new_te)->name)) {
5490 err = got_error(GOT_ERR_NO_SPACE);
5494 (*new_te)->mode = get_ct_file_mode(ct);
5496 if (ct->staged_status == GOT_STATUS_ADD)
5497 memcpy(&(*new_te)->id, ct->staged_blob_id,
5498 sizeof((*new_te)->id));
5500 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
5503 if (err && *new_te) {
5510 static const struct got_error *
5511 insert_tree_entry(struct got_tree_entry *new_te,
5512 struct got_pathlist_head *paths)
5514 const struct got_error *err = NULL;
5515 struct got_pathlist_entry *new_pe;
5517 err = got_pathlist_insert(&new_pe, paths, new_te->name, new_te);
5521 return got_error(GOT_ERR_TREE_DUP_ENTRY);
5525 static const struct got_error *
5526 report_ct_status(struct got_commitable *ct,
5527 got_worktree_status_cb status_cb, void *status_arg)
5529 const char *ct_path = ct->path;
5530 unsigned char status;
5532 if (status_cb == NULL) /* no commit progress output desired */
5535 while (ct_path[0] == '/')
5538 if (ct->staged_status != GOT_STATUS_NO_CHANGE)
5539 status = ct->staged_status;
5541 status = ct->status;
5543 return (*status_cb)(status_arg, status, GOT_STATUS_NO_CHANGE,
5544 ct_path, ct->blob_id, NULL, NULL, -1, NULL);
5547 static const struct got_error *
5548 match_modified_subtree(int *modified, struct got_tree_entry *te,
5549 const char *base_tree_path, struct got_pathlist_head *commitable_paths)
5551 const struct got_error *err = NULL;
5552 struct got_pathlist_entry *pe;
5557 if (asprintf(&te_path, "%s%s%s", base_tree_path,
5558 got_path_is_root_dir(base_tree_path) ? "" : "/",
5560 return got_error_from_errno("asprintf");
5562 TAILQ_FOREACH(pe, commitable_paths, entry) {
5563 struct got_commitable *ct = pe->data;
5564 *modified = got_path_is_child(ct->in_repo_path, te_path,
5574 static const struct got_error *
5575 match_deleted_or_modified_ct(struct got_commitable **ctp,
5576 struct got_tree_entry *te, const char *base_tree_path,
5577 struct got_pathlist_head *commitable_paths)
5579 const struct got_error *err = NULL;
5580 struct got_pathlist_entry *pe;
5584 TAILQ_FOREACH(pe, commitable_paths, entry) {
5585 struct got_commitable *ct = pe->data;
5586 char *ct_name = NULL;
5589 if (ct->staged_status == GOT_STATUS_NO_CHANGE) {
5590 if (ct->status != GOT_STATUS_MODIFY &&
5591 ct->status != GOT_STATUS_MODE_CHANGE &&
5592 ct->status != GOT_STATUS_DELETE &&
5593 ct->status != GOT_STATUS_CONFLICT)
5596 if (ct->staged_status != GOT_STATUS_MODIFY &&
5597 ct->staged_status != GOT_STATUS_DELETE)
5601 if (got_object_id_cmp(ct->base_blob_id, &te->id) != 0)
5604 err = match_ct_parent_path(&path_matches, ct, base_tree_path);
5610 err = got_path_basename(&ct_name, pe->path);
5614 if (strcmp(te->name, ct_name) != 0) {
5627 static const struct got_error *
5628 make_subtree_for_added_blob(struct got_tree_entry **new_tep,
5629 const char *child_path, const char *path_base_tree,
5630 struct got_pathlist_head *commitable_paths,
5631 got_worktree_status_cb status_cb, void *status_arg,
5632 struct got_repository *repo)
5634 const struct got_error *err = NULL;
5635 struct got_tree_entry *new_te;
5637 struct got_object_id *id = NULL;
5642 if (asprintf(&subtree_path, "%s%s%s", path_base_tree,
5643 got_path_is_root_dir(path_base_tree) ? "" : "/",
5645 return got_error_from_errno("asprintf");
5647 new_te = calloc(1, sizeof(*new_te));
5649 return got_error_from_errno("calloc");
5650 new_te->mode = S_IFDIR;
5652 if (strlcpy(new_te->name, child_path, sizeof(new_te->name)) >=
5653 sizeof(new_te->name)) {
5654 err = got_error(GOT_ERR_NO_SPACE);
5657 err = write_tree(&id, &nentries, NULL, subtree_path,
5658 commitable_paths, status_cb, status_arg, repo);
5663 memcpy(&new_te->id, id, sizeof(new_te->id));
5672 static const struct got_error *
5673 write_tree(struct got_object_id **new_tree_id, int *nentries,
5674 struct got_tree_object *base_tree, const char *path_base_tree,
5675 struct got_pathlist_head *commitable_paths,
5676 got_worktree_status_cb status_cb, void *status_arg,
5677 struct got_repository *repo)
5679 const struct got_error *err = NULL;
5680 struct got_pathlist_head paths;
5681 struct got_tree_entry *te, *new_te = NULL;
5682 struct got_pathlist_entry *pe;
5687 /* Insert, and recurse into, newly added entries first. */
5688 TAILQ_FOREACH(pe, commitable_paths, entry) {
5689 struct got_commitable *ct = pe->data;
5690 char *child_path = NULL, *slash;
5692 if ((ct->status != GOT_STATUS_ADD &&
5693 ct->staged_status != GOT_STATUS_ADD) ||
5694 (ct->flags & GOT_COMMITABLE_ADDED))
5697 if (!got_path_is_child(ct->in_repo_path, path_base_tree,
5698 strlen(path_base_tree)))
5701 err = got_path_skip_common_ancestor(&child_path, path_base_tree,
5706 slash = strchr(child_path, '/');
5707 if (slash == NULL) {
5708 err = alloc_added_blob_tree_entry(&new_te, ct);
5711 err = report_ct_status(ct, status_cb, status_arg);
5714 ct->flags |= GOT_COMMITABLE_ADDED;
5715 err = insert_tree_entry(new_te, &paths);
5720 *slash = '\0'; /* trim trailing path components */
5721 if (base_tree == NULL ||
5722 got_object_tree_find_entry(base_tree, child_path)
5724 err = make_subtree_for_added_blob(&new_te,
5725 child_path, path_base_tree,
5726 commitable_paths, status_cb, status_arg,
5730 err = insert_tree_entry(new_te, &paths);
5739 int i, nbase_entries;
5740 /* Handle modified and deleted entries. */
5741 nbase_entries = got_object_tree_get_nentries(base_tree);
5742 for (i = 0; i < nbase_entries; i++) {
5743 struct got_commitable *ct = NULL;
5745 te = got_object_tree_get_entry(base_tree, i);
5746 if (got_object_tree_entry_is_submodule(te)) {
5747 /* Entry is a submodule; just copy it. */
5748 err = got_object_tree_entry_dup(&new_te, te);
5751 err = insert_tree_entry(new_te, &paths);
5758 if (S_ISDIR(te->mode)) {
5760 err = got_object_tree_entry_dup(&new_te, te);
5763 err = match_modified_subtree(&modified, te,
5764 path_base_tree, commitable_paths);
5767 /* Avoid recursion into unmodified subtrees. */
5769 struct got_object_id *new_id;
5771 err = write_subtree(&new_id,
5773 path_base_tree, commitable_paths,
5774 status_cb, status_arg, repo);
5777 if (nsubentries == 0) {
5778 /* All entries were deleted. */
5782 memcpy(&new_te->id, new_id,
5783 sizeof(new_te->id));
5786 err = insert_tree_entry(new_te, &paths);
5793 err = match_deleted_or_modified_ct(&ct, te,
5794 path_base_tree, commitable_paths);
5798 /* NB: Deleted entries get dropped here. */
5799 if (ct->status == GOT_STATUS_MODIFY ||
5800 ct->status == GOT_STATUS_MODE_CHANGE ||
5801 ct->status == GOT_STATUS_CONFLICT ||
5802 ct->staged_status == GOT_STATUS_MODIFY) {
5803 err = alloc_modified_blob_tree_entry(
5807 err = insert_tree_entry(new_te, &paths);
5812 err = report_ct_status(ct, status_cb,
5817 /* Entry is unchanged; just copy it. */
5818 err = got_object_tree_entry_dup(&new_te, te);
5821 err = insert_tree_entry(new_te, &paths);
5829 /* Write new list of entries; deleted entries have been dropped. */
5830 err = got_object_tree_create(new_tree_id, &paths, *nentries, repo);
5832 got_pathlist_free(&paths, GOT_PATHLIST_FREE_NONE);
5836 static const struct got_error *
5837 update_fileindex_after_commit(struct got_worktree *worktree,
5838 struct got_pathlist_head *commitable_paths,
5839 struct got_object_id *new_base_commit_id,
5840 struct got_fileindex *fileindex, int have_staged_files)
5842 const struct got_error *err = NULL;
5843 struct got_pathlist_entry *pe;
5844 char *relpath = NULL;
5846 TAILQ_FOREACH(pe, commitable_paths, entry) {
5847 struct got_fileindex_entry *ie;
5848 struct got_commitable *ct = pe->data;
5850 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
5852 err = got_path_skip_common_ancestor(&relpath,
5853 worktree->root_path, ct->ondisk_path);
5858 if (ct->status == GOT_STATUS_DELETE ||
5859 ct->staged_status == GOT_STATUS_DELETE) {
5860 got_fileindex_entry_remove(fileindex, ie);
5861 } else if (ct->staged_status == GOT_STATUS_ADD ||
5862 ct->staged_status == GOT_STATUS_MODIFY) {
5863 got_fileindex_entry_stage_set(ie,
5864 GOT_FILEIDX_STAGE_NONE);
5865 got_fileindex_entry_staged_filetype_set(ie, 0);
5867 err = got_fileindex_entry_update(ie,
5868 worktree->root_fd, relpath,
5869 ct->staged_blob_id->sha1,
5870 new_base_commit_id->sha1,
5871 !have_staged_files);
5873 err = got_fileindex_entry_update(ie,
5874 worktree->root_fd, relpath,
5876 new_base_commit_id->sha1,
5877 !have_staged_files);
5879 err = got_fileindex_entry_alloc(&ie, pe->path);
5882 err = got_fileindex_entry_update(ie,
5883 worktree->root_fd, relpath, ct->blob_id->sha1,
5884 new_base_commit_id->sha1, 1);
5886 got_fileindex_entry_free(ie);
5889 err = got_fileindex_entry_add(fileindex, ie);
5891 got_fileindex_entry_free(ie);
5904 static const struct got_error *
5905 check_out_of_date(const char *in_repo_path, unsigned char status,
5906 unsigned char staged_status, struct got_object_id *base_blob_id,
5907 struct got_object_id *base_commit_id,
5908 struct got_object_id *head_commit_id, struct got_repository *repo,
5911 const struct got_error *err = NULL;
5912 struct got_commit_object *commit = NULL;
5913 struct got_object_id *id = NULL;
5915 if (status != GOT_STATUS_ADD && staged_status != GOT_STATUS_ADD) {
5916 /* Trivial case: base commit == head commit */
5917 if (got_object_id_cmp(base_commit_id, head_commit_id) == 0)
5920 * Ensure file content which local changes were based
5921 * on matches file content in the branch head.
5923 err = got_object_open_as_commit(&commit, repo, head_commit_id);
5926 err = got_object_id_by_path(&id, repo, commit, in_repo_path);
5928 if (err->code == GOT_ERR_NO_TREE_ENTRY)
5929 err = got_error(ood_errcode);
5931 } else if (got_object_id_cmp(id, base_blob_id) != 0)
5932 err = got_error(ood_errcode);
5934 /* Require that added files don't exist in the branch head. */
5935 err = got_object_open_as_commit(&commit, repo, head_commit_id);
5938 err = got_object_id_by_path(&id, repo, commit, in_repo_path);
5939 if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
5941 err = id ? got_error(ood_errcode) : NULL;
5946 got_object_commit_close(commit);
5950 static const struct got_error *
5951 commit_worktree(struct got_object_id **new_commit_id,
5952 struct got_pathlist_head *commitable_paths,
5953 struct got_object_id *head_commit_id,
5954 struct got_object_id *parent_id2,
5955 struct got_worktree *worktree,
5956 const char *author, const char *committer, char *diff_path,
5957 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
5958 got_worktree_status_cb status_cb, void *status_arg,
5959 struct got_repository *repo)
5961 const struct got_error *err = NULL, *unlockerr = NULL;
5962 struct got_pathlist_entry *pe;
5963 const char *head_ref_name = NULL;
5964 struct got_commit_object *head_commit = NULL;
5965 struct got_reference *head_ref2 = NULL;
5966 struct got_object_id *head_commit_id2 = NULL;
5967 struct got_tree_object *head_tree = NULL;
5968 struct got_object_id *new_tree_id = NULL;
5969 int nentries, nparents = 0;
5970 struct got_object_id_queue parent_ids;
5971 struct got_object_qid *pid = NULL;
5972 char *logmsg = NULL;
5975 *new_commit_id = NULL;
5977 STAILQ_INIT(&parent_ids);
5979 err = got_object_open_as_commit(&head_commit, repo, head_commit_id);
5983 err = got_object_open_as_tree(&head_tree, repo, head_commit->tree_id);
5987 if (commit_msg_cb != NULL) {
5988 err = commit_msg_cb(commitable_paths, diff_path,
5989 &logmsg, commit_arg);
5994 if (logmsg == NULL || strlen(logmsg) == 0) {
5995 err = got_error(GOT_ERR_COMMIT_MSG_EMPTY);
5999 /* Create blobs from added and modified files and record their IDs. */
6000 TAILQ_FOREACH(pe, commitable_paths, entry) {
6001 struct got_commitable *ct = pe->data;
6004 /* Blobs for staged files already exist. */
6005 if (ct->staged_status == GOT_STATUS_ADD ||
6006 ct->staged_status == GOT_STATUS_MODIFY)
6009 if (ct->status != GOT_STATUS_ADD &&
6010 ct->status != GOT_STATUS_MODIFY &&
6011 ct->status != GOT_STATUS_MODE_CHANGE &&
6012 ct->status != GOT_STATUS_CONFLICT)
6015 if (asprintf(&ondisk_path, "%s/%s",
6016 worktree->root_path, pe->path) == -1) {
6017 err = got_error_from_errno("asprintf");
6020 err = got_object_blob_create(&ct->blob_id, ondisk_path, repo);
6026 /* Recursively write new tree objects. */
6027 err = write_tree(&new_tree_id, &nentries, head_tree, "/",
6028 commitable_paths, status_cb, status_arg, repo);
6032 err = got_object_qid_alloc(&pid, worktree->base_commit_id);
6035 STAILQ_INSERT_TAIL(&parent_ids, pid, entry);
6038 err = got_object_qid_alloc(&pid, parent_id2);
6041 STAILQ_INSERT_TAIL(&parent_ids, pid, entry);
6044 timestamp = time(NULL);
6045 err = got_object_commit_create(new_commit_id, new_tree_id, &parent_ids,
6046 nparents, author, timestamp, committer, timestamp, logmsg, repo);
6052 /* Check if a concurrent commit to our branch has occurred. */
6053 head_ref_name = got_worktree_get_head_ref_name(worktree);
6054 if (head_ref_name == NULL) {
6055 err = got_error_from_errno("got_worktree_get_head_ref_name");
6058 /* Lock the reference here to prevent concurrent modification. */
6059 err = got_ref_open(&head_ref2, repo, head_ref_name, 1);
6062 err = got_ref_resolve(&head_commit_id2, repo, head_ref2);
6065 if (got_object_id_cmp(head_commit_id, head_commit_id2) != 0) {
6066 err = got_error(GOT_ERR_COMMIT_HEAD_CHANGED);
6069 /* Update branch head in repository. */
6070 err = got_ref_change_ref(head_ref2, *new_commit_id);
6073 err = got_ref_write(head_ref2, repo);
6077 err = got_worktree_set_base_commit_id(worktree, repo, *new_commit_id);
6081 err = ref_base_commit(worktree, repo);
6085 got_object_id_queue_free(&parent_ids);
6087 got_object_tree_close(head_tree);
6089 got_object_commit_close(head_commit);
6090 free(head_commit_id2);
6092 unlockerr = got_ref_unlock(head_ref2);
6093 if (unlockerr && err == NULL)
6095 got_ref_close(head_ref2);
6100 static const struct got_error *
6101 check_path_is_commitable(const char *path,
6102 struct got_pathlist_head *commitable_paths)
6104 struct got_pathlist_entry *cpe = NULL;
6105 size_t path_len = strlen(path);
6107 TAILQ_FOREACH(cpe, commitable_paths, entry) {
6108 struct got_commitable *ct = cpe->data;
6109 const char *ct_path = ct->path;
6111 while (ct_path[0] == '/')
6114 if (strcmp(path, ct_path) == 0 ||
6115 got_path_is_child(ct_path, path, path_len))
6120 return got_error_path(path, GOT_ERR_BAD_PATH);
6125 static const struct got_error *
6126 check_staged_file(void *arg, struct got_fileindex_entry *ie)
6128 int *have_staged_files = arg;
6130 if (got_fileindex_entry_stage_get(ie) != GOT_FILEIDX_STAGE_NONE) {
6131 *have_staged_files = 1;
6132 return got_error(GOT_ERR_CANCELLED);
6138 static const struct got_error *
6139 check_non_staged_files(struct got_fileindex *fileindex,
6140 struct got_pathlist_head *paths)
6142 struct got_pathlist_entry *pe;
6143 struct got_fileindex_entry *ie;
6145 TAILQ_FOREACH(pe, paths, entry) {
6146 if (pe->path[0] == '\0')
6148 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
6150 return got_error_path(pe->path, GOT_ERR_BAD_PATH);
6151 if (got_fileindex_entry_stage_get(ie) == GOT_FILEIDX_STAGE_NONE)
6152 return got_error_path(pe->path,
6153 GOT_ERR_FILE_NOT_STAGED);
6159 const struct got_error *
6160 got_worktree_commit(struct got_object_id **new_commit_id,
6161 struct got_worktree *worktree, struct got_pathlist_head *paths,
6162 const char *author, const char *committer, int allow_bad_symlinks,
6163 int show_diff, int commit_conflicts,
6164 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
6165 got_worktree_status_cb status_cb, void *status_arg,
6166 struct got_repository *repo)
6168 const struct got_error *err = NULL, *unlockerr = NULL, *sync_err;
6169 struct got_fileindex *fileindex = NULL;
6170 char *fileindex_path = NULL;
6171 struct got_pathlist_head commitable_paths;
6172 struct collect_commitables_arg cc_arg;
6173 struct got_pathlist_entry *pe;
6174 struct got_reference *head_ref = NULL;
6175 struct got_object_id *head_commit_id = NULL;
6176 char *diff_path = NULL;
6177 int have_staged_files = 0;
6179 *new_commit_id = NULL;
6181 memset(&cc_arg, 0, sizeof(cc_arg));
6182 TAILQ_INIT(&commitable_paths);
6184 err = lock_worktree(worktree, LOCK_EX);
6188 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
6192 err = got_ref_resolve(&head_commit_id, repo, head_ref);
6196 err = open_fileindex(&fileindex, &fileindex_path, worktree);
6200 err = got_fileindex_for_each_entry_safe(fileindex, check_staged_file,
6201 &have_staged_files);
6202 if (err && err->code != GOT_ERR_CANCELLED)
6204 if (have_staged_files) {
6205 err = check_non_staged_files(fileindex, paths);
6210 cc_arg.commitable_paths = &commitable_paths;
6211 cc_arg.worktree = worktree;
6212 cc_arg.fileindex = fileindex;
6214 cc_arg.have_staged_files = have_staged_files;
6215 cc_arg.allow_bad_symlinks = allow_bad_symlinks;
6216 cc_arg.diff_header_shown = 0;
6217 cc_arg.commit_conflicts = commit_conflicts;
6219 err = got_opentemp_named(&diff_path, &cc_arg.diff_outfile,
6220 GOT_TMPDIR_STR "/got", ".diff");
6223 cc_arg.f1 = got_opentemp();
6224 if (cc_arg.f1 == NULL) {
6225 err = got_error_from_errno("got_opentemp");
6228 cc_arg.f2 = got_opentemp();
6229 if (cc_arg.f2 == NULL) {
6230 err = got_error_from_errno("got_opentemp");
6235 TAILQ_FOREACH(pe, paths, entry) {
6236 err = worktree_status(worktree, pe->path, fileindex, repo,
6237 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
6243 if (fflush(cc_arg.diff_outfile) == EOF) {
6244 err = got_error_from_errno("fflush");
6249 if (TAILQ_EMPTY(&commitable_paths)) {
6250 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
6254 TAILQ_FOREACH(pe, paths, entry) {
6255 err = check_path_is_commitable(pe->path, &commitable_paths);
6260 TAILQ_FOREACH(pe, &commitable_paths, entry) {
6261 struct got_commitable *ct = pe->data;
6262 const char *ct_path = ct->in_repo_path;
6264 while (ct_path[0] == '/')
6266 err = check_out_of_date(ct_path, ct->status,
6267 ct->staged_status, ct->base_blob_id, ct->base_commit_id,
6268 head_commit_id, repo, GOT_ERR_COMMIT_OUT_OF_DATE);
6274 err = commit_worktree(new_commit_id, &commitable_paths,
6275 head_commit_id, NULL, worktree, author, committer,
6276 (diff_path && cc_arg.diff_header_shown) ? diff_path : NULL,
6277 commit_msg_cb, commit_arg, status_cb, status_arg, repo);
6281 err = update_fileindex_after_commit(worktree, &commitable_paths,
6282 *new_commit_id, fileindex, have_staged_files);
6283 sync_err = sync_fileindex(fileindex, fileindex_path);
6284 if (sync_err && err == NULL)
6288 got_fileindex_free(fileindex);
6289 free(fileindex_path);
6290 unlockerr = lock_worktree(worktree, LOCK_SH);
6291 if (unlockerr && err == NULL)
6293 TAILQ_FOREACH(pe, &commitable_paths, entry) {
6294 struct got_commitable *ct = pe->data;
6296 free_commitable(ct);
6298 got_pathlist_free(&commitable_paths, GOT_PATHLIST_FREE_NONE);
6299 if (diff_path && unlink(diff_path) == -1 && err == NULL)
6300 err = got_error_from_errno2("unlink", diff_path);
6302 if (cc_arg.diff_outfile && fclose(cc_arg.diff_outfile) == EOF &&
6304 err = got_error_from_errno("fclose");
6309 got_commitable_get_path(struct got_commitable *ct)
6315 got_commitable_get_status(struct got_commitable *ct)
6320 struct check_rebase_ok_arg {
6321 struct got_worktree *worktree;
6322 struct got_repository *repo;
6325 static const struct got_error *
6326 check_rebase_ok(void *arg, struct got_fileindex_entry *ie)
6328 const struct got_error *err = NULL;
6329 struct check_rebase_ok_arg *a = arg;
6330 unsigned char status;
6334 /* Reject rebase of a work tree with mixed base commits. */
6335 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
6336 SHA1_DIGEST_LENGTH))
6337 return got_error(GOT_ERR_MIXED_COMMITS);
6339 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
6341 return got_error_from_errno("asprintf");
6343 /* Reject rebase of a work tree with modified or staged files. */
6344 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
6349 if (status != GOT_STATUS_NO_CHANGE)
6350 return got_error(GOT_ERR_MODIFIED);
6351 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
6352 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
6357 const struct got_error *
6358 got_worktree_rebase_prepare(struct got_reference **new_base_branch_ref,
6359 struct got_reference **tmp_branch, struct got_fileindex **fileindex,
6360 struct got_worktree *worktree, struct got_reference *branch,
6361 struct got_repository *repo)
6363 const struct got_error *err = NULL;
6364 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
6365 char *branch_ref_name = NULL;
6366 char *fileindex_path = NULL;
6367 struct check_rebase_ok_arg ok_arg;
6368 struct got_reference *wt_branch = NULL, *branch_ref = NULL;
6369 struct got_object_id *wt_branch_tip = NULL;
6371 *new_base_branch_ref = NULL;
6375 err = lock_worktree(worktree, LOCK_EX);
6379 err = open_fileindex(fileindex, &fileindex_path, worktree);
6383 ok_arg.worktree = worktree;
6385 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
6390 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6394 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
6398 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
6402 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
6407 err = got_ref_resolve(&wt_branch_tip, repo, wt_branch);
6410 if (got_object_id_cmp(worktree->base_commit_id, wt_branch_tip) != 0) {
6411 err = got_error(GOT_ERR_REBASE_OUT_OF_DATE);
6415 err = got_ref_alloc_symref(new_base_branch_ref,
6416 new_base_branch_ref_name, wt_branch);
6419 err = got_ref_write(*new_base_branch_ref, repo);
6423 /* TODO Lock original branch's ref while rebasing? */
6425 err = got_ref_alloc_symref(&branch_ref, branch_ref_name, branch);
6429 err = got_ref_write(branch_ref, repo);
6433 err = got_ref_alloc(tmp_branch, tmp_branch_name,
6434 worktree->base_commit_id);
6437 err = got_ref_write(*tmp_branch, repo);
6441 err = got_worktree_set_head_ref(worktree, *tmp_branch);
6445 free(fileindex_path);
6446 free(tmp_branch_name);
6447 free(new_base_branch_ref_name);
6448 free(branch_ref_name);
6450 got_ref_close(branch_ref);
6452 got_ref_close(wt_branch);
6453 free(wt_branch_tip);
6455 if (*new_base_branch_ref) {
6456 got_ref_close(*new_base_branch_ref);
6457 *new_base_branch_ref = NULL;
6460 got_ref_close(*tmp_branch);
6464 got_fileindex_free(*fileindex);
6467 lock_worktree(worktree, LOCK_SH);
6472 const struct got_error *
6473 got_worktree_rebase_continue(struct got_object_id **commit_id,
6474 struct got_reference **new_base_branch, struct got_reference **tmp_branch,
6475 struct got_reference **branch, struct got_fileindex **fileindex,
6476 struct got_worktree *worktree, struct got_repository *repo)
6478 const struct got_error *err;
6479 char *commit_ref_name = NULL, *new_base_branch_ref_name = NULL;
6480 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
6481 struct got_reference *commit_ref = NULL, *branch_ref = NULL;
6482 char *fileindex_path = NULL;
6483 int have_staged_files = 0;
6486 *new_base_branch = NULL;
6491 err = lock_worktree(worktree, LOCK_EX);
6495 err = open_fileindex(fileindex, &fileindex_path, worktree);
6499 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
6500 &have_staged_files);
6501 if (err && err->code != GOT_ERR_CANCELLED)
6503 if (have_staged_files) {
6504 err = got_error(GOT_ERR_STAGED_PATHS);
6508 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6512 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
6516 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6520 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
6524 err = got_ref_open(&branch_ref, repo, branch_ref_name, 0);
6528 err = got_ref_open(branch, repo,
6529 got_ref_get_symref_target(branch_ref), 0);
6533 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6537 err = got_ref_resolve(commit_id, repo, commit_ref);
6541 err = got_ref_open(new_base_branch, repo,
6542 new_base_branch_ref_name, 0);
6546 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
6550 free(commit_ref_name);
6551 free(branch_ref_name);
6552 free(fileindex_path);
6554 got_ref_close(commit_ref);
6556 got_ref_close(branch_ref);
6561 got_ref_close(*tmp_branch);
6564 if (*new_base_branch) {
6565 got_ref_close(*new_base_branch);
6566 *new_base_branch = NULL;
6569 got_ref_close(*branch);
6573 got_fileindex_free(*fileindex);
6576 lock_worktree(worktree, LOCK_SH);
6581 const struct got_error *
6582 got_worktree_rebase_in_progress(int *in_progress, struct got_worktree *worktree)
6584 const struct got_error *err;
6585 char *tmp_branch_name = NULL;
6587 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6591 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
6592 free(tmp_branch_name);
6596 static const struct got_error *
6597 collect_rebase_commit_msg(struct got_pathlist_head *commitable_paths,
6598 const char *diff_path, char **logmsg, void *arg)
6604 static const struct got_error *
6605 rebase_status(void *arg, unsigned char status, unsigned char staged_status,
6606 const char *path, struct got_object_id *blob_id,
6607 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
6608 int dirfd, const char *de_name)
6613 struct collect_merged_paths_arg {
6614 got_worktree_checkout_cb progress_cb;
6616 struct got_pathlist_head *merged_paths;
6619 static const struct got_error *
6620 collect_merged_paths(void *arg, unsigned char status, const char *path)
6622 const struct got_error *err;
6623 struct collect_merged_paths_arg *a = arg;
6625 struct got_pathlist_entry *new;
6627 err = (*a->progress_cb)(a->progress_arg, status, path);
6631 if (status != GOT_STATUS_MERGE &&
6632 status != GOT_STATUS_ADD &&
6633 status != GOT_STATUS_DELETE &&
6634 status != GOT_STATUS_CONFLICT)
6639 return got_error_from_errno("strdup");
6641 err = got_pathlist_insert(&new, a->merged_paths, p, NULL);
6642 if (err || new == NULL)
6647 static const struct got_error *
6648 store_commit_id(const char *commit_ref_name, struct got_object_id *commit_id,
6649 int is_rebase, struct got_repository *repo)
6651 const struct got_error *err;
6652 struct got_reference *commit_ref = NULL;
6654 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6656 if (err->code != GOT_ERR_NOT_REF)
6658 err = got_ref_alloc(&commit_ref, commit_ref_name, commit_id);
6661 err = got_ref_write(commit_ref, repo);
6664 } else if (is_rebase) {
6665 struct got_object_id *stored_id;
6668 err = got_ref_resolve(&stored_id, repo, commit_ref);
6671 cmp = got_object_id_cmp(commit_id, stored_id);
6674 err = got_error(GOT_ERR_REBASE_COMMITID);
6680 got_ref_close(commit_ref);
6684 static const struct got_error *
6685 rebase_merge_files(struct got_pathlist_head *merged_paths,
6686 const char *commit_ref_name, struct got_worktree *worktree,
6687 struct got_fileindex *fileindex, struct got_object_id *parent_commit_id,
6688 struct got_object_id *commit_id, struct got_repository *repo,
6689 got_worktree_checkout_cb progress_cb, void *progress_arg,
6690 got_cancel_cb cancel_cb, void *cancel_arg)
6692 const struct got_error *err;
6693 struct got_reference *commit_ref = NULL;
6694 struct collect_merged_paths_arg cmp_arg;
6695 char *fileindex_path;
6697 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6699 err = get_fileindex_path(&fileindex_path, worktree);
6703 cmp_arg.progress_cb = progress_cb;
6704 cmp_arg.progress_arg = progress_arg;
6705 cmp_arg.merged_paths = merged_paths;
6706 err = merge_files(worktree, fileindex, fileindex_path,
6707 parent_commit_id, commit_id, repo, collect_merged_paths,
6708 &cmp_arg, cancel_cb, cancel_arg);
6710 got_ref_close(commit_ref);
6714 const struct got_error *
6715 got_worktree_rebase_merge_files(struct got_pathlist_head *merged_paths,
6716 struct got_worktree *worktree, struct got_fileindex *fileindex,
6717 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
6718 struct got_repository *repo,
6719 got_worktree_checkout_cb progress_cb, void *progress_arg,
6720 got_cancel_cb cancel_cb, void *cancel_arg)
6722 const struct got_error *err;
6723 char *commit_ref_name;
6725 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6729 err = store_commit_id(commit_ref_name, commit_id, 1, repo);
6733 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
6734 fileindex, parent_commit_id, commit_id, repo, progress_cb,
6735 progress_arg, cancel_cb, cancel_arg);
6737 free(commit_ref_name);
6741 const struct got_error *
6742 got_worktree_histedit_merge_files(struct got_pathlist_head *merged_paths,
6743 struct got_worktree *worktree, struct got_fileindex *fileindex,
6744 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
6745 struct got_repository *repo,
6746 got_worktree_checkout_cb progress_cb, void *progress_arg,
6747 got_cancel_cb cancel_cb, void *cancel_arg)
6749 const struct got_error *err;
6750 char *commit_ref_name;
6752 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6756 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
6760 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
6761 fileindex, parent_commit_id, commit_id, repo, progress_cb,
6762 progress_arg, cancel_cb, cancel_arg);
6764 free(commit_ref_name);
6768 static const struct got_error *
6769 rebase_commit(struct got_object_id **new_commit_id,
6770 struct got_pathlist_head *merged_paths, struct got_reference *commit_ref,
6771 struct got_worktree *worktree, struct got_fileindex *fileindex,
6772 struct got_reference *tmp_branch, const char *committer,
6773 struct got_commit_object *orig_commit, const char *new_logmsg,
6774 int allow_conflict, struct got_repository *repo)
6776 const struct got_error *err, *sync_err;
6777 struct got_pathlist_head commitable_paths;
6778 struct collect_commitables_arg cc_arg;
6779 char *fileindex_path = NULL;
6780 struct got_reference *head_ref = NULL;
6781 struct got_object_id *head_commit_id = NULL;
6782 char *logmsg = NULL;
6784 memset(&cc_arg, 0, sizeof(cc_arg));
6785 TAILQ_INIT(&commitable_paths);
6786 *new_commit_id = NULL;
6788 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6790 err = get_fileindex_path(&fileindex_path, worktree);
6794 cc_arg.commitable_paths = &commitable_paths;
6795 cc_arg.worktree = worktree;
6797 cc_arg.have_staged_files = 0;
6798 cc_arg.commit_conflicts = allow_conflict;
6800 * If possible get the status of individual files directly to
6801 * avoid crawling the entire work tree once per rebased commit.
6803 * Ideally, merged_paths would contain a list of commitables
6804 * we could use so we could skip worktree_status() entirely.
6805 * However, we would then need carefully keep track of cumulative
6806 * effects of operations such as file additions and deletions
6807 * in 'got histedit -f' (folding multiple commits into one),
6808 * and this extra complexity is not really worth it.
6811 struct got_pathlist_entry *pe;
6812 TAILQ_FOREACH(pe, merged_paths, entry) {
6813 err = worktree_status(worktree, pe->path, fileindex,
6814 repo, collect_commitables, &cc_arg, NULL, NULL, 1,
6820 err = worktree_status(worktree, "", fileindex, repo,
6821 collect_commitables, &cc_arg, NULL, NULL, 1, 0);
6826 if (TAILQ_EMPTY(&commitable_paths)) {
6827 /* No-op change; commit will be elided. */
6828 err = got_ref_delete(commit_ref, repo);
6831 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
6835 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
6839 err = got_ref_resolve(&head_commit_id, repo, head_ref);
6844 logmsg = strdup(new_logmsg);
6845 if (logmsg == NULL) {
6846 err = got_error_from_errno("strdup");
6850 err = got_object_commit_get_logmsg(&logmsg, orig_commit);
6855 /* NB: commit_worktree will call free(logmsg) */
6856 err = commit_worktree(new_commit_id, &commitable_paths, head_commit_id,
6857 NULL, worktree, got_object_commit_get_author(orig_commit),
6858 committer ? committer :
6859 got_object_commit_get_committer(orig_commit), NULL,
6860 collect_rebase_commit_msg, logmsg, rebase_status, NULL, repo);
6864 err = got_ref_change_ref(tmp_branch, *new_commit_id);
6868 err = got_ref_delete(commit_ref, repo);
6872 err = update_fileindex_after_commit(worktree, &commitable_paths,
6873 *new_commit_id, fileindex, 0);
6874 sync_err = sync_fileindex(fileindex, fileindex_path);
6875 if (sync_err && err == NULL)
6878 free(fileindex_path);
6879 free(head_commit_id);
6881 got_ref_close(head_ref);
6883 free(*new_commit_id);
6884 *new_commit_id = NULL;
6889 const struct got_error *
6890 got_worktree_rebase_commit(struct got_object_id **new_commit_id,
6891 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
6892 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6893 const char *committer, struct got_commit_object *orig_commit,
6894 struct got_object_id *orig_commit_id, int allow_conflict,
6895 struct got_repository *repo)
6897 const struct got_error *err;
6898 char *commit_ref_name;
6899 struct got_reference *commit_ref = NULL;
6900 struct got_object_id *commit_id = NULL;
6902 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6906 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6909 err = got_ref_resolve(&commit_id, repo, commit_ref);
6912 if (got_object_id_cmp(commit_id, orig_commit_id) != 0) {
6913 err = got_error(GOT_ERR_REBASE_COMMITID);
6917 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
6918 worktree, fileindex, tmp_branch, committer, orig_commit,
6919 NULL, allow_conflict, repo);
6922 got_ref_close(commit_ref);
6923 free(commit_ref_name);
6928 const struct got_error *
6929 got_worktree_histedit_commit(struct got_object_id **new_commit_id,
6930 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
6931 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6932 const char *committer, struct got_commit_object *orig_commit,
6933 struct got_object_id *orig_commit_id, const char *new_logmsg,
6934 int allow_conflict, struct got_repository *repo)
6936 const struct got_error *err;
6937 char *commit_ref_name;
6938 struct got_reference *commit_ref = NULL;
6940 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6944 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6948 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
6949 worktree, fileindex, tmp_branch, committer, orig_commit,
6950 new_logmsg, allow_conflict, repo);
6953 got_ref_close(commit_ref);
6954 free(commit_ref_name);
6958 const struct got_error *
6959 got_worktree_rebase_postpone(struct got_worktree *worktree,
6960 struct got_fileindex *fileindex)
6963 got_fileindex_free(fileindex);
6964 return lock_worktree(worktree, LOCK_SH);
6967 static const struct got_error *
6968 delete_ref(const char *name, struct got_repository *repo)
6970 const struct got_error *err;
6971 struct got_reference *ref;
6973 err = got_ref_open(&ref, repo, name, 0);
6975 if (err->code == GOT_ERR_NOT_REF)
6980 err = got_ref_delete(ref, repo);
6985 static const struct got_error *
6986 delete_rebase_refs(struct got_worktree *worktree, struct got_repository *repo)
6988 const struct got_error *err;
6989 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
6990 char *branch_ref_name = NULL, *commit_ref_name = NULL;
6992 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6995 err = delete_ref(tmp_branch_name, repo);
6999 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
7002 err = delete_ref(new_base_branch_ref_name, repo);
7006 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
7009 err = delete_ref(branch_ref_name, repo);
7013 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
7016 err = delete_ref(commit_ref_name, repo);
7021 free(tmp_branch_name);
7022 free(new_base_branch_ref_name);
7023 free(branch_ref_name);
7024 free(commit_ref_name);
7028 static const struct got_error *
7029 create_backup_ref(const char *backup_ref_prefix, struct got_reference *branch,
7030 struct got_object_id *new_commit_id, struct got_repository *repo)
7032 const struct got_error *err;
7033 struct got_reference *ref = NULL;
7034 struct got_object_id *old_commit_id = NULL;
7035 const char *branch_name = NULL;
7036 char *new_id_str = NULL;
7037 char *refname = NULL;
7039 branch_name = got_ref_get_name(branch);
7040 if (strncmp(branch_name, "refs/heads/", 11) != 0)
7041 return got_error(GOT_ERR_BAD_REF_NAME); /* should not happen */
7044 err = got_object_id_str(&new_id_str, new_commit_id);
7048 if (asprintf(&refname, "%s/%s/%s", backup_ref_prefix, branch_name,
7049 new_id_str) == -1) {
7050 err = got_error_from_errno("asprintf");
7054 err = got_ref_resolve(&old_commit_id, repo, branch);
7058 err = got_ref_alloc(&ref, refname, old_commit_id);
7062 err = got_ref_write(ref, repo);
7066 free(old_commit_id);
7072 const struct got_error *
7073 got_worktree_rebase_complete(struct got_worktree *worktree,
7074 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
7075 struct got_reference *rebased_branch, struct got_repository *repo,
7078 const struct got_error *err, *unlockerr, *sync_err;
7079 struct got_object_id *new_head_commit_id = NULL;
7080 char *fileindex_path = NULL;
7082 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
7086 if (create_backup) {
7087 err = create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX,
7088 rebased_branch, new_head_commit_id, repo);
7093 err = got_ref_change_ref(rebased_branch, new_head_commit_id);
7097 err = got_ref_write(rebased_branch, repo);
7101 err = got_worktree_set_head_ref(worktree, rebased_branch);
7105 err = delete_rebase_refs(worktree, repo);
7109 err = get_fileindex_path(&fileindex_path, worktree);
7112 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
7113 sync_err = sync_fileindex(fileindex, fileindex_path);
7114 if (sync_err && err == NULL)
7117 got_fileindex_free(fileindex);
7118 free(fileindex_path);
7119 free(new_head_commit_id);
7120 unlockerr = lock_worktree(worktree, LOCK_SH);
7121 if (unlockerr && err == NULL)
7126 const struct got_error *
7127 got_worktree_rebase_abort(struct got_worktree *worktree,
7128 struct got_fileindex *fileindex, struct got_repository *repo,
7129 struct got_reference *new_base_branch,
7130 got_worktree_checkout_cb progress_cb, void *progress_arg)
7132 const struct got_error *err, *unlockerr, *sync_err;
7133 struct got_reference *resolved = NULL;
7134 struct got_object_id *commit_id = NULL;
7135 struct got_commit_object *commit = NULL;
7136 char *fileindex_path = NULL;
7137 struct revert_file_args rfa;
7138 struct got_object_id *tree_id = NULL;
7140 err = lock_worktree(worktree, LOCK_EX);
7144 err = got_object_open_as_commit(&commit, repo,
7145 worktree->base_commit_id);
7149 err = got_ref_open(&resolved, repo,
7150 got_ref_get_symref_target(new_base_branch), 0);
7154 err = got_worktree_set_head_ref(worktree, resolved);
7159 * XXX commits to the base branch could have happened while
7160 * we were busy rebasing; should we store the original commit ID
7161 * when rebase begins and read it back here?
7163 err = got_ref_resolve(&commit_id, repo, resolved);
7167 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
7171 err = got_object_id_by_path(&tree_id, repo, commit,
7172 worktree->path_prefix);
7176 err = delete_rebase_refs(worktree, repo);
7180 err = get_fileindex_path(&fileindex_path, worktree);
7184 rfa.worktree = worktree;
7185 rfa.fileindex = fileindex;
7186 rfa.progress_cb = progress_cb;
7187 rfa.progress_arg = progress_arg;
7188 rfa.patch_cb = NULL;
7189 rfa.patch_arg = NULL;
7191 rfa.unlink_added_files = 0;
7192 err = worktree_status(worktree, "", fileindex, repo,
7193 revert_file, &rfa, NULL, NULL, 1, 0);
7197 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
7198 repo, progress_cb, progress_arg, NULL, NULL);
7200 sync_err = sync_fileindex(fileindex, fileindex_path);
7201 if (sync_err && err == NULL)
7204 got_ref_close(resolved);
7208 got_object_commit_close(commit);
7210 got_fileindex_free(fileindex);
7211 free(fileindex_path);
7213 unlockerr = lock_worktree(worktree, LOCK_SH);
7214 if (unlockerr && err == NULL)
7219 const struct got_error *
7220 got_worktree_histedit_prepare(struct got_reference **tmp_branch,
7221 struct got_reference **branch_ref, struct got_object_id **base_commit_id,
7222 struct got_fileindex **fileindex, struct got_worktree *worktree,
7223 struct got_repository *repo)
7225 const struct got_error *err = NULL;
7226 char *tmp_branch_name = NULL;
7227 char *branch_ref_name = NULL;
7228 char *base_commit_ref_name = NULL;
7229 char *fileindex_path = NULL;
7230 struct check_rebase_ok_arg ok_arg;
7231 struct got_reference *wt_branch = NULL;
7232 struct got_reference *base_commit_ref = NULL;
7236 *base_commit_id = NULL;
7239 err = lock_worktree(worktree, LOCK_EX);
7243 err = open_fileindex(fileindex, &fileindex_path, worktree);
7247 ok_arg.worktree = worktree;
7249 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
7254 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
7258 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
7262 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
7267 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
7272 err = got_ref_alloc_symref(branch_ref, branch_ref_name, wt_branch);
7276 err = got_ref_write(*branch_ref, repo);
7280 err = got_ref_alloc(&base_commit_ref, base_commit_ref_name,
7281 worktree->base_commit_id);
7284 err = got_ref_write(base_commit_ref, repo);
7287 *base_commit_id = got_object_id_dup(worktree->base_commit_id);
7288 if (*base_commit_id == NULL) {
7289 err = got_error_from_errno("got_object_id_dup");
7293 err = got_ref_alloc(tmp_branch, tmp_branch_name,
7294 worktree->base_commit_id);
7297 err = got_ref_write(*tmp_branch, repo);
7301 err = got_worktree_set_head_ref(worktree, *tmp_branch);
7305 free(fileindex_path);
7306 free(tmp_branch_name);
7307 free(branch_ref_name);
7308 free(base_commit_ref_name);
7310 got_ref_close(wt_branch);
7313 got_ref_close(*branch_ref);
7317 got_ref_close(*tmp_branch);
7320 free(*base_commit_id);
7322 got_fileindex_free(*fileindex);
7325 lock_worktree(worktree, LOCK_SH);
7330 const struct got_error *
7331 got_worktree_histedit_postpone(struct got_worktree *worktree,
7332 struct got_fileindex *fileindex)
7335 got_fileindex_free(fileindex);
7336 return lock_worktree(worktree, LOCK_SH);
7339 const struct got_error *
7340 got_worktree_histedit_in_progress(int *in_progress,
7341 struct got_worktree *worktree)
7343 const struct got_error *err;
7344 char *tmp_branch_name = NULL;
7346 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
7350 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
7351 free(tmp_branch_name);
7355 const struct got_error *
7356 got_worktree_histedit_continue(struct got_object_id **commit_id,
7357 struct got_reference **tmp_branch, struct got_reference **branch_ref,
7358 struct got_object_id **base_commit_id, struct got_fileindex **fileindex,
7359 struct got_worktree *worktree, struct got_repository *repo)
7361 const struct got_error *err;
7362 char *commit_ref_name = NULL, *base_commit_ref_name = NULL;
7363 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
7364 struct got_reference *commit_ref = NULL;
7365 struct got_reference *base_commit_ref = NULL;
7366 char *fileindex_path = NULL;
7367 int have_staged_files = 0;
7371 *base_commit_id = NULL;
7374 err = lock_worktree(worktree, LOCK_EX);
7378 err = open_fileindex(fileindex, &fileindex_path, worktree);
7382 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
7383 &have_staged_files);
7384 if (err && err->code != GOT_ERR_CANCELLED)
7386 if (have_staged_files) {
7387 err = got_error(GOT_ERR_STAGED_PATHS);
7391 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
7395 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
7399 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
7403 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
7408 err = got_ref_open(branch_ref, repo, branch_ref_name, 0);
7412 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
7415 err = got_ref_resolve(commit_id, repo, commit_ref);
7419 err = got_ref_open(&base_commit_ref, repo, base_commit_ref_name, 0);
7422 err = got_ref_resolve(base_commit_id, repo, base_commit_ref);
7426 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
7430 free(commit_ref_name);
7431 free(branch_ref_name);
7432 free(fileindex_path);
7434 got_ref_close(commit_ref);
7435 if (base_commit_ref)
7436 got_ref_close(base_commit_ref);
7440 free(*base_commit_id);
7441 *base_commit_id = NULL;
7443 got_ref_close(*tmp_branch);
7447 got_fileindex_free(*fileindex);
7450 lock_worktree(worktree, LOCK_EX);
7455 static const struct got_error *
7456 delete_histedit_refs(struct got_worktree *worktree, struct got_repository *repo)
7458 const struct got_error *err;
7459 char *tmp_branch_name = NULL, *base_commit_ref_name = NULL;
7460 char *branch_ref_name = NULL, *commit_ref_name = NULL;
7462 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
7465 err = delete_ref(tmp_branch_name, repo);
7469 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
7473 err = delete_ref(base_commit_ref_name, repo);
7477 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
7480 err = delete_ref(branch_ref_name, repo);
7484 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
7487 err = delete_ref(commit_ref_name, repo);
7491 free(tmp_branch_name);
7492 free(base_commit_ref_name);
7493 free(branch_ref_name);
7494 free(commit_ref_name);
7498 const struct got_error *
7499 got_worktree_histedit_abort(struct got_worktree *worktree,
7500 struct got_fileindex *fileindex, struct got_repository *repo,
7501 struct got_reference *branch, struct got_object_id *base_commit_id,
7502 got_worktree_checkout_cb progress_cb, void *progress_arg)
7504 const struct got_error *err, *unlockerr, *sync_err;
7505 struct got_reference *resolved = NULL;
7506 char *fileindex_path = NULL;
7507 struct got_commit_object *commit = NULL;
7508 struct got_object_id *tree_id = NULL;
7509 struct revert_file_args rfa;
7511 err = lock_worktree(worktree, LOCK_EX);
7515 err = got_object_open_as_commit(&commit, repo,
7516 worktree->base_commit_id);
7520 err = got_ref_open(&resolved, repo,
7521 got_ref_get_symref_target(branch), 0);
7525 err = got_worktree_set_head_ref(worktree, resolved);
7529 err = got_worktree_set_base_commit_id(worktree, repo, base_commit_id);
7533 err = got_object_id_by_path(&tree_id, repo, commit,
7534 worktree->path_prefix);
7538 err = delete_histedit_refs(worktree, repo);
7542 err = get_fileindex_path(&fileindex_path, worktree);
7546 rfa.worktree = worktree;
7547 rfa.fileindex = fileindex;
7548 rfa.progress_cb = progress_cb;
7549 rfa.progress_arg = progress_arg;
7550 rfa.patch_cb = NULL;
7551 rfa.patch_arg = NULL;
7553 rfa.unlink_added_files = 0;
7554 err = worktree_status(worktree, "", fileindex, repo,
7555 revert_file, &rfa, NULL, NULL, 1, 0);
7559 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
7560 repo, progress_cb, progress_arg, NULL, NULL);
7562 sync_err = sync_fileindex(fileindex, fileindex_path);
7563 if (sync_err && err == NULL)
7566 got_ref_close(resolved);
7568 free(fileindex_path);
7570 unlockerr = lock_worktree(worktree, LOCK_SH);
7571 if (unlockerr && err == NULL)
7576 const struct got_error *
7577 got_worktree_histedit_complete(struct got_worktree *worktree,
7578 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
7579 struct got_reference *edited_branch, struct got_repository *repo)
7581 const struct got_error *err, *unlockerr, *sync_err;
7582 struct got_object_id *new_head_commit_id = NULL;
7583 struct got_reference *resolved = NULL;
7584 char *fileindex_path = NULL;
7586 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
7590 err = got_ref_open(&resolved, repo,
7591 got_ref_get_symref_target(edited_branch), 0);
7595 err = create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX,
7596 resolved, new_head_commit_id, repo);
7600 err = got_ref_change_ref(resolved, new_head_commit_id);
7604 err = got_ref_write(resolved, repo);
7608 err = got_worktree_set_head_ref(worktree, resolved);
7612 err = delete_histedit_refs(worktree, repo);
7616 err = get_fileindex_path(&fileindex_path, worktree);
7619 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
7620 sync_err = sync_fileindex(fileindex, fileindex_path);
7621 if (sync_err && err == NULL)
7624 got_fileindex_free(fileindex);
7625 free(fileindex_path);
7626 free(new_head_commit_id);
7627 unlockerr = lock_worktree(worktree, LOCK_SH);
7628 if (unlockerr && err == NULL)
7633 const struct got_error *
7634 got_worktree_histedit_skip_commit(struct got_worktree *worktree,
7635 struct got_object_id *commit_id, struct got_repository *repo)
7637 const struct got_error *err;
7638 char *commit_ref_name;
7640 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
7644 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
7648 err = delete_ref(commit_ref_name, repo);
7650 free(commit_ref_name);
7654 const struct got_error *
7655 got_worktree_integrate_prepare(struct got_fileindex **fileindex,
7656 struct got_reference **branch_ref, struct got_reference **base_branch_ref,
7657 struct got_worktree *worktree, const char *refname,
7658 struct got_repository *repo)
7660 const struct got_error *err = NULL;
7661 char *fileindex_path = NULL;
7662 struct check_rebase_ok_arg ok_arg;
7666 *base_branch_ref = NULL;
7668 err = lock_worktree(worktree, LOCK_EX);
7672 if (strcmp(refname, got_worktree_get_head_ref_name(worktree)) == 0) {
7673 err = got_error_msg(GOT_ERR_SAME_BRANCH,
7674 "cannot integrate a branch into itself; "
7675 "update -b or different branch name required");
7679 err = open_fileindex(fileindex, &fileindex_path, worktree);
7683 /* Preconditions are the same as for rebase. */
7684 ok_arg.worktree = worktree;
7686 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
7691 err = got_ref_open(branch_ref, repo, refname, 1);
7695 err = got_ref_open(base_branch_ref, repo,
7696 got_worktree_get_head_ref_name(worktree), 1);
7700 got_ref_close(*branch_ref);
7703 if (*base_branch_ref) {
7704 got_ref_close(*base_branch_ref);
7705 *base_branch_ref = NULL;
7708 got_fileindex_free(*fileindex);
7711 lock_worktree(worktree, LOCK_SH);
7716 const struct got_error *
7717 got_worktree_integrate_continue(struct got_worktree *worktree,
7718 struct got_fileindex *fileindex, struct got_repository *repo,
7719 struct got_reference *branch_ref, struct got_reference *base_branch_ref,
7720 got_worktree_checkout_cb progress_cb, void *progress_arg,
7721 got_cancel_cb cancel_cb, void *cancel_arg)
7723 const struct got_error *err = NULL, *sync_err, *unlockerr;
7724 char *fileindex_path = NULL;
7725 struct got_object_id *tree_id = NULL, *commit_id = NULL;
7726 struct got_commit_object *commit = NULL;
7728 err = get_fileindex_path(&fileindex_path, worktree);
7732 err = got_ref_resolve(&commit_id, repo, branch_ref);
7736 err = got_object_open_as_commit(&commit, repo, commit_id);
7740 err = got_object_id_by_path(&tree_id, repo, commit,
7741 worktree->path_prefix);
7745 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
7749 err = checkout_files(worktree, fileindex, "", tree_id, NULL, repo,
7750 progress_cb, progress_arg, cancel_cb, cancel_arg);
7754 err = got_ref_change_ref(base_branch_ref, commit_id);
7758 err = got_ref_write(base_branch_ref, repo);
7762 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
7764 sync_err = sync_fileindex(fileindex, fileindex_path);
7765 if (sync_err && err == NULL)
7769 unlockerr = got_ref_unlock(branch_ref);
7770 if (unlockerr && err == NULL)
7772 got_ref_close(branch_ref);
7774 unlockerr = got_ref_unlock(base_branch_ref);
7775 if (unlockerr && err == NULL)
7777 got_ref_close(base_branch_ref);
7779 got_fileindex_free(fileindex);
7780 free(fileindex_path);
7783 got_object_commit_close(commit);
7785 unlockerr = lock_worktree(worktree, LOCK_SH);
7786 if (unlockerr && err == NULL)
7791 const struct got_error *
7792 got_worktree_integrate_abort(struct got_worktree *worktree,
7793 struct got_fileindex *fileindex, struct got_repository *repo,
7794 struct got_reference *branch_ref, struct got_reference *base_branch_ref)
7796 const struct got_error *err = NULL, *unlockerr = NULL;
7798 got_fileindex_free(fileindex);
7800 err = lock_worktree(worktree, LOCK_SH);
7802 unlockerr = got_ref_unlock(branch_ref);
7803 if (unlockerr && err == NULL)
7805 got_ref_close(branch_ref);
7807 unlockerr = got_ref_unlock(base_branch_ref);
7808 if (unlockerr && err == NULL)
7810 got_ref_close(base_branch_ref);
7815 const struct got_error *
7816 got_worktree_merge_postpone(struct got_worktree *worktree,
7817 struct got_fileindex *fileindex)
7819 const struct got_error *err, *sync_err;
7820 char *fileindex_path = NULL;
7822 err = get_fileindex_path(&fileindex_path, worktree);
7826 sync_err = sync_fileindex(fileindex, fileindex_path);
7828 err = lock_worktree(worktree, LOCK_SH);
7829 if (sync_err && err == NULL)
7832 got_fileindex_free(fileindex);
7833 free(fileindex_path);
7837 static const struct got_error *
7838 delete_merge_refs(struct got_worktree *worktree, struct got_repository *repo)
7840 const struct got_error *err;
7841 char *branch_refname = NULL, *commit_refname = NULL;
7843 err = get_merge_branch_ref_name(&branch_refname, worktree);
7846 err = delete_ref(branch_refname, repo);
7850 err = get_merge_commit_ref_name(&commit_refname, worktree);
7853 err = delete_ref(commit_refname, repo);
7858 free(branch_refname);
7859 free(commit_refname);
7863 struct merge_commit_msg_arg {
7864 struct got_worktree *worktree;
7865 const char *branch_name;
7868 static const struct got_error *
7869 merge_commit_msg_cb(struct got_pathlist_head *commitable_paths,
7870 const char *diff_path, char **logmsg, void *arg)
7872 struct merge_commit_msg_arg *a = arg;
7874 if (asprintf(logmsg, "merge %s into %s\n", a->branch_name,
7875 got_worktree_get_head_ref_name(a->worktree)) == -1)
7876 return got_error_from_errno("asprintf");
7882 const struct got_error *
7883 got_worktree_merge_branch(struct got_worktree *worktree,
7884 struct got_fileindex *fileindex,
7885 struct got_object_id *yca_commit_id,
7886 struct got_object_id *branch_tip,
7887 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
7888 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
7890 const struct got_error *err;
7891 char *fileindex_path = NULL;
7893 err = get_fileindex_path(&fileindex_path, worktree);
7897 err = got_fileindex_for_each_entry_safe(fileindex, check_mixed_commits,
7902 err = merge_files(worktree, fileindex, fileindex_path, yca_commit_id,
7903 branch_tip, repo, progress_cb, progress_arg,
7904 cancel_cb, cancel_arg);
7906 free(fileindex_path);
7910 const struct got_error *
7911 got_worktree_merge_commit(struct got_object_id **new_commit_id,
7912 struct got_worktree *worktree, struct got_fileindex *fileindex,
7913 const char *author, const char *committer, int allow_bad_symlinks,
7914 struct got_object_id *branch_tip, const char *branch_name,
7915 int allow_conflict, struct got_repository *repo,
7916 got_worktree_status_cb status_cb, void *status_arg)
7919 const struct got_error *err = NULL, *sync_err;
7920 struct got_pathlist_head commitable_paths;
7921 struct collect_commitables_arg cc_arg;
7922 struct got_pathlist_entry *pe;
7923 struct got_reference *head_ref = NULL;
7924 struct got_object_id *head_commit_id = NULL;
7925 int have_staged_files = 0;
7926 struct merge_commit_msg_arg mcm_arg;
7927 char *fileindex_path = NULL;
7929 memset(&cc_arg, 0, sizeof(cc_arg));
7930 *new_commit_id = NULL;
7932 TAILQ_INIT(&commitable_paths);
7934 err = get_fileindex_path(&fileindex_path, worktree);
7938 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
7942 err = got_ref_resolve(&head_commit_id, repo, head_ref);
7946 err = got_fileindex_for_each_entry_safe(fileindex, check_staged_file,
7947 &have_staged_files);
7948 if (err && err->code != GOT_ERR_CANCELLED)
7950 if (have_staged_files) {
7951 err = got_error(GOT_ERR_MERGE_STAGED_PATHS);
7955 cc_arg.commitable_paths = &commitable_paths;
7956 cc_arg.worktree = worktree;
7957 cc_arg.fileindex = fileindex;
7959 cc_arg.have_staged_files = have_staged_files;
7960 cc_arg.allow_bad_symlinks = allow_bad_symlinks;
7961 cc_arg.commit_conflicts = allow_conflict;
7962 err = worktree_status(worktree, "", fileindex, repo,
7963 collect_commitables, &cc_arg, NULL, NULL, 1, 0);
7967 if (TAILQ_EMPTY(&commitable_paths)) {
7968 err = got_error_fmt(GOT_ERR_COMMIT_NO_CHANGES,
7969 "merge of %s cannot proceed", branch_name);
7973 TAILQ_FOREACH(pe, &commitable_paths, entry) {
7974 struct got_commitable *ct = pe->data;
7975 const char *ct_path = ct->in_repo_path;
7977 while (ct_path[0] == '/')
7979 err = check_out_of_date(ct_path, ct->status,
7980 ct->staged_status, ct->base_blob_id, ct->base_commit_id,
7981 head_commit_id, repo, GOT_ERR_MERGE_COMMIT_OUT_OF_DATE);
7987 mcm_arg.worktree = worktree;
7988 mcm_arg.branch_name = branch_name;
7989 err = commit_worktree(new_commit_id, &commitable_paths,
7990 head_commit_id, branch_tip, worktree, author, committer, NULL,
7991 merge_commit_msg_cb, &mcm_arg, status_cb, status_arg, repo);
7995 err = update_fileindex_after_commit(worktree, &commitable_paths,
7996 *new_commit_id, fileindex, have_staged_files);
7997 sync_err = sync_fileindex(fileindex, fileindex_path);
7998 if (sync_err && err == NULL)
8001 TAILQ_FOREACH(pe, &commitable_paths, entry) {
8002 struct got_commitable *ct = pe->data;
8004 free_commitable(ct);
8006 got_pathlist_free(&commitable_paths, GOT_PATHLIST_FREE_NONE);
8007 free(fileindex_path);
8011 const struct got_error *
8012 got_worktree_merge_complete(struct got_worktree *worktree,
8013 struct got_fileindex *fileindex, struct got_repository *repo)
8015 const struct got_error *err, *unlockerr, *sync_err;
8016 char *fileindex_path = NULL;
8018 err = delete_merge_refs(worktree, repo);
8022 err = get_fileindex_path(&fileindex_path, worktree);
8025 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
8026 sync_err = sync_fileindex(fileindex, fileindex_path);
8027 if (sync_err && err == NULL)
8030 got_fileindex_free(fileindex);
8031 free(fileindex_path);
8032 unlockerr = lock_worktree(worktree, LOCK_SH);
8033 if (unlockerr && err == NULL)
8038 const struct got_error *
8039 got_worktree_merge_in_progress(int *in_progress, struct got_worktree *worktree,
8040 struct got_repository *repo)
8042 const struct got_error *err;
8043 char *branch_refname = NULL;
8044 struct got_reference *branch_ref = NULL;
8048 err = get_merge_branch_ref_name(&branch_refname, worktree);
8051 err = got_ref_open(&branch_ref, repo, branch_refname, 0);
8052 free(branch_refname);
8054 if (err->code != GOT_ERR_NOT_REF)
8062 const struct got_error *got_worktree_merge_prepare(
8063 struct got_fileindex **fileindex, struct got_worktree *worktree,
8064 struct got_reference *branch, struct got_repository *repo)
8066 const struct got_error *err = NULL;
8067 char *fileindex_path = NULL;
8068 char *branch_refname = NULL, *commit_refname = NULL;
8069 struct got_reference *wt_branch = NULL, *branch_ref = NULL;
8070 struct got_reference *commit_ref = NULL;
8071 struct got_object_id *branch_tip = NULL, *wt_branch_tip = NULL;
8072 struct check_rebase_ok_arg ok_arg;
8076 err = lock_worktree(worktree, LOCK_EX);
8080 err = open_fileindex(fileindex, &fileindex_path, worktree);
8084 /* Preconditions are the same as for rebase. */
8085 ok_arg.worktree = worktree;
8087 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
8092 err = get_merge_branch_ref_name(&branch_refname, worktree);
8096 err = get_merge_commit_ref_name(&commit_refname, worktree);
8100 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
8105 err = got_ref_resolve(&wt_branch_tip, repo, wt_branch);
8109 if (got_object_id_cmp(worktree->base_commit_id, wt_branch_tip) != 0) {
8110 err = got_error(GOT_ERR_MERGE_OUT_OF_DATE);
8114 err = got_ref_resolve(&branch_tip, repo, branch);
8118 err = got_ref_alloc_symref(&branch_ref, branch_refname, branch);
8121 err = got_ref_write(branch_ref, repo);
8125 err = got_ref_alloc(&commit_ref, commit_refname, branch_tip);
8128 err = got_ref_write(commit_ref, repo);
8133 free(branch_refname);
8134 free(commit_refname);
8135 free(fileindex_path);
8137 got_ref_close(branch_ref);
8139 got_ref_close(commit_ref);
8141 got_ref_close(wt_branch);
8142 free(wt_branch_tip);
8145 got_fileindex_free(*fileindex);
8148 lock_worktree(worktree, LOCK_SH);
8153 const struct got_error *
8154 got_worktree_merge_continue(char **branch_name,
8155 struct got_object_id **branch_tip, struct got_fileindex **fileindex,
8156 struct got_worktree *worktree, struct got_repository *repo)
8158 const struct got_error *err;
8159 char *commit_refname = NULL, *branch_refname = NULL;
8160 struct got_reference *commit_ref = NULL, *branch_ref = NULL;
8161 char *fileindex_path = NULL;
8162 int have_staged_files = 0;
8164 *branch_name = NULL;
8168 err = lock_worktree(worktree, LOCK_EX);
8172 err = open_fileindex(fileindex, &fileindex_path, worktree);
8176 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
8177 &have_staged_files);
8178 if (err && err->code != GOT_ERR_CANCELLED)
8180 if (have_staged_files) {
8181 err = got_error(GOT_ERR_STAGED_PATHS);
8185 err = get_merge_branch_ref_name(&branch_refname, worktree);
8189 err = get_merge_commit_ref_name(&commit_refname, worktree);
8193 err = got_ref_open(&branch_ref, repo, branch_refname, 0);
8197 if (!got_ref_is_symbolic(branch_ref)) {
8198 err = got_error_fmt(GOT_ERR_BAD_REF_TYPE,
8199 "%s is not a symbolic reference",
8200 got_ref_get_name(branch_ref));
8203 *branch_name = strdup(got_ref_get_symref_target(branch_ref));
8204 if (*branch_name == NULL) {
8205 err = got_error_from_errno("strdup");
8209 err = got_ref_open(&commit_ref, repo, commit_refname, 0);
8213 err = got_ref_resolve(branch_tip, repo, commit_ref);
8217 free(commit_refname);
8218 free(branch_refname);
8219 free(fileindex_path);
8221 got_ref_close(commit_ref);
8223 got_ref_close(branch_ref);
8227 *branch_name = NULL;
8232 got_fileindex_free(*fileindex);
8235 lock_worktree(worktree, LOCK_SH);
8240 const struct got_error *
8241 got_worktree_merge_abort(struct got_worktree *worktree,
8242 struct got_fileindex *fileindex, struct got_repository *repo,
8243 got_worktree_checkout_cb progress_cb, void *progress_arg)
8245 const struct got_error *err, *unlockerr, *sync_err;
8246 struct got_object_id *commit_id = NULL;
8247 struct got_commit_object *commit = NULL;
8248 char *fileindex_path = NULL;
8249 struct revert_file_args rfa;
8250 struct got_object_id *tree_id = NULL;
8252 err = got_object_open_as_commit(&commit, repo,
8253 worktree->base_commit_id);
8257 err = got_object_id_by_path(&tree_id, repo, commit,
8258 worktree->path_prefix);
8262 err = delete_merge_refs(worktree, repo);
8266 err = get_fileindex_path(&fileindex_path, worktree);
8270 rfa.worktree = worktree;
8271 rfa.fileindex = fileindex;
8272 rfa.progress_cb = progress_cb;
8273 rfa.progress_arg = progress_arg;
8274 rfa.patch_cb = NULL;
8275 rfa.patch_arg = NULL;
8277 rfa.unlink_added_files = 1;
8278 err = worktree_status(worktree, "", fileindex, repo,
8279 revert_file, &rfa, NULL, NULL, 1, 0);
8283 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
8284 repo, progress_cb, progress_arg, NULL, NULL);
8286 sync_err = sync_fileindex(fileindex, fileindex_path);
8287 if (sync_err && err == NULL)
8293 got_object_commit_close(commit);
8295 got_fileindex_free(fileindex);
8296 free(fileindex_path);
8298 unlockerr = lock_worktree(worktree, LOCK_SH);
8299 if (unlockerr && err == NULL)
8304 struct check_stage_ok_arg {
8305 struct got_object_id *head_commit_id;
8306 struct got_worktree *worktree;
8307 struct got_fileindex *fileindex;
8308 struct got_repository *repo;
8312 static const struct got_error *
8313 check_stage_ok(void *arg, unsigned char status,
8314 unsigned char staged_status, const char *relpath,
8315 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
8316 struct got_object_id *commit_id, int dirfd, const char *de_name)
8318 struct check_stage_ok_arg *a = arg;
8319 const struct got_error *err = NULL;
8320 struct got_fileindex_entry *ie;
8321 struct got_object_id base_commit_id;
8322 struct got_object_id *base_commit_idp = NULL;
8323 char *in_repo_path = NULL, *p;
8325 if (status == GOT_STATUS_UNVERSIONED ||
8326 status == GOT_STATUS_NO_CHANGE)
8328 if (status == GOT_STATUS_NONEXISTENT)
8329 return got_error_set_errno(ENOENT, relpath);
8331 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
8333 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
8335 if (asprintf(&in_repo_path, "%s%s%s", a->worktree->path_prefix,
8336 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
8338 return got_error_from_errno("asprintf");
8340 if (got_fileindex_entry_has_commit(ie)) {
8341 base_commit_idp = got_fileindex_entry_get_commit_id(
8342 &base_commit_id, ie);
8345 if (status == GOT_STATUS_CONFLICT) {
8346 err = got_error_path(ie->path, GOT_ERR_STAGE_CONFLICT);
8348 } else if (status != GOT_STATUS_ADD &&
8349 status != GOT_STATUS_MODIFY &&
8350 status != GOT_STATUS_DELETE) {
8351 err = got_error_path(ie->path, GOT_ERR_FILE_STATUS);
8355 a->have_changes = 1;
8360 err = check_out_of_date(p, status, staged_status,
8361 blob_id, base_commit_idp, a->head_commit_id, a->repo,
8362 GOT_ERR_STAGE_OUT_OF_DATE);
8368 struct stage_path_arg {
8369 struct got_worktree *worktree;
8370 struct got_fileindex *fileindex;
8371 struct got_repository *repo;
8372 got_worktree_status_cb status_cb;
8374 got_worktree_patch_cb patch_cb;
8376 int staged_something;
8377 int allow_bad_symlinks;
8380 static const struct got_error *
8381 stage_path(void *arg, unsigned char status,
8382 unsigned char staged_status, const char *relpath,
8383 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
8384 struct got_object_id *commit_id, int dirfd, const char *de_name)
8386 struct stage_path_arg *a = arg;
8387 const struct got_error *err = NULL;
8388 struct got_fileindex_entry *ie;
8389 char *ondisk_path = NULL, *path_content = NULL;
8391 struct got_object_id *new_staged_blob_id = NULL;
8394 if (status == GOT_STATUS_UNVERSIONED)
8397 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
8399 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
8401 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
8403 return got_error_from_errno("asprintf");
8406 case GOT_STATUS_ADD:
8407 case GOT_STATUS_MODIFY:
8408 /* XXX could sb.st_mode be passed in by our caller? */
8409 if (lstat(ondisk_path, &sb) == -1) {
8410 err = got_error_from_errno2("lstat", ondisk_path);
8414 if (status == GOT_STATUS_ADD) {
8415 int choice = GOT_PATCH_CHOICE_NONE;
8416 err = (*a->patch_cb)(&choice, a->patch_arg,
8417 status, ie->path, NULL, 1, 1);
8420 if (choice != GOT_PATCH_CHOICE_YES)
8423 err = create_patched_content(&path_content, 0,
8424 staged_blob_id ? staged_blob_id : blob_id,
8425 ondisk_path, dirfd, de_name, ie->path,
8426 a->repo, a->patch_cb, a->patch_arg);
8427 if (err || path_content == NULL)
8431 err = got_object_blob_create(&new_staged_blob_id,
8432 path_content ? path_content : ondisk_path, a->repo);
8435 memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1,
8436 SHA1_DIGEST_LENGTH);
8437 if (status == GOT_STATUS_ADD || staged_status == GOT_STATUS_ADD)
8438 stage = GOT_FILEIDX_STAGE_ADD;
8440 stage = GOT_FILEIDX_STAGE_MODIFY;
8441 got_fileindex_entry_stage_set(ie, stage);
8442 if (S_ISLNK(sb.st_mode)) {
8443 int is_bad_symlink = 0;
8444 if (!a->allow_bad_symlinks) {
8445 char target_path[PATH_MAX];
8447 target_len = readlink(ondisk_path, target_path,
8448 sizeof(target_path));
8449 if (target_len == -1) {
8450 err = got_error_from_errno2("readlink",
8454 err = is_bad_symlink_target(&is_bad_symlink,
8455 target_path, target_len, ondisk_path,
8456 a->worktree->root_path);
8459 if (is_bad_symlink) {
8460 err = got_error_path(ondisk_path,
8461 GOT_ERR_BAD_SYMLINK);
8466 got_fileindex_entry_staged_filetype_set(ie,
8467 GOT_FILEIDX_MODE_BAD_SYMLINK);
8469 got_fileindex_entry_staged_filetype_set(ie,
8470 GOT_FILEIDX_MODE_SYMLINK);
8472 got_fileindex_entry_staged_filetype_set(ie,
8473 GOT_FILEIDX_MODE_REGULAR_FILE);
8475 a->staged_something = 1;
8476 if (a->status_cb == NULL)
8478 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
8479 get_staged_status(ie), relpath, blob_id,
8480 new_staged_blob_id, NULL, dirfd, de_name);
8484 * When staging the reverse of the staged diff,
8485 * implicitly unstage the file.
8487 if (memcmp(ie->staged_blob_sha1, ie->blob_sha1,
8488 sizeof(ie->blob_sha1)) == 0) {
8489 got_fileindex_entry_stage_set(ie,
8490 GOT_FILEIDX_STAGE_NONE);
8493 case GOT_STATUS_DELETE:
8494 if (staged_status == GOT_STATUS_DELETE)
8497 int choice = GOT_PATCH_CHOICE_NONE;
8498 err = (*a->patch_cb)(&choice, a->patch_arg, status,
8499 ie->path, NULL, 1, 1);
8502 if (choice == GOT_PATCH_CHOICE_NO)
8504 if (choice != GOT_PATCH_CHOICE_YES) {
8505 err = got_error(GOT_ERR_PATCH_CHOICE);
8509 stage = GOT_FILEIDX_STAGE_DELETE;
8510 got_fileindex_entry_stage_set(ie, stage);
8511 a->staged_something = 1;
8512 if (a->status_cb == NULL)
8514 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
8515 get_staged_status(ie), relpath, NULL, NULL, NULL, dirfd,
8518 case GOT_STATUS_NO_CHANGE:
8520 case GOT_STATUS_CONFLICT:
8521 err = got_error_path(relpath, GOT_ERR_STAGE_CONFLICT);
8523 case GOT_STATUS_NONEXISTENT:
8524 err = got_error_set_errno(ENOENT, relpath);
8527 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
8531 if (path_content && unlink(path_content) == -1 && err == NULL)
8532 err = got_error_from_errno2("unlink", path_content);
8535 free(new_staged_blob_id);
8539 const struct got_error *
8540 got_worktree_stage(struct got_worktree *worktree,
8541 struct got_pathlist_head *paths,
8542 got_worktree_status_cb status_cb, void *status_arg,
8543 got_worktree_patch_cb patch_cb, void *patch_arg,
8544 int allow_bad_symlinks, struct got_repository *repo)
8546 const struct got_error *err = NULL, *sync_err, *unlockerr;
8547 struct got_pathlist_entry *pe;
8548 struct got_fileindex *fileindex = NULL;
8549 char *fileindex_path = NULL;
8550 struct got_reference *head_ref = NULL;
8551 struct got_object_id *head_commit_id = NULL;
8552 struct check_stage_ok_arg oka;
8553 struct stage_path_arg spa;
8555 err = lock_worktree(worktree, LOCK_EX);
8559 err = got_ref_open(&head_ref, repo,
8560 got_worktree_get_head_ref_name(worktree), 0);
8563 err = got_ref_resolve(&head_commit_id, repo, head_ref);
8566 err = open_fileindex(&fileindex, &fileindex_path, worktree);
8570 /* Check pre-conditions before staging anything. */
8571 oka.head_commit_id = head_commit_id;
8572 oka.worktree = worktree;
8573 oka.fileindex = fileindex;
8575 oka.have_changes = 0;
8576 TAILQ_FOREACH(pe, paths, entry) {
8577 err = worktree_status(worktree, pe->path, fileindex, repo,
8578 check_stage_ok, &oka, NULL, NULL, 1, 0);
8582 if (!oka.have_changes) {
8583 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
8587 spa.worktree = worktree;
8588 spa.fileindex = fileindex;
8590 spa.patch_cb = patch_cb;
8591 spa.patch_arg = patch_arg;
8592 spa.status_cb = status_cb;
8593 spa.status_arg = status_arg;
8594 spa.staged_something = 0;
8595 spa.allow_bad_symlinks = allow_bad_symlinks;
8596 TAILQ_FOREACH(pe, paths, entry) {
8597 err = worktree_status(worktree, pe->path, fileindex, repo,
8598 stage_path, &spa, NULL, NULL, 1, 0);
8602 if (!spa.staged_something) {
8603 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
8607 sync_err = sync_fileindex(fileindex, fileindex_path);
8608 if (sync_err && err == NULL)
8612 got_ref_close(head_ref);
8613 free(head_commit_id);
8614 free(fileindex_path);
8616 got_fileindex_free(fileindex);
8617 unlockerr = lock_worktree(worktree, LOCK_SH);
8618 if (unlockerr && err == NULL)
8623 struct unstage_path_arg {
8624 struct got_worktree *worktree;
8625 struct got_fileindex *fileindex;
8626 struct got_repository *repo;
8627 got_worktree_checkout_cb progress_cb;
8629 got_worktree_patch_cb patch_cb;
8633 static const struct got_error *
8634 create_unstaged_content(char **path_unstaged_content,
8635 char **path_new_staged_content, struct got_object_id *blob_id,
8636 struct got_object_id *staged_blob_id, const char *relpath,
8637 struct got_repository *repo,
8638 got_worktree_patch_cb patch_cb, void *patch_arg)
8640 const struct got_error *err, *free_err;
8641 struct got_blob_object *blob = NULL, *staged_blob = NULL;
8642 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL, *rejectfile = NULL;
8643 char *path1 = NULL, *path2 = NULL, *label1 = NULL;
8644 struct got_diffreg_result *diffreg_result = NULL;
8645 int line_cur1 = 1, line_cur2 = 1, n = 0, nchunks_used = 0;
8646 int have_content = 0, have_rejected_content = 0, i = 0, nchanges = 0;
8647 int fd1 = -1, fd2 = -1;
8649 *path_unstaged_content = NULL;
8650 *path_new_staged_content = NULL;
8652 err = got_object_id_str(&label1, blob_id);
8656 fd1 = got_opentempfd();
8658 err = got_error_from_errno("got_opentempfd");
8661 fd2 = got_opentempfd();
8663 err = got_error_from_errno("got_opentempfd");
8667 err = got_object_open_as_blob(&blob, repo, blob_id, 8192, fd1);
8671 err = got_opentemp_named(&path1, &f1, "got-unstage-blob-base", "");
8675 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
8679 err = got_object_open_as_blob(&staged_blob, repo, staged_blob_id, 8192,
8684 err = got_opentemp_named(&path2, &f2, "got-unstage-blob-staged", "");
8688 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f2, staged_blob);
8692 err = got_diff_files(&diffreg_result, f1, 1, label1, f2, 1,
8693 path2, 3, 0, 1, NULL, GOT_DIFF_ALGORITHM_MYERS);
8697 err = got_opentemp_named(path_unstaged_content, &outfile,
8698 "got-unstaged-content", "");
8701 err = got_opentemp_named(path_new_staged_content, &rejectfile,
8702 "got-new-staged-content", "");
8706 if (fseek(f1, 0L, SEEK_SET) == -1) {
8707 err = got_ferror(f1, GOT_ERR_IO);
8710 if (fseek(f2, 0L, SEEK_SET) == -1) {
8711 err = got_ferror(f2, GOT_ERR_IO);
8714 /* Count the number of actual changes in the diff result. */
8715 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
8716 struct diff_chunk_context cc = {};
8717 diff_chunk_context_load_change(&cc, &nchunks_used,
8718 diffreg_result->result, n, 0);
8721 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
8723 err = apply_or_reject_change(&choice, &nchunks_used,
8724 diffreg_result->result, n, relpath, f1, f2,
8725 &line_cur1, &line_cur2,
8726 outfile, rejectfile, ++i, nchanges, patch_cb, patch_arg);
8729 if (choice == GOT_PATCH_CHOICE_YES)
8732 have_rejected_content = 1;
8733 if (choice == GOT_PATCH_CHOICE_QUIT)
8736 if (have_content || have_rejected_content)
8737 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
8738 outfile, rejectfile);
8741 if (fd1 != -1 && close(fd1) == -1 && err == NULL)
8742 err = got_error_from_errno("close");
8744 got_object_blob_close(blob);
8745 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
8746 err = got_error_from_errno("close");
8748 got_object_blob_close(staged_blob);
8749 free_err = got_diffreg_result_free(diffreg_result);
8750 if (free_err && err == NULL)
8752 if (f1 && fclose(f1) == EOF && err == NULL)
8753 err = got_error_from_errno2("fclose", path1);
8754 if (f2 && fclose(f2) == EOF && err == NULL)
8755 err = got_error_from_errno2("fclose", path2);
8756 if (outfile && fclose(outfile) == EOF && err == NULL)
8757 err = got_error_from_errno2("fclose", *path_unstaged_content);
8758 if (rejectfile && fclose(rejectfile) == EOF && err == NULL)
8759 err = got_error_from_errno2("fclose", *path_new_staged_content);
8760 if (path1 && unlink(path1) == -1 && err == NULL)
8761 err = got_error_from_errno2("unlink", path1);
8762 if (path2 && unlink(path2) == -1 && err == NULL)
8763 err = got_error_from_errno2("unlink", path2);
8764 if (err || !have_content) {
8765 if (*path_unstaged_content &&
8766 unlink(*path_unstaged_content) == -1 && err == NULL)
8767 err = got_error_from_errno2("unlink",
8768 *path_unstaged_content);
8769 free(*path_unstaged_content);
8770 *path_unstaged_content = NULL;
8772 if (err || !have_content || !have_rejected_content) {
8773 if (*path_new_staged_content &&
8774 unlink(*path_new_staged_content) == -1 && err == NULL)
8775 err = got_error_from_errno2("unlink",
8776 *path_new_staged_content);
8777 free(*path_new_staged_content);
8778 *path_new_staged_content = NULL;
8785 static const struct got_error *
8786 unstage_hunks(struct got_object_id *staged_blob_id,
8787 struct got_blob_object *blob_base,
8788 struct got_object_id *blob_id, struct got_fileindex_entry *ie,
8789 const char *ondisk_path, const char *label_orig,
8790 struct got_worktree *worktree, struct got_repository *repo,
8791 got_worktree_patch_cb patch_cb, void *patch_arg,
8792 got_worktree_checkout_cb progress_cb, void *progress_arg)
8794 const struct got_error *err = NULL;
8795 char *path_unstaged_content = NULL;
8796 char *path_new_staged_content = NULL;
8797 char *parent = NULL, *base_path = NULL;
8798 char *blob_base_path = NULL;
8799 struct got_object_id *new_staged_blob_id = NULL;
8800 FILE *f = NULL, *f_base = NULL, *f_deriv2 = NULL;
8803 err = create_unstaged_content(&path_unstaged_content,
8804 &path_new_staged_content, blob_id, staged_blob_id,
8805 ie->path, repo, patch_cb, patch_arg);
8809 if (path_unstaged_content == NULL)
8812 if (path_new_staged_content) {
8813 err = got_object_blob_create(&new_staged_blob_id,
8814 path_new_staged_content, repo);
8819 f = fopen(path_unstaged_content, "re");
8821 err = got_error_from_errno2("fopen",
8822 path_unstaged_content);
8825 if (fstat(fileno(f), &sb) == -1) {
8826 err = got_error_from_errno2("fstat", path_unstaged_content);
8829 if (got_fileindex_entry_staged_filetype_get(ie) ==
8830 GOT_FILEIDX_MODE_SYMLINK && sb.st_size < PATH_MAX) {
8831 char link_target[PATH_MAX];
8833 r = fread(link_target, 1, sizeof(link_target), f);
8834 if (r == 0 && ferror(f)) {
8835 err = got_error_from_errno("fread");
8838 if (r >= sizeof(link_target)) { /* should not happen */
8839 err = got_error(GOT_ERR_NO_SPACE);
8842 link_target[r] = '\0';
8843 err = merge_symlink(worktree, blob_base,
8844 ondisk_path, ie->path, label_orig, link_target,
8845 worktree->base_commit_id, repo, progress_cb,
8848 int local_changes_subsumed;
8850 err = got_path_dirname(&parent, ondisk_path);
8854 if (asprintf(&base_path, "%s/got-unstage-blob-orig",
8856 err = got_error_from_errno("asprintf");
8861 err = got_opentemp_named(&blob_base_path, &f_base,
8865 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_base,
8871 * In order the run a 3-way merge with a symlink we copy the symlink's
8872 * target path into a temporary file and use that file with diff3.
8874 if (S_ISLNK(got_fileindex_perms_to_st(ie))) {
8875 err = dump_symlink_target_path_to_file(&f_deriv2,
8881 fd = open(ondisk_path,
8882 O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
8884 err = got_error_from_errno2("open", ondisk_path);
8887 f_deriv2 = fdopen(fd, "r");
8888 if (f_deriv2 == NULL) {
8889 err = got_error_from_errno2("fdopen", ondisk_path);
8895 err = merge_file(&local_changes_subsumed, worktree,
8896 f_base, f, f_deriv2, ondisk_path, ie->path,
8897 got_fileindex_perms_to_st(ie),
8898 label_orig, "unstaged", NULL, GOT_DIFF_ALGORITHM_MYERS,
8899 repo, progress_cb, progress_arg);
8904 if (new_staged_blob_id) {
8905 memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1,
8906 SHA1_DIGEST_LENGTH);
8908 got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE);
8909 got_fileindex_entry_staged_filetype_set(ie, 0);
8912 free(new_staged_blob_id);
8913 if (path_unstaged_content &&
8914 unlink(path_unstaged_content) == -1 && err == NULL)
8915 err = got_error_from_errno2("unlink", path_unstaged_content);
8916 if (path_new_staged_content &&
8917 unlink(path_new_staged_content) == -1 && err == NULL)
8918 err = got_error_from_errno2("unlink", path_new_staged_content);
8919 if (blob_base_path && unlink(blob_base_path) == -1 && err == NULL)
8920 err = got_error_from_errno2("unlink", blob_base_path);
8921 if (f_base && fclose(f_base) == EOF && err == NULL)
8922 err = got_error_from_errno2("fclose", path_unstaged_content);
8923 if (f && fclose(f) == EOF && err == NULL)
8924 err = got_error_from_errno2("fclose", path_unstaged_content);
8925 if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
8926 err = got_error_from_errno2("fclose", ondisk_path);
8927 free(path_unstaged_content);
8928 free(path_new_staged_content);
8929 free(blob_base_path);
8935 static const struct got_error *
8936 unstage_path(void *arg, unsigned char status,
8937 unsigned char staged_status, const char *relpath,
8938 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
8939 struct got_object_id *commit_id, int dirfd, const char *de_name)
8941 const struct got_error *err = NULL;
8942 struct unstage_path_arg *a = arg;
8943 struct got_fileindex_entry *ie;
8944 struct got_blob_object *blob_base = NULL, *blob_staged = NULL;
8945 char *ondisk_path = NULL;
8946 char *id_str = NULL, *label_orig = NULL;
8947 int local_changes_subsumed;
8949 int fd1 = -1, fd2 = -1;
8951 if (staged_status != GOT_STATUS_ADD &&
8952 staged_status != GOT_STATUS_MODIFY &&
8953 staged_status != GOT_STATUS_DELETE)
8956 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
8958 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
8960 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, relpath)
8962 return got_error_from_errno("asprintf");
8964 err = got_object_id_str(&id_str,
8965 commit_id ? commit_id : a->worktree->base_commit_id);
8968 if (asprintf(&label_orig, "%s: commit %s", GOT_MERGE_LABEL_BASE,
8970 err = got_error_from_errno("asprintf");
8974 fd1 = got_opentempfd();
8976 err = got_error_from_errno("got_opentempfd");
8979 fd2 = got_opentempfd();
8981 err = got_error_from_errno("got_opentempfd");
8985 switch (staged_status) {
8986 case GOT_STATUS_MODIFY:
8987 err = got_object_open_as_blob(&blob_base, a->repo,
8988 blob_id, 8192, fd1);
8992 case GOT_STATUS_ADD:
8994 if (staged_status == GOT_STATUS_ADD) {
8995 int choice = GOT_PATCH_CHOICE_NONE;
8996 err = (*a->patch_cb)(&choice, a->patch_arg,
8997 staged_status, ie->path, NULL, 1, 1);
9000 if (choice != GOT_PATCH_CHOICE_YES)
9003 err = unstage_hunks(staged_blob_id,
9004 blob_base, blob_id, ie, ondisk_path,
9005 label_orig, a->worktree, a->repo,
9006 a->patch_cb, a->patch_arg,
9007 a->progress_cb, a->progress_arg);
9008 break; /* Done with this file. */
9011 err = got_object_open_as_blob(&blob_staged, a->repo,
9012 staged_blob_id, 8192, fd2);
9015 switch (got_fileindex_entry_staged_filetype_get(ie)) {
9016 case GOT_FILEIDX_MODE_BAD_SYMLINK:
9017 case GOT_FILEIDX_MODE_REGULAR_FILE:
9018 err = merge_blob(&local_changes_subsumed, a->worktree,
9019 blob_base, ondisk_path, relpath,
9020 got_fileindex_perms_to_st(ie), label_orig,
9021 blob_staged, commit_id ? commit_id :
9022 a->worktree->base_commit_id, a->repo,
9023 a->progress_cb, a->progress_arg);
9025 case GOT_FILEIDX_MODE_SYMLINK:
9026 if (S_ISLNK(got_fileindex_perms_to_st(ie))) {
9027 char *staged_target;
9028 err = got_object_blob_read_to_str(
9029 &staged_target, blob_staged);
9032 err = merge_symlink(a->worktree, blob_base,
9033 ondisk_path, relpath, label_orig,
9034 staged_target, commit_id ? commit_id :
9035 a->worktree->base_commit_id,
9036 a->repo, a->progress_cb, a->progress_arg);
9037 free(staged_target);
9039 err = merge_blob(&local_changes_subsumed,
9040 a->worktree, blob_base, ondisk_path,
9041 relpath, got_fileindex_perms_to_st(ie),
9042 label_orig, blob_staged,
9043 commit_id ? commit_id :
9044 a->worktree->base_commit_id, a->repo,
9045 a->progress_cb, a->progress_arg);
9049 err = got_error_path(relpath, GOT_ERR_BAD_FILETYPE);
9053 got_fileindex_entry_stage_set(ie,
9054 GOT_FILEIDX_STAGE_NONE);
9055 got_fileindex_entry_staged_filetype_set(ie, 0);
9058 case GOT_STATUS_DELETE:
9060 int choice = GOT_PATCH_CHOICE_NONE;
9061 err = (*a->patch_cb)(&choice, a->patch_arg,
9062 staged_status, ie->path, NULL, 1, 1);
9065 if (choice == GOT_PATCH_CHOICE_NO)
9067 if (choice != GOT_PATCH_CHOICE_YES) {
9068 err = got_error(GOT_ERR_PATCH_CHOICE);
9072 got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE);
9073 got_fileindex_entry_staged_filetype_set(ie, 0);
9074 err = get_file_status(&status, &sb, ie, ondisk_path,
9075 dirfd, de_name, a->repo);
9078 err = (*a->progress_cb)(a->progress_arg, status, relpath);
9083 if (fd1 != -1 && close(fd1) == -1 && err == NULL)
9084 err = got_error_from_errno("close");
9086 got_object_blob_close(blob_base);
9087 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
9088 err = got_error_from_errno("close");
9090 got_object_blob_close(blob_staged);
9096 const struct got_error *
9097 got_worktree_unstage(struct got_worktree *worktree,
9098 struct got_pathlist_head *paths,
9099 got_worktree_checkout_cb progress_cb, void *progress_arg,
9100 got_worktree_patch_cb patch_cb, void *patch_arg,
9101 struct got_repository *repo)
9103 const struct got_error *err = NULL, *sync_err, *unlockerr;
9104 struct got_pathlist_entry *pe;
9105 struct got_fileindex *fileindex = NULL;
9106 char *fileindex_path = NULL;
9107 struct unstage_path_arg upa;
9109 err = lock_worktree(worktree, LOCK_EX);
9113 err = open_fileindex(&fileindex, &fileindex_path, worktree);
9117 upa.worktree = worktree;
9118 upa.fileindex = fileindex;
9120 upa.progress_cb = progress_cb;
9121 upa.progress_arg = progress_arg;
9122 upa.patch_cb = patch_cb;
9123 upa.patch_arg = patch_arg;
9124 TAILQ_FOREACH(pe, paths, entry) {
9125 err = worktree_status(worktree, pe->path, fileindex, repo,
9126 unstage_path, &upa, NULL, NULL, 1, 0);
9131 sync_err = sync_fileindex(fileindex, fileindex_path);
9132 if (sync_err && err == NULL)
9135 free(fileindex_path);
9137 got_fileindex_free(fileindex);
9138 unlockerr = lock_worktree(worktree, LOCK_SH);
9139 if (unlockerr && err == NULL)
9144 struct report_file_info_arg {
9145 struct got_worktree *worktree;
9146 got_worktree_path_info_cb info_cb;
9148 struct got_pathlist_head *paths;
9149 got_cancel_cb cancel_cb;
9153 static const struct got_error *
9154 report_file_info(void *arg, struct got_fileindex_entry *ie)
9156 struct report_file_info_arg *a = arg;
9157 struct got_pathlist_entry *pe;
9158 struct got_object_id blob_id, staged_blob_id, commit_id;
9159 struct got_object_id *blob_idp = NULL, *staged_blob_idp = NULL;
9160 struct got_object_id *commit_idp = NULL;
9163 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
9164 return got_error(GOT_ERR_CANCELLED);
9166 TAILQ_FOREACH(pe, a->paths, entry) {
9167 if (pe->path_len == 0 || strcmp(pe->path, ie->path) == 0 ||
9168 got_path_is_child(ie->path, pe->path, pe->path_len))
9171 if (pe == NULL) /* not found */
9174 if (got_fileindex_entry_has_blob(ie))
9175 blob_idp = got_fileindex_entry_get_blob_id(&blob_id, ie);
9176 stage = got_fileindex_entry_stage_get(ie);
9177 if (stage == GOT_FILEIDX_STAGE_MODIFY ||
9178 stage == GOT_FILEIDX_STAGE_ADD) {
9179 staged_blob_idp = got_fileindex_entry_get_staged_blob_id(
9180 &staged_blob_id, ie);
9183 if (got_fileindex_entry_has_commit(ie))
9184 commit_idp = got_fileindex_entry_get_commit_id(&commit_id, ie);
9186 return a->info_cb(a->info_arg, ie->path, got_fileindex_perms_to_st(ie),
9187 (time_t)ie->mtime_sec, blob_idp, staged_blob_idp, commit_idp);
9190 const struct got_error *
9191 got_worktree_path_info(struct got_worktree *worktree,
9192 struct got_pathlist_head *paths,
9193 got_worktree_path_info_cb info_cb, void *info_arg,
9194 got_cancel_cb cancel_cb, void *cancel_arg)
9197 const struct got_error *err = NULL, *unlockerr;
9198 struct got_fileindex *fileindex = NULL;
9199 char *fileindex_path = NULL;
9200 struct report_file_info_arg arg;
9202 err = lock_worktree(worktree, LOCK_SH);
9206 err = open_fileindex(&fileindex, &fileindex_path, worktree);
9210 arg.worktree = worktree;
9211 arg.info_cb = info_cb;
9212 arg.info_arg = info_arg;
9214 arg.cancel_cb = cancel_cb;
9215 arg.cancel_arg = cancel_arg;
9216 err = got_fileindex_for_each_entry_safe(fileindex, report_file_info,
9219 free(fileindex_path);
9221 got_fileindex_free(fileindex);
9222 unlockerr = lock_worktree(worktree, LOCK_UN);
9223 if (unlockerr && err == NULL)
9228 static const struct got_error *
9229 patch_check_path(const char *p, char **path, unsigned char *status,
9230 unsigned char *staged_status, struct got_fileindex *fileindex,
9231 struct got_worktree *worktree, struct got_repository *repo)
9233 const struct got_error *err;
9234 struct got_fileindex_entry *ie;
9236 char *ondisk_path = NULL;
9238 err = got_worktree_resolve_path(path, worktree, p);
9242 if (asprintf(&ondisk_path, "%s%s%s", worktree->root_path,
9243 *path[0] ? "/" : "", *path) == -1)
9244 return got_error_from_errno("asprintf");
9246 ie = got_fileindex_entry_get(fileindex, *path, strlen(*path));
9248 *staged_status = get_staged_status(ie);
9249 err = get_file_status(status, &sb, ie, ondisk_path, -1, NULL,
9254 *staged_status = GOT_STATUS_NO_CHANGE;
9255 *status = GOT_STATUS_UNVERSIONED;
9256 if (lstat(ondisk_path, &sb) == -1) {
9257 if (errno != ENOENT) {
9258 err = got_error_from_errno2("lstat",
9262 *status = GOT_STATUS_NONEXISTENT;
9271 static const struct got_error *
9272 patch_can_rm(const char *path, unsigned char status,
9273 unsigned char staged_status)
9275 if (status == GOT_STATUS_NONEXISTENT)
9276 return got_error_set_errno(ENOENT, path);
9277 if (status != GOT_STATUS_NO_CHANGE &&
9278 status != GOT_STATUS_ADD &&
9279 status != GOT_STATUS_MODIFY &&
9280 status != GOT_STATUS_MODE_CHANGE)
9281 return got_error_path(path, GOT_ERR_FILE_STATUS);
9282 if (staged_status == GOT_STATUS_DELETE)
9283 return got_error_path(path, GOT_ERR_FILE_STATUS);
9287 static const struct got_error *
9288 patch_can_add(const char *path, unsigned char status)
9290 if (status != GOT_STATUS_NONEXISTENT)
9291 return got_error_path(path, GOT_ERR_FILE_STATUS);
9295 static const struct got_error *
9296 patch_can_edit(const char *path, unsigned char status,
9297 unsigned char staged_status)
9299 if (status == GOT_STATUS_NONEXISTENT)
9300 return got_error_set_errno(ENOENT, path);
9301 if (status != GOT_STATUS_NO_CHANGE &&
9302 status != GOT_STATUS_ADD &&
9303 status != GOT_STATUS_MODIFY)
9304 return got_error_path(path, GOT_ERR_FILE_STATUS);
9305 if (staged_status == GOT_STATUS_DELETE)
9306 return got_error_path(path, GOT_ERR_FILE_STATUS);
9310 const struct got_error *
9311 got_worktree_patch_prepare(struct got_fileindex **fileindex,
9312 char **fileindex_path, struct got_worktree *worktree)
9314 return open_fileindex(fileindex, fileindex_path, worktree);
9317 const struct got_error *
9318 got_worktree_patch_check_path(const char *old, const char *new,
9319 char **oldpath, char **newpath, struct got_worktree *worktree,
9320 struct got_repository *repo, struct got_fileindex *fileindex)
9322 const struct got_error *err = NULL;
9323 int file_renamed = 0;
9324 unsigned char status_old, staged_status_old;
9325 unsigned char status_new, staged_status_new;
9330 err = patch_check_path(old != NULL ? old : new, oldpath,
9331 &status_old, &staged_status_old, fileindex, worktree, repo);
9335 err = patch_check_path(new != NULL ? new : old, newpath,
9336 &status_new, &staged_status_new, fileindex, worktree, repo);
9340 if (old != NULL && new != NULL && strcmp(old, new) != 0)
9343 if (old != NULL && new == NULL)
9344 err = patch_can_rm(*oldpath, status_old, staged_status_old);
9345 else if (file_renamed) {
9346 err = patch_can_rm(*oldpath, status_old, staged_status_old);
9348 err = patch_can_add(*newpath, status_new);
9349 } else if (old == NULL)
9350 err = patch_can_add(*newpath, status_new);
9352 err = patch_can_edit(*newpath, status_new, staged_status_new);
9364 const struct got_error *
9365 got_worktree_patch_schedule_add(const char *path, struct got_repository *repo,
9366 struct got_worktree *worktree, struct got_fileindex *fileindex,
9367 got_worktree_checkout_cb progress_cb, void *progress_arg)
9369 struct schedule_addition_args saa;
9371 memset(&saa, 0, sizeof(saa));
9372 saa.worktree = worktree;
9373 saa.fileindex = fileindex;
9374 saa.progress_cb = progress_cb;
9375 saa.progress_arg = progress_arg;
9378 return worktree_status(worktree, path, fileindex, repo,
9379 schedule_addition, &saa, NULL, NULL, 1, 0);
9382 const struct got_error *
9383 got_worktree_patch_schedule_rm(const char *path, struct got_repository *repo,
9384 struct got_worktree *worktree, struct got_fileindex *fileindex,
9385 got_worktree_delete_cb progress_cb, void *progress_arg)
9387 struct schedule_deletion_args sda;
9389 memset(&sda, 0, sizeof(sda));
9390 sda.worktree = worktree;
9391 sda.fileindex = fileindex;
9392 sda.progress_cb = progress_cb;
9393 sda.progress_arg = progress_arg;
9395 sda.delete_local_mods = 0;
9396 sda.keep_on_disk = 0;
9397 sda.ignore_missing_paths = 0;
9398 sda.status_codes = NULL;
9400 return worktree_status(worktree, path, fileindex, repo,
9401 schedule_for_deletion, &sda, NULL, NULL, 1, 1);
9404 const struct got_error *
9405 got_worktree_patch_complete(struct got_fileindex *fileindex,
9406 const char *fileindex_path)
9408 const struct got_error *err = NULL;
9410 err = sync_fileindex(fileindex, fileindex_path);
9411 got_fileindex_free(fileindex);