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"
60 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
63 #define GOT_MERGE_LABEL_MERGED "merged change"
64 #define GOT_MERGE_LABEL_BASE "3-way merge base"
66 static const struct got_error *
67 create_meta_file(const char *path_got, const char *name, const char *content)
69 const struct got_error *err = NULL;
72 if (asprintf(&path, "%s/%s", path_got, name) == -1)
73 return got_error_from_errno("asprintf");
75 err = got_path_create_file(path, content);
80 static const struct got_error *
81 update_meta_file(const char *path_got, const char *name, const char *content)
83 const struct got_error *err = NULL;
88 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
89 err = got_error_from_errno("asprintf");
94 err = got_opentemp_named(&tmppath, &tmpfile, path);
99 int len = fprintf(tmpfile, "%s\n", content);
100 if (len != strlen(content) + 1) {
101 err = got_error_from_errno2("fprintf", tmppath);
106 if (rename(tmppath, path) != 0) {
107 err = got_error_from_errno3("rename", tmppath, path);
113 if (fclose(tmpfile) != 0 && err == NULL)
114 err = got_error_from_errno2("fclose", tmppath);
119 static const struct got_error *
120 read_meta_file(char **content, const char *path_got, const char *name)
122 const struct got_error *err = NULL;
130 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
131 err = got_error_from_errno("asprintf");
136 fd = open(path, O_RDONLY | O_NOFOLLOW);
139 err = got_error_path(path, GOT_ERR_WORKTREE_META);
141 err = got_error_from_errno2("open", path);
144 if (flock(fd, LOCK_SH | LOCK_NB) == -1) {
145 err = (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
146 : got_error_from_errno2("flock", path));
150 if (fstat(fd, &sb) != 0) {
151 err = got_error_from_errno2("fstat", path);
154 *content = calloc(1, sb.st_size);
155 if (*content == NULL) {
156 err = got_error_from_errno("calloc");
160 n = read(fd, *content, sb.st_size);
161 if (n != sb.st_size) {
162 err = (n == -1 ? got_error_from_errno2("read", path) :
163 got_error_path(path, GOT_ERR_WORKTREE_META));
166 if ((*content)[sb.st_size - 1] != '\n') {
167 err = got_error_path(path, GOT_ERR_WORKTREE_META);
170 (*content)[sb.st_size - 1] = '\0';
173 if (fd != -1 && close(fd) == -1 && err == NULL)
174 err = got_error_from_errno2("close", path_got);
183 static const struct got_error *
184 write_head_ref(const char *path_got, struct got_reference *head_ref)
186 const struct got_error *err = NULL;
189 if (got_ref_is_symbolic(head_ref)) {
190 refstr = got_ref_to_str(head_ref);
192 return got_error_from_errno("got_ref_to_str");
194 refstr = strdup(got_ref_get_name(head_ref));
196 return got_error_from_errno("strdup");
198 err = update_meta_file(path_got, GOT_WORKTREE_HEAD_REF, refstr);
203 const struct got_error *
204 got_worktree_init(const char *path, struct got_reference *head_ref,
205 const char *prefix, struct got_repository *repo)
207 const struct got_error *err = NULL;
208 struct got_object_id *commit_id = NULL;
210 uint32_t uuid_status;
212 char *path_got = NULL;
213 char *formatstr = NULL;
214 char *absprefix = NULL;
215 char *basestr = NULL;
216 char *uuidstr = NULL;
218 if (strcmp(path, got_repo_get_path(repo)) == 0) {
219 err = got_error(GOT_ERR_WORKTREE_REPO);
223 err = got_ref_resolve(&commit_id, repo, head_ref);
226 err = got_object_get_type(&obj_type, repo, commit_id);
229 if (obj_type != GOT_OBJ_TYPE_COMMIT)
230 return got_error(GOT_ERR_OBJ_TYPE);
232 if (!got_path_is_absolute(prefix)) {
233 if (asprintf(&absprefix, "/%s", prefix) == -1)
234 return got_error_from_errno("asprintf");
237 /* Create top-level directory (may already exist). */
238 if (mkdir(path, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
239 err = got_error_from_errno2("mkdir", path);
243 /* Create .got directory (may already exist). */
244 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
245 err = got_error_from_errno("asprintf");
248 if (mkdir(path_got, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
249 err = got_error_from_errno2("mkdir", path_got);
253 /* Create an empty lock file. */
254 err = create_meta_file(path_got, GOT_WORKTREE_LOCK, NULL);
258 /* Create an empty file index. */
259 err = create_meta_file(path_got, GOT_WORKTREE_FILE_INDEX, NULL);
263 /* Write the HEAD reference. */
264 err = write_head_ref(path_got, head_ref);
268 /* Record our base commit. */
269 err = got_object_id_str(&basestr, commit_id);
272 err = create_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, basestr);
276 /* Store path to repository. */
277 err = create_meta_file(path_got, GOT_WORKTREE_REPOSITORY,
278 got_repo_get_path(repo));
282 /* Store in-repository path prefix. */
283 err = create_meta_file(path_got, GOT_WORKTREE_PATH_PREFIX,
284 absprefix ? absprefix : prefix);
289 uuid_create(&uuid, &uuid_status);
290 if (uuid_status != uuid_s_ok) {
291 err = got_error_uuid(uuid_status, "uuid_create");
294 uuid_to_string(&uuid, &uuidstr, &uuid_status);
295 if (uuid_status != uuid_s_ok) {
296 err = got_error_uuid(uuid_status, "uuid_to_string");
299 err = create_meta_file(path_got, GOT_WORKTREE_UUID, uuidstr);
303 /* Stamp work tree with format file. */
304 if (asprintf(&formatstr, "%d", GOT_WORKTREE_FORMAT_VERSION) == -1) {
305 err = got_error_from_errno("asprintf");
308 err = create_meta_file(path_got, GOT_WORKTREE_FORMAT, formatstr);
322 static const struct got_error *
323 open_worktree(struct got_worktree **worktree, const char *path)
325 const struct got_error *err = NULL;
327 char *formatstr = NULL;
328 char *uuidstr = NULL;
329 char *path_lock = NULL;
330 char *base_commit_id_str = NULL;
331 int version, fd = -1;
333 struct got_repository *repo = NULL;
334 uint32_t uuid_status;
338 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
339 err = got_error_from_errno("asprintf");
344 if (asprintf(&path_lock, "%s/%s", path_got, GOT_WORKTREE_LOCK) == -1) {
345 err = got_error_from_errno("asprintf");
350 fd = open(path_lock, O_RDWR | O_EXLOCK | O_NONBLOCK);
352 err = (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
353 : got_error_from_errno2("open", path_lock));
357 err = read_meta_file(&formatstr, path_got, GOT_WORKTREE_FORMAT);
361 version = strtonum(formatstr, 1, INT_MAX, &errstr);
363 err = got_error_msg(GOT_ERR_WORKTREE_META,
364 "could not parse work tree format version number");
367 if (version != GOT_WORKTREE_FORMAT_VERSION) {
368 err = got_error(GOT_ERR_WORKTREE_VERS);
372 *worktree = calloc(1, sizeof(**worktree));
373 if (*worktree == NULL) {
374 err = got_error_from_errno("calloc");
377 (*worktree)->lockfd = -1;
379 (*worktree)->root_path = strdup(path);
380 if ((*worktree)->root_path == NULL) {
381 err = got_error_from_errno("strdup");
384 err = read_meta_file(&(*worktree)->repo_path, path_got,
385 GOT_WORKTREE_REPOSITORY);
389 err = read_meta_file(&(*worktree)->path_prefix, path_got,
390 GOT_WORKTREE_PATH_PREFIX);
394 err = read_meta_file(&base_commit_id_str, path_got,
395 GOT_WORKTREE_BASE_COMMIT);
399 err = read_meta_file(&uuidstr, path_got, GOT_WORKTREE_UUID);
402 uuid_from_string(uuidstr, &(*worktree)->uuid, &uuid_status);
403 if (uuid_status != uuid_s_ok) {
404 err = got_error_uuid(uuid_status, "uuid_from_string");
408 err = got_repo_open(&repo, (*worktree)->repo_path, NULL);
412 err = got_object_resolve_id_str(&(*worktree)->base_commit_id, repo,
417 err = read_meta_file(&(*worktree)->head_ref_name, path_got,
418 GOT_WORKTREE_HEAD_REF);
421 got_repo_close(repo);
424 free(base_commit_id_str);
430 if (*worktree != NULL)
431 got_worktree_close(*worktree);
434 (*worktree)->lockfd = fd;
439 const struct got_error *
440 got_worktree_open(struct got_worktree **worktree, const char *path)
442 const struct got_error *err = NULL;
445 err = open_worktree(worktree, path);
446 if (err && !(err->code == GOT_ERR_ERRNO && errno == ENOENT))
450 path = dirname(path);
452 return got_error_from_errno2("dirname", path);
453 } while (!((path[0] == '.' || path[0] == '/') && path[1] == '\0'));
455 return got_error(GOT_ERR_NOT_WORKTREE);
458 const struct got_error *
459 got_worktree_close(struct got_worktree *worktree)
461 const struct got_error *err = NULL;
462 free(worktree->repo_path);
463 free(worktree->path_prefix);
464 free(worktree->base_commit_id);
465 free(worktree->head_ref_name);
466 if (worktree->lockfd != -1)
467 if (close(worktree->lockfd) != 0)
468 err = got_error_from_errno2("close",
469 got_worktree_get_root_path(worktree));
470 free(worktree->root_path);
476 got_worktree_get_root_path(struct got_worktree *worktree)
478 return worktree->root_path;
482 got_worktree_get_repo_path(struct got_worktree *worktree)
484 return worktree->repo_path;
488 got_worktree_get_path_prefix(struct got_worktree *worktree)
490 return worktree->path_prefix;
493 const struct got_error *
494 got_worktree_match_path_prefix(int *match, struct got_worktree *worktree,
495 const char *path_prefix)
497 char *absprefix = NULL;
499 if (!got_path_is_absolute(path_prefix)) {
500 if (asprintf(&absprefix, "/%s", path_prefix) == -1)
501 return got_error_from_errno("asprintf");
503 *match = (strcmp(absprefix ? absprefix : path_prefix,
504 worktree->path_prefix) == 0);
510 got_worktree_get_head_ref_name(struct got_worktree *worktree)
512 return worktree->head_ref_name;
515 const struct got_error *
516 got_worktree_set_head_ref(struct got_worktree *worktree,
517 struct got_reference *head_ref)
519 const struct got_error *err = NULL;
520 char *path_got = NULL, *head_ref_name = NULL;
522 if (asprintf(&path_got, "%s/%s", worktree->root_path,
523 GOT_WORKTREE_GOT_DIR) == -1) {
524 err = got_error_from_errno("asprintf");
529 head_ref_name = strdup(got_ref_get_name(head_ref));
530 if (head_ref_name == NULL) {
531 err = got_error_from_errno("strdup");
535 err = write_head_ref(path_got, head_ref);
539 free(worktree->head_ref_name);
540 worktree->head_ref_name = head_ref_name;
548 struct got_object_id *
549 got_worktree_get_base_commit_id(struct got_worktree *worktree)
551 return worktree->base_commit_id;
554 const struct got_error *
555 got_worktree_set_base_commit_id(struct got_worktree *worktree,
556 struct got_repository *repo, struct got_object_id *commit_id)
558 const struct got_error *err;
559 struct got_object *obj = NULL;
561 char *path_got = NULL;
563 if (asprintf(&path_got, "%s/%s", worktree->root_path,
564 GOT_WORKTREE_GOT_DIR) == -1) {
565 err = got_error_from_errno("asprintf");
570 err = got_object_open(&obj, repo, commit_id);
574 if (obj->type != GOT_OBJ_TYPE_COMMIT) {
575 err = got_error(GOT_ERR_OBJ_TYPE);
579 /* Record our base commit. */
580 err = got_object_id_str(&id_str, commit_id);
583 err = update_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, id_str);
587 free(worktree->base_commit_id);
588 worktree->base_commit_id = got_object_id_dup(commit_id);
589 if (worktree->base_commit_id == NULL) {
590 err = got_error_from_errno("got_object_id_dup");
595 got_object_close(obj);
601 static const struct got_error *
602 lock_worktree(struct got_worktree *worktree, int operation)
604 if (flock(worktree->lockfd, operation | LOCK_NB) == -1)
605 return (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
606 : got_error_from_errno2("flock",
607 got_worktree_get_root_path(worktree)));
611 static const struct got_error *
612 add_dir_on_disk(struct got_worktree *worktree, const char *path)
614 const struct got_error *err = NULL;
617 if (asprintf(&abspath, "%s/%s", worktree->root_path, path) == -1)
618 return got_error_from_errno("asprintf");
620 err = got_path_mkdir(abspath);
621 if (err && err->code == GOT_ERR_ERRNO && errno == EEXIST) {
624 if (lstat(abspath, &sb) == -1) {
625 err = got_error_from_errno2("lstat", abspath);
626 } else if (!S_ISDIR(sb.st_mode)) {
627 /* TODO directory is obstructed; do something */
628 err = got_error_path(abspath, GOT_ERR_FILE_OBSTRUCTED);
635 static const struct got_error *
636 check_file_contents_equal(int *same, FILE *f1, FILE *f2)
638 const struct got_error *err = NULL;
641 size_t flen1 = 0, flen2 = 0;
646 flen1 = fread(fbuf1, 1, sizeof(fbuf1), f1);
647 if (flen1 == 0 && ferror(f1)) {
648 err = got_error_from_errno("fread");
651 flen2 = fread(fbuf2, 1, sizeof(fbuf2), f2);
652 if (flen2 == 0 && ferror(f2)) {
653 err = got_error_from_errno("fread");
660 } else if (flen2 == 0) {
664 } else if (flen1 == flen2) {
665 if (memcmp(fbuf1, fbuf2, flen2) != 0) {
678 static const struct got_error *
679 check_files_equal(int *same, const char *f1_path, const char *f2_path)
681 const struct got_error *err = NULL;
684 FILE *f1 = NULL, *f2 = NULL;
688 if (lstat(f1_path, &sb) != 0) {
689 err = got_error_from_errno2("lstat", f1_path);
694 if (lstat(f2_path, &sb) != 0) {
695 err = got_error_from_errno2("lstat", f2_path);
700 if (size1 != size2) {
705 f1 = fopen(f1_path, "r");
707 return got_error_from_errno2("fopen", f1_path);
709 f2 = fopen(f2_path, "r");
711 err = got_error_from_errno2("fopen", f2_path);
715 err = check_file_contents_equal(same, f1, f2);
717 if (f1 && fclose(f1) != 0 && err == NULL)
718 err = got_error_from_errno("fclose");
719 if (f2 && fclose(f2) != 0 && err == NULL)
720 err = got_error_from_errno("fclose");
726 * Perform a 3-way merge where blob_orig acts as the common ancestor,
727 * the file at deriv_path acts as the first derived version, and the
728 * file on disk acts as the second derived version.
730 static const struct got_error *
731 merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
732 struct got_blob_object *blob_orig, const char *ondisk_path,
733 const char *path, uint16_t st_mode, const char *deriv_path,
734 const char *label_orig, const char *label_deriv,
735 struct got_repository *repo,
736 got_worktree_checkout_cb progress_cb, void *progress_arg)
738 const struct got_error *err = NULL;
741 char *blob_orig_path = NULL;
742 char *merged_path = NULL, *base_path = NULL;
746 *local_changes_subsumed = 0;
748 parent = dirname(ondisk_path);
750 return got_error_from_errno2("dirname", ondisk_path);
752 if (asprintf(&base_path, "%s/got-merged", parent) == -1)
753 return got_error_from_errno("asprintf");
755 err = got_opentemp_named_fd(&merged_path, &merged_fd, base_path);
760 if (asprintf(&base_path, "%s/got-merge-blob-orig", parent) == -1) {
761 err = got_error_from_errno("asprintf");
766 err = got_opentemp_named(&blob_orig_path, &f_orig, base_path);
770 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_orig,
776 * If the file has no blob, this is an "add vs add" conflict,
777 * and we simply use an empty ancestor file to make both files
778 * appear in the merged result in their entirety.
782 err = got_merge_diff3(&overlapcnt, merged_fd, deriv_path,
783 blob_orig_path, ondisk_path, label_deriv, label_orig, NULL);
787 err = (*progress_cb)(progress_arg,
788 overlapcnt > 0 ? GOT_STATUS_CONFLICT : GOT_STATUS_MERGE, path);
792 if (fsync(merged_fd) != 0) {
793 err = got_error_from_errno("fsync");
797 /* Check if a clean merge has subsumed all local changes. */
798 if (overlapcnt == 0) {
799 err = check_files_equal(local_changes_subsumed, deriv_path,
805 if (fchmod(merged_fd, st_mode) != 0) {
806 err = got_error_from_errno2("fchmod", merged_path);
810 if (rename(merged_path, ondisk_path) != 0) {
811 err = got_error_from_errno3("rename", merged_path,
820 if (merged_fd != -1 && close(merged_fd) != 0 && err == NULL)
821 err = got_error_from_errno("close");
822 if (f_orig && fclose(f_orig) != 0 && err == NULL)
823 err = got_error_from_errno("fclose");
826 if (blob_orig_path) {
827 unlink(blob_orig_path);
828 free(blob_orig_path);
834 * Perform a 3-way merge where blob_orig acts as the common ancestor,
835 * blob_deriv acts as the first derived version, and the file on disk
836 * acts as the second derived version.
838 static const struct got_error *
839 merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
840 struct got_blob_object *blob_orig, const char *ondisk_path,
841 const char *path, uint16_t st_mode, const char *label_orig,
842 struct got_blob_object *blob_deriv,
843 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
844 got_worktree_checkout_cb progress_cb, void *progress_arg)
846 const struct got_error *err = NULL;
847 FILE *f_deriv = NULL;
848 char *blob_deriv_path = NULL, *base_path = NULL, *id_str = NULL;
849 char *label_deriv = NULL, *parent;
851 *local_changes_subsumed = 0;
853 parent = dirname(ondisk_path);
855 return got_error_from_errno2("dirname", ondisk_path);
858 if (asprintf(&base_path, "%s/got-merge-blob-deriv", parent) == -1) {
859 err = got_error_from_errno("asprintf");
864 err = got_opentemp_named(&blob_deriv_path, &f_deriv, base_path);
867 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_deriv,
872 err = got_object_id_str(&id_str, deriv_base_commit_id);
875 if (asprintf(&label_deriv, "%s: commit %s",
876 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
877 err = got_error_from_errno("asprintf");
881 err = merge_file(local_changes_subsumed, worktree, blob_orig,
882 ondisk_path, path, st_mode, blob_deriv_path, label_orig,
883 label_deriv, repo, progress_cb, progress_arg);
885 if (f_deriv && fclose(f_deriv) != 0 && err == NULL)
886 err = got_error_from_errno("fclose");
888 if (blob_deriv_path) {
889 unlink(blob_deriv_path);
890 free(blob_deriv_path);
897 static const struct got_error *
898 create_fileindex_entry(struct got_fileindex *fileindex,
899 struct got_object_id *base_commit_id, const char *ondisk_path,
900 const char *path, struct got_object_id *blob_id)
902 const struct got_error *err = NULL;
903 struct got_fileindex_entry *new_ie;
905 err = got_fileindex_entry_alloc(&new_ie, path);
909 err = got_fileindex_entry_update(new_ie, ondisk_path,
910 blob_id->sha1, base_commit_id->sha1, 1);
914 err = got_fileindex_entry_add(fileindex, new_ie);
917 got_fileindex_entry_free(new_ie);
922 get_ondisk_perms(int executable, mode_t st_mode)
924 mode_t xbits = S_IXUSR;
927 /* Map read bits to execute bits. */
928 if (st_mode & S_IRGRP)
930 if (st_mode & S_IROTH)
932 return st_mode | xbits;
935 return (st_mode & ~(S_IXUSR | S_IXGRP | S_IXOTH));
938 /* forward declaration */
939 static const struct got_error *
940 install_blob(struct got_worktree *worktree, const char *ondisk_path,
941 const char *path, mode_t te_mode, mode_t st_mode,
942 struct got_blob_object *blob, int restoring_missing_file,
943 int reverting_versioned_file, struct got_repository *repo,
944 got_worktree_checkout_cb progress_cb, void *progress_arg);
946 static const struct got_error *
947 install_symlink(struct got_worktree *worktree, const char *ondisk_path,
948 const char *path, mode_t te_mode, mode_t st_mode,
949 struct got_blob_object *blob, int restoring_missing_file,
950 int reverting_versioned_file, struct got_repository *repo,
951 got_worktree_checkout_cb progress_cb, void *progress_arg)
953 const struct got_error *err = NULL;
954 char target_path[PATH_MAX];
955 size_t len, target_len = 0;
956 char *resolved_path = NULL, *abspath = NULL;
957 const uint8_t *buf = got_object_blob_get_read_buf(blob);
958 size_t hdrlen = got_object_blob_get_hdrlen(blob);
961 * Blob object content specifies the target path of the link.
962 * If a symbolic link cannot be installed we instead create
963 * a regular file which contains the link target path stored
964 * in the blob object.
967 err = got_object_blob_read_block(&len, blob);
968 if (len + target_len >= sizeof(target_path)) {
969 /* Path too long; install as a regular file. */
970 got_object_blob_rewind(blob);
971 return install_blob(worktree, ondisk_path, path,
972 GOT_DEFAULT_FILE_MODE, st_mode, blob,
973 restoring_missing_file, reverting_versioned_file,
974 repo, progress_cb, progress_arg);
977 /* Skip blob object header first time around. */
978 memcpy(target_path + target_len, buf + hdrlen,
980 target_len += len - hdrlen;
984 target_path[target_len] = '\0';
987 * Relative symlink target lookup should begin at the directory
988 * in which the blob object is being installed.
990 if (!got_path_is_absolute(target_path)) {
991 char *parent = dirname(ondisk_path);
992 if (asprintf(&abspath, "%s/%s", parent, target_path) == -1) {
993 err = got_error_from_errno("asprintf");
999 * unveil(2) restricts our view of paths in the filesystem.
1000 * ENOENT will occur if a link target path does not exist or
1001 * if it points outside our unveiled path space.
1003 resolved_path = realpath(abspath ? abspath : target_path, NULL);
1004 if (resolved_path == NULL) {
1005 if (errno != ENOENT)
1006 return got_error_from_errno2("realpath", target_path);
1009 /* Only allow symlinks pointing at paths within the work tree. */
1010 if (!got_path_is_child(resolved_path ? resolved_path : (abspath ?
1011 abspath : target_path), worktree->root_path,
1012 strlen(worktree->root_path))) {
1013 /* install as a regular file */
1014 got_object_blob_rewind(blob);
1015 err = install_blob(worktree, ondisk_path, path,
1016 GOT_DEFAULT_FILE_MODE, st_mode, blob,
1017 restoring_missing_file, reverting_versioned_file,
1018 repo, progress_cb, progress_arg);
1022 if (symlink(target_path, ondisk_path) == -1) {
1023 if (errno == ENOENT) {
1024 char *parent = dirname(ondisk_path);
1025 if (parent == NULL) {
1026 err = got_error_from_errno2("dirname",
1030 err = add_dir_on_disk(worktree, parent);
1034 * Retry, and fall through to error handling
1035 * below if this second attempt fails.
1037 if (symlink(target_path, ondisk_path) != -1) {
1038 err = NULL; /* success */
1043 /* Handle errors from first or second creation attempt. */
1044 if (errno == EEXIST) {
1047 char etarget[PATH_MAX];
1048 if (lstat(ondisk_path, &sb) == -1) {
1049 err = got_error_from_errno2("lstat",
1053 if (!S_ISLNK(sb.st_mode)) {
1054 err = got_error_path(ondisk_path,
1055 GOT_ERR_FILE_OBSTRUCTED);
1058 elen = readlink(ondisk_path, etarget, sizeof(etarget));
1060 err = got_error_from_errno2("readlink",
1064 if (elen == target_len &&
1065 memcmp(etarget, target_path, target_len) == 0)
1068 err = got_error_path(ondisk_path,
1069 GOT_ERR_FILE_OBSTRUCTED);
1070 } else if (errno == ENAMETOOLONG) {
1071 /* bad target path; install as a regular file */
1072 got_object_blob_rewind(blob);
1073 err = install_blob(worktree, ondisk_path, path,
1074 GOT_DEFAULT_FILE_MODE, st_mode, blob,
1075 restoring_missing_file, reverting_versioned_file,
1076 repo, progress_cb, progress_arg);
1077 } else if (errno == ENOTDIR) {
1078 err = got_error_path(ondisk_path,
1079 GOT_ERR_FILE_OBSTRUCTED);
1081 err = got_error_from_errno3("symlink",
1082 target_path, ondisk_path);
1086 free(resolved_path);
1091 static const struct got_error *
1092 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1093 const char *path, mode_t te_mode, mode_t st_mode,
1094 struct got_blob_object *blob, int restoring_missing_file,
1095 int reverting_versioned_file, struct got_repository *repo,
1096 got_worktree_checkout_cb progress_cb, void *progress_arg)
1098 const struct got_error *err = NULL;
1102 char *tmppath = NULL;
1104 if (S_ISLNK(te_mode))
1105 return install_symlink(worktree, ondisk_path, path, te_mode,
1106 st_mode, blob, restoring_missing_file,
1107 reverting_versioned_file, repo, progress_cb, progress_arg);
1109 fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1110 GOT_DEFAULT_FILE_MODE);
1112 if (errno == ENOENT) {
1113 char *parent = dirname(path);
1115 return got_error_from_errno2("dirname", path);
1116 err = add_dir_on_disk(worktree, parent);
1119 fd = open(ondisk_path,
1120 O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1121 GOT_DEFAULT_FILE_MODE);
1123 return got_error_from_errno2("open",
1125 } else if (errno == EEXIST) {
1126 if (!S_ISREG(st_mode)) {
1127 /* TODO file is obstructed; do something */
1128 err = got_error_path(ondisk_path,
1129 GOT_ERR_FILE_OBSTRUCTED);
1132 err = got_opentemp_named_fd(&tmppath, &fd,
1139 return got_error_from_errno2("open", ondisk_path);
1142 if (restoring_missing_file)
1143 err = (*progress_cb)(progress_arg, GOT_STATUS_MISSING, path);
1144 else if (reverting_versioned_file)
1145 err = (*progress_cb)(progress_arg, GOT_STATUS_REVERT, path);
1147 err = (*progress_cb)(progress_arg,
1148 update ? GOT_STATUS_UPDATE : GOT_STATUS_ADD, path);
1152 hdrlen = got_object_blob_get_hdrlen(blob);
1154 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1155 err = got_object_blob_read_block(&len, blob);
1159 /* Skip blob object header first time around. */
1160 ssize_t outlen = write(fd, buf + hdrlen, len - hdrlen);
1162 err = got_error_from_errno("write");
1164 } else if (outlen != len - hdrlen) {
1165 err = got_error(GOT_ERR_IO);
1172 if (fsync(fd) != 0) {
1173 err = got_error_from_errno("fsync");
1178 if (rename(tmppath, ondisk_path) != 0) {
1179 err = got_error_from_errno3("rename", tmppath,
1186 if (chmod(ondisk_path,
1187 get_ondisk_perms(te_mode & S_IXUSR, st_mode)) == -1) {
1188 err = got_error_from_errno2("chmod", ondisk_path);
1193 if (fd != -1 && close(fd) != 0 && err == NULL)
1194 err = got_error_from_errno("close");
1199 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1200 static const struct got_error *
1201 get_modified_file_content_status(unsigned char *status, FILE *f)
1203 const struct got_error *err = NULL;
1204 const char *markers[3] = {
1205 GOT_DIFF_CONFLICT_MARKER_BEGIN,
1206 GOT_DIFF_CONFLICT_MARKER_SEP,
1207 GOT_DIFF_CONFLICT_MARKER_END
1212 const char delim[3] = {'\0', '\0', '\0'};
1214 while (*status == GOT_STATUS_MODIFY) {
1215 line = fparseln(f, &len, NULL, delim, 0);
1219 err = got_ferror(f, GOT_ERR_IO);
1223 if (strncmp(line, markers[i], strlen(markers[i])) == 0) {
1224 if (strcmp(markers[i], GOT_DIFF_CONFLICT_MARKER_END)
1226 *status = GOT_STATUS_CONFLICT;
1236 xbit_differs(struct got_fileindex_entry *ie, uint16_t st_mode)
1238 mode_t ie_mode = got_fileindex_perms_to_st(ie);
1239 return ((ie_mode & S_IXUSR) != (st_mode & S_IXUSR));
1243 stat_info_differs(struct got_fileindex_entry *ie, struct stat *sb)
1245 return !(ie->ctime_sec == sb->st_ctime &&
1246 ie->ctime_nsec == sb->st_ctimensec &&
1247 ie->mtime_sec == sb->st_mtime &&
1248 ie->mtime_nsec == sb->st_mtimensec &&
1249 ie->size == (sb->st_size & 0xffffffff) &&
1250 !xbit_differs(ie, sb->st_mode));
1253 static unsigned char
1254 get_staged_status(struct got_fileindex_entry *ie)
1256 switch (got_fileindex_entry_stage_get(ie)) {
1257 case GOT_FILEIDX_STAGE_ADD:
1258 return GOT_STATUS_ADD;
1259 case GOT_FILEIDX_STAGE_DELETE:
1260 return GOT_STATUS_DELETE;
1261 case GOT_FILEIDX_STAGE_MODIFY:
1262 return GOT_STATUS_MODIFY;
1264 return GOT_STATUS_NO_CHANGE;
1268 static const struct got_error *
1269 get_file_status(unsigned char *status, struct stat *sb,
1270 struct got_fileindex_entry *ie, const char *abspath,
1271 int dirfd, const char *de_name, struct got_repository *repo)
1273 const struct got_error *err = NULL;
1274 struct got_object_id id;
1279 struct got_blob_object *blob = NULL;
1281 unsigned char staged_status = get_staged_status(ie);
1283 *status = GOT_STATUS_NO_CHANGE;
1286 * Whenever the caller provides a directory descriptor and a
1287 * directory entry name for the file, use them! This prevents
1288 * race conditions if filesystem paths change beneath our feet.
1291 if (fstatat(dirfd, de_name, sb, AT_SYMLINK_NOFOLLOW) == -1) {
1292 if (errno == ENOENT) {
1293 if (got_fileindex_entry_has_file_on_disk(ie))
1294 *status = GOT_STATUS_MISSING;
1296 *status = GOT_STATUS_DELETE;
1299 err = got_error_from_errno2("fstatat", abspath);
1303 fd = open(abspath, O_RDONLY | O_NOFOLLOW);
1304 if (fd == -1 && errno != ENOENT)
1305 return got_error_from_errno2("open", abspath);
1306 if (fd == -1 || fstat(fd, sb) == -1) {
1307 if (errno == ENOENT) {
1308 if (got_fileindex_entry_has_file_on_disk(ie))
1309 *status = GOT_STATUS_MISSING;
1311 *status = GOT_STATUS_DELETE;
1314 err = got_error_from_errno2("fstat", abspath);
1319 if (!S_ISREG(sb->st_mode)) {
1320 *status = GOT_STATUS_OBSTRUCTED;
1324 if (!got_fileindex_entry_has_file_on_disk(ie)) {
1325 *status = GOT_STATUS_DELETE;
1327 } else if (!got_fileindex_entry_has_blob(ie) &&
1328 staged_status != GOT_STATUS_ADD) {
1329 *status = GOT_STATUS_ADD;
1333 if (!stat_info_differs(ie, sb))
1336 if (staged_status == GOT_STATUS_MODIFY ||
1337 staged_status == GOT_STATUS_ADD)
1338 memcpy(id.sha1, ie->staged_blob_sha1, sizeof(id.sha1));
1340 memcpy(id.sha1, ie->blob_sha1, sizeof(id.sha1));
1342 err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf));
1347 fd = openat(dirfd, de_name, O_RDONLY | O_NOFOLLOW);
1349 err = got_error_from_errno2("openat", abspath);
1354 f = fdopen(fd, "r");
1356 err = got_error_from_errno2("fdopen", abspath);
1360 hdrlen = got_object_blob_get_hdrlen(blob);
1362 const uint8_t *bbuf = got_object_blob_get_read_buf(blob);
1363 err = got_object_blob_read_block(&blen, blob);
1366 /* Skip length of blob object header first time around. */
1367 flen = fread(fbuf, 1, sizeof(fbuf) - hdrlen, f);
1368 if (flen == 0 && ferror(f)) {
1369 err = got_error_from_errno("fread");
1374 *status = GOT_STATUS_MODIFY;
1376 } else if (flen == 0) {
1378 *status = GOT_STATUS_MODIFY;
1380 } else if (blen - hdrlen == flen) {
1381 /* Skip blob object header first time around. */
1382 if (memcmp(bbuf + hdrlen, fbuf, flen) != 0) {
1383 *status = GOT_STATUS_MODIFY;
1387 *status = GOT_STATUS_MODIFY;
1393 if (*status == GOT_STATUS_MODIFY) {
1395 err = get_modified_file_content_status(status, f);
1396 } else if (xbit_differs(ie, sb->st_mode))
1397 *status = GOT_STATUS_MODE_CHANGE;
1400 got_object_blob_close(blob);
1401 if (f != NULL && fclose(f) == EOF && err == NULL)
1402 err = got_error_from_errno2("fclose", abspath);
1403 if (fd != -1 && close(fd) == -1 && err == NULL)
1404 err = got_error_from_errno2("close", abspath);
1409 * Update timestamps in the file index if a file is unmodified and
1410 * we had to run a full content comparison to find out.
1412 static const struct got_error *
1413 sync_timestamps(char *ondisk_path, unsigned char status,
1414 struct got_fileindex_entry *ie, struct stat *sb)
1416 if (status == GOT_STATUS_NO_CHANGE && stat_info_differs(ie, sb))
1417 return got_fileindex_entry_update(ie, ondisk_path,
1418 ie->blob_sha1, ie->commit_sha1, 1);
1423 static const struct got_error *
1424 update_blob(struct got_worktree *worktree,
1425 struct got_fileindex *fileindex, struct got_fileindex_entry *ie,
1426 struct got_tree_entry *te, const char *path,
1427 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
1430 const struct got_error *err = NULL;
1431 struct got_blob_object *blob = NULL;
1433 unsigned char status = GOT_STATUS_NO_CHANGE;
1436 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, path) == -1)
1437 return got_error_from_errno("asprintf");
1440 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE) {
1441 err = got_error_path(ie->path, GOT_ERR_FILE_STAGED);
1444 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
1448 if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE)
1449 sb.st_mode = got_fileindex_perms_to_st(ie);
1451 sb.st_mode = GOT_DEFAULT_FILE_MODE;
1453 if (status == GOT_STATUS_OBSTRUCTED) {
1454 err = (*progress_cb)(progress_arg, status, path);
1457 if (status == GOT_STATUS_CONFLICT) {
1458 err = (*progress_cb)(progress_arg, GOT_STATUS_CANNOT_UPDATE,
1463 if (ie && status != GOT_STATUS_MISSING &&
1464 (te->mode & S_IXUSR) == (sb.st_mode & S_IXUSR)) {
1465 if (got_fileindex_entry_has_commit(ie) &&
1466 memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
1467 SHA1_DIGEST_LENGTH) == 0) {
1468 err = sync_timestamps(ondisk_path, status, ie, &sb);
1471 err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
1475 if (got_fileindex_entry_has_blob(ie) &&
1476 memcmp(ie->blob_sha1, te->id.sha1,
1477 SHA1_DIGEST_LENGTH) == 0) {
1478 err = sync_timestamps(ondisk_path, status, ie, &sb);
1483 err = got_object_open_as_blob(&blob, repo, &te->id, 8192);
1487 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_ADD) {
1488 int update_timestamps;
1489 struct got_blob_object *blob2 = NULL;
1490 char *label_orig = NULL;
1491 if (got_fileindex_entry_has_blob(ie)) {
1492 struct got_object_id id2;
1493 memcpy(id2.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
1494 err = got_object_open_as_blob(&blob2, repo, &id2, 8192);
1498 if (got_fileindex_entry_has_commit(ie)) {
1499 char id_str[SHA1_DIGEST_STRING_LENGTH];
1500 if (got_sha1_digest_to_str(ie->commit_sha1, id_str,
1501 sizeof(id_str)) == NULL) {
1502 err = got_error_path(id_str,
1503 GOT_ERR_BAD_OBJ_ID_STR);
1506 if (asprintf(&label_orig, "%s: commit %s",
1507 GOT_MERGE_LABEL_BASE, id_str) == -1) {
1508 err = got_error_from_errno("asprintf");
1512 err = merge_blob(&update_timestamps, worktree, blob2,
1513 ondisk_path, path, sb.st_mode, label_orig, blob,
1514 worktree->base_commit_id, repo,
1515 progress_cb, progress_arg);
1518 got_object_blob_close(blob2);
1522 * Do not update timestamps of files with local changes.
1523 * Otherwise, a future status walk would treat them as
1524 * unmodified files again.
1526 err = got_fileindex_entry_update(ie, ondisk_path,
1527 blob->id.sha1, worktree->base_commit_id->sha1,
1529 } else if (status == GOT_STATUS_MODE_CHANGE) {
1530 err = got_fileindex_entry_update(ie, ondisk_path,
1531 blob->id.sha1, worktree->base_commit_id->sha1, 0);
1532 } else if (status == GOT_STATUS_DELETE) {
1533 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
1536 err = got_fileindex_entry_update(ie, ondisk_path,
1537 blob->id.sha1, worktree->base_commit_id->sha1, 0);
1541 err = install_blob(worktree, ondisk_path, path, te->mode,
1542 sb.st_mode, blob, status == GOT_STATUS_MISSING, 0,
1543 repo, progress_cb, progress_arg);
1547 err = got_fileindex_entry_update(ie, ondisk_path,
1548 blob->id.sha1, worktree->base_commit_id->sha1, 1);
1550 err = create_fileindex_entry(fileindex,
1551 worktree->base_commit_id, ondisk_path, path,
1557 got_object_blob_close(blob);
1563 static const struct got_error *
1564 remove_ondisk_file(const char *root_path, const char *path)
1566 const struct got_error *err = NULL;
1567 char *ondisk_path = NULL;
1569 if (asprintf(&ondisk_path, "%s/%s", root_path, path) == -1)
1570 return got_error_from_errno("asprintf");
1572 if (unlink(ondisk_path) == -1) {
1573 if (errno != ENOENT)
1574 err = got_error_from_errno2("unlink", ondisk_path);
1576 char *parent = dirname(ondisk_path);
1577 while (parent && strcmp(parent, root_path) != 0) {
1578 if (rmdir(parent) == -1) {
1579 if (errno != ENOTEMPTY)
1580 err = got_error_from_errno2("rmdir",
1584 parent = dirname(parent);
1591 static const struct got_error *
1592 delete_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
1593 struct got_fileindex_entry *ie, struct got_repository *repo,
1594 got_worktree_checkout_cb progress_cb, void *progress_arg)
1596 const struct got_error *err = NULL;
1597 unsigned char status;
1601 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
1602 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
1604 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, ie->path)
1606 return got_error_from_errno("asprintf");
1608 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, repo);
1612 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_CONFLICT ||
1613 status == GOT_STATUS_ADD) {
1614 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, ie->path);
1618 * Preserve the working file and change the deleted blob's
1619 * entry into a schedule-add entry.
1621 err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL,
1624 err = (*progress_cb)(progress_arg, GOT_STATUS_DELETE, ie->path);
1627 if (status == GOT_STATUS_NO_CHANGE) {
1628 err = remove_ondisk_file(worktree->root_path, ie->path);
1632 got_fileindex_entry_remove(fileindex, ie);
1639 struct diff_cb_arg {
1640 struct got_fileindex *fileindex;
1641 struct got_worktree *worktree;
1642 struct got_repository *repo;
1643 got_worktree_checkout_cb progress_cb;
1645 got_cancel_cb cancel_cb;
1649 static const struct got_error *
1650 diff_old_new(void *arg, struct got_fileindex_entry *ie,
1651 struct got_tree_entry *te, const char *parent_path)
1653 struct diff_cb_arg *a = arg;
1655 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
1656 return got_error(GOT_ERR_CANCELLED);
1658 return update_blob(a->worktree, a->fileindex, ie, te,
1659 ie->path, a->repo, a->progress_cb, a->progress_arg);
1662 static const struct got_error *
1663 diff_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
1665 struct diff_cb_arg *a = arg;
1667 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
1668 return got_error(GOT_ERR_CANCELLED);
1670 return delete_blob(a->worktree, a->fileindex, ie,
1671 a->repo, a->progress_cb, a->progress_arg);
1674 static const struct got_error *
1675 diff_new(void *arg, struct got_tree_entry *te, const char *parent_path)
1677 struct diff_cb_arg *a = arg;
1678 const struct got_error *err;
1681 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
1682 return got_error(GOT_ERR_CANCELLED);
1684 if (got_object_tree_entry_is_submodule(te))
1687 if (asprintf(&path, "%s%s%s", parent_path,
1688 parent_path[0] ? "/" : "", te->name)
1690 return got_error_from_errno("asprintf");
1692 if (S_ISDIR(te->mode))
1693 err = add_dir_on_disk(a->worktree, path);
1695 err = update_blob(a->worktree, a->fileindex, NULL, te, path,
1696 a->repo, a->progress_cb, a->progress_arg);
1702 static const struct got_error *
1703 get_ref_name(char **refname, struct got_worktree *worktree, const char *prefix)
1705 const struct got_error *err = NULL;
1706 char *uuidstr = NULL;
1707 uint32_t uuid_status;
1711 uuid_to_string(&worktree->uuid, &uuidstr, &uuid_status);
1712 if (uuid_status != uuid_s_ok)
1713 return got_error_uuid(uuid_status, "uuid_to_string");
1715 if (asprintf(refname, "%s-%s", prefix, uuidstr)
1717 err = got_error_from_errno("asprintf");
1724 const struct got_error *
1725 got_worktree_get_base_ref_name(char **refname, struct got_worktree *worktree)
1727 return get_ref_name(refname, worktree, GOT_WORKTREE_BASE_REF_PREFIX);
1730 static const struct got_error *
1731 get_rebase_tmp_ref_name(char **refname, struct got_worktree *worktree)
1733 return get_ref_name(refname, worktree,
1734 GOT_WORKTREE_REBASE_TMP_REF_PREFIX);
1737 static const struct got_error *
1738 get_newbase_symref_name(char **refname, struct got_worktree *worktree)
1740 return get_ref_name(refname, worktree, GOT_WORKTREE_NEWBASE_REF_PREFIX);
1743 static const struct got_error *
1744 get_rebase_branch_symref_name(char **refname, struct got_worktree *worktree)
1746 return get_ref_name(refname, worktree,
1747 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX);
1750 static const struct got_error *
1751 get_rebase_commit_ref_name(char **refname, struct got_worktree *worktree)
1753 return get_ref_name(refname, worktree,
1754 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX);
1757 static const struct got_error *
1758 get_histedit_tmp_ref_name(char **refname, struct got_worktree *worktree)
1760 return get_ref_name(refname, worktree,
1761 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX);
1764 static const struct got_error *
1765 get_histedit_branch_symref_name(char **refname, struct got_worktree *worktree)
1767 return get_ref_name(refname, worktree,
1768 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX);
1771 static const struct got_error *
1772 get_histedit_base_commit_ref_name(char **refname, struct got_worktree *worktree)
1774 return get_ref_name(refname, worktree,
1775 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX);
1778 static const struct got_error *
1779 get_histedit_commit_ref_name(char **refname, struct got_worktree *worktree)
1781 return get_ref_name(refname, worktree,
1782 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX);
1785 const struct got_error *
1786 got_worktree_get_histedit_script_path(char **path,
1787 struct got_worktree *worktree)
1789 if (asprintf(path, "%s/%s/%s", worktree->root_path,
1790 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_HISTEDIT_SCRIPT) == -1) {
1792 return got_error_from_errno("asprintf");
1798 * Prevent Git's garbage collector from deleting our base commit by
1799 * setting a reference to our base commit's ID.
1801 static const struct got_error *
1802 ref_base_commit(struct got_worktree *worktree, struct got_repository *repo)
1804 const struct got_error *err = NULL;
1805 struct got_reference *ref = NULL;
1808 err = got_worktree_get_base_ref_name(&refname, worktree);
1812 err = got_ref_alloc(&ref, refname, worktree->base_commit_id);
1816 err = got_ref_write(ref, repo);
1824 static const struct got_error *
1825 get_fileindex_path(char **fileindex_path, struct got_worktree *worktree)
1827 const struct got_error *err = NULL;
1829 if (asprintf(fileindex_path, "%s/%s/%s", worktree->root_path,
1830 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_FILE_INDEX) == -1) {
1831 err = got_error_from_errno("asprintf");
1832 *fileindex_path = NULL;
1838 static const struct got_error *
1839 open_fileindex(struct got_fileindex **fileindex, char **fileindex_path,
1840 struct got_worktree *worktree)
1842 const struct got_error *err = NULL;
1845 *fileindex_path = NULL;
1846 *fileindex = got_fileindex_alloc();
1847 if (*fileindex == NULL)
1848 return got_error_from_errno("got_fileindex_alloc");
1850 err = get_fileindex_path(fileindex_path, worktree);
1854 index = fopen(*fileindex_path, "rb");
1855 if (index == NULL) {
1856 if (errno != ENOENT)
1857 err = got_error_from_errno2("fopen", *fileindex_path);
1859 err = got_fileindex_read(*fileindex, index);
1860 if (fclose(index) != 0 && err == NULL)
1861 err = got_error_from_errno("fclose");
1865 free(*fileindex_path);
1866 *fileindex_path = NULL;
1867 got_fileindex_free(*fileindex);
1873 struct bump_base_commit_id_arg {
1874 struct got_object_id *base_commit_id;
1877 const char *entry_name;
1878 got_worktree_checkout_cb progress_cb;
1882 /* Bump base commit ID of all files within an updated part of the work tree. */
1883 static const struct got_error *
1884 bump_base_commit_id(void *arg, struct got_fileindex_entry *ie)
1886 const struct got_error *err;
1887 struct bump_base_commit_id_arg *a = arg;
1889 if (a->entry_name) {
1890 if (strcmp(ie->path, a->path) != 0)
1892 } else if (!got_path_is_child(ie->path, a->path, a->path_len))
1895 if (memcmp(ie->commit_sha1, a->base_commit_id->sha1,
1896 SHA1_DIGEST_LENGTH) == 0)
1899 if (a->progress_cb) {
1900 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_BUMP_BASE,
1905 memcpy(ie->commit_sha1, a->base_commit_id->sha1, SHA1_DIGEST_LENGTH);
1909 static const struct got_error *
1910 sync_fileindex(struct got_fileindex *fileindex, const char *fileindex_path)
1912 const struct got_error *err = NULL;
1913 char *new_fileindex_path = NULL;
1914 FILE *new_index = NULL;
1915 struct timespec timeout;
1917 err = got_opentemp_named(&new_fileindex_path, &new_index,
1922 err = got_fileindex_write(fileindex, new_index);
1926 if (rename(new_fileindex_path, fileindex_path) != 0) {
1927 err = got_error_from_errno3("rename", new_fileindex_path,
1929 unlink(new_fileindex_path);
1933 * Sleep for a short amount of time to ensure that files modified after
1934 * this program exits have a different time stamp from the one which
1935 * was recorded in the file index.
1938 timeout.tv_nsec = 1;
1939 nanosleep(&timeout, NULL);
1943 free(new_fileindex_path);
1947 static const struct got_error *
1948 find_tree_entry_for_checkout(int *entry_type, char **tree_relpath,
1949 struct got_object_id **tree_id, const char *wt_relpath,
1950 struct got_worktree *worktree, struct got_repository *repo)
1952 const struct got_error *err = NULL;
1953 struct got_object_id *id = NULL;
1954 char *in_repo_path = NULL;
1955 int is_root_wt = got_path_is_root_dir(worktree->path_prefix);
1957 *entry_type = GOT_OBJ_TYPE_ANY;
1958 *tree_relpath = NULL;
1961 if (wt_relpath[0] == '\0') {
1962 /* Check out all files within the work tree. */
1963 *entry_type = GOT_OBJ_TYPE_TREE;
1964 *tree_relpath = strdup("");
1965 if (*tree_relpath == NULL) {
1966 err = got_error_from_errno("strdup");
1969 err = got_object_id_by_path(tree_id, repo,
1970 worktree->base_commit_id, worktree->path_prefix);
1976 /* Check out a subset of files in the work tree. */
1978 if (asprintf(&in_repo_path, "%s%s%s", worktree->path_prefix,
1979 is_root_wt ? "" : "/", wt_relpath) == -1) {
1980 err = got_error_from_errno("asprintf");
1984 err = got_object_id_by_path(&id, repo, worktree->base_commit_id,
1990 in_repo_path = NULL;
1992 err = got_object_get_type(entry_type, repo, id);
1996 if (*entry_type == GOT_OBJ_TYPE_BLOB) {
1997 /* Check out a single file. */
1998 if (strchr(wt_relpath, '/') == NULL) {
1999 /* Check out a single file in work tree's root dir. */
2000 in_repo_path = strdup(worktree->path_prefix);
2001 if (in_repo_path == NULL) {
2002 err = got_error_from_errno("strdup");
2005 *tree_relpath = strdup("");
2006 if (*tree_relpath == NULL) {
2007 err = got_error_from_errno("strdup");
2011 /* Check out a single file in a subdirectory. */
2012 err = got_path_dirname(tree_relpath, wt_relpath);
2015 if (asprintf(&in_repo_path, "%s%s%s",
2016 worktree->path_prefix, is_root_wt ? "" : "/",
2017 *tree_relpath) == -1) {
2018 err = got_error_from_errno("asprintf");
2022 err = got_object_id_by_path(tree_id, repo,
2023 worktree->base_commit_id, in_repo_path);
2025 /* Check out all files within a subdirectory. */
2026 *tree_id = got_object_id_dup(id);
2027 if (*tree_id == NULL) {
2028 err = got_error_from_errno("got_object_id_dup");
2031 *tree_relpath = strdup(wt_relpath);
2032 if (*tree_relpath == NULL) {
2033 err = got_error_from_errno("strdup");
2041 *entry_type = GOT_OBJ_TYPE_ANY;
2042 free(*tree_relpath);
2043 *tree_relpath = NULL;
2050 static const struct got_error *
2051 checkout_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
2052 const char *relpath, struct got_object_id *tree_id, const char *entry_name,
2053 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
2054 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
2056 const struct got_error *err = NULL;
2057 struct got_commit_object *commit = NULL;
2058 struct got_tree_object *tree = NULL;
2059 struct got_fileindex_diff_tree_cb diff_cb;
2060 struct diff_cb_arg arg;
2062 err = ref_base_commit(worktree, repo);
2064 if (!(err->code == GOT_ERR_ERRNO &&
2065 (errno == EACCES || errno == EROFS)))
2067 err = (*progress_cb)(progress_arg,
2068 GOT_STATUS_BASE_REF_ERR, worktree->root_path);
2073 err = got_object_open_as_commit(&commit, repo,
2074 worktree->base_commit_id);
2078 err = got_object_open_as_tree(&tree, repo, tree_id);
2083 got_object_tree_find_entry(tree, entry_name) == NULL) {
2084 err = got_error(GOT_ERR_NO_TREE_ENTRY);
2088 diff_cb.diff_old_new = diff_old_new;
2089 diff_cb.diff_old = diff_old;
2090 diff_cb.diff_new = diff_new;
2091 arg.fileindex = fileindex;
2092 arg.worktree = worktree;
2094 arg.progress_cb = progress_cb;
2095 arg.progress_arg = progress_arg;
2096 arg.cancel_cb = cancel_cb;
2097 arg.cancel_arg = cancel_arg;
2098 err = got_fileindex_diff_tree(fileindex, tree, relpath,
2099 entry_name, repo, &diff_cb, &arg);
2102 got_object_tree_close(tree);
2104 got_object_commit_close(commit);
2108 const struct got_error *
2109 got_worktree_checkout_files(struct got_worktree *worktree,
2110 struct got_pathlist_head *paths, struct got_repository *repo,
2111 got_worktree_checkout_cb progress_cb, void *progress_arg,
2112 got_cancel_cb cancel_cb, void *cancel_arg)
2114 const struct got_error *err = NULL, *sync_err, *unlockerr;
2115 struct got_commit_object *commit = NULL;
2116 struct got_tree_object *tree = NULL;
2117 struct got_fileindex *fileindex = NULL;
2118 char *fileindex_path = NULL;
2119 struct got_pathlist_entry *pe;
2120 struct tree_path_data {
2121 SIMPLEQ_ENTRY(tree_path_data) entry;
2122 struct got_object_id *tree_id;
2127 SIMPLEQ_HEAD(tree_paths, tree_path_data) tree_paths;
2129 SIMPLEQ_INIT(&tree_paths);
2131 err = lock_worktree(worktree, LOCK_EX);
2135 /* Map all specified paths to in-repository trees. */
2136 TAILQ_FOREACH(pe, paths, entry) {
2137 tpd = malloc(sizeof(*tpd));
2139 err = got_error_from_errno("malloc");
2143 err = find_tree_entry_for_checkout(&tpd->entry_type,
2144 &tpd->relpath, &tpd->tree_id, pe->path, worktree, repo);
2150 if (tpd->entry_type == GOT_OBJ_TYPE_BLOB) {
2151 err = got_path_basename(&tpd->entry_name, pe->path);
2159 tpd->entry_name = NULL;
2161 SIMPLEQ_INSERT_TAIL(&tree_paths, tpd, entry);
2165 * Read the file index.
2166 * Checking out files is supposed to be an idempotent operation.
2167 * If the on-disk file index is incomplete we will try to complete it.
2169 err = open_fileindex(&fileindex, &fileindex_path, worktree);
2173 tpd = SIMPLEQ_FIRST(&tree_paths);
2174 TAILQ_FOREACH(pe, paths, entry) {
2175 struct bump_base_commit_id_arg bbc_arg;
2177 err = checkout_files(worktree, fileindex, tpd->relpath,
2178 tpd->tree_id, tpd->entry_name, repo,
2179 progress_cb, progress_arg, cancel_cb, cancel_arg);
2183 bbc_arg.base_commit_id = worktree->base_commit_id;
2184 bbc_arg.entry_name = tpd->entry_name;
2185 bbc_arg.path = pe->path;
2186 bbc_arg.path_len = pe->path_len;
2187 bbc_arg.progress_cb = progress_cb;
2188 bbc_arg.progress_arg = progress_arg;
2189 err = got_fileindex_for_each_entry_safe(fileindex,
2190 bump_base_commit_id, &bbc_arg);
2194 tpd = SIMPLEQ_NEXT(tpd, entry);
2196 sync_err = sync_fileindex(fileindex, fileindex_path);
2197 if (sync_err && err == NULL)
2200 free(fileindex_path);
2202 got_object_tree_close(tree);
2204 got_object_commit_close(commit);
2206 got_fileindex_free(fileindex);
2207 while (!SIMPLEQ_EMPTY(&tree_paths)) {
2208 tpd = SIMPLEQ_FIRST(&tree_paths);
2209 SIMPLEQ_REMOVE_HEAD(&tree_paths, entry);
2214 unlockerr = lock_worktree(worktree, LOCK_SH);
2215 if (unlockerr && err == NULL)
2220 struct merge_file_cb_arg {
2221 struct got_worktree *worktree;
2222 struct got_fileindex *fileindex;
2223 got_worktree_checkout_cb progress_cb;
2225 got_cancel_cb cancel_cb;
2227 const char *label_orig;
2228 struct got_object_id *commit_id2;
2231 static const struct got_error *
2232 merge_file_cb(void *arg, struct got_blob_object *blob1,
2233 struct got_blob_object *blob2, struct got_object_id *id1,
2234 struct got_object_id *id2, const char *path1, const char *path2,
2235 mode_t mode1, mode_t mode2, struct got_repository *repo)
2237 static const struct got_error *err = NULL;
2238 struct merge_file_cb_arg *a = arg;
2239 struct got_fileindex_entry *ie;
2240 char *ondisk_path = NULL;
2242 unsigned char status;
2243 int local_changes_subsumed;
2245 if (blob1 && blob2) {
2246 ie = got_fileindex_entry_get(a->fileindex, path2,
2249 return (*a->progress_cb)(a->progress_arg,
2250 GOT_STATUS_MISSING, path2);
2252 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2254 return got_error_from_errno("asprintf");
2256 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2261 if (status == GOT_STATUS_DELETE) {
2262 err = (*a->progress_cb)(a->progress_arg,
2263 GOT_STATUS_MERGE, path2);
2266 if (status != GOT_STATUS_NO_CHANGE &&
2267 status != GOT_STATUS_MODIFY &&
2268 status != GOT_STATUS_CONFLICT &&
2269 status != GOT_STATUS_ADD) {
2270 err = (*a->progress_cb)(a->progress_arg, status, path2);
2274 err = merge_blob(&local_changes_subsumed, a->worktree, blob1,
2275 ondisk_path, path2, sb.st_mode, a->label_orig, blob2,
2276 a->commit_id2, repo, a->progress_cb, a->progress_arg);
2278 ie = got_fileindex_entry_get(a->fileindex, path1,
2281 return (*a->progress_cb)(a->progress_arg,
2282 GOT_STATUS_MISSING, path1);
2284 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2286 return got_error_from_errno("asprintf");
2288 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2294 case GOT_STATUS_NO_CHANGE:
2295 err = (*a->progress_cb)(a->progress_arg,
2296 GOT_STATUS_DELETE, path1);
2299 err = remove_ondisk_file(a->worktree->root_path, path1);
2303 got_fileindex_entry_mark_deleted_from_disk(ie);
2305 case GOT_STATUS_DELETE:
2306 case GOT_STATUS_MISSING:
2307 err = (*a->progress_cb)(a->progress_arg,
2308 GOT_STATUS_DELETE, path1);
2312 got_fileindex_entry_mark_deleted_from_disk(ie);
2314 case GOT_STATUS_ADD:
2315 case GOT_STATUS_MODIFY:
2316 case GOT_STATUS_CONFLICT:
2317 err = (*a->progress_cb)(a->progress_arg,
2318 GOT_STATUS_CANNOT_DELETE, path1);
2322 case GOT_STATUS_OBSTRUCTED:
2323 err = (*a->progress_cb)(a->progress_arg, status, path1);
2331 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2333 return got_error_from_errno("asprintf");
2334 ie = got_fileindex_entry_get(a->fileindex, path2,
2337 err = get_file_status(&status, &sb, ie, ondisk_path,
2341 if (status != GOT_STATUS_NO_CHANGE &&
2342 status != GOT_STATUS_MODIFY &&
2343 status != GOT_STATUS_CONFLICT &&
2344 status != GOT_STATUS_ADD) {
2345 err = (*a->progress_cb)(a->progress_arg,
2349 err = merge_blob(&local_changes_subsumed, a->worktree,
2350 NULL, ondisk_path, path2, sb.st_mode,
2351 a->label_orig, blob2, a->commit_id2, repo,
2354 if (status == GOT_STATUS_DELETE) {
2355 err = got_fileindex_entry_update(ie,
2356 ondisk_path, blob2->id.sha1,
2357 a->worktree->base_commit_id->sha1, 0);
2362 sb.st_mode = GOT_DEFAULT_FILE_MODE;
2363 err = install_blob(a->worktree, ondisk_path, path2,
2364 /* XXX get this from parent tree! */
2365 GOT_DEFAULT_FILE_MODE,
2366 sb.st_mode, blob2, 0, 0, repo,
2367 a->progress_cb, a->progress_arg);
2370 err = got_fileindex_entry_alloc(&ie, path2);
2373 err = got_fileindex_entry_update(ie, ondisk_path,
2376 got_fileindex_entry_free(ie);
2379 err = got_fileindex_entry_add(a->fileindex, ie);
2381 got_fileindex_entry_free(ie);
2391 struct check_merge_ok_arg {
2392 struct got_worktree *worktree;
2393 struct got_repository *repo;
2396 static const struct got_error *
2397 check_merge_ok(void *arg, struct got_fileindex_entry *ie)
2399 const struct got_error *err = NULL;
2400 struct check_merge_ok_arg *a = arg;
2401 unsigned char status;
2405 /* Reject merges into a work tree with mixed base commits. */
2406 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
2407 SHA1_DIGEST_LENGTH))
2408 return got_error(GOT_ERR_MIXED_COMMITS);
2410 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
2412 return got_error_from_errno("asprintf");
2414 /* Reject merges into a work tree with conflicted files. */
2415 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
2418 if (status == GOT_STATUS_CONFLICT)
2419 return got_error(GOT_ERR_CONFLICTS);
2424 static const struct got_error *
2425 merge_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
2426 const char *fileindex_path, struct got_object_id *commit_id1,
2427 struct got_object_id *commit_id2, struct got_repository *repo,
2428 got_worktree_checkout_cb progress_cb, void *progress_arg,
2429 got_cancel_cb cancel_cb, void *cancel_arg)
2431 const struct got_error *err = NULL, *sync_err;
2432 struct got_object_id *tree_id1 = NULL, *tree_id2 = NULL;
2433 struct got_tree_object *tree1 = NULL, *tree2 = NULL;
2434 struct merge_file_cb_arg arg;
2435 char *label_orig = NULL;
2440 err = got_object_id_by_path(&tree_id1, repo, commit_id1,
2441 worktree->path_prefix);
2445 err = got_object_open_as_tree(&tree1, repo, tree_id1);
2449 err = got_object_id_str(&id_str, commit_id1);
2453 if (asprintf(&label_orig, "%s: commit %s",
2454 GOT_MERGE_LABEL_BASE, id_str) == -1) {
2455 err = got_error_from_errno("asprintf");
2462 err = got_object_id_by_path(&tree_id2, repo, commit_id2,
2463 worktree->path_prefix);
2467 err = got_object_open_as_tree(&tree2, repo, tree_id2);
2471 arg.worktree = worktree;
2472 arg.fileindex = fileindex;
2473 arg.progress_cb = progress_cb;
2474 arg.progress_arg = progress_arg;
2475 arg.cancel_cb = cancel_cb;
2476 arg.cancel_arg = cancel_arg;
2477 arg.label_orig = label_orig;
2478 arg.commit_id2 = commit_id2;
2479 err = got_diff_tree(tree1, tree2, "", "", repo, merge_file_cb, &arg, 1);
2480 sync_err = sync_fileindex(fileindex, fileindex_path);
2481 if (sync_err && err == NULL)
2485 got_object_tree_close(tree1);
2487 got_object_tree_close(tree2);
2492 const struct got_error *
2493 got_worktree_merge_files(struct got_worktree *worktree,
2494 struct got_object_id *commit_id1, struct got_object_id *commit_id2,
2495 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
2496 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
2498 const struct got_error *err, *unlockerr;
2499 char *fileindex_path = NULL;
2500 struct got_fileindex *fileindex = NULL;
2501 struct check_merge_ok_arg mok_arg;
2503 err = lock_worktree(worktree, LOCK_EX);
2507 err = open_fileindex(&fileindex, &fileindex_path, worktree);
2511 mok_arg.worktree = worktree;
2512 mok_arg.repo = repo;
2513 err = got_fileindex_for_each_entry_safe(fileindex, check_merge_ok,
2518 err = merge_files(worktree, fileindex, fileindex_path, commit_id1,
2519 commit_id2, repo, progress_cb, progress_arg, cancel_cb, cancel_arg);
2522 got_fileindex_free(fileindex);
2523 free(fileindex_path);
2524 unlockerr = lock_worktree(worktree, LOCK_SH);
2525 if (unlockerr && err == NULL)
2530 struct diff_dir_cb_arg {
2531 struct got_fileindex *fileindex;
2532 struct got_worktree *worktree;
2533 const char *status_path;
2534 size_t status_path_len;
2535 struct got_repository *repo;
2536 got_worktree_status_cb status_cb;
2538 got_cancel_cb cancel_cb;
2540 /* A pathlist containing per-directory pathlists of ignore patterns. */
2541 struct got_pathlist_head ignores;
2542 int report_unchanged;
2546 static const struct got_error *
2547 report_file_status(struct got_fileindex_entry *ie, const char *abspath,
2548 int dirfd, const char *de_name,
2549 got_worktree_status_cb status_cb, void *status_arg,
2550 struct got_repository *repo, int report_unchanged)
2552 const struct got_error *err = NULL;
2553 unsigned char status = GOT_STATUS_NO_CHANGE;
2554 unsigned char staged_status = get_staged_status(ie);
2556 struct got_object_id blob_id, commit_id, staged_blob_id;
2557 struct got_object_id *blob_idp = NULL, *commit_idp = NULL;
2558 struct got_object_id *staged_blob_idp = NULL;
2560 err = get_file_status(&status, &sb, ie, abspath, dirfd, de_name, repo);
2564 if (status == GOT_STATUS_NO_CHANGE &&
2565 staged_status == GOT_STATUS_NO_CHANGE && !report_unchanged)
2568 if (got_fileindex_entry_has_blob(ie)) {
2569 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
2570 blob_idp = &blob_id;
2572 if (got_fileindex_entry_has_commit(ie)) {
2573 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
2574 commit_idp = &commit_id;
2576 if (staged_status == GOT_STATUS_ADD ||
2577 staged_status == GOT_STATUS_MODIFY) {
2578 memcpy(staged_blob_id.sha1, ie->staged_blob_sha1,
2579 SHA1_DIGEST_LENGTH);
2580 staged_blob_idp = &staged_blob_id;
2583 return (*status_cb)(status_arg, status, staged_status,
2584 ie->path, blob_idp, staged_blob_idp, commit_idp, dirfd, de_name);
2587 static const struct got_error *
2588 status_old_new(void *arg, struct got_fileindex_entry *ie,
2589 struct dirent *de, const char *parent_path, int dirfd)
2591 const struct got_error *err = NULL;
2592 struct diff_dir_cb_arg *a = arg;
2595 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2596 return got_error(GOT_ERR_CANCELLED);
2598 if (got_path_cmp(parent_path, a->status_path,
2599 strlen(parent_path), a->status_path_len) != 0 &&
2600 !got_path_is_child(parent_path, a->status_path, a->status_path_len))
2603 if (parent_path[0]) {
2604 if (asprintf(&abspath, "%s/%s/%s", a->worktree->root_path,
2605 parent_path, de->d_name) == -1)
2606 return got_error_from_errno("asprintf");
2608 if (asprintf(&abspath, "%s/%s", a->worktree->root_path,
2610 return got_error_from_errno("asprintf");
2613 err = report_file_status(ie, abspath, dirfd, de->d_name,
2614 a->status_cb, a->status_arg, a->repo, a->report_unchanged);
2619 static const struct got_error *
2620 status_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
2622 struct diff_dir_cb_arg *a = arg;
2623 struct got_object_id blob_id, commit_id;
2624 unsigned char status;
2626 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2627 return got_error(GOT_ERR_CANCELLED);
2629 if (!got_path_is_child(ie->path, a->status_path, a->status_path_len))
2632 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
2633 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
2634 if (got_fileindex_entry_has_file_on_disk(ie))
2635 status = GOT_STATUS_MISSING;
2637 status = GOT_STATUS_DELETE;
2638 return (*a->status_cb)(a->status_arg, status, get_staged_status(ie),
2639 ie->path, &blob_id, NULL, &commit_id, -1, NULL);
2643 free_ignorelist(struct got_pathlist_head *ignorelist)
2645 struct got_pathlist_entry *pe;
2647 TAILQ_FOREACH(pe, ignorelist, entry)
2648 free((char *)pe->path);
2649 got_pathlist_free(ignorelist);
2653 free_ignores(struct got_pathlist_head *ignores)
2655 struct got_pathlist_entry *pe;
2657 TAILQ_FOREACH(pe, ignores, entry) {
2658 struct got_pathlist_head *ignorelist = pe->data;
2659 free_ignorelist(ignorelist);
2660 free((char *)pe->path);
2662 got_pathlist_free(ignores);
2665 static const struct got_error *
2666 read_ignores(struct got_pathlist_head *ignores, const char *path, FILE *f)
2668 const struct got_error *err = NULL;
2669 struct got_pathlist_entry *pe = NULL;
2670 struct got_pathlist_head *ignorelist;
2671 char *line = NULL, *pattern, *dirpath = NULL;
2672 size_t linesize = 0;
2675 ignorelist = calloc(1, sizeof(*ignorelist));
2676 if (ignorelist == NULL)
2677 return got_error_from_errno("calloc");
2678 TAILQ_INIT(ignorelist);
2680 while ((linelen = getline(&line, &linesize, f)) != -1) {
2681 if (linelen > 0 && line[linelen - 1] == '\n')
2682 line[linelen - 1] = '\0';
2684 /* Git's ignores may contain comments. */
2688 /* Git's negated patterns are not (yet?) supported. */
2692 if (asprintf(&pattern, "%s%s%s", path, path[0] ? "/" : "",
2694 err = got_error_from_errno("asprintf");
2697 err = got_pathlist_insert(NULL, ignorelist, pattern, NULL);
2702 err = got_error_from_errno("getline");
2706 dirpath = strdup(path);
2707 if (dirpath == NULL) {
2708 err = got_error_from_errno("strdup");
2711 err = got_pathlist_insert(&pe, ignores, dirpath, ignorelist);
2714 if (err || pe == NULL) {
2716 free_ignorelist(ignorelist);
2722 match_ignores(struct got_pathlist_head *ignores, const char *path)
2724 struct got_pathlist_entry *pe;
2726 /* Handle patterns which match in all directories. */
2727 TAILQ_FOREACH(pe, ignores, entry) {
2728 struct got_pathlist_head *ignorelist = pe->data;
2729 struct got_pathlist_entry *pi;
2731 TAILQ_FOREACH(pi, ignorelist, entry) {
2732 const char *p, *pattern = pi->path;
2734 if (strncmp(pattern, "**/", 3) != 0)
2739 if (fnmatch(pattern, p,
2740 FNM_PATHNAME | FNM_LEADING_DIR)) {
2741 /* Retry in next directory. */
2742 while (*p && *p != '/')
2754 * The ignores pathlist contains ignore lists from children before
2755 * parents, so we can find the most specific ignorelist by walking
2756 * ignores backwards.
2758 pe = TAILQ_LAST(ignores, got_pathlist_head);
2760 if (got_path_is_child(path, pe->path, pe->path_len)) {
2761 struct got_pathlist_head *ignorelist = pe->data;
2762 struct got_pathlist_entry *pi;
2763 TAILQ_FOREACH(pi, ignorelist, entry) {
2764 const char *pattern = pi->path;
2765 int flags = FNM_LEADING_DIR;
2766 if (strstr(pattern, "/**/") == NULL)
2767 flags |= FNM_PATHNAME;
2768 if (fnmatch(pattern, path, flags))
2773 pe = TAILQ_PREV(pe, got_pathlist_head, entry);
2779 static const struct got_error *
2780 add_ignores(struct got_pathlist_head *ignores, const char *root_path,
2781 const char *path, int dirfd, const char *ignores_filename)
2783 const struct got_error *err = NULL;
2786 FILE *ignoresfile = NULL;
2788 if (asprintf(&ignorespath, "%s/%s%s%s", root_path, path,
2789 path[0] ? "/" : "", ignores_filename) == -1)
2790 return got_error_from_errno("asprintf");
2793 fd = openat(dirfd, ignores_filename, O_RDONLY | O_NOFOLLOW);
2795 if (errno != ENOENT && errno != EACCES)
2796 err = got_error_from_errno2("openat",
2799 ignoresfile = fdopen(fd, "r");
2800 if (ignoresfile == NULL)
2801 err = got_error_from_errno2("fdopen",
2805 err = read_ignores(ignores, path, ignoresfile);
2809 ignoresfile = fopen(ignorespath, "r");
2810 if (ignoresfile == NULL) {
2811 if (errno != ENOENT && errno != EACCES)
2812 err = got_error_from_errno2("fopen",
2815 err = read_ignores(ignores, path, ignoresfile);
2818 if (ignoresfile && fclose(ignoresfile) == EOF && err == NULL)
2819 err = got_error_from_errno2("fclose", path);
2820 if (fd != -1 && close(fd) == -1 && err == NULL)
2821 err = got_error_from_errno2("close", path);
2826 static const struct got_error *
2827 status_new(void *arg, struct dirent *de, const char *parent_path, int dirfd)
2829 const struct got_error *err = NULL;
2830 struct diff_dir_cb_arg *a = arg;
2833 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2834 return got_error(GOT_ERR_CANCELLED);
2836 /* XXX ignore symlinks for now */
2837 if (de->d_type == DT_LNK)
2840 if (parent_path[0]) {
2841 if (asprintf(&path, "%s/%s", parent_path, de->d_name) == -1)
2842 return got_error_from_errno("asprintf");
2847 if (de->d_type != DT_DIR &&
2848 got_path_is_child(path, a->status_path, a->status_path_len)
2849 && !match_ignores(&a->ignores, path))
2850 err = (*a->status_cb)(a->status_arg, GOT_STATUS_UNVERSIONED,
2851 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
2857 static const struct got_error *
2858 status_traverse(void *arg, const char *path, int dirfd)
2860 const struct got_error *err = NULL;
2861 struct diff_dir_cb_arg *a = arg;
2866 err = add_ignores(&a->ignores, a->worktree->root_path,
2867 path, dirfd, ".cvsignore");
2871 err = add_ignores(&a->ignores, a->worktree->root_path, path,
2872 dirfd, ".gitignore");
2877 static const struct got_error *
2878 report_single_file_status(const char *path, const char *ondisk_path,
2879 struct got_fileindex *fileindex, got_worktree_status_cb status_cb,
2880 void *status_arg, struct got_repository *repo, int report_unchanged)
2882 struct got_fileindex_entry *ie;
2885 ie = got_fileindex_entry_get(fileindex, path, strlen(path));
2887 return report_file_status(ie, ondisk_path, -1, NULL,
2888 status_cb, status_arg, repo, report_unchanged);
2890 if (lstat(ondisk_path, &sb) == -1) {
2891 if (errno != ENOENT)
2892 return got_error_from_errno2("lstat", ondisk_path);
2893 return (*status_cb)(status_arg, GOT_STATUS_NONEXISTENT,
2894 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
2898 if (S_ISREG(sb.st_mode))
2899 return (*status_cb)(status_arg, GOT_STATUS_UNVERSIONED,
2900 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
2905 static const struct got_error *
2906 add_ignores_from_parent_paths(struct got_pathlist_head *ignores,
2907 const char *root_path, const char *path)
2909 const struct got_error *err;
2910 char *parent_path, *next_parent_path = NULL;
2912 err = add_ignores(ignores, root_path, "", -1,
2917 err = add_ignores(ignores, root_path, "", -1,
2922 err = got_path_dirname(&parent_path, path);
2924 if (err->code == GOT_ERR_BAD_PATH)
2925 return NULL; /* cannot traverse parent */
2929 err = add_ignores(ignores, root_path, parent_path, -1,
2933 err = add_ignores(ignores, root_path, parent_path, -1,
2937 err = got_path_dirname(&next_parent_path, parent_path);
2939 if (err->code == GOT_ERR_BAD_PATH)
2940 err = NULL; /* traversed everything */
2944 parent_path = next_parent_path;
2945 next_parent_path = NULL;
2949 free(next_parent_path);
2953 static const struct got_error *
2954 worktree_status(struct got_worktree *worktree, const char *path,
2955 struct got_fileindex *fileindex, struct got_repository *repo,
2956 got_worktree_status_cb status_cb, void *status_arg,
2957 got_cancel_cb cancel_cb, void *cancel_arg, int no_ignores,
2958 int report_unchanged)
2960 const struct got_error *err = NULL;
2962 struct got_fileindex_diff_dir_cb fdiff_cb;
2963 struct diff_dir_cb_arg arg;
2964 char *ondisk_path = NULL;
2966 TAILQ_INIT(&arg.ignores);
2968 if (asprintf(&ondisk_path, "%s%s%s",
2969 worktree->root_path, path[0] ? "/" : "", path) == -1)
2970 return got_error_from_errno("asprintf");
2972 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_DIRECTORY);
2974 if (errno != ENOTDIR && errno != ENOENT && errno != EACCES)
2975 err = got_error_from_errno2("open", ondisk_path);
2977 err = report_single_file_status(path, ondisk_path,
2978 fileindex, status_cb, status_arg, repo,
2981 fdiff_cb.diff_old_new = status_old_new;
2982 fdiff_cb.diff_old = status_old;
2983 fdiff_cb.diff_new = status_new;
2984 fdiff_cb.diff_traverse = status_traverse;
2985 arg.fileindex = fileindex;
2986 arg.worktree = worktree;
2987 arg.status_path = path;
2988 arg.status_path_len = strlen(path);
2990 arg.status_cb = status_cb;
2991 arg.status_arg = status_arg;
2992 arg.cancel_cb = cancel_cb;
2993 arg.cancel_arg = cancel_arg;
2994 arg.report_unchanged = report_unchanged;
2995 arg.no_ignores = no_ignores;
2997 err = add_ignores_from_parent_paths(&arg.ignores,
2998 worktree->root_path, path);
3002 err = got_fileindex_diff_dir(fileindex, fd,
3003 worktree->root_path, path, repo, &fdiff_cb, &arg);
3006 free_ignores(&arg.ignores);
3007 if (fd != -1 && close(fd) != 0 && err == NULL)
3008 err = got_error_from_errno("close");
3013 const struct got_error *
3014 got_worktree_status(struct got_worktree *worktree,
3015 struct got_pathlist_head *paths, struct got_repository *repo,
3016 got_worktree_status_cb status_cb, void *status_arg,
3017 got_cancel_cb cancel_cb, void *cancel_arg)
3019 const struct got_error *err = NULL;
3020 char *fileindex_path = NULL;
3021 struct got_fileindex *fileindex = NULL;
3022 struct got_pathlist_entry *pe;
3024 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3028 TAILQ_FOREACH(pe, paths, entry) {
3029 err = worktree_status(worktree, pe->path, fileindex, repo,
3030 status_cb, status_arg, cancel_cb, cancel_arg, 0, 0);
3034 free(fileindex_path);
3035 got_fileindex_free(fileindex);
3039 const struct got_error *
3040 got_worktree_resolve_path(char **wt_path, struct got_worktree *worktree,
3043 const struct got_error *err = NULL;
3044 char *resolved, *cwd = NULL, *path = NULL;
3049 resolved = realpath(arg, NULL);
3050 if (resolved == NULL) {
3051 if (errno != ENOENT)
3052 return got_error_from_errno2("realpath", arg);
3053 cwd = getcwd(NULL, 0);
3055 return got_error_from_errno("getcwd");
3056 if (asprintf(&resolved, "%s/%s", cwd, arg) == -1) {
3057 err = got_error_from_errno("asprintf");
3062 if (strncmp(got_worktree_get_root_path(worktree), resolved,
3063 strlen(got_worktree_get_root_path(worktree)))) {
3064 err = got_error_path(resolved, GOT_ERR_BAD_PATH);
3068 if (strlen(resolved) > strlen(got_worktree_get_root_path(worktree))) {
3069 err = got_path_skip_common_ancestor(&path,
3070 got_worktree_get_root_path(worktree), resolved);
3076 err = got_error_from_errno("strdup");
3081 /* XXX status walk can't deal with trailing slash! */
3083 while (len > 0 && path[len - 1] == '/') {
3084 path[len - 1] = '\0';
3097 struct schedule_addition_args {
3098 struct got_worktree *worktree;
3099 struct got_fileindex *fileindex;
3100 got_worktree_checkout_cb progress_cb;
3102 struct got_repository *repo;
3105 static const struct got_error *
3106 schedule_addition(void *arg, unsigned char status, unsigned char staged_status,
3107 const char *relpath, struct got_object_id *blob_id,
3108 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
3109 int dirfd, const char *de_name)
3111 struct schedule_addition_args *a = arg;
3112 const struct got_error *err = NULL;
3113 struct got_fileindex_entry *ie;
3117 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3119 return got_error_from_errno("asprintf");
3121 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3123 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd,
3127 /* Re-adding an existing entry is a no-op. */
3128 if (status == GOT_STATUS_ADD)
3130 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
3135 if (status != GOT_STATUS_UNVERSIONED) {
3136 err = got_error_path(ondisk_path, GOT_ERR_FILE_STATUS);
3140 err = got_fileindex_entry_alloc(&ie, relpath);
3143 err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL, 1);
3145 got_fileindex_entry_free(ie);
3148 err = got_fileindex_entry_add(a->fileindex, ie);
3150 got_fileindex_entry_free(ie);
3157 if (status == GOT_STATUS_ADD)
3159 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_ADD, relpath);
3162 const struct got_error *
3163 got_worktree_schedule_add(struct got_worktree *worktree,
3164 struct got_pathlist_head *paths,
3165 got_worktree_checkout_cb progress_cb, void *progress_arg,
3166 struct got_repository *repo, int no_ignores)
3168 struct got_fileindex *fileindex = NULL;
3169 char *fileindex_path = NULL;
3170 const struct got_error *err = NULL, *sync_err, *unlockerr;
3171 struct got_pathlist_entry *pe;
3172 struct schedule_addition_args saa;
3174 err = lock_worktree(worktree, LOCK_EX);
3178 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3182 saa.worktree = worktree;
3183 saa.fileindex = fileindex;
3184 saa.progress_cb = progress_cb;
3185 saa.progress_arg = progress_arg;
3188 TAILQ_FOREACH(pe, paths, entry) {
3189 err = worktree_status(worktree, pe->path, fileindex, repo,
3190 schedule_addition, &saa, NULL, NULL, no_ignores, 0);
3194 sync_err = sync_fileindex(fileindex, fileindex_path);
3195 if (sync_err && err == NULL)
3198 free(fileindex_path);
3200 got_fileindex_free(fileindex);
3201 unlockerr = lock_worktree(worktree, LOCK_SH);
3202 if (unlockerr && err == NULL)
3207 struct schedule_deletion_args {
3208 struct got_worktree *worktree;
3209 struct got_fileindex *fileindex;
3210 got_worktree_delete_cb progress_cb;
3212 struct got_repository *repo;
3213 int delete_local_mods;
3217 static const struct got_error *
3218 schedule_for_deletion(void *arg, unsigned char status,
3219 unsigned char staged_status, const char *relpath,
3220 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
3221 struct got_object_id *commit_id, int dirfd, const char *de_name)
3223 struct schedule_deletion_args *a = arg;
3224 const struct got_error *err = NULL;
3225 struct got_fileindex_entry *ie = NULL;
3227 char *ondisk_path, *parent = NULL;
3229 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3231 return got_error_path(relpath, GOT_ERR_BAD_PATH);
3233 staged_status = get_staged_status(ie);
3234 if (staged_status != GOT_STATUS_NO_CHANGE) {
3235 if (staged_status == GOT_STATUS_DELETE)
3237 return got_error_path(relpath, GOT_ERR_FILE_STAGED);
3240 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3242 return got_error_from_errno("asprintf");
3244 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd, de_name,
3249 if (status != GOT_STATUS_NO_CHANGE) {
3250 if (status == GOT_STATUS_DELETE)
3252 if (status == GOT_STATUS_MODIFY && !a->delete_local_mods) {
3253 err = got_error_path(relpath, GOT_ERR_FILE_MODIFIED);
3256 if (status != GOT_STATUS_MODIFY &&
3257 status != GOT_STATUS_MISSING) {
3258 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
3263 if (!a->keep_on_disk && status != GOT_STATUS_MISSING) {
3265 if (unlinkat(dirfd, de_name, 0) != 0) {
3266 err = got_error_from_errno2("unlinkat",
3270 } else if (unlink(ondisk_path) != 0) {
3271 err = got_error_from_errno2("unlink", ondisk_path);
3275 parent = dirname(ondisk_path);
3277 if (parent == NULL) {
3278 err = got_error_from_errno2("dirname", ondisk_path);
3281 while (parent && strcmp(parent, a->worktree->root_path) != 0) {
3282 if (rmdir(parent) == -1) {
3283 if (errno != ENOTEMPTY)
3284 err = got_error_from_errno2("rmdir",
3288 parent = dirname(parent);
3289 if (parent == NULL) {
3290 err = got_error_from_errno2("dirname", parent);
3296 got_fileindex_entry_mark_deleted_from_disk(ie);
3301 if (status == GOT_STATUS_DELETE)
3303 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE,
3304 staged_status, relpath);
3307 const struct got_error *
3308 got_worktree_schedule_delete(struct got_worktree *worktree,
3309 struct got_pathlist_head *paths, int delete_local_mods,
3310 got_worktree_delete_cb progress_cb, void *progress_arg,
3311 struct got_repository *repo, int keep_on_disk)
3313 struct got_fileindex *fileindex = NULL;
3314 char *fileindex_path = NULL;
3315 const struct got_error *err = NULL, *sync_err, *unlockerr;
3316 struct got_pathlist_entry *pe;
3317 struct schedule_deletion_args sda;
3319 err = lock_worktree(worktree, LOCK_EX);
3323 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3327 sda.worktree = worktree;
3328 sda.fileindex = fileindex;
3329 sda.progress_cb = progress_cb;
3330 sda.progress_arg = progress_arg;
3332 sda.delete_local_mods = delete_local_mods;
3333 sda.keep_on_disk = keep_on_disk;
3335 TAILQ_FOREACH(pe, paths, entry) {
3336 err = worktree_status(worktree, pe->path, fileindex, repo,
3337 schedule_for_deletion, &sda, NULL, NULL, 0, 1);
3341 sync_err = sync_fileindex(fileindex, fileindex_path);
3342 if (sync_err && err == NULL)
3345 free(fileindex_path);
3347 got_fileindex_free(fileindex);
3348 unlockerr = lock_worktree(worktree, LOCK_SH);
3349 if (unlockerr && err == NULL)
3354 static const struct got_error *
3355 copy_one_line(FILE *infile, FILE *outfile, FILE *rejectfile)
3357 const struct got_error *err = NULL;
3359 size_t linesize = 0, n;
3362 linelen = getline(&line, &linesize, infile);
3363 if (linelen == -1) {
3364 if (ferror(infile)) {
3365 err = got_error_from_errno("getline");
3371 n = fwrite(line, 1, linelen, outfile);
3373 err = got_ferror(outfile, GOT_ERR_IO);
3378 n = fwrite(line, 1, linelen, rejectfile);
3380 err = got_ferror(outfile, GOT_ERR_IO);
3387 static const struct got_error *
3388 skip_one_line(FILE *f)
3391 size_t linesize = 0;
3394 linelen = getline(&line, &linesize, f);
3395 if (linelen == -1) {
3397 return got_error_from_errno("getline");
3404 static const struct got_error *
3405 copy_change(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
3406 int start_old, int end_old, int start_new, int end_new,
3407 FILE *outfile, FILE *rejectfile)
3409 const struct got_error *err;
3411 /* Copy old file's lines leading up to patch. */
3412 while (!feof(f1) && *line_cur1 < start_old) {
3413 err = copy_one_line(f1, outfile, NULL);
3418 /* Skip new file's lines leading up to patch. */
3419 while (!feof(f2) && *line_cur2 < start_new) {
3421 err = copy_one_line(f2, NULL, rejectfile);
3423 err = skip_one_line(f2);
3428 /* Copy patched lines. */
3429 while (!feof(f2) && *line_cur2 <= end_new) {
3430 err = copy_one_line(f2, outfile, NULL);
3435 /* Skip over old file's replaced lines. */
3436 while (!feof(f1) && *line_cur1 <= end_old) {
3438 err = copy_one_line(f1, NULL, rejectfile);
3440 err = skip_one_line(f1);
3449 static const struct got_error *
3450 copy_remaining_content(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
3451 FILE *outfile, FILE *rejectfile)
3453 const struct got_error *err;
3456 /* Copy old file's lines until EOF. */
3458 err = copy_one_line(f1, outfile, NULL);
3465 /* Copy new file's lines until EOF. */
3467 err = copy_one_line(f2, NULL, rejectfile);
3477 static const struct got_error *
3478 apply_or_reject_change(int *choice, struct got_diff_change *change, int n,
3479 int nchanges, struct got_diff_state *ds, struct got_diff_args *args,
3480 int diff_flags, const char *relpath, FILE *f1, FILE *f2, int *line_cur1,
3481 int *line_cur2, FILE *outfile, FILE *rejectfile,
3482 got_worktree_patch_cb patch_cb, void *patch_arg)
3484 const struct got_error *err = NULL;
3485 int start_old = change->cv.a;
3486 int end_old = change->cv.b;
3487 int start_new = change->cv.c;
3488 int end_new = change->cv.d;
3492 *choice = GOT_PATCH_CHOICE_NONE;
3494 hunkfile = got_opentemp();
3495 if (hunkfile == NULL)
3496 return got_error_from_errno("got_opentemp");
3501 /* XXX TODO needs error checking */
3502 got_diff_dump_change(hunkfile, change, ds, args, f1, f2, diff_flags);
3504 if (fseek(f1, pos1, SEEK_SET) == -1) {
3505 err = got_ferror(f1, GOT_ERR_IO);
3508 if (fseek(f2, pos2, SEEK_SET) == -1) {
3509 err = got_ferror(f1, GOT_ERR_IO);
3512 if (fseek(hunkfile, 0L, SEEK_SET) == -1) {
3513 err = got_ferror(hunkfile, GOT_ERR_IO);
3517 err = (*patch_cb)(choice, patch_arg, GOT_STATUS_MODIFY, relpath,
3518 hunkfile, n, nchanges);
3523 case GOT_PATCH_CHOICE_YES:
3524 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
3525 end_old, start_new, end_new, outfile, rejectfile);
3527 case GOT_PATCH_CHOICE_NO:
3528 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
3529 end_old, start_new, end_new, rejectfile, outfile);
3531 case GOT_PATCH_CHOICE_QUIT:
3534 err = got_error(GOT_ERR_PATCH_CHOICE);
3538 if (hunkfile && fclose(hunkfile) == EOF && err == NULL)
3539 err = got_error_from_errno("fclose");
3543 struct revert_file_args {
3544 struct got_worktree *worktree;
3545 struct got_fileindex *fileindex;
3546 got_worktree_checkout_cb progress_cb;
3548 got_worktree_patch_cb patch_cb;
3550 struct got_repository *repo;
3553 static const struct got_error *
3554 create_patched_content(char **path_outfile, int reverse_patch,
3555 struct got_object_id *blob_id, const char *path2,
3556 int dirfd2, const char *de_name2,
3557 const char *relpath, struct got_repository *repo,
3558 got_worktree_patch_cb patch_cb, void *patch_arg)
3560 const struct got_error *err;
3561 struct got_blob_object *blob = NULL;
3562 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL;
3564 char *path1 = NULL, *id_str = NULL;
3565 struct stat sb1, sb2;
3566 struct got_diff_changes *changes = NULL;
3567 struct got_diff_state *ds = NULL;
3568 struct got_diff_args *args = NULL;
3569 struct got_diff_change *change;
3570 int diff_flags = 0, line_cur1 = 1, line_cur2 = 1, have_content = 0;
3573 *path_outfile = NULL;
3575 err = got_object_id_str(&id_str, blob_id);
3580 fd2 = openat(dirfd2, de_name2, O_RDONLY | O_NOFOLLOW);
3582 err = got_error_from_errno2("openat", path2);
3586 fd2 = open(path2, O_RDONLY | O_NOFOLLOW);
3588 err = got_error_from_errno2("open", path2);
3592 if (fstat(fd2, &sb2) == -1) {
3593 err = got_error_from_errno2("fstat", path2);
3597 f2 = fdopen(fd2, "r");
3599 err = got_error_from_errno2("fdopen", path2);
3604 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
3608 err = got_opentemp_named(&path1, &f1, "got-patched-blob");
3612 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
3616 if (stat(path1, &sb1) == -1) {
3617 err = got_error_from_errno2("stat", path1);
3621 err = got_diff_files(&changes, &ds, &args, &diff_flags,
3622 f1, sb1.st_size, id_str, f2, sb2.st_size, path2, 3, NULL);
3626 err = got_opentemp_named(path_outfile, &outfile, "got-patched-content");
3630 if (fseek(f1, 0L, SEEK_SET) == -1)
3631 return got_ferror(f1, GOT_ERR_IO);
3632 if (fseek(f2, 0L, SEEK_SET) == -1)
3633 return got_ferror(f2, GOT_ERR_IO);
3634 SIMPLEQ_FOREACH(change, &changes->entries, entry) {
3636 err = apply_or_reject_change(&choice, change, ++n,
3637 changes->nchanges, ds, args, diff_flags, relpath,
3638 f1, f2, &line_cur1, &line_cur2,
3639 reverse_patch ? NULL : outfile,
3640 reverse_patch ? outfile : NULL,
3641 patch_cb, patch_arg);
3644 if (choice == GOT_PATCH_CHOICE_YES)
3646 else if (choice == GOT_PATCH_CHOICE_QUIT)
3650 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
3651 reverse_patch ? NULL : outfile,
3652 reverse_patch ? outfile : NULL);
3656 if (chmod(*path_outfile, sb2.st_mode) == -1) {
3657 err = got_error_from_errno2("chmod", path2);
3664 got_object_blob_close(blob);
3665 if (f1 && fclose(f1) == EOF && err == NULL)
3666 err = got_error_from_errno2("fclose", path1);
3667 if (f2 && fclose(f2) == EOF && err == NULL)
3668 err = got_error_from_errno2("fclose", path2);
3669 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
3670 err = got_error_from_errno2("close", path2);
3671 if (outfile && fclose(outfile) == EOF && err == NULL)
3672 err = got_error_from_errno2("fclose", *path_outfile);
3673 if (path1 && unlink(path1) == -1 && err == NULL)
3674 err = got_error_from_errno2("unlink", path1);
3675 if (err || !have_content) {
3676 if (*path_outfile && unlink(*path_outfile) == -1 && err == NULL)
3677 err = got_error_from_errno2("unlink", *path_outfile);
3678 free(*path_outfile);
3679 *path_outfile = NULL;
3683 got_diff_state_free(ds);
3687 got_diff_free_changes(changes);
3692 static const struct got_error *
3693 revert_file(void *arg, unsigned char status, unsigned char staged_status,
3694 const char *relpath, struct got_object_id *blob_id,
3695 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
3696 int dirfd, const char *de_name)
3698 struct revert_file_args *a = arg;
3699 const struct got_error *err = NULL;
3700 char *parent_path = NULL;
3701 struct got_fileindex_entry *ie;
3702 struct got_tree_object *tree = NULL;
3703 struct got_object_id *tree_id = NULL;
3704 const struct got_tree_entry *te = NULL;
3705 char *tree_path = NULL, *te_name;
3706 char *ondisk_path = NULL, *path_content = NULL;
3707 struct got_blob_object *blob = NULL;
3709 /* Reverting a staged deletion is a no-op. */
3710 if (status == GOT_STATUS_DELETE &&
3711 staged_status != GOT_STATUS_NO_CHANGE)
3714 if (status == GOT_STATUS_UNVERSIONED)
3715 return (*a->progress_cb)(a->progress_arg,
3716 GOT_STATUS_UNVERSIONED, relpath);
3718 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3720 return got_error_path(relpath, GOT_ERR_BAD_PATH);
3722 /* Construct in-repository path of tree which contains this blob. */
3723 err = got_path_dirname(&parent_path, ie->path);
3725 if (err->code != GOT_ERR_BAD_PATH)
3727 parent_path = strdup("/");
3728 if (parent_path == NULL) {
3729 err = got_error_from_errno("strdup");
3733 if (got_path_is_root_dir(a->worktree->path_prefix)) {
3734 tree_path = strdup(parent_path);
3735 if (tree_path == NULL) {
3736 err = got_error_from_errno("strdup");
3740 if (got_path_is_root_dir(parent_path)) {
3741 tree_path = strdup(a->worktree->path_prefix);
3742 if (tree_path == NULL) {
3743 err = got_error_from_errno("strdup");
3747 if (asprintf(&tree_path, "%s/%s",
3748 a->worktree->path_prefix, parent_path) == -1) {
3749 err = got_error_from_errno("asprintf");
3755 err = got_object_id_by_path(&tree_id, a->repo,
3756 a->worktree->base_commit_id, tree_path);
3758 if (!(err->code == GOT_ERR_NO_TREE_ENTRY &&
3759 (status == GOT_STATUS_ADD ||
3760 staged_status == GOT_STATUS_ADD)))
3763 err = got_object_open_as_tree(&tree, a->repo, tree_id);
3767 te_name = basename(ie->path);
3768 if (te_name == NULL) {
3769 err = got_error_from_errno2("basename", ie->path);
3773 te = got_object_tree_find_entry(tree, te_name);
3774 if (te == NULL && status != GOT_STATUS_ADD &&
3775 staged_status != GOT_STATUS_ADD) {
3776 err = got_error(GOT_ERR_NO_TREE_ENTRY);
3782 case GOT_STATUS_ADD:
3784 int choice = GOT_PATCH_CHOICE_NONE;
3785 err = (*a->patch_cb)(&choice, a->patch_arg,
3786 status, ie->path, NULL, 1, 1);
3789 if (choice != GOT_PATCH_CHOICE_YES)
3792 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_REVERT,
3796 got_fileindex_entry_remove(a->fileindex, ie);
3798 case GOT_STATUS_DELETE:
3800 int choice = GOT_PATCH_CHOICE_NONE;
3801 err = (*a->patch_cb)(&choice, a->patch_arg,
3802 status, ie->path, NULL, 1, 1);
3805 if (choice != GOT_PATCH_CHOICE_YES)
3809 case GOT_STATUS_MODIFY:
3810 case GOT_STATUS_MODE_CHANGE:
3811 case GOT_STATUS_CONFLICT:
3812 case GOT_STATUS_MISSING: {
3813 struct got_object_id id;
3814 if (staged_status == GOT_STATUS_ADD ||
3815 staged_status == GOT_STATUS_MODIFY) {
3816 memcpy(id.sha1, ie->staged_blob_sha1,
3817 SHA1_DIGEST_LENGTH);
3819 memcpy(id.sha1, ie->blob_sha1,
3820 SHA1_DIGEST_LENGTH);
3821 err = got_object_open_as_blob(&blob, a->repo, &id, 8192);
3825 if (asprintf(&ondisk_path, "%s/%s",
3826 got_worktree_get_root_path(a->worktree), relpath) == -1) {
3827 err = got_error_from_errno("asprintf");
3831 if (a->patch_cb && (status == GOT_STATUS_MODIFY ||
3832 status == GOT_STATUS_CONFLICT)) {
3833 err = create_patched_content(&path_content, 1, &id,
3834 ondisk_path, dirfd, de_name, ie->path, a->repo,
3835 a->patch_cb, a->patch_arg);
3836 if (err || path_content == NULL)
3838 if (rename(path_content, ondisk_path) == -1) {
3839 err = got_error_from_errno3("rename",
3840 path_content, ondisk_path);
3844 err = install_blob(a->worktree, ondisk_path, ie->path,
3845 te ? te->mode : GOT_DEFAULT_FILE_MODE,
3846 got_fileindex_perms_to_st(ie), blob, 0, 1,
3847 a->repo, a->progress_cb, a->progress_arg);
3850 if (status == GOT_STATUS_DELETE ||
3851 status == GOT_STATUS_MODE_CHANGE) {
3852 err = got_fileindex_entry_update(ie,
3853 ondisk_path, blob->id.sha1,
3854 a->worktree->base_commit_id->sha1, 1);
3870 got_object_blob_close(blob);
3872 got_object_tree_close(tree);
3877 const struct got_error *
3878 got_worktree_revert(struct got_worktree *worktree,
3879 struct got_pathlist_head *paths,
3880 got_worktree_checkout_cb progress_cb, void *progress_arg,
3881 got_worktree_patch_cb patch_cb, void *patch_arg,
3882 struct got_repository *repo)
3884 struct got_fileindex *fileindex = NULL;
3885 char *fileindex_path = NULL;
3886 const struct got_error *err = NULL, *unlockerr = NULL;
3887 const struct got_error *sync_err = NULL;
3888 struct got_pathlist_entry *pe;
3889 struct revert_file_args rfa;
3891 err = lock_worktree(worktree, LOCK_EX);
3895 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3899 rfa.worktree = worktree;
3900 rfa.fileindex = fileindex;
3901 rfa.progress_cb = progress_cb;
3902 rfa.progress_arg = progress_arg;
3903 rfa.patch_cb = patch_cb;
3904 rfa.patch_arg = patch_arg;
3906 TAILQ_FOREACH(pe, paths, entry) {
3907 err = worktree_status(worktree, pe->path, fileindex, repo,
3908 revert_file, &rfa, NULL, NULL, 0, 0);
3912 sync_err = sync_fileindex(fileindex, fileindex_path);
3913 if (sync_err && err == NULL)
3916 free(fileindex_path);
3918 got_fileindex_free(fileindex);
3919 unlockerr = lock_worktree(worktree, LOCK_SH);
3920 if (unlockerr && err == NULL)
3926 free_commitable(struct got_commitable *ct)
3929 free(ct->in_repo_path);
3930 free(ct->ondisk_path);
3932 free(ct->base_blob_id);
3933 free(ct->staged_blob_id);
3934 free(ct->base_commit_id);
3938 struct collect_commitables_arg {
3939 struct got_pathlist_head *commitable_paths;
3940 struct got_repository *repo;
3941 struct got_worktree *worktree;
3942 int have_staged_files;
3945 static const struct got_error *
3946 collect_commitables(void *arg, unsigned char status,
3947 unsigned char staged_status, const char *relpath,
3948 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
3949 struct got_object_id *commit_id, int dirfd, const char *de_name)
3951 struct collect_commitables_arg *a = arg;
3952 const struct got_error *err = NULL;
3953 struct got_commitable *ct = NULL;
3954 struct got_pathlist_entry *new = NULL;
3955 char *parent_path = NULL, *path = NULL;
3958 if (a->have_staged_files) {
3959 if (staged_status != GOT_STATUS_MODIFY &&
3960 staged_status != GOT_STATUS_ADD &&
3961 staged_status != GOT_STATUS_DELETE)
3964 if (status == GOT_STATUS_CONFLICT)
3965 return got_error(GOT_ERR_COMMIT_CONFLICT);
3967 if (status != GOT_STATUS_MODIFY &&
3968 status != GOT_STATUS_MODE_CHANGE &&
3969 status != GOT_STATUS_ADD &&
3970 status != GOT_STATUS_DELETE)
3974 if (asprintf(&path, "/%s", relpath) == -1) {
3975 err = got_error_from_errno("asprintf");
3978 if (strcmp(path, "/") == 0) {
3979 parent_path = strdup("");
3980 if (parent_path == NULL)
3981 return got_error_from_errno("strdup");
3983 err = got_path_dirname(&parent_path, path);
3988 ct = calloc(1, sizeof(*ct));
3990 err = got_error_from_errno("calloc");
3994 if (asprintf(&ct->ondisk_path, "%s/%s", a->worktree->root_path,
3996 err = got_error_from_errno("asprintf");
3999 if (status == GOT_STATUS_DELETE || staged_status == GOT_STATUS_DELETE) {
4000 sb.st_mode = GOT_DEFAULT_FILE_MODE;
4003 if (fstatat(dirfd, de_name, &sb,
4004 AT_SYMLINK_NOFOLLOW) == -1) {
4005 err = got_error_from_errno2("fstatat",
4009 } else if (lstat(ct->ondisk_path, &sb) == -1) {
4010 err = got_error_from_errno2("lstat", ct->ondisk_path);
4013 ct->mode = sb.st_mode;
4016 if (asprintf(&ct->in_repo_path, "%s%s%s", a->worktree->path_prefix,
4017 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
4019 err = got_error_from_errno("asprintf");
4023 ct->status = status;
4024 ct->staged_status = staged_status;
4025 ct->blob_id = NULL; /* will be filled in when blob gets created */
4026 if (ct->status != GOT_STATUS_ADD &&
4027 ct->staged_status != GOT_STATUS_ADD) {
4028 ct->base_blob_id = got_object_id_dup(blob_id);
4029 if (ct->base_blob_id == NULL) {
4030 err = got_error_from_errno("got_object_id_dup");
4033 ct->base_commit_id = got_object_id_dup(commit_id);
4034 if (ct->base_commit_id == NULL) {
4035 err = got_error_from_errno("got_object_id_dup");
4039 if (ct->staged_status == GOT_STATUS_ADD ||
4040 ct->staged_status == GOT_STATUS_MODIFY) {
4041 ct->staged_blob_id = got_object_id_dup(staged_blob_id);
4042 if (ct->staged_blob_id == NULL) {
4043 err = got_error_from_errno("got_object_id_dup");
4047 ct->path = strdup(path);
4048 if (ct->path == NULL) {
4049 err = got_error_from_errno("strdup");
4052 err = got_pathlist_insert(&new, a->commitable_paths, ct->path, ct);
4054 if (ct && (err || new == NULL))
4055 free_commitable(ct);
4061 static const struct got_error *write_tree(struct got_object_id **, int *,
4062 struct got_tree_object *, const char *, struct got_pathlist_head *,
4063 got_worktree_status_cb status_cb, void *status_arg,
4064 struct got_repository *);
4066 static const struct got_error *
4067 write_subtree(struct got_object_id **new_subtree_id, int *nentries,
4068 struct got_tree_entry *te, const char *parent_path,
4069 struct got_pathlist_head *commitable_paths,
4070 got_worktree_status_cb status_cb, void *status_arg,
4071 struct got_repository *repo)
4073 const struct got_error *err = NULL;
4074 struct got_tree_object *subtree;
4077 if (asprintf(&subpath, "%s%s%s", parent_path,
4078 got_path_is_root_dir(parent_path) ? "" : "/", te->name) == -1)
4079 return got_error_from_errno("asprintf");
4081 err = got_object_open_as_tree(&subtree, repo, &te->id);
4085 err = write_tree(new_subtree_id, nentries, subtree, subpath,
4086 commitable_paths, status_cb, status_arg, repo);
4087 got_object_tree_close(subtree);
4092 static const struct got_error *
4093 match_ct_parent_path(int *match, struct got_commitable *ct, const char *path)
4095 const struct got_error *err = NULL;
4096 char *ct_parent_path = NULL;
4100 if (strchr(ct->in_repo_path, '/') == NULL) {
4101 *match = got_path_is_root_dir(path);
4105 err = got_path_dirname(&ct_parent_path, ct->in_repo_path);
4108 *match = (strcmp(path, ct_parent_path) == 0);
4109 free(ct_parent_path);
4114 get_ct_file_mode(struct got_commitable *ct)
4116 return S_IFREG | (ct->mode & ((S_IRWXU | S_IRWXG | S_IRWXO)));
4119 static const struct got_error *
4120 alloc_modified_blob_tree_entry(struct got_tree_entry **new_te,
4121 struct got_tree_entry *te, struct got_commitable *ct)
4123 const struct got_error *err = NULL;
4127 err = got_object_tree_entry_dup(new_te, te);
4131 (*new_te)->mode = get_ct_file_mode(ct);
4133 if (ct->staged_status == GOT_STATUS_MODIFY)
4134 memcpy(&(*new_te)->id, ct->staged_blob_id,
4135 sizeof((*new_te)->id));
4137 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
4139 if (err && *new_te) {
4146 static const struct got_error *
4147 alloc_added_blob_tree_entry(struct got_tree_entry **new_te,
4148 struct got_commitable *ct)
4150 const struct got_error *err = NULL;
4155 *new_te = calloc(1, sizeof(**new_te));
4156 if (*new_te == NULL)
4157 return got_error_from_errno("calloc");
4159 ct_name = basename(ct->path);
4160 if (ct_name == NULL) {
4161 err = got_error_from_errno2("basename", ct->path);
4164 if (strlcpy((*new_te)->name, ct_name, sizeof((*new_te)->name)) >=
4165 sizeof((*new_te)->name)) {
4166 err = got_error(GOT_ERR_NO_SPACE);
4170 (*new_te)->mode = get_ct_file_mode(ct);
4172 if (ct->staged_status == GOT_STATUS_ADD)
4173 memcpy(&(*new_te)->id, ct->staged_blob_id,
4174 sizeof((*new_te)->id));
4176 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
4178 if (err && *new_te) {
4185 static const struct got_error *
4186 insert_tree_entry(struct got_tree_entry *new_te,
4187 struct got_pathlist_head *paths)
4189 const struct got_error *err = NULL;
4190 struct got_pathlist_entry *new_pe;
4192 err = got_pathlist_insert(&new_pe, paths, new_te->name, new_te);
4196 return got_error(GOT_ERR_TREE_DUP_ENTRY);
4200 static const struct got_error *
4201 report_ct_status(struct got_commitable *ct,
4202 got_worktree_status_cb status_cb, void *status_arg)
4204 const char *ct_path = ct->path;
4205 unsigned char status;
4207 while (ct_path[0] == '/')
4210 if (ct->staged_status != GOT_STATUS_NO_CHANGE)
4211 status = ct->staged_status;
4213 status = ct->status;
4215 return (*status_cb)(status_arg, status, GOT_STATUS_NO_CHANGE,
4216 ct_path, ct->blob_id, NULL, NULL, -1, NULL);
4219 static const struct got_error *
4220 match_modified_subtree(int *modified, struct got_tree_entry *te,
4221 const char *base_tree_path, struct got_pathlist_head *commitable_paths)
4223 const struct got_error *err = NULL;
4224 struct got_pathlist_entry *pe;
4229 if (asprintf(&te_path, "%s%s%s", base_tree_path,
4230 got_path_is_root_dir(base_tree_path) ? "" : "/",
4232 return got_error_from_errno("asprintf");
4234 TAILQ_FOREACH(pe, commitable_paths, entry) {
4235 struct got_commitable *ct = pe->data;
4236 *modified = got_path_is_child(ct->in_repo_path, te_path,
4246 static const struct got_error *
4247 match_deleted_or_modified_ct(struct got_commitable **ctp,
4248 struct got_tree_entry *te, const char *base_tree_path,
4249 struct got_pathlist_head *commitable_paths)
4251 const struct got_error *err = NULL;
4252 struct got_pathlist_entry *pe;
4256 TAILQ_FOREACH(pe, commitable_paths, entry) {
4257 struct got_commitable *ct = pe->data;
4258 char *ct_name = NULL;
4261 if (ct->staged_status == GOT_STATUS_NO_CHANGE) {
4262 if (ct->status != GOT_STATUS_MODIFY &&
4263 ct->status != GOT_STATUS_MODE_CHANGE &&
4264 ct->status != GOT_STATUS_DELETE)
4267 if (ct->staged_status != GOT_STATUS_MODIFY &&
4268 ct->staged_status != GOT_STATUS_DELETE)
4272 if (got_object_id_cmp(ct->base_blob_id, &te->id) != 0)
4275 err = match_ct_parent_path(&path_matches, ct, base_tree_path);
4281 ct_name = basename(pe->path);
4282 if (ct_name == NULL)
4283 return got_error_from_errno2("basename", pe->path);
4285 if (strcmp(te->name, ct_name) != 0)
4295 static const struct got_error *
4296 make_subtree_for_added_blob(struct got_tree_entry **new_tep,
4297 const char *child_path, const char *path_base_tree,
4298 struct got_pathlist_head *commitable_paths,
4299 got_worktree_status_cb status_cb, void *status_arg,
4300 struct got_repository *repo)
4302 const struct got_error *err = NULL;
4303 struct got_tree_entry *new_te;
4305 struct got_object_id *id = NULL;
4310 if (asprintf(&subtree_path, "%s%s%s", path_base_tree,
4311 got_path_is_root_dir(path_base_tree) ? "" : "/",
4313 return got_error_from_errno("asprintf");
4315 new_te = calloc(1, sizeof(*new_te));
4317 return got_error_from_errno("calloc");
4318 new_te->mode = S_IFDIR;
4320 if (strlcpy(new_te->name, child_path, sizeof(new_te->name)) >=
4321 sizeof(new_te->name)) {
4322 err = got_error(GOT_ERR_NO_SPACE);
4325 err = write_tree(&id, &nentries, NULL, subtree_path,
4326 commitable_paths, status_cb, status_arg, repo);
4331 memcpy(&new_te->id, id, sizeof(new_te->id));
4340 static const struct got_error *
4341 write_tree(struct got_object_id **new_tree_id, int *nentries,
4342 struct got_tree_object *base_tree, const char *path_base_tree,
4343 struct got_pathlist_head *commitable_paths,
4344 got_worktree_status_cb status_cb, void *status_arg,
4345 struct got_repository *repo)
4347 const struct got_error *err = NULL;
4348 struct got_pathlist_head paths;
4349 struct got_tree_entry *te, *new_te = NULL;
4350 struct got_pathlist_entry *pe;
4355 /* Insert, and recurse into, newly added entries first. */
4356 TAILQ_FOREACH(pe, commitable_paths, entry) {
4357 struct got_commitable *ct = pe->data;
4358 char *child_path = NULL, *slash;
4360 if ((ct->status != GOT_STATUS_ADD &&
4361 ct->staged_status != GOT_STATUS_ADD) ||
4362 (ct->flags & GOT_COMMITABLE_ADDED))
4365 if (!got_path_is_child(pe->path, path_base_tree,
4366 strlen(path_base_tree)))
4369 err = got_path_skip_common_ancestor(&child_path, path_base_tree,
4374 slash = strchr(child_path, '/');
4375 if (slash == NULL) {
4376 err = alloc_added_blob_tree_entry(&new_te, ct);
4379 err = report_ct_status(ct, status_cb, status_arg);
4382 ct->flags |= GOT_COMMITABLE_ADDED;
4383 err = insert_tree_entry(new_te, &paths);
4388 *slash = '\0'; /* trim trailing path components */
4389 if (base_tree == NULL ||
4390 got_object_tree_find_entry(base_tree, child_path)
4392 err = make_subtree_for_added_blob(&new_te,
4393 child_path, path_base_tree,
4394 commitable_paths, status_cb, status_arg,
4398 err = insert_tree_entry(new_te, &paths);
4407 int i, nbase_entries;
4408 /* Handle modified and deleted entries. */
4409 nbase_entries = got_object_tree_get_nentries(base_tree);
4410 for (i = 0; i < nbase_entries; i++) {
4411 struct got_commitable *ct = NULL;
4413 te = got_object_tree_get_entry(base_tree, i);
4414 if (got_object_tree_entry_is_submodule(te)) {
4415 /* Entry is a submodule; just copy it. */
4416 err = got_object_tree_entry_dup(&new_te, te);
4419 err = insert_tree_entry(new_te, &paths);
4426 if (S_ISDIR(te->mode)) {
4428 err = got_object_tree_entry_dup(&new_te, te);
4431 err = match_modified_subtree(&modified, te,
4432 path_base_tree, commitable_paths);
4435 /* Avoid recursion into unmodified subtrees. */
4437 struct got_object_id *new_id;
4439 err = write_subtree(&new_id,
4441 path_base_tree, commitable_paths,
4442 status_cb, status_arg, repo);
4445 if (nsubentries == 0) {
4446 /* All entries were deleted. */
4450 memcpy(&new_te->id, new_id,
4451 sizeof(new_te->id));
4454 err = insert_tree_entry(new_te, &paths);
4461 err = match_deleted_or_modified_ct(&ct, te,
4462 path_base_tree, commitable_paths);
4466 /* NB: Deleted entries get dropped here. */
4467 if (ct->status == GOT_STATUS_MODIFY ||
4468 ct->status == GOT_STATUS_MODE_CHANGE ||
4469 ct->staged_status == GOT_STATUS_MODIFY) {
4470 err = alloc_modified_blob_tree_entry(
4474 err = insert_tree_entry(new_te, &paths);
4479 err = report_ct_status(ct, status_cb,
4484 /* Entry is unchanged; just copy it. */
4485 err = got_object_tree_entry_dup(&new_te, te);
4488 err = insert_tree_entry(new_te, &paths);
4496 /* Write new list of entries; deleted entries have been dropped. */
4497 err = got_object_tree_create(new_tree_id, &paths, *nentries, repo);
4499 got_pathlist_free(&paths);
4503 static const struct got_error *
4504 update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
4505 struct got_object_id *new_base_commit_id, struct got_fileindex *fileindex,
4506 int have_staged_files)
4508 const struct got_error *err = NULL;
4509 struct got_pathlist_entry *pe;
4511 TAILQ_FOREACH(pe, commitable_paths, entry) {
4512 struct got_fileindex_entry *ie;
4513 struct got_commitable *ct = pe->data;
4515 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
4517 if (ct->status == GOT_STATUS_DELETE ||
4518 ct->staged_status == GOT_STATUS_DELETE) {
4519 got_fileindex_entry_remove(fileindex, ie);
4520 } else if (ct->staged_status == GOT_STATUS_ADD ||
4521 ct->staged_status == GOT_STATUS_MODIFY) {
4522 got_fileindex_entry_stage_set(ie,
4523 GOT_FILEIDX_STAGE_NONE);
4524 err = got_fileindex_entry_update(ie,
4525 ct->ondisk_path, ct->staged_blob_id->sha1,
4526 new_base_commit_id->sha1,
4527 !have_staged_files);
4529 err = got_fileindex_entry_update(ie,
4530 ct->ondisk_path, ct->blob_id->sha1,
4531 new_base_commit_id->sha1,
4532 !have_staged_files);
4534 err = got_fileindex_entry_alloc(&ie, pe->path);
4537 err = got_fileindex_entry_update(ie, ct->ondisk_path,
4538 ct->blob_id->sha1, new_base_commit_id->sha1, 1);
4540 got_fileindex_entry_free(ie);
4543 err = got_fileindex_entry_add(fileindex, ie);
4545 got_fileindex_entry_free(ie);
4554 static const struct got_error *
4555 check_out_of_date(const char *in_repo_path, unsigned char status,
4556 unsigned char staged_status, struct got_object_id *base_blob_id,
4557 struct got_object_id *base_commit_id,
4558 struct got_object_id *head_commit_id, struct got_repository *repo,
4561 const struct got_error *err = NULL;
4562 struct got_object_id *id = NULL;
4564 if (status != GOT_STATUS_ADD && staged_status != GOT_STATUS_ADD) {
4565 /* Trivial case: base commit == head commit */
4566 if (got_object_id_cmp(base_commit_id, head_commit_id) == 0)
4569 * Ensure file content which local changes were based
4570 * on matches file content in the branch head.
4572 err = got_object_id_by_path(&id, repo, head_commit_id,
4575 if (err->code == GOT_ERR_NO_TREE_ENTRY)
4576 err = got_error(ood_errcode);
4578 } else if (got_object_id_cmp(id, base_blob_id) != 0)
4579 err = got_error(ood_errcode);
4581 /* Require that added files don't exist in the branch head. */
4582 err = got_object_id_by_path(&id, repo, head_commit_id,
4584 if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
4586 err = id ? got_error(ood_errcode) : NULL;
4593 const struct got_error *
4594 commit_worktree(struct got_object_id **new_commit_id,
4595 struct got_pathlist_head *commitable_paths,
4596 struct got_object_id *head_commit_id, struct got_worktree *worktree,
4597 const char *author, const char *committer,
4598 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
4599 got_worktree_status_cb status_cb, void *status_arg,
4600 struct got_repository *repo)
4602 const struct got_error *err = NULL, *unlockerr = NULL;
4603 struct got_pathlist_entry *pe;
4604 const char *head_ref_name = NULL;
4605 struct got_commit_object *head_commit = NULL;
4606 struct got_reference *head_ref2 = NULL;
4607 struct got_object_id *head_commit_id2 = NULL;
4608 struct got_tree_object *head_tree = NULL;
4609 struct got_object_id *new_tree_id = NULL;
4611 struct got_object_id_queue parent_ids;
4612 struct got_object_qid *pid = NULL;
4613 char *logmsg = NULL;
4615 *new_commit_id = NULL;
4617 SIMPLEQ_INIT(&parent_ids);
4619 err = got_object_open_as_commit(&head_commit, repo, head_commit_id);
4623 err = got_object_open_as_tree(&head_tree, repo, head_commit->tree_id);
4627 if (commit_msg_cb != NULL) {
4628 err = commit_msg_cb(commitable_paths, &logmsg, commit_arg);
4633 if (logmsg == NULL || strlen(logmsg) == 0) {
4634 err = got_error(GOT_ERR_COMMIT_MSG_EMPTY);
4638 /* Create blobs from added and modified files and record their IDs. */
4639 TAILQ_FOREACH(pe, commitable_paths, entry) {
4640 struct got_commitable *ct = pe->data;
4643 /* Blobs for staged files already exist. */
4644 if (ct->staged_status == GOT_STATUS_ADD ||
4645 ct->staged_status == GOT_STATUS_MODIFY)
4648 if (ct->status != GOT_STATUS_ADD &&
4649 ct->status != GOT_STATUS_MODIFY &&
4650 ct->status != GOT_STATUS_MODE_CHANGE)
4653 if (asprintf(&ondisk_path, "%s/%s",
4654 worktree->root_path, pe->path) == -1) {
4655 err = got_error_from_errno("asprintf");
4658 err = got_object_blob_create(&ct->blob_id, ondisk_path, repo);
4664 /* Recursively write new tree objects. */
4665 err = write_tree(&new_tree_id, &nentries, head_tree, "/",
4666 commitable_paths, status_cb, status_arg, repo);
4670 err = got_object_qid_alloc(&pid, worktree->base_commit_id);
4673 SIMPLEQ_INSERT_TAIL(&parent_ids, pid, entry);
4674 err = got_object_commit_create(new_commit_id, new_tree_id, &parent_ids,
4675 1, author, time(NULL), committer, time(NULL), logmsg, repo);
4676 got_object_qid_free(pid);
4682 /* Check if a concurrent commit to our branch has occurred. */
4683 head_ref_name = got_worktree_get_head_ref_name(worktree);
4684 if (head_ref_name == NULL) {
4685 err = got_error_from_errno("got_worktree_get_head_ref_name");
4688 /* Lock the reference here to prevent concurrent modification. */
4689 err = got_ref_open(&head_ref2, repo, head_ref_name, 1);
4692 err = got_ref_resolve(&head_commit_id2, repo, head_ref2);
4695 if (got_object_id_cmp(head_commit_id, head_commit_id2) != 0) {
4696 err = got_error(GOT_ERR_COMMIT_HEAD_CHANGED);
4699 /* Update branch head in repository. */
4700 err = got_ref_change_ref(head_ref2, *new_commit_id);
4703 err = got_ref_write(head_ref2, repo);
4707 err = got_worktree_set_base_commit_id(worktree, repo, *new_commit_id);
4711 err = ref_base_commit(worktree, repo);
4716 got_object_tree_close(head_tree);
4718 got_object_commit_close(head_commit);
4719 free(head_commit_id2);
4721 unlockerr = got_ref_unlock(head_ref2);
4722 if (unlockerr && err == NULL)
4724 got_ref_close(head_ref2);
4729 static const struct got_error *
4730 check_path_is_commitable(const char *path,
4731 struct got_pathlist_head *commitable_paths)
4733 struct got_pathlist_entry *cpe = NULL;
4734 size_t path_len = strlen(path);
4736 TAILQ_FOREACH(cpe, commitable_paths, entry) {
4737 struct got_commitable *ct = cpe->data;
4738 const char *ct_path = ct->path;
4740 while (ct_path[0] == '/')
4743 if (strcmp(path, ct_path) == 0 ||
4744 got_path_is_child(ct_path, path, path_len))
4749 return got_error_path(path, GOT_ERR_BAD_PATH);
4754 static const struct got_error *
4755 check_staged_file(void *arg, struct got_fileindex_entry *ie)
4757 int *have_staged_files = arg;
4759 if (got_fileindex_entry_stage_get(ie) != GOT_FILEIDX_STAGE_NONE) {
4760 *have_staged_files = 1;
4761 return got_error(GOT_ERR_CANCELLED);
4767 static const struct got_error *
4768 check_non_staged_files(struct got_fileindex *fileindex,
4769 struct got_pathlist_head *paths)
4771 struct got_pathlist_entry *pe;
4772 struct got_fileindex_entry *ie;
4774 TAILQ_FOREACH(pe, paths, entry) {
4775 if (pe->path[0] == '\0')
4777 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
4779 return got_error_path(pe->path, GOT_ERR_BAD_PATH);
4780 if (got_fileindex_entry_stage_get(ie) == GOT_FILEIDX_STAGE_NONE)
4781 return got_error_path(pe->path,
4782 GOT_ERR_FILE_NOT_STAGED);
4788 const struct got_error *
4789 got_worktree_commit(struct got_object_id **new_commit_id,
4790 struct got_worktree *worktree, struct got_pathlist_head *paths,
4791 const char *author, const char *committer,
4792 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
4793 got_worktree_status_cb status_cb, void *status_arg,
4794 struct got_repository *repo)
4796 const struct got_error *err = NULL, *unlockerr = NULL, *sync_err;
4797 struct got_fileindex *fileindex = NULL;
4798 char *fileindex_path = NULL;
4799 struct got_pathlist_head commitable_paths;
4800 struct collect_commitables_arg cc_arg;
4801 struct got_pathlist_entry *pe;
4802 struct got_reference *head_ref = NULL;
4803 struct got_object_id *head_commit_id = NULL;
4804 int have_staged_files = 0;
4806 *new_commit_id = NULL;
4808 TAILQ_INIT(&commitable_paths);
4810 err = lock_worktree(worktree, LOCK_EX);
4814 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
4818 err = got_ref_resolve(&head_commit_id, repo, head_ref);
4822 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4826 err = got_fileindex_for_each_entry_safe(fileindex, check_staged_file,
4827 &have_staged_files);
4828 if (err && err->code != GOT_ERR_CANCELLED)
4830 if (have_staged_files) {
4831 err = check_non_staged_files(fileindex, paths);
4836 cc_arg.commitable_paths = &commitable_paths;
4837 cc_arg.worktree = worktree;
4839 cc_arg.have_staged_files = have_staged_files;
4840 TAILQ_FOREACH(pe, paths, entry) {
4841 err = worktree_status(worktree, pe->path, fileindex, repo,
4842 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
4847 if (TAILQ_EMPTY(&commitable_paths)) {
4848 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
4852 TAILQ_FOREACH(pe, paths, entry) {
4853 err = check_path_is_commitable(pe->path, &commitable_paths);
4858 TAILQ_FOREACH(pe, &commitable_paths, entry) {
4859 struct got_commitable *ct = pe->data;
4860 const char *ct_path = ct->in_repo_path;
4862 while (ct_path[0] == '/')
4864 err = check_out_of_date(ct_path, ct->status,
4865 ct->staged_status, ct->base_blob_id, ct->base_commit_id,
4866 head_commit_id, repo, GOT_ERR_COMMIT_OUT_OF_DATE);
4872 err = commit_worktree(new_commit_id, &commitable_paths,
4873 head_commit_id, worktree, author, committer,
4874 commit_msg_cb, commit_arg, status_cb, status_arg, repo);
4878 err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
4879 fileindex, have_staged_files);
4880 sync_err = sync_fileindex(fileindex, fileindex_path);
4881 if (sync_err && err == NULL)
4885 got_fileindex_free(fileindex);
4886 free(fileindex_path);
4887 unlockerr = lock_worktree(worktree, LOCK_SH);
4888 if (unlockerr && err == NULL)
4890 TAILQ_FOREACH(pe, &commitable_paths, entry) {
4891 struct got_commitable *ct = pe->data;
4892 free_commitable(ct);
4894 got_pathlist_free(&commitable_paths);
4899 got_commitable_get_path(struct got_commitable *ct)
4905 got_commitable_get_status(struct got_commitable *ct)
4910 struct check_rebase_ok_arg {
4911 struct got_worktree *worktree;
4912 struct got_repository *repo;
4915 static const struct got_error *
4916 check_rebase_ok(void *arg, struct got_fileindex_entry *ie)
4918 const struct got_error *err = NULL;
4919 struct check_rebase_ok_arg *a = arg;
4920 unsigned char status;
4924 /* Reject rebase of a work tree with mixed base commits. */
4925 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
4926 SHA1_DIGEST_LENGTH))
4927 return got_error(GOT_ERR_MIXED_COMMITS);
4929 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
4931 return got_error_from_errno("asprintf");
4933 /* Reject rebase of a work tree with modified or staged files. */
4934 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
4939 if (status != GOT_STATUS_NO_CHANGE)
4940 return got_error(GOT_ERR_MODIFIED);
4941 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
4942 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
4947 const struct got_error *
4948 got_worktree_rebase_prepare(struct got_reference **new_base_branch_ref,
4949 struct got_reference **tmp_branch, struct got_fileindex **fileindex,
4950 struct got_worktree *worktree, struct got_reference *branch,
4951 struct got_repository *repo)
4953 const struct got_error *err = NULL;
4954 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
4955 char *branch_ref_name = NULL;
4956 char *fileindex_path = NULL;
4957 struct check_rebase_ok_arg ok_arg;
4958 struct got_reference *wt_branch = NULL, *branch_ref = NULL;
4959 struct got_object_id *wt_branch_tip = NULL;
4961 *new_base_branch_ref = NULL;
4965 err = lock_worktree(worktree, LOCK_EX);
4969 err = open_fileindex(fileindex, &fileindex_path, worktree);
4973 ok_arg.worktree = worktree;
4975 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
4980 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
4984 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
4988 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
4992 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
4997 err = got_ref_resolve(&wt_branch_tip, repo, wt_branch);
5000 if (got_object_id_cmp(worktree->base_commit_id, wt_branch_tip) != 0) {
5001 err = got_error(GOT_ERR_REBASE_OUT_OF_DATE);
5005 err = got_ref_alloc_symref(new_base_branch_ref,
5006 new_base_branch_ref_name, wt_branch);
5009 err = got_ref_write(*new_base_branch_ref, repo);
5013 /* TODO Lock original branch's ref while rebasing? */
5015 err = got_ref_alloc_symref(&branch_ref, branch_ref_name, branch);
5019 err = got_ref_write(branch_ref, repo);
5023 err = got_ref_alloc(tmp_branch, tmp_branch_name,
5024 worktree->base_commit_id);
5027 err = got_ref_write(*tmp_branch, repo);
5031 err = got_worktree_set_head_ref(worktree, *tmp_branch);
5035 free(fileindex_path);
5036 free(tmp_branch_name);
5037 free(new_base_branch_ref_name);
5038 free(branch_ref_name);
5040 got_ref_close(branch_ref);
5042 got_ref_close(wt_branch);
5043 free(wt_branch_tip);
5045 if (*new_base_branch_ref) {
5046 got_ref_close(*new_base_branch_ref);
5047 *new_base_branch_ref = NULL;
5050 got_ref_close(*tmp_branch);
5054 got_fileindex_free(*fileindex);
5057 lock_worktree(worktree, LOCK_SH);
5062 const struct got_error *
5063 got_worktree_rebase_continue(struct got_object_id **commit_id,
5064 struct got_reference **new_base_branch, struct got_reference **tmp_branch,
5065 struct got_reference **branch, struct got_fileindex **fileindex,
5066 struct got_worktree *worktree, struct got_repository *repo)
5068 const struct got_error *err;
5069 char *commit_ref_name = NULL, *new_base_branch_ref_name = NULL;
5070 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
5071 struct got_reference *commit_ref = NULL, *branch_ref = NULL;
5072 char *fileindex_path = NULL;
5073 int have_staged_files = 0;
5076 *new_base_branch = NULL;
5081 err = lock_worktree(worktree, LOCK_EX);
5085 err = open_fileindex(fileindex, &fileindex_path, worktree);
5089 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
5090 &have_staged_files);
5091 if (err && err->code != GOT_ERR_CANCELLED)
5093 if (have_staged_files) {
5094 err = got_error(GOT_ERR_STAGED_PATHS);
5098 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5102 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
5106 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
5110 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
5114 err = got_ref_open(&branch_ref, repo, branch_ref_name, 0);
5118 err = got_ref_open(branch, repo,
5119 got_ref_get_symref_target(branch_ref), 0);
5123 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5127 err = got_ref_resolve(commit_id, repo, commit_ref);
5131 err = got_ref_open(new_base_branch, repo,
5132 new_base_branch_ref_name, 0);
5136 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
5140 free(commit_ref_name);
5141 free(branch_ref_name);
5142 free(fileindex_path);
5144 got_ref_close(commit_ref);
5146 got_ref_close(branch_ref);
5151 got_ref_close(*tmp_branch);
5154 if (*new_base_branch) {
5155 got_ref_close(*new_base_branch);
5156 *new_base_branch = NULL;
5159 got_ref_close(*branch);
5163 got_fileindex_free(*fileindex);
5166 lock_worktree(worktree, LOCK_SH);
5171 const struct got_error *
5172 got_worktree_rebase_in_progress(int *in_progress, struct got_worktree *worktree)
5174 const struct got_error *err;
5175 char *tmp_branch_name = NULL;
5177 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5181 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
5182 free(tmp_branch_name);
5186 static const struct got_error *
5187 collect_rebase_commit_msg(struct got_pathlist_head *commitable_paths,
5188 char **logmsg, void *arg)
5194 static const struct got_error *
5195 rebase_status(void *arg, unsigned char status, unsigned char staged_status,
5196 const char *path, struct got_object_id *blob_id,
5197 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
5198 int dirfd, const char *de_name)
5203 struct collect_merged_paths_arg {
5204 got_worktree_checkout_cb progress_cb;
5206 struct got_pathlist_head *merged_paths;
5209 static const struct got_error *
5210 collect_merged_paths(void *arg, unsigned char status, const char *path)
5212 const struct got_error *err;
5213 struct collect_merged_paths_arg *a = arg;
5215 struct got_pathlist_entry *new;
5217 err = (*a->progress_cb)(a->progress_arg, status, path);
5221 if (status != GOT_STATUS_MERGE &&
5222 status != GOT_STATUS_ADD &&
5223 status != GOT_STATUS_DELETE &&
5224 status != GOT_STATUS_CONFLICT)
5229 return got_error_from_errno("strdup");
5231 err = got_pathlist_insert(&new, a->merged_paths, p, NULL);
5232 if (err || new == NULL)
5238 got_worktree_rebase_pathlist_free(struct got_pathlist_head *merged_paths)
5240 struct got_pathlist_entry *pe;
5242 TAILQ_FOREACH(pe, merged_paths, entry)
5243 free((char *)pe->path);
5245 got_pathlist_free(merged_paths);
5248 static const struct got_error *
5249 store_commit_id(const char *commit_ref_name, struct got_object_id *commit_id,
5250 int is_rebase, struct got_repository *repo)
5252 const struct got_error *err;
5253 struct got_reference *commit_ref = NULL;
5255 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5257 if (err->code != GOT_ERR_NOT_REF)
5259 err = got_ref_alloc(&commit_ref, commit_ref_name, commit_id);
5262 err = got_ref_write(commit_ref, repo);
5265 } else if (is_rebase) {
5266 struct got_object_id *stored_id;
5269 err = got_ref_resolve(&stored_id, repo, commit_ref);
5272 cmp = got_object_id_cmp(commit_id, stored_id);
5275 err = got_error(GOT_ERR_REBASE_COMMITID);
5281 got_ref_close(commit_ref);
5285 static const struct got_error *
5286 rebase_merge_files(struct got_pathlist_head *merged_paths,
5287 const char *commit_ref_name, struct got_worktree *worktree,
5288 struct got_fileindex *fileindex, struct got_object_id *parent_commit_id,
5289 struct got_object_id *commit_id, struct got_repository *repo,
5290 got_worktree_checkout_cb progress_cb, void *progress_arg,
5291 got_cancel_cb cancel_cb, void *cancel_arg)
5293 const struct got_error *err;
5294 struct got_reference *commit_ref = NULL;
5295 struct collect_merged_paths_arg cmp_arg;
5296 char *fileindex_path;
5298 /* Work tree is locked/unlocked during rebase preparation/teardown. */
5300 err = get_fileindex_path(&fileindex_path, worktree);
5304 cmp_arg.progress_cb = progress_cb;
5305 cmp_arg.progress_arg = progress_arg;
5306 cmp_arg.merged_paths = merged_paths;
5307 err = merge_files(worktree, fileindex, fileindex_path,
5308 parent_commit_id, commit_id, repo, collect_merged_paths,
5309 &cmp_arg, cancel_cb, cancel_arg);
5311 got_ref_close(commit_ref);
5315 const struct got_error *
5316 got_worktree_rebase_merge_files(struct got_pathlist_head *merged_paths,
5317 struct got_worktree *worktree, struct got_fileindex *fileindex,
5318 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
5319 struct got_repository *repo,
5320 got_worktree_checkout_cb progress_cb, void *progress_arg,
5321 got_cancel_cb cancel_cb, void *cancel_arg)
5323 const struct got_error *err;
5324 char *commit_ref_name;
5326 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
5330 err = store_commit_id(commit_ref_name, commit_id, 1, repo);
5334 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
5335 fileindex, parent_commit_id, commit_id, repo, progress_cb,
5336 progress_arg, cancel_cb, cancel_arg);
5338 free(commit_ref_name);
5342 const struct got_error *
5343 got_worktree_histedit_merge_files(struct got_pathlist_head *merged_paths,
5344 struct got_worktree *worktree, struct got_fileindex *fileindex,
5345 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
5346 struct got_repository *repo,
5347 got_worktree_checkout_cb progress_cb, void *progress_arg,
5348 got_cancel_cb cancel_cb, void *cancel_arg)
5350 const struct got_error *err;
5351 char *commit_ref_name;
5353 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
5357 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
5361 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
5362 fileindex, parent_commit_id, commit_id, repo, progress_cb,
5363 progress_arg, cancel_cb, cancel_arg);
5365 free(commit_ref_name);
5369 static const struct got_error *
5370 rebase_commit(struct got_object_id **new_commit_id,
5371 struct got_pathlist_head *merged_paths, struct got_reference *commit_ref,
5372 struct got_worktree *worktree, struct got_fileindex *fileindex,
5373 struct got_reference *tmp_branch, struct got_commit_object *orig_commit,
5374 const char *new_logmsg, struct got_repository *repo)
5376 const struct got_error *err, *sync_err;
5377 struct got_pathlist_head commitable_paths;
5378 struct collect_commitables_arg cc_arg;
5379 char *fileindex_path = NULL;
5380 struct got_reference *head_ref = NULL;
5381 struct got_object_id *head_commit_id = NULL;
5382 char *logmsg = NULL;
5384 TAILQ_INIT(&commitable_paths);
5385 *new_commit_id = NULL;
5387 /* Work tree is locked/unlocked during rebase preparation/teardown. */
5389 err = get_fileindex_path(&fileindex_path, worktree);
5393 cc_arg.commitable_paths = &commitable_paths;
5394 cc_arg.worktree = worktree;
5396 cc_arg.have_staged_files = 0;
5398 * If possible get the status of individual files directly to
5399 * avoid crawling the entire work tree once per rebased commit.
5400 * TODO: Ideally, merged_paths would contain a list of commitables
5401 * we could use so we could skip worktree_status() entirely.
5404 struct got_pathlist_entry *pe;
5405 TAILQ_FOREACH(pe, merged_paths, entry) {
5406 err = worktree_status(worktree, pe->path, fileindex,
5407 repo, collect_commitables, &cc_arg, NULL, NULL, 0,
5413 err = worktree_status(worktree, "", fileindex, repo,
5414 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
5419 if (TAILQ_EMPTY(&commitable_paths)) {
5420 /* No-op change; commit will be elided. */
5421 err = got_ref_delete(commit_ref, repo);
5424 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
5428 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
5432 err = got_ref_resolve(&head_commit_id, repo, head_ref);
5437 logmsg = strdup(new_logmsg);
5438 if (logmsg == NULL) {
5439 err = got_error_from_errno("strdup");
5443 err = got_object_commit_get_logmsg(&logmsg, orig_commit);
5448 /* NB: commit_worktree will call free(logmsg) */
5449 err = commit_worktree(new_commit_id, &commitable_paths, head_commit_id,
5450 worktree, got_object_commit_get_author(orig_commit),
5451 got_object_commit_get_committer(orig_commit),
5452 collect_rebase_commit_msg, logmsg, rebase_status, NULL, repo);
5456 err = got_ref_change_ref(tmp_branch, *new_commit_id);
5460 err = got_ref_delete(commit_ref, repo);
5464 err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
5466 sync_err = sync_fileindex(fileindex, fileindex_path);
5467 if (sync_err && err == NULL)
5470 free(fileindex_path);
5471 free(head_commit_id);
5473 got_ref_close(head_ref);
5475 free(*new_commit_id);
5476 *new_commit_id = NULL;
5481 const struct got_error *
5482 got_worktree_rebase_commit(struct got_object_id **new_commit_id,
5483 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
5484 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
5485 struct got_commit_object *orig_commit,
5486 struct got_object_id *orig_commit_id, struct got_repository *repo)
5488 const struct got_error *err;
5489 char *commit_ref_name;
5490 struct got_reference *commit_ref = NULL;
5491 struct got_object_id *commit_id = NULL;
5493 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
5497 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5500 err = got_ref_resolve(&commit_id, repo, commit_ref);
5503 if (got_object_id_cmp(commit_id, orig_commit_id) != 0) {
5504 err = got_error(GOT_ERR_REBASE_COMMITID);
5508 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
5509 worktree, fileindex, tmp_branch, orig_commit, NULL, repo);
5512 got_ref_close(commit_ref);
5513 free(commit_ref_name);
5518 const struct got_error *
5519 got_worktree_histedit_commit(struct got_object_id **new_commit_id,
5520 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
5521 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
5522 struct got_commit_object *orig_commit,
5523 struct got_object_id *orig_commit_id, const char *new_logmsg,
5524 struct got_repository *repo)
5526 const struct got_error *err;
5527 char *commit_ref_name;
5528 struct got_reference *commit_ref = NULL;
5530 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
5534 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5538 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
5539 worktree, fileindex, tmp_branch, orig_commit, new_logmsg, repo);
5542 got_ref_close(commit_ref);
5543 free(commit_ref_name);
5547 const struct got_error *
5548 got_worktree_rebase_postpone(struct got_worktree *worktree,
5549 struct got_fileindex *fileindex)
5552 got_fileindex_free(fileindex);
5553 return lock_worktree(worktree, LOCK_SH);
5556 static const struct got_error *
5557 delete_ref(const char *name, struct got_repository *repo)
5559 const struct got_error *err;
5560 struct got_reference *ref;
5562 err = got_ref_open(&ref, repo, name, 0);
5564 if (err->code == GOT_ERR_NOT_REF)
5569 err = got_ref_delete(ref, repo);
5574 static const struct got_error *
5575 delete_rebase_refs(struct got_worktree *worktree, struct got_repository *repo)
5577 const struct got_error *err;
5578 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
5579 char *branch_ref_name = NULL, *commit_ref_name = NULL;
5581 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5584 err = delete_ref(tmp_branch_name, repo);
5588 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
5591 err = delete_ref(new_base_branch_ref_name, repo);
5595 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
5598 err = delete_ref(branch_ref_name, repo);
5602 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
5605 err = delete_ref(commit_ref_name, repo);
5610 free(tmp_branch_name);
5611 free(new_base_branch_ref_name);
5612 free(branch_ref_name);
5613 free(commit_ref_name);
5617 const struct got_error *
5618 got_worktree_rebase_complete(struct got_worktree *worktree,
5619 struct got_fileindex *fileindex, struct got_reference *new_base_branch,
5620 struct got_reference *tmp_branch, struct got_reference *rebased_branch,
5621 struct got_repository *repo)
5623 const struct got_error *err, *unlockerr;
5624 struct got_object_id *new_head_commit_id = NULL;
5626 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
5630 err = got_ref_change_ref(rebased_branch, new_head_commit_id);
5634 err = got_ref_write(rebased_branch, repo);
5638 err = got_worktree_set_head_ref(worktree, rebased_branch);
5642 err = delete_rebase_refs(worktree, repo);
5645 got_fileindex_free(fileindex);
5646 free(new_head_commit_id);
5647 unlockerr = lock_worktree(worktree, LOCK_SH);
5648 if (unlockerr && err == NULL)
5653 const struct got_error *
5654 got_worktree_rebase_abort(struct got_worktree *worktree,
5655 struct got_fileindex *fileindex, struct got_repository *repo,
5656 struct got_reference *new_base_branch,
5657 got_worktree_checkout_cb progress_cb, void *progress_arg)
5659 const struct got_error *err, *unlockerr, *sync_err;
5660 struct got_reference *resolved = NULL;
5661 struct got_object_id *commit_id = NULL;
5662 char *fileindex_path = NULL;
5663 struct revert_file_args rfa;
5664 struct got_object_id *tree_id = NULL;
5666 err = lock_worktree(worktree, LOCK_EX);
5670 err = got_ref_open(&resolved, repo,
5671 got_ref_get_symref_target(new_base_branch), 0);
5675 err = got_worktree_set_head_ref(worktree, resolved);
5680 * XXX commits to the base branch could have happened while
5681 * we were busy rebasing; should we store the original commit ID
5682 * when rebase begins and read it back here?
5684 err = got_ref_resolve(&commit_id, repo, resolved);
5688 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
5692 err = got_object_id_by_path(&tree_id, repo,
5693 worktree->base_commit_id, worktree->path_prefix);
5697 err = delete_rebase_refs(worktree, repo);
5701 err = get_fileindex_path(&fileindex_path, worktree);
5705 rfa.worktree = worktree;
5706 rfa.fileindex = fileindex;
5707 rfa.progress_cb = progress_cb;
5708 rfa.progress_arg = progress_arg;
5709 rfa.patch_cb = NULL;
5710 rfa.patch_arg = NULL;
5712 err = worktree_status(worktree, "", fileindex, repo,
5713 revert_file, &rfa, NULL, NULL, 0, 0);
5717 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
5718 repo, progress_cb, progress_arg, NULL, NULL);
5720 sync_err = sync_fileindex(fileindex, fileindex_path);
5721 if (sync_err && err == NULL)
5724 got_ref_close(resolved);
5728 got_fileindex_free(fileindex);
5729 free(fileindex_path);
5731 unlockerr = lock_worktree(worktree, LOCK_SH);
5732 if (unlockerr && err == NULL)
5737 const struct got_error *
5738 got_worktree_histedit_prepare(struct got_reference **tmp_branch,
5739 struct got_reference **branch_ref, struct got_object_id **base_commit_id,
5740 struct got_fileindex **fileindex, struct got_worktree *worktree,
5741 struct got_repository *repo)
5743 const struct got_error *err = NULL;
5744 char *tmp_branch_name = NULL;
5745 char *branch_ref_name = NULL;
5746 char *base_commit_ref_name = NULL;
5747 char *fileindex_path = NULL;
5748 struct check_rebase_ok_arg ok_arg;
5749 struct got_reference *wt_branch = NULL;
5750 struct got_reference *base_commit_ref = NULL;
5754 *base_commit_id = NULL;
5757 err = lock_worktree(worktree, LOCK_EX);
5761 err = open_fileindex(fileindex, &fileindex_path, worktree);
5765 ok_arg.worktree = worktree;
5767 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
5772 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
5776 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
5780 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
5785 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
5790 err = got_ref_alloc_symref(branch_ref, branch_ref_name, wt_branch);
5794 err = got_ref_write(*branch_ref, repo);
5798 err = got_ref_alloc(&base_commit_ref, base_commit_ref_name,
5799 worktree->base_commit_id);
5802 err = got_ref_write(base_commit_ref, repo);
5805 *base_commit_id = got_object_id_dup(worktree->base_commit_id);
5806 if (*base_commit_id == NULL) {
5807 err = got_error_from_errno("got_object_id_dup");
5811 err = got_ref_alloc(tmp_branch, tmp_branch_name,
5812 worktree->base_commit_id);
5815 err = got_ref_write(*tmp_branch, repo);
5819 err = got_worktree_set_head_ref(worktree, *tmp_branch);
5823 free(fileindex_path);
5824 free(tmp_branch_name);
5825 free(branch_ref_name);
5826 free(base_commit_ref_name);
5828 got_ref_close(wt_branch);
5831 got_ref_close(*branch_ref);
5835 got_ref_close(*tmp_branch);
5838 free(*base_commit_id);
5840 got_fileindex_free(*fileindex);
5843 lock_worktree(worktree, LOCK_SH);
5848 const struct got_error *
5849 got_worktree_histedit_postpone(struct got_worktree *worktree,
5850 struct got_fileindex *fileindex)
5853 got_fileindex_free(fileindex);
5854 return lock_worktree(worktree, LOCK_SH);
5857 const struct got_error *
5858 got_worktree_histedit_in_progress(int *in_progress,
5859 struct got_worktree *worktree)
5861 const struct got_error *err;
5862 char *tmp_branch_name = NULL;
5864 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
5868 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
5869 free(tmp_branch_name);
5873 const struct got_error *
5874 got_worktree_histedit_continue(struct got_object_id **commit_id,
5875 struct got_reference **tmp_branch, struct got_reference **branch_ref,
5876 struct got_object_id **base_commit_id, struct got_fileindex **fileindex,
5877 struct got_worktree *worktree, struct got_repository *repo)
5879 const struct got_error *err;
5880 char *commit_ref_name = NULL, *base_commit_ref_name = NULL;
5881 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
5882 struct got_reference *commit_ref = NULL;
5883 struct got_reference *base_commit_ref = NULL;
5884 char *fileindex_path = NULL;
5885 int have_staged_files = 0;
5889 *base_commit_id = NULL;
5892 err = lock_worktree(worktree, LOCK_EX);
5896 err = open_fileindex(fileindex, &fileindex_path, worktree);
5900 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
5901 &have_staged_files);
5902 if (err && err->code != GOT_ERR_CANCELLED)
5904 if (have_staged_files) {
5905 err = got_error(GOT_ERR_STAGED_PATHS);
5909 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
5913 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
5917 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
5921 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
5926 err = got_ref_open(branch_ref, repo, branch_ref_name, 0);
5930 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5933 err = got_ref_resolve(commit_id, repo, commit_ref);
5937 err = got_ref_open(&base_commit_ref, repo, base_commit_ref_name, 0);
5940 err = got_ref_resolve(base_commit_id, repo, base_commit_ref);
5944 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
5948 free(commit_ref_name);
5949 free(branch_ref_name);
5950 free(fileindex_path);
5952 got_ref_close(commit_ref);
5953 if (base_commit_ref)
5954 got_ref_close(base_commit_ref);
5958 free(*base_commit_id);
5959 *base_commit_id = NULL;
5961 got_ref_close(*tmp_branch);
5965 got_fileindex_free(*fileindex);
5968 lock_worktree(worktree, LOCK_EX);
5973 static const struct got_error *
5974 delete_histedit_refs(struct got_worktree *worktree, struct got_repository *repo)
5976 const struct got_error *err;
5977 char *tmp_branch_name = NULL, *base_commit_ref_name = NULL;
5978 char *branch_ref_name = NULL, *commit_ref_name = NULL;
5980 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
5983 err = delete_ref(tmp_branch_name, repo);
5987 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
5991 err = delete_ref(base_commit_ref_name, repo);
5995 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
5998 err = delete_ref(branch_ref_name, repo);
6002 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6005 err = delete_ref(commit_ref_name, repo);
6009 free(tmp_branch_name);
6010 free(base_commit_ref_name);
6011 free(branch_ref_name);
6012 free(commit_ref_name);
6016 const struct got_error *
6017 got_worktree_histedit_abort(struct got_worktree *worktree,
6018 struct got_fileindex *fileindex, struct got_repository *repo,
6019 struct got_reference *branch, struct got_object_id *base_commit_id,
6020 got_worktree_checkout_cb progress_cb, void *progress_arg)
6022 const struct got_error *err, *unlockerr, *sync_err;
6023 struct got_reference *resolved = NULL;
6024 char *fileindex_path = NULL;
6025 struct got_object_id *tree_id = NULL;
6026 struct revert_file_args rfa;
6028 err = lock_worktree(worktree, LOCK_EX);
6032 err = got_ref_open(&resolved, repo,
6033 got_ref_get_symref_target(branch), 0);
6037 err = got_worktree_set_head_ref(worktree, resolved);
6041 err = got_worktree_set_base_commit_id(worktree, repo, base_commit_id);
6045 err = got_object_id_by_path(&tree_id, repo, base_commit_id,
6046 worktree->path_prefix);
6050 err = delete_histedit_refs(worktree, repo);
6054 err = get_fileindex_path(&fileindex_path, worktree);
6058 rfa.worktree = worktree;
6059 rfa.fileindex = fileindex;
6060 rfa.progress_cb = progress_cb;
6061 rfa.progress_arg = progress_arg;
6062 rfa.patch_cb = NULL;
6063 rfa.patch_arg = NULL;
6065 err = worktree_status(worktree, "", fileindex, repo,
6066 revert_file, &rfa, NULL, NULL, 0, 0);
6070 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
6071 repo, progress_cb, progress_arg, NULL, NULL);
6073 sync_err = sync_fileindex(fileindex, fileindex_path);
6074 if (sync_err && err == NULL)
6077 got_ref_close(resolved);
6079 free(fileindex_path);
6081 unlockerr = lock_worktree(worktree, LOCK_SH);
6082 if (unlockerr && err == NULL)
6087 const struct got_error *
6088 got_worktree_histedit_complete(struct got_worktree *worktree,
6089 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6090 struct got_reference *edited_branch, struct got_repository *repo)
6092 const struct got_error *err, *unlockerr;
6093 struct got_object_id *new_head_commit_id = NULL;
6094 struct got_reference *resolved = NULL;
6096 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
6100 err = got_ref_open(&resolved, repo,
6101 got_ref_get_symref_target(edited_branch), 0);
6105 err = got_ref_change_ref(resolved, new_head_commit_id);
6109 err = got_ref_write(resolved, repo);
6113 err = got_worktree_set_head_ref(worktree, resolved);
6117 err = delete_histedit_refs(worktree, repo);
6120 got_fileindex_free(fileindex);
6121 free(new_head_commit_id);
6122 unlockerr = lock_worktree(worktree, LOCK_SH);
6123 if (unlockerr && err == NULL)
6128 const struct got_error *
6129 got_worktree_histedit_skip_commit(struct got_worktree *worktree,
6130 struct got_object_id *commit_id, struct got_repository *repo)
6132 const struct got_error *err;
6133 char *commit_ref_name;
6135 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6139 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
6143 err = delete_ref(commit_ref_name, repo);
6145 free(commit_ref_name);
6149 const struct got_error *
6150 got_worktree_integrate_prepare(struct got_fileindex **fileindex,
6151 struct got_reference **branch_ref, struct got_reference **base_branch_ref,
6152 struct got_worktree *worktree, const char *refname,
6153 struct got_repository *repo)
6155 const struct got_error *err = NULL;
6156 char *fileindex_path = NULL;
6157 struct check_rebase_ok_arg ok_arg;
6161 *base_branch_ref = NULL;
6163 err = lock_worktree(worktree, LOCK_EX);
6167 if (strcmp(refname, got_worktree_get_head_ref_name(worktree)) == 0) {
6168 err = got_error_msg(GOT_ERR_SAME_BRANCH,
6169 "cannot integrate a branch into itself; "
6170 "update -b or different branch name required");
6174 err = open_fileindex(fileindex, &fileindex_path, worktree);
6178 /* Preconditions are the same as for rebase. */
6179 ok_arg.worktree = worktree;
6181 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
6186 err = got_ref_open(branch_ref, repo, refname, 1);
6190 err = got_ref_open(base_branch_ref, repo,
6191 got_worktree_get_head_ref_name(worktree), 1);
6195 got_ref_close(*branch_ref);
6198 if (*base_branch_ref) {
6199 got_ref_close(*base_branch_ref);
6200 *base_branch_ref = NULL;
6203 got_fileindex_free(*fileindex);
6206 lock_worktree(worktree, LOCK_SH);
6211 const struct got_error *
6212 got_worktree_integrate_continue(struct got_worktree *worktree,
6213 struct got_fileindex *fileindex, struct got_repository *repo,
6214 struct got_reference *branch_ref, struct got_reference *base_branch_ref,
6215 got_worktree_checkout_cb progress_cb, void *progress_arg,
6216 got_cancel_cb cancel_cb, void *cancel_arg)
6218 const struct got_error *err = NULL, *sync_err, *unlockerr;
6219 char *fileindex_path = NULL;
6220 struct got_object_id *tree_id = NULL, *commit_id = NULL;
6222 err = get_fileindex_path(&fileindex_path, worktree);
6226 err = got_ref_resolve(&commit_id, repo, branch_ref);
6230 err = got_object_id_by_path(&tree_id, repo, commit_id,
6231 worktree->path_prefix);
6235 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
6239 err = checkout_files(worktree, fileindex, "", tree_id, NULL, repo,
6240 progress_cb, progress_arg, cancel_cb, cancel_arg);
6244 err = got_ref_change_ref(base_branch_ref, commit_id);
6248 err = got_ref_write(base_branch_ref, repo);
6250 sync_err = sync_fileindex(fileindex, fileindex_path);
6251 if (sync_err && err == NULL)
6255 unlockerr = got_ref_unlock(branch_ref);
6256 if (unlockerr && err == NULL)
6258 got_ref_close(branch_ref);
6260 unlockerr = got_ref_unlock(base_branch_ref);
6261 if (unlockerr && err == NULL)
6263 got_ref_close(base_branch_ref);
6265 got_fileindex_free(fileindex);
6266 free(fileindex_path);
6269 unlockerr = lock_worktree(worktree, LOCK_SH);
6270 if (unlockerr && err == NULL)
6275 const struct got_error *
6276 got_worktree_integrate_abort(struct got_worktree *worktree,
6277 struct got_fileindex *fileindex, struct got_repository *repo,
6278 struct got_reference *branch_ref, struct got_reference *base_branch_ref)
6280 const struct got_error *err = NULL, *unlockerr = NULL;
6282 got_fileindex_free(fileindex);
6284 err = lock_worktree(worktree, LOCK_SH);
6286 unlockerr = got_ref_unlock(branch_ref);
6287 if (unlockerr && err == NULL)
6289 got_ref_close(branch_ref);
6291 unlockerr = got_ref_unlock(base_branch_ref);
6292 if (unlockerr && err == NULL)
6294 got_ref_close(base_branch_ref);
6299 struct check_stage_ok_arg {
6300 struct got_object_id *head_commit_id;
6301 struct got_worktree *worktree;
6302 struct got_fileindex *fileindex;
6303 struct got_repository *repo;
6307 const struct got_error *
6308 check_stage_ok(void *arg, unsigned char status,
6309 unsigned char staged_status, const char *relpath,
6310 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
6311 struct got_object_id *commit_id, int dirfd, const char *de_name)
6313 struct check_stage_ok_arg *a = arg;
6314 const struct got_error *err = NULL;
6315 struct got_fileindex_entry *ie;
6316 struct got_object_id base_commit_id;
6317 struct got_object_id *base_commit_idp = NULL;
6318 char *in_repo_path = NULL, *p;
6320 if (status == GOT_STATUS_UNVERSIONED ||
6321 status == GOT_STATUS_NO_CHANGE)
6323 if (status == GOT_STATUS_NONEXISTENT)
6324 return got_error_set_errno(ENOENT, relpath);
6326 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
6328 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
6330 if (asprintf(&in_repo_path, "%s%s%s", a->worktree->path_prefix,
6331 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
6333 return got_error_from_errno("asprintf");
6335 if (got_fileindex_entry_has_commit(ie)) {
6336 memcpy(base_commit_id.sha1, ie->commit_sha1,
6337 SHA1_DIGEST_LENGTH);
6338 base_commit_idp = &base_commit_id;
6341 if (status == GOT_STATUS_CONFLICT) {
6342 err = got_error_path(ie->path, GOT_ERR_STAGE_CONFLICT);
6344 } else if (status != GOT_STATUS_ADD &&
6345 status != GOT_STATUS_MODIFY &&
6346 status != GOT_STATUS_DELETE) {
6347 err = got_error_path(ie->path, GOT_ERR_FILE_STATUS);
6351 a->have_changes = 1;
6356 err = check_out_of_date(p, status, staged_status,
6357 blob_id, base_commit_idp, a->head_commit_id, a->repo,
6358 GOT_ERR_STAGE_OUT_OF_DATE);
6364 struct stage_path_arg {
6365 struct got_worktree *worktree;
6366 struct got_fileindex *fileindex;
6367 struct got_repository *repo;
6368 got_worktree_status_cb status_cb;
6370 got_worktree_patch_cb patch_cb;
6372 int staged_something;
6375 static const struct got_error *
6376 stage_path(void *arg, unsigned char status,
6377 unsigned char staged_status, const char *relpath,
6378 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
6379 struct got_object_id *commit_id, int dirfd, const char *de_name)
6381 struct stage_path_arg *a = arg;
6382 const struct got_error *err = NULL;
6383 struct got_fileindex_entry *ie;
6384 char *ondisk_path = NULL, *path_content = NULL;
6386 struct got_object_id *new_staged_blob_id = NULL;
6388 if (status == GOT_STATUS_UNVERSIONED)
6391 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
6393 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
6395 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
6397 return got_error_from_errno("asprintf");
6400 case GOT_STATUS_ADD:
6401 case GOT_STATUS_MODIFY:
6403 if (status == GOT_STATUS_ADD) {
6404 int choice = GOT_PATCH_CHOICE_NONE;
6405 err = (*a->patch_cb)(&choice, a->patch_arg,
6406 status, ie->path, NULL, 1, 1);
6409 if (choice != GOT_PATCH_CHOICE_YES)
6412 err = create_patched_content(&path_content, 0,
6413 staged_blob_id ? staged_blob_id : blob_id,
6414 ondisk_path, dirfd, de_name, ie->path,
6415 a->repo, a->patch_cb, a->patch_arg);
6416 if (err || path_content == NULL)
6420 err = got_object_blob_create(&new_staged_blob_id,
6421 path_content ? path_content : ondisk_path, a->repo);
6424 memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1,
6425 SHA1_DIGEST_LENGTH);
6426 if (status == GOT_STATUS_ADD || staged_status == GOT_STATUS_ADD)
6427 stage = GOT_FILEIDX_STAGE_ADD;
6429 stage = GOT_FILEIDX_STAGE_MODIFY;
6430 got_fileindex_entry_stage_set(ie, stage);
6431 a->staged_something = 1;
6432 if (a->status_cb == NULL)
6434 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
6435 get_staged_status(ie), relpath, blob_id,
6436 new_staged_blob_id, NULL, dirfd, de_name);
6438 case GOT_STATUS_DELETE:
6439 if (staged_status == GOT_STATUS_DELETE)
6442 int choice = GOT_PATCH_CHOICE_NONE;
6443 err = (*a->patch_cb)(&choice, a->patch_arg, status,
6444 ie->path, NULL, 1, 1);
6447 if (choice == GOT_PATCH_CHOICE_NO)
6449 if (choice != GOT_PATCH_CHOICE_YES) {
6450 err = got_error(GOT_ERR_PATCH_CHOICE);
6454 stage = GOT_FILEIDX_STAGE_DELETE;
6455 got_fileindex_entry_stage_set(ie, stage);
6456 a->staged_something = 1;
6457 if (a->status_cb == NULL)
6459 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
6460 get_staged_status(ie), relpath, NULL, NULL, NULL, dirfd,
6463 case GOT_STATUS_NO_CHANGE:
6465 case GOT_STATUS_CONFLICT:
6466 err = got_error_path(relpath, GOT_ERR_STAGE_CONFLICT);
6468 case GOT_STATUS_NONEXISTENT:
6469 err = got_error_set_errno(ENOENT, relpath);
6472 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
6476 if (path_content && unlink(path_content) == -1 && err == NULL)
6477 err = got_error_from_errno2("unlink", path_content);
6480 free(new_staged_blob_id);
6484 const struct got_error *
6485 got_worktree_stage(struct got_worktree *worktree,
6486 struct got_pathlist_head *paths,
6487 got_worktree_status_cb status_cb, void *status_arg,
6488 got_worktree_patch_cb patch_cb, void *patch_arg,
6489 struct got_repository *repo)
6491 const struct got_error *err = NULL, *sync_err, *unlockerr;
6492 struct got_pathlist_entry *pe;
6493 struct got_fileindex *fileindex = NULL;
6494 char *fileindex_path = NULL;
6495 struct got_reference *head_ref = NULL;
6496 struct got_object_id *head_commit_id = NULL;
6497 struct check_stage_ok_arg oka;
6498 struct stage_path_arg spa;
6500 err = lock_worktree(worktree, LOCK_EX);
6504 err = got_ref_open(&head_ref, repo,
6505 got_worktree_get_head_ref_name(worktree), 0);
6508 err = got_ref_resolve(&head_commit_id, repo, head_ref);
6511 err = open_fileindex(&fileindex, &fileindex_path, worktree);
6515 /* Check pre-conditions before staging anything. */
6516 oka.head_commit_id = head_commit_id;
6517 oka.worktree = worktree;
6518 oka.fileindex = fileindex;
6520 oka.have_changes = 0;
6521 TAILQ_FOREACH(pe, paths, entry) {
6522 err = worktree_status(worktree, pe->path, fileindex, repo,
6523 check_stage_ok, &oka, NULL, NULL, 0, 0);
6527 if (!oka.have_changes) {
6528 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
6532 spa.worktree = worktree;
6533 spa.fileindex = fileindex;
6535 spa.patch_cb = patch_cb;
6536 spa.patch_arg = patch_arg;
6537 spa.status_cb = status_cb;
6538 spa.status_arg = status_arg;
6539 spa.staged_something = 0;
6540 TAILQ_FOREACH(pe, paths, entry) {
6541 err = worktree_status(worktree, pe->path, fileindex, repo,
6542 stage_path, &spa, NULL, NULL, 0, 0);
6546 if (!spa.staged_something) {
6547 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
6551 sync_err = sync_fileindex(fileindex, fileindex_path);
6552 if (sync_err && err == NULL)
6556 got_ref_close(head_ref);
6557 free(head_commit_id);
6558 free(fileindex_path);
6560 got_fileindex_free(fileindex);
6561 unlockerr = lock_worktree(worktree, LOCK_SH);
6562 if (unlockerr && err == NULL)
6567 struct unstage_path_arg {
6568 struct got_worktree *worktree;
6569 struct got_fileindex *fileindex;
6570 struct got_repository *repo;
6571 got_worktree_checkout_cb progress_cb;
6573 got_worktree_patch_cb patch_cb;
6577 static const struct got_error *
6578 create_unstaged_content(char **path_unstaged_content,
6579 char **path_new_staged_content, struct got_object_id *blob_id,
6580 struct got_object_id *staged_blob_id, const char *relpath,
6581 struct got_repository *repo,
6582 got_worktree_patch_cb patch_cb, void *patch_arg)
6584 const struct got_error *err;
6585 struct got_blob_object *blob = NULL, *staged_blob = NULL;
6586 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL, *rejectfile = NULL;
6587 char *path1 = NULL, *path2 = NULL, *label1 = NULL;
6588 struct stat sb1, sb2;
6589 struct got_diff_changes *changes = NULL;
6590 struct got_diff_state *ds = NULL;
6591 struct got_diff_args *args = NULL;
6592 struct got_diff_change *change;
6593 int diff_flags = 0, line_cur1 = 1, line_cur2 = 1, n = 0;
6594 int have_content = 0, have_rejected_content = 0;
6596 *path_unstaged_content = NULL;
6597 *path_new_staged_content = NULL;
6599 err = got_object_id_str(&label1, blob_id);
6602 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
6606 err = got_opentemp_named(&path1, &f1, "got-unstage-blob-base");
6610 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
6614 err = got_object_open_as_blob(&staged_blob, repo, staged_blob_id, 8192);
6618 err = got_opentemp_named(&path2, &f2, "got-unstage-blob-staged");
6622 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f2, staged_blob);
6626 if (stat(path1, &sb1) == -1) {
6627 err = got_error_from_errno2("stat", path1);
6631 if (stat(path2, &sb2) == -1) {
6632 err = got_error_from_errno2("stat", path2);
6636 err = got_diff_files(&changes, &ds, &args, &diff_flags,
6637 f1, sb1.st_size, label1, f2, sb2.st_size, path2, 3, NULL);
6641 err = got_opentemp_named(path_unstaged_content, &outfile,
6642 "got-unstaged-content");
6645 err = got_opentemp_named(path_new_staged_content, &rejectfile,
6646 "got-new-staged-content");
6650 if (fseek(f1, 0L, SEEK_SET) == -1) {
6651 err = got_ferror(f1, GOT_ERR_IO);
6654 if (fseek(f2, 0L, SEEK_SET) == -1) {
6655 err = got_ferror(f2, GOT_ERR_IO);
6658 SIMPLEQ_FOREACH(change, &changes->entries, entry) {
6660 err = apply_or_reject_change(&choice, change, ++n,
6661 changes->nchanges, ds, args, diff_flags, relpath,
6662 f1, f2, &line_cur1, &line_cur2,
6663 outfile, rejectfile, patch_cb, patch_arg);
6666 if (choice == GOT_PATCH_CHOICE_YES)
6669 have_rejected_content = 1;
6670 if (choice == GOT_PATCH_CHOICE_QUIT)
6673 if (have_content || have_rejected_content)
6674 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
6675 outfile, rejectfile);
6679 got_object_blob_close(blob);
6681 got_object_blob_close(staged_blob);
6682 if (f1 && fclose(f1) == EOF && err == NULL)
6683 err = got_error_from_errno2("fclose", path1);
6684 if (f2 && fclose(f2) == EOF && err == NULL)
6685 err = got_error_from_errno2("fclose", path2);
6686 if (outfile && fclose(outfile) == EOF && err == NULL)
6687 err = got_error_from_errno2("fclose", *path_unstaged_content);
6688 if (rejectfile && fclose(rejectfile) == EOF && err == NULL)
6689 err = got_error_from_errno2("fclose", *path_new_staged_content);
6690 if (path1 && unlink(path1) == -1 && err == NULL)
6691 err = got_error_from_errno2("unlink", path1);
6692 if (path2 && unlink(path2) == -1 && err == NULL)
6693 err = got_error_from_errno2("unlink", path2);
6694 if (err || !have_content) {
6695 if (*path_unstaged_content &&
6696 unlink(*path_unstaged_content) == -1 && err == NULL)
6697 err = got_error_from_errno2("unlink",
6698 *path_unstaged_content);
6699 free(*path_unstaged_content);
6700 *path_unstaged_content = NULL;
6702 if (err || !have_rejected_content) {
6703 if (*path_new_staged_content &&
6704 unlink(*path_new_staged_content) == -1 && err == NULL)
6705 err = got_error_from_errno2("unlink",
6706 *path_new_staged_content);
6707 free(*path_new_staged_content);
6708 *path_new_staged_content = NULL;
6712 got_diff_state_free(ds);
6716 got_diff_free_changes(changes);
6722 static const struct got_error *
6723 unstage_path(void *arg, unsigned char status,
6724 unsigned char staged_status, const char *relpath,
6725 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
6726 struct got_object_id *commit_id, int dirfd, const char *de_name)
6728 const struct got_error *err = NULL;
6729 struct unstage_path_arg *a = arg;
6730 struct got_fileindex_entry *ie;
6731 struct got_blob_object *blob_base = NULL, *blob_staged = NULL;
6732 char *ondisk_path = NULL, *path_unstaged_content = NULL;
6733 char *path_new_staged_content = NULL;
6734 char *id_str = NULL, *label_orig = NULL;
6735 int local_changes_subsumed;
6738 if (staged_status != GOT_STATUS_ADD &&
6739 staged_status != GOT_STATUS_MODIFY &&
6740 staged_status != GOT_STATUS_DELETE)
6743 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
6745 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
6747 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, relpath)
6749 return got_error_from_errno("asprintf");
6751 err = got_object_id_str(&id_str,
6752 commit_id ? commit_id : a->worktree->base_commit_id);
6755 if (asprintf(&label_orig, "%s: commit %s", GOT_MERGE_LABEL_BASE,
6757 err = got_error_from_errno("asprintf");
6761 switch (staged_status) {
6762 case GOT_STATUS_MODIFY:
6763 err = got_object_open_as_blob(&blob_base, a->repo,
6768 case GOT_STATUS_ADD:
6770 if (staged_status == GOT_STATUS_ADD) {
6771 int choice = GOT_PATCH_CHOICE_NONE;
6772 err = (*a->patch_cb)(&choice, a->patch_arg,
6773 staged_status, ie->path, NULL, 1, 1);
6776 if (choice != GOT_PATCH_CHOICE_YES)
6779 err = create_unstaged_content(
6780 &path_unstaged_content,
6781 &path_new_staged_content, blob_id,
6782 staged_blob_id, ie->path, a->repo,
6783 a->patch_cb, a->patch_arg);
6784 if (err || path_unstaged_content == NULL)
6786 if (path_new_staged_content) {
6787 err = got_object_blob_create(
6789 path_new_staged_content,
6793 memcpy(ie->staged_blob_sha1,
6794 staged_blob_id->sha1,
6795 SHA1_DIGEST_LENGTH);
6797 err = merge_file(&local_changes_subsumed,
6798 a->worktree, blob_base, ondisk_path,
6799 relpath, got_fileindex_perms_to_st(ie),
6800 path_unstaged_content, label_orig,
6801 "unstaged", a->repo, a->progress_cb,
6804 path_new_staged_content == NULL)
6805 got_fileindex_entry_stage_set(ie,
6806 GOT_FILEIDX_STAGE_NONE);
6807 break; /* Done with this file. */
6810 err = got_object_open_as_blob(&blob_staged, a->repo,
6811 staged_blob_id, 8192);
6814 err = merge_blob(&local_changes_subsumed, a->worktree,
6815 blob_base, ondisk_path, relpath,
6816 got_fileindex_perms_to_st(ie), label_orig, blob_staged,
6817 commit_id ? commit_id : a->worktree->base_commit_id,
6818 a->repo, a->progress_cb, a->progress_arg);
6820 got_fileindex_entry_stage_set(ie,
6821 GOT_FILEIDX_STAGE_NONE);
6823 case GOT_STATUS_DELETE:
6825 int choice = GOT_PATCH_CHOICE_NONE;
6826 err = (*a->patch_cb)(&choice, a->patch_arg,
6827 staged_status, ie->path, NULL, 1, 1);
6830 if (choice == GOT_PATCH_CHOICE_NO)
6832 if (choice != GOT_PATCH_CHOICE_YES) {
6833 err = got_error(GOT_ERR_PATCH_CHOICE);
6837 got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE);
6838 err = get_file_status(&status, &sb, ie, ondisk_path,
6839 dirfd, de_name, a->repo);
6842 err = (*a->progress_cb)(a->progress_arg, status, relpath);
6847 if (path_unstaged_content &&
6848 unlink(path_unstaged_content) == -1 && err == NULL)
6849 err = got_error_from_errno2("unlink", path_unstaged_content);
6850 if (path_new_staged_content &&
6851 unlink(path_new_staged_content) == -1 && err == NULL)
6852 err = got_error_from_errno2("unlink", path_new_staged_content);
6853 free(path_unstaged_content);
6854 free(path_new_staged_content);
6856 got_object_blob_close(blob_base);
6858 got_object_blob_close(blob_staged);
6864 const struct got_error *
6865 got_worktree_unstage(struct got_worktree *worktree,
6866 struct got_pathlist_head *paths,
6867 got_worktree_checkout_cb progress_cb, void *progress_arg,
6868 got_worktree_patch_cb patch_cb, void *patch_arg,
6869 struct got_repository *repo)
6871 const struct got_error *err = NULL, *sync_err, *unlockerr;
6872 struct got_pathlist_entry *pe;
6873 struct got_fileindex *fileindex = NULL;
6874 char *fileindex_path = NULL;
6875 struct unstage_path_arg upa;
6877 err = lock_worktree(worktree, LOCK_EX);
6881 err = open_fileindex(&fileindex, &fileindex_path, worktree);
6885 upa.worktree = worktree;
6886 upa.fileindex = fileindex;
6888 upa.progress_cb = progress_cb;
6889 upa.progress_arg = progress_arg;
6890 upa.patch_cb = patch_cb;
6891 upa.patch_arg = patch_arg;
6892 TAILQ_FOREACH(pe, paths, entry) {
6893 err = worktree_status(worktree, pe->path, fileindex, repo,
6894 unstage_path, &upa, NULL, NULL, 0, 0);
6899 sync_err = sync_fileindex(fileindex, fileindex_path);
6900 if (sync_err && err == NULL)
6903 free(fileindex_path);
6905 got_fileindex_free(fileindex);
6906 unlockerr = lock_worktree(worktree, LOCK_SH);
6907 if (unlockerr && err == NULL)