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>
19 #include <dirent.h>
20 #include <limits.h>
21 #include <stddef.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <time.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <sha1.h>
30 #include <zlib.h>
31 #include <fnmatch.h>
32 #include <libgen.h>
34 #include "got_compat.h"
36 #include "got_error.h"
37 #include "got_repository.h"
38 #include "got_reference.h"
39 #include "got_object.h"
40 #include "got_path.h"
41 #include "got_cancel.h"
42 #include "got_worktree.h"
43 #include "got_opentemp.h"
44 #include "got_diff.h"
46 #include "got_lib_worktree.h"
47 #include "got_lib_sha1.h"
48 #include "got_lib_fileindex.h"
49 #include "got_lib_inflate.h"
50 #include "got_lib_delta.h"
51 #include "got_lib_object.h"
52 #include "got_lib_object_parse.h"
53 #include "got_lib_object_create.h"
54 #include "got_lib_object_idset.h"
55 #include "got_lib_diff.h"
56 #include "got_lib_gotconfig.h"
58 #ifndef MIN
59 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
60 #endif
62 #define GOT_MERGE_LABEL_MERGED "merged change"
63 #define GOT_MERGE_LABEL_BASE "3-way merge base"
65 static const struct got_error *
66 create_meta_file(const char *path_got, const char *name, const char *content)
67 {
68 const struct got_error *err = NULL;
69 char *path;
71 if (asprintf(&path, "%s/%s", path_got, name) == -1)
72 return got_error_from_errno("asprintf");
74 err = got_path_create_file(path, content);
75 free(path);
76 return err;
77 }
79 static const struct got_error *
80 update_meta_file(const char *path_got, const char *name, const char *content)
81 {
82 const struct got_error *err = NULL;
83 FILE *tmpfile = NULL;
84 char *tmppath = NULL;
85 char *path = NULL;
87 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
88 err = got_error_from_errno("asprintf");
89 path = NULL;
90 goto done;
91 }
93 err = got_opentemp_named(&tmppath, &tmpfile, path);
94 if (err)
95 goto done;
97 if (content) {
98 int len = fprintf(tmpfile, "%s\n", content);
99 if (len != strlen(content) + 1) {
100 err = got_error_from_errno2("fprintf", tmppath);
101 goto done;
105 if (rename(tmppath, path) != 0) {
106 err = got_error_from_errno3("rename", tmppath, path);
107 unlink(tmppath);
108 goto done;
111 done:
112 if (fclose(tmpfile) == EOF && err == NULL)
113 err = got_error_from_errno2("fclose", tmppath);
114 free(tmppath);
115 return err;
118 static const struct got_error *
119 read_meta_file(char **content, const char *path_got, const char *name)
121 const struct got_error *err = NULL;
122 char *path;
123 int fd = -1;
124 ssize_t n;
125 struct stat sb;
127 *content = NULL;
129 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
130 err = got_error_from_errno("asprintf");
131 path = NULL;
132 goto done;
135 fd = open(path, O_RDONLY | O_NOFOLLOW);
136 if (fd == -1) {
137 if (errno == ENOENT)
138 err = got_error_path(path, GOT_ERR_WORKTREE_META);
139 else
140 err = got_error_from_errno2("open", path);
141 goto done;
143 if (flock(fd, LOCK_SH | LOCK_NB) == -1) {
144 err = (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
145 : got_error_from_errno2("flock", path));
146 goto done;
149 if (fstat(fd, &sb) != 0) {
150 err = got_error_from_errno2("fstat", path);
151 goto done;
153 *content = calloc(1, sb.st_size);
154 if (*content == NULL) {
155 err = got_error_from_errno("calloc");
156 goto done;
159 n = read(fd, *content, sb.st_size);
160 if (n != sb.st_size) {
161 err = (n == -1 ? got_error_from_errno2("read", path) :
162 got_error_path(path, GOT_ERR_WORKTREE_META));
163 goto done;
165 if ((*content)[sb.st_size - 1] != '\n') {
166 err = got_error_path(path, GOT_ERR_WORKTREE_META);
167 goto done;
169 (*content)[sb.st_size - 1] = '\0';
171 done:
172 if (fd != -1 && close(fd) == -1 && err == NULL)
173 err = got_error_from_errno2("close", path_got);
174 free(path);
175 if (err) {
176 free(*content);
177 *content = NULL;
179 return err;
182 static const struct got_error *
183 write_head_ref(const char *path_got, struct got_reference *head_ref)
185 const struct got_error *err = NULL;
186 char *refstr = NULL;
188 if (got_ref_is_symbolic(head_ref)) {
189 refstr = got_ref_to_str(head_ref);
190 if (refstr == NULL)
191 return got_error_from_errno("got_ref_to_str");
192 } else {
193 refstr = strdup(got_ref_get_name(head_ref));
194 if (refstr == NULL)
195 return got_error_from_errno("strdup");
197 err = update_meta_file(path_got, GOT_WORKTREE_HEAD_REF, refstr);
198 free(refstr);
199 return err;
202 const struct got_error *
203 got_worktree_init(const char *path, struct got_reference *head_ref,
204 const char *prefix, struct got_repository *repo)
206 const struct got_error *err = NULL;
207 struct got_object_id *commit_id = NULL;
208 uuid_t uuid;
209 uint32_t uuid_status;
210 int obj_type;
211 char *path_got = NULL;
212 char *formatstr = NULL;
213 char *absprefix = NULL;
214 char *basestr = NULL;
215 char *uuidstr = NULL;
217 if (strcmp(path, got_repo_get_path(repo)) == 0) {
218 err = got_error(GOT_ERR_WORKTREE_REPO);
219 goto done;
222 err = got_ref_resolve(&commit_id, repo, head_ref);
223 if (err)
224 return err;
225 err = got_object_get_type(&obj_type, repo, commit_id);
226 if (err)
227 return err;
228 if (obj_type != GOT_OBJ_TYPE_COMMIT)
229 return got_error(GOT_ERR_OBJ_TYPE);
231 if (!got_path_is_absolute(prefix)) {
232 if (asprintf(&absprefix, "/%s", prefix) == -1)
233 return got_error_from_errno("asprintf");
236 /* Create top-level directory (may already exist). */
237 if (mkdir(path, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
238 err = got_error_from_errno2("mkdir", path);
239 goto done;
242 /* Create .got directory (may already exist). */
243 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
244 err = got_error_from_errno("asprintf");
245 goto done;
247 if (mkdir(path_got, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
248 err = got_error_from_errno2("mkdir", path_got);
249 goto done;
252 /* Create an empty lock file. */
253 err = create_meta_file(path_got, GOT_WORKTREE_LOCK, NULL);
254 if (err)
255 goto done;
257 /* Create an empty file index. */
258 err = create_meta_file(path_got, GOT_WORKTREE_FILE_INDEX, NULL);
259 if (err)
260 goto done;
262 /* Write the HEAD reference. */
263 err = write_head_ref(path_got, head_ref);
264 if (err)
265 goto done;
267 /* Record our base commit. */
268 err = got_object_id_str(&basestr, commit_id);
269 if (err)
270 goto done;
271 err = create_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, basestr);
272 if (err)
273 goto done;
275 /* Store path to repository. */
276 err = create_meta_file(path_got, GOT_WORKTREE_REPOSITORY,
277 got_repo_get_path(repo));
278 if (err)
279 goto done;
281 /* Store in-repository path prefix. */
282 err = create_meta_file(path_got, GOT_WORKTREE_PATH_PREFIX,
283 absprefix ? absprefix : prefix);
284 if (err)
285 goto done;
287 /* Generate UUID. */
288 uuid_create(&uuid, &uuid_status);
289 if (uuid_status != uuid_s_ok) {
290 err = got_error_uuid(uuid_status, "uuid_create");
291 goto done;
293 uuid_to_string(&uuid, &uuidstr, &uuid_status);
294 if (uuid_status != uuid_s_ok) {
295 err = got_error_uuid(uuid_status, "uuid_to_string");
296 goto done;
298 err = create_meta_file(path_got, GOT_WORKTREE_UUID, uuidstr);
299 if (err)
300 goto done;
302 /* Stamp work tree with format file. */
303 if (asprintf(&formatstr, "%d", GOT_WORKTREE_FORMAT_VERSION) == -1) {
304 err = got_error_from_errno("asprintf");
305 goto done;
307 err = create_meta_file(path_got, GOT_WORKTREE_FORMAT, formatstr);
308 if (err)
309 goto done;
311 done:
312 free(commit_id);
313 free(path_got);
314 free(formatstr);
315 free(absprefix);
316 free(basestr);
317 free(uuidstr);
318 return err;
321 static const struct got_error *
322 open_worktree(struct got_worktree **worktree, const char *path)
324 const struct got_error *err = NULL;
325 char *path_got;
326 char *formatstr = NULL;
327 char *uuidstr = NULL;
328 char *path_lock = NULL;
329 char *base_commit_id_str = NULL;
330 int version, fd = -1;
331 const char *errstr;
332 struct got_repository *repo = NULL;
333 uint32_t uuid_status;
335 *worktree = NULL;
337 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
338 err = got_error_from_errno("asprintf");
339 path_got = NULL;
340 goto done;
343 if (asprintf(&path_lock, "%s/%s", path_got, GOT_WORKTREE_LOCK) == -1) {
344 err = got_error_from_errno("asprintf");
345 path_lock = NULL;
346 goto done;
349 fd = open(path_lock, O_RDWR | O_EXLOCK | O_NONBLOCK);
350 if (fd == -1) {
351 err = (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
352 : got_error_from_errno2("open", path_lock));
353 goto done;
356 err = read_meta_file(&formatstr, path_got, GOT_WORKTREE_FORMAT);
357 if (err)
358 goto done;
360 version = strtonum(formatstr, 1, INT_MAX, &errstr);
361 if (errstr) {
362 err = got_error_msg(GOT_ERR_WORKTREE_META,
363 "could not parse work tree format version number");
364 goto done;
366 if (version != GOT_WORKTREE_FORMAT_VERSION) {
367 err = got_error(GOT_ERR_WORKTREE_VERS);
368 goto done;
371 *worktree = calloc(1, sizeof(**worktree));
372 if (*worktree == NULL) {
373 err = got_error_from_errno("calloc");
374 goto done;
376 (*worktree)->lockfd = -1;
378 (*worktree)->root_path = realpath(path, NULL);
379 if ((*worktree)->root_path == NULL) {
380 err = got_error_from_errno2("realpath", path);
381 goto done;
383 err = read_meta_file(&(*worktree)->repo_path, path_got,
384 GOT_WORKTREE_REPOSITORY);
385 if (err)
386 goto done;
388 err = read_meta_file(&(*worktree)->path_prefix, path_got,
389 GOT_WORKTREE_PATH_PREFIX);
390 if (err)
391 goto done;
393 err = read_meta_file(&base_commit_id_str, path_got,
394 GOT_WORKTREE_BASE_COMMIT);
395 if (err)
396 goto done;
398 err = read_meta_file(&uuidstr, path_got, GOT_WORKTREE_UUID);
399 if (err)
400 goto done;
401 uuid_from_string(uuidstr, &(*worktree)->uuid, &uuid_status);
402 if (uuid_status != uuid_s_ok) {
403 err = got_error_uuid(uuid_status, "uuid_from_string");
404 goto done;
407 err = got_repo_open(&repo, (*worktree)->repo_path, NULL);
408 if (err)
409 goto done;
411 err = got_object_resolve_id_str(&(*worktree)->base_commit_id, repo,
412 base_commit_id_str);
413 if (err)
414 goto done;
416 err = read_meta_file(&(*worktree)->head_ref_name, path_got,
417 GOT_WORKTREE_HEAD_REF);
418 if (err)
419 goto done;
421 if (asprintf(&(*worktree)->gotconfig_path, "%s/%s/%s",
422 (*worktree)->root_path,
423 GOT_WORKTREE_GOT_DIR, GOT_GOTCONFIG_FILENAME) == -1) {
424 err = got_error_from_errno("asprintf");
425 goto done;
428 err = got_gotconfig_read(&(*worktree)->gotconfig,
429 (*worktree)->gotconfig_path);
431 (*worktree)->root_fd = open((*worktree)->root_path, O_DIRECTORY);
432 if ((*worktree)->root_fd == -1) {
433 err = got_error_from_errno2("open", (*worktree)->root_path);
434 goto done;
436 done:
437 if (repo) {
438 const struct got_error *close_err = got_repo_close(repo);
439 if (err == NULL)
440 err = close_err;
442 free(path_got);
443 free(path_lock);
444 free(base_commit_id_str);
445 free(uuidstr);
446 free(formatstr);
447 if (err) {
448 if (fd != -1)
449 close(fd);
450 if (*worktree != NULL)
451 got_worktree_close(*worktree);
452 *worktree = NULL;
453 } else
454 (*worktree)->lockfd = fd;
456 return err;
459 const struct got_error *
460 got_worktree_open(struct got_worktree **worktree, const char *path)
462 const struct got_error *err = NULL;
463 char *worktree_path;
465 worktree_path = strdup(path);
466 if (worktree_path == NULL)
467 return got_error_from_errno("strdup");
469 for (;;) {
470 char *parent_path;
472 err = open_worktree(worktree, worktree_path);
473 if (err && !(err->code == GOT_ERR_ERRNO && errno == ENOENT)) {
474 free(worktree_path);
475 return err;
477 if (*worktree) {
478 free(worktree_path);
479 return NULL;
481 if (worktree_path[0] == '/' && worktree_path[1] == '\0')
482 break;
483 err = got_path_dirname(&parent_path, worktree_path);
484 if (err) {
485 if (err->code != GOT_ERR_BAD_PATH) {
486 free(worktree_path);
487 return err;
489 break;
491 free(worktree_path);
492 worktree_path = parent_path;
495 free(worktree_path);
496 return got_error(GOT_ERR_NOT_WORKTREE);
499 const struct got_error *
500 got_worktree_close(struct got_worktree *worktree)
502 const struct got_error *err = NULL;
504 if (worktree->lockfd != -1) {
505 if (close(worktree->lockfd) == -1)
506 err = got_error_from_errno2("close",
507 got_worktree_get_root_path(worktree));
509 if (close(worktree->root_fd) == -1 && err == NULL)
510 err = got_error_from_errno2("close",
511 got_worktree_get_root_path(worktree));
512 free(worktree->repo_path);
513 free(worktree->path_prefix);
514 free(worktree->base_commit_id);
515 free(worktree->head_ref_name);
516 free(worktree->root_path);
517 free(worktree->gotconfig_path);
518 got_gotconfig_free(worktree->gotconfig);
519 free(worktree);
520 return err;
523 const char *
524 got_worktree_get_root_path(struct got_worktree *worktree)
526 return worktree->root_path;
529 const char *
530 got_worktree_get_repo_path(struct got_worktree *worktree)
532 return worktree->repo_path;
534 const char *
535 got_worktree_get_path_prefix(struct got_worktree *worktree)
537 return worktree->path_prefix;
540 const struct got_error *
541 got_worktree_match_path_prefix(int *match, struct got_worktree *worktree,
542 const char *path_prefix)
544 char *absprefix = NULL;
546 if (!got_path_is_absolute(path_prefix)) {
547 if (asprintf(&absprefix, "/%s", path_prefix) == -1)
548 return got_error_from_errno("asprintf");
550 *match = (strcmp(absprefix ? absprefix : path_prefix,
551 worktree->path_prefix) == 0);
552 free(absprefix);
553 return NULL;
556 const char *
557 got_worktree_get_head_ref_name(struct got_worktree *worktree)
559 return worktree->head_ref_name;
562 const struct got_error *
563 got_worktree_set_head_ref(struct got_worktree *worktree,
564 struct got_reference *head_ref)
566 const struct got_error *err = NULL;
567 char *path_got = NULL, *head_ref_name = NULL;
569 if (asprintf(&path_got, "%s/%s", worktree->root_path,
570 GOT_WORKTREE_GOT_DIR) == -1) {
571 err = got_error_from_errno("asprintf");
572 path_got = NULL;
573 goto done;
576 head_ref_name = strdup(got_ref_get_name(head_ref));
577 if (head_ref_name == NULL) {
578 err = got_error_from_errno("strdup");
579 goto done;
582 err = write_head_ref(path_got, head_ref);
583 if (err)
584 goto done;
586 free(worktree->head_ref_name);
587 worktree->head_ref_name = head_ref_name;
588 done:
589 free(path_got);
590 if (err)
591 free(head_ref_name);
592 return err;
595 struct got_object_id *
596 got_worktree_get_base_commit_id(struct got_worktree *worktree)
598 return worktree->base_commit_id;
601 const struct got_error *
602 got_worktree_set_base_commit_id(struct got_worktree *worktree,
603 struct got_repository *repo, struct got_object_id *commit_id)
605 const struct got_error *err;
606 struct got_object *obj = NULL;
607 char *id_str = NULL;
608 char *path_got = NULL;
610 if (asprintf(&path_got, "%s/%s", worktree->root_path,
611 GOT_WORKTREE_GOT_DIR) == -1) {
612 err = got_error_from_errno("asprintf");
613 path_got = NULL;
614 goto done;
617 err = got_object_open(&obj, repo, commit_id);
618 if (err)
619 return err;
621 if (obj->type != GOT_OBJ_TYPE_COMMIT) {
622 err = got_error(GOT_ERR_OBJ_TYPE);
623 goto done;
626 /* Record our base commit. */
627 err = got_object_id_str(&id_str, commit_id);
628 if (err)
629 goto done;
630 err = update_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, id_str);
631 if (err)
632 goto done;
634 free(worktree->base_commit_id);
635 worktree->base_commit_id = got_object_id_dup(commit_id);
636 if (worktree->base_commit_id == NULL) {
637 err = got_error_from_errno("got_object_id_dup");
638 goto done;
640 done:
641 if (obj)
642 got_object_close(obj);
643 free(id_str);
644 free(path_got);
645 return err;
648 const struct got_gotconfig *
649 got_worktree_get_gotconfig(struct got_worktree *worktree)
651 return worktree->gotconfig;
654 static const struct got_error *
655 lock_worktree(struct got_worktree *worktree, int operation)
657 if (flock(worktree->lockfd, operation | LOCK_NB) == -1)
658 return (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
659 : got_error_from_errno2("flock",
660 got_worktree_get_root_path(worktree)));
661 return NULL;
664 static const struct got_error *
665 add_dir_on_disk(struct got_worktree *worktree, const char *path)
667 const struct got_error *err = NULL;
668 char *abspath;
670 if (asprintf(&abspath, "%s/%s", worktree->root_path, path) == -1)
671 return got_error_from_errno("asprintf");
673 err = got_path_mkdir(abspath);
674 if (err && err->code == GOT_ERR_ERRNO && errno == EEXIST) {
675 struct stat sb;
676 err = NULL;
677 if (lstat(abspath, &sb) == -1) {
678 err = got_error_from_errno2("lstat", abspath);
679 } else if (!S_ISDIR(sb.st_mode)) {
680 /* TODO directory is obstructed; do something */
681 err = got_error_path(abspath, GOT_ERR_FILE_OBSTRUCTED);
684 free(abspath);
685 return err;
688 static const struct got_error *
689 check_file_contents_equal(int *same, FILE *f1, FILE *f2)
691 const struct got_error *err = NULL;
692 uint8_t fbuf1[8192];
693 uint8_t fbuf2[8192];
694 size_t flen1 = 0, flen2 = 0;
696 *same = 1;
698 for (;;) {
699 flen1 = fread(fbuf1, 1, sizeof(fbuf1), f1);
700 if (flen1 == 0 && ferror(f1)) {
701 err = got_error_from_errno("fread");
702 break;
704 flen2 = fread(fbuf2, 1, sizeof(fbuf2), f2);
705 if (flen2 == 0 && ferror(f2)) {
706 err = got_error_from_errno("fread");
707 break;
709 if (flen1 == 0) {
710 if (flen2 != 0)
711 *same = 0;
712 break;
713 } else if (flen2 == 0) {
714 if (flen1 != 0)
715 *same = 0;
716 break;
717 } else if (flen1 == flen2) {
718 if (memcmp(fbuf1, fbuf2, flen2) != 0) {
719 *same = 0;
720 break;
722 } else {
723 *same = 0;
724 break;
728 return err;
731 static const struct got_error *
732 check_files_equal(int *same, FILE *f1, FILE *f2)
734 struct stat sb;
735 size_t size1, size2;
737 *same = 1;
739 if (fstat(fileno(f1), &sb) != 0)
740 return got_error_from_errno("fstat");
741 size1 = sb.st_size;
743 if (fstat(fileno(f2), &sb) != 0)
744 return got_error_from_errno("fstat");
745 size2 = sb.st_size;
747 if (size1 != size2) {
748 *same = 0;
749 return NULL;
752 if (fseek(f1, 0L, SEEK_SET) == -1)
753 return got_ferror(f1, GOT_ERR_IO);
754 if (fseek(f2, 0L, SEEK_SET) == -1)
755 return got_ferror(f2, GOT_ERR_IO);
757 return check_file_contents_equal(same, f1, f2);
760 /*
761 * Perform a 3-way merge where the file f_orig acts as the common
762 * ancestor, the file f_deriv acts as the first derived version,
763 * and the file f_deriv2 acts as the second derived version.
764 * The merge result will be written to a new file at ondisk_path; any
765 * existing file at this path will be replaced.
766 */
767 static const struct got_error *
768 merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
769 FILE *f_orig, FILE *f_deriv, FILE *f_deriv2, const char *ondisk_path,
770 const char *path, uint16_t st_mode,
771 const char *label_orig, const char *label_deriv, const char *label_deriv2,
772 enum got_diff_algorithm diff_algo, struct got_repository *repo,
773 got_worktree_checkout_cb progress_cb, void *progress_arg)
775 const struct got_error *err = NULL;
776 int merged_fd = -1;
777 FILE *f_merged = NULL;
778 char *merged_path = NULL, *base_path = NULL;
779 int overlapcnt = 0;
780 char *parent = NULL;
782 *local_changes_subsumed = 0;
784 err = got_path_dirname(&parent, ondisk_path);
785 if (err)
786 return err;
788 if (asprintf(&base_path, "%s/got-merged", parent) == -1) {
789 err = got_error_from_errno("asprintf");
790 goto done;
793 err = got_opentemp_named_fd(&merged_path, &merged_fd, base_path);
794 if (err)
795 goto done;
797 err = got_merge_diff3(&overlapcnt, merged_fd, f_deriv, f_orig,
798 f_deriv2, label_deriv, label_orig, label_deriv2, diff_algo);
799 if (err)
800 goto done;
802 err = (*progress_cb)(progress_arg,
803 overlapcnt > 0 ? GOT_STATUS_CONFLICT : GOT_STATUS_MERGE, path);
804 if (err)
805 goto done;
807 if (fsync(merged_fd) != 0) {
808 err = got_error_from_errno("fsync");
809 goto done;
812 f_merged = fdopen(merged_fd, "r");
813 if (f_merged == NULL) {
814 err = got_error_from_errno("fdopen");
815 goto done;
817 merged_fd = -1;
819 /* Check if a clean merge has subsumed all local changes. */
820 if (overlapcnt == 0) {
821 err = check_files_equal(local_changes_subsumed, f_deriv,
822 f_merged);
823 if (err)
824 goto done;
827 if (fchmod(fileno(f_merged), st_mode) != 0) {
828 err = got_error_from_errno2("fchmod", merged_path);
829 goto done;
832 if (rename(merged_path, ondisk_path) != 0) {
833 err = got_error_from_errno3("rename", merged_path,
834 ondisk_path);
835 goto done;
837 done:
838 if (err) {
839 if (merged_path)
840 unlink(merged_path);
842 if (merged_fd != -1 && close(merged_fd) == -1 && err == NULL)
843 err = got_error_from_errno("close");
844 if (f_merged && fclose(f_merged) == EOF && err == NULL)
845 err = got_error_from_errno("fclose");
846 free(merged_path);
847 free(base_path);
848 free(parent);
849 return err;
852 static const struct got_error *
853 update_symlink(const char *ondisk_path, const char *target_path,
854 size_t target_len)
856 /* This is not atomic but matches what 'ln -sf' does. */
857 if (unlink(ondisk_path) == -1)
858 return got_error_from_errno2("unlink", ondisk_path);
859 if (symlink(target_path, ondisk_path) == -1)
860 return got_error_from_errno3("symlink", target_path,
861 ondisk_path);
862 return NULL;
865 /*
866 * Overwrite a symlink (or a regular file in case there was a "bad" symlink)
867 * in the work tree with a file that contains conflict markers and the
868 * conflicting target paths of the original version, a "derived version"
869 * of a symlink from an incoming change, and a local version of the symlink.
871 * The original versions's target path can be NULL if it is not available,
872 * such as if both derived versions added a new symlink at the same path.
874 * The incoming derived symlink target is NULL in case the incoming change
875 * has deleted this symlink.
876 */
877 static const struct got_error *
878 install_symlink_conflict(const char *deriv_target,
879 struct got_object_id *deriv_base_commit_id, const char *orig_target,
880 const char *label_orig, const char *local_target, const char *ondisk_path)
882 const struct got_error *err;
883 char *id_str = NULL, *label_deriv = NULL, *path = NULL;
884 FILE *f = NULL;
886 err = got_object_id_str(&id_str, deriv_base_commit_id);
887 if (err)
888 return got_error_from_errno("asprintf");
890 if (asprintf(&label_deriv, "%s: commit %s",
891 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
892 err = got_error_from_errno("asprintf");
893 goto done;
896 err = got_opentemp_named(&path, &f, "got-symlink-conflict");
897 if (err)
898 goto done;
900 if (fchmod(fileno(f), GOT_DEFAULT_FILE_MODE) == -1) {
901 err = got_error_from_errno2("fchmod", path);
902 goto done;
905 if (fprintf(f, "%s %s\n%s\n%s%s%s%s%s\n%s\n%s\n",
906 GOT_DIFF_CONFLICT_MARKER_BEGIN, label_deriv,
907 deriv_target ? deriv_target : "(symlink was deleted)",
908 orig_target ? label_orig : "",
909 orig_target ? "\n" : "",
910 orig_target ? orig_target : "",
911 orig_target ? "\n" : "",
912 GOT_DIFF_CONFLICT_MARKER_SEP,
913 local_target, GOT_DIFF_CONFLICT_MARKER_END) < 0) {
914 err = got_error_from_errno2("fprintf", path);
915 goto done;
918 if (unlink(ondisk_path) == -1) {
919 err = got_error_from_errno2("unlink", ondisk_path);
920 goto done;
922 if (rename(path, ondisk_path) == -1) {
923 err = got_error_from_errno3("rename", path, ondisk_path);
924 goto done;
926 done:
927 if (f != NULL && fclose(f) == EOF && err == NULL)
928 err = got_error_from_errno2("fclose", path);
929 free(path);
930 free(id_str);
931 free(label_deriv);
932 return err;
935 /* forward declaration */
936 static const struct got_error *
937 merge_blob(int *, struct got_worktree *, struct got_blob_object *,
938 const char *, const char *, uint16_t, const char *,
939 struct got_blob_object *, struct got_object_id *,
940 struct got_repository *, got_worktree_checkout_cb, void *);
942 /*
943 * Merge a symlink into the work tree, where blob_orig acts as the common
944 * ancestor, deriv_target is the link target of the first derived version,
945 * and the symlink on disk acts as the second derived version.
946 * Assume that contents of both blobs represent symlinks.
947 */
948 static const struct got_error *
949 merge_symlink(struct got_worktree *worktree,
950 struct got_blob_object *blob_orig, const char *ondisk_path,
951 const char *path, const char *label_orig, const char *deriv_target,
952 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
953 got_worktree_checkout_cb progress_cb, void *progress_arg)
955 const struct got_error *err = NULL;
956 char *ancestor_target = NULL;
957 struct stat sb;
958 ssize_t ondisk_len, deriv_len;
959 char ondisk_target[PATH_MAX];
960 int have_local_change = 0;
961 int have_incoming_change = 0;
963 if (lstat(ondisk_path, &sb) == -1)
964 return got_error_from_errno2("lstat", ondisk_path);
966 ondisk_len = readlink(ondisk_path, ondisk_target,
967 sizeof(ondisk_target));
968 if (ondisk_len == -1) {
969 err = got_error_from_errno2("readlink",
970 ondisk_path);
971 goto done;
973 ondisk_target[ondisk_len] = '\0';
975 if (blob_orig) {
976 err = got_object_blob_read_to_str(&ancestor_target, blob_orig);
977 if (err)
978 goto done;
981 if (ancestor_target == NULL ||
982 (ondisk_len != strlen(ancestor_target) ||
983 memcmp(ondisk_target, ancestor_target, ondisk_len) != 0))
984 have_local_change = 1;
986 deriv_len = strlen(deriv_target);
987 if (ancestor_target == NULL ||
988 (deriv_len != strlen(ancestor_target) ||
989 memcmp(deriv_target, ancestor_target, deriv_len) != 0))
990 have_incoming_change = 1;
992 if (!have_local_change && !have_incoming_change) {
993 if (ancestor_target) {
994 /* Both sides made the same change. */
995 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
996 path);
997 } else if (deriv_len == ondisk_len &&
998 memcmp(ondisk_target, deriv_target, deriv_len) == 0) {
999 /* Both sides added the same symlink. */
1000 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
1001 path);
1002 } else {
1003 /* Both sides added symlinks which don't match. */
1004 err = install_symlink_conflict(deriv_target,
1005 deriv_base_commit_id, ancestor_target,
1006 label_orig, ondisk_target, ondisk_path);
1007 if (err)
1008 goto done;
1009 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
1010 path);
1012 } else if (!have_local_change && have_incoming_change) {
1013 /* Apply the incoming change. */
1014 err = update_symlink(ondisk_path, deriv_target,
1015 strlen(deriv_target));
1016 if (err)
1017 goto done;
1018 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
1019 } else if (have_local_change && have_incoming_change) {
1020 if (deriv_len == ondisk_len &&
1021 memcmp(deriv_target, ondisk_target, deriv_len) == 0) {
1022 /* Both sides made the same change. */
1023 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE,
1024 path);
1025 } else {
1026 err = install_symlink_conflict(deriv_target,
1027 deriv_base_commit_id, ancestor_target, label_orig,
1028 ondisk_target, ondisk_path);
1029 if (err)
1030 goto done;
1031 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
1032 path);
1036 done:
1037 free(ancestor_target);
1038 return err;
1041 static const struct got_error *
1042 dump_symlink_target_path_to_file(FILE **outfile, const char *ondisk_path)
1044 const struct got_error *err = NULL;
1045 char target_path[PATH_MAX];
1046 ssize_t target_len;
1047 size_t n;
1048 FILE *f;
1050 *outfile = NULL;
1052 f = got_opentemp();
1053 if (f == NULL)
1054 return got_error_from_errno("got_opentemp");
1055 target_len = readlink(ondisk_path, target_path, sizeof(target_path));
1056 if (target_len == -1) {
1057 err = got_error_from_errno2("readlink", ondisk_path);
1058 goto done;
1060 n = fwrite(target_path, 1, target_len, f);
1061 if (n != target_len) {
1062 err = got_ferror(f, GOT_ERR_IO);
1063 goto done;
1065 if (fflush(f) == EOF) {
1066 err = got_error_from_errno("fflush");
1067 goto done;
1069 if (fseek(f, 0L, SEEK_SET) == -1) {
1070 err = got_ferror(f, GOT_ERR_IO);
1071 goto done;
1073 done:
1074 if (err)
1075 fclose(f);
1076 else
1077 *outfile = f;
1078 return err;
1082 * Perform a 3-way merge where blob_orig acts as the common ancestor,
1083 * blob_deriv acts as the first derived version, and the file on disk
1084 * acts as the second derived version.
1086 static const struct got_error *
1087 merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
1088 struct got_blob_object *blob_orig, const char *ondisk_path,
1089 const char *path, uint16_t st_mode, const char *label_orig,
1090 struct got_blob_object *blob_deriv,
1091 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
1092 got_worktree_checkout_cb progress_cb, void *progress_arg)
1094 const struct got_error *err = NULL;
1095 FILE *f_orig = NULL, *f_deriv = NULL, *f_deriv2 = NULL;
1096 char *blob_orig_path = NULL;
1097 char *blob_deriv_path = NULL, *base_path = NULL, *id_str = NULL;
1098 char *label_deriv = NULL, *parent = NULL;
1100 *local_changes_subsumed = 0;
1102 err = got_path_dirname(&parent, ondisk_path);
1103 if (err)
1104 return err;
1106 if (blob_orig) {
1107 if (asprintf(&base_path, "%s/got-merge-blob-orig",
1108 parent) == -1) {
1109 err = got_error_from_errno("asprintf");
1110 base_path = NULL;
1111 goto done;
1114 err = got_opentemp_named(&blob_orig_path, &f_orig, base_path);
1115 if (err)
1116 goto done;
1117 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_orig,
1118 blob_orig);
1119 if (err)
1120 goto done;
1121 free(base_path);
1122 } else {
1124 * No common ancestor exists. This is an "add vs add" conflict
1125 * and we simply use an empty ancestor file to make both files
1126 * appear in the merged result in their entirety.
1128 f_orig = got_opentemp();
1129 if (f_orig == NULL) {
1130 err = got_error_from_errno("got_opentemp");
1131 goto done;
1135 if (asprintf(&base_path, "%s/got-merge-blob-deriv", parent) == -1) {
1136 err = got_error_from_errno("asprintf");
1137 base_path = NULL;
1138 goto done;
1141 err = got_opentemp_named(&blob_deriv_path, &f_deriv, base_path);
1142 if (err)
1143 goto done;
1144 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_deriv,
1145 blob_deriv);
1146 if (err)
1147 goto done;
1149 err = got_object_id_str(&id_str, deriv_base_commit_id);
1150 if (err)
1151 goto done;
1152 if (asprintf(&label_deriv, "%s: commit %s",
1153 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
1154 err = got_error_from_errno("asprintf");
1155 goto done;
1159 * In order the run a 3-way merge with a symlink we copy the symlink's
1160 * target path into a temporary file and use that file with diff3.
1162 if (S_ISLNK(st_mode)) {
1163 err = dump_symlink_target_path_to_file(&f_deriv2, ondisk_path);
1164 if (err)
1165 goto done;
1166 } else {
1167 int fd;
1168 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW);
1169 if (fd == -1) {
1170 err = got_error_from_errno2("open", ondisk_path);
1171 goto done;
1173 f_deriv2 = fdopen(fd, "r");
1174 if (f_deriv2 == NULL) {
1175 err = got_error_from_errno2("fdopen", ondisk_path);
1176 close(fd);
1177 goto done;
1181 err = merge_file(local_changes_subsumed, worktree, f_orig, f_deriv,
1182 f_deriv2, ondisk_path, path, st_mode, label_orig, label_deriv,
1183 NULL, GOT_DIFF_ALGORITHM_MYERS, repo, progress_cb, progress_arg);
1184 done:
1185 if (f_orig && fclose(f_orig) == EOF && err == NULL)
1186 err = got_error_from_errno("fclose");
1187 if (f_deriv && fclose(f_deriv) == EOF && err == NULL)
1188 err = got_error_from_errno("fclose");
1189 if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
1190 err = got_error_from_errno("fclose");
1191 free(base_path);
1192 if (blob_orig_path) {
1193 unlink(blob_orig_path);
1194 free(blob_orig_path);
1196 if (blob_deriv_path) {
1197 unlink(blob_deriv_path);
1198 free(blob_deriv_path);
1200 free(id_str);
1201 free(label_deriv);
1202 free(parent);
1203 return err;
1206 static const struct got_error *
1207 create_fileindex_entry(struct got_fileindex_entry **new_iep,
1208 struct got_fileindex *fileindex, struct got_object_id *base_commit_id,
1209 int wt_fd, const char *path, struct got_object_id *blob_id)
1211 const struct got_error *err = NULL;
1212 struct got_fileindex_entry *new_ie;
1214 *new_iep = NULL;
1216 err = got_fileindex_entry_alloc(&new_ie, path);
1217 if (err)
1218 return err;
1220 err = got_fileindex_entry_update(new_ie, wt_fd, path,
1221 blob_id->sha1, base_commit_id->sha1, 1);
1222 if (err)
1223 goto done;
1225 err = got_fileindex_entry_add(fileindex, new_ie);
1226 done:
1227 if (err)
1228 got_fileindex_entry_free(new_ie);
1229 else
1230 *new_iep = new_ie;
1231 return err;
1234 static mode_t
1235 get_ondisk_perms(int executable, mode_t st_mode)
1237 mode_t xbits = S_IXUSR;
1239 if (executable) {
1240 /* Map read bits to execute bits. */
1241 if (st_mode & S_IRGRP)
1242 xbits |= S_IXGRP;
1243 if (st_mode & S_IROTH)
1244 xbits |= S_IXOTH;
1245 return st_mode | xbits;
1248 return (st_mode & ~(S_IXUSR | S_IXGRP | S_IXOTH));
1251 /* forward declaration */
1252 static const struct got_error *
1253 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1254 const char *path, mode_t te_mode, mode_t st_mode,
1255 struct got_blob_object *blob, int restoring_missing_file,
1256 int reverting_versioned_file, int installing_bad_symlink,
1257 int path_is_unversioned, struct got_repository *repo,
1258 got_worktree_checkout_cb progress_cb, void *progress_arg);
1261 * This function assumes that the provided symlink target points at a
1262 * safe location in the work tree!
1264 static const struct got_error *
1265 replace_existing_symlink(int *did_something, const char *ondisk_path,
1266 const char *target_path, size_t target_len)
1268 const struct got_error *err = NULL;
1269 ssize_t elen;
1270 char etarget[PATH_MAX];
1271 int fd;
1273 *did_something = 0;
1276 * "Bad" symlinks (those pointing outside the work tree or into the
1277 * .got directory) are installed in the work tree as a regular file
1278 * which contains the bad symlink target path.
1279 * The new symlink target has already been checked for safety by our
1280 * caller. If we can successfully open a regular file then we simply
1281 * replace this file with a symlink below.
1283 fd = open(ondisk_path, O_RDWR | O_EXCL | O_NOFOLLOW);
1284 if (fd == -1) {
1285 if (errno != ELOOP)
1286 return got_error_from_errno2("open", ondisk_path);
1288 /* We are updating an existing on-disk symlink. */
1289 elen = readlink(ondisk_path, etarget, sizeof(etarget));
1290 if (elen == -1)
1291 return got_error_from_errno2("readlink", ondisk_path);
1293 if (elen == target_len &&
1294 memcmp(etarget, target_path, target_len) == 0)
1295 return NULL; /* nothing to do */
1298 *did_something = 1;
1299 err = update_symlink(ondisk_path, target_path, target_len);
1300 if (fd != -1 && close(fd) == -1 && err == NULL)
1301 err = got_error_from_errno2("close", ondisk_path);
1302 return err;
1305 static const struct got_error *
1306 is_bad_symlink_target(int *is_bad_symlink, const char *target_path,
1307 size_t target_len, const char *ondisk_path, const char *wtroot_path)
1309 const struct got_error *err = NULL;
1310 char canonpath[PATH_MAX];
1311 char *path_got = NULL;
1313 *is_bad_symlink = 0;
1315 if (target_len >= sizeof(canonpath)) {
1316 *is_bad_symlink = 1;
1317 return NULL;
1321 * We do not use realpath(3) to resolve the symlink's target
1322 * path because we don't want to resolve symlinks recursively.
1323 * Instead we make the path absolute and then canonicalize it.
1324 * Relative symlink target lookup should begin at the directory
1325 * in which the blob object is being installed.
1327 if (!got_path_is_absolute(target_path)) {
1328 char *abspath, *parent;
1329 err = got_path_dirname(&parent, ondisk_path);
1330 if (err)
1331 return err;
1332 if (asprintf(&abspath, "%s/%s", parent, target_path) == -1) {
1333 free(parent);
1334 return got_error_from_errno("asprintf");
1336 free(parent);
1337 if (strlen(abspath) >= sizeof(canonpath)) {
1338 err = got_error_path(abspath, GOT_ERR_BAD_PATH);
1339 free(abspath);
1340 return err;
1342 err = got_canonpath(abspath, canonpath, sizeof(canonpath));
1343 free(abspath);
1344 if (err)
1345 return err;
1346 } else {
1347 err = got_canonpath(target_path, canonpath, sizeof(canonpath));
1348 if (err)
1349 return err;
1352 /* Only allow symlinks pointing at paths within the work tree. */
1353 if (!got_path_is_child(canonpath, wtroot_path, strlen(wtroot_path))) {
1354 *is_bad_symlink = 1;
1355 return NULL;
1358 /* Do not allow symlinks pointing into the .got directory. */
1359 if (asprintf(&path_got, "%s/%s", wtroot_path,
1360 GOT_WORKTREE_GOT_DIR) == -1)
1361 return got_error_from_errno("asprintf");
1362 if (got_path_is_child(canonpath, path_got, strlen(path_got)))
1363 *is_bad_symlink = 1;
1365 free(path_got);
1366 return NULL;
1369 static const struct got_error *
1370 install_symlink(int *is_bad_symlink, struct got_worktree *worktree,
1371 const char *ondisk_path, const char *path, struct got_blob_object *blob,
1372 int restoring_missing_file, int reverting_versioned_file,
1373 int path_is_unversioned, struct got_repository *repo,
1374 got_worktree_checkout_cb progress_cb, void *progress_arg)
1376 const struct got_error *err = NULL;
1377 char target_path[PATH_MAX];
1378 size_t len, target_len = 0;
1379 char *path_got = NULL;
1380 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1381 size_t hdrlen = got_object_blob_get_hdrlen(blob);
1383 *is_bad_symlink = 0;
1386 * Blob object content specifies the target path of the link.
1387 * If a symbolic link cannot be installed we instead create
1388 * a regular file which contains the link target path stored
1389 * in the blob object.
1391 do {
1392 err = got_object_blob_read_block(&len, blob);
1393 if (len + target_len >= sizeof(target_path)) {
1394 /* Path too long; install as a regular file. */
1395 *is_bad_symlink = 1;
1396 got_object_blob_rewind(blob);
1397 return install_blob(worktree, ondisk_path, path,
1398 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1399 restoring_missing_file, reverting_versioned_file,
1400 1, path_is_unversioned, repo, progress_cb,
1401 progress_arg);
1403 if (len > 0) {
1404 /* Skip blob object header first time around. */
1405 memcpy(target_path + target_len, buf + hdrlen,
1406 len - hdrlen);
1407 target_len += len - hdrlen;
1408 hdrlen = 0;
1410 } while (len != 0);
1411 target_path[target_len] = '\0';
1413 err = is_bad_symlink_target(is_bad_symlink, target_path, target_len,
1414 ondisk_path, worktree->root_path);
1415 if (err)
1416 return err;
1418 if (*is_bad_symlink) {
1419 /* install as a regular file */
1420 got_object_blob_rewind(blob);
1421 err = install_blob(worktree, ondisk_path, path,
1422 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1423 restoring_missing_file, reverting_versioned_file, 1,
1424 path_is_unversioned, repo, progress_cb, progress_arg);
1425 goto done;
1428 if (symlink(target_path, ondisk_path) == -1) {
1429 if (errno == EEXIST) {
1430 int symlink_replaced;
1431 if (path_is_unversioned) {
1432 err = (*progress_cb)(progress_arg,
1433 GOT_STATUS_UNVERSIONED, path);
1434 goto done;
1436 err = replace_existing_symlink(&symlink_replaced,
1437 ondisk_path, target_path, target_len);
1438 if (err)
1439 goto done;
1440 if (progress_cb) {
1441 if (symlink_replaced) {
1442 err = (*progress_cb)(progress_arg,
1443 reverting_versioned_file ?
1444 GOT_STATUS_REVERT :
1445 GOT_STATUS_UPDATE, path);
1446 } else {
1447 err = (*progress_cb)(progress_arg,
1448 GOT_STATUS_EXISTS, path);
1451 goto done; /* Nothing else to do. */
1454 if (errno == ENOENT) {
1455 char *parent;
1456 err = got_path_dirname(&parent, ondisk_path);
1457 if (err)
1458 goto done;
1459 err = add_dir_on_disk(worktree, parent);
1460 free(parent);
1461 if (err)
1462 goto done;
1464 * Retry, and fall through to error handling
1465 * below if this second attempt fails.
1467 if (symlink(target_path, ondisk_path) != -1) {
1468 err = NULL; /* success */
1469 goto done;
1473 /* Handle errors from first or second creation attempt. */
1474 if (errno == ENAMETOOLONG) {
1475 /* bad target path; install as a regular file */
1476 *is_bad_symlink = 1;
1477 got_object_blob_rewind(blob);
1478 err = install_blob(worktree, ondisk_path, path,
1479 GOT_DEFAULT_FILE_MODE, GOT_DEFAULT_FILE_MODE, blob,
1480 restoring_missing_file, reverting_versioned_file, 1,
1481 path_is_unversioned, repo,
1482 progress_cb, progress_arg);
1483 } else if (errno == ENOTDIR) {
1484 err = got_error_path(ondisk_path,
1485 GOT_ERR_FILE_OBSTRUCTED);
1486 } else {
1487 err = got_error_from_errno3("symlink",
1488 target_path, ondisk_path);
1490 } else if (progress_cb)
1491 err = (*progress_cb)(progress_arg, reverting_versioned_file ?
1492 GOT_STATUS_REVERT : GOT_STATUS_ADD, path);
1493 done:
1494 free(path_got);
1495 return err;
1498 static const struct got_error *
1499 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1500 const char *path, mode_t te_mode, mode_t st_mode,
1501 struct got_blob_object *blob, int restoring_missing_file,
1502 int reverting_versioned_file, int installing_bad_symlink,
1503 int path_is_unversioned, struct got_repository *repo,
1504 got_worktree_checkout_cb progress_cb, void *progress_arg)
1506 const struct got_error *err = NULL;
1507 int fd = -1;
1508 size_t len, hdrlen;
1509 int update = 0;
1510 char *tmppath = NULL;
1512 fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1513 GOT_DEFAULT_FILE_MODE);
1514 if (fd == -1) {
1515 if (errno == ENOENT) {
1516 char *parent;
1517 err = got_path_dirname(&parent, path);
1518 if (err)
1519 return err;
1520 err = add_dir_on_disk(worktree, parent);
1521 free(parent);
1522 if (err)
1523 return err;
1524 fd = open(ondisk_path,
1525 O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1526 GOT_DEFAULT_FILE_MODE);
1527 if (fd == -1)
1528 return got_error_from_errno2("open",
1529 ondisk_path);
1530 } else if (errno == EEXIST) {
1531 if (path_is_unversioned) {
1532 err = (*progress_cb)(progress_arg,
1533 GOT_STATUS_UNVERSIONED, path);
1534 goto done;
1536 if (!(S_ISLNK(st_mode) && S_ISREG(te_mode)) &&
1537 !S_ISREG(st_mode) && !installing_bad_symlink) {
1538 /* TODO file is obstructed; do something */
1539 err = got_error_path(ondisk_path,
1540 GOT_ERR_FILE_OBSTRUCTED);
1541 goto done;
1542 } else {
1543 err = got_opentemp_named_fd(&tmppath, &fd,
1544 ondisk_path);
1545 if (err)
1546 goto done;
1547 update = 1;
1549 } else
1550 return got_error_from_errno2("open", ondisk_path);
1553 if (fchmod(fd, get_ondisk_perms(te_mode & S_IXUSR, st_mode)) == -1) {
1554 err = got_error_from_errno2("fchmod",
1555 update ? tmppath : ondisk_path);
1556 goto done;
1559 if (progress_cb) {
1560 if (restoring_missing_file)
1561 err = (*progress_cb)(progress_arg, GOT_STATUS_MISSING,
1562 path);
1563 else if (reverting_versioned_file)
1564 err = (*progress_cb)(progress_arg, GOT_STATUS_REVERT,
1565 path);
1566 else
1567 err = (*progress_cb)(progress_arg,
1568 update ? GOT_STATUS_UPDATE : GOT_STATUS_ADD, path);
1569 if (err)
1570 goto done;
1573 hdrlen = got_object_blob_get_hdrlen(blob);
1574 do {
1575 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1576 err = got_object_blob_read_block(&len, blob);
1577 if (err)
1578 break;
1579 if (len > 0) {
1580 /* Skip blob object header first time around. */
1581 ssize_t outlen = write(fd, buf + hdrlen, len - hdrlen);
1582 if (outlen == -1) {
1583 err = got_error_from_errno("write");
1584 goto done;
1585 } else if (outlen != len - hdrlen) {
1586 err = got_error(GOT_ERR_IO);
1587 goto done;
1589 hdrlen = 0;
1591 } while (len != 0);
1593 if (fsync(fd) != 0) {
1594 err = got_error_from_errno("fsync");
1595 goto done;
1598 if (update) {
1599 if (S_ISLNK(st_mode) && unlink(ondisk_path) == -1) {
1600 err = got_error_from_errno2("unlink", ondisk_path);
1601 goto done;
1603 if (rename(tmppath, ondisk_path) != 0) {
1604 err = got_error_from_errno3("rename", tmppath,
1605 ondisk_path);
1606 goto done;
1608 free(tmppath);
1609 tmppath = NULL;
1612 done:
1613 if (fd != -1 && close(fd) == -1 && err == NULL)
1614 err = got_error_from_errno("close");
1615 if (tmppath != NULL && unlink(tmppath) == -1 && err == NULL)
1616 err = got_error_from_errno2("unlink", tmppath);
1617 free(tmppath);
1618 return err;
1621 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1622 static const struct got_error *
1623 get_modified_file_content_status(unsigned char *status, FILE *f)
1625 const struct got_error *err = NULL;
1626 const char *markers[3] = {
1627 GOT_DIFF_CONFLICT_MARKER_BEGIN,
1628 GOT_DIFF_CONFLICT_MARKER_SEP,
1629 GOT_DIFF_CONFLICT_MARKER_END
1631 int i = 0;
1632 char *line = NULL;
1633 size_t linesize = 0;
1634 ssize_t linelen;
1636 while (*status == GOT_STATUS_MODIFY) {
1637 linelen = getline(&line, &linesize, f);
1638 if (linelen == -1) {
1639 if (feof(f))
1640 break;
1641 err = got_ferror(f, GOT_ERR_IO);
1642 break;
1645 if (strncmp(line, markers[i], strlen(markers[i])) == 0) {
1646 if (strcmp(markers[i], GOT_DIFF_CONFLICT_MARKER_END)
1647 == 0)
1648 *status = GOT_STATUS_CONFLICT;
1649 else
1650 i++;
1653 free(line);
1655 return err;
1658 static int
1659 xbit_differs(struct got_fileindex_entry *ie, uint16_t st_mode)
1661 mode_t ie_mode = got_fileindex_perms_to_st(ie);
1662 return ((ie_mode & S_IXUSR) != (st_mode & S_IXUSR));
1665 static int
1666 stat_info_differs(struct got_fileindex_entry *ie, struct stat *sb)
1668 return !(ie->ctime_sec == sb->st_ctim.tv_sec &&
1669 ie->ctime_nsec == sb->st_ctim.tv_nsec &&
1670 ie->mtime_sec == sb->st_mtim.tv_sec &&
1671 ie->mtime_nsec == sb->st_mtim.tv_nsec &&
1672 ie->size == (sb->st_size & 0xffffffff) &&
1673 !xbit_differs(ie, sb->st_mode));
1676 static unsigned char
1677 get_staged_status(struct got_fileindex_entry *ie)
1679 switch (got_fileindex_entry_stage_get(ie)) {
1680 case GOT_FILEIDX_STAGE_ADD:
1681 return GOT_STATUS_ADD;
1682 case GOT_FILEIDX_STAGE_DELETE:
1683 return GOT_STATUS_DELETE;
1684 case GOT_FILEIDX_STAGE_MODIFY:
1685 return GOT_STATUS_MODIFY;
1686 default:
1687 return GOT_STATUS_NO_CHANGE;
1691 static const struct got_error *
1692 get_symlink_modification_status(unsigned char *status,
1693 struct got_fileindex_entry *ie, const char *abspath,
1694 int dirfd, const char *de_name, struct got_blob_object *blob)
1696 const struct got_error *err = NULL;
1697 char target_path[PATH_MAX];
1698 char etarget[PATH_MAX];
1699 ssize_t elen;
1700 size_t len, target_len = 0;
1701 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1702 size_t hdrlen = got_object_blob_get_hdrlen(blob);
1704 *status = GOT_STATUS_NO_CHANGE;
1706 /* Blob object content specifies the target path of the link. */
1707 do {
1708 err = got_object_blob_read_block(&len, blob);
1709 if (err)
1710 return err;
1711 if (len + target_len >= sizeof(target_path)) {
1713 * Should not happen. The blob contents were OK
1714 * when this symlink was installed.
1716 return got_error(GOT_ERR_NO_SPACE);
1718 if (len > 0) {
1719 /* Skip blob object header first time around. */
1720 memcpy(target_path + target_len, buf + hdrlen,
1721 len - hdrlen);
1722 target_len += len - hdrlen;
1723 hdrlen = 0;
1725 } while (len != 0);
1726 target_path[target_len] = '\0';
1728 if (dirfd != -1) {
1729 elen = readlinkat(dirfd, de_name, etarget, sizeof(etarget));
1730 if (elen == -1)
1731 return got_error_from_errno2("readlinkat", abspath);
1732 } else {
1733 elen = readlink(abspath, etarget, sizeof(etarget));
1734 if (elen == -1)
1735 return got_error_from_errno2("readlink", abspath);
1738 if (elen != target_len || memcmp(etarget, target_path, target_len) != 0)
1739 *status = GOT_STATUS_MODIFY;
1741 return NULL;
1744 static const struct got_error *
1745 get_file_status(unsigned char *status, struct stat *sb,
1746 struct got_fileindex_entry *ie, const char *abspath,
1747 int dirfd, const char *de_name, struct got_repository *repo)
1749 const struct got_error *err = NULL;
1750 struct got_object_id id;
1751 size_t hdrlen;
1752 int fd = -1;
1753 FILE *f = NULL;
1754 uint8_t fbuf[8192];
1755 struct got_blob_object *blob = NULL;
1756 size_t flen, blen;
1757 unsigned char staged_status = get_staged_status(ie);
1759 *status = GOT_STATUS_NO_CHANGE;
1760 memset(sb, 0, sizeof(*sb));
1763 * Whenever the caller provides a directory descriptor and a
1764 * directory entry name for the file, use them! This prevents
1765 * race conditions if filesystem paths change beneath our feet.
1767 if (dirfd != -1) {
1768 if (fstatat(dirfd, de_name, sb, AT_SYMLINK_NOFOLLOW) == -1) {
1769 if (errno == ENOENT) {
1770 if (got_fileindex_entry_has_file_on_disk(ie))
1771 *status = GOT_STATUS_MISSING;
1772 else
1773 *status = GOT_STATUS_DELETE;
1774 goto done;
1776 err = got_error_from_errno2("fstatat", abspath);
1777 goto done;
1779 } else {
1780 fd = open(abspath, O_RDONLY | O_NOFOLLOW);
1781 if (fd == -1 && errno != ENOENT && errno != ELOOP)
1782 return got_error_from_errno2("open", abspath);
1783 else if (fd == -1 && errno == ELOOP) {
1784 if (lstat(abspath, sb) == -1)
1785 return got_error_from_errno2("lstat", abspath);
1786 } else if (fd == -1 || fstat(fd, sb) == -1) {
1787 if (errno == ENOENT) {
1788 if (got_fileindex_entry_has_file_on_disk(ie))
1789 *status = GOT_STATUS_MISSING;
1790 else
1791 *status = GOT_STATUS_DELETE;
1792 goto done;
1794 err = got_error_from_errno2("fstat", abspath);
1795 goto done;
1799 if (!S_ISREG(sb->st_mode) && !S_ISLNK(sb->st_mode)) {
1800 *status = GOT_STATUS_OBSTRUCTED;
1801 goto done;
1804 if (!got_fileindex_entry_has_file_on_disk(ie)) {
1805 *status = GOT_STATUS_DELETE;
1806 goto done;
1807 } else if (!got_fileindex_entry_has_blob(ie) &&
1808 staged_status != GOT_STATUS_ADD) {
1809 *status = GOT_STATUS_ADD;
1810 goto done;
1813 if (!stat_info_differs(ie, sb))
1814 goto done;
1816 if (S_ISLNK(sb->st_mode) &&
1817 got_fileindex_entry_filetype_get(ie) != GOT_FILEIDX_MODE_SYMLINK) {
1818 *status = GOT_STATUS_MODIFY;
1819 goto done;
1822 if (staged_status == GOT_STATUS_MODIFY ||
1823 staged_status == GOT_STATUS_ADD)
1824 memcpy(id.sha1, ie->staged_blob_sha1, sizeof(id.sha1));
1825 else
1826 memcpy(id.sha1, ie->blob_sha1, sizeof(id.sha1));
1828 err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf));
1829 if (err)
1830 goto done;
1832 if (S_ISLNK(sb->st_mode)) {
1833 err = get_symlink_modification_status(status, ie,
1834 abspath, dirfd, de_name, blob);
1835 goto done;
1838 if (dirfd != -1) {
1839 fd = openat(dirfd, de_name, O_RDONLY | O_NOFOLLOW);
1840 if (fd == -1) {
1841 err = got_error_from_errno2("openat", abspath);
1842 goto done;
1846 f = fdopen(fd, "r");
1847 if (f == NULL) {
1848 err = got_error_from_errno2("fdopen", abspath);
1849 goto done;
1851 fd = -1;
1852 hdrlen = got_object_blob_get_hdrlen(blob);
1853 for (;;) {
1854 const uint8_t *bbuf = got_object_blob_get_read_buf(blob);
1855 err = got_object_blob_read_block(&blen, blob);
1856 if (err)
1857 goto done;
1858 /* Skip length of blob object header first time around. */
1859 flen = fread(fbuf, 1, sizeof(fbuf) - hdrlen, f);
1860 if (flen == 0 && ferror(f)) {
1861 err = got_error_from_errno("fread");
1862 goto done;
1864 if (blen - hdrlen == 0) {
1865 if (flen != 0)
1866 *status = GOT_STATUS_MODIFY;
1867 break;
1868 } else if (flen == 0) {
1869 if (blen - hdrlen != 0)
1870 *status = GOT_STATUS_MODIFY;
1871 break;
1872 } else if (blen - hdrlen == flen) {
1873 /* Skip blob object header first time around. */
1874 if (memcmp(bbuf + hdrlen, fbuf, flen) != 0) {
1875 *status = GOT_STATUS_MODIFY;
1876 break;
1878 } else {
1879 *status = GOT_STATUS_MODIFY;
1880 break;
1882 hdrlen = 0;
1885 if (*status == GOT_STATUS_MODIFY) {
1886 rewind(f);
1887 err = get_modified_file_content_status(status, f);
1888 } else if (xbit_differs(ie, sb->st_mode))
1889 *status = GOT_STATUS_MODE_CHANGE;
1890 done:
1891 if (blob)
1892 got_object_blob_close(blob);
1893 if (f != NULL && fclose(f) == EOF && err == NULL)
1894 err = got_error_from_errno2("fclose", abspath);
1895 if (fd != -1 && close(fd) == -1 && err == NULL)
1896 err = got_error_from_errno2("close", abspath);
1897 return err;
1901 * Update timestamps in the file index if a file is unmodified and
1902 * we had to run a full content comparison to find out.
1904 static const struct got_error *
1905 sync_timestamps(int wt_fd, const char *path, unsigned char status,
1906 struct got_fileindex_entry *ie, struct stat *sb)
1908 if (status == GOT_STATUS_NO_CHANGE && stat_info_differs(ie, sb))
1909 return got_fileindex_entry_update(ie, wt_fd, path,
1910 ie->blob_sha1, ie->commit_sha1, 1);
1912 return NULL;
1915 static const struct got_error *
1916 update_blob(struct got_worktree *worktree,
1917 struct got_fileindex *fileindex, struct got_fileindex_entry *ie,
1918 struct got_tree_entry *te, const char *path,
1919 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
1920 void *progress_arg)
1922 const struct got_error *err = NULL;
1923 struct got_blob_object *blob = NULL;
1924 char *ondisk_path;
1925 unsigned char status = GOT_STATUS_NO_CHANGE;
1926 struct stat sb;
1928 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, path) == -1)
1929 return got_error_from_errno("asprintf");
1931 if (ie) {
1932 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE) {
1933 err = got_error_path(ie->path, GOT_ERR_FILE_STAGED);
1934 goto done;
1936 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
1937 repo);
1938 if (err)
1939 goto done;
1940 if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE)
1941 sb.st_mode = got_fileindex_perms_to_st(ie);
1942 } else {
1943 sb.st_mode = GOT_DEFAULT_FILE_MODE;
1944 status = GOT_STATUS_UNVERSIONED;
1947 if (status == GOT_STATUS_OBSTRUCTED) {
1948 if (ie)
1949 got_fileindex_entry_mark_skipped(ie);
1950 err = (*progress_cb)(progress_arg, status, path);
1951 goto done;
1953 if (status == GOT_STATUS_CONFLICT) {
1954 if (ie)
1955 got_fileindex_entry_mark_skipped(ie);
1956 err = (*progress_cb)(progress_arg, GOT_STATUS_CANNOT_UPDATE,
1957 path);
1958 goto done;
1961 if (ie && status != GOT_STATUS_MISSING && S_ISREG(sb.st_mode) &&
1962 (S_ISLNK(te->mode) ||
1963 (te->mode & S_IXUSR) == (sb.st_mode & S_IXUSR))) {
1965 * This is a regular file or an installed bad symlink.
1966 * If the file index indicates that this file is already
1967 * up-to-date with respect to the repository we can skip
1968 * updating contents of this file.
1970 if (got_fileindex_entry_has_commit(ie) &&
1971 memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
1972 SHA1_DIGEST_LENGTH) == 0) {
1973 /* Same commit. */
1974 err = sync_timestamps(worktree->root_fd,
1975 path, status, ie, &sb);
1976 if (err)
1977 goto done;
1978 err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
1979 path);
1980 goto done;
1982 if (got_fileindex_entry_has_blob(ie) &&
1983 memcmp(ie->blob_sha1, te->id.sha1,
1984 SHA1_DIGEST_LENGTH) == 0) {
1985 /* Different commit but the same blob. */
1986 err = sync_timestamps(worktree->root_fd,
1987 path, status, ie, &sb);
1988 if (err)
1989 goto done;
1990 err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
1991 path);
1992 goto done;
1996 err = got_object_open_as_blob(&blob, repo, &te->id, 8192);
1997 if (err)
1998 goto done;
2000 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_ADD) {
2001 int update_timestamps;
2002 struct got_blob_object *blob2 = NULL;
2003 char *label_orig = NULL;
2004 if (got_fileindex_entry_has_blob(ie)) {
2005 struct got_object_id id2;
2006 memcpy(id2.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
2007 err = got_object_open_as_blob(&blob2, repo, &id2, 8192);
2008 if (err)
2009 goto done;
2011 if (got_fileindex_entry_has_commit(ie)) {
2012 char id_str[SHA1_DIGEST_STRING_LENGTH];
2013 if (got_sha1_digest_to_str(ie->commit_sha1, id_str,
2014 sizeof(id_str)) == NULL) {
2015 err = got_error_path(id_str,
2016 GOT_ERR_BAD_OBJ_ID_STR);
2017 goto done;
2019 if (asprintf(&label_orig, "%s: commit %s",
2020 GOT_MERGE_LABEL_BASE, id_str) == -1) {
2021 err = got_error_from_errno("asprintf");
2022 goto done;
2025 if (S_ISLNK(te->mode) && S_ISLNK(sb.st_mode)) {
2026 char *link_target;
2027 err = got_object_blob_read_to_str(&link_target, blob);
2028 if (err)
2029 goto done;
2030 err = merge_symlink(worktree, blob2, ondisk_path, path,
2031 label_orig, link_target, worktree->base_commit_id,
2032 repo, progress_cb, progress_arg);
2033 free(link_target);
2034 } else {
2035 err = merge_blob(&update_timestamps, worktree, blob2,
2036 ondisk_path, path, sb.st_mode, label_orig, blob,
2037 worktree->base_commit_id, repo,
2038 progress_cb, progress_arg);
2040 free(label_orig);
2041 if (blob2)
2042 got_object_blob_close(blob2);
2043 if (err)
2044 goto done;
2046 * Do not update timestamps of files with local changes.
2047 * Otherwise, a future status walk would treat them as
2048 * unmodified files again.
2050 err = got_fileindex_entry_update(ie, worktree->root_fd, path,
2051 blob->id.sha1, worktree->base_commit_id->sha1,
2052 update_timestamps);
2053 } else if (status == GOT_STATUS_MODE_CHANGE) {
2054 err = got_fileindex_entry_update(ie, worktree->root_fd, path,
2055 blob->id.sha1, worktree->base_commit_id->sha1, 0);
2056 } else if (status == GOT_STATUS_DELETE) {
2057 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
2058 if (err)
2059 goto done;
2060 err = got_fileindex_entry_update(ie, worktree->root_fd, path,
2061 blob->id.sha1, worktree->base_commit_id->sha1, 0);
2062 if (err)
2063 goto done;
2064 } else {
2065 int is_bad_symlink = 0;
2066 if (S_ISLNK(te->mode)) {
2067 err = install_symlink(&is_bad_symlink, worktree,
2068 ondisk_path, path, blob,
2069 status == GOT_STATUS_MISSING, 0,
2070 status == GOT_STATUS_UNVERSIONED, repo,
2071 progress_cb, progress_arg);
2072 } else {
2073 err = install_blob(worktree, ondisk_path, path,
2074 te->mode, sb.st_mode, blob,
2075 status == GOT_STATUS_MISSING, 0, 0,
2076 status == GOT_STATUS_UNVERSIONED, repo,
2077 progress_cb, progress_arg);
2079 if (err)
2080 goto done;
2082 if (ie) {
2083 err = got_fileindex_entry_update(ie,
2084 worktree->root_fd, path, blob->id.sha1,
2085 worktree->base_commit_id->sha1, 1);
2086 } else {
2087 err = create_fileindex_entry(&ie, fileindex,
2088 worktree->base_commit_id, worktree->root_fd, path,
2089 &blob->id);
2091 if (err)
2092 goto done;
2094 if (is_bad_symlink) {
2095 got_fileindex_entry_filetype_set(ie,
2096 GOT_FILEIDX_MODE_BAD_SYMLINK);
2099 got_object_blob_close(blob);
2100 done:
2101 free(ondisk_path);
2102 return err;
2105 static const struct got_error *
2106 remove_ondisk_file(const char *root_path, const char *path)
2108 const struct got_error *err = NULL;
2109 char *ondisk_path = NULL, *parent = NULL;
2111 if (asprintf(&ondisk_path, "%s/%s", root_path, path) == -1)
2112 return got_error_from_errno("asprintf");
2114 if (unlink(ondisk_path) == -1) {
2115 if (errno != ENOENT)
2116 err = got_error_from_errno2("unlink", ondisk_path);
2117 } else {
2118 size_t root_len = strlen(root_path);
2119 err = got_path_dirname(&parent, ondisk_path);
2120 if (err)
2121 goto done;
2122 while (got_path_cmp(parent, root_path,
2123 strlen(parent), root_len) != 0) {
2124 free(ondisk_path);
2125 ondisk_path = parent;
2126 parent = NULL;
2127 if (rmdir(ondisk_path) == -1) {
2128 if (errno != ENOTEMPTY)
2129 err = got_error_from_errno2("rmdir",
2130 ondisk_path);
2131 break;
2133 err = got_path_dirname(&parent, ondisk_path);
2134 if (err)
2135 break;
2138 done:
2139 free(ondisk_path);
2140 free(parent);
2141 return err;
2144 static const struct got_error *
2145 delete_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
2146 struct got_fileindex_entry *ie, struct got_repository *repo,
2147 got_worktree_checkout_cb progress_cb, void *progress_arg)
2149 const struct got_error *err = NULL;
2150 unsigned char status;
2151 struct stat sb;
2152 char *ondisk_path;
2154 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
2155 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
2157 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, ie->path)
2158 == -1)
2159 return got_error_from_errno("asprintf");
2161 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, repo);
2162 if (err)
2163 goto done;
2165 if (S_ISLNK(sb.st_mode) && status != GOT_STATUS_NO_CHANGE) {
2166 char ondisk_target[PATH_MAX];
2167 ssize_t ondisk_len = readlink(ondisk_path, ondisk_target,
2168 sizeof(ondisk_target));
2169 if (ondisk_len == -1) {
2170 err = got_error_from_errno2("readlink", ondisk_path);
2171 goto done;
2173 ondisk_target[ondisk_len] = '\0';
2174 err = install_symlink_conflict(NULL, worktree->base_commit_id,
2175 NULL, NULL, /* XXX pass common ancestor info? */
2176 ondisk_target, ondisk_path);
2177 if (err)
2178 goto done;
2179 err = (*progress_cb)(progress_arg, GOT_STATUS_CONFLICT,
2180 ie->path);
2181 goto done;
2184 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_CONFLICT ||
2185 status == GOT_STATUS_ADD) {
2186 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, ie->path);
2187 if (err)
2188 goto done;
2190 * Preserve the working file and change the deleted blob's
2191 * entry into a schedule-add entry.
2193 err = got_fileindex_entry_update(ie, worktree->root_fd,
2194 ie->path, NULL, NULL, 0);
2195 } else {
2196 err = (*progress_cb)(progress_arg, GOT_STATUS_DELETE, ie->path);
2197 if (err)
2198 goto done;
2199 if (status == GOT_STATUS_NO_CHANGE) {
2200 err = remove_ondisk_file(worktree->root_path, ie->path);
2201 if (err)
2202 goto done;
2204 got_fileindex_entry_remove(fileindex, ie);
2206 done:
2207 free(ondisk_path);
2208 return err;
2211 struct diff_cb_arg {
2212 struct got_fileindex *fileindex;
2213 struct got_worktree *worktree;
2214 struct got_repository *repo;
2215 got_worktree_checkout_cb progress_cb;
2216 void *progress_arg;
2217 got_cancel_cb cancel_cb;
2218 void *cancel_arg;
2221 static const struct got_error *
2222 diff_old_new(void *arg, struct got_fileindex_entry *ie,
2223 struct got_tree_entry *te, const char *parent_path)
2225 struct diff_cb_arg *a = arg;
2227 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2228 return got_error(GOT_ERR_CANCELLED);
2230 return update_blob(a->worktree, a->fileindex, ie, te,
2231 ie->path, a->repo, a->progress_cb, a->progress_arg);
2234 static const struct got_error *
2235 diff_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
2237 struct diff_cb_arg *a = arg;
2239 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2240 return got_error(GOT_ERR_CANCELLED);
2242 return delete_blob(a->worktree, a->fileindex, ie,
2243 a->repo, a->progress_cb, a->progress_arg);
2246 static const struct got_error *
2247 diff_new(void *arg, struct got_tree_entry *te, const char *parent_path)
2249 struct diff_cb_arg *a = arg;
2250 const struct got_error *err;
2251 char *path;
2253 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2254 return got_error(GOT_ERR_CANCELLED);
2256 if (got_object_tree_entry_is_submodule(te))
2257 return NULL;
2259 if (asprintf(&path, "%s%s%s", parent_path,
2260 parent_path[0] ? "/" : "", te->name)
2261 == -1)
2262 return got_error_from_errno("asprintf");
2264 if (S_ISDIR(te->mode))
2265 err = add_dir_on_disk(a->worktree, path);
2266 else
2267 err = update_blob(a->worktree, a->fileindex, NULL, te, path,
2268 a->repo, a->progress_cb, a->progress_arg);
2270 free(path);
2271 return err;
2274 const struct got_error *
2275 got_worktree_get_uuid(char **uuidstr, struct got_worktree *worktree)
2277 uint32_t uuid_status;
2279 uuid_to_string(&worktree->uuid, uuidstr, &uuid_status);
2280 if (uuid_status != uuid_s_ok) {
2281 *uuidstr = NULL;
2282 return got_error_uuid(uuid_status, "uuid_to_string");
2285 return NULL;
2288 static const struct got_error *
2289 get_ref_name(char **refname, struct got_worktree *worktree, const char *prefix)
2291 const struct got_error *err = NULL;
2292 char *uuidstr = NULL;
2294 *refname = NULL;
2296 err = got_worktree_get_uuid(&uuidstr, worktree);
2297 if (err)
2298 return err;
2300 if (asprintf(refname, "%s-%s", prefix, uuidstr) == -1) {
2301 err = got_error_from_errno("asprintf");
2302 *refname = NULL;
2304 free(uuidstr);
2305 return err;
2308 const struct got_error *
2309 got_worktree_get_base_ref_name(char **refname, struct got_worktree *worktree)
2311 return get_ref_name(refname, worktree, GOT_WORKTREE_BASE_REF_PREFIX);
2314 static const struct got_error *
2315 get_rebase_tmp_ref_name(char **refname, struct got_worktree *worktree)
2317 return get_ref_name(refname, worktree,
2318 GOT_WORKTREE_REBASE_TMP_REF_PREFIX);
2321 static const struct got_error *
2322 get_newbase_symref_name(char **refname, struct got_worktree *worktree)
2324 return get_ref_name(refname, worktree, GOT_WORKTREE_NEWBASE_REF_PREFIX);
2327 static const struct got_error *
2328 get_rebase_branch_symref_name(char **refname, struct got_worktree *worktree)
2330 return get_ref_name(refname, worktree,
2331 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX);
2334 static const struct got_error *
2335 get_rebase_commit_ref_name(char **refname, struct got_worktree *worktree)
2337 return get_ref_name(refname, worktree,
2338 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX);
2341 static const struct got_error *
2342 get_histedit_tmp_ref_name(char **refname, struct got_worktree *worktree)
2344 return get_ref_name(refname, worktree,
2345 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX);
2348 static const struct got_error *
2349 get_histedit_branch_symref_name(char **refname, struct got_worktree *worktree)
2351 return get_ref_name(refname, worktree,
2352 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX);
2355 static const struct got_error *
2356 get_histedit_base_commit_ref_name(char **refname, struct got_worktree *worktree)
2358 return get_ref_name(refname, worktree,
2359 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX);
2362 static const struct got_error *
2363 get_histedit_commit_ref_name(char **refname, struct got_worktree *worktree)
2365 return get_ref_name(refname, worktree,
2366 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX);
2369 const struct got_error *
2370 got_worktree_get_histedit_script_path(char **path,
2371 struct got_worktree *worktree)
2373 if (asprintf(path, "%s/%s/%s", worktree->root_path,
2374 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_HISTEDIT_SCRIPT) == -1) {
2375 *path = NULL;
2376 return got_error_from_errno("asprintf");
2378 return NULL;
2381 static const struct got_error *
2382 get_merge_branch_ref_name(char **refname, struct got_worktree *worktree)
2384 return get_ref_name(refname, worktree,
2385 GOT_WORKTREE_MERGE_BRANCH_REF_PREFIX);
2388 static const struct got_error *
2389 get_merge_commit_ref_name(char **refname, struct got_worktree *worktree)
2391 return get_ref_name(refname, worktree,
2392 GOT_WORKTREE_MERGE_COMMIT_REF_PREFIX);
2396 * Prevent Git's garbage collector from deleting our base commit by
2397 * setting a reference to our base commit's ID.
2399 static const struct got_error *
2400 ref_base_commit(struct got_worktree *worktree, struct got_repository *repo)
2402 const struct got_error *err = NULL;
2403 struct got_reference *ref = NULL;
2404 char *refname;
2406 err = got_worktree_get_base_ref_name(&refname, worktree);
2407 if (err)
2408 return err;
2410 err = got_ref_alloc(&ref, refname, worktree->base_commit_id);
2411 if (err)
2412 goto done;
2414 err = got_ref_write(ref, repo);
2415 done:
2416 free(refname);
2417 if (ref)
2418 got_ref_close(ref);
2419 return err;
2422 static const struct got_error *
2423 get_fileindex_path(char **fileindex_path, struct got_worktree *worktree)
2425 const struct got_error *err = NULL;
2427 if (asprintf(fileindex_path, "%s/%s/%s", worktree->root_path,
2428 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_FILE_INDEX) == -1) {
2429 err = got_error_from_errno("asprintf");
2430 *fileindex_path = NULL;
2432 return err;
2436 static const struct got_error *
2437 open_fileindex(struct got_fileindex **fileindex, char **fileindex_path,
2438 struct got_worktree *worktree)
2440 const struct got_error *err = NULL;
2441 FILE *index = NULL;
2443 *fileindex_path = NULL;
2444 *fileindex = got_fileindex_alloc();
2445 if (*fileindex == NULL)
2446 return got_error_from_errno("got_fileindex_alloc");
2448 err = get_fileindex_path(fileindex_path, worktree);
2449 if (err)
2450 goto done;
2452 index = fopen(*fileindex_path, "rb");
2453 if (index == NULL) {
2454 if (errno != ENOENT)
2455 err = got_error_from_errno2("fopen", *fileindex_path);
2456 } else {
2457 err = got_fileindex_read(*fileindex, index);
2458 if (fclose(index) == EOF && err == NULL)
2459 err = got_error_from_errno("fclose");
2461 done:
2462 if (err) {
2463 free(*fileindex_path);
2464 *fileindex_path = NULL;
2465 got_fileindex_free(*fileindex);
2466 *fileindex = NULL;
2468 return err;
2471 struct bump_base_commit_id_arg {
2472 struct got_object_id *base_commit_id;
2473 const char *path;
2474 size_t path_len;
2475 const char *entry_name;
2476 got_worktree_checkout_cb progress_cb;
2477 void *progress_arg;
2480 /* Bump base commit ID of all files within an updated part of the work tree. */
2481 static const struct got_error *
2482 bump_base_commit_id(void *arg, struct got_fileindex_entry *ie)
2484 const struct got_error *err;
2485 struct bump_base_commit_id_arg *a = arg;
2487 if (a->entry_name) {
2488 if (strcmp(ie->path, a->path) != 0)
2489 return NULL;
2490 } else if (!got_path_is_child(ie->path, a->path, a->path_len))
2491 return NULL;
2493 if (got_fileindex_entry_was_skipped(ie))
2494 return NULL;
2496 if (memcmp(ie->commit_sha1, a->base_commit_id->sha1,
2497 SHA1_DIGEST_LENGTH) == 0)
2498 return NULL;
2500 if (a->progress_cb) {
2501 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_BUMP_BASE,
2502 ie->path);
2503 if (err)
2504 return err;
2506 memcpy(ie->commit_sha1, a->base_commit_id->sha1, SHA1_DIGEST_LENGTH);
2507 return NULL;
2510 static const struct got_error *
2511 bump_base_commit_id_everywhere(struct got_worktree *worktree,
2512 struct got_fileindex *fileindex,
2513 got_worktree_checkout_cb progress_cb, void *progress_arg)
2515 struct bump_base_commit_id_arg bbc_arg;
2517 bbc_arg.base_commit_id = worktree->base_commit_id;
2518 bbc_arg.entry_name = NULL;
2519 bbc_arg.path = "";
2520 bbc_arg.path_len = 0;
2521 bbc_arg.progress_cb = progress_cb;
2522 bbc_arg.progress_arg = progress_arg;
2524 return got_fileindex_for_each_entry_safe(fileindex,
2525 bump_base_commit_id, &bbc_arg);
2528 static const struct got_error *
2529 sync_fileindex(struct got_fileindex *fileindex, const char *fileindex_path)
2531 const struct got_error *err = NULL;
2532 char *new_fileindex_path = NULL;
2533 FILE *new_index = NULL;
2534 struct timespec timeout;
2536 err = got_opentemp_named(&new_fileindex_path, &new_index,
2537 fileindex_path);
2538 if (err)
2539 goto done;
2541 err = got_fileindex_write(fileindex, new_index);
2542 if (err)
2543 goto done;
2545 if (rename(new_fileindex_path, fileindex_path) != 0) {
2546 err = got_error_from_errno3("rename", new_fileindex_path,
2547 fileindex_path);
2548 unlink(new_fileindex_path);
2552 * Sleep for a short amount of time to ensure that files modified after
2553 * this program exits have a different time stamp from the one which
2554 * was recorded in the file index.
2556 timeout.tv_sec = 0;
2557 timeout.tv_nsec = 1;
2558 nanosleep(&timeout, NULL);
2559 done:
2560 if (new_index)
2561 fclose(new_index);
2562 free(new_fileindex_path);
2563 return err;
2566 static const struct got_error *
2567 find_tree_entry_for_checkout(int *entry_type, char **tree_relpath,
2568 struct got_object_id **tree_id, const char *wt_relpath,
2569 struct got_worktree *worktree, struct got_repository *repo)
2571 const struct got_error *err = NULL;
2572 struct got_object_id *id = NULL;
2573 char *in_repo_path = NULL;
2574 int is_root_wt = got_path_is_root_dir(worktree->path_prefix);
2576 *entry_type = GOT_OBJ_TYPE_ANY;
2577 *tree_relpath = NULL;
2578 *tree_id = NULL;
2580 if (wt_relpath[0] == '\0') {
2581 /* Check out all files within the work tree. */
2582 *entry_type = GOT_OBJ_TYPE_TREE;
2583 *tree_relpath = strdup("");
2584 if (*tree_relpath == NULL) {
2585 err = got_error_from_errno("strdup");
2586 goto done;
2588 err = got_object_id_by_path(tree_id, repo,
2589 worktree->base_commit_id, worktree->path_prefix);
2590 if (err)
2591 goto done;
2592 return NULL;
2595 /* Check out a subset of files in the work tree. */
2597 if (asprintf(&in_repo_path, "%s%s%s", worktree->path_prefix,
2598 is_root_wt ? "" : "/", wt_relpath) == -1) {
2599 err = got_error_from_errno("asprintf");
2600 goto done;
2603 err = got_object_id_by_path(&id, repo, worktree->base_commit_id,
2604 in_repo_path);
2605 if (err)
2606 goto done;
2608 free(in_repo_path);
2609 in_repo_path = NULL;
2611 err = got_object_get_type(entry_type, repo, id);
2612 if (err)
2613 goto done;
2615 if (*entry_type == GOT_OBJ_TYPE_BLOB) {
2616 /* Check out a single file. */
2617 if (strchr(wt_relpath, '/') == NULL) {
2618 /* Check out a single file in work tree's root dir. */
2619 in_repo_path = strdup(worktree->path_prefix);
2620 if (in_repo_path == NULL) {
2621 err = got_error_from_errno("strdup");
2622 goto done;
2624 *tree_relpath = strdup("");
2625 if (*tree_relpath == NULL) {
2626 err = got_error_from_errno("strdup");
2627 goto done;
2629 } else {
2630 /* Check out a single file in a subdirectory. */
2631 err = got_path_dirname(tree_relpath, wt_relpath);
2632 if (err)
2633 return err;
2634 if (asprintf(&in_repo_path, "%s%s%s",
2635 worktree->path_prefix, is_root_wt ? "" : "/",
2636 *tree_relpath) == -1) {
2637 err = got_error_from_errno("asprintf");
2638 goto done;
2641 err = got_object_id_by_path(tree_id, repo,
2642 worktree->base_commit_id, in_repo_path);
2643 } else {
2644 /* Check out all files within a subdirectory. */
2645 *tree_id = got_object_id_dup(id);
2646 if (*tree_id == NULL) {
2647 err = got_error_from_errno("got_object_id_dup");
2648 goto done;
2650 *tree_relpath = strdup(wt_relpath);
2651 if (*tree_relpath == NULL) {
2652 err = got_error_from_errno("strdup");
2653 goto done;
2656 done:
2657 free(id);
2658 free(in_repo_path);
2659 if (err) {
2660 *entry_type = GOT_OBJ_TYPE_ANY;
2661 free(*tree_relpath);
2662 *tree_relpath = NULL;
2663 free(*tree_id);
2664 *tree_id = NULL;
2666 return err;
2669 static const struct got_error *
2670 checkout_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
2671 const char *relpath, struct got_object_id *tree_id, const char *entry_name,
2672 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
2673 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
2675 const struct got_error *err = NULL;
2676 struct got_commit_object *commit = NULL;
2677 struct got_tree_object *tree = NULL;
2678 struct got_fileindex_diff_tree_cb diff_cb;
2679 struct diff_cb_arg arg;
2681 err = ref_base_commit(worktree, repo);
2682 if (err) {
2683 if (!(err->code == GOT_ERR_ERRNO &&
2684 (errno == EACCES || errno == EROFS)))
2685 goto done;
2686 err = (*progress_cb)(progress_arg,
2687 GOT_STATUS_BASE_REF_ERR, worktree->root_path);
2688 if (err)
2689 return err;
2692 err = got_object_open_as_commit(&commit, repo,
2693 worktree->base_commit_id);
2694 if (err)
2695 goto done;
2697 err = got_object_open_as_tree(&tree, repo, tree_id);
2698 if (err)
2699 goto done;
2701 if (entry_name &&
2702 got_object_tree_find_entry(tree, entry_name) == NULL) {
2703 err = got_error_path(entry_name, GOT_ERR_NO_TREE_ENTRY);
2704 goto done;
2707 diff_cb.diff_old_new = diff_old_new;
2708 diff_cb.diff_old = diff_old;
2709 diff_cb.diff_new = diff_new;
2710 arg.fileindex = fileindex;
2711 arg.worktree = worktree;
2712 arg.repo = repo;
2713 arg.progress_cb = progress_cb;
2714 arg.progress_arg = progress_arg;
2715 arg.cancel_cb = cancel_cb;
2716 arg.cancel_arg = cancel_arg;
2717 err = got_fileindex_diff_tree(fileindex, tree, relpath,
2718 entry_name, repo, &diff_cb, &arg);
2719 done:
2720 if (tree)
2721 got_object_tree_close(tree);
2722 if (commit)
2723 got_object_commit_close(commit);
2724 return err;
2727 const struct got_error *
2728 got_worktree_checkout_files(struct got_worktree *worktree,
2729 struct got_pathlist_head *paths, struct got_repository *repo,
2730 got_worktree_checkout_cb progress_cb, void *progress_arg,
2731 got_cancel_cb cancel_cb, void *cancel_arg)
2733 const struct got_error *err = NULL, *sync_err, *unlockerr;
2734 struct got_commit_object *commit = NULL;
2735 struct got_tree_object *tree = NULL;
2736 struct got_fileindex *fileindex = NULL;
2737 char *fileindex_path = NULL;
2738 struct got_pathlist_entry *pe;
2739 struct tree_path_data {
2740 STAILQ_ENTRY(tree_path_data) entry;
2741 struct got_object_id *tree_id;
2742 int entry_type;
2743 char *relpath;
2744 char *entry_name;
2745 } *tpd = NULL;
2746 STAILQ_HEAD(tree_paths, tree_path_data) tree_paths;
2748 STAILQ_INIT(&tree_paths);
2750 err = lock_worktree(worktree, LOCK_EX);
2751 if (err)
2752 return err;
2754 /* Map all specified paths to in-repository trees. */
2755 TAILQ_FOREACH(pe, paths, entry) {
2756 tpd = malloc(sizeof(*tpd));
2757 if (tpd == NULL) {
2758 err = got_error_from_errno("malloc");
2759 goto done;
2762 err = find_tree_entry_for_checkout(&tpd->entry_type,
2763 &tpd->relpath, &tpd->tree_id, pe->path, worktree, repo);
2764 if (err) {
2765 free(tpd);
2766 goto done;
2769 if (tpd->entry_type == GOT_OBJ_TYPE_BLOB) {
2770 err = got_path_basename(&tpd->entry_name, pe->path);
2771 if (err) {
2772 free(tpd->relpath);
2773 free(tpd->tree_id);
2774 free(tpd);
2775 goto done;
2777 } else
2778 tpd->entry_name = NULL;
2780 STAILQ_INSERT_TAIL(&tree_paths, tpd, entry);
2784 * Read the file index.
2785 * Checking out files is supposed to be an idempotent operation.
2786 * If the on-disk file index is incomplete we will try to complete it.
2788 err = open_fileindex(&fileindex, &fileindex_path, worktree);
2789 if (err)
2790 goto done;
2792 tpd = STAILQ_FIRST(&tree_paths);
2793 TAILQ_FOREACH(pe, paths, entry) {
2794 struct bump_base_commit_id_arg bbc_arg;
2796 err = checkout_files(worktree, fileindex, tpd->relpath,
2797 tpd->tree_id, tpd->entry_name, repo,
2798 progress_cb, progress_arg, cancel_cb, cancel_arg);
2799 if (err)
2800 break;
2802 bbc_arg.base_commit_id = worktree->base_commit_id;
2803 bbc_arg.entry_name = tpd->entry_name;
2804 bbc_arg.path = pe->path;
2805 bbc_arg.path_len = pe->path_len;
2806 bbc_arg.progress_cb = progress_cb;
2807 bbc_arg.progress_arg = progress_arg;
2808 err = got_fileindex_for_each_entry_safe(fileindex,
2809 bump_base_commit_id, &bbc_arg);
2810 if (err)
2811 break;
2813 tpd = STAILQ_NEXT(tpd, entry);
2815 sync_err = sync_fileindex(fileindex, fileindex_path);
2816 if (sync_err && err == NULL)
2817 err = sync_err;
2818 done:
2819 free(fileindex_path);
2820 if (tree)
2821 got_object_tree_close(tree);
2822 if (commit)
2823 got_object_commit_close(commit);
2824 if (fileindex)
2825 got_fileindex_free(fileindex);
2826 while (!STAILQ_EMPTY(&tree_paths)) {
2827 tpd = STAILQ_FIRST(&tree_paths);
2828 STAILQ_REMOVE_HEAD(&tree_paths, entry);
2829 free(tpd->relpath);
2830 free(tpd->tree_id);
2831 free(tpd);
2833 unlockerr = lock_worktree(worktree, LOCK_SH);
2834 if (unlockerr && err == NULL)
2835 err = unlockerr;
2836 return err;
2839 struct merge_file_cb_arg {
2840 struct got_worktree *worktree;
2841 struct got_fileindex *fileindex;
2842 got_worktree_checkout_cb progress_cb;
2843 void *progress_arg;
2844 got_cancel_cb cancel_cb;
2845 void *cancel_arg;
2846 const char *label_orig;
2847 struct got_object_id *commit_id2;
2850 static const struct got_error *
2851 merge_file_cb(void *arg, struct got_blob_object *blob1,
2852 struct got_blob_object *blob2, struct got_object_id *id1,
2853 struct got_object_id *id2, const char *path1, const char *path2,
2854 mode_t mode1, mode_t mode2, struct got_repository *repo)
2856 static const struct got_error *err = NULL;
2857 struct merge_file_cb_arg *a = arg;
2858 struct got_fileindex_entry *ie;
2859 char *ondisk_path = NULL;
2860 struct stat sb;
2861 unsigned char status;
2862 int local_changes_subsumed;
2863 FILE *f_orig = NULL, *f_deriv = NULL, *f_deriv2 = NULL;
2864 char *id_str = NULL, *label_deriv2 = NULL;
2866 if (blob1 && blob2) {
2867 ie = got_fileindex_entry_get(a->fileindex, path2,
2868 strlen(path2));
2869 if (ie == NULL)
2870 return (*a->progress_cb)(a->progress_arg,
2871 GOT_STATUS_MISSING, path2);
2873 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2874 path2) == -1)
2875 return got_error_from_errno("asprintf");
2877 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2878 repo);
2879 if (err)
2880 goto done;
2882 if (status == GOT_STATUS_DELETE) {
2883 err = (*a->progress_cb)(a->progress_arg,
2884 GOT_STATUS_MERGE, path2);
2885 goto done;
2887 if (status != GOT_STATUS_NO_CHANGE &&
2888 status != GOT_STATUS_MODIFY &&
2889 status != GOT_STATUS_CONFLICT &&
2890 status != GOT_STATUS_ADD) {
2891 err = (*a->progress_cb)(a->progress_arg, status, path2);
2892 goto done;
2895 if (S_ISLNK(mode1) && S_ISLNK(mode2)) {
2896 char *link_target2;
2897 err = got_object_blob_read_to_str(&link_target2, blob2);
2898 if (err)
2899 goto done;
2900 err = merge_symlink(a->worktree, blob1, ondisk_path,
2901 path2, a->label_orig, link_target2, a->commit_id2,
2902 repo, a->progress_cb, a->progress_arg);
2903 free(link_target2);
2904 } else {
2905 int fd;
2907 f_orig = got_opentemp();
2908 if (f_orig == NULL) {
2909 err = got_error_from_errno("got_opentemp");
2910 goto done;
2912 err = got_object_blob_dump_to_file(NULL, NULL, NULL,
2913 f_orig, blob1);
2914 if (err)
2915 goto done;
2917 f_deriv2 = got_opentemp();
2918 if (f_deriv2 == NULL)
2919 goto done;
2920 err = got_object_blob_dump_to_file(NULL, NULL, NULL,
2921 f_deriv2, blob2);
2922 if (err)
2923 goto done;
2925 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW);
2926 if (fd == -1) {
2927 err = got_error_from_errno2("open",
2928 ondisk_path);
2929 goto done;
2931 f_deriv = fdopen(fd, "r");
2932 if (f_deriv == NULL) {
2933 err = got_error_from_errno2("fdopen",
2934 ondisk_path);
2935 close(fd);
2936 goto done;
2938 err = got_object_id_str(&id_str, a->commit_id2);
2939 if (err)
2940 goto done;
2941 if (asprintf(&label_deriv2, "%s: commit %s",
2942 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
2943 err = got_error_from_errno("asprintf");
2944 goto done;
2946 err = merge_file(&local_changes_subsumed, a->worktree,
2947 f_orig, f_deriv, f_deriv2, ondisk_path, path2,
2948 sb.st_mode, a->label_orig, NULL, label_deriv2,
2949 GOT_DIFF_ALGORITHM_PATIENCE, repo,
2950 a->progress_cb, a->progress_arg);
2952 } else if (blob1) {
2953 ie = got_fileindex_entry_get(a->fileindex, path1,
2954 strlen(path1));
2955 if (ie == NULL)
2956 return (*a->progress_cb)(a->progress_arg,
2957 GOT_STATUS_MISSING, path1);
2959 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2960 path1) == -1)
2961 return got_error_from_errno("asprintf");
2963 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2964 repo);
2965 if (err)
2966 goto done;
2968 switch (status) {
2969 case GOT_STATUS_NO_CHANGE:
2970 err = (*a->progress_cb)(a->progress_arg,
2971 GOT_STATUS_DELETE, path1);
2972 if (err)
2973 goto done;
2974 err = remove_ondisk_file(a->worktree->root_path, path1);
2975 if (err)
2976 goto done;
2977 if (ie)
2978 got_fileindex_entry_mark_deleted_from_disk(ie);
2979 break;
2980 case GOT_STATUS_DELETE:
2981 case GOT_STATUS_MISSING:
2982 err = (*a->progress_cb)(a->progress_arg,
2983 GOT_STATUS_DELETE, path1);
2984 if (err)
2985 goto done;
2986 if (ie)
2987 got_fileindex_entry_mark_deleted_from_disk(ie);
2988 break;
2989 case GOT_STATUS_ADD: {
2990 struct got_object_id *id;
2991 FILE *blob1_f;
2993 * Delete the added file only if its content already
2994 * exists in the repository.
2996 err = got_object_blob_file_create(&id, &blob1_f, path1);
2997 if (err)
2998 goto done;
2999 if (got_object_id_cmp(id, id1) == 0) {
3000 err = (*a->progress_cb)(a->progress_arg,
3001 GOT_STATUS_DELETE, path1);
3002 if (err)
3003 goto done;
3004 err = remove_ondisk_file(a->worktree->root_path,
3005 path1);
3006 if (err)
3007 goto done;
3008 if (ie)
3009 got_fileindex_entry_remove(a->fileindex,
3010 ie);
3011 } else {
3012 err = (*a->progress_cb)(a->progress_arg,
3013 GOT_STATUS_CANNOT_DELETE, path1);
3015 if (fclose(blob1_f) == EOF && err == NULL)
3016 err = got_error_from_errno("fclose");
3017 free(id);
3018 if (err)
3019 goto done;
3020 break;
3022 case GOT_STATUS_MODIFY:
3023 case GOT_STATUS_CONFLICT:
3024 err = (*a->progress_cb)(a->progress_arg,
3025 GOT_STATUS_CANNOT_DELETE, path1);
3026 if (err)
3027 goto done;
3028 break;
3029 case GOT_STATUS_OBSTRUCTED:
3030 err = (*a->progress_cb)(a->progress_arg, status, path1);
3031 if (err)
3032 goto done;
3033 break;
3034 default:
3035 break;
3037 } else if (blob2) {
3038 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3039 path2) == -1)
3040 return got_error_from_errno("asprintf");
3041 ie = got_fileindex_entry_get(a->fileindex, path2,
3042 strlen(path2));
3043 if (ie) {
3044 err = get_file_status(&status, &sb, ie, ondisk_path,
3045 -1, NULL, repo);
3046 if (err)
3047 goto done;
3048 if (status != GOT_STATUS_NO_CHANGE &&
3049 status != GOT_STATUS_MODIFY &&
3050 status != GOT_STATUS_CONFLICT &&
3051 status != GOT_STATUS_ADD) {
3052 err = (*a->progress_cb)(a->progress_arg,
3053 status, path2);
3054 goto done;
3056 if (S_ISLNK(mode2) && S_ISLNK(sb.st_mode)) {
3057 char *link_target2;
3058 err = got_object_blob_read_to_str(&link_target2,
3059 blob2);
3060 if (err)
3061 goto done;
3062 err = merge_symlink(a->worktree, NULL,
3063 ondisk_path, path2, a->label_orig,
3064 link_target2, a->commit_id2, repo,
3065 a->progress_cb, a->progress_arg);
3066 free(link_target2);
3067 } else if (S_ISREG(sb.st_mode)) {
3068 err = merge_blob(&local_changes_subsumed,
3069 a->worktree, NULL, ondisk_path, path2,
3070 sb.st_mode, a->label_orig, blob2,
3071 a->commit_id2, repo, a->progress_cb,
3072 a->progress_arg);
3073 } else {
3074 err = got_error_path(ondisk_path,
3075 GOT_ERR_FILE_OBSTRUCTED);
3077 if (err)
3078 goto done;
3079 if (status == GOT_STATUS_DELETE) {
3080 err = got_fileindex_entry_update(ie,
3081 a->worktree->root_fd, path2, blob2->id.sha1,
3082 a->worktree->base_commit_id->sha1, 0);
3083 if (err)
3084 goto done;
3086 } else {
3087 int is_bad_symlink = 0;
3088 sb.st_mode = GOT_DEFAULT_FILE_MODE;
3089 if (S_ISLNK(mode2)) {
3090 err = install_symlink(&is_bad_symlink,
3091 a->worktree, ondisk_path, path2, blob2, 0,
3092 0, 1, repo, a->progress_cb, a->progress_arg);
3093 } else {
3094 err = install_blob(a->worktree, ondisk_path, path2,
3095 mode2, sb.st_mode, blob2, 0, 0, 0, 1, repo,
3096 a->progress_cb, a->progress_arg);
3098 if (err)
3099 goto done;
3100 err = got_fileindex_entry_alloc(&ie, path2);
3101 if (err)
3102 goto done;
3103 err = got_fileindex_entry_update(ie,
3104 a->worktree->root_fd, path2, NULL, NULL, 1);
3105 if (err) {
3106 got_fileindex_entry_free(ie);
3107 goto done;
3109 err = got_fileindex_entry_add(a->fileindex, ie);
3110 if (err) {
3111 got_fileindex_entry_free(ie);
3112 goto done;
3114 if (is_bad_symlink) {
3115 got_fileindex_entry_filetype_set(ie,
3116 GOT_FILEIDX_MODE_BAD_SYMLINK);
3120 done:
3121 if (f_orig && fclose(f_orig) == EOF && err == NULL)
3122 err = got_error_from_errno("fclose");
3123 if (f_deriv && fclose(f_deriv) == EOF && err == NULL)
3124 err = got_error_from_errno("fclose");
3125 if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
3126 err = got_error_from_errno("fclose");
3127 free(id_str);
3128 free(label_deriv2);
3129 free(ondisk_path);
3130 return err;
3133 static const struct got_error *
3134 check_mixed_commits(void *arg, struct got_fileindex_entry *ie)
3136 struct got_worktree *worktree = arg;
3138 /* Reject merges into a work tree with mixed base commits. */
3139 if (got_fileindex_entry_has_commit(ie) &&
3140 memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
3141 SHA1_DIGEST_LENGTH) != 0)
3142 return got_error(GOT_ERR_MIXED_COMMITS);
3144 return NULL;
3147 struct check_merge_conflicts_arg {
3148 struct got_worktree *worktree;
3149 struct got_fileindex *fileindex;
3150 struct got_repository *repo;
3153 static const struct got_error *
3154 check_merge_conflicts(void *arg, struct got_blob_object *blob1,
3155 struct got_blob_object *blob2, struct got_object_id *id1,
3156 struct got_object_id *id2, const char *path1, const char *path2,
3157 mode_t mode1, mode_t mode2, struct got_repository *repo)
3159 const struct got_error *err = NULL;
3160 struct check_merge_conflicts_arg *a = arg;
3161 unsigned char status;
3162 struct stat sb;
3163 struct got_fileindex_entry *ie;
3164 const char *path = path2 ? path2 : path1;
3165 struct got_object_id *id = id2 ? id2 : id1;
3166 char *ondisk_path;
3168 if (id == NULL)
3169 return NULL;
3171 ie = got_fileindex_entry_get(a->fileindex, path, strlen(path));
3172 if (ie == NULL)
3173 return NULL;
3175 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
3176 == -1)
3177 return got_error_from_errno("asprintf");
3179 /* Reject merges into a work tree with conflicted files. */
3180 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
3181 free(ondisk_path);
3182 if (err)
3183 return err;
3184 if (status == GOT_STATUS_CONFLICT)
3185 return got_error(GOT_ERR_CONFLICTS);
3187 return NULL;
3190 static const struct got_error *
3191 merge_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
3192 const char *fileindex_path, struct got_object_id *commit_id1,
3193 struct got_object_id *commit_id2, struct got_repository *repo,
3194 got_worktree_checkout_cb progress_cb, void *progress_arg,
3195 got_cancel_cb cancel_cb, void *cancel_arg)
3197 const struct got_error *err = NULL, *sync_err;
3198 struct got_object_id *tree_id1 = NULL, *tree_id2 = NULL;
3199 struct got_tree_object *tree1 = NULL, *tree2 = NULL;
3200 struct check_merge_conflicts_arg cmc_arg;
3201 struct merge_file_cb_arg arg;
3202 char *label_orig = NULL;
3204 if (commit_id1) {
3205 err = got_object_id_by_path(&tree_id1, repo, commit_id1,
3206 worktree->path_prefix);
3207 if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
3208 goto done;
3210 if (tree_id1) {
3211 char *id_str;
3213 err = got_object_open_as_tree(&tree1, repo, tree_id1);
3214 if (err)
3215 goto done;
3217 err = got_object_id_str(&id_str, commit_id1);
3218 if (err)
3219 goto done;
3221 if (asprintf(&label_orig, "%s: commit %s",
3222 GOT_MERGE_LABEL_BASE, id_str) == -1) {
3223 err = got_error_from_errno("asprintf");
3224 free(id_str);
3225 goto done;
3227 free(id_str);
3230 err = got_object_id_by_path(&tree_id2, repo, commit_id2,
3231 worktree->path_prefix);
3232 if (err)
3233 goto done;
3235 err = got_object_open_as_tree(&tree2, repo, tree_id2);
3236 if (err)
3237 goto done;
3239 cmc_arg.worktree = worktree;
3240 cmc_arg.fileindex = fileindex;
3241 cmc_arg.repo = repo;
3242 err = got_diff_tree(tree1, tree2, "", "", repo,
3243 check_merge_conflicts, &cmc_arg, 0);
3244 if (err)
3245 goto done;
3247 arg.worktree = worktree;
3248 arg.fileindex = fileindex;
3249 arg.progress_cb = progress_cb;
3250 arg.progress_arg = progress_arg;
3251 arg.cancel_cb = cancel_cb;
3252 arg.cancel_arg = cancel_arg;
3253 arg.label_orig = label_orig;
3254 arg.commit_id2 = commit_id2;
3255 err = got_diff_tree(tree1, tree2, "", "", repo, merge_file_cb, &arg, 1);
3256 sync_err = sync_fileindex(fileindex, fileindex_path);
3257 if (sync_err && err == NULL)
3258 err = sync_err;
3259 done:
3260 if (tree1)
3261 got_object_tree_close(tree1);
3262 if (tree2)
3263 got_object_tree_close(tree2);
3264 free(label_orig);
3265 return err;
3268 const struct got_error *
3269 got_worktree_merge_files(struct got_worktree *worktree,
3270 struct got_object_id *commit_id1, struct got_object_id *commit_id2,
3271 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
3272 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
3274 const struct got_error *err, *unlockerr;
3275 char *fileindex_path = NULL;
3276 struct got_fileindex *fileindex = NULL;
3278 err = lock_worktree(worktree, LOCK_EX);
3279 if (err)
3280 return err;
3282 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3283 if (err)
3284 goto done;
3286 err = got_fileindex_for_each_entry_safe(fileindex, check_mixed_commits,
3287 worktree);
3288 if (err)
3289 goto done;
3291 err = merge_files(worktree, fileindex, fileindex_path, commit_id1,
3292 commit_id2, repo, progress_cb, progress_arg,
3293 cancel_cb, cancel_arg);
3294 done:
3295 if (fileindex)
3296 got_fileindex_free(fileindex);
3297 free(fileindex_path);
3298 unlockerr = lock_worktree(worktree, LOCK_SH);
3299 if (unlockerr && err == NULL)
3300 err = unlockerr;
3301 return err;
3304 struct diff_dir_cb_arg {
3305 struct got_fileindex *fileindex;
3306 struct got_worktree *worktree;
3307 const char *status_path;
3308 size_t status_path_len;
3309 struct got_repository *repo;
3310 got_worktree_status_cb status_cb;
3311 void *status_arg;
3312 got_cancel_cb cancel_cb;
3313 void *cancel_arg;
3314 /* A pathlist containing per-directory pathlists of ignore patterns. */
3315 struct got_pathlist_head *ignores;
3316 int report_unchanged;
3317 int no_ignores;
3320 static const struct got_error *
3321 report_file_status(struct got_fileindex_entry *ie, const char *abspath,
3322 int dirfd, const char *de_name,
3323 got_worktree_status_cb status_cb, void *status_arg,
3324 struct got_repository *repo, int report_unchanged)
3326 const struct got_error *err = NULL;
3327 unsigned char status = GOT_STATUS_NO_CHANGE;
3328 unsigned char staged_status = get_staged_status(ie);
3329 struct stat sb;
3330 struct got_object_id blob_id, commit_id, staged_blob_id;
3331 struct got_object_id *blob_idp = NULL, *commit_idp = NULL;
3332 struct got_object_id *staged_blob_idp = NULL;
3334 err = get_file_status(&status, &sb, ie, abspath, dirfd, de_name, repo);
3335 if (err)
3336 return err;
3338 if (status == GOT_STATUS_NO_CHANGE &&
3339 staged_status == GOT_STATUS_NO_CHANGE && !report_unchanged)
3340 return NULL;
3342 if (got_fileindex_entry_has_blob(ie)) {
3343 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
3344 blob_idp = &blob_id;
3346 if (got_fileindex_entry_has_commit(ie)) {
3347 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
3348 commit_idp = &commit_id;
3350 if (staged_status == GOT_STATUS_ADD ||
3351 staged_status == GOT_STATUS_MODIFY) {
3352 memcpy(staged_blob_id.sha1, ie->staged_blob_sha1,
3353 SHA1_DIGEST_LENGTH);
3354 staged_blob_idp = &staged_blob_id;
3357 return (*status_cb)(status_arg, status, staged_status,
3358 ie->path, blob_idp, staged_blob_idp, commit_idp, dirfd, de_name);
3361 static const struct got_error *
3362 status_old_new(void *arg, struct got_fileindex_entry *ie,
3363 struct dirent *de, const char *parent_path, int dirfd)
3365 const struct got_error *err = NULL;
3366 struct diff_dir_cb_arg *a = arg;
3367 char *abspath;
3369 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3370 return got_error(GOT_ERR_CANCELLED);
3372 if (got_path_cmp(parent_path, a->status_path,
3373 strlen(parent_path), a->status_path_len) != 0 &&
3374 !got_path_is_child(parent_path, a->status_path, a->status_path_len))
3375 return NULL;
3377 if (parent_path[0]) {
3378 if (asprintf(&abspath, "%s/%s/%s", a->worktree->root_path,
3379 parent_path, de->d_name) == -1)
3380 return got_error_from_errno("asprintf");
3381 } else {
3382 if (asprintf(&abspath, "%s/%s", a->worktree->root_path,
3383 de->d_name) == -1)
3384 return got_error_from_errno("asprintf");
3387 err = report_file_status(ie, abspath, dirfd, de->d_name,
3388 a->status_cb, a->status_arg, a->repo, a->report_unchanged);
3389 free(abspath);
3390 return err;
3393 static const struct got_error *
3394 status_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
3396 struct diff_dir_cb_arg *a = arg;
3397 struct got_object_id blob_id, commit_id;
3398 unsigned char status;
3400 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3401 return got_error(GOT_ERR_CANCELLED);
3403 if (!got_path_is_child(ie->path, a->status_path, a->status_path_len))
3404 return NULL;
3406 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
3407 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
3408 if (got_fileindex_entry_has_file_on_disk(ie))
3409 status = GOT_STATUS_MISSING;
3410 else
3411 status = GOT_STATUS_DELETE;
3412 return (*a->status_cb)(a->status_arg, status, get_staged_status(ie),
3413 ie->path, &blob_id, NULL, &commit_id, -1, NULL);
3416 void
3417 free_ignorelist(struct got_pathlist_head *ignorelist)
3419 struct got_pathlist_entry *pe;
3421 TAILQ_FOREACH(pe, ignorelist, entry)
3422 free((char *)pe->path);
3423 got_pathlist_free(ignorelist);
3426 void
3427 free_ignores(struct got_pathlist_head *ignores)
3429 struct got_pathlist_entry *pe;
3431 TAILQ_FOREACH(pe, ignores, entry) {
3432 struct got_pathlist_head *ignorelist = pe->data;
3433 free_ignorelist(ignorelist);
3434 free((char *)pe->path);
3436 got_pathlist_free(ignores);
3439 static const struct got_error *
3440 read_ignores(struct got_pathlist_head *ignores, const char *path, FILE *f)
3442 const struct got_error *err = NULL;
3443 struct got_pathlist_entry *pe = NULL;
3444 struct got_pathlist_head *ignorelist;
3445 char *line = NULL, *pattern, *dirpath = NULL;
3446 size_t linesize = 0;
3447 ssize_t linelen;
3449 ignorelist = calloc(1, sizeof(*ignorelist));
3450 if (ignorelist == NULL)
3451 return got_error_from_errno("calloc");
3452 TAILQ_INIT(ignorelist);
3454 while ((linelen = getline(&line, &linesize, f)) != -1) {
3455 if (linelen > 0 && line[linelen - 1] == '\n')
3456 line[linelen - 1] = '\0';
3458 /* Git's ignores may contain comments. */
3459 if (line[0] == '#')
3460 continue;
3462 /* Git's negated patterns are not (yet?) supported. */
3463 if (line[0] == '!')
3464 continue;
3466 if (asprintf(&pattern, "%s%s%s", path, path[0] ? "/" : "",
3467 line) == -1) {
3468 err = got_error_from_errno("asprintf");
3469 goto done;
3471 err = got_pathlist_insert(NULL, ignorelist, pattern, NULL);
3472 if (err)
3473 goto done;
3475 if (ferror(f)) {
3476 err = got_error_from_errno("getline");
3477 goto done;
3480 dirpath = strdup(path);
3481 if (dirpath == NULL) {
3482 err = got_error_from_errno("strdup");
3483 goto done;
3485 err = got_pathlist_insert(&pe, ignores, dirpath, ignorelist);
3486 done:
3487 free(line);
3488 if (err || pe == NULL) {
3489 free(dirpath);
3490 free_ignorelist(ignorelist);
3492 return err;
3495 int
3496 match_ignores(struct got_pathlist_head *ignores, const char *path)
3498 struct got_pathlist_entry *pe;
3500 /* Handle patterns which match in all directories. */
3501 TAILQ_FOREACH(pe, ignores, entry) {
3502 struct got_pathlist_head *ignorelist = pe->data;
3503 struct got_pathlist_entry *pi;
3505 TAILQ_FOREACH(pi, ignorelist, entry) {
3506 const char *p, *pattern = pi->path;
3508 if (strncmp(pattern, "**/", 3) != 0)
3509 continue;
3510 pattern += 3;
3511 p = path;
3512 while (*p) {
3513 if (fnmatch(pattern, p,
3514 FNM_PATHNAME | FNM_LEADING_DIR)) {
3515 /* Retry in next directory. */
3516 while (*p && *p != '/')
3517 p++;
3518 while (*p == '/')
3519 p++;
3520 continue;
3522 return 1;
3528 * The ignores pathlist contains ignore lists from children before
3529 * parents, so we can find the most specific ignorelist by walking
3530 * ignores backwards.
3532 pe = TAILQ_LAST(ignores, got_pathlist_head);
3533 while (pe) {
3534 if (got_path_is_child(path, pe->path, pe->path_len)) {
3535 struct got_pathlist_head *ignorelist = pe->data;
3536 struct got_pathlist_entry *pi;
3537 TAILQ_FOREACH(pi, ignorelist, entry) {
3538 const char *pattern = pi->path;
3539 int flags = FNM_LEADING_DIR;
3540 if (strstr(pattern, "/**/") == NULL)
3541 flags |= FNM_PATHNAME;
3542 if (fnmatch(pattern, path, flags))
3543 continue;
3544 return 1;
3547 pe = TAILQ_PREV(pe, got_pathlist_head, entry);
3550 return 0;
3553 static const struct got_error *
3554 add_ignores(struct got_pathlist_head *ignores, const char *root_path,
3555 const char *path, int dirfd, const char *ignores_filename)
3557 const struct got_error *err = NULL;
3558 char *ignorespath;
3559 int fd = -1;
3560 FILE *ignoresfile = NULL;
3562 if (asprintf(&ignorespath, "%s/%s%s%s", root_path, path,
3563 path[0] ? "/" : "", ignores_filename) == -1)
3564 return got_error_from_errno("asprintf");
3566 if (dirfd != -1) {
3567 fd = openat(dirfd, ignores_filename, O_RDONLY | O_NOFOLLOW);
3568 if (fd == -1) {
3569 if (errno != ENOENT && errno != EACCES)
3570 err = got_error_from_errno2("openat",
3571 ignorespath);
3572 } else {
3573 ignoresfile = fdopen(fd, "r");
3574 if (ignoresfile == NULL)
3575 err = got_error_from_errno2("fdopen",
3576 ignorespath);
3577 else {
3578 fd = -1;
3579 err = read_ignores(ignores, path, ignoresfile);
3582 } else {
3583 ignoresfile = fopen(ignorespath, "r");
3584 if (ignoresfile == NULL) {
3585 if (errno != ENOENT && errno != EACCES)
3586 err = got_error_from_errno2("fopen",
3587 ignorespath);
3588 } else
3589 err = read_ignores(ignores, path, ignoresfile);
3592 if (ignoresfile && fclose(ignoresfile) == EOF && err == NULL)
3593 err = got_error_from_errno2("fclose", path);
3594 if (fd != -1 && close(fd) == -1 && err == NULL)
3595 err = got_error_from_errno2("close", path);
3596 free(ignorespath);
3597 return err;
3600 static const struct got_error *
3601 status_new(void *arg, struct dirent *de, const char *parent_path, int dirfd)
3603 const struct got_error *err = NULL;
3604 struct diff_dir_cb_arg *a = arg;
3605 char *path = NULL;
3607 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
3608 return got_error(GOT_ERR_CANCELLED);
3610 if (parent_path[0]) {
3611 if (asprintf(&path, "%s/%s", parent_path, de->d_name) == -1)
3612 return got_error_from_errno("asprintf");
3613 } else {
3614 path = de->d_name;
3617 if (de->d_type != DT_DIR &&
3618 got_path_is_child(path, a->status_path, a->status_path_len)
3619 && !match_ignores(a->ignores, path))
3620 err = (*a->status_cb)(a->status_arg, GOT_STATUS_UNVERSIONED,
3621 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3622 if (parent_path[0])
3623 free(path);
3624 return err;
3627 static const struct got_error *
3628 status_traverse(void *arg, const char *path, int dirfd)
3630 const struct got_error *err = NULL;
3631 struct diff_dir_cb_arg *a = arg;
3633 if (a->no_ignores)
3634 return NULL;
3636 err = add_ignores(a->ignores, a->worktree->root_path,
3637 path, dirfd, ".cvsignore");
3638 if (err)
3639 return err;
3641 err = add_ignores(a->ignores, a->worktree->root_path, path,
3642 dirfd, ".gitignore");
3644 return err;
3647 static const struct got_error *
3648 report_single_file_status(const char *path, const char *ondisk_path,
3649 struct got_fileindex *fileindex, got_worktree_status_cb status_cb,
3650 void *status_arg, struct got_repository *repo, int report_unchanged,
3651 struct got_pathlist_head *ignores, int no_ignores)
3653 struct got_fileindex_entry *ie;
3654 struct stat sb;
3656 if (!no_ignores && match_ignores(ignores, path))
3657 return NULL;
3659 ie = got_fileindex_entry_get(fileindex, path, strlen(path));
3660 if (ie)
3661 return report_file_status(ie, ondisk_path, -1, NULL,
3662 status_cb, status_arg, repo, report_unchanged);
3664 if (lstat(ondisk_path, &sb) == -1) {
3665 if (errno != ENOENT)
3666 return got_error_from_errno2("lstat", ondisk_path);
3667 return (*status_cb)(status_arg, GOT_STATUS_NONEXISTENT,
3668 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3669 return NULL;
3672 if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode))
3673 return (*status_cb)(status_arg, GOT_STATUS_UNVERSIONED,
3674 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
3676 return NULL;
3679 static const struct got_error *
3680 add_ignores_from_parent_paths(struct got_pathlist_head *ignores,
3681 const char *root_path, const char *path)
3683 const struct got_error *err;
3684 char *parent_path, *next_parent_path = NULL;
3686 err = add_ignores(ignores, root_path, "", -1,
3687 ".cvsignore");
3688 if (err)
3689 return err;
3691 err = add_ignores(ignores, root_path, "", -1,
3692 ".gitignore");
3693 if (err)
3694 return err;
3696 err = got_path_dirname(&parent_path, path);
3697 if (err) {
3698 if (err->code == GOT_ERR_BAD_PATH)
3699 return NULL; /* cannot traverse parent */
3700 return err;
3702 for (;;) {
3703 err = add_ignores(ignores, root_path, parent_path, -1,
3704 ".cvsignore");
3705 if (err)
3706 break;
3707 err = add_ignores(ignores, root_path, parent_path, -1,
3708 ".gitignore");
3709 if (err)
3710 break;
3711 err = got_path_dirname(&next_parent_path, parent_path);
3712 if (err) {
3713 if (err->code == GOT_ERR_BAD_PATH)
3714 err = NULL; /* traversed everything */
3715 break;
3717 if (got_path_is_root_dir(parent_path))
3718 break;
3719 free(parent_path);
3720 parent_path = next_parent_path;
3721 next_parent_path = NULL;
3724 free(parent_path);
3725 free(next_parent_path);
3726 return err;
3729 static const struct got_error *
3730 worktree_status(struct got_worktree *worktree, const char *path,
3731 struct got_fileindex *fileindex, struct got_repository *repo,
3732 got_worktree_status_cb status_cb, void *status_arg,
3733 got_cancel_cb cancel_cb, void *cancel_arg, int no_ignores,
3734 int report_unchanged)
3736 const struct got_error *err = NULL;
3737 int fd = -1;
3738 struct got_fileindex_diff_dir_cb fdiff_cb;
3739 struct diff_dir_cb_arg arg;
3740 char *ondisk_path = NULL;
3741 struct got_pathlist_head ignores;
3743 TAILQ_INIT(&ignores);
3745 if (asprintf(&ondisk_path, "%s%s%s",
3746 worktree->root_path, path[0] ? "/" : "", path) == -1)
3747 return got_error_from_errno("asprintf");
3749 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_DIRECTORY);
3750 if (fd == -1) {
3751 if (errno != ENOTDIR && errno != ENOENT && errno != EACCES &&
3752 errno != ELOOP)
3753 err = got_error_from_errno2("open", ondisk_path);
3754 else {
3755 if (!no_ignores) {
3756 err = add_ignores_from_parent_paths(&ignores,
3757 worktree->root_path, ondisk_path);
3758 if (err)
3759 goto done;
3761 err = report_single_file_status(path, ondisk_path,
3762 fileindex, status_cb, status_arg, repo,
3763 report_unchanged, &ignores, no_ignores);
3765 } else {
3766 fdiff_cb.diff_old_new = status_old_new;
3767 fdiff_cb.diff_old = status_old;
3768 fdiff_cb.diff_new = status_new;
3769 fdiff_cb.diff_traverse = status_traverse;
3770 arg.fileindex = fileindex;
3771 arg.worktree = worktree;
3772 arg.status_path = path;
3773 arg.status_path_len = strlen(path);
3774 arg.repo = repo;
3775 arg.status_cb = status_cb;
3776 arg.status_arg = status_arg;
3777 arg.cancel_cb = cancel_cb;
3778 arg.cancel_arg = cancel_arg;
3779 arg.report_unchanged = report_unchanged;
3780 arg.no_ignores = no_ignores;
3781 if (!no_ignores) {
3782 err = add_ignores_from_parent_paths(&ignores,
3783 worktree->root_path, path);
3784 if (err)
3785 goto done;
3787 arg.ignores = &ignores;
3788 err = got_fileindex_diff_dir(fileindex, fd,
3789 worktree->root_path, path, repo, &fdiff_cb, &arg);
3791 done:
3792 free_ignores(&ignores);
3793 if (fd != -1 && close(fd) == -1 && err == NULL)
3794 err = got_error_from_errno("close");
3795 free(ondisk_path);
3796 return err;
3799 const struct got_error *
3800 got_worktree_status(struct got_worktree *worktree,
3801 struct got_pathlist_head *paths, struct got_repository *repo,
3802 int no_ignores, got_worktree_status_cb status_cb, void *status_arg,
3803 got_cancel_cb cancel_cb, void *cancel_arg)
3805 const struct got_error *err = NULL;
3806 char *fileindex_path = NULL;
3807 struct got_fileindex *fileindex = NULL;
3808 struct got_pathlist_entry *pe;
3810 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3811 if (err)
3812 return err;
3814 TAILQ_FOREACH(pe, paths, entry) {
3815 err = worktree_status(worktree, pe->path, fileindex, repo,
3816 status_cb, status_arg, cancel_cb, cancel_arg,
3817 no_ignores, 0);
3818 if (err)
3819 break;
3821 free(fileindex_path);
3822 got_fileindex_free(fileindex);
3823 return err;
3826 const struct got_error *
3827 got_worktree_resolve_path(char **wt_path, struct got_worktree *worktree,
3828 const char *arg)
3830 const struct got_error *err = NULL;
3831 char *resolved = NULL, *cwd = NULL, *path = NULL;
3832 size_t len;
3833 struct stat sb;
3834 char *abspath = NULL;
3835 char canonpath[PATH_MAX];
3837 *wt_path = NULL;
3839 cwd = getcwd(NULL, 0);
3840 if (cwd == NULL)
3841 return got_error_from_errno("getcwd");
3843 if (lstat(arg, &sb) == -1) {
3844 if (errno != ENOENT) {
3845 err = got_error_from_errno2("lstat", arg);
3846 goto done;
3848 sb.st_mode = 0;
3850 if (S_ISLNK(sb.st_mode)) {
3852 * We cannot use realpath(3) with symlinks since we want to
3853 * operate on the symlink itself.
3854 * But we can make the path absolute, assuming it is relative
3855 * to the current working directory, and then canonicalize it.
3857 if (!got_path_is_absolute(arg)) {
3858 if (asprintf(&abspath, "%s/%s", cwd, arg) == -1) {
3859 err = got_error_from_errno("asprintf");
3860 goto done;
3864 err = got_canonpath(abspath ? abspath : arg, canonpath,
3865 sizeof(canonpath));
3866 if (err)
3867 goto done;
3868 resolved = strdup(canonpath);
3869 if (resolved == NULL) {
3870 err = got_error_from_errno("strdup");
3871 goto done;
3873 } else {
3874 resolved = realpath(arg, NULL);
3875 if (resolved == NULL) {
3876 if (errno != ENOENT) {
3877 err = got_error_from_errno2("realpath", arg);
3878 goto done;
3880 if (asprintf(&abspath, "%s/%s", cwd, arg) == -1) {
3881 err = got_error_from_errno("asprintf");
3882 goto done;
3884 err = got_canonpath(abspath, canonpath,
3885 sizeof(canonpath));
3886 if (err)
3887 goto done;
3888 resolved = strdup(canonpath);
3889 if (resolved == NULL) {
3890 err = got_error_from_errno("strdup");
3891 goto done;
3896 if (strncmp(got_worktree_get_root_path(worktree), resolved,
3897 strlen(got_worktree_get_root_path(worktree)))) {
3898 err = got_error_path(resolved, GOT_ERR_BAD_PATH);
3899 goto done;
3902 if (strlen(resolved) > strlen(got_worktree_get_root_path(worktree))) {
3903 err = got_path_skip_common_ancestor(&path,
3904 got_worktree_get_root_path(worktree), resolved);
3905 if (err)
3906 goto done;
3907 } else {
3908 path = strdup("");
3909 if (path == NULL) {
3910 err = got_error_from_errno("strdup");
3911 goto done;
3915 /* XXX status walk can't deal with trailing slash! */
3916 len = strlen(path);
3917 while (len > 0 && path[len - 1] == '/') {
3918 path[len - 1] = '\0';
3919 len--;
3921 done:
3922 free(abspath);
3923 free(resolved);
3924 free(cwd);
3925 if (err == NULL)
3926 *wt_path = path;
3927 else
3928 free(path);
3929 return err;
3932 struct schedule_addition_args {
3933 struct got_worktree *worktree;
3934 struct got_fileindex *fileindex;
3935 got_worktree_checkout_cb progress_cb;
3936 void *progress_arg;
3937 struct got_repository *repo;
3940 static const struct got_error *
3941 schedule_addition(void *arg, unsigned char status, unsigned char staged_status,
3942 const char *relpath, struct got_object_id *blob_id,
3943 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
3944 int dirfd, const char *de_name)
3946 struct schedule_addition_args *a = arg;
3947 const struct got_error *err = NULL;
3948 struct got_fileindex_entry *ie;
3949 struct stat sb;
3950 char *ondisk_path;
3952 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3953 relpath) == -1)
3954 return got_error_from_errno("asprintf");
3956 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3957 if (ie) {
3958 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd,
3959 de_name, a->repo);
3960 if (err)
3961 goto done;
3962 /* Re-adding an existing entry is a no-op. */
3963 if (status == GOT_STATUS_ADD)
3964 goto done;
3965 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
3966 if (err)
3967 goto done;
3970 if (status != GOT_STATUS_UNVERSIONED) {
3971 err = got_error_path(ondisk_path, GOT_ERR_FILE_STATUS);
3972 goto done;
3975 err = got_fileindex_entry_alloc(&ie, relpath);
3976 if (err)
3977 goto done;
3978 err = got_fileindex_entry_update(ie, a->worktree->root_fd,
3979 relpath, NULL, NULL, 1);
3980 if (err) {
3981 got_fileindex_entry_free(ie);
3982 goto done;
3984 err = got_fileindex_entry_add(a->fileindex, ie);
3985 if (err) {
3986 got_fileindex_entry_free(ie);
3987 goto done;
3989 done:
3990 free(ondisk_path);
3991 if (err)
3992 return err;
3993 if (status == GOT_STATUS_ADD)
3994 return NULL;
3995 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_ADD, relpath);
3998 const struct got_error *
3999 got_worktree_schedule_add(struct got_worktree *worktree,
4000 struct got_pathlist_head *paths,
4001 got_worktree_checkout_cb progress_cb, void *progress_arg,
4002 struct got_repository *repo, int no_ignores)
4004 struct got_fileindex *fileindex = NULL;
4005 char *fileindex_path = NULL;
4006 const struct got_error *err = NULL, *sync_err, *unlockerr;
4007 struct got_pathlist_entry *pe;
4008 struct schedule_addition_args saa;
4010 err = lock_worktree(worktree, LOCK_EX);
4011 if (err)
4012 return err;
4014 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4015 if (err)
4016 goto done;
4018 saa.worktree = worktree;
4019 saa.fileindex = fileindex;
4020 saa.progress_cb = progress_cb;
4021 saa.progress_arg = progress_arg;
4022 saa.repo = repo;
4024 TAILQ_FOREACH(pe, paths, entry) {
4025 err = worktree_status(worktree, pe->path, fileindex, repo,
4026 schedule_addition, &saa, NULL, NULL, no_ignores, 0);
4027 if (err)
4028 break;
4030 sync_err = sync_fileindex(fileindex, fileindex_path);
4031 if (sync_err && err == NULL)
4032 err = sync_err;
4033 done:
4034 free(fileindex_path);
4035 if (fileindex)
4036 got_fileindex_free(fileindex);
4037 unlockerr = lock_worktree(worktree, LOCK_SH);
4038 if (unlockerr && err == NULL)
4039 err = unlockerr;
4040 return err;
4043 struct schedule_deletion_args {
4044 struct got_worktree *worktree;
4045 struct got_fileindex *fileindex;
4046 got_worktree_delete_cb progress_cb;
4047 void *progress_arg;
4048 struct got_repository *repo;
4049 int delete_local_mods;
4050 int keep_on_disk;
4051 const char *status_codes;
4054 static const struct got_error *
4055 schedule_for_deletion(void *arg, unsigned char status,
4056 unsigned char staged_status, const char *relpath,
4057 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
4058 struct got_object_id *commit_id, int dirfd, const char *de_name)
4060 struct schedule_deletion_args *a = arg;
4061 const struct got_error *err = NULL;
4062 struct got_fileindex_entry *ie = NULL;
4063 struct stat sb;
4064 char *ondisk_path;
4066 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
4067 if (ie == NULL)
4068 return got_error_path(relpath, GOT_ERR_BAD_PATH);
4070 staged_status = get_staged_status(ie);
4071 if (staged_status != GOT_STATUS_NO_CHANGE) {
4072 if (staged_status == GOT_STATUS_DELETE)
4073 return NULL;
4074 return got_error_path(relpath, GOT_ERR_FILE_STAGED);
4077 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
4078 relpath) == -1)
4079 return got_error_from_errno("asprintf");
4081 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd, de_name,
4082 a->repo);
4083 if (err)
4084 goto done;
4086 if (a->status_codes) {
4087 size_t ncodes = strlen(a->status_codes);
4088 int i;
4089 for (i = 0; i < ncodes ; i++) {
4090 if (status == a->status_codes[i])
4091 break;
4093 if (i == ncodes) {
4094 /* Do not delete files in non-matching status. */
4095 free(ondisk_path);
4096 return NULL;
4098 if (a->status_codes[i] != GOT_STATUS_MODIFY &&
4099 a->status_codes[i] != GOT_STATUS_MISSING) {
4100 static char msg[64];
4101 snprintf(msg, sizeof(msg),
4102 "invalid status code '%c'", a->status_codes[i]);
4103 err = got_error_msg(GOT_ERR_FILE_STATUS, msg);
4104 goto done;
4108 if (status != GOT_STATUS_NO_CHANGE) {
4109 if (status == GOT_STATUS_DELETE)
4110 goto done;
4111 if (status == GOT_STATUS_MODIFY && !a->delete_local_mods) {
4112 err = got_error_path(relpath, GOT_ERR_FILE_MODIFIED);
4113 goto done;
4115 if (status != GOT_STATUS_MODIFY &&
4116 status != GOT_STATUS_MISSING) {
4117 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
4118 goto done;
4122 if (!a->keep_on_disk && status != GOT_STATUS_MISSING) {
4123 size_t root_len;
4125 if (dirfd != -1) {
4126 if (unlinkat(dirfd, de_name, 0) != 0) {
4127 err = got_error_from_errno2("unlinkat",
4128 ondisk_path);
4129 goto done;
4131 } else if (unlink(ondisk_path) != 0) {
4132 err = got_error_from_errno2("unlink", ondisk_path);
4133 goto done;
4136 root_len = strlen(a->worktree->root_path);
4137 do {
4138 char *parent;
4139 err = got_path_dirname(&parent, ondisk_path);
4140 if (err)
4141 goto done;
4142 free(ondisk_path);
4143 ondisk_path = parent;
4144 if (rmdir(ondisk_path) == -1) {
4145 if (errno != ENOTEMPTY)
4146 err = got_error_from_errno2("rmdir",
4147 ondisk_path);
4148 break;
4150 } while (got_path_cmp(ondisk_path, a->worktree->root_path,
4151 strlen(ondisk_path), root_len) != 0);
4154 got_fileindex_entry_mark_deleted_from_disk(ie);
4155 done:
4156 free(ondisk_path);
4157 if (err)
4158 return err;
4159 if (status == GOT_STATUS_DELETE)
4160 return NULL;
4161 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE,
4162 staged_status, relpath);
4165 const struct got_error *
4166 got_worktree_schedule_delete(struct got_worktree *worktree,
4167 struct got_pathlist_head *paths, int delete_local_mods,
4168 const char *status_codes,
4169 got_worktree_delete_cb progress_cb, void *progress_arg,
4170 struct got_repository *repo, int keep_on_disk)
4172 struct got_fileindex *fileindex = NULL;
4173 char *fileindex_path = NULL;
4174 const struct got_error *err = NULL, *sync_err, *unlockerr;
4175 struct got_pathlist_entry *pe;
4176 struct schedule_deletion_args sda;
4178 err = lock_worktree(worktree, LOCK_EX);
4179 if (err)
4180 return err;
4182 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4183 if (err)
4184 goto done;
4186 sda.worktree = worktree;
4187 sda.fileindex = fileindex;
4188 sda.progress_cb = progress_cb;
4189 sda.progress_arg = progress_arg;
4190 sda.repo = repo;
4191 sda.delete_local_mods = delete_local_mods;
4192 sda.keep_on_disk = keep_on_disk;
4193 sda.status_codes = status_codes;
4195 TAILQ_FOREACH(pe, paths, entry) {
4196 err = worktree_status(worktree, pe->path, fileindex, repo,
4197 schedule_for_deletion, &sda, NULL, NULL, 0, 1);
4198 if (err)
4199 break;
4201 sync_err = sync_fileindex(fileindex, fileindex_path);
4202 if (sync_err && err == NULL)
4203 err = sync_err;
4204 done:
4205 free(fileindex_path);
4206 if (fileindex)
4207 got_fileindex_free(fileindex);
4208 unlockerr = lock_worktree(worktree, LOCK_SH);
4209 if (unlockerr && err == NULL)
4210 err = unlockerr;
4211 return err;
4214 static const struct got_error *
4215 copy_one_line(FILE *infile, FILE *outfile, FILE *rejectfile)
4217 const struct got_error *err = NULL;
4218 char *line = NULL;
4219 size_t linesize = 0, n;
4220 ssize_t linelen;
4222 linelen = getline(&line, &linesize, infile);
4223 if (linelen == -1) {
4224 if (ferror(infile)) {
4225 err = got_error_from_errno("getline");
4226 goto done;
4228 return NULL;
4230 if (outfile) {
4231 n = fwrite(line, 1, linelen, outfile);
4232 if (n != linelen) {
4233 err = got_ferror(outfile, GOT_ERR_IO);
4234 goto done;
4237 if (rejectfile) {
4238 n = fwrite(line, 1, linelen, rejectfile);
4239 if (n != linelen)
4240 err = got_ferror(outfile, GOT_ERR_IO);
4242 done:
4243 free(line);
4244 return err;
4247 static const struct got_error *
4248 skip_one_line(FILE *f)
4250 char *line = NULL;
4251 size_t linesize = 0;
4252 ssize_t linelen;
4254 linelen = getline(&line, &linesize, f);
4255 if (linelen == -1) {
4256 if (ferror(f))
4257 return got_error_from_errno("getline");
4258 return NULL;
4260 free(line);
4261 return NULL;
4264 static const struct got_error *
4265 copy_change(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
4266 int start_old, int end_old, int start_new, int end_new,
4267 FILE *outfile, FILE *rejectfile)
4269 const struct got_error *err;
4271 /* Copy old file's lines leading up to patch. */
4272 while (!feof(f1) && *line_cur1 < start_old) {
4273 err = copy_one_line(f1, outfile, NULL);
4274 if (err)
4275 return err;
4276 (*line_cur1)++;
4278 /* Skip new file's lines leading up to patch. */
4279 while (!feof(f2) && *line_cur2 < start_new) {
4280 if (rejectfile)
4281 err = copy_one_line(f2, NULL, rejectfile);
4282 else
4283 err = skip_one_line(f2);
4284 if (err)
4285 return err;
4286 (*line_cur2)++;
4288 /* Copy patched lines. */
4289 while (!feof(f2) && *line_cur2 <= end_new) {
4290 err = copy_one_line(f2, outfile, NULL);
4291 if (err)
4292 return err;
4293 (*line_cur2)++;
4295 /* Skip over old file's replaced lines. */
4296 while (!feof(f1) && *line_cur1 <= end_old) {
4297 if (rejectfile)
4298 err = copy_one_line(f1, NULL, rejectfile);
4299 else
4300 err = skip_one_line(f1);
4301 if (err)
4302 return err;
4303 (*line_cur1)++;
4306 return NULL;
4309 static const struct got_error *
4310 copy_remaining_content(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
4311 FILE *outfile, FILE *rejectfile)
4313 const struct got_error *err;
4315 if (outfile) {
4316 /* Copy old file's lines until EOF. */
4317 while (!feof(f1)) {
4318 err = copy_one_line(f1, outfile, NULL);
4319 if (err)
4320 return err;
4321 (*line_cur1)++;
4324 if (rejectfile) {
4325 /* Copy new file's lines until EOF. */
4326 while (!feof(f2)) {
4327 err = copy_one_line(f2, NULL, rejectfile);
4328 if (err)
4329 return err;
4330 (*line_cur2)++;
4334 return NULL;
4337 static const struct got_error *
4338 apply_or_reject_change(int *choice, int *nchunks_used,
4339 struct diff_result *diff_result, int n,
4340 const char *relpath, FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
4341 FILE *outfile, FILE *rejectfile, int changeno, int nchanges,
4342 got_worktree_patch_cb patch_cb, void *patch_arg)
4344 const struct got_error *err = NULL;
4345 struct diff_chunk_context cc = {};
4346 int start_old, end_old, start_new, end_new;
4347 FILE *hunkfile;
4348 struct diff_output_unidiff_state *diff_state;
4349 struct diff_input_info diff_info;
4350 int rc;
4352 *choice = GOT_PATCH_CHOICE_NONE;
4354 /* Get changed line numbers without context lines for copy_change(). */
4355 diff_chunk_context_load_change(&cc, NULL, diff_result, n, 0);
4356 start_old = cc.left.start;
4357 end_old = cc.left.end;
4358 start_new = cc.right.start;
4359 end_new = cc.right.end;
4361 /* Get the same change with context lines for display. */
4362 memset(&cc, 0, sizeof(cc));
4363 diff_chunk_context_load_change(&cc, nchunks_used, diff_result, n, 3);
4365 memset(&diff_info, 0, sizeof(diff_info));
4366 diff_info.left_path = relpath;
4367 diff_info.right_path = relpath;
4369 diff_state = diff_output_unidiff_state_alloc();
4370 if (diff_state == NULL)
4371 return got_error_set_errno(ENOMEM,
4372 "diff_output_unidiff_state_alloc");
4374 hunkfile = got_opentemp();
4375 if (hunkfile == NULL) {
4376 err = got_error_from_errno("got_opentemp");
4377 goto done;
4380 rc = diff_output_unidiff_chunk(NULL, hunkfile, diff_state, &diff_info,
4381 diff_result, &cc);
4382 if (rc != DIFF_RC_OK) {
4383 err = got_error_set_errno(rc, "diff_output_unidiff_chunk");
4384 goto done;
4387 if (fseek(hunkfile, 0L, SEEK_SET) == -1) {
4388 err = got_ferror(hunkfile, GOT_ERR_IO);
4389 goto done;
4392 err = (*patch_cb)(choice, patch_arg, GOT_STATUS_MODIFY, relpath,
4393 hunkfile, changeno, nchanges);
4394 if (err)
4395 goto done;
4397 switch (*choice) {
4398 case GOT_PATCH_CHOICE_YES:
4399 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
4400 end_old, start_new, end_new, outfile, rejectfile);
4401 break;
4402 case GOT_PATCH_CHOICE_NO:
4403 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
4404 end_old, start_new, end_new, rejectfile, outfile);
4405 break;
4406 case GOT_PATCH_CHOICE_QUIT:
4407 break;
4408 default:
4409 err = got_error(GOT_ERR_PATCH_CHOICE);
4410 break;
4412 done:
4413 diff_output_unidiff_state_free(diff_state);
4414 if (hunkfile && fclose(hunkfile) == EOF && err == NULL)
4415 err = got_error_from_errno("fclose");
4416 return err;
4419 struct revert_file_args {
4420 struct got_worktree *worktree;
4421 struct got_fileindex *fileindex;
4422 got_worktree_checkout_cb progress_cb;
4423 void *progress_arg;
4424 got_worktree_patch_cb patch_cb;
4425 void *patch_arg;
4426 struct got_repository *repo;
4427 int unlink_added_files;
4430 static const struct got_error *
4431 create_patched_content(char **path_outfile, int reverse_patch,
4432 struct got_object_id *blob_id, const char *path2,
4433 int dirfd2, const char *de_name2,
4434 const char *relpath, struct got_repository *repo,
4435 got_worktree_patch_cb patch_cb, void *patch_arg)
4437 const struct got_error *err, *free_err;
4438 struct got_blob_object *blob = NULL;
4439 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL;
4440 int fd2 = -1;
4441 char link_target[PATH_MAX];
4442 ssize_t link_len = 0;
4443 char *path1 = NULL, *id_str = NULL;
4444 struct stat sb2;
4445 struct got_diffreg_result *diffreg_result = NULL;
4446 int line_cur1 = 1, line_cur2 = 1, have_content = 0;
4447 int i = 0, n = 0, nchunks_used = 0, nchanges = 0;
4449 *path_outfile = NULL;
4451 err = got_object_id_str(&id_str, blob_id);
4452 if (err)
4453 return err;
4455 if (dirfd2 != -1) {
4456 fd2 = openat(dirfd2, de_name2, O_RDONLY | O_NOFOLLOW);
4457 if (fd2 == -1) {
4458 if (errno != ELOOP) {
4459 err = got_error_from_errno2("openat", path2);
4460 goto done;
4462 link_len = readlinkat(dirfd2, de_name2,
4463 link_target, sizeof(link_target));
4464 if (link_len == -1)
4465 return got_error_from_errno2("readlinkat", path2);
4466 sb2.st_mode = S_IFLNK;
4467 sb2.st_size = link_len;
4469 } else {
4470 fd2 = open(path2, O_RDONLY | O_NOFOLLOW);
4471 if (fd2 == -1) {
4472 if (errno != ELOOP) {
4473 err = got_error_from_errno2("open", path2);
4474 goto done;
4476 link_len = readlink(path2, link_target,
4477 sizeof(link_target));
4478 if (link_len == -1)
4479 return got_error_from_errno2("readlink", path2);
4480 sb2.st_mode = S_IFLNK;
4481 sb2.st_size = link_len;
4484 if (fd2 != -1) {
4485 if (fstat(fd2, &sb2) == -1) {
4486 err = got_error_from_errno2("fstat", path2);
4487 goto done;
4490 f2 = fdopen(fd2, "r");
4491 if (f2 == NULL) {
4492 err = got_error_from_errno2("fdopen", path2);
4493 goto done;
4495 fd2 = -1;
4496 } else {
4497 size_t n;
4498 f2 = got_opentemp();
4499 if (f2 == NULL) {
4500 err = got_error_from_errno2("got_opentemp", path2);
4501 goto done;
4503 n = fwrite(link_target, 1, link_len, f2);
4504 if (n != link_len) {
4505 err = got_ferror(f2, GOT_ERR_IO);
4506 goto done;
4508 if (fflush(f2) == EOF) {
4509 err = got_error_from_errno("fflush");
4510 goto done;
4512 rewind(f2);
4515 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
4516 if (err)
4517 goto done;
4519 err = got_opentemp_named(&path1, &f1, "got-patched-blob");
4520 if (err)
4521 goto done;
4523 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
4524 if (err)
4525 goto done;
4527 err = got_diff_files(&diffreg_result, f1, id_str, f2, path2, 3, 0, 1,
4528 NULL);
4529 if (err)
4530 goto done;
4532 err = got_opentemp_named(path_outfile, &outfile, "got-patched-content");
4533 if (err)
4534 goto done;
4536 if (fseek(f1, 0L, SEEK_SET) == -1)
4537 return got_ferror(f1, GOT_ERR_IO);
4538 if (fseek(f2, 0L, SEEK_SET) == -1)
4539 return got_ferror(f2, GOT_ERR_IO);
4541 /* Count the number of actual changes in the diff result. */
4542 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
4543 struct diff_chunk_context cc = {};
4544 diff_chunk_context_load_change(&cc, &nchunks_used,
4545 diffreg_result->result, n, 0);
4546 nchanges++;
4548 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
4549 int choice;
4550 err = apply_or_reject_change(&choice, &nchunks_used,
4551 diffreg_result->result, n, relpath, f1, f2,
4552 &line_cur1, &line_cur2,
4553 reverse_patch ? NULL : outfile,
4554 reverse_patch ? outfile : NULL,
4555 ++i, nchanges, patch_cb, patch_arg);
4556 if (err)
4557 goto done;
4558 if (choice == GOT_PATCH_CHOICE_YES)
4559 have_content = 1;
4560 else if (choice == GOT_PATCH_CHOICE_QUIT)
4561 break;
4563 if (have_content) {
4564 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
4565 reverse_patch ? NULL : outfile,
4566 reverse_patch ? outfile : NULL);
4567 if (err)
4568 goto done;
4570 if (!S_ISLNK(sb2.st_mode)) {
4571 if (fchmod(fileno(outfile), sb2.st_mode) == -1) {
4572 err = got_error_from_errno2("fchmod", path2);
4573 goto done;
4577 done:
4578 free(id_str);
4579 if (blob)
4580 got_object_blob_close(blob);
4581 free_err = got_diffreg_result_free(diffreg_result);
4582 if (err == NULL)
4583 err = free_err;
4584 if (f1 && fclose(f1) == EOF && err == NULL)
4585 err = got_error_from_errno2("fclose", path1);
4586 if (f2 && fclose(f2) == EOF && err == NULL)
4587 err = got_error_from_errno2("fclose", path2);
4588 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
4589 err = got_error_from_errno2("close", path2);
4590 if (outfile && fclose(outfile) == EOF && err == NULL)
4591 err = got_error_from_errno2("fclose", *path_outfile);
4592 if (path1 && unlink(path1) == -1 && err == NULL)
4593 err = got_error_from_errno2("unlink", path1);
4594 if (err || !have_content) {
4595 if (*path_outfile && unlink(*path_outfile) == -1 && err == NULL)
4596 err = got_error_from_errno2("unlink", *path_outfile);
4597 free(*path_outfile);
4598 *path_outfile = NULL;
4600 free(path1);
4601 return err;
4604 static const struct got_error *
4605 revert_file(void *arg, unsigned char status, unsigned char staged_status,
4606 const char *relpath, struct got_object_id *blob_id,
4607 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
4608 int dirfd, const char *de_name)
4610 struct revert_file_args *a = arg;
4611 const struct got_error *err = NULL;
4612 char *parent_path = NULL;
4613 struct got_fileindex_entry *ie;
4614 struct got_tree_object *tree = NULL;
4615 struct got_object_id *tree_id = NULL;
4616 const struct got_tree_entry *te = NULL;
4617 char *tree_path = NULL, *te_name;
4618 char *ondisk_path = NULL, *path_content = NULL;
4619 struct got_blob_object *blob = NULL;
4621 /* Reverting a staged deletion is a no-op. */
4622 if (status == GOT_STATUS_DELETE &&
4623 staged_status != GOT_STATUS_NO_CHANGE)
4624 return NULL;
4626 if (status == GOT_STATUS_UNVERSIONED)
4627 return (*a->progress_cb)(a->progress_arg,
4628 GOT_STATUS_UNVERSIONED, relpath);
4630 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
4631 if (ie == NULL)
4632 return got_error_path(relpath, GOT_ERR_BAD_PATH);
4634 /* Construct in-repository path of tree which contains this blob. */
4635 err = got_path_dirname(&parent_path, ie->path);
4636 if (err) {
4637 if (err->code != GOT_ERR_BAD_PATH)
4638 goto done;
4639 parent_path = strdup("/");
4640 if (parent_path == NULL) {
4641 err = got_error_from_errno("strdup");
4642 goto done;
4645 if (got_path_is_root_dir(a->worktree->path_prefix)) {
4646 tree_path = strdup(parent_path);
4647 if (tree_path == NULL) {
4648 err = got_error_from_errno("strdup");
4649 goto done;
4651 } else {
4652 if (got_path_is_root_dir(parent_path)) {
4653 tree_path = strdup(a->worktree->path_prefix);
4654 if (tree_path == NULL) {
4655 err = got_error_from_errno("strdup");
4656 goto done;
4658 } else {
4659 if (asprintf(&tree_path, "%s/%s",
4660 a->worktree->path_prefix, parent_path) == -1) {
4661 err = got_error_from_errno("asprintf");
4662 goto done;
4667 err = got_object_id_by_path(&tree_id, a->repo,
4668 a->worktree->base_commit_id, tree_path);
4669 if (err) {
4670 if (!(err->code == GOT_ERR_NO_TREE_ENTRY &&
4671 (status == GOT_STATUS_ADD ||
4672 staged_status == GOT_STATUS_ADD)))
4673 goto done;
4674 } else {
4675 err = got_object_open_as_tree(&tree, a->repo, tree_id);
4676 if (err)
4677 goto done;
4679 err = got_path_basename(&te_name, ie->path);
4680 if (err)
4681 goto done;
4683 te = got_object_tree_find_entry(tree, te_name);
4684 free(te_name);
4685 if (te == NULL && status != GOT_STATUS_ADD &&
4686 staged_status != GOT_STATUS_ADD) {
4687 err = got_error_path(ie->path, GOT_ERR_NO_TREE_ENTRY);
4688 goto done;
4692 switch (status) {
4693 case GOT_STATUS_ADD:
4694 if (a->patch_cb) {
4695 int choice = GOT_PATCH_CHOICE_NONE;
4696 err = (*a->patch_cb)(&choice, a->patch_arg,
4697 status, ie->path, NULL, 1, 1);
4698 if (err)
4699 goto done;
4700 if (choice != GOT_PATCH_CHOICE_YES)
4701 break;
4703 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_REVERT,
4704 ie->path);
4705 if (err)
4706 goto done;
4707 got_fileindex_entry_remove(a->fileindex, ie);
4708 if (a->unlink_added_files) {
4709 if (asprintf(&ondisk_path, "%s/%s",
4710 got_worktree_get_root_path(a->worktree),
4711 relpath) == -1) {
4712 err = got_error_from_errno("asprintf");
4713 goto done;
4715 if (unlink(ondisk_path) == -1) {
4716 err = got_error_from_errno2("unlink",
4717 ondisk_path);
4718 break;
4721 break;
4722 case GOT_STATUS_DELETE:
4723 if (a->patch_cb) {
4724 int choice = GOT_PATCH_CHOICE_NONE;
4725 err = (*a->patch_cb)(&choice, a->patch_arg,
4726 status, ie->path, NULL, 1, 1);
4727 if (err)
4728 goto done;
4729 if (choice != GOT_PATCH_CHOICE_YES)
4730 break;
4732 /* fall through */
4733 case GOT_STATUS_MODIFY:
4734 case GOT_STATUS_MODE_CHANGE:
4735 case GOT_STATUS_CONFLICT:
4736 case GOT_STATUS_MISSING: {
4737 struct got_object_id id;
4738 if (staged_status == GOT_STATUS_ADD ||
4739 staged_status == GOT_STATUS_MODIFY) {
4740 memcpy(id.sha1, ie->staged_blob_sha1,
4741 SHA1_DIGEST_LENGTH);
4742 } else
4743 memcpy(id.sha1, ie->blob_sha1,
4744 SHA1_DIGEST_LENGTH);
4745 err = got_object_open_as_blob(&blob, a->repo, &id, 8192);
4746 if (err)
4747 goto done;
4749 if (asprintf(&ondisk_path, "%s/%s",
4750 got_worktree_get_root_path(a->worktree), relpath) == -1) {
4751 err = got_error_from_errno("asprintf");
4752 goto done;
4755 if (a->patch_cb && (status == GOT_STATUS_MODIFY ||
4756 status == GOT_STATUS_CONFLICT)) {
4757 int is_bad_symlink = 0;
4758 err = create_patched_content(&path_content, 1, &id,
4759 ondisk_path, dirfd, de_name, ie->path, a->repo,
4760 a->patch_cb, a->patch_arg);
4761 if (err || path_content == NULL)
4762 break;
4763 if (te && S_ISLNK(te->mode)) {
4764 if (unlink(path_content) == -1) {
4765 err = got_error_from_errno2("unlink",
4766 path_content);
4767 break;
4769 err = install_symlink(&is_bad_symlink,
4770 a->worktree, ondisk_path, ie->path,
4771 blob, 0, 1, 0, a->repo,
4772 a->progress_cb, a->progress_arg);
4773 } else {
4774 if (rename(path_content, ondisk_path) == -1) {
4775 err = got_error_from_errno3("rename",
4776 path_content, ondisk_path);
4777 goto done;
4780 } else {
4781 int is_bad_symlink = 0;
4782 if (te && S_ISLNK(te->mode)) {
4783 err = install_symlink(&is_bad_symlink,
4784 a->worktree, ondisk_path, ie->path,
4785 blob, 0, 1, 0, a->repo,
4786 a->progress_cb, a->progress_arg);
4787 } else {
4788 err = install_blob(a->worktree, ondisk_path,
4789 ie->path,
4790 te ? te->mode : GOT_DEFAULT_FILE_MODE,
4791 got_fileindex_perms_to_st(ie), blob,
4792 0, 1, 0, 0, a->repo,
4793 a->progress_cb, a->progress_arg);
4795 if (err)
4796 goto done;
4797 if (status == GOT_STATUS_DELETE ||
4798 status == GOT_STATUS_MODE_CHANGE) {
4799 err = got_fileindex_entry_update(ie,
4800 a->worktree->root_fd, relpath,
4801 blob->id.sha1,
4802 a->worktree->base_commit_id->sha1, 1);
4803 if (err)
4804 goto done;
4806 if (is_bad_symlink) {
4807 got_fileindex_entry_filetype_set(ie,
4808 GOT_FILEIDX_MODE_BAD_SYMLINK);
4811 break;
4813 default:
4814 break;
4816 done:
4817 free(ondisk_path);
4818 free(path_content);
4819 free(parent_path);
4820 free(tree_path);
4821 if (blob)
4822 got_object_blob_close(blob);
4823 if (tree)
4824 got_object_tree_close(tree);
4825 free(tree_id);
4826 return err;
4829 const struct got_error *
4830 got_worktree_revert(struct got_worktree *worktree,
4831 struct got_pathlist_head *paths,
4832 got_worktree_checkout_cb progress_cb, void *progress_arg,
4833 got_worktree_patch_cb patch_cb, void *patch_arg,
4834 struct got_repository *repo)
4836 struct got_fileindex *fileindex = NULL;
4837 char *fileindex_path = NULL;
4838 const struct got_error *err = NULL, *unlockerr = NULL;
4839 const struct got_error *sync_err = NULL;
4840 struct got_pathlist_entry *pe;
4841 struct revert_file_args rfa;
4843 err = lock_worktree(worktree, LOCK_EX);
4844 if (err)
4845 return err;
4847 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4848 if (err)
4849 goto done;
4851 rfa.worktree = worktree;
4852 rfa.fileindex = fileindex;
4853 rfa.progress_cb = progress_cb;
4854 rfa.progress_arg = progress_arg;
4855 rfa.patch_cb = patch_cb;
4856 rfa.patch_arg = patch_arg;
4857 rfa.repo = repo;
4858 rfa.unlink_added_files = 0;
4859 TAILQ_FOREACH(pe, paths, entry) {
4860 err = worktree_status(worktree, pe->path, fileindex, repo,
4861 revert_file, &rfa, NULL, NULL, 0, 0);
4862 if (err)
4863 break;
4865 sync_err = sync_fileindex(fileindex, fileindex_path);
4866 if (sync_err && err == NULL)
4867 err = sync_err;
4868 done:
4869 free(fileindex_path);
4870 if (fileindex)
4871 got_fileindex_free(fileindex);
4872 unlockerr = lock_worktree(worktree, LOCK_SH);
4873 if (unlockerr && err == NULL)
4874 err = unlockerr;
4875 return err;
4878 static void
4879 free_commitable(struct got_commitable *ct)
4881 free(ct->path);
4882 free(ct->in_repo_path);
4883 free(ct->ondisk_path);
4884 free(ct->blob_id);
4885 free(ct->base_blob_id);
4886 free(ct->staged_blob_id);
4887 free(ct->base_commit_id);
4888 free(ct);
4891 struct collect_commitables_arg {
4892 struct got_pathlist_head *commitable_paths;
4893 struct got_repository *repo;
4894 struct got_worktree *worktree;
4895 struct got_fileindex *fileindex;
4896 int have_staged_files;
4897 int allow_bad_symlinks;
4900 static const struct got_error *
4901 collect_commitables(void *arg, unsigned char status,
4902 unsigned char staged_status, const char *relpath,
4903 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
4904 struct got_object_id *commit_id, int dirfd, const char *de_name)
4906 struct collect_commitables_arg *a = arg;
4907 const struct got_error *err = NULL;
4908 struct got_commitable *ct = NULL;
4909 struct got_pathlist_entry *new = NULL;
4910 char *parent_path = NULL, *path = NULL;
4911 struct stat sb;
4913 if (a->have_staged_files) {
4914 if (staged_status != GOT_STATUS_MODIFY &&
4915 staged_status != GOT_STATUS_ADD &&
4916 staged_status != GOT_STATUS_DELETE)
4917 return NULL;
4918 } else {
4919 if (status == GOT_STATUS_CONFLICT)
4920 return got_error(GOT_ERR_COMMIT_CONFLICT);
4922 if (status != GOT_STATUS_MODIFY &&
4923 status != GOT_STATUS_MODE_CHANGE &&
4924 status != GOT_STATUS_ADD &&
4925 status != GOT_STATUS_DELETE)
4926 return NULL;
4929 if (asprintf(&path, "/%s", relpath) == -1) {
4930 err = got_error_from_errno("asprintf");
4931 goto done;
4933 if (strcmp(path, "/") == 0) {
4934 parent_path = strdup("");
4935 if (parent_path == NULL)
4936 return got_error_from_errno("strdup");
4937 } else {
4938 err = got_path_dirname(&parent_path, path);
4939 if (err)
4940 return err;
4943 ct = calloc(1, sizeof(*ct));
4944 if (ct == NULL) {
4945 err = got_error_from_errno("calloc");
4946 goto done;
4949 if (asprintf(&ct->ondisk_path, "%s/%s", a->worktree->root_path,
4950 relpath) == -1) {
4951 err = got_error_from_errno("asprintf");
4952 goto done;
4955 if (staged_status == GOT_STATUS_ADD ||
4956 staged_status == GOT_STATUS_MODIFY) {
4957 struct got_fileindex_entry *ie;
4958 ie = got_fileindex_entry_get(a->fileindex, path, strlen(path));
4959 switch (got_fileindex_entry_staged_filetype_get(ie)) {
4960 case GOT_FILEIDX_MODE_REGULAR_FILE:
4961 case GOT_FILEIDX_MODE_BAD_SYMLINK:
4962 ct->mode = S_IFREG;
4963 break;
4964 case GOT_FILEIDX_MODE_SYMLINK:
4965 ct->mode = S_IFLNK;
4966 break;
4967 default:
4968 err = got_error_path(path, GOT_ERR_BAD_FILETYPE);
4969 goto done;
4971 ct->mode |= got_fileindex_entry_perms_get(ie);
4972 } else if (status != GOT_STATUS_DELETE &&
4973 staged_status != GOT_STATUS_DELETE) {
4974 if (dirfd != -1) {
4975 if (fstatat(dirfd, de_name, &sb,
4976 AT_SYMLINK_NOFOLLOW) == -1) {
4977 err = got_error_from_errno2("fstatat",
4978 ct->ondisk_path);
4979 goto done;
4981 } else if (lstat(ct->ondisk_path, &sb) == -1) {
4982 err = got_error_from_errno2("lstat", ct->ondisk_path);
4983 goto done;
4985 ct->mode = sb.st_mode;
4988 if (asprintf(&ct->in_repo_path, "%s%s%s", a->worktree->path_prefix,
4989 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
4990 relpath) == -1) {
4991 err = got_error_from_errno("asprintf");
4992 goto done;
4995 if (S_ISLNK(ct->mode) && staged_status == GOT_STATUS_NO_CHANGE &&
4996 status == GOT_STATUS_ADD && !a->allow_bad_symlinks) {
4997 int is_bad_symlink;
4998 char target_path[PATH_MAX];
4999 ssize_t target_len;
5000 target_len = readlink(ct->ondisk_path, target_path,
5001 sizeof(target_path));
5002 if (target_len == -1) {
5003 err = got_error_from_errno2("readlink",
5004 ct->ondisk_path);
5005 goto done;
5007 err = is_bad_symlink_target(&is_bad_symlink, target_path,
5008 target_len, ct->ondisk_path, a->worktree->root_path);
5009 if (err)
5010 goto done;
5011 if (is_bad_symlink) {
5012 err = got_error_path(ct->ondisk_path,
5013 GOT_ERR_BAD_SYMLINK);
5014 goto done;
5019 ct->status = status;
5020 ct->staged_status = staged_status;
5021 ct->blob_id = NULL; /* will be filled in when blob gets created */
5022 if (ct->status != GOT_STATUS_ADD &&
5023 ct->staged_status != GOT_STATUS_ADD) {
5024 ct->base_blob_id = got_object_id_dup(blob_id);
5025 if (ct->base_blob_id == NULL) {
5026 err = got_error_from_errno("got_object_id_dup");
5027 goto done;
5029 ct->base_commit_id = got_object_id_dup(commit_id);
5030 if (ct->base_commit_id == NULL) {
5031 err = got_error_from_errno("got_object_id_dup");
5032 goto done;
5035 if (ct->staged_status == GOT_STATUS_ADD ||
5036 ct->staged_status == GOT_STATUS_MODIFY) {
5037 ct->staged_blob_id = got_object_id_dup(staged_blob_id);
5038 if (ct->staged_blob_id == NULL) {
5039 err = got_error_from_errno("got_object_id_dup");
5040 goto done;
5043 ct->path = strdup(path);
5044 if (ct->path == NULL) {
5045 err = got_error_from_errno("strdup");
5046 goto done;
5048 err = got_pathlist_insert(&new, a->commitable_paths, ct->path, ct);
5049 done:
5050 if (ct && (err || new == NULL))
5051 free_commitable(ct);
5052 free(parent_path);
5053 free(path);
5054 return err;
5057 static const struct got_error *write_tree(struct got_object_id **, int *,
5058 struct got_tree_object *, const char *, struct got_pathlist_head *,
5059 got_worktree_status_cb status_cb, void *status_arg,
5060 struct got_repository *);
5062 static const struct got_error *
5063 write_subtree(struct got_object_id **new_subtree_id, int *nentries,
5064 struct got_tree_entry *te, const char *parent_path,
5065 struct got_pathlist_head *commitable_paths,
5066 got_worktree_status_cb status_cb, void *status_arg,
5067 struct got_repository *repo)
5069 const struct got_error *err = NULL;
5070 struct got_tree_object *subtree;
5071 char *subpath;
5073 if (asprintf(&subpath, "%s%s%s", parent_path,
5074 got_path_is_root_dir(parent_path) ? "" : "/", te->name) == -1)
5075 return got_error_from_errno("asprintf");
5077 err = got_object_open_as_tree(&subtree, repo, &te->id);
5078 if (err)
5079 return err;
5081 err = write_tree(new_subtree_id, nentries, subtree, subpath,
5082 commitable_paths, status_cb, status_arg, repo);
5083 got_object_tree_close(subtree);
5084 free(subpath);
5085 return err;
5088 static const struct got_error *
5089 match_ct_parent_path(int *match, struct got_commitable *ct, const char *path)
5091 const struct got_error *err = NULL;
5092 char *ct_parent_path = NULL;
5094 *match = 0;
5096 if (strchr(ct->in_repo_path, '/') == NULL) {
5097 *match = got_path_is_root_dir(path);
5098 return NULL;
5101 err = got_path_dirname(&ct_parent_path, ct->in_repo_path);
5102 if (err)
5103 return err;
5104 *match = (strcmp(path, ct_parent_path) == 0);
5105 free(ct_parent_path);
5106 return err;
5109 static mode_t
5110 get_ct_file_mode(struct got_commitable *ct)
5112 if (S_ISLNK(ct->mode))
5113 return S_IFLNK;
5115 return S_IFREG | (ct->mode & ((S_IRWXU | S_IRWXG | S_IRWXO)));
5118 static const struct got_error *
5119 alloc_modified_blob_tree_entry(struct got_tree_entry **new_te,
5120 struct got_tree_entry *te, struct got_commitable *ct)
5122 const struct got_error *err = NULL;
5124 *new_te = NULL;
5126 err = got_object_tree_entry_dup(new_te, te);
5127 if (err)
5128 goto done;
5130 (*new_te)->mode = get_ct_file_mode(ct);
5132 if (ct->staged_status == GOT_STATUS_MODIFY)
5133 memcpy(&(*new_te)->id, ct->staged_blob_id,
5134 sizeof((*new_te)->id));
5135 else
5136 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
5137 done:
5138 if (err && *new_te) {
5139 free(*new_te);
5140 *new_te = NULL;
5142 return err;
5145 static const struct got_error *
5146 alloc_added_blob_tree_entry(struct got_tree_entry **new_te,
5147 struct got_commitable *ct)
5149 const struct got_error *err = NULL;
5150 char *ct_name = NULL;
5152 *new_te = NULL;
5154 *new_te = calloc(1, sizeof(**new_te));
5155 if (*new_te == NULL)
5156 return got_error_from_errno("calloc");
5158 err = got_path_basename(&ct_name, ct->path);
5159 if (err)
5160 goto done;
5161 if (strlcpy((*new_te)->name, ct_name, sizeof((*new_te)->name)) >=
5162 sizeof((*new_te)->name)) {
5163 err = got_error(GOT_ERR_NO_SPACE);
5164 goto done;
5167 (*new_te)->mode = get_ct_file_mode(ct);
5169 if (ct->staged_status == GOT_STATUS_ADD)
5170 memcpy(&(*new_te)->id, ct->staged_blob_id,
5171 sizeof((*new_te)->id));
5172 else
5173 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
5174 done:
5175 free(ct_name);
5176 if (err && *new_te) {
5177 free(*new_te);
5178 *new_te = NULL;
5180 return err;
5183 static const struct got_error *
5184 insert_tree_entry(struct got_tree_entry *new_te,
5185 struct got_pathlist_head *paths)
5187 const struct got_error *err = NULL;
5188 struct got_pathlist_entry *new_pe;
5190 err = got_pathlist_insert(&new_pe, paths, new_te->name, new_te);
5191 if (err)
5192 return err;
5193 if (new_pe == NULL)
5194 return got_error(GOT_ERR_TREE_DUP_ENTRY);
5195 return NULL;
5198 static const struct got_error *
5199 report_ct_status(struct got_commitable *ct,
5200 got_worktree_status_cb status_cb, void *status_arg)
5202 const char *ct_path = ct->path;
5203 unsigned char status;
5205 while (ct_path[0] == '/')
5206 ct_path++;
5208 if (ct->staged_status != GOT_STATUS_NO_CHANGE)
5209 status = ct->staged_status;
5210 else
5211 status = ct->status;
5213 return (*status_cb)(status_arg, status, GOT_STATUS_NO_CHANGE,
5214 ct_path, ct->blob_id, NULL, NULL, -1, NULL);
5217 static const struct got_error *
5218 match_modified_subtree(int *modified, struct got_tree_entry *te,
5219 const char *base_tree_path, struct got_pathlist_head *commitable_paths)
5221 const struct got_error *err = NULL;
5222 struct got_pathlist_entry *pe;
5223 char *te_path;
5225 *modified = 0;
5227 if (asprintf(&te_path, "%s%s%s", base_tree_path,
5228 got_path_is_root_dir(base_tree_path) ? "" : "/",
5229 te->name) == -1)
5230 return got_error_from_errno("asprintf");
5232 TAILQ_FOREACH(pe, commitable_paths, entry) {
5233 struct got_commitable *ct = pe->data;
5234 *modified = got_path_is_child(ct->in_repo_path, te_path,
5235 strlen(te_path));
5236 if (*modified)
5237 break;
5240 free(te_path);
5241 return err;
5244 static const struct got_error *
5245 match_deleted_or_modified_ct(struct got_commitable **ctp,
5246 struct got_tree_entry *te, const char *base_tree_path,
5247 struct got_pathlist_head *commitable_paths)
5249 const struct got_error *err = NULL;
5250 struct got_pathlist_entry *pe;
5252 *ctp = NULL;
5254 TAILQ_FOREACH(pe, commitable_paths, entry) {
5255 struct got_commitable *ct = pe->data;
5256 char *ct_name = NULL;
5257 int path_matches;
5259 if (ct->staged_status == GOT_STATUS_NO_CHANGE) {
5260 if (ct->status != GOT_STATUS_MODIFY &&
5261 ct->status != GOT_STATUS_MODE_CHANGE &&
5262 ct->status != GOT_STATUS_DELETE)
5263 continue;
5264 } else {
5265 if (ct->staged_status != GOT_STATUS_MODIFY &&
5266 ct->staged_status != GOT_STATUS_DELETE)
5267 continue;
5270 if (got_object_id_cmp(ct->base_blob_id, &te->id) != 0)
5271 continue;
5273 err = match_ct_parent_path(&path_matches, ct, base_tree_path);
5274 if (err)
5275 return err;
5276 if (!path_matches)
5277 continue;
5279 err = got_path_basename(&ct_name, pe->path);
5280 if (err)
5281 return err;
5283 if (strcmp(te->name, ct_name) != 0) {
5284 free(ct_name);
5285 continue;
5287 free(ct_name);
5289 *ctp = ct;
5290 break;
5293 return err;
5296 static const struct got_error *
5297 make_subtree_for_added_blob(struct got_tree_entry **new_tep,
5298 const char *child_path, const char *path_base_tree,
5299 struct got_pathlist_head *commitable_paths,
5300 got_worktree_status_cb status_cb, void *status_arg,
5301 struct got_repository *repo)
5303 const struct got_error *err = NULL;
5304 struct got_tree_entry *new_te;
5305 char *subtree_path;
5306 struct got_object_id *id = NULL;
5307 int nentries;
5309 *new_tep = NULL;
5311 if (asprintf(&subtree_path, "%s%s%s", path_base_tree,
5312 got_path_is_root_dir(path_base_tree) ? "" : "/",
5313 child_path) == -1)
5314 return got_error_from_errno("asprintf");
5316 new_te = calloc(1, sizeof(*new_te));
5317 if (new_te == NULL)
5318 return got_error_from_errno("calloc");
5319 new_te->mode = S_IFDIR;
5321 if (strlcpy(new_te->name, child_path, sizeof(new_te->name)) >=
5322 sizeof(new_te->name)) {
5323 err = got_error(GOT_ERR_NO_SPACE);
5324 goto done;
5326 err = write_tree(&id, &nentries, NULL, subtree_path,
5327 commitable_paths, status_cb, status_arg, repo);
5328 if (err) {
5329 free(new_te);
5330 goto done;
5332 memcpy(&new_te->id, id, sizeof(new_te->id));
5333 done:
5334 free(id);
5335 free(subtree_path);
5336 if (err == NULL)
5337 *new_tep = new_te;
5338 return err;
5341 static const struct got_error *
5342 write_tree(struct got_object_id **new_tree_id, int *nentries,
5343 struct got_tree_object *base_tree, const char *path_base_tree,
5344 struct got_pathlist_head *commitable_paths,
5345 got_worktree_status_cb status_cb, void *status_arg,
5346 struct got_repository *repo)
5348 const struct got_error *err = NULL;
5349 struct got_pathlist_head paths;
5350 struct got_tree_entry *te, *new_te = NULL;
5351 struct got_pathlist_entry *pe;
5353 TAILQ_INIT(&paths);
5354 *nentries = 0;
5356 /* Insert, and recurse into, newly added entries first. */
5357 TAILQ_FOREACH(pe, commitable_paths, entry) {
5358 struct got_commitable *ct = pe->data;
5359 char *child_path = NULL, *slash;
5361 if ((ct->status != GOT_STATUS_ADD &&
5362 ct->staged_status != GOT_STATUS_ADD) ||
5363 (ct->flags & GOT_COMMITABLE_ADDED))
5364 continue;
5366 if (!got_path_is_child(ct->in_repo_path, path_base_tree,
5367 strlen(path_base_tree)))
5368 continue;
5370 err = got_path_skip_common_ancestor(&child_path, path_base_tree,
5371 ct->in_repo_path);
5372 if (err)
5373 goto done;
5375 slash = strchr(child_path, '/');
5376 if (slash == NULL) {
5377 err = alloc_added_blob_tree_entry(&new_te, ct);
5378 if (err)
5379 goto done;
5380 err = report_ct_status(ct, status_cb, status_arg);
5381 if (err)
5382 goto done;
5383 ct->flags |= GOT_COMMITABLE_ADDED;
5384 err = insert_tree_entry(new_te, &paths);
5385 if (err)
5386 goto done;
5387 (*nentries)++;
5388 } else {
5389 *slash = '\0'; /* trim trailing path components */
5390 if (base_tree == NULL ||
5391 got_object_tree_find_entry(base_tree, child_path)
5392 == NULL) {
5393 err = make_subtree_for_added_blob(&new_te,
5394 child_path, path_base_tree,
5395 commitable_paths, status_cb, status_arg,
5396 repo);
5397 if (err)
5398 goto done;
5399 err = insert_tree_entry(new_te, &paths);
5400 if (err)
5401 goto done;
5402 (*nentries)++;
5407 if (base_tree) {
5408 int i, nbase_entries;
5409 /* Handle modified and deleted entries. */
5410 nbase_entries = got_object_tree_get_nentries(base_tree);
5411 for (i = 0; i < nbase_entries; i++) {
5412 struct got_commitable *ct = NULL;
5414 te = got_object_tree_get_entry(base_tree, i);
5415 if (got_object_tree_entry_is_submodule(te)) {
5416 /* Entry is a submodule; just copy it. */
5417 err = got_object_tree_entry_dup(&new_te, te);
5418 if (err)
5419 goto done;
5420 err = insert_tree_entry(new_te, &paths);
5421 if (err)
5422 goto done;
5423 (*nentries)++;
5424 continue;
5427 if (S_ISDIR(te->mode)) {
5428 int modified;
5429 err = got_object_tree_entry_dup(&new_te, te);
5430 if (err)
5431 goto done;
5432 err = match_modified_subtree(&modified, te,
5433 path_base_tree, commitable_paths);
5434 if (err)
5435 goto done;
5436 /* Avoid recursion into unmodified subtrees. */
5437 if (modified) {
5438 struct got_object_id *new_id;
5439 int nsubentries;
5440 err = write_subtree(&new_id,
5441 &nsubentries, te,
5442 path_base_tree, commitable_paths,
5443 status_cb, status_arg, repo);
5444 if (err)
5445 goto done;
5446 if (nsubentries == 0) {
5447 /* All entries were deleted. */
5448 free(new_id);
5449 continue;
5451 memcpy(&new_te->id, new_id,
5452 sizeof(new_te->id));
5453 free(new_id);
5455 err = insert_tree_entry(new_te, &paths);
5456 if (err)
5457 goto done;
5458 (*nentries)++;
5459 continue;
5462 err = match_deleted_or_modified_ct(&ct, te,
5463 path_base_tree, commitable_paths);
5464 if (err)
5465 goto done;
5466 if (ct) {
5467 /* NB: Deleted entries get dropped here. */
5468 if (ct->status == GOT_STATUS_MODIFY ||
5469 ct->status == GOT_STATUS_MODE_CHANGE ||
5470 ct->staged_status == GOT_STATUS_MODIFY) {
5471 err = alloc_modified_blob_tree_entry(
5472 &new_te, te, ct);
5473 if (err)
5474 goto done;
5475 err = insert_tree_entry(new_te, &paths);
5476 if (err)
5477 goto done;
5478 (*nentries)++;
5480 err = report_ct_status(ct, status_cb,
5481 status_arg);
5482 if (err)
5483 goto done;
5484 } else {
5485 /* Entry is unchanged; just copy it. */
5486 err = got_object_tree_entry_dup(&new_te, te);
5487 if (err)
5488 goto done;
5489 err = insert_tree_entry(new_te, &paths);
5490 if (err)
5491 goto done;
5492 (*nentries)++;
5497 /* Write new list of entries; deleted entries have been dropped. */
5498 err = got_object_tree_create(new_tree_id, &paths, *nentries, repo);
5499 done:
5500 got_pathlist_free(&paths);
5501 return err;
5504 static const struct got_error *
5505 update_fileindex_after_commit(struct got_worktree *worktree,
5506 struct got_pathlist_head *commitable_paths,
5507 struct got_object_id *new_base_commit_id,
5508 struct got_fileindex *fileindex, int have_staged_files)
5510 const struct got_error *err = NULL;
5511 struct got_pathlist_entry *pe;
5512 char *relpath = NULL;
5514 TAILQ_FOREACH(pe, commitable_paths, entry) {
5515 struct got_fileindex_entry *ie;
5516 struct got_commitable *ct = pe->data;
5518 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
5520 err = got_path_skip_common_ancestor(&relpath,
5521 worktree->root_path, ct->ondisk_path);
5522 if (err)
5523 goto done;
5525 if (ie) {
5526 if (ct->status == GOT_STATUS_DELETE ||
5527 ct->staged_status == GOT_STATUS_DELETE) {
5528 got_fileindex_entry_remove(fileindex, ie);
5529 } else if (ct->staged_status == GOT_STATUS_ADD ||
5530 ct->staged_status == GOT_STATUS_MODIFY) {
5531 got_fileindex_entry_stage_set(ie,
5532 GOT_FILEIDX_STAGE_NONE);
5533 got_fileindex_entry_staged_filetype_set(ie, 0);
5535 err = got_fileindex_entry_update(ie,
5536 worktree->root_fd, relpath,
5537 ct->staged_blob_id->sha1,
5538 new_base_commit_id->sha1,
5539 !have_staged_files);
5540 } else
5541 err = got_fileindex_entry_update(ie,
5542 worktree->root_fd, relpath,
5543 ct->blob_id->sha1,
5544 new_base_commit_id->sha1,
5545 !have_staged_files);
5546 } else {
5547 err = got_fileindex_entry_alloc(&ie, pe->path);
5548 if (err)
5549 goto done;
5550 err = got_fileindex_entry_update(ie,
5551 worktree->root_fd, relpath, ct->blob_id->sha1,
5552 new_base_commit_id->sha1, 1);
5553 if (err) {
5554 got_fileindex_entry_free(ie);
5555 goto done;
5557 err = got_fileindex_entry_add(fileindex, ie);
5558 if (err) {
5559 got_fileindex_entry_free(ie);
5560 goto done;
5563 free(relpath);
5564 relpath = NULL;
5566 done:
5567 free(relpath);
5568 return err;
5572 static const struct got_error *
5573 check_out_of_date(const char *in_repo_path, unsigned char status,
5574 unsigned char staged_status, struct got_object_id *base_blob_id,
5575 struct got_object_id *base_commit_id,
5576 struct got_object_id *head_commit_id, struct got_repository *repo,
5577 int ood_errcode)
5579 const struct got_error *err = NULL;
5580 struct got_object_id *id = NULL;
5582 if (status != GOT_STATUS_ADD && staged_status != GOT_STATUS_ADD) {
5583 /* Trivial case: base commit == head commit */
5584 if (got_object_id_cmp(base_commit_id, head_commit_id) == 0)
5585 return NULL;
5587 * Ensure file content which local changes were based
5588 * on matches file content in the branch head.
5590 err = got_object_id_by_path(&id, repo, head_commit_id,
5591 in_repo_path);
5592 if (err) {
5593 if (err->code == GOT_ERR_NO_TREE_ENTRY)
5594 err = got_error(ood_errcode);
5595 goto done;
5596 } else if (got_object_id_cmp(id, base_blob_id) != 0)
5597 err = got_error(ood_errcode);
5598 } else {
5599 /* Require that added files don't exist in the branch head. */
5600 err = got_object_id_by_path(&id, repo, head_commit_id,
5601 in_repo_path);
5602 if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
5603 goto done;
5604 err = id ? got_error(ood_errcode) : NULL;
5606 done:
5607 free(id);
5608 return err;
5611 const struct got_error *
5612 commit_worktree(struct got_object_id **new_commit_id,
5613 struct got_pathlist_head *commitable_paths,
5614 struct got_object_id *head_commit_id,
5615 struct got_object_id *parent_id2,
5616 struct got_worktree *worktree,
5617 const char *author, const char *committer,
5618 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
5619 got_worktree_status_cb status_cb, void *status_arg,
5620 struct got_repository *repo)
5622 const struct got_error *err = NULL, *unlockerr = NULL;
5623 struct got_pathlist_entry *pe;
5624 const char *head_ref_name = NULL;
5625 struct got_commit_object *head_commit = NULL;
5626 struct got_reference *head_ref2 = NULL;
5627 struct got_object_id *head_commit_id2 = NULL;
5628 struct got_tree_object *head_tree = NULL;
5629 struct got_object_id *new_tree_id = NULL;
5630 int nentries, nparents = 0;
5631 struct got_object_id_queue parent_ids;
5632 struct got_object_qid *pid = NULL;
5633 char *logmsg = NULL;
5635 *new_commit_id = NULL;
5637 STAILQ_INIT(&parent_ids);
5639 err = got_object_open_as_commit(&head_commit, repo, head_commit_id);
5640 if (err)
5641 goto done;
5643 err = got_object_open_as_tree(&head_tree, repo, head_commit->tree_id);
5644 if (err)
5645 goto done;
5647 if (commit_msg_cb != NULL) {
5648 err = commit_msg_cb(commitable_paths, &logmsg, commit_arg);
5649 if (err)
5650 goto done;
5653 if (logmsg == NULL || strlen(logmsg) == 0) {
5654 err = got_error(GOT_ERR_COMMIT_MSG_EMPTY);
5655 goto done;
5658 /* Create blobs from added and modified files and record their IDs. */
5659 TAILQ_FOREACH(pe, commitable_paths, entry) {
5660 struct got_commitable *ct = pe->data;
5661 char *ondisk_path;
5663 /* Blobs for staged files already exist. */
5664 if (ct->staged_status == GOT_STATUS_ADD ||
5665 ct->staged_status == GOT_STATUS_MODIFY)
5666 continue;
5668 if (ct->status != GOT_STATUS_ADD &&
5669 ct->status != GOT_STATUS_MODIFY &&
5670 ct->status != GOT_STATUS_MODE_CHANGE)
5671 continue;
5673 if (asprintf(&ondisk_path, "%s/%s",
5674 worktree->root_path, pe->path) == -1) {
5675 err = got_error_from_errno("asprintf");
5676 goto done;
5678 err = got_object_blob_create(&ct->blob_id, ondisk_path, repo);
5679 free(ondisk_path);
5680 if (err)
5681 goto done;
5684 /* Recursively write new tree objects. */
5685 err = write_tree(&new_tree_id, &nentries, head_tree, "/",
5686 commitable_paths, status_cb, status_arg, repo);
5687 if (err)
5688 goto done;
5690 err = got_object_qid_alloc(&pid, worktree->base_commit_id);
5691 if (err)
5692 goto done;
5693 STAILQ_INSERT_TAIL(&parent_ids, pid, entry);
5694 nparents++;
5695 if (parent_id2) {
5696 err = got_object_qid_alloc(&pid, parent_id2);
5697 if (err)
5698 goto done;
5699 STAILQ_INSERT_TAIL(&parent_ids, pid, entry);
5700 nparents++;
5702 err = got_object_commit_create(new_commit_id, new_tree_id, &parent_ids,
5703 nparents, author, time(NULL), committer, time(NULL), logmsg, repo);
5704 if (logmsg != NULL)
5705 free(logmsg);
5706 if (err)
5707 goto done;
5709 /* Check if a concurrent commit to our branch has occurred. */
5710 head_ref_name = got_worktree_get_head_ref_name(worktree);
5711 if (head_ref_name == NULL) {
5712 err = got_error_from_errno("got_worktree_get_head_ref_name");
5713 goto done;
5715 /* Lock the reference here to prevent concurrent modification. */
5716 err = got_ref_open(&head_ref2, repo, head_ref_name, 1);
5717 if (err)
5718 goto done;
5719 err = got_ref_resolve(&head_commit_id2, repo, head_ref2);
5720 if (err)
5721 goto done;
5722 if (got_object_id_cmp(head_commit_id, head_commit_id2) != 0) {
5723 err = got_error(GOT_ERR_COMMIT_HEAD_CHANGED);
5724 goto done;
5726 /* Update branch head in repository. */
5727 err = got_ref_change_ref(head_ref2, *new_commit_id);
5728 if (err)
5729 goto done;
5730 err = got_ref_write(head_ref2, repo);
5731 if (err)
5732 goto done;
5734 err = got_worktree_set_base_commit_id(worktree, repo, *new_commit_id);
5735 if (err)
5736 goto done;
5738 err = ref_base_commit(worktree, repo);
5739 if (err)
5740 goto done;
5741 done:
5742 got_object_id_queue_free(&parent_ids);
5743 if (head_tree)
5744 got_object_tree_close(head_tree);
5745 if (head_commit)
5746 got_object_commit_close(head_commit);
5747 free(head_commit_id2);
5748 if (head_ref2) {
5749 unlockerr = got_ref_unlock(head_ref2);
5750 if (unlockerr && err == NULL)
5751 err = unlockerr;
5752 got_ref_close(head_ref2);
5754 return err;
5757 static const struct got_error *
5758 check_path_is_commitable(const char *path,
5759 struct got_pathlist_head *commitable_paths)
5761 struct got_pathlist_entry *cpe = NULL;
5762 size_t path_len = strlen(path);
5764 TAILQ_FOREACH(cpe, commitable_paths, entry) {
5765 struct got_commitable *ct = cpe->data;
5766 const char *ct_path = ct->path;
5768 while (ct_path[0] == '/')
5769 ct_path++;
5771 if (strcmp(path, ct_path) == 0 ||
5772 got_path_is_child(ct_path, path, path_len))
5773 break;
5776 if (cpe == NULL)
5777 return got_error_path(path, GOT_ERR_BAD_PATH);
5779 return NULL;
5782 static const struct got_error *
5783 check_staged_file(void *arg, struct got_fileindex_entry *ie)
5785 int *have_staged_files = arg;
5787 if (got_fileindex_entry_stage_get(ie) != GOT_FILEIDX_STAGE_NONE) {
5788 *have_staged_files = 1;
5789 return got_error(GOT_ERR_CANCELLED);
5792 return NULL;
5795 static const struct got_error *
5796 check_non_staged_files(struct got_fileindex *fileindex,
5797 struct got_pathlist_head *paths)
5799 struct got_pathlist_entry *pe;
5800 struct got_fileindex_entry *ie;
5802 TAILQ_FOREACH(pe, paths, entry) {
5803 if (pe->path[0] == '\0')
5804 continue;
5805 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
5806 if (ie == NULL)
5807 return got_error_path(pe->path, GOT_ERR_BAD_PATH);
5808 if (got_fileindex_entry_stage_get(ie) == GOT_FILEIDX_STAGE_NONE)
5809 return got_error_path(pe->path,
5810 GOT_ERR_FILE_NOT_STAGED);
5813 return NULL;
5816 const struct got_error *
5817 got_worktree_commit(struct got_object_id **new_commit_id,
5818 struct got_worktree *worktree, struct got_pathlist_head *paths,
5819 const char *author, const char *committer, int allow_bad_symlinks,
5820 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
5821 got_worktree_status_cb status_cb, void *status_arg,
5822 struct got_repository *repo)
5824 const struct got_error *err = NULL, *unlockerr = NULL, *sync_err;
5825 struct got_fileindex *fileindex = NULL;
5826 char *fileindex_path = NULL;
5827 struct got_pathlist_head commitable_paths;
5828 struct collect_commitables_arg cc_arg;
5829 struct got_pathlist_entry *pe;
5830 struct got_reference *head_ref = NULL;
5831 struct got_object_id *head_commit_id = NULL;
5832 int have_staged_files = 0;
5834 *new_commit_id = NULL;
5836 TAILQ_INIT(&commitable_paths);
5838 err = lock_worktree(worktree, LOCK_EX);
5839 if (err)
5840 goto done;
5842 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
5843 if (err)
5844 goto done;
5846 err = got_ref_resolve(&head_commit_id, repo, head_ref);
5847 if (err)
5848 goto done;
5850 err = open_fileindex(&fileindex, &fileindex_path, worktree);
5851 if (err)
5852 goto done;
5854 err = got_fileindex_for_each_entry_safe(fileindex, check_staged_file,
5855 &have_staged_files);
5856 if (err && err->code != GOT_ERR_CANCELLED)
5857 goto done;
5858 if (have_staged_files) {
5859 err = check_non_staged_files(fileindex, paths);
5860 if (err)
5861 goto done;
5864 cc_arg.commitable_paths = &commitable_paths;
5865 cc_arg.worktree = worktree;
5866 cc_arg.fileindex = fileindex;
5867 cc_arg.repo = repo;
5868 cc_arg.have_staged_files = have_staged_files;
5869 cc_arg.allow_bad_symlinks = allow_bad_symlinks;
5870 TAILQ_FOREACH(pe, paths, entry) {
5871 err = worktree_status(worktree, pe->path, fileindex, repo,
5872 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
5873 if (err)
5874 goto done;
5877 if (TAILQ_EMPTY(&commitable_paths)) {
5878 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
5879 goto done;
5882 TAILQ_FOREACH(pe, paths, entry) {
5883 err = check_path_is_commitable(pe->path, &commitable_paths);
5884 if (err)
5885 goto done;
5888 TAILQ_FOREACH(pe, &commitable_paths, entry) {
5889 struct got_commitable *ct = pe->data;
5890 const char *ct_path = ct->in_repo_path;
5892 while (ct_path[0] == '/')
5893 ct_path++;
5894 err = check_out_of_date(ct_path, ct->status,
5895 ct->staged_status, ct->base_blob_id, ct->base_commit_id,
5896 head_commit_id, repo, GOT_ERR_COMMIT_OUT_OF_DATE);
5897 if (err)
5898 goto done;
5902 err = commit_worktree(new_commit_id, &commitable_paths,
5903 head_commit_id, NULL, worktree, author, committer,
5904 commit_msg_cb, commit_arg, status_cb, status_arg, repo);
5905 if (err)
5906 goto done;
5908 err = update_fileindex_after_commit(worktree, &commitable_paths,
5909 *new_commit_id, fileindex, have_staged_files);
5910 sync_err = sync_fileindex(fileindex, fileindex_path);
5911 if (sync_err && err == NULL)
5912 err = sync_err;
5913 done:
5914 if (fileindex)
5915 got_fileindex_free(fileindex);
5916 free(fileindex_path);
5917 unlockerr = lock_worktree(worktree, LOCK_SH);
5918 if (unlockerr && err == NULL)
5919 err = unlockerr;
5920 TAILQ_FOREACH(pe, &commitable_paths, entry) {
5921 struct got_commitable *ct = pe->data;
5922 free_commitable(ct);
5924 got_pathlist_free(&commitable_paths);
5925 return err;
5928 const char *
5929 got_commitable_get_path(struct got_commitable *ct)
5931 return ct->path;
5934 unsigned int
5935 got_commitable_get_status(struct got_commitable *ct)
5937 return ct->status;
5940 struct check_rebase_ok_arg {
5941 struct got_worktree *worktree;
5942 struct got_repository *repo;
5945 static const struct got_error *
5946 check_rebase_ok(void *arg, struct got_fileindex_entry *ie)
5948 const struct got_error *err = NULL;
5949 struct check_rebase_ok_arg *a = arg;
5950 unsigned char status;
5951 struct stat sb;
5952 char *ondisk_path;
5954 /* Reject rebase of a work tree with mixed base commits. */
5955 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
5956 SHA1_DIGEST_LENGTH))
5957 return got_error(GOT_ERR_MIXED_COMMITS);
5959 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
5960 == -1)
5961 return got_error_from_errno("asprintf");
5963 /* Reject rebase of a work tree with modified or staged files. */
5964 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
5965 free(ondisk_path);
5966 if (err)
5967 return err;
5969 if (status != GOT_STATUS_NO_CHANGE)
5970 return got_error(GOT_ERR_MODIFIED);
5971 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
5972 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
5974 return NULL;
5977 const struct got_error *
5978 got_worktree_rebase_prepare(struct got_reference **new_base_branch_ref,
5979 struct got_reference **tmp_branch, struct got_fileindex **fileindex,
5980 struct got_worktree *worktree, struct got_reference *branch,
5981 struct got_repository *repo)
5983 const struct got_error *err = NULL;
5984 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
5985 char *branch_ref_name = NULL;
5986 char *fileindex_path = NULL;
5987 struct check_rebase_ok_arg ok_arg;
5988 struct got_reference *wt_branch = NULL, *branch_ref = NULL;
5989 struct got_object_id *wt_branch_tip = NULL;
5991 *new_base_branch_ref = NULL;
5992 *tmp_branch = NULL;
5993 *fileindex = NULL;
5995 err = lock_worktree(worktree, LOCK_EX);
5996 if (err)
5997 return err;
5999 err = open_fileindex(fileindex, &fileindex_path, worktree);
6000 if (err)
6001 goto done;
6003 ok_arg.worktree = worktree;
6004 ok_arg.repo = repo;
6005 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
6006 &ok_arg);
6007 if (err)
6008 goto done;
6010 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6011 if (err)
6012 goto done;
6014 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
6015 if (err)
6016 goto done;
6018 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
6019 if (err)
6020 goto done;
6022 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
6023 0);
6024 if (err)
6025 goto done;
6027 err = got_ref_resolve(&wt_branch_tip, repo, wt_branch);
6028 if (err)
6029 goto done;
6030 if (got_object_id_cmp(worktree->base_commit_id, wt_branch_tip) != 0) {
6031 err = got_error(GOT_ERR_REBASE_OUT_OF_DATE);
6032 goto done;
6035 err = got_ref_alloc_symref(new_base_branch_ref,
6036 new_base_branch_ref_name, wt_branch);
6037 if (err)
6038 goto done;
6039 err = got_ref_write(*new_base_branch_ref, repo);
6040 if (err)
6041 goto done;
6043 /* TODO Lock original branch's ref while rebasing? */
6045 err = got_ref_alloc_symref(&branch_ref, branch_ref_name, branch);
6046 if (err)
6047 goto done;
6049 err = got_ref_write(branch_ref, repo);
6050 if (err)
6051 goto done;
6053 err = got_ref_alloc(tmp_branch, tmp_branch_name,
6054 worktree->base_commit_id);
6055 if (err)
6056 goto done;
6057 err = got_ref_write(*tmp_branch, repo);
6058 if (err)
6059 goto done;
6061 err = got_worktree_set_head_ref(worktree, *tmp_branch);
6062 if (err)
6063 goto done;
6064 done:
6065 free(fileindex_path);
6066 free(tmp_branch_name);
6067 free(new_base_branch_ref_name);
6068 free(branch_ref_name);
6069 if (branch_ref)
6070 got_ref_close(branch_ref);
6071 if (wt_branch)
6072 got_ref_close(wt_branch);
6073 free(wt_branch_tip);
6074 if (err) {
6075 if (*new_base_branch_ref) {
6076 got_ref_close(*new_base_branch_ref);
6077 *new_base_branch_ref = NULL;
6079 if (*tmp_branch) {
6080 got_ref_close(*tmp_branch);
6081 *tmp_branch = NULL;
6083 if (*fileindex) {
6084 got_fileindex_free(*fileindex);
6085 *fileindex = NULL;
6087 lock_worktree(worktree, LOCK_SH);
6089 return err;
6092 const struct got_error *
6093 got_worktree_rebase_continue(struct got_object_id **commit_id,
6094 struct got_reference **new_base_branch, struct got_reference **tmp_branch,
6095 struct got_reference **branch, struct got_fileindex **fileindex,
6096 struct got_worktree *worktree, struct got_repository *repo)
6098 const struct got_error *err;
6099 char *commit_ref_name = NULL, *new_base_branch_ref_name = NULL;
6100 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
6101 struct got_reference *commit_ref = NULL, *branch_ref = NULL;
6102 char *fileindex_path = NULL;
6103 int have_staged_files = 0;
6105 *commit_id = NULL;
6106 *new_base_branch = NULL;
6107 *tmp_branch = NULL;
6108 *branch = NULL;
6109 *fileindex = NULL;
6111 err = lock_worktree(worktree, LOCK_EX);
6112 if (err)
6113 return err;
6115 err = open_fileindex(fileindex, &fileindex_path, worktree);
6116 if (err)
6117 goto done;
6119 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
6120 &have_staged_files);
6121 if (err && err->code != GOT_ERR_CANCELLED)
6122 goto done;
6123 if (have_staged_files) {
6124 err = got_error(GOT_ERR_STAGED_PATHS);
6125 goto done;
6128 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6129 if (err)
6130 goto done;
6132 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
6133 if (err)
6134 goto done;
6136 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6137 if (err)
6138 goto done;
6140 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
6141 if (err)
6142 goto done;
6144 err = got_ref_open(&branch_ref, repo, branch_ref_name, 0);
6145 if (err)
6146 goto done;
6148 err = got_ref_open(branch, repo,
6149 got_ref_get_symref_target(branch_ref), 0);
6150 if (err)
6151 goto done;
6153 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6154 if (err)
6155 goto done;
6157 err = got_ref_resolve(commit_id, repo, commit_ref);
6158 if (err)
6159 goto done;
6161 err = got_ref_open(new_base_branch, repo,
6162 new_base_branch_ref_name, 0);
6163 if (err)
6164 goto done;
6166 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
6167 if (err)
6168 goto done;
6169 done:
6170 free(commit_ref_name);
6171 free(branch_ref_name);
6172 free(fileindex_path);
6173 if (commit_ref)
6174 got_ref_close(commit_ref);
6175 if (branch_ref)
6176 got_ref_close(branch_ref);
6177 if (err) {
6178 free(*commit_id);
6179 *commit_id = NULL;
6180 if (*tmp_branch) {
6181 got_ref_close(*tmp_branch);
6182 *tmp_branch = NULL;
6184 if (*new_base_branch) {
6185 got_ref_close(*new_base_branch);
6186 *new_base_branch = NULL;
6188 if (*branch) {
6189 got_ref_close(*branch);
6190 *branch = NULL;
6192 if (*fileindex) {
6193 got_fileindex_free(*fileindex);
6194 *fileindex = NULL;
6196 lock_worktree(worktree, LOCK_SH);
6198 return err;
6201 const struct got_error *
6202 got_worktree_rebase_in_progress(int *in_progress, struct got_worktree *worktree)
6204 const struct got_error *err;
6205 char *tmp_branch_name = NULL;
6207 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6208 if (err)
6209 return err;
6211 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
6212 free(tmp_branch_name);
6213 return NULL;
6216 static const struct got_error *
6217 collect_rebase_commit_msg(struct got_pathlist_head *commitable_paths,
6218 char **logmsg, void *arg)
6220 *logmsg = arg;
6221 return NULL;
6224 static const struct got_error *
6225 rebase_status(void *arg, unsigned char status, unsigned char staged_status,
6226 const char *path, struct got_object_id *blob_id,
6227 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
6228 int dirfd, const char *de_name)
6230 return NULL;
6233 struct collect_merged_paths_arg {
6234 got_worktree_checkout_cb progress_cb;
6235 void *progress_arg;
6236 struct got_pathlist_head *merged_paths;
6239 static const struct got_error *
6240 collect_merged_paths(void *arg, unsigned char status, const char *path)
6242 const struct got_error *err;
6243 struct collect_merged_paths_arg *a = arg;
6244 char *p;
6245 struct got_pathlist_entry *new;
6247 err = (*a->progress_cb)(a->progress_arg, status, path);
6248 if (err)
6249 return err;
6251 if (status != GOT_STATUS_MERGE &&
6252 status != GOT_STATUS_ADD &&
6253 status != GOT_STATUS_DELETE &&
6254 status != GOT_STATUS_CONFLICT)
6255 return NULL;
6257 p = strdup(path);
6258 if (p == NULL)
6259 return got_error_from_errno("strdup");
6261 err = got_pathlist_insert(&new, a->merged_paths, p, NULL);
6262 if (err || new == NULL)
6263 free(p);
6264 return err;
6267 void
6268 got_worktree_rebase_pathlist_free(struct got_pathlist_head *merged_paths)
6270 struct got_pathlist_entry *pe;
6272 TAILQ_FOREACH(pe, merged_paths, entry)
6273 free((char *)pe->path);
6275 got_pathlist_free(merged_paths);
6278 static const struct got_error *
6279 store_commit_id(const char *commit_ref_name, struct got_object_id *commit_id,
6280 int is_rebase, struct got_repository *repo)
6282 const struct got_error *err;
6283 struct got_reference *commit_ref = NULL;
6285 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6286 if (err) {
6287 if (err->code != GOT_ERR_NOT_REF)
6288 goto done;
6289 err = got_ref_alloc(&commit_ref, commit_ref_name, commit_id);
6290 if (err)
6291 goto done;
6292 err = got_ref_write(commit_ref, repo);
6293 if (err)
6294 goto done;
6295 } else if (is_rebase) {
6296 struct got_object_id *stored_id;
6297 int cmp;
6299 err = got_ref_resolve(&stored_id, repo, commit_ref);
6300 if (err)
6301 goto done;
6302 cmp = got_object_id_cmp(commit_id, stored_id);
6303 free(stored_id);
6304 if (cmp != 0) {
6305 err = got_error(GOT_ERR_REBASE_COMMITID);
6306 goto done;
6309 done:
6310 if (commit_ref)
6311 got_ref_close(commit_ref);
6312 return err;
6315 static const struct got_error *
6316 rebase_merge_files(struct got_pathlist_head *merged_paths,
6317 const char *commit_ref_name, struct got_worktree *worktree,
6318 struct got_fileindex *fileindex, struct got_object_id *parent_commit_id,
6319 struct got_object_id *commit_id, struct got_repository *repo,
6320 got_worktree_checkout_cb progress_cb, void *progress_arg,
6321 got_cancel_cb cancel_cb, void *cancel_arg)
6323 const struct got_error *err;
6324 struct got_reference *commit_ref = NULL;
6325 struct collect_merged_paths_arg cmp_arg;
6326 char *fileindex_path;
6328 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6330 err = get_fileindex_path(&fileindex_path, worktree);
6331 if (err)
6332 return err;
6334 cmp_arg.progress_cb = progress_cb;
6335 cmp_arg.progress_arg = progress_arg;
6336 cmp_arg.merged_paths = merged_paths;
6337 err = merge_files(worktree, fileindex, fileindex_path,
6338 parent_commit_id, commit_id, repo, collect_merged_paths,
6339 &cmp_arg, cancel_cb, cancel_arg);
6340 if (commit_ref)
6341 got_ref_close(commit_ref);
6342 return err;
6345 const struct got_error *
6346 got_worktree_rebase_merge_files(struct got_pathlist_head *merged_paths,
6347 struct got_worktree *worktree, struct got_fileindex *fileindex,
6348 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
6349 struct got_repository *repo,
6350 got_worktree_checkout_cb progress_cb, void *progress_arg,
6351 got_cancel_cb cancel_cb, void *cancel_arg)
6353 const struct got_error *err;
6354 char *commit_ref_name;
6356 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6357 if (err)
6358 return err;
6360 err = store_commit_id(commit_ref_name, commit_id, 1, repo);
6361 if (err)
6362 goto done;
6364 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
6365 fileindex, parent_commit_id, commit_id, repo, progress_cb,
6366 progress_arg, cancel_cb, cancel_arg);
6367 done:
6368 free(commit_ref_name);
6369 return err;
6372 const struct got_error *
6373 got_worktree_histedit_merge_files(struct got_pathlist_head *merged_paths,
6374 struct got_worktree *worktree, struct got_fileindex *fileindex,
6375 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
6376 struct got_repository *repo,
6377 got_worktree_checkout_cb progress_cb, void *progress_arg,
6378 got_cancel_cb cancel_cb, void *cancel_arg)
6380 const struct got_error *err;
6381 char *commit_ref_name;
6383 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6384 if (err)
6385 return err;
6387 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
6388 if (err)
6389 goto done;
6391 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
6392 fileindex, parent_commit_id, commit_id, repo, progress_cb,
6393 progress_arg, cancel_cb, cancel_arg);
6394 done:
6395 free(commit_ref_name);
6396 return err;
6399 static const struct got_error *
6400 rebase_commit(struct got_object_id **new_commit_id,
6401 struct got_pathlist_head *merged_paths, struct got_reference *commit_ref,
6402 struct got_worktree *worktree, struct got_fileindex *fileindex,
6403 struct got_reference *tmp_branch, struct got_commit_object *orig_commit,
6404 const char *new_logmsg, struct got_repository *repo)
6406 const struct got_error *err, *sync_err;
6407 struct got_pathlist_head commitable_paths;
6408 struct collect_commitables_arg cc_arg;
6409 char *fileindex_path = NULL;
6410 struct got_reference *head_ref = NULL;
6411 struct got_object_id *head_commit_id = NULL;
6412 char *logmsg = NULL;
6414 TAILQ_INIT(&commitable_paths);
6415 *new_commit_id = NULL;
6417 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6419 err = get_fileindex_path(&fileindex_path, worktree);
6420 if (err)
6421 return err;
6423 cc_arg.commitable_paths = &commitable_paths;
6424 cc_arg.worktree = worktree;
6425 cc_arg.repo = repo;
6426 cc_arg.have_staged_files = 0;
6428 * If possible get the status of individual files directly to
6429 * avoid crawling the entire work tree once per rebased commit.
6431 * Ideally, merged_paths would contain a list of commitables
6432 * we could use so we could skip worktree_status() entirely.
6433 * However, we would then need carefully keep track of cumulative
6434 * effects of operations such as file additions and deletions
6435 * in 'got histedit -f' (folding multiple commits into one),
6436 * and this extra complexity is not really worth it.
6438 if (merged_paths) {
6439 struct got_pathlist_entry *pe;
6440 TAILQ_FOREACH(pe, merged_paths, entry) {
6441 err = worktree_status(worktree, pe->path, fileindex,
6442 repo, collect_commitables, &cc_arg, NULL, NULL, 1,
6443 0);
6444 if (err)
6445 goto done;
6447 } else {
6448 err = worktree_status(worktree, "", fileindex, repo,
6449 collect_commitables, &cc_arg, NULL, NULL, 1, 0);
6450 if (err)
6451 goto done;
6454 if (TAILQ_EMPTY(&commitable_paths)) {
6455 /* No-op change; commit will be elided. */
6456 err = got_ref_delete(commit_ref, repo);
6457 if (err)
6458 goto done;
6459 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
6460 goto done;
6463 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
6464 if (err)
6465 goto done;
6467 err = got_ref_resolve(&head_commit_id, repo, head_ref);
6468 if (err)
6469 goto done;
6471 if (new_logmsg) {
6472 logmsg = strdup(new_logmsg);
6473 if (logmsg == NULL) {
6474 err = got_error_from_errno("strdup");
6475 goto done;
6477 } else {
6478 err = got_object_commit_get_logmsg(&logmsg, orig_commit);
6479 if (err)
6480 goto done;
6483 /* NB: commit_worktree will call free(logmsg) */
6484 err = commit_worktree(new_commit_id, &commitable_paths, head_commit_id,
6485 NULL, worktree, got_object_commit_get_author(orig_commit),
6486 got_object_commit_get_committer(orig_commit),
6487 collect_rebase_commit_msg, logmsg, rebase_status, NULL, repo);
6488 if (err)
6489 goto done;
6491 err = got_ref_change_ref(tmp_branch, *new_commit_id);
6492 if (err)
6493 goto done;
6495 err = got_ref_delete(commit_ref, repo);
6496 if (err)
6497 goto done;
6499 err = update_fileindex_after_commit(worktree, &commitable_paths,
6500 *new_commit_id, fileindex, 0);
6501 sync_err = sync_fileindex(fileindex, fileindex_path);
6502 if (sync_err && err == NULL)
6503 err = sync_err;
6504 done:
6505 free(fileindex_path);
6506 free(head_commit_id);
6507 if (head_ref)
6508 got_ref_close(head_ref);
6509 if (err) {
6510 free(*new_commit_id);
6511 *new_commit_id = NULL;
6513 return err;
6516 const struct got_error *
6517 got_worktree_rebase_commit(struct got_object_id **new_commit_id,
6518 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
6519 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6520 struct got_commit_object *orig_commit,
6521 struct got_object_id *orig_commit_id, struct got_repository *repo)
6523 const struct got_error *err;
6524 char *commit_ref_name;
6525 struct got_reference *commit_ref = NULL;
6526 struct got_object_id *commit_id = NULL;
6528 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6529 if (err)
6530 return err;
6532 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6533 if (err)
6534 goto done;
6535 err = got_ref_resolve(&commit_id, repo, commit_ref);
6536 if (err)
6537 goto done;
6538 if (got_object_id_cmp(commit_id, orig_commit_id) != 0) {
6539 err = got_error(GOT_ERR_REBASE_COMMITID);
6540 goto done;
6543 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
6544 worktree, fileindex, tmp_branch, orig_commit, NULL, repo);
6545 done:
6546 if (commit_ref)
6547 got_ref_close(commit_ref);
6548 free(commit_ref_name);
6549 free(commit_id);
6550 return err;
6553 const struct got_error *
6554 got_worktree_histedit_commit(struct got_object_id **new_commit_id,
6555 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
6556 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6557 struct got_commit_object *orig_commit,
6558 struct got_object_id *orig_commit_id, const char *new_logmsg,
6559 struct got_repository *repo)
6561 const struct got_error *err;
6562 char *commit_ref_name;
6563 struct got_reference *commit_ref = NULL;
6565 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6566 if (err)
6567 return err;
6569 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
6570 if (err)
6571 goto done;
6573 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
6574 worktree, fileindex, tmp_branch, orig_commit, new_logmsg, repo);
6575 done:
6576 if (commit_ref)
6577 got_ref_close(commit_ref);
6578 free(commit_ref_name);
6579 return err;
6582 const struct got_error *
6583 got_worktree_rebase_postpone(struct got_worktree *worktree,
6584 struct got_fileindex *fileindex)
6586 if (fileindex)
6587 got_fileindex_free(fileindex);
6588 return lock_worktree(worktree, LOCK_SH);
6591 static const struct got_error *
6592 delete_ref(const char *name, struct got_repository *repo)
6594 const struct got_error *err;
6595 struct got_reference *ref;
6597 err = got_ref_open(&ref, repo, name, 0);
6598 if (err) {
6599 if (err->code == GOT_ERR_NOT_REF)
6600 return NULL;
6601 return err;
6604 err = got_ref_delete(ref, repo);
6605 got_ref_close(ref);
6606 return err;
6609 static const struct got_error *
6610 delete_rebase_refs(struct got_worktree *worktree, struct got_repository *repo)
6612 const struct got_error *err;
6613 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
6614 char *branch_ref_name = NULL, *commit_ref_name = NULL;
6616 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
6617 if (err)
6618 goto done;
6619 err = delete_ref(tmp_branch_name, repo);
6620 if (err)
6621 goto done;
6623 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
6624 if (err)
6625 goto done;
6626 err = delete_ref(new_base_branch_ref_name, repo);
6627 if (err)
6628 goto done;
6630 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
6631 if (err)
6632 goto done;
6633 err = delete_ref(branch_ref_name, repo);
6634 if (err)
6635 goto done;
6637 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
6638 if (err)
6639 goto done;
6640 err = delete_ref(commit_ref_name, repo);
6641 if (err)
6642 goto done;
6644 done:
6645 free(tmp_branch_name);
6646 free(new_base_branch_ref_name);
6647 free(branch_ref_name);
6648 free(commit_ref_name);
6649 return err;
6652 const struct got_error *
6653 create_backup_ref(const char *backup_ref_prefix, struct got_reference *branch,
6654 struct got_object_id *new_commit_id, struct got_repository *repo)
6656 const struct got_error *err;
6657 struct got_reference *ref = NULL;
6658 struct got_object_id *old_commit_id = NULL;
6659 const char *branch_name = NULL;
6660 char *new_id_str = NULL;
6661 char *refname = NULL;
6663 branch_name = got_ref_get_name(branch);
6664 if (strncmp(branch_name, "refs/heads/", 11) != 0)
6665 return got_error(GOT_ERR_BAD_REF_NAME); /* should not happen */
6666 branch_name += 11;
6668 err = got_object_id_str(&new_id_str, new_commit_id);
6669 if (err)
6670 return err;
6672 if (asprintf(&refname, "%s/%s/%s", backup_ref_prefix, branch_name,
6673 new_id_str) == -1) {
6674 err = got_error_from_errno("asprintf");
6675 goto done;
6678 err = got_ref_resolve(&old_commit_id, repo, branch);
6679 if (err)
6680 goto done;
6682 err = got_ref_alloc(&ref, refname, old_commit_id);
6683 if (err)
6684 goto done;
6686 err = got_ref_write(ref, repo);
6687 done:
6688 free(new_id_str);
6689 free(refname);
6690 free(old_commit_id);
6691 if (ref)
6692 got_ref_close(ref);
6693 return err;
6696 const struct got_error *
6697 got_worktree_rebase_complete(struct got_worktree *worktree,
6698 struct got_fileindex *fileindex, struct got_reference *new_base_branch,
6699 struct got_reference *tmp_branch, struct got_reference *rebased_branch,
6700 struct got_repository *repo, int create_backup)
6702 const struct got_error *err, *unlockerr, *sync_err;
6703 struct got_object_id *new_head_commit_id = NULL;
6704 char *fileindex_path = NULL;
6706 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
6707 if (err)
6708 return err;
6710 if (create_backup) {
6711 err = create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX,
6712 rebased_branch, new_head_commit_id, repo);
6713 if (err)
6714 goto done;
6717 err = got_ref_change_ref(rebased_branch, new_head_commit_id);
6718 if (err)
6719 goto done;
6721 err = got_ref_write(rebased_branch, repo);
6722 if (err)
6723 goto done;
6725 err = got_worktree_set_head_ref(worktree, rebased_branch);
6726 if (err)
6727 goto done;
6729 err = delete_rebase_refs(worktree, repo);
6730 if (err)
6731 goto done;
6733 err = get_fileindex_path(&fileindex_path, worktree);
6734 if (err)
6735 goto done;
6736 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
6737 sync_err = sync_fileindex(fileindex, fileindex_path);
6738 if (sync_err && err == NULL)
6739 err = sync_err;
6740 done:
6741 got_fileindex_free(fileindex);
6742 free(fileindex_path);
6743 free(new_head_commit_id);
6744 unlockerr = lock_worktree(worktree, LOCK_SH);
6745 if (unlockerr && err == NULL)
6746 err = unlockerr;
6747 return err;
6750 const struct got_error *
6751 got_worktree_rebase_abort(struct got_worktree *worktree,
6752 struct got_fileindex *fileindex, struct got_repository *repo,
6753 struct got_reference *new_base_branch,
6754 got_worktree_checkout_cb progress_cb, void *progress_arg)
6756 const struct got_error *err, *unlockerr, *sync_err;
6757 struct got_reference *resolved = NULL;
6758 struct got_object_id *commit_id = NULL;
6759 char *fileindex_path = NULL;
6760 struct revert_file_args rfa;
6761 struct got_object_id *tree_id = NULL;
6763 err = lock_worktree(worktree, LOCK_EX);
6764 if (err)
6765 return err;
6767 err = got_ref_open(&resolved, repo,
6768 got_ref_get_symref_target(new_base_branch), 0);
6769 if (err)
6770 goto done;
6772 err = got_worktree_set_head_ref(worktree, resolved);
6773 if (err)
6774 goto done;
6777 * XXX commits to the base branch could have happened while
6778 * we were busy rebasing; should we store the original commit ID
6779 * when rebase begins and read it back here?
6781 err = got_ref_resolve(&commit_id, repo, resolved);
6782 if (err)
6783 goto done;
6785 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
6786 if (err)
6787 goto done;
6789 err = got_object_id_by_path(&tree_id, repo,
6790 worktree->base_commit_id, worktree->path_prefix);
6791 if (err)
6792 goto done;
6794 err = delete_rebase_refs(worktree, repo);
6795 if (err)
6796 goto done;
6798 err = get_fileindex_path(&fileindex_path, worktree);
6799 if (err)
6800 goto done;
6802 rfa.worktree = worktree;
6803 rfa.fileindex = fileindex;
6804 rfa.progress_cb = progress_cb;
6805 rfa.progress_arg = progress_arg;
6806 rfa.patch_cb = NULL;
6807 rfa.patch_arg = NULL;
6808 rfa.repo = repo;
6809 rfa.unlink_added_files = 0;
6810 err = worktree_status(worktree, "", fileindex, repo,
6811 revert_file, &rfa, NULL, NULL, 0, 0);
6812 if (err)
6813 goto sync;
6815 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
6816 repo, progress_cb, progress_arg, NULL, NULL);
6817 sync:
6818 sync_err = sync_fileindex(fileindex, fileindex_path);
6819 if (sync_err && err == NULL)
6820 err = sync_err;
6821 done:
6822 got_ref_close(resolved);
6823 free(tree_id);
6824 free(commit_id);
6825 if (fileindex)
6826 got_fileindex_free(fileindex);
6827 free(fileindex_path);
6829 unlockerr = lock_worktree(worktree, LOCK_SH);
6830 if (unlockerr && err == NULL)
6831 err = unlockerr;
6832 return err;
6835 const struct got_error *
6836 got_worktree_histedit_prepare(struct got_reference **tmp_branch,
6837 struct got_reference **branch_ref, struct got_object_id **base_commit_id,
6838 struct got_fileindex **fileindex, struct got_worktree *worktree,
6839 struct got_repository *repo)
6841 const struct got_error *err = NULL;
6842 char *tmp_branch_name = NULL;
6843 char *branch_ref_name = NULL;
6844 char *base_commit_ref_name = NULL;
6845 char *fileindex_path = NULL;
6846 struct check_rebase_ok_arg ok_arg;
6847 struct got_reference *wt_branch = NULL;
6848 struct got_reference *base_commit_ref = NULL;
6850 *tmp_branch = NULL;
6851 *branch_ref = NULL;
6852 *base_commit_id = NULL;
6853 *fileindex = NULL;
6855 err = lock_worktree(worktree, LOCK_EX);
6856 if (err)
6857 return err;
6859 err = open_fileindex(fileindex, &fileindex_path, worktree);
6860 if (err)
6861 goto done;
6863 ok_arg.worktree = worktree;
6864 ok_arg.repo = repo;
6865 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
6866 &ok_arg);
6867 if (err)
6868 goto done;
6870 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6871 if (err)
6872 goto done;
6874 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
6875 if (err)
6876 goto done;
6878 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
6879 worktree);
6880 if (err)
6881 goto done;
6883 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
6884 0);
6885 if (err)
6886 goto done;
6888 err = got_ref_alloc_symref(branch_ref, branch_ref_name, wt_branch);
6889 if (err)
6890 goto done;
6892 err = got_ref_write(*branch_ref, repo);
6893 if (err)
6894 goto done;
6896 err = got_ref_alloc(&base_commit_ref, base_commit_ref_name,
6897 worktree->base_commit_id);
6898 if (err)
6899 goto done;
6900 err = got_ref_write(base_commit_ref, repo);
6901 if (err)
6902 goto done;
6903 *base_commit_id = got_object_id_dup(worktree->base_commit_id);
6904 if (*base_commit_id == NULL) {
6905 err = got_error_from_errno("got_object_id_dup");
6906 goto done;
6909 err = got_ref_alloc(tmp_branch, tmp_branch_name,
6910 worktree->base_commit_id);
6911 if (err)
6912 goto done;
6913 err = got_ref_write(*tmp_branch, repo);
6914 if (err)
6915 goto done;
6917 err = got_worktree_set_head_ref(worktree, *tmp_branch);
6918 if (err)
6919 goto done;
6920 done:
6921 free(fileindex_path);
6922 free(tmp_branch_name);
6923 free(branch_ref_name);
6924 free(base_commit_ref_name);
6925 if (wt_branch)
6926 got_ref_close(wt_branch);
6927 if (err) {
6928 if (*branch_ref) {
6929 got_ref_close(*branch_ref);
6930 *branch_ref = NULL;
6932 if (*tmp_branch) {
6933 got_ref_close(*tmp_branch);
6934 *tmp_branch = NULL;
6936 free(*base_commit_id);
6937 if (*fileindex) {
6938 got_fileindex_free(*fileindex);
6939 *fileindex = NULL;
6941 lock_worktree(worktree, LOCK_SH);
6943 return err;
6946 const struct got_error *
6947 got_worktree_histedit_postpone(struct got_worktree *worktree,
6948 struct got_fileindex *fileindex)
6950 if (fileindex)
6951 got_fileindex_free(fileindex);
6952 return lock_worktree(worktree, LOCK_SH);
6955 const struct got_error *
6956 got_worktree_histedit_in_progress(int *in_progress,
6957 struct got_worktree *worktree)
6959 const struct got_error *err;
6960 char *tmp_branch_name = NULL;
6962 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
6963 if (err)
6964 return err;
6966 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
6967 free(tmp_branch_name);
6968 return NULL;
6971 const struct got_error *
6972 got_worktree_histedit_continue(struct got_object_id **commit_id,
6973 struct got_reference **tmp_branch, struct got_reference **branch_ref,
6974 struct got_object_id **base_commit_id, struct got_fileindex **fileindex,
6975 struct got_worktree *worktree, struct got_repository *repo)
6977 const struct got_error *err;
6978 char *commit_ref_name = NULL, *base_commit_ref_name = NULL;
6979 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
6980 struct got_reference *commit_ref = NULL;
6981 struct got_reference *base_commit_ref = NULL;
6982 char *fileindex_path = NULL;
6983 int have_staged_files = 0;
6985 *commit_id = NULL;
6986 *tmp_branch = NULL;
6987 *base_commit_id = NULL;
6988 *fileindex = NULL;
6990 err = lock_worktree(worktree, LOCK_EX);
6991 if (err)
6992 return err;
6994 err = open_fileindex(fileindex, &fileindex_path, worktree);
6995 if (err)
6996 goto done;
6998 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
6999 &have_staged_files);
7000 if (err && err->code != GOT_ERR_CANCELLED)
7001 goto done;
7002 if (have_staged_files) {
7003 err = got_error(GOT_ERR_STAGED_PATHS);
7004 goto done;
7007 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
7008 if (err)
7009 goto done;
7011 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
7012 if (err)
7013 goto done;
7015 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
7016 if (err)
7017 goto done;
7019 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
7020 worktree);
7021 if (err)
7022 goto done;
7024 err = got_ref_open(branch_ref, repo, branch_ref_name, 0);
7025 if (err)
7026 goto done;
7028 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
7029 if (err)
7030 goto done;
7031 err = got_ref_resolve(commit_id, repo, commit_ref);
7032 if (err)
7033 goto done;
7035 err = got_ref_open(&base_commit_ref, repo, base_commit_ref_name, 0);
7036 if (err)
7037 goto done;
7038 err = got_ref_resolve(base_commit_id, repo, base_commit_ref);
7039 if (err)
7040 goto done;
7042 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
7043 if (err)
7044 goto done;
7045 done:
7046 free(commit_ref_name);
7047 free(branch_ref_name);
7048 free(fileindex_path);
7049 if (commit_ref)
7050 got_ref_close(commit_ref);
7051 if (base_commit_ref)
7052 got_ref_close(base_commit_ref);
7053 if (err) {
7054 free(*commit_id);
7055 *commit_id = NULL;
7056 free(*base_commit_id);
7057 *base_commit_id = NULL;
7058 if (*tmp_branch) {
7059 got_ref_close(*tmp_branch);
7060 *tmp_branch = NULL;
7062 if (*fileindex) {
7063 got_fileindex_free(*fileindex);
7064 *fileindex = NULL;
7066 lock_worktree(worktree, LOCK_EX);
7068 return err;
7071 static const struct got_error *
7072 delete_histedit_refs(struct got_worktree *worktree, struct got_repository *repo)
7074 const struct got_error *err;
7075 char *tmp_branch_name = NULL, *base_commit_ref_name = NULL;
7076 char *branch_ref_name = NULL, *commit_ref_name = NULL;
7078 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
7079 if (err)
7080 goto done;
7081 err = delete_ref(tmp_branch_name, repo);
7082 if (err)
7083 goto done;
7085 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
7086 worktree);
7087 if (err)
7088 goto done;
7089 err = delete_ref(base_commit_ref_name, repo);
7090 if (err)
7091 goto done;
7093 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
7094 if (err)
7095 goto done;
7096 err = delete_ref(branch_ref_name, repo);
7097 if (err)
7098 goto done;
7100 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
7101 if (err)
7102 goto done;
7103 err = delete_ref(commit_ref_name, repo);
7104 if (err)
7105 goto done;
7106 done:
7107 free(tmp_branch_name);
7108 free(base_commit_ref_name);
7109 free(branch_ref_name);
7110 free(commit_ref_name);
7111 return err;
7114 const struct got_error *
7115 got_worktree_histedit_abort(struct got_worktree *worktree,
7116 struct got_fileindex *fileindex, struct got_repository *repo,
7117 struct got_reference *branch, struct got_object_id *base_commit_id,
7118 got_worktree_checkout_cb progress_cb, void *progress_arg)
7120 const struct got_error *err, *unlockerr, *sync_err;
7121 struct got_reference *resolved = NULL;
7122 char *fileindex_path = NULL;
7123 struct got_object_id *tree_id = NULL;
7124 struct revert_file_args rfa;
7126 err = lock_worktree(worktree, LOCK_EX);
7127 if (err)
7128 return err;
7130 err = got_ref_open(&resolved, repo,
7131 got_ref_get_symref_target(branch), 0);
7132 if (err)
7133 goto done;
7135 err = got_worktree_set_head_ref(worktree, resolved);
7136 if (err)
7137 goto done;
7139 err = got_worktree_set_base_commit_id(worktree, repo, base_commit_id);
7140 if (err)
7141 goto done;
7143 err = got_object_id_by_path(&tree_id, repo, base_commit_id,
7144 worktree->path_prefix);
7145 if (err)
7146 goto done;
7148 err = delete_histedit_refs(worktree, repo);
7149 if (err)
7150 goto done;
7152 err = get_fileindex_path(&fileindex_path, worktree);
7153 if (err)
7154 goto done;
7156 rfa.worktree = worktree;
7157 rfa.fileindex = fileindex;
7158 rfa.progress_cb = progress_cb;
7159 rfa.progress_arg = progress_arg;
7160 rfa.patch_cb = NULL;
7161 rfa.patch_arg = NULL;
7162 rfa.repo = repo;
7163 rfa.unlink_added_files = 0;
7164 err = worktree_status(worktree, "", fileindex, repo,
7165 revert_file, &rfa, NULL, NULL, 0, 0);
7166 if (err)
7167 goto sync;
7169 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
7170 repo, progress_cb, progress_arg, NULL, NULL);
7171 sync:
7172 sync_err = sync_fileindex(fileindex, fileindex_path);
7173 if (sync_err && err == NULL)
7174 err = sync_err;
7175 done:
7176 got_ref_close(resolved);
7177 free(tree_id);
7178 free(fileindex_path);
7180 unlockerr = lock_worktree(worktree, LOCK_SH);
7181 if (unlockerr && err == NULL)
7182 err = unlockerr;
7183 return err;
7186 const struct got_error *
7187 got_worktree_histedit_complete(struct got_worktree *worktree,
7188 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
7189 struct got_reference *edited_branch, struct got_repository *repo)
7191 const struct got_error *err, *unlockerr, *sync_err;
7192 struct got_object_id *new_head_commit_id = NULL;
7193 struct got_reference *resolved = NULL;
7194 char *fileindex_path = NULL;
7196 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
7197 if (err)
7198 return err;
7200 err = got_ref_open(&resolved, repo,
7201 got_ref_get_symref_target(edited_branch), 0);
7202 if (err)
7203 goto done;
7205 err = create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX,
7206 resolved, new_head_commit_id, repo);
7207 if (err)
7208 goto done;
7210 err = got_ref_change_ref(resolved, new_head_commit_id);
7211 if (err)
7212 goto done;
7214 err = got_ref_write(resolved, repo);
7215 if (err)
7216 goto done;
7218 err = got_worktree_set_head_ref(worktree, resolved);
7219 if (err)
7220 goto done;
7222 err = delete_histedit_refs(worktree, repo);
7223 if (err)
7224 goto done;
7226 err = get_fileindex_path(&fileindex_path, worktree);
7227 if (err)
7228 goto done;
7229 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
7230 sync_err = sync_fileindex(fileindex, fileindex_path);
7231 if (sync_err && err == NULL)
7232 err = sync_err;
7233 done:
7234 got_fileindex_free(fileindex);
7235 free(fileindex_path);
7236 free(new_head_commit_id);
7237 unlockerr = lock_worktree(worktree, LOCK_SH);
7238 if (unlockerr && err == NULL)
7239 err = unlockerr;
7240 return err;
7243 const struct got_error *
7244 got_worktree_histedit_skip_commit(struct got_worktree *worktree,
7245 struct got_object_id *commit_id, struct got_repository *repo)
7247 const struct got_error *err;
7248 char *commit_ref_name;
7250 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
7251 if (err)
7252 return err;
7254 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
7255 if (err)
7256 goto done;
7258 err = delete_ref(commit_ref_name, repo);
7259 done:
7260 free(commit_ref_name);
7261 return err;
7264 const struct got_error *
7265 got_worktree_integrate_prepare(struct got_fileindex **fileindex,
7266 struct got_reference **branch_ref, struct got_reference **base_branch_ref,
7267 struct got_worktree *worktree, const char *refname,
7268 struct got_repository *repo)
7270 const struct got_error *err = NULL;
7271 char *fileindex_path = NULL;
7272 struct check_rebase_ok_arg ok_arg;
7274 *fileindex = NULL;
7275 *branch_ref = NULL;
7276 *base_branch_ref = NULL;
7278 err = lock_worktree(worktree, LOCK_EX);
7279 if (err)
7280 return err;
7282 if (strcmp(refname, got_worktree_get_head_ref_name(worktree)) == 0) {
7283 err = got_error_msg(GOT_ERR_SAME_BRANCH,
7284 "cannot integrate a branch into itself; "
7285 "update -b or different branch name required");
7286 goto done;
7289 err = open_fileindex(fileindex, &fileindex_path, worktree);
7290 if (err)
7291 goto done;
7293 /* Preconditions are the same as for rebase. */
7294 ok_arg.worktree = worktree;
7295 ok_arg.repo = repo;
7296 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
7297 &ok_arg);
7298 if (err)
7299 goto done;
7301 err = got_ref_open(branch_ref, repo, refname, 1);
7302 if (err)
7303 goto done;
7305 err = got_ref_open(base_branch_ref, repo,
7306 got_worktree_get_head_ref_name(worktree), 1);
7307 done:
7308 if (err) {
7309 if (*branch_ref) {
7310 got_ref_close(*branch_ref);
7311 *branch_ref = NULL;
7313 if (*base_branch_ref) {
7314 got_ref_close(*base_branch_ref);
7315 *base_branch_ref = NULL;
7317 if (*fileindex) {
7318 got_fileindex_free(*fileindex);
7319 *fileindex = NULL;
7321 lock_worktree(worktree, LOCK_SH);
7323 return err;
7326 const struct got_error *
7327 got_worktree_integrate_continue(struct got_worktree *worktree,
7328 struct got_fileindex *fileindex, struct got_repository *repo,
7329 struct got_reference *branch_ref, struct got_reference *base_branch_ref,
7330 got_worktree_checkout_cb progress_cb, void *progress_arg,
7331 got_cancel_cb cancel_cb, void *cancel_arg)
7333 const struct got_error *err = NULL, *sync_err, *unlockerr;
7334 char *fileindex_path = NULL;
7335 struct got_object_id *tree_id = NULL, *commit_id = NULL;
7337 err = get_fileindex_path(&fileindex_path, worktree);
7338 if (err)
7339 goto done;
7341 err = got_ref_resolve(&commit_id, repo, branch_ref);
7342 if (err)
7343 goto done;
7345 err = got_object_id_by_path(&tree_id, repo, commit_id,
7346 worktree->path_prefix);
7347 if (err)
7348 goto done;
7350 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
7351 if (err)
7352 goto done;
7354 err = checkout_files(worktree, fileindex, "", tree_id, NULL, repo,
7355 progress_cb, progress_arg, cancel_cb, cancel_arg);
7356 if (err)
7357 goto sync;
7359 err = got_ref_change_ref(base_branch_ref, commit_id);
7360 if (err)
7361 goto sync;
7363 err = got_ref_write(base_branch_ref, repo);
7364 if (err)
7365 goto sync;
7367 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
7368 sync:
7369 sync_err = sync_fileindex(fileindex, fileindex_path);
7370 if (sync_err && err == NULL)
7371 err = sync_err;
7373 done:
7374 unlockerr = got_ref_unlock(branch_ref);
7375 if (unlockerr && err == NULL)
7376 err = unlockerr;
7377 got_ref_close(branch_ref);
7379 unlockerr = got_ref_unlock(base_branch_ref);
7380 if (unlockerr && err == NULL)
7381 err = unlockerr;
7382 got_ref_close(base_branch_ref);
7384 got_fileindex_free(fileindex);
7385 free(fileindex_path);
7386 free(tree_id);
7388 unlockerr = lock_worktree(worktree, LOCK_SH);
7389 if (unlockerr && err == NULL)
7390 err = unlockerr;
7391 return err;
7394 const struct got_error *
7395 got_worktree_integrate_abort(struct got_worktree *worktree,
7396 struct got_fileindex *fileindex, struct got_repository *repo,
7397 struct got_reference *branch_ref, struct got_reference *base_branch_ref)
7399 const struct got_error *err = NULL, *unlockerr = NULL;
7401 got_fileindex_free(fileindex);
7403 err = lock_worktree(worktree, LOCK_SH);
7405 unlockerr = got_ref_unlock(branch_ref);
7406 if (unlockerr && err == NULL)
7407 err = unlockerr;
7408 got_ref_close(branch_ref);
7410 unlockerr = got_ref_unlock(base_branch_ref);
7411 if (unlockerr && err == NULL)
7412 err = unlockerr;
7413 got_ref_close(base_branch_ref);
7415 return err;
7418 const struct got_error *
7419 got_worktree_merge_postpone(struct got_worktree *worktree,
7420 struct got_fileindex *fileindex)
7422 const struct got_error *err, *sync_err;
7423 char *fileindex_path = NULL;
7425 err = get_fileindex_path(&fileindex_path, worktree);
7426 if (err)
7427 goto done;
7429 sync_err = sync_fileindex(fileindex, fileindex_path);
7431 err = lock_worktree(worktree, LOCK_SH);
7432 if (sync_err && err == NULL)
7433 err = sync_err;
7434 done:
7435 got_fileindex_free(fileindex);
7436 free(fileindex_path);
7437 return err;
7440 static const struct got_error *
7441 delete_merge_refs(struct got_worktree *worktree, struct got_repository *repo)
7443 const struct got_error *err;
7444 char *branch_refname = NULL, *commit_refname = NULL;
7446 err = get_merge_branch_ref_name(&branch_refname, worktree);
7447 if (err)
7448 goto done;
7449 err = delete_ref(branch_refname, repo);
7450 if (err)
7451 goto done;
7453 err = get_merge_commit_ref_name(&commit_refname, worktree);
7454 if (err)
7455 goto done;
7456 err = delete_ref(commit_refname, repo);
7457 if (err)
7458 goto done;
7460 done:
7461 free(branch_refname);
7462 free(commit_refname);
7463 return err;
7466 struct merge_commit_msg_arg {
7467 struct got_worktree *worktree;
7468 const char *branch_name;
7471 static const struct got_error *
7472 merge_commit_msg_cb(struct got_pathlist_head *commitable_paths, char **logmsg,
7473 void *arg)
7475 struct merge_commit_msg_arg *a = arg;
7477 if (asprintf(logmsg, "merge %s into %s\n", a->branch_name,
7478 got_worktree_get_head_ref_name(a->worktree)) == -1)
7479 return got_error_from_errno("asprintf");
7481 return NULL;
7484 static const struct got_error *
7485 merge_status_cb(void *arg, unsigned char status, unsigned char staged_status,
7486 const char *path, struct got_object_id *blob_id,
7487 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
7488 int dirfd, const char *de_name)
7490 return NULL;
7493 const struct got_error *
7494 got_worktree_merge_branch(struct got_worktree *worktree,
7495 struct got_fileindex *fileindex,
7496 struct got_object_id *yca_commit_id,
7497 struct got_object_id *branch_tip,
7498 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
7499 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
7501 const struct got_error *err;
7502 char *fileindex_path = NULL;
7504 err = get_fileindex_path(&fileindex_path, worktree);
7505 if (err)
7506 goto done;
7508 err = got_fileindex_for_each_entry_safe(fileindex, check_mixed_commits,
7509 worktree);
7510 if (err)
7511 goto done;
7513 err = merge_files(worktree, fileindex, fileindex_path, yca_commit_id,
7514 branch_tip, repo, progress_cb, progress_arg,
7515 cancel_cb, cancel_arg);
7516 done:
7517 free(fileindex_path);
7518 return err;
7521 const struct got_error *
7522 got_worktree_merge_commit(struct got_object_id **new_commit_id,
7523 struct got_worktree *worktree, struct got_fileindex *fileindex,
7524 const char *author, const char *committer, int allow_bad_symlinks,
7525 struct got_object_id *branch_tip, const char *branch_name,
7526 struct got_repository *repo)
7528 const struct got_error *err = NULL, *sync_err;
7529 struct got_pathlist_head commitable_paths;
7530 struct collect_commitables_arg cc_arg;
7531 struct got_pathlist_entry *pe;
7532 struct got_reference *head_ref = NULL;
7533 struct got_object_id *head_commit_id = NULL;
7534 int have_staged_files = 0;
7535 struct merge_commit_msg_arg mcm_arg;
7536 char *fileindex_path = NULL;
7538 *new_commit_id = NULL;
7540 TAILQ_INIT(&commitable_paths);
7542 err = get_fileindex_path(&fileindex_path, worktree);
7543 if (err)
7544 goto done;
7546 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
7547 if (err)
7548 goto done;
7550 err = got_ref_resolve(&head_commit_id, repo, head_ref);
7551 if (err)
7552 goto done;
7554 err = got_fileindex_for_each_entry_safe(fileindex, check_staged_file,
7555 &have_staged_files);
7556 if (err && err->code != GOT_ERR_CANCELLED)
7557 goto done;
7558 if (have_staged_files) {
7559 err = got_error(GOT_ERR_MERGE_STAGED_PATHS);
7560 goto done;
7563 cc_arg.commitable_paths = &commitable_paths;
7564 cc_arg.worktree = worktree;
7565 cc_arg.fileindex = fileindex;
7566 cc_arg.repo = repo;
7567 cc_arg.have_staged_files = have_staged_files;
7568 cc_arg.allow_bad_symlinks = allow_bad_symlinks;
7569 err = worktree_status(worktree, "", fileindex, repo,
7570 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
7571 if (err)
7572 goto done;
7574 if (TAILQ_EMPTY(&commitable_paths)) {
7575 err = got_error_fmt(GOT_ERR_COMMIT_NO_CHANGES,
7576 "merge of %s cannot proceed", branch_name);
7577 goto done;
7580 TAILQ_FOREACH(pe, &commitable_paths, entry) {
7581 struct got_commitable *ct = pe->data;
7582 const char *ct_path = ct->in_repo_path;
7584 while (ct_path[0] == '/')
7585 ct_path++;
7586 err = check_out_of_date(ct_path, ct->status,
7587 ct->staged_status, ct->base_blob_id, ct->base_commit_id,
7588 head_commit_id, repo, GOT_ERR_MERGE_COMMIT_OUT_OF_DATE);
7589 if (err)
7590 goto done;
7594 mcm_arg.worktree = worktree;
7595 mcm_arg.branch_name = branch_name;
7596 err = commit_worktree(new_commit_id, &commitable_paths,
7597 head_commit_id, branch_tip, worktree, author, committer,
7598 merge_commit_msg_cb, &mcm_arg, merge_status_cb, NULL, repo);
7599 if (err)
7600 goto done;
7602 err = update_fileindex_after_commit(worktree, &commitable_paths,
7603 *new_commit_id, fileindex, have_staged_files);
7604 sync_err = sync_fileindex(fileindex, fileindex_path);
7605 if (sync_err && err == NULL)
7606 err = sync_err;
7607 done:
7608 TAILQ_FOREACH(pe, &commitable_paths, entry) {
7609 struct got_commitable *ct = pe->data;
7610 free_commitable(ct);
7612 got_pathlist_free(&commitable_paths);
7613 free(fileindex_path);
7614 return err;
7617 const struct got_error *
7618 got_worktree_merge_complete(struct got_worktree *worktree,
7619 struct got_fileindex *fileindex, struct got_repository *repo)
7621 const struct got_error *err, *unlockerr, *sync_err;
7622 char *fileindex_path = NULL;
7624 err = delete_merge_refs(worktree, repo);
7625 if (err)
7626 goto done;
7628 err = get_fileindex_path(&fileindex_path, worktree);
7629 if (err)
7630 goto done;
7631 err = bump_base_commit_id_everywhere(worktree, fileindex, NULL, NULL);
7632 sync_err = sync_fileindex(fileindex, fileindex_path);
7633 if (sync_err && err == NULL)
7634 err = sync_err;
7635 done:
7636 got_fileindex_free(fileindex);
7637 free(fileindex_path);
7638 unlockerr = lock_worktree(worktree, LOCK_SH);
7639 if (unlockerr && err == NULL)
7640 err = unlockerr;
7641 return err;
7644 const struct got_error *
7645 got_worktree_merge_in_progress(int *in_progress, struct got_worktree *worktree,
7646 struct got_repository *repo)
7648 const struct got_error *err;
7649 char *branch_refname = NULL;
7650 struct got_reference *branch_ref = NULL;
7652 *in_progress = 0;
7654 err = get_merge_branch_ref_name(&branch_refname, worktree);
7655 if (err)
7656 return err;
7657 err = got_ref_open(&branch_ref, repo, branch_refname, 0);
7658 free(branch_refname);
7659 if (err) {
7660 if (err->code != GOT_ERR_NOT_REF)
7661 return err;
7662 } else
7663 *in_progress = 1;
7665 return NULL;
7668 const struct got_error *got_worktree_merge_prepare(
7669 struct got_fileindex **fileindex, struct got_worktree *worktree,
7670 struct got_reference *branch, struct got_repository *repo)
7672 const struct got_error *err = NULL;
7673 char *fileindex_path = NULL;
7674 char *branch_refname = NULL, *commit_refname = NULL;
7675 struct got_reference *wt_branch = NULL, *branch_ref = NULL;
7676 struct got_reference *commit_ref = NULL;
7677 struct got_object_id *branch_tip = NULL, *wt_branch_tip = NULL;
7678 struct check_rebase_ok_arg ok_arg;
7680 *fileindex = NULL;
7682 err = lock_worktree(worktree, LOCK_EX);
7683 if (err)
7684 return err;
7686 err = open_fileindex(fileindex, &fileindex_path, worktree);
7687 if (err)
7688 goto done;
7690 /* Preconditions are the same as for rebase. */
7691 ok_arg.worktree = worktree;
7692 ok_arg.repo = repo;
7693 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
7694 &ok_arg);
7695 if (err)
7696 goto done;
7698 err = get_merge_branch_ref_name(&branch_refname, worktree);
7699 if (err)
7700 return err;
7702 err = get_merge_commit_ref_name(&commit_refname, worktree);
7703 if (err)
7704 return err;
7706 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
7707 0);
7708 if (err)
7709 goto done;
7711 err = got_ref_resolve(&wt_branch_tip, repo, wt_branch);
7712 if (err)
7713 goto done;
7715 if (got_object_id_cmp(worktree->base_commit_id, wt_branch_tip) != 0) {
7716 err = got_error(GOT_ERR_MERGE_OUT_OF_DATE);
7717 goto done;
7720 err = got_ref_resolve(&branch_tip, repo, branch);
7721 if (err)
7722 goto done;
7724 err = got_ref_alloc_symref(&branch_ref, branch_refname, branch);
7725 if (err)
7726 goto done;
7727 err = got_ref_write(branch_ref, repo);
7728 if (err)
7729 goto done;
7731 err = got_ref_alloc(&commit_ref, commit_refname, branch_tip);
7732 if (err)
7733 goto done;
7734 err = got_ref_write(commit_ref, repo);
7735 if (err)
7736 goto done;
7738 done:
7739 free(branch_refname);
7740 free(commit_refname);
7741 free(fileindex_path);
7742 if (branch_ref)
7743 got_ref_close(branch_ref);
7744 if (commit_ref)
7745 got_ref_close(commit_ref);
7746 if (wt_branch)
7747 got_ref_close(wt_branch);
7748 free(wt_branch_tip);
7749 if (err) {
7750 if (*fileindex) {
7751 got_fileindex_free(*fileindex);
7752 *fileindex = NULL;
7754 lock_worktree(worktree, LOCK_SH);
7756 return err;
7759 const struct got_error *
7760 got_worktree_merge_continue(char **branch_name,
7761 struct got_object_id **branch_tip, struct got_fileindex **fileindex,
7762 struct got_worktree *worktree, struct got_repository *repo)
7764 const struct got_error *err;
7765 char *commit_refname = NULL, *branch_refname = NULL;
7766 struct got_reference *commit_ref = NULL, *branch_ref = NULL;
7767 char *fileindex_path = NULL;
7768 int have_staged_files = 0;
7770 *branch_name = NULL;
7771 *branch_tip = NULL;
7772 *fileindex = NULL;
7774 err = lock_worktree(worktree, LOCK_EX);
7775 if (err)
7776 return err;
7778 err = open_fileindex(fileindex, &fileindex_path, worktree);
7779 if (err)
7780 goto done;
7782 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
7783 &have_staged_files);
7784 if (err && err->code != GOT_ERR_CANCELLED)
7785 goto done;
7786 if (have_staged_files) {
7787 err = got_error(GOT_ERR_STAGED_PATHS);
7788 goto done;
7791 err = get_merge_branch_ref_name(&branch_refname, worktree);
7792 if (err)
7793 goto done;
7795 err = get_merge_commit_ref_name(&commit_refname, worktree);
7796 if (err)
7797 goto done;
7799 err = got_ref_open(&branch_ref, repo, branch_refname, 0);
7800 if (err)
7801 goto done;
7803 if (!got_ref_is_symbolic(branch_ref)) {
7804 err = got_error_fmt(GOT_ERR_BAD_REF_TYPE,
7805 "%s is not a symbolic reference",
7806 got_ref_get_name(branch_ref));
7807 goto done;
7809 *branch_name = strdup(got_ref_get_symref_target(branch_ref));
7810 if (*branch_name == NULL) {
7811 err = got_error_from_errno("strdup");
7812 goto done;
7815 err = got_ref_open(&commit_ref, repo, commit_refname, 0);
7816 if (err)
7817 goto done;
7819 err = got_ref_resolve(branch_tip, repo, commit_ref);
7820 if (err)
7821 goto done;
7822 done:
7823 free(commit_refname);
7824 free(branch_refname);
7825 free(fileindex_path);
7826 if (commit_ref)
7827 got_ref_close(commit_ref);
7828 if (branch_ref)
7829 got_ref_close(branch_ref);
7830 if (err) {
7831 if (*branch_name) {
7832 free(*branch_name);
7833 *branch_name = NULL;
7835 free(*branch_tip);
7836 *branch_tip = NULL;
7837 if (*fileindex) {
7838 got_fileindex_free(*fileindex);
7839 *fileindex = NULL;
7841 lock_worktree(worktree, LOCK_SH);
7843 return err;
7846 const struct got_error *
7847 got_worktree_merge_abort(struct got_worktree *worktree,
7848 struct got_fileindex *fileindex, struct got_repository *repo,
7849 got_worktree_checkout_cb progress_cb, void *progress_arg)
7851 const struct got_error *err, *unlockerr, *sync_err;
7852 struct got_object_id *commit_id = NULL;
7853 char *fileindex_path = NULL;
7854 struct revert_file_args rfa;
7855 struct got_object_id *tree_id = NULL;
7857 err = got_object_id_by_path(&tree_id, repo,
7858 worktree->base_commit_id, worktree->path_prefix);
7859 if (err)
7860 goto done;
7862 err = delete_merge_refs(worktree, repo);
7863 if (err)
7864 goto done;
7866 err = get_fileindex_path(&fileindex_path, worktree);
7867 if (err)
7868 goto done;
7870 rfa.worktree = worktree;
7871 rfa.fileindex = fileindex;
7872 rfa.progress_cb = progress_cb;
7873 rfa.progress_arg = progress_arg;
7874 rfa.patch_cb = NULL;
7875 rfa.patch_arg = NULL;
7876 rfa.repo = repo;
7877 rfa.unlink_added_files = 1;
7878 err = worktree_status(worktree, "", fileindex, repo,
7879 revert_file, &rfa, NULL, NULL, 0, 0);
7880 if (err)
7881 goto sync;
7883 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
7884 repo, progress_cb, progress_arg, NULL, NULL);
7885 sync:
7886 sync_err = sync_fileindex(fileindex, fileindex_path);
7887 if (sync_err && err == NULL)
7888 err = sync_err;
7889 done:
7890 free(tree_id);
7891 free(commit_id);
7892 if (fileindex)
7893 got_fileindex_free(fileindex);
7894 free(fileindex_path);
7896 unlockerr = lock_worktree(worktree, LOCK_SH);
7897 if (unlockerr && err == NULL)
7898 err = unlockerr;
7899 return err;
7902 struct check_stage_ok_arg {
7903 struct got_object_id *head_commit_id;
7904 struct got_worktree *worktree;
7905 struct got_fileindex *fileindex;
7906 struct got_repository *repo;
7907 int have_changes;
7910 const struct got_error *
7911 check_stage_ok(void *arg, unsigned char status,
7912 unsigned char staged_status, const char *relpath,
7913 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
7914 struct got_object_id *commit_id, int dirfd, const char *de_name)
7916 struct check_stage_ok_arg *a = arg;
7917 const struct got_error *err = NULL;
7918 struct got_fileindex_entry *ie;
7919 struct got_object_id base_commit_id;
7920 struct got_object_id *base_commit_idp = NULL;
7921 char *in_repo_path = NULL, *p;
7923 if (status == GOT_STATUS_UNVERSIONED ||
7924 status == GOT_STATUS_NO_CHANGE)
7925 return NULL;
7926 if (status == GOT_STATUS_NONEXISTENT)
7927 return got_error_set_errno(ENOENT, relpath);
7929 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
7930 if (ie == NULL)
7931 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
7933 if (asprintf(&in_repo_path, "%s%s%s", a->worktree->path_prefix,
7934 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
7935 relpath) == -1)
7936 return got_error_from_errno("asprintf");
7938 if (got_fileindex_entry_has_commit(ie)) {
7939 memcpy(base_commit_id.sha1, ie->commit_sha1,
7940 SHA1_DIGEST_LENGTH);
7941 base_commit_idp = &base_commit_id;
7944 if (status == GOT_STATUS_CONFLICT) {
7945 err = got_error_path(ie->path, GOT_ERR_STAGE_CONFLICT);
7946 goto done;
7947 } else if (status != GOT_STATUS_ADD &&
7948 status != GOT_STATUS_MODIFY &&
7949 status != GOT_STATUS_DELETE) {
7950 err = got_error_path(ie->path, GOT_ERR_FILE_STATUS);
7951 goto done;
7954 a->have_changes = 1;
7956 p = in_repo_path;
7957 while (p[0] == '/')
7958 p++;
7959 err = check_out_of_date(p, status, staged_status,
7960 blob_id, base_commit_idp, a->head_commit_id, a->repo,
7961 GOT_ERR_STAGE_OUT_OF_DATE);
7962 done:
7963 free(in_repo_path);
7964 return err;
7967 struct stage_path_arg {
7968 struct got_worktree *worktree;
7969 struct got_fileindex *fileindex;
7970 struct got_repository *repo;
7971 got_worktree_status_cb status_cb;
7972 void *status_arg;
7973 got_worktree_patch_cb patch_cb;
7974 void *patch_arg;
7975 int staged_something;
7976 int allow_bad_symlinks;
7979 static const struct got_error *
7980 stage_path(void *arg, unsigned char status,
7981 unsigned char staged_status, const char *relpath,
7982 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
7983 struct got_object_id *commit_id, int dirfd, const char *de_name)
7985 struct stage_path_arg *a = arg;
7986 const struct got_error *err = NULL;
7987 struct got_fileindex_entry *ie;
7988 char *ondisk_path = NULL, *path_content = NULL;
7989 uint32_t stage;
7990 struct got_object_id *new_staged_blob_id = NULL;
7991 struct stat sb;
7993 if (status == GOT_STATUS_UNVERSIONED)
7994 return NULL;
7996 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
7997 if (ie == NULL)
7998 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
8000 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
8001 relpath)== -1)
8002 return got_error_from_errno("asprintf");
8004 switch (status) {
8005 case GOT_STATUS_ADD:
8006 case GOT_STATUS_MODIFY:
8007 /* XXX could sb.st_mode be passed in by our caller? */
8008 if (lstat(ondisk_path, &sb) == -1) {
8009 err = got_error_from_errno2("lstat", ondisk_path);
8010 break;
8012 if (a->patch_cb) {
8013 if (status == GOT_STATUS_ADD) {
8014 int choice = GOT_PATCH_CHOICE_NONE;
8015 err = (*a->patch_cb)(&choice, a->patch_arg,
8016 status, ie->path, NULL, 1, 1);
8017 if (err)
8018 break;
8019 if (choice != GOT_PATCH_CHOICE_YES)
8020 break;
8021 } else {
8022 err = create_patched_content(&path_content, 0,
8023 staged_blob_id ? staged_blob_id : blob_id,
8024 ondisk_path, dirfd, de_name, ie->path,
8025 a->repo, a->patch_cb, a->patch_arg);
8026 if (err || path_content == NULL)
8027 break;
8030 err = got_object_blob_create(&new_staged_blob_id,
8031 path_content ? path_content : ondisk_path, a->repo);
8032 if (err)
8033 break;
8034 memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1,
8035 SHA1_DIGEST_LENGTH);
8036 if (status == GOT_STATUS_ADD || staged_status == GOT_STATUS_ADD)
8037 stage = GOT_FILEIDX_STAGE_ADD;
8038 else
8039 stage = GOT_FILEIDX_STAGE_MODIFY;
8040 got_fileindex_entry_stage_set(ie, stage);
8041 if (S_ISLNK(sb.st_mode)) {
8042 int is_bad_symlink = 0;
8043 if (!a->allow_bad_symlinks) {
8044 char target_path[PATH_MAX];
8045 ssize_t target_len;
8046 target_len = readlink(ondisk_path, target_path,
8047 sizeof(target_path));
8048 if (target_len == -1) {
8049 err = got_error_from_errno2("readlink",
8050 ondisk_path);
8051 break;
8053 err = is_bad_symlink_target(&is_bad_symlink,
8054 target_path, target_len, ondisk_path,
8055 a->worktree->root_path);
8056 if (err)
8057 break;
8058 if (is_bad_symlink) {
8059 err = got_error_path(ondisk_path,
8060 GOT_ERR_BAD_SYMLINK);
8061 break;
8064 if (is_bad_symlink)
8065 got_fileindex_entry_staged_filetype_set(ie,
8066 GOT_FILEIDX_MODE_BAD_SYMLINK);
8067 else
8068 got_fileindex_entry_staged_filetype_set(ie,
8069 GOT_FILEIDX_MODE_SYMLINK);
8070 } else {
8071 got_fileindex_entry_staged_filetype_set(ie,
8072 GOT_FILEIDX_MODE_REGULAR_FILE);
8074 a->staged_something = 1;
8075 if (a->status_cb == NULL)
8076 break;
8077 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
8078 get_staged_status(ie), relpath, blob_id,
8079 new_staged_blob_id, NULL, dirfd, de_name);
8080 break;
8081 case GOT_STATUS_DELETE:
8082 if (staged_status == GOT_STATUS_DELETE)
8083 break;
8084 if (a->patch_cb) {
8085 int choice = GOT_PATCH_CHOICE_NONE;
8086 err = (*a->patch_cb)(&choice, a->patch_arg, status,
8087 ie->path, NULL, 1, 1);
8088 if (err)
8089 break;
8090 if (choice == GOT_PATCH_CHOICE_NO)
8091 break;
8092 if (choice != GOT_PATCH_CHOICE_YES) {
8093 err = got_error(GOT_ERR_PATCH_CHOICE);
8094 break;
8097 stage = GOT_FILEIDX_STAGE_DELETE;
8098 got_fileindex_entry_stage_set(ie, stage);
8099 a->staged_something = 1;
8100 if (a->status_cb == NULL)
8101 break;
8102 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
8103 get_staged_status(ie), relpath, NULL, NULL, NULL, dirfd,
8104 de_name);
8105 break;
8106 case GOT_STATUS_NO_CHANGE:
8107 break;
8108 case GOT_STATUS_CONFLICT:
8109 err = got_error_path(relpath, GOT_ERR_STAGE_CONFLICT);
8110 break;
8111 case GOT_STATUS_NONEXISTENT:
8112 err = got_error_set_errno(ENOENT, relpath);
8113 break;
8114 default:
8115 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
8116 break;
8119 if (path_content && unlink(path_content) == -1 && err == NULL)
8120 err = got_error_from_errno2("unlink", path_content);
8121 free(path_content);
8122 free(ondisk_path);
8123 free(new_staged_blob_id);
8124 return err;
8127 const struct got_error *
8128 got_worktree_stage(struct got_worktree *worktree,
8129 struct got_pathlist_head *paths,
8130 got_worktree_status_cb status_cb, void *status_arg,
8131 got_worktree_patch_cb patch_cb, void *patch_arg,
8132 int allow_bad_symlinks, struct got_repository *repo)
8134 const struct got_error *err = NULL, *sync_err, *unlockerr;
8135 struct got_pathlist_entry *pe;
8136 struct got_fileindex *fileindex = NULL;
8137 char *fileindex_path = NULL;
8138 struct got_reference *head_ref = NULL;
8139 struct got_object_id *head_commit_id = NULL;
8140 struct check_stage_ok_arg oka;
8141 struct stage_path_arg spa;
8143 err = lock_worktree(worktree, LOCK_EX);
8144 if (err)
8145 return err;
8147 err = got_ref_open(&head_ref, repo,
8148 got_worktree_get_head_ref_name(worktree), 0);
8149 if (err)
8150 goto done;
8151 err = got_ref_resolve(&head_commit_id, repo, head_ref);
8152 if (err)
8153 goto done;
8154 err = open_fileindex(&fileindex, &fileindex_path, worktree);
8155 if (err)
8156 goto done;
8158 /* Check pre-conditions before staging anything. */
8159 oka.head_commit_id = head_commit_id;
8160 oka.worktree = worktree;
8161 oka.fileindex = fileindex;
8162 oka.repo = repo;
8163 oka.have_changes = 0;
8164 TAILQ_FOREACH(pe, paths, entry) {
8165 err = worktree_status(worktree, pe->path, fileindex, repo,
8166 check_stage_ok, &oka, NULL, NULL, 0, 0);
8167 if (err)
8168 goto done;
8170 if (!oka.have_changes) {
8171 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
8172 goto done;
8175 spa.worktree = worktree;
8176 spa.fileindex = fileindex;
8177 spa.repo = repo;
8178 spa.patch_cb = patch_cb;
8179 spa.patch_arg = patch_arg;
8180 spa.status_cb = status_cb;
8181 spa.status_arg = status_arg;
8182 spa.staged_something = 0;
8183 spa.allow_bad_symlinks = allow_bad_symlinks;
8184 TAILQ_FOREACH(pe, paths, entry) {
8185 err = worktree_status(worktree, pe->path, fileindex, repo,
8186 stage_path, &spa, NULL, NULL, 0, 0);
8187 if (err)
8188 goto done;
8190 if (!spa.staged_something) {
8191 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
8192 goto done;
8195 sync_err = sync_fileindex(fileindex, fileindex_path);
8196 if (sync_err && err == NULL)
8197 err = sync_err;
8198 done:
8199 if (head_ref)
8200 got_ref_close(head_ref);
8201 free(head_commit_id);
8202 free(fileindex_path);
8203 if (fileindex)
8204 got_fileindex_free(fileindex);
8205 unlockerr = lock_worktree(worktree, LOCK_SH);
8206 if (unlockerr && err == NULL)
8207 err = unlockerr;
8208 return err;
8211 struct unstage_path_arg {
8212 struct got_worktree *worktree;
8213 struct got_fileindex *fileindex;
8214 struct got_repository *repo;
8215 got_worktree_checkout_cb progress_cb;
8216 void *progress_arg;
8217 got_worktree_patch_cb patch_cb;
8218 void *patch_arg;
8221 static const struct got_error *
8222 create_unstaged_content(char **path_unstaged_content,
8223 char **path_new_staged_content, struct got_object_id *blob_id,
8224 struct got_object_id *staged_blob_id, const char *relpath,
8225 struct got_repository *repo,
8226 got_worktree_patch_cb patch_cb, void *patch_arg)
8228 const struct got_error *err, *free_err;
8229 struct got_blob_object *blob = NULL, *staged_blob = NULL;
8230 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL, *rejectfile = NULL;
8231 char *path1 = NULL, *path2 = NULL, *label1 = NULL;
8232 struct got_diffreg_result *diffreg_result = NULL;
8233 int line_cur1 = 1, line_cur2 = 1, n = 0, nchunks_used = 0;
8234 int have_content = 0, have_rejected_content = 0, i = 0, nchanges = 0;
8236 *path_unstaged_content = NULL;
8237 *path_new_staged_content = NULL;
8239 err = got_object_id_str(&label1, blob_id);
8240 if (err)
8241 return err;
8242 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
8243 if (err)
8244 goto done;
8246 err = got_opentemp_named(&path1, &f1, "got-unstage-blob-base");
8247 if (err)
8248 goto done;
8250 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
8251 if (err)
8252 goto done;
8254 err = got_object_open_as_blob(&staged_blob, repo, staged_blob_id, 8192);
8255 if (err)
8256 goto done;
8258 err = got_opentemp_named(&path2, &f2, "got-unstage-blob-staged");
8259 if (err)
8260 goto done;
8262 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f2, staged_blob);
8263 if (err)
8264 goto done;
8266 err = got_diff_files(&diffreg_result, f1, label1, f2,
8267 path2, 3, 0, 1, NULL);
8268 if (err)
8269 goto done;
8271 err = got_opentemp_named(path_unstaged_content, &outfile,
8272 "got-unstaged-content");
8273 if (err)
8274 goto done;
8275 err = got_opentemp_named(path_new_staged_content, &rejectfile,
8276 "got-new-staged-content");
8277 if (err)
8278 goto done;
8280 if (fseek(f1, 0L, SEEK_SET) == -1) {
8281 err = got_ferror(f1, GOT_ERR_IO);
8282 goto done;
8284 if (fseek(f2, 0L, SEEK_SET) == -1) {
8285 err = got_ferror(f2, GOT_ERR_IO);
8286 goto done;
8288 /* Count the number of actual changes in the diff result. */
8289 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
8290 struct diff_chunk_context cc = {};
8291 diff_chunk_context_load_change(&cc, &nchunks_used,
8292 diffreg_result->result, n, 0);
8293 nchanges++;
8295 for (n = 0; n < diffreg_result->result->chunks.len; n += nchunks_used) {
8296 int choice;
8297 err = apply_or_reject_change(&choice, &nchunks_used,
8298 diffreg_result->result, n, relpath, f1, f2,
8299 &line_cur1, &line_cur2,
8300 outfile, rejectfile, ++i, nchanges, patch_cb, patch_arg);
8301 if (err)
8302 goto done;
8303 if (choice == GOT_PATCH_CHOICE_YES)
8304 have_content = 1;
8305 else
8306 have_rejected_content = 1;
8307 if (choice == GOT_PATCH_CHOICE_QUIT)
8308 break;
8310 if (have_content || have_rejected_content)
8311 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
8312 outfile, rejectfile);
8313 done:
8314 free(label1);
8315 if (blob)
8316 got_object_blob_close(blob);
8317 if (staged_blob)
8318 got_object_blob_close(staged_blob);
8319 free_err = got_diffreg_result_free(diffreg_result);
8320 if (free_err && err == NULL)
8321 err = free_err;
8322 if (f1 && fclose(f1) == EOF && err == NULL)
8323 err = got_error_from_errno2("fclose", path1);
8324 if (f2 && fclose(f2) == EOF && err == NULL)
8325 err = got_error_from_errno2("fclose", path2);
8326 if (outfile && fclose(outfile) == EOF && err == NULL)
8327 err = got_error_from_errno2("fclose", *path_unstaged_content);
8328 if (rejectfile && fclose(rejectfile) == EOF && err == NULL)
8329 err = got_error_from_errno2("fclose", *path_new_staged_content);
8330 if (path1 && unlink(path1) == -1 && err == NULL)
8331 err = got_error_from_errno2("unlink", path1);
8332 if (path2 && unlink(path2) == -1 && err == NULL)
8333 err = got_error_from_errno2("unlink", path2);
8334 if (err || !have_content) {
8335 if (*path_unstaged_content &&
8336 unlink(*path_unstaged_content) == -1 && err == NULL)
8337 err = got_error_from_errno2("unlink",
8338 *path_unstaged_content);
8339 free(*path_unstaged_content);
8340 *path_unstaged_content = NULL;
8342 if (err || !have_content || !have_rejected_content) {
8343 if (*path_new_staged_content &&
8344 unlink(*path_new_staged_content) == -1 && err == NULL)
8345 err = got_error_from_errno2("unlink",
8346 *path_new_staged_content);
8347 free(*path_new_staged_content);
8348 *path_new_staged_content = NULL;
8350 free(path1);
8351 free(path2);
8352 return err;
8355 static const struct got_error *
8356 unstage_hunks(struct got_object_id *staged_blob_id,
8357 struct got_blob_object *blob_base,
8358 struct got_object_id *blob_id, struct got_fileindex_entry *ie,
8359 const char *ondisk_path, const char *label_orig,
8360 struct got_worktree *worktree, struct got_repository *repo,
8361 got_worktree_patch_cb patch_cb, void *patch_arg,
8362 got_worktree_checkout_cb progress_cb, void *progress_arg)
8364 const struct got_error *err = NULL;
8365 char *path_unstaged_content = NULL;
8366 char *path_new_staged_content = NULL;
8367 char *parent = NULL, *base_path = NULL;
8368 char *blob_base_path = NULL;
8369 struct got_object_id *new_staged_blob_id = NULL;
8370 FILE *f = NULL, *f_base = NULL, *f_deriv2 = NULL;
8371 struct stat sb;
8373 err = create_unstaged_content(&path_unstaged_content,
8374 &path_new_staged_content, blob_id, staged_blob_id,
8375 ie->path, repo, patch_cb, patch_arg);
8376 if (err)
8377 return err;
8379 if (path_unstaged_content == NULL)
8380 return NULL;
8382 if (path_new_staged_content) {
8383 err = got_object_blob_create(&new_staged_blob_id,
8384 path_new_staged_content, repo);
8385 if (err)
8386 goto done;
8389 f = fopen(path_unstaged_content, "r");
8390 if (f == NULL) {
8391 err = got_error_from_errno2("fopen",
8392 path_unstaged_content);
8393 goto done;
8395 if (fstat(fileno(f), &sb) == -1) {
8396 err = got_error_from_errno2("fstat", path_unstaged_content);
8397 goto done;
8399 if (got_fileindex_entry_staged_filetype_get(ie) ==
8400 GOT_FILEIDX_MODE_SYMLINK && sb.st_size < PATH_MAX) {
8401 char link_target[PATH_MAX];
8402 size_t r;
8403 r = fread(link_target, 1, sizeof(link_target), f);
8404 if (r == 0 && ferror(f)) {
8405 err = got_error_from_errno("fread");
8406 goto done;
8408 if (r >= sizeof(link_target)) { /* should not happen */
8409 err = got_error(GOT_ERR_NO_SPACE);
8410 goto done;
8412 link_target[r] = '\0';
8413 err = merge_symlink(worktree, blob_base,
8414 ondisk_path, ie->path, label_orig, link_target,
8415 worktree->base_commit_id, repo, progress_cb,
8416 progress_arg);
8417 } else {
8418 int local_changes_subsumed;
8420 err = got_path_dirname(&parent, ondisk_path);
8421 if (err)
8422 return err;
8424 if (asprintf(&base_path, "%s/got-unstage-blob-orig",
8425 parent) == -1) {
8426 err = got_error_from_errno("asprintf");
8427 base_path = NULL;
8428 goto done;
8431 err = got_opentemp_named(&blob_base_path, &f_base, base_path);
8432 if (err)
8433 goto done;
8434 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_base,
8435 blob_base);
8436 if (err)
8437 goto done;
8440 * In order the run a 3-way merge with a symlink we copy the symlink's
8441 * target path into a temporary file and use that file with diff3.
8443 if (S_ISLNK(got_fileindex_perms_to_st(ie))) {
8444 err = dump_symlink_target_path_to_file(&f_deriv2,
8445 ondisk_path);
8446 if (err)
8447 goto done;
8448 } else {
8449 int fd;
8450 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW);
8451 if (fd == -1) {
8452 err = got_error_from_errno2("open", ondisk_path);
8453 goto done;
8455 f_deriv2 = fdopen(fd, "r");
8456 if (f_deriv2 == NULL) {
8457 err = got_error_from_errno2("fdopen", ondisk_path);
8458 close(fd);
8459 goto done;
8463 err = merge_file(&local_changes_subsumed, worktree,
8464 f_base, f, f_deriv2, ondisk_path, ie->path,
8465 got_fileindex_perms_to_st(ie),
8466 label_orig, "unstaged", NULL, GOT_DIFF_ALGORITHM_MYERS,
8467 repo, progress_cb, progress_arg);
8469 if (err)
8470 goto done;
8472 if (new_staged_blob_id) {
8473 memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1,
8474 SHA1_DIGEST_LENGTH);
8475 } else {
8476 got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE);
8477 got_fileindex_entry_staged_filetype_set(ie, 0);
8479 done:
8480 free(new_staged_blob_id);
8481 if (path_unstaged_content &&
8482 unlink(path_unstaged_content) == -1 && err == NULL)
8483 err = got_error_from_errno2("unlink", path_unstaged_content);
8484 if (path_new_staged_content &&
8485 unlink(path_new_staged_content) == -1 && err == NULL)
8486 err = got_error_from_errno2("unlink", path_new_staged_content);
8487 if (blob_base_path && unlink(blob_base_path) == -1 && err == NULL)
8488 err = got_error_from_errno2("unlink", blob_base_path);
8489 if (f_base && fclose(f_base) == EOF && err == NULL)
8490 err = got_error_from_errno2("fclose", path_unstaged_content);
8491 if (f && fclose(f) == EOF && err == NULL)
8492 err = got_error_from_errno2("fclose", path_unstaged_content);
8493 if (f_deriv2 && fclose(f_deriv2) == EOF && err == NULL)
8494 err = got_error_from_errno2("fclose", ondisk_path);
8495 free(path_unstaged_content);
8496 free(path_new_staged_content);
8497 free(blob_base_path);
8498 free(parent);
8499 free(base_path);
8500 return err;
8503 static const struct got_error *
8504 unstage_path(void *arg, unsigned char status,
8505 unsigned char staged_status, const char *relpath,
8506 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
8507 struct got_object_id *commit_id, int dirfd, const char *de_name)
8509 const struct got_error *err = NULL;
8510 struct unstage_path_arg *a = arg;
8511 struct got_fileindex_entry *ie;
8512 struct got_blob_object *blob_base = NULL, *blob_staged = NULL;
8513 char *ondisk_path = NULL;
8514 char *id_str = NULL, *label_orig = NULL;
8515 int local_changes_subsumed;
8516 struct stat sb;
8518 if (staged_status != GOT_STATUS_ADD &&
8519 staged_status != GOT_STATUS_MODIFY &&
8520 staged_status != GOT_STATUS_DELETE)
8521 return NULL;
8523 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
8524 if (ie == NULL)
8525 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
8527 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, relpath)
8528 == -1)
8529 return got_error_from_errno("asprintf");
8531 err = got_object_id_str(&id_str,
8532 commit_id ? commit_id : a->worktree->base_commit_id);
8533 if (err)
8534 goto done;
8535 if (asprintf(&label_orig, "%s: commit %s", GOT_MERGE_LABEL_BASE,
8536 id_str) == -1) {
8537 err = got_error_from_errno("asprintf");
8538 goto done;
8541 switch (staged_status) {
8542 case GOT_STATUS_MODIFY:
8543 err = got_object_open_as_blob(&blob_base, a->repo,
8544 blob_id, 8192);
8545 if (err)
8546 break;
8547 /* fall through */
8548 case GOT_STATUS_ADD:
8549 if (a->patch_cb) {
8550 if (staged_status == GOT_STATUS_ADD) {
8551 int choice = GOT_PATCH_CHOICE_NONE;
8552 err = (*a->patch_cb)(&choice, a->patch_arg,
8553 staged_status, ie->path, NULL, 1, 1);
8554 if (err)
8555 break;
8556 if (choice != GOT_PATCH_CHOICE_YES)
8557 break;
8558 } else {
8559 err = unstage_hunks(staged_blob_id,
8560 blob_base, blob_id, ie, ondisk_path,
8561 label_orig, a->worktree, a->repo,
8562 a->patch_cb, a->patch_arg,
8563 a->progress_cb, a->progress_arg);
8564 break; /* Done with this file. */
8567 err = got_object_open_as_blob(&blob_staged, a->repo,
8568 staged_blob_id, 8192);
8569 if (err)
8570 break;
8571 switch (got_fileindex_entry_staged_filetype_get(ie)) {
8572 case GOT_FILEIDX_MODE_BAD_SYMLINK:
8573 case GOT_FILEIDX_MODE_REGULAR_FILE:
8574 err = merge_blob(&local_changes_subsumed, a->worktree,
8575 blob_base, ondisk_path, relpath,
8576 got_fileindex_perms_to_st(ie), label_orig,
8577 blob_staged, commit_id ? commit_id :
8578 a->worktree->base_commit_id, a->repo,
8579 a->progress_cb, a->progress_arg);
8580 break;
8581 case GOT_FILEIDX_MODE_SYMLINK:
8582 if (S_ISLNK(got_fileindex_perms_to_st(ie))) {
8583 char *staged_target;
8584 err = got_object_blob_read_to_str(
8585 &staged_target, blob_staged);
8586 if (err)
8587 goto done;
8588 err = merge_symlink(a->worktree, blob_base,
8589 ondisk_path, relpath, label_orig,
8590 staged_target, commit_id ? commit_id :
8591 a->worktree->base_commit_id,
8592 a->repo, a->progress_cb, a->progress_arg);
8593 free(staged_target);
8594 } else {
8595 err = merge_blob(&local_changes_subsumed,
8596 a->worktree, blob_base, ondisk_path,
8597 relpath, got_fileindex_perms_to_st(ie),
8598 label_orig, blob_staged,
8599 commit_id ? commit_id :
8600 a->worktree->base_commit_id, a->repo,
8601 a->progress_cb, a->progress_arg);
8603 break;
8604 default:
8605 err = got_error_path(relpath, GOT_ERR_BAD_FILETYPE);
8606 break;
8608 if (err == NULL) {
8609 got_fileindex_entry_stage_set(ie,
8610 GOT_FILEIDX_STAGE_NONE);
8611 got_fileindex_entry_staged_filetype_set(ie, 0);
8613 break;
8614 case GOT_STATUS_DELETE:
8615 if (a->patch_cb) {
8616 int choice = GOT_PATCH_CHOICE_NONE;
8617 err = (*a->patch_cb)(&choice, a->patch_arg,
8618 staged_status, ie->path, NULL, 1, 1);
8619 if (err)
8620 break;
8621 if (choice == GOT_PATCH_CHOICE_NO)
8622 break;
8623 if (choice != GOT_PATCH_CHOICE_YES) {
8624 err = got_error(GOT_ERR_PATCH_CHOICE);
8625 break;
8628 got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE);
8629 got_fileindex_entry_staged_filetype_set(ie, 0);
8630 err = get_file_status(&status, &sb, ie, ondisk_path,
8631 dirfd, de_name, a->repo);
8632 if (err)
8633 break;
8634 err = (*a->progress_cb)(a->progress_arg, status, relpath);
8635 break;
8637 done:
8638 free(ondisk_path);
8639 if (blob_base)
8640 got_object_blob_close(blob_base);
8641 if (blob_staged)
8642 got_object_blob_close(blob_staged);
8643 free(id_str);
8644 free(label_orig);
8645 return err;
8648 const struct got_error *
8649 got_worktree_unstage(struct got_worktree *worktree,
8650 struct got_pathlist_head *paths,
8651 got_worktree_checkout_cb progress_cb, void *progress_arg,
8652 got_worktree_patch_cb patch_cb, void *patch_arg,
8653 struct got_repository *repo)
8655 const struct got_error *err = NULL, *sync_err, *unlockerr;
8656 struct got_pathlist_entry *pe;
8657 struct got_fileindex *fileindex = NULL;
8658 char *fileindex_path = NULL;
8659 struct unstage_path_arg upa;
8661 err = lock_worktree(worktree, LOCK_EX);
8662 if (err)
8663 return err;
8665 err = open_fileindex(&fileindex, &fileindex_path, worktree);
8666 if (err)
8667 goto done;
8669 upa.worktree = worktree;
8670 upa.fileindex = fileindex;
8671 upa.repo = repo;
8672 upa.progress_cb = progress_cb;
8673 upa.progress_arg = progress_arg;
8674 upa.patch_cb = patch_cb;
8675 upa.patch_arg = patch_arg;
8676 TAILQ_FOREACH(pe, paths, entry) {
8677 err = worktree_status(worktree, pe->path, fileindex, repo,
8678 unstage_path, &upa, NULL, NULL, 0, 0);
8679 if (err)
8680 goto done;
8683 sync_err = sync_fileindex(fileindex, fileindex_path);
8684 if (sync_err && err == NULL)
8685 err = sync_err;
8686 done:
8687 free(fileindex_path);
8688 if (fileindex)
8689 got_fileindex_free(fileindex);
8690 unlockerr = lock_worktree(worktree, LOCK_SH);
8691 if (unlockerr && err == NULL)
8692 err = unlockerr;
8693 return err;
8696 struct report_file_info_arg {
8697 struct got_worktree *worktree;
8698 got_worktree_path_info_cb info_cb;
8699 void *info_arg;
8700 struct got_pathlist_head *paths;
8701 got_cancel_cb cancel_cb;
8702 void *cancel_arg;
8705 static const struct got_error *
8706 report_file_info(void *arg, struct got_fileindex_entry *ie)
8708 struct report_file_info_arg *a = arg;
8709 struct got_pathlist_entry *pe;
8710 struct got_object_id blob_id, staged_blob_id, commit_id;
8711 struct got_object_id *blob_idp = NULL, *staged_blob_idp = NULL;
8712 struct got_object_id *commit_idp = NULL;
8713 int stage;
8715 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
8716 return got_error(GOT_ERR_CANCELLED);
8718 TAILQ_FOREACH(pe, a->paths, entry) {
8719 if (pe->path_len == 0 || strcmp(pe->path, ie->path) == 0 ||
8720 got_path_is_child(ie->path, pe->path, pe->path_len))
8721 break;
8723 if (pe == NULL) /* not found */
8724 return NULL;
8726 if (got_fileindex_entry_has_blob(ie)) {
8727 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
8728 blob_idp = &blob_id;
8730 stage = got_fileindex_entry_stage_get(ie);
8731 if (stage == GOT_FILEIDX_STAGE_MODIFY ||
8732 stage == GOT_FILEIDX_STAGE_ADD) {
8733 memcpy(staged_blob_id.sha1, ie->staged_blob_sha1,
8734 SHA1_DIGEST_LENGTH);
8735 staged_blob_idp = &staged_blob_id;
8738 if (got_fileindex_entry_has_commit(ie)) {
8739 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
8740 commit_idp = &commit_id;
8743 return a->info_cb(a->info_arg, ie->path, got_fileindex_perms_to_st(ie),
8744 (time_t)ie->mtime_sec, blob_idp, staged_blob_idp, commit_idp);
8747 const struct got_error *
8748 got_worktree_path_info(struct got_worktree *worktree,
8749 struct got_pathlist_head *paths,
8750 got_worktree_path_info_cb info_cb, void *info_arg,
8751 got_cancel_cb cancel_cb, void *cancel_arg)
8754 const struct got_error *err = NULL, *unlockerr;
8755 struct got_fileindex *fileindex = NULL;
8756 char *fileindex_path = NULL;
8757 struct report_file_info_arg arg;
8759 err = lock_worktree(worktree, LOCK_SH);
8760 if (err)
8761 return err;
8763 err = open_fileindex(&fileindex, &fileindex_path, worktree);
8764 if (err)
8765 goto done;
8767 arg.worktree = worktree;
8768 arg.info_cb = info_cb;
8769 arg.info_arg = info_arg;
8770 arg.paths = paths;
8771 arg.cancel_cb = cancel_cb;
8772 arg.cancel_arg = cancel_arg;
8773 err = got_fileindex_for_each_entry_safe(fileindex, report_file_info,
8774 &arg);
8775 done:
8776 free(fileindex_path);
8777 if (fileindex)
8778 got_fileindex_free(fileindex);
8779 unlockerr = lock_worktree(worktree, LOCK_UN);
8780 if (unlockerr && err == NULL)
8781 err = unlockerr;
8782 return err;