Blob


1 /*
2 * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
3 *
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.
7 *
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.
15 */
17 #include <sys/stat.h>
18 #include <sys/queue.h>
19 #include <sys/tree.h>
21 #include <dirent.h>
22 #include <limits.h>
23 #include <stddef.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <time.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <sha1.h>
32 #include <zlib.h>
33 #include <fnmatch.h>
34 #include <libgen.h>
35 #include <uuid.h>
36 #include <util.h>
38 #include "got_error.h"
39 #include "got_repository.h"
40 #include "got_reference.h"
41 #include "got_object.h"
42 #include "got_path.h"
43 #include "got_cancel.h"
44 #include "got_worktree.h"
45 #include "got_opentemp.h"
46 #include "got_diff.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"
59 #ifndef MIN
60 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
61 #endif
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)
68 {
69 const struct got_error *err = NULL;
70 char *path;
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);
76 free(path);
77 return err;
78 }
80 static const struct got_error *
81 update_meta_file(const char *path_got, const char *name, const char *content)
82 {
83 const struct got_error *err = NULL;
84 FILE *tmpfile = NULL;
85 char *tmppath = NULL;
86 char *path = NULL;
88 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
89 err = got_error_from_errno("asprintf");
90 path = NULL;
91 goto done;
92 }
94 err = got_opentemp_named(&tmppath, &tmpfile, path);
95 if (err)
96 goto done;
98 if (content) {
99 int len = fprintf(tmpfile, "%s\n", content);
100 if (len != strlen(content) + 1) {
101 err = got_error_from_errno2("fprintf", tmppath);
102 goto done;
106 if (rename(tmppath, path) != 0) {
107 err = got_error_from_errno3("rename", tmppath, path);
108 unlink(tmppath);
109 goto done;
112 done:
113 if (fclose(tmpfile) != 0 && err == NULL)
114 err = got_error_from_errno2("fclose", tmppath);
115 free(tmppath);
116 return err;
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;
123 char *path;
124 int fd = -1;
125 ssize_t n;
126 struct stat sb;
128 *content = NULL;
130 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
131 err = got_error_from_errno("asprintf");
132 path = NULL;
133 goto done;
136 fd = open(path, O_RDONLY | O_NOFOLLOW);
137 if (fd == -1) {
138 if (errno == ENOENT)
139 err = got_error_path(path, GOT_ERR_WORKTREE_META);
140 else
141 err = got_error_from_errno2("open", path);
142 goto done;
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));
147 goto done;
150 if (fstat(fd, &sb) != 0) {
151 err = got_error_from_errno2("fstat", path);
152 goto done;
154 *content = calloc(1, sb.st_size);
155 if (*content == NULL) {
156 err = got_error_from_errno("calloc");
157 goto done;
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));
164 goto done;
166 if ((*content)[sb.st_size - 1] != '\n') {
167 err = got_error_path(path, GOT_ERR_WORKTREE_META);
168 goto done;
170 (*content)[sb.st_size - 1] = '\0';
172 done:
173 if (fd != -1 && close(fd) == -1 && err == NULL)
174 err = got_error_from_errno2("close", path_got);
175 free(path);
176 if (err) {
177 free(*content);
178 *content = NULL;
180 return err;
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;
187 char *refstr = NULL;
189 if (got_ref_is_symbolic(head_ref)) {
190 refstr = got_ref_to_str(head_ref);
191 if (refstr == NULL)
192 return got_error_from_errno("got_ref_to_str");
193 } else {
194 refstr = strdup(got_ref_get_name(head_ref));
195 if (refstr == NULL)
196 return got_error_from_errno("strdup");
198 err = update_meta_file(path_got, GOT_WORKTREE_HEAD_REF, refstr);
199 free(refstr);
200 return err;
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;
209 uuid_t uuid;
210 uint32_t uuid_status;
211 int obj_type;
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);
220 goto done;
223 err = got_ref_resolve(&commit_id, repo, head_ref);
224 if (err)
225 return err;
226 err = got_object_get_type(&obj_type, repo, commit_id);
227 if (err)
228 return err;
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);
240 goto done;
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");
246 goto done;
248 if (mkdir(path_got, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
249 err = got_error_from_errno2("mkdir", path_got);
250 goto done;
253 /* Create an empty lock file. */
254 err = create_meta_file(path_got, GOT_WORKTREE_LOCK, NULL);
255 if (err)
256 goto done;
258 /* Create an empty file index. */
259 err = create_meta_file(path_got, GOT_WORKTREE_FILE_INDEX, NULL);
260 if (err)
261 goto done;
263 /* Write the HEAD reference. */
264 err = write_head_ref(path_got, head_ref);
265 if (err)
266 goto done;
268 /* Record our base commit. */
269 err = got_object_id_str(&basestr, commit_id);
270 if (err)
271 goto done;
272 err = create_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, basestr);
273 if (err)
274 goto done;
276 /* Store path to repository. */
277 err = create_meta_file(path_got, GOT_WORKTREE_REPOSITORY,
278 got_repo_get_path(repo));
279 if (err)
280 goto done;
282 /* Store in-repository path prefix. */
283 err = create_meta_file(path_got, GOT_WORKTREE_PATH_PREFIX,
284 absprefix ? absprefix : prefix);
285 if (err)
286 goto done;
288 /* Generate UUID. */
289 uuid_create(&uuid, &uuid_status);
290 if (uuid_status != uuid_s_ok) {
291 err = got_error_uuid(uuid_status, "uuid_create");
292 goto done;
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");
297 goto done;
299 err = create_meta_file(path_got, GOT_WORKTREE_UUID, uuidstr);
300 if (err)
301 goto done;
303 /* Stamp work tree with format file. */
304 if (asprintf(&formatstr, "%d", GOT_WORKTREE_FORMAT_VERSION) == -1) {
305 err = got_error_from_errno("asprintf");
306 goto done;
308 err = create_meta_file(path_got, GOT_WORKTREE_FORMAT, formatstr);
309 if (err)
310 goto done;
312 done:
313 free(commit_id);
314 free(path_got);
315 free(formatstr);
316 free(absprefix);
317 free(basestr);
318 free(uuidstr);
319 return err;
322 static const struct got_error *
323 open_worktree(struct got_worktree **worktree, const char *path)
325 const struct got_error *err = NULL;
326 char *path_got;
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;
332 const char *errstr;
333 struct got_repository *repo = NULL;
334 uint32_t uuid_status;
336 *worktree = NULL;
338 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
339 err = got_error_from_errno("asprintf");
340 path_got = NULL;
341 goto done;
344 if (asprintf(&path_lock, "%s/%s", path_got, GOT_WORKTREE_LOCK) == -1) {
345 err = got_error_from_errno("asprintf");
346 path_lock = NULL;
347 goto done;
350 fd = open(path_lock, O_RDWR | O_EXLOCK | O_NONBLOCK);
351 if (fd == -1) {
352 err = (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
353 : got_error_from_errno2("open", path_lock));
354 goto done;
357 err = read_meta_file(&formatstr, path_got, GOT_WORKTREE_FORMAT);
358 if (err)
359 goto done;
361 version = strtonum(formatstr, 1, INT_MAX, &errstr);
362 if (errstr) {
363 err = got_error_msg(GOT_ERR_WORKTREE_META,
364 "could not parse work tree format version number");
365 goto done;
367 if (version != GOT_WORKTREE_FORMAT_VERSION) {
368 err = got_error(GOT_ERR_WORKTREE_VERS);
369 goto done;
372 *worktree = calloc(1, sizeof(**worktree));
373 if (*worktree == NULL) {
374 err = got_error_from_errno("calloc");
375 goto done;
377 (*worktree)->lockfd = -1;
379 (*worktree)->root_path = realpath(path, NULL);
380 if ((*worktree)->root_path == NULL) {
381 err = got_error_from_errno2("realpath", path);
382 goto done;
384 err = read_meta_file(&(*worktree)->repo_path, path_got,
385 GOT_WORKTREE_REPOSITORY);
386 if (err)
387 goto done;
389 err = read_meta_file(&(*worktree)->path_prefix, path_got,
390 GOT_WORKTREE_PATH_PREFIX);
391 if (err)
392 goto done;
394 err = read_meta_file(&base_commit_id_str, path_got,
395 GOT_WORKTREE_BASE_COMMIT);
396 if (err)
397 goto done;
399 err = read_meta_file(&uuidstr, path_got, GOT_WORKTREE_UUID);
400 if (err)
401 goto done;
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");
405 goto done;
408 err = got_repo_open(&repo, (*worktree)->repo_path, NULL);
409 if (err)
410 goto done;
412 err = got_object_resolve_id_str(&(*worktree)->base_commit_id, repo,
413 base_commit_id_str);
414 if (err)
415 goto done;
417 err = read_meta_file(&(*worktree)->head_ref_name, path_got,
418 GOT_WORKTREE_HEAD_REF);
419 done:
420 if (repo)
421 got_repo_close(repo);
422 free(path_got);
423 free(path_lock);
424 free(base_commit_id_str);
425 free(uuidstr);
426 free(formatstr);
427 if (err) {
428 if (fd != -1)
429 close(fd);
430 if (*worktree != NULL)
431 got_worktree_close(*worktree);
432 *worktree = NULL;
433 } else
434 (*worktree)->lockfd = fd;
436 return err;
439 const struct got_error *
440 got_worktree_open(struct got_worktree **worktree, const char *path)
442 const struct got_error *err = NULL;
444 do {
445 err = open_worktree(worktree, path);
446 if (err && !(err->code == GOT_ERR_ERRNO && errno == ENOENT))
447 return err;
448 if (*worktree)
449 return NULL;
450 path = dirname(path);
451 if (path == NULL)
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);
471 free(worktree);
472 return err;
475 const char *
476 got_worktree_get_root_path(struct got_worktree *worktree)
478 return worktree->root_path;
481 const char *
482 got_worktree_get_repo_path(struct got_worktree *worktree)
484 return worktree->repo_path;
487 const char *
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);
505 free(absprefix);
506 return NULL;
509 const char *
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");
525 path_got = NULL;
526 goto done;
529 head_ref_name = strdup(got_ref_get_name(head_ref));
530 if (head_ref_name == NULL) {
531 err = got_error_from_errno("strdup");
532 goto done;
535 err = write_head_ref(path_got, head_ref);
536 if (err)
537 goto done;
539 free(worktree->head_ref_name);
540 worktree->head_ref_name = head_ref_name;
541 done:
542 free(path_got);
543 if (err)
544 free(head_ref_name);
545 return err;
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;
560 char *id_str = 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");
566 path_got = NULL;
567 goto done;
570 err = got_object_open(&obj, repo, commit_id);
571 if (err)
572 return err;
574 if (obj->type != GOT_OBJ_TYPE_COMMIT) {
575 err = got_error(GOT_ERR_OBJ_TYPE);
576 goto done;
579 /* Record our base commit. */
580 err = got_object_id_str(&id_str, commit_id);
581 if (err)
582 goto done;
583 err = update_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, id_str);
584 if (err)
585 goto done;
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");
591 goto done;
593 done:
594 if (obj)
595 got_object_close(obj);
596 free(id_str);
597 free(path_got);
598 return err;
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)));
608 return NULL;
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;
615 char *abspath;
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) {
622 struct stat sb;
623 err = NULL;
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);
631 free(abspath);
632 return err;
635 static const struct got_error *
636 check_file_contents_equal(int *same, FILE *f1, FILE *f2)
638 const struct got_error *err = NULL;
639 uint8_t fbuf1[8192];
640 uint8_t fbuf2[8192];
641 size_t flen1 = 0, flen2 = 0;
643 *same = 1;
645 for (;;) {
646 flen1 = fread(fbuf1, 1, sizeof(fbuf1), f1);
647 if (flen1 == 0 && ferror(f1)) {
648 err = got_error_from_errno("fread");
649 break;
651 flen2 = fread(fbuf2, 1, sizeof(fbuf2), f2);
652 if (flen2 == 0 && ferror(f2)) {
653 err = got_error_from_errno("fread");
654 break;
656 if (flen1 == 0) {
657 if (flen2 != 0)
658 *same = 0;
659 break;
660 } else if (flen2 == 0) {
661 if (flen1 != 0)
662 *same = 0;
663 break;
664 } else if (flen1 == flen2) {
665 if (memcmp(fbuf1, fbuf2, flen2) != 0) {
666 *same = 0;
667 break;
669 } else {
670 *same = 0;
671 break;
675 return err;
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;
682 struct stat sb;
683 size_t size1, size2;
684 FILE *f1 = NULL, *f2 = NULL;
686 *same = 1;
688 if (lstat(f1_path, &sb) != 0) {
689 err = got_error_from_errno2("lstat", f1_path);
690 goto done;
692 size1 = sb.st_size;
694 if (lstat(f2_path, &sb) != 0) {
695 err = got_error_from_errno2("lstat", f2_path);
696 goto done;
698 size2 = sb.st_size;
700 if (size1 != size2) {
701 *same = 0;
702 return NULL;
705 f1 = fopen(f1_path, "r");
706 if (f1 == NULL)
707 return got_error_from_errno2("fopen", f1_path);
709 f2 = fopen(f2_path, "r");
710 if (f2 == NULL) {
711 err = got_error_from_errno2("fopen", f2_path);
712 goto done;
715 err = check_file_contents_equal(same, f1, f2);
716 done:
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");
722 return err;
725 /*
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.
729 */
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;
739 int merged_fd = -1;
740 FILE *f_orig = NULL;
741 char *blob_orig_path = NULL;
742 char *merged_path = NULL, *base_path = NULL;
743 int overlapcnt = 0;
744 char *parent;
745 char *symlink_path = NULL;
746 FILE *symlinkf = NULL;
748 *local_changes_subsumed = 0;
750 parent = dirname(ondisk_path);
751 if (parent == NULL)
752 return got_error_from_errno2("dirname", ondisk_path);
754 if (asprintf(&base_path, "%s/got-merged", parent) == -1)
755 return got_error_from_errno("asprintf");
757 err = got_opentemp_named_fd(&merged_path, &merged_fd, base_path);
758 if (err)
759 goto done;
761 free(base_path);
762 if (asprintf(&base_path, "%s/got-merge-blob-orig", parent) == -1) {
763 err = got_error_from_errno("asprintf");
764 base_path = NULL;
765 goto done;
768 err = got_opentemp_named(&blob_orig_path, &f_orig, base_path);
769 if (err)
770 goto done;
771 if (blob_orig) {
772 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_orig,
773 blob_orig);
774 if (err)
775 goto done;
776 } else {
777 /*
778 * If the file has no blob, this is an "add vs add" conflict,
779 * and we simply use an empty ancestor file to make both files
780 * appear in the merged result in their entirety.
781 */
784 /*
785 * In order the run a 3-way merge with a symlink we copy the symlink's
786 * target path into a temporary file and use that file with diff3.
787 */
788 if (S_ISLNK(st_mode)) {
789 char target_path[PATH_MAX];
790 ssize_t target_len;
791 size_t n;
793 free(base_path);
794 if (asprintf(&base_path, "%s/got-symlink-merge",
795 parent) == -1) {
796 err = got_error_from_errno("asprintf");
797 base_path = NULL;
798 goto done;
800 err = got_opentemp_named(&symlink_path, &symlinkf, base_path);
801 if (err)
802 goto done;
803 target_len = readlink(ondisk_path, target_path,
804 sizeof(target_path));
805 if (target_len == -1) {
806 err = got_error_from_errno2("readlink", ondisk_path);
807 goto done;
809 n = fwrite(target_path, 1, target_len, symlinkf);
810 if (n != target_len) {
811 err = got_ferror(symlinkf, GOT_ERR_IO);
812 goto done;
814 if (fflush(symlinkf) == EOF) {
815 err = got_error_from_errno2("fflush", symlink_path);
816 goto done;
820 err = got_merge_diff3(&overlapcnt, merged_fd, deriv_path,
821 blob_orig_path, symlink_path ? symlink_path : ondisk_path,
822 label_deriv, label_orig, NULL);
823 if (err)
824 goto done;
826 err = (*progress_cb)(progress_arg,
827 overlapcnt > 0 ? GOT_STATUS_CONFLICT : GOT_STATUS_MERGE, path);
828 if (err)
829 goto done;
831 if (fsync(merged_fd) != 0) {
832 err = got_error_from_errno("fsync");
833 goto done;
836 /* Check if a clean merge has subsumed all local changes. */
837 if (overlapcnt == 0) {
838 err = check_files_equal(local_changes_subsumed, deriv_path,
839 merged_path);
840 if (err)
841 goto done;
844 if (fchmod(merged_fd, st_mode) != 0) {
845 err = got_error_from_errno2("fchmod", merged_path);
846 goto done;
849 if (rename(merged_path, ondisk_path) != 0) {
850 err = got_error_from_errno3("rename", merged_path,
851 ondisk_path);
852 goto done;
854 done:
855 if (err) {
856 if (merged_path)
857 unlink(merged_path);
859 if (symlink_path) {
860 if (unlink(symlink_path) == -1 && err == NULL)
861 err = got_error_from_errno2("unlink", symlink_path);
863 if (symlinkf && fclose(symlinkf) == EOF && err == NULL)
864 err = got_error_from_errno2("fclose", symlink_path);
865 free(symlink_path);
866 if (merged_fd != -1 && close(merged_fd) != 0 && err == NULL)
867 err = got_error_from_errno("close");
868 if (f_orig && fclose(f_orig) != 0 && err == NULL)
869 err = got_error_from_errno("fclose");
870 free(merged_path);
871 free(base_path);
872 if (blob_orig_path) {
873 unlink(blob_orig_path);
874 free(blob_orig_path);
876 return err;
879 static const struct got_error *
880 update_symlink(const char *ondisk_path, const char *target_path,
881 size_t target_len)
883 /* This is not atomic but matches what 'ln -sf' does. */
884 if (unlink(ondisk_path) == -1)
885 return got_error_from_errno2("unlink", ondisk_path);
886 if (symlink(target_path, ondisk_path) == -1)
887 return got_error_from_errno3("symlink", target_path,
888 ondisk_path);
889 return NULL;
892 /*
893 * Overwrite a symlink (or a regular file in case there was a "bad" symlink)
894 * in the work tree with a file that contains conflict markers and the
895 * conflicting target paths of the original version, a "derived version"
896 * of a symlink from an incoming change, and a local version of the symlink.
898 * The original versions's target path can be NULL if it is not available,
899 * such as if both derived versions added a new symlink at the same path.
901 * The incoming derived symlink target is NULL in case the incoming change
902 * has deleted this symlink.
903 */
904 static const struct got_error *
905 install_symlink_conflict(const char *deriv_target,
906 struct got_object_id *deriv_base_commit_id, const char *orig_target,
907 const char *label_orig, const char *local_target, const char *ondisk_path)
909 const struct got_error *err;
910 char *id_str = NULL, *label_deriv = NULL, *path = NULL;
911 FILE *f = NULL;
913 err = got_object_id_str(&id_str, deriv_base_commit_id);
914 if (err)
915 return got_error_from_errno("asprintf");
917 if (asprintf(&label_deriv, "%s: commit %s",
918 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
919 err = got_error_from_errno("asprintf");
920 goto done;
923 err = got_opentemp_named(&path, &f, "got-symlink-conflict");
924 if (err)
925 goto done;
927 if (fprintf(f, "%s: Could not install symbolic link because of merge "
928 "conflict.\nln(1) may be used to fix the situation. If this is "
929 "intended to be a\nregular file instead then its expected "
930 "contents may be filled in.\nThe following conflicting symlink "
931 "target paths were found:\n"
932 "%s %s\n%s\n%s%s%s%s%s\n%s\n%s\n", getprogname(),
933 GOT_DIFF_CONFLICT_MARKER_BEGIN, label_deriv,
934 deriv_target ? deriv_target : "(symlink was deleted)",
935 orig_target ? label_orig : "",
936 orig_target ? "\n" : "",
937 orig_target ? orig_target : "",
938 orig_target ? "\n" : "",
939 GOT_DIFF_CONFLICT_MARKER_SEP,
940 local_target, GOT_DIFF_CONFLICT_MARKER_END) < 0) {
941 err = got_error_from_errno2("fprintf", path);
942 goto done;
945 if (unlink(ondisk_path) == -1) {
946 err = got_error_from_errno2("unlink", ondisk_path);
947 goto done;
949 if (rename(path, ondisk_path) == -1) {
950 err = got_error_from_errno3("rename", path, ondisk_path);
951 goto done;
953 if (chmod(ondisk_path, GOT_DEFAULT_FILE_MODE) == -1) {
954 err = got_error_from_errno2("chmod", ondisk_path);
955 goto done;
957 done:
958 if (f != NULL && fclose(f) == EOF && err == NULL)
959 err = got_error_from_errno2("fclose", path);
960 free(path);
961 free(id_str);
962 free(label_deriv);
963 return err;
966 /* forward declaration */
967 static const struct got_error *
968 merge_blob(int *, struct got_worktree *, struct got_blob_object *,
969 const char *, const char *, uint16_t, const char *,
970 struct got_blob_object *, struct got_object_id *,
971 struct got_repository *, got_worktree_checkout_cb, void *);
973 /*
974 * Merge a symlink into the work tree, where blob_orig acts as the common
975 * ancestor, blob_deriv acts as the first derived version, and the symlink
976 * on disk acts as the second derived version.
977 * Assume that contents of both blobs represent symlinks.
978 */
979 static const struct got_error *
980 merge_symlink(struct got_worktree *worktree,
981 struct got_blob_object *blob_orig, const char *ondisk_path,
982 const char *path, uint16_t st_mode, const char *label_orig,
983 struct got_blob_object *blob_deriv,
984 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
985 got_worktree_checkout_cb progress_cb, void *progress_arg)
987 const struct got_error *err = NULL;
988 char *ancestor_target = NULL, *deriv_target = NULL;
989 struct stat sb;
990 ssize_t ondisk_len, deriv_len;
991 char ondisk_target[PATH_MAX];
992 int have_local_change = 0;
993 int have_incoming_change = 0;
995 if (lstat(ondisk_path, &sb) == -1)
996 return got_error_from_errno2("lstat", ondisk_path);
998 if (!S_ISLNK(sb.st_mode)) {
999 /*
1000 * If there is a regular file on disk, merge the symlink
1001 * target path into this file, which will usually cause
1002 * a merge conflict.
1004 if (S_ISREG(sb.st_mode)) {
1005 int local_changes_subsumed;
1006 return merge_blob(&local_changes_subsumed, worktree,
1007 NULL, ondisk_path, path, sb.st_mode, label_orig,
1008 blob_deriv, deriv_base_commit_id,
1009 repo, progress_cb, progress_arg);
1012 /* TODO symlink is obstructed; do something */
1013 return got_error_path(ondisk_path, GOT_ERR_FILE_OBSTRUCTED);
1016 ondisk_len = readlink(ondisk_path, ondisk_target,
1017 sizeof(ondisk_target));
1018 if (ondisk_len == -1) {
1019 err = got_error_from_errno2("readlink",
1020 ondisk_path);
1021 goto done;
1023 ondisk_target[ondisk_len] = '\0';
1025 if (blob_orig) {
1026 err = got_object_blob_read_to_str(&ancestor_target, blob_orig);
1027 if (err)
1028 goto done;
1031 err = got_object_blob_read_to_str(&deriv_target, blob_deriv);
1032 if (err)
1033 goto done;
1035 if (ancestor_target == NULL ||
1036 (ondisk_len != strlen(ancestor_target) ||
1037 memcmp(ondisk_target, ancestor_target, ondisk_len) != 0))
1038 have_local_change = 1;
1040 deriv_len = strlen(deriv_target);
1041 if (ancestor_target == NULL ||
1042 (deriv_len != strlen(ancestor_target) ||
1043 memcmp(deriv_target, ancestor_target, deriv_len) != 0))
1044 have_incoming_change = 1;
1046 if (!have_local_change && !have_incoming_change) {
1047 if (ancestor_target) {
1048 /* Both sides made the same change. */
1049 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
1050 path);
1051 } else if (deriv_len == ondisk_len &&
1052 memcmp(ondisk_target, deriv_target, deriv_len) == 0) {
1053 /* Both sides added the same symlink. */
1054 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
1055 path);
1056 } else {
1057 /* Both sides added symlinks which don't match. */
1058 err = install_symlink_conflict(deriv_target,
1059 deriv_base_commit_id, ancestor_target,
1060 label_orig, ondisk_target, ondisk_path);
1061 if (err)
1062 goto done;
1063 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
1064 path);
1066 } else if (!have_local_change && have_incoming_change) {
1067 /* Apply the incoming change. */
1068 err = update_symlink(ondisk_path, deriv_target,
1069 strlen(deriv_target));
1070 if (err)
1071 goto done;
1072 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
1073 } else if (have_local_change && have_incoming_change) {
1074 err = install_symlink_conflict(deriv_target,
1075 deriv_base_commit_id, ancestor_target, label_orig,
1076 ondisk_target, ondisk_path);
1077 if (err)
1078 goto done;
1079 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
1080 path);
1083 done:
1084 free(ancestor_target);
1085 free(deriv_target);
1086 return err;
1090 * Perform a 3-way merge where blob_orig acts as the common ancestor,
1091 * blob_deriv acts as the first derived version, and the file on disk
1092 * acts as the second derived version.
1094 static const struct got_error *
1095 merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
1096 struct got_blob_object *blob_orig, const char *ondisk_path,
1097 const char *path, uint16_t st_mode, const char *label_orig,
1098 struct got_blob_object *blob_deriv,
1099 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
1100 got_worktree_checkout_cb progress_cb, void *progress_arg)
1102 const struct got_error *err = NULL;
1103 FILE *f_deriv = NULL;
1104 char *blob_deriv_path = NULL, *base_path = NULL, *id_str = NULL;
1105 char *label_deriv = NULL, *parent;
1107 *local_changes_subsumed = 0;
1109 parent = dirname(ondisk_path);
1110 if (parent == NULL)
1111 return got_error_from_errno2("dirname", ondisk_path);
1113 free(base_path);
1114 if (asprintf(&base_path, "%s/got-merge-blob-deriv", parent) == -1) {
1115 err = got_error_from_errno("asprintf");
1116 base_path = NULL;
1117 goto done;
1120 err = got_opentemp_named(&blob_deriv_path, &f_deriv, base_path);
1121 if (err)
1122 goto done;
1123 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_deriv,
1124 blob_deriv);
1125 if (err)
1126 goto done;
1128 err = got_object_id_str(&id_str, deriv_base_commit_id);
1129 if (err)
1130 goto done;
1131 if (asprintf(&label_deriv, "%s: commit %s",
1132 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
1133 err = got_error_from_errno("asprintf");
1134 goto done;
1137 err = merge_file(local_changes_subsumed, worktree, blob_orig,
1138 ondisk_path, path, st_mode, blob_deriv_path, label_orig,
1139 label_deriv, repo, progress_cb, progress_arg);
1140 done:
1141 if (f_deriv && fclose(f_deriv) != 0 && err == NULL)
1142 err = got_error_from_errno("fclose");
1143 free(base_path);
1144 if (blob_deriv_path) {
1145 unlink(blob_deriv_path);
1146 free(blob_deriv_path);
1148 free(id_str);
1149 free(label_deriv);
1150 return err;
1153 static const struct got_error *
1154 create_fileindex_entry(struct got_fileindex_entry **new_iep,
1155 struct got_fileindex *fileindex, struct got_object_id *base_commit_id,
1156 const char *ondisk_path, const char *path, struct got_object_id *blob_id)
1158 const struct got_error *err = NULL;
1159 struct got_fileindex_entry *new_ie;
1161 *new_iep = NULL;
1163 err = got_fileindex_entry_alloc(&new_ie, path);
1164 if (err)
1165 return err;
1167 err = got_fileindex_entry_update(new_ie, ondisk_path,
1168 blob_id->sha1, base_commit_id->sha1, 1);
1169 if (err)
1170 goto done;
1172 err = got_fileindex_entry_add(fileindex, new_ie);
1173 done:
1174 if (err)
1175 got_fileindex_entry_free(new_ie);
1176 else
1177 *new_iep = new_ie;
1178 return err;
1181 static mode_t
1182 get_ondisk_perms(int executable, mode_t st_mode)
1184 mode_t xbits = S_IXUSR;
1186 if (executable) {
1187 /* Map read bits to execute bits. */
1188 if (st_mode & S_IRGRP)
1189 xbits |= S_IXGRP;
1190 if (st_mode & S_IROTH)
1191 xbits |= S_IXOTH;
1192 return st_mode | xbits;
1195 return (st_mode & ~(S_IXUSR | S_IXGRP | S_IXOTH));
1198 /* forward declaration */
1199 static const struct got_error *
1200 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1201 const char *path, mode_t te_mode, mode_t st_mode,
1202 struct got_blob_object *blob, int restoring_missing_file,
1203 int reverting_versioned_file, int installing_bad_symlink,
1204 int path_is_unversioned, struct got_repository *repo,
1205 got_worktree_checkout_cb progress_cb, void *progress_arg);
1208 * This function assumes that the provided symlink target points at a
1209 * safe location in the work tree!
1211 static const struct got_error *
1212 replace_existing_symlink(const char *ondisk_path, const char *target_path,
1213 size_t target_len)
1215 const struct got_error *err = NULL;
1216 ssize_t elen;
1217 char etarget[PATH_MAX];
1218 int fd;
1221 * "Bad" symlinks (those pointing outside the work tree or into the
1222 * .got directory) are installed in the work tree as a regular file
1223 * which contains the bad symlink target path.
1224 * The new symlink target has already been checked for safety by our
1225 * caller. If we can successfully open a regular file then we simply
1226 * replace this file with a symlink below.
1228 fd = open(ondisk_path, O_RDWR | O_EXCL | O_NOFOLLOW);
1229 if (fd == -1) {
1230 if (errno != ELOOP)
1231 return got_error_from_errno2("open", ondisk_path);
1233 /* We are updating an existing on-disk symlink. */
1234 elen = readlink(ondisk_path, etarget, sizeof(etarget));
1235 if (elen == -1)
1236 return got_error_from_errno2("readlink", ondisk_path);
1238 if (elen == target_len &&
1239 memcmp(etarget, target_path, target_len) == 0)
1240 return NULL; /* nothing to do */
1243 err = update_symlink(ondisk_path, target_path, target_len);
1244 if (fd != -1 && close(fd) == -1 && err == NULL)
1245 err = got_error_from_errno2("close", ondisk_path);
1246 return err;
1249 static const struct got_error *
1250 install_symlink(int *is_bad_symlink, struct got_worktree *worktree,
1251 const char *ondisk_path, const char *path, struct got_blob_object *blob,
1252 int restoring_missing_file, int reverting_versioned_file,
1253 int path_is_unversioned, struct got_repository *repo,
1254 got_worktree_checkout_cb progress_cb, void *progress_arg)
1256 const struct got_error *err = NULL;
1257 char target_path[PATH_MAX];
1258 size_t len, target_len = 0;
1259 char *resolved_path = NULL, *abspath = NULL;
1260 char *path_got = NULL;
1261 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1262 size_t hdrlen = got_object_blob_get_hdrlen(blob);
1264 *is_bad_symlink = 0;
1267 * Blob object content specifies the target path of the link.
1268 * If a symbolic link cannot be installed we instead create
1269 * a regular file which contains the link target path stored
1270 * in the blob object.
1272 do {
1273 err = got_object_blob_read_block(&len, blob);
1274 if (len + target_len >= sizeof(target_path)) {
1275 /* Path too long; install as a regular file. */
1276 *is_bad_symlink = 1;
1277 got_object_blob_rewind(blob);
1278 return install_blob(worktree, ondisk_path, path,
1279 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1280 restoring_missing_file, reverting_versioned_file,
1281 1, path_is_unversioned, repo, progress_cb,
1282 progress_arg);
1284 if (len > 0) {
1285 /* Skip blob object header first time around. */
1286 memcpy(target_path + target_len, buf + hdrlen,
1287 len - hdrlen);
1288 target_len += len - hdrlen;
1289 hdrlen = 0;
1291 } while (len != 0);
1292 target_path[target_len] = '\0';
1295 * Relative symlink target lookup should begin at the directory
1296 * in which the blob object is being installed.
1298 if (!got_path_is_absolute(target_path)) {
1299 char *parent = dirname(ondisk_path);
1300 if (parent == NULL) {
1301 err = got_error_from_errno2("dirname", ondisk_path);
1302 goto done;
1304 if (asprintf(&abspath, "%s/%s", parent, target_path) == -1) {
1305 err = got_error_from_errno("asprintf");
1306 goto done;
1311 * unveil(2) restricts our view of paths in the filesystem.
1312 * ENOENT will occur if a link target path does not exist or
1313 * if it points outside our unveiled path space.
1315 resolved_path = realpath(abspath ? abspath : target_path, NULL);
1316 if (resolved_path == NULL) {
1317 if (errno != ENOENT) {
1318 err = got_error_from_errno2("realpath", target_path);
1319 goto done;
1323 /* Only allow symlinks pointing at paths within the work tree. */
1324 if (!got_path_is_child(resolved_path ? resolved_path : (abspath ?
1325 abspath : target_path), worktree->root_path,
1326 strlen(worktree->root_path))) {
1327 /* install as a regular file */
1328 *is_bad_symlink = 1;
1329 got_object_blob_rewind(blob);
1330 err = install_blob(worktree, ondisk_path, path,
1331 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1332 restoring_missing_file, reverting_versioned_file, 1,
1333 path_is_unversioned, repo, progress_cb, progress_arg);
1334 goto done;
1337 /* Do not allow symlinks pointing into the .got directory. */
1338 if (asprintf(&path_got, "%s/%s", worktree->root_path,
1339 GOT_WORKTREE_GOT_DIR) == -1) {
1340 err = got_error_from_errno("asprintf");
1341 goto done;
1343 if (got_path_is_child(resolved_path ? resolved_path : (abspath ?
1344 abspath : target_path), path_got, strlen(path_got))) {
1345 /* install as a regular file */
1346 *is_bad_symlink = 1;
1347 got_object_blob_rewind(blob);
1348 err = install_blob(worktree, ondisk_path, path,
1349 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1350 restoring_missing_file, reverting_versioned_file, 1,
1351 path_is_unversioned, repo, progress_cb, progress_arg);
1352 goto done;
1355 if (symlink(target_path, ondisk_path) == -1) {
1356 if (errno == EEXIST) {
1357 if (path_is_unversioned) {
1358 err = (*progress_cb)(progress_arg,
1359 GOT_STATUS_UNVERSIONED, path);
1360 goto done;
1362 err = replace_existing_symlink(ondisk_path,
1363 target_path, target_len);
1364 if (err)
1365 goto done;
1366 if (progress_cb) {
1367 err = (*progress_cb)(progress_arg,
1368 reverting_versioned_file ?
1369 GOT_STATUS_REVERT : GOT_STATUS_UPDATE,
1370 path);
1372 goto done; /* Nothing else to do. */
1375 if (errno == ENOENT) {
1376 char *parent = dirname(ondisk_path);
1377 if (parent == NULL) {
1378 err = got_error_from_errno2("dirname",
1379 ondisk_path);
1380 goto done;
1382 err = add_dir_on_disk(worktree, parent);
1383 if (err)
1384 goto done;
1386 * Retry, and fall through to error handling
1387 * below if this second attempt fails.
1389 if (symlink(target_path, ondisk_path) != -1) {
1390 err = NULL; /* success */
1391 goto done;
1395 /* Handle errors from first or second creation attempt. */
1396 if (errno == ENAMETOOLONG) {
1397 /* bad target path; install as a regular file */
1398 *is_bad_symlink = 1;
1399 got_object_blob_rewind(blob);
1400 err = install_blob(worktree, ondisk_path, path,
1401 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1402 restoring_missing_file, reverting_versioned_file, 1,
1403 path_is_unversioned, repo,
1404 progress_cb, progress_arg);
1405 } else if (errno == ENOTDIR) {
1406 err = got_error_path(ondisk_path,
1407 GOT_ERR_FILE_OBSTRUCTED);
1408 } else {
1409 err = got_error_from_errno3("symlink",
1410 target_path, ondisk_path);
1412 } else if (progress_cb)
1413 err = (*progress_cb)(progress_arg, reverting_versioned_file ?
1414 GOT_STATUS_REVERT : GOT_STATUS_ADD, path);
1415 done:
1416 free(resolved_path);
1417 free(abspath);
1418 free(path_got);
1419 return err;
1422 static const struct got_error *
1423 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1424 const char *path, mode_t te_mode, mode_t st_mode,
1425 struct got_blob_object *blob, int restoring_missing_file,
1426 int reverting_versioned_file, int installing_bad_symlink,
1427 int path_is_unversioned, struct got_repository *repo,
1428 got_worktree_checkout_cb progress_cb, void *progress_arg)
1430 const struct got_error *err = NULL;
1431 int fd = -1;
1432 size_t len, hdrlen;
1433 int update = 0;
1434 char *tmppath = NULL;
1436 fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1437 GOT_DEFAULT_FILE_MODE);
1438 if (fd == -1) {
1439 if (errno == ENOENT) {
1440 char *parent = dirname(path);
1441 if (parent == NULL)
1442 return got_error_from_errno2("dirname", path);
1443 err = add_dir_on_disk(worktree, parent);
1444 if (err)
1445 return err;
1446 fd = open(ondisk_path,
1447 O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1448 GOT_DEFAULT_FILE_MODE);
1449 if (fd == -1)
1450 return got_error_from_errno2("open",
1451 ondisk_path);
1452 } else if (errno == EEXIST) {
1453 if (path_is_unversioned) {
1454 err = (*progress_cb)(progress_arg,
1455 GOT_STATUS_UNVERSIONED, path);
1456 goto done;
1458 if (!S_ISREG(st_mode) && !installing_bad_symlink) {
1459 /* TODO file is obstructed; do something */
1460 err = got_error_path(ondisk_path,
1461 GOT_ERR_FILE_OBSTRUCTED);
1462 goto done;
1463 } else {
1464 err = got_opentemp_named_fd(&tmppath, &fd,
1465 ondisk_path);
1466 if (err)
1467 goto done;
1468 update = 1;
1470 } else
1471 return got_error_from_errno2("open", ondisk_path);
1474 if (progress_cb) {
1475 if (restoring_missing_file)
1476 err = (*progress_cb)(progress_arg, GOT_STATUS_MISSING,
1477 path);
1478 else if (reverting_versioned_file)
1479 err = (*progress_cb)(progress_arg, GOT_STATUS_REVERT,
1480 path);
1481 else
1482 err = (*progress_cb)(progress_arg,
1483 update ? GOT_STATUS_UPDATE : GOT_STATUS_ADD, path);
1484 if (err)
1485 goto done;
1488 hdrlen = got_object_blob_get_hdrlen(blob);
1489 do {
1490 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1491 err = got_object_blob_read_block(&len, blob);
1492 if (err)
1493 break;
1494 if (len > 0) {
1495 /* Skip blob object header first time around. */
1496 ssize_t outlen = write(fd, buf + hdrlen, len - hdrlen);
1497 if (outlen == -1) {
1498 err = got_error_from_errno("write");
1499 goto done;
1500 } else if (outlen != len - hdrlen) {
1501 err = got_error(GOT_ERR_IO);
1502 goto done;
1504 hdrlen = 0;
1506 } while (len != 0);
1508 if (fsync(fd) != 0) {
1509 err = got_error_from_errno("fsync");
1510 goto done;
1513 if (update) {
1514 if (rename(tmppath, ondisk_path) != 0) {
1515 err = got_error_from_errno3("rename", tmppath,
1516 ondisk_path);
1517 unlink(tmppath);
1518 goto done;
1522 if (chmod(ondisk_path,
1523 get_ondisk_perms(te_mode & S_IXUSR, st_mode)) == -1) {
1524 err = got_error_from_errno2("chmod", ondisk_path);
1525 goto done;
1528 done:
1529 if (fd != -1 && close(fd) != 0 && err == NULL)
1530 err = got_error_from_errno("close");
1531 free(tmppath);
1532 return err;
1535 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1536 static const struct got_error *
1537 get_modified_file_content_status(unsigned char *status, FILE *f)
1539 const struct got_error *err = NULL;
1540 const char *markers[3] = {
1541 GOT_DIFF_CONFLICT_MARKER_BEGIN,
1542 GOT_DIFF_CONFLICT_MARKER_SEP,
1543 GOT_DIFF_CONFLICT_MARKER_END
1545 int i = 0;
1546 char *line;
1547 size_t len;
1548 const char delim[3] = {'\0', '\0', '\0'};
1550 while (*status == GOT_STATUS_MODIFY) {
1551 line = fparseln(f, &len, NULL, delim, 0);
1552 if (line == NULL) {
1553 if (feof(f))
1554 break;
1555 err = got_ferror(f, GOT_ERR_IO);
1556 break;
1559 if (strncmp(line, markers[i], strlen(markers[i])) == 0) {
1560 if (strcmp(markers[i], GOT_DIFF_CONFLICT_MARKER_END)
1561 == 0)
1562 *status = GOT_STATUS_CONFLICT;
1563 else
1564 i++;
1568 return err;
1571 static int
1572 xbit_differs(struct got_fileindex_entry *ie, uint16_t st_mode)
1574 mode_t ie_mode = got_fileindex_perms_to_st(ie);
1575 return ((ie_mode & S_IXUSR) != (st_mode & S_IXUSR));
1578 static int
1579 stat_info_differs(struct got_fileindex_entry *ie, struct stat *sb)
1581 return !(ie->ctime_sec == sb->st_ctime &&
1582 ie->ctime_nsec == sb->st_ctimensec &&
1583 ie->mtime_sec == sb->st_mtime &&
1584 ie->mtime_nsec == sb->st_mtimensec &&
1585 ie->size == (sb->st_size & 0xffffffff) &&
1586 !xbit_differs(ie, sb->st_mode));
1589 static unsigned char
1590 get_staged_status(struct got_fileindex_entry *ie)
1592 switch (got_fileindex_entry_stage_get(ie)) {
1593 case GOT_FILEIDX_STAGE_ADD:
1594 return GOT_STATUS_ADD;
1595 case GOT_FILEIDX_STAGE_DELETE:
1596 return GOT_STATUS_DELETE;
1597 case GOT_FILEIDX_STAGE_MODIFY:
1598 return GOT_STATUS_MODIFY;
1599 default:
1600 return GOT_STATUS_NO_CHANGE;
1604 static const struct got_error *
1605 get_symlink_status(unsigned char *status, struct stat *sb,
1606 struct got_fileindex_entry *ie, const char *abspath,
1607 int dirfd, const char *de_name, struct got_blob_object *blob)
1609 const struct got_error *err = NULL;
1610 char target_path[PATH_MAX];
1611 char etarget[PATH_MAX];
1612 ssize_t elen;
1613 size_t len, target_len = 0;
1614 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1615 size_t hdrlen = got_object_blob_get_hdrlen(blob);
1617 *status = GOT_STATUS_NO_CHANGE;
1619 /* Blob object content specifies the target path of the link. */
1620 do {
1621 err = got_object_blob_read_block(&len, blob);
1622 if (err)
1623 return err;
1624 if (len + target_len >= sizeof(target_path)) {
1626 * Should not happen. The blob contents were OK
1627 * when this symlink was installed.
1629 return got_error(GOT_ERR_NO_SPACE);
1631 if (len > 0) {
1632 /* Skip blob object header first time around. */
1633 memcpy(target_path + target_len, buf + hdrlen,
1634 len - hdrlen);
1635 target_len += len - hdrlen;
1636 hdrlen = 0;
1638 } while (len != 0);
1639 target_path[target_len] = '\0';
1641 if (dirfd != -1) {
1642 elen = readlinkat(dirfd, de_name, etarget, sizeof(etarget));
1643 if (elen == -1)
1644 return got_error_from_errno2("readlinkat", abspath);
1645 } else {
1646 elen = readlink(abspath, etarget, sizeof(etarget));
1647 if (elen == -1)
1648 return got_error_from_errno2("readlink", abspath);
1651 if (elen != target_len || memcmp(etarget, target_path, target_len) != 0)
1652 *status = GOT_STATUS_MODIFY;
1654 return NULL;
1657 static const struct got_error *
1658 get_file_status(unsigned char *status, struct stat *sb,
1659 struct got_fileindex_entry *ie, const char *abspath,
1660 int dirfd, const char *de_name, struct got_repository *repo)
1662 const struct got_error *err = NULL;
1663 struct got_object_id id;
1664 size_t hdrlen;
1665 int fd = -1;
1666 FILE *f = NULL;
1667 uint8_t fbuf[8192];
1668 struct got_blob_object *blob = NULL;
1669 size_t flen, blen;
1670 unsigned char staged_status = get_staged_status(ie);
1672 *status = GOT_STATUS_NO_CHANGE;
1675 * Whenever the caller provides a directory descriptor and a
1676 * directory entry name for the file, use them! This prevents
1677 * race conditions if filesystem paths change beneath our feet.
1679 if (dirfd != -1) {
1680 if (fstatat(dirfd, de_name, sb, AT_SYMLINK_NOFOLLOW) == -1) {
1681 if (errno == ENOENT) {
1682 if (got_fileindex_entry_has_file_on_disk(ie))
1683 *status = GOT_STATUS_MISSING;
1684 else
1685 *status = GOT_STATUS_DELETE;
1686 goto done;
1688 err = got_error_from_errno2("fstatat", abspath);
1689 goto done;
1691 } else {
1692 fd = open(abspath, O_RDONLY | O_NOFOLLOW);
1693 if (fd == -1 && errno != ENOENT && errno != ELOOP)
1694 return got_error_from_errno2("open", abspath);
1695 else if (fd == -1 && errno == ELOOP) {
1696 if (lstat(abspath, sb) == -1)
1697 return got_error_from_errno2("lstat", abspath);
1698 } else if (fd == -1 || fstat(fd, sb) == -1) {
1699 if (errno == ENOENT) {
1700 if (got_fileindex_entry_has_file_on_disk(ie))
1701 *status = GOT_STATUS_MISSING;
1702 else
1703 *status = GOT_STATUS_DELETE;
1704 goto done;
1706 err = got_error_from_errno2("fstat", abspath);
1707 goto done;
1711 if (!S_ISREG(sb->st_mode) && !S_ISLNK(sb->st_mode)) {
1712 *status = GOT_STATUS_OBSTRUCTED;
1713 goto done;
1716 if (!got_fileindex_entry_has_file_on_disk(ie)) {
1717 *status = GOT_STATUS_DELETE;
1718 goto done;
1719 } else if (!got_fileindex_entry_has_blob(ie) &&
1720 staged_status != GOT_STATUS_ADD) {
1721 *status = GOT_STATUS_ADD;
1722 goto done;
1725 if (!stat_info_differs(ie, sb))
1726 goto done;
1728 if (staged_status == GOT_STATUS_MODIFY ||
1729 staged_status == GOT_STATUS_ADD)
1730 memcpy(id.sha1, ie->staged_blob_sha1, sizeof(id.sha1));
1731 else
1732 memcpy(id.sha1, ie->blob_sha1, sizeof(id.sha1));
1734 err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf));
1735 if (err)
1736 goto done;
1738 if (S_ISLNK(sb->st_mode)) {
1739 err = get_symlink_status(status, sb, ie, abspath, dirfd,
1740 de_name, blob);
1741 goto done;
1745 if (dirfd != -1) {
1746 fd = openat(dirfd, de_name, O_RDONLY | O_NOFOLLOW);
1747 if (fd == -1) {
1748 err = got_error_from_errno2("openat", abspath);
1749 goto done;
1753 f = fdopen(fd, "r");
1754 if (f == NULL) {
1755 err = got_error_from_errno2("fdopen", abspath);
1756 goto done;
1758 fd = -1;
1759 hdrlen = got_object_blob_get_hdrlen(blob);
1760 for (;;) {
1761 const uint8_t *bbuf = got_object_blob_get_read_buf(blob);
1762 err = got_object_blob_read_block(&blen, blob);
1763 if (err)
1764 goto done;
1765 /* Skip length of blob object header first time around. */
1766 flen = fread(fbuf, 1, sizeof(fbuf) - hdrlen, f);
1767 if (flen == 0 && ferror(f)) {
1768 err = got_error_from_errno("fread");
1769 goto done;
1771 if (blen == 0) {
1772 if (flen != 0)
1773 *status = GOT_STATUS_MODIFY;
1774 break;
1775 } else if (flen == 0) {
1776 if (blen != 0)
1777 *status = GOT_STATUS_MODIFY;
1778 break;
1779 } else if (blen - hdrlen == flen) {
1780 /* Skip blob object header first time around. */
1781 if (memcmp(bbuf + hdrlen, fbuf, flen) != 0) {
1782 *status = GOT_STATUS_MODIFY;
1783 break;
1785 } else {
1786 *status = GOT_STATUS_MODIFY;
1787 break;
1789 hdrlen = 0;
1792 if (*status == GOT_STATUS_MODIFY) {
1793 rewind(f);
1794 err = get_modified_file_content_status(status, f);
1795 } else if (xbit_differs(ie, sb->st_mode))
1796 *status = GOT_STATUS_MODE_CHANGE;
1797 done:
1798 if (blob)
1799 got_object_blob_close(blob);
1800 if (f != NULL && fclose(f) == EOF && err == NULL)
1801 err = got_error_from_errno2("fclose", abspath);
1802 if (fd != -1 && close(fd) == -1 && err == NULL)
1803 err = got_error_from_errno2("close", abspath);
1804 return err;
1808 * Update timestamps in the file index if a file is unmodified and
1809 * we had to run a full content comparison to find out.
1811 static const struct got_error *
1812 sync_timestamps(char *ondisk_path, unsigned char status,
1813 struct got_fileindex_entry *ie, struct stat *sb)
1815 if (status == GOT_STATUS_NO_CHANGE && stat_info_differs(ie, sb))
1816 return got_fileindex_entry_update(ie, ondisk_path,
1817 ie->blob_sha1, ie->commit_sha1, 1);
1819 return NULL;
1822 static const struct got_error *
1823 update_blob(struct got_worktree *worktree,
1824 struct got_fileindex *fileindex, struct got_fileindex_entry *ie,
1825 struct got_tree_entry *te, const char *path,
1826 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
1827 void *progress_arg)
1829 const struct got_error *err = NULL;
1830 struct got_blob_object *blob = NULL;
1831 char *ondisk_path;
1832 unsigned char status = GOT_STATUS_NO_CHANGE;
1833 struct stat sb;
1835 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, path) == -1)
1836 return got_error_from_errno("asprintf");
1838 if (ie) {
1839 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE) {
1840 err = got_error_path(ie->path, GOT_ERR_FILE_STAGED);
1841 goto done;
1843 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
1844 repo);
1845 if (err)
1846 goto done;
1847 if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE)
1848 sb.st_mode = got_fileindex_perms_to_st(ie);
1849 } else {
1850 sb.st_mode = GOT_DEFAULT_FILE_MODE;
1851 status = GOT_STATUS_UNVERSIONED;
1854 if (status == GOT_STATUS_OBSTRUCTED) {
1855 err = (*progress_cb)(progress_arg, status, path);
1856 goto done;
1858 if (status == GOT_STATUS_CONFLICT) {
1859 err = (*progress_cb)(progress_arg, GOT_STATUS_CANNOT_UPDATE,
1860 path);
1861 goto done;
1864 if (ie && status != GOT_STATUS_MISSING &&
1865 (te->mode & S_IXUSR) == (sb.st_mode & S_IXUSR)) {
1866 if (got_fileindex_entry_has_commit(ie) &&
1867 memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
1868 SHA1_DIGEST_LENGTH) == 0) {
1869 err = sync_timestamps(ondisk_path, status, ie, &sb);
1870 if (err)
1871 goto done;
1872 err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
1873 path);
1874 goto done;
1876 if (got_fileindex_entry_has_blob(ie) &&
1877 memcmp(ie->blob_sha1, te->id.sha1,
1878 SHA1_DIGEST_LENGTH) == 0) {
1879 err = sync_timestamps(ondisk_path, status, ie, &sb);
1880 goto done;
1884 err = got_object_open_as_blob(&blob, repo, &te->id, 8192);
1885 if (err)
1886 goto done;
1888 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_ADD) {
1889 int update_timestamps;
1890 struct got_blob_object *blob2 = NULL;
1891 char *label_orig = NULL;
1892 if (got_fileindex_entry_has_blob(ie)) {
1893 struct got_object_id id2;
1894 memcpy(id2.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
1895 err = got_object_open_as_blob(&blob2, repo, &id2, 8192);
1896 if (err)
1897 goto done;
1899 if (got_fileindex_entry_has_commit(ie)) {
1900 char id_str[SHA1_DIGEST_STRING_LENGTH];
1901 if (got_sha1_digest_to_str(ie->commit_sha1, id_str,
1902 sizeof(id_str)) == NULL) {
1903 err = got_error_path(id_str,
1904 GOT_ERR_BAD_OBJ_ID_STR);
1905 goto done;
1907 if (asprintf(&label_orig, "%s: commit %s",
1908 GOT_MERGE_LABEL_BASE, id_str) == -1) {
1909 err = got_error_from_errno("asprintf");
1910 goto done;
1913 if (S_ISLNK(te->mode)) {
1914 err = merge_symlink(worktree, blob2,
1915 ondisk_path, path, sb.st_mode, label_orig,
1916 blob, worktree->base_commit_id, repo,
1917 progress_cb, progress_arg);
1918 } else {
1919 err = merge_blob(&update_timestamps, worktree, blob2,
1920 ondisk_path, path, sb.st_mode, label_orig, blob,
1921 worktree->base_commit_id, repo,
1922 progress_cb, progress_arg);
1924 free(label_orig);
1925 if (blob2)
1926 got_object_blob_close(blob2);
1927 if (err)
1928 goto done;
1930 * Do not update timestamps of files with local changes.
1931 * Otherwise, a future status walk would treat them as
1932 * unmodified files again.
1934 err = got_fileindex_entry_update(ie, ondisk_path,
1935 blob->id.sha1, worktree->base_commit_id->sha1,
1936 update_timestamps);
1937 } else if (status == GOT_STATUS_MODE_CHANGE) {
1938 err = got_fileindex_entry_update(ie, ondisk_path,
1939 blob->id.sha1, worktree->base_commit_id->sha1, 0);
1940 } else if (status == GOT_STATUS_DELETE) {
1941 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
1942 if (err)
1943 goto done;
1944 err = got_fileindex_entry_update(ie, ondisk_path,
1945 blob->id.sha1, worktree->base_commit_id->sha1, 0);
1946 if (err)
1947 goto done;
1948 } else {
1949 int is_bad_symlink = 0;
1950 if (S_ISLNK(te->mode)) {
1951 err = install_symlink(&is_bad_symlink, worktree,
1952 ondisk_path, path, blob,
1953 status == GOT_STATUS_MISSING, 0,
1954 status == GOT_STATUS_UNVERSIONED, repo,
1955 progress_cb, progress_arg);
1956 } else {
1957 err = install_blob(worktree, ondisk_path, path,
1958 te->mode, sb.st_mode, blob,
1959 status == GOT_STATUS_MISSING, 0, 0,
1960 status == GOT_STATUS_UNVERSIONED, repo,
1961 progress_cb, progress_arg);
1963 if (err)
1964 goto done;
1966 if (ie) {
1967 err = got_fileindex_entry_update(ie, ondisk_path,
1968 blob->id.sha1, worktree->base_commit_id->sha1, 1);
1969 } else {
1970 err = create_fileindex_entry(&ie, fileindex,
1971 worktree->base_commit_id, ondisk_path, path,
1972 &blob->id);
1974 if (err)
1975 goto done;
1977 if (is_bad_symlink) {
1978 got_fileindex_entry_filetype_set(ie,
1979 GOT_FILEIDX_MODE_BAD_SYMLINK);
1982 got_object_blob_close(blob);
1983 done:
1984 free(ondisk_path);
1985 return err;
1988 static const struct got_error *
1989 remove_ondisk_file(const char *root_path, const char *path)
1991 const struct got_error *err = NULL;
1992 char *ondisk_path = NULL;
1994 if (asprintf(&ondisk_path, "%s/%s", root_path, path) == -1)
1995 return got_error_from_errno("asprintf");
1997 if (unlink(ondisk_path) == -1) {
1998 if (errno != ENOENT)
1999 err = got_error_from_errno2("unlink", ondisk_path);
2000 } else {
2001 char *parent = dirname(ondisk_path);
2002 while (parent && strcmp(parent, root_path) != 0) {
2003 if (rmdir(parent) == -1) {
2004 if (errno != ENOTEMPTY)
2005 err = got_error_from_errno2("rmdir",
2006 parent);
2007 break;
2009 parent = dirname(parent);
2012 free(ondisk_path);
2013 return err;
2016 static const struct got_error *
2017 delete_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
2018 struct got_fileindex_entry *ie, struct got_repository *repo,
2019 got_worktree_checkout_cb progress_cb, void *progress_arg)
2021 const struct got_error *err = NULL;
2022 unsigned char status;
2023 struct stat sb;
2024 char *ondisk_path;
2026 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
2027 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
2029 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, ie->path)
2030 == -1)
2031 return got_error_from_errno("asprintf");
2033 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, repo);
2034 if (err)
2035 goto done;
2037 if (S_ISLNK(sb.st_mode) && status != GOT_STATUS_NO_CHANGE) {
2038 char ondisk_target[PATH_MAX];
2039 ssize_t ondisk_len = readlink(ondisk_path, ondisk_target,
2040 sizeof(ondisk_target));
2041 if (ondisk_len == -1) {
2042 err = got_error_from_errno2("readlink", ondisk_path);
2043 goto done;
2045 ondisk_target[ondisk_len] = '\0';
2046 err = install_symlink_conflict(NULL, worktree->base_commit_id,
2047 NULL, NULL, /* XXX pass common ancestor info? */
2048 ondisk_target, ondisk_path);
2049 if (err)
2050 goto done;
2051 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
2052 ie->path);
2053 goto done;
2056 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_CONFLICT ||
2057 status == GOT_STATUS_ADD) {
2058 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, ie->path);
2059 if (err)
2060 goto done;
2062 * Preserve the working file and change the deleted blob's
2063 * entry into a schedule-add entry.
2065 err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL,
2066 0);
2067 } else {
2068 err = (*progress_cb)(progress_arg, GOT_STATUS_DELETE, ie->path);
2069 if (err)
2070 goto done;
2071 if (status == GOT_STATUS_NO_CHANGE) {
2072 err = remove_ondisk_file(worktree->root_path, ie->path);
2073 if (err)
2074 goto done;
2076 got_fileindex_entry_remove(fileindex, ie);
2078 done:
2079 free(ondisk_path);
2080 return err;
2083 struct diff_cb_arg {
2084 struct got_fileindex *fileindex;
2085 struct got_worktree *worktree;
2086 struct got_repository *repo;
2087 got_worktree_checkout_cb progress_cb;
2088 void *progress_arg;
2089 got_cancel_cb cancel_cb;
2090 void *cancel_arg;
2093 static const struct got_error *
2094 diff_old_new(void *arg, struct got_fileindex_entry *ie,
2095 struct got_tree_entry *te, const char *parent_path)
2097 struct diff_cb_arg *a = arg;
2099 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2100 return got_error(GOT_ERR_CANCELLED);
2102 return update_blob(a->worktree, a->fileindex, ie, te,
2103 ie->path, a->repo, a->progress_cb, a->progress_arg);
2106 static const struct got_error *
2107 diff_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
2109 struct diff_cb_arg *a = arg;
2111 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2112 return got_error(GOT_ERR_CANCELLED);
2114 return delete_blob(a->worktree, a->fileindex, ie,
2115 a->repo, a->progress_cb, a->progress_arg);
2118 static const struct got_error *
2119 diff_new(void *arg, struct got_tree_entry *te, const char *parent_path)
2121 struct diff_cb_arg *a = arg;
2122 const struct got_error *err;
2123 char *path;
2125 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2126 return got_error(GOT_ERR_CANCELLED);
2128 if (got_object_tree_entry_is_submodule(te))
2129 return NULL;
2131 if (asprintf(&path, "%s%s%s", parent_path,
2132 parent_path[0] ? "/" : "", te->name)
2133 == -1)
2134 return got_error_from_errno("asprintf");
2136 if (S_ISDIR(te->mode))
2137 err = add_dir_on_disk(a->worktree, path);
2138 else
2139 err = update_blob(a->worktree, a->fileindex, NULL, te, path,
2140 a->repo, a->progress_cb, a->progress_arg);
2142 free(path);
2143 return err;
2146 static const struct got_error *
2147 get_ref_name(char **refname, struct got_worktree *worktree, const char *prefix)
2149 const struct got_error *err = NULL;
2150 char *uuidstr = NULL;
2151 uint32_t uuid_status;
2153 *refname = NULL;
2155 uuid_to_string(&worktree->uuid, &uuidstr, &uuid_status);
2156 if (uuid_status != uuid_s_ok)
2157 return got_error_uuid(uuid_status, "uuid_to_string");
2159 if (asprintf(refname, "%s-%s", prefix, uuidstr)
2160 == -1) {
2161 err = got_error_from_errno("asprintf");
2162 *refname = NULL;
2164 free(uuidstr);
2165 return err;
2168 const struct got_error *
2169 got_worktree_get_base_ref_name(char **refname, struct got_worktree *worktree)
2171 return get_ref_name(refname, worktree, GOT_WORKTREE_BASE_REF_PREFIX);
2174 static const struct got_error *
2175 get_rebase_tmp_ref_name(char **refname, struct got_worktree *worktree)
2177 return get_ref_name(refname, worktree,
2178 GOT_WORKTREE_REBASE_TMP_REF_PREFIX);
2181 static const struct got_error *
2182 get_newbase_symref_name(char **refname, struct got_worktree *worktree)
2184 return get_ref_name(refname, worktree, GOT_WORKTREE_NEWBASE_REF_PREFIX);
2187 static const struct got_error *
2188 get_rebase_branch_symref_name(char **refname, struct got_worktree *worktree)
2190 return get_ref_name(refname, worktree,
2191 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX);
2194 static const struct got_error *
2195 get_rebase_commit_ref_name(char **refname, struct got_worktree *worktree)
2197 return get_ref_name(refname, worktree,
2198 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX);
2201 static const struct got_error *
2202 get_histedit_tmp_ref_name(char **refname, struct got_worktree *worktree)
2204 return get_ref_name(refname, worktree,
2205 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX);
2208 static const struct got_error *
2209 get_histedit_branch_symref_name(char **refname, struct got_worktree *worktree)
2211 return get_ref_name(refname, worktree,
2212 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX);
2215 static const struct got_error *
2216 get_histedit_base_commit_ref_name(char **refname, struct got_worktree *worktree)
2218 return get_ref_name(refname, worktree,
2219 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX);
2222 static const struct got_error *
2223 get_histedit_commit_ref_name(char **refname, struct got_worktree *worktree)
2225 return get_ref_name(refname, worktree,
2226 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX);
2229 const struct got_error *
2230 got_worktree_get_histedit_script_path(char **path,
2231 struct got_worktree *worktree)
2233 if (asprintf(path, "%s/%s/%s", worktree->root_path,
2234 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_HISTEDIT_SCRIPT) == -1) {
2235 *path = NULL;
2236 return got_error_from_errno("asprintf");
2238 return NULL;
2242 * Prevent Git's garbage collector from deleting our base commit by
2243 * setting a reference to our base commit's ID.
2245 static const struct got_error *
2246 ref_base_commit(struct got_worktree *worktree, struct got_repository *repo)
2248 const struct got_error *err = NULL;
2249 struct got_reference *ref = NULL;
2250 char *refname;
2252 err = got_worktree_get_base_ref_name(&refname, worktree);
2253 if (err)
2254 return err;
2256 err = got_ref_alloc(&ref, refname, worktree->base_commit_id);
2257 if (err)
2258 goto done;
2260 err = got_ref_write(ref, repo);
2261 done:
2262 free(refname);
2263 if (ref)
2264 got_ref_close(ref);
2265 return err;
2268 static const struct got_error *
2269 get_fileindex_path(char **fileindex_path, struct got_worktree *worktree)
2271 const struct got_error *err = NULL;
2273 if (asprintf(fileindex_path, "%s/%s/%s", worktree->root_path,
2274 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_FILE_INDEX) == -1) {
2275 err = got_error_from_errno("asprintf");
2276 *fileindex_path = NULL;
2278 return err;
2282 static const struct got_error *
2283 open_fileindex(struct got_fileindex **fileindex, char **fileindex_path,
2284 struct got_worktree *worktree)
2286 const struct got_error *err = NULL;
2287 FILE *index = NULL;
2289 *fileindex_path = NULL;
2290 *fileindex = got_fileindex_alloc();
2291 if (*fileindex == NULL)
2292 return got_error_from_errno("got_fileindex_alloc");
2294 err = get_fileindex_path(fileindex_path, worktree);
2295 if (err)
2296 goto done;
2298 index = fopen(*fileindex_path, "rb");
2299 if (index == NULL) {
2300 if (errno != ENOENT)
2301 err = got_error_from_errno2("fopen", *fileindex_path);
2302 } else {
2303 err = got_fileindex_read(*fileindex, index);
2304 if (fclose(index) != 0 && err == NULL)
2305 err = got_error_from_errno("fclose");
2307 done:
2308 if (err) {
2309 free(*fileindex_path);
2310 *fileindex_path = NULL;
2311 got_fileindex_free(*fileindex);
2312 *fileindex = NULL;
2314 return err;
2317 struct bump_base_commit_id_arg {
2318 struct got_object_id *base_commit_id;
2319 const char *path;
2320 size_t path_len;
2321 const char *entry_name;
2322 got_worktree_checkout_cb progress_cb;
2323 void *progress_arg;
2326 /* Bump base commit ID of all files within an updated part of the work tree. */
2327 static const struct got_error *
2328 bump_base_commit_id(void *arg, struct got_fileindex_entry *ie)
2330 const struct got_error *err;
2331 struct bump_base_commit_id_arg *a = arg;
2333 if (a->entry_name) {
2334 if (strcmp(ie->path, a->path) != 0)
2335 return NULL;
2336 } else if (!got_path_is_child(ie->path, a->path, a->path_len))
2337 return NULL;
2339 if (memcmp(ie->commit_sha1, a->base_commit_id->sha1,
2340 SHA1_DIGEST_LENGTH) == 0)
2341 return NULL;
2343 if (a->progress_cb) {
2344 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_BUMP_BASE,
2345 ie->path);
2346 if (err)
2347 return err;
2349 memcpy(ie->commit_sha1, a->base_commit_id->sha1, SHA1_DIGEST_LENGTH);
2350 return NULL;
2353 static const struct got_error *
2354 sync_fileindex(struct got_fileindex *fileindex, const char *fileindex_path)
2356 const struct got_error *err = NULL;
2357 char *new_fileindex_path = NULL;
2358 FILE *new_index = NULL;
2359 struct timespec timeout;
2361 err = got_opentemp_named(&new_fileindex_path, &new_index,
2362 fileindex_path);
2363 if (err)
2364 goto done;
2366 err = got_fileindex_write(fileindex, new_index);
2367 if (err)
2368 goto done;
2370 if (rename(new_fileindex_path, fileindex_path) != 0) {
2371 err = got_error_from_errno3("rename", new_fileindex_path,
2372 fileindex_path);
2373 unlink(new_fileindex_path);
2377 * Sleep for a short amount of time to ensure that files modified after
2378 * this program exits have a different time stamp from the one which
2379 * was recorded in the file index.
2381 timeout.tv_sec = 0;
2382 timeout.tv_nsec = 1;
2383 nanosleep(&timeout, NULL);
2384 done:
2385 if (new_index)
2386 fclose(new_index);
2387 free(new_fileindex_path);
2388 return err;
2391 static const struct got_error *
2392 find_tree_entry_for_checkout(int *entry_type, char **tree_relpath,
2393 struct got_object_id **tree_id, const char *wt_relpath,
2394 struct got_worktree *worktree, struct got_repository *repo)
2396 const struct got_error *err = NULL;
2397 struct got_object_id *id = NULL;
2398 char *in_repo_path = NULL;
2399 int is_root_wt = got_path_is_root_dir(worktree->path_prefix);
2401 *entry_type = GOT_OBJ_TYPE_ANY;
2402 *tree_relpath = NULL;
2403 *tree_id = NULL;
2405 if (wt_relpath[0] == '\0') {
2406 /* Check out all files within the work tree. */
2407 *entry_type = GOT_OBJ_TYPE_TREE;
2408 *tree_relpath = strdup("");
2409 if (*tree_relpath == NULL) {
2410 err = got_error_from_errno("strdup");
2411 goto done;
2413 err = got_object_id_by_path(tree_id, repo,
2414 worktree->base_commit_id, worktree->path_prefix);
2415 if (err)
2416 goto done;
2417 return NULL;
2420 /* Check out a subset of files in the work tree. */
2422 if (asprintf(&in_repo_path, "%s%s%s", worktree->path_prefix,
2423 is_root_wt ? "" : "/", wt_relpath) == -1) {
2424 err = got_error_from_errno("asprintf");
2425 goto done;
2428 err = got_object_id_by_path(&id, repo, worktree->base_commit_id,
2429 in_repo_path);
2430 if (err)
2431 goto done;
2433 free(in_repo_path);
2434 in_repo_path = NULL;
2436 err = got_object_get_type(entry_type, repo, id);
2437 if (err)
2438 goto done;
2440 if (*entry_type == GOT_OBJ_TYPE_BLOB) {
2441 /* Check out a single file. */
2442 if (strchr(wt_relpath, '/') == NULL) {
2443 /* Check out a single file in work tree's root dir. */
2444 in_repo_path = strdup(worktree->path_prefix);
2445 if (in_repo_path == NULL) {
2446 err = got_error_from_errno("strdup");
2447 goto done;
2449 *tree_relpath = strdup("");
2450 if (*tree_relpath == NULL) {
2451 err = got_error_from_errno("strdup");
2452 goto done;
2454 } else {
2455 /* Check out a single file in a subdirectory. */
2456 err = got_path_dirname(tree_relpath, wt_relpath);
2457 if (err)
2458 return err;
2459 if (asprintf(&in_repo_path, "%s%s%s",
2460 worktree->path_prefix, is_root_wt ? "" : "/",
2461 *tree_relpath) == -1) {
2462 err = got_error_from_errno("asprintf");
2463 goto done;
2466 err = got_object_id_by_path(tree_id, repo,
2467 worktree->base_commit_id, in_repo_path);
2468 } else {
2469 /* Check out all files within a subdirectory. */
2470 *tree_id = got_object_id_dup(id);
2471 if (*tree_id == NULL) {
2472 err = got_error_from_errno("got_object_id_dup");
2473 goto done;
2475 *tree_relpath = strdup(wt_relpath);
2476 if (*tree_relpath == NULL) {
2477 err = got_error_from_errno("strdup");
2478 goto done;
2481 done:
2482 free(id);
2483 free(in_repo_path);
2484 if (err) {
2485 *entry_type = GOT_OBJ_TYPE_ANY;
2486 free(*tree_relpath);
2487 *tree_relpath = NULL;
2488 free(*tree_id);
2489 *tree_id = NULL;
2491 return err;
2494 static const struct got_error *
2495 checkout_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
2496 const char *relpath, struct got_object_id *tree_id, const char *entry_name,
2497 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
2498 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
2500 const struct got_error *err = NULL;
2501 struct got_commit_object *commit = NULL;
2502 struct got_tree_object *tree = NULL;
2503 struct got_fileindex_diff_tree_cb diff_cb;
2504 struct diff_cb_arg arg;
2506 err = ref_base_commit(worktree, repo);
2507 if (err) {
2508 if (!(err->code == GOT_ERR_ERRNO &&
2509 (errno == EACCES || errno == EROFS)))
2510 goto done;
2511 err = (*progress_cb)(progress_arg,
2512 GOT_STATUS_BASE_REF_ERR, worktree->root_path);
2513 if (err)
2514 return err;
2517 err = got_object_open_as_commit(&commit, repo,
2518 worktree->base_commit_id);
2519 if (err)
2520 goto done;
2522 err = got_object_open_as_tree(&tree, repo, tree_id);
2523 if (err)
2524 goto done;
2526 if (entry_name &&
2527 got_object_tree_find_entry(tree, entry_name) == NULL) {
2528 err = got_error(GOT_ERR_NO_TREE_ENTRY);
2529 goto done;
2532 diff_cb.diff_old_new = diff_old_new;
2533 diff_cb.diff_old = diff_old;
2534 diff_cb.diff_new = diff_new;
2535 arg.fileindex = fileindex;
2536 arg.worktree = worktree;
2537 arg.repo = repo;
2538 arg.progress_cb = progress_cb;
2539 arg.progress_arg = progress_arg;
2540 arg.cancel_cb = cancel_cb;
2541 arg.cancel_arg = cancel_arg;
2542 err = got_fileindex_diff_tree(fileindex, tree, relpath,
2543 entry_name, repo, &diff_cb, &arg);
2544 done:
2545 if (tree)
2546 got_object_tree_close(tree);
2547 if (commit)
2548 got_object_commit_close(commit);
2549 return err;
2552 const struct got_error *
2553 got_worktree_checkout_files(struct got_worktree *worktree,
2554 struct got_pathlist_head *paths, struct got_repository *repo,
2555 got_worktree_checkout_cb progress_cb, void *progress_arg,
2556 got_cancel_cb cancel_cb, void *cancel_arg)
2558 const struct got_error *err = NULL, *sync_err, *unlockerr;
2559 struct got_commit_object *commit = NULL;
2560 struct got_tree_object *tree = NULL;
2561 struct got_fileindex *fileindex = NULL;
2562 char *fileindex_path = NULL;
2563 struct got_pathlist_entry *pe;
2564 struct tree_path_data {
2565 SIMPLEQ_ENTRY(tree_path_data) entry;
2566 struct got_object_id *tree_id;
2567 int entry_type;
2568 char *relpath;
2569 char *entry_name;
2570 } *tpd = NULL;
2571 SIMPLEQ_HEAD(tree_paths, tree_path_data) tree_paths;
2573 SIMPLEQ_INIT(&tree_paths);
2575 err = lock_worktree(worktree, LOCK_EX);
2576 if (err)
2577 return err;
2579 /* Map all specified paths to in-repository trees. */
2580 TAILQ_FOREACH(pe, paths, entry) {
2581 tpd = malloc(sizeof(*tpd));
2582 if (tpd == NULL) {
2583 err = got_error_from_errno("malloc");
2584 goto done;
2587 err = find_tree_entry_for_checkout(&tpd->entry_type,
2588 &tpd->relpath, &tpd->tree_id, pe->path, worktree, repo);
2589 if (err) {
2590 free(tpd);
2591 goto done;
2594 if (tpd->entry_type == GOT_OBJ_TYPE_BLOB) {
2595 err = got_path_basename(&tpd->entry_name, pe->path);
2596 if (err) {
2597 free(tpd->relpath);
2598 free(tpd->tree_id);
2599 free(tpd);
2600 goto done;
2602 } else
2603 tpd->entry_name = NULL;
2605 SIMPLEQ_INSERT_TAIL(&tree_paths, tpd, entry);
2609 * Read the file index.
2610 * Checking out files is supposed to be an idempotent operation.
2611 * If the on-disk file index is incomplete we will try to complete it.
2613 err = open_fileindex(&fileindex, &fileindex_path, worktree);
2614 if (err)
2615 goto done;
2617 tpd = SIMPLEQ_FIRST(&tree_paths);
2618 TAILQ_FOREACH(pe, paths, entry) {
2619 struct bump_base_commit_id_arg bbc_arg;
2621 err = checkout_files(worktree, fileindex, tpd->relpath,
2622 tpd->tree_id, tpd->entry_name, repo,
2623 progress_cb, progress_arg, cancel_cb, cancel_arg);
2624 if (err)
2625 break;
2627 bbc_arg.base_commit_id = worktree->base_commit_id;
2628 bbc_arg.entry_name = tpd->entry_name;
2629 bbc_arg.path = pe->path;
2630 bbc_arg.path_len = pe->path_len;
2631 bbc_arg.progress_cb = progress_cb;
2632 bbc_arg.progress_arg = progress_arg;
2633 err = got_fileindex_for_each_entry_safe(fileindex,
2634 bump_base_commit_id, &bbc_arg);
2635 if (err)
2636 break;
2638 tpd = SIMPLEQ_NEXT(tpd, entry);
2640 sync_err = sync_fileindex(fileindex, fileindex_path);
2641 if (sync_err && err == NULL)
2642 err = sync_err;
2643 done:
2644 free(fileindex_path);
2645 if (tree)
2646 got_object_tree_close(tree);
2647 if (commit)
2648 got_object_commit_close(commit);
2649 if (fileindex)
2650 got_fileindex_free(fileindex);
2651 while (!SIMPLEQ_EMPTY(&tree_paths)) {
2652 tpd = SIMPLEQ_FIRST(&tree_paths);
2653 SIMPLEQ_REMOVE_HEAD(&tree_paths, entry);
2654 free(tpd->relpath);
2655 free(tpd->tree_id);
2656 free(tpd);
2658 unlockerr = lock_worktree(worktree, LOCK_SH);
2659 if (unlockerr && err == NULL)
2660 err = unlockerr;
2661 return err;
2664 struct merge_file_cb_arg {
2665 struct got_worktree *worktree;
2666 struct got_fileindex *fileindex;
2667 got_worktree_checkout_cb progress_cb;
2668 void *progress_arg;
2669 got_cancel_cb cancel_cb;
2670 void *cancel_arg;
2671 const char *label_orig;
2672 struct got_object_id *commit_id2;
2675 static const struct got_error *
2676 merge_file_cb(void *arg, struct got_blob_object *blob1,
2677 struct got_blob_object *blob2, struct got_object_id *id1,
2678 struct got_object_id *id2, const char *path1, const char *path2,
2679 mode_t mode1, mode_t mode2, struct got_repository *repo)
2681 static const struct got_error *err = NULL;
2682 struct merge_file_cb_arg *a = arg;
2683 struct got_fileindex_entry *ie;
2684 char *ondisk_path = NULL;
2685 struct stat sb;
2686 unsigned char status;
2687 int local_changes_subsumed;
2689 if (blob1 && blob2) {
2690 ie = got_fileindex_entry_get(a->fileindex, path2,
2691 strlen(path2));
2692 if (ie == NULL)
2693 return (*a->progress_cb)(a->progress_arg,
2694 GOT_STATUS_MISSING, path2);
2696 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2697 path2) == -1)
2698 return got_error_from_errno("asprintf");
2700 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2701 repo);
2702 if (err)
2703 goto done;
2705 if (status == GOT_STATUS_DELETE) {
2706 err = (*a->progress_cb)(a->progress_arg,
2707 GOT_STATUS_MERGE, path2);
2708 goto done;
2710 if (status != GOT_STATUS_NO_CHANGE &&
2711 status != GOT_STATUS_MODIFY &&
2712 status != GOT_STATUS_CONFLICT &&
2713 status != GOT_STATUS_ADD) {
2714 err = (*a->progress_cb)(a->progress_arg, status, path2);
2715 goto done;
2718 if (S_ISLNK(mode1) && S_ISLNK(mode2)) {
2719 err = merge_symlink(a->worktree, blob1,
2720 ondisk_path, path2, sb.st_mode, a->label_orig,
2721 blob2, a->commit_id2, repo, a->progress_cb,
2722 a->progress_arg);
2723 } else {
2724 err = merge_blob(&local_changes_subsumed, a->worktree,
2725 blob1, ondisk_path, path2, sb.st_mode,
2726 a->label_orig, blob2, a->commit_id2, repo,
2727 a->progress_cb, a->progress_arg);
2729 } else if (blob1) {
2730 ie = got_fileindex_entry_get(a->fileindex, path1,
2731 strlen(path1));
2732 if (ie == NULL)
2733 return (*a->progress_cb)(a->progress_arg,
2734 GOT_STATUS_MISSING, path1);
2736 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2737 path1) == -1)
2738 return got_error_from_errno("asprintf");
2740 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2741 repo);
2742 if (err)
2743 goto done;
2745 switch (status) {
2746 case GOT_STATUS_NO_CHANGE:
2747 err = (*a->progress_cb)(a->progress_arg,
2748 GOT_STATUS_DELETE, path1);
2749 if (err)
2750 goto done;
2751 err = remove_ondisk_file(a->worktree->root_path, path1);
2752 if (err)
2753 goto done;
2754 if (ie)
2755 got_fileindex_entry_mark_deleted_from_disk(ie);
2756 break;
2757 case GOT_STATUS_DELETE:
2758 case GOT_STATUS_MISSING:
2759 err = (*a->progress_cb)(a->progress_arg,
2760 GOT_STATUS_DELETE, path1);
2761 if (err)
2762 goto done;
2763 if (ie)
2764 got_fileindex_entry_mark_deleted_from_disk(ie);
2765 break;
2766 case GOT_STATUS_ADD:
2767 case GOT_STATUS_MODIFY:
2768 case GOT_STATUS_CONFLICT:
2769 err = (*a->progress_cb)(a->progress_arg,
2770 GOT_STATUS_CANNOT_DELETE, path1);
2771 if (err)
2772 goto done;
2773 break;
2774 case GOT_STATUS_OBSTRUCTED:
2775 err = (*a->progress_cb)(a->progress_arg, status, path1);
2776 if (err)
2777 goto done;
2778 break;
2779 default:
2780 break;
2782 } else if (blob2) {
2783 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2784 path2) == -1)
2785 return got_error_from_errno("asprintf");
2786 ie = got_fileindex_entry_get(a->fileindex, path2,
2787 strlen(path2));
2788 if (ie) {
2789 err = get_file_status(&status, &sb, ie, ondisk_path,
2790 -1, NULL, repo);
2791 if (err)
2792 goto done;
2793 if (status != GOT_STATUS_NO_CHANGE &&
2794 status != GOT_STATUS_MODIFY &&
2795 status != GOT_STATUS_CONFLICT &&
2796 status != GOT_STATUS_ADD) {
2797 err = (*a->progress_cb)(a->progress_arg,
2798 status, path2);
2799 goto done;
2801 if (S_ISLNK(mode2)) {
2802 err = merge_symlink(a->worktree, NULL,
2803 ondisk_path, path2, sb.st_mode,
2804 a->label_orig, blob2, a->commit_id2,
2805 repo, a->progress_cb, a->progress_arg);
2806 if (err)
2807 goto done;
2808 } else {
2809 err = merge_blob(&local_changes_subsumed,
2810 a->worktree, NULL, ondisk_path, path2,
2811 sb.st_mode, a->label_orig, blob2,
2812 a->commit_id2, repo, a->progress_cb,
2813 a->progress_arg);
2814 if (err)
2815 goto done;
2817 if (status == GOT_STATUS_DELETE) {
2818 err = got_fileindex_entry_update(ie,
2819 ondisk_path, blob2->id.sha1,
2820 a->worktree->base_commit_id->sha1, 0);
2821 if (err)
2822 goto done;
2824 } else {
2825 int is_bad_symlink = 0;
2826 sb.st_mode = GOT_DEFAULT_FILE_MODE;
2827 if (S_ISLNK(mode2)) {
2828 err = install_symlink(&is_bad_symlink,
2829 a->worktree, ondisk_path, path2, blob2, 0,
2830 0, 1, repo, a->progress_cb, a->progress_arg);
2831 } else {
2832 err = install_blob(a->worktree, ondisk_path, path2,
2833 mode2, sb.st_mode, blob2, 0, 0, 0, 1, repo,
2834 a->progress_cb, a->progress_arg);
2836 if (err)
2837 goto done;
2838 err = got_fileindex_entry_alloc(&ie, path2);
2839 if (err)
2840 goto done;
2841 err = got_fileindex_entry_update(ie, ondisk_path,
2842 NULL, NULL, 1);
2843 if (err) {
2844 got_fileindex_entry_free(ie);
2845 goto done;
2847 err = got_fileindex_entry_add(a->fileindex, ie);
2848 if (err) {
2849 got_fileindex_entry_free(ie);
2850 goto done;
2852 if (is_bad_symlink) {
2853 got_fileindex_entry_filetype_set(ie,
2854 GOT_FILEIDX_MODE_BAD_SYMLINK);
2858 done:
2859 free(ondisk_path);
2860 return err;
2863 struct check_merge_ok_arg {
2864 struct got_worktree *worktree;
2865 struct got_repository *repo;
2868 static const struct got_error *
2869 check_merge_ok(void *arg, struct got_fileindex_entry *ie)
2871 const struct got_error *err = NULL;
2872 struct check_merge_ok_arg *a = arg;
2873 unsigned char status;
2874 struct stat sb;
2875 char *ondisk_path;
2877 /* Reject merges into a work tree with mixed base commits. */
2878 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
2879 SHA1_DIGEST_LENGTH))
2880 return got_error(GOT_ERR_MIXED_COMMITS);
2882 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
2883 == -1)
2884 return got_error_from_errno("asprintf");
2886 /* Reject merges into a work tree with conflicted files. */
2887 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
2888 if (err)
2889 return err;
2890 if (status == GOT_STATUS_CONFLICT)
2891 return got_error(GOT_ERR_CONFLICTS);
2893 return NULL;
2896 static const struct got_error *
2897 merge_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
2898 const char *fileindex_path, struct got_object_id *commit_id1,
2899 struct got_object_id *commit_id2, struct got_repository *repo,
2900 got_worktree_checkout_cb progress_cb, void *progress_arg,
2901 got_cancel_cb cancel_cb, void *cancel_arg)
2903 const struct got_error *err = NULL, *sync_err;
2904 struct got_object_id *tree_id1 = NULL, *tree_id2 = NULL;
2905 struct got_tree_object *tree1 = NULL, *tree2 = NULL;
2906 struct merge_file_cb_arg arg;
2907 char *label_orig = NULL;
2909 if (commit_id1) {
2910 char *id_str;
2912 err = got_object_id_by_path(&tree_id1, repo, commit_id1,
2913 worktree->path_prefix);
2914 if (err)
2915 goto done;
2917 err = got_object_open_as_tree(&tree1, repo, tree_id1);
2918 if (err)
2919 goto done;
2921 err = got_object_id_str(&id_str, commit_id1);
2922 if (err)
2923 goto done;
2925 if (asprintf(&label_orig, "%s: commit %s",
2926 GOT_MERGE_LABEL_BASE, id_str) == -1) {
2927 err = got_error_from_errno("asprintf");
2928 free(id_str);
2929 goto done;
2931 free(id_str);
2934 err = got_object_id_by_path(&tree_id2, repo, commit_id2,
2935 worktree->path_prefix);
2936 if (err)
2937 goto done;
2939 err = got_object_open_as_tree(&tree2, repo, tree_id2);
2940 if (err)
2941 goto done;
2943 arg.worktree = worktree;
2944 arg.fileindex = fileindex;
2945 arg.progress_cb = progress_cb;
2946 arg.progress_arg = progress_arg;
2947 arg.cancel_cb = cancel_cb;
2948 arg.cancel_arg = cancel_arg;
2949 arg.label_orig = label_orig;
2950 arg.commit_id2 = commit_id2;
2951 err = got_diff_tree(tree1, tree2, "", "", repo, merge_file_cb, &arg, 1);
2952 sync_err = sync_fileindex(fileindex, fileindex_path);
2953 if (sync_err && err == NULL)
2954 err = sync_err;
2955 done:
2956 if (tree1)
2957 got_object_tree_close(tree1);
2958 if (tree2)
2959 got_object_tree_close(tree2);
2960 free(label_orig);
2961 return err;
2964 const struct got_error *
2965 got_worktree_merge_files(struct got_worktree *worktree,
2966 struct got_object_id *commit_id1, struct got_object_id *commit_id2,
2967 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
2968 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
2970 const struct got_error *err, *unlockerr;
2971 char *fileindex_path = NULL;
2972 struct got_fileindex *fileindex = NULL;
2973 struct check_merge_ok_arg mok_arg;
2975 err = lock_worktree(worktree, LOCK_EX);
2976 if (err)
2977 return err;
2979 err = open_fileindex(&fileindex, &fileindex_path, worktree);
2980 if (err)
2981 goto done;
2983 mok_arg.worktree = worktree;
2984 mok_arg.repo = repo;
2985 err = got_fileindex_for_each_entry_safe(fileindex, check_merge_ok,
2986 &mok_arg);
2987 if (err)
2988 goto done;
2990 err = merge_files(worktree, fileindex, fileindex_path, commit_id1,
2991 commit_id2, repo, progress_cb, progress_arg, cancel_cb, cancel_arg);
2992 done:
2993 if (fileindex)
2994 got_fileindex_free(fileindex);
2995 free(fileindex_path);
2996 unlockerr = lock_worktree(worktree, LOCK_SH);
2997 if (unlockerr && err == NULL)
2998 err = unlockerr;
2999 return err;
3002 struct diff_dir_cb_arg {
3003 struct got_fileindex *fileindex;
3004 struct got_worktree *worktree;
3005 const char *status_path;
3006 size_t status_path_len;
3007 struct got_repository *repo;
3008 got_worktree_status_cb status_cb;
3009 void *status_arg;
3010 got_cancel_cb cancel_cb;
3011 void *cancel_arg;
3012 /* A pathlist containing per-directory pathlists of ignore patterns. */
3013 struct got_pathlist_head ignores;
3014 int report_unchanged;
3015 int no_ignores;
3018 static const struct got_error *
3019 report_file_status(struct got_fileindex_entry *ie, const char *abspath,
3020 int dirfd, const char *de_name,
3021 got_worktree_status_cb status_cb, void *status_arg,
3022 struct got_repository *repo, int report_unchanged)
3024 const struct got_error *err = NULL;
3025 unsigned char status = GOT_STATUS_NO_CHANGE;
3026 unsigned char staged_status = get_staged_status(ie);
3027 struct stat sb;
3028 struct got_object_id blob_id, commit_id, staged_blob_id;
3029 struct got_object_id *blob_idp = NULL, *commit_idp = NULL;
3030 struct got_object_id *staged_blob_idp = NULL;
3032 err = get_file_status(&status, &sb, ie, abspath, dirfd, de_name, repo);
3033 if (err)
3034 return err;
3036 if (status == GOT_STATUS_NO_CHANGE &&
3037 staged_status == GOT_STATUS_NO_CHANGE && !report_unchanged)
3038 return NULL;
3040 if (got_fileindex_entry_has_blob(ie)) {
3041 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
3042 blob_idp = &blob_id;
3044 if (got_fileindex_entry_has_commit(ie)) {
3045 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
3046 commit_idp = &commit_id;
3048 if (staged_status == GOT_STATUS_ADD ||
3049 staged_status == GOT_STATUS_MODIFY) {
3050 memcpy(staged_blob_id.sha1, ie->staged_blob_sha1,
3051 SHA1_DIGEST_LENGTH);
3052 staged_blob_idp = &staged_blob_id;
3055 return (*status_cb)(status_arg, status, staged_status,
3056 ie->path, blob_idp, staged_blob_idp, commit_idp, dirfd, de_name);
3059 static const struct got_error *
3060 status_old_new(void *arg, struct got_fileindex_entry *ie,
3061 struct dirent *de, const char *parent_path, int dirfd)
3063 const struct got_error *err = NULL;
3064 struct diff_dir_cb_arg *a = arg;
3065 char *abspath;
3067 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3068 return got_error(GOT_ERR_CANCELLED);
3070 if (got_path_cmp(parent_path, a->status_path,
3071 strlen(parent_path), a->status_path_len) != 0 &&
3072 !got_path_is_child(parent_path, a->status_path, a->status_path_len))
3073 return NULL;
3075 if (parent_path[0]) {
3076 if (asprintf(&abspath, "%s/%s/%s", a->worktree->root_path,
3077 parent_path, de->d_name) == -1)
3078 return got_error_from_errno("asprintf");
3079 } else {
3080 if (asprintf(&abspath, "%s/%s", a->worktree->root_path,
3081 de->d_name) == -1)
3082 return got_error_from_errno("asprintf");
3085 err = report_file_status(ie, abspath, dirfd, de->d_name,
3086 a->status_cb, a->status_arg, a->repo, a->report_unchanged);
3087 free(abspath);
3088 return err;
3091 static const struct got_error *
3092 status_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
3094 struct diff_dir_cb_arg *a = arg;
3095 struct got_object_id blob_id, commit_id;
3096 unsigned char status;
3098 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3099 return got_error(GOT_ERR_CANCELLED);
3101 if (!got_path_is_child(ie->path, a->status_path, a->status_path_len))
3102 return NULL;
3104 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
3105 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
3106 if (got_fileindex_entry_has_file_on_disk(ie))
3107 status = GOT_STATUS_MISSING;
3108 else
3109 status = GOT_STATUS_DELETE;
3110 return (*a->status_cb)(a->status_arg, status, get_staged_status(ie),
3111 ie->path, &blob_id, NULL, &commit_id, -1, NULL);
3114 void
3115 free_ignorelist(struct got_pathlist_head *ignorelist)
3117 struct got_pathlist_entry *pe;
3119 TAILQ_FOREACH(pe, ignorelist, entry)
3120 free((char *)pe->path);
3121 got_pathlist_free(ignorelist);
3124 void
3125 free_ignores(struct got_pathlist_head *ignores)
3127 struct got_pathlist_entry *pe;
3129 TAILQ_FOREACH(pe, ignores, entry) {
3130 struct got_pathlist_head *ignorelist = pe->data;
3131 free_ignorelist(ignorelist);
3132 free((char *)pe->path);
3134 got_pathlist_free(ignores);
3137 static const struct got_error *
3138 read_ignores(struct got_pathlist_head *ignores, const char *path, FILE *f)
3140 const struct got_error *err = NULL;
3141 struct got_pathlist_entry *pe = NULL;
3142 struct got_pathlist_head *ignorelist;
3143 char *line = NULL, *pattern, *dirpath = NULL;
3144 size_t linesize = 0;
3145 ssize_t linelen;
3147 ignorelist = calloc(1, sizeof(*ignorelist));
3148 if (ignorelist == NULL)
3149 return got_error_from_errno("calloc");
3150 TAILQ_INIT(ignorelist);
3152 while ((linelen = getline(&line, &linesize, f)) != -1) {
3153 if (linelen > 0 && line[linelen - 1] == '\n')
3154 line[linelen - 1] = '\0';
3156 /* Git's ignores may contain comments. */
3157 if (line[0] == '#')
3158 continue;
3160 /* Git's negated patterns are not (yet?) supported. */
3161 if (line[0] == '!')
3162 continue;
3164 if (asprintf(&pattern, "%s%s%s", path, path[0] ? "/" : "",
3165 line) == -1) {
3166 err = got_error_from_errno("asprintf");
3167 goto done;
3169 err = got_pathlist_insert(NULL, ignorelist, pattern, NULL);
3170 if (err)
3171 goto done;
3173 if (ferror(f)) {
3174 err = got_error_from_errno("getline");
3175 goto done;
3178 dirpath = strdup(path);
3179 if (dirpath == NULL) {
3180 err = got_error_from_errno("strdup");
3181 goto done;
3183 err = got_pathlist_insert(&pe, ignores, dirpath, ignorelist);
3184 done:
3185 free(line);
3186 if (err || pe == NULL) {
3187 free(dirpath);
3188 free_ignorelist(ignorelist);
3190 return err;
3193 int
3194 match_ignores(struct got_pathlist_head *ignores, const char *path)
3196 struct got_pathlist_entry *pe;
3198 /* Handle patterns which match in all directories. */
3199 TAILQ_FOREACH(pe, ignores, entry) {
3200 struct got_pathlist_head *ignorelist = pe->data;
3201 struct got_pathlist_entry *pi;
3203 TAILQ_FOREACH(pi, ignorelist, entry) {
3204 const char *p, *pattern = pi->path;
3206 if (strncmp(pattern, "**/", 3) != 0)
3207 continue;
3208 pattern += 3;
3209 p = path;
3210 while (*p) {
3211 if (fnmatch(pattern, p,
3212 FNM_PATHNAME | FNM_LEADING_DIR)) {
3213 /* Retry in next directory. */
3214 while (*p && *p != '/')
3215 p++;
3216 while (*p == '/')
3217 p++;
3218 continue;
3220 return 1;
3226 * The ignores pathlist contains ignore lists from children before
3227 * parents, so we can find the most specific ignorelist by walking
3228 * ignores backwards.
3230 pe = TAILQ_LAST(ignores, got_pathlist_head);
3231 while (pe) {
3232 if (got_path_is_child(path, pe->path, pe->path_len)) {
3233 struct got_pathlist_head *ignorelist = pe->data;
3234 struct got_pathlist_entry *pi;
3235 TAILQ_FOREACH(pi, ignorelist, entry) {
3236 const char *pattern = pi->path;
3237 int flags = FNM_LEADING_DIR;
3238 if (strstr(pattern, "/**/") == NULL)
3239 flags |= FNM_PATHNAME;
3240 if (fnmatch(pattern, path, flags))
3241 continue;
3242 return 1;
3245 pe = TAILQ_PREV(pe, got_pathlist_head, entry);
3248 return 0;
3251 static const struct got_error *
3252 add_ignores(struct got_pathlist_head *ignores, const char *root_path,
3253 const char *path, int dirfd, const char *ignores_filename)
3255 const struct got_error *err = NULL;
3256 char *ignorespath;
3257 int fd = -1;
3258 FILE *ignoresfile = NULL;
3260 if (asprintf(&ignorespath, "%s/%s%s%s", root_path, path,
3261 path[0] ? "/" : "", ignores_filename) == -1)
3262 return got_error_from_errno("asprintf");
3264 if (dirfd != -1) {
3265 fd = openat(dirfd, ignores_filename, O_RDONLY | O_NOFOLLOW);
3266 if (fd == -1) {
3267 if (errno != ENOENT && errno != EACCES)
3268 err = got_error_from_errno2("openat",
3269 ignorespath);
3270 } else {
3271 ignoresfile = fdopen(fd, "r");
3272 if (ignoresfile == NULL)
3273 err = got_error_from_errno2("fdopen",
3274 ignorespath);
3275 else {
3276 fd = -1;
3277 err = read_ignores(ignores, path, ignoresfile);
3280 } else {
3281 ignoresfile = fopen(ignorespath, "r");
3282 if (ignoresfile == NULL) {
3283 if (errno != ENOENT && errno != EACCES)
3284 err = got_error_from_errno2("fopen",
3285 ignorespath);
3286 } else
3287 err = read_ignores(ignores, path, ignoresfile);
3290 if (ignoresfile && fclose(ignoresfile) == EOF && err == NULL)
3291 err = got_error_from_errno2("fclose", path);
3292 if (fd != -1 && close(fd) == -1 && err == NULL)
3293 err = got_error_from_errno2("close", path);
3294 free(ignorespath);
3295 return err;
3298 static const struct got_error *
3299 status_new(void *arg, struct dirent *de, const char *parent_path, int dirfd)
3301 const struct got_error *err = NULL;
3302 struct diff_dir_cb_arg *a = arg;
3303 char *path = NULL;
3305 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3306 return got_error(GOT_ERR_CANCELLED);
3308 if (parent_path[0]) {
3309 if (asprintf(&path, "%s/%s", parent_path, de->d_name) == -1)
3310 return got_error_from_errno("asprintf");
3311 } else {
3312 path = de->d_name;
3315 if (de->d_type != DT_DIR &&
3316 got_path_is_child(path, a->status_path, a->status_path_len)
3317 && !match_ignores(&a->ignores, path))
3318 err = (*a->status_cb)(a->status_arg, GOT_STATUS_UNVERSIONED,
3319 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3320 if (parent_path[0])
3321 free(path);
3322 return err;
3325 static const struct got_error *
3326 status_traverse(void *arg, const char *path, int dirfd)
3328 const struct got_error *err = NULL;
3329 struct diff_dir_cb_arg *a = arg;
3331 if (a->no_ignores)
3332 return NULL;
3334 err = add_ignores(&a->ignores, a->worktree->root_path,
3335 path, dirfd, ".cvsignore");
3336 if (err)
3337 return err;
3339 err = add_ignores(&a->ignores, a->worktree->root_path, path,
3340 dirfd, ".gitignore");
3342 return err;
3345 static const struct got_error *
3346 report_single_file_status(const char *path, const char *ondisk_path,
3347 struct got_fileindex *fileindex, got_worktree_status_cb status_cb,
3348 void *status_arg, struct got_repository *repo, int report_unchanged)
3350 struct got_fileindex_entry *ie;
3351 struct stat sb;
3353 ie = got_fileindex_entry_get(fileindex, path, strlen(path));
3354 if (ie)
3355 return report_file_status(ie, ondisk_path, -1, NULL,
3356 status_cb, status_arg, repo, report_unchanged);
3358 if (lstat(ondisk_path, &sb) == -1) {
3359 if (errno != ENOENT)
3360 return got_error_from_errno2("lstat", ondisk_path);
3361 return (*status_cb)(status_arg, GOT_STATUS_NONEXISTENT,
3362 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3363 return NULL;
3366 if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode))
3367 return (*status_cb)(status_arg, GOT_STATUS_UNVERSIONED,
3368 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3370 return NULL;
3373 static const struct got_error *
3374 add_ignores_from_parent_paths(struct got_pathlist_head *ignores,
3375 const char *root_path, const char *path)
3377 const struct got_error *err;
3378 char *parent_path, *next_parent_path = NULL;
3380 err = add_ignores(ignores, root_path, "", -1,
3381 ".cvsignore");
3382 if (err)
3383 return err;
3385 err = add_ignores(ignores, root_path, "", -1,
3386 ".gitignore");
3387 if (err)
3388 return err;
3390 err = got_path_dirname(&parent_path, path);
3391 if (err) {
3392 if (err->code == GOT_ERR_BAD_PATH)
3393 return NULL; /* cannot traverse parent */
3394 return err;
3396 for (;;) {
3397 err = add_ignores(ignores, root_path, parent_path, -1,
3398 ".cvsignore");
3399 if (err)
3400 break;
3401 err = add_ignores(ignores, root_path, parent_path, -1,
3402 ".gitignore");
3403 if (err)
3404 break;
3405 err = got_path_dirname(&next_parent_path, parent_path);
3406 if (err) {
3407 if (err->code == GOT_ERR_BAD_PATH)
3408 err = NULL; /* traversed everything */
3409 break;
3411 free(parent_path);
3412 parent_path = next_parent_path;
3413 next_parent_path = NULL;
3416 free(parent_path);
3417 free(next_parent_path);
3418 return err;
3421 static const struct got_error *
3422 worktree_status(struct got_worktree *worktree, const char *path,
3423 struct got_fileindex *fileindex, struct got_repository *repo,
3424 got_worktree_status_cb status_cb, void *status_arg,
3425 got_cancel_cb cancel_cb, void *cancel_arg, int no_ignores,
3426 int report_unchanged)
3428 const struct got_error *err = NULL;
3429 int fd = -1;
3430 struct got_fileindex_diff_dir_cb fdiff_cb;
3431 struct diff_dir_cb_arg arg;
3432 char *ondisk_path = NULL;
3434 TAILQ_INIT(&arg.ignores);
3436 if (asprintf(&ondisk_path, "%s%s%s",
3437 worktree->root_path, path[0] ? "/" : "", path) == -1)
3438 return got_error_from_errno("asprintf");
3440 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_DIRECTORY);
3441 if (fd == -1) {
3442 if (errno != ENOTDIR && errno != ENOENT && errno != EACCES &&
3443 errno != ELOOP)
3444 err = got_error_from_errno2("open", ondisk_path);
3445 else
3446 err = report_single_file_status(path, ondisk_path,
3447 fileindex, status_cb, status_arg, repo,
3448 report_unchanged);
3449 } else {
3450 fdiff_cb.diff_old_new = status_old_new;
3451 fdiff_cb.diff_old = status_old;
3452 fdiff_cb.diff_new = status_new;
3453 fdiff_cb.diff_traverse = status_traverse;
3454 arg.fileindex = fileindex;
3455 arg.worktree = worktree;
3456 arg.status_path = path;
3457 arg.status_path_len = strlen(path);
3458 arg.repo = repo;
3459 arg.status_cb = status_cb;
3460 arg.status_arg = status_arg;
3461 arg.cancel_cb = cancel_cb;
3462 arg.cancel_arg = cancel_arg;
3463 arg.report_unchanged = report_unchanged;
3464 arg.no_ignores = no_ignores;
3465 if (!no_ignores) {
3466 err = add_ignores_from_parent_paths(&arg.ignores,
3467 worktree->root_path, path);
3468 if (err)
3469 goto done;
3471 err = got_fileindex_diff_dir(fileindex, fd,
3472 worktree->root_path, path, repo, &fdiff_cb, &arg);
3474 done:
3475 free_ignores(&arg.ignores);
3476 if (fd != -1 && close(fd) != 0 && err == NULL)
3477 err = got_error_from_errno("close");
3478 free(ondisk_path);
3479 return err;
3482 const struct got_error *
3483 got_worktree_status(struct got_worktree *worktree,
3484 struct got_pathlist_head *paths, struct got_repository *repo,
3485 got_worktree_status_cb status_cb, void *status_arg,
3486 got_cancel_cb cancel_cb, void *cancel_arg)
3488 const struct got_error *err = NULL;
3489 char *fileindex_path = NULL;
3490 struct got_fileindex *fileindex = NULL;
3491 struct got_pathlist_entry *pe;
3493 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3494 if (err)
3495 return err;
3497 TAILQ_FOREACH(pe, paths, entry) {
3498 err = worktree_status(worktree, pe->path, fileindex, repo,
3499 status_cb, status_arg, cancel_cb, cancel_arg, 0, 0);
3500 if (err)
3501 break;
3503 free(fileindex_path);
3504 got_fileindex_free(fileindex);
3505 return err;
3508 const struct got_error *
3509 got_worktree_resolve_path(char **wt_path, struct got_worktree *worktree,
3510 const char *arg)
3512 const struct got_error *err = NULL;
3513 char *resolved = NULL, *cwd = NULL, *path = NULL;
3514 size_t len;
3515 struct stat sb;
3517 *wt_path = NULL;
3519 cwd = getcwd(NULL, 0);
3520 if (cwd == NULL)
3521 return got_error_from_errno("getcwd");
3523 if (lstat(arg, &sb) == -1) {
3524 if (errno != ENOENT) {
3525 err = got_error_from_errno2("lstat", arg);
3526 goto done;
3529 if (S_ISLNK(sb.st_mode)) {
3531 * We cannot use realpath(3) with symlinks since we want to
3532 * operate on the symlink itself.
3533 * But we can make the path absolute, assuming it is relative
3534 * to the current working directory, and then canonicalize it.
3536 char *abspath = NULL;
3537 char canonpath[PATH_MAX];
3538 if (!got_path_is_absolute(arg)) {
3539 if (asprintf(&abspath, "%s/%s", cwd, arg) == -1) {
3540 err = got_error_from_errno("asprintf");
3541 goto done;
3545 err = got_canonpath(abspath ? abspath : arg, canonpath,
3546 sizeof(canonpath));
3547 if (err)
3548 goto done;
3549 resolved = strdup(canonpath);
3550 if (resolved == NULL) {
3551 err = got_error_from_errno("strdup");
3552 goto done;
3554 } else {
3555 resolved = realpath(arg, NULL);
3556 if (resolved == NULL) {
3557 if (errno != ENOENT) {
3558 err = got_error_from_errno2("realpath", arg);
3559 goto done;
3561 if (asprintf(&resolved, "%s/%s", cwd, arg) == -1) {
3562 err = got_error_from_errno("asprintf");
3563 goto done;
3568 if (strncmp(got_worktree_get_root_path(worktree), resolved,
3569 strlen(got_worktree_get_root_path(worktree)))) {
3570 err = got_error_path(resolved, GOT_ERR_BAD_PATH);
3571 goto done;
3574 if (strlen(resolved) > strlen(got_worktree_get_root_path(worktree))) {
3575 err = got_path_skip_common_ancestor(&path,
3576 got_worktree_get_root_path(worktree), resolved);
3577 if (err)
3578 goto done;
3579 } else {
3580 path = strdup("");
3581 if (path == NULL) {
3582 err = got_error_from_errno("strdup");
3583 goto done;
3587 /* XXX status walk can't deal with trailing slash! */
3588 len = strlen(path);
3589 while (len > 0 && path[len - 1] == '/') {
3590 path[len - 1] = '\0';
3591 len--;
3593 done:
3594 free(resolved);
3595 free(cwd);
3596 if (err == NULL)
3597 *wt_path = path;
3598 else
3599 free(path);
3600 return err;
3603 struct schedule_addition_args {
3604 struct got_worktree *worktree;
3605 struct got_fileindex *fileindex;
3606 got_worktree_checkout_cb progress_cb;
3607 void *progress_arg;
3608 struct got_repository *repo;
3611 static const struct got_error *
3612 schedule_addition(void *arg, unsigned char status, unsigned char staged_status,
3613 const char *relpath, struct got_object_id *blob_id,
3614 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
3615 int dirfd, const char *de_name)
3617 struct schedule_addition_args *a = arg;
3618 const struct got_error *err = NULL;
3619 struct got_fileindex_entry *ie;
3620 struct stat sb;
3621 char *ondisk_path;
3623 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3624 relpath) == -1)
3625 return got_error_from_errno("asprintf");
3627 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3628 if (ie) {
3629 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd,
3630 de_name, a->repo);
3631 if (err)
3632 goto done;
3633 /* Re-adding an existing entry is a no-op. */
3634 if (status == GOT_STATUS_ADD)
3635 goto done;
3636 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
3637 if (err)
3638 goto done;
3641 if (status != GOT_STATUS_UNVERSIONED) {
3642 err = got_error_path(ondisk_path, GOT_ERR_FILE_STATUS);
3643 goto done;
3646 err = got_fileindex_entry_alloc(&ie, relpath);
3647 if (err)
3648 goto done;
3649 err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL, 1);
3650 if (err) {
3651 got_fileindex_entry_free(ie);
3652 goto done;
3654 err = got_fileindex_entry_add(a->fileindex, ie);
3655 if (err) {
3656 got_fileindex_entry_free(ie);
3657 goto done;
3659 done:
3660 free(ondisk_path);
3661 if (err)
3662 return err;
3663 if (status == GOT_STATUS_ADD)
3664 return NULL;
3665 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_ADD, relpath);
3668 const struct got_error *
3669 got_worktree_schedule_add(struct got_worktree *worktree,
3670 struct got_pathlist_head *paths,
3671 got_worktree_checkout_cb progress_cb, void *progress_arg,
3672 struct got_repository *repo, int no_ignores)
3674 struct got_fileindex *fileindex = NULL;
3675 char *fileindex_path = NULL;
3676 const struct got_error *err = NULL, *sync_err, *unlockerr;
3677 struct got_pathlist_entry *pe;
3678 struct schedule_addition_args saa;
3680 err = lock_worktree(worktree, LOCK_EX);
3681 if (err)
3682 return err;
3684 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3685 if (err)
3686 goto done;
3688 saa.worktree = worktree;
3689 saa.fileindex = fileindex;
3690 saa.progress_cb = progress_cb;
3691 saa.progress_arg = progress_arg;
3692 saa.repo = repo;
3694 TAILQ_FOREACH(pe, paths, entry) {
3695 err = worktree_status(worktree, pe->path, fileindex, repo,
3696 schedule_addition, &saa, NULL, NULL, no_ignores, 0);
3697 if (err)
3698 break;
3700 sync_err = sync_fileindex(fileindex, fileindex_path);
3701 if (sync_err && err == NULL)
3702 err = sync_err;
3703 done:
3704 free(fileindex_path);
3705 if (fileindex)
3706 got_fileindex_free(fileindex);
3707 unlockerr = lock_worktree(worktree, LOCK_SH);
3708 if (unlockerr && err == NULL)
3709 err = unlockerr;
3710 return err;
3713 struct schedule_deletion_args {
3714 struct got_worktree *worktree;
3715 struct got_fileindex *fileindex;
3716 got_worktree_delete_cb progress_cb;
3717 void *progress_arg;
3718 struct got_repository *repo;
3719 int delete_local_mods;
3720 int keep_on_disk;
3723 static const struct got_error *
3724 schedule_for_deletion(void *arg, unsigned char status,
3725 unsigned char staged_status, const char *relpath,
3726 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
3727 struct got_object_id *commit_id, int dirfd, const char *de_name)
3729 struct schedule_deletion_args *a = arg;
3730 const struct got_error *err = NULL;
3731 struct got_fileindex_entry *ie = NULL;
3732 struct stat sb;
3733 char *ondisk_path, *parent = NULL;
3735 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3736 if (ie == NULL)
3737 return got_error_path(relpath, GOT_ERR_BAD_PATH);
3739 staged_status = get_staged_status(ie);
3740 if (staged_status != GOT_STATUS_NO_CHANGE) {
3741 if (staged_status == GOT_STATUS_DELETE)
3742 return NULL;
3743 return got_error_path(relpath, GOT_ERR_FILE_STAGED);
3746 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3747 relpath) == -1)
3748 return got_error_from_errno("asprintf");
3750 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd, de_name,
3751 a->repo);
3752 if (err)
3753 goto done;
3755 if (status != GOT_STATUS_NO_CHANGE) {
3756 if (status == GOT_STATUS_DELETE)
3757 goto done;
3758 if (status == GOT_STATUS_MODIFY && !a->delete_local_mods) {
3759 err = got_error_path(relpath, GOT_ERR_FILE_MODIFIED);
3760 goto done;
3762 if (status != GOT_STATUS_MODIFY &&
3763 status != GOT_STATUS_MISSING) {
3764 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
3765 goto done;
3769 if (!a->keep_on_disk && status != GOT_STATUS_MISSING) {
3770 if (dirfd != -1) {
3771 if (unlinkat(dirfd, de_name, 0) != 0) {
3772 err = got_error_from_errno2("unlinkat",
3773 ondisk_path);
3774 goto done;
3776 } else if (unlink(ondisk_path) != 0) {
3777 err = got_error_from_errno2("unlink", ondisk_path);
3778 goto done;
3781 parent = dirname(ondisk_path);
3783 if (parent == NULL) {
3784 err = got_error_from_errno2("dirname", ondisk_path);
3785 goto done;
3787 while (parent && strcmp(parent, a->worktree->root_path) != 0) {
3788 if (rmdir(parent) == -1) {
3789 if (errno != ENOTEMPTY)
3790 err = got_error_from_errno2("rmdir",
3791 parent);
3792 break;
3794 parent = dirname(parent);
3795 if (parent == NULL) {
3796 err = got_error_from_errno2("dirname", parent);
3797 goto done;
3802 got_fileindex_entry_mark_deleted_from_disk(ie);
3803 done:
3804 free(ondisk_path);
3805 if (err)
3806 return err;
3807 if (status == GOT_STATUS_DELETE)
3808 return NULL;
3809 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE,
3810 staged_status, relpath);
3813 const struct got_error *
3814 got_worktree_schedule_delete(struct got_worktree *worktree,
3815 struct got_pathlist_head *paths, int delete_local_mods,
3816 got_worktree_delete_cb progress_cb, void *progress_arg,
3817 struct got_repository *repo, int keep_on_disk)
3819 struct got_fileindex *fileindex = NULL;
3820 char *fileindex_path = NULL;
3821 const struct got_error *err = NULL, *sync_err, *unlockerr;
3822 struct got_pathlist_entry *pe;
3823 struct schedule_deletion_args sda;
3825 err = lock_worktree(worktree, LOCK_EX);
3826 if (err)
3827 return err;
3829 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3830 if (err)
3831 goto done;
3833 sda.worktree = worktree;
3834 sda.fileindex = fileindex;
3835 sda.progress_cb = progress_cb;
3836 sda.progress_arg = progress_arg;
3837 sda.repo = repo;
3838 sda.delete_local_mods = delete_local_mods;
3839 sda.keep_on_disk = keep_on_disk;
3841 TAILQ_FOREACH(pe, paths, entry) {
3842 err = worktree_status(worktree, pe->path, fileindex, repo,
3843 schedule_for_deletion, &sda, NULL, NULL, 0, 1);
3844 if (err)
3845 break;
3847 sync_err = sync_fileindex(fileindex, fileindex_path);
3848 if (sync_err && err == NULL)
3849 err = sync_err;
3850 done:
3851 free(fileindex_path);
3852 if (fileindex)
3853 got_fileindex_free(fileindex);
3854 unlockerr = lock_worktree(worktree, LOCK_SH);
3855 if (unlockerr && err == NULL)
3856 err = unlockerr;
3857 return err;
3860 static const struct got_error *
3861 copy_one_line(FILE *infile, FILE *outfile, FILE *rejectfile)
3863 const struct got_error *err = NULL;
3864 char *line = NULL;
3865 size_t linesize = 0, n;
3866 ssize_t linelen;
3868 linelen = getline(&line, &linesize, infile);
3869 if (linelen == -1) {
3870 if (ferror(infile)) {
3871 err = got_error_from_errno("getline");
3872 goto done;
3874 return NULL;
3876 if (outfile) {
3877 n = fwrite(line, 1, linelen, outfile);
3878 if (n != linelen) {
3879 err = got_ferror(outfile, GOT_ERR_IO);
3880 goto done;
3883 if (rejectfile) {
3884 n = fwrite(line, 1, linelen, rejectfile);
3885 if (n != linelen)
3886 err = got_ferror(outfile, GOT_ERR_IO);
3888 done:
3889 free(line);
3890 return err;
3893 static const struct got_error *
3894 skip_one_line(FILE *f)
3896 char *line = NULL;
3897 size_t linesize = 0;
3898 ssize_t linelen;
3900 linelen = getline(&line, &linesize, f);
3901 if (linelen == -1) {
3902 if (ferror(f))
3903 return got_error_from_errno("getline");
3904 return NULL;
3906 free(line);
3907 return NULL;
3910 static const struct got_error *
3911 copy_change(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
3912 int start_old, int end_old, int start_new, int end_new,
3913 FILE *outfile, FILE *rejectfile)
3915 const struct got_error *err;
3917 /* Copy old file's lines leading up to patch. */
3918 while (!feof(f1) && *line_cur1 < start_old) {
3919 err = copy_one_line(f1, outfile, NULL);
3920 if (err)
3921 return err;
3922 (*line_cur1)++;
3924 /* Skip new file's lines leading up to patch. */
3925 while (!feof(f2) && *line_cur2 < start_new) {
3926 if (rejectfile)
3927 err = copy_one_line(f2, NULL, rejectfile);
3928 else
3929 err = skip_one_line(f2);
3930 if (err)
3931 return err;
3932 (*line_cur2)++;
3934 /* Copy patched lines. */
3935 while (!feof(f2) && *line_cur2 <= end_new) {
3936 err = copy_one_line(f2, outfile, NULL);
3937 if (err)
3938 return err;
3939 (*line_cur2)++;
3941 /* Skip over old file's replaced lines. */
3942 while (!feof(f1) && *line_cur1 <= end_old) {
3943 if (rejectfile)
3944 err = copy_one_line(f1, NULL, rejectfile);
3945 else
3946 err = skip_one_line(f1);
3947 if (err)
3948 return err;
3949 (*line_cur1)++;
3952 return NULL;
3955 static const struct got_error *
3956 copy_remaining_content(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
3957 FILE *outfile, FILE *rejectfile)
3959 const struct got_error *err;
3961 if (outfile) {
3962 /* Copy old file's lines until EOF. */
3963 while (!feof(f1)) {
3964 err = copy_one_line(f1, outfile, NULL);
3965 if (err)
3966 return err;
3967 (*line_cur1)++;
3970 if (rejectfile) {
3971 /* Copy new file's lines until EOF. */
3972 while (!feof(f2)) {
3973 err = copy_one_line(f2, NULL, rejectfile);
3974 if (err)
3975 return err;
3976 (*line_cur2)++;
3980 return NULL;
3983 static const struct got_error *
3984 apply_or_reject_change(int *choice, struct got_diff_change *change, int n,
3985 int nchanges, struct got_diff_state *ds, struct got_diff_args *args,
3986 int diff_flags, const char *relpath, FILE *f1, FILE *f2, int *line_cur1,
3987 int *line_cur2, FILE *outfile, FILE *rejectfile,
3988 got_worktree_patch_cb patch_cb, void *patch_arg)
3990 const struct got_error *err = NULL;
3991 int start_old = change->cv.a;
3992 int end_old = change->cv.b;
3993 int start_new = change->cv.c;
3994 int end_new = change->cv.d;
3995 long pos1, pos2;
3996 FILE *hunkfile;
3998 *choice = GOT_PATCH_CHOICE_NONE;
4000 hunkfile = got_opentemp();
4001 if (hunkfile == NULL)
4002 return got_error_from_errno("got_opentemp");
4004 pos1 = ftell(f1);
4005 pos2 = ftell(f2);
4007 /* XXX TODO needs error checking */
4008 got_diff_dump_change(hunkfile, change, ds, args, f1, f2, diff_flags);
4010 if (fseek(f1, pos1, SEEK_SET) == -1) {
4011 err = got_ferror(f1, GOT_ERR_IO);
4012 goto done;
4014 if (fseek(f2, pos2, SEEK_SET) == -1) {
4015 err = got_ferror(f1, GOT_ERR_IO);
4016 goto done;
4018 if (fseek(hunkfile, 0L, SEEK_SET) == -1) {
4019 err = got_ferror(hunkfile, GOT_ERR_IO);
4020 goto done;
4023 err = (*patch_cb)(choice, patch_arg, GOT_STATUS_MODIFY, relpath,
4024 hunkfile, n, nchanges);
4025 if (err)
4026 goto done;
4028 switch (*choice) {
4029 case GOT_PATCH_CHOICE_YES:
4030 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
4031 end_old, start_new, end_new, outfile, rejectfile);
4032 break;
4033 case GOT_PATCH_CHOICE_NO:
4034 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
4035 end_old, start_new, end_new, rejectfile, outfile);
4036 break;
4037 case GOT_PATCH_CHOICE_QUIT:
4038 break;
4039 default:
4040 err = got_error(GOT_ERR_PATCH_CHOICE);
4041 break;
4043 done:
4044 if (hunkfile && fclose(hunkfile) == EOF && err == NULL)
4045 err = got_error_from_errno("fclose");
4046 return err;
4049 struct revert_file_args {
4050 struct got_worktree *worktree;
4051 struct got_fileindex *fileindex;
4052 got_worktree_checkout_cb progress_cb;
4053 void *progress_arg;
4054 got_worktree_patch_cb patch_cb;
4055 void *patch_arg;
4056 struct got_repository *repo;
4059 static const struct got_error *
4060 create_patched_content(char **path_outfile, int reverse_patch,
4061 struct got_object_id *blob_id, const char *path2,
4062 int dirfd2, const char *de_name2,
4063 const char *relpath, struct got_repository *repo,
4064 got_worktree_patch_cb patch_cb, void *patch_arg)
4066 const struct got_error *err;
4067 struct got_blob_object *blob = NULL;
4068 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL;
4069 int fd2 = -1;
4070 char link_target[PATH_MAX];
4071 ssize_t link_len = 0;
4072 char *path1 = NULL, *id_str = NULL;
4073 struct stat sb1, sb2;
4074 struct got_diff_changes *changes = NULL;
4075 struct got_diff_state *ds = NULL;
4076 struct got_diff_args *args = NULL;
4077 struct got_diff_change *change;
4078 int diff_flags = 0, line_cur1 = 1, line_cur2 = 1, have_content = 0;
4079 int n = 0;
4081 *path_outfile = NULL;
4083 err = got_object_id_str(&id_str, blob_id);
4084 if (err)
4085 return err;
4087 if (dirfd2 != -1) {
4088 fd2 = openat(dirfd2, de_name2, O_RDONLY | O_NOFOLLOW);
4089 if (fd2 == -1) {
4090 if (errno != ELOOP) {
4091 err = got_error_from_errno2("openat", path2);
4092 goto done;
4094 link_len = readlinkat(dirfd2, de_name2,
4095 link_target, sizeof(link_target));
4096 if (link_len == -1)
4097 return got_error_from_errno2("readlinkat", path2);
4098 sb2.st_mode = S_IFLNK;
4099 sb2.st_size = link_len;
4101 } else {
4102 fd2 = open(path2, O_RDONLY | O_NOFOLLOW);
4103 if (fd2 == -1) {
4104 if (errno != ELOOP) {
4105 err = got_error_from_errno2("open", path2);
4106 goto done;
4108 link_len = readlink(path2, link_target,
4109 sizeof(link_target));
4110 if (link_len == -1)
4111 return got_error_from_errno2("readlink", path2);
4112 sb2.st_mode = S_IFLNK;
4113 sb2.st_size = link_len;
4116 if (fd2 != -1) {
4117 if (fstat(fd2, &sb2) == -1) {
4118 err = got_error_from_errno2("fstat", path2);
4119 goto done;
4122 f2 = fdopen(fd2, "r");
4123 if (f2 == NULL) {
4124 err = got_error_from_errno2("fdopen", path2);
4125 goto done;
4127 fd2 = -1;
4128 } else {
4129 size_t n;
4130 f2 = got_opentemp();
4131 if (f2 == NULL) {
4132 err = got_error_from_errno2("got_opentemp", path2);
4133 goto done;
4135 n = fwrite(link_target, 1, link_len, f2);
4136 if (n != link_len) {
4137 err = got_ferror(f2, GOT_ERR_IO);
4138 goto done;
4140 if (fflush(f2) == EOF) {
4141 err = got_error_from_errno("fflush");
4142 goto done;
4144 rewind(f2);
4147 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
4148 if (err)
4149 goto done;
4151 err = got_opentemp_named(&path1, &f1, "got-patched-blob");
4152 if (err)
4153 goto done;
4155 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
4156 if (err)
4157 goto done;
4159 if (stat(path1, &sb1) == -1) {
4160 err = got_error_from_errno2("stat", path1);
4161 goto done;
4164 err = got_diff_files(&changes, &ds, &args, &diff_flags,
4165 f1, sb1.st_size, id_str, f2, sb2.st_size, path2, 3, NULL);
4166 if (err)
4167 goto done;
4169 err = got_opentemp_named(path_outfile, &outfile, "got-patched-content");
4170 if (err)
4171 goto done;
4173 if (fseek(f1, 0L, SEEK_SET) == -1)
4174 return got_ferror(f1, GOT_ERR_IO);
4175 if (fseek(f2, 0L, SEEK_SET) == -1)
4176 return got_ferror(f2, GOT_ERR_IO);
4177 SIMPLEQ_FOREACH(change, &changes->entries, entry) {
4178 int choice;
4179 err = apply_or_reject_change(&choice, change, ++n,
4180 changes->nchanges, ds, args, diff_flags, relpath,
4181 f1, f2, &line_cur1, &line_cur2,
4182 reverse_patch ? NULL : outfile,
4183 reverse_patch ? outfile : NULL,
4184 patch_cb, patch_arg);
4185 if (err)
4186 goto done;
4187 if (choice == GOT_PATCH_CHOICE_YES)
4188 have_content = 1;
4189 else if (choice == GOT_PATCH_CHOICE_QUIT)
4190 break;
4192 if (have_content) {
4193 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
4194 reverse_patch ? NULL : outfile,
4195 reverse_patch ? outfile : NULL);
4196 if (err)
4197 goto done;
4199 if (!S_ISLNK(sb2.st_mode)) {
4200 if (chmod(*path_outfile, sb2.st_mode) == -1) {
4201 err = got_error_from_errno2("chmod", path2);
4202 goto done;
4206 done:
4207 free(id_str);
4208 if (blob)
4209 got_object_blob_close(blob);
4210 if (f1 && fclose(f1) == EOF && err == NULL)
4211 err = got_error_from_errno2("fclose", path1);
4212 if (f2 && fclose(f2) == EOF && err == NULL)
4213 err = got_error_from_errno2("fclose", path2);
4214 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
4215 err = got_error_from_errno2("close", path2);
4216 if (outfile && fclose(outfile) == EOF && err == NULL)
4217 err = got_error_from_errno2("fclose", *path_outfile);
4218 if (path1 && unlink(path1) == -1 && err == NULL)
4219 err = got_error_from_errno2("unlink", path1);
4220 if (err || !have_content) {
4221 if (*path_outfile && unlink(*path_outfile) == -1 && err == NULL)
4222 err = got_error_from_errno2("unlink", *path_outfile);
4223 free(*path_outfile);
4224 *path_outfile = NULL;
4226 free(args);
4227 if (ds) {
4228 got_diff_state_free(ds);
4229 free(ds);
4231 if (changes)
4232 got_diff_free_changes(changes);
4233 free(path1);
4234 return err;
4237 static const struct got_error *
4238 revert_file(void *arg, unsigned char status, unsigned char staged_status,
4239 const char *relpath, struct got_object_id *blob_id,
4240 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
4241 int dirfd, const char *de_name)
4243 struct revert_file_args *a = arg;
4244 const struct got_error *err = NULL;
4245 char *parent_path = NULL;
4246 struct got_fileindex_entry *ie;
4247 struct got_tree_object *tree = NULL;
4248 struct got_object_id *tree_id = NULL;
4249 const struct got_tree_entry *te = NULL;
4250 char *tree_path = NULL, *te_name;
4251 char *ondisk_path = NULL, *path_content = NULL;
4252 struct got_blob_object *blob = NULL;
4254 /* Reverting a staged deletion is a no-op. */
4255 if (status == GOT_STATUS_DELETE &&
4256 staged_status != GOT_STATUS_NO_CHANGE)
4257 return NULL;
4259 if (status == GOT_STATUS_UNVERSIONED)
4260 return (*a->progress_cb)(a->progress_arg,
4261 GOT_STATUS_UNVERSIONED, relpath);
4263 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
4264 if (ie == NULL)
4265 return got_error_path(relpath, GOT_ERR_BAD_PATH);
4267 /* Construct in-repository path of tree which contains this blob. */
4268 err = got_path_dirname(&parent_path, ie->path);
4269 if (err) {
4270 if (err->code != GOT_ERR_BAD_PATH)
4271 goto done;
4272 parent_path = strdup("/");
4273 if (parent_path == NULL) {
4274 err = got_error_from_errno("strdup");
4275 goto done;
4278 if (got_path_is_root_dir(a->worktree->path_prefix)) {
4279 tree_path = strdup(parent_path);
4280 if (tree_path == NULL) {
4281 err = got_error_from_errno("strdup");
4282 goto done;
4284 } else {
4285 if (got_path_is_root_dir(parent_path)) {
4286 tree_path = strdup(a->worktree->path_prefix);
4287 if (tree_path == NULL) {
4288 err = got_error_from_errno("strdup");
4289 goto done;
4291 } else {
4292 if (asprintf(&tree_path, "%s/%s",
4293 a->worktree->path_prefix, parent_path) == -1) {
4294 err = got_error_from_errno("asprintf");
4295 goto done;
4300 err = got_object_id_by_path(&tree_id, a->repo,
4301 a->worktree->base_commit_id, tree_path);
4302 if (err) {
4303 if (!(err->code == GOT_ERR_NO_TREE_ENTRY &&
4304 (status == GOT_STATUS_ADD ||
4305 staged_status == GOT_STATUS_ADD)))
4306 goto done;
4307 } else {
4308 err = got_object_open_as_tree(&tree, a->repo, tree_id);
4309 if (err)
4310 goto done;
4312 te_name = basename(ie->path);
4313 if (te_name == NULL) {
4314 err = got_error_from_errno2("basename", ie->path);
4315 goto done;
4318 te = got_object_tree_find_entry(tree, te_name);
4319 if (te == NULL && status != GOT_STATUS_ADD &&
4320 staged_status != GOT_STATUS_ADD) {
4321 err = got_error(GOT_ERR_NO_TREE_ENTRY);
4322 goto done;
4326 switch (status) {
4327 case GOT_STATUS_ADD:
4328 if (a->patch_cb) {
4329 int choice = GOT_PATCH_CHOICE_NONE;
4330 err = (*a->patch_cb)(&choice, a->patch_arg,
4331 status, ie->path, NULL, 1, 1);
4332 if (err)
4333 goto done;
4334 if (choice != GOT_PATCH_CHOICE_YES)
4335 break;
4337 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_REVERT,
4338 ie->path);
4339 if (err)
4340 goto done;
4341 got_fileindex_entry_remove(a->fileindex, ie);
4342 break;
4343 case GOT_STATUS_DELETE:
4344 if (a->patch_cb) {
4345 int choice = GOT_PATCH_CHOICE_NONE;
4346 err = (*a->patch_cb)(&choice, a->patch_arg,
4347 status, ie->path, NULL, 1, 1);
4348 if (err)
4349 goto done;
4350 if (choice != GOT_PATCH_CHOICE_YES)
4351 break;
4353 /* fall through */
4354 case GOT_STATUS_MODIFY:
4355 case GOT_STATUS_MODE_CHANGE:
4356 case GOT_STATUS_CONFLICT:
4357 case GOT_STATUS_MISSING: {
4358 struct got_object_id id;
4359 if (staged_status == GOT_STATUS_ADD ||
4360 staged_status == GOT_STATUS_MODIFY) {
4361 memcpy(id.sha1, ie->staged_blob_sha1,
4362 SHA1_DIGEST_LENGTH);
4363 } else
4364 memcpy(id.sha1, ie->blob_sha1,
4365 SHA1_DIGEST_LENGTH);
4366 err = got_object_open_as_blob(&blob, a->repo, &id, 8192);
4367 if (err)
4368 goto done;
4370 if (asprintf(&ondisk_path, "%s/%s",
4371 got_worktree_get_root_path(a->worktree), relpath) == -1) {
4372 err = got_error_from_errno("asprintf");
4373 goto done;
4376 if (a->patch_cb && (status == GOT_STATUS_MODIFY ||
4377 status == GOT_STATUS_CONFLICT)) {
4378 int is_bad_symlink = 0;
4379 err = create_patched_content(&path_content, 1, &id,
4380 ondisk_path, dirfd, de_name, ie->path, a->repo,
4381 a->patch_cb, a->patch_arg);
4382 if (err || path_content == NULL)
4383 break;
4384 if (te && S_ISLNK(te->mode)) {
4385 if (unlink(path_content) == -1) {
4386 err = got_error_from_errno2("unlink",
4387 path_content);
4388 break;
4390 err = install_symlink(&is_bad_symlink,
4391 a->worktree, ondisk_path, ie->path,
4392 blob, 0, 1, 0, a->repo,
4393 a->progress_cb, a->progress_arg);
4394 } else {
4395 if (rename(path_content, ondisk_path) == -1) {
4396 err = got_error_from_errno3("rename",
4397 path_content, ondisk_path);
4398 goto done;
4401 } else {
4402 int is_bad_symlink = 0;
4403 if (te && S_ISLNK(te->mode)) {
4404 err = install_symlink(&is_bad_symlink,
4405 a->worktree, ondisk_path, ie->path,
4406 blob, 0, 1, 0, a->repo,
4407 a->progress_cb, a->progress_arg);
4408 } else {
4409 err = install_blob(a->worktree, ondisk_path,
4410 ie->path,
4411 te ? te->mode : GOT_DEFAULT_FILE_MODE,
4412 got_fileindex_perms_to_st(ie), blob,
4413 0, 1, 0, 0, a->repo,
4414 a->progress_cb, a->progress_arg);
4416 if (err)
4417 goto done;
4418 if (status == GOT_STATUS_DELETE ||
4419 status == GOT_STATUS_MODE_CHANGE) {
4420 err = got_fileindex_entry_update(ie,
4421 ondisk_path, blob->id.sha1,
4422 a->worktree->base_commit_id->sha1, 1);
4423 if (err)
4424 goto done;
4426 if (is_bad_symlink) {
4427 got_fileindex_entry_filetype_set(ie,
4428 GOT_FILEIDX_MODE_BAD_SYMLINK);
4431 break;
4433 default:
4434 break;
4436 done:
4437 free(ondisk_path);
4438 free(path_content);
4439 free(parent_path);
4440 free(tree_path);
4441 if (blob)
4442 got_object_blob_close(blob);
4443 if (tree)
4444 got_object_tree_close(tree);
4445 free(tree_id);
4446 return err;
4449 const struct got_error *
4450 got_worktree_revert(struct got_worktree *worktree,
4451 struct got_pathlist_head *paths,
4452 got_worktree_checkout_cb progress_cb, void *progress_arg,
4453 got_worktree_patch_cb patch_cb, void *patch_arg,
4454 struct got_repository *repo)
4456 struct got_fileindex *fileindex = NULL;
4457 char *fileindex_path = NULL;
4458 const struct got_error *err = NULL, *unlockerr = NULL;
4459 const struct got_error *sync_err = NULL;
4460 struct got_pathlist_entry *pe;
4461 struct revert_file_args rfa;
4463 err = lock_worktree(worktree, LOCK_EX);
4464 if (err)
4465 return err;
4467 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4468 if (err)
4469 goto done;
4471 rfa.worktree = worktree;
4472 rfa.fileindex = fileindex;
4473 rfa.progress_cb = progress_cb;
4474 rfa.progress_arg = progress_arg;
4475 rfa.patch_cb = patch_cb;
4476 rfa.patch_arg = patch_arg;
4477 rfa.repo = repo;
4478 TAILQ_FOREACH(pe, paths, entry) {
4479 err = worktree_status(worktree, pe->path, fileindex, repo,
4480 revert_file, &rfa, NULL, NULL, 0, 0);
4481 if (err)
4482 break;
4484 sync_err = sync_fileindex(fileindex, fileindex_path);
4485 if (sync_err && err == NULL)
4486 err = sync_err;
4487 done:
4488 free(fileindex_path);
4489 if (fileindex)
4490 got_fileindex_free(fileindex);
4491 unlockerr = lock_worktree(worktree, LOCK_SH);
4492 if (unlockerr && err == NULL)
4493 err = unlockerr;
4494 return err;
4497 static void
4498 free_commitable(struct got_commitable *ct)
4500 free(ct->path);
4501 free(ct->in_repo_path);
4502 free(ct->ondisk_path);
4503 free(ct->blob_id);
4504 free(ct->base_blob_id);
4505 free(ct->staged_blob_id);
4506 free(ct->base_commit_id);
4507 free(ct);
4510 struct collect_commitables_arg {
4511 struct got_pathlist_head *commitable_paths;
4512 struct got_repository *repo;
4513 struct got_worktree *worktree;
4514 struct got_fileindex *fileindex;
4515 int have_staged_files;
4518 static const struct got_error *
4519 collect_commitables(void *arg, unsigned char status,
4520 unsigned char staged_status, const char *relpath,
4521 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
4522 struct got_object_id *commit_id, int dirfd, const char *de_name)
4524 struct collect_commitables_arg *a = arg;
4525 const struct got_error *err = NULL;
4526 struct got_commitable *ct = NULL;
4527 struct got_pathlist_entry *new = NULL;
4528 char *parent_path = NULL, *path = NULL;
4529 struct stat sb;
4531 if (a->have_staged_files) {
4532 if (staged_status != GOT_STATUS_MODIFY &&
4533 staged_status != GOT_STATUS_ADD &&
4534 staged_status != GOT_STATUS_DELETE)
4535 return NULL;
4536 } else {
4537 if (status == GOT_STATUS_CONFLICT)
4538 return got_error(GOT_ERR_COMMIT_CONFLICT);
4540 if (status != GOT_STATUS_MODIFY &&
4541 status != GOT_STATUS_MODE_CHANGE &&
4542 status != GOT_STATUS_ADD &&
4543 status != GOT_STATUS_DELETE)
4544 return NULL;
4547 if (asprintf(&path, "/%s", relpath) == -1) {
4548 err = got_error_from_errno("asprintf");
4549 goto done;
4551 if (strcmp(path, "/") == 0) {
4552 parent_path = strdup("");
4553 if (parent_path == NULL)
4554 return got_error_from_errno("strdup");
4555 } else {
4556 err = got_path_dirname(&parent_path, path);
4557 if (err)
4558 return err;
4561 ct = calloc(1, sizeof(*ct));
4562 if (ct == NULL) {
4563 err = got_error_from_errno("calloc");
4564 goto done;
4567 if (asprintf(&ct->ondisk_path, "%s/%s", a->worktree->root_path,
4568 relpath) == -1) {
4569 err = got_error_from_errno("asprintf");
4570 goto done;
4573 if (staged_status == GOT_STATUS_ADD ||
4574 staged_status == GOT_STATUS_MODIFY) {
4575 struct got_fileindex_entry *ie;
4576 ie = got_fileindex_entry_get(a->fileindex, path, strlen(path));
4577 switch (got_fileindex_entry_staged_filetype_get(ie)) {
4578 case GOT_FILEIDX_MODE_REGULAR_FILE:
4579 case GOT_FILEIDX_MODE_BAD_SYMLINK:
4580 ct->mode = S_IFREG;
4581 break;
4582 case GOT_FILEIDX_MODE_SYMLINK:
4583 ct->mode = S_IFLNK;
4584 break;
4585 default:
4586 fprintf(stderr, "got: ie mode is 0x%x\n", ie->mode);
4587 err = got_error_path(path, GOT_ERR_BAD_FILETYPE);
4588 goto done;
4590 ct->mode |= got_fileindex_entry_perms_get(ie);
4591 } else if (status != GOT_STATUS_DELETE &&
4592 staged_status != GOT_STATUS_DELETE) {
4593 if (dirfd != -1) {
4594 if (fstatat(dirfd, de_name, &sb,
4595 AT_SYMLINK_NOFOLLOW) == -1) {
4596 err = got_error_from_errno2("fstatat",
4597 ct->ondisk_path);
4598 goto done;
4600 } else if (lstat(ct->ondisk_path, &sb) == -1) {
4601 err = got_error_from_errno2("lstat", ct->ondisk_path);
4602 goto done;
4604 ct->mode = sb.st_mode;
4607 if (asprintf(&ct->in_repo_path, "%s%s%s", a->worktree->path_prefix,
4608 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
4609 relpath) == -1) {
4610 err = got_error_from_errno("asprintf");
4611 goto done;
4614 ct->status = status;
4615 ct->staged_status = staged_status;
4616 ct->blob_id = NULL; /* will be filled in when blob gets created */
4617 if (ct->status != GOT_STATUS_ADD &&
4618 ct->staged_status != GOT_STATUS_ADD) {
4619 ct->base_blob_id = got_object_id_dup(blob_id);
4620 if (ct->base_blob_id == NULL) {
4621 err = got_error_from_errno("got_object_id_dup");
4622 goto done;
4624 ct->base_commit_id = got_object_id_dup(commit_id);
4625 if (ct->base_commit_id == NULL) {
4626 err = got_error_from_errno("got_object_id_dup");
4627 goto done;
4630 if (ct->staged_status == GOT_STATUS_ADD ||
4631 ct->staged_status == GOT_STATUS_MODIFY) {
4632 ct->staged_blob_id = got_object_id_dup(staged_blob_id);
4633 if (ct->staged_blob_id == NULL) {
4634 err = got_error_from_errno("got_object_id_dup");
4635 goto done;
4638 ct->path = strdup(path);
4639 if (ct->path == NULL) {
4640 err = got_error_from_errno("strdup");
4641 goto done;
4643 err = got_pathlist_insert(&new, a->commitable_paths, ct->path, ct);
4644 done:
4645 if (ct && (err || new == NULL))
4646 free_commitable(ct);
4647 free(parent_path);
4648 free(path);
4649 return err;
4652 static const struct got_error *write_tree(struct got_object_id **, int *,
4653 struct got_tree_object *, const char *, struct got_pathlist_head *,
4654 got_worktree_status_cb status_cb, void *status_arg,
4655 struct got_repository *);
4657 static const struct got_error *
4658 write_subtree(struct got_object_id **new_subtree_id, int *nentries,
4659 struct got_tree_entry *te, const char *parent_path,
4660 struct got_pathlist_head *commitable_paths,
4661 got_worktree_status_cb status_cb, void *status_arg,
4662 struct got_repository *repo)
4664 const struct got_error *err = NULL;
4665 struct got_tree_object *subtree;
4666 char *subpath;
4668 if (asprintf(&subpath, "%s%s%s", parent_path,
4669 got_path_is_root_dir(parent_path) ? "" : "/", te->name) == -1)
4670 return got_error_from_errno("asprintf");
4672 err = got_object_open_as_tree(&subtree, repo, &te->id);
4673 if (err)
4674 return err;
4676 err = write_tree(new_subtree_id, nentries, subtree, subpath,
4677 commitable_paths, status_cb, status_arg, repo);
4678 got_object_tree_close(subtree);
4679 free(subpath);
4680 return err;
4683 static const struct got_error *
4684 match_ct_parent_path(int *match, struct got_commitable *ct, const char *path)
4686 const struct got_error *err = NULL;
4687 char *ct_parent_path = NULL;
4689 *match = 0;
4691 if (strchr(ct->in_repo_path, '/') == NULL) {
4692 *match = got_path_is_root_dir(path);
4693 return NULL;
4696 err = got_path_dirname(&ct_parent_path, ct->in_repo_path);
4697 if (err)
4698 return err;
4699 *match = (strcmp(path, ct_parent_path) == 0);
4700 free(ct_parent_path);
4701 return err;
4704 static mode_t
4705 get_ct_file_mode(struct got_commitable *ct)
4707 if (S_ISLNK(ct->mode))
4708 return S_IFLNK;
4710 return S_IFREG | (ct->mode & ((S_IRWXU | S_IRWXG | S_IRWXO)));
4713 static const struct got_error *
4714 alloc_modified_blob_tree_entry(struct got_tree_entry **new_te,
4715 struct got_tree_entry *te, struct got_commitable *ct)
4717 const struct got_error *err = NULL;
4719 *new_te = NULL;
4721 err = got_object_tree_entry_dup(new_te, te);
4722 if (err)
4723 goto done;
4725 (*new_te)->mode = get_ct_file_mode(ct);
4727 if (ct->staged_status == GOT_STATUS_MODIFY)
4728 memcpy(&(*new_te)->id, ct->staged_blob_id,
4729 sizeof((*new_te)->id));
4730 else
4731 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
4732 done:
4733 if (err && *new_te) {
4734 free(*new_te);
4735 *new_te = NULL;
4737 return err;
4740 static const struct got_error *
4741 alloc_added_blob_tree_entry(struct got_tree_entry **new_te,
4742 struct got_commitable *ct)
4744 const struct got_error *err = NULL;
4745 char *ct_name;
4747 *new_te = NULL;
4749 *new_te = calloc(1, sizeof(**new_te));
4750 if (*new_te == NULL)
4751 return got_error_from_errno("calloc");
4753 ct_name = basename(ct->path);
4754 if (ct_name == NULL) {
4755 err = got_error_from_errno2("basename", ct->path);
4756 goto done;
4758 if (strlcpy((*new_te)->name, ct_name, sizeof((*new_te)->name)) >=
4759 sizeof((*new_te)->name)) {
4760 err = got_error(GOT_ERR_NO_SPACE);
4761 goto done;
4764 (*new_te)->mode = get_ct_file_mode(ct);
4766 if (ct->staged_status == GOT_STATUS_ADD)
4767 memcpy(&(*new_te)->id, ct->staged_blob_id,
4768 sizeof((*new_te)->id));
4769 else
4770 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
4771 done:
4772 if (err && *new_te) {
4773 free(*new_te);
4774 *new_te = NULL;
4776 return err;
4779 static const struct got_error *
4780 insert_tree_entry(struct got_tree_entry *new_te,
4781 struct got_pathlist_head *paths)
4783 const struct got_error *err = NULL;
4784 struct got_pathlist_entry *new_pe;
4786 err = got_pathlist_insert(&new_pe, paths, new_te->name, new_te);
4787 if (err)
4788 return err;
4789 if (new_pe == NULL)
4790 return got_error(GOT_ERR_TREE_DUP_ENTRY);
4791 return NULL;
4794 static const struct got_error *
4795 report_ct_status(struct got_commitable *ct,
4796 got_worktree_status_cb status_cb, void *status_arg)
4798 const char *ct_path = ct->path;
4799 unsigned char status;
4801 while (ct_path[0] == '/')
4802 ct_path++;
4804 if (ct->staged_status != GOT_STATUS_NO_CHANGE)
4805 status = ct->staged_status;
4806 else
4807 status = ct->status;
4809 return (*status_cb)(status_arg, status, GOT_STATUS_NO_CHANGE,
4810 ct_path, ct->blob_id, NULL, NULL, -1, NULL);
4813 static const struct got_error *
4814 match_modified_subtree(int *modified, struct got_tree_entry *te,
4815 const char *base_tree_path, struct got_pathlist_head *commitable_paths)
4817 const struct got_error *err = NULL;
4818 struct got_pathlist_entry *pe;
4819 char *te_path;
4821 *modified = 0;
4823 if (asprintf(&te_path, "%s%s%s", base_tree_path,
4824 got_path_is_root_dir(base_tree_path) ? "" : "/",
4825 te->name) == -1)
4826 return got_error_from_errno("asprintf");
4828 TAILQ_FOREACH(pe, commitable_paths, entry) {
4829 struct got_commitable *ct = pe->data;
4830 *modified = got_path_is_child(ct->in_repo_path, te_path,
4831 strlen(te_path));
4832 if (*modified)
4833 break;
4836 free(te_path);
4837 return err;
4840 static const struct got_error *
4841 match_deleted_or_modified_ct(struct got_commitable **ctp,
4842 struct got_tree_entry *te, const char *base_tree_path,
4843 struct got_pathlist_head *commitable_paths)
4845 const struct got_error *err = NULL;
4846 struct got_pathlist_entry *pe;
4848 *ctp = NULL;
4850 TAILQ_FOREACH(pe, commitable_paths, entry) {
4851 struct got_commitable *ct = pe->data;
4852 char *ct_name = NULL;
4853 int path_matches;
4855 if (ct->staged_status == GOT_STATUS_NO_CHANGE) {
4856 if (ct->status != GOT_STATUS_MODIFY &&
4857 ct->status != GOT_STATUS_MODE_CHANGE &&
4858 ct->status != GOT_STATUS_DELETE)
4859 continue;
4860 } else {
4861 if (ct->staged_status != GOT_STATUS_MODIFY &&
4862 ct->staged_status != GOT_STATUS_DELETE)
4863 continue;
4866 if (got_object_id_cmp(ct->base_blob_id, &te->id) != 0)
4867 continue;
4869 err = match_ct_parent_path(&path_matches, ct, base_tree_path);
4870 if (err)
4871 return err;
4872 if (!path_matches)
4873 continue;
4875 ct_name = basename(pe->path);
4876 if (ct_name == NULL)
4877 return got_error_from_errno2("basename", pe->path);
4879 if (strcmp(te->name, ct_name) != 0)
4880 continue;
4882 *ctp = ct;
4883 break;
4886 return err;
4889 static const struct got_error *
4890 make_subtree_for_added_blob(struct got_tree_entry **new_tep,
4891 const char *child_path, const char *path_base_tree,
4892 struct got_pathlist_head *commitable_paths,
4893 got_worktree_status_cb status_cb, void *status_arg,
4894 struct got_repository *repo)
4896 const struct got_error *err = NULL;
4897 struct got_tree_entry *new_te;
4898 char *subtree_path;
4899 struct got_object_id *id = NULL;
4900 int nentries;
4902 *new_tep = NULL;
4904 if (asprintf(&subtree_path, "%s%s%s", path_base_tree,
4905 got_path_is_root_dir(path_base_tree) ? "" : "/",
4906 child_path) == -1)
4907 return got_error_from_errno("asprintf");
4909 new_te = calloc(1, sizeof(*new_te));
4910 if (new_te == NULL)
4911 return got_error_from_errno("calloc");
4912 new_te->mode = S_IFDIR;
4914 if (strlcpy(new_te->name, child_path, sizeof(new_te->name)) >=
4915 sizeof(new_te->name)) {
4916 err = got_error(GOT_ERR_NO_SPACE);
4917 goto done;
4919 err = write_tree(&id, &nentries, NULL, subtree_path,
4920 commitable_paths, status_cb, status_arg, repo);
4921 if (err) {
4922 free(new_te);
4923 goto done;
4925 memcpy(&new_te->id, id, sizeof(new_te->id));
4926 done:
4927 free(id);
4928 free(subtree_path);
4929 if (err == NULL)
4930 *new_tep = new_te;
4931 return err;
4934 static const struct got_error *
4935 write_tree(struct got_object_id **new_tree_id, int *nentries,
4936 struct got_tree_object *base_tree, const char *path_base_tree,
4937 struct got_pathlist_head *commitable_paths,
4938 got_worktree_status_cb status_cb, void *status_arg,
4939 struct got_repository *repo)
4941 const struct got_error *err = NULL;
4942 struct got_pathlist_head paths;
4943 struct got_tree_entry *te, *new_te = NULL;
4944 struct got_pathlist_entry *pe;
4946 TAILQ_INIT(&paths);
4947 *nentries = 0;
4949 /* Insert, and recurse into, newly added entries first. */
4950 TAILQ_FOREACH(pe, commitable_paths, entry) {
4951 struct got_commitable *ct = pe->data;
4952 char *child_path = NULL, *slash;
4954 if ((ct->status != GOT_STATUS_ADD &&
4955 ct->staged_status != GOT_STATUS_ADD) ||
4956 (ct->flags & GOT_COMMITABLE_ADDED))
4957 continue;
4959 if (!got_path_is_child(pe->path, path_base_tree,
4960 strlen(path_base_tree)))
4961 continue;
4963 err = got_path_skip_common_ancestor(&child_path, path_base_tree,
4964 pe->path);
4965 if (err)
4966 goto done;
4968 slash = strchr(child_path, '/');
4969 if (slash == NULL) {
4970 err = alloc_added_blob_tree_entry(&new_te, ct);
4971 if (err)
4972 goto done;
4973 err = report_ct_status(ct, status_cb, status_arg);
4974 if (err)
4975 goto done;
4976 ct->flags |= GOT_COMMITABLE_ADDED;
4977 err = insert_tree_entry(new_te, &paths);
4978 if (err)
4979 goto done;
4980 (*nentries)++;
4981 } else {
4982 *slash = '\0'; /* trim trailing path components */
4983 if (base_tree == NULL ||
4984 got_object_tree_find_entry(base_tree, child_path)
4985 == NULL) {
4986 err = make_subtree_for_added_blob(&new_te,
4987 child_path, path_base_tree,
4988 commitable_paths, status_cb, status_arg,
4989 repo);
4990 if (err)
4991 goto done;
4992 err = insert_tree_entry(new_te, &paths);
4993 if (err)
4994 goto done;
4995 (*nentries)++;
5000 if (base_tree) {
5001 int i, nbase_entries;
5002 /* Handle modified and deleted entries. */
5003 nbase_entries = got_object_tree_get_nentries(base_tree);
5004 for (i = 0; i < nbase_entries; i++) {
5005 struct got_commitable *ct = NULL;
5007 te = got_object_tree_get_entry(base_tree, i);
5008 if (got_object_tree_entry_is_submodule(te)) {
5009 /* Entry is a submodule; just copy it. */
5010 err = got_object_tree_entry_dup(&new_te, te);
5011 if (err)
5012 goto done;
5013 err = insert_tree_entry(new_te, &paths);
5014 if (err)
5015 goto done;
5016 (*nentries)++;
5017 continue;
5020 if (S_ISDIR(te->mode)) {
5021 int modified;
5022 err = got_object_tree_entry_dup(&new_te, te);
5023 if (err)
5024 goto done;
5025 err = match_modified_subtree(&modified, te,
5026 path_base_tree, commitable_paths);
5027 if (err)
5028 goto done;
5029 /* Avoid recursion into unmodified subtrees. */
5030 if (modified) {
5031 struct got_object_id *new_id;
5032 int nsubentries;
5033 err = write_subtree(&new_id,
5034 &nsubentries, te,
5035 path_base_tree, commitable_paths,
5036 status_cb, status_arg, repo);
5037 if (err)
5038 goto done;
5039 if (nsubentries == 0) {
5040 /* All entries were deleted. */
5041 free(new_id);
5042 continue;
5044 memcpy(&new_te->id, new_id,
5045 sizeof(new_te->id));
5046 free(new_id);
5048 err = insert_tree_entry(new_te, &paths);
5049 if (err)
5050 goto done;
5051 (*nentries)++;
5052 continue;
5055 err = match_deleted_or_modified_ct(&ct, te,
5056 path_base_tree, commitable_paths);
5057 if (err)
5058 goto done;
5059 if (ct) {
5060 /* NB: Deleted entries get dropped here. */
5061 if (ct->status == GOT_STATUS_MODIFY ||
5062 ct->status == GOT_STATUS_MODE_CHANGE ||
5063 ct->staged_status == GOT_STATUS_MODIFY) {
5064 err = alloc_modified_blob_tree_entry(
5065 &new_te, te, ct);
5066 if (err)
5067 goto done;
5068 err = insert_tree_entry(new_te, &paths);
5069 if (err)
5070 goto done;
5071 (*nentries)++;
5073 err = report_ct_status(ct, status_cb,
5074 status_arg);
5075 if (err)
5076 goto done;
5077 } else {
5078 /* Entry is unchanged; just copy it. */
5079 err = got_object_tree_entry_dup(&new_te, te);
5080 if (err)
5081 goto done;
5082 err = insert_tree_entry(new_te, &paths);
5083 if (err)
5084 goto done;
5085 (*nentries)++;
5090 /* Write new list of entries; deleted entries have been dropped. */
5091 err = got_object_tree_create(new_tree_id, &paths, *nentries, repo);
5092 done:
5093 got_pathlist_free(&paths);
5094 return err;
5097 static const struct got_error *
5098 reinstall_symlink_after_commit(int *is_bad_symlink, struct got_commitable *ct,
5099 struct got_object_id *new_base_commit_id, struct got_worktree *worktree,
5100 struct got_fileindex_entry *ie, struct got_repository *repo)
5102 const struct got_error *err = NULL;
5103 struct got_blob_object *blob = NULL;
5104 struct got_object_id *tree_id = NULL;
5105 char *tree_path = NULL;
5106 struct got_tree_object *tree = NULL;
5107 struct got_tree_entry *te;
5108 char *entry_name;
5109 unsigned char status;
5110 struct stat sb;
5112 err = get_file_status(&status, &sb, ie, ct->ondisk_path,
5113 -1, NULL, repo);
5114 if (err)
5115 return err;
5116 if (status != GOT_STATUS_NO_CHANGE)
5117 return NULL;
5119 if (ct->staged_status == GOT_STATUS_ADD ||
5120 ct->staged_status == GOT_STATUS_MODIFY) {
5121 err = got_object_open_as_blob(&blob, repo, ct->staged_blob_id,
5122 PATH_MAX);
5123 if (err)
5124 return err;
5125 } else {
5126 err = got_object_open_as_blob(&blob, repo, ct->blob_id,
5127 PATH_MAX);
5128 if (err)
5129 return err;
5132 err = got_path_dirname(&tree_path, ct->in_repo_path);
5133 if (err) {
5134 if (err->code != GOT_ERR_BAD_PATH)
5135 goto done;
5136 err = got_object_id_by_path(&tree_id, repo,
5137 new_base_commit_id, "");
5138 if (err)
5139 goto done;
5140 } else {
5141 err = got_object_id_by_path(&tree_id, repo,
5142 new_base_commit_id, tree_path);
5143 if (err)
5144 goto done;
5147 err = got_object_open_as_tree(&tree, repo, tree_id);
5148 if (err)
5149 goto done;
5151 entry_name = basename(ct->path);
5152 if (entry_name == NULL) {
5153 err = got_error_from_errno2("basename", ct->path);
5154 goto done;
5157 te = got_object_tree_find_entry(tree, entry_name);
5158 if (te == NULL) {
5159 err = got_error_path(ct->path, GOT_ERR_NO_TREE_ENTRY);
5160 goto done;
5163 err = install_symlink(is_bad_symlink, worktree, ct->ondisk_path,
5164 ct->path, blob, 0, 0, 0, repo, NULL, NULL);
5165 done:
5166 if (blob)
5167 got_object_blob_close(blob);
5168 if (tree)
5169 got_object_tree_close(tree);
5170 free(tree_id);
5171 free(tree_path);
5172 return err;
5176 * After comitting a symlink we have a chance to convert "bad" symlinks
5177 * (those which point outside the work tree or into .got) to regular files.
5178 * This way, the post-commit work tree state matches a fresh checkout of
5179 * the tree which was just committed. We also mark such newly committed
5180 * symlinks as "bad" in the work tree's fileindex.
5182 static const struct got_error *
5183 reinstall_symlinks_after_commit(struct got_pathlist_head *commitable_paths,
5184 struct got_object_id *new_base_commit_id, struct got_fileindex *fileindex,
5185 struct got_worktree *worktree, struct got_repository *repo)
5187 const struct got_error *err = NULL;
5188 struct got_pathlist_entry *pe;
5190 TAILQ_FOREACH(pe, commitable_paths, entry) {
5191 struct got_commitable *ct = pe->data;
5192 struct got_fileindex_entry *ie;
5193 int is_bad_symlink = 0;
5195 if (!S_ISLNK(get_ct_file_mode(ct)) ||
5196 ct->staged_status == GOT_STATUS_DELETE ||
5197 ct->status == GOT_STATUS_DELETE)
5198 continue;
5200 ie = got_fileindex_entry_get(fileindex, ct->path,
5201 strlen(ct->path));
5202 if (ie == NULL) {
5203 err = got_error_path(ct->path, GOT_ERR_BAD_PATH);
5204 break;
5206 err = reinstall_symlink_after_commit(&is_bad_symlink,
5207 ct, new_base_commit_id, worktree, ie, repo);
5208 if (err)
5209 break;
5210 if (ie && is_bad_symlink) {
5211 got_fileindex_entry_filetype_set(ie,
5212 GOT_FILEIDX_MODE_BAD_SYMLINK);
5216 return err;
5219 static const struct got_error *
5220 update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
5221 struct got_object_id *new_base_commit_id, struct got_fileindex *fileindex,
5222 int have_staged_files)
5224 const struct got_error *err = NULL;
5225 struct got_pathlist_entry *pe;
5227 TAILQ_FOREACH(pe, commitable_paths, entry) {
5228 struct got_fileindex_entry *ie;
5229 struct got_commitable *ct = pe->data;
5231 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
5232 if (ie) {
5233 if (ct->status == GOT_STATUS_DELETE ||
5234 ct->staged_status == GOT_STATUS_DELETE) {
5235 got_fileindex_entry_remove(fileindex, ie);
5236 } else if (ct->staged_status == GOT_STATUS_ADD ||
5237 ct->staged_status == GOT_STATUS_MODIFY) {
5238 got_fileindex_entry_stage_set(ie,
5239 GOT_FILEIDX_STAGE_NONE);
5240 err = got_fileindex_entry_update(ie,
5241 ct->ondisk_path, ct->staged_blob_id->sha1,
5242 new_base_commit_id->sha1,
5243 !have_staged_files);
5244 } else
5245 err = got_fileindex_entry_update(ie,
5246 ct->ondisk_path, ct->blob_id->sha1,
5247 new_base_commit_id->sha1,
5248 !have_staged_files);
5249 } else {
5250 err = got_fileindex_entry_alloc(&ie, pe->path);
5251 if (err)
5252 break;
5253 err = got_fileindex_entry_update(ie, ct->ondisk_path,
5254 ct->blob_id->sha1, new_base_commit_id->sha1, 1);
5255 if (err) {
5256 got_fileindex_entry_free(ie);
5257 break;
5259 err = got_fileindex_entry_add(fileindex, ie);
5260 if (err) {
5261 got_fileindex_entry_free(ie);
5262 break;
5266 return err;
5270 static const struct got_error *
5271 check_out_of_date(const char *in_repo_path, unsigned char status,
5272 unsigned char staged_status, struct got_object_id *base_blob_id,
5273 struct got_object_id *base_commit_id,
5274 struct got_object_id *head_commit_id, struct got_repository *repo,
5275 int ood_errcode)
5277 const struct got_error *err = NULL;
5278 struct got_object_id *id = NULL;
5280 if (status != GOT_STATUS_ADD && staged_status != GOT_STATUS_ADD) {
5281 /* Trivial case: base commit == head commit */
5282 if (got_object_id_cmp(base_commit_id, head_commit_id) == 0)
5283 return NULL;
5285 * Ensure file content which local changes were based
5286 * on matches file content in the branch head.
5288 err = got_object_id_by_path(&id, repo, head_commit_id,
5289 in_repo_path);
5290 if (err) {
5291 if (err->code == GOT_ERR_NO_TREE_ENTRY)
5292 err = got_error(ood_errcode);
5293 goto done;
5294 } else if (got_object_id_cmp(id, base_blob_id) != 0)
5295 err = got_error(ood_errcode);
5296 } else {
5297 /* Require that added files don't exist in the branch head. */
5298 err = got_object_id_by_path(&id, repo, head_commit_id,
5299 in_repo_path);
5300 if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
5301 goto done;
5302 err = id ? got_error(ood_errcode) : NULL;
5304 done:
5305 free(id);
5306 return err;
5309 const struct got_error *
5310 commit_worktree(struct got_object_id **new_commit_id,
5311 struct got_pathlist_head *commitable_paths,
5312 struct got_object_id *head_commit_id, struct got_worktree *worktree,
5313 const char *author, const char *committer,
5314 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
5315 got_worktree_status_cb status_cb, void *status_arg,
5316 struct got_repository *repo)
5318 const struct got_error *err = NULL, *unlockerr = NULL;
5319 struct got_pathlist_entry *pe;
5320 const char *head_ref_name = NULL;
5321 struct got_commit_object *head_commit = NULL;
5322 struct got_reference *head_ref2 = NULL;
5323 struct got_object_id *head_commit_id2 = NULL;
5324 struct got_tree_object *head_tree = NULL;
5325 struct got_object_id *new_tree_id = NULL;
5326 int nentries;
5327 struct got_object_id_queue parent_ids;
5328 struct got_object_qid *pid = NULL;
5329 char *logmsg = NULL;
5331 *new_commit_id = NULL;
5333 SIMPLEQ_INIT(&parent_ids);
5335 err = got_object_open_as_commit(&head_commit, repo, head_commit_id);
5336 if (err)
5337 goto done;
5339 err = got_object_open_as_tree(&head_tree, repo, head_commit->tree_id);
5340 if (err)
5341 goto done;
5343 if (commit_msg_cb != NULL) {
5344 err = commit_msg_cb(commitable_paths, &logmsg, commit_arg);
5345 if (err)
5346 goto done;
5349 if (logmsg == NULL || strlen(logmsg) == 0) {
5350 err = got_error(GOT_ERR_COMMIT_MSG_EMPTY);
5351 goto done;
5354 /* Create blobs from added and modified files and record their IDs. */
5355 TAILQ_FOREACH(pe, commitable_paths, entry) {
5356 struct got_commitable *ct = pe->data;
5357 char *ondisk_path;
5359 /* Blobs for staged files already exist. */
5360 if (ct->staged_status == GOT_STATUS_ADD ||
5361 ct->staged_status == GOT_STATUS_MODIFY)
5362 continue;
5364 if (ct->status != GOT_STATUS_ADD &&
5365 ct->status != GOT_STATUS_MODIFY &&
5366 ct->status != GOT_STATUS_MODE_CHANGE)
5367 continue;
5369 if (asprintf(&ondisk_path, "%s/%s",
5370 worktree->root_path, pe->path) == -1) {
5371 err = got_error_from_errno("asprintf");
5372 goto done;
5374 err = got_object_blob_create(&ct->blob_id, ondisk_path, repo);
5375 free(ondisk_path);
5376 if (err)
5377 goto done;
5380 /* Recursively write new tree objects. */
5381 err = write_tree(&new_tree_id, &nentries, head_tree, "/",
5382 commitable_paths, status_cb, status_arg, repo);
5383 if (err)
5384 goto done;
5386 err = got_object_qid_alloc(&pid, worktree->base_commit_id);
5387 if (err)
5388 goto done;
5389 SIMPLEQ_INSERT_TAIL(&parent_ids, pid, entry);
5390 err = got_object_commit_create(new_commit_id, new_tree_id, &parent_ids,
5391 1, author, time(NULL), committer, time(NULL), logmsg, repo);
5392 got_object_qid_free(pid);
5393 if (logmsg != NULL)
5394 free(logmsg);
5395 if (err)
5396 goto done;
5398 /* Check if a concurrent commit to our branch has occurred. */
5399 head_ref_name = got_worktree_get_head_ref_name(worktree);
5400 if (head_ref_name == NULL) {
5401 err = got_error_from_errno("got_worktree_get_head_ref_name");
5402 goto done;
5404 /* Lock the reference here to prevent concurrent modification. */
5405 err = got_ref_open(&head_ref2, repo, head_ref_name, 1);
5406 if (err)
5407 goto done;
5408 err = got_ref_resolve(&head_commit_id2, repo, head_ref2);
5409 if (err)
5410 goto done;
5411 if (got_object_id_cmp(head_commit_id, head_commit_id2) != 0) {
5412 err = got_error(GOT_ERR_COMMIT_HEAD_CHANGED);
5413 goto done;
5415 /* Update branch head in repository. */
5416 err = got_ref_change_ref(head_ref2, *new_commit_id);
5417 if (err)
5418 goto done;
5419 err = got_ref_write(head_ref2, repo);
5420 if (err)
5421 goto done;
5423 err = got_worktree_set_base_commit_id(worktree, repo, *new_commit_id);
5424 if (err)
5425 goto done;
5427 err = ref_base_commit(worktree, repo);
5428 if (err)
5429 goto done;
5430 done:
5431 if (head_tree)
5432 got_object_tree_close(head_tree);
5433 if (head_commit)
5434 got_object_commit_close(head_commit);
5435 free(head_commit_id2);
5436 if (head_ref2) {
5437 unlockerr = got_ref_unlock(head_ref2);
5438 if (unlockerr && err == NULL)
5439 err = unlockerr;
5440 got_ref_close(head_ref2);
5442 return err;
5445 static const struct got_error *
5446 check_path_is_commitable(const char *path,
5447 struct got_pathlist_head *commitable_paths)
5449 struct got_pathlist_entry *cpe = NULL;
5450 size_t path_len = strlen(path);
5452 TAILQ_FOREACH(cpe, commitable_paths, entry) {
5453 struct got_commitable *ct = cpe->data;
5454 const char *ct_path = ct->path;
5456 while (ct_path[0] == '/')
5457 ct_path++;
5459 if (strcmp(path, ct_path) == 0 ||
5460 got_path_is_child(ct_path, path, path_len))
5461 break;
5464 if (cpe == NULL)
5465 return got_error_path(path, GOT_ERR_BAD_PATH);
5467 return NULL;
5470 static const struct got_error *
5471 check_staged_file(void *arg, struct got_fileindex_entry *ie)
5473 int *have_staged_files = arg;
5475 if (got_fileindex_entry_stage_get(ie) != GOT_FILEIDX_STAGE_NONE) {
5476 *have_staged_files = 1;
5477 return got_error(GOT_ERR_CANCELLED);
5480 return NULL;
5483 static const struct got_error *
5484 check_non_staged_files(struct got_fileindex *fileindex,
5485 struct got_pathlist_head *paths)
5487 struct got_pathlist_entry *pe;
5488 struct got_fileindex_entry *ie;
5490 TAILQ_FOREACH(pe, paths, entry) {
5491 if (pe->path[0] == '\0')
5492 continue;
5493 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
5494 if (ie == NULL)
5495 return got_error_path(pe->path, GOT_ERR_BAD_PATH);
5496 if (got_fileindex_entry_stage_get(ie) == GOT_FILEIDX_STAGE_NONE)
5497 return got_error_path(pe->path,
5498 GOT_ERR_FILE_NOT_STAGED);
5501 return NULL;
5504 const struct got_error *
5505 got_worktree_commit(struct got_object_id **new_commit_id,
5506 struct got_worktree *worktree, struct got_pathlist_head *paths,
5507 const char *author, const char *committer,
5508 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
5509 got_worktree_status_cb status_cb, void *status_arg,
5510 struct got_repository *repo)
5512 const struct got_error *err = NULL, *unlockerr = NULL, *sync_err;
5513 struct got_fileindex *fileindex = NULL;
5514 char *fileindex_path = NULL;
5515 struct got_pathlist_head commitable_paths;
5516 struct collect_commitables_arg cc_arg;
5517 struct got_pathlist_entry *pe;
5518 struct got_reference *head_ref = NULL;
5519 struct got_object_id *head_commit_id = NULL;
5520 int have_staged_files = 0;
5522 *new_commit_id = NULL;
5524 TAILQ_INIT(&commitable_paths);
5526 err = lock_worktree(worktree, LOCK_EX);
5527 if (err)
5528 goto done;
5530 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
5531 if (err)
5532 goto done;
5534 err = got_ref_resolve(&head_commit_id, repo, head_ref);
5535 if (err)
5536 goto done;
5538 err = open_fileindex(&fileindex, &fileindex_path, worktree);
5539 if (err)
5540 goto done;
5542 err = got_fileindex_for_each_entry_safe(fileindex, check_staged_file,
5543 &have_staged_files);
5544 if (err && err->code != GOT_ERR_CANCELLED)
5545 goto done;
5546 if (have_staged_files) {
5547 err = check_non_staged_files(fileindex, paths);
5548 if (err)
5549 goto done;
5552 cc_arg.commitable_paths = &commitable_paths;
5553 cc_arg.worktree = worktree;
5554 cc_arg.fileindex = fileindex;
5555 cc_arg.repo = repo;
5556 cc_arg.have_staged_files = have_staged_files;
5557 TAILQ_FOREACH(pe, paths, entry) {
5558 err = worktree_status(worktree, pe->path, fileindex, repo,
5559 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
5560 if (err)
5561 goto done;
5564 if (TAILQ_EMPTY(&commitable_paths)) {
5565 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
5566 goto done;
5569 TAILQ_FOREACH(pe, paths, entry) {
5570 err = check_path_is_commitable(pe->path, &commitable_paths);
5571 if (err)
5572 goto done;
5575 TAILQ_FOREACH(pe, &commitable_paths, entry) {
5576 struct got_commitable *ct = pe->data;
5577 const char *ct_path = ct->in_repo_path;
5579 while (ct_path[0] == '/')
5580 ct_path++;
5581 err = check_out_of_date(ct_path, ct->status,
5582 ct->staged_status, ct->base_blob_id, ct->base_commit_id,
5583 head_commit_id, repo, GOT_ERR_COMMIT_OUT_OF_DATE);
5584 if (err)
5585 goto done;
5589 err = commit_worktree(new_commit_id, &commitable_paths,
5590 head_commit_id, worktree, author, committer,
5591 commit_msg_cb, commit_arg, status_cb, status_arg, repo);
5592 if (err)
5593 goto done;
5595 err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
5596 fileindex, have_staged_files);
5597 if (err == NULL) {
5598 err = reinstall_symlinks_after_commit(&commitable_paths,
5599 *new_commit_id, fileindex, worktree, repo);
5601 sync_err = sync_fileindex(fileindex, fileindex_path);
5602 if (sync_err && err == NULL)
5603 err = sync_err;
5604 done:
5605 if (fileindex)
5606 got_fileindex_free(fileindex);
5607 free(fileindex_path);
5608 unlockerr = lock_worktree(worktree, LOCK_SH);
5609 if (unlockerr && err == NULL)
5610 err = unlockerr;
5611 TAILQ_FOREACH(pe, &commitable_paths, entry) {
5612 struct got_commitable *ct = pe->data;
5613 free_commitable(ct);
5615 got_pathlist_free(&commitable_paths);
5616 return err;
5619 const char *
5620 got_commitable_get_path(struct got_commitable *ct)
5622 return ct->path;
5625 unsigned int
5626 got_commitable_get_status(struct got_commitable *ct)
5628 return ct->status;
5631 struct check_rebase_ok_arg {
5632 struct got_worktree *worktree;
5633 struct got_repository *repo;
5636 static const struct got_error *
5637 check_rebase_ok(void *arg, struct got_fileindex_entry *ie)
5639 const struct got_error *err = NULL;
5640 struct check_rebase_ok_arg *a = arg;
5641 unsigned char status;
5642 struct stat sb;
5643 char *ondisk_path;
5645 /* Reject rebase of a work tree with mixed base commits. */
5646 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
5647 SHA1_DIGEST_LENGTH))
5648 return got_error(GOT_ERR_MIXED_COMMITS);
5650 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
5651 == -1)
5652 return got_error_from_errno("asprintf");
5654 /* Reject rebase of a work tree with modified or staged files. */
5655 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
5656 free(ondisk_path);
5657 if (err)
5658 return err;
5660 if (status != GOT_STATUS_NO_CHANGE)
5661 return got_error(GOT_ERR_MODIFIED);
5662 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
5663 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
5665 return NULL;
5668 const struct got_error *
5669 got_worktree_rebase_prepare(struct got_reference **new_base_branch_ref,
5670 struct got_reference **tmp_branch, struct got_fileindex **fileindex,
5671 struct got_worktree *worktree, struct got_reference *branch,
5672 struct got_repository *repo)
5674 const struct got_error *err = NULL;
5675 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
5676 char *branch_ref_name = NULL;
5677 char *fileindex_path = NULL;
5678 struct check_rebase_ok_arg ok_arg;
5679 struct got_reference *wt_branch = NULL, *branch_ref = NULL;
5680 struct got_object_id *wt_branch_tip = NULL;
5682 *new_base_branch_ref = NULL;
5683 *tmp_branch = NULL;
5684 *fileindex = NULL;
5686 err = lock_worktree(worktree, LOCK_EX);
5687 if (err)
5688 return err;
5690 err = open_fileindex(fileindex, &fileindex_path, worktree);
5691 if (err)
5692 goto done;
5694 ok_arg.worktree = worktree;
5695 ok_arg.repo = repo;
5696 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
5697 &ok_arg);
5698 if (err)
5699 goto done;
5701 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5702 if (err)
5703 goto done;
5705 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
5706 if (err)
5707 goto done;
5709 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
5710 if (err)
5711 goto done;
5713 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
5714 0);
5715 if (err)
5716 goto done;
5718 err = got_ref_resolve(&wt_branch_tip, repo, wt_branch);
5719 if (err)
5720 goto done;
5721 if (got_object_id_cmp(worktree->base_commit_id, wt_branch_tip) != 0) {
5722 err = got_error(GOT_ERR_REBASE_OUT_OF_DATE);
5723 goto done;
5726 err = got_ref_alloc_symref(new_base_branch_ref,
5727 new_base_branch_ref_name, wt_branch);
5728 if (err)
5729 goto done;
5730 err = got_ref_write(*new_base_branch_ref, repo);
5731 if (err)
5732 goto done;
5734 /* TODO Lock original branch's ref while rebasing? */
5736 err = got_ref_alloc_symref(&branch_ref, branch_ref_name, branch);
5737 if (err)
5738 goto done;
5740 err = got_ref_write(branch_ref, repo);
5741 if (err)
5742 goto done;
5744 err = got_ref_alloc(tmp_branch, tmp_branch_name,
5745 worktree->base_commit_id);
5746 if (err)
5747 goto done;
5748 err = got_ref_write(*tmp_branch, repo);
5749 if (err)
5750 goto done;
5752 err = got_worktree_set_head_ref(worktree, *tmp_branch);
5753 if (err)
5754 goto done;
5755 done:
5756 free(fileindex_path);
5757 free(tmp_branch_name);
5758 free(new_base_branch_ref_name);
5759 free(branch_ref_name);
5760 if (branch_ref)
5761 got_ref_close(branch_ref);
5762 if (wt_branch)
5763 got_ref_close(wt_branch);
5764 free(wt_branch_tip);
5765 if (err) {
5766 if (*new_base_branch_ref) {
5767 got_ref_close(*new_base_branch_ref);
5768 *new_base_branch_ref = NULL;
5770 if (*tmp_branch) {
5771 got_ref_close(*tmp_branch);
5772 *tmp_branch = NULL;
5774 if (*fileindex) {
5775 got_fileindex_free(*fileindex);
5776 *fileindex = NULL;
5778 lock_worktree(worktree, LOCK_SH);
5780 return err;
5783 const struct got_error *
5784 got_worktree_rebase_continue(struct got_object_id **commit_id,
5785 struct got_reference **new_base_branch, struct got_reference **tmp_branch,
5786 struct got_reference **branch, struct got_fileindex **fileindex,
5787 struct got_worktree *worktree, struct got_repository *repo)
5789 const struct got_error *err;
5790 char *commit_ref_name = NULL, *new_base_branch_ref_name = NULL;
5791 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
5792 struct got_reference *commit_ref = NULL, *branch_ref = NULL;
5793 char *fileindex_path = NULL;
5794 int have_staged_files = 0;
5796 *commit_id = NULL;
5797 *new_base_branch = NULL;
5798 *tmp_branch = NULL;
5799 *branch = NULL;
5800 *fileindex = NULL;
5802 err = lock_worktree(worktree, LOCK_EX);
5803 if (err)
5804 return err;
5806 err = open_fileindex(fileindex, &fileindex_path, worktree);
5807 if (err)
5808 goto done;
5810 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
5811 &have_staged_files);
5812 if (err && err->code != GOT_ERR_CANCELLED)
5813 goto done;
5814 if (have_staged_files) {
5815 err = got_error(GOT_ERR_STAGED_PATHS);
5816 goto done;
5819 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5820 if (err)
5821 goto done;
5823 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
5824 if (err)
5825 goto done;
5827 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
5828 if (err)
5829 goto done;
5831 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
5832 if (err)
5833 goto done;
5835 err = got_ref_open(&branch_ref, repo, branch_ref_name, 0);
5836 if (err)
5837 goto done;
5839 err = got_ref_open(branch, repo,
5840 got_ref_get_symref_target(branch_ref), 0);
5841 if (err)
5842 goto done;
5844 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5845 if (err)
5846 goto done;
5848 err = got_ref_resolve(commit_id, repo, commit_ref);
5849 if (err)
5850 goto done;
5852 err = got_ref_open(new_base_branch, repo,
5853 new_base_branch_ref_name, 0);
5854 if (err)
5855 goto done;
5857 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
5858 if (err)
5859 goto done;
5860 done:
5861 free(commit_ref_name);
5862 free(branch_ref_name);
5863 free(fileindex_path);
5864 if (commit_ref)
5865 got_ref_close(commit_ref);
5866 if (branch_ref)
5867 got_ref_close(branch_ref);
5868 if (err) {
5869 free(*commit_id);
5870 *commit_id = NULL;
5871 if (*tmp_branch) {
5872 got_ref_close(*tmp_branch);
5873 *tmp_branch = NULL;
5875 if (*new_base_branch) {
5876 got_ref_close(*new_base_branch);
5877 *new_base_branch = NULL;
5879 if (*branch) {
5880 got_ref_close(*branch);
5881 *branch = NULL;
5883 if (*fileindex) {
5884 got_fileindex_free(*fileindex);
5885 *fileindex = NULL;
5887 lock_worktree(worktree, LOCK_SH);
5889 return err;
5892 const struct got_error *
5893 got_worktree_rebase_in_progress(int *in_progress, struct got_worktree *worktree)
5895 const struct got_error *err;
5896 char *tmp_branch_name = NULL;
5898 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5899 if (err)
5900 return err;
5902 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
5903 free(tmp_branch_name);
5904 return NULL;
5907 static const struct got_error *
5908 collect_rebase_commit_msg(struct got_pathlist_head *commitable_paths,
5909 char **logmsg, void *arg)
5911 *logmsg = arg;
5912 return NULL;
5915 static const struct got_error *
5916 rebase_status(void *arg, unsigned char status, unsigned char staged_status,
5917 const char *path, struct got_object_id *blob_id,
5918 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
5919 int dirfd, const char *de_name)
5921 return NULL;
5924 struct collect_merged_paths_arg {
5925 got_worktree_checkout_cb progress_cb;
5926 void *progress_arg;
5927 struct got_pathlist_head *merged_paths;
5930 static const struct got_error *
5931 collect_merged_paths(void *arg, unsigned char status, const char *path)
5933 const struct got_error *err;
5934 struct collect_merged_paths_arg *a = arg;
5935 char *p;
5936 struct got_pathlist_entry *new;
5938 err = (*a->progress_cb)(a->progress_arg, status, path);
5939 if (err)
5940 return err;
5942 if (status != GOT_STATUS_MERGE &&
5943 status != GOT_STATUS_ADD &&
5944 status != GOT_STATUS_DELETE &&
5945 status != GOT_STATUS_CONFLICT)
5946 return NULL;
5948 p = strdup(path);
5949 if (p == NULL)
5950 return got_error_from_errno("strdup");
5952 err = got_pathlist_insert(&new, a->merged_paths, p, NULL);
5953 if (err || new == NULL)
5954 free(p);
5955 return err;
5958 void
5959 got_worktree_rebase_pathlist_free(struct got_pathlist_head *merged_paths)
5961 struct got_pathlist_entry *pe;
5963 TAILQ_FOREACH(pe, merged_paths, entry)
5964 free((char *)pe->path);
5966 got_pathlist_free(merged_paths);
5969 static const struct got_error *
5970 store_commit_id(const char *commit_ref_name, struct got_object_id *commit_id,
5971 int is_rebase, struct got_repository *repo)
5973 const struct got_error *err;
5974 struct got_reference *commit_ref = NULL;
5976 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5977 if (err) {
5978 if (err->code != GOT_ERR_NOT_REF)
5979 goto done;
5980 err = got_ref_alloc(&commit_ref, commit_ref_name, commit_id);
5981 if (err)
5982 goto done;
5983 err = got_ref_write(commit_ref, repo);
5984 if (err)
5985 goto done;
5986 } else if (is_rebase) {
5987 struct got_object_id *stored_id;
5988 int cmp;
5990 err = got_ref_resolve(&stored_id, repo, commit_ref);
5991 if (err)
5992 goto done;
5993 cmp = got_object_id_cmp(commit_id, stored_id);
5994 free(stored_id);
5995 if (cmp != 0) {
5996 err = got_error(GOT_ERR_REBASE_COMMITID);
5997 goto done;
6000 done:
6001 if (commit_ref)
6002 got_ref_close(commit_ref);
6003 return err;
6006 static const struct got_error *
6007 rebase_merge_files(struct got_pathlist_head *merged_paths,
6008 const char *commit_ref_name, struct got_worktree *worktree,
6009 struct got_fileindex *fileindex, struct got_object_id *parent_commit_id,
6010 struct got_object_id *commit_id, struct got_repository *repo,
6011 got_worktree_checkout_cb progress_cb, void *progress_arg,
6012 got_cancel_cb cancel_cb, void *cancel_arg)
6014 const struct got_error *err;
6015 struct got_reference *commit_ref = NULL;
6016 struct collect_merged_paths_arg cmp_arg;
6017 char *fileindex_path;
6019 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6021 err = get_fileindex_path(&fileindex_path, worktree);
6022 if (err)
6023 return err;
6025 cmp_arg.progress_cb = progress_cb;
6026 cmp_arg.progress_arg = progress_arg;
6027 cmp_arg.merged_paths = merged_paths;
6028 err = merge_files(worktree, fileindex, fileindex_path,
6029 parent_commit_id, commit_id, repo, collect_merged_paths,
6030 &cmp_arg, cancel_cb, cancel_arg);
6031 if (commit_ref)
6032 got_ref_close(commit_ref);
6033 return err;
6036 const struct got_error *
6037 got_worktree_rebase_merge_files(struct got_pathlist_head *merged_paths,
6038 struct got_worktree *worktree, struct got_fileindex *fileindex,
6039 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
6040 struct got_repository *repo,
6041 got_worktree_checkout_cb progress_cb, void *progress_arg,
6042 got_cancel_cb cancel_cb, void *cancel_arg)
6044 const struct got_error *err;
6045 char *commit_ref_name;
6047 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6048 if (err)
6049 return err;
6051 err = store_commit_id(commit_ref_name, commit_id, 1, repo);
6052 if (err)
6053 goto done;
6055 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
6056 fileindex, parent_commit_id, commit_id, repo, progress_cb,
6057 progress_arg, cancel_cb, cancel_arg);
6058 done:
6059 free(commit_ref_name);
6060 return err;
6063 const struct got_error *
6064 got_worktree_histedit_merge_files(struct got_pathlist_head *merged_paths,
6065 struct got_worktree *worktree, struct got_fileindex *fileindex,
6066 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
6067 struct got_repository *repo,
6068 got_worktree_checkout_cb progress_cb, void *progress_arg,
6069 got_cancel_cb cancel_cb, void *cancel_arg)
6071 const struct got_error *err;
6072 char *commit_ref_name;
6074 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6075 if (err)
6076 return err;
6078 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
6079 if (err)
6080 goto done;
6082 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
6083 fileindex, parent_commit_id, commit_id, repo, progress_cb,
6084 progress_arg, cancel_cb, cancel_arg);
6085 done:
6086 free(commit_ref_name);
6087 return err;
6090 static const struct got_error *
6091 rebase_commit(struct got_object_id **new_commit_id,
6092 struct got_pathlist_head *merged_paths, struct got_reference *commit_ref,
6093 struct got_worktree *worktree, struct got_fileindex *fileindex,
6094 struct got_reference *tmp_branch, struct got_commit_object *orig_commit,
6095 const char *new_logmsg, struct got_repository *repo)
6097 const struct got_error *err, *sync_err;
6098 struct got_pathlist_head commitable_paths;
6099 struct collect_commitables_arg cc_arg;
6100 char *fileindex_path = NULL;
6101 struct got_reference *head_ref = NULL;
6102 struct got_object_id *head_commit_id = NULL;
6103 char *logmsg = NULL;
6105 TAILQ_INIT(&commitable_paths);
6106 *new_commit_id = NULL;
6108 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6110 err = get_fileindex_path(&fileindex_path, worktree);
6111 if (err)
6112 return err;
6114 cc_arg.commitable_paths = &commitable_paths;
6115 cc_arg.worktree = worktree;
6116 cc_arg.repo = repo;
6117 cc_arg.have_staged_files = 0;
6119 * If possible get the status of individual files directly to
6120 * avoid crawling the entire work tree once per rebased commit.
6121 * TODO: Ideally, merged_paths would contain a list of commitables
6122 * we could use so we could skip worktree_status() entirely.
6124 if (merged_paths) {
6125 struct got_pathlist_entry *pe;
6126 TAILQ_FOREACH(pe, merged_paths, entry) {
6127 err = worktree_status(worktree, pe->path, fileindex,
6128 repo, collect_commitables, &cc_arg, NULL, NULL, 0,
6129 0);
6130 if (err)
6131 goto done;
6133 } else {
6134 err = worktree_status(worktree, "", fileindex, repo,
6135 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
6136 if (err)
6137 goto done;
6140 if (TAILQ_EMPTY(&commitable_paths)) {
6141 /* No-op change; commit will be elided. */
6142 err = got_ref_delete(commit_ref, repo);
6143 if (err)
6144 goto done;
6145 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
6146 goto done;
6149 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
6150 if (err)
6151 goto done;
6153 err = got_ref_resolve(&head_commit_id, repo, head_ref);
6154 if (err)
6155 goto done;
6157 if (new_logmsg) {
6158 logmsg = strdup(new_logmsg);
6159 if (logmsg == NULL) {
6160 err = got_error_from_errno("strdup");
6161 goto done;
6163 } else {
6164 err = got_object_commit_get_logmsg(&logmsg, orig_commit);
6165 if (err)
6166 goto done;
6169 /* NB: commit_worktree will call free(logmsg) */
6170 err = commit_worktree(new_commit_id, &commitable_paths, head_commit_id,
6171 worktree, got_object_commit_get_author(orig_commit),
6172 got_object_commit_get_committer(orig_commit),
6173 collect_rebase_commit_msg, logmsg, rebase_status, NULL, repo);
6174 if (err)
6175 goto done;
6177 err = got_ref_change_ref(tmp_branch, *new_commit_id);
6178 if (err)
6179 goto done;
6181 err = got_ref_delete(commit_ref, repo);
6182 if (err)
6183 goto done;
6185 err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
6186 fileindex, 0);
6187 sync_err = sync_fileindex(fileindex, fileindex_path);
6188 if (sync_err && err == NULL)
6189 err = sync_err;
6190 done:
6191 free(fileindex_path);
6192 free(head_commit_id);
6193 if (head_ref)
6194 got_ref_close(head_ref);
6195 if (err) {
6196 free(*new_commit_id);
6197 *new_commit_id = NULL;
6199 return err;
6202 const struct got_error *
6203 got_worktree_rebase_commit(struct got_object_id **new_commit_id,
6204 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
6205 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6206 struct got_commit_object *orig_commit,
6207 struct got_object_id *orig_commit_id, struct got_repository *repo)
6209 const struct got_error *err;
6210 char *commit_ref_name;
6211 struct got_reference *commit_ref = NULL;
6212 struct got_object_id *commit_id = NULL;
6214 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6215 if (err)
6216 return err;
6218 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6219 if (err)
6220 goto done;
6221 err = got_ref_resolve(&commit_id, repo, commit_ref);
6222 if (err)
6223 goto done;
6224 if (got_object_id_cmp(commit_id, orig_commit_id) != 0) {
6225 err = got_error(GOT_ERR_REBASE_COMMITID);
6226 goto done;
6229 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
6230 worktree, fileindex, tmp_branch, orig_commit, NULL, repo);
6231 done:
6232 if (commit_ref)
6233 got_ref_close(commit_ref);
6234 free(commit_ref_name);
6235 free(commit_id);
6236 return err;
6239 const struct got_error *
6240 got_worktree_histedit_commit(struct got_object_id **new_commit_id,
6241 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
6242 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6243 struct got_commit_object *orig_commit,
6244 struct got_object_id *orig_commit_id, const char *new_logmsg,
6245 struct got_repository *repo)
6247 const struct got_error *err;
6248 char *commit_ref_name;
6249 struct got_reference *commit_ref = NULL;
6251 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6252 if (err)
6253 return err;
6255 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6256 if (err)
6257 goto done;
6259 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
6260 worktree, fileindex, tmp_branch, orig_commit, new_logmsg, repo);
6261 done:
6262 if (commit_ref)
6263 got_ref_close(commit_ref);
6264 free(commit_ref_name);
6265 return err;
6268 const struct got_error *
6269 got_worktree_rebase_postpone(struct got_worktree *worktree,
6270 struct got_fileindex *fileindex)
6272 if (fileindex)
6273 got_fileindex_free(fileindex);
6274 return lock_worktree(worktree, LOCK_SH);
6277 static const struct got_error *
6278 delete_ref(const char *name, struct got_repository *repo)
6280 const struct got_error *err;
6281 struct got_reference *ref;
6283 err = got_ref_open(&ref, repo, name, 0);
6284 if (err) {
6285 if (err->code == GOT_ERR_NOT_REF)
6286 return NULL;
6287 return err;
6290 err = got_ref_delete(ref, repo);
6291 got_ref_close(ref);
6292 return err;
6295 static const struct got_error *
6296 delete_rebase_refs(struct got_worktree *worktree, struct got_repository *repo)
6298 const struct got_error *err;
6299 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
6300 char *branch_ref_name = NULL, *commit_ref_name = NULL;
6302 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6303 if (err)
6304 goto done;
6305 err = delete_ref(tmp_branch_name, repo);
6306 if (err)
6307 goto done;
6309 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
6310 if (err)
6311 goto done;
6312 err = delete_ref(new_base_branch_ref_name, repo);
6313 if (err)
6314 goto done;
6316 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
6317 if (err)
6318 goto done;
6319 err = delete_ref(branch_ref_name, repo);
6320 if (err)
6321 goto done;
6323 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6324 if (err)
6325 goto done;
6326 err = delete_ref(commit_ref_name, repo);
6327 if (err)
6328 goto done;
6330 done:
6331 free(tmp_branch_name);
6332 free(new_base_branch_ref_name);
6333 free(branch_ref_name);
6334 free(commit_ref_name);
6335 return err;
6338 const struct got_error *
6339 got_worktree_rebase_complete(struct got_worktree *worktree,
6340 struct got_fileindex *fileindex, struct got_reference *new_base_branch,
6341 struct got_reference *tmp_branch, struct got_reference *rebased_branch,
6342 struct got_repository *repo)
6344 const struct got_error *err, *unlockerr;
6345 struct got_object_id *new_head_commit_id = NULL;
6347 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
6348 if (err)
6349 return err;
6351 err = got_ref_change_ref(rebased_branch, new_head_commit_id);
6352 if (err)
6353 goto done;
6355 err = got_ref_write(rebased_branch, repo);
6356 if (err)
6357 goto done;
6359 err = got_worktree_set_head_ref(worktree, rebased_branch);
6360 if (err)
6361 goto done;
6363 err = delete_rebase_refs(worktree, repo);
6364 done:
6365 if (fileindex)
6366 got_fileindex_free(fileindex);
6367 free(new_head_commit_id);
6368 unlockerr = lock_worktree(worktree, LOCK_SH);
6369 if (unlockerr && err == NULL)
6370 err = unlockerr;
6371 return err;
6374 const struct got_error *
6375 got_worktree_rebase_abort(struct got_worktree *worktree,
6376 struct got_fileindex *fileindex, struct got_repository *repo,
6377 struct got_reference *new_base_branch,
6378 got_worktree_checkout_cb progress_cb, void *progress_arg)
6380 const struct got_error *err, *unlockerr, *sync_err;
6381 struct got_reference *resolved = NULL;
6382 struct got_object_id *commit_id = NULL;
6383 char *fileindex_path = NULL;
6384 struct revert_file_args rfa;
6385 struct got_object_id *tree_id = NULL;
6387 err = lock_worktree(worktree, LOCK_EX);
6388 if (err)
6389 return err;
6391 err = got_ref_open(&resolved, repo,
6392 got_ref_get_symref_target(new_base_branch), 0);
6393 if (err)
6394 goto done;
6396 err = got_worktree_set_head_ref(worktree, resolved);
6397 if (err)
6398 goto done;
6401 * XXX commits to the base branch could have happened while
6402 * we were busy rebasing; should we store the original commit ID
6403 * when rebase begins and read it back here?
6405 err = got_ref_resolve(&commit_id, repo, resolved);
6406 if (err)
6407 goto done;
6409 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
6410 if (err)
6411 goto done;
6413 err = got_object_id_by_path(&tree_id, repo,
6414 worktree->base_commit_id, worktree->path_prefix);
6415 if (err)
6416 goto done;
6418 err = delete_rebase_refs(worktree, repo);
6419 if (err)
6420 goto done;
6422 err = get_fileindex_path(&fileindex_path, worktree);
6423 if (err)
6424 goto done;
6426 rfa.worktree = worktree;
6427 rfa.fileindex = fileindex;
6428 rfa.progress_cb = progress_cb;
6429 rfa.progress_arg = progress_arg;
6430 rfa.patch_cb = NULL;
6431 rfa.patch_arg = NULL;
6432 rfa.repo = repo;
6433 err = worktree_status(worktree, "", fileindex, repo,
6434 revert_file, &rfa, NULL, NULL, 0, 0);
6435 if (err)
6436 goto sync;
6438 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
6439 repo, progress_cb, progress_arg, NULL, NULL);
6440 sync:
6441 sync_err = sync_fileindex(fileindex, fileindex_path);
6442 if (sync_err && err == NULL)
6443 err = sync_err;
6444 done:
6445 got_ref_close(resolved);
6446 free(tree_id);
6447 free(commit_id);
6448 if (fileindex)
6449 got_fileindex_free(fileindex);
6450 free(fileindex_path);
6452 unlockerr = lock_worktree(worktree, LOCK_SH);
6453 if (unlockerr && err == NULL)
6454 err = unlockerr;
6455 return err;
6458 const struct got_error *
6459 got_worktree_histedit_prepare(struct got_reference **tmp_branch,
6460 struct got_reference **branch_ref, struct got_object_id **base_commit_id,
6461 struct got_fileindex **fileindex, struct got_worktree *worktree,
6462 struct got_repository *repo)
6464 const struct got_error *err = NULL;
6465 char *tmp_branch_name = NULL;
6466 char *branch_ref_name = NULL;
6467 char *base_commit_ref_name = NULL;
6468 char *fileindex_path = NULL;
6469 struct check_rebase_ok_arg ok_arg;
6470 struct got_reference *wt_branch = NULL;
6471 struct got_reference *base_commit_ref = NULL;
6473 *tmp_branch = NULL;
6474 *branch_ref = NULL;
6475 *base_commit_id = NULL;
6476 *fileindex = NULL;
6478 err = lock_worktree(worktree, LOCK_EX);
6479 if (err)
6480 return err;
6482 err = open_fileindex(fileindex, &fileindex_path, worktree);
6483 if (err)
6484 goto done;
6486 ok_arg.worktree = worktree;
6487 ok_arg.repo = repo;
6488 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
6489 &ok_arg);
6490 if (err)
6491 goto done;
6493 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6494 if (err)
6495 goto done;
6497 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
6498 if (err)
6499 goto done;
6501 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
6502 worktree);
6503 if (err)
6504 goto done;
6506 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
6507 0);
6508 if (err)
6509 goto done;
6511 err = got_ref_alloc_symref(branch_ref, branch_ref_name, wt_branch);
6512 if (err)
6513 goto done;
6515 err = got_ref_write(*branch_ref, repo);
6516 if (err)
6517 goto done;
6519 err = got_ref_alloc(&base_commit_ref, base_commit_ref_name,
6520 worktree->base_commit_id);
6521 if (err)
6522 goto done;
6523 err = got_ref_write(base_commit_ref, repo);
6524 if (err)
6525 goto done;
6526 *base_commit_id = got_object_id_dup(worktree->base_commit_id);
6527 if (*base_commit_id == NULL) {
6528 err = got_error_from_errno("got_object_id_dup");
6529 goto done;
6532 err = got_ref_alloc(tmp_branch, tmp_branch_name,
6533 worktree->base_commit_id);
6534 if (err)
6535 goto done;
6536 err = got_ref_write(*tmp_branch, repo);
6537 if (err)
6538 goto done;
6540 err = got_worktree_set_head_ref(worktree, *tmp_branch);
6541 if (err)
6542 goto done;
6543 done:
6544 free(fileindex_path);
6545 free(tmp_branch_name);
6546 free(branch_ref_name);
6547 free(base_commit_ref_name);
6548 if (wt_branch)
6549 got_ref_close(wt_branch);
6550 if (err) {
6551 if (*branch_ref) {
6552 got_ref_close(*branch_ref);
6553 *branch_ref = NULL;
6555 if (*tmp_branch) {
6556 got_ref_close(*tmp_branch);
6557 *tmp_branch = NULL;
6559 free(*base_commit_id);
6560 if (*fileindex) {
6561 got_fileindex_free(*fileindex);
6562 *fileindex = NULL;
6564 lock_worktree(worktree, LOCK_SH);
6566 return err;
6569 const struct got_error *
6570 got_worktree_histedit_postpone(struct got_worktree *worktree,
6571 struct got_fileindex *fileindex)
6573 if (fileindex)
6574 got_fileindex_free(fileindex);
6575 return lock_worktree(worktree, LOCK_SH);
6578 const struct got_error *
6579 got_worktree_histedit_in_progress(int *in_progress,
6580 struct got_worktree *worktree)
6582 const struct got_error *err;
6583 char *tmp_branch_name = NULL;
6585 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6586 if (err)
6587 return err;
6589 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
6590 free(tmp_branch_name);
6591 return NULL;
6594 const struct got_error *
6595 got_worktree_histedit_continue(struct got_object_id **commit_id,
6596 struct got_reference **tmp_branch, struct got_reference **branch_ref,
6597 struct got_object_id **base_commit_id, struct got_fileindex **fileindex,
6598 struct got_worktree *worktree, struct got_repository *repo)
6600 const struct got_error *err;
6601 char *commit_ref_name = NULL, *base_commit_ref_name = NULL;
6602 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
6603 struct got_reference *commit_ref = NULL;
6604 struct got_reference *base_commit_ref = NULL;
6605 char *fileindex_path = NULL;
6606 int have_staged_files = 0;
6608 *commit_id = NULL;
6609 *tmp_branch = NULL;
6610 *base_commit_id = NULL;
6611 *fileindex = NULL;
6613 err = lock_worktree(worktree, LOCK_EX);
6614 if (err)
6615 return err;
6617 err = open_fileindex(fileindex, &fileindex_path, worktree);
6618 if (err)
6619 goto done;
6621 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
6622 &have_staged_files);
6623 if (err && err->code != GOT_ERR_CANCELLED)
6624 goto done;
6625 if (have_staged_files) {
6626 err = got_error(GOT_ERR_STAGED_PATHS);
6627 goto done;
6630 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6631 if (err)
6632 goto done;
6634 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
6635 if (err)
6636 goto done;
6638 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6639 if (err)
6640 goto done;
6642 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
6643 worktree);
6644 if (err)
6645 goto done;
6647 err = got_ref_open(branch_ref, repo, branch_ref_name, 0);
6648 if (err)
6649 goto done;
6651 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6652 if (err)
6653 goto done;
6654 err = got_ref_resolve(commit_id, repo, commit_ref);
6655 if (err)
6656 goto done;
6658 err = got_ref_open(&base_commit_ref, repo, base_commit_ref_name, 0);
6659 if (err)
6660 goto done;
6661 err = got_ref_resolve(base_commit_id, repo, base_commit_ref);
6662 if (err)
6663 goto done;
6665 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
6666 if (err)
6667 goto done;
6668 done:
6669 free(commit_ref_name);
6670 free(branch_ref_name);
6671 free(fileindex_path);
6672 if (commit_ref)
6673 got_ref_close(commit_ref);
6674 if (base_commit_ref)
6675 got_ref_close(base_commit_ref);
6676 if (err) {
6677 free(*commit_id);
6678 *commit_id = NULL;
6679 free(*base_commit_id);
6680 *base_commit_id = NULL;
6681 if (*tmp_branch) {
6682 got_ref_close(*tmp_branch);
6683 *tmp_branch = NULL;
6685 if (*fileindex) {
6686 got_fileindex_free(*fileindex);
6687 *fileindex = NULL;
6689 lock_worktree(worktree, LOCK_EX);
6691 return err;
6694 static const struct got_error *
6695 delete_histedit_refs(struct got_worktree *worktree, struct got_repository *repo)
6697 const struct got_error *err;
6698 char *tmp_branch_name = NULL, *base_commit_ref_name = NULL;
6699 char *branch_ref_name = NULL, *commit_ref_name = NULL;
6701 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6702 if (err)
6703 goto done;
6704 err = delete_ref(tmp_branch_name, repo);
6705 if (err)
6706 goto done;
6708 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
6709 worktree);
6710 if (err)
6711 goto done;
6712 err = delete_ref(base_commit_ref_name, repo);
6713 if (err)
6714 goto done;
6716 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
6717 if (err)
6718 goto done;
6719 err = delete_ref(branch_ref_name, repo);
6720 if (err)
6721 goto done;
6723 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6724 if (err)
6725 goto done;
6726 err = delete_ref(commit_ref_name, repo);
6727 if (err)
6728 goto done;
6729 done:
6730 free(tmp_branch_name);
6731 free(base_commit_ref_name);
6732 free(branch_ref_name);
6733 free(commit_ref_name);
6734 return err;
6737 const struct got_error *
6738 got_worktree_histedit_abort(struct got_worktree *worktree,
6739 struct got_fileindex *fileindex, struct got_repository *repo,
6740 struct got_reference *branch, struct got_object_id *base_commit_id,
6741 got_worktree_checkout_cb progress_cb, void *progress_arg)
6743 const struct got_error *err, *unlockerr, *sync_err;
6744 struct got_reference *resolved = NULL;
6745 char *fileindex_path = NULL;
6746 struct got_object_id *tree_id = NULL;
6747 struct revert_file_args rfa;
6749 err = lock_worktree(worktree, LOCK_EX);
6750 if (err)
6751 return err;
6753 err = got_ref_open(&resolved, repo,
6754 got_ref_get_symref_target(branch), 0);
6755 if (err)
6756 goto done;
6758 err = got_worktree_set_head_ref(worktree, resolved);
6759 if (err)
6760 goto done;
6762 err = got_worktree_set_base_commit_id(worktree, repo, base_commit_id);
6763 if (err)
6764 goto done;
6766 err = got_object_id_by_path(&tree_id, repo, base_commit_id,
6767 worktree->path_prefix);
6768 if (err)
6769 goto done;
6771 err = delete_histedit_refs(worktree, repo);
6772 if (err)
6773 goto done;
6775 err = get_fileindex_path(&fileindex_path, worktree);
6776 if (err)
6777 goto done;
6779 rfa.worktree = worktree;
6780 rfa.fileindex = fileindex;
6781 rfa.progress_cb = progress_cb;
6782 rfa.progress_arg = progress_arg;
6783 rfa.patch_cb = NULL;
6784 rfa.patch_arg = NULL;
6785 rfa.repo = repo;
6786 err = worktree_status(worktree, "", fileindex, repo,
6787 revert_file, &rfa, NULL, NULL, 0, 0);
6788 if (err)
6789 goto sync;
6791 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
6792 repo, progress_cb, progress_arg, NULL, NULL);
6793 sync:
6794 sync_err = sync_fileindex(fileindex, fileindex_path);
6795 if (sync_err && err == NULL)
6796 err = sync_err;
6797 done:
6798 got_ref_close(resolved);
6799 free(tree_id);
6800 free(fileindex_path);
6802 unlockerr = lock_worktree(worktree, LOCK_SH);
6803 if (unlockerr && err == NULL)
6804 err = unlockerr;
6805 return err;
6808 const struct got_error *
6809 got_worktree_histedit_complete(struct got_worktree *worktree,
6810 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6811 struct got_reference *edited_branch, struct got_repository *repo)
6813 const struct got_error *err, *unlockerr;
6814 struct got_object_id *new_head_commit_id = NULL;
6815 struct got_reference *resolved = NULL;
6817 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
6818 if (err)
6819 return err;
6821 err = got_ref_open(&resolved, repo,
6822 got_ref_get_symref_target(edited_branch), 0);
6823 if (err)
6824 goto done;
6826 err = got_ref_change_ref(resolved, new_head_commit_id);
6827 if (err)
6828 goto done;
6830 err = got_ref_write(resolved, repo);
6831 if (err)
6832 goto done;
6834 err = got_worktree_set_head_ref(worktree, resolved);
6835 if (err)
6836 goto done;
6838 err = delete_histedit_refs(worktree, repo);
6839 done:
6840 if (fileindex)
6841 got_fileindex_free(fileindex);
6842 free(new_head_commit_id);
6843 unlockerr = lock_worktree(worktree, LOCK_SH);
6844 if (unlockerr && err == NULL)
6845 err = unlockerr;
6846 return err;
6849 const struct got_error *
6850 got_worktree_histedit_skip_commit(struct got_worktree *worktree,
6851 struct got_object_id *commit_id, struct got_repository *repo)
6853 const struct got_error *err;
6854 char *commit_ref_name;
6856 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6857 if (err)
6858 return err;
6860 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
6861 if (err)
6862 goto done;
6864 err = delete_ref(commit_ref_name, repo);
6865 done:
6866 free(commit_ref_name);
6867 return err;
6870 const struct got_error *
6871 got_worktree_integrate_prepare(struct got_fileindex **fileindex,
6872 struct got_reference **branch_ref, struct got_reference **base_branch_ref,
6873 struct got_worktree *worktree, const char *refname,
6874 struct got_repository *repo)
6876 const struct got_error *err = NULL;
6877 char *fileindex_path = NULL;
6878 struct check_rebase_ok_arg ok_arg;
6880 *fileindex = NULL;
6881 *branch_ref = NULL;
6882 *base_branch_ref = NULL;
6884 err = lock_worktree(worktree, LOCK_EX);
6885 if (err)
6886 return err;
6888 if (strcmp(refname, got_worktree_get_head_ref_name(worktree)) == 0) {
6889 err = got_error_msg(GOT_ERR_SAME_BRANCH,
6890 "cannot integrate a branch into itself; "
6891 "update -b or different branch name required");
6892 goto done;
6895 err = open_fileindex(fileindex, &fileindex_path, worktree);
6896 if (err)
6897 goto done;
6899 /* Preconditions are the same as for rebase. */
6900 ok_arg.worktree = worktree;
6901 ok_arg.repo = repo;
6902 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
6903 &ok_arg);
6904 if (err)
6905 goto done;
6907 err = got_ref_open(branch_ref, repo, refname, 1);
6908 if (err)
6909 goto done;
6911 err = got_ref_open(base_branch_ref, repo,
6912 got_worktree_get_head_ref_name(worktree), 1);
6913 done:
6914 if (err) {
6915 if (*branch_ref) {
6916 got_ref_close(*branch_ref);
6917 *branch_ref = NULL;
6919 if (*base_branch_ref) {
6920 got_ref_close(*base_branch_ref);
6921 *base_branch_ref = NULL;
6923 if (*fileindex) {
6924 got_fileindex_free(*fileindex);
6925 *fileindex = NULL;
6927 lock_worktree(worktree, LOCK_SH);
6929 return err;
6932 const struct got_error *
6933 got_worktree_integrate_continue(struct got_worktree *worktree,
6934 struct got_fileindex *fileindex, struct got_repository *repo,
6935 struct got_reference *branch_ref, struct got_reference *base_branch_ref,
6936 got_worktree_checkout_cb progress_cb, void *progress_arg,
6937 got_cancel_cb cancel_cb, void *cancel_arg)
6939 const struct got_error *err = NULL, *sync_err, *unlockerr;
6940 char *fileindex_path = NULL;
6941 struct got_object_id *tree_id = NULL, *commit_id = NULL;
6943 err = get_fileindex_path(&fileindex_path, worktree);
6944 if (err)
6945 goto done;
6947 err = got_ref_resolve(&commit_id, repo, branch_ref);
6948 if (err)
6949 goto done;
6951 err = got_object_id_by_path(&tree_id, repo, commit_id,
6952 worktree->path_prefix);
6953 if (err)
6954 goto done;
6956 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
6957 if (err)
6958 goto done;
6960 err = checkout_files(worktree, fileindex, "", tree_id, NULL, repo,
6961 progress_cb, progress_arg, cancel_cb, cancel_arg);
6962 if (err)
6963 goto sync;
6965 err = got_ref_change_ref(base_branch_ref, commit_id);
6966 if (err)
6967 goto sync;
6969 err = got_ref_write(base_branch_ref, repo);
6970 sync:
6971 sync_err = sync_fileindex(fileindex, fileindex_path);
6972 if (sync_err && err == NULL)
6973 err = sync_err;
6975 done:
6976 unlockerr = got_ref_unlock(branch_ref);
6977 if (unlockerr && err == NULL)
6978 err = unlockerr;
6979 got_ref_close(branch_ref);
6981 unlockerr = got_ref_unlock(base_branch_ref);
6982 if (unlockerr && err == NULL)
6983 err = unlockerr;
6984 got_ref_close(base_branch_ref);
6986 got_fileindex_free(fileindex);
6987 free(fileindex_path);
6988 free(tree_id);
6990 unlockerr = lock_worktree(worktree, LOCK_SH);
6991 if (unlockerr && err == NULL)
6992 err = unlockerr;
6993 return err;
6996 const struct got_error *
6997 got_worktree_integrate_abort(struct got_worktree *worktree,
6998 struct got_fileindex *fileindex, struct got_repository *repo,
6999 struct got_reference *branch_ref, struct got_reference *base_branch_ref)
7001 const struct got_error *err = NULL, *unlockerr = NULL;
7003 got_fileindex_free(fileindex);
7005 err = lock_worktree(worktree, LOCK_SH);
7007 unlockerr = got_ref_unlock(branch_ref);
7008 if (unlockerr && err == NULL)
7009 err = unlockerr;
7010 got_ref_close(branch_ref);
7012 unlockerr = got_ref_unlock(base_branch_ref);
7013 if (unlockerr && err == NULL)
7014 err = unlockerr;
7015 got_ref_close(base_branch_ref);
7017 return err;
7020 struct check_stage_ok_arg {
7021 struct got_object_id *head_commit_id;
7022 struct got_worktree *worktree;
7023 struct got_fileindex *fileindex;
7024 struct got_repository *repo;
7025 int have_changes;
7028 const struct got_error *
7029 check_stage_ok(void *arg, unsigned char status,
7030 unsigned char staged_status, const char *relpath,
7031 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
7032 struct got_object_id *commit_id, int dirfd, const char *de_name)
7034 struct check_stage_ok_arg *a = arg;
7035 const struct got_error *err = NULL;
7036 struct got_fileindex_entry *ie;
7037 struct got_object_id base_commit_id;
7038 struct got_object_id *base_commit_idp = NULL;
7039 char *in_repo_path = NULL, *p;
7041 if (status == GOT_STATUS_UNVERSIONED ||
7042 status == GOT_STATUS_NO_CHANGE)
7043 return NULL;
7044 if (status == GOT_STATUS_NONEXISTENT)
7045 return got_error_set_errno(ENOENT, relpath);
7047 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
7048 if (ie == NULL)
7049 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
7051 if (asprintf(&in_repo_path, "%s%s%s", a->worktree->path_prefix,
7052 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
7053 relpath) == -1)
7054 return got_error_from_errno("asprintf");
7056 if (got_fileindex_entry_has_commit(ie)) {
7057 memcpy(base_commit_id.sha1, ie->commit_sha1,
7058 SHA1_DIGEST_LENGTH);
7059 base_commit_idp = &base_commit_id;
7062 if (status == GOT_STATUS_CONFLICT) {
7063 err = got_error_path(ie->path, GOT_ERR_STAGE_CONFLICT);
7064 goto done;
7065 } else if (status != GOT_STATUS_ADD &&
7066 status != GOT_STATUS_MODIFY &&
7067 status != GOT_STATUS_DELETE) {
7068 err = got_error_path(ie->path, GOT_ERR_FILE_STATUS);
7069 goto done;
7072 a->have_changes = 1;
7074 p = in_repo_path;
7075 while (p[0] == '/')
7076 p++;
7077 err = check_out_of_date(p, status, staged_status,
7078 blob_id, base_commit_idp, a->head_commit_id, a->repo,
7079 GOT_ERR_STAGE_OUT_OF_DATE);
7080 done:
7081 free(in_repo_path);
7082 return err;
7085 struct stage_path_arg {
7086 struct got_worktree *worktree;
7087 struct got_fileindex *fileindex;
7088 struct got_repository *repo;
7089 got_worktree_status_cb status_cb;
7090 void *status_arg;
7091 got_worktree_patch_cb patch_cb;
7092 void *patch_arg;
7093 int staged_something;
7096 static const struct got_error *
7097 stage_path(void *arg, unsigned char status,
7098 unsigned char staged_status, const char *relpath,
7099 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
7100 struct got_object_id *commit_id, int dirfd, const char *de_name)
7102 struct stage_path_arg *a = arg;
7103 const struct got_error *err = NULL;
7104 struct got_fileindex_entry *ie;
7105 char *ondisk_path = NULL, *path_content = NULL;
7106 uint32_t stage;
7107 struct got_object_id *new_staged_blob_id = NULL;
7108 struct stat sb;
7110 if (status == GOT_STATUS_UNVERSIONED)
7111 return NULL;
7113 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
7114 if (ie == NULL)
7115 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
7117 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
7118 relpath)== -1)
7119 return got_error_from_errno("asprintf");
7121 switch (status) {
7122 case GOT_STATUS_ADD:
7123 case GOT_STATUS_MODIFY:
7124 /* XXX could sb.st_mode be passed in by our caller? */
7125 if (lstat(ondisk_path, &sb) == -1) {
7126 err = got_error_from_errno2("lstat", ondisk_path);
7127 break;
7129 if (a->patch_cb) {
7130 if (status == GOT_STATUS_ADD) {
7131 int choice = GOT_PATCH_CHOICE_NONE;
7132 err = (*a->patch_cb)(&choice, a->patch_arg,
7133 status, ie->path, NULL, 1, 1);
7134 if (err)
7135 break;
7136 if (choice != GOT_PATCH_CHOICE_YES)
7137 break;
7138 } else {
7139 err = create_patched_content(&path_content, 0,
7140 staged_blob_id ? staged_blob_id : blob_id,
7141 ondisk_path, dirfd, de_name, ie->path,
7142 a->repo, a->patch_cb, a->patch_arg);
7143 if (err || path_content == NULL)
7144 break;
7147 err = got_object_blob_create(&new_staged_blob_id,
7148 path_content ? path_content : ondisk_path, a->repo);
7149 if (err)
7150 break;
7151 memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1,
7152 SHA1_DIGEST_LENGTH);
7153 if (status == GOT_STATUS_ADD || staged_status == GOT_STATUS_ADD)
7154 stage = GOT_FILEIDX_STAGE_ADD;
7155 else
7156 stage = GOT_FILEIDX_STAGE_MODIFY;
7157 got_fileindex_entry_stage_set(ie, stage);
7158 if (S_ISLNK(sb.st_mode)) {
7159 got_fileindex_entry_staged_filetype_set(ie,
7160 GOT_FILEIDX_MODE_SYMLINK);
7161 } else {
7162 got_fileindex_entry_staged_filetype_set(ie,
7163 GOT_FILEIDX_MODE_REGULAR_FILE);
7165 a->staged_something = 1;
7166 if (a->status_cb == NULL)
7167 break;
7168 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
7169 get_staged_status(ie), relpath, blob_id,
7170 new_staged_blob_id, NULL, dirfd, de_name);
7171 break;
7172 case GOT_STATUS_DELETE:
7173 if (staged_status == GOT_STATUS_DELETE)
7174 break;
7175 if (a->patch_cb) {
7176 int choice = GOT_PATCH_CHOICE_NONE;
7177 err = (*a->patch_cb)(&choice, a->patch_arg, status,
7178 ie->path, NULL, 1, 1);
7179 if (err)
7180 break;
7181 if (choice == GOT_PATCH_CHOICE_NO)
7182 break;
7183 if (choice != GOT_PATCH_CHOICE_YES) {
7184 err = got_error(GOT_ERR_PATCH_CHOICE);
7185 break;
7188 stage = GOT_FILEIDX_STAGE_DELETE;
7189 got_fileindex_entry_stage_set(ie, stage);
7190 a->staged_something = 1;
7191 if (a->status_cb == NULL)
7192 break;
7193 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
7194 get_staged_status(ie), relpath, NULL, NULL, NULL, dirfd,
7195 de_name);
7196 break;
7197 case GOT_STATUS_NO_CHANGE:
7198 break;
7199 case GOT_STATUS_CONFLICT:
7200 err = got_error_path(relpath, GOT_ERR_STAGE_CONFLICT);
7201 break;
7202 case GOT_STATUS_NONEXISTENT:
7203 err = got_error_set_errno(ENOENT, relpath);
7204 break;
7205 default:
7206 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
7207 break;
7210 if (path_content && unlink(path_content) == -1 && err == NULL)
7211 err = got_error_from_errno2("unlink", path_content);
7212 free(path_content);
7213 free(ondisk_path);
7214 free(new_staged_blob_id);
7215 return err;
7218 const struct got_error *
7219 got_worktree_stage(struct got_worktree *worktree,
7220 struct got_pathlist_head *paths,
7221 got_worktree_status_cb status_cb, void *status_arg,
7222 got_worktree_patch_cb patch_cb, void *patch_arg,
7223 struct got_repository *repo)
7225 const struct got_error *err = NULL, *sync_err, *unlockerr;
7226 struct got_pathlist_entry *pe;
7227 struct got_fileindex *fileindex = NULL;
7228 char *fileindex_path = NULL;
7229 struct got_reference *head_ref = NULL;
7230 struct got_object_id *head_commit_id = NULL;
7231 struct check_stage_ok_arg oka;
7232 struct stage_path_arg spa;
7234 err = lock_worktree(worktree, LOCK_EX);
7235 if (err)
7236 return err;
7238 err = got_ref_open(&head_ref, repo,
7239 got_worktree_get_head_ref_name(worktree), 0);
7240 if (err)
7241 goto done;
7242 err = got_ref_resolve(&head_commit_id, repo, head_ref);
7243 if (err)
7244 goto done;
7245 err = open_fileindex(&fileindex, &fileindex_path, worktree);
7246 if (err)
7247 goto done;
7249 /* Check pre-conditions before staging anything. */
7250 oka.head_commit_id = head_commit_id;
7251 oka.worktree = worktree;
7252 oka.fileindex = fileindex;
7253 oka.repo = repo;
7254 oka.have_changes = 0;
7255 TAILQ_FOREACH(pe, paths, entry) {
7256 err = worktree_status(worktree, pe->path, fileindex, repo,
7257 check_stage_ok, &oka, NULL, NULL, 0, 0);
7258 if (err)
7259 goto done;
7261 if (!oka.have_changes) {
7262 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
7263 goto done;
7266 spa.worktree = worktree;
7267 spa.fileindex = fileindex;
7268 spa.repo = repo;
7269 spa.patch_cb = patch_cb;
7270 spa.patch_arg = patch_arg;
7271 spa.status_cb = status_cb;
7272 spa.status_arg = status_arg;
7273 spa.staged_something = 0;
7274 TAILQ_FOREACH(pe, paths, entry) {
7275 err = worktree_status(worktree, pe->path, fileindex, repo,
7276 stage_path, &spa, NULL, NULL, 0, 0);
7277 if (err)
7278 goto done;
7280 if (!spa.staged_something) {
7281 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
7282 goto done;
7285 sync_err = sync_fileindex(fileindex, fileindex_path);
7286 if (sync_err && err == NULL)
7287 err = sync_err;
7288 done:
7289 if (head_ref)
7290 got_ref_close(head_ref);
7291 free(head_commit_id);
7292 free(fileindex_path);
7293 if (fileindex)
7294 got_fileindex_free(fileindex);
7295 unlockerr = lock_worktree(worktree, LOCK_SH);
7296 if (unlockerr && err == NULL)
7297 err = unlockerr;
7298 return err;
7301 struct unstage_path_arg {
7302 struct got_worktree *worktree;
7303 struct got_fileindex *fileindex;
7304 struct got_repository *repo;
7305 got_worktree_checkout_cb progress_cb;
7306 void *progress_arg;
7307 got_worktree_patch_cb patch_cb;
7308 void *patch_arg;
7311 static const struct got_error *
7312 create_unstaged_content(char **path_unstaged_content,
7313 char **path_new_staged_content, struct got_object_id *blob_id,
7314 struct got_object_id *staged_blob_id, const char *relpath,
7315 struct got_repository *repo,
7316 got_worktree_patch_cb patch_cb, void *patch_arg)
7318 const struct got_error *err;
7319 struct got_blob_object *blob = NULL, *staged_blob = NULL;
7320 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL, *rejectfile = NULL;
7321 char *path1 = NULL, *path2 = NULL, *label1 = NULL;
7322 struct stat sb1, sb2;
7323 struct got_diff_changes *changes = NULL;
7324 struct got_diff_state *ds = NULL;
7325 struct got_diff_args *args = NULL;
7326 struct got_diff_change *change;
7327 int diff_flags = 0, line_cur1 = 1, line_cur2 = 1, n = 0;
7328 int have_content = 0, have_rejected_content = 0;
7330 *path_unstaged_content = NULL;
7331 *path_new_staged_content = NULL;
7333 err = got_object_id_str(&label1, blob_id);
7334 if (err)
7335 return err;
7336 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
7337 if (err)
7338 goto done;
7340 err = got_opentemp_named(&path1, &f1, "got-unstage-blob-base");
7341 if (err)
7342 goto done;
7344 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
7345 if (err)
7346 goto done;
7348 err = got_object_open_as_blob(&staged_blob, repo, staged_blob_id, 8192);
7349 if (err)
7350 goto done;
7352 err = got_opentemp_named(&path2, &f2, "got-unstage-blob-staged");
7353 if (err)
7354 goto done;
7356 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f2, staged_blob);
7357 if (err)
7358 goto done;
7360 if (stat(path1, &sb1) == -1) {
7361 err = got_error_from_errno2("stat", path1);
7362 goto done;
7365 if (stat(path2, &sb2) == -1) {
7366 err = got_error_from_errno2("stat", path2);
7367 goto done;
7370 err = got_diff_files(&changes, &ds, &args, &diff_flags,
7371 f1, sb1.st_size, label1, f2, sb2.st_size, path2, 3, NULL);
7372 if (err)
7373 goto done;
7375 err = got_opentemp_named(path_unstaged_content, &outfile,
7376 "got-unstaged-content");
7377 if (err)
7378 goto done;
7379 err = got_opentemp_named(path_new_staged_content, &rejectfile,
7380 "got-new-staged-content");
7381 if (err)
7382 goto done;
7384 if (fseek(f1, 0L, SEEK_SET) == -1) {
7385 err = got_ferror(f1, GOT_ERR_IO);
7386 goto done;
7388 if (fseek(f2, 0L, SEEK_SET) == -1) {
7389 err = got_ferror(f2, GOT_ERR_IO);
7390 goto done;
7392 SIMPLEQ_FOREACH(change, &changes->entries, entry) {
7393 int choice;
7394 err = apply_or_reject_change(&choice, change, ++n,
7395 changes->nchanges, ds, args, diff_flags, relpath,
7396 f1, f2, &line_cur1, &line_cur2,
7397 outfile, rejectfile, patch_cb, patch_arg);
7398 if (err)
7399 goto done;
7400 if (choice == GOT_PATCH_CHOICE_YES)
7401 have_content = 1;
7402 else
7403 have_rejected_content = 1;
7404 if (choice == GOT_PATCH_CHOICE_QUIT)
7405 break;
7407 if (have_content || have_rejected_content)
7408 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
7409 outfile, rejectfile);
7410 done:
7411 free(label1);
7412 if (blob)
7413 got_object_blob_close(blob);
7414 if (staged_blob)
7415 got_object_blob_close(staged_blob);
7416 if (f1 && fclose(f1) == EOF && err == NULL)
7417 err = got_error_from_errno2("fclose", path1);
7418 if (f2 && fclose(f2) == EOF && err == NULL)
7419 err = got_error_from_errno2("fclose", path2);
7420 if (outfile && fclose(outfile) == EOF && err == NULL)
7421 err = got_error_from_errno2("fclose", *path_unstaged_content);
7422 if (rejectfile && fclose(rejectfile) == EOF && err == NULL)
7423 err = got_error_from_errno2("fclose", *path_new_staged_content);
7424 if (path1 && unlink(path1) == -1 && err == NULL)
7425 err = got_error_from_errno2("unlink", path1);
7426 if (path2 && unlink(path2) == -1 && err == NULL)
7427 err = got_error_from_errno2("unlink", path2);
7428 if (err || !have_content) {
7429 if (*path_unstaged_content &&
7430 unlink(*path_unstaged_content) == -1 && err == NULL)
7431 err = got_error_from_errno2("unlink",
7432 *path_unstaged_content);
7433 free(*path_unstaged_content);
7434 *path_unstaged_content = NULL;
7436 if (err || !have_rejected_content) {
7437 if (*path_new_staged_content &&
7438 unlink(*path_new_staged_content) == -1 && err == NULL)
7439 err = got_error_from_errno2("unlink",
7440 *path_new_staged_content);
7441 free(*path_new_staged_content);
7442 *path_new_staged_content = NULL;
7444 free(args);
7445 if (ds) {
7446 got_diff_state_free(ds);
7447 free(ds);
7449 if (changes)
7450 got_diff_free_changes(changes);
7451 free(path1);
7452 free(path2);
7453 return err;
7456 static const struct got_error *
7457 unstage_path(void *arg, unsigned char status,
7458 unsigned char staged_status, const char *relpath,
7459 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
7460 struct got_object_id *commit_id, int dirfd, const char *de_name)
7462 const struct got_error *err = NULL;
7463 struct unstage_path_arg *a = arg;
7464 struct got_fileindex_entry *ie;
7465 struct got_blob_object *blob_base = NULL, *blob_staged = NULL;
7466 char *ondisk_path = NULL, *path_unstaged_content = NULL;
7467 char *path_new_staged_content = NULL;
7468 char *id_str = NULL, *label_orig = NULL;
7469 int local_changes_subsumed;
7470 struct stat sb;
7472 if (staged_status != GOT_STATUS_ADD &&
7473 staged_status != GOT_STATUS_MODIFY &&
7474 staged_status != GOT_STATUS_DELETE)
7475 return NULL;
7477 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
7478 if (ie == NULL)
7479 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
7481 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, relpath)
7482 == -1)
7483 return got_error_from_errno("asprintf");
7485 err = got_object_id_str(&id_str,
7486 commit_id ? commit_id : a->worktree->base_commit_id);
7487 if (err)
7488 goto done;
7489 if (asprintf(&label_orig, "%s: commit %s", GOT_MERGE_LABEL_BASE,
7490 id_str) == -1) {
7491 err = got_error_from_errno("asprintf");
7492 goto done;
7495 switch (staged_status) {
7496 case GOT_STATUS_MODIFY:
7497 err = got_object_open_as_blob(&blob_base, a->repo,
7498 blob_id, 8192);
7499 if (err)
7500 break;
7501 /* fall through */
7502 case GOT_STATUS_ADD:
7503 if (a->patch_cb) {
7504 if (staged_status == GOT_STATUS_ADD) {
7505 int choice = GOT_PATCH_CHOICE_NONE;
7506 err = (*a->patch_cb)(&choice, a->patch_arg,
7507 staged_status, ie->path, NULL, 1, 1);
7508 if (err)
7509 break;
7510 if (choice != GOT_PATCH_CHOICE_YES)
7511 break;
7512 } else {
7513 err = create_unstaged_content(
7514 &path_unstaged_content,
7515 &path_new_staged_content, blob_id,
7516 staged_blob_id, ie->path, a->repo,
7517 a->patch_cb, a->patch_arg);
7518 if (err || path_unstaged_content == NULL)
7519 break;
7520 if (path_new_staged_content) {
7521 err = got_object_blob_create(
7522 &staged_blob_id,
7523 path_new_staged_content,
7524 a->repo);
7525 if (err)
7526 break;
7527 memcpy(ie->staged_blob_sha1,
7528 staged_blob_id->sha1,
7529 SHA1_DIGEST_LENGTH);
7531 err = merge_file(&local_changes_subsumed,
7532 a->worktree, blob_base, ondisk_path,
7533 relpath, got_fileindex_perms_to_st(ie),
7534 path_unstaged_content, label_orig,
7535 "unstaged", a->repo, a->progress_cb,
7536 a->progress_arg);
7537 if (err == NULL &&
7538 path_new_staged_content == NULL)
7539 got_fileindex_entry_stage_set(ie,
7540 GOT_FILEIDX_STAGE_NONE);
7541 break; /* Done with this file. */
7544 err = got_object_open_as_blob(&blob_staged, a->repo,
7545 staged_blob_id, 8192);
7546 if (err)
7547 break;
7548 err = merge_blob(&local_changes_subsumed, a->worktree,
7549 blob_base, ondisk_path, relpath,
7550 got_fileindex_perms_to_st(ie), label_orig, blob_staged,
7551 commit_id ? commit_id : a->worktree->base_commit_id,
7552 a->repo, a->progress_cb, a->progress_arg);
7553 if (err == NULL)
7554 got_fileindex_entry_stage_set(ie,
7555 GOT_FILEIDX_STAGE_NONE);
7556 break;
7557 case GOT_STATUS_DELETE:
7558 if (a->patch_cb) {
7559 int choice = GOT_PATCH_CHOICE_NONE;
7560 err = (*a->patch_cb)(&choice, a->patch_arg,
7561 staged_status, ie->path, NULL, 1, 1);
7562 if (err)
7563 break;
7564 if (choice == GOT_PATCH_CHOICE_NO)
7565 break;
7566 if (choice != GOT_PATCH_CHOICE_YES) {
7567 err = got_error(GOT_ERR_PATCH_CHOICE);
7568 break;
7571 got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE);
7572 err = get_file_status(&status, &sb, ie, ondisk_path,
7573 dirfd, de_name, a->repo);
7574 if (err)
7575 break;
7576 err = (*a->progress_cb)(a->progress_arg, status, relpath);
7577 break;
7579 done:
7580 free(ondisk_path);
7581 if (path_unstaged_content &&
7582 unlink(path_unstaged_content) == -1 && err == NULL)
7583 err = got_error_from_errno2("unlink", path_unstaged_content);
7584 if (path_new_staged_content &&
7585 unlink(path_new_staged_content) == -1 && err == NULL)
7586 err = got_error_from_errno2("unlink", path_new_staged_content);
7587 free(path_unstaged_content);
7588 free(path_new_staged_content);
7589 if (blob_base)
7590 got_object_blob_close(blob_base);
7591 if (blob_staged)
7592 got_object_blob_close(blob_staged);
7593 free(id_str);
7594 free(label_orig);
7595 return err;
7598 const struct got_error *
7599 got_worktree_unstage(struct got_worktree *worktree,
7600 struct got_pathlist_head *paths,
7601 got_worktree_checkout_cb progress_cb, void *progress_arg,
7602 got_worktree_patch_cb patch_cb, void *patch_arg,
7603 struct got_repository *repo)
7605 const struct got_error *err = NULL, *sync_err, *unlockerr;
7606 struct got_pathlist_entry *pe;
7607 struct got_fileindex *fileindex = NULL;
7608 char *fileindex_path = NULL;
7609 struct unstage_path_arg upa;
7611 err = lock_worktree(worktree, LOCK_EX);
7612 if (err)
7613 return err;
7615 err = open_fileindex(&fileindex, &fileindex_path, worktree);
7616 if (err)
7617 goto done;
7619 upa.worktree = worktree;
7620 upa.fileindex = fileindex;
7621 upa.repo = repo;
7622 upa.progress_cb = progress_cb;
7623 upa.progress_arg = progress_arg;
7624 upa.patch_cb = patch_cb;
7625 upa.patch_arg = patch_arg;
7626 TAILQ_FOREACH(pe, paths, entry) {
7627 err = worktree_status(worktree, pe->path, fileindex, repo,
7628 unstage_path, &upa, NULL, NULL, 0, 0);
7629 if (err)
7630 goto done;
7633 sync_err = sync_fileindex(fileindex, fileindex_path);
7634 if (sync_err && err == NULL)
7635 err = sync_err;
7636 done:
7637 free(fileindex_path);
7638 if (fileindex)
7639 got_fileindex_free(fileindex);
7640 unlockerr = lock_worktree(worktree, LOCK_SH);
7641 if (unlockerr && err == NULL)
7642 err = unlockerr;
7643 return err;