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"
58 #include "got_lib_gotconfig.h"
60 #ifndef MIN
61 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
62 #endif
64 #define GOT_MERGE_LABEL_MERGED "merged change"
65 #define GOT_MERGE_LABEL_BASE "3-way merge base"
67 static const struct got_error *
68 create_meta_file(const char *path_got, const char *name, const char *content)
69 {
70 const struct got_error *err = NULL;
71 char *path;
73 if (asprintf(&path, "%s/%s", path_got, name) == -1)
74 return got_error_from_errno("asprintf");
76 err = got_path_create_file(path, content);
77 free(path);
78 return err;
79 }
81 static const struct got_error *
82 update_meta_file(const char *path_got, const char *name, const char *content)
83 {
84 const struct got_error *err = NULL;
85 FILE *tmpfile = NULL;
86 char *tmppath = NULL;
87 char *path = NULL;
89 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
90 err = got_error_from_errno("asprintf");
91 path = NULL;
92 goto done;
93 }
95 err = got_opentemp_named(&tmppath, &tmpfile, path);
96 if (err)
97 goto done;
99 if (content) {
100 int len = fprintf(tmpfile, "%s\n", content);
101 if (len != strlen(content) + 1) {
102 err = got_error_from_errno2("fprintf", tmppath);
103 goto done;
107 if (rename(tmppath, path) != 0) {
108 err = got_error_from_errno3("rename", tmppath, path);
109 unlink(tmppath);
110 goto done;
113 done:
114 if (fclose(tmpfile) == EOF && err == NULL)
115 err = got_error_from_errno2("fclose", tmppath);
116 free(tmppath);
117 return err;
120 static const struct got_error *
121 read_meta_file(char **content, const char *path_got, const char *name)
123 const struct got_error *err = NULL;
124 char *path;
125 int fd = -1;
126 ssize_t n;
127 struct stat sb;
129 *content = NULL;
131 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
132 err = got_error_from_errno("asprintf");
133 path = NULL;
134 goto done;
137 fd = open(path, O_RDONLY | O_NOFOLLOW);
138 if (fd == -1) {
139 if (errno == ENOENT)
140 err = got_error_path(path, GOT_ERR_WORKTREE_META);
141 else
142 err = got_error_from_errno2("open", path);
143 goto done;
145 if (flock(fd, LOCK_SH | LOCK_NB) == -1) {
146 err = (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
147 : got_error_from_errno2("flock", path));
148 goto done;
151 if (fstat(fd, &sb) != 0) {
152 err = got_error_from_errno2("fstat", path);
153 goto done;
155 *content = calloc(1, sb.st_size);
156 if (*content == NULL) {
157 err = got_error_from_errno("calloc");
158 goto done;
161 n = read(fd, *content, sb.st_size);
162 if (n != sb.st_size) {
163 err = (n == -1 ? got_error_from_errno2("read", path) :
164 got_error_path(path, GOT_ERR_WORKTREE_META));
165 goto done;
167 if ((*content)[sb.st_size - 1] != '\n') {
168 err = got_error_path(path, GOT_ERR_WORKTREE_META);
169 goto done;
171 (*content)[sb.st_size - 1] = '\0';
173 done:
174 if (fd != -1 && close(fd) == -1 && err == NULL)
175 err = got_error_from_errno2("close", path_got);
176 free(path);
177 if (err) {
178 free(*content);
179 *content = NULL;
181 return err;
184 static const struct got_error *
185 write_head_ref(const char *path_got, struct got_reference *head_ref)
187 const struct got_error *err = NULL;
188 char *refstr = NULL;
190 if (got_ref_is_symbolic(head_ref)) {
191 refstr = got_ref_to_str(head_ref);
192 if (refstr == NULL)
193 return got_error_from_errno("got_ref_to_str");
194 } else {
195 refstr = strdup(got_ref_get_name(head_ref));
196 if (refstr == NULL)
197 return got_error_from_errno("strdup");
199 err = update_meta_file(path_got, GOT_WORKTREE_HEAD_REF, refstr);
200 free(refstr);
201 return err;
204 const struct got_error *
205 got_worktree_init(const char *path, struct got_reference *head_ref,
206 const char *prefix, struct got_repository *repo)
208 const struct got_error *err = NULL;
209 struct got_object_id *commit_id = NULL;
210 uuid_t uuid;
211 uint32_t uuid_status;
212 int obj_type;
213 char *path_got = NULL;
214 char *formatstr = NULL;
215 char *absprefix = NULL;
216 char *basestr = NULL;
217 char *uuidstr = NULL;
219 if (strcmp(path, got_repo_get_path(repo)) == 0) {
220 err = got_error(GOT_ERR_WORKTREE_REPO);
221 goto done;
224 err = got_ref_resolve(&commit_id, repo, head_ref);
225 if (err)
226 return err;
227 err = got_object_get_type(&obj_type, repo, commit_id);
228 if (err)
229 return err;
230 if (obj_type != GOT_OBJ_TYPE_COMMIT)
231 return got_error(GOT_ERR_OBJ_TYPE);
233 if (!got_path_is_absolute(prefix)) {
234 if (asprintf(&absprefix, "/%s", prefix) == -1)
235 return got_error_from_errno("asprintf");
238 /* Create top-level directory (may already exist). */
239 if (mkdir(path, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
240 err = got_error_from_errno2("mkdir", path);
241 goto done;
244 /* Create .got directory (may already exist). */
245 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
246 err = got_error_from_errno("asprintf");
247 goto done;
249 if (mkdir(path_got, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
250 err = got_error_from_errno2("mkdir", path_got);
251 goto done;
254 /* Create an empty lock file. */
255 err = create_meta_file(path_got, GOT_WORKTREE_LOCK, NULL);
256 if (err)
257 goto done;
259 /* Create an empty file index. */
260 err = create_meta_file(path_got, GOT_WORKTREE_FILE_INDEX, NULL);
261 if (err)
262 goto done;
264 /* Write the HEAD reference. */
265 err = write_head_ref(path_got, head_ref);
266 if (err)
267 goto done;
269 /* Record our base commit. */
270 err = got_object_id_str(&basestr, commit_id);
271 if (err)
272 goto done;
273 err = create_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, basestr);
274 if (err)
275 goto done;
277 /* Store path to repository. */
278 err = create_meta_file(path_got, GOT_WORKTREE_REPOSITORY,
279 got_repo_get_path(repo));
280 if (err)
281 goto done;
283 /* Store in-repository path prefix. */
284 err = create_meta_file(path_got, GOT_WORKTREE_PATH_PREFIX,
285 absprefix ? absprefix : prefix);
286 if (err)
287 goto done;
289 /* Generate UUID. */
290 uuid_create(&uuid, &uuid_status);
291 if (uuid_status != uuid_s_ok) {
292 err = got_error_uuid(uuid_status, "uuid_create");
293 goto done;
295 uuid_to_string(&uuid, &uuidstr, &uuid_status);
296 if (uuid_status != uuid_s_ok) {
297 err = got_error_uuid(uuid_status, "uuid_to_string");
298 goto done;
300 err = create_meta_file(path_got, GOT_WORKTREE_UUID, uuidstr);
301 if (err)
302 goto done;
304 /* Stamp work tree with format file. */
305 if (asprintf(&formatstr, "%d", GOT_WORKTREE_FORMAT_VERSION) == -1) {
306 err = got_error_from_errno("asprintf");
307 goto done;
309 err = create_meta_file(path_got, GOT_WORKTREE_FORMAT, formatstr);
310 if (err)
311 goto done;
313 done:
314 free(commit_id);
315 free(path_got);
316 free(formatstr);
317 free(absprefix);
318 free(basestr);
319 free(uuidstr);
320 return err;
323 static const struct got_error *
324 open_worktree(struct got_worktree **worktree, const char *path)
326 const struct got_error *err = NULL;
327 char *path_got;
328 char *formatstr = NULL;
329 char *uuidstr = NULL;
330 char *path_lock = NULL;
331 char *base_commit_id_str = NULL;
332 int version, fd = -1;
333 const char *errstr;
334 struct got_repository *repo = NULL;
335 uint32_t uuid_status;
337 *worktree = NULL;
339 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
340 err = got_error_from_errno("asprintf");
341 path_got = NULL;
342 goto done;
345 if (asprintf(&path_lock, "%s/%s", path_got, GOT_WORKTREE_LOCK) == -1) {
346 err = got_error_from_errno("asprintf");
347 path_lock = NULL;
348 goto done;
351 fd = open(path_lock, O_RDWR | O_EXLOCK | O_NONBLOCK);
352 if (fd == -1) {
353 err = (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
354 : got_error_from_errno2("open", path_lock));
355 goto done;
358 err = read_meta_file(&formatstr, path_got, GOT_WORKTREE_FORMAT);
359 if (err)
360 goto done;
362 version = strtonum(formatstr, 1, INT_MAX, &errstr);
363 if (errstr) {
364 err = got_error_msg(GOT_ERR_WORKTREE_META,
365 "could not parse work tree format version number");
366 goto done;
368 if (version != GOT_WORKTREE_FORMAT_VERSION) {
369 err = got_error(GOT_ERR_WORKTREE_VERS);
370 goto done;
373 *worktree = calloc(1, sizeof(**worktree));
374 if (*worktree == NULL) {
375 err = got_error_from_errno("calloc");
376 goto done;
378 (*worktree)->lockfd = -1;
380 (*worktree)->root_path = realpath(path, NULL);
381 if ((*worktree)->root_path == NULL) {
382 err = got_error_from_errno2("realpath", path);
383 goto done;
385 err = read_meta_file(&(*worktree)->repo_path, path_got,
386 GOT_WORKTREE_REPOSITORY);
387 if (err)
388 goto done;
390 err = read_meta_file(&(*worktree)->path_prefix, path_got,
391 GOT_WORKTREE_PATH_PREFIX);
392 if (err)
393 goto done;
395 err = read_meta_file(&base_commit_id_str, path_got,
396 GOT_WORKTREE_BASE_COMMIT);
397 if (err)
398 goto done;
400 err = read_meta_file(&uuidstr, path_got, GOT_WORKTREE_UUID);
401 if (err)
402 goto done;
403 uuid_from_string(uuidstr, &(*worktree)->uuid, &uuid_status);
404 if (uuid_status != uuid_s_ok) {
405 err = got_error_uuid(uuid_status, "uuid_from_string");
406 goto done;
409 err = got_repo_open(&repo, (*worktree)->repo_path, NULL);
410 if (err)
411 goto done;
413 err = got_object_resolve_id_str(&(*worktree)->base_commit_id, repo,
414 base_commit_id_str);
415 if (err)
416 goto done;
418 err = read_meta_file(&(*worktree)->head_ref_name, path_got,
419 GOT_WORKTREE_HEAD_REF);
420 if (err)
421 goto done;
423 if (asprintf(&(*worktree)->gotconfig_path, "%s/%s/%s",
424 (*worktree)->root_path,
425 GOT_WORKTREE_GOT_DIR, GOT_GOTCONFIG_FILENAME) == -1) {
426 err = got_error_from_errno("asprintf");
427 goto done;
430 err = got_gotconfig_read(&(*worktree)->gotconfig,
431 (*worktree)->gotconfig_path);
433 (*worktree)->root_fd = open((*worktree)->root_path, O_DIRECTORY);
434 if ((*worktree)->root_fd == -1) {
435 err = got_error_from_errno2("open", (*worktree)->root_path);
436 goto done;
438 done:
439 if (repo)
440 got_repo_close(repo);
441 free(path_got);
442 free(path_lock);
443 free(base_commit_id_str);
444 free(uuidstr);
445 free(formatstr);
446 if (err) {
447 if (fd != -1)
448 close(fd);
449 if (*worktree != NULL)
450 got_worktree_close(*worktree);
451 *worktree = NULL;
452 } else
453 (*worktree)->lockfd = fd;
455 return err;
458 const struct got_error *
459 got_worktree_open(struct got_worktree **worktree, const char *path)
461 const struct got_error *err = NULL;
462 char *worktree_path;
464 worktree_path = strdup(path);
465 if (worktree_path == NULL)
466 return got_error_from_errno("strdup");
468 for (;;) {
469 char *parent_path;
471 err = open_worktree(worktree, worktree_path);
472 if (err && !(err->code == GOT_ERR_ERRNO && errno == ENOENT)) {
473 free(worktree_path);
474 return err;
476 if (*worktree) {
477 free(worktree_path);
478 return NULL;
480 if (worktree_path[0] == '/' && worktree_path[1] == '\0')
481 break;
482 err = got_path_dirname(&parent_path, worktree_path);
483 if (err) {
484 if (err->code != GOT_ERR_BAD_PATH) {
485 free(worktree_path);
486 return err;
488 break;
490 free(worktree_path);
491 worktree_path = parent_path;
494 free(worktree_path);
495 return got_error(GOT_ERR_NOT_WORKTREE);
498 const struct got_error *
499 got_worktree_close(struct got_worktree *worktree)
501 const struct got_error *err = NULL;
503 if (worktree->lockfd != -1) {
504 if (close(worktree->lockfd) == -1)
505 err = got_error_from_errno2("close",
506 got_worktree_get_root_path(worktree));
508 if (close(worktree->root_fd) == -1 && err == NULL)
509 err = got_error_from_errno2("close",
510 got_worktree_get_root_path(worktree));
511 free(worktree->repo_path);
512 free(worktree->path_prefix);
513 free(worktree->base_commit_id);
514 free(worktree->head_ref_name);
515 free(worktree->root_path);
516 free(worktree->gotconfig_path);
517 got_gotconfig_free(worktree->gotconfig);
518 free(worktree);
519 return err;
522 const char *
523 got_worktree_get_root_path(struct got_worktree *worktree)
525 return worktree->root_path;
528 const char *
529 got_worktree_get_repo_path(struct got_worktree *worktree)
531 return worktree->repo_path;
533 const char *
534 got_worktree_get_path_prefix(struct got_worktree *worktree)
536 return worktree->path_prefix;
539 const struct got_error *
540 got_worktree_match_path_prefix(int *match, struct got_worktree *worktree,
541 const char *path_prefix)
543 char *absprefix = NULL;
545 if (!got_path_is_absolute(path_prefix)) {
546 if (asprintf(&absprefix, "/%s", path_prefix) == -1)
547 return got_error_from_errno("asprintf");
549 *match = (strcmp(absprefix ? absprefix : path_prefix,
550 worktree->path_prefix) == 0);
551 free(absprefix);
552 return NULL;
555 const char *
556 got_worktree_get_head_ref_name(struct got_worktree *worktree)
558 return worktree->head_ref_name;
561 const struct got_error *
562 got_worktree_set_head_ref(struct got_worktree *worktree,
563 struct got_reference *head_ref)
565 const struct got_error *err = NULL;
566 char *path_got = NULL, *head_ref_name = NULL;
568 if (asprintf(&path_got, "%s/%s", worktree->root_path,
569 GOT_WORKTREE_GOT_DIR) == -1) {
570 err = got_error_from_errno("asprintf");
571 path_got = NULL;
572 goto done;
575 head_ref_name = strdup(got_ref_get_name(head_ref));
576 if (head_ref_name == NULL) {
577 err = got_error_from_errno("strdup");
578 goto done;
581 err = write_head_ref(path_got, head_ref);
582 if (err)
583 goto done;
585 free(worktree->head_ref_name);
586 worktree->head_ref_name = head_ref_name;
587 done:
588 free(path_got);
589 if (err)
590 free(head_ref_name);
591 return err;
594 struct got_object_id *
595 got_worktree_get_base_commit_id(struct got_worktree *worktree)
597 return worktree->base_commit_id;
600 const struct got_error *
601 got_worktree_set_base_commit_id(struct got_worktree *worktree,
602 struct got_repository *repo, struct got_object_id *commit_id)
604 const struct got_error *err;
605 struct got_object *obj = NULL;
606 char *id_str = NULL;
607 char *path_got = NULL;
609 if (asprintf(&path_got, "%s/%s", worktree->root_path,
610 GOT_WORKTREE_GOT_DIR) == -1) {
611 err = got_error_from_errno("asprintf");
612 path_got = NULL;
613 goto done;
616 err = got_object_open(&obj, repo, commit_id);
617 if (err)
618 return err;
620 if (obj->type != GOT_OBJ_TYPE_COMMIT) {
621 err = got_error(GOT_ERR_OBJ_TYPE);
622 goto done;
625 /* Record our base commit. */
626 err = got_object_id_str(&id_str, commit_id);
627 if (err)
628 goto done;
629 err = update_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, id_str);
630 if (err)
631 goto done;
633 free(worktree->base_commit_id);
634 worktree->base_commit_id = got_object_id_dup(commit_id);
635 if (worktree->base_commit_id == NULL) {
636 err = got_error_from_errno("got_object_id_dup");
637 goto done;
639 done:
640 if (obj)
641 got_object_close(obj);
642 free(id_str);
643 free(path_got);
644 return err;
647 const struct got_gotconfig *
648 got_worktree_get_gotconfig(struct got_worktree *worktree)
650 return worktree->gotconfig;
653 static const struct got_error *
654 lock_worktree(struct got_worktree *worktree, int operation)
656 if (flock(worktree->lockfd, operation | LOCK_NB) == -1)
657 return (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
658 : got_error_from_errno2("flock",
659 got_worktree_get_root_path(worktree)));
660 return NULL;
663 static const struct got_error *
664 add_dir_on_disk(struct got_worktree *worktree, const char *path)
666 const struct got_error *err = NULL;
667 char *abspath;
669 if (asprintf(&abspath, "%s/%s", worktree->root_path, path) == -1)
670 return got_error_from_errno("asprintf");
672 err = got_path_mkdir(abspath);
673 if (err && err->code == GOT_ERR_ERRNO && errno == EEXIST) {
674 struct stat sb;
675 err = NULL;
676 if (lstat(abspath, &sb) == -1) {
677 err = got_error_from_errno2("lstat", abspath);
678 } else if (!S_ISDIR(sb.st_mode)) {
679 /* TODO directory is obstructed; do something */
680 err = got_error_path(abspath, GOT_ERR_FILE_OBSTRUCTED);
683 free(abspath);
684 return err;
687 static const struct got_error *
688 check_file_contents_equal(int *same, FILE *f1, FILE *f2)
690 const struct got_error *err = NULL;
691 uint8_t fbuf1[8192];
692 uint8_t fbuf2[8192];
693 size_t flen1 = 0, flen2 = 0;
695 *same = 1;
697 for (;;) {
698 flen1 = fread(fbuf1, 1, sizeof(fbuf1), f1);
699 if (flen1 == 0 && ferror(f1)) {
700 err = got_error_from_errno("fread");
701 break;
703 flen2 = fread(fbuf2, 1, sizeof(fbuf2), f2);
704 if (flen2 == 0 && ferror(f2)) {
705 err = got_error_from_errno("fread");
706 break;
708 if (flen1 == 0) {
709 if (flen2 != 0)
710 *same = 0;
711 break;
712 } else if (flen2 == 0) {
713 if (flen1 != 0)
714 *same = 0;
715 break;
716 } else if (flen1 == flen2) {
717 if (memcmp(fbuf1, fbuf2, flen2) != 0) {
718 *same = 0;
719 break;
721 } else {
722 *same = 0;
723 break;
727 return err;
730 static const struct got_error *
731 check_files_equal(int *same, FILE *f1, FILE *f2)
733 struct stat sb;
734 size_t size1, size2;
736 *same = 1;
738 if (fstat(fileno(f1), &sb) != 0)
739 return got_error_from_errno("fstat");
740 size1 = sb.st_size;
742 if (fstat(fileno(f2), &sb) != 0)
743 return got_error_from_errno("fstat");
744 size2 = sb.st_size;
746 if (size1 != size2) {
747 *same = 0;
748 return NULL;
751 if (fseek(f1, 0L, SEEK_SET) == -1)
752 return got_ferror(f1, GOT_ERR_IO);
753 if (fseek(f2, 0L, SEEK_SET) == -1)
754 return got_ferror(f2, GOT_ERR_IO);
756 return check_file_contents_equal(same, f1, f2);
759 /*
760 * Perform a 3-way merge where the file f_orig acts as the common
761 * ancestor, the file f_deriv acts as the first derived version,
762 * and the file f_deriv2 acts as the second derived version.
763 * The merge result will be written to a new file at ondisk_path; any
764 * existing file at this path will be replaced.
765 */
766 static const struct got_error *
767 merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
768 FILE *f_orig, FILE *f_deriv, FILE *f_deriv2, const char *ondisk_path,
769 const char *path, uint16_t st_mode,
770 const char *label_orig, const char *label_deriv, const char *label_deriv2,
771 struct got_repository *repo,
772 got_worktree_checkout_cb progress_cb, void *progress_arg)
774 const struct got_error *err = NULL;
775 int merged_fd = -1;
776 FILE *f_merged = NULL;
777 char *merged_path = NULL, *base_path = NULL;
778 int overlapcnt = 0;
779 char *parent = NULL;
781 *local_changes_subsumed = 0;
783 err = got_path_dirname(&parent, ondisk_path);
784 if (err)
785 return err;
787 if (asprintf(&base_path, "%s/got-merged", parent) == -1) {
788 err = got_error_from_errno("asprintf");
789 goto done;
792 err = got_opentemp_named_fd(&merged_path, &merged_fd, base_path);
793 if (err)
794 goto done;
796 err = got_merge_diff3(&overlapcnt, merged_fd, f_deriv, f_orig,
797 f_deriv2, label_deriv, label_orig, label_deriv2);
798 if (err)
799 goto done;
801 err = (*progress_cb)(progress_arg,
802 overlapcnt > 0 ? GOT_STATUS_CONFLICT : GOT_STATUS_MERGE, path);
803 if (err)
804 goto done;
806 if (fsync(merged_fd) != 0) {
807 err = got_error_from_errno("fsync");
808 goto done;
811 f_merged = fdopen(merged_fd, "r");
812 if (f_merged == NULL) {
813 err = got_error_from_errno("fdopen");
814 goto done;
816 merged_fd = -1;
818 /* Check if a clean merge has subsumed all local changes. */
819 if (overlapcnt == 0) {
820 err = check_files_equal(local_changes_subsumed, f_deriv,
821 f_merged);
822 if (err)
823 goto done;
826 if (fchmod(fileno(f_merged), st_mode) != 0) {
827 err = got_error_from_errno2("fchmod", merged_path);
828 goto done;
831 if (rename(merged_path, ondisk_path) != 0) {
832 err = got_error_from_errno3("rename", merged_path,
833 ondisk_path);
834 goto done;
836 done:
837 if (err) {
838 if (merged_path)
839 unlink(merged_path);
841 if (merged_fd != -1 && close(merged_fd) == -1 && err == NULL)
842 err = got_error_from_errno("close");
843 if (f_merged && fclose(f_merged) == EOF && err == NULL)
844 err = got_error_from_errno("fclose");
845 free(merged_path);
846 free(base_path);
847 free(parent);
848 return err;
851 static const struct got_error *
852 update_symlink(const char *ondisk_path, const char *target_path,
853 size_t target_len)
855 /* This is not atomic but matches what 'ln -sf' does. */
856 if (unlink(ondisk_path) == -1)
857 return got_error_from_errno2("unlink", ondisk_path);
858 if (symlink(target_path, ondisk_path) == -1)
859 return got_error_from_errno3("symlink", target_path,
860 ondisk_path);
861 return NULL;
864 /*
865 * Overwrite a symlink (or a regular file in case there was a "bad" symlink)
866 * in the work tree with a file that contains conflict markers and the
867 * conflicting target paths of the original version, a "derived version"
868 * of a symlink from an incoming change, and a local version of the symlink.
870 * The original versions's target path can be NULL if it is not available,
871 * such as if both derived versions added a new symlink at the same path.
873 * The incoming derived symlink target is NULL in case the incoming change
874 * has deleted this symlink.
875 */
876 static const struct got_error *
877 install_symlink_conflict(const char *deriv_target,
878 struct got_object_id *deriv_base_commit_id, const char *orig_target,
879 const char *label_orig, const char *local_target, const char *ondisk_path)
881 const struct got_error *err;
882 char *id_str = NULL, *label_deriv = NULL, *path = NULL;
883 FILE *f = NULL;
885 err = got_object_id_str(&id_str, deriv_base_commit_id);
886 if (err)
887 return got_error_from_errno("asprintf");
889 if (asprintf(&label_deriv, "%s: commit %s",
890 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
891 err = got_error_from_errno("asprintf");
892 goto done;
895 err = got_opentemp_named(&path, &f, "got-symlink-conflict");
896 if (err)
897 goto done;
899 if (fchmod(fileno(f), GOT_DEFAULT_FILE_MODE) == -1) {
900 err = got_error_from_errno2("fchmod", path);
901 goto done;
904 if (fprintf(f, "%s %s\n%s\n%s%s%s%s%s\n%s\n%s\n",
905 GOT_DIFF_CONFLICT_MARKER_BEGIN, label_deriv,
906 deriv_target ? deriv_target : "(symlink was deleted)",
907 orig_target ? label_orig : "",
908 orig_target ? "\n" : "",
909 orig_target ? orig_target : "",
910 orig_target ? "\n" : "",
911 GOT_DIFF_CONFLICT_MARKER_SEP,
912 local_target, GOT_DIFF_CONFLICT_MARKER_END) < 0) {
913 err = got_error_from_errno2("fprintf", path);
914 goto done;
917 if (unlink(ondisk_path) == -1) {
918 err = got_error_from_errno2("unlink", ondisk_path);
919 goto done;
921 if (rename(path, ondisk_path) == -1) {
922 err = got_error_from_errno3("rename", path, ondisk_path);
923 goto done;
925 done:
926 if (f != NULL && fclose(f) == EOF && err == NULL)
927 err = got_error_from_errno2("fclose", path);
928 free(path);
929 free(id_str);
930 free(label_deriv);
931 return err;
934 /* forward declaration */
935 static const struct got_error *
936 merge_blob(int *, struct got_worktree *, struct got_blob_object *,
937 const char *, const char *, uint16_t, const char *,
938 struct got_blob_object *, struct got_object_id *,
939 struct got_repository *, got_worktree_checkout_cb, void *);
941 /*
942 * Merge a symlink into the work tree, where blob_orig acts as the common
943 * ancestor, deriv_target is the link target of the first derived version,
944 * and the symlink on disk acts as the second derived version.
945 * Assume that contents of both blobs represent symlinks.
946 */
947 static const struct got_error *
948 merge_symlink(struct got_worktree *worktree,
949 struct got_blob_object *blob_orig, const char *ondisk_path,
950 const char *path, const char *label_orig, const char *deriv_target,
951 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
952 got_worktree_checkout_cb progress_cb, void *progress_arg)
954 const struct got_error *err = NULL;
955 char *ancestor_target = NULL;
956 struct stat sb;
957 ssize_t ondisk_len, deriv_len;
958 char ondisk_target[PATH_MAX];
959 int have_local_change = 0;
960 int have_incoming_change = 0;
962 if (lstat(ondisk_path, &sb) == -1)
963 return got_error_from_errno2("lstat", ondisk_path);
965 ondisk_len = readlink(ondisk_path, ondisk_target,
966 sizeof(ondisk_target));
967 if (ondisk_len == -1) {
968 err = got_error_from_errno2("readlink",
969 ondisk_path);
970 goto done;
972 ondisk_target[ondisk_len] = '\0';
974 if (blob_orig) {
975 err = got_object_blob_read_to_str(&ancestor_target, blob_orig);
976 if (err)
977 goto done;
980 if (ancestor_target == NULL ||
981 (ondisk_len != strlen(ancestor_target) ||
982 memcmp(ondisk_target, ancestor_target, ondisk_len) != 0))
983 have_local_change = 1;
985 deriv_len = strlen(deriv_target);
986 if (ancestor_target == NULL ||
987 (deriv_len != strlen(ancestor_target) ||
988 memcmp(deriv_target, ancestor_target, deriv_len) != 0))
989 have_incoming_change = 1;
991 if (!have_local_change && !have_incoming_change) {
992 if (ancestor_target) {
993 /* Both sides made the same change. */
994 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
995 path);
996 } else if (deriv_len == ondisk_len &&
997 memcmp(ondisk_target, deriv_target, deriv_len) == 0) {
998 /* Both sides added the same symlink. */
999 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
1000 path);
1001 } else {
1002 /* Both sides added symlinks which don't match. */
1003 err = install_symlink_conflict(deriv_target,
1004 deriv_base_commit_id, ancestor_target,
1005 label_orig, ondisk_target, ondisk_path);
1006 if (err)
1007 goto done;
1008 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
1009 path);
1011 } else if (!have_local_change && have_incoming_change) {
1012 /* Apply the incoming change. */
1013 err = update_symlink(ondisk_path, deriv_target,
1014 strlen(deriv_target));
1015 if (err)
1016 goto done;
1017 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
1018 } else if (have_local_change && have_incoming_change) {
1019 if (deriv_len == ondisk_len &&
1020 memcmp(deriv_target, ondisk_target, deriv_len) == 0) {
1021 /* Both sides made the same change. */
1022 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
1023 path);
1024 } else {
1025 err = install_symlink_conflict(deriv_target,
1026 deriv_base_commit_id, ancestor_target, label_orig,
1027 ondisk_target, ondisk_path);
1028 if (err)
1029 goto done;
1030 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
1031 path);
1035 done:
1036 free(ancestor_target);
1037 return err;
1040 static const struct got_error *
1041 dump_symlink_target_path_to_file(FILE **outfile, const char *ondisk_path)
1043 const struct got_error *err = NULL;
1044 char target_path[PATH_MAX];
1045 ssize_t target_len;
1046 size_t n;
1047 FILE *f;
1049 *outfile = NULL;
1051 f = got_opentemp();
1052 if (f == NULL)
1053 return got_error_from_errno("got_opentemp");
1054 target_len = readlink(ondisk_path, target_path, sizeof(target_path));
1055 if (target_len == -1) {
1056 err = got_error_from_errno2("readlink", ondisk_path);
1057 goto done;
1059 n = fwrite(target_path, 1, target_len, f);
1060 if (n != target_len) {
1061 err = got_ferror(f, GOT_ERR_IO);
1062 goto done;
1064 if (fflush(f) == EOF) {
1065 err = got_error_from_errno("fflush");
1066 goto done;
1068 if (fseek(f, 0L, SEEK_SET) == -1) {
1069 err = got_ferror(f, GOT_ERR_IO);
1070 goto done;
1072 done:
1073 if (err)
1074 fclose(f);
1075 else
1076 *outfile = f;
1077 return err;
1081 * Perform a 3-way merge where blob_orig acts as the common ancestor,
1082 * blob_deriv acts as the first derived version, and the file on disk
1083 * acts as the second derived version.
1085 static const struct got_error *
1086 merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
1087 struct got_blob_object *blob_orig, const char *ondisk_path,
1088 const char *path, uint16_t st_mode, const char *label_orig,
1089 struct got_blob_object *blob_deriv,
1090 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
1091 got_worktree_checkout_cb progress_cb, void *progress_arg)
1093 const struct got_error *err = NULL;
1094 FILE *f_orig = NULL, *f_deriv = NULL, *f_deriv2 = NULL;
1095 char *blob_orig_path = NULL;
1096 char *blob_deriv_path = NULL, *base_path = NULL, *id_str = NULL;
1097 char *label_deriv = NULL, *parent = NULL;
1099 *local_changes_subsumed = 0;
1101 err = got_path_dirname(&parent, ondisk_path);
1102 if (err)
1103 return err;
1105 if (blob_orig) {
1106 if (asprintf(&base_path, "%s/got-merge-blob-orig",
1107 parent) == -1) {
1108 err = got_error_from_errno("asprintf");
1109 base_path = NULL;
1110 goto done;
1113 err = got_opentemp_named(&blob_orig_path, &f_orig, base_path);
1114 if (err)
1115 goto done;
1116 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_orig,
1117 blob_orig);
1118 if (err)
1119 goto done;
1120 free(base_path);
1121 } else {
1123 * No common ancestor exists. This is an "add vs add" conflict
1124 * and we simply use an empty ancestor file to make both files
1125 * appear in the merged result in their entirety.
1127 f_orig = got_opentemp();
1128 if (f_orig == NULL) {
1129 err = got_error_from_errno("got_opentemp");
1130 goto done;
1134 if (asprintf(&base_path, "%s/got-merge-blob-deriv", parent) == -1) {
1135 err = got_error_from_errno("asprintf");
1136 base_path = NULL;
1137 goto done;
1140 err = got_opentemp_named(&blob_deriv_path, &f_deriv, base_path);
1141 if (err)
1142 goto done;
1143 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_deriv,
1144 blob_deriv);
1145 if (err)
1146 goto done;
1148 err = got_object_id_str(&id_str, deriv_base_commit_id);
1149 if (err)
1150 goto done;
1151 if (asprintf(&label_deriv, "%s: commit %s",
1152 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
1153 err = got_error_from_errno("asprintf");
1154 goto done;
1158 * In order the run a 3-way merge with a symlink we copy the symlink's
1159 * target path into a temporary file and use that file with diff3.
1161 if (S_ISLNK(st_mode)) {
1162 err = dump_symlink_target_path_to_file(&f_deriv2, ondisk_path);
1163 if (err)
1164 goto done;
1165 } else {
1166 int fd;
1167 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW);
1168 if (fd == -1) {
1169 err = got_error_from_errno2("open", ondisk_path);
1170 goto done;
1172 f_deriv2 = fdopen(fd, "r");
1173 if (f_deriv2 == NULL) {
1174 err = got_error_from_errno2("fdopen", ondisk_path);
1175 close(fd);
1176 goto done;
1180 err = merge_file(local_changes_subsumed, worktree, f_orig, f_deriv,
1181 f_deriv2, ondisk_path, path, st_mode, label_orig, label_deriv,
1182 NULL, repo, progress_cb, progress_arg);
1183 done:
1184 if (f_orig && fclose(f_orig) == EOF && err == NULL)
1185 err = got_error_from_errno("fclose");
1186 if (f_deriv && fclose(f_deriv) == EOF && err == NULL)
1187 err = got_error_from_errno("fclose");
1188 if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
1189 err = got_error_from_errno("fclose");
1190 free(base_path);
1191 if (blob_orig_path) {
1192 unlink(blob_orig_path);
1193 free(blob_orig_path);
1195 if (blob_deriv_path) {
1196 unlink(blob_deriv_path);
1197 free(blob_deriv_path);
1199 free(id_str);
1200 free(label_deriv);
1201 free(parent);
1202 return err;
1205 static const struct got_error *
1206 create_fileindex_entry(struct got_fileindex_entry **new_iep,
1207 struct got_fileindex *fileindex, struct got_object_id *base_commit_id,
1208 int wt_fd, const char *path, struct got_object_id *blob_id)
1210 const struct got_error *err = NULL;
1211 struct got_fileindex_entry *new_ie;
1213 *new_iep = NULL;
1215 err = got_fileindex_entry_alloc(&new_ie, path);
1216 if (err)
1217 return err;
1219 err = got_fileindex_entry_update(new_ie, wt_fd, path,
1220 blob_id->sha1, base_commit_id->sha1, 1);
1221 if (err)
1222 goto done;
1224 err = got_fileindex_entry_add(fileindex, new_ie);
1225 done:
1226 if (err)
1227 got_fileindex_entry_free(new_ie);
1228 else
1229 *new_iep = new_ie;
1230 return err;
1233 static mode_t
1234 get_ondisk_perms(int executable, mode_t st_mode)
1236 mode_t xbits = S_IXUSR;
1238 if (executable) {
1239 /* Map read bits to execute bits. */
1240 if (st_mode & S_IRGRP)
1241 xbits |= S_IXGRP;
1242 if (st_mode & S_IROTH)
1243 xbits |= S_IXOTH;
1244 return st_mode | xbits;
1247 return (st_mode & ~(S_IXUSR | S_IXGRP | S_IXOTH));
1250 /* forward declaration */
1251 static const struct got_error *
1252 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1253 const char *path, mode_t te_mode, mode_t st_mode,
1254 struct got_blob_object *blob, int restoring_missing_file,
1255 int reverting_versioned_file, int installing_bad_symlink,
1256 int path_is_unversioned, struct got_repository *repo,
1257 got_worktree_checkout_cb progress_cb, void *progress_arg);
1260 * This function assumes that the provided symlink target points at a
1261 * safe location in the work tree!
1263 static const struct got_error *
1264 replace_existing_symlink(int *did_something, const char *ondisk_path,
1265 const char *target_path, size_t target_len)
1267 const struct got_error *err = NULL;
1268 ssize_t elen;
1269 char etarget[PATH_MAX];
1270 int fd;
1272 *did_something = 0;
1275 * "Bad" symlinks (those pointing outside the work tree or into the
1276 * .got directory) are installed in the work tree as a regular file
1277 * which contains the bad symlink target path.
1278 * The new symlink target has already been checked for safety by our
1279 * caller. If we can successfully open a regular file then we simply
1280 * replace this file with a symlink below.
1282 fd = open(ondisk_path, O_RDWR | O_EXCL | O_NOFOLLOW);
1283 if (fd == -1) {
1284 if (errno != ELOOP)
1285 return got_error_from_errno2("open", ondisk_path);
1287 /* We are updating an existing on-disk symlink. */
1288 elen = readlink(ondisk_path, etarget, sizeof(etarget));
1289 if (elen == -1)
1290 return got_error_from_errno2("readlink", ondisk_path);
1292 if (elen == target_len &&
1293 memcmp(etarget, target_path, target_len) == 0)
1294 return NULL; /* nothing to do */
1297 *did_something = 1;
1298 err = update_symlink(ondisk_path, target_path, target_len);
1299 if (fd != -1 && close(fd) == -1 && err == NULL)
1300 err = got_error_from_errno2("close", ondisk_path);
1301 return err;
1304 static const struct got_error *
1305 is_bad_symlink_target(int *is_bad_symlink, const char *target_path,
1306 size_t target_len, const char *ondisk_path, const char *wtroot_path)
1308 const struct got_error *err = NULL;
1309 char canonpath[PATH_MAX];
1310 char *path_got = NULL;
1312 *is_bad_symlink = 0;
1314 if (target_len >= sizeof(canonpath)) {
1315 *is_bad_symlink = 1;
1316 return NULL;
1320 * We do not use realpath(3) to resolve the symlink's target
1321 * path because we don't want to resolve symlinks recursively.
1322 * Instead we make the path absolute and then canonicalize it.
1323 * Relative symlink target lookup should begin at the directory
1324 * in which the blob object is being installed.
1326 if (!got_path_is_absolute(target_path)) {
1327 char *abspath, *parent;
1328 err = got_path_dirname(&parent, ondisk_path);
1329 if (err)
1330 return err;
1331 if (asprintf(&abspath, "%s/%s", parent, target_path) == -1) {
1332 free(parent);
1333 return got_error_from_errno("asprintf");
1335 free(parent);
1336 if (strlen(abspath) >= sizeof(canonpath)) {
1337 err = got_error_path(abspath, GOT_ERR_BAD_PATH);
1338 free(abspath);
1339 return err;
1341 err = got_canonpath(abspath, canonpath, sizeof(canonpath));
1342 free(abspath);
1343 if (err)
1344 return err;
1345 } else {
1346 err = got_canonpath(target_path, canonpath, sizeof(canonpath));
1347 if (err)
1348 return err;
1351 /* Only allow symlinks pointing at paths within the work tree. */
1352 if (!got_path_is_child(canonpath, wtroot_path, strlen(wtroot_path))) {
1353 *is_bad_symlink = 1;
1354 return NULL;
1357 /* Do not allow symlinks pointing into the .got directory. */
1358 if (asprintf(&path_got, "%s/%s", wtroot_path,
1359 GOT_WORKTREE_GOT_DIR) == -1)
1360 return got_error_from_errno("asprintf");
1361 if (got_path_is_child(canonpath, path_got, strlen(path_got)))
1362 *is_bad_symlink = 1;
1364 free(path_got);
1365 return NULL;
1368 static const struct got_error *
1369 install_symlink(int *is_bad_symlink, struct got_worktree *worktree,
1370 const char *ondisk_path, const char *path, struct got_blob_object *blob,
1371 int restoring_missing_file, int reverting_versioned_file,
1372 int path_is_unversioned, struct got_repository *repo,
1373 got_worktree_checkout_cb progress_cb, void *progress_arg)
1375 const struct got_error *err = NULL;
1376 char target_path[PATH_MAX];
1377 size_t len, target_len = 0;
1378 char *path_got = NULL;
1379 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1380 size_t hdrlen = got_object_blob_get_hdrlen(blob);
1382 *is_bad_symlink = 0;
1385 * Blob object content specifies the target path of the link.
1386 * If a symbolic link cannot be installed we instead create
1387 * a regular file which contains the link target path stored
1388 * in the blob object.
1390 do {
1391 err = got_object_blob_read_block(&len, blob);
1392 if (len + target_len >= sizeof(target_path)) {
1393 /* Path too long; install as a regular file. */
1394 *is_bad_symlink = 1;
1395 got_object_blob_rewind(blob);
1396 return install_blob(worktree, ondisk_path, path,
1397 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1398 restoring_missing_file, reverting_versioned_file,
1399 1, path_is_unversioned, repo, progress_cb,
1400 progress_arg);
1402 if (len > 0) {
1403 /* Skip blob object header first time around. */
1404 memcpy(target_path + target_len, buf + hdrlen,
1405 len - hdrlen);
1406 target_len += len - hdrlen;
1407 hdrlen = 0;
1409 } while (len != 0);
1410 target_path[target_len] = '\0';
1412 err = is_bad_symlink_target(is_bad_symlink, target_path, target_len,
1413 ondisk_path, worktree->root_path);
1414 if (err)
1415 return err;
1417 if (*is_bad_symlink) {
1418 /* install as a regular file */
1419 got_object_blob_rewind(blob);
1420 err = install_blob(worktree, ondisk_path, path,
1421 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1422 restoring_missing_file, reverting_versioned_file, 1,
1423 path_is_unversioned, repo, progress_cb, progress_arg);
1424 goto done;
1427 if (symlink(target_path, ondisk_path) == -1) {
1428 if (errno == EEXIST) {
1429 int symlink_replaced;
1430 if (path_is_unversioned) {
1431 err = (*progress_cb)(progress_arg,
1432 GOT_STATUS_UNVERSIONED, path);
1433 goto done;
1435 err = replace_existing_symlink(&symlink_replaced,
1436 ondisk_path, target_path, target_len);
1437 if (err)
1438 goto done;
1439 if (progress_cb) {
1440 if (symlink_replaced) {
1441 err = (*progress_cb)(progress_arg,
1442 reverting_versioned_file ?
1443 GOT_STATUS_REVERT :
1444 GOT_STATUS_UPDATE, path);
1445 } else {
1446 err = (*progress_cb)(progress_arg,
1447 GOT_STATUS_EXISTS, path);
1450 goto done; /* Nothing else to do. */
1453 if (errno == ENOENT) {
1454 char *parent;
1455 err = got_path_dirname(&parent, ondisk_path);
1456 if (err)
1457 goto done;
1458 err = add_dir_on_disk(worktree, parent);
1459 free(parent);
1460 if (err)
1461 goto done;
1463 * Retry, and fall through to error handling
1464 * below if this second attempt fails.
1466 if (symlink(target_path, ondisk_path) != -1) {
1467 err = NULL; /* success */
1468 goto done;
1472 /* Handle errors from first or second creation attempt. */
1473 if (errno == ENAMETOOLONG) {
1474 /* bad target path; install as a regular file */
1475 *is_bad_symlink = 1;
1476 got_object_blob_rewind(blob);
1477 err = install_blob(worktree, ondisk_path, path,
1478 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1479 restoring_missing_file, reverting_versioned_file, 1,
1480 path_is_unversioned, repo,
1481 progress_cb, progress_arg);
1482 } else if (errno == ENOTDIR) {
1483 err = got_error_path(ondisk_path,
1484 GOT_ERR_FILE_OBSTRUCTED);
1485 } else {
1486 err = got_error_from_errno3("symlink",
1487 target_path, ondisk_path);
1489 } else if (progress_cb)
1490 err = (*progress_cb)(progress_arg, reverting_versioned_file ?
1491 GOT_STATUS_REVERT : GOT_STATUS_ADD, path);
1492 done:
1493 free(path_got);
1494 return err;
1497 static const struct got_error *
1498 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1499 const char *path, mode_t te_mode, mode_t st_mode,
1500 struct got_blob_object *blob, int restoring_missing_file,
1501 int reverting_versioned_file, int installing_bad_symlink,
1502 int path_is_unversioned, struct got_repository *repo,
1503 got_worktree_checkout_cb progress_cb, void *progress_arg)
1505 const struct got_error *err = NULL;
1506 int fd = -1;
1507 size_t len, hdrlen;
1508 int update = 0;
1509 char *tmppath = NULL;
1511 fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1512 GOT_DEFAULT_FILE_MODE);
1513 if (fd == -1) {
1514 if (errno == ENOENT) {
1515 char *parent;
1516 err = got_path_dirname(&parent, path);
1517 if (err)
1518 return err;
1519 err = add_dir_on_disk(worktree, parent);
1520 free(parent);
1521 if (err)
1522 return err;
1523 fd = open(ondisk_path,
1524 O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1525 GOT_DEFAULT_FILE_MODE);
1526 if (fd == -1)
1527 return got_error_from_errno2("open",
1528 ondisk_path);
1529 } else if (errno == EEXIST) {
1530 if (path_is_unversioned) {
1531 err = (*progress_cb)(progress_arg,
1532 GOT_STATUS_UNVERSIONED, path);
1533 goto done;
1535 if (!(S_ISLNK(st_mode) && S_ISREG(te_mode)) &&
1536 !S_ISREG(st_mode) && !installing_bad_symlink) {
1537 /* TODO file is obstructed; do something */
1538 err = got_error_path(ondisk_path,
1539 GOT_ERR_FILE_OBSTRUCTED);
1540 goto done;
1541 } else {
1542 err = got_opentemp_named_fd(&tmppath, &fd,
1543 ondisk_path);
1544 if (err)
1545 goto done;
1546 update = 1;
1548 } else
1549 return got_error_from_errno2("open", ondisk_path);
1552 if (fchmod(fd, get_ondisk_perms(te_mode & S_IXUSR, st_mode)) == -1) {
1553 err = got_error_from_errno2("fchmod",
1554 update ? tmppath : ondisk_path);
1555 goto done;
1558 if (progress_cb) {
1559 if (restoring_missing_file)
1560 err = (*progress_cb)(progress_arg, GOT_STATUS_MISSING,
1561 path);
1562 else if (reverting_versioned_file)
1563 err = (*progress_cb)(progress_arg, GOT_STATUS_REVERT,
1564 path);
1565 else
1566 err = (*progress_cb)(progress_arg,
1567 update ? GOT_STATUS_UPDATE : GOT_STATUS_ADD, path);
1568 if (err)
1569 goto done;
1572 hdrlen = got_object_blob_get_hdrlen(blob);
1573 do {
1574 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1575 err = got_object_blob_read_block(&len, blob);
1576 if (err)
1577 break;
1578 if (len > 0) {
1579 /* Skip blob object header first time around. */
1580 ssize_t outlen = write(fd, buf + hdrlen, len - hdrlen);
1581 if (outlen == -1) {
1582 err = got_error_from_errno("write");
1583 goto done;
1584 } else if (outlen != len - hdrlen) {
1585 err = got_error(GOT_ERR_IO);
1586 goto done;
1588 hdrlen = 0;
1590 } while (len != 0);
1592 if (fsync(fd) != 0) {
1593 err = got_error_from_errno("fsync");
1594 goto done;
1597 if (update) {
1598 if (S_ISLNK(st_mode) && unlink(ondisk_path) == -1) {
1599 err = got_error_from_errno2("unlink", ondisk_path);
1600 goto done;
1602 if (rename(tmppath, ondisk_path) != 0) {
1603 err = got_error_from_errno3("rename", tmppath,
1604 ondisk_path);
1605 goto done;
1607 free(tmppath);
1608 tmppath = NULL;
1611 done:
1612 if (fd != -1 && close(fd) == -1 && err == NULL)
1613 err = got_error_from_errno("close");
1614 if (tmppath != NULL && unlink(tmppath) == -1 && err == NULL)
1615 err = got_error_from_errno2("unlink", tmppath);
1616 free(tmppath);
1617 return err;
1620 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1621 static const struct got_error *
1622 get_modified_file_content_status(unsigned char *status, FILE *f)
1624 const struct got_error *err = NULL;
1625 const char *markers[3] = {
1626 GOT_DIFF_CONFLICT_MARKER_BEGIN,
1627 GOT_DIFF_CONFLICT_MARKER_SEP,
1628 GOT_DIFF_CONFLICT_MARKER_END
1630 int i = 0;
1631 char *line = NULL;
1632 size_t linesize = 0;
1633 ssize_t linelen;
1635 while (*status == GOT_STATUS_MODIFY) {
1636 linelen = getline(&line, &linesize, f);
1637 if (linelen == -1) {
1638 if (feof(f))
1639 break;
1640 err = got_ferror(f, GOT_ERR_IO);
1641 break;
1644 if (strncmp(line, markers[i], strlen(markers[i])) == 0) {
1645 if (strcmp(markers[i], GOT_DIFF_CONFLICT_MARKER_END)
1646 == 0)
1647 *status = GOT_STATUS_CONFLICT;
1648 else
1649 i++;
1652 free(line);
1654 return err;
1657 static int
1658 xbit_differs(struct got_fileindex_entry *ie, uint16_t st_mode)
1660 mode_t ie_mode = got_fileindex_perms_to_st(ie);
1661 return ((ie_mode & S_IXUSR) != (st_mode & S_IXUSR));
1664 static int
1665 stat_info_differs(struct got_fileindex_entry *ie, struct stat *sb)
1667 return !(ie->ctime_sec == sb->st_ctim.tv_sec &&
1668 ie->ctime_nsec == sb->st_ctim.tv_nsec &&
1669 ie->mtime_sec == sb->st_mtim.tv_sec &&
1670 ie->mtime_nsec == sb->st_mtim.tv_nsec &&
1671 ie->size == (sb->st_size & 0xffffffff) &&
1672 !xbit_differs(ie, sb->st_mode));
1675 static unsigned char
1676 get_staged_status(struct got_fileindex_entry *ie)
1678 switch (got_fileindex_entry_stage_get(ie)) {
1679 case GOT_FILEIDX_STAGE_ADD:
1680 return GOT_STATUS_ADD;
1681 case GOT_FILEIDX_STAGE_DELETE:
1682 return GOT_STATUS_DELETE;
1683 case GOT_FILEIDX_STAGE_MODIFY:
1684 return GOT_STATUS_MODIFY;
1685 default:
1686 return GOT_STATUS_NO_CHANGE;
1690 static const struct got_error *
1691 get_symlink_modification_status(unsigned char *status,
1692 struct got_fileindex_entry *ie, const char *abspath,
1693 int dirfd, const char *de_name, struct got_blob_object *blob)
1695 const struct got_error *err = NULL;
1696 char target_path[PATH_MAX];
1697 char etarget[PATH_MAX];
1698 ssize_t elen;
1699 size_t len, target_len = 0;
1700 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1701 size_t hdrlen = got_object_blob_get_hdrlen(blob);
1703 *status = GOT_STATUS_NO_CHANGE;
1705 /* Blob object content specifies the target path of the link. */
1706 do {
1707 err = got_object_blob_read_block(&len, blob);
1708 if (err)
1709 return err;
1710 if (len + target_len >= sizeof(target_path)) {
1712 * Should not happen. The blob contents were OK
1713 * when this symlink was installed.
1715 return got_error(GOT_ERR_NO_SPACE);
1717 if (len > 0) {
1718 /* Skip blob object header first time around. */
1719 memcpy(target_path + target_len, buf + hdrlen,
1720 len - hdrlen);
1721 target_len += len - hdrlen;
1722 hdrlen = 0;
1724 } while (len != 0);
1725 target_path[target_len] = '\0';
1727 if (dirfd != -1) {
1728 elen = readlinkat(dirfd, de_name, etarget, sizeof(etarget));
1729 if (elen == -1)
1730 return got_error_from_errno2("readlinkat", abspath);
1731 } else {
1732 elen = readlink(abspath, etarget, sizeof(etarget));
1733 if (elen == -1)
1734 return got_error_from_errno2("readlink", abspath);
1737 if (elen != target_len || memcmp(etarget, target_path, target_len) != 0)
1738 *status = GOT_STATUS_MODIFY;
1740 return NULL;
1743 static const struct got_error *
1744 get_file_status(unsigned char *status, struct stat *sb,
1745 struct got_fileindex_entry *ie, const char *abspath,
1746 int dirfd, const char *de_name, struct got_repository *repo)
1748 const struct got_error *err = NULL;
1749 struct got_object_id id;
1750 size_t hdrlen;
1751 int fd = -1;
1752 FILE *f = NULL;
1753 uint8_t fbuf[8192];
1754 struct got_blob_object *blob = NULL;
1755 size_t flen, blen;
1756 unsigned char staged_status = get_staged_status(ie);
1758 *status = GOT_STATUS_NO_CHANGE;
1759 memset(sb, 0, sizeof(*sb));
1762 * Whenever the caller provides a directory descriptor and a
1763 * directory entry name for the file, use them! This prevents
1764 * race conditions if filesystem paths change beneath our feet.
1766 if (dirfd != -1) {
1767 if (fstatat(dirfd, de_name, sb, AT_SYMLINK_NOFOLLOW) == -1) {
1768 if (errno == ENOENT) {
1769 if (got_fileindex_entry_has_file_on_disk(ie))
1770 *status = GOT_STATUS_MISSING;
1771 else
1772 *status = GOT_STATUS_DELETE;
1773 goto done;
1775 err = got_error_from_errno2("fstatat", abspath);
1776 goto done;
1778 } else {
1779 fd = open(abspath, O_RDONLY | O_NOFOLLOW);
1780 if (fd == -1 && errno != ENOENT && errno != ELOOP)
1781 return got_error_from_errno2("open", abspath);
1782 else if (fd == -1 && errno == ELOOP) {
1783 if (lstat(abspath, sb) == -1)
1784 return got_error_from_errno2("lstat", abspath);
1785 } else if (fd == -1 || fstat(fd, sb) == -1) {
1786 if (errno == ENOENT) {
1787 if (got_fileindex_entry_has_file_on_disk(ie))
1788 *status = GOT_STATUS_MISSING;
1789 else
1790 *status = GOT_STATUS_DELETE;
1791 goto done;
1793 err = got_error_from_errno2("fstat", abspath);
1794 goto done;
1798 if (!S_ISREG(sb->st_mode) && !S_ISLNK(sb->st_mode)) {
1799 *status = GOT_STATUS_OBSTRUCTED;
1800 goto done;
1803 if (!got_fileindex_entry_has_file_on_disk(ie)) {
1804 *status = GOT_STATUS_DELETE;
1805 goto done;
1806 } else if (!got_fileindex_entry_has_blob(ie) &&
1807 staged_status != GOT_STATUS_ADD) {
1808 *status = GOT_STATUS_ADD;
1809 goto done;
1812 if (!stat_info_differs(ie, sb))
1813 goto done;
1815 if (S_ISLNK(sb->st_mode) &&
1816 got_fileindex_entry_filetype_get(ie) != GOT_FILEIDX_MODE_SYMLINK) {
1817 *status = GOT_STATUS_MODIFY;
1818 goto done;
1821 if (staged_status == GOT_STATUS_MODIFY ||
1822 staged_status == GOT_STATUS_ADD)
1823 memcpy(id.sha1, ie->staged_blob_sha1, sizeof(id.sha1));
1824 else
1825 memcpy(id.sha1, ie->blob_sha1, sizeof(id.sha1));
1827 err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf));
1828 if (err)
1829 goto done;
1831 if (S_ISLNK(sb->st_mode)) {
1832 err = get_symlink_modification_status(status, ie,
1833 abspath, dirfd, de_name, blob);
1834 goto done;
1837 if (dirfd != -1) {
1838 fd = openat(dirfd, de_name, O_RDONLY | O_NOFOLLOW);
1839 if (fd == -1) {
1840 err = got_error_from_errno2("openat", abspath);
1841 goto done;
1845 f = fdopen(fd, "r");
1846 if (f == NULL) {
1847 err = got_error_from_errno2("fdopen", abspath);
1848 goto done;
1850 fd = -1;
1851 hdrlen = got_object_blob_get_hdrlen(blob);
1852 for (;;) {
1853 const uint8_t *bbuf = got_object_blob_get_read_buf(blob);
1854 err = got_object_blob_read_block(&blen, blob);
1855 if (err)
1856 goto done;
1857 /* Skip length of blob object header first time around. */
1858 flen = fread(fbuf, 1, sizeof(fbuf) - hdrlen, f);
1859 if (flen == 0 && ferror(f)) {
1860 err = got_error_from_errno("fread");
1861 goto done;
1863 if (blen - hdrlen == 0) {
1864 if (flen != 0)
1865 *status = GOT_STATUS_MODIFY;
1866 break;
1867 } else if (flen == 0) {
1868 if (blen - hdrlen != 0)
1869 *status = GOT_STATUS_MODIFY;
1870 break;
1871 } else if (blen - hdrlen == flen) {
1872 /* Skip blob object header first time around. */
1873 if (memcmp(bbuf + hdrlen, fbuf, flen) != 0) {
1874 *status = GOT_STATUS_MODIFY;
1875 break;
1877 } else {
1878 *status = GOT_STATUS_MODIFY;
1879 break;
1881 hdrlen = 0;
1884 if (*status == GOT_STATUS_MODIFY) {
1885 rewind(f);
1886 err = get_modified_file_content_status(status, f);
1887 } else if (xbit_differs(ie, sb->st_mode))
1888 *status = GOT_STATUS_MODE_CHANGE;
1889 done:
1890 if (blob)
1891 got_object_blob_close(blob);
1892 if (f != NULL && fclose(f) == EOF && err == NULL)
1893 err = got_error_from_errno2("fclose", abspath);
1894 if (fd != -1 && close(fd) == -1 && err == NULL)
1895 err = got_error_from_errno2("close", abspath);
1896 return err;
1900 * Update timestamps in the file index if a file is unmodified and
1901 * we had to run a full content comparison to find out.
1903 static const struct got_error *
1904 sync_timestamps(int wt_fd, const char *path, unsigned char status,
1905 struct got_fileindex_entry *ie, struct stat *sb)
1907 if (status == GOT_STATUS_NO_CHANGE && stat_info_differs(ie, sb))
1908 return got_fileindex_entry_update(ie, wt_fd, path,
1909 ie->blob_sha1, ie->commit_sha1, 1);
1911 return NULL;
1914 static const struct got_error *
1915 update_blob(struct got_worktree *worktree,
1916 struct got_fileindex *fileindex, struct got_fileindex_entry *ie,
1917 struct got_tree_entry *te, const char *path,
1918 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
1919 void *progress_arg)
1921 const struct got_error *err = NULL;
1922 struct got_blob_object *blob = NULL;
1923 char *ondisk_path;
1924 unsigned char status = GOT_STATUS_NO_CHANGE;
1925 struct stat sb;
1927 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, path) == -1)
1928 return got_error_from_errno("asprintf");
1930 if (ie) {
1931 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE) {
1932 err = got_error_path(ie->path, GOT_ERR_FILE_STAGED);
1933 goto done;
1935 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
1936 repo);
1937 if (err)
1938 goto done;
1939 if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE)
1940 sb.st_mode = got_fileindex_perms_to_st(ie);
1941 } else {
1942 sb.st_mode = GOT_DEFAULT_FILE_MODE;
1943 status = GOT_STATUS_UNVERSIONED;
1946 if (status == GOT_STATUS_OBSTRUCTED) {
1947 err = (*progress_cb)(progress_arg, status, path);
1948 goto done;
1950 if (status == GOT_STATUS_CONFLICT) {
1951 err = (*progress_cb)(progress_arg, GOT_STATUS_CANNOT_UPDATE,
1952 path);
1953 goto done;
1956 if (ie && status != GOT_STATUS_MISSING && S_ISREG(sb.st_mode) &&
1957 (S_ISLNK(te->mode) ||
1958 (te->mode & S_IXUSR) == (sb.st_mode & S_IXUSR))) {
1960 * This is a regular file or an installed bad symlink.
1961 * If the file index indicates that this file is already
1962 * up-to-date with respect to the repository we can skip
1963 * updating contents of this file.
1965 if (got_fileindex_entry_has_commit(ie) &&
1966 memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
1967 SHA1_DIGEST_LENGTH) == 0) {
1968 /* Same commit. */
1969 err = sync_timestamps(worktree->root_fd,
1970 path, status, ie, &sb);
1971 if (err)
1972 goto done;
1973 err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
1974 path);
1975 goto done;
1977 if (got_fileindex_entry_has_blob(ie) &&
1978 memcmp(ie->blob_sha1, te->id.sha1,
1979 SHA1_DIGEST_LENGTH) == 0) {
1980 /* Different commit but the same blob. */
1981 err = sync_timestamps(worktree->root_fd,
1982 path, status, ie, &sb);
1983 if (err)
1984 goto done;
1985 err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
1986 path);
1987 goto done;
1991 err = got_object_open_as_blob(&blob, repo, &te->id, 8192);
1992 if (err)
1993 goto done;
1995 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_ADD) {
1996 int update_timestamps;
1997 struct got_blob_object *blob2 = NULL;
1998 char *label_orig = NULL;
1999 if (got_fileindex_entry_has_blob(ie)) {
2000 struct got_object_id id2;
2001 memcpy(id2.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
2002 err = got_object_open_as_blob(&blob2, repo, &id2, 8192);
2003 if (err)
2004 goto done;
2006 if (got_fileindex_entry_has_commit(ie)) {
2007 char id_str[SHA1_DIGEST_STRING_LENGTH];
2008 if (got_sha1_digest_to_str(ie->commit_sha1, id_str,
2009 sizeof(id_str)) == NULL) {
2010 err = got_error_path(id_str,
2011 GOT_ERR_BAD_OBJ_ID_STR);
2012 goto done;
2014 if (asprintf(&label_orig, "%s: commit %s",
2015 GOT_MERGE_LABEL_BASE, id_str) == -1) {
2016 err = got_error_from_errno("asprintf");
2017 goto done;
2020 if (S_ISLNK(te->mode) && S_ISLNK(sb.st_mode)) {
2021 char *link_target;
2022 err = got_object_blob_read_to_str(&link_target, blob);
2023 if (err)
2024 goto done;
2025 err = merge_symlink(worktree, blob2, ondisk_path, path,
2026 label_orig, link_target, worktree->base_commit_id,
2027 repo, progress_cb, progress_arg);
2028 free(link_target);
2029 } else {
2030 err = merge_blob(&update_timestamps, worktree, blob2,
2031 ondisk_path, path, sb.st_mode, label_orig, blob,
2032 worktree->base_commit_id, repo,
2033 progress_cb, progress_arg);
2035 free(label_orig);
2036 if (blob2)
2037 got_object_blob_close(blob2);
2038 if (err)
2039 goto done;
2041 * Do not update timestamps of files with local changes.
2042 * Otherwise, a future status walk would treat them as
2043 * unmodified files again.
2045 err = got_fileindex_entry_update(ie, worktree->root_fd, path,
2046 blob->id.sha1, worktree->base_commit_id->sha1,
2047 update_timestamps);
2048 } else if (status == GOT_STATUS_MODE_CHANGE) {
2049 err = got_fileindex_entry_update(ie, worktree->root_fd, path,
2050 blob->id.sha1, worktree->base_commit_id->sha1, 0);
2051 } else if (status == GOT_STATUS_DELETE) {
2052 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
2053 if (err)
2054 goto done;
2055 err = got_fileindex_entry_update(ie, worktree->root_fd, path,
2056 blob->id.sha1, worktree->base_commit_id->sha1, 0);
2057 if (err)
2058 goto done;
2059 } else {
2060 int is_bad_symlink = 0;
2061 if (S_ISLNK(te->mode)) {
2062 err = install_symlink(&is_bad_symlink, worktree,
2063 ondisk_path, path, blob,
2064 status == GOT_STATUS_MISSING, 0,
2065 status == GOT_STATUS_UNVERSIONED, repo,
2066 progress_cb, progress_arg);
2067 } else {
2068 err = install_blob(worktree, ondisk_path, path,
2069 te->mode, sb.st_mode, blob,
2070 status == GOT_STATUS_MISSING, 0, 0,
2071 status == GOT_STATUS_UNVERSIONED, repo,
2072 progress_cb, progress_arg);
2074 if (err)
2075 goto done;
2077 if (ie) {
2078 err = got_fileindex_entry_update(ie,
2079 worktree->root_fd, path, blob->id.sha1,
2080 worktree->base_commit_id->sha1, 1);
2081 } else {
2082 err = create_fileindex_entry(&ie, fileindex,
2083 worktree->base_commit_id, worktree->root_fd, path,
2084 &blob->id);
2086 if (err)
2087 goto done;
2089 if (is_bad_symlink) {
2090 got_fileindex_entry_filetype_set(ie,
2091 GOT_FILEIDX_MODE_BAD_SYMLINK);
2094 got_object_blob_close(blob);
2095 done:
2096 free(ondisk_path);
2097 return err;
2100 static const struct got_error *
2101 remove_ondisk_file(const char *root_path, const char *path)
2103 const struct got_error *err = NULL;
2104 char *ondisk_path = NULL;
2106 if (asprintf(&ondisk_path, "%s/%s", root_path, path) == -1)
2107 return got_error_from_errno("asprintf");
2109 if (unlink(ondisk_path) == -1) {
2110 if (errno != ENOENT)
2111 err = got_error_from_errno2("unlink", ondisk_path);
2112 } else {
2113 size_t root_len = strlen(root_path);
2114 do {
2115 char *parent;
2116 err = got_path_dirname(&parent, ondisk_path);
2117 if (err)
2118 break;
2119 free(ondisk_path);
2120 ondisk_path = parent;
2121 if (rmdir(ondisk_path) == -1) {
2122 if (errno != ENOTEMPTY)
2123 err = got_error_from_errno2("rmdir",
2124 ondisk_path);
2125 break;
2127 } while (got_path_cmp(ondisk_path, root_path,
2128 strlen(ondisk_path), root_len) != 0);
2130 free(ondisk_path);
2131 return err;
2134 static const struct got_error *
2135 delete_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
2136 struct got_fileindex_entry *ie, struct got_repository *repo,
2137 got_worktree_checkout_cb progress_cb, void *progress_arg)
2139 const struct got_error *err = NULL;
2140 unsigned char status;
2141 struct stat sb;
2142 char *ondisk_path;
2144 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
2145 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
2147 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, ie->path)
2148 == -1)
2149 return got_error_from_errno("asprintf");
2151 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, repo);
2152 if (err)
2153 goto done;
2155 if (S_ISLNK(sb.st_mode) && status != GOT_STATUS_NO_CHANGE) {
2156 char ondisk_target[PATH_MAX];
2157 ssize_t ondisk_len = readlink(ondisk_path, ondisk_target,
2158 sizeof(ondisk_target));
2159 if (ondisk_len == -1) {
2160 err = got_error_from_errno2("readlink", ondisk_path);
2161 goto done;
2163 ondisk_target[ondisk_len] = '\0';
2164 err = install_symlink_conflict(NULL, worktree->base_commit_id,
2165 NULL, NULL, /* XXX pass common ancestor info? */
2166 ondisk_target, ondisk_path);
2167 if (err)
2168 goto done;
2169 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
2170 ie->path);
2171 goto done;
2174 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_CONFLICT ||
2175 status == GOT_STATUS_ADD) {
2176 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, ie->path);
2177 if (err)
2178 goto done;
2180 * Preserve the working file and change the deleted blob's
2181 * entry into a schedule-add entry.
2183 err = got_fileindex_entry_update(ie, worktree->root_fd,
2184 ie->path, NULL, NULL, 0);
2185 } else {
2186 err = (*progress_cb)(progress_arg, GOT_STATUS_DELETE, ie->path);
2187 if (err)
2188 goto done;
2189 if (status == GOT_STATUS_NO_CHANGE) {
2190 err = remove_ondisk_file(worktree->root_path, ie->path);
2191 if (err)
2192 goto done;
2194 got_fileindex_entry_remove(fileindex, ie);
2196 done:
2197 free(ondisk_path);
2198 return err;
2201 struct diff_cb_arg {
2202 struct got_fileindex *fileindex;
2203 struct got_worktree *worktree;
2204 struct got_repository *repo;
2205 got_worktree_checkout_cb progress_cb;
2206 void *progress_arg;
2207 got_cancel_cb cancel_cb;
2208 void *cancel_arg;
2211 static const struct got_error *
2212 diff_old_new(void *arg, struct got_fileindex_entry *ie,
2213 struct got_tree_entry *te, const char *parent_path)
2215 struct diff_cb_arg *a = arg;
2217 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2218 return got_error(GOT_ERR_CANCELLED);
2220 return update_blob(a->worktree, a->fileindex, ie, te,
2221 ie->path, a->repo, a->progress_cb, a->progress_arg);
2224 static const struct got_error *
2225 diff_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
2227 struct diff_cb_arg *a = arg;
2229 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2230 return got_error(GOT_ERR_CANCELLED);
2232 return delete_blob(a->worktree, a->fileindex, ie,
2233 a->repo, a->progress_cb, a->progress_arg);
2236 static const struct got_error *
2237 diff_new(void *arg, struct got_tree_entry *te, const char *parent_path)
2239 struct diff_cb_arg *a = arg;
2240 const struct got_error *err;
2241 char *path;
2243 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2244 return got_error(GOT_ERR_CANCELLED);
2246 if (got_object_tree_entry_is_submodule(te))
2247 return NULL;
2249 if (asprintf(&path, "%s%s%s", parent_path,
2250 parent_path[0] ? "/" : "", te->name)
2251 == -1)
2252 return got_error_from_errno("asprintf");
2254 if (S_ISDIR(te->mode))
2255 err = add_dir_on_disk(a->worktree, path);
2256 else
2257 err = update_blob(a->worktree, a->fileindex, NULL, te, path,
2258 a->repo, a->progress_cb, a->progress_arg);
2260 free(path);
2261 return err;
2264 const struct got_error *
2265 got_worktree_get_uuid(char **uuidstr, struct got_worktree *worktree)
2267 uint32_t uuid_status;
2269 uuid_to_string(&worktree->uuid, uuidstr, &uuid_status);
2270 if (uuid_status != uuid_s_ok) {
2271 *uuidstr = NULL;
2272 return got_error_uuid(uuid_status, "uuid_to_string");
2275 return NULL;
2278 static const struct got_error *
2279 get_ref_name(char **refname, struct got_worktree *worktree, const char *prefix)
2281 const struct got_error *err = NULL;
2282 char *uuidstr = NULL;
2284 *refname = NULL;
2286 err = got_worktree_get_uuid(&uuidstr, worktree);
2287 if (err)
2288 return err;
2290 if (asprintf(refname, "%s-%s", prefix, uuidstr) == -1) {
2291 err = got_error_from_errno("asprintf");
2292 *refname = NULL;
2294 free(uuidstr);
2295 return err;
2298 const struct got_error *
2299 got_worktree_get_base_ref_name(char **refname, struct got_worktree *worktree)
2301 return get_ref_name(refname, worktree, GOT_WORKTREE_BASE_REF_PREFIX);
2304 static const struct got_error *
2305 get_rebase_tmp_ref_name(char **refname, struct got_worktree *worktree)
2307 return get_ref_name(refname, worktree,
2308 GOT_WORKTREE_REBASE_TMP_REF_PREFIX);
2311 static const struct got_error *
2312 get_newbase_symref_name(char **refname, struct got_worktree *worktree)
2314 return get_ref_name(refname, worktree, GOT_WORKTREE_NEWBASE_REF_PREFIX);
2317 static const struct got_error *
2318 get_rebase_branch_symref_name(char **refname, struct got_worktree *worktree)
2320 return get_ref_name(refname, worktree,
2321 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX);
2324 static const struct got_error *
2325 get_rebase_commit_ref_name(char **refname, struct got_worktree *worktree)
2327 return get_ref_name(refname, worktree,
2328 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX);
2331 static const struct got_error *
2332 get_histedit_tmp_ref_name(char **refname, struct got_worktree *worktree)
2334 return get_ref_name(refname, worktree,
2335 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX);
2338 static const struct got_error *
2339 get_histedit_branch_symref_name(char **refname, struct got_worktree *worktree)
2341 return get_ref_name(refname, worktree,
2342 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX);
2345 static const struct got_error *
2346 get_histedit_base_commit_ref_name(char **refname, struct got_worktree *worktree)
2348 return get_ref_name(refname, worktree,
2349 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX);
2352 static const struct got_error *
2353 get_histedit_commit_ref_name(char **refname, struct got_worktree *worktree)
2355 return get_ref_name(refname, worktree,
2356 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX);
2359 const struct got_error *
2360 got_worktree_get_histedit_script_path(char **path,
2361 struct got_worktree *worktree)
2363 if (asprintf(path, "%s/%s/%s", worktree->root_path,
2364 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_HISTEDIT_SCRIPT) == -1) {
2365 *path = NULL;
2366 return got_error_from_errno("asprintf");
2368 return NULL;
2372 * Prevent Git's garbage collector from deleting our base commit by
2373 * setting a reference to our base commit's ID.
2375 static const struct got_error *
2376 ref_base_commit(struct got_worktree *worktree, struct got_repository *repo)
2378 const struct got_error *err = NULL;
2379 struct got_reference *ref = NULL;
2380 char *refname;
2382 err = got_worktree_get_base_ref_name(&refname, worktree);
2383 if (err)
2384 return err;
2386 err = got_ref_alloc(&ref, refname, worktree->base_commit_id);
2387 if (err)
2388 goto done;
2390 err = got_ref_write(ref, repo);
2391 done:
2392 free(refname);
2393 if (ref)
2394 got_ref_close(ref);
2395 return err;
2398 static const struct got_error *
2399 get_fileindex_path(char **fileindex_path, struct got_worktree *worktree)
2401 const struct got_error *err = NULL;
2403 if (asprintf(fileindex_path, "%s/%s/%s", worktree->root_path,
2404 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_FILE_INDEX) == -1) {
2405 err = got_error_from_errno("asprintf");
2406 *fileindex_path = NULL;
2408 return err;
2412 static const struct got_error *
2413 open_fileindex(struct got_fileindex **fileindex, char **fileindex_path,
2414 struct got_worktree *worktree)
2416 const struct got_error *err = NULL;
2417 FILE *index = NULL;
2419 *fileindex_path = NULL;
2420 *fileindex = got_fileindex_alloc();
2421 if (*fileindex == NULL)
2422 return got_error_from_errno("got_fileindex_alloc");
2424 err = get_fileindex_path(fileindex_path, worktree);
2425 if (err)
2426 goto done;
2428 index = fopen(*fileindex_path, "rb");
2429 if (index == NULL) {
2430 if (errno != ENOENT)
2431 err = got_error_from_errno2("fopen", *fileindex_path);
2432 } else {
2433 err = got_fileindex_read(*fileindex, index);
2434 if (fclose(index) == EOF && err == NULL)
2435 err = got_error_from_errno("fclose");
2437 done:
2438 if (err) {
2439 free(*fileindex_path);
2440 *fileindex_path = NULL;
2441 got_fileindex_free(*fileindex);
2442 *fileindex = NULL;
2444 return err;
2447 struct bump_base_commit_id_arg {
2448 struct got_object_id *base_commit_id;
2449 const char *path;
2450 size_t path_len;
2451 const char *entry_name;
2452 got_worktree_checkout_cb progress_cb;
2453 void *progress_arg;
2456 /* Bump base commit ID of all files within an updated part of the work tree. */
2457 static const struct got_error *
2458 bump_base_commit_id(void *arg, struct got_fileindex_entry *ie)
2460 const struct got_error *err;
2461 struct bump_base_commit_id_arg *a = arg;
2463 if (a->entry_name) {
2464 if (strcmp(ie->path, a->path) != 0)
2465 return NULL;
2466 } else if (!got_path_is_child(ie->path, a->path, a->path_len))
2467 return NULL;
2469 if (memcmp(ie->commit_sha1, a->base_commit_id->sha1,
2470 SHA1_DIGEST_LENGTH) == 0)
2471 return NULL;
2473 if (a->progress_cb) {
2474 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_BUMP_BASE,
2475 ie->path);
2476 if (err)
2477 return err;
2479 memcpy(ie->commit_sha1, a->base_commit_id->sha1, SHA1_DIGEST_LENGTH);
2480 return NULL;
2483 static const struct got_error *
2484 bump_base_commit_id_everywhere(struct got_worktree *worktree,
2485 struct got_fileindex *fileindex,
2486 got_worktree_checkout_cb progress_cb, void *progress_arg)
2488 struct bump_base_commit_id_arg bbc_arg;
2490 bbc_arg.base_commit_id = worktree->base_commit_id;
2491 bbc_arg.entry_name = NULL;
2492 bbc_arg.path = "";
2493 bbc_arg.path_len = 0;
2494 bbc_arg.progress_cb = progress_cb;
2495 bbc_arg.progress_arg = progress_arg;
2497 return got_fileindex_for_each_entry_safe(fileindex,
2498 bump_base_commit_id, &bbc_arg);
2501 static const struct got_error *
2502 sync_fileindex(struct got_fileindex *fileindex, const char *fileindex_path)
2504 const struct got_error *err = NULL;
2505 char *new_fileindex_path = NULL;
2506 FILE *new_index = NULL;
2507 struct timespec timeout;
2509 err = got_opentemp_named(&new_fileindex_path, &new_index,
2510 fileindex_path);
2511 if (err)
2512 goto done;
2514 err = got_fileindex_write(fileindex, new_index);
2515 if (err)
2516 goto done;
2518 if (rename(new_fileindex_path, fileindex_path) != 0) {
2519 err = got_error_from_errno3("rename", new_fileindex_path,
2520 fileindex_path);
2521 unlink(new_fileindex_path);
2525 * Sleep for a short amount of time to ensure that files modified after
2526 * this program exits have a different time stamp from the one which
2527 * was recorded in the file index.
2529 timeout.tv_sec = 0;
2530 timeout.tv_nsec = 1;
2531 nanosleep(&timeout, NULL);
2532 done:
2533 if (new_index)
2534 fclose(new_index);
2535 free(new_fileindex_path);
2536 return err;
2539 static const struct got_error *
2540 find_tree_entry_for_checkout(int *entry_type, char **tree_relpath,
2541 struct got_object_id **tree_id, const char *wt_relpath,
2542 struct got_worktree *worktree, struct got_repository *repo)
2544 const struct got_error *err = NULL;
2545 struct got_object_id *id = NULL;
2546 char *in_repo_path = NULL;
2547 int is_root_wt = got_path_is_root_dir(worktree->path_prefix);
2549 *entry_type = GOT_OBJ_TYPE_ANY;
2550 *tree_relpath = NULL;
2551 *tree_id = NULL;
2553 if (wt_relpath[0] == '\0') {
2554 /* Check out all files within the work tree. */
2555 *entry_type = GOT_OBJ_TYPE_TREE;
2556 *tree_relpath = strdup("");
2557 if (*tree_relpath == NULL) {
2558 err = got_error_from_errno("strdup");
2559 goto done;
2561 err = got_object_id_by_path(tree_id, repo,
2562 worktree->base_commit_id, worktree->path_prefix);
2563 if (err)
2564 goto done;
2565 return NULL;
2568 /* Check out a subset of files in the work tree. */
2570 if (asprintf(&in_repo_path, "%s%s%s", worktree->path_prefix,
2571 is_root_wt ? "" : "/", wt_relpath) == -1) {
2572 err = got_error_from_errno("asprintf");
2573 goto done;
2576 err = got_object_id_by_path(&id, repo, worktree->base_commit_id,
2577 in_repo_path);
2578 if (err)
2579 goto done;
2581 free(in_repo_path);
2582 in_repo_path = NULL;
2584 err = got_object_get_type(entry_type, repo, id);
2585 if (err)
2586 goto done;
2588 if (*entry_type == GOT_OBJ_TYPE_BLOB) {
2589 /* Check out a single file. */
2590 if (strchr(wt_relpath, '/') == NULL) {
2591 /* Check out a single file in work tree's root dir. */
2592 in_repo_path = strdup(worktree->path_prefix);
2593 if (in_repo_path == NULL) {
2594 err = got_error_from_errno("strdup");
2595 goto done;
2597 *tree_relpath = strdup("");
2598 if (*tree_relpath == NULL) {
2599 err = got_error_from_errno("strdup");
2600 goto done;
2602 } else {
2603 /* Check out a single file in a subdirectory. */
2604 err = got_path_dirname(tree_relpath, wt_relpath);
2605 if (err)
2606 return err;
2607 if (asprintf(&in_repo_path, "%s%s%s",
2608 worktree->path_prefix, is_root_wt ? "" : "/",
2609 *tree_relpath) == -1) {
2610 err = got_error_from_errno("asprintf");
2611 goto done;
2614 err = got_object_id_by_path(tree_id, repo,
2615 worktree->base_commit_id, in_repo_path);
2616 } else {
2617 /* Check out all files within a subdirectory. */
2618 *tree_id = got_object_id_dup(id);
2619 if (*tree_id == NULL) {
2620 err = got_error_from_errno("got_object_id_dup");
2621 goto done;
2623 *tree_relpath = strdup(wt_relpath);
2624 if (*tree_relpath == NULL) {
2625 err = got_error_from_errno("strdup");
2626 goto done;
2629 done:
2630 free(id);
2631 free(in_repo_path);
2632 if (err) {
2633 *entry_type = GOT_OBJ_TYPE_ANY;
2634 free(*tree_relpath);
2635 *tree_relpath = NULL;
2636 free(*tree_id);
2637 *tree_id = NULL;
2639 return err;
2642 static const struct got_error *
2643 checkout_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
2644 const char *relpath, struct got_object_id *tree_id, const char *entry_name,
2645 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
2646 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
2648 const struct got_error *err = NULL;
2649 struct got_commit_object *commit = NULL;
2650 struct got_tree_object *tree = NULL;
2651 struct got_fileindex_diff_tree_cb diff_cb;
2652 struct diff_cb_arg arg;
2654 err = ref_base_commit(worktree, repo);
2655 if (err) {
2656 if (!(err->code == GOT_ERR_ERRNO &&
2657 (errno == EACCES || errno == EROFS)))
2658 goto done;
2659 err = (*progress_cb)(progress_arg,
2660 GOT_STATUS_BASE_REF_ERR, worktree->root_path);
2661 if (err)
2662 return err;
2665 err = got_object_open_as_commit(&commit, repo,
2666 worktree->base_commit_id);
2667 if (err)
2668 goto done;
2670 err = got_object_open_as_tree(&tree, repo, tree_id);
2671 if (err)
2672 goto done;
2674 if (entry_name &&
2675 got_object_tree_find_entry(tree, entry_name) == NULL) {
2676 err = got_error_path(entry_name, GOT_ERR_NO_TREE_ENTRY);
2677 goto done;
2680 diff_cb.diff_old_new = diff_old_new;
2681 diff_cb.diff_old = diff_old;
2682 diff_cb.diff_new = diff_new;
2683 arg.fileindex = fileindex;
2684 arg.worktree = worktree;
2685 arg.repo = repo;
2686 arg.progress_cb = progress_cb;
2687 arg.progress_arg = progress_arg;
2688 arg.cancel_cb = cancel_cb;
2689 arg.cancel_arg = cancel_arg;
2690 err = got_fileindex_diff_tree(fileindex, tree, relpath,
2691 entry_name, repo, &diff_cb, &arg);
2692 done:
2693 if (tree)
2694 got_object_tree_close(tree);
2695 if (commit)
2696 got_object_commit_close(commit);
2697 return err;
2700 const struct got_error *
2701 got_worktree_checkout_files(struct got_worktree *worktree,
2702 struct got_pathlist_head *paths, struct got_repository *repo,
2703 got_worktree_checkout_cb progress_cb, void *progress_arg,
2704 got_cancel_cb cancel_cb, void *cancel_arg)
2706 const struct got_error *err = NULL, *sync_err, *unlockerr;
2707 struct got_commit_object *commit = NULL;
2708 struct got_tree_object *tree = NULL;
2709 struct got_fileindex *fileindex = NULL;
2710 char *fileindex_path = NULL;
2711 struct got_pathlist_entry *pe;
2712 struct tree_path_data {
2713 SIMPLEQ_ENTRY(tree_path_data) entry;
2714 struct got_object_id *tree_id;
2715 int entry_type;
2716 char *relpath;
2717 char *entry_name;
2718 } *tpd = NULL;
2719 SIMPLEQ_HEAD(tree_paths, tree_path_data) tree_paths;
2721 SIMPLEQ_INIT(&tree_paths);
2723 err = lock_worktree(worktree, LOCK_EX);
2724 if (err)
2725 return err;
2727 /* Map all specified paths to in-repository trees. */
2728 TAILQ_FOREACH(pe, paths, entry) {
2729 tpd = malloc(sizeof(*tpd));
2730 if (tpd == NULL) {
2731 err = got_error_from_errno("malloc");
2732 goto done;
2735 err = find_tree_entry_for_checkout(&tpd->entry_type,
2736 &tpd->relpath, &tpd->tree_id, pe->path, worktree, repo);
2737 if (err) {
2738 free(tpd);
2739 goto done;
2742 if (tpd->entry_type == GOT_OBJ_TYPE_BLOB) {
2743 err = got_path_basename(&tpd->entry_name, pe->path);
2744 if (err) {
2745 free(tpd->relpath);
2746 free(tpd->tree_id);
2747 free(tpd);
2748 goto done;
2750 } else
2751 tpd->entry_name = NULL;
2753 SIMPLEQ_INSERT_TAIL(&tree_paths, tpd, entry);
2757 * Read the file index.
2758 * Checking out files is supposed to be an idempotent operation.
2759 * If the on-disk file index is incomplete we will try to complete it.
2761 err = open_fileindex(&fileindex, &fileindex_path, worktree);
2762 if (err)
2763 goto done;
2765 tpd = SIMPLEQ_FIRST(&tree_paths);
2766 TAILQ_FOREACH(pe, paths, entry) {
2767 struct bump_base_commit_id_arg bbc_arg;
2769 err = checkout_files(worktree, fileindex, tpd->relpath,
2770 tpd->tree_id, tpd->entry_name, repo,
2771 progress_cb, progress_arg, cancel_cb, cancel_arg);
2772 if (err)
2773 break;
2775 bbc_arg.base_commit_id = worktree->base_commit_id;
2776 bbc_arg.entry_name = tpd->entry_name;
2777 bbc_arg.path = pe->path;
2778 bbc_arg.path_len = pe->path_len;
2779 bbc_arg.progress_cb = progress_cb;
2780 bbc_arg.progress_arg = progress_arg;
2781 err = got_fileindex_for_each_entry_safe(fileindex,
2782 bump_base_commit_id, &bbc_arg);
2783 if (err)
2784 break;
2786 tpd = SIMPLEQ_NEXT(tpd, entry);
2788 sync_err = sync_fileindex(fileindex, fileindex_path);
2789 if (sync_err && err == NULL)
2790 err = sync_err;
2791 done:
2792 free(fileindex_path);
2793 if (tree)
2794 got_object_tree_close(tree);
2795 if (commit)
2796 got_object_commit_close(commit);
2797 if (fileindex)
2798 got_fileindex_free(fileindex);
2799 while (!SIMPLEQ_EMPTY(&tree_paths)) {
2800 tpd = SIMPLEQ_FIRST(&tree_paths);
2801 SIMPLEQ_REMOVE_HEAD(&tree_paths, entry);
2802 free(tpd->relpath);
2803 free(tpd->tree_id);
2804 free(tpd);
2806 unlockerr = lock_worktree(worktree, LOCK_SH);
2807 if (unlockerr && err == NULL)
2808 err = unlockerr;
2809 return err;
2812 struct merge_file_cb_arg {
2813 struct got_worktree *worktree;
2814 struct got_fileindex *fileindex;
2815 got_worktree_checkout_cb progress_cb;
2816 void *progress_arg;
2817 got_cancel_cb cancel_cb;
2818 void *cancel_arg;
2819 const char *label_orig;
2820 struct got_object_id *commit_id2;
2823 static const struct got_error *
2824 merge_file_cb(void *arg, struct got_blob_object *blob1,
2825 struct got_blob_object *blob2, struct got_object_id *id1,
2826 struct got_object_id *id2, const char *path1, const char *path2,
2827 mode_t mode1, mode_t mode2, struct got_repository *repo)
2829 static const struct got_error *err = NULL;
2830 struct merge_file_cb_arg *a = arg;
2831 struct got_fileindex_entry *ie;
2832 char *ondisk_path = NULL;
2833 struct stat sb;
2834 unsigned char status;
2835 int local_changes_subsumed;
2836 FILE *f_orig = NULL, *f_deriv = NULL, *f_deriv2 = NULL;
2837 char *id_str = NULL, *label_deriv2 = NULL;
2839 if (blob1 && blob2) {
2840 ie = got_fileindex_entry_get(a->fileindex, path2,
2841 strlen(path2));
2842 if (ie == NULL)
2843 return (*a->progress_cb)(a->progress_arg,
2844 GOT_STATUS_MISSING, path2);
2846 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2847 path2) == -1)
2848 return got_error_from_errno("asprintf");
2850 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2851 repo);
2852 if (err)
2853 goto done;
2855 if (status == GOT_STATUS_DELETE) {
2856 err = (*a->progress_cb)(a->progress_arg,
2857 GOT_STATUS_MERGE, path2);
2858 goto done;
2860 if (status != GOT_STATUS_NO_CHANGE &&
2861 status != GOT_STATUS_MODIFY &&
2862 status != GOT_STATUS_CONFLICT &&
2863 status != GOT_STATUS_ADD) {
2864 err = (*a->progress_cb)(a->progress_arg, status, path2);
2865 goto done;
2868 if (S_ISLNK(mode1) && S_ISLNK(mode2)) {
2869 char *link_target2;
2870 err = got_object_blob_read_to_str(&link_target2, blob2);
2871 if (err)
2872 goto done;
2873 err = merge_symlink(a->worktree, blob1, ondisk_path,
2874 path2, a->label_orig, link_target2, a->commit_id2,
2875 repo, a->progress_cb, a->progress_arg);
2876 free(link_target2);
2877 } else {
2878 int fd;
2880 f_orig = got_opentemp();
2881 if (f_orig == NULL) {
2882 err = got_error_from_errno("got_opentemp");
2883 goto done;
2885 err = got_object_blob_dump_to_file(NULL, NULL, NULL,
2886 f_orig, blob1);
2887 if (err)
2888 goto done;
2890 f_deriv2 = got_opentemp();
2891 if (f_deriv2 == NULL)
2892 goto done;
2893 err = got_object_blob_dump_to_file(NULL, NULL, NULL,
2894 f_deriv2, blob2);
2895 if (err)
2896 goto done;
2898 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW);
2899 if (fd == -1) {
2900 err = got_error_from_errno2("open",
2901 ondisk_path);
2902 goto done;
2904 f_deriv = fdopen(fd, "r");
2905 if (f_deriv == NULL) {
2906 err = got_error_from_errno2("fdopen",
2907 ondisk_path);
2908 close(fd);
2909 goto done;
2911 err = got_object_id_str(&id_str, a->commit_id2);
2912 if (err)
2913 goto done;
2914 if (asprintf(&label_deriv2, "%s: commit %s",
2915 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
2916 err = got_error_from_errno("asprintf");
2917 goto done;
2919 err = merge_file(&local_changes_subsumed, a->worktree,
2920 f_orig, f_deriv, f_deriv2, ondisk_path, path2,
2921 sb.st_mode, a->label_orig, NULL, label_deriv2,
2922 repo, a->progress_cb, a->progress_arg);
2924 } else if (blob1) {
2925 ie = got_fileindex_entry_get(a->fileindex, path1,
2926 strlen(path1));
2927 if (ie == NULL)
2928 return (*a->progress_cb)(a->progress_arg,
2929 GOT_STATUS_MISSING, path1);
2931 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2932 path1) == -1)
2933 return got_error_from_errno("asprintf");
2935 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2936 repo);
2937 if (err)
2938 goto done;
2940 switch (status) {
2941 case GOT_STATUS_NO_CHANGE:
2942 err = (*a->progress_cb)(a->progress_arg,
2943 GOT_STATUS_DELETE, path1);
2944 if (err)
2945 goto done;
2946 err = remove_ondisk_file(a->worktree->root_path, path1);
2947 if (err)
2948 goto done;
2949 if (ie)
2950 got_fileindex_entry_mark_deleted_from_disk(ie);
2951 break;
2952 case GOT_STATUS_DELETE:
2953 case GOT_STATUS_MISSING:
2954 err = (*a->progress_cb)(a->progress_arg,
2955 GOT_STATUS_DELETE, path1);
2956 if (err)
2957 goto done;
2958 if (ie)
2959 got_fileindex_entry_mark_deleted_from_disk(ie);
2960 break;
2961 case GOT_STATUS_ADD: {
2962 struct got_object_id *id;
2963 FILE *blob1_f;
2965 * Delete the added file only if its content already
2966 * exists in the repository.
2968 err = got_object_blob_file_create(&id, &blob1_f, path1);
2969 if (err)
2970 goto done;
2971 if (got_object_id_cmp(id, id1) == 0) {
2972 err = (*a->progress_cb)(a->progress_arg,
2973 GOT_STATUS_DELETE, path1);
2974 if (err)
2975 goto done;
2976 err = remove_ondisk_file(a->worktree->root_path,
2977 path1);
2978 if (err)
2979 goto done;
2980 if (ie)
2981 got_fileindex_entry_remove(a->fileindex,
2982 ie);
2983 } else {
2984 err = (*a->progress_cb)(a->progress_arg,
2985 GOT_STATUS_CANNOT_DELETE, path1);
2987 if (fclose(blob1_f) == EOF && err == NULL)
2988 err = got_error_from_errno("fclose");
2989 free(id);
2990 if (err)
2991 goto done;
2992 break;
2994 case GOT_STATUS_MODIFY:
2995 case GOT_STATUS_CONFLICT:
2996 err = (*a->progress_cb)(a->progress_arg,
2997 GOT_STATUS_CANNOT_DELETE, path1);
2998 if (err)
2999 goto done;
3000 break;
3001 case GOT_STATUS_OBSTRUCTED:
3002 err = (*a->progress_cb)(a->progress_arg, status, path1);
3003 if (err)
3004 goto done;
3005 break;
3006 default:
3007 break;
3009 } else if (blob2) {
3010 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3011 path2) == -1)
3012 return got_error_from_errno("asprintf");
3013 ie = got_fileindex_entry_get(a->fileindex, path2,
3014 strlen(path2));
3015 if (ie) {
3016 err = get_file_status(&status, &sb, ie, ondisk_path,
3017 -1, NULL, repo);
3018 if (err)
3019 goto done;
3020 if (status != GOT_STATUS_NO_CHANGE &&
3021 status != GOT_STATUS_MODIFY &&
3022 status != GOT_STATUS_CONFLICT &&
3023 status != GOT_STATUS_ADD) {
3024 err = (*a->progress_cb)(a->progress_arg,
3025 status, path2);
3026 goto done;
3028 if (S_ISLNK(mode2) && S_ISLNK(sb.st_mode)) {
3029 char *link_target2;
3030 err = got_object_blob_read_to_str(&link_target2,
3031 blob2);
3032 if (err)
3033 goto done;
3034 err = merge_symlink(a->worktree, NULL,
3035 ondisk_path, path2, a->label_orig,
3036 link_target2, a->commit_id2, repo,
3037 a->progress_cb, a->progress_arg);
3038 free(link_target2);
3039 } else if (S_ISREG(sb.st_mode)) {
3040 err = merge_blob(&local_changes_subsumed,
3041 a->worktree, NULL, ondisk_path, path2,
3042 sb.st_mode, a->label_orig, blob2,
3043 a->commit_id2, repo, a->progress_cb,
3044 a->progress_arg);
3045 } else {
3046 err = got_error_path(ondisk_path,
3047 GOT_ERR_FILE_OBSTRUCTED);
3049 if (err)
3050 goto done;
3051 if (status == GOT_STATUS_DELETE) {
3052 err = got_fileindex_entry_update(ie,
3053 a->worktree->root_fd, path2, blob2->id.sha1,
3054 a->worktree->base_commit_id->sha1, 0);
3055 if (err)
3056 goto done;
3058 } else {
3059 int is_bad_symlink = 0;
3060 sb.st_mode = GOT_DEFAULT_FILE_MODE;
3061 if (S_ISLNK(mode2)) {
3062 err = install_symlink(&is_bad_symlink,
3063 a->worktree, ondisk_path, path2, blob2, 0,
3064 0, 1, repo, a->progress_cb, a->progress_arg);
3065 } else {
3066 err = install_blob(a->worktree, ondisk_path, path2,
3067 mode2, sb.st_mode, blob2, 0, 0, 0, 1, repo,
3068 a->progress_cb, a->progress_arg);
3070 if (err)
3071 goto done;
3072 err = got_fileindex_entry_alloc(&ie, path2);
3073 if (err)
3074 goto done;
3075 err = got_fileindex_entry_update(ie,
3076 a->worktree->root_fd, path2, NULL, NULL, 1);
3077 if (err) {
3078 got_fileindex_entry_free(ie);
3079 goto done;
3081 err = got_fileindex_entry_add(a->fileindex, ie);
3082 if (err) {
3083 got_fileindex_entry_free(ie);
3084 goto done;
3086 if (is_bad_symlink) {
3087 got_fileindex_entry_filetype_set(ie,
3088 GOT_FILEIDX_MODE_BAD_SYMLINK);
3092 done:
3093 if (f_orig && fclose(f_orig) == EOF && err == NULL)
3094 err = got_error_from_errno("fclose");
3095 if (f_deriv && fclose(f_deriv) == EOF && err == NULL)
3096 err = got_error_from_errno("fclose");
3097 if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
3098 err = got_error_from_errno("fclose");
3099 free(id_str);
3100 free(label_deriv2);
3101 free(ondisk_path);
3102 return err;
3105 struct check_merge_ok_arg {
3106 struct got_worktree *worktree;
3107 struct got_repository *repo;
3110 static const struct got_error *
3111 check_merge_ok(void *arg, struct got_fileindex_entry *ie)
3113 const struct got_error *err = NULL;
3114 struct check_merge_ok_arg *a = arg;
3115 unsigned char status;
3116 struct stat sb;
3117 char *ondisk_path;
3119 /* Reject merges into a work tree with mixed base commits. */
3120 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
3121 SHA1_DIGEST_LENGTH))
3122 return got_error(GOT_ERR_MIXED_COMMITS);
3124 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
3125 == -1)
3126 return got_error_from_errno("asprintf");
3128 /* Reject merges into a work tree with conflicted files. */
3129 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
3130 if (err)
3131 return err;
3132 if (status == GOT_STATUS_CONFLICT)
3133 return got_error(GOT_ERR_CONFLICTS);
3135 return NULL;
3138 static const struct got_error *
3139 merge_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
3140 const char *fileindex_path, struct got_object_id *commit_id1,
3141 struct got_object_id *commit_id2, struct got_repository *repo,
3142 got_worktree_checkout_cb progress_cb, void *progress_arg,
3143 got_cancel_cb cancel_cb, void *cancel_arg)
3145 const struct got_error *err = NULL, *sync_err;
3146 struct got_object_id *tree_id1 = NULL, *tree_id2 = NULL;
3147 struct got_tree_object *tree1 = NULL, *tree2 = NULL;
3148 struct merge_file_cb_arg arg;
3149 char *label_orig = NULL;
3151 if (commit_id1) {
3152 err = got_object_id_by_path(&tree_id1, repo, commit_id1,
3153 worktree->path_prefix);
3154 if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
3155 goto done;
3157 if (tree_id1) {
3158 char *id_str;
3160 err = got_object_open_as_tree(&tree1, repo, tree_id1);
3161 if (err)
3162 goto done;
3164 err = got_object_id_str(&id_str, commit_id1);
3165 if (err)
3166 goto done;
3168 if (asprintf(&label_orig, "%s: commit %s",
3169 GOT_MERGE_LABEL_BASE, id_str) == -1) {
3170 err = got_error_from_errno("asprintf");
3171 free(id_str);
3172 goto done;
3174 free(id_str);
3177 err = got_object_id_by_path(&tree_id2, repo, commit_id2,
3178 worktree->path_prefix);
3179 if (err)
3180 goto done;
3182 err = got_object_open_as_tree(&tree2, repo, tree_id2);
3183 if (err)
3184 goto done;
3186 arg.worktree = worktree;
3187 arg.fileindex = fileindex;
3188 arg.progress_cb = progress_cb;
3189 arg.progress_arg = progress_arg;
3190 arg.cancel_cb = cancel_cb;
3191 arg.cancel_arg = cancel_arg;
3192 arg.label_orig = label_orig;
3193 arg.commit_id2 = commit_id2;
3194 err = got_diff_tree(tree1, tree2, "", "", repo, merge_file_cb, &arg, 1);
3195 sync_err = sync_fileindex(fileindex, fileindex_path);
3196 if (sync_err && err == NULL)
3197 err = sync_err;
3198 done:
3199 if (tree1)
3200 got_object_tree_close(tree1);
3201 if (tree2)
3202 got_object_tree_close(tree2);
3203 free(label_orig);
3204 return err;
3207 const struct got_error *
3208 got_worktree_merge_files(struct got_worktree *worktree,
3209 struct got_object_id *commit_id1, struct got_object_id *commit_id2,
3210 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
3211 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
3213 const struct got_error *err, *unlockerr;
3214 char *fileindex_path = NULL;
3215 struct got_fileindex *fileindex = NULL;
3216 struct check_merge_ok_arg mok_arg;
3218 err = lock_worktree(worktree, LOCK_EX);
3219 if (err)
3220 return err;
3222 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3223 if (err)
3224 goto done;
3226 mok_arg.worktree = worktree;
3227 mok_arg.repo = repo;
3228 err = got_fileindex_for_each_entry_safe(fileindex, check_merge_ok,
3229 &mok_arg);
3230 if (err)
3231 goto done;
3233 err = merge_files(worktree, fileindex, fileindex_path, commit_id1,
3234 commit_id2, repo, progress_cb, progress_arg, cancel_cb, cancel_arg);
3235 done:
3236 if (fileindex)
3237 got_fileindex_free(fileindex);
3238 free(fileindex_path);
3239 unlockerr = lock_worktree(worktree, LOCK_SH);
3240 if (unlockerr && err == NULL)
3241 err = unlockerr;
3242 return err;
3245 struct diff_dir_cb_arg {
3246 struct got_fileindex *fileindex;
3247 struct got_worktree *worktree;
3248 const char *status_path;
3249 size_t status_path_len;
3250 struct got_repository *repo;
3251 got_worktree_status_cb status_cb;
3252 void *status_arg;
3253 got_cancel_cb cancel_cb;
3254 void *cancel_arg;
3255 /* A pathlist containing per-directory pathlists of ignore patterns. */
3256 struct got_pathlist_head ignores;
3257 int report_unchanged;
3258 int no_ignores;
3261 static const struct got_error *
3262 report_file_status(struct got_fileindex_entry *ie, const char *abspath,
3263 int dirfd, const char *de_name,
3264 got_worktree_status_cb status_cb, void *status_arg,
3265 struct got_repository *repo, int report_unchanged)
3267 const struct got_error *err = NULL;
3268 unsigned char status = GOT_STATUS_NO_CHANGE;
3269 unsigned char staged_status = get_staged_status(ie);
3270 struct stat sb;
3271 struct got_object_id blob_id, commit_id, staged_blob_id;
3272 struct got_object_id *blob_idp = NULL, *commit_idp = NULL;
3273 struct got_object_id *staged_blob_idp = NULL;
3275 err = get_file_status(&status, &sb, ie, abspath, dirfd, de_name, repo);
3276 if (err)
3277 return err;
3279 if (status == GOT_STATUS_NO_CHANGE &&
3280 staged_status == GOT_STATUS_NO_CHANGE && !report_unchanged)
3281 return NULL;
3283 if (got_fileindex_entry_has_blob(ie)) {
3284 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
3285 blob_idp = &blob_id;
3287 if (got_fileindex_entry_has_commit(ie)) {
3288 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
3289 commit_idp = &commit_id;
3291 if (staged_status == GOT_STATUS_ADD ||
3292 staged_status == GOT_STATUS_MODIFY) {
3293 memcpy(staged_blob_id.sha1, ie->staged_blob_sha1,
3294 SHA1_DIGEST_LENGTH);
3295 staged_blob_idp = &staged_blob_id;
3298 return (*status_cb)(status_arg, status, staged_status,
3299 ie->path, blob_idp, staged_blob_idp, commit_idp, dirfd, de_name);
3302 static const struct got_error *
3303 status_old_new(void *arg, struct got_fileindex_entry *ie,
3304 struct dirent *de, const char *parent_path, int dirfd)
3306 const struct got_error *err = NULL;
3307 struct diff_dir_cb_arg *a = arg;
3308 char *abspath;
3310 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3311 return got_error(GOT_ERR_CANCELLED);
3313 if (got_path_cmp(parent_path, a->status_path,
3314 strlen(parent_path), a->status_path_len) != 0 &&
3315 !got_path_is_child(parent_path, a->status_path, a->status_path_len))
3316 return NULL;
3318 if (parent_path[0]) {
3319 if (asprintf(&abspath, "%s/%s/%s", a->worktree->root_path,
3320 parent_path, de->d_name) == -1)
3321 return got_error_from_errno("asprintf");
3322 } else {
3323 if (asprintf(&abspath, "%s/%s", a->worktree->root_path,
3324 de->d_name) == -1)
3325 return got_error_from_errno("asprintf");
3328 err = report_file_status(ie, abspath, dirfd, de->d_name,
3329 a->status_cb, a->status_arg, a->repo, a->report_unchanged);
3330 free(abspath);
3331 return err;
3334 static const struct got_error *
3335 status_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
3337 struct diff_dir_cb_arg *a = arg;
3338 struct got_object_id blob_id, commit_id;
3339 unsigned char status;
3341 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3342 return got_error(GOT_ERR_CANCELLED);
3344 if (!got_path_is_child(ie->path, a->status_path, a->status_path_len))
3345 return NULL;
3347 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
3348 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
3349 if (got_fileindex_entry_has_file_on_disk(ie))
3350 status = GOT_STATUS_MISSING;
3351 else
3352 status = GOT_STATUS_DELETE;
3353 return (*a->status_cb)(a->status_arg, status, get_staged_status(ie),
3354 ie->path, &blob_id, NULL, &commit_id, -1, NULL);
3357 void
3358 free_ignorelist(struct got_pathlist_head *ignorelist)
3360 struct got_pathlist_entry *pe;
3362 TAILQ_FOREACH(pe, ignorelist, entry)
3363 free((char *)pe->path);
3364 got_pathlist_free(ignorelist);
3367 void
3368 free_ignores(struct got_pathlist_head *ignores)
3370 struct got_pathlist_entry *pe;
3372 TAILQ_FOREACH(pe, ignores, entry) {
3373 struct got_pathlist_head *ignorelist = pe->data;
3374 free_ignorelist(ignorelist);
3375 free((char *)pe->path);
3377 got_pathlist_free(ignores);
3380 static const struct got_error *
3381 read_ignores(struct got_pathlist_head *ignores, const char *path, FILE *f)
3383 const struct got_error *err = NULL;
3384 struct got_pathlist_entry *pe = NULL;
3385 struct got_pathlist_head *ignorelist;
3386 char *line = NULL, *pattern, *dirpath = NULL;
3387 size_t linesize = 0;
3388 ssize_t linelen;
3390 ignorelist = calloc(1, sizeof(*ignorelist));
3391 if (ignorelist == NULL)
3392 return got_error_from_errno("calloc");
3393 TAILQ_INIT(ignorelist);
3395 while ((linelen = getline(&line, &linesize, f)) != -1) {
3396 if (linelen > 0 && line[linelen - 1] == '\n')
3397 line[linelen - 1] = '\0';
3399 /* Git's ignores may contain comments. */
3400 if (line[0] == '#')
3401 continue;
3403 /* Git's negated patterns are not (yet?) supported. */
3404 if (line[0] == '!')
3405 continue;
3407 if (asprintf(&pattern, "%s%s%s", path, path[0] ? "/" : "",
3408 line) == -1) {
3409 err = got_error_from_errno("asprintf");
3410 goto done;
3412 err = got_pathlist_insert(NULL, ignorelist, pattern, NULL);
3413 if (err)
3414 goto done;
3416 if (ferror(f)) {
3417 err = got_error_from_errno("getline");
3418 goto done;
3421 dirpath = strdup(path);
3422 if (dirpath == NULL) {
3423 err = got_error_from_errno("strdup");
3424 goto done;
3426 err = got_pathlist_insert(&pe, ignores, dirpath, ignorelist);
3427 done:
3428 free(line);
3429 if (err || pe == NULL) {
3430 free(dirpath);
3431 free_ignorelist(ignorelist);
3433 return err;
3436 int
3437 match_ignores(struct got_pathlist_head *ignores, const char *path)
3439 struct got_pathlist_entry *pe;
3441 /* Handle patterns which match in all directories. */
3442 TAILQ_FOREACH(pe, ignores, entry) {
3443 struct got_pathlist_head *ignorelist = pe->data;
3444 struct got_pathlist_entry *pi;
3446 TAILQ_FOREACH(pi, ignorelist, entry) {
3447 const char *p, *pattern = pi->path;
3449 if (strncmp(pattern, "**/", 3) != 0)
3450 continue;
3451 pattern += 3;
3452 p = path;
3453 while (*p) {
3454 if (fnmatch(pattern, p,
3455 FNM_PATHNAME | FNM_LEADING_DIR)) {
3456 /* Retry in next directory. */
3457 while (*p && *p != '/')
3458 p++;
3459 while (*p == '/')
3460 p++;
3461 continue;
3463 return 1;
3469 * The ignores pathlist contains ignore lists from children before
3470 * parents, so we can find the most specific ignorelist by walking
3471 * ignores backwards.
3473 pe = TAILQ_LAST(ignores, got_pathlist_head);
3474 while (pe) {
3475 if (got_path_is_child(path, pe->path, pe->path_len)) {
3476 struct got_pathlist_head *ignorelist = pe->data;
3477 struct got_pathlist_entry *pi;
3478 TAILQ_FOREACH(pi, ignorelist, entry) {
3479 const char *pattern = pi->path;
3480 int flags = FNM_LEADING_DIR;
3481 if (strstr(pattern, "/**/") == NULL)
3482 flags |= FNM_PATHNAME;
3483 if (fnmatch(pattern, path, flags))
3484 continue;
3485 return 1;
3488 pe = TAILQ_PREV(pe, got_pathlist_head, entry);
3491 return 0;
3494 static const struct got_error *
3495 add_ignores(struct got_pathlist_head *ignores, const char *root_path,
3496 const char *path, int dirfd, const char *ignores_filename)
3498 const struct got_error *err = NULL;
3499 char *ignorespath;
3500 int fd = -1;
3501 FILE *ignoresfile = NULL;
3503 if (asprintf(&ignorespath, "%s/%s%s%s", root_path, path,
3504 path[0] ? "/" : "", ignores_filename) == -1)
3505 return got_error_from_errno("asprintf");
3507 if (dirfd != -1) {
3508 fd = openat(dirfd, ignores_filename, O_RDONLY | O_NOFOLLOW);
3509 if (fd == -1) {
3510 if (errno != ENOENT && errno != EACCES)
3511 err = got_error_from_errno2("openat",
3512 ignorespath);
3513 } else {
3514 ignoresfile = fdopen(fd, "r");
3515 if (ignoresfile == NULL)
3516 err = got_error_from_errno2("fdopen",
3517 ignorespath);
3518 else {
3519 fd = -1;
3520 err = read_ignores(ignores, path, ignoresfile);
3523 } else {
3524 ignoresfile = fopen(ignorespath, "r");
3525 if (ignoresfile == NULL) {
3526 if (errno != ENOENT && errno != EACCES)
3527 err = got_error_from_errno2("fopen",
3528 ignorespath);
3529 } else
3530 err = read_ignores(ignores, path, ignoresfile);
3533 if (ignoresfile && fclose(ignoresfile) == EOF && err == NULL)
3534 err = got_error_from_errno2("fclose", path);
3535 if (fd != -1 && close(fd) == -1 && err == NULL)
3536 err = got_error_from_errno2("close", path);
3537 free(ignorespath);
3538 return err;
3541 static const struct got_error *
3542 status_new(void *arg, struct dirent *de, const char *parent_path, int dirfd)
3544 const struct got_error *err = NULL;
3545 struct diff_dir_cb_arg *a = arg;
3546 char *path = NULL;
3548 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3549 return got_error(GOT_ERR_CANCELLED);
3551 if (parent_path[0]) {
3552 if (asprintf(&path, "%s/%s", parent_path, de->d_name) == -1)
3553 return got_error_from_errno("asprintf");
3554 } else {
3555 path = de->d_name;
3558 if (de->d_type != DT_DIR &&
3559 got_path_is_child(path, a->status_path, a->status_path_len)
3560 && !match_ignores(&a->ignores, path))
3561 err = (*a->status_cb)(a->status_arg, GOT_STATUS_UNVERSIONED,
3562 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3563 if (parent_path[0])
3564 free(path);
3565 return err;
3568 static const struct got_error *
3569 status_traverse(void *arg, const char *path, int dirfd)
3571 const struct got_error *err = NULL;
3572 struct diff_dir_cb_arg *a = arg;
3574 if (a->no_ignores)
3575 return NULL;
3577 err = add_ignores(&a->ignores, a->worktree->root_path,
3578 path, dirfd, ".cvsignore");
3579 if (err)
3580 return err;
3582 err = add_ignores(&a->ignores, a->worktree->root_path, path,
3583 dirfd, ".gitignore");
3585 return err;
3588 static const struct got_error *
3589 report_single_file_status(const char *path, const char *ondisk_path,
3590 struct got_fileindex *fileindex, got_worktree_status_cb status_cb,
3591 void *status_arg, struct got_repository *repo, int report_unchanged)
3593 struct got_fileindex_entry *ie;
3594 struct stat sb;
3596 ie = got_fileindex_entry_get(fileindex, path, strlen(path));
3597 if (ie)
3598 return report_file_status(ie, ondisk_path, -1, NULL,
3599 status_cb, status_arg, repo, report_unchanged);
3601 if (lstat(ondisk_path, &sb) == -1) {
3602 if (errno != ENOENT)
3603 return got_error_from_errno2("lstat", ondisk_path);
3604 return (*status_cb)(status_arg, GOT_STATUS_NONEXISTENT,
3605 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3606 return NULL;
3609 if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode))
3610 return (*status_cb)(status_arg, GOT_STATUS_UNVERSIONED,
3611 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3613 return NULL;
3616 static const struct got_error *
3617 add_ignores_from_parent_paths(struct got_pathlist_head *ignores,
3618 const char *root_path, const char *path)
3620 const struct got_error *err;
3621 char *parent_path, *next_parent_path = NULL;
3623 err = add_ignores(ignores, root_path, "", -1,
3624 ".cvsignore");
3625 if (err)
3626 return err;
3628 err = add_ignores(ignores, root_path, "", -1,
3629 ".gitignore");
3630 if (err)
3631 return err;
3633 err = got_path_dirname(&parent_path, path);
3634 if (err) {
3635 if (err->code == GOT_ERR_BAD_PATH)
3636 return NULL; /* cannot traverse parent */
3637 return err;
3639 for (;;) {
3640 err = add_ignores(ignores, root_path, parent_path, -1,
3641 ".cvsignore");
3642 if (err)
3643 break;
3644 err = add_ignores(ignores, root_path, parent_path, -1,
3645 ".gitignore");
3646 if (err)
3647 break;
3648 err = got_path_dirname(&next_parent_path, parent_path);
3649 if (err) {
3650 if (err->code == GOT_ERR_BAD_PATH)
3651 err = NULL; /* traversed everything */
3652 break;
3654 free(parent_path);
3655 parent_path = next_parent_path;
3656 next_parent_path = NULL;
3659 free(parent_path);
3660 free(next_parent_path);
3661 return err;
3664 static const struct got_error *
3665 worktree_status(struct got_worktree *worktree, const char *path,
3666 struct got_fileindex *fileindex, struct got_repository *repo,
3667 got_worktree_status_cb status_cb, void *status_arg,
3668 got_cancel_cb cancel_cb, void *cancel_arg, int no_ignores,
3669 int report_unchanged)
3671 const struct got_error *err = NULL;
3672 int fd = -1;
3673 struct got_fileindex_diff_dir_cb fdiff_cb;
3674 struct diff_dir_cb_arg arg;
3675 char *ondisk_path = NULL;
3677 TAILQ_INIT(&arg.ignores);
3679 if (asprintf(&ondisk_path, "%s%s%s",
3680 worktree->root_path, path[0] ? "/" : "", path) == -1)
3681 return got_error_from_errno("asprintf");
3683 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_DIRECTORY);
3684 if (fd == -1) {
3685 if (errno != ENOTDIR && errno != ENOENT && errno != EACCES &&
3686 errno != ELOOP)
3687 err = got_error_from_errno2("open", ondisk_path);
3688 else
3689 err = report_single_file_status(path, ondisk_path,
3690 fileindex, status_cb, status_arg, repo,
3691 report_unchanged);
3692 } else {
3693 fdiff_cb.diff_old_new = status_old_new;
3694 fdiff_cb.diff_old = status_old;
3695 fdiff_cb.diff_new = status_new;
3696 fdiff_cb.diff_traverse = status_traverse;
3697 arg.fileindex = fileindex;
3698 arg.worktree = worktree;
3699 arg.status_path = path;
3700 arg.status_path_len = strlen(path);
3701 arg.repo = repo;
3702 arg.status_cb = status_cb;
3703 arg.status_arg = status_arg;
3704 arg.cancel_cb = cancel_cb;
3705 arg.cancel_arg = cancel_arg;
3706 arg.report_unchanged = report_unchanged;
3707 arg.no_ignores = no_ignores;
3708 if (!no_ignores) {
3709 err = add_ignores_from_parent_paths(&arg.ignores,
3710 worktree->root_path, path);
3711 if (err)
3712 goto done;
3714 err = got_fileindex_diff_dir(fileindex, fd,
3715 worktree->root_path, path, repo, &fdiff_cb, &arg);
3717 done:
3718 free_ignores(&arg.ignores);
3719 if (fd != -1 && close(fd) == -1 && err == NULL)
3720 err = got_error_from_errno("close");
3721 free(ondisk_path);
3722 return err;
3725 const struct got_error *
3726 got_worktree_status(struct got_worktree *worktree,
3727 struct got_pathlist_head *paths, struct got_repository *repo,
3728 got_worktree_status_cb status_cb, void *status_arg,
3729 got_cancel_cb cancel_cb, void *cancel_arg)
3731 const struct got_error *err = NULL;
3732 char *fileindex_path = NULL;
3733 struct got_fileindex *fileindex = NULL;
3734 struct got_pathlist_entry *pe;
3736 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3737 if (err)
3738 return err;
3740 TAILQ_FOREACH(pe, paths, entry) {
3741 err = worktree_status(worktree, pe->path, fileindex, repo,
3742 status_cb, status_arg, cancel_cb, cancel_arg, 0, 0);
3743 if (err)
3744 break;
3746 free(fileindex_path);
3747 got_fileindex_free(fileindex);
3748 return err;
3751 const struct got_error *
3752 got_worktree_resolve_path(char **wt_path, struct got_worktree *worktree,
3753 const char *arg)
3755 const struct got_error *err = NULL;
3756 char *resolved = NULL, *cwd = NULL, *path = NULL;
3757 size_t len;
3758 struct stat sb;
3759 char *abspath = NULL;
3760 char canonpath[PATH_MAX];
3762 *wt_path = NULL;
3764 cwd = getcwd(NULL, 0);
3765 if (cwd == NULL)
3766 return got_error_from_errno("getcwd");
3768 if (lstat(arg, &sb) == -1) {
3769 if (errno != ENOENT) {
3770 err = got_error_from_errno2("lstat", arg);
3771 goto done;
3773 sb.st_mode = 0;
3775 if (S_ISLNK(sb.st_mode)) {
3777 * We cannot use realpath(3) with symlinks since we want to
3778 * operate on the symlink itself.
3779 * But we can make the path absolute, assuming it is relative
3780 * to the current working directory, and then canonicalize it.
3782 if (!got_path_is_absolute(arg)) {
3783 if (asprintf(&abspath, "%s/%s", cwd, arg) == -1) {
3784 err = got_error_from_errno("asprintf");
3785 goto done;
3789 err = got_canonpath(abspath ? abspath : arg, canonpath,
3790 sizeof(canonpath));
3791 if (err)
3792 goto done;
3793 resolved = strdup(canonpath);
3794 if (resolved == NULL) {
3795 err = got_error_from_errno("strdup");
3796 goto done;
3798 } else {
3799 resolved = realpath(arg, NULL);
3800 if (resolved == NULL) {
3801 if (errno != ENOENT) {
3802 err = got_error_from_errno2("realpath", arg);
3803 goto done;
3805 if (asprintf(&abspath, "%s/%s", cwd, arg) == -1) {
3806 err = got_error_from_errno("asprintf");
3807 goto done;
3809 err = got_canonpath(abspath, canonpath,
3810 sizeof(canonpath));
3811 if (err)
3812 goto done;
3813 resolved = strdup(canonpath);
3814 if (resolved == NULL) {
3815 err = got_error_from_errno("strdup");
3816 goto done;
3821 if (strncmp(got_worktree_get_root_path(worktree), resolved,
3822 strlen(got_worktree_get_root_path(worktree)))) {
3823 err = got_error_path(resolved, GOT_ERR_BAD_PATH);
3824 goto done;
3827 if (strlen(resolved) > strlen(got_worktree_get_root_path(worktree))) {
3828 err = got_path_skip_common_ancestor(&path,
3829 got_worktree_get_root_path(worktree), resolved);
3830 if (err)
3831 goto done;
3832 } else {
3833 path = strdup("");
3834 if (path == NULL) {
3835 err = got_error_from_errno("strdup");
3836 goto done;
3840 /* XXX status walk can't deal with trailing slash! */
3841 len = strlen(path);
3842 while (len > 0 && path[len - 1] == '/') {
3843 path[len - 1] = '\0';
3844 len--;
3846 done:
3847 free(abspath);
3848 free(resolved);
3849 free(cwd);
3850 if (err == NULL)
3851 *wt_path = path;
3852 else
3853 free(path);
3854 return err;
3857 struct schedule_addition_args {
3858 struct got_worktree *worktree;
3859 struct got_fileindex *fileindex;
3860 got_worktree_checkout_cb progress_cb;
3861 void *progress_arg;
3862 struct got_repository *repo;
3865 static const struct got_error *
3866 schedule_addition(void *arg, unsigned char status, unsigned char staged_status,
3867 const char *relpath, struct got_object_id *blob_id,
3868 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
3869 int dirfd, const char *de_name)
3871 struct schedule_addition_args *a = arg;
3872 const struct got_error *err = NULL;
3873 struct got_fileindex_entry *ie;
3874 struct stat sb;
3875 char *ondisk_path;
3877 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3878 relpath) == -1)
3879 return got_error_from_errno("asprintf");
3881 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3882 if (ie) {
3883 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd,
3884 de_name, a->repo);
3885 if (err)
3886 goto done;
3887 /* Re-adding an existing entry is a no-op. */
3888 if (status == GOT_STATUS_ADD)
3889 goto done;
3890 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
3891 if (err)
3892 goto done;
3895 if (status != GOT_STATUS_UNVERSIONED) {
3896 err = got_error_path(ondisk_path, GOT_ERR_FILE_STATUS);
3897 goto done;
3900 err = got_fileindex_entry_alloc(&ie, relpath);
3901 if (err)
3902 goto done;
3903 err = got_fileindex_entry_update(ie, a->worktree->root_fd,
3904 relpath, NULL, NULL, 1);
3905 if (err) {
3906 got_fileindex_entry_free(ie);
3907 goto done;
3909 err = got_fileindex_entry_add(a->fileindex, ie);
3910 if (err) {
3911 got_fileindex_entry_free(ie);
3912 goto done;
3914 done:
3915 free(ondisk_path);
3916 if (err)
3917 return err;
3918 if (status == GOT_STATUS_ADD)
3919 return NULL;
3920 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_ADD, relpath);
3923 const struct got_error *
3924 got_worktree_schedule_add(struct got_worktree *worktree,
3925 struct got_pathlist_head *paths,
3926 got_worktree_checkout_cb progress_cb, void *progress_arg,
3927 struct got_repository *repo, int no_ignores)
3929 struct got_fileindex *fileindex = NULL;
3930 char *fileindex_path = NULL;
3931 const struct got_error *err = NULL, *sync_err, *unlockerr;
3932 struct got_pathlist_entry *pe;
3933 struct schedule_addition_args saa;
3935 err = lock_worktree(worktree, LOCK_EX);
3936 if (err)
3937 return err;
3939 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3940 if (err)
3941 goto done;
3943 saa.worktree = worktree;
3944 saa.fileindex = fileindex;
3945 saa.progress_cb = progress_cb;
3946 saa.progress_arg = progress_arg;
3947 saa.repo = repo;
3949 TAILQ_FOREACH(pe, paths, entry) {
3950 err = worktree_status(worktree, pe->path, fileindex, repo,
3951 schedule_addition, &saa, NULL, NULL, no_ignores, 0);
3952 if (err)
3953 break;
3955 sync_err = sync_fileindex(fileindex, fileindex_path);
3956 if (sync_err && err == NULL)
3957 err = sync_err;
3958 done:
3959 free(fileindex_path);
3960 if (fileindex)
3961 got_fileindex_free(fileindex);
3962 unlockerr = lock_worktree(worktree, LOCK_SH);
3963 if (unlockerr && err == NULL)
3964 err = unlockerr;
3965 return err;
3968 struct schedule_deletion_args {
3969 struct got_worktree *worktree;
3970 struct got_fileindex *fileindex;
3971 got_worktree_delete_cb progress_cb;
3972 void *progress_arg;
3973 struct got_repository *repo;
3974 int delete_local_mods;
3975 int keep_on_disk;
3976 const char *status_codes;
3979 static const struct got_error *
3980 schedule_for_deletion(void *arg, unsigned char status,
3981 unsigned char staged_status, const char *relpath,
3982 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
3983 struct got_object_id *commit_id, int dirfd, const char *de_name)
3985 struct schedule_deletion_args *a = arg;
3986 const struct got_error *err = NULL;
3987 struct got_fileindex_entry *ie = NULL;
3988 struct stat sb;
3989 char *ondisk_path;
3991 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3992 if (ie == NULL)
3993 return got_error_path(relpath, GOT_ERR_BAD_PATH);
3995 staged_status = get_staged_status(ie);
3996 if (staged_status != GOT_STATUS_NO_CHANGE) {
3997 if (staged_status == GOT_STATUS_DELETE)
3998 return NULL;
3999 return got_error_path(relpath, GOT_ERR_FILE_STAGED);
4002 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
4003 relpath) == -1)
4004 return got_error_from_errno("asprintf");
4006 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd, de_name,
4007 a->repo);
4008 if (err)
4009 goto done;
4011 if (a->status_codes) {
4012 size_t ncodes = strlen(a->status_codes);
4013 int i;
4014 for (i = 0; i < ncodes ; i++) {
4015 if (status == a->status_codes[i])
4016 break;
4018 if (i == ncodes) {
4019 /* Do not delete files in non-matching status. */
4020 free(ondisk_path);
4021 return NULL;
4023 if (a->status_codes[i] != GOT_STATUS_MODIFY &&
4024 a->status_codes[i] != GOT_STATUS_MISSING) {
4025 static char msg[64];
4026 snprintf(msg, sizeof(msg),
4027 "invalid status code '%c'", a->status_codes[i]);
4028 err = got_error_msg(GOT_ERR_FILE_STATUS, msg);
4029 goto done;
4033 if (status != GOT_STATUS_NO_CHANGE) {
4034 if (status == GOT_STATUS_DELETE)
4035 goto done;
4036 if (status == GOT_STATUS_MODIFY && !a->delete_local_mods) {
4037 err = got_error_path(relpath, GOT_ERR_FILE_MODIFIED);
4038 goto done;
4040 if (status != GOT_STATUS_MODIFY &&
4041 status != GOT_STATUS_MISSING) {
4042 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
4043 goto done;
4047 if (!a->keep_on_disk && status != GOT_STATUS_MISSING) {
4048 size_t root_len;
4050 if (dirfd != -1) {
4051 if (unlinkat(dirfd, de_name, 0) != 0) {
4052 err = got_error_from_errno2("unlinkat",
4053 ondisk_path);
4054 goto done;
4056 } else if (unlink(ondisk_path) != 0) {
4057 err = got_error_from_errno2("unlink", ondisk_path);
4058 goto done;
4061 root_len = strlen(a->worktree->root_path);
4062 do {
4063 char *parent;
4064 err = got_path_dirname(&parent, ondisk_path);
4065 if (err)
4066 goto done;
4067 free(ondisk_path);
4068 ondisk_path = parent;
4069 if (rmdir(ondisk_path) == -1) {
4070 if (errno != ENOTEMPTY)
4071 err = got_error_from_errno2("rmdir",
4072 ondisk_path);
4073 break;
4075 } while (got_path_cmp(ondisk_path, a->worktree->root_path,
4076 strlen(ondisk_path), root_len) != 0);
4079 got_fileindex_entry_mark_deleted_from_disk(ie);
4080 done:
4081 free(ondisk_path);
4082 if (err)
4083 return err;
4084 if (status == GOT_STATUS_DELETE)
4085 return NULL;
4086 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE,
4087 staged_status, relpath);
4090 const struct got_error *
4091 got_worktree_schedule_delete(struct got_worktree *worktree,
4092 struct got_pathlist_head *paths, int delete_local_mods,
4093 const char *status_codes,
4094 got_worktree_delete_cb progress_cb, void *progress_arg,
4095 struct got_repository *repo, int keep_on_disk)
4097 struct got_fileindex *fileindex = NULL;
4098 char *fileindex_path = NULL;
4099 const struct got_error *err = NULL, *sync_err, *unlockerr;
4100 struct got_pathlist_entry *pe;
4101 struct schedule_deletion_args sda;
4103 err = lock_worktree(worktree, LOCK_EX);
4104 if (err)
4105 return err;
4107 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4108 if (err)
4109 goto done;
4111 sda.worktree = worktree;
4112 sda.fileindex = fileindex;
4113 sda.progress_cb = progress_cb;
4114 sda.progress_arg = progress_arg;
4115 sda.repo = repo;
4116 sda.delete_local_mods = delete_local_mods;
4117 sda.keep_on_disk = keep_on_disk;
4118 sda.status_codes = status_codes;
4120 TAILQ_FOREACH(pe, paths, entry) {
4121 err = worktree_status(worktree, pe->path, fileindex, repo,
4122 schedule_for_deletion, &sda, NULL, NULL, 0, 1);
4123 if (err)
4124 break;
4126 sync_err = sync_fileindex(fileindex, fileindex_path);
4127 if (sync_err && err == NULL)
4128 err = sync_err;
4129 done:
4130 free(fileindex_path);
4131 if (fileindex)
4132 got_fileindex_free(fileindex);
4133 unlockerr = lock_worktree(worktree, LOCK_SH);
4134 if (unlockerr && err == NULL)
4135 err = unlockerr;
4136 return err;
4139 static const struct got_error *
4140 copy_one_line(FILE *infile, FILE *outfile, FILE *rejectfile)
4142 const struct got_error *err = NULL;
4143 char *line = NULL;
4144 size_t linesize = 0, n;
4145 ssize_t linelen;
4147 linelen = getline(&line, &linesize, infile);
4148 if (linelen == -1) {
4149 if (ferror(infile)) {
4150 err = got_error_from_errno("getline");
4151 goto done;
4153 return NULL;
4155 if (outfile) {
4156 n = fwrite(line, 1, linelen, outfile);
4157 if (n != linelen) {
4158 err = got_ferror(outfile, GOT_ERR_IO);
4159 goto done;
4162 if (rejectfile) {
4163 n = fwrite(line, 1, linelen, rejectfile);
4164 if (n != linelen)
4165 err = got_ferror(outfile, GOT_ERR_IO);
4167 done:
4168 free(line);
4169 return err;
4172 static const struct got_error *
4173 skip_one_line(FILE *f)
4175 char *line = NULL;
4176 size_t linesize = 0;
4177 ssize_t linelen;
4179 linelen = getline(&line, &linesize, f);
4180 if (linelen == -1) {
4181 if (ferror(f))
4182 return got_error_from_errno("getline");
4183 return NULL;
4185 free(line);
4186 return NULL;
4189 static const struct got_error *
4190 copy_change(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
4191 int start_old, int end_old, int start_new, int end_new,
4192 FILE *outfile, FILE *rejectfile)
4194 const struct got_error *err;
4196 /* Copy old file's lines leading up to patch. */
4197 while (!feof(f1) && *line_cur1 < start_old) {
4198 err = copy_one_line(f1, outfile, NULL);
4199 if (err)
4200 return err;
4201 (*line_cur1)++;
4203 /* Skip new file's lines leading up to patch. */
4204 while (!feof(f2) && *line_cur2 < start_new) {
4205 if (rejectfile)
4206 err = copy_one_line(f2, NULL, rejectfile);
4207 else
4208 err = skip_one_line(f2);
4209 if (err)
4210 return err;
4211 (*line_cur2)++;
4213 /* Copy patched lines. */
4214 while (!feof(f2) && *line_cur2 <= end_new) {
4215 err = copy_one_line(f2, outfile, NULL);
4216 if (err)
4217 return err;
4218 (*line_cur2)++;
4220 /* Skip over old file's replaced lines. */
4221 while (!feof(f1) && *line_cur1 <= end_old) {
4222 if (rejectfile)
4223 err = copy_one_line(f1, NULL, rejectfile);
4224 else
4225 err = skip_one_line(f1);
4226 if (err)
4227 return err;
4228 (*line_cur1)++;
4231 return NULL;
4234 static const struct got_error *
4235 copy_remaining_content(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
4236 FILE *outfile, FILE *rejectfile)
4238 const struct got_error *err;
4240 if (outfile) {
4241 /* Copy old file's lines until EOF. */
4242 while (!feof(f1)) {
4243 err = copy_one_line(f1, outfile, NULL);
4244 if (err)
4245 return err;
4246 (*line_cur1)++;
4249 if (rejectfile) {
4250 /* Copy new file's lines until EOF. */
4251 while (!feof(f2)) {
4252 err = copy_one_line(f2, NULL, rejectfile);
4253 if (err)
4254 return err;
4255 (*line_cur2)++;
4259 return NULL;
4262 static const struct got_error *
4263 apply_or_reject_change(int *choice, int *nchunks_used,
4264 struct diff_result *diff_result, int n,
4265 const char *relpath, FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
4266 FILE *outfile, FILE *rejectfile, int changeno, int nchanges,
4267 got_worktree_patch_cb patch_cb, void *patch_arg)
4269 const struct got_error *err = NULL;
4270 struct diff_chunk_context cc = {};
4271 int start_old, end_old, start_new, end_new;
4272 FILE *hunkfile;
4273 struct diff_output_unidiff_state *diff_state;
4274 struct diff_input_info diff_info;
4275 int rc;
4277 *choice = GOT_PATCH_CHOICE_NONE;
4279 /* Get changed line numbers without context lines for copy_change(). */
4280 diff_chunk_context_load_change(&cc, NULL, diff_result, n, 0);
4281 start_old = cc.left.start;
4282 end_old = cc.left.end;
4283 start_new = cc.right.start;
4284 end_new = cc.right.end;
4286 /* Get the same change with context lines for display. */
4287 memset(&cc, 0, sizeof(cc));
4288 diff_chunk_context_load_change(&cc, nchunks_used, diff_result, n, 3);
4290 memset(&diff_info, 0, sizeof(diff_info));
4291 diff_info.left_path = relpath;
4292 diff_info.right_path = relpath;
4294 diff_state = diff_output_unidiff_state_alloc();
4295 if (diff_state == NULL)
4296 return got_error_set_errno(ENOMEM,
4297 "diff_output_unidiff_state_alloc");
4299 hunkfile = got_opentemp();
4300 if (hunkfile == NULL) {
4301 err = got_error_from_errno("got_opentemp");
4302 goto done;
4305 rc = diff_output_unidiff_chunk(NULL, hunkfile, diff_state, &diff_info,
4306 diff_result, &cc);
4307 if (rc != DIFF_RC_OK) {
4308 err = got_error_set_errno(rc, "diff_output_unidiff_chunk");
4309 goto done;
4312 if (fseek(hunkfile, 0L, SEEK_SET) == -1) {
4313 err = got_ferror(hunkfile, GOT_ERR_IO);
4314 goto done;
4317 err = (*patch_cb)(choice, patch_arg, GOT_STATUS_MODIFY, relpath,
4318 hunkfile, changeno, nchanges);
4319 if (err)
4320 goto done;
4322 switch (*choice) {
4323 case GOT_PATCH_CHOICE_YES:
4324 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
4325 end_old, start_new, end_new, outfile, rejectfile);
4326 break;
4327 case GOT_PATCH_CHOICE_NO:
4328 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
4329 end_old, start_new, end_new, rejectfile, outfile);
4330 break;
4331 case GOT_PATCH_CHOICE_QUIT:
4332 break;
4333 default:
4334 err = got_error(GOT_ERR_PATCH_CHOICE);
4335 break;
4337 done:
4338 diff_output_unidiff_state_free(diff_state);
4339 if (hunkfile && fclose(hunkfile) == EOF && err == NULL)
4340 err = got_error_from_errno("fclose");
4341 return err;
4344 struct revert_file_args {
4345 struct got_worktree *worktree;
4346 struct got_fileindex *fileindex;
4347 got_worktree_checkout_cb progress_cb;
4348 void *progress_arg;
4349 got_worktree_patch_cb patch_cb;
4350 void *patch_arg;
4351 struct got_repository *repo;
4354 static const struct got_error *
4355 create_patched_content(char **path_outfile, int reverse_patch,
4356 struct got_object_id *blob_id, const char *path2,
4357 int dirfd2, const char *de_name2,
4358 const char *relpath, struct got_repository *repo,
4359 got_worktree_patch_cb patch_cb, void *patch_arg)
4361 const struct got_error *err, *free_err;
4362 struct got_blob_object *blob = NULL;
4363 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL;
4364 int fd2 = -1;
4365 char link_target[PATH_MAX];
4366 ssize_t link_len = 0;
4367 char *path1 = NULL, *id_str = NULL;
4368 struct stat sb2;
4369 struct got_diffreg_result *diffreg_result = NULL;
4370 int line_cur1 = 1, line_cur2 = 1, have_content = 0;
4371 int i = 0, n = 0, nchunks_used = 0, nchanges = 0;
4373 *path_outfile = NULL;
4375 err = got_object_id_str(&id_str, blob_id);
4376 if (err)
4377 return err;
4379 if (dirfd2 != -1) {
4380 fd2 = openat(dirfd2, de_name2, O_RDONLY | O_NOFOLLOW);
4381 if (fd2 == -1) {
4382 if (errno != ELOOP) {
4383 err = got_error_from_errno2("openat", path2);
4384 goto done;
4386 link_len = readlinkat(dirfd2, de_name2,
4387 link_target, sizeof(link_target));
4388 if (link_len == -1)
4389 return got_error_from_errno2("readlinkat", path2);
4390 sb2.st_mode = S_IFLNK;
4391 sb2.st_size = link_len;
4393 } else {
4394 fd2 = open(path2, O_RDONLY | O_NOFOLLOW);
4395 if (fd2 == -1) {
4396 if (errno != ELOOP) {
4397 err = got_error_from_errno2("open", path2);
4398 goto done;
4400 link_len = readlink(path2, link_target,
4401 sizeof(link_target));
4402 if (link_len == -1)
4403 return got_error_from_errno2("readlink", path2);
4404 sb2.st_mode = S_IFLNK;
4405 sb2.st_size = link_len;
4408 if (fd2 != -1) {
4409 if (fstat(fd2, &sb2) == -1) {
4410 err = got_error_from_errno2("fstat", path2);
4411 goto done;
4414 f2 = fdopen(fd2, "r");
4415 if (f2 == NULL) {
4416 err = got_error_from_errno2("fdopen", path2);
4417 goto done;
4419 fd2 = -1;
4420 } else {
4421 size_t n;
4422 f2 = got_opentemp();
4423 if (f2 == NULL) {
4424 err = got_error_from_errno2("got_opentemp", path2);
4425 goto done;
4427 n = fwrite(link_target, 1, link_len, f2);
4428 if (n != link_len) {
4429 err = got_ferror(f2, GOT_ERR_IO);
4430 goto done;
4432 if (fflush(f2) == EOF) {
4433 err = got_error_from_errno("fflush");
4434 goto done;
4436 rewind(f2);
4439 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
4440 if (err)
4441 goto done;
4443 err = got_opentemp_named(&path1, &f1, "got-patched-blob");
4444 if (err)
4445 goto done;
4447 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
4448 if (err)
4449 goto done;
4451 err = got_diff_files(&diffreg_result, f1, id_str, f2, path2, 3, 0, 1,
4452 NULL);
4453 if (err)
4454 goto done;
4456 err = got_opentemp_named(path_outfile, &outfile, "got-patched-content");
4457 if (err)
4458 goto done;
4460 if (fseek(f1, 0L, SEEK_SET) == -1)
4461 return got_ferror(f1, GOT_ERR_IO);
4462 if (fseek(f2, 0L, SEEK_SET) == -1)
4463 return got_ferror(f2, GOT_ERR_IO);
4465 /* Count the number of actual changes in the diff result. */
4466 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
4467 struct diff_chunk_context cc = {};
4468 diff_chunk_context_load_change(&cc, &nchunks_used,
4469 diffreg_result->result, n, 0);
4470 nchanges++;
4472 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
4473 int choice;
4474 err = apply_or_reject_change(&choice, &nchunks_used,
4475 diffreg_result->result, n, relpath, f1, f2,
4476 &line_cur1, &line_cur2,
4477 reverse_patch ? NULL : outfile,
4478 reverse_patch ? outfile : NULL,
4479 ++i, nchanges, patch_cb, patch_arg);
4480 if (err)
4481 goto done;
4482 if (choice == GOT_PATCH_CHOICE_YES)
4483 have_content = 1;
4484 else if (choice == GOT_PATCH_CHOICE_QUIT)
4485 break;
4487 if (have_content) {
4488 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
4489 reverse_patch ? NULL : outfile,
4490 reverse_patch ? outfile : NULL);
4491 if (err)
4492 goto done;
4494 if (!S_ISLNK(sb2.st_mode)) {
4495 if (fchmod(fileno(outfile), sb2.st_mode) == -1) {
4496 err = got_error_from_errno2("fchmod", path2);
4497 goto done;
4501 done:
4502 free(id_str);
4503 if (blob)
4504 got_object_blob_close(blob);
4505 free_err = got_diffreg_result_free(diffreg_result);
4506 if (err == NULL)
4507 err = free_err;
4508 if (f1 && fclose(f1) == EOF && err == NULL)
4509 err = got_error_from_errno2("fclose", path1);
4510 if (f2 && fclose(f2) == EOF && err == NULL)
4511 err = got_error_from_errno2("fclose", path2);
4512 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
4513 err = got_error_from_errno2("close", path2);
4514 if (outfile && fclose(outfile) == EOF && err == NULL)
4515 err = got_error_from_errno2("fclose", *path_outfile);
4516 if (path1 && unlink(path1) == -1 && err == NULL)
4517 err = got_error_from_errno2("unlink", path1);
4518 if (err || !have_content) {
4519 if (*path_outfile && unlink(*path_outfile) == -1 && err == NULL)
4520 err = got_error_from_errno2("unlink", *path_outfile);
4521 free(*path_outfile);
4522 *path_outfile = NULL;
4524 free(path1);
4525 return err;
4528 static const struct got_error *
4529 revert_file(void *arg, unsigned char status, unsigned char staged_status,
4530 const char *relpath, struct got_object_id *blob_id,
4531 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
4532 int dirfd, const char *de_name)
4534 struct revert_file_args *a = arg;
4535 const struct got_error *err = NULL;
4536 char *parent_path = NULL;
4537 struct got_fileindex_entry *ie;
4538 struct got_tree_object *tree = NULL;
4539 struct got_object_id *tree_id = NULL;
4540 const struct got_tree_entry *te = NULL;
4541 char *tree_path = NULL, *te_name;
4542 char *ondisk_path = NULL, *path_content = NULL;
4543 struct got_blob_object *blob = NULL;
4545 /* Reverting a staged deletion is a no-op. */
4546 if (status == GOT_STATUS_DELETE &&
4547 staged_status != GOT_STATUS_NO_CHANGE)
4548 return NULL;
4550 if (status == GOT_STATUS_UNVERSIONED)
4551 return (*a->progress_cb)(a->progress_arg,
4552 GOT_STATUS_UNVERSIONED, relpath);
4554 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
4555 if (ie == NULL)
4556 return got_error_path(relpath, GOT_ERR_BAD_PATH);
4558 /* Construct in-repository path of tree which contains this blob. */
4559 err = got_path_dirname(&parent_path, ie->path);
4560 if (err) {
4561 if (err->code != GOT_ERR_BAD_PATH)
4562 goto done;
4563 parent_path = strdup("/");
4564 if (parent_path == NULL) {
4565 err = got_error_from_errno("strdup");
4566 goto done;
4569 if (got_path_is_root_dir(a->worktree->path_prefix)) {
4570 tree_path = strdup(parent_path);
4571 if (tree_path == NULL) {
4572 err = got_error_from_errno("strdup");
4573 goto done;
4575 } else {
4576 if (got_path_is_root_dir(parent_path)) {
4577 tree_path = strdup(a->worktree->path_prefix);
4578 if (tree_path == NULL) {
4579 err = got_error_from_errno("strdup");
4580 goto done;
4582 } else {
4583 if (asprintf(&tree_path, "%s/%s",
4584 a->worktree->path_prefix, parent_path) == -1) {
4585 err = got_error_from_errno("asprintf");
4586 goto done;
4591 err = got_object_id_by_path(&tree_id, a->repo,
4592 a->worktree->base_commit_id, tree_path);
4593 if (err) {
4594 if (!(err->code == GOT_ERR_NO_TREE_ENTRY &&
4595 (status == GOT_STATUS_ADD ||
4596 staged_status == GOT_STATUS_ADD)))
4597 goto done;
4598 } else {
4599 err = got_object_open_as_tree(&tree, a->repo, tree_id);
4600 if (err)
4601 goto done;
4603 err = got_path_basename(&te_name, ie->path);
4604 if (err)
4605 goto done;
4607 te = got_object_tree_find_entry(tree, te_name);
4608 free(te_name);
4609 if (te == NULL && status != GOT_STATUS_ADD &&
4610 staged_status != GOT_STATUS_ADD) {
4611 err = got_error_path(ie->path, GOT_ERR_NO_TREE_ENTRY);
4612 goto done;
4616 switch (status) {
4617 case GOT_STATUS_ADD:
4618 if (a->patch_cb) {
4619 int choice = GOT_PATCH_CHOICE_NONE;
4620 err = (*a->patch_cb)(&choice, a->patch_arg,
4621 status, ie->path, NULL, 1, 1);
4622 if (err)
4623 goto done;
4624 if (choice != GOT_PATCH_CHOICE_YES)
4625 break;
4627 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_REVERT,
4628 ie->path);
4629 if (err)
4630 goto done;
4631 got_fileindex_entry_remove(a->fileindex, ie);
4632 break;
4633 case GOT_STATUS_DELETE:
4634 if (a->patch_cb) {
4635 int choice = GOT_PATCH_CHOICE_NONE;
4636 err = (*a->patch_cb)(&choice, a->patch_arg,
4637 status, ie->path, NULL, 1, 1);
4638 if (err)
4639 goto done;
4640 if (choice != GOT_PATCH_CHOICE_YES)
4641 break;
4643 /* fall through */
4644 case GOT_STATUS_MODIFY:
4645 case GOT_STATUS_MODE_CHANGE:
4646 case GOT_STATUS_CONFLICT:
4647 case GOT_STATUS_MISSING: {
4648 struct got_object_id id;
4649 if (staged_status == GOT_STATUS_ADD ||
4650 staged_status == GOT_STATUS_MODIFY) {
4651 memcpy(id.sha1, ie->staged_blob_sha1,
4652 SHA1_DIGEST_LENGTH);
4653 } else
4654 memcpy(id.sha1, ie->blob_sha1,
4655 SHA1_DIGEST_LENGTH);
4656 err = got_object_open_as_blob(&blob, a->repo, &id, 8192);
4657 if (err)
4658 goto done;
4660 if (asprintf(&ondisk_path, "%s/%s",
4661 got_worktree_get_root_path(a->worktree), relpath) == -1) {
4662 err = got_error_from_errno("asprintf");
4663 goto done;
4666 if (a->patch_cb && (status == GOT_STATUS_MODIFY ||
4667 status == GOT_STATUS_CONFLICT)) {
4668 int is_bad_symlink = 0;
4669 err = create_patched_content(&path_content, 1, &id,
4670 ondisk_path, dirfd, de_name, ie->path, a->repo,
4671 a->patch_cb, a->patch_arg);
4672 if (err || path_content == NULL)
4673 break;
4674 if (te && S_ISLNK(te->mode)) {
4675 if (unlink(path_content) == -1) {
4676 err = got_error_from_errno2("unlink",
4677 path_content);
4678 break;
4680 err = install_symlink(&is_bad_symlink,
4681 a->worktree, ondisk_path, ie->path,
4682 blob, 0, 1, 0, a->repo,
4683 a->progress_cb, a->progress_arg);
4684 } else {
4685 if (rename(path_content, ondisk_path) == -1) {
4686 err = got_error_from_errno3("rename",
4687 path_content, ondisk_path);
4688 goto done;
4691 } else {
4692 int is_bad_symlink = 0;
4693 if (te && S_ISLNK(te->mode)) {
4694 err = install_symlink(&is_bad_symlink,
4695 a->worktree, ondisk_path, ie->path,
4696 blob, 0, 1, 0, a->repo,
4697 a->progress_cb, a->progress_arg);
4698 } else {
4699 err = install_blob(a->worktree, ondisk_path,
4700 ie->path,
4701 te ? te->mode : GOT_DEFAULT_FILE_MODE,
4702 got_fileindex_perms_to_st(ie), blob,
4703 0, 1, 0, 0, a->repo,
4704 a->progress_cb, a->progress_arg);
4706 if (err)
4707 goto done;
4708 if (status == GOT_STATUS_DELETE ||
4709 status == GOT_STATUS_MODE_CHANGE) {
4710 err = got_fileindex_entry_update(ie,
4711 a->worktree->root_fd, relpath,
4712 blob->id.sha1,
4713 a->worktree->base_commit_id->sha1, 1);
4714 if (err)
4715 goto done;
4717 if (is_bad_symlink) {
4718 got_fileindex_entry_filetype_set(ie,
4719 GOT_FILEIDX_MODE_BAD_SYMLINK);
4722 break;
4724 default:
4725 break;
4727 done:
4728 free(ondisk_path);
4729 free(path_content);
4730 free(parent_path);
4731 free(tree_path);
4732 if (blob)
4733 got_object_blob_close(blob);
4734 if (tree)
4735 got_object_tree_close(tree);
4736 free(tree_id);
4737 return err;
4740 const struct got_error *
4741 got_worktree_revert(struct got_worktree *worktree,
4742 struct got_pathlist_head *paths,
4743 got_worktree_checkout_cb progress_cb, void *progress_arg,
4744 got_worktree_patch_cb patch_cb, void *patch_arg,
4745 struct got_repository *repo)
4747 struct got_fileindex *fileindex = NULL;
4748 char *fileindex_path = NULL;
4749 const struct got_error *err = NULL, *unlockerr = NULL;
4750 const struct got_error *sync_err = NULL;
4751 struct got_pathlist_entry *pe;
4752 struct revert_file_args rfa;
4754 err = lock_worktree(worktree, LOCK_EX);
4755 if (err)
4756 return err;
4758 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4759 if (err)
4760 goto done;
4762 rfa.worktree = worktree;
4763 rfa.fileindex = fileindex;
4764 rfa.progress_cb = progress_cb;
4765 rfa.progress_arg = progress_arg;
4766 rfa.patch_cb = patch_cb;
4767 rfa.patch_arg = patch_arg;
4768 rfa.repo = repo;
4769 TAILQ_FOREACH(pe, paths, entry) {
4770 err = worktree_status(worktree, pe->path, fileindex, repo,
4771 revert_file, &rfa, NULL, NULL, 0, 0);
4772 if (err)
4773 break;
4775 sync_err = sync_fileindex(fileindex, fileindex_path);
4776 if (sync_err && err == NULL)
4777 err = sync_err;
4778 done:
4779 free(fileindex_path);
4780 if (fileindex)
4781 got_fileindex_free(fileindex);
4782 unlockerr = lock_worktree(worktree, LOCK_SH);
4783 if (unlockerr && err == NULL)
4784 err = unlockerr;
4785 return err;
4788 static void
4789 free_commitable(struct got_commitable *ct)
4791 free(ct->path);
4792 free(ct->in_repo_path);
4793 free(ct->ondisk_path);
4794 free(ct->blob_id);
4795 free(ct->base_blob_id);
4796 free(ct->staged_blob_id);
4797 free(ct->base_commit_id);
4798 free(ct);
4801 struct collect_commitables_arg {
4802 struct got_pathlist_head *commitable_paths;
4803 struct got_repository *repo;
4804 struct got_worktree *worktree;
4805 struct got_fileindex *fileindex;
4806 int have_staged_files;
4807 int allow_bad_symlinks;
4810 static const struct got_error *
4811 collect_commitables(void *arg, unsigned char status,
4812 unsigned char staged_status, const char *relpath,
4813 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
4814 struct got_object_id *commit_id, int dirfd, const char *de_name)
4816 struct collect_commitables_arg *a = arg;
4817 const struct got_error *err = NULL;
4818 struct got_commitable *ct = NULL;
4819 struct got_pathlist_entry *new = NULL;
4820 char *parent_path = NULL, *path = NULL;
4821 struct stat sb;
4823 if (a->have_staged_files) {
4824 if (staged_status != GOT_STATUS_MODIFY &&
4825 staged_status != GOT_STATUS_ADD &&
4826 staged_status != GOT_STATUS_DELETE)
4827 return NULL;
4828 } else {
4829 if (status == GOT_STATUS_CONFLICT)
4830 return got_error(GOT_ERR_COMMIT_CONFLICT);
4832 if (status != GOT_STATUS_MODIFY &&
4833 status != GOT_STATUS_MODE_CHANGE &&
4834 status != GOT_STATUS_ADD &&
4835 status != GOT_STATUS_DELETE)
4836 return NULL;
4839 if (asprintf(&path, "/%s", relpath) == -1) {
4840 err = got_error_from_errno("asprintf");
4841 goto done;
4843 if (strcmp(path, "/") == 0) {
4844 parent_path = strdup("");
4845 if (parent_path == NULL)
4846 return got_error_from_errno("strdup");
4847 } else {
4848 err = got_path_dirname(&parent_path, path);
4849 if (err)
4850 return err;
4853 ct = calloc(1, sizeof(*ct));
4854 if (ct == NULL) {
4855 err = got_error_from_errno("calloc");
4856 goto done;
4859 if (asprintf(&ct->ondisk_path, "%s/%s", a->worktree->root_path,
4860 relpath) == -1) {
4861 err = got_error_from_errno("asprintf");
4862 goto done;
4865 if (staged_status == GOT_STATUS_ADD ||
4866 staged_status == GOT_STATUS_MODIFY) {
4867 struct got_fileindex_entry *ie;
4868 ie = got_fileindex_entry_get(a->fileindex, path, strlen(path));
4869 switch (got_fileindex_entry_staged_filetype_get(ie)) {
4870 case GOT_FILEIDX_MODE_REGULAR_FILE:
4871 case GOT_FILEIDX_MODE_BAD_SYMLINK:
4872 ct->mode = S_IFREG;
4873 break;
4874 case GOT_FILEIDX_MODE_SYMLINK:
4875 ct->mode = S_IFLNK;
4876 break;
4877 default:
4878 err = got_error_path(path, GOT_ERR_BAD_FILETYPE);
4879 goto done;
4881 ct->mode |= got_fileindex_entry_perms_get(ie);
4882 } else if (status != GOT_STATUS_DELETE &&
4883 staged_status != GOT_STATUS_DELETE) {
4884 if (dirfd != -1) {
4885 if (fstatat(dirfd, de_name, &sb,
4886 AT_SYMLINK_NOFOLLOW) == -1) {
4887 err = got_error_from_errno2("fstatat",
4888 ct->ondisk_path);
4889 goto done;
4891 } else if (lstat(ct->ondisk_path, &sb) == -1) {
4892 err = got_error_from_errno2("lstat", ct->ondisk_path);
4893 goto done;
4895 ct->mode = sb.st_mode;
4898 if (asprintf(&ct->in_repo_path, "%s%s%s", a->worktree->path_prefix,
4899 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
4900 relpath) == -1) {
4901 err = got_error_from_errno("asprintf");
4902 goto done;
4905 if (S_ISLNK(ct->mode) && staged_status == GOT_STATUS_NO_CHANGE &&
4906 status == GOT_STATUS_ADD && !a->allow_bad_symlinks) {
4907 int is_bad_symlink;
4908 char target_path[PATH_MAX];
4909 ssize_t target_len;
4910 target_len = readlink(ct->ondisk_path, target_path,
4911 sizeof(target_path));
4912 if (target_len == -1) {
4913 err = got_error_from_errno2("readlink",
4914 ct->ondisk_path);
4915 goto done;
4917 err = is_bad_symlink_target(&is_bad_symlink, target_path,
4918 target_len, ct->ondisk_path, a->worktree->root_path);
4919 if (err)
4920 goto done;
4921 if (is_bad_symlink) {
4922 err = got_error_path(ct->ondisk_path,
4923 GOT_ERR_BAD_SYMLINK);
4924 goto done;
4929 ct->status = status;
4930 ct->staged_status = staged_status;
4931 ct->blob_id = NULL; /* will be filled in when blob gets created */
4932 if (ct->status != GOT_STATUS_ADD &&
4933 ct->staged_status != GOT_STATUS_ADD) {
4934 ct->base_blob_id = got_object_id_dup(blob_id);
4935 if (ct->base_blob_id == NULL) {
4936 err = got_error_from_errno("got_object_id_dup");
4937 goto done;
4939 ct->base_commit_id = got_object_id_dup(commit_id);
4940 if (ct->base_commit_id == NULL) {
4941 err = got_error_from_errno("got_object_id_dup");
4942 goto done;
4945 if (ct->staged_status == GOT_STATUS_ADD ||
4946 ct->staged_status == GOT_STATUS_MODIFY) {
4947 ct->staged_blob_id = got_object_id_dup(staged_blob_id);
4948 if (ct->staged_blob_id == NULL) {
4949 err = got_error_from_errno("got_object_id_dup");
4950 goto done;
4953 ct->path = strdup(path);
4954 if (ct->path == NULL) {
4955 err = got_error_from_errno("strdup");
4956 goto done;
4958 err = got_pathlist_insert(&new, a->commitable_paths, ct->path, ct);
4959 done:
4960 if (ct && (err || new == NULL))
4961 free_commitable(ct);
4962 free(parent_path);
4963 free(path);
4964 return err;
4967 static const struct got_error *write_tree(struct got_object_id **, int *,
4968 struct got_tree_object *, const char *, struct got_pathlist_head *,
4969 got_worktree_status_cb status_cb, void *status_arg,
4970 struct got_repository *);
4972 static const struct got_error *
4973 write_subtree(struct got_object_id **new_subtree_id, int *nentries,
4974 struct got_tree_entry *te, const char *parent_path,
4975 struct got_pathlist_head *commitable_paths,
4976 got_worktree_status_cb status_cb, void *status_arg,
4977 struct got_repository *repo)
4979 const struct got_error *err = NULL;
4980 struct got_tree_object *subtree;
4981 char *subpath;
4983 if (asprintf(&subpath, "%s%s%s", parent_path,
4984 got_path_is_root_dir(parent_path) ? "" : "/", te->name) == -1)
4985 return got_error_from_errno("asprintf");
4987 err = got_object_open_as_tree(&subtree, repo, &te->id);
4988 if (err)
4989 return err;
4991 err = write_tree(new_subtree_id, nentries, subtree, subpath,
4992 commitable_paths, status_cb, status_arg, repo);
4993 got_object_tree_close(subtree);
4994 free(subpath);
4995 return err;
4998 static const struct got_error *
4999 match_ct_parent_path(int *match, struct got_commitable *ct, const char *path)
5001 const struct got_error *err = NULL;
5002 char *ct_parent_path = NULL;
5004 *match = 0;
5006 if (strchr(ct->in_repo_path, '/') == NULL) {
5007 *match = got_path_is_root_dir(path);
5008 return NULL;
5011 err = got_path_dirname(&ct_parent_path, ct->in_repo_path);
5012 if (err)
5013 return err;
5014 *match = (strcmp(path, ct_parent_path) == 0);
5015 free(ct_parent_path);
5016 return err;
5019 static mode_t
5020 get_ct_file_mode(struct got_commitable *ct)
5022 if (S_ISLNK(ct->mode))
5023 return S_IFLNK;
5025 return S_IFREG | (ct->mode & ((S_IRWXU | S_IRWXG | S_IRWXO)));
5028 static const struct got_error *
5029 alloc_modified_blob_tree_entry(struct got_tree_entry **new_te,
5030 struct got_tree_entry *te, struct got_commitable *ct)
5032 const struct got_error *err = NULL;
5034 *new_te = NULL;
5036 err = got_object_tree_entry_dup(new_te, te);
5037 if (err)
5038 goto done;
5040 (*new_te)->mode = get_ct_file_mode(ct);
5042 if (ct->staged_status == GOT_STATUS_MODIFY)
5043 memcpy(&(*new_te)->id, ct->staged_blob_id,
5044 sizeof((*new_te)->id));
5045 else
5046 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
5047 done:
5048 if (err && *new_te) {
5049 free(*new_te);
5050 *new_te = NULL;
5052 return err;
5055 static const struct got_error *
5056 alloc_added_blob_tree_entry(struct got_tree_entry **new_te,
5057 struct got_commitable *ct)
5059 const struct got_error *err = NULL;
5060 char *ct_name = NULL;
5062 *new_te = NULL;
5064 *new_te = calloc(1, sizeof(**new_te));
5065 if (*new_te == NULL)
5066 return got_error_from_errno("calloc");
5068 err = got_path_basename(&ct_name, ct->path);
5069 if (err)
5070 goto done;
5071 if (strlcpy((*new_te)->name, ct_name, sizeof((*new_te)->name)) >=
5072 sizeof((*new_te)->name)) {
5073 err = got_error(GOT_ERR_NO_SPACE);
5074 goto done;
5077 (*new_te)->mode = get_ct_file_mode(ct);
5079 if (ct->staged_status == GOT_STATUS_ADD)
5080 memcpy(&(*new_te)->id, ct->staged_blob_id,
5081 sizeof((*new_te)->id));
5082 else
5083 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
5084 done:
5085 free(ct_name);
5086 if (err && *new_te) {
5087 free(*new_te);
5088 *new_te = NULL;
5090 return err;
5093 static const struct got_error *
5094 insert_tree_entry(struct got_tree_entry *new_te,
5095 struct got_pathlist_head *paths)
5097 const struct got_error *err = NULL;
5098 struct got_pathlist_entry *new_pe;
5100 err = got_pathlist_insert(&new_pe, paths, new_te->name, new_te);
5101 if (err)
5102 return err;
5103 if (new_pe == NULL)
5104 return got_error(GOT_ERR_TREE_DUP_ENTRY);
5105 return NULL;
5108 static const struct got_error *
5109 report_ct_status(struct got_commitable *ct,
5110 got_worktree_status_cb status_cb, void *status_arg)
5112 const char *ct_path = ct->path;
5113 unsigned char status;
5115 while (ct_path[0] == '/')
5116 ct_path++;
5118 if (ct->staged_status != GOT_STATUS_NO_CHANGE)
5119 status = ct->staged_status;
5120 else
5121 status = ct->status;
5123 return (*status_cb)(status_arg, status, GOT_STATUS_NO_CHANGE,
5124 ct_path, ct->blob_id, NULL, NULL, -1, NULL);
5127 static const struct got_error *
5128 match_modified_subtree(int *modified, struct got_tree_entry *te,
5129 const char *base_tree_path, struct got_pathlist_head *commitable_paths)
5131 const struct got_error *err = NULL;
5132 struct got_pathlist_entry *pe;
5133 char *te_path;
5135 *modified = 0;
5137 if (asprintf(&te_path, "%s%s%s", base_tree_path,
5138 got_path_is_root_dir(base_tree_path) ? "" : "/",
5139 te->name) == -1)
5140 return got_error_from_errno("asprintf");
5142 TAILQ_FOREACH(pe, commitable_paths, entry) {
5143 struct got_commitable *ct = pe->data;
5144 *modified = got_path_is_child(ct->in_repo_path, te_path,
5145 strlen(te_path));
5146 if (*modified)
5147 break;
5150 free(te_path);
5151 return err;
5154 static const struct got_error *
5155 match_deleted_or_modified_ct(struct got_commitable **ctp,
5156 struct got_tree_entry *te, const char *base_tree_path,
5157 struct got_pathlist_head *commitable_paths)
5159 const struct got_error *err = NULL;
5160 struct got_pathlist_entry *pe;
5162 *ctp = NULL;
5164 TAILQ_FOREACH(pe, commitable_paths, entry) {
5165 struct got_commitable *ct = pe->data;
5166 char *ct_name = NULL;
5167 int path_matches;
5169 if (ct->staged_status == GOT_STATUS_NO_CHANGE) {
5170 if (ct->status != GOT_STATUS_MODIFY &&
5171 ct->status != GOT_STATUS_MODE_CHANGE &&
5172 ct->status != GOT_STATUS_DELETE)
5173 continue;
5174 } else {
5175 if (ct->staged_status != GOT_STATUS_MODIFY &&
5176 ct->staged_status != GOT_STATUS_DELETE)
5177 continue;
5180 if (got_object_id_cmp(ct->base_blob_id, &te->id) != 0)
5181 continue;
5183 err = match_ct_parent_path(&path_matches, ct, base_tree_path);
5184 if (err)
5185 return err;
5186 if (!path_matches)
5187 continue;
5189 err = got_path_basename(&ct_name, pe->path);
5190 if (err)
5191 return err;
5193 if (strcmp(te->name, ct_name) != 0) {
5194 free(ct_name);
5195 continue;
5197 free(ct_name);
5199 *ctp = ct;
5200 break;
5203 return err;
5206 static const struct got_error *
5207 make_subtree_for_added_blob(struct got_tree_entry **new_tep,
5208 const char *child_path, const char *path_base_tree,
5209 struct got_pathlist_head *commitable_paths,
5210 got_worktree_status_cb status_cb, void *status_arg,
5211 struct got_repository *repo)
5213 const struct got_error *err = NULL;
5214 struct got_tree_entry *new_te;
5215 char *subtree_path;
5216 struct got_object_id *id = NULL;
5217 int nentries;
5219 *new_tep = NULL;
5221 if (asprintf(&subtree_path, "%s%s%s", path_base_tree,
5222 got_path_is_root_dir(path_base_tree) ? "" : "/",
5223 child_path) == -1)
5224 return got_error_from_errno("asprintf");
5226 new_te = calloc(1, sizeof(*new_te));
5227 if (new_te == NULL)
5228 return got_error_from_errno("calloc");
5229 new_te->mode = S_IFDIR;
5231 if (strlcpy(new_te->name, child_path, sizeof(new_te->name)) >=
5232 sizeof(new_te->name)) {
5233 err = got_error(GOT_ERR_NO_SPACE);
5234 goto done;
5236 err = write_tree(&id, &nentries, NULL, subtree_path,
5237 commitable_paths, status_cb, status_arg, repo);
5238 if (err) {
5239 free(new_te);
5240 goto done;
5242 memcpy(&new_te->id, id, sizeof(new_te->id));
5243 done:
5244 free(id);
5245 free(subtree_path);
5246 if (err == NULL)
5247 *new_tep = new_te;
5248 return err;
5251 static const struct got_error *
5252 write_tree(struct got_object_id **new_tree_id, int *nentries,
5253 struct got_tree_object *base_tree, const char *path_base_tree,
5254 struct got_pathlist_head *commitable_paths,
5255 got_worktree_status_cb status_cb, void *status_arg,
5256 struct got_repository *repo)
5258 const struct got_error *err = NULL;
5259 struct got_pathlist_head paths;
5260 struct got_tree_entry *te, *new_te = NULL;
5261 struct got_pathlist_entry *pe;
5263 TAILQ_INIT(&paths);
5264 *nentries = 0;
5266 /* Insert, and recurse into, newly added entries first. */
5267 TAILQ_FOREACH(pe, commitable_paths, entry) {
5268 struct got_commitable *ct = pe->data;
5269 char *child_path = NULL, *slash;
5271 if ((ct->status != GOT_STATUS_ADD &&
5272 ct->staged_status != GOT_STATUS_ADD) ||
5273 (ct->flags & GOT_COMMITABLE_ADDED))
5274 continue;
5276 if (!got_path_is_child(ct->in_repo_path, path_base_tree,
5277 strlen(path_base_tree)))
5278 continue;
5280 err = got_path_skip_common_ancestor(&child_path, path_base_tree,
5281 ct->in_repo_path);
5282 if (err)
5283 goto done;
5285 slash = strchr(child_path, '/');
5286 if (slash == NULL) {
5287 err = alloc_added_blob_tree_entry(&new_te, ct);
5288 if (err)
5289 goto done;
5290 err = report_ct_status(ct, status_cb, status_arg);
5291 if (err)
5292 goto done;
5293 ct->flags |= GOT_COMMITABLE_ADDED;
5294 err = insert_tree_entry(new_te, &paths);
5295 if (err)
5296 goto done;
5297 (*nentries)++;
5298 } else {
5299 *slash = '\0'; /* trim trailing path components */
5300 if (base_tree == NULL ||
5301 got_object_tree_find_entry(base_tree, child_path)
5302 == NULL) {
5303 err = make_subtree_for_added_blob(&new_te,
5304 child_path, path_base_tree,
5305 commitable_paths, status_cb, status_arg,
5306 repo);
5307 if (err)
5308 goto done;
5309 err = insert_tree_entry(new_te, &paths);
5310 if (err)
5311 goto done;
5312 (*nentries)++;
5317 if (base_tree) {
5318 int i, nbase_entries;
5319 /* Handle modified and deleted entries. */
5320 nbase_entries = got_object_tree_get_nentries(base_tree);
5321 for (i = 0; i < nbase_entries; i++) {
5322 struct got_commitable *ct = NULL;
5324 te = got_object_tree_get_entry(base_tree, i);
5325 if (got_object_tree_entry_is_submodule(te)) {
5326 /* Entry is a submodule; just copy it. */
5327 err = got_object_tree_entry_dup(&new_te, te);
5328 if (err)
5329 goto done;
5330 err = insert_tree_entry(new_te, &paths);
5331 if (err)
5332 goto done;
5333 (*nentries)++;
5334 continue;
5337 if (S_ISDIR(te->mode)) {
5338 int modified;
5339 err = got_object_tree_entry_dup(&new_te, te);
5340 if (err)
5341 goto done;
5342 err = match_modified_subtree(&modified, te,
5343 path_base_tree, commitable_paths);
5344 if (err)
5345 goto done;
5346 /* Avoid recursion into unmodified subtrees. */
5347 if (modified) {
5348 struct got_object_id *new_id;
5349 int nsubentries;
5350 err = write_subtree(&new_id,
5351 &nsubentries, te,
5352 path_base_tree, commitable_paths,
5353 status_cb, status_arg, repo);
5354 if (err)
5355 goto done;
5356 if (nsubentries == 0) {
5357 /* All entries were deleted. */
5358 free(new_id);
5359 continue;
5361 memcpy(&new_te->id, new_id,
5362 sizeof(new_te->id));
5363 free(new_id);
5365 err = insert_tree_entry(new_te, &paths);
5366 if (err)
5367 goto done;
5368 (*nentries)++;
5369 continue;
5372 err = match_deleted_or_modified_ct(&ct, te,
5373 path_base_tree, commitable_paths);
5374 if (err)
5375 goto done;
5376 if (ct) {
5377 /* NB: Deleted entries get dropped here. */
5378 if (ct->status == GOT_STATUS_MODIFY ||
5379 ct->status == GOT_STATUS_MODE_CHANGE ||
5380 ct->staged_status == GOT_STATUS_MODIFY) {
5381 err = alloc_modified_blob_tree_entry(
5382 &new_te, te, ct);
5383 if (err)
5384 goto done;
5385 err = insert_tree_entry(new_te, &paths);
5386 if (err)
5387 goto done;
5388 (*nentries)++;
5390 err = report_ct_status(ct, status_cb,
5391 status_arg);
5392 if (err)
5393 goto done;
5394 } else {
5395 /* Entry is unchanged; just copy it. */
5396 err = got_object_tree_entry_dup(&new_te, te);
5397 if (err)
5398 goto done;
5399 err = insert_tree_entry(new_te, &paths);
5400 if (err)
5401 goto done;
5402 (*nentries)++;
5407 /* Write new list of entries; deleted entries have been dropped. */
5408 err = got_object_tree_create(new_tree_id, &paths, *nentries, repo);
5409 done:
5410 got_pathlist_free(&paths);
5411 return err;
5414 static const struct got_error *
5415 update_fileindex_after_commit(struct got_worktree *worktree,
5416 struct got_pathlist_head *commitable_paths,
5417 struct got_object_id *new_base_commit_id,
5418 struct got_fileindex *fileindex, int have_staged_files)
5420 const struct got_error *err = NULL;
5421 struct got_pathlist_entry *pe;
5422 char *relpath = NULL;
5424 TAILQ_FOREACH(pe, commitable_paths, entry) {
5425 struct got_fileindex_entry *ie;
5426 struct got_commitable *ct = pe->data;
5428 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
5430 err = got_path_skip_common_ancestor(&relpath,
5431 worktree->root_path, ct->ondisk_path);
5432 if (err)
5433 goto done;
5435 if (ie) {
5436 if (ct->status == GOT_STATUS_DELETE ||
5437 ct->staged_status == GOT_STATUS_DELETE) {
5438 got_fileindex_entry_remove(fileindex, ie);
5439 } else if (ct->staged_status == GOT_STATUS_ADD ||
5440 ct->staged_status == GOT_STATUS_MODIFY) {
5441 got_fileindex_entry_stage_set(ie,
5442 GOT_FILEIDX_STAGE_NONE);
5443 got_fileindex_entry_staged_filetype_set(ie, 0);
5445 err = got_fileindex_entry_update(ie,
5446 worktree->root_fd, relpath,
5447 ct->staged_blob_id->sha1,
5448 new_base_commit_id->sha1,
5449 !have_staged_files);
5450 } else
5451 err = got_fileindex_entry_update(ie,
5452 worktree->root_fd, relpath,
5453 ct->blob_id->sha1,
5454 new_base_commit_id->sha1,
5455 !have_staged_files);
5456 } else {
5457 err = got_fileindex_entry_alloc(&ie, pe->path);
5458 if (err)
5459 goto done;
5460 err = got_fileindex_entry_update(ie,
5461 worktree->root_fd, relpath, ct->blob_id->sha1,
5462 new_base_commit_id->sha1, 1);
5463 if (err) {
5464 got_fileindex_entry_free(ie);
5465 goto done;
5467 err = got_fileindex_entry_add(fileindex, ie);
5468 if (err) {
5469 got_fileindex_entry_free(ie);
5470 goto done;
5473 free(relpath);
5474 relpath = NULL;
5476 done:
5477 free(relpath);
5478 return err;
5482 static const struct got_error *
5483 check_out_of_date(const char *in_repo_path, unsigned char status,
5484 unsigned char staged_status, struct got_object_id *base_blob_id,
5485 struct got_object_id *base_commit_id,
5486 struct got_object_id *head_commit_id, struct got_repository *repo,
5487 int ood_errcode)
5489 const struct got_error *err = NULL;
5490 struct got_object_id *id = NULL;
5492 if (status != GOT_STATUS_ADD && staged_status != GOT_STATUS_ADD) {
5493 /* Trivial case: base commit == head commit */
5494 if (got_object_id_cmp(base_commit_id, head_commit_id) == 0)
5495 return NULL;
5497 * Ensure file content which local changes were based
5498 * on matches file content in the branch head.
5500 err = got_object_id_by_path(&id, repo, head_commit_id,
5501 in_repo_path);
5502 if (err) {
5503 if (err->code == GOT_ERR_NO_TREE_ENTRY)
5504 err = got_error(ood_errcode);
5505 goto done;
5506 } else if (got_object_id_cmp(id, base_blob_id) != 0)
5507 err = got_error(ood_errcode);
5508 } else {
5509 /* Require that added files don't exist in the branch head. */
5510 err = got_object_id_by_path(&id, repo, head_commit_id,
5511 in_repo_path);
5512 if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
5513 goto done;
5514 err = id ? got_error(ood_errcode) : NULL;
5516 done:
5517 free(id);
5518 return err;
5521 const struct got_error *
5522 commit_worktree(struct got_object_id **new_commit_id,
5523 struct got_pathlist_head *commitable_paths,
5524 struct got_object_id *head_commit_id, struct got_worktree *worktree,
5525 const char *author, const char *committer,
5526 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
5527 got_worktree_status_cb status_cb, void *status_arg,
5528 struct got_repository *repo)
5530 const struct got_error *err = NULL, *unlockerr = NULL;
5531 struct got_pathlist_entry *pe;
5532 const char *head_ref_name = NULL;
5533 struct got_commit_object *head_commit = NULL;
5534 struct got_reference *head_ref2 = NULL;
5535 struct got_object_id *head_commit_id2 = NULL;
5536 struct got_tree_object *head_tree = NULL;
5537 struct got_object_id *new_tree_id = NULL;
5538 int nentries;
5539 struct got_object_id_queue parent_ids;
5540 struct got_object_qid *pid = NULL;
5541 char *logmsg = NULL;
5543 *new_commit_id = NULL;
5545 SIMPLEQ_INIT(&parent_ids);
5547 err = got_object_open_as_commit(&head_commit, repo, head_commit_id);
5548 if (err)
5549 goto done;
5551 err = got_object_open_as_tree(&head_tree, repo, head_commit->tree_id);
5552 if (err)
5553 goto done;
5555 if (commit_msg_cb != NULL) {
5556 err = commit_msg_cb(commitable_paths, &logmsg, commit_arg);
5557 if (err)
5558 goto done;
5561 if (logmsg == NULL || strlen(logmsg) == 0) {
5562 err = got_error(GOT_ERR_COMMIT_MSG_EMPTY);
5563 goto done;
5566 /* Create blobs from added and modified files and record their IDs. */
5567 TAILQ_FOREACH(pe, commitable_paths, entry) {
5568 struct got_commitable *ct = pe->data;
5569 char *ondisk_path;
5571 /* Blobs for staged files already exist. */
5572 if (ct->staged_status == GOT_STATUS_ADD ||
5573 ct->staged_status == GOT_STATUS_MODIFY)
5574 continue;
5576 if (ct->status != GOT_STATUS_ADD &&
5577 ct->status != GOT_STATUS_MODIFY &&
5578 ct->status != GOT_STATUS_MODE_CHANGE)
5579 continue;
5581 if (asprintf(&ondisk_path, "%s/%s",
5582 worktree->root_path, pe->path) == -1) {
5583 err = got_error_from_errno("asprintf");
5584 goto done;
5586 err = got_object_blob_create(&ct->blob_id, ondisk_path, repo);
5587 free(ondisk_path);
5588 if (err)
5589 goto done;
5592 /* Recursively write new tree objects. */
5593 err = write_tree(&new_tree_id, &nentries, head_tree, "/",
5594 commitable_paths, status_cb, status_arg, repo);
5595 if (err)
5596 goto done;
5598 err = got_object_qid_alloc(&pid, worktree->base_commit_id);
5599 if (err)
5600 goto done;
5601 SIMPLEQ_INSERT_TAIL(&parent_ids, pid, entry);
5602 err = got_object_commit_create(new_commit_id, new_tree_id, &parent_ids,
5603 1, author, time(NULL), committer, time(NULL), logmsg, repo);
5604 got_object_qid_free(pid);
5605 if (logmsg != NULL)
5606 free(logmsg);
5607 if (err)
5608 goto done;
5610 /* Check if a concurrent commit to our branch has occurred. */
5611 head_ref_name = got_worktree_get_head_ref_name(worktree);
5612 if (head_ref_name == NULL) {
5613 err = got_error_from_errno("got_worktree_get_head_ref_name");
5614 goto done;
5616 /* Lock the reference here to prevent concurrent modification. */
5617 err = got_ref_open(&head_ref2, repo, head_ref_name, 1);
5618 if (err)
5619 goto done;
5620 err = got_ref_resolve(&head_commit_id2, repo, head_ref2);
5621 if (err)
5622 goto done;
5623 if (got_object_id_cmp(head_commit_id, head_commit_id2) != 0) {
5624 err = got_error(GOT_ERR_COMMIT_HEAD_CHANGED);
5625 goto done;
5627 /* Update branch head in repository. */
5628 err = got_ref_change_ref(head_ref2, *new_commit_id);
5629 if (err)
5630 goto done;
5631 err = got_ref_write(head_ref2, repo);
5632 if (err)
5633 goto done;
5635 err = got_worktree_set_base_commit_id(worktree, repo, *new_commit_id);
5636 if (err)
5637 goto done;
5639 err = ref_base_commit(worktree, repo);
5640 if (err)
5641 goto done;
5642 done:
5643 if (head_tree)
5644 got_object_tree_close(head_tree);
5645 if (head_commit)
5646 got_object_commit_close(head_commit);
5647 free(head_commit_id2);
5648 if (head_ref2) {
5649 unlockerr = got_ref_unlock(head_ref2);
5650 if (unlockerr && err == NULL)
5651 err = unlockerr;
5652 got_ref_close(head_ref2);
5654 return err;
5657 static const struct got_error *
5658 check_path_is_commitable(const char *path,
5659 struct got_pathlist_head *commitable_paths)
5661 struct got_pathlist_entry *cpe = NULL;
5662 size_t path_len = strlen(path);
5664 TAILQ_FOREACH(cpe, commitable_paths, entry) {
5665 struct got_commitable *ct = cpe->data;
5666 const char *ct_path = ct->path;
5668 while (ct_path[0] == '/')
5669 ct_path++;
5671 if (strcmp(path, ct_path) == 0 ||
5672 got_path_is_child(ct_path, path, path_len))
5673 break;
5676 if (cpe == NULL)
5677 return got_error_path(path, GOT_ERR_BAD_PATH);
5679 return NULL;
5682 static const struct got_error *
5683 check_staged_file(void *arg, struct got_fileindex_entry *ie)
5685 int *have_staged_files = arg;
5687 if (got_fileindex_entry_stage_get(ie) != GOT_FILEIDX_STAGE_NONE) {
5688 *have_staged_files = 1;
5689 return got_error(GOT_ERR_CANCELLED);
5692 return NULL;
5695 static const struct got_error *
5696 check_non_staged_files(struct got_fileindex *fileindex,
5697 struct got_pathlist_head *paths)
5699 struct got_pathlist_entry *pe;
5700 struct got_fileindex_entry *ie;
5702 TAILQ_FOREACH(pe, paths, entry) {
5703 if (pe->path[0] == '\0')
5704 continue;
5705 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
5706 if (ie == NULL)
5707 return got_error_path(pe->path, GOT_ERR_BAD_PATH);
5708 if (got_fileindex_entry_stage_get(ie) == GOT_FILEIDX_STAGE_NONE)
5709 return got_error_path(pe->path,
5710 GOT_ERR_FILE_NOT_STAGED);
5713 return NULL;
5716 const struct got_error *
5717 got_worktree_commit(struct got_object_id **new_commit_id,
5718 struct got_worktree *worktree, struct got_pathlist_head *paths,
5719 const char *author, const char *committer, int allow_bad_symlinks,
5720 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
5721 got_worktree_status_cb status_cb, void *status_arg,
5722 struct got_repository *repo)
5724 const struct got_error *err = NULL, *unlockerr = NULL, *sync_err;
5725 struct got_fileindex *fileindex = NULL;
5726 char *fileindex_path = NULL;
5727 struct got_pathlist_head commitable_paths;
5728 struct collect_commitables_arg cc_arg;
5729 struct got_pathlist_entry *pe;
5730 struct got_reference *head_ref = NULL;
5731 struct got_object_id *head_commit_id = NULL;
5732 int have_staged_files = 0;
5734 *new_commit_id = NULL;
5736 TAILQ_INIT(&commitable_paths);
5738 err = lock_worktree(worktree, LOCK_EX);
5739 if (err)
5740 goto done;
5742 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
5743 if (err)
5744 goto done;
5746 err = got_ref_resolve(&head_commit_id, repo, head_ref);
5747 if (err)
5748 goto done;
5750 err = open_fileindex(&fileindex, &fileindex_path, worktree);
5751 if (err)
5752 goto done;
5754 err = got_fileindex_for_each_entry_safe(fileindex, check_staged_file,
5755 &have_staged_files);
5756 if (err && err->code != GOT_ERR_CANCELLED)
5757 goto done;
5758 if (have_staged_files) {
5759 err = check_non_staged_files(fileindex, paths);
5760 if (err)
5761 goto done;
5764 cc_arg.commitable_paths = &commitable_paths;
5765 cc_arg.worktree = worktree;
5766 cc_arg.fileindex = fileindex;
5767 cc_arg.repo = repo;
5768 cc_arg.have_staged_files = have_staged_files;
5769 cc_arg.allow_bad_symlinks = allow_bad_symlinks;
5770 TAILQ_FOREACH(pe, paths, entry) {
5771 err = worktree_status(worktree, pe->path, fileindex, repo,
5772 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
5773 if (err)
5774 goto done;
5777 if (TAILQ_EMPTY(&commitable_paths)) {
5778 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
5779 goto done;
5782 TAILQ_FOREACH(pe, paths, entry) {
5783 err = check_path_is_commitable(pe->path, &commitable_paths);
5784 if (err)
5785 goto done;
5788 TAILQ_FOREACH(pe, &commitable_paths, entry) {
5789 struct got_commitable *ct = pe->data;
5790 const char *ct_path = ct->in_repo_path;
5792 while (ct_path[0] == '/')
5793 ct_path++;
5794 err = check_out_of_date(ct_path, ct->status,
5795 ct->staged_status, ct->base_blob_id, ct->base_commit_id,
5796 head_commit_id, repo, GOT_ERR_COMMIT_OUT_OF_DATE);
5797 if (err)
5798 goto done;
5802 err = commit_worktree(new_commit_id, &commitable_paths,
5803 head_commit_id, worktree, author, committer,
5804 commit_msg_cb, commit_arg, status_cb, status_arg, repo);
5805 if (err)
5806 goto done;
5808 err = update_fileindex_after_commit(worktree, &commitable_paths,
5809 *new_commit_id, fileindex, have_staged_files);
5810 sync_err = sync_fileindex(fileindex, fileindex_path);
5811 if (sync_err && err == NULL)
5812 err = sync_err;
5813 done:
5814 if (fileindex)
5815 got_fileindex_free(fileindex);
5816 free(fileindex_path);
5817 unlockerr = lock_worktree(worktree, LOCK_SH);
5818 if (unlockerr && err == NULL)
5819 err = unlockerr;
5820 TAILQ_FOREACH(pe, &commitable_paths, entry) {
5821 struct got_commitable *ct = pe->data;
5822 free_commitable(ct);
5824 got_pathlist_free(&commitable_paths);
5825 return err;
5828 const char *
5829 got_commitable_get_path(struct got_commitable *ct)
5831 return ct->path;
5834 unsigned int
5835 got_commitable_get_status(struct got_commitable *ct)
5837 return ct->status;
5840 struct check_rebase_ok_arg {
5841 struct got_worktree *worktree;
5842 struct got_repository *repo;
5845 static const struct got_error *
5846 check_rebase_ok(void *arg, struct got_fileindex_entry *ie)
5848 const struct got_error *err = NULL;
5849 struct check_rebase_ok_arg *a = arg;
5850 unsigned char status;
5851 struct stat sb;
5852 char *ondisk_path;
5854 /* Reject rebase of a work tree with mixed base commits. */
5855 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
5856 SHA1_DIGEST_LENGTH))
5857 return got_error(GOT_ERR_MIXED_COMMITS);
5859 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
5860 == -1)
5861 return got_error_from_errno("asprintf");
5863 /* Reject rebase of a work tree with modified or staged files. */
5864 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
5865 free(ondisk_path);
5866 if (err)
5867 return err;
5869 if (status != GOT_STATUS_NO_CHANGE)
5870 return got_error(GOT_ERR_MODIFIED);
5871 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
5872 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
5874 return NULL;
5877 const struct got_error *
5878 got_worktree_rebase_prepare(struct got_reference **new_base_branch_ref,
5879 struct got_reference **tmp_branch, struct got_fileindex **fileindex,
5880 struct got_worktree *worktree, struct got_reference *branch,
5881 struct got_repository *repo)
5883 const struct got_error *err = NULL;
5884 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
5885 char *branch_ref_name = NULL;
5886 char *fileindex_path = NULL;
5887 struct check_rebase_ok_arg ok_arg;
5888 struct got_reference *wt_branch = NULL, *branch_ref = NULL;
5889 struct got_object_id *wt_branch_tip = NULL;
5891 *new_base_branch_ref = NULL;
5892 *tmp_branch = NULL;
5893 *fileindex = NULL;
5895 err = lock_worktree(worktree, LOCK_EX);
5896 if (err)
5897 return err;
5899 err = open_fileindex(fileindex, &fileindex_path, worktree);
5900 if (err)
5901 goto done;
5903 ok_arg.worktree = worktree;
5904 ok_arg.repo = repo;
5905 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
5906 &ok_arg);
5907 if (err)
5908 goto done;
5910 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5911 if (err)
5912 goto done;
5914 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
5915 if (err)
5916 goto done;
5918 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
5919 if (err)
5920 goto done;
5922 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
5923 0);
5924 if (err)
5925 goto done;
5927 err = got_ref_resolve(&wt_branch_tip, repo, wt_branch);
5928 if (err)
5929 goto done;
5930 if (got_object_id_cmp(worktree->base_commit_id, wt_branch_tip) != 0) {
5931 err = got_error(GOT_ERR_REBASE_OUT_OF_DATE);
5932 goto done;
5935 err = got_ref_alloc_symref(new_base_branch_ref,
5936 new_base_branch_ref_name, wt_branch);
5937 if (err)
5938 goto done;
5939 err = got_ref_write(*new_base_branch_ref, repo);
5940 if (err)
5941 goto done;
5943 /* TODO Lock original branch's ref while rebasing? */
5945 err = got_ref_alloc_symref(&branch_ref, branch_ref_name, branch);
5946 if (err)
5947 goto done;
5949 err = got_ref_write(branch_ref, repo);
5950 if (err)
5951 goto done;
5953 err = got_ref_alloc(tmp_branch, tmp_branch_name,
5954 worktree->base_commit_id);
5955 if (err)
5956 goto done;
5957 err = got_ref_write(*tmp_branch, repo);
5958 if (err)
5959 goto done;
5961 err = got_worktree_set_head_ref(worktree, *tmp_branch);
5962 if (err)
5963 goto done;
5964 done:
5965 free(fileindex_path);
5966 free(tmp_branch_name);
5967 free(new_base_branch_ref_name);
5968 free(branch_ref_name);
5969 if (branch_ref)
5970 got_ref_close(branch_ref);
5971 if (wt_branch)
5972 got_ref_close(wt_branch);
5973 free(wt_branch_tip);
5974 if (err) {
5975 if (*new_base_branch_ref) {
5976 got_ref_close(*new_base_branch_ref);
5977 *new_base_branch_ref = NULL;
5979 if (*tmp_branch) {
5980 got_ref_close(*tmp_branch);
5981 *tmp_branch = NULL;
5983 if (*fileindex) {
5984 got_fileindex_free(*fileindex);
5985 *fileindex = NULL;
5987 lock_worktree(worktree, LOCK_SH);
5989 return err;
5992 const struct got_error *
5993 got_worktree_rebase_continue(struct got_object_id **commit_id,
5994 struct got_reference **new_base_branch, struct got_reference **tmp_branch,
5995 struct got_reference **branch, struct got_fileindex **fileindex,
5996 struct got_worktree *worktree, struct got_repository *repo)
5998 const struct got_error *err;
5999 char *commit_ref_name = NULL, *new_base_branch_ref_name = NULL;
6000 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
6001 struct got_reference *commit_ref = NULL, *branch_ref = NULL;
6002 char *fileindex_path = NULL;
6003 int have_staged_files = 0;
6005 *commit_id = NULL;
6006 *new_base_branch = NULL;
6007 *tmp_branch = NULL;
6008 *branch = NULL;
6009 *fileindex = NULL;
6011 err = lock_worktree(worktree, LOCK_EX);
6012 if (err)
6013 return err;
6015 err = open_fileindex(fileindex, &fileindex_path, worktree);
6016 if (err)
6017 goto done;
6019 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
6020 &have_staged_files);
6021 if (err && err->code != GOT_ERR_CANCELLED)
6022 goto done;
6023 if (have_staged_files) {
6024 err = got_error(GOT_ERR_STAGED_PATHS);
6025 goto done;
6028 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6029 if (err)
6030 goto done;
6032 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
6033 if (err)
6034 goto done;
6036 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6037 if (err)
6038 goto done;
6040 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
6041 if (err)
6042 goto done;
6044 err = got_ref_open(&branch_ref, repo, branch_ref_name, 0);
6045 if (err)
6046 goto done;
6048 err = got_ref_open(branch, repo,
6049 got_ref_get_symref_target(branch_ref), 0);
6050 if (err)
6051 goto done;
6053 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6054 if (err)
6055 goto done;
6057 err = got_ref_resolve(commit_id, repo, commit_ref);
6058 if (err)
6059 goto done;
6061 err = got_ref_open(new_base_branch, repo,
6062 new_base_branch_ref_name, 0);
6063 if (err)
6064 goto done;
6066 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
6067 if (err)
6068 goto done;
6069 done:
6070 free(commit_ref_name);
6071 free(branch_ref_name);
6072 free(fileindex_path);
6073 if (commit_ref)
6074 got_ref_close(commit_ref);
6075 if (branch_ref)
6076 got_ref_close(branch_ref);
6077 if (err) {
6078 free(*commit_id);
6079 *commit_id = NULL;
6080 if (*tmp_branch) {
6081 got_ref_close(*tmp_branch);
6082 *tmp_branch = NULL;
6084 if (*new_base_branch) {
6085 got_ref_close(*new_base_branch);
6086 *new_base_branch = NULL;
6088 if (*branch) {
6089 got_ref_close(*branch);
6090 *branch = NULL;
6092 if (*fileindex) {
6093 got_fileindex_free(*fileindex);
6094 *fileindex = NULL;
6096 lock_worktree(worktree, LOCK_SH);
6098 return err;
6101 const struct got_error *
6102 got_worktree_rebase_in_progress(int *in_progress, struct got_worktree *worktree)
6104 const struct got_error *err;
6105 char *tmp_branch_name = NULL;
6107 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6108 if (err)
6109 return err;
6111 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
6112 free(tmp_branch_name);
6113 return NULL;
6116 static const struct got_error *
6117 collect_rebase_commit_msg(struct got_pathlist_head *commitable_paths,
6118 char **logmsg, void *arg)
6120 *logmsg = arg;
6121 return NULL;
6124 static const struct got_error *
6125 rebase_status(void *arg, unsigned char status, unsigned char staged_status,
6126 const char *path, struct got_object_id *blob_id,
6127 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
6128 int dirfd, const char *de_name)
6130 return NULL;
6133 struct collect_merged_paths_arg {
6134 got_worktree_checkout_cb progress_cb;
6135 void *progress_arg;
6136 struct got_pathlist_head *merged_paths;
6139 static const struct got_error *
6140 collect_merged_paths(void *arg, unsigned char status, const char *path)
6142 const struct got_error *err;
6143 struct collect_merged_paths_arg *a = arg;
6144 char *p;
6145 struct got_pathlist_entry *new;
6147 err = (*a->progress_cb)(a->progress_arg, status, path);
6148 if (err)
6149 return err;
6151 if (status != GOT_STATUS_MERGE &&
6152 status != GOT_STATUS_ADD &&
6153 status != GOT_STATUS_DELETE &&
6154 status != GOT_STATUS_CONFLICT)
6155 return NULL;
6157 p = strdup(path);
6158 if (p == NULL)
6159 return got_error_from_errno("strdup");
6161 err = got_pathlist_insert(&new, a->merged_paths, p, NULL);
6162 if (err || new == NULL)
6163 free(p);
6164 return err;
6167 void
6168 got_worktree_rebase_pathlist_free(struct got_pathlist_head *merged_paths)
6170 struct got_pathlist_entry *pe;
6172 TAILQ_FOREACH(pe, merged_paths, entry)
6173 free((char *)pe->path);
6175 got_pathlist_free(merged_paths);
6178 static const struct got_error *
6179 store_commit_id(const char *commit_ref_name, struct got_object_id *commit_id,
6180 int is_rebase, struct got_repository *repo)
6182 const struct got_error *err;
6183 struct got_reference *commit_ref = NULL;
6185 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6186 if (err) {
6187 if (err->code != GOT_ERR_NOT_REF)
6188 goto done;
6189 err = got_ref_alloc(&commit_ref, commit_ref_name, commit_id);
6190 if (err)
6191 goto done;
6192 err = got_ref_write(commit_ref, repo);
6193 if (err)
6194 goto done;
6195 } else if (is_rebase) {
6196 struct got_object_id *stored_id;
6197 int cmp;
6199 err = got_ref_resolve(&stored_id, repo, commit_ref);
6200 if (err)
6201 goto done;
6202 cmp = got_object_id_cmp(commit_id, stored_id);
6203 free(stored_id);
6204 if (cmp != 0) {
6205 err = got_error(GOT_ERR_REBASE_COMMITID);
6206 goto done;
6209 done:
6210 if (commit_ref)
6211 got_ref_close(commit_ref);
6212 return err;
6215 static const struct got_error *
6216 rebase_merge_files(struct got_pathlist_head *merged_paths,
6217 const char *commit_ref_name, struct got_worktree *worktree,
6218 struct got_fileindex *fileindex, struct got_object_id *parent_commit_id,
6219 struct got_object_id *commit_id, struct got_repository *repo,
6220 got_worktree_checkout_cb progress_cb, void *progress_arg,
6221 got_cancel_cb cancel_cb, void *cancel_arg)
6223 const struct got_error *err;
6224 struct got_reference *commit_ref = NULL;
6225 struct collect_merged_paths_arg cmp_arg;
6226 char *fileindex_path;
6228 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6230 err = get_fileindex_path(&fileindex_path, worktree);
6231 if (err)
6232 return err;
6234 cmp_arg.progress_cb = progress_cb;
6235 cmp_arg.progress_arg = progress_arg;
6236 cmp_arg.merged_paths = merged_paths;
6237 err = merge_files(worktree, fileindex, fileindex_path,
6238 parent_commit_id, commit_id, repo, collect_merged_paths,
6239 &cmp_arg, cancel_cb, cancel_arg);
6240 if (commit_ref)
6241 got_ref_close(commit_ref);
6242 return err;
6245 const struct got_error *
6246 got_worktree_rebase_merge_files(struct got_pathlist_head *merged_paths,
6247 struct got_worktree *worktree, struct got_fileindex *fileindex,
6248 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
6249 struct got_repository *repo,
6250 got_worktree_checkout_cb progress_cb, void *progress_arg,
6251 got_cancel_cb cancel_cb, void *cancel_arg)
6253 const struct got_error *err;
6254 char *commit_ref_name;
6256 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6257 if (err)
6258 return err;
6260 err = store_commit_id(commit_ref_name, commit_id, 1, repo);
6261 if (err)
6262 goto done;
6264 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
6265 fileindex, parent_commit_id, commit_id, repo, progress_cb,
6266 progress_arg, cancel_cb, cancel_arg);
6267 done:
6268 free(commit_ref_name);
6269 return err;
6272 const struct got_error *
6273 got_worktree_histedit_merge_files(struct got_pathlist_head *merged_paths,
6274 struct got_worktree *worktree, struct got_fileindex *fileindex,
6275 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
6276 struct got_repository *repo,
6277 got_worktree_checkout_cb progress_cb, void *progress_arg,
6278 got_cancel_cb cancel_cb, void *cancel_arg)
6280 const struct got_error *err;
6281 char *commit_ref_name;
6283 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6284 if (err)
6285 return err;
6287 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
6288 if (err)
6289 goto done;
6291 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
6292 fileindex, parent_commit_id, commit_id, repo, progress_cb,
6293 progress_arg, cancel_cb, cancel_arg);
6294 done:
6295 free(commit_ref_name);
6296 return err;
6299 static const struct got_error *
6300 rebase_commit(struct got_object_id **new_commit_id,
6301 struct got_pathlist_head *merged_paths, struct got_reference *commit_ref,
6302 struct got_worktree *worktree, struct got_fileindex *fileindex,
6303 struct got_reference *tmp_branch, struct got_commit_object *orig_commit,
6304 const char *new_logmsg, struct got_repository *repo)
6306 const struct got_error *err, *sync_err;
6307 struct got_pathlist_head commitable_paths;
6308 struct collect_commitables_arg cc_arg;
6309 char *fileindex_path = NULL;
6310 struct got_reference *head_ref = NULL;
6311 struct got_object_id *head_commit_id = NULL;
6312 char *logmsg = NULL;
6314 TAILQ_INIT(&commitable_paths);
6315 *new_commit_id = NULL;
6317 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6319 err = get_fileindex_path(&fileindex_path, worktree);
6320 if (err)
6321 return err;
6323 cc_arg.commitable_paths = &commitable_paths;
6324 cc_arg.worktree = worktree;
6325 cc_arg.repo = repo;
6326 cc_arg.have_staged_files = 0;
6328 * If possible get the status of individual files directly to
6329 * avoid crawling the entire work tree once per rebased commit.
6330 * TODO: Ideally, merged_paths would contain a list of commitables
6331 * we could use so we could skip worktree_status() entirely.
6333 if (merged_paths) {
6334 struct got_pathlist_entry *pe;
6335 TAILQ_FOREACH(pe, merged_paths, entry) {
6336 err = worktree_status(worktree, pe->path, fileindex,
6337 repo, collect_commitables, &cc_arg, NULL, NULL, 0,
6338 0);
6339 if (err)
6340 goto done;
6342 } else {
6343 err = worktree_status(worktree, "", fileindex, repo,
6344 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
6345 if (err)
6346 goto done;
6349 if (TAILQ_EMPTY(&commitable_paths)) {
6350 /* No-op change; commit will be elided. */
6351 err = got_ref_delete(commit_ref, repo);
6352 if (err)
6353 goto done;
6354 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
6355 goto done;
6358 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
6359 if (err)
6360 goto done;
6362 err = got_ref_resolve(&head_commit_id, repo, head_ref);
6363 if (err)
6364 goto done;
6366 if (new_logmsg) {
6367 logmsg = strdup(new_logmsg);
6368 if (logmsg == NULL) {
6369 err = got_error_from_errno("strdup");
6370 goto done;
6372 } else {
6373 err = got_object_commit_get_logmsg(&logmsg, orig_commit);
6374 if (err)
6375 goto done;
6378 /* NB: commit_worktree will call free(logmsg) */
6379 err = commit_worktree(new_commit_id, &commitable_paths, head_commit_id,
6380 worktree, got_object_commit_get_author(orig_commit),
6381 got_object_commit_get_committer(orig_commit),
6382 collect_rebase_commit_msg, logmsg, rebase_status, NULL, repo);
6383 if (err)
6384 goto done;
6386 err = got_ref_change_ref(tmp_branch, *new_commit_id);
6387 if (err)
6388 goto done;
6390 err = got_ref_delete(commit_ref, repo);
6391 if (err)
6392 goto done;
6394 err = update_fileindex_after_commit(worktree, &commitable_paths,
6395 *new_commit_id, fileindex, 0);
6396 sync_err = sync_fileindex(fileindex, fileindex_path);
6397 if (sync_err && err == NULL)
6398 err = sync_err;
6399 done:
6400 free(fileindex_path);
6401 free(head_commit_id);
6402 if (head_ref)
6403 got_ref_close(head_ref);
6404 if (err) {
6405 free(*new_commit_id);
6406 *new_commit_id = NULL;
6408 return err;
6411 const struct got_error *
6412 got_worktree_rebase_commit(struct got_object_id **new_commit_id,
6413 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
6414 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6415 struct got_commit_object *orig_commit,
6416 struct got_object_id *orig_commit_id, struct got_repository *repo)
6418 const struct got_error *err;
6419 char *commit_ref_name;
6420 struct got_reference *commit_ref = NULL;
6421 struct got_object_id *commit_id = NULL;
6423 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6424 if (err)
6425 return err;
6427 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6428 if (err)
6429 goto done;
6430 err = got_ref_resolve(&commit_id, repo, commit_ref);
6431 if (err)
6432 goto done;
6433 if (got_object_id_cmp(commit_id, orig_commit_id) != 0) {
6434 err = got_error(GOT_ERR_REBASE_COMMITID);
6435 goto done;
6438 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
6439 worktree, fileindex, tmp_branch, orig_commit, NULL, repo);
6440 done:
6441 if (commit_ref)
6442 got_ref_close(commit_ref);
6443 free(commit_ref_name);
6444 free(commit_id);
6445 return err;
6448 const struct got_error *
6449 got_worktree_histedit_commit(struct got_object_id **new_commit_id,
6450 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
6451 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6452 struct got_commit_object *orig_commit,
6453 struct got_object_id *orig_commit_id, const char *new_logmsg,
6454 struct got_repository *repo)
6456 const struct got_error *err;
6457 char *commit_ref_name;
6458 struct got_reference *commit_ref = NULL;
6460 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6461 if (err)
6462 return err;
6464 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6465 if (err)
6466 goto done;
6468 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
6469 worktree, fileindex, tmp_branch, orig_commit, new_logmsg, repo);
6470 done:
6471 if (commit_ref)
6472 got_ref_close(commit_ref);
6473 free(commit_ref_name);
6474 return err;
6477 const struct got_error *
6478 got_worktree_rebase_postpone(struct got_worktree *worktree,
6479 struct got_fileindex *fileindex)
6481 if (fileindex)
6482 got_fileindex_free(fileindex);
6483 return lock_worktree(worktree, LOCK_SH);
6486 static const struct got_error *
6487 delete_ref(const char *name, struct got_repository *repo)
6489 const struct got_error *err;
6490 struct got_reference *ref;
6492 err = got_ref_open(&ref, repo, name, 0);
6493 if (err) {
6494 if (err->code == GOT_ERR_NOT_REF)
6495 return NULL;
6496 return err;
6499 err = got_ref_delete(ref, repo);
6500 got_ref_close(ref);
6501 return err;
6504 static const struct got_error *
6505 delete_rebase_refs(struct got_worktree *worktree, struct got_repository *repo)
6507 const struct got_error *err;
6508 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
6509 char *branch_ref_name = NULL, *commit_ref_name = NULL;
6511 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6512 if (err)
6513 goto done;
6514 err = delete_ref(tmp_branch_name, repo);
6515 if (err)
6516 goto done;
6518 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
6519 if (err)
6520 goto done;
6521 err = delete_ref(new_base_branch_ref_name, repo);
6522 if (err)
6523 goto done;
6525 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
6526 if (err)
6527 goto done;
6528 err = delete_ref(branch_ref_name, repo);
6529 if (err)
6530 goto done;
6532 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6533 if (err)
6534 goto done;
6535 err = delete_ref(commit_ref_name, repo);
6536 if (err)
6537 goto done;
6539 done:
6540 free(tmp_branch_name);
6541 free(new_base_branch_ref_name);
6542 free(branch_ref_name);
6543 free(commit_ref_name);
6544 return err;
6547 const struct got_error *
6548 create_backup_ref(const char *backup_ref_prefix, struct got_reference *branch,
6549 struct got_object_id *new_commit_id, struct got_repository *repo)
6551 const struct got_error *err;
6552 struct got_reference *ref = NULL;
6553 struct got_object_id *old_commit_id = NULL;
6554 const char *branch_name = NULL;
6555 char *new_id_str = NULL;
6556 char *refname = NULL;
6558 branch_name = got_ref_get_name(branch);
6559 if (strncmp(branch_name, "refs/heads/", 11) != 0)
6560 return got_error(GOT_ERR_BAD_REF_NAME); /* should not happen */
6561 branch_name += 11;
6563 err = got_object_id_str(&new_id_str, new_commit_id);
6564 if (err)
6565 return err;
6567 if (asprintf(&refname, "%s/%s/%s", backup_ref_prefix, branch_name,
6568 new_id_str) == -1) {
6569 err = got_error_from_errno("asprintf");
6570 goto done;
6573 err = got_ref_resolve(&old_commit_id, repo, branch);
6574 if (err)
6575 goto done;
6577 err = got_ref_alloc(&ref, refname, old_commit_id);
6578 if (err)
6579 goto done;
6581 err = got_ref_write(ref, repo);
6582 done:
6583 free(new_id_str);
6584 free(refname);
6585 free(old_commit_id);
6586 if (ref)
6587 got_ref_close(ref);
6588 return err;
6591 const struct got_error *
6592 got_worktree_rebase_complete(struct got_worktree *worktree,
6593 struct got_fileindex *fileindex, struct got_reference *new_base_branch,
6594 struct got_reference *tmp_branch, struct got_reference *rebased_branch,
6595 struct got_repository *repo, int create_backup)
6597 const struct got_error *err, *unlockerr, *sync_err;
6598 struct got_object_id *new_head_commit_id = NULL;
6599 char *fileindex_path = NULL;
6601 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
6602 if (err)
6603 return err;
6605 if (create_backup) {
6606 err = create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX,
6607 rebased_branch, new_head_commit_id, repo);
6608 if (err)
6609 goto done;
6612 err = got_ref_change_ref(rebased_branch, new_head_commit_id);
6613 if (err)
6614 goto done;
6616 err = got_ref_write(rebased_branch, repo);
6617 if (err)
6618 goto done;
6620 err = got_worktree_set_head_ref(worktree, rebased_branch);
6621 if (err)
6622 goto done;
6624 err = delete_rebase_refs(worktree, repo);
6625 if (err)
6626 goto done;
6628 err = get_fileindex_path(&fileindex_path, worktree);
6629 if (err)
6630 goto done;
6631 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
6632 sync_err = sync_fileindex(fileindex, fileindex_path);
6633 if (sync_err && err == NULL)
6634 err = sync_err;
6635 done:
6636 got_fileindex_free(fileindex);
6637 free(fileindex_path);
6638 free(new_head_commit_id);
6639 unlockerr = lock_worktree(worktree, LOCK_SH);
6640 if (unlockerr && err == NULL)
6641 err = unlockerr;
6642 return err;
6645 const struct got_error *
6646 got_worktree_rebase_abort(struct got_worktree *worktree,
6647 struct got_fileindex *fileindex, struct got_repository *repo,
6648 struct got_reference *new_base_branch,
6649 got_worktree_checkout_cb progress_cb, void *progress_arg)
6651 const struct got_error *err, *unlockerr, *sync_err;
6652 struct got_reference *resolved = NULL;
6653 struct got_object_id *commit_id = NULL;
6654 char *fileindex_path = NULL;
6655 struct revert_file_args rfa;
6656 struct got_object_id *tree_id = NULL;
6658 err = lock_worktree(worktree, LOCK_EX);
6659 if (err)
6660 return err;
6662 err = got_ref_open(&resolved, repo,
6663 got_ref_get_symref_target(new_base_branch), 0);
6664 if (err)
6665 goto done;
6667 err = got_worktree_set_head_ref(worktree, resolved);
6668 if (err)
6669 goto done;
6672 * XXX commits to the base branch could have happened while
6673 * we were busy rebasing; should we store the original commit ID
6674 * when rebase begins and read it back here?
6676 err = got_ref_resolve(&commit_id, repo, resolved);
6677 if (err)
6678 goto done;
6680 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
6681 if (err)
6682 goto done;
6684 err = got_object_id_by_path(&tree_id, repo,
6685 worktree->base_commit_id, worktree->path_prefix);
6686 if (err)
6687 goto done;
6689 err = delete_rebase_refs(worktree, repo);
6690 if (err)
6691 goto done;
6693 err = get_fileindex_path(&fileindex_path, worktree);
6694 if (err)
6695 goto done;
6697 rfa.worktree = worktree;
6698 rfa.fileindex = fileindex;
6699 rfa.progress_cb = progress_cb;
6700 rfa.progress_arg = progress_arg;
6701 rfa.patch_cb = NULL;
6702 rfa.patch_arg = NULL;
6703 rfa.repo = repo;
6704 err = worktree_status(worktree, "", fileindex, repo,
6705 revert_file, &rfa, NULL, NULL, 0, 0);
6706 if (err)
6707 goto sync;
6709 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
6710 repo, progress_cb, progress_arg, NULL, NULL);
6711 sync:
6712 sync_err = sync_fileindex(fileindex, fileindex_path);
6713 if (sync_err && err == NULL)
6714 err = sync_err;
6715 done:
6716 got_ref_close(resolved);
6717 free(tree_id);
6718 free(commit_id);
6719 if (fileindex)
6720 got_fileindex_free(fileindex);
6721 free(fileindex_path);
6723 unlockerr = lock_worktree(worktree, LOCK_SH);
6724 if (unlockerr && err == NULL)
6725 err = unlockerr;
6726 return err;
6729 const struct got_error *
6730 got_worktree_histedit_prepare(struct got_reference **tmp_branch,
6731 struct got_reference **branch_ref, struct got_object_id **base_commit_id,
6732 struct got_fileindex **fileindex, struct got_worktree *worktree,
6733 struct got_repository *repo)
6735 const struct got_error *err = NULL;
6736 char *tmp_branch_name = NULL;
6737 char *branch_ref_name = NULL;
6738 char *base_commit_ref_name = NULL;
6739 char *fileindex_path = NULL;
6740 struct check_rebase_ok_arg ok_arg;
6741 struct got_reference *wt_branch = NULL;
6742 struct got_reference *base_commit_ref = NULL;
6744 *tmp_branch = NULL;
6745 *branch_ref = NULL;
6746 *base_commit_id = NULL;
6747 *fileindex = NULL;
6749 err = lock_worktree(worktree, LOCK_EX);
6750 if (err)
6751 return err;
6753 err = open_fileindex(fileindex, &fileindex_path, worktree);
6754 if (err)
6755 goto done;
6757 ok_arg.worktree = worktree;
6758 ok_arg.repo = repo;
6759 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
6760 &ok_arg);
6761 if (err)
6762 goto done;
6764 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6765 if (err)
6766 goto done;
6768 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
6769 if (err)
6770 goto done;
6772 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
6773 worktree);
6774 if (err)
6775 goto done;
6777 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
6778 0);
6779 if (err)
6780 goto done;
6782 err = got_ref_alloc_symref(branch_ref, branch_ref_name, wt_branch);
6783 if (err)
6784 goto done;
6786 err = got_ref_write(*branch_ref, repo);
6787 if (err)
6788 goto done;
6790 err = got_ref_alloc(&base_commit_ref, base_commit_ref_name,
6791 worktree->base_commit_id);
6792 if (err)
6793 goto done;
6794 err = got_ref_write(base_commit_ref, repo);
6795 if (err)
6796 goto done;
6797 *base_commit_id = got_object_id_dup(worktree->base_commit_id);
6798 if (*base_commit_id == NULL) {
6799 err = got_error_from_errno("got_object_id_dup");
6800 goto done;
6803 err = got_ref_alloc(tmp_branch, tmp_branch_name,
6804 worktree->base_commit_id);
6805 if (err)
6806 goto done;
6807 err = got_ref_write(*tmp_branch, repo);
6808 if (err)
6809 goto done;
6811 err = got_worktree_set_head_ref(worktree, *tmp_branch);
6812 if (err)
6813 goto done;
6814 done:
6815 free(fileindex_path);
6816 free(tmp_branch_name);
6817 free(branch_ref_name);
6818 free(base_commit_ref_name);
6819 if (wt_branch)
6820 got_ref_close(wt_branch);
6821 if (err) {
6822 if (*branch_ref) {
6823 got_ref_close(*branch_ref);
6824 *branch_ref = NULL;
6826 if (*tmp_branch) {
6827 got_ref_close(*tmp_branch);
6828 *tmp_branch = NULL;
6830 free(*base_commit_id);
6831 if (*fileindex) {
6832 got_fileindex_free(*fileindex);
6833 *fileindex = NULL;
6835 lock_worktree(worktree, LOCK_SH);
6837 return err;
6840 const struct got_error *
6841 got_worktree_histedit_postpone(struct got_worktree *worktree,
6842 struct got_fileindex *fileindex)
6844 if (fileindex)
6845 got_fileindex_free(fileindex);
6846 return lock_worktree(worktree, LOCK_SH);
6849 const struct got_error *
6850 got_worktree_histedit_in_progress(int *in_progress,
6851 struct got_worktree *worktree)
6853 const struct got_error *err;
6854 char *tmp_branch_name = NULL;
6856 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6857 if (err)
6858 return err;
6860 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
6861 free(tmp_branch_name);
6862 return NULL;
6865 const struct got_error *
6866 got_worktree_histedit_continue(struct got_object_id **commit_id,
6867 struct got_reference **tmp_branch, struct got_reference **branch_ref,
6868 struct got_object_id **base_commit_id, struct got_fileindex **fileindex,
6869 struct got_worktree *worktree, struct got_repository *repo)
6871 const struct got_error *err;
6872 char *commit_ref_name = NULL, *base_commit_ref_name = NULL;
6873 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
6874 struct got_reference *commit_ref = NULL;
6875 struct got_reference *base_commit_ref = NULL;
6876 char *fileindex_path = NULL;
6877 int have_staged_files = 0;
6879 *commit_id = NULL;
6880 *tmp_branch = NULL;
6881 *base_commit_id = NULL;
6882 *fileindex = NULL;
6884 err = lock_worktree(worktree, LOCK_EX);
6885 if (err)
6886 return err;
6888 err = open_fileindex(fileindex, &fileindex_path, worktree);
6889 if (err)
6890 goto done;
6892 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
6893 &have_staged_files);
6894 if (err && err->code != GOT_ERR_CANCELLED)
6895 goto done;
6896 if (have_staged_files) {
6897 err = got_error(GOT_ERR_STAGED_PATHS);
6898 goto done;
6901 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6902 if (err)
6903 goto done;
6905 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
6906 if (err)
6907 goto done;
6909 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6910 if (err)
6911 goto done;
6913 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
6914 worktree);
6915 if (err)
6916 goto done;
6918 err = got_ref_open(branch_ref, repo, branch_ref_name, 0);
6919 if (err)
6920 goto done;
6922 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6923 if (err)
6924 goto done;
6925 err = got_ref_resolve(commit_id, repo, commit_ref);
6926 if (err)
6927 goto done;
6929 err = got_ref_open(&base_commit_ref, repo, base_commit_ref_name, 0);
6930 if (err)
6931 goto done;
6932 err = got_ref_resolve(base_commit_id, repo, base_commit_ref);
6933 if (err)
6934 goto done;
6936 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
6937 if (err)
6938 goto done;
6939 done:
6940 free(commit_ref_name);
6941 free(branch_ref_name);
6942 free(fileindex_path);
6943 if (commit_ref)
6944 got_ref_close(commit_ref);
6945 if (base_commit_ref)
6946 got_ref_close(base_commit_ref);
6947 if (err) {
6948 free(*commit_id);
6949 *commit_id = NULL;
6950 free(*base_commit_id);
6951 *base_commit_id = NULL;
6952 if (*tmp_branch) {
6953 got_ref_close(*tmp_branch);
6954 *tmp_branch = NULL;
6956 if (*fileindex) {
6957 got_fileindex_free(*fileindex);
6958 *fileindex = NULL;
6960 lock_worktree(worktree, LOCK_EX);
6962 return err;
6965 static const struct got_error *
6966 delete_histedit_refs(struct got_worktree *worktree, struct got_repository *repo)
6968 const struct got_error *err;
6969 char *tmp_branch_name = NULL, *base_commit_ref_name = NULL;
6970 char *branch_ref_name = NULL, *commit_ref_name = NULL;
6972 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6973 if (err)
6974 goto done;
6975 err = delete_ref(tmp_branch_name, repo);
6976 if (err)
6977 goto done;
6979 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
6980 worktree);
6981 if (err)
6982 goto done;
6983 err = delete_ref(base_commit_ref_name, repo);
6984 if (err)
6985 goto done;
6987 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
6988 if (err)
6989 goto done;
6990 err = delete_ref(branch_ref_name, repo);
6991 if (err)
6992 goto done;
6994 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6995 if (err)
6996 goto done;
6997 err = delete_ref(commit_ref_name, repo);
6998 if (err)
6999 goto done;
7000 done:
7001 free(tmp_branch_name);
7002 free(base_commit_ref_name);
7003 free(branch_ref_name);
7004 free(commit_ref_name);
7005 return err;
7008 const struct got_error *
7009 got_worktree_histedit_abort(struct got_worktree *worktree,
7010 struct got_fileindex *fileindex, struct got_repository *repo,
7011 struct got_reference *branch, struct got_object_id *base_commit_id,
7012 got_worktree_checkout_cb progress_cb, void *progress_arg)
7014 const struct got_error *err, *unlockerr, *sync_err;
7015 struct got_reference *resolved = NULL;
7016 char *fileindex_path = NULL;
7017 struct got_object_id *tree_id = NULL;
7018 struct revert_file_args rfa;
7020 err = lock_worktree(worktree, LOCK_EX);
7021 if (err)
7022 return err;
7024 err = got_ref_open(&resolved, repo,
7025 got_ref_get_symref_target(branch), 0);
7026 if (err)
7027 goto done;
7029 err = got_worktree_set_head_ref(worktree, resolved);
7030 if (err)
7031 goto done;
7033 err = got_worktree_set_base_commit_id(worktree, repo, base_commit_id);
7034 if (err)
7035 goto done;
7037 err = got_object_id_by_path(&tree_id, repo, base_commit_id,
7038 worktree->path_prefix);
7039 if (err)
7040 goto done;
7042 err = delete_histedit_refs(worktree, repo);
7043 if (err)
7044 goto done;
7046 err = get_fileindex_path(&fileindex_path, worktree);
7047 if (err)
7048 goto done;
7050 rfa.worktree = worktree;
7051 rfa.fileindex = fileindex;
7052 rfa.progress_cb = progress_cb;
7053 rfa.progress_arg = progress_arg;
7054 rfa.patch_cb = NULL;
7055 rfa.patch_arg = NULL;
7056 rfa.repo = repo;
7057 err = worktree_status(worktree, "", fileindex, repo,
7058 revert_file, &rfa, NULL, NULL, 0, 0);
7059 if (err)
7060 goto sync;
7062 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
7063 repo, progress_cb, progress_arg, NULL, NULL);
7064 sync:
7065 sync_err = sync_fileindex(fileindex, fileindex_path);
7066 if (sync_err && err == NULL)
7067 err = sync_err;
7068 done:
7069 got_ref_close(resolved);
7070 free(tree_id);
7071 free(fileindex_path);
7073 unlockerr = lock_worktree(worktree, LOCK_SH);
7074 if (unlockerr && err == NULL)
7075 err = unlockerr;
7076 return err;
7079 const struct got_error *
7080 got_worktree_histedit_complete(struct got_worktree *worktree,
7081 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
7082 struct got_reference *edited_branch, struct got_repository *repo)
7084 const struct got_error *err, *unlockerr, *sync_err;
7085 struct got_object_id *new_head_commit_id = NULL;
7086 struct got_reference *resolved = NULL;
7087 char *fileindex_path = NULL;
7089 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
7090 if (err)
7091 return err;
7093 err = got_ref_open(&resolved, repo,
7094 got_ref_get_symref_target(edited_branch), 0);
7095 if (err)
7096 goto done;
7098 err = create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX,
7099 resolved, new_head_commit_id, repo);
7100 if (err)
7101 goto done;
7103 err = got_ref_change_ref(resolved, new_head_commit_id);
7104 if (err)
7105 goto done;
7107 err = got_ref_write(resolved, repo);
7108 if (err)
7109 goto done;
7111 err = got_worktree_set_head_ref(worktree, resolved);
7112 if (err)
7113 goto done;
7115 err = delete_histedit_refs(worktree, repo);
7116 if (err)
7117 goto done;
7119 err = get_fileindex_path(&fileindex_path, worktree);
7120 if (err)
7121 goto done;
7122 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
7123 sync_err = sync_fileindex(fileindex, fileindex_path);
7124 if (sync_err && err == NULL)
7125 err = sync_err;
7126 done:
7127 got_fileindex_free(fileindex);
7128 free(fileindex_path);
7129 free(new_head_commit_id);
7130 unlockerr = lock_worktree(worktree, LOCK_SH);
7131 if (unlockerr && err == NULL)
7132 err = unlockerr;
7133 return err;
7136 const struct got_error *
7137 got_worktree_histedit_skip_commit(struct got_worktree *worktree,
7138 struct got_object_id *commit_id, struct got_repository *repo)
7140 const struct got_error *err;
7141 char *commit_ref_name;
7143 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
7144 if (err)
7145 return err;
7147 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
7148 if (err)
7149 goto done;
7151 err = delete_ref(commit_ref_name, repo);
7152 done:
7153 free(commit_ref_name);
7154 return err;
7157 const struct got_error *
7158 got_worktree_integrate_prepare(struct got_fileindex **fileindex,
7159 struct got_reference **branch_ref, struct got_reference **base_branch_ref,
7160 struct got_worktree *worktree, const char *refname,
7161 struct got_repository *repo)
7163 const struct got_error *err = NULL;
7164 char *fileindex_path = NULL;
7165 struct check_rebase_ok_arg ok_arg;
7167 *fileindex = NULL;
7168 *branch_ref = NULL;
7169 *base_branch_ref = NULL;
7171 err = lock_worktree(worktree, LOCK_EX);
7172 if (err)
7173 return err;
7175 if (strcmp(refname, got_worktree_get_head_ref_name(worktree)) == 0) {
7176 err = got_error_msg(GOT_ERR_SAME_BRANCH,
7177 "cannot integrate a branch into itself; "
7178 "update -b or different branch name required");
7179 goto done;
7182 err = open_fileindex(fileindex, &fileindex_path, worktree);
7183 if (err)
7184 goto done;
7186 /* Preconditions are the same as for rebase. */
7187 ok_arg.worktree = worktree;
7188 ok_arg.repo = repo;
7189 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
7190 &ok_arg);
7191 if (err)
7192 goto done;
7194 err = got_ref_open(branch_ref, repo, refname, 1);
7195 if (err)
7196 goto done;
7198 err = got_ref_open(base_branch_ref, repo,
7199 got_worktree_get_head_ref_name(worktree), 1);
7200 done:
7201 if (err) {
7202 if (*branch_ref) {
7203 got_ref_close(*branch_ref);
7204 *branch_ref = NULL;
7206 if (*base_branch_ref) {
7207 got_ref_close(*base_branch_ref);
7208 *base_branch_ref = NULL;
7210 if (*fileindex) {
7211 got_fileindex_free(*fileindex);
7212 *fileindex = NULL;
7214 lock_worktree(worktree, LOCK_SH);
7216 return err;
7219 const struct got_error *
7220 got_worktree_integrate_continue(struct got_worktree *worktree,
7221 struct got_fileindex *fileindex, struct got_repository *repo,
7222 struct got_reference *branch_ref, struct got_reference *base_branch_ref,
7223 got_worktree_checkout_cb progress_cb, void *progress_arg,
7224 got_cancel_cb cancel_cb, void *cancel_arg)
7226 const struct got_error *err = NULL, *sync_err, *unlockerr;
7227 char *fileindex_path = NULL;
7228 struct got_object_id *tree_id = NULL, *commit_id = NULL;
7230 err = get_fileindex_path(&fileindex_path, worktree);
7231 if (err)
7232 goto done;
7234 err = got_ref_resolve(&commit_id, repo, branch_ref);
7235 if (err)
7236 goto done;
7238 err = got_object_id_by_path(&tree_id, repo, commit_id,
7239 worktree->path_prefix);
7240 if (err)
7241 goto done;
7243 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
7244 if (err)
7245 goto done;
7247 err = checkout_files(worktree, fileindex, "", tree_id, NULL, repo,
7248 progress_cb, progress_arg, cancel_cb, cancel_arg);
7249 if (err)
7250 goto sync;
7252 err = got_ref_change_ref(base_branch_ref, commit_id);
7253 if (err)
7254 goto sync;
7256 err = got_ref_write(base_branch_ref, repo);
7257 if (err)
7258 goto sync;
7260 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
7261 sync:
7262 sync_err = sync_fileindex(fileindex, fileindex_path);
7263 if (sync_err && err == NULL)
7264 err = sync_err;
7266 done:
7267 unlockerr = got_ref_unlock(branch_ref);
7268 if (unlockerr && err == NULL)
7269 err = unlockerr;
7270 got_ref_close(branch_ref);
7272 unlockerr = got_ref_unlock(base_branch_ref);
7273 if (unlockerr && err == NULL)
7274 err = unlockerr;
7275 got_ref_close(base_branch_ref);
7277 got_fileindex_free(fileindex);
7278 free(fileindex_path);
7279 free(tree_id);
7281 unlockerr = lock_worktree(worktree, LOCK_SH);
7282 if (unlockerr && err == NULL)
7283 err = unlockerr;
7284 return err;
7287 const struct got_error *
7288 got_worktree_integrate_abort(struct got_worktree *worktree,
7289 struct got_fileindex *fileindex, struct got_repository *repo,
7290 struct got_reference *branch_ref, struct got_reference *base_branch_ref)
7292 const struct got_error *err = NULL, *unlockerr = NULL;
7294 got_fileindex_free(fileindex);
7296 err = lock_worktree(worktree, LOCK_SH);
7298 unlockerr = got_ref_unlock(branch_ref);
7299 if (unlockerr && err == NULL)
7300 err = unlockerr;
7301 got_ref_close(branch_ref);
7303 unlockerr = got_ref_unlock(base_branch_ref);
7304 if (unlockerr && err == NULL)
7305 err = unlockerr;
7306 got_ref_close(base_branch_ref);
7308 return err;
7311 struct check_stage_ok_arg {
7312 struct got_object_id *head_commit_id;
7313 struct got_worktree *worktree;
7314 struct got_fileindex *fileindex;
7315 struct got_repository *repo;
7316 int have_changes;
7319 const struct got_error *
7320 check_stage_ok(void *arg, unsigned char status,
7321 unsigned char staged_status, const char *relpath,
7322 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
7323 struct got_object_id *commit_id, int dirfd, const char *de_name)
7325 struct check_stage_ok_arg *a = arg;
7326 const struct got_error *err = NULL;
7327 struct got_fileindex_entry *ie;
7328 struct got_object_id base_commit_id;
7329 struct got_object_id *base_commit_idp = NULL;
7330 char *in_repo_path = NULL, *p;
7332 if (status == GOT_STATUS_UNVERSIONED ||
7333 status == GOT_STATUS_NO_CHANGE)
7334 return NULL;
7335 if (status == GOT_STATUS_NONEXISTENT)
7336 return got_error_set_errno(ENOENT, relpath);
7338 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
7339 if (ie == NULL)
7340 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
7342 if (asprintf(&in_repo_path, "%s%s%s", a->worktree->path_prefix,
7343 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
7344 relpath) == -1)
7345 return got_error_from_errno("asprintf");
7347 if (got_fileindex_entry_has_commit(ie)) {
7348 memcpy(base_commit_id.sha1, ie->commit_sha1,
7349 SHA1_DIGEST_LENGTH);
7350 base_commit_idp = &base_commit_id;
7353 if (status == GOT_STATUS_CONFLICT) {
7354 err = got_error_path(ie->path, GOT_ERR_STAGE_CONFLICT);
7355 goto done;
7356 } else if (status != GOT_STATUS_ADD &&
7357 status != GOT_STATUS_MODIFY &&
7358 status != GOT_STATUS_DELETE) {
7359 err = got_error_path(ie->path, GOT_ERR_FILE_STATUS);
7360 goto done;
7363 a->have_changes = 1;
7365 p = in_repo_path;
7366 while (p[0] == '/')
7367 p++;
7368 err = check_out_of_date(p, status, staged_status,
7369 blob_id, base_commit_idp, a->head_commit_id, a->repo,
7370 GOT_ERR_STAGE_OUT_OF_DATE);
7371 done:
7372 free(in_repo_path);
7373 return err;
7376 struct stage_path_arg {
7377 struct got_worktree *worktree;
7378 struct got_fileindex *fileindex;
7379 struct got_repository *repo;
7380 got_worktree_status_cb status_cb;
7381 void *status_arg;
7382 got_worktree_patch_cb patch_cb;
7383 void *patch_arg;
7384 int staged_something;
7385 int allow_bad_symlinks;
7388 static const struct got_error *
7389 stage_path(void *arg, unsigned char status,
7390 unsigned char staged_status, const char *relpath,
7391 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
7392 struct got_object_id *commit_id, int dirfd, const char *de_name)
7394 struct stage_path_arg *a = arg;
7395 const struct got_error *err = NULL;
7396 struct got_fileindex_entry *ie;
7397 char *ondisk_path = NULL, *path_content = NULL;
7398 uint32_t stage;
7399 struct got_object_id *new_staged_blob_id = NULL;
7400 struct stat sb;
7402 if (status == GOT_STATUS_UNVERSIONED)
7403 return NULL;
7405 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
7406 if (ie == NULL)
7407 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
7409 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
7410 relpath)== -1)
7411 return got_error_from_errno("asprintf");
7413 switch (status) {
7414 case GOT_STATUS_ADD:
7415 case GOT_STATUS_MODIFY:
7416 /* XXX could sb.st_mode be passed in by our caller? */
7417 if (lstat(ondisk_path, &sb) == -1) {
7418 err = got_error_from_errno2("lstat", ondisk_path);
7419 break;
7421 if (a->patch_cb) {
7422 if (status == GOT_STATUS_ADD) {
7423 int choice = GOT_PATCH_CHOICE_NONE;
7424 err = (*a->patch_cb)(&choice, a->patch_arg,
7425 status, ie->path, NULL, 1, 1);
7426 if (err)
7427 break;
7428 if (choice != GOT_PATCH_CHOICE_YES)
7429 break;
7430 } else {
7431 err = create_patched_content(&path_content, 0,
7432 staged_blob_id ? staged_blob_id : blob_id,
7433 ondisk_path, dirfd, de_name, ie->path,
7434 a->repo, a->patch_cb, a->patch_arg);
7435 if (err || path_content == NULL)
7436 break;
7439 err = got_object_blob_create(&new_staged_blob_id,
7440 path_content ? path_content : ondisk_path, a->repo);
7441 if (err)
7442 break;
7443 memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1,
7444 SHA1_DIGEST_LENGTH);
7445 if (status == GOT_STATUS_ADD || staged_status == GOT_STATUS_ADD)
7446 stage = GOT_FILEIDX_STAGE_ADD;
7447 else
7448 stage = GOT_FILEIDX_STAGE_MODIFY;
7449 got_fileindex_entry_stage_set(ie, stage);
7450 if (S_ISLNK(sb.st_mode)) {
7451 int is_bad_symlink = 0;
7452 if (!a->allow_bad_symlinks) {
7453 char target_path[PATH_MAX];
7454 ssize_t target_len;
7455 target_len = readlink(ondisk_path, target_path,
7456 sizeof(target_path));
7457 if (target_len == -1) {
7458 err = got_error_from_errno2("readlink",
7459 ondisk_path);
7460 break;
7462 err = is_bad_symlink_target(&is_bad_symlink,
7463 target_path, target_len, ondisk_path,
7464 a->worktree->root_path);
7465 if (err)
7466 break;
7467 if (is_bad_symlink) {
7468 err = got_error_path(ondisk_path,
7469 GOT_ERR_BAD_SYMLINK);
7470 break;
7473 if (is_bad_symlink)
7474 got_fileindex_entry_staged_filetype_set(ie,
7475 GOT_FILEIDX_MODE_BAD_SYMLINK);
7476 else
7477 got_fileindex_entry_staged_filetype_set(ie,
7478 GOT_FILEIDX_MODE_SYMLINK);
7479 } else {
7480 got_fileindex_entry_staged_filetype_set(ie,
7481 GOT_FILEIDX_MODE_REGULAR_FILE);
7483 a->staged_something = 1;
7484 if (a->status_cb == NULL)
7485 break;
7486 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
7487 get_staged_status(ie), relpath, blob_id,
7488 new_staged_blob_id, NULL, dirfd, de_name);
7489 break;
7490 case GOT_STATUS_DELETE:
7491 if (staged_status == GOT_STATUS_DELETE)
7492 break;
7493 if (a->patch_cb) {
7494 int choice = GOT_PATCH_CHOICE_NONE;
7495 err = (*a->patch_cb)(&choice, a->patch_arg, status,
7496 ie->path, NULL, 1, 1);
7497 if (err)
7498 break;
7499 if (choice == GOT_PATCH_CHOICE_NO)
7500 break;
7501 if (choice != GOT_PATCH_CHOICE_YES) {
7502 err = got_error(GOT_ERR_PATCH_CHOICE);
7503 break;
7506 stage = GOT_FILEIDX_STAGE_DELETE;
7507 got_fileindex_entry_stage_set(ie, stage);
7508 a->staged_something = 1;
7509 if (a->status_cb == NULL)
7510 break;
7511 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
7512 get_staged_status(ie), relpath, NULL, NULL, NULL, dirfd,
7513 de_name);
7514 break;
7515 case GOT_STATUS_NO_CHANGE:
7516 break;
7517 case GOT_STATUS_CONFLICT:
7518 err = got_error_path(relpath, GOT_ERR_STAGE_CONFLICT);
7519 break;
7520 case GOT_STATUS_NONEXISTENT:
7521 err = got_error_set_errno(ENOENT, relpath);
7522 break;
7523 default:
7524 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
7525 break;
7528 if (path_content && unlink(path_content) == -1 && err == NULL)
7529 err = got_error_from_errno2("unlink", path_content);
7530 free(path_content);
7531 free(ondisk_path);
7532 free(new_staged_blob_id);
7533 return err;
7536 const struct got_error *
7537 got_worktree_stage(struct got_worktree *worktree,
7538 struct got_pathlist_head *paths,
7539 got_worktree_status_cb status_cb, void *status_arg,
7540 got_worktree_patch_cb patch_cb, void *patch_arg,
7541 int allow_bad_symlinks, struct got_repository *repo)
7543 const struct got_error *err = NULL, *sync_err, *unlockerr;
7544 struct got_pathlist_entry *pe;
7545 struct got_fileindex *fileindex = NULL;
7546 char *fileindex_path = NULL;
7547 struct got_reference *head_ref = NULL;
7548 struct got_object_id *head_commit_id = NULL;
7549 struct check_stage_ok_arg oka;
7550 struct stage_path_arg spa;
7552 err = lock_worktree(worktree, LOCK_EX);
7553 if (err)
7554 return err;
7556 err = got_ref_open(&head_ref, repo,
7557 got_worktree_get_head_ref_name(worktree), 0);
7558 if (err)
7559 goto done;
7560 err = got_ref_resolve(&head_commit_id, repo, head_ref);
7561 if (err)
7562 goto done;
7563 err = open_fileindex(&fileindex, &fileindex_path, worktree);
7564 if (err)
7565 goto done;
7567 /* Check pre-conditions before staging anything. */
7568 oka.head_commit_id = head_commit_id;
7569 oka.worktree = worktree;
7570 oka.fileindex = fileindex;
7571 oka.repo = repo;
7572 oka.have_changes = 0;
7573 TAILQ_FOREACH(pe, paths, entry) {
7574 err = worktree_status(worktree, pe->path, fileindex, repo,
7575 check_stage_ok, &oka, NULL, NULL, 0, 0);
7576 if (err)
7577 goto done;
7579 if (!oka.have_changes) {
7580 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
7581 goto done;
7584 spa.worktree = worktree;
7585 spa.fileindex = fileindex;
7586 spa.repo = repo;
7587 spa.patch_cb = patch_cb;
7588 spa.patch_arg = patch_arg;
7589 spa.status_cb = status_cb;
7590 spa.status_arg = status_arg;
7591 spa.staged_something = 0;
7592 spa.allow_bad_symlinks = allow_bad_symlinks;
7593 TAILQ_FOREACH(pe, paths, entry) {
7594 err = worktree_status(worktree, pe->path, fileindex, repo,
7595 stage_path, &spa, NULL, NULL, 0, 0);
7596 if (err)
7597 goto done;
7599 if (!spa.staged_something) {
7600 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
7601 goto done;
7604 sync_err = sync_fileindex(fileindex, fileindex_path);
7605 if (sync_err && err == NULL)
7606 err = sync_err;
7607 done:
7608 if (head_ref)
7609 got_ref_close(head_ref);
7610 free(head_commit_id);
7611 free(fileindex_path);
7612 if (fileindex)
7613 got_fileindex_free(fileindex);
7614 unlockerr = lock_worktree(worktree, LOCK_SH);
7615 if (unlockerr && err == NULL)
7616 err = unlockerr;
7617 return err;
7620 struct unstage_path_arg {
7621 struct got_worktree *worktree;
7622 struct got_fileindex *fileindex;
7623 struct got_repository *repo;
7624 got_worktree_checkout_cb progress_cb;
7625 void *progress_arg;
7626 got_worktree_patch_cb patch_cb;
7627 void *patch_arg;
7630 static const struct got_error *
7631 create_unstaged_content(char **path_unstaged_content,
7632 char **path_new_staged_content, struct got_object_id *blob_id,
7633 struct got_object_id *staged_blob_id, const char *relpath,
7634 struct got_repository *repo,
7635 got_worktree_patch_cb patch_cb, void *patch_arg)
7637 const struct got_error *err, *free_err;
7638 struct got_blob_object *blob = NULL, *staged_blob = NULL;
7639 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL, *rejectfile = NULL;
7640 char *path1 = NULL, *path2 = NULL, *label1 = NULL;
7641 struct got_diffreg_result *diffreg_result = NULL;
7642 int line_cur1 = 1, line_cur2 = 1, n = 0, nchunks_used = 0;
7643 int have_content = 0, have_rejected_content = 0, i = 0, nchanges = 0;
7645 *path_unstaged_content = NULL;
7646 *path_new_staged_content = NULL;
7648 err = got_object_id_str(&label1, blob_id);
7649 if (err)
7650 return err;
7651 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
7652 if (err)
7653 goto done;
7655 err = got_opentemp_named(&path1, &f1, "got-unstage-blob-base");
7656 if (err)
7657 goto done;
7659 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
7660 if (err)
7661 goto done;
7663 err = got_object_open_as_blob(&staged_blob, repo, staged_blob_id, 8192);
7664 if (err)
7665 goto done;
7667 err = got_opentemp_named(&path2, &f2, "got-unstage-blob-staged");
7668 if (err)
7669 goto done;
7671 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f2, staged_blob);
7672 if (err)
7673 goto done;
7675 err = got_diff_files(&diffreg_result, f1, label1, f2,
7676 path2, 3, 0, 1, NULL);
7677 if (err)
7678 goto done;
7680 err = got_opentemp_named(path_unstaged_content, &outfile,
7681 "got-unstaged-content");
7682 if (err)
7683 goto done;
7684 err = got_opentemp_named(path_new_staged_content, &rejectfile,
7685 "got-new-staged-content");
7686 if (err)
7687 goto done;
7689 if (fseek(f1, 0L, SEEK_SET) == -1) {
7690 err = got_ferror(f1, GOT_ERR_IO);
7691 goto done;
7693 if (fseek(f2, 0L, SEEK_SET) == -1) {
7694 err = got_ferror(f2, GOT_ERR_IO);
7695 goto done;
7697 /* Count the number of actual changes in the diff result. */
7698 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
7699 struct diff_chunk_context cc = {};
7700 diff_chunk_context_load_change(&cc, &nchunks_used,
7701 diffreg_result->result, n, 0);
7702 nchanges++;
7704 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
7705 int choice;
7706 err = apply_or_reject_change(&choice, &nchunks_used,
7707 diffreg_result->result, n, relpath, f1, f2,
7708 &line_cur1, &line_cur2,
7709 outfile, rejectfile, ++i, nchanges, patch_cb, patch_arg);
7710 if (err)
7711 goto done;
7712 if (choice == GOT_PATCH_CHOICE_YES)
7713 have_content = 1;
7714 else
7715 have_rejected_content = 1;
7716 if (choice == GOT_PATCH_CHOICE_QUIT)
7717 break;
7719 if (have_content || have_rejected_content)
7720 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
7721 outfile, rejectfile);
7722 done:
7723 free(label1);
7724 if (blob)
7725 got_object_blob_close(blob);
7726 if (staged_blob)
7727 got_object_blob_close(staged_blob);
7728 free_err = got_diffreg_result_free(diffreg_result);
7729 if (free_err && err == NULL)
7730 err = free_err;
7731 if (f1 && fclose(f1) == EOF && err == NULL)
7732 err = got_error_from_errno2("fclose", path1);
7733 if (f2 && fclose(f2) == EOF && err == NULL)
7734 err = got_error_from_errno2("fclose", path2);
7735 if (outfile && fclose(outfile) == EOF && err == NULL)
7736 err = got_error_from_errno2("fclose", *path_unstaged_content);
7737 if (rejectfile && fclose(rejectfile) == EOF && err == NULL)
7738 err = got_error_from_errno2("fclose", *path_new_staged_content);
7739 if (path1 && unlink(path1) == -1 && err == NULL)
7740 err = got_error_from_errno2("unlink", path1);
7741 if (path2 && unlink(path2) == -1 && err == NULL)
7742 err = got_error_from_errno2("unlink", path2);
7743 if (err || !have_content) {
7744 if (*path_unstaged_content &&
7745 unlink(*path_unstaged_content) == -1 && err == NULL)
7746 err = got_error_from_errno2("unlink",
7747 *path_unstaged_content);
7748 free(*path_unstaged_content);
7749 *path_unstaged_content = NULL;
7751 if (err || !have_content || !have_rejected_content) {
7752 if (*path_new_staged_content &&
7753 unlink(*path_new_staged_content) == -1 && err == NULL)
7754 err = got_error_from_errno2("unlink",
7755 *path_new_staged_content);
7756 free(*path_new_staged_content);
7757 *path_new_staged_content = NULL;
7759 free(path1);
7760 free(path2);
7761 return err;
7764 static const struct got_error *
7765 unstage_hunks(struct got_object_id *staged_blob_id,
7766 struct got_blob_object *blob_base,
7767 struct got_object_id *blob_id, struct got_fileindex_entry *ie,
7768 const char *ondisk_path, const char *label_orig,
7769 struct got_worktree *worktree, struct got_repository *repo,
7770 got_worktree_patch_cb patch_cb, void *patch_arg,
7771 got_worktree_checkout_cb progress_cb, void *progress_arg)
7773 const struct got_error *err = NULL;
7774 char *path_unstaged_content = NULL;
7775 char *path_new_staged_content = NULL;
7776 char *parent = NULL, *base_path = NULL;
7777 char *blob_base_path = NULL;
7778 struct got_object_id *new_staged_blob_id = NULL;
7779 FILE *f = NULL, *f_base = NULL, *f_deriv2 = NULL;
7780 struct stat sb;
7782 err = create_unstaged_content(&path_unstaged_content,
7783 &path_new_staged_content, blob_id, staged_blob_id,
7784 ie->path, repo, patch_cb, patch_arg);
7785 if (err)
7786 return err;
7788 if (path_unstaged_content == NULL)
7789 return NULL;
7791 if (path_new_staged_content) {
7792 err = got_object_blob_create(&new_staged_blob_id,
7793 path_new_staged_content, repo);
7794 if (err)
7795 goto done;
7798 f = fopen(path_unstaged_content, "r");
7799 if (f == NULL) {
7800 err = got_error_from_errno2("fopen",
7801 path_unstaged_content);
7802 goto done;
7804 if (fstat(fileno(f), &sb) == -1) {
7805 err = got_error_from_errno2("fstat", path_unstaged_content);
7806 goto done;
7808 if (got_fileindex_entry_staged_filetype_get(ie) ==
7809 GOT_FILEIDX_MODE_SYMLINK && sb.st_size < PATH_MAX) {
7810 char link_target[PATH_MAX];
7811 size_t r;
7812 r = fread(link_target, 1, sizeof(link_target), f);
7813 if (r == 0 && ferror(f)) {
7814 err = got_error_from_errno("fread");
7815 goto done;
7817 if (r >= sizeof(link_target)) { /* should not happen */
7818 err = got_error(GOT_ERR_NO_SPACE);
7819 goto done;
7821 link_target[r] = '\0';
7822 err = merge_symlink(worktree, blob_base,
7823 ondisk_path, ie->path, label_orig, link_target,
7824 worktree->base_commit_id, repo, progress_cb,
7825 progress_arg);
7826 } else {
7827 int local_changes_subsumed;
7829 err = got_path_dirname(&parent, ondisk_path);
7830 if (err)
7831 return err;
7833 if (asprintf(&base_path, "%s/got-unstage-blob-orig",
7834 parent) == -1) {
7835 err = got_error_from_errno("asprintf");
7836 base_path = NULL;
7837 goto done;
7840 err = got_opentemp_named(&blob_base_path, &f_base, base_path);
7841 if (err)
7842 goto done;
7843 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_base,
7844 blob_base);
7845 if (err)
7846 goto done;
7849 * In order the run a 3-way merge with a symlink we copy the symlink's
7850 * target path into a temporary file and use that file with diff3.
7852 if (S_ISLNK(got_fileindex_perms_to_st(ie))) {
7853 err = dump_symlink_target_path_to_file(&f_deriv2,
7854 ondisk_path);
7855 if (err)
7856 goto done;
7857 } else {
7858 int fd;
7859 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW);
7860 if (fd == -1) {
7861 err = got_error_from_errno2("open", ondisk_path);
7862 goto done;
7864 f_deriv2 = fdopen(fd, "r");
7865 if (f_deriv2 == NULL) {
7866 err = got_error_from_errno2("fdopen", ondisk_path);
7867 close(fd);
7868 goto done;
7872 err = merge_file(&local_changes_subsumed, worktree,
7873 f_base, f, f_deriv2, ondisk_path, ie->path,
7874 got_fileindex_perms_to_st(ie),
7875 label_orig, "unstaged", NULL,
7876 repo, progress_cb, progress_arg);
7878 if (err)
7879 goto done;
7881 if (new_staged_blob_id) {
7882 memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1,
7883 SHA1_DIGEST_LENGTH);
7884 } else {
7885 got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE);
7886 got_fileindex_entry_staged_filetype_set(ie, 0);
7888 done:
7889 free(new_staged_blob_id);
7890 if (path_unstaged_content &&
7891 unlink(path_unstaged_content) == -1 && err == NULL)
7892 err = got_error_from_errno2("unlink", path_unstaged_content);
7893 if (path_new_staged_content &&
7894 unlink(path_new_staged_content) == -1 && err == NULL)
7895 err = got_error_from_errno2("unlink", path_new_staged_content);
7896 if (blob_base_path && unlink(blob_base_path) == -1 && err == NULL)
7897 err = got_error_from_errno2("unlink", blob_base_path);
7898 if (f_base && fclose(f_base) == EOF && err == NULL)
7899 err = got_error_from_errno2("fclose", path_unstaged_content);
7900 if (f && fclose(f) == EOF && err == NULL)
7901 err = got_error_from_errno2("fclose", path_unstaged_content);
7902 if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
7903 err = got_error_from_errno2("fclose", ondisk_path);
7904 free(path_unstaged_content);
7905 free(path_new_staged_content);
7906 free(blob_base_path);
7907 free(parent);
7908 free(base_path);
7909 return err;
7912 static const struct got_error *
7913 unstage_path(void *arg, unsigned char status,
7914 unsigned char staged_status, const char *relpath,
7915 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
7916 struct got_object_id *commit_id, int dirfd, const char *de_name)
7918 const struct got_error *err = NULL;
7919 struct unstage_path_arg *a = arg;
7920 struct got_fileindex_entry *ie;
7921 struct got_blob_object *blob_base = NULL, *blob_staged = NULL;
7922 char *ondisk_path = NULL;
7923 char *id_str = NULL, *label_orig = NULL;
7924 int local_changes_subsumed;
7925 struct stat sb;
7927 if (staged_status != GOT_STATUS_ADD &&
7928 staged_status != GOT_STATUS_MODIFY &&
7929 staged_status != GOT_STATUS_DELETE)
7930 return NULL;
7932 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
7933 if (ie == NULL)
7934 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
7936 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, relpath)
7937 == -1)
7938 return got_error_from_errno("asprintf");
7940 err = got_object_id_str(&id_str,
7941 commit_id ? commit_id : a->worktree->base_commit_id);
7942 if (err)
7943 goto done;
7944 if (asprintf(&label_orig, "%s: commit %s", GOT_MERGE_LABEL_BASE,
7945 id_str) == -1) {
7946 err = got_error_from_errno("asprintf");
7947 goto done;
7950 switch (staged_status) {
7951 case GOT_STATUS_MODIFY:
7952 err = got_object_open_as_blob(&blob_base, a->repo,
7953 blob_id, 8192);
7954 if (err)
7955 break;
7956 /* fall through */
7957 case GOT_STATUS_ADD:
7958 if (a->patch_cb) {
7959 if (staged_status == GOT_STATUS_ADD) {
7960 int choice = GOT_PATCH_CHOICE_NONE;
7961 err = (*a->patch_cb)(&choice, a->patch_arg,
7962 staged_status, ie->path, NULL, 1, 1);
7963 if (err)
7964 break;
7965 if (choice != GOT_PATCH_CHOICE_YES)
7966 break;
7967 } else {
7968 err = unstage_hunks(staged_blob_id,
7969 blob_base, blob_id, ie, ondisk_path,
7970 label_orig, a->worktree, a->repo,
7971 a->patch_cb, a->patch_arg,
7972 a->progress_cb, a->progress_arg);
7973 break; /* Done with this file. */
7976 err = got_object_open_as_blob(&blob_staged, a->repo,
7977 staged_blob_id, 8192);
7978 if (err)
7979 break;
7980 switch (got_fileindex_entry_staged_filetype_get(ie)) {
7981 case GOT_FILEIDX_MODE_BAD_SYMLINK:
7982 case GOT_FILEIDX_MODE_REGULAR_FILE:
7983 err = merge_blob(&local_changes_subsumed, a->worktree,
7984 blob_base, ondisk_path, relpath,
7985 got_fileindex_perms_to_st(ie), label_orig,
7986 blob_staged, commit_id ? commit_id :
7987 a->worktree->base_commit_id, a->repo,
7988 a->progress_cb, a->progress_arg);
7989 break;
7990 case GOT_FILEIDX_MODE_SYMLINK:
7991 if (S_ISLNK(got_fileindex_perms_to_st(ie))) {
7992 char *staged_target;
7993 err = got_object_blob_read_to_str(
7994 &staged_target, blob_staged);
7995 if (err)
7996 goto done;
7997 err = merge_symlink(a->worktree, blob_base,
7998 ondisk_path, relpath, label_orig,
7999 staged_target, commit_id ? commit_id :
8000 a->worktree->base_commit_id,
8001 a->repo, a->progress_cb, a->progress_arg);
8002 free(staged_target);
8003 } else {
8004 err = merge_blob(&local_changes_subsumed,
8005 a->worktree, blob_base, ondisk_path,
8006 relpath, got_fileindex_perms_to_st(ie),
8007 label_orig, blob_staged,
8008 commit_id ? commit_id :
8009 a->worktree->base_commit_id, a->repo,
8010 a->progress_cb, a->progress_arg);
8012 break;
8013 default:
8014 err = got_error_path(relpath, GOT_ERR_BAD_FILETYPE);
8015 break;
8017 if (err == NULL) {
8018 got_fileindex_entry_stage_set(ie,
8019 GOT_FILEIDX_STAGE_NONE);
8020 got_fileindex_entry_staged_filetype_set(ie, 0);
8022 break;
8023 case GOT_STATUS_DELETE:
8024 if (a->patch_cb) {
8025 int choice = GOT_PATCH_CHOICE_NONE;
8026 err = (*a->patch_cb)(&choice, a->patch_arg,
8027 staged_status, ie->path, NULL, 1, 1);
8028 if (err)
8029 break;
8030 if (choice == GOT_PATCH_CHOICE_NO)
8031 break;
8032 if (choice != GOT_PATCH_CHOICE_YES) {
8033 err = got_error(GOT_ERR_PATCH_CHOICE);
8034 break;
8037 got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE);
8038 got_fileindex_entry_staged_filetype_set(ie, 0);
8039 err = get_file_status(&status, &sb, ie, ondisk_path,
8040 dirfd, de_name, a->repo);
8041 if (err)
8042 break;
8043 err = (*a->progress_cb)(a->progress_arg, status, relpath);
8044 break;
8046 done:
8047 free(ondisk_path);
8048 if (blob_base)
8049 got_object_blob_close(blob_base);
8050 if (blob_staged)
8051 got_object_blob_close(blob_staged);
8052 free(id_str);
8053 free(label_orig);
8054 return err;
8057 const struct got_error *
8058 got_worktree_unstage(struct got_worktree *worktree,
8059 struct got_pathlist_head *paths,
8060 got_worktree_checkout_cb progress_cb, void *progress_arg,
8061 got_worktree_patch_cb patch_cb, void *patch_arg,
8062 struct got_repository *repo)
8064 const struct got_error *err = NULL, *sync_err, *unlockerr;
8065 struct got_pathlist_entry *pe;
8066 struct got_fileindex *fileindex = NULL;
8067 char *fileindex_path = NULL;
8068 struct unstage_path_arg upa;
8070 err = lock_worktree(worktree, LOCK_EX);
8071 if (err)
8072 return err;
8074 err = open_fileindex(&fileindex, &fileindex_path, worktree);
8075 if (err)
8076 goto done;
8078 upa.worktree = worktree;
8079 upa.fileindex = fileindex;
8080 upa.repo = repo;
8081 upa.progress_cb = progress_cb;
8082 upa.progress_arg = progress_arg;
8083 upa.patch_cb = patch_cb;
8084 upa.patch_arg = patch_arg;
8085 TAILQ_FOREACH(pe, paths, entry) {
8086 err = worktree_status(worktree, pe->path, fileindex, repo,
8087 unstage_path, &upa, NULL, NULL, 0, 0);
8088 if (err)
8089 goto done;
8092 sync_err = sync_fileindex(fileindex, fileindex_path);
8093 if (sync_err && err == NULL)
8094 err = sync_err;
8095 done:
8096 free(fileindex_path);
8097 if (fileindex)
8098 got_fileindex_free(fileindex);
8099 unlockerr = lock_worktree(worktree, LOCK_SH);
8100 if (unlockerr && err == NULL)
8101 err = unlockerr;
8102 return err;
8105 struct report_file_info_arg {
8106 struct got_worktree *worktree;
8107 got_worktree_path_info_cb info_cb;
8108 void *info_arg;
8109 struct got_pathlist_head *paths;
8110 got_cancel_cb cancel_cb;
8111 void *cancel_arg;
8114 static const struct got_error *
8115 report_file_info(void *arg, struct got_fileindex_entry *ie)
8117 struct report_file_info_arg *a = arg;
8118 struct got_pathlist_entry *pe;
8119 struct got_object_id blob_id, staged_blob_id, commit_id;
8120 struct got_object_id *blob_idp = NULL, *staged_blob_idp = NULL;
8121 struct got_object_id *commit_idp = NULL;
8122 int stage;
8124 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
8125 return got_error(GOT_ERR_CANCELLED);
8127 TAILQ_FOREACH(pe, a->paths, entry) {
8128 if (pe->path_len == 0 || strcmp(pe->path, ie->path) == 0 ||
8129 got_path_is_child(ie->path, pe->path, pe->path_len))
8130 break;
8132 if (pe == NULL) /* not found */
8133 return NULL;
8135 if (got_fileindex_entry_has_blob(ie)) {
8136 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
8137 blob_idp = &blob_id;
8139 stage = got_fileindex_entry_stage_get(ie);
8140 if (stage == GOT_FILEIDX_STAGE_MODIFY ||
8141 stage == GOT_FILEIDX_STAGE_ADD) {
8142 memcpy(staged_blob_id.sha1, ie->staged_blob_sha1,
8143 SHA1_DIGEST_LENGTH);
8144 staged_blob_idp = &staged_blob_id;
8147 if (got_fileindex_entry_has_commit(ie)) {
8148 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
8149 commit_idp = &commit_id;
8152 return a->info_cb(a->info_arg, ie->path, got_fileindex_perms_to_st(ie),
8153 (time_t)ie->mtime_sec, blob_idp, staged_blob_idp, commit_idp);
8156 const struct got_error *
8157 got_worktree_path_info(struct got_worktree *worktree,
8158 struct got_pathlist_head *paths,
8159 got_worktree_path_info_cb info_cb, void *info_arg,
8160 got_cancel_cb cancel_cb, void *cancel_arg)
8163 const struct got_error *err = NULL, *unlockerr;
8164 struct got_fileindex *fileindex = NULL;
8165 char *fileindex_path = NULL;
8166 struct report_file_info_arg arg;
8168 err = lock_worktree(worktree, LOCK_SH);
8169 if (err)
8170 return err;
8172 err = open_fileindex(&fileindex, &fileindex_path, worktree);
8173 if (err)
8174 goto done;
8176 arg.worktree = worktree;
8177 arg.info_cb = info_cb;
8178 arg.info_arg = info_arg;
8179 arg.paths = paths;
8180 arg.cancel_cb = cancel_cb;
8181 arg.cancel_arg = cancel_arg;
8182 err = got_fileindex_for_each_entry_safe(fileindex, report_file_info,
8183 &arg);
8184 done:
8185 free(fileindex_path);
8186 if (fileindex)
8187 got_fileindex_free(fileindex);
8188 unlockerr = lock_worktree(worktree, LOCK_UN);
8189 if (unlockerr && err == NULL)
8190 err = unlockerr;
8191 return err;