Blob


1 /*
2 * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include <sys/stat.h>
18 #include <sys/queue.h>
19 #include <sys/tree.h>
21 #include <dirent.h>
22 #include <limits.h>
23 #include <stddef.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <time.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <sha1.h>
32 #include <zlib.h>
33 #include <fnmatch.h>
34 #include <libgen.h>
35 #include <uuid.h>
36 #include <util.h>
38 #include "got_error.h"
39 #include "got_repository.h"
40 #include "got_reference.h"
41 #include "got_object.h"
42 #include "got_path.h"
43 #include "got_cancel.h"
44 #include "got_worktree.h"
45 #include "got_opentemp.h"
46 #include "got_diff.h"
48 #include "got_lib_worktree.h"
49 #include "got_lib_sha1.h"
50 #include "got_lib_fileindex.h"
51 #include "got_lib_inflate.h"
52 #include "got_lib_delta.h"
53 #include "got_lib_object.h"
54 #include "got_lib_object_parse.h"
55 #include "got_lib_object_create.h"
56 #include "got_lib_object_idset.h"
57 #include "got_lib_diff.h"
59 #ifndef MIN
60 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
61 #endif
63 #define GOT_MERGE_LABEL_MERGED "merged change"
64 #define GOT_MERGE_LABEL_BASE "3-way merge base"
66 static const struct got_error *
67 create_meta_file(const char *path_got, const char *name, const char *content)
68 {
69 const struct got_error *err = NULL;
70 char *path;
72 if (asprintf(&path, "%s/%s", path_got, name) == -1)
73 return got_error_from_errno("asprintf");
75 err = got_path_create_file(path, content);
76 free(path);
77 return err;
78 }
80 static const struct got_error *
81 update_meta_file(const char *path_got, const char *name, const char *content)
82 {
83 const struct got_error *err = NULL;
84 FILE *tmpfile = NULL;
85 char *tmppath = NULL;
86 char *path = NULL;
88 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
89 err = got_error_from_errno("asprintf");
90 path = NULL;
91 goto done;
92 }
94 err = got_opentemp_named(&tmppath, &tmpfile, path);
95 if (err)
96 goto done;
98 if (content) {
99 int len = fprintf(tmpfile, "%s\n", content);
100 if (len != strlen(content) + 1) {
101 err = got_error_from_errno2("fprintf", tmppath);
102 goto done;
106 if (rename(tmppath, path) != 0) {
107 err = got_error_from_errno3("rename", tmppath, path);
108 unlink(tmppath);
109 goto done;
112 done:
113 if (fclose(tmpfile) != 0 && err == NULL)
114 err = got_error_from_errno2("fclose", tmppath);
115 free(tmppath);
116 return err;
119 static const struct got_error *
120 read_meta_file(char **content, const char *path_got, const char *name)
122 const struct got_error *err = NULL;
123 char *path;
124 int fd = -1;
125 ssize_t n;
126 struct stat sb;
128 *content = NULL;
130 if (asprintf(&path, "%s/%s", path_got, name) == -1) {
131 err = got_error_from_errno("asprintf");
132 path = NULL;
133 goto done;
136 fd = open(path, O_RDONLY | O_NOFOLLOW);
137 if (fd == -1) {
138 if (errno == ENOENT)
139 err = got_error_path(path, GOT_ERR_WORKTREE_META);
140 else
141 err = got_error_from_errno2("open", path);
142 goto done;
144 if (flock(fd, LOCK_SH | LOCK_NB) == -1) {
145 err = (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
146 : got_error_from_errno2("flock", path));
147 goto done;
150 if (fstat(fd, &sb) != 0) {
151 err = got_error_from_errno2("fstat", path);
152 goto done;
154 *content = calloc(1, sb.st_size);
155 if (*content == NULL) {
156 err = got_error_from_errno("calloc");
157 goto done;
160 n = read(fd, *content, sb.st_size);
161 if (n != sb.st_size) {
162 err = (n == -1 ? got_error_from_errno2("read", path) :
163 got_error_path(path, GOT_ERR_WORKTREE_META));
164 goto done;
166 if ((*content)[sb.st_size - 1] != '\n') {
167 err = got_error_path(path, GOT_ERR_WORKTREE_META);
168 goto done;
170 (*content)[sb.st_size - 1] = '\0';
172 done:
173 if (fd != -1 && close(fd) == -1 && err == NULL)
174 err = got_error_from_errno2("close", path_got);
175 free(path);
176 if (err) {
177 free(*content);
178 *content = NULL;
180 return err;
183 static const struct got_error *
184 write_head_ref(const char *path_got, struct got_reference *head_ref)
186 const struct got_error *err = NULL;
187 char *refstr = NULL;
189 if (got_ref_is_symbolic(head_ref)) {
190 refstr = got_ref_to_str(head_ref);
191 if (refstr == NULL)
192 return got_error_from_errno("got_ref_to_str");
193 } else {
194 refstr = strdup(got_ref_get_name(head_ref));
195 if (refstr == NULL)
196 return got_error_from_errno("strdup");
198 err = update_meta_file(path_got, GOT_WORKTREE_HEAD_REF, refstr);
199 free(refstr);
200 return err;
203 const struct got_error *
204 got_worktree_init(const char *path, struct got_reference *head_ref,
205 const char *prefix, struct got_repository *repo)
207 const struct got_error *err = NULL;
208 struct got_object_id *commit_id = NULL;
209 uuid_t uuid;
210 uint32_t uuid_status;
211 int obj_type;
212 char *path_got = NULL;
213 char *formatstr = NULL;
214 char *absprefix = NULL;
215 char *basestr = NULL;
216 char *uuidstr = NULL;
218 if (strcmp(path, got_repo_get_path(repo)) == 0) {
219 err = got_error(GOT_ERR_WORKTREE_REPO);
220 goto done;
223 err = got_ref_resolve(&commit_id, repo, head_ref);
224 if (err)
225 return err;
226 err = got_object_get_type(&obj_type, repo, commit_id);
227 if (err)
228 return err;
229 if (obj_type != GOT_OBJ_TYPE_COMMIT)
230 return got_error(GOT_ERR_OBJ_TYPE);
232 if (!got_path_is_absolute(prefix)) {
233 if (asprintf(&absprefix, "/%s", prefix) == -1)
234 return got_error_from_errno("asprintf");
237 /* Create top-level directory (may already exist). */
238 if (mkdir(path, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
239 err = got_error_from_errno2("mkdir", path);
240 goto done;
243 /* Create .got directory (may already exist). */
244 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
245 err = got_error_from_errno("asprintf");
246 goto done;
248 if (mkdir(path_got, GOT_DEFAULT_DIR_MODE) == -1 && errno != EEXIST) {
249 err = got_error_from_errno2("mkdir", path_got);
250 goto done;
253 /* Create an empty lock file. */
254 err = create_meta_file(path_got, GOT_WORKTREE_LOCK, NULL);
255 if (err)
256 goto done;
258 /* Create an empty file index. */
259 err = create_meta_file(path_got, GOT_WORKTREE_FILE_INDEX, NULL);
260 if (err)
261 goto done;
263 /* Write the HEAD reference. */
264 err = write_head_ref(path_got, head_ref);
265 if (err)
266 goto done;
268 /* Record our base commit. */
269 err = got_object_id_str(&basestr, commit_id);
270 if (err)
271 goto done;
272 err = create_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, basestr);
273 if (err)
274 goto done;
276 /* Store path to repository. */
277 err = create_meta_file(path_got, GOT_WORKTREE_REPOSITORY,
278 got_repo_get_path(repo));
279 if (err)
280 goto done;
282 /* Store in-repository path prefix. */
283 err = create_meta_file(path_got, GOT_WORKTREE_PATH_PREFIX,
284 absprefix ? absprefix : prefix);
285 if (err)
286 goto done;
288 /* Generate UUID. */
289 uuid_create(&uuid, &uuid_status);
290 if (uuid_status != uuid_s_ok) {
291 err = got_error_uuid(uuid_status, "uuid_create");
292 goto done;
294 uuid_to_string(&uuid, &uuidstr, &uuid_status);
295 if (uuid_status != uuid_s_ok) {
296 err = got_error_uuid(uuid_status, "uuid_to_string");
297 goto done;
299 err = create_meta_file(path_got, GOT_WORKTREE_UUID, uuidstr);
300 if (err)
301 goto done;
303 /* Stamp work tree with format file. */
304 if (asprintf(&formatstr, "%d", GOT_WORKTREE_FORMAT_VERSION) == -1) {
305 err = got_error_from_errno("asprintf");
306 goto done;
308 err = create_meta_file(path_got, GOT_WORKTREE_FORMAT, formatstr);
309 if (err)
310 goto done;
312 done:
313 free(commit_id);
314 free(path_got);
315 free(formatstr);
316 free(absprefix);
317 free(basestr);
318 free(uuidstr);
319 return err;
322 static const struct got_error *
323 open_worktree(struct got_worktree **worktree, const char *path)
325 const struct got_error *err = NULL;
326 char *path_got;
327 char *formatstr = NULL;
328 char *uuidstr = NULL;
329 char *path_lock = NULL;
330 char *base_commit_id_str = NULL;
331 int version, fd = -1;
332 const char *errstr;
333 struct got_repository *repo = NULL;
334 uint32_t uuid_status;
336 *worktree = NULL;
338 if (asprintf(&path_got, "%s/%s", path, GOT_WORKTREE_GOT_DIR) == -1) {
339 err = got_error_from_errno("asprintf");
340 path_got = NULL;
341 goto done;
344 if (asprintf(&path_lock, "%s/%s", path_got, GOT_WORKTREE_LOCK) == -1) {
345 err = got_error_from_errno("asprintf");
346 path_lock = NULL;
347 goto done;
350 fd = open(path_lock, O_RDWR | O_EXLOCK | O_NONBLOCK);
351 if (fd == -1) {
352 err = (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
353 : got_error_from_errno2("open", path_lock));
354 goto done;
357 err = read_meta_file(&formatstr, path_got, GOT_WORKTREE_FORMAT);
358 if (err)
359 goto done;
361 version = strtonum(formatstr, 1, INT_MAX, &errstr);
362 if (errstr) {
363 err = got_error_msg(GOT_ERR_WORKTREE_META,
364 "could not parse work tree format version number");
365 goto done;
367 if (version != GOT_WORKTREE_FORMAT_VERSION) {
368 err = got_error(GOT_ERR_WORKTREE_VERS);
369 goto done;
372 *worktree = calloc(1, sizeof(**worktree));
373 if (*worktree == NULL) {
374 err = got_error_from_errno("calloc");
375 goto done;
377 (*worktree)->lockfd = -1;
379 (*worktree)->root_path = strdup(path);
380 if ((*worktree)->root_path == NULL) {
381 err = got_error_from_errno("strdup");
382 goto done;
384 err = read_meta_file(&(*worktree)->repo_path, path_got,
385 GOT_WORKTREE_REPOSITORY);
386 if (err)
387 goto done;
389 err = read_meta_file(&(*worktree)->path_prefix, path_got,
390 GOT_WORKTREE_PATH_PREFIX);
391 if (err)
392 goto done;
394 err = read_meta_file(&base_commit_id_str, path_got,
395 GOT_WORKTREE_BASE_COMMIT);
396 if (err)
397 goto done;
399 err = read_meta_file(&uuidstr, path_got, GOT_WORKTREE_UUID);
400 if (err)
401 goto done;
402 uuid_from_string(uuidstr, &(*worktree)->uuid, &uuid_status);
403 if (uuid_status != uuid_s_ok) {
404 err = got_error_uuid(uuid_status, "uuid_from_string");
405 goto done;
408 err = got_repo_open(&repo, (*worktree)->repo_path, NULL);
409 if (err)
410 goto done;
412 err = got_object_resolve_id_str(&(*worktree)->base_commit_id, repo,
413 base_commit_id_str);
414 if (err)
415 goto done;
417 err = read_meta_file(&(*worktree)->head_ref_name, path_got,
418 GOT_WORKTREE_HEAD_REF);
419 done:
420 if (repo)
421 got_repo_close(repo);
422 free(path_got);
423 free(path_lock);
424 free(base_commit_id_str);
425 free(uuidstr);
426 free(formatstr);
427 if (err) {
428 if (fd != -1)
429 close(fd);
430 if (*worktree != NULL)
431 got_worktree_close(*worktree);
432 *worktree = NULL;
433 } else
434 (*worktree)->lockfd = fd;
436 return err;
439 const struct got_error *
440 got_worktree_open(struct got_worktree **worktree, const char *path)
442 const struct got_error *err = NULL;
444 do {
445 err = open_worktree(worktree, path);
446 if (err && !(err->code == GOT_ERR_ERRNO && errno == ENOENT))
447 return err;
448 if (*worktree)
449 return NULL;
450 path = dirname(path);
451 if (path == NULL)
452 return got_error_from_errno2("dirname", path);
453 } while (!((path[0] == '.' || path[0] == '/') && path[1] == '\0'));
455 return got_error(GOT_ERR_NOT_WORKTREE);
458 const struct got_error *
459 got_worktree_close(struct got_worktree *worktree)
461 const struct got_error *err = NULL;
462 free(worktree->repo_path);
463 free(worktree->path_prefix);
464 free(worktree->base_commit_id);
465 free(worktree->head_ref_name);
466 if (worktree->lockfd != -1)
467 if (close(worktree->lockfd) != 0)
468 err = got_error_from_errno2("close",
469 got_worktree_get_root_path(worktree));
470 free(worktree->root_path);
471 free(worktree);
472 return err;
475 const char *
476 got_worktree_get_root_path(struct got_worktree *worktree)
478 return worktree->root_path;
481 const char *
482 got_worktree_get_repo_path(struct got_worktree *worktree)
484 return worktree->repo_path;
487 const char *
488 got_worktree_get_path_prefix(struct got_worktree *worktree)
490 return worktree->path_prefix;
493 const struct got_error *
494 got_worktree_match_path_prefix(int *match, struct got_worktree *worktree,
495 const char *path_prefix)
497 char *absprefix = NULL;
499 if (!got_path_is_absolute(path_prefix)) {
500 if (asprintf(&absprefix, "/%s", path_prefix) == -1)
501 return got_error_from_errno("asprintf");
503 *match = (strcmp(absprefix ? absprefix : path_prefix,
504 worktree->path_prefix) == 0);
505 free(absprefix);
506 return NULL;
509 const char *
510 got_worktree_get_head_ref_name(struct got_worktree *worktree)
512 return worktree->head_ref_name;
515 const struct got_error *
516 got_worktree_set_head_ref(struct got_worktree *worktree,
517 struct got_reference *head_ref)
519 const struct got_error *err = NULL;
520 char *path_got = NULL, *head_ref_name = NULL;
522 if (asprintf(&path_got, "%s/%s", worktree->root_path,
523 GOT_WORKTREE_GOT_DIR) == -1) {
524 err = got_error_from_errno("asprintf");
525 path_got = NULL;
526 goto done;
529 head_ref_name = strdup(got_ref_get_name(head_ref));
530 if (head_ref_name == NULL) {
531 err = got_error_from_errno("strdup");
532 goto done;
535 err = write_head_ref(path_got, head_ref);
536 if (err)
537 goto done;
539 free(worktree->head_ref_name);
540 worktree->head_ref_name = head_ref_name;
541 done:
542 free(path_got);
543 if (err)
544 free(head_ref_name);
545 return err;
548 struct got_object_id *
549 got_worktree_get_base_commit_id(struct got_worktree *worktree)
551 return worktree->base_commit_id;
554 const struct got_error *
555 got_worktree_set_base_commit_id(struct got_worktree *worktree,
556 struct got_repository *repo, struct got_object_id *commit_id)
558 const struct got_error *err;
559 struct got_object *obj = NULL;
560 char *id_str = NULL;
561 char *path_got = NULL;
563 if (asprintf(&path_got, "%s/%s", worktree->root_path,
564 GOT_WORKTREE_GOT_DIR) == -1) {
565 err = got_error_from_errno("asprintf");
566 path_got = NULL;
567 goto done;
570 err = got_object_open(&obj, repo, commit_id);
571 if (err)
572 return err;
574 if (obj->type != GOT_OBJ_TYPE_COMMIT) {
575 err = got_error(GOT_ERR_OBJ_TYPE);
576 goto done;
579 /* Record our base commit. */
580 err = got_object_id_str(&id_str, commit_id);
581 if (err)
582 goto done;
583 err = update_meta_file(path_got, GOT_WORKTREE_BASE_COMMIT, id_str);
584 if (err)
585 goto done;
587 free(worktree->base_commit_id);
588 worktree->base_commit_id = got_object_id_dup(commit_id);
589 if (worktree->base_commit_id == NULL) {
590 err = got_error_from_errno("got_object_id_dup");
591 goto done;
593 done:
594 if (obj)
595 got_object_close(obj);
596 free(id_str);
597 free(path_got);
598 return err;
601 static const struct got_error *
602 lock_worktree(struct got_worktree *worktree, int operation)
604 if (flock(worktree->lockfd, operation | LOCK_NB) == -1)
605 return (errno == EWOULDBLOCK ? got_error(GOT_ERR_WORKTREE_BUSY)
606 : got_error_from_errno2("flock",
607 got_worktree_get_root_path(worktree)));
608 return NULL;
611 static const struct got_error *
612 add_dir_on_disk(struct got_worktree *worktree, const char *path)
614 const struct got_error *err = NULL;
615 char *abspath;
617 if (asprintf(&abspath, "%s/%s", worktree->root_path, path) == -1)
618 return got_error_from_errno("asprintf");
620 err = got_path_mkdir(abspath);
621 if (err && err->code == GOT_ERR_ERRNO && errno == EEXIST) {
622 struct stat sb;
623 err = NULL;
624 if (lstat(abspath, &sb) == -1) {
625 err = got_error_from_errno2("lstat", abspath);
626 } else if (!S_ISDIR(sb.st_mode)) {
627 /* TODO directory is obstructed; do something */
628 err = got_error_path(abspath, GOT_ERR_FILE_OBSTRUCTED);
631 free(abspath);
632 return err;
635 static const struct got_error *
636 check_file_contents_equal(int *same, FILE *f1, FILE *f2)
638 const struct got_error *err = NULL;
639 uint8_t fbuf1[8192];
640 uint8_t fbuf2[8192];
641 size_t flen1 = 0, flen2 = 0;
643 *same = 1;
645 for (;;) {
646 flen1 = fread(fbuf1, 1, sizeof(fbuf1), f1);
647 if (flen1 == 0 && ferror(f1)) {
648 err = got_error_from_errno("fread");
649 break;
651 flen2 = fread(fbuf2, 1, sizeof(fbuf2), f2);
652 if (flen2 == 0 && ferror(f2)) {
653 err = got_error_from_errno("fread");
654 break;
656 if (flen1 == 0) {
657 if (flen2 != 0)
658 *same = 0;
659 break;
660 } else if (flen2 == 0) {
661 if (flen1 != 0)
662 *same = 0;
663 break;
664 } else if (flen1 == flen2) {
665 if (memcmp(fbuf1, fbuf2, flen2) != 0) {
666 *same = 0;
667 break;
669 } else {
670 *same = 0;
671 break;
675 return err;
678 static const struct got_error *
679 check_files_equal(int *same, const char *f1_path, const char *f2_path)
681 const struct got_error *err = NULL;
682 struct stat sb;
683 size_t size1, size2;
684 FILE *f1 = NULL, *f2 = NULL;
686 *same = 1;
688 if (lstat(f1_path, &sb) != 0) {
689 err = got_error_from_errno2("lstat", f1_path);
690 goto done;
692 size1 = sb.st_size;
694 if (lstat(f2_path, &sb) != 0) {
695 err = got_error_from_errno2("lstat", f2_path);
696 goto done;
698 size2 = sb.st_size;
700 if (size1 != size2) {
701 *same = 0;
702 return NULL;
705 f1 = fopen(f1_path, "r");
706 if (f1 == NULL)
707 return got_error_from_errno2("fopen", f1_path);
709 f2 = fopen(f2_path, "r");
710 if (f2 == NULL) {
711 err = got_error_from_errno2("fopen", f2_path);
712 goto done;
715 err = check_file_contents_equal(same, f1, f2);
716 done:
717 if (f1 && fclose(f1) != 0 && err == NULL)
718 err = got_error_from_errno("fclose");
719 if (f2 && fclose(f2) != 0 && err == NULL)
720 err = got_error_from_errno("fclose");
722 return err;
725 /*
726 * Perform a 3-way merge where blob_orig acts as the common ancestor,
727 * the file at deriv_path acts as the first derived version, and the
728 * file on disk acts as the second derived version.
729 */
730 static const struct got_error *
731 merge_file(int *local_changes_subsumed, struct got_worktree *worktree,
732 struct got_blob_object *blob_orig, const char *ondisk_path,
733 const char *path, uint16_t st_mode, const char *deriv_path,
734 const char *label_orig, const char *label_deriv,
735 struct got_repository *repo,
736 got_worktree_checkout_cb progress_cb, void *progress_arg)
738 const struct got_error *err = NULL;
739 int merged_fd = -1;
740 FILE *f_orig = NULL;
741 char *blob_orig_path = NULL;
742 char *merged_path = NULL, *base_path = NULL;
743 int overlapcnt = 0;
744 char *parent;
746 *local_changes_subsumed = 0;
748 parent = dirname(ondisk_path);
749 if (parent == NULL)
750 return got_error_from_errno2("dirname", ondisk_path);
752 if (asprintf(&base_path, "%s/got-merged", parent) == -1)
753 return got_error_from_errno("asprintf");
755 err = got_opentemp_named_fd(&merged_path, &merged_fd, base_path);
756 if (err)
757 goto done;
759 free(base_path);
760 if (asprintf(&base_path, "%s/got-merge-blob-orig", parent) == -1) {
761 err = got_error_from_errno("asprintf");
762 base_path = NULL;
763 goto done;
766 err = got_opentemp_named(&blob_orig_path, &f_orig, base_path);
767 if (err)
768 goto done;
769 if (blob_orig) {
770 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_orig,
771 blob_orig);
772 if (err)
773 goto done;
774 } else {
775 /*
776 * If the file has no blob, this is an "add vs add" conflict,
777 * and we simply use an empty ancestor file to make both files
778 * appear in the merged result in their entirety.
779 */
782 err = got_merge_diff3(&overlapcnt, merged_fd, deriv_path,
783 blob_orig_path, ondisk_path, label_deriv, label_orig, NULL);
784 if (err)
785 goto done;
787 err = (*progress_cb)(progress_arg,
788 overlapcnt > 0 ? GOT_STATUS_CONFLICT : GOT_STATUS_MERGE, path);
789 if (err)
790 goto done;
792 if (fsync(merged_fd) != 0) {
793 err = got_error_from_errno("fsync");
794 goto done;
797 /* Check if a clean merge has subsumed all local changes. */
798 if (overlapcnt == 0) {
799 err = check_files_equal(local_changes_subsumed, deriv_path,
800 merged_path);
801 if (err)
802 goto done;
805 if (fchmod(merged_fd, st_mode) != 0) {
806 err = got_error_from_errno2("fchmod", merged_path);
807 goto done;
810 if (rename(merged_path, ondisk_path) != 0) {
811 err = got_error_from_errno3("rename", merged_path,
812 ondisk_path);
813 goto done;
815 done:
816 if (err) {
817 if (merged_path)
818 unlink(merged_path);
820 if (merged_fd != -1 && close(merged_fd) != 0 && err == NULL)
821 err = got_error_from_errno("close");
822 if (f_orig && fclose(f_orig) != 0 && err == NULL)
823 err = got_error_from_errno("fclose");
824 free(merged_path);
825 free(base_path);
826 if (blob_orig_path) {
827 unlink(blob_orig_path);
828 free(blob_orig_path);
830 return err;
833 /*
834 * Perform a 3-way merge where blob_orig acts as the common ancestor,
835 * blob_deriv acts as the first derived version, and the file on disk
836 * acts as the second derived version.
837 */
838 static const struct got_error *
839 merge_blob(int *local_changes_subsumed, struct got_worktree *worktree,
840 struct got_blob_object *blob_orig, const char *ondisk_path,
841 const char *path, uint16_t st_mode, const char *label_orig,
842 struct got_blob_object *blob_deriv,
843 struct got_object_id *deriv_base_commit_id, struct got_repository *repo,
844 got_worktree_checkout_cb progress_cb, void *progress_arg)
846 const struct got_error *err = NULL;
847 FILE *f_deriv = NULL;
848 char *blob_deriv_path = NULL, *base_path = NULL, *id_str = NULL;
849 char *label_deriv = NULL, *parent;
851 *local_changes_subsumed = 0;
853 parent = dirname(ondisk_path);
854 if (parent == NULL)
855 return got_error_from_errno2("dirname", ondisk_path);
857 free(base_path);
858 if (asprintf(&base_path, "%s/got-merge-blob-deriv", parent) == -1) {
859 err = got_error_from_errno("asprintf");
860 base_path = NULL;
861 goto done;
864 err = got_opentemp_named(&blob_deriv_path, &f_deriv, base_path);
865 if (err)
866 goto done;
867 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f_deriv,
868 blob_deriv);
869 if (err)
870 goto done;
872 err = got_object_id_str(&id_str, deriv_base_commit_id);
873 if (err)
874 goto done;
875 if (asprintf(&label_deriv, "%s: commit %s",
876 GOT_MERGE_LABEL_MERGED, id_str) == -1) {
877 err = got_error_from_errno("asprintf");
878 goto done;
881 err = merge_file(local_changes_subsumed, worktree, blob_orig,
882 ondisk_path, path, st_mode, blob_deriv_path, label_orig,
883 label_deriv, repo, progress_cb, progress_arg);
884 done:
885 if (f_deriv && fclose(f_deriv) != 0 && err == NULL)
886 err = got_error_from_errno("fclose");
887 free(base_path);
888 if (blob_deriv_path) {
889 unlink(blob_deriv_path);
890 free(blob_deriv_path);
892 free(id_str);
893 free(label_deriv);
894 return err;
897 static const struct got_error *
898 create_fileindex_entry(struct got_fileindex *fileindex,
899 struct got_object_id *base_commit_id, const char *ondisk_path,
900 const char *path, struct got_object_id *blob_id)
902 const struct got_error *err = NULL;
903 struct got_fileindex_entry *new_ie;
905 err = got_fileindex_entry_alloc(&new_ie, path);
906 if (err)
907 return err;
909 err = got_fileindex_entry_update(new_ie, ondisk_path,
910 blob_id->sha1, base_commit_id->sha1, 1);
911 if (err)
912 goto done;
914 err = got_fileindex_entry_add(fileindex, new_ie);
915 done:
916 if (err)
917 got_fileindex_entry_free(new_ie);
918 return err;
921 static mode_t
922 get_ondisk_perms(int executable, mode_t st_mode)
924 mode_t xbits = S_IXUSR;
926 if (executable) {
927 /* Map read bits to execute bits. */
928 if (st_mode & S_IRGRP)
929 xbits |= S_IXGRP;
930 if (st_mode & S_IROTH)
931 xbits |= S_IXOTH;
932 return st_mode | xbits;
935 return (st_mode & ~(S_IXUSR | S_IXGRP | S_IXOTH));
938 /* forward declaration */
939 static const struct got_error *
940 install_blob(struct got_worktree *worktree, const char *ondisk_path,
941 const char *path, mode_t te_mode, mode_t st_mode,
942 struct got_blob_object *blob, int restoring_missing_file,
943 int reverting_versioned_file, struct got_repository *repo,
944 got_worktree_checkout_cb progress_cb, void *progress_arg);
946 static const struct got_error *
947 install_symlink(struct got_worktree *worktree, const char *ondisk_path,
948 const char *path, mode_t te_mode, mode_t st_mode,
949 struct got_blob_object *blob, int restoring_missing_file,
950 int reverting_versioned_file, struct got_repository *repo,
951 got_worktree_checkout_cb progress_cb, void *progress_arg)
953 const struct got_error *err = NULL;
954 char target_path[PATH_MAX];
955 size_t len, target_len = 0;
956 char *resolved_path = NULL, *abspath = NULL;
957 const uint8_t *buf = got_object_blob_get_read_buf(blob);
958 size_t hdrlen = got_object_blob_get_hdrlen(blob);
960 /*
961 * Blob object content specifies the target path of the link.
962 * If a symbolic link cannot be installed we instead create
963 * a regular file which contains the link target path stored
964 * in the blob object.
965 */
966 do {
967 err = got_object_blob_read_block(&len, blob);
968 if (len + target_len >= sizeof(target_path)) {
969 /* Path too long; install as a regular file. */
970 got_object_blob_rewind(blob);
971 return install_blob(worktree, ondisk_path, path,
972 GOT_DEFAULT_FILE_MODE, st_mode, blob,
973 restoring_missing_file, reverting_versioned_file,
974 repo, progress_cb, progress_arg);
976 if (len > 0) {
977 /* Skip blob object header first time around. */
978 memcpy(target_path + target_len, buf + hdrlen,
979 len - hdrlen);
980 target_len += len - hdrlen;
981 hdrlen = 0;
983 } while (len != 0);
984 target_path[target_len] = '\0';
986 /*
987 * Relative symlink target lookup should begin at the directory
988 * in which the blob object is being installed.
989 */
990 if (!got_path_is_absolute(target_path)) {
991 char *parent = dirname(ondisk_path);
992 if (asprintf(&abspath, "%s/%s", parent, target_path) == -1) {
993 err = got_error_from_errno("asprintf");
994 goto done;
998 /*
999 * unveil(2) restricts our view of paths in the filesystem.
1000 * ENOENT will occur if a link target path does not exist or
1001 * if it points outside our unveiled path space.
1003 resolved_path = realpath(abspath ? abspath : target_path, NULL);
1004 if (resolved_path == NULL) {
1005 if (errno != ENOENT)
1006 return got_error_from_errno2("realpath", target_path);
1009 /* Only allow symlinks pointing at paths within the work tree. */
1010 if (!got_path_is_child(resolved_path ? resolved_path : (abspath ?
1011 abspath : target_path), worktree->root_path,
1012 strlen(worktree->root_path))) {
1013 /* install as a regular file */
1014 got_object_blob_rewind(blob);
1015 err = install_blob(worktree, ondisk_path, path,
1016 GOT_DEFAULT_FILE_MODE, st_mode, blob,
1017 restoring_missing_file, reverting_versioned_file,
1018 repo, progress_cb, progress_arg);
1019 goto done;
1022 if (symlink(target_path, ondisk_path) == -1) {
1023 if (errno == ENOENT) {
1024 char *parent = dirname(ondisk_path);
1025 if (parent == NULL) {
1026 err = got_error_from_errno2("dirname",
1027 ondisk_path);
1028 goto done;
1030 err = add_dir_on_disk(worktree, parent);
1031 if (err)
1032 goto done;
1034 * Retry, and fall through to error handling
1035 * below if this second attempt fails.
1037 if (symlink(target_path, ondisk_path) != -1) {
1038 err = NULL; /* success */
1039 goto done;
1043 /* Handle errors from first or second creation attempt. */
1044 if (errno == EEXIST) {
1045 struct stat sb;
1046 ssize_t elen;
1047 char etarget[PATH_MAX];
1048 if (lstat(ondisk_path, &sb) == -1) {
1049 err = got_error_from_errno2("lstat",
1050 ondisk_path);
1051 goto done;
1053 if (!S_ISLNK(sb.st_mode)) {
1054 err = got_error_path(ondisk_path,
1055 GOT_ERR_FILE_OBSTRUCTED);
1056 goto done;
1058 elen = readlink(ondisk_path, etarget, sizeof(etarget));
1059 if (elen == -1) {
1060 err = got_error_from_errno2("readlink",
1061 ondisk_path);
1062 goto done;
1064 if (elen == target_len &&
1065 memcmp(etarget, target_path, target_len) == 0)
1066 err = NULL;
1067 else
1068 err = got_error_path(ondisk_path,
1069 GOT_ERR_FILE_OBSTRUCTED);
1070 } else if (errno == ENAMETOOLONG) {
1071 /* bad target path; install as a regular file */
1072 got_object_blob_rewind(blob);
1073 err = install_blob(worktree, ondisk_path, path,
1074 GOT_DEFAULT_FILE_MODE, st_mode, blob,
1075 restoring_missing_file, reverting_versioned_file,
1076 repo, progress_cb, progress_arg);
1077 } else if (errno == ENOTDIR) {
1078 err = got_error_path(ondisk_path,
1079 GOT_ERR_FILE_OBSTRUCTED);
1080 } else {
1081 err = got_error_from_errno3("symlink",
1082 target_path, ondisk_path);
1085 done:
1086 free(resolved_path);
1087 free(abspath);
1088 return err;
1091 static const struct got_error *
1092 install_blob(struct got_worktree *worktree, const char *ondisk_path,
1093 const char *path, mode_t te_mode, mode_t st_mode,
1094 struct got_blob_object *blob, int restoring_missing_file,
1095 int reverting_versioned_file, struct got_repository *repo,
1096 got_worktree_checkout_cb progress_cb, void *progress_arg)
1098 const struct got_error *err = NULL;
1099 int fd = -1;
1100 size_t len, hdrlen;
1101 int update = 0;
1102 char *tmppath = NULL;
1104 if (S_ISLNK(te_mode))
1105 return install_symlink(worktree, ondisk_path, path, te_mode,
1106 st_mode, blob, restoring_missing_file,
1107 reverting_versioned_file, repo, progress_cb, progress_arg);
1109 fd = open(ondisk_path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1110 GOT_DEFAULT_FILE_MODE);
1111 if (fd == -1) {
1112 if (errno == ENOENT) {
1113 char *parent = dirname(path);
1114 if (parent == NULL)
1115 return got_error_from_errno2("dirname", path);
1116 err = add_dir_on_disk(worktree, parent);
1117 if (err)
1118 return err;
1119 fd = open(ondisk_path,
1120 O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
1121 GOT_DEFAULT_FILE_MODE);
1122 if (fd == -1)
1123 return got_error_from_errno2("open",
1124 ondisk_path);
1125 } else if (errno == EEXIST) {
1126 if (!S_ISREG(st_mode)) {
1127 /* TODO file is obstructed; do something */
1128 err = got_error_path(ondisk_path,
1129 GOT_ERR_FILE_OBSTRUCTED);
1130 goto done;
1131 } else {
1132 err = got_opentemp_named_fd(&tmppath, &fd,
1133 ondisk_path);
1134 if (err)
1135 goto done;
1136 update = 1;
1138 } else
1139 return got_error_from_errno2("open", ondisk_path);
1142 if (restoring_missing_file)
1143 err = (*progress_cb)(progress_arg, GOT_STATUS_MISSING, path);
1144 else if (reverting_versioned_file)
1145 err = (*progress_cb)(progress_arg, GOT_STATUS_REVERT, path);
1146 else
1147 err = (*progress_cb)(progress_arg,
1148 update ? GOT_STATUS_UPDATE : GOT_STATUS_ADD, path);
1149 if (err)
1150 goto done;
1152 hdrlen = got_object_blob_get_hdrlen(blob);
1153 do {
1154 const uint8_t *buf = got_object_blob_get_read_buf(blob);
1155 err = got_object_blob_read_block(&len, blob);
1156 if (err)
1157 break;
1158 if (len > 0) {
1159 /* Skip blob object header first time around. */
1160 ssize_t outlen = write(fd, buf + hdrlen, len - hdrlen);
1161 if (outlen == -1) {
1162 err = got_error_from_errno("write");
1163 goto done;
1164 } else if (outlen != len - hdrlen) {
1165 err = got_error(GOT_ERR_IO);
1166 goto done;
1168 hdrlen = 0;
1170 } while (len != 0);
1172 if (fsync(fd) != 0) {
1173 err = got_error_from_errno("fsync");
1174 goto done;
1177 if (update) {
1178 if (rename(tmppath, ondisk_path) != 0) {
1179 err = got_error_from_errno3("rename", tmppath,
1180 ondisk_path);
1181 unlink(tmppath);
1182 goto done;
1186 if (chmod(ondisk_path,
1187 get_ondisk_perms(te_mode & S_IXUSR, st_mode)) == -1) {
1188 err = got_error_from_errno2("chmod", ondisk_path);
1189 goto done;
1192 done:
1193 if (fd != -1 && close(fd) != 0 && err == NULL)
1194 err = got_error_from_errno("close");
1195 free(tmppath);
1196 return err;
1199 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1200 static const struct got_error *
1201 get_modified_file_content_status(unsigned char *status, FILE *f)
1203 const struct got_error *err = NULL;
1204 const char *markers[3] = {
1205 GOT_DIFF_CONFLICT_MARKER_BEGIN,
1206 GOT_DIFF_CONFLICT_MARKER_SEP,
1207 GOT_DIFF_CONFLICT_MARKER_END
1209 int i = 0;
1210 char *line;
1211 size_t len;
1212 const char delim[3] = {'\0', '\0', '\0'};
1214 while (*status == GOT_STATUS_MODIFY) {
1215 line = fparseln(f, &len, NULL, delim, 0);
1216 if (line == NULL) {
1217 if (feof(f))
1218 break;
1219 err = got_ferror(f, GOT_ERR_IO);
1220 break;
1223 if (strncmp(line, markers[i], strlen(markers[i])) == 0) {
1224 if (strcmp(markers[i], GOT_DIFF_CONFLICT_MARKER_END)
1225 == 0)
1226 *status = GOT_STATUS_CONFLICT;
1227 else
1228 i++;
1232 return err;
1235 static int
1236 xbit_differs(struct got_fileindex_entry *ie, uint16_t st_mode)
1238 mode_t ie_mode = got_fileindex_perms_to_st(ie);
1239 return ((ie_mode & S_IXUSR) != (st_mode & S_IXUSR));
1242 static int
1243 stat_info_differs(struct got_fileindex_entry *ie, struct stat *sb)
1245 return !(ie->ctime_sec == sb->st_ctime &&
1246 ie->ctime_nsec == sb->st_ctimensec &&
1247 ie->mtime_sec == sb->st_mtime &&
1248 ie->mtime_nsec == sb->st_mtimensec &&
1249 ie->size == (sb->st_size & 0xffffffff) &&
1250 !xbit_differs(ie, sb->st_mode));
1253 static unsigned char
1254 get_staged_status(struct got_fileindex_entry *ie)
1256 switch (got_fileindex_entry_stage_get(ie)) {
1257 case GOT_FILEIDX_STAGE_ADD:
1258 return GOT_STATUS_ADD;
1259 case GOT_FILEIDX_STAGE_DELETE:
1260 return GOT_STATUS_DELETE;
1261 case GOT_FILEIDX_STAGE_MODIFY:
1262 return GOT_STATUS_MODIFY;
1263 default:
1264 return GOT_STATUS_NO_CHANGE;
1268 static const struct got_error *
1269 get_file_status(unsigned char *status, struct stat *sb,
1270 struct got_fileindex_entry *ie, const char *abspath,
1271 int dirfd, const char *de_name, struct got_repository *repo)
1273 const struct got_error *err = NULL;
1274 struct got_object_id id;
1275 size_t hdrlen;
1276 int fd = -1;
1277 FILE *f = NULL;
1278 uint8_t fbuf[8192];
1279 struct got_blob_object *blob = NULL;
1280 size_t flen, blen;
1281 unsigned char staged_status = get_staged_status(ie);
1283 *status = GOT_STATUS_NO_CHANGE;
1286 * Whenever the caller provides a directory descriptor and a
1287 * directory entry name for the file, use them! This prevents
1288 * race conditions if filesystem paths change beneath our feet.
1290 if (dirfd != -1) {
1291 if (fstatat(dirfd, de_name, sb, AT_SYMLINK_NOFOLLOW) == -1) {
1292 if (errno == ENOENT) {
1293 if (got_fileindex_entry_has_file_on_disk(ie))
1294 *status = GOT_STATUS_MISSING;
1295 else
1296 *status = GOT_STATUS_DELETE;
1297 goto done;
1299 err = got_error_from_errno2("fstatat", abspath);
1300 goto done;
1302 } else {
1303 fd = open(abspath, O_RDONLY | O_NOFOLLOW);
1304 if (fd == -1 && errno != ENOENT)
1305 return got_error_from_errno2("open", abspath);
1306 if (fd == -1 || fstat(fd, sb) == -1) {
1307 if (errno == ENOENT) {
1308 if (got_fileindex_entry_has_file_on_disk(ie))
1309 *status = GOT_STATUS_MISSING;
1310 else
1311 *status = GOT_STATUS_DELETE;
1312 goto done;
1314 err = got_error_from_errno2("fstat", abspath);
1315 goto done;
1319 if (!S_ISREG(sb->st_mode)) {
1320 *status = GOT_STATUS_OBSTRUCTED;
1321 goto done;
1324 if (!got_fileindex_entry_has_file_on_disk(ie)) {
1325 *status = GOT_STATUS_DELETE;
1326 goto done;
1327 } else if (!got_fileindex_entry_has_blob(ie) &&
1328 staged_status != GOT_STATUS_ADD) {
1329 *status = GOT_STATUS_ADD;
1330 goto done;
1333 if (!stat_info_differs(ie, sb))
1334 goto done;
1336 if (staged_status == GOT_STATUS_MODIFY ||
1337 staged_status == GOT_STATUS_ADD)
1338 memcpy(id.sha1, ie->staged_blob_sha1, sizeof(id.sha1));
1339 else
1340 memcpy(id.sha1, ie->blob_sha1, sizeof(id.sha1));
1342 err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf));
1343 if (err)
1344 goto done;
1346 if (dirfd != -1) {
1347 fd = openat(dirfd, de_name, O_RDONLY | O_NOFOLLOW);
1348 if (fd == -1) {
1349 err = got_error_from_errno2("openat", abspath);
1350 goto done;
1354 f = fdopen(fd, "r");
1355 if (f == NULL) {
1356 err = got_error_from_errno2("fdopen", abspath);
1357 goto done;
1359 fd = -1;
1360 hdrlen = got_object_blob_get_hdrlen(blob);
1361 for (;;) {
1362 const uint8_t *bbuf = got_object_blob_get_read_buf(blob);
1363 err = got_object_blob_read_block(&blen, blob);
1364 if (err)
1365 goto done;
1366 /* Skip length of blob object header first time around. */
1367 flen = fread(fbuf, 1, sizeof(fbuf) - hdrlen, f);
1368 if (flen == 0 && ferror(f)) {
1369 err = got_error_from_errno("fread");
1370 goto done;
1372 if (blen == 0) {
1373 if (flen != 0)
1374 *status = GOT_STATUS_MODIFY;
1375 break;
1376 } else if (flen == 0) {
1377 if (blen != 0)
1378 *status = GOT_STATUS_MODIFY;
1379 break;
1380 } else if (blen - hdrlen == flen) {
1381 /* Skip blob object header first time around. */
1382 if (memcmp(bbuf + hdrlen, fbuf, flen) != 0) {
1383 *status = GOT_STATUS_MODIFY;
1384 break;
1386 } else {
1387 *status = GOT_STATUS_MODIFY;
1388 break;
1390 hdrlen = 0;
1393 if (*status == GOT_STATUS_MODIFY) {
1394 rewind(f);
1395 err = get_modified_file_content_status(status, f);
1396 } else if (xbit_differs(ie, sb->st_mode))
1397 *status = GOT_STATUS_MODE_CHANGE;
1398 done:
1399 if (blob)
1400 got_object_blob_close(blob);
1401 if (f != NULL && fclose(f) == EOF && err == NULL)
1402 err = got_error_from_errno2("fclose", abspath);
1403 if (fd != -1 && close(fd) == -1 && err == NULL)
1404 err = got_error_from_errno2("close", abspath);
1405 return err;
1409 * Update timestamps in the file index if a file is unmodified and
1410 * we had to run a full content comparison to find out.
1412 static const struct got_error *
1413 sync_timestamps(char *ondisk_path, unsigned char status,
1414 struct got_fileindex_entry *ie, struct stat *sb)
1416 if (status == GOT_STATUS_NO_CHANGE && stat_info_differs(ie, sb))
1417 return got_fileindex_entry_update(ie, ondisk_path,
1418 ie->blob_sha1, ie->commit_sha1, 1);
1420 return NULL;
1423 static const struct got_error *
1424 update_blob(struct got_worktree *worktree,
1425 struct got_fileindex *fileindex, struct got_fileindex_entry *ie,
1426 struct got_tree_entry *te, const char *path,
1427 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
1428 void *progress_arg)
1430 const struct got_error *err = NULL;
1431 struct got_blob_object *blob = NULL;
1432 char *ondisk_path;
1433 unsigned char status = GOT_STATUS_NO_CHANGE;
1434 struct stat sb;
1436 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, path) == -1)
1437 return got_error_from_errno("asprintf");
1439 if (ie) {
1440 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE) {
1441 err = got_error_path(ie->path, GOT_ERR_FILE_STAGED);
1442 goto done;
1444 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
1445 repo);
1446 if (err)
1447 goto done;
1448 if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE)
1449 sb.st_mode = got_fileindex_perms_to_st(ie);
1450 } else
1451 sb.st_mode = GOT_DEFAULT_FILE_MODE;
1453 if (status == GOT_STATUS_OBSTRUCTED) {
1454 err = (*progress_cb)(progress_arg, status, path);
1455 goto done;
1457 if (status == GOT_STATUS_CONFLICT) {
1458 err = (*progress_cb)(progress_arg, GOT_STATUS_CANNOT_UPDATE,
1459 path);
1460 goto done;
1463 if (ie && status != GOT_STATUS_MISSING &&
1464 (te->mode & S_IXUSR) == (sb.st_mode & S_IXUSR)) {
1465 if (got_fileindex_entry_has_commit(ie) &&
1466 memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
1467 SHA1_DIGEST_LENGTH) == 0) {
1468 err = sync_timestamps(ondisk_path, status, ie, &sb);
1469 if (err)
1470 goto done;
1471 err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
1472 path);
1473 goto done;
1475 if (got_fileindex_entry_has_blob(ie) &&
1476 memcmp(ie->blob_sha1, te->id.sha1,
1477 SHA1_DIGEST_LENGTH) == 0) {
1478 err = sync_timestamps(ondisk_path, status, ie, &sb);
1479 goto done;
1483 err = got_object_open_as_blob(&blob, repo, &te->id, 8192);
1484 if (err)
1485 goto done;
1487 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_ADD) {
1488 int update_timestamps;
1489 struct got_blob_object *blob2 = NULL;
1490 char *label_orig = NULL;
1491 if (got_fileindex_entry_has_blob(ie)) {
1492 struct got_object_id id2;
1493 memcpy(id2.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
1494 err = got_object_open_as_blob(&blob2, repo, &id2, 8192);
1495 if (err)
1496 goto done;
1498 if (got_fileindex_entry_has_commit(ie)) {
1499 char id_str[SHA1_DIGEST_STRING_LENGTH];
1500 if (got_sha1_digest_to_str(ie->commit_sha1, id_str,
1501 sizeof(id_str)) == NULL) {
1502 err = got_error_path(id_str,
1503 GOT_ERR_BAD_OBJ_ID_STR);
1504 goto done;
1506 if (asprintf(&label_orig, "%s: commit %s",
1507 GOT_MERGE_LABEL_BASE, id_str) == -1) {
1508 err = got_error_from_errno("asprintf");
1509 goto done;
1512 err = merge_blob(&update_timestamps, worktree, blob2,
1513 ondisk_path, path, sb.st_mode, label_orig, blob,
1514 worktree->base_commit_id, repo,
1515 progress_cb, progress_arg);
1516 free(label_orig);
1517 if (blob2)
1518 got_object_blob_close(blob2);
1519 if (err)
1520 goto done;
1522 * Do not update timestamps of files with local changes.
1523 * Otherwise, a future status walk would treat them as
1524 * unmodified files again.
1526 err = got_fileindex_entry_update(ie, ondisk_path,
1527 blob->id.sha1, worktree->base_commit_id->sha1,
1528 update_timestamps);
1529 } else if (status == GOT_STATUS_MODE_CHANGE) {
1530 err = got_fileindex_entry_update(ie, ondisk_path,
1531 blob->id.sha1, worktree->base_commit_id->sha1, 0);
1532 } else if (status == GOT_STATUS_DELETE) {
1533 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
1534 if (err)
1535 goto done;
1536 err = got_fileindex_entry_update(ie, ondisk_path,
1537 blob->id.sha1, worktree->base_commit_id->sha1, 0);
1538 if (err)
1539 goto done;
1540 } else {
1541 err = install_blob(worktree, ondisk_path, path, te->mode,
1542 sb.st_mode, blob, status == GOT_STATUS_MISSING, 0,
1543 repo, progress_cb, progress_arg);
1544 if (err)
1545 goto done;
1546 if (ie) {
1547 err = got_fileindex_entry_update(ie, ondisk_path,
1548 blob->id.sha1, worktree->base_commit_id->sha1, 1);
1549 } else {
1550 err = create_fileindex_entry(fileindex,
1551 worktree->base_commit_id, ondisk_path, path,
1552 &blob->id);
1554 if (err)
1555 goto done;
1557 got_object_blob_close(blob);
1558 done:
1559 free(ondisk_path);
1560 return err;
1563 static const struct got_error *
1564 remove_ondisk_file(const char *root_path, const char *path)
1566 const struct got_error *err = NULL;
1567 char *ondisk_path = NULL;
1569 if (asprintf(&ondisk_path, "%s/%s", root_path, path) == -1)
1570 return got_error_from_errno("asprintf");
1572 if (unlink(ondisk_path) == -1) {
1573 if (errno != ENOENT)
1574 err = got_error_from_errno2("unlink", ondisk_path);
1575 } else {
1576 char *parent = dirname(ondisk_path);
1577 while (parent && strcmp(parent, root_path) != 0) {
1578 if (rmdir(parent) == -1) {
1579 if (errno != ENOTEMPTY)
1580 err = got_error_from_errno2("rmdir",
1581 parent);
1582 break;
1584 parent = dirname(parent);
1587 free(ondisk_path);
1588 return err;
1591 static const struct got_error *
1592 delete_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
1593 struct got_fileindex_entry *ie, struct got_repository *repo,
1594 got_worktree_checkout_cb progress_cb, void *progress_arg)
1596 const struct got_error *err = NULL;
1597 unsigned char status;
1598 struct stat sb;
1599 char *ondisk_path;
1601 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
1602 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
1604 if (asprintf(&ondisk_path, "%s/%s", worktree->root_path, ie->path)
1605 == -1)
1606 return got_error_from_errno("asprintf");
1608 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, repo);
1609 if (err)
1610 goto done;
1612 if (status == GOT_STATUS_MODIFY || status == GOT_STATUS_CONFLICT ||
1613 status == GOT_STATUS_ADD) {
1614 err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, ie->path);
1615 if (err)
1616 goto done;
1618 * Preserve the working file and change the deleted blob's
1619 * entry into a schedule-add entry.
1621 err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL,
1622 0);
1623 } else {
1624 err = (*progress_cb)(progress_arg, GOT_STATUS_DELETE, ie->path);
1625 if (err)
1626 goto done;
1627 if (status == GOT_STATUS_NO_CHANGE) {
1628 err = remove_ondisk_file(worktree->root_path, ie->path);
1629 if (err)
1630 goto done;
1632 got_fileindex_entry_remove(fileindex, ie);
1634 done:
1635 free(ondisk_path);
1636 return err;
1639 struct diff_cb_arg {
1640 struct got_fileindex *fileindex;
1641 struct got_worktree *worktree;
1642 struct got_repository *repo;
1643 got_worktree_checkout_cb progress_cb;
1644 void *progress_arg;
1645 got_cancel_cb cancel_cb;
1646 void *cancel_arg;
1649 static const struct got_error *
1650 diff_old_new(void *arg, struct got_fileindex_entry *ie,
1651 struct got_tree_entry *te, const char *parent_path)
1653 struct diff_cb_arg *a = arg;
1655 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
1656 return got_error(GOT_ERR_CANCELLED);
1658 return update_blob(a->worktree, a->fileindex, ie, te,
1659 ie->path, a->repo, a->progress_cb, a->progress_arg);
1662 static const struct got_error *
1663 diff_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
1665 struct diff_cb_arg *a = arg;
1667 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
1668 return got_error(GOT_ERR_CANCELLED);
1670 return delete_blob(a->worktree, a->fileindex, ie,
1671 a->repo, a->progress_cb, a->progress_arg);
1674 static const struct got_error *
1675 diff_new(void *arg, struct got_tree_entry *te, const char *parent_path)
1677 struct diff_cb_arg *a = arg;
1678 const struct got_error *err;
1679 char *path;
1681 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
1682 return got_error(GOT_ERR_CANCELLED);
1684 if (got_object_tree_entry_is_submodule(te))
1685 return NULL;
1687 if (asprintf(&path, "%s%s%s", parent_path,
1688 parent_path[0] ? "/" : "", te->name)
1689 == -1)
1690 return got_error_from_errno("asprintf");
1692 if (S_ISDIR(te->mode))
1693 err = add_dir_on_disk(a->worktree, path);
1694 else
1695 err = update_blob(a->worktree, a->fileindex, NULL, te, path,
1696 a->repo, a->progress_cb, a->progress_arg);
1698 free(path);
1699 return err;
1702 static const struct got_error *
1703 get_ref_name(char **refname, struct got_worktree *worktree, const char *prefix)
1705 const struct got_error *err = NULL;
1706 char *uuidstr = NULL;
1707 uint32_t uuid_status;
1709 *refname = NULL;
1711 uuid_to_string(&worktree->uuid, &uuidstr, &uuid_status);
1712 if (uuid_status != uuid_s_ok)
1713 return got_error_uuid(uuid_status, "uuid_to_string");
1715 if (asprintf(refname, "%s-%s", prefix, uuidstr)
1716 == -1) {
1717 err = got_error_from_errno("asprintf");
1718 *refname = NULL;
1720 free(uuidstr);
1721 return err;
1724 const struct got_error *
1725 got_worktree_get_base_ref_name(char **refname, struct got_worktree *worktree)
1727 return get_ref_name(refname, worktree, GOT_WORKTREE_BASE_REF_PREFIX);
1730 static const struct got_error *
1731 get_rebase_tmp_ref_name(char **refname, struct got_worktree *worktree)
1733 return get_ref_name(refname, worktree,
1734 GOT_WORKTREE_REBASE_TMP_REF_PREFIX);
1737 static const struct got_error *
1738 get_newbase_symref_name(char **refname, struct got_worktree *worktree)
1740 return get_ref_name(refname, worktree, GOT_WORKTREE_NEWBASE_REF_PREFIX);
1743 static const struct got_error *
1744 get_rebase_branch_symref_name(char **refname, struct got_worktree *worktree)
1746 return get_ref_name(refname, worktree,
1747 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX);
1750 static const struct got_error *
1751 get_rebase_commit_ref_name(char **refname, struct got_worktree *worktree)
1753 return get_ref_name(refname, worktree,
1754 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX);
1757 static const struct got_error *
1758 get_histedit_tmp_ref_name(char **refname, struct got_worktree *worktree)
1760 return get_ref_name(refname, worktree,
1761 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX);
1764 static const struct got_error *
1765 get_histedit_branch_symref_name(char **refname, struct got_worktree *worktree)
1767 return get_ref_name(refname, worktree,
1768 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX);
1771 static const struct got_error *
1772 get_histedit_base_commit_ref_name(char **refname, struct got_worktree *worktree)
1774 return get_ref_name(refname, worktree,
1775 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX);
1778 static const struct got_error *
1779 get_histedit_commit_ref_name(char **refname, struct got_worktree *worktree)
1781 return get_ref_name(refname, worktree,
1782 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX);
1785 const struct got_error *
1786 got_worktree_get_histedit_script_path(char **path,
1787 struct got_worktree *worktree)
1789 if (asprintf(path, "%s/%s/%s", worktree->root_path,
1790 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_HISTEDIT_SCRIPT) == -1) {
1791 *path = NULL;
1792 return got_error_from_errno("asprintf");
1794 return NULL;
1798 * Prevent Git's garbage collector from deleting our base commit by
1799 * setting a reference to our base commit's ID.
1801 static const struct got_error *
1802 ref_base_commit(struct got_worktree *worktree, struct got_repository *repo)
1804 const struct got_error *err = NULL;
1805 struct got_reference *ref = NULL;
1806 char *refname;
1808 err = got_worktree_get_base_ref_name(&refname, worktree);
1809 if (err)
1810 return err;
1812 err = got_ref_alloc(&ref, refname, worktree->base_commit_id);
1813 if (err)
1814 goto done;
1816 err = got_ref_write(ref, repo);
1817 done:
1818 free(refname);
1819 if (ref)
1820 got_ref_close(ref);
1821 return err;
1824 static const struct got_error *
1825 get_fileindex_path(char **fileindex_path, struct got_worktree *worktree)
1827 const struct got_error *err = NULL;
1829 if (asprintf(fileindex_path, "%s/%s/%s", worktree->root_path,
1830 GOT_WORKTREE_GOT_DIR, GOT_WORKTREE_FILE_INDEX) == -1) {
1831 err = got_error_from_errno("asprintf");
1832 *fileindex_path = NULL;
1834 return err;
1838 static const struct got_error *
1839 open_fileindex(struct got_fileindex **fileindex, char **fileindex_path,
1840 struct got_worktree *worktree)
1842 const struct got_error *err = NULL;
1843 FILE *index = NULL;
1845 *fileindex_path = NULL;
1846 *fileindex = got_fileindex_alloc();
1847 if (*fileindex == NULL)
1848 return got_error_from_errno("got_fileindex_alloc");
1850 err = get_fileindex_path(fileindex_path, worktree);
1851 if (err)
1852 goto done;
1854 index = fopen(*fileindex_path, "rb");
1855 if (index == NULL) {
1856 if (errno != ENOENT)
1857 err = got_error_from_errno2("fopen", *fileindex_path);
1858 } else {
1859 err = got_fileindex_read(*fileindex, index);
1860 if (fclose(index) != 0 && err == NULL)
1861 err = got_error_from_errno("fclose");
1863 done:
1864 if (err) {
1865 free(*fileindex_path);
1866 *fileindex_path = NULL;
1867 got_fileindex_free(*fileindex);
1868 *fileindex = NULL;
1870 return err;
1873 struct bump_base_commit_id_arg {
1874 struct got_object_id *base_commit_id;
1875 const char *path;
1876 size_t path_len;
1877 const char *entry_name;
1878 got_worktree_checkout_cb progress_cb;
1879 void *progress_arg;
1882 /* Bump base commit ID of all files within an updated part of the work tree. */
1883 static const struct got_error *
1884 bump_base_commit_id(void *arg, struct got_fileindex_entry *ie)
1886 const struct got_error *err;
1887 struct bump_base_commit_id_arg *a = arg;
1889 if (a->entry_name) {
1890 if (strcmp(ie->path, a->path) != 0)
1891 return NULL;
1892 } else if (!got_path_is_child(ie->path, a->path, a->path_len))
1893 return NULL;
1895 if (memcmp(ie->commit_sha1, a->base_commit_id->sha1,
1896 SHA1_DIGEST_LENGTH) == 0)
1897 return NULL;
1899 if (a->progress_cb) {
1900 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_BUMP_BASE,
1901 ie->path);
1902 if (err)
1903 return err;
1905 memcpy(ie->commit_sha1, a->base_commit_id->sha1, SHA1_DIGEST_LENGTH);
1906 return NULL;
1909 static const struct got_error *
1910 sync_fileindex(struct got_fileindex *fileindex, const char *fileindex_path)
1912 const struct got_error *err = NULL;
1913 char *new_fileindex_path = NULL;
1914 FILE *new_index = NULL;
1915 struct timespec timeout;
1917 err = got_opentemp_named(&new_fileindex_path, &new_index,
1918 fileindex_path);
1919 if (err)
1920 goto done;
1922 err = got_fileindex_write(fileindex, new_index);
1923 if (err)
1924 goto done;
1926 if (rename(new_fileindex_path, fileindex_path) != 0) {
1927 err = got_error_from_errno3("rename", new_fileindex_path,
1928 fileindex_path);
1929 unlink(new_fileindex_path);
1933 * Sleep for a short amount of time to ensure that files modified after
1934 * this program exits have a different time stamp from the one which
1935 * was recorded in the file index.
1937 timeout.tv_sec = 0;
1938 timeout.tv_nsec = 1;
1939 nanosleep(&timeout, NULL);
1940 done:
1941 if (new_index)
1942 fclose(new_index);
1943 free(new_fileindex_path);
1944 return err;
1947 static const struct got_error *
1948 find_tree_entry_for_checkout(int *entry_type, char **tree_relpath,
1949 struct got_object_id **tree_id, const char *wt_relpath,
1950 struct got_worktree *worktree, struct got_repository *repo)
1952 const struct got_error *err = NULL;
1953 struct got_object_id *id = NULL;
1954 char *in_repo_path = NULL;
1955 int is_root_wt = got_path_is_root_dir(worktree->path_prefix);
1957 *entry_type = GOT_OBJ_TYPE_ANY;
1958 *tree_relpath = NULL;
1959 *tree_id = NULL;
1961 if (wt_relpath[0] == '\0') {
1962 /* Check out all files within the work tree. */
1963 *entry_type = GOT_OBJ_TYPE_TREE;
1964 *tree_relpath = strdup("");
1965 if (*tree_relpath == NULL) {
1966 err = got_error_from_errno("strdup");
1967 goto done;
1969 err = got_object_id_by_path(tree_id, repo,
1970 worktree->base_commit_id, worktree->path_prefix);
1971 if (err)
1972 goto done;
1973 return NULL;
1976 /* Check out a subset of files in the work tree. */
1978 if (asprintf(&in_repo_path, "%s%s%s", worktree->path_prefix,
1979 is_root_wt ? "" : "/", wt_relpath) == -1) {
1980 err = got_error_from_errno("asprintf");
1981 goto done;
1984 err = got_object_id_by_path(&id, repo, worktree->base_commit_id,
1985 in_repo_path);
1986 if (err)
1987 goto done;
1989 free(in_repo_path);
1990 in_repo_path = NULL;
1992 err = got_object_get_type(entry_type, repo, id);
1993 if (err)
1994 goto done;
1996 if (*entry_type == GOT_OBJ_TYPE_BLOB) {
1997 /* Check out a single file. */
1998 if (strchr(wt_relpath, '/') == NULL) {
1999 /* Check out a single file in work tree's root dir. */
2000 in_repo_path = strdup(worktree->path_prefix);
2001 if (in_repo_path == NULL) {
2002 err = got_error_from_errno("strdup");
2003 goto done;
2005 *tree_relpath = strdup("");
2006 if (*tree_relpath == NULL) {
2007 err = got_error_from_errno("strdup");
2008 goto done;
2010 } else {
2011 /* Check out a single file in a subdirectory. */
2012 err = got_path_dirname(tree_relpath, wt_relpath);
2013 if (err)
2014 return err;
2015 if (asprintf(&in_repo_path, "%s%s%s",
2016 worktree->path_prefix, is_root_wt ? "" : "/",
2017 *tree_relpath) == -1) {
2018 err = got_error_from_errno("asprintf");
2019 goto done;
2022 err = got_object_id_by_path(tree_id, repo,
2023 worktree->base_commit_id, in_repo_path);
2024 } else {
2025 /* Check out all files within a subdirectory. */
2026 *tree_id = got_object_id_dup(id);
2027 if (*tree_id == NULL) {
2028 err = got_error_from_errno("got_object_id_dup");
2029 goto done;
2031 *tree_relpath = strdup(wt_relpath);
2032 if (*tree_relpath == NULL) {
2033 err = got_error_from_errno("strdup");
2034 goto done;
2037 done:
2038 free(id);
2039 free(in_repo_path);
2040 if (err) {
2041 *entry_type = GOT_OBJ_TYPE_ANY;
2042 free(*tree_relpath);
2043 *tree_relpath = NULL;
2044 free(*tree_id);
2045 *tree_id = NULL;
2047 return err;
2050 static const struct got_error *
2051 checkout_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
2052 const char *relpath, struct got_object_id *tree_id, const char *entry_name,
2053 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
2054 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
2056 const struct got_error *err = NULL;
2057 struct got_commit_object *commit = NULL;
2058 struct got_tree_object *tree = NULL;
2059 struct got_fileindex_diff_tree_cb diff_cb;
2060 struct diff_cb_arg arg;
2062 err = ref_base_commit(worktree, repo);
2063 if (err) {
2064 if (!(err->code == GOT_ERR_ERRNO &&
2065 (errno == EACCES || errno == EROFS)))
2066 goto done;
2067 err = (*progress_cb)(progress_arg,
2068 GOT_STATUS_BASE_REF_ERR, worktree->root_path);
2069 if (err)
2070 return err;
2073 err = got_object_open_as_commit(&commit, repo,
2074 worktree->base_commit_id);
2075 if (err)
2076 goto done;
2078 err = got_object_open_as_tree(&tree, repo, tree_id);
2079 if (err)
2080 goto done;
2082 if (entry_name &&
2083 got_object_tree_find_entry(tree, entry_name) == NULL) {
2084 err = got_error(GOT_ERR_NO_TREE_ENTRY);
2085 goto done;
2088 diff_cb.diff_old_new = diff_old_new;
2089 diff_cb.diff_old = diff_old;
2090 diff_cb.diff_new = diff_new;
2091 arg.fileindex = fileindex;
2092 arg.worktree = worktree;
2093 arg.repo = repo;
2094 arg.progress_cb = progress_cb;
2095 arg.progress_arg = progress_arg;
2096 arg.cancel_cb = cancel_cb;
2097 arg.cancel_arg = cancel_arg;
2098 err = got_fileindex_diff_tree(fileindex, tree, relpath,
2099 entry_name, repo, &diff_cb, &arg);
2100 done:
2101 if (tree)
2102 got_object_tree_close(tree);
2103 if (commit)
2104 got_object_commit_close(commit);
2105 return err;
2108 const struct got_error *
2109 got_worktree_checkout_files(struct got_worktree *worktree,
2110 struct got_pathlist_head *paths, struct got_repository *repo,
2111 got_worktree_checkout_cb progress_cb, void *progress_arg,
2112 got_cancel_cb cancel_cb, void *cancel_arg)
2114 const struct got_error *err = NULL, *sync_err, *unlockerr;
2115 struct got_commit_object *commit = NULL;
2116 struct got_tree_object *tree = NULL;
2117 struct got_fileindex *fileindex = NULL;
2118 char *fileindex_path = NULL;
2119 struct got_pathlist_entry *pe;
2120 struct tree_path_data {
2121 SIMPLEQ_ENTRY(tree_path_data) entry;
2122 struct got_object_id *tree_id;
2123 int entry_type;
2124 char *relpath;
2125 char *entry_name;
2126 } *tpd = NULL;
2127 SIMPLEQ_HEAD(tree_paths, tree_path_data) tree_paths;
2129 SIMPLEQ_INIT(&tree_paths);
2131 err = lock_worktree(worktree, LOCK_EX);
2132 if (err)
2133 return err;
2135 /* Map all specified paths to in-repository trees. */
2136 TAILQ_FOREACH(pe, paths, entry) {
2137 tpd = malloc(sizeof(*tpd));
2138 if (tpd == NULL) {
2139 err = got_error_from_errno("malloc");
2140 goto done;
2143 err = find_tree_entry_for_checkout(&tpd->entry_type,
2144 &tpd->relpath, &tpd->tree_id, pe->path, worktree, repo);
2145 if (err) {
2146 free(tpd);
2147 goto done;
2150 if (tpd->entry_type == GOT_OBJ_TYPE_BLOB) {
2151 err = got_path_basename(&tpd->entry_name, pe->path);
2152 if (err) {
2153 free(tpd->relpath);
2154 free(tpd->tree_id);
2155 free(tpd);
2156 goto done;
2158 } else
2159 tpd->entry_name = NULL;
2161 SIMPLEQ_INSERT_TAIL(&tree_paths, tpd, entry);
2165 * Read the file index.
2166 * Checking out files is supposed to be an idempotent operation.
2167 * If the on-disk file index is incomplete we will try to complete it.
2169 err = open_fileindex(&fileindex, &fileindex_path, worktree);
2170 if (err)
2171 goto done;
2173 tpd = SIMPLEQ_FIRST(&tree_paths);
2174 TAILQ_FOREACH(pe, paths, entry) {
2175 struct bump_base_commit_id_arg bbc_arg;
2177 err = checkout_files(worktree, fileindex, tpd->relpath,
2178 tpd->tree_id, tpd->entry_name, repo,
2179 progress_cb, progress_arg, cancel_cb, cancel_arg);
2180 if (err)
2181 break;
2183 bbc_arg.base_commit_id = worktree->base_commit_id;
2184 bbc_arg.entry_name = tpd->entry_name;
2185 bbc_arg.path = pe->path;
2186 bbc_arg.path_len = pe->path_len;
2187 bbc_arg.progress_cb = progress_cb;
2188 bbc_arg.progress_arg = progress_arg;
2189 err = got_fileindex_for_each_entry_safe(fileindex,
2190 bump_base_commit_id, &bbc_arg);
2191 if (err)
2192 break;
2194 tpd = SIMPLEQ_NEXT(tpd, entry);
2196 sync_err = sync_fileindex(fileindex, fileindex_path);
2197 if (sync_err && err == NULL)
2198 err = sync_err;
2199 done:
2200 free(fileindex_path);
2201 if (tree)
2202 got_object_tree_close(tree);
2203 if (commit)
2204 got_object_commit_close(commit);
2205 if (fileindex)
2206 got_fileindex_free(fileindex);
2207 while (!SIMPLEQ_EMPTY(&tree_paths)) {
2208 tpd = SIMPLEQ_FIRST(&tree_paths);
2209 SIMPLEQ_REMOVE_HEAD(&tree_paths, entry);
2210 free(tpd->relpath);
2211 free(tpd->tree_id);
2212 free(tpd);
2214 unlockerr = lock_worktree(worktree, LOCK_SH);
2215 if (unlockerr && err == NULL)
2216 err = unlockerr;
2217 return err;
2220 struct merge_file_cb_arg {
2221 struct got_worktree *worktree;
2222 struct got_fileindex *fileindex;
2223 got_worktree_checkout_cb progress_cb;
2224 void *progress_arg;
2225 got_cancel_cb cancel_cb;
2226 void *cancel_arg;
2227 const char *label_orig;
2228 struct got_object_id *commit_id2;
2231 static const struct got_error *
2232 merge_file_cb(void *arg, struct got_blob_object *blob1,
2233 struct got_blob_object *blob2, struct got_object_id *id1,
2234 struct got_object_id *id2, const char *path1, const char *path2,
2235 mode_t mode1, mode_t mode2, struct got_repository *repo)
2237 static const struct got_error *err = NULL;
2238 struct merge_file_cb_arg *a = arg;
2239 struct got_fileindex_entry *ie;
2240 char *ondisk_path = NULL;
2241 struct stat sb;
2242 unsigned char status;
2243 int local_changes_subsumed;
2245 if (blob1 && blob2) {
2246 ie = got_fileindex_entry_get(a->fileindex, path2,
2247 strlen(path2));
2248 if (ie == NULL)
2249 return (*a->progress_cb)(a->progress_arg,
2250 GOT_STATUS_MISSING, path2);
2252 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2253 path2) == -1)
2254 return got_error_from_errno("asprintf");
2256 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2257 repo);
2258 if (err)
2259 goto done;
2261 if (status == GOT_STATUS_DELETE) {
2262 err = (*a->progress_cb)(a->progress_arg,
2263 GOT_STATUS_MERGE, path2);
2264 goto done;
2266 if (status != GOT_STATUS_NO_CHANGE &&
2267 status != GOT_STATUS_MODIFY &&
2268 status != GOT_STATUS_CONFLICT &&
2269 status != GOT_STATUS_ADD) {
2270 err = (*a->progress_cb)(a->progress_arg, status, path2);
2271 goto done;
2274 err = merge_blob(&local_changes_subsumed, a->worktree, blob1,
2275 ondisk_path, path2, sb.st_mode, a->label_orig, blob2,
2276 a->commit_id2, repo, a->progress_cb, a->progress_arg);
2277 } else if (blob1) {
2278 ie = got_fileindex_entry_get(a->fileindex, path1,
2279 strlen(path1));
2280 if (ie == NULL)
2281 return (*a->progress_cb)(a->progress_arg,
2282 GOT_STATUS_MISSING, path1);
2284 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2285 path1) == -1)
2286 return got_error_from_errno("asprintf");
2288 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL,
2289 repo);
2290 if (err)
2291 goto done;
2293 switch (status) {
2294 case GOT_STATUS_NO_CHANGE:
2295 err = (*a->progress_cb)(a->progress_arg,
2296 GOT_STATUS_DELETE, path1);
2297 if (err)
2298 goto done;
2299 err = remove_ondisk_file(a->worktree->root_path, path1);
2300 if (err)
2301 goto done;
2302 if (ie)
2303 got_fileindex_entry_mark_deleted_from_disk(ie);
2304 break;
2305 case GOT_STATUS_DELETE:
2306 case GOT_STATUS_MISSING:
2307 err = (*a->progress_cb)(a->progress_arg,
2308 GOT_STATUS_DELETE, path1);
2309 if (err)
2310 goto done;
2311 if (ie)
2312 got_fileindex_entry_mark_deleted_from_disk(ie);
2313 break;
2314 case GOT_STATUS_ADD:
2315 case GOT_STATUS_MODIFY:
2316 case GOT_STATUS_CONFLICT:
2317 err = (*a->progress_cb)(a->progress_arg,
2318 GOT_STATUS_CANNOT_DELETE, path1);
2319 if (err)
2320 goto done;
2321 break;
2322 case GOT_STATUS_OBSTRUCTED:
2323 err = (*a->progress_cb)(a->progress_arg, status, path1);
2324 if (err)
2325 goto done;
2326 break;
2327 default:
2328 break;
2330 } else if (blob2) {
2331 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
2332 path2) == -1)
2333 return got_error_from_errno("asprintf");
2334 ie = got_fileindex_entry_get(a->fileindex, path2,
2335 strlen(path2));
2336 if (ie) {
2337 err = get_file_status(&status, &sb, ie, ondisk_path,
2338 -1, NULL, repo);
2339 if (err)
2340 goto done;
2341 if (status != GOT_STATUS_NO_CHANGE &&
2342 status != GOT_STATUS_MODIFY &&
2343 status != GOT_STATUS_CONFLICT &&
2344 status != GOT_STATUS_ADD) {
2345 err = (*a->progress_cb)(a->progress_arg,
2346 status, path2);
2347 goto done;
2349 err = merge_blob(&local_changes_subsumed, a->worktree,
2350 NULL, ondisk_path, path2, sb.st_mode,
2351 a->label_orig, blob2, a->commit_id2, repo,
2352 a->progress_cb,
2353 a->progress_arg);
2354 if (status == GOT_STATUS_DELETE) {
2355 err = got_fileindex_entry_update(ie,
2356 ondisk_path, blob2->id.sha1,
2357 a->worktree->base_commit_id->sha1, 0);
2358 if (err)
2359 goto done;
2361 } else {
2362 sb.st_mode = GOT_DEFAULT_FILE_MODE;
2363 err = install_blob(a->worktree, ondisk_path, path2,
2364 /* XXX get this from parent tree! */
2365 GOT_DEFAULT_FILE_MODE,
2366 sb.st_mode, blob2, 0, 0, repo,
2367 a->progress_cb, a->progress_arg);
2368 if (err)
2369 goto done;
2370 err = got_fileindex_entry_alloc(&ie, path2);
2371 if (err)
2372 goto done;
2373 err = got_fileindex_entry_update(ie, ondisk_path,
2374 NULL, NULL, 1);
2375 if (err) {
2376 got_fileindex_entry_free(ie);
2377 goto done;
2379 err = got_fileindex_entry_add(a->fileindex, ie);
2380 if (err) {
2381 got_fileindex_entry_free(ie);
2382 goto done;
2386 done:
2387 free(ondisk_path);
2388 return err;
2391 struct check_merge_ok_arg {
2392 struct got_worktree *worktree;
2393 struct got_repository *repo;
2396 static const struct got_error *
2397 check_merge_ok(void *arg, struct got_fileindex_entry *ie)
2399 const struct got_error *err = NULL;
2400 struct check_merge_ok_arg *a = arg;
2401 unsigned char status;
2402 struct stat sb;
2403 char *ondisk_path;
2405 /* Reject merges into a work tree with mixed base commits. */
2406 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
2407 SHA1_DIGEST_LENGTH))
2408 return got_error(GOT_ERR_MIXED_COMMITS);
2410 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
2411 == -1)
2412 return got_error_from_errno("asprintf");
2414 /* Reject merges into a work tree with conflicted files. */
2415 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
2416 if (err)
2417 return err;
2418 if (status == GOT_STATUS_CONFLICT)
2419 return got_error(GOT_ERR_CONFLICTS);
2421 return NULL;
2424 static const struct got_error *
2425 merge_files(struct got_worktree *worktree, struct got_fileindex *fileindex,
2426 const char *fileindex_path, struct got_object_id *commit_id1,
2427 struct got_object_id *commit_id2, struct got_repository *repo,
2428 got_worktree_checkout_cb progress_cb, void *progress_arg,
2429 got_cancel_cb cancel_cb, void *cancel_arg)
2431 const struct got_error *err = NULL, *sync_err;
2432 struct got_object_id *tree_id1 = NULL, *tree_id2 = NULL;
2433 struct got_tree_object *tree1 = NULL, *tree2 = NULL;
2434 struct merge_file_cb_arg arg;
2435 char *label_orig = NULL;
2437 if (commit_id1) {
2438 char *id_str;
2440 err = got_object_id_by_path(&tree_id1, repo, commit_id1,
2441 worktree->path_prefix);
2442 if (err)
2443 goto done;
2445 err = got_object_open_as_tree(&tree1, repo, tree_id1);
2446 if (err)
2447 goto done;
2449 err = got_object_id_str(&id_str, commit_id1);
2450 if (err)
2451 goto done;
2453 if (asprintf(&label_orig, "%s: commit %s",
2454 GOT_MERGE_LABEL_BASE, id_str) == -1) {
2455 err = got_error_from_errno("asprintf");
2456 free(id_str);
2457 goto done;
2459 free(id_str);
2462 err = got_object_id_by_path(&tree_id2, repo, commit_id2,
2463 worktree->path_prefix);
2464 if (err)
2465 goto done;
2467 err = got_object_open_as_tree(&tree2, repo, tree_id2);
2468 if (err)
2469 goto done;
2471 arg.worktree = worktree;
2472 arg.fileindex = fileindex;
2473 arg.progress_cb = progress_cb;
2474 arg.progress_arg = progress_arg;
2475 arg.cancel_cb = cancel_cb;
2476 arg.cancel_arg = cancel_arg;
2477 arg.label_orig = label_orig;
2478 arg.commit_id2 = commit_id2;
2479 err = got_diff_tree(tree1, tree2, "", "", repo, merge_file_cb, &arg, 1);
2480 sync_err = sync_fileindex(fileindex, fileindex_path);
2481 if (sync_err && err == NULL)
2482 err = sync_err;
2483 done:
2484 if (tree1)
2485 got_object_tree_close(tree1);
2486 if (tree2)
2487 got_object_tree_close(tree2);
2488 free(label_orig);
2489 return err;
2492 const struct got_error *
2493 got_worktree_merge_files(struct got_worktree *worktree,
2494 struct got_object_id *commit_id1, struct got_object_id *commit_id2,
2495 struct got_repository *repo, got_worktree_checkout_cb progress_cb,
2496 void *progress_arg, got_cancel_cb cancel_cb, void *cancel_arg)
2498 const struct got_error *err, *unlockerr;
2499 char *fileindex_path = NULL;
2500 struct got_fileindex *fileindex = NULL;
2501 struct check_merge_ok_arg mok_arg;
2503 err = lock_worktree(worktree, LOCK_EX);
2504 if (err)
2505 return err;
2507 err = open_fileindex(&fileindex, &fileindex_path, worktree);
2508 if (err)
2509 goto done;
2511 mok_arg.worktree = worktree;
2512 mok_arg.repo = repo;
2513 err = got_fileindex_for_each_entry_safe(fileindex, check_merge_ok,
2514 &mok_arg);
2515 if (err)
2516 goto done;
2518 err = merge_files(worktree, fileindex, fileindex_path, commit_id1,
2519 commit_id2, repo, progress_cb, progress_arg, cancel_cb, cancel_arg);
2520 done:
2521 if (fileindex)
2522 got_fileindex_free(fileindex);
2523 free(fileindex_path);
2524 unlockerr = lock_worktree(worktree, LOCK_SH);
2525 if (unlockerr && err == NULL)
2526 err = unlockerr;
2527 return err;
2530 struct diff_dir_cb_arg {
2531 struct got_fileindex *fileindex;
2532 struct got_worktree *worktree;
2533 const char *status_path;
2534 size_t status_path_len;
2535 struct got_repository *repo;
2536 got_worktree_status_cb status_cb;
2537 void *status_arg;
2538 got_cancel_cb cancel_cb;
2539 void *cancel_arg;
2540 /* A pathlist containing per-directory pathlists of ignore patterns. */
2541 struct got_pathlist_head ignores;
2542 int report_unchanged;
2543 int no_ignores;
2546 static const struct got_error *
2547 report_file_status(struct got_fileindex_entry *ie, const char *abspath,
2548 int dirfd, const char *de_name,
2549 got_worktree_status_cb status_cb, void *status_arg,
2550 struct got_repository *repo, int report_unchanged)
2552 const struct got_error *err = NULL;
2553 unsigned char status = GOT_STATUS_NO_CHANGE;
2554 unsigned char staged_status = get_staged_status(ie);
2555 struct stat sb;
2556 struct got_object_id blob_id, commit_id, staged_blob_id;
2557 struct got_object_id *blob_idp = NULL, *commit_idp = NULL;
2558 struct got_object_id *staged_blob_idp = NULL;
2560 err = get_file_status(&status, &sb, ie, abspath, dirfd, de_name, repo);
2561 if (err)
2562 return err;
2564 if (status == GOT_STATUS_NO_CHANGE &&
2565 staged_status == GOT_STATUS_NO_CHANGE && !report_unchanged)
2566 return NULL;
2568 if (got_fileindex_entry_has_blob(ie)) {
2569 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
2570 blob_idp = &blob_id;
2572 if (got_fileindex_entry_has_commit(ie)) {
2573 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
2574 commit_idp = &commit_id;
2576 if (staged_status == GOT_STATUS_ADD ||
2577 staged_status == GOT_STATUS_MODIFY) {
2578 memcpy(staged_blob_id.sha1, ie->staged_blob_sha1,
2579 SHA1_DIGEST_LENGTH);
2580 staged_blob_idp = &staged_blob_id;
2583 return (*status_cb)(status_arg, status, staged_status,
2584 ie->path, blob_idp, staged_blob_idp, commit_idp, dirfd, de_name);
2587 static const struct got_error *
2588 status_old_new(void *arg, struct got_fileindex_entry *ie,
2589 struct dirent *de, const char *parent_path, int dirfd)
2591 const struct got_error *err = NULL;
2592 struct diff_dir_cb_arg *a = arg;
2593 char *abspath;
2595 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2596 return got_error(GOT_ERR_CANCELLED);
2598 if (got_path_cmp(parent_path, a->status_path,
2599 strlen(parent_path), a->status_path_len) != 0 &&
2600 !got_path_is_child(parent_path, a->status_path, a->status_path_len))
2601 return NULL;
2603 if (parent_path[0]) {
2604 if (asprintf(&abspath, "%s/%s/%s", a->worktree->root_path,
2605 parent_path, de->d_name) == -1)
2606 return got_error_from_errno("asprintf");
2607 } else {
2608 if (asprintf(&abspath, "%s/%s", a->worktree->root_path,
2609 de->d_name) == -1)
2610 return got_error_from_errno("asprintf");
2613 err = report_file_status(ie, abspath, dirfd, de->d_name,
2614 a->status_cb, a->status_arg, a->repo, a->report_unchanged);
2615 free(abspath);
2616 return err;
2619 static const struct got_error *
2620 status_old(void *arg, struct got_fileindex_entry *ie, const char *parent_path)
2622 struct diff_dir_cb_arg *a = arg;
2623 struct got_object_id blob_id, commit_id;
2624 unsigned char status;
2626 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2627 return got_error(GOT_ERR_CANCELLED);
2629 if (!got_path_is_child(ie->path, a->status_path, a->status_path_len))
2630 return NULL;
2632 memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
2633 memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
2634 if (got_fileindex_entry_has_file_on_disk(ie))
2635 status = GOT_STATUS_MISSING;
2636 else
2637 status = GOT_STATUS_DELETE;
2638 return (*a->status_cb)(a->status_arg, status, get_staged_status(ie),
2639 ie->path, &blob_id, NULL, &commit_id, -1, NULL);
2642 void
2643 free_ignorelist(struct got_pathlist_head *ignorelist)
2645 struct got_pathlist_entry *pe;
2647 TAILQ_FOREACH(pe, ignorelist, entry)
2648 free((char *)pe->path);
2649 got_pathlist_free(ignorelist);
2652 void
2653 free_ignores(struct got_pathlist_head *ignores)
2655 struct got_pathlist_entry *pe;
2657 TAILQ_FOREACH(pe, ignores, entry) {
2658 struct got_pathlist_head *ignorelist = pe->data;
2659 free_ignorelist(ignorelist);
2660 free((char *)pe->path);
2662 got_pathlist_free(ignores);
2665 static const struct got_error *
2666 read_ignores(struct got_pathlist_head *ignores, const char *path, FILE *f)
2668 const struct got_error *err = NULL;
2669 struct got_pathlist_entry *pe = NULL;
2670 struct got_pathlist_head *ignorelist;
2671 char *line = NULL, *pattern, *dirpath = NULL;
2672 size_t linesize = 0;
2673 ssize_t linelen;
2675 ignorelist = calloc(1, sizeof(*ignorelist));
2676 if (ignorelist == NULL)
2677 return got_error_from_errno("calloc");
2678 TAILQ_INIT(ignorelist);
2680 while ((linelen = getline(&line, &linesize, f)) != -1) {
2681 if (linelen > 0 && line[linelen - 1] == '\n')
2682 line[linelen - 1] = '\0';
2684 /* Git's ignores may contain comments. */
2685 if (line[0] == '#')
2686 continue;
2688 /* Git's negated patterns are not (yet?) supported. */
2689 if (line[0] == '!')
2690 continue;
2692 if (asprintf(&pattern, "%s%s%s", path, path[0] ? "/" : "",
2693 line) == -1) {
2694 err = got_error_from_errno("asprintf");
2695 goto done;
2697 err = got_pathlist_insert(NULL, ignorelist, pattern, NULL);
2698 if (err)
2699 goto done;
2701 if (ferror(f)) {
2702 err = got_error_from_errno("getline");
2703 goto done;
2706 dirpath = strdup(path);
2707 if (dirpath == NULL) {
2708 err = got_error_from_errno("strdup");
2709 goto done;
2711 err = got_pathlist_insert(&pe, ignores, dirpath, ignorelist);
2712 done:
2713 free(line);
2714 if (err || pe == NULL) {
2715 free(dirpath);
2716 free_ignorelist(ignorelist);
2718 return err;
2721 int
2722 match_ignores(struct got_pathlist_head *ignores, const char *path)
2724 struct got_pathlist_entry *pe;
2726 /* Handle patterns which match in all directories. */
2727 TAILQ_FOREACH(pe, ignores, entry) {
2728 struct got_pathlist_head *ignorelist = pe->data;
2729 struct got_pathlist_entry *pi;
2731 TAILQ_FOREACH(pi, ignorelist, entry) {
2732 const char *p, *pattern = pi->path;
2734 if (strncmp(pattern, "**/", 3) != 0)
2735 continue;
2736 pattern += 3;
2737 p = path;
2738 while (*p) {
2739 if (fnmatch(pattern, p,
2740 FNM_PATHNAME | FNM_LEADING_DIR)) {
2741 /* Retry in next directory. */
2742 while (*p && *p != '/')
2743 p++;
2744 while (*p == '/')
2745 p++;
2746 continue;
2748 return 1;
2754 * The ignores pathlist contains ignore lists from children before
2755 * parents, so we can find the most specific ignorelist by walking
2756 * ignores backwards.
2758 pe = TAILQ_LAST(ignores, got_pathlist_head);
2759 while (pe) {
2760 if (got_path_is_child(path, pe->path, pe->path_len)) {
2761 struct got_pathlist_head *ignorelist = pe->data;
2762 struct got_pathlist_entry *pi;
2763 TAILQ_FOREACH(pi, ignorelist, entry) {
2764 const char *pattern = pi->path;
2765 int flags = FNM_LEADING_DIR;
2766 if (strstr(pattern, "/**/") == NULL)
2767 flags |= FNM_PATHNAME;
2768 if (fnmatch(pattern, path, flags))
2769 continue;
2770 return 1;
2773 pe = TAILQ_PREV(pe, got_pathlist_head, entry);
2776 return 0;
2779 static const struct got_error *
2780 add_ignores(struct got_pathlist_head *ignores, const char *root_path,
2781 const char *path, int dirfd, const char *ignores_filename)
2783 const struct got_error *err = NULL;
2784 char *ignorespath;
2785 int fd = -1;
2786 FILE *ignoresfile = NULL;
2788 if (asprintf(&ignorespath, "%s/%s%s%s", root_path, path,
2789 path[0] ? "/" : "", ignores_filename) == -1)
2790 return got_error_from_errno("asprintf");
2792 if (dirfd != -1) {
2793 fd = openat(dirfd, ignores_filename, O_RDONLY | O_NOFOLLOW);
2794 if (fd == -1) {
2795 if (errno != ENOENT && errno != EACCES)
2796 err = got_error_from_errno2("openat",
2797 ignorespath);
2798 } else {
2799 ignoresfile = fdopen(fd, "r");
2800 if (ignoresfile == NULL)
2801 err = got_error_from_errno2("fdopen",
2802 ignorespath);
2803 else {
2804 fd = -1;
2805 err = read_ignores(ignores, path, ignoresfile);
2808 } else {
2809 ignoresfile = fopen(ignorespath, "r");
2810 if (ignoresfile == NULL) {
2811 if (errno != ENOENT && errno != EACCES)
2812 err = got_error_from_errno2("fopen",
2813 ignorespath);
2814 } else
2815 err = read_ignores(ignores, path, ignoresfile);
2818 if (ignoresfile && fclose(ignoresfile) == EOF && err == NULL)
2819 err = got_error_from_errno2("fclose", path);
2820 if (fd != -1 && close(fd) == -1 && err == NULL)
2821 err = got_error_from_errno2("close", path);
2822 free(ignorespath);
2823 return err;
2826 static const struct got_error *
2827 status_new(void *arg, struct dirent *de, const char *parent_path, int dirfd)
2829 const struct got_error *err = NULL;
2830 struct diff_dir_cb_arg *a = arg;
2831 char *path = NULL;
2833 if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
2834 return got_error(GOT_ERR_CANCELLED);
2836 /* XXX ignore symlinks for now */
2837 if (de->d_type == DT_LNK)
2838 return NULL;
2840 if (parent_path[0]) {
2841 if (asprintf(&path, "%s/%s", parent_path, de->d_name) == -1)
2842 return got_error_from_errno("asprintf");
2843 } else {
2844 path = de->d_name;
2847 if (de->d_type != DT_DIR &&
2848 got_path_is_child(path, a->status_path, a->status_path_len)
2849 && !match_ignores(&a->ignores, path))
2850 err = (*a->status_cb)(a->status_arg, GOT_STATUS_UNVERSIONED,
2851 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
2852 if (parent_path[0])
2853 free(path);
2854 return err;
2857 static const struct got_error *
2858 status_traverse(void *arg, const char *path, int dirfd)
2860 const struct got_error *err = NULL;
2861 struct diff_dir_cb_arg *a = arg;
2863 if (a->no_ignores)
2864 return NULL;
2866 err = add_ignores(&a->ignores, a->worktree->root_path,
2867 path, dirfd, ".cvsignore");
2868 if (err)
2869 return err;
2871 err = add_ignores(&a->ignores, a->worktree->root_path, path,
2872 dirfd, ".gitignore");
2874 return err;
2877 static const struct got_error *
2878 report_single_file_status(const char *path, const char *ondisk_path,
2879 struct got_fileindex *fileindex, got_worktree_status_cb status_cb,
2880 void *status_arg, struct got_repository *repo, int report_unchanged)
2882 struct got_fileindex_entry *ie;
2883 struct stat sb;
2885 ie = got_fileindex_entry_get(fileindex, path, strlen(path));
2886 if (ie)
2887 return report_file_status(ie, ondisk_path, -1, NULL,
2888 status_cb, status_arg, repo, report_unchanged);
2890 if (lstat(ondisk_path, &sb) == -1) {
2891 if (errno != ENOENT)
2892 return got_error_from_errno2("lstat", ondisk_path);
2893 return (*status_cb)(status_arg, GOT_STATUS_NONEXISTENT,
2894 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
2895 return NULL;
2898 if (S_ISREG(sb.st_mode))
2899 return (*status_cb)(status_arg, GOT_STATUS_UNVERSIONED,
2900 GOT_STATUS_NO_CHANGE, path, NULL, NULL, NULL, -1, NULL);
2902 return NULL;
2905 static const struct got_error *
2906 add_ignores_from_parent_paths(struct got_pathlist_head *ignores,
2907 const char *root_path, const char *path)
2909 const struct got_error *err;
2910 char *parent_path, *next_parent_path = NULL;
2912 err = add_ignores(ignores, root_path, "", -1,
2913 ".cvsignore");
2914 if (err)
2915 return err;
2917 err = add_ignores(ignores, root_path, "", -1,
2918 ".gitignore");
2919 if (err)
2920 return err;
2922 err = got_path_dirname(&parent_path, path);
2923 if (err) {
2924 if (err->code == GOT_ERR_BAD_PATH)
2925 return NULL; /* cannot traverse parent */
2926 return err;
2928 for (;;) {
2929 err = add_ignores(ignores, root_path, parent_path, -1,
2930 ".cvsignore");
2931 if (err)
2932 break;
2933 err = add_ignores(ignores, root_path, parent_path, -1,
2934 ".gitignore");
2935 if (err)
2936 break;
2937 err = got_path_dirname(&next_parent_path, parent_path);
2938 if (err) {
2939 if (err->code == GOT_ERR_BAD_PATH)
2940 err = NULL; /* traversed everything */
2941 break;
2943 free(parent_path);
2944 parent_path = next_parent_path;
2945 next_parent_path = NULL;
2948 free(parent_path);
2949 free(next_parent_path);
2950 return err;
2953 static const struct got_error *
2954 worktree_status(struct got_worktree *worktree, const char *path,
2955 struct got_fileindex *fileindex, struct got_repository *repo,
2956 got_worktree_status_cb status_cb, void *status_arg,
2957 got_cancel_cb cancel_cb, void *cancel_arg, int no_ignores,
2958 int report_unchanged)
2960 const struct got_error *err = NULL;
2961 int fd = -1;
2962 struct got_fileindex_diff_dir_cb fdiff_cb;
2963 struct diff_dir_cb_arg arg;
2964 char *ondisk_path = NULL;
2966 TAILQ_INIT(&arg.ignores);
2968 if (asprintf(&ondisk_path, "%s%s%s",
2969 worktree->root_path, path[0] ? "/" : "", path) == -1)
2970 return got_error_from_errno("asprintf");
2972 fd = open(ondisk_path, O_RDONLY | O_NOFOLLOW | O_DIRECTORY);
2973 if (fd == -1) {
2974 if (errno != ENOTDIR && errno != ENOENT && errno != EACCES)
2975 err = got_error_from_errno2("open", ondisk_path);
2976 else
2977 err = report_single_file_status(path, ondisk_path,
2978 fileindex, status_cb, status_arg, repo,
2979 report_unchanged);
2980 } else {
2981 fdiff_cb.diff_old_new = status_old_new;
2982 fdiff_cb.diff_old = status_old;
2983 fdiff_cb.diff_new = status_new;
2984 fdiff_cb.diff_traverse = status_traverse;
2985 arg.fileindex = fileindex;
2986 arg.worktree = worktree;
2987 arg.status_path = path;
2988 arg.status_path_len = strlen(path);
2989 arg.repo = repo;
2990 arg.status_cb = status_cb;
2991 arg.status_arg = status_arg;
2992 arg.cancel_cb = cancel_cb;
2993 arg.cancel_arg = cancel_arg;
2994 arg.report_unchanged = report_unchanged;
2995 arg.no_ignores = no_ignores;
2996 if (!no_ignores) {
2997 err = add_ignores_from_parent_paths(&arg.ignores,
2998 worktree->root_path, path);
2999 if (err)
3000 goto done;
3002 err = got_fileindex_diff_dir(fileindex, fd,
3003 worktree->root_path, path, repo, &fdiff_cb, &arg);
3005 done:
3006 free_ignores(&arg.ignores);
3007 if (fd != -1 && close(fd) != 0 && err == NULL)
3008 err = got_error_from_errno("close");
3009 free(ondisk_path);
3010 return err;
3013 const struct got_error *
3014 got_worktree_status(struct got_worktree *worktree,
3015 struct got_pathlist_head *paths, struct got_repository *repo,
3016 got_worktree_status_cb status_cb, void *status_arg,
3017 got_cancel_cb cancel_cb, void *cancel_arg)
3019 const struct got_error *err = NULL;
3020 char *fileindex_path = NULL;
3021 struct got_fileindex *fileindex = NULL;
3022 struct got_pathlist_entry *pe;
3024 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3025 if (err)
3026 return err;
3028 TAILQ_FOREACH(pe, paths, entry) {
3029 err = worktree_status(worktree, pe->path, fileindex, repo,
3030 status_cb, status_arg, cancel_cb, cancel_arg, 0, 0);
3031 if (err)
3032 break;
3034 free(fileindex_path);
3035 got_fileindex_free(fileindex);
3036 return err;
3039 const struct got_error *
3040 got_worktree_resolve_path(char **wt_path, struct got_worktree *worktree,
3041 const char *arg)
3043 const struct got_error *err = NULL;
3044 char *resolved, *cwd = NULL, *path = NULL;
3045 size_t len;
3047 *wt_path = NULL;
3049 resolved = realpath(arg, NULL);
3050 if (resolved == NULL) {
3051 if (errno != ENOENT)
3052 return got_error_from_errno2("realpath", arg);
3053 cwd = getcwd(NULL, 0);
3054 if (cwd == NULL)
3055 return got_error_from_errno("getcwd");
3056 if (asprintf(&resolved, "%s/%s", cwd, arg) == -1) {
3057 err = got_error_from_errno("asprintf");
3058 goto done;
3062 if (strncmp(got_worktree_get_root_path(worktree), resolved,
3063 strlen(got_worktree_get_root_path(worktree)))) {
3064 err = got_error_path(resolved, GOT_ERR_BAD_PATH);
3065 goto done;
3068 if (strlen(resolved) > strlen(got_worktree_get_root_path(worktree))) {
3069 err = got_path_skip_common_ancestor(&path,
3070 got_worktree_get_root_path(worktree), resolved);
3071 if (err)
3072 goto done;
3073 } else {
3074 path = strdup("");
3075 if (path == NULL) {
3076 err = got_error_from_errno("strdup");
3077 goto done;
3081 /* XXX status walk can't deal with trailing slash! */
3082 len = strlen(path);
3083 while (len > 0 && path[len - 1] == '/') {
3084 path[len - 1] = '\0';
3085 len--;
3087 done:
3088 free(resolved);
3089 free(cwd);
3090 if (err == NULL)
3091 *wt_path = path;
3092 else
3093 free(path);
3094 return err;
3097 struct schedule_addition_args {
3098 struct got_worktree *worktree;
3099 struct got_fileindex *fileindex;
3100 got_worktree_checkout_cb progress_cb;
3101 void *progress_arg;
3102 struct got_repository *repo;
3105 static const struct got_error *
3106 schedule_addition(void *arg, unsigned char status, unsigned char staged_status,
3107 const char *relpath, struct got_object_id *blob_id,
3108 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
3109 int dirfd, const char *de_name)
3111 struct schedule_addition_args *a = arg;
3112 const struct got_error *err = NULL;
3113 struct got_fileindex_entry *ie;
3114 struct stat sb;
3115 char *ondisk_path;
3117 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3118 relpath) == -1)
3119 return got_error_from_errno("asprintf");
3121 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3122 if (ie) {
3123 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd,
3124 de_name, a->repo);
3125 if (err)
3126 goto done;
3127 /* Re-adding an existing entry is a no-op. */
3128 if (status == GOT_STATUS_ADD)
3129 goto done;
3130 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
3131 if (err)
3132 goto done;
3135 if (status != GOT_STATUS_UNVERSIONED) {
3136 err = got_error_path(ondisk_path, GOT_ERR_FILE_STATUS);
3137 goto done;
3140 err = got_fileindex_entry_alloc(&ie, relpath);
3141 if (err)
3142 goto done;
3143 err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL, 1);
3144 if (err) {
3145 got_fileindex_entry_free(ie);
3146 goto done;
3148 err = got_fileindex_entry_add(a->fileindex, ie);
3149 if (err) {
3150 got_fileindex_entry_free(ie);
3151 goto done;
3153 done:
3154 free(ondisk_path);
3155 if (err)
3156 return err;
3157 if (status == GOT_STATUS_ADD)
3158 return NULL;
3159 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_ADD, relpath);
3162 const struct got_error *
3163 got_worktree_schedule_add(struct got_worktree *worktree,
3164 struct got_pathlist_head *paths,
3165 got_worktree_checkout_cb progress_cb, void *progress_arg,
3166 struct got_repository *repo, int no_ignores)
3168 struct got_fileindex *fileindex = NULL;
3169 char *fileindex_path = NULL;
3170 const struct got_error *err = NULL, *sync_err, *unlockerr;
3171 struct got_pathlist_entry *pe;
3172 struct schedule_addition_args saa;
3174 err = lock_worktree(worktree, LOCK_EX);
3175 if (err)
3176 return err;
3178 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3179 if (err)
3180 goto done;
3182 saa.worktree = worktree;
3183 saa.fileindex = fileindex;
3184 saa.progress_cb = progress_cb;
3185 saa.progress_arg = progress_arg;
3186 saa.repo = repo;
3188 TAILQ_FOREACH(pe, paths, entry) {
3189 err = worktree_status(worktree, pe->path, fileindex, repo,
3190 schedule_addition, &saa, NULL, NULL, no_ignores, 0);
3191 if (err)
3192 break;
3194 sync_err = sync_fileindex(fileindex, fileindex_path);
3195 if (sync_err && err == NULL)
3196 err = sync_err;
3197 done:
3198 free(fileindex_path);
3199 if (fileindex)
3200 got_fileindex_free(fileindex);
3201 unlockerr = lock_worktree(worktree, LOCK_SH);
3202 if (unlockerr && err == NULL)
3203 err = unlockerr;
3204 return err;
3207 struct schedule_deletion_args {
3208 struct got_worktree *worktree;
3209 struct got_fileindex *fileindex;
3210 got_worktree_delete_cb progress_cb;
3211 void *progress_arg;
3212 struct got_repository *repo;
3213 int delete_local_mods;
3214 int keep_on_disk;
3217 static const struct got_error *
3218 schedule_for_deletion(void *arg, unsigned char status,
3219 unsigned char staged_status, const char *relpath,
3220 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
3221 struct got_object_id *commit_id, int dirfd, const char *de_name)
3223 struct schedule_deletion_args *a = arg;
3224 const struct got_error *err = NULL;
3225 struct got_fileindex_entry *ie = NULL;
3226 struct stat sb;
3227 char *ondisk_path, *parent = NULL;
3229 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3230 if (ie == NULL)
3231 return got_error_path(relpath, GOT_ERR_BAD_PATH);
3233 staged_status = get_staged_status(ie);
3234 if (staged_status != GOT_STATUS_NO_CHANGE) {
3235 if (staged_status == GOT_STATUS_DELETE)
3236 return NULL;
3237 return got_error_path(relpath, GOT_ERR_FILE_STAGED);
3240 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
3241 relpath) == -1)
3242 return got_error_from_errno("asprintf");
3244 err = get_file_status(&status, &sb, ie, ondisk_path, dirfd, de_name,
3245 a->repo);
3246 if (err)
3247 goto done;
3249 if (status != GOT_STATUS_NO_CHANGE) {
3250 if (status == GOT_STATUS_DELETE)
3251 goto done;
3252 if (status == GOT_STATUS_MODIFY && !a->delete_local_mods) {
3253 err = got_error_path(relpath, GOT_ERR_FILE_MODIFIED);
3254 goto done;
3256 if (status != GOT_STATUS_MODIFY &&
3257 status != GOT_STATUS_MISSING) {
3258 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
3259 goto done;
3263 if (!a->keep_on_disk && status != GOT_STATUS_MISSING) {
3264 if (dirfd != -1) {
3265 if (unlinkat(dirfd, de_name, 0) != 0) {
3266 err = got_error_from_errno2("unlinkat",
3267 ondisk_path);
3268 goto done;
3270 } else if (unlink(ondisk_path) != 0) {
3271 err = got_error_from_errno2("unlink", ondisk_path);
3272 goto done;
3275 parent = dirname(ondisk_path);
3277 if (parent == NULL) {
3278 err = got_error_from_errno2("dirname", ondisk_path);
3279 goto done;
3281 while (parent && strcmp(parent, a->worktree->root_path) != 0) {
3282 if (rmdir(parent) == -1) {
3283 if (errno != ENOTEMPTY)
3284 err = got_error_from_errno2("rmdir",
3285 parent);
3286 break;
3288 parent = dirname(parent);
3289 if (parent == NULL) {
3290 err = got_error_from_errno2("dirname", parent);
3291 goto done;
3296 got_fileindex_entry_mark_deleted_from_disk(ie);
3297 done:
3298 free(ondisk_path);
3299 if (err)
3300 return err;
3301 if (status == GOT_STATUS_DELETE)
3302 return NULL;
3303 return (*a->progress_cb)(a->progress_arg, GOT_STATUS_DELETE,
3304 staged_status, relpath);
3307 const struct got_error *
3308 got_worktree_schedule_delete(struct got_worktree *worktree,
3309 struct got_pathlist_head *paths, int delete_local_mods,
3310 got_worktree_delete_cb progress_cb, void *progress_arg,
3311 struct got_repository *repo, int keep_on_disk)
3313 struct got_fileindex *fileindex = NULL;
3314 char *fileindex_path = NULL;
3315 const struct got_error *err = NULL, *sync_err, *unlockerr;
3316 struct got_pathlist_entry *pe;
3317 struct schedule_deletion_args sda;
3319 err = lock_worktree(worktree, LOCK_EX);
3320 if (err)
3321 return err;
3323 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3324 if (err)
3325 goto done;
3327 sda.worktree = worktree;
3328 sda.fileindex = fileindex;
3329 sda.progress_cb = progress_cb;
3330 sda.progress_arg = progress_arg;
3331 sda.repo = repo;
3332 sda.delete_local_mods = delete_local_mods;
3333 sda.keep_on_disk = keep_on_disk;
3335 TAILQ_FOREACH(pe, paths, entry) {
3336 err = worktree_status(worktree, pe->path, fileindex, repo,
3337 schedule_for_deletion, &sda, NULL, NULL, 0, 1);
3338 if (err)
3339 break;
3341 sync_err = sync_fileindex(fileindex, fileindex_path);
3342 if (sync_err && err == NULL)
3343 err = sync_err;
3344 done:
3345 free(fileindex_path);
3346 if (fileindex)
3347 got_fileindex_free(fileindex);
3348 unlockerr = lock_worktree(worktree, LOCK_SH);
3349 if (unlockerr && err == NULL)
3350 err = unlockerr;
3351 return err;
3354 static const struct got_error *
3355 copy_one_line(FILE *infile, FILE *outfile, FILE *rejectfile)
3357 const struct got_error *err = NULL;
3358 char *line = NULL;
3359 size_t linesize = 0, n;
3360 ssize_t linelen;
3362 linelen = getline(&line, &linesize, infile);
3363 if (linelen == -1) {
3364 if (ferror(infile)) {
3365 err = got_error_from_errno("getline");
3366 goto done;
3368 return NULL;
3370 if (outfile) {
3371 n = fwrite(line, 1, linelen, outfile);
3372 if (n != linelen) {
3373 err = got_ferror(outfile, GOT_ERR_IO);
3374 goto done;
3377 if (rejectfile) {
3378 n = fwrite(line, 1, linelen, rejectfile);
3379 if (n != linelen)
3380 err = got_ferror(outfile, GOT_ERR_IO);
3382 done:
3383 free(line);
3384 return err;
3387 static const struct got_error *
3388 skip_one_line(FILE *f)
3390 char *line = NULL;
3391 size_t linesize = 0;
3392 ssize_t linelen;
3394 linelen = getline(&line, &linesize, f);
3395 if (linelen == -1) {
3396 if (ferror(f))
3397 return got_error_from_errno("getline");
3398 return NULL;
3400 free(line);
3401 return NULL;
3404 static const struct got_error *
3405 copy_change(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
3406 int start_old, int end_old, int start_new, int end_new,
3407 FILE *outfile, FILE *rejectfile)
3409 const struct got_error *err;
3411 /* Copy old file's lines leading up to patch. */
3412 while (!feof(f1) && *line_cur1 < start_old) {
3413 err = copy_one_line(f1, outfile, NULL);
3414 if (err)
3415 return err;
3416 (*line_cur1)++;
3418 /* Skip new file's lines leading up to patch. */
3419 while (!feof(f2) && *line_cur2 < start_new) {
3420 if (rejectfile)
3421 err = copy_one_line(f2, NULL, rejectfile);
3422 else
3423 err = skip_one_line(f2);
3424 if (err)
3425 return err;
3426 (*line_cur2)++;
3428 /* Copy patched lines. */
3429 while (!feof(f2) && *line_cur2 <= end_new) {
3430 err = copy_one_line(f2, outfile, NULL);
3431 if (err)
3432 return err;
3433 (*line_cur2)++;
3435 /* Skip over old file's replaced lines. */
3436 while (!feof(f1) && *line_cur1 <= end_old) {
3437 if (rejectfile)
3438 err = copy_one_line(f1, NULL, rejectfile);
3439 else
3440 err = skip_one_line(f1);
3441 if (err)
3442 return err;
3443 (*line_cur1)++;
3446 return NULL;
3449 static const struct got_error *
3450 copy_remaining_content(FILE *f1, FILE *f2, int *line_cur1, int *line_cur2,
3451 FILE *outfile, FILE *rejectfile)
3453 const struct got_error *err;
3455 if (outfile) {
3456 /* Copy old file's lines until EOF. */
3457 while (!feof(f1)) {
3458 err = copy_one_line(f1, outfile, NULL);
3459 if (err)
3460 return err;
3461 (*line_cur1)++;
3464 if (rejectfile) {
3465 /* Copy new file's lines until EOF. */
3466 while (!feof(f2)) {
3467 err = copy_one_line(f2, NULL, rejectfile);
3468 if (err)
3469 return err;
3470 (*line_cur2)++;
3474 return NULL;
3477 static const struct got_error *
3478 apply_or_reject_change(int *choice, struct got_diff_change *change, int n,
3479 int nchanges, struct got_diff_state *ds, struct got_diff_args *args,
3480 int diff_flags, const char *relpath, FILE *f1, FILE *f2, int *line_cur1,
3481 int *line_cur2, FILE *outfile, FILE *rejectfile,
3482 got_worktree_patch_cb patch_cb, void *patch_arg)
3484 const struct got_error *err = NULL;
3485 int start_old = change->cv.a;
3486 int end_old = change->cv.b;
3487 int start_new = change->cv.c;
3488 int end_new = change->cv.d;
3489 long pos1, pos2;
3490 FILE *hunkfile;
3492 *choice = GOT_PATCH_CHOICE_NONE;
3494 hunkfile = got_opentemp();
3495 if (hunkfile == NULL)
3496 return got_error_from_errno("got_opentemp");
3498 pos1 = ftell(f1);
3499 pos2 = ftell(f2);
3501 /* XXX TODO needs error checking */
3502 got_diff_dump_change(hunkfile, change, ds, args, f1, f2, diff_flags);
3504 if (fseek(f1, pos1, SEEK_SET) == -1) {
3505 err = got_ferror(f1, GOT_ERR_IO);
3506 goto done;
3508 if (fseek(f2, pos2, SEEK_SET) == -1) {
3509 err = got_ferror(f1, GOT_ERR_IO);
3510 goto done;
3512 if (fseek(hunkfile, 0L, SEEK_SET) == -1) {
3513 err = got_ferror(hunkfile, GOT_ERR_IO);
3514 goto done;
3517 err = (*patch_cb)(choice, patch_arg, GOT_STATUS_MODIFY, relpath,
3518 hunkfile, n, nchanges);
3519 if (err)
3520 goto done;
3522 switch (*choice) {
3523 case GOT_PATCH_CHOICE_YES:
3524 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
3525 end_old, start_new, end_new, outfile, rejectfile);
3526 break;
3527 case GOT_PATCH_CHOICE_NO:
3528 err = copy_change(f1, f2, line_cur1, line_cur2, start_old,
3529 end_old, start_new, end_new, rejectfile, outfile);
3530 break;
3531 case GOT_PATCH_CHOICE_QUIT:
3532 break;
3533 default:
3534 err = got_error(GOT_ERR_PATCH_CHOICE);
3535 break;
3537 done:
3538 if (hunkfile && fclose(hunkfile) == EOF && err == NULL)
3539 err = got_error_from_errno("fclose");
3540 return err;
3543 struct revert_file_args {
3544 struct got_worktree *worktree;
3545 struct got_fileindex *fileindex;
3546 got_worktree_checkout_cb progress_cb;
3547 void *progress_arg;
3548 got_worktree_patch_cb patch_cb;
3549 void *patch_arg;
3550 struct got_repository *repo;
3553 static const struct got_error *
3554 create_patched_content(char **path_outfile, int reverse_patch,
3555 struct got_object_id *blob_id, const char *path2,
3556 int dirfd2, const char *de_name2,
3557 const char *relpath, struct got_repository *repo,
3558 got_worktree_patch_cb patch_cb, void *patch_arg)
3560 const struct got_error *err;
3561 struct got_blob_object *blob = NULL;
3562 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL;
3563 int fd2 = -1;
3564 char *path1 = NULL, *id_str = NULL;
3565 struct stat sb1, sb2;
3566 struct got_diff_changes *changes = NULL;
3567 struct got_diff_state *ds = NULL;
3568 struct got_diff_args *args = NULL;
3569 struct got_diff_change *change;
3570 int diff_flags = 0, line_cur1 = 1, line_cur2 = 1, have_content = 0;
3571 int n = 0;
3573 *path_outfile = NULL;
3575 err = got_object_id_str(&id_str, blob_id);
3576 if (err)
3577 return err;
3579 if (dirfd2 != -1) {
3580 fd2 = openat(dirfd2, de_name2, O_RDONLY | O_NOFOLLOW);
3581 if (fd2 == -1) {
3582 err = got_error_from_errno2("openat", path2);
3583 goto done;
3585 } else {
3586 fd2 = open(path2, O_RDONLY | O_NOFOLLOW);
3587 if (fd2 == -1) {
3588 err = got_error_from_errno2("open", path2);
3589 goto done;
3592 if (fstat(fd2, &sb2) == -1) {
3593 err = got_error_from_errno2("fstat", path2);
3594 goto done;
3597 f2 = fdopen(fd2, "r");
3598 if (f2 == NULL) {
3599 err = got_error_from_errno2("fdopen", path2);
3600 goto done;
3602 fd2 = -1;
3604 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
3605 if (err)
3606 goto done;
3608 err = got_opentemp_named(&path1, &f1, "got-patched-blob");
3609 if (err)
3610 goto done;
3612 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
3613 if (err)
3614 goto done;
3616 if (stat(path1, &sb1) == -1) {
3617 err = got_error_from_errno2("stat", path1);
3618 goto done;
3621 err = got_diff_files(&changes, &ds, &args, &diff_flags,
3622 f1, sb1.st_size, id_str, f2, sb2.st_size, path2, 3, NULL);
3623 if (err)
3624 goto done;
3626 err = got_opentemp_named(path_outfile, &outfile, "got-patched-content");
3627 if (err)
3628 goto done;
3630 if (fseek(f1, 0L, SEEK_SET) == -1)
3631 return got_ferror(f1, GOT_ERR_IO);
3632 if (fseek(f2, 0L, SEEK_SET) == -1)
3633 return got_ferror(f2, GOT_ERR_IO);
3634 SIMPLEQ_FOREACH(change, &changes->entries, entry) {
3635 int choice;
3636 err = apply_or_reject_change(&choice, change, ++n,
3637 changes->nchanges, ds, args, diff_flags, relpath,
3638 f1, f2, &line_cur1, &line_cur2,
3639 reverse_patch ? NULL : outfile,
3640 reverse_patch ? outfile : NULL,
3641 patch_cb, patch_arg);
3642 if (err)
3643 goto done;
3644 if (choice == GOT_PATCH_CHOICE_YES)
3645 have_content = 1;
3646 else if (choice == GOT_PATCH_CHOICE_QUIT)
3647 break;
3649 if (have_content) {
3650 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
3651 reverse_patch ? NULL : outfile,
3652 reverse_patch ? outfile : NULL);
3653 if (err)
3654 goto done;
3656 if (chmod(*path_outfile, sb2.st_mode) == -1) {
3657 err = got_error_from_errno2("chmod", path2);
3658 goto done;
3661 done:
3662 free(id_str);
3663 if (blob)
3664 got_object_blob_close(blob);
3665 if (f1 && fclose(f1) == EOF && err == NULL)
3666 err = got_error_from_errno2("fclose", path1);
3667 if (f2 && fclose(f2) == EOF && err == NULL)
3668 err = got_error_from_errno2("fclose", path2);
3669 if (fd2 != -1 && close(fd2) == -1 && err == NULL)
3670 err = got_error_from_errno2("close", path2);
3671 if (outfile && fclose(outfile) == EOF && err == NULL)
3672 err = got_error_from_errno2("fclose", *path_outfile);
3673 if (path1 && unlink(path1) == -1 && err == NULL)
3674 err = got_error_from_errno2("unlink", path1);
3675 if (err || !have_content) {
3676 if (*path_outfile && unlink(*path_outfile) == -1 && err == NULL)
3677 err = got_error_from_errno2("unlink", *path_outfile);
3678 free(*path_outfile);
3679 *path_outfile = NULL;
3681 free(args);
3682 if (ds) {
3683 got_diff_state_free(ds);
3684 free(ds);
3686 if (changes)
3687 got_diff_free_changes(changes);
3688 free(path1);
3689 return err;
3692 static const struct got_error *
3693 revert_file(void *arg, unsigned char status, unsigned char staged_status,
3694 const char *relpath, struct got_object_id *blob_id,
3695 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
3696 int dirfd, const char *de_name)
3698 struct revert_file_args *a = arg;
3699 const struct got_error *err = NULL;
3700 char *parent_path = NULL;
3701 struct got_fileindex_entry *ie;
3702 struct got_tree_object *tree = NULL;
3703 struct got_object_id *tree_id = NULL;
3704 const struct got_tree_entry *te = NULL;
3705 char *tree_path = NULL, *te_name;
3706 char *ondisk_path = NULL, *path_content = NULL;
3707 struct got_blob_object *blob = NULL;
3709 /* Reverting a staged deletion is a no-op. */
3710 if (status == GOT_STATUS_DELETE &&
3711 staged_status != GOT_STATUS_NO_CHANGE)
3712 return NULL;
3714 if (status == GOT_STATUS_UNVERSIONED)
3715 return (*a->progress_cb)(a->progress_arg,
3716 GOT_STATUS_UNVERSIONED, relpath);
3718 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
3719 if (ie == NULL)
3720 return got_error_path(relpath, GOT_ERR_BAD_PATH);
3722 /* Construct in-repository path of tree which contains this blob. */
3723 err = got_path_dirname(&parent_path, ie->path);
3724 if (err) {
3725 if (err->code != GOT_ERR_BAD_PATH)
3726 goto done;
3727 parent_path = strdup("/");
3728 if (parent_path == NULL) {
3729 err = got_error_from_errno("strdup");
3730 goto done;
3733 if (got_path_is_root_dir(a->worktree->path_prefix)) {
3734 tree_path = strdup(parent_path);
3735 if (tree_path == NULL) {
3736 err = got_error_from_errno("strdup");
3737 goto done;
3739 } else {
3740 if (got_path_is_root_dir(parent_path)) {
3741 tree_path = strdup(a->worktree->path_prefix);
3742 if (tree_path == NULL) {
3743 err = got_error_from_errno("strdup");
3744 goto done;
3746 } else {
3747 if (asprintf(&tree_path, "%s/%s",
3748 a->worktree->path_prefix, parent_path) == -1) {
3749 err = got_error_from_errno("asprintf");
3750 goto done;
3755 err = got_object_id_by_path(&tree_id, a->repo,
3756 a->worktree->base_commit_id, tree_path);
3757 if (err) {
3758 if (!(err->code == GOT_ERR_NO_TREE_ENTRY &&
3759 (status == GOT_STATUS_ADD ||
3760 staged_status == GOT_STATUS_ADD)))
3761 goto done;
3762 } else {
3763 err = got_object_open_as_tree(&tree, a->repo, tree_id);
3764 if (err)
3765 goto done;
3767 te_name = basename(ie->path);
3768 if (te_name == NULL) {
3769 err = got_error_from_errno2("basename", ie->path);
3770 goto done;
3773 te = got_object_tree_find_entry(tree, te_name);
3774 if (te == NULL && status != GOT_STATUS_ADD &&
3775 staged_status != GOT_STATUS_ADD) {
3776 err = got_error(GOT_ERR_NO_TREE_ENTRY);
3777 goto done;
3781 switch (status) {
3782 case GOT_STATUS_ADD:
3783 if (a->patch_cb) {
3784 int choice = GOT_PATCH_CHOICE_NONE;
3785 err = (*a->patch_cb)(&choice, a->patch_arg,
3786 status, ie->path, NULL, 1, 1);
3787 if (err)
3788 goto done;
3789 if (choice != GOT_PATCH_CHOICE_YES)
3790 break;
3792 err = (*a->progress_cb)(a->progress_arg, GOT_STATUS_REVERT,
3793 ie->path);
3794 if (err)
3795 goto done;
3796 got_fileindex_entry_remove(a->fileindex, ie);
3797 break;
3798 case GOT_STATUS_DELETE:
3799 if (a->patch_cb) {
3800 int choice = GOT_PATCH_CHOICE_NONE;
3801 err = (*a->patch_cb)(&choice, a->patch_arg,
3802 status, ie->path, NULL, 1, 1);
3803 if (err)
3804 goto done;
3805 if (choice != GOT_PATCH_CHOICE_YES)
3806 break;
3808 /* fall through */
3809 case GOT_STATUS_MODIFY:
3810 case GOT_STATUS_MODE_CHANGE:
3811 case GOT_STATUS_CONFLICT:
3812 case GOT_STATUS_MISSING: {
3813 struct got_object_id id;
3814 if (staged_status == GOT_STATUS_ADD ||
3815 staged_status == GOT_STATUS_MODIFY) {
3816 memcpy(id.sha1, ie->staged_blob_sha1,
3817 SHA1_DIGEST_LENGTH);
3818 } else
3819 memcpy(id.sha1, ie->blob_sha1,
3820 SHA1_DIGEST_LENGTH);
3821 err = got_object_open_as_blob(&blob, a->repo, &id, 8192);
3822 if (err)
3823 goto done;
3825 if (asprintf(&ondisk_path, "%s/%s",
3826 got_worktree_get_root_path(a->worktree), relpath) == -1) {
3827 err = got_error_from_errno("asprintf");
3828 goto done;
3831 if (a->patch_cb && (status == GOT_STATUS_MODIFY ||
3832 status == GOT_STATUS_CONFLICT)) {
3833 err = create_patched_content(&path_content, 1, &id,
3834 ondisk_path, dirfd, de_name, ie->path, a->repo,
3835 a->patch_cb, a->patch_arg);
3836 if (err || path_content == NULL)
3837 break;
3838 if (rename(path_content, ondisk_path) == -1) {
3839 err = got_error_from_errno3("rename",
3840 path_content, ondisk_path);
3841 goto done;
3843 } else {
3844 err = install_blob(a->worktree, ondisk_path, ie->path,
3845 te ? te->mode : GOT_DEFAULT_FILE_MODE,
3846 got_fileindex_perms_to_st(ie), blob, 0, 1,
3847 a->repo, a->progress_cb, a->progress_arg);
3848 if (err)
3849 goto done;
3850 if (status == GOT_STATUS_DELETE ||
3851 status == GOT_STATUS_MODE_CHANGE) {
3852 err = got_fileindex_entry_update(ie,
3853 ondisk_path, blob->id.sha1,
3854 a->worktree->base_commit_id->sha1, 1);
3855 if (err)
3856 goto done;
3859 break;
3861 default:
3862 break;
3864 done:
3865 free(ondisk_path);
3866 free(path_content);
3867 free(parent_path);
3868 free(tree_path);
3869 if (blob)
3870 got_object_blob_close(blob);
3871 if (tree)
3872 got_object_tree_close(tree);
3873 free(tree_id);
3874 return err;
3877 const struct got_error *
3878 got_worktree_revert(struct got_worktree *worktree,
3879 struct got_pathlist_head *paths,
3880 got_worktree_checkout_cb progress_cb, void *progress_arg,
3881 got_worktree_patch_cb patch_cb, void *patch_arg,
3882 struct got_repository *repo)
3884 struct got_fileindex *fileindex = NULL;
3885 char *fileindex_path = NULL;
3886 const struct got_error *err = NULL, *unlockerr = NULL;
3887 const struct got_error *sync_err = NULL;
3888 struct got_pathlist_entry *pe;
3889 struct revert_file_args rfa;
3891 err = lock_worktree(worktree, LOCK_EX);
3892 if (err)
3893 return err;
3895 err = open_fileindex(&fileindex, &fileindex_path, worktree);
3896 if (err)
3897 goto done;
3899 rfa.worktree = worktree;
3900 rfa.fileindex = fileindex;
3901 rfa.progress_cb = progress_cb;
3902 rfa.progress_arg = progress_arg;
3903 rfa.patch_cb = patch_cb;
3904 rfa.patch_arg = patch_arg;
3905 rfa.repo = repo;
3906 TAILQ_FOREACH(pe, paths, entry) {
3907 err = worktree_status(worktree, pe->path, fileindex, repo,
3908 revert_file, &rfa, NULL, NULL, 0, 0);
3909 if (err)
3910 break;
3912 sync_err = sync_fileindex(fileindex, fileindex_path);
3913 if (sync_err && err == NULL)
3914 err = sync_err;
3915 done:
3916 free(fileindex_path);
3917 if (fileindex)
3918 got_fileindex_free(fileindex);
3919 unlockerr = lock_worktree(worktree, LOCK_SH);
3920 if (unlockerr && err == NULL)
3921 err = unlockerr;
3922 return err;
3925 static void
3926 free_commitable(struct got_commitable *ct)
3928 free(ct->path);
3929 free(ct->in_repo_path);
3930 free(ct->ondisk_path);
3931 free(ct->blob_id);
3932 free(ct->base_blob_id);
3933 free(ct->staged_blob_id);
3934 free(ct->base_commit_id);
3935 free(ct);
3938 struct collect_commitables_arg {
3939 struct got_pathlist_head *commitable_paths;
3940 struct got_repository *repo;
3941 struct got_worktree *worktree;
3942 int have_staged_files;
3945 static const struct got_error *
3946 collect_commitables(void *arg, unsigned char status,
3947 unsigned char staged_status, const char *relpath,
3948 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
3949 struct got_object_id *commit_id, int dirfd, const char *de_name)
3951 struct collect_commitables_arg *a = arg;
3952 const struct got_error *err = NULL;
3953 struct got_commitable *ct = NULL;
3954 struct got_pathlist_entry *new = NULL;
3955 char *parent_path = NULL, *path = NULL;
3956 struct stat sb;
3958 if (a->have_staged_files) {
3959 if (staged_status != GOT_STATUS_MODIFY &&
3960 staged_status != GOT_STATUS_ADD &&
3961 staged_status != GOT_STATUS_DELETE)
3962 return NULL;
3963 } else {
3964 if (status == GOT_STATUS_CONFLICT)
3965 return got_error(GOT_ERR_COMMIT_CONFLICT);
3967 if (status != GOT_STATUS_MODIFY &&
3968 status != GOT_STATUS_MODE_CHANGE &&
3969 status != GOT_STATUS_ADD &&
3970 status != GOT_STATUS_DELETE)
3971 return NULL;
3974 if (asprintf(&path, "/%s", relpath) == -1) {
3975 err = got_error_from_errno("asprintf");
3976 goto done;
3978 if (strcmp(path, "/") == 0) {
3979 parent_path = strdup("");
3980 if (parent_path == NULL)
3981 return got_error_from_errno("strdup");
3982 } else {
3983 err = got_path_dirname(&parent_path, path);
3984 if (err)
3985 return err;
3988 ct = calloc(1, sizeof(*ct));
3989 if (ct == NULL) {
3990 err = got_error_from_errno("calloc");
3991 goto done;
3994 if (asprintf(&ct->ondisk_path, "%s/%s", a->worktree->root_path,
3995 relpath) == -1) {
3996 err = got_error_from_errno("asprintf");
3997 goto done;
3999 if (status == GOT_STATUS_DELETE || staged_status == GOT_STATUS_DELETE) {
4000 sb.st_mode = GOT_DEFAULT_FILE_MODE;
4001 } else {
4002 if (dirfd != -1) {
4003 if (fstatat(dirfd, de_name, &sb,
4004 AT_SYMLINK_NOFOLLOW) == -1) {
4005 err = got_error_from_errno2("fstatat",
4006 ct->ondisk_path);
4007 goto done;
4009 } else if (lstat(ct->ondisk_path, &sb) == -1) {
4010 err = got_error_from_errno2("lstat", ct->ondisk_path);
4011 goto done;
4013 ct->mode = sb.st_mode;
4016 if (asprintf(&ct->in_repo_path, "%s%s%s", a->worktree->path_prefix,
4017 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
4018 relpath) == -1) {
4019 err = got_error_from_errno("asprintf");
4020 goto done;
4023 ct->status = status;
4024 ct->staged_status = staged_status;
4025 ct->blob_id = NULL; /* will be filled in when blob gets created */
4026 if (ct->status != GOT_STATUS_ADD &&
4027 ct->staged_status != GOT_STATUS_ADD) {
4028 ct->base_blob_id = got_object_id_dup(blob_id);
4029 if (ct->base_blob_id == NULL) {
4030 err = got_error_from_errno("got_object_id_dup");
4031 goto done;
4033 ct->base_commit_id = got_object_id_dup(commit_id);
4034 if (ct->base_commit_id == NULL) {
4035 err = got_error_from_errno("got_object_id_dup");
4036 goto done;
4039 if (ct->staged_status == GOT_STATUS_ADD ||
4040 ct->staged_status == GOT_STATUS_MODIFY) {
4041 ct->staged_blob_id = got_object_id_dup(staged_blob_id);
4042 if (ct->staged_blob_id == NULL) {
4043 err = got_error_from_errno("got_object_id_dup");
4044 goto done;
4047 ct->path = strdup(path);
4048 if (ct->path == NULL) {
4049 err = got_error_from_errno("strdup");
4050 goto done;
4052 err = got_pathlist_insert(&new, a->commitable_paths, ct->path, ct);
4053 done:
4054 if (ct && (err || new == NULL))
4055 free_commitable(ct);
4056 free(parent_path);
4057 free(path);
4058 return err;
4061 static const struct got_error *write_tree(struct got_object_id **, int *,
4062 struct got_tree_object *, const char *, struct got_pathlist_head *,
4063 got_worktree_status_cb status_cb, void *status_arg,
4064 struct got_repository *);
4066 static const struct got_error *
4067 write_subtree(struct got_object_id **new_subtree_id, int *nentries,
4068 struct got_tree_entry *te, const char *parent_path,
4069 struct got_pathlist_head *commitable_paths,
4070 got_worktree_status_cb status_cb, void *status_arg,
4071 struct got_repository *repo)
4073 const struct got_error *err = NULL;
4074 struct got_tree_object *subtree;
4075 char *subpath;
4077 if (asprintf(&subpath, "%s%s%s", parent_path,
4078 got_path_is_root_dir(parent_path) ? "" : "/", te->name) == -1)
4079 return got_error_from_errno("asprintf");
4081 err = got_object_open_as_tree(&subtree, repo, &te->id);
4082 if (err)
4083 return err;
4085 err = write_tree(new_subtree_id, nentries, subtree, subpath,
4086 commitable_paths, status_cb, status_arg, repo);
4087 got_object_tree_close(subtree);
4088 free(subpath);
4089 return err;
4092 static const struct got_error *
4093 match_ct_parent_path(int *match, struct got_commitable *ct, const char *path)
4095 const struct got_error *err = NULL;
4096 char *ct_parent_path = NULL;
4098 *match = 0;
4100 if (strchr(ct->in_repo_path, '/') == NULL) {
4101 *match = got_path_is_root_dir(path);
4102 return NULL;
4105 err = got_path_dirname(&ct_parent_path, ct->in_repo_path);
4106 if (err)
4107 return err;
4108 *match = (strcmp(path, ct_parent_path) == 0);
4109 free(ct_parent_path);
4110 return err;
4113 static mode_t
4114 get_ct_file_mode(struct got_commitable *ct)
4116 return S_IFREG | (ct->mode & ((S_IRWXU | S_IRWXG | S_IRWXO)));
4119 static const struct got_error *
4120 alloc_modified_blob_tree_entry(struct got_tree_entry **new_te,
4121 struct got_tree_entry *te, struct got_commitable *ct)
4123 const struct got_error *err = NULL;
4125 *new_te = NULL;
4127 err = got_object_tree_entry_dup(new_te, te);
4128 if (err)
4129 goto done;
4131 (*new_te)->mode = get_ct_file_mode(ct);
4133 if (ct->staged_status == GOT_STATUS_MODIFY)
4134 memcpy(&(*new_te)->id, ct->staged_blob_id,
4135 sizeof((*new_te)->id));
4136 else
4137 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
4138 done:
4139 if (err && *new_te) {
4140 free(*new_te);
4141 *new_te = NULL;
4143 return err;
4146 static const struct got_error *
4147 alloc_added_blob_tree_entry(struct got_tree_entry **new_te,
4148 struct got_commitable *ct)
4150 const struct got_error *err = NULL;
4151 char *ct_name;
4153 *new_te = NULL;
4155 *new_te = calloc(1, sizeof(**new_te));
4156 if (*new_te == NULL)
4157 return got_error_from_errno("calloc");
4159 ct_name = basename(ct->path);
4160 if (ct_name == NULL) {
4161 err = got_error_from_errno2("basename", ct->path);
4162 goto done;
4164 if (strlcpy((*new_te)->name, ct_name, sizeof((*new_te)->name)) >=
4165 sizeof((*new_te)->name)) {
4166 err = got_error(GOT_ERR_NO_SPACE);
4167 goto done;
4170 (*new_te)->mode = get_ct_file_mode(ct);
4172 if (ct->staged_status == GOT_STATUS_ADD)
4173 memcpy(&(*new_te)->id, ct->staged_blob_id,
4174 sizeof((*new_te)->id));
4175 else
4176 memcpy(&(*new_te)->id, ct->blob_id, sizeof((*new_te)->id));
4177 done:
4178 if (err && *new_te) {
4179 free(*new_te);
4180 *new_te = NULL;
4182 return err;
4185 static const struct got_error *
4186 insert_tree_entry(struct got_tree_entry *new_te,
4187 struct got_pathlist_head *paths)
4189 const struct got_error *err = NULL;
4190 struct got_pathlist_entry *new_pe;
4192 err = got_pathlist_insert(&new_pe, paths, new_te->name, new_te);
4193 if (err)
4194 return err;
4195 if (new_pe == NULL)
4196 return got_error(GOT_ERR_TREE_DUP_ENTRY);
4197 return NULL;
4200 static const struct got_error *
4201 report_ct_status(struct got_commitable *ct,
4202 got_worktree_status_cb status_cb, void *status_arg)
4204 const char *ct_path = ct->path;
4205 unsigned char status;
4207 while (ct_path[0] == '/')
4208 ct_path++;
4210 if (ct->staged_status != GOT_STATUS_NO_CHANGE)
4211 status = ct->staged_status;
4212 else
4213 status = ct->status;
4215 return (*status_cb)(status_arg, status, GOT_STATUS_NO_CHANGE,
4216 ct_path, ct->blob_id, NULL, NULL, -1, NULL);
4219 static const struct got_error *
4220 match_modified_subtree(int *modified, struct got_tree_entry *te,
4221 const char *base_tree_path, struct got_pathlist_head *commitable_paths)
4223 const struct got_error *err = NULL;
4224 struct got_pathlist_entry *pe;
4225 char *te_path;
4227 *modified = 0;
4229 if (asprintf(&te_path, "%s%s%s", base_tree_path,
4230 got_path_is_root_dir(base_tree_path) ? "" : "/",
4231 te->name) == -1)
4232 return got_error_from_errno("asprintf");
4234 TAILQ_FOREACH(pe, commitable_paths, entry) {
4235 struct got_commitable *ct = pe->data;
4236 *modified = got_path_is_child(ct->in_repo_path, te_path,
4237 strlen(te_path));
4238 if (*modified)
4239 break;
4242 free(te_path);
4243 return err;
4246 static const struct got_error *
4247 match_deleted_or_modified_ct(struct got_commitable **ctp,
4248 struct got_tree_entry *te, const char *base_tree_path,
4249 struct got_pathlist_head *commitable_paths)
4251 const struct got_error *err = NULL;
4252 struct got_pathlist_entry *pe;
4254 *ctp = NULL;
4256 TAILQ_FOREACH(pe, commitable_paths, entry) {
4257 struct got_commitable *ct = pe->data;
4258 char *ct_name = NULL;
4259 int path_matches;
4261 if (ct->staged_status == GOT_STATUS_NO_CHANGE) {
4262 if (ct->status != GOT_STATUS_MODIFY &&
4263 ct->status != GOT_STATUS_MODE_CHANGE &&
4264 ct->status != GOT_STATUS_DELETE)
4265 continue;
4266 } else {
4267 if (ct->staged_status != GOT_STATUS_MODIFY &&
4268 ct->staged_status != GOT_STATUS_DELETE)
4269 continue;
4272 if (got_object_id_cmp(ct->base_blob_id, &te->id) != 0)
4273 continue;
4275 err = match_ct_parent_path(&path_matches, ct, base_tree_path);
4276 if (err)
4277 return err;
4278 if (!path_matches)
4279 continue;
4281 ct_name = basename(pe->path);
4282 if (ct_name == NULL)
4283 return got_error_from_errno2("basename", pe->path);
4285 if (strcmp(te->name, ct_name) != 0)
4286 continue;
4288 *ctp = ct;
4289 break;
4292 return err;
4295 static const struct got_error *
4296 make_subtree_for_added_blob(struct got_tree_entry **new_tep,
4297 const char *child_path, const char *path_base_tree,
4298 struct got_pathlist_head *commitable_paths,
4299 got_worktree_status_cb status_cb, void *status_arg,
4300 struct got_repository *repo)
4302 const struct got_error *err = NULL;
4303 struct got_tree_entry *new_te;
4304 char *subtree_path;
4305 struct got_object_id *id = NULL;
4306 int nentries;
4308 *new_tep = NULL;
4310 if (asprintf(&subtree_path, "%s%s%s", path_base_tree,
4311 got_path_is_root_dir(path_base_tree) ? "" : "/",
4312 child_path) == -1)
4313 return got_error_from_errno("asprintf");
4315 new_te = calloc(1, sizeof(*new_te));
4316 if (new_te == NULL)
4317 return got_error_from_errno("calloc");
4318 new_te->mode = S_IFDIR;
4320 if (strlcpy(new_te->name, child_path, sizeof(new_te->name)) >=
4321 sizeof(new_te->name)) {
4322 err = got_error(GOT_ERR_NO_SPACE);
4323 goto done;
4325 err = write_tree(&id, &nentries, NULL, subtree_path,
4326 commitable_paths, status_cb, status_arg, repo);
4327 if (err) {
4328 free(new_te);
4329 goto done;
4331 memcpy(&new_te->id, id, sizeof(new_te->id));
4332 done:
4333 free(id);
4334 free(subtree_path);
4335 if (err == NULL)
4336 *new_tep = new_te;
4337 return err;
4340 static const struct got_error *
4341 write_tree(struct got_object_id **new_tree_id, int *nentries,
4342 struct got_tree_object *base_tree, const char *path_base_tree,
4343 struct got_pathlist_head *commitable_paths,
4344 got_worktree_status_cb status_cb, void *status_arg,
4345 struct got_repository *repo)
4347 const struct got_error *err = NULL;
4348 struct got_pathlist_head paths;
4349 struct got_tree_entry *te, *new_te = NULL;
4350 struct got_pathlist_entry *pe;
4352 TAILQ_INIT(&paths);
4353 *nentries = 0;
4355 /* Insert, and recurse into, newly added entries first. */
4356 TAILQ_FOREACH(pe, commitable_paths, entry) {
4357 struct got_commitable *ct = pe->data;
4358 char *child_path = NULL, *slash;
4360 if ((ct->status != GOT_STATUS_ADD &&
4361 ct->staged_status != GOT_STATUS_ADD) ||
4362 (ct->flags & GOT_COMMITABLE_ADDED))
4363 continue;
4365 if (!got_path_is_child(pe->path, path_base_tree,
4366 strlen(path_base_tree)))
4367 continue;
4369 err = got_path_skip_common_ancestor(&child_path, path_base_tree,
4370 pe->path);
4371 if (err)
4372 goto done;
4374 slash = strchr(child_path, '/');
4375 if (slash == NULL) {
4376 err = alloc_added_blob_tree_entry(&new_te, ct);
4377 if (err)
4378 goto done;
4379 err = report_ct_status(ct, status_cb, status_arg);
4380 if (err)
4381 goto done;
4382 ct->flags |= GOT_COMMITABLE_ADDED;
4383 err = insert_tree_entry(new_te, &paths);
4384 if (err)
4385 goto done;
4386 (*nentries)++;
4387 } else {
4388 *slash = '\0'; /* trim trailing path components */
4389 if (base_tree == NULL ||
4390 got_object_tree_find_entry(base_tree, child_path)
4391 == NULL) {
4392 err = make_subtree_for_added_blob(&new_te,
4393 child_path, path_base_tree,
4394 commitable_paths, status_cb, status_arg,
4395 repo);
4396 if (err)
4397 goto done;
4398 err = insert_tree_entry(new_te, &paths);
4399 if (err)
4400 goto done;
4401 (*nentries)++;
4406 if (base_tree) {
4407 int i, nbase_entries;
4408 /* Handle modified and deleted entries. */
4409 nbase_entries = got_object_tree_get_nentries(base_tree);
4410 for (i = 0; i < nbase_entries; i++) {
4411 struct got_commitable *ct = NULL;
4413 te = got_object_tree_get_entry(base_tree, i);
4414 if (got_object_tree_entry_is_submodule(te)) {
4415 /* Entry is a submodule; just copy it. */
4416 err = got_object_tree_entry_dup(&new_te, te);
4417 if (err)
4418 goto done;
4419 err = insert_tree_entry(new_te, &paths);
4420 if (err)
4421 goto done;
4422 (*nentries)++;
4423 continue;
4426 if (S_ISDIR(te->mode)) {
4427 int modified;
4428 err = got_object_tree_entry_dup(&new_te, te);
4429 if (err)
4430 goto done;
4431 err = match_modified_subtree(&modified, te,
4432 path_base_tree, commitable_paths);
4433 if (err)
4434 goto done;
4435 /* Avoid recursion into unmodified subtrees. */
4436 if (modified) {
4437 struct got_object_id *new_id;
4438 int nsubentries;
4439 err = write_subtree(&new_id,
4440 &nsubentries, te,
4441 path_base_tree, commitable_paths,
4442 status_cb, status_arg, repo);
4443 if (err)
4444 goto done;
4445 if (nsubentries == 0) {
4446 /* All entries were deleted. */
4447 free(new_id);
4448 continue;
4450 memcpy(&new_te->id, new_id,
4451 sizeof(new_te->id));
4452 free(new_id);
4454 err = insert_tree_entry(new_te, &paths);
4455 if (err)
4456 goto done;
4457 (*nentries)++;
4458 continue;
4461 err = match_deleted_or_modified_ct(&ct, te,
4462 path_base_tree, commitable_paths);
4463 if (err)
4464 goto done;
4465 if (ct) {
4466 /* NB: Deleted entries get dropped here. */
4467 if (ct->status == GOT_STATUS_MODIFY ||
4468 ct->status == GOT_STATUS_MODE_CHANGE ||
4469 ct->staged_status == GOT_STATUS_MODIFY) {
4470 err = alloc_modified_blob_tree_entry(
4471 &new_te, te, ct);
4472 if (err)
4473 goto done;
4474 err = insert_tree_entry(new_te, &paths);
4475 if (err)
4476 goto done;
4477 (*nentries)++;
4479 err = report_ct_status(ct, status_cb,
4480 status_arg);
4481 if (err)
4482 goto done;
4483 } else {
4484 /* Entry is unchanged; just copy it. */
4485 err = got_object_tree_entry_dup(&new_te, te);
4486 if (err)
4487 goto done;
4488 err = insert_tree_entry(new_te, &paths);
4489 if (err)
4490 goto done;
4491 (*nentries)++;
4496 /* Write new list of entries; deleted entries have been dropped. */
4497 err = got_object_tree_create(new_tree_id, &paths, *nentries, repo);
4498 done:
4499 got_pathlist_free(&paths);
4500 return err;
4503 static const struct got_error *
4504 update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
4505 struct got_object_id *new_base_commit_id, struct got_fileindex *fileindex,
4506 int have_staged_files)
4508 const struct got_error *err = NULL;
4509 struct got_pathlist_entry *pe;
4511 TAILQ_FOREACH(pe, commitable_paths, entry) {
4512 struct got_fileindex_entry *ie;
4513 struct got_commitable *ct = pe->data;
4515 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
4516 if (ie) {
4517 if (ct->status == GOT_STATUS_DELETE ||
4518 ct->staged_status == GOT_STATUS_DELETE) {
4519 got_fileindex_entry_remove(fileindex, ie);
4520 } else if (ct->staged_status == GOT_STATUS_ADD ||
4521 ct->staged_status == GOT_STATUS_MODIFY) {
4522 got_fileindex_entry_stage_set(ie,
4523 GOT_FILEIDX_STAGE_NONE);
4524 err = got_fileindex_entry_update(ie,
4525 ct->ondisk_path, ct->staged_blob_id->sha1,
4526 new_base_commit_id->sha1,
4527 !have_staged_files);
4528 } else
4529 err = got_fileindex_entry_update(ie,
4530 ct->ondisk_path, ct->blob_id->sha1,
4531 new_base_commit_id->sha1,
4532 !have_staged_files);
4533 } else {
4534 err = got_fileindex_entry_alloc(&ie, pe->path);
4535 if (err)
4536 break;
4537 err = got_fileindex_entry_update(ie, ct->ondisk_path,
4538 ct->blob_id->sha1, new_base_commit_id->sha1, 1);
4539 if (err) {
4540 got_fileindex_entry_free(ie);
4541 break;
4543 err = got_fileindex_entry_add(fileindex, ie);
4544 if (err) {
4545 got_fileindex_entry_free(ie);
4546 break;
4550 return err;
4554 static const struct got_error *
4555 check_out_of_date(const char *in_repo_path, unsigned char status,
4556 unsigned char staged_status, struct got_object_id *base_blob_id,
4557 struct got_object_id *base_commit_id,
4558 struct got_object_id *head_commit_id, struct got_repository *repo,
4559 int ood_errcode)
4561 const struct got_error *err = NULL;
4562 struct got_object_id *id = NULL;
4564 if (status != GOT_STATUS_ADD && staged_status != GOT_STATUS_ADD) {
4565 /* Trivial case: base commit == head commit */
4566 if (got_object_id_cmp(base_commit_id, head_commit_id) == 0)
4567 return NULL;
4569 * Ensure file content which local changes were based
4570 * on matches file content in the branch head.
4572 err = got_object_id_by_path(&id, repo, head_commit_id,
4573 in_repo_path);
4574 if (err) {
4575 if (err->code == GOT_ERR_NO_TREE_ENTRY)
4576 err = got_error(ood_errcode);
4577 goto done;
4578 } else if (got_object_id_cmp(id, base_blob_id) != 0)
4579 err = got_error(ood_errcode);
4580 } else {
4581 /* Require that added files don't exist in the branch head. */
4582 err = got_object_id_by_path(&id, repo, head_commit_id,
4583 in_repo_path);
4584 if (err && err->code != GOT_ERR_NO_TREE_ENTRY)
4585 goto done;
4586 err = id ? got_error(ood_errcode) : NULL;
4588 done:
4589 free(id);
4590 return err;
4593 const struct got_error *
4594 commit_worktree(struct got_object_id **new_commit_id,
4595 struct got_pathlist_head *commitable_paths,
4596 struct got_object_id *head_commit_id, struct got_worktree *worktree,
4597 const char *author, const char *committer,
4598 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
4599 got_worktree_status_cb status_cb, void *status_arg,
4600 struct got_repository *repo)
4602 const struct got_error *err = NULL, *unlockerr = NULL;
4603 struct got_pathlist_entry *pe;
4604 const char *head_ref_name = NULL;
4605 struct got_commit_object *head_commit = NULL;
4606 struct got_reference *head_ref2 = NULL;
4607 struct got_object_id *head_commit_id2 = NULL;
4608 struct got_tree_object *head_tree = NULL;
4609 struct got_object_id *new_tree_id = NULL;
4610 int nentries;
4611 struct got_object_id_queue parent_ids;
4612 struct got_object_qid *pid = NULL;
4613 char *logmsg = NULL;
4615 *new_commit_id = NULL;
4617 SIMPLEQ_INIT(&parent_ids);
4619 err = got_object_open_as_commit(&head_commit, repo, head_commit_id);
4620 if (err)
4621 goto done;
4623 err = got_object_open_as_tree(&head_tree, repo, head_commit->tree_id);
4624 if (err)
4625 goto done;
4627 if (commit_msg_cb != NULL) {
4628 err = commit_msg_cb(commitable_paths, &logmsg, commit_arg);
4629 if (err)
4630 goto done;
4633 if (logmsg == NULL || strlen(logmsg) == 0) {
4634 err = got_error(GOT_ERR_COMMIT_MSG_EMPTY);
4635 goto done;
4638 /* Create blobs from added and modified files and record their IDs. */
4639 TAILQ_FOREACH(pe, commitable_paths, entry) {
4640 struct got_commitable *ct = pe->data;
4641 char *ondisk_path;
4643 /* Blobs for staged files already exist. */
4644 if (ct->staged_status == GOT_STATUS_ADD ||
4645 ct->staged_status == GOT_STATUS_MODIFY)
4646 continue;
4648 if (ct->status != GOT_STATUS_ADD &&
4649 ct->status != GOT_STATUS_MODIFY &&
4650 ct->status != GOT_STATUS_MODE_CHANGE)
4651 continue;
4653 if (asprintf(&ondisk_path, "%s/%s",
4654 worktree->root_path, pe->path) == -1) {
4655 err = got_error_from_errno("asprintf");
4656 goto done;
4658 err = got_object_blob_create(&ct->blob_id, ondisk_path, repo);
4659 free(ondisk_path);
4660 if (err)
4661 goto done;
4664 /* Recursively write new tree objects. */
4665 err = write_tree(&new_tree_id, &nentries, head_tree, "/",
4666 commitable_paths, status_cb, status_arg, repo);
4667 if (err)
4668 goto done;
4670 err = got_object_qid_alloc(&pid, worktree->base_commit_id);
4671 if (err)
4672 goto done;
4673 SIMPLEQ_INSERT_TAIL(&parent_ids, pid, entry);
4674 err = got_object_commit_create(new_commit_id, new_tree_id, &parent_ids,
4675 1, author, time(NULL), committer, time(NULL), logmsg, repo);
4676 got_object_qid_free(pid);
4677 if (logmsg != NULL)
4678 free(logmsg);
4679 if (err)
4680 goto done;
4682 /* Check if a concurrent commit to our branch has occurred. */
4683 head_ref_name = got_worktree_get_head_ref_name(worktree);
4684 if (head_ref_name == NULL) {
4685 err = got_error_from_errno("got_worktree_get_head_ref_name");
4686 goto done;
4688 /* Lock the reference here to prevent concurrent modification. */
4689 err = got_ref_open(&head_ref2, repo, head_ref_name, 1);
4690 if (err)
4691 goto done;
4692 err = got_ref_resolve(&head_commit_id2, repo, head_ref2);
4693 if (err)
4694 goto done;
4695 if (got_object_id_cmp(head_commit_id, head_commit_id2) != 0) {
4696 err = got_error(GOT_ERR_COMMIT_HEAD_CHANGED);
4697 goto done;
4699 /* Update branch head in repository. */
4700 err = got_ref_change_ref(head_ref2, *new_commit_id);
4701 if (err)
4702 goto done;
4703 err = got_ref_write(head_ref2, repo);
4704 if (err)
4705 goto done;
4707 err = got_worktree_set_base_commit_id(worktree, repo, *new_commit_id);
4708 if (err)
4709 goto done;
4711 err = ref_base_commit(worktree, repo);
4712 if (err)
4713 goto done;
4714 done:
4715 if (head_tree)
4716 got_object_tree_close(head_tree);
4717 if (head_commit)
4718 got_object_commit_close(head_commit);
4719 free(head_commit_id2);
4720 if (head_ref2) {
4721 unlockerr = got_ref_unlock(head_ref2);
4722 if (unlockerr && err == NULL)
4723 err = unlockerr;
4724 got_ref_close(head_ref2);
4726 return err;
4729 static const struct got_error *
4730 check_path_is_commitable(const char *path,
4731 struct got_pathlist_head *commitable_paths)
4733 struct got_pathlist_entry *cpe = NULL;
4734 size_t path_len = strlen(path);
4736 TAILQ_FOREACH(cpe, commitable_paths, entry) {
4737 struct got_commitable *ct = cpe->data;
4738 const char *ct_path = ct->path;
4740 while (ct_path[0] == '/')
4741 ct_path++;
4743 if (strcmp(path, ct_path) == 0 ||
4744 got_path_is_child(ct_path, path, path_len))
4745 break;
4748 if (cpe == NULL)
4749 return got_error_path(path, GOT_ERR_BAD_PATH);
4751 return NULL;
4754 static const struct got_error *
4755 check_staged_file(void *arg, struct got_fileindex_entry *ie)
4757 int *have_staged_files = arg;
4759 if (got_fileindex_entry_stage_get(ie) != GOT_FILEIDX_STAGE_NONE) {
4760 *have_staged_files = 1;
4761 return got_error(GOT_ERR_CANCELLED);
4764 return NULL;
4767 static const struct got_error *
4768 check_non_staged_files(struct got_fileindex *fileindex,
4769 struct got_pathlist_head *paths)
4771 struct got_pathlist_entry *pe;
4772 struct got_fileindex_entry *ie;
4774 TAILQ_FOREACH(pe, paths, entry) {
4775 if (pe->path[0] == '\0')
4776 continue;
4777 ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
4778 if (ie == NULL)
4779 return got_error_path(pe->path, GOT_ERR_BAD_PATH);
4780 if (got_fileindex_entry_stage_get(ie) == GOT_FILEIDX_STAGE_NONE)
4781 return got_error_path(pe->path,
4782 GOT_ERR_FILE_NOT_STAGED);
4785 return NULL;
4788 const struct got_error *
4789 got_worktree_commit(struct got_object_id **new_commit_id,
4790 struct got_worktree *worktree, struct got_pathlist_head *paths,
4791 const char *author, const char *committer,
4792 got_worktree_commit_msg_cb commit_msg_cb, void *commit_arg,
4793 got_worktree_status_cb status_cb, void *status_arg,
4794 struct got_repository *repo)
4796 const struct got_error *err = NULL, *unlockerr = NULL, *sync_err;
4797 struct got_fileindex *fileindex = NULL;
4798 char *fileindex_path = NULL;
4799 struct got_pathlist_head commitable_paths;
4800 struct collect_commitables_arg cc_arg;
4801 struct got_pathlist_entry *pe;
4802 struct got_reference *head_ref = NULL;
4803 struct got_object_id *head_commit_id = NULL;
4804 int have_staged_files = 0;
4806 *new_commit_id = NULL;
4808 TAILQ_INIT(&commitable_paths);
4810 err = lock_worktree(worktree, LOCK_EX);
4811 if (err)
4812 goto done;
4814 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
4815 if (err)
4816 goto done;
4818 err = got_ref_resolve(&head_commit_id, repo, head_ref);
4819 if (err)
4820 goto done;
4822 err = open_fileindex(&fileindex, &fileindex_path, worktree);
4823 if (err)
4824 goto done;
4826 err = got_fileindex_for_each_entry_safe(fileindex, check_staged_file,
4827 &have_staged_files);
4828 if (err && err->code != GOT_ERR_CANCELLED)
4829 goto done;
4830 if (have_staged_files) {
4831 err = check_non_staged_files(fileindex, paths);
4832 if (err)
4833 goto done;
4836 cc_arg.commitable_paths = &commitable_paths;
4837 cc_arg.worktree = worktree;
4838 cc_arg.repo = repo;
4839 cc_arg.have_staged_files = have_staged_files;
4840 TAILQ_FOREACH(pe, paths, entry) {
4841 err = worktree_status(worktree, pe->path, fileindex, repo,
4842 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
4843 if (err)
4844 goto done;
4847 if (TAILQ_EMPTY(&commitable_paths)) {
4848 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
4849 goto done;
4852 TAILQ_FOREACH(pe, paths, entry) {
4853 err = check_path_is_commitable(pe->path, &commitable_paths);
4854 if (err)
4855 goto done;
4858 TAILQ_FOREACH(pe, &commitable_paths, entry) {
4859 struct got_commitable *ct = pe->data;
4860 const char *ct_path = ct->in_repo_path;
4862 while (ct_path[0] == '/')
4863 ct_path++;
4864 err = check_out_of_date(ct_path, ct->status,
4865 ct->staged_status, ct->base_blob_id, ct->base_commit_id,
4866 head_commit_id, repo, GOT_ERR_COMMIT_OUT_OF_DATE);
4867 if (err)
4868 goto done;
4872 err = commit_worktree(new_commit_id, &commitable_paths,
4873 head_commit_id, worktree, author, committer,
4874 commit_msg_cb, commit_arg, status_cb, status_arg, repo);
4875 if (err)
4876 goto done;
4878 err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
4879 fileindex, have_staged_files);
4880 sync_err = sync_fileindex(fileindex, fileindex_path);
4881 if (sync_err && err == NULL)
4882 err = sync_err;
4883 done:
4884 if (fileindex)
4885 got_fileindex_free(fileindex);
4886 free(fileindex_path);
4887 unlockerr = lock_worktree(worktree, LOCK_SH);
4888 if (unlockerr && err == NULL)
4889 err = unlockerr;
4890 TAILQ_FOREACH(pe, &commitable_paths, entry) {
4891 struct got_commitable *ct = pe->data;
4892 free_commitable(ct);
4894 got_pathlist_free(&commitable_paths);
4895 return err;
4898 const char *
4899 got_commitable_get_path(struct got_commitable *ct)
4901 return ct->path;
4904 unsigned int
4905 got_commitable_get_status(struct got_commitable *ct)
4907 return ct->status;
4910 struct check_rebase_ok_arg {
4911 struct got_worktree *worktree;
4912 struct got_repository *repo;
4915 static const struct got_error *
4916 check_rebase_ok(void *arg, struct got_fileindex_entry *ie)
4918 const struct got_error *err = NULL;
4919 struct check_rebase_ok_arg *a = arg;
4920 unsigned char status;
4921 struct stat sb;
4922 char *ondisk_path;
4924 /* Reject rebase of a work tree with mixed base commits. */
4925 if (memcmp(ie->commit_sha1, a->worktree->base_commit_id->sha1,
4926 SHA1_DIGEST_LENGTH))
4927 return got_error(GOT_ERR_MIXED_COMMITS);
4929 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, ie->path)
4930 == -1)
4931 return got_error_from_errno("asprintf");
4933 /* Reject rebase of a work tree with modified or staged files. */
4934 err = get_file_status(&status, &sb, ie, ondisk_path, -1, NULL, a->repo);
4935 free(ondisk_path);
4936 if (err)
4937 return err;
4939 if (status != GOT_STATUS_NO_CHANGE)
4940 return got_error(GOT_ERR_MODIFIED);
4941 if (get_staged_status(ie) != GOT_STATUS_NO_CHANGE)
4942 return got_error_path(ie->path, GOT_ERR_FILE_STAGED);
4944 return NULL;
4947 const struct got_error *
4948 got_worktree_rebase_prepare(struct got_reference **new_base_branch_ref,
4949 struct got_reference **tmp_branch, struct got_fileindex **fileindex,
4950 struct got_worktree *worktree, struct got_reference *branch,
4951 struct got_repository *repo)
4953 const struct got_error *err = NULL;
4954 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
4955 char *branch_ref_name = NULL;
4956 char *fileindex_path = NULL;
4957 struct check_rebase_ok_arg ok_arg;
4958 struct got_reference *wt_branch = NULL, *branch_ref = NULL;
4959 struct got_object_id *wt_branch_tip = NULL;
4961 *new_base_branch_ref = NULL;
4962 *tmp_branch = NULL;
4963 *fileindex = NULL;
4965 err = lock_worktree(worktree, LOCK_EX);
4966 if (err)
4967 return err;
4969 err = open_fileindex(fileindex, &fileindex_path, worktree);
4970 if (err)
4971 goto done;
4973 ok_arg.worktree = worktree;
4974 ok_arg.repo = repo;
4975 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
4976 &ok_arg);
4977 if (err)
4978 goto done;
4980 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
4981 if (err)
4982 goto done;
4984 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
4985 if (err)
4986 goto done;
4988 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
4989 if (err)
4990 goto done;
4992 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
4993 0);
4994 if (err)
4995 goto done;
4997 err = got_ref_resolve(&wt_branch_tip, repo, wt_branch);
4998 if (err)
4999 goto done;
5000 if (got_object_id_cmp(worktree->base_commit_id, wt_branch_tip) != 0) {
5001 err = got_error(GOT_ERR_REBASE_OUT_OF_DATE);
5002 goto done;
5005 err = got_ref_alloc_symref(new_base_branch_ref,
5006 new_base_branch_ref_name, wt_branch);
5007 if (err)
5008 goto done;
5009 err = got_ref_write(*new_base_branch_ref, repo);
5010 if (err)
5011 goto done;
5013 /* TODO Lock original branch's ref while rebasing? */
5015 err = got_ref_alloc_symref(&branch_ref, branch_ref_name, branch);
5016 if (err)
5017 goto done;
5019 err = got_ref_write(branch_ref, repo);
5020 if (err)
5021 goto done;
5023 err = got_ref_alloc(tmp_branch, tmp_branch_name,
5024 worktree->base_commit_id);
5025 if (err)
5026 goto done;
5027 err = got_ref_write(*tmp_branch, repo);
5028 if (err)
5029 goto done;
5031 err = got_worktree_set_head_ref(worktree, *tmp_branch);
5032 if (err)
5033 goto done;
5034 done:
5035 free(fileindex_path);
5036 free(tmp_branch_name);
5037 free(new_base_branch_ref_name);
5038 free(branch_ref_name);
5039 if (branch_ref)
5040 got_ref_close(branch_ref);
5041 if (wt_branch)
5042 got_ref_close(wt_branch);
5043 free(wt_branch_tip);
5044 if (err) {
5045 if (*new_base_branch_ref) {
5046 got_ref_close(*new_base_branch_ref);
5047 *new_base_branch_ref = NULL;
5049 if (*tmp_branch) {
5050 got_ref_close(*tmp_branch);
5051 *tmp_branch = NULL;
5053 if (*fileindex) {
5054 got_fileindex_free(*fileindex);
5055 *fileindex = NULL;
5057 lock_worktree(worktree, LOCK_SH);
5059 return err;
5062 const struct got_error *
5063 got_worktree_rebase_continue(struct got_object_id **commit_id,
5064 struct got_reference **new_base_branch, struct got_reference **tmp_branch,
5065 struct got_reference **branch, struct got_fileindex **fileindex,
5066 struct got_worktree *worktree, struct got_repository *repo)
5068 const struct got_error *err;
5069 char *commit_ref_name = NULL, *new_base_branch_ref_name = NULL;
5070 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
5071 struct got_reference *commit_ref = NULL, *branch_ref = NULL;
5072 char *fileindex_path = NULL;
5073 int have_staged_files = 0;
5075 *commit_id = NULL;
5076 *new_base_branch = NULL;
5077 *tmp_branch = NULL;
5078 *branch = NULL;
5079 *fileindex = NULL;
5081 err = lock_worktree(worktree, LOCK_EX);
5082 if (err)
5083 return err;
5085 err = open_fileindex(fileindex, &fileindex_path, worktree);
5086 if (err)
5087 goto done;
5089 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
5090 &have_staged_files);
5091 if (err && err->code != GOT_ERR_CANCELLED)
5092 goto done;
5093 if (have_staged_files) {
5094 err = got_error(GOT_ERR_STAGED_PATHS);
5095 goto done;
5098 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5099 if (err)
5100 goto done;
5102 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
5103 if (err)
5104 goto done;
5106 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
5107 if (err)
5108 goto done;
5110 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
5111 if (err)
5112 goto done;
5114 err = got_ref_open(&branch_ref, repo, branch_ref_name, 0);
5115 if (err)
5116 goto done;
5118 err = got_ref_open(branch, repo,
5119 got_ref_get_symref_target(branch_ref), 0);
5120 if (err)
5121 goto done;
5123 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5124 if (err)
5125 goto done;
5127 err = got_ref_resolve(commit_id, repo, commit_ref);
5128 if (err)
5129 goto done;
5131 err = got_ref_open(new_base_branch, repo,
5132 new_base_branch_ref_name, 0);
5133 if (err)
5134 goto done;
5136 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
5137 if (err)
5138 goto done;
5139 done:
5140 free(commit_ref_name);
5141 free(branch_ref_name);
5142 free(fileindex_path);
5143 if (commit_ref)
5144 got_ref_close(commit_ref);
5145 if (branch_ref)
5146 got_ref_close(branch_ref);
5147 if (err) {
5148 free(*commit_id);
5149 *commit_id = NULL;
5150 if (*tmp_branch) {
5151 got_ref_close(*tmp_branch);
5152 *tmp_branch = NULL;
5154 if (*new_base_branch) {
5155 got_ref_close(*new_base_branch);
5156 *new_base_branch = NULL;
5158 if (*branch) {
5159 got_ref_close(*branch);
5160 *branch = NULL;
5162 if (*fileindex) {
5163 got_fileindex_free(*fileindex);
5164 *fileindex = NULL;
5166 lock_worktree(worktree, LOCK_SH);
5168 return err;
5171 const struct got_error *
5172 got_worktree_rebase_in_progress(int *in_progress, struct got_worktree *worktree)
5174 const struct got_error *err;
5175 char *tmp_branch_name = NULL;
5177 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5178 if (err)
5179 return err;
5181 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
5182 free(tmp_branch_name);
5183 return NULL;
5186 static const struct got_error *
5187 collect_rebase_commit_msg(struct got_pathlist_head *commitable_paths,
5188 char **logmsg, void *arg)
5190 *logmsg = arg;
5191 return NULL;
5194 static const struct got_error *
5195 rebase_status(void *arg, unsigned char status, unsigned char staged_status,
5196 const char *path, struct got_object_id *blob_id,
5197 struct got_object_id *staged_blob_id, struct got_object_id *commit_id,
5198 int dirfd, const char *de_name)
5200 return NULL;
5203 struct collect_merged_paths_arg {
5204 got_worktree_checkout_cb progress_cb;
5205 void *progress_arg;
5206 struct got_pathlist_head *merged_paths;
5209 static const struct got_error *
5210 collect_merged_paths(void *arg, unsigned char status, const char *path)
5212 const struct got_error *err;
5213 struct collect_merged_paths_arg *a = arg;
5214 char *p;
5215 struct got_pathlist_entry *new;
5217 err = (*a->progress_cb)(a->progress_arg, status, path);
5218 if (err)
5219 return err;
5221 if (status != GOT_STATUS_MERGE &&
5222 status != GOT_STATUS_ADD &&
5223 status != GOT_STATUS_DELETE &&
5224 status != GOT_STATUS_CONFLICT)
5225 return NULL;
5227 p = strdup(path);
5228 if (p == NULL)
5229 return got_error_from_errno("strdup");
5231 err = got_pathlist_insert(&new, a->merged_paths, p, NULL);
5232 if (err || new == NULL)
5233 free(p);
5234 return err;
5237 void
5238 got_worktree_rebase_pathlist_free(struct got_pathlist_head *merged_paths)
5240 struct got_pathlist_entry *pe;
5242 TAILQ_FOREACH(pe, merged_paths, entry)
5243 free((char *)pe->path);
5245 got_pathlist_free(merged_paths);
5248 static const struct got_error *
5249 store_commit_id(const char *commit_ref_name, struct got_object_id *commit_id,
5250 int is_rebase, struct got_repository *repo)
5252 const struct got_error *err;
5253 struct got_reference *commit_ref = NULL;
5255 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5256 if (err) {
5257 if (err->code != GOT_ERR_NOT_REF)
5258 goto done;
5259 err = got_ref_alloc(&commit_ref, commit_ref_name, commit_id);
5260 if (err)
5261 goto done;
5262 err = got_ref_write(commit_ref, repo);
5263 if (err)
5264 goto done;
5265 } else if (is_rebase) {
5266 struct got_object_id *stored_id;
5267 int cmp;
5269 err = got_ref_resolve(&stored_id, repo, commit_ref);
5270 if (err)
5271 goto done;
5272 cmp = got_object_id_cmp(commit_id, stored_id);
5273 free(stored_id);
5274 if (cmp != 0) {
5275 err = got_error(GOT_ERR_REBASE_COMMITID);
5276 goto done;
5279 done:
5280 if (commit_ref)
5281 got_ref_close(commit_ref);
5282 return err;
5285 static const struct got_error *
5286 rebase_merge_files(struct got_pathlist_head *merged_paths,
5287 const char *commit_ref_name, struct got_worktree *worktree,
5288 struct got_fileindex *fileindex, struct got_object_id *parent_commit_id,
5289 struct got_object_id *commit_id, struct got_repository *repo,
5290 got_worktree_checkout_cb progress_cb, void *progress_arg,
5291 got_cancel_cb cancel_cb, void *cancel_arg)
5293 const struct got_error *err;
5294 struct got_reference *commit_ref = NULL;
5295 struct collect_merged_paths_arg cmp_arg;
5296 char *fileindex_path;
5298 /* Work tree is locked/unlocked during rebase preparation/teardown. */
5300 err = get_fileindex_path(&fileindex_path, worktree);
5301 if (err)
5302 return err;
5304 cmp_arg.progress_cb = progress_cb;
5305 cmp_arg.progress_arg = progress_arg;
5306 cmp_arg.merged_paths = merged_paths;
5307 err = merge_files(worktree, fileindex, fileindex_path,
5308 parent_commit_id, commit_id, repo, collect_merged_paths,
5309 &cmp_arg, cancel_cb, cancel_arg);
5310 if (commit_ref)
5311 got_ref_close(commit_ref);
5312 return err;
5315 const struct got_error *
5316 got_worktree_rebase_merge_files(struct got_pathlist_head *merged_paths,
5317 struct got_worktree *worktree, struct got_fileindex *fileindex,
5318 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
5319 struct got_repository *repo,
5320 got_worktree_checkout_cb progress_cb, void *progress_arg,
5321 got_cancel_cb cancel_cb, void *cancel_arg)
5323 const struct got_error *err;
5324 char *commit_ref_name;
5326 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
5327 if (err)
5328 return err;
5330 err = store_commit_id(commit_ref_name, commit_id, 1, repo);
5331 if (err)
5332 goto done;
5334 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
5335 fileindex, parent_commit_id, commit_id, repo, progress_cb,
5336 progress_arg, cancel_cb, cancel_arg);
5337 done:
5338 free(commit_ref_name);
5339 return err;
5342 const struct got_error *
5343 got_worktree_histedit_merge_files(struct got_pathlist_head *merged_paths,
5344 struct got_worktree *worktree, struct got_fileindex *fileindex,
5345 struct got_object_id *parent_commit_id, struct got_object_id *commit_id,
5346 struct got_repository *repo,
5347 got_worktree_checkout_cb progress_cb, void *progress_arg,
5348 got_cancel_cb cancel_cb, void *cancel_arg)
5350 const struct got_error *err;
5351 char *commit_ref_name;
5353 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
5354 if (err)
5355 return err;
5357 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
5358 if (err)
5359 goto done;
5361 err = rebase_merge_files(merged_paths, commit_ref_name, worktree,
5362 fileindex, parent_commit_id, commit_id, repo, progress_cb,
5363 progress_arg, cancel_cb, cancel_arg);
5364 done:
5365 free(commit_ref_name);
5366 return err;
5369 static const struct got_error *
5370 rebase_commit(struct got_object_id **new_commit_id,
5371 struct got_pathlist_head *merged_paths, struct got_reference *commit_ref,
5372 struct got_worktree *worktree, struct got_fileindex *fileindex,
5373 struct got_reference *tmp_branch, struct got_commit_object *orig_commit,
5374 const char *new_logmsg, struct got_repository *repo)
5376 const struct got_error *err, *sync_err;
5377 struct got_pathlist_head commitable_paths;
5378 struct collect_commitables_arg cc_arg;
5379 char *fileindex_path = NULL;
5380 struct got_reference *head_ref = NULL;
5381 struct got_object_id *head_commit_id = NULL;
5382 char *logmsg = NULL;
5384 TAILQ_INIT(&commitable_paths);
5385 *new_commit_id = NULL;
5387 /* Work tree is locked/unlocked during rebase preparation/teardown. */
5389 err = get_fileindex_path(&fileindex_path, worktree);
5390 if (err)
5391 return err;
5393 cc_arg.commitable_paths = &commitable_paths;
5394 cc_arg.worktree = worktree;
5395 cc_arg.repo = repo;
5396 cc_arg.have_staged_files = 0;
5398 * If possible get the status of individual files directly to
5399 * avoid crawling the entire work tree once per rebased commit.
5400 * TODO: Ideally, merged_paths would contain a list of commitables
5401 * we could use so we could skip worktree_status() entirely.
5403 if (merged_paths) {
5404 struct got_pathlist_entry *pe;
5405 TAILQ_FOREACH(pe, merged_paths, entry) {
5406 err = worktree_status(worktree, pe->path, fileindex,
5407 repo, collect_commitables, &cc_arg, NULL, NULL, 0,
5408 0);
5409 if (err)
5410 goto done;
5412 } else {
5413 err = worktree_status(worktree, "", fileindex, repo,
5414 collect_commitables, &cc_arg, NULL, NULL, 0, 0);
5415 if (err)
5416 goto done;
5419 if (TAILQ_EMPTY(&commitable_paths)) {
5420 /* No-op change; commit will be elided. */
5421 err = got_ref_delete(commit_ref, repo);
5422 if (err)
5423 goto done;
5424 err = got_error(GOT_ERR_COMMIT_NO_CHANGES);
5425 goto done;
5428 err = got_ref_open(&head_ref, repo, worktree->head_ref_name, 0);
5429 if (err)
5430 goto done;
5432 err = got_ref_resolve(&head_commit_id, repo, head_ref);
5433 if (err)
5434 goto done;
5436 if (new_logmsg) {
5437 logmsg = strdup(new_logmsg);
5438 if (logmsg == NULL) {
5439 err = got_error_from_errno("strdup");
5440 goto done;
5442 } else {
5443 err = got_object_commit_get_logmsg(&logmsg, orig_commit);
5444 if (err)
5445 goto done;
5448 /* NB: commit_worktree will call free(logmsg) */
5449 err = commit_worktree(new_commit_id, &commitable_paths, head_commit_id,
5450 worktree, got_object_commit_get_author(orig_commit),
5451 got_object_commit_get_committer(orig_commit),
5452 collect_rebase_commit_msg, logmsg, rebase_status, NULL, repo);
5453 if (err)
5454 goto done;
5456 err = got_ref_change_ref(tmp_branch, *new_commit_id);
5457 if (err)
5458 goto done;
5460 err = got_ref_delete(commit_ref, repo);
5461 if (err)
5462 goto done;
5464 err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
5465 fileindex, 0);
5466 sync_err = sync_fileindex(fileindex, fileindex_path);
5467 if (sync_err && err == NULL)
5468 err = sync_err;
5469 done:
5470 free(fileindex_path);
5471 free(head_commit_id);
5472 if (head_ref)
5473 got_ref_close(head_ref);
5474 if (err) {
5475 free(*new_commit_id);
5476 *new_commit_id = NULL;
5478 return err;
5481 const struct got_error *
5482 got_worktree_rebase_commit(struct got_object_id **new_commit_id,
5483 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
5484 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
5485 struct got_commit_object *orig_commit,
5486 struct got_object_id *orig_commit_id, struct got_repository *repo)
5488 const struct got_error *err;
5489 char *commit_ref_name;
5490 struct got_reference *commit_ref = NULL;
5491 struct got_object_id *commit_id = NULL;
5493 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
5494 if (err)
5495 return err;
5497 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5498 if (err)
5499 goto done;
5500 err = got_ref_resolve(&commit_id, repo, commit_ref);
5501 if (err)
5502 goto done;
5503 if (got_object_id_cmp(commit_id, orig_commit_id) != 0) {
5504 err = got_error(GOT_ERR_REBASE_COMMITID);
5505 goto done;
5508 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
5509 worktree, fileindex, tmp_branch, orig_commit, NULL, repo);
5510 done:
5511 if (commit_ref)
5512 got_ref_close(commit_ref);
5513 free(commit_ref_name);
5514 free(commit_id);
5515 return err;
5518 const struct got_error *
5519 got_worktree_histedit_commit(struct got_object_id **new_commit_id,
5520 struct got_pathlist_head *merged_paths, struct got_worktree *worktree,
5521 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
5522 struct got_commit_object *orig_commit,
5523 struct got_object_id *orig_commit_id, const char *new_logmsg,
5524 struct got_repository *repo)
5526 const struct got_error *err;
5527 char *commit_ref_name;
5528 struct got_reference *commit_ref = NULL;
5530 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
5531 if (err)
5532 return err;
5534 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5535 if (err)
5536 goto done;
5538 err = rebase_commit(new_commit_id, merged_paths, commit_ref,
5539 worktree, fileindex, tmp_branch, orig_commit, new_logmsg, repo);
5540 done:
5541 if (commit_ref)
5542 got_ref_close(commit_ref);
5543 free(commit_ref_name);
5544 return err;
5547 const struct got_error *
5548 got_worktree_rebase_postpone(struct got_worktree *worktree,
5549 struct got_fileindex *fileindex)
5551 if (fileindex)
5552 got_fileindex_free(fileindex);
5553 return lock_worktree(worktree, LOCK_SH);
5556 static const struct got_error *
5557 delete_ref(const char *name, struct got_repository *repo)
5559 const struct got_error *err;
5560 struct got_reference *ref;
5562 err = got_ref_open(&ref, repo, name, 0);
5563 if (err) {
5564 if (err->code == GOT_ERR_NOT_REF)
5565 return NULL;
5566 return err;
5569 err = got_ref_delete(ref, repo);
5570 got_ref_close(ref);
5571 return err;
5574 static const struct got_error *
5575 delete_rebase_refs(struct got_worktree *worktree, struct got_repository *repo)
5577 const struct got_error *err;
5578 char *tmp_branch_name = NULL, *new_base_branch_ref_name = NULL;
5579 char *branch_ref_name = NULL, *commit_ref_name = NULL;
5581 err = get_rebase_tmp_ref_name(&tmp_branch_name, worktree);
5582 if (err)
5583 goto done;
5584 err = delete_ref(tmp_branch_name, repo);
5585 if (err)
5586 goto done;
5588 err = get_newbase_symref_name(&new_base_branch_ref_name, worktree);
5589 if (err)
5590 goto done;
5591 err = delete_ref(new_base_branch_ref_name, repo);
5592 if (err)
5593 goto done;
5595 err = get_rebase_branch_symref_name(&branch_ref_name, worktree);
5596 if (err)
5597 goto done;
5598 err = delete_ref(branch_ref_name, repo);
5599 if (err)
5600 goto done;
5602 err = get_rebase_commit_ref_name(&commit_ref_name, worktree);
5603 if (err)
5604 goto done;
5605 err = delete_ref(commit_ref_name, repo);
5606 if (err)
5607 goto done;
5609 done:
5610 free(tmp_branch_name);
5611 free(new_base_branch_ref_name);
5612 free(branch_ref_name);
5613 free(commit_ref_name);
5614 return err;
5617 const struct got_error *
5618 got_worktree_rebase_complete(struct got_worktree *worktree,
5619 struct got_fileindex *fileindex, struct got_reference *new_base_branch,
5620 struct got_reference *tmp_branch, struct got_reference *rebased_branch,
5621 struct got_repository *repo)
5623 const struct got_error *err, *unlockerr;
5624 struct got_object_id *new_head_commit_id = NULL;
5626 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
5627 if (err)
5628 return err;
5630 err = got_ref_change_ref(rebased_branch, new_head_commit_id);
5631 if (err)
5632 goto done;
5634 err = got_ref_write(rebased_branch, repo);
5635 if (err)
5636 goto done;
5638 err = got_worktree_set_head_ref(worktree, rebased_branch);
5639 if (err)
5640 goto done;
5642 err = delete_rebase_refs(worktree, repo);
5643 done:
5644 if (fileindex)
5645 got_fileindex_free(fileindex);
5646 free(new_head_commit_id);
5647 unlockerr = lock_worktree(worktree, LOCK_SH);
5648 if (unlockerr && err == NULL)
5649 err = unlockerr;
5650 return err;
5653 const struct got_error *
5654 got_worktree_rebase_abort(struct got_worktree *worktree,
5655 struct got_fileindex *fileindex, struct got_repository *repo,
5656 struct got_reference *new_base_branch,
5657 got_worktree_checkout_cb progress_cb, void *progress_arg)
5659 const struct got_error *err, *unlockerr, *sync_err;
5660 struct got_reference *resolved = NULL;
5661 struct got_object_id *commit_id = NULL;
5662 char *fileindex_path = NULL;
5663 struct revert_file_args rfa;
5664 struct got_object_id *tree_id = NULL;
5666 err = lock_worktree(worktree, LOCK_EX);
5667 if (err)
5668 return err;
5670 err = got_ref_open(&resolved, repo,
5671 got_ref_get_symref_target(new_base_branch), 0);
5672 if (err)
5673 goto done;
5675 err = got_worktree_set_head_ref(worktree, resolved);
5676 if (err)
5677 goto done;
5680 * XXX commits to the base branch could have happened while
5681 * we were busy rebasing; should we store the original commit ID
5682 * when rebase begins and read it back here?
5684 err = got_ref_resolve(&commit_id, repo, resolved);
5685 if (err)
5686 goto done;
5688 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
5689 if (err)
5690 goto done;
5692 err = got_object_id_by_path(&tree_id, repo,
5693 worktree->base_commit_id, worktree->path_prefix);
5694 if (err)
5695 goto done;
5697 err = delete_rebase_refs(worktree, repo);
5698 if (err)
5699 goto done;
5701 err = get_fileindex_path(&fileindex_path, worktree);
5702 if (err)
5703 goto done;
5705 rfa.worktree = worktree;
5706 rfa.fileindex = fileindex;
5707 rfa.progress_cb = progress_cb;
5708 rfa.progress_arg = progress_arg;
5709 rfa.patch_cb = NULL;
5710 rfa.patch_arg = NULL;
5711 rfa.repo = repo;
5712 err = worktree_status(worktree, "", fileindex, repo,
5713 revert_file, &rfa, NULL, NULL, 0, 0);
5714 if (err)
5715 goto sync;
5717 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
5718 repo, progress_cb, progress_arg, NULL, NULL);
5719 sync:
5720 sync_err = sync_fileindex(fileindex, fileindex_path);
5721 if (sync_err && err == NULL)
5722 err = sync_err;
5723 done:
5724 got_ref_close(resolved);
5725 free(tree_id);
5726 free(commit_id);
5727 if (fileindex)
5728 got_fileindex_free(fileindex);
5729 free(fileindex_path);
5731 unlockerr = lock_worktree(worktree, LOCK_SH);
5732 if (unlockerr && err == NULL)
5733 err = unlockerr;
5734 return err;
5737 const struct got_error *
5738 got_worktree_histedit_prepare(struct got_reference **tmp_branch,
5739 struct got_reference **branch_ref, struct got_object_id **base_commit_id,
5740 struct got_fileindex **fileindex, struct got_worktree *worktree,
5741 struct got_repository *repo)
5743 const struct got_error *err = NULL;
5744 char *tmp_branch_name = NULL;
5745 char *branch_ref_name = NULL;
5746 char *base_commit_ref_name = NULL;
5747 char *fileindex_path = NULL;
5748 struct check_rebase_ok_arg ok_arg;
5749 struct got_reference *wt_branch = NULL;
5750 struct got_reference *base_commit_ref = NULL;
5752 *tmp_branch = NULL;
5753 *branch_ref = NULL;
5754 *base_commit_id = NULL;
5755 *fileindex = NULL;
5757 err = lock_worktree(worktree, LOCK_EX);
5758 if (err)
5759 return err;
5761 err = open_fileindex(fileindex, &fileindex_path, worktree);
5762 if (err)
5763 goto done;
5765 ok_arg.worktree = worktree;
5766 ok_arg.repo = repo;
5767 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
5768 &ok_arg);
5769 if (err)
5770 goto done;
5772 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
5773 if (err)
5774 goto done;
5776 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
5777 if (err)
5778 goto done;
5780 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
5781 worktree);
5782 if (err)
5783 goto done;
5785 err = got_ref_open(&wt_branch, repo, worktree->head_ref_name,
5786 0);
5787 if (err)
5788 goto done;
5790 err = got_ref_alloc_symref(branch_ref, branch_ref_name, wt_branch);
5791 if (err)
5792 goto done;
5794 err = got_ref_write(*branch_ref, repo);
5795 if (err)
5796 goto done;
5798 err = got_ref_alloc(&base_commit_ref, base_commit_ref_name,
5799 worktree->base_commit_id);
5800 if (err)
5801 goto done;
5802 err = got_ref_write(base_commit_ref, repo);
5803 if (err)
5804 goto done;
5805 *base_commit_id = got_object_id_dup(worktree->base_commit_id);
5806 if (*base_commit_id == NULL) {
5807 err = got_error_from_errno("got_object_id_dup");
5808 goto done;
5811 err = got_ref_alloc(tmp_branch, tmp_branch_name,
5812 worktree->base_commit_id);
5813 if (err)
5814 goto done;
5815 err = got_ref_write(*tmp_branch, repo);
5816 if (err)
5817 goto done;
5819 err = got_worktree_set_head_ref(worktree, *tmp_branch);
5820 if (err)
5821 goto done;
5822 done:
5823 free(fileindex_path);
5824 free(tmp_branch_name);
5825 free(branch_ref_name);
5826 free(base_commit_ref_name);
5827 if (wt_branch)
5828 got_ref_close(wt_branch);
5829 if (err) {
5830 if (*branch_ref) {
5831 got_ref_close(*branch_ref);
5832 *branch_ref = NULL;
5834 if (*tmp_branch) {
5835 got_ref_close(*tmp_branch);
5836 *tmp_branch = NULL;
5838 free(*base_commit_id);
5839 if (*fileindex) {
5840 got_fileindex_free(*fileindex);
5841 *fileindex = NULL;
5843 lock_worktree(worktree, LOCK_SH);
5845 return err;
5848 const struct got_error *
5849 got_worktree_histedit_postpone(struct got_worktree *worktree,
5850 struct got_fileindex *fileindex)
5852 if (fileindex)
5853 got_fileindex_free(fileindex);
5854 return lock_worktree(worktree, LOCK_SH);
5857 const struct got_error *
5858 got_worktree_histedit_in_progress(int *in_progress,
5859 struct got_worktree *worktree)
5861 const struct got_error *err;
5862 char *tmp_branch_name = NULL;
5864 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
5865 if (err)
5866 return err;
5868 *in_progress = (strcmp(tmp_branch_name, worktree->head_ref_name) == 0);
5869 free(tmp_branch_name);
5870 return NULL;
5873 const struct got_error *
5874 got_worktree_histedit_continue(struct got_object_id **commit_id,
5875 struct got_reference **tmp_branch, struct got_reference **branch_ref,
5876 struct got_object_id **base_commit_id, struct got_fileindex **fileindex,
5877 struct got_worktree *worktree, struct got_repository *repo)
5879 const struct got_error *err;
5880 char *commit_ref_name = NULL, *base_commit_ref_name = NULL;
5881 char *tmp_branch_name = NULL, *branch_ref_name = NULL;
5882 struct got_reference *commit_ref = NULL;
5883 struct got_reference *base_commit_ref = NULL;
5884 char *fileindex_path = NULL;
5885 int have_staged_files = 0;
5887 *commit_id = NULL;
5888 *tmp_branch = NULL;
5889 *base_commit_id = NULL;
5890 *fileindex = NULL;
5892 err = lock_worktree(worktree, LOCK_EX);
5893 if (err)
5894 return err;
5896 err = open_fileindex(fileindex, &fileindex_path, worktree);
5897 if (err)
5898 goto done;
5900 err = got_fileindex_for_each_entry_safe(*fileindex, check_staged_file,
5901 &have_staged_files);
5902 if (err && err->code != GOT_ERR_CANCELLED)
5903 goto done;
5904 if (have_staged_files) {
5905 err = got_error(GOT_ERR_STAGED_PATHS);
5906 goto done;
5909 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
5910 if (err)
5911 goto done;
5913 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
5914 if (err)
5915 goto done;
5917 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
5918 if (err)
5919 goto done;
5921 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
5922 worktree);
5923 if (err)
5924 goto done;
5926 err = got_ref_open(branch_ref, repo, branch_ref_name, 0);
5927 if (err)
5928 goto done;
5930 err = got_ref_open(&commit_ref, repo, commit_ref_name, 0);
5931 if (err)
5932 goto done;
5933 err = got_ref_resolve(commit_id, repo, commit_ref);
5934 if (err)
5935 goto done;
5937 err = got_ref_open(&base_commit_ref, repo, base_commit_ref_name, 0);
5938 if (err)
5939 goto done;
5940 err = got_ref_resolve(base_commit_id, repo, base_commit_ref);
5941 if (err)
5942 goto done;
5944 err = got_ref_open(tmp_branch, repo, tmp_branch_name, 0);
5945 if (err)
5946 goto done;
5947 done:
5948 free(commit_ref_name);
5949 free(branch_ref_name);
5950 free(fileindex_path);
5951 if (commit_ref)
5952 got_ref_close(commit_ref);
5953 if (base_commit_ref)
5954 got_ref_close(base_commit_ref);
5955 if (err) {
5956 free(*commit_id);
5957 *commit_id = NULL;
5958 free(*base_commit_id);
5959 *base_commit_id = NULL;
5960 if (*tmp_branch) {
5961 got_ref_close(*tmp_branch);
5962 *tmp_branch = NULL;
5964 if (*fileindex) {
5965 got_fileindex_free(*fileindex);
5966 *fileindex = NULL;
5968 lock_worktree(worktree, LOCK_EX);
5970 return err;
5973 static const struct got_error *
5974 delete_histedit_refs(struct got_worktree *worktree, struct got_repository *repo)
5976 const struct got_error *err;
5977 char *tmp_branch_name = NULL, *base_commit_ref_name = NULL;
5978 char *branch_ref_name = NULL, *commit_ref_name = NULL;
5980 err = get_histedit_tmp_ref_name(&tmp_branch_name, worktree);
5981 if (err)
5982 goto done;
5983 err = delete_ref(tmp_branch_name, repo);
5984 if (err)
5985 goto done;
5987 err = get_histedit_base_commit_ref_name(&base_commit_ref_name,
5988 worktree);
5989 if (err)
5990 goto done;
5991 err = delete_ref(base_commit_ref_name, repo);
5992 if (err)
5993 goto done;
5995 err = get_histedit_branch_symref_name(&branch_ref_name, worktree);
5996 if (err)
5997 goto done;
5998 err = delete_ref(branch_ref_name, repo);
5999 if (err)
6000 goto done;
6002 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6003 if (err)
6004 goto done;
6005 err = delete_ref(commit_ref_name, repo);
6006 if (err)
6007 goto done;
6008 done:
6009 free(tmp_branch_name);
6010 free(base_commit_ref_name);
6011 free(branch_ref_name);
6012 free(commit_ref_name);
6013 return err;
6016 const struct got_error *
6017 got_worktree_histedit_abort(struct got_worktree *worktree,
6018 struct got_fileindex *fileindex, struct got_repository *repo,
6019 struct got_reference *branch, struct got_object_id *base_commit_id,
6020 got_worktree_checkout_cb progress_cb, void *progress_arg)
6022 const struct got_error *err, *unlockerr, *sync_err;
6023 struct got_reference *resolved = NULL;
6024 char *fileindex_path = NULL;
6025 struct got_object_id *tree_id = NULL;
6026 struct revert_file_args rfa;
6028 err = lock_worktree(worktree, LOCK_EX);
6029 if (err)
6030 return err;
6032 err = got_ref_open(&resolved, repo,
6033 got_ref_get_symref_target(branch), 0);
6034 if (err)
6035 goto done;
6037 err = got_worktree_set_head_ref(worktree, resolved);
6038 if (err)
6039 goto done;
6041 err = got_worktree_set_base_commit_id(worktree, repo, base_commit_id);
6042 if (err)
6043 goto done;
6045 err = got_object_id_by_path(&tree_id, repo, base_commit_id,
6046 worktree->path_prefix);
6047 if (err)
6048 goto done;
6050 err = delete_histedit_refs(worktree, repo);
6051 if (err)
6052 goto done;
6054 err = get_fileindex_path(&fileindex_path, worktree);
6055 if (err)
6056 goto done;
6058 rfa.worktree = worktree;
6059 rfa.fileindex = fileindex;
6060 rfa.progress_cb = progress_cb;
6061 rfa.progress_arg = progress_arg;
6062 rfa.patch_cb = NULL;
6063 rfa.patch_arg = NULL;
6064 rfa.repo = repo;
6065 err = worktree_status(worktree, "", fileindex, repo,
6066 revert_file, &rfa, NULL, NULL, 0, 0);
6067 if (err)
6068 goto sync;
6070 err = checkout_files(worktree, fileindex, "", tree_id, NULL,
6071 repo, progress_cb, progress_arg, NULL, NULL);
6072 sync:
6073 sync_err = sync_fileindex(fileindex, fileindex_path);
6074 if (sync_err && err == NULL)
6075 err = sync_err;
6076 done:
6077 got_ref_close(resolved);
6078 free(tree_id);
6079 free(fileindex_path);
6081 unlockerr = lock_worktree(worktree, LOCK_SH);
6082 if (unlockerr && err == NULL)
6083 err = unlockerr;
6084 return err;
6087 const struct got_error *
6088 got_worktree_histedit_complete(struct got_worktree *worktree,
6089 struct got_fileindex *fileindex, struct got_reference *tmp_branch,
6090 struct got_reference *edited_branch, struct got_repository *repo)
6092 const struct got_error *err, *unlockerr;
6093 struct got_object_id *new_head_commit_id = NULL;
6094 struct got_reference *resolved = NULL;
6096 err = got_ref_resolve(&new_head_commit_id, repo, tmp_branch);
6097 if (err)
6098 return err;
6100 err = got_ref_open(&resolved, repo,
6101 got_ref_get_symref_target(edited_branch), 0);
6102 if (err)
6103 goto done;
6105 err = got_ref_change_ref(resolved, new_head_commit_id);
6106 if (err)
6107 goto done;
6109 err = got_ref_write(resolved, repo);
6110 if (err)
6111 goto done;
6113 err = got_worktree_set_head_ref(worktree, resolved);
6114 if (err)
6115 goto done;
6117 err = delete_histedit_refs(worktree, repo);
6118 done:
6119 if (fileindex)
6120 got_fileindex_free(fileindex);
6121 free(new_head_commit_id);
6122 unlockerr = lock_worktree(worktree, LOCK_SH);
6123 if (unlockerr && err == NULL)
6124 err = unlockerr;
6125 return err;
6128 const struct got_error *
6129 got_worktree_histedit_skip_commit(struct got_worktree *worktree,
6130 struct got_object_id *commit_id, struct got_repository *repo)
6132 const struct got_error *err;
6133 char *commit_ref_name;
6135 err = get_histedit_commit_ref_name(&commit_ref_name, worktree);
6136 if (err)
6137 return err;
6139 err = store_commit_id(commit_ref_name, commit_id, 0, repo);
6140 if (err)
6141 goto done;
6143 err = delete_ref(commit_ref_name, repo);
6144 done:
6145 free(commit_ref_name);
6146 return err;
6149 const struct got_error *
6150 got_worktree_integrate_prepare(struct got_fileindex **fileindex,
6151 struct got_reference **branch_ref, struct got_reference **base_branch_ref,
6152 struct got_worktree *worktree, const char *refname,
6153 struct got_repository *repo)
6155 const struct got_error *err = NULL;
6156 char *fileindex_path = NULL;
6157 struct check_rebase_ok_arg ok_arg;
6159 *fileindex = NULL;
6160 *branch_ref = NULL;
6161 *base_branch_ref = NULL;
6163 err = lock_worktree(worktree, LOCK_EX);
6164 if (err)
6165 return err;
6167 if (strcmp(refname, got_worktree_get_head_ref_name(worktree)) == 0) {
6168 err = got_error_msg(GOT_ERR_SAME_BRANCH,
6169 "cannot integrate a branch into itself; "
6170 "update -b or different branch name required");
6171 goto done;
6174 err = open_fileindex(fileindex, &fileindex_path, worktree);
6175 if (err)
6176 goto done;
6178 /* Preconditions are the same as for rebase. */
6179 ok_arg.worktree = worktree;
6180 ok_arg.repo = repo;
6181 err = got_fileindex_for_each_entry_safe(*fileindex, check_rebase_ok,
6182 &ok_arg);
6183 if (err)
6184 goto done;
6186 err = got_ref_open(branch_ref, repo, refname, 1);
6187 if (err)
6188 goto done;
6190 err = got_ref_open(base_branch_ref, repo,
6191 got_worktree_get_head_ref_name(worktree), 1);
6192 done:
6193 if (err) {
6194 if (*branch_ref) {
6195 got_ref_close(*branch_ref);
6196 *branch_ref = NULL;
6198 if (*base_branch_ref) {
6199 got_ref_close(*base_branch_ref);
6200 *base_branch_ref = NULL;
6202 if (*fileindex) {
6203 got_fileindex_free(*fileindex);
6204 *fileindex = NULL;
6206 lock_worktree(worktree, LOCK_SH);
6208 return err;
6211 const struct got_error *
6212 got_worktree_integrate_continue(struct got_worktree *worktree,
6213 struct got_fileindex *fileindex, struct got_repository *repo,
6214 struct got_reference *branch_ref, struct got_reference *base_branch_ref,
6215 got_worktree_checkout_cb progress_cb, void *progress_arg,
6216 got_cancel_cb cancel_cb, void *cancel_arg)
6218 const struct got_error *err = NULL, *sync_err, *unlockerr;
6219 char *fileindex_path = NULL;
6220 struct got_object_id *tree_id = NULL, *commit_id = NULL;
6222 err = get_fileindex_path(&fileindex_path, worktree);
6223 if (err)
6224 goto done;
6226 err = got_ref_resolve(&commit_id, repo, branch_ref);
6227 if (err)
6228 goto done;
6230 err = got_object_id_by_path(&tree_id, repo, commit_id,
6231 worktree->path_prefix);
6232 if (err)
6233 goto done;
6235 err = got_worktree_set_base_commit_id(worktree, repo, commit_id);
6236 if (err)
6237 goto done;
6239 err = checkout_files(worktree, fileindex, "", tree_id, NULL, repo,
6240 progress_cb, progress_arg, cancel_cb, cancel_arg);
6241 if (err)
6242 goto sync;
6244 err = got_ref_change_ref(base_branch_ref, commit_id);
6245 if (err)
6246 goto sync;
6248 err = got_ref_write(base_branch_ref, repo);
6249 sync:
6250 sync_err = sync_fileindex(fileindex, fileindex_path);
6251 if (sync_err && err == NULL)
6252 err = sync_err;
6254 done:
6255 unlockerr = got_ref_unlock(branch_ref);
6256 if (unlockerr && err == NULL)
6257 err = unlockerr;
6258 got_ref_close(branch_ref);
6260 unlockerr = got_ref_unlock(base_branch_ref);
6261 if (unlockerr && err == NULL)
6262 err = unlockerr;
6263 got_ref_close(base_branch_ref);
6265 got_fileindex_free(fileindex);
6266 free(fileindex_path);
6267 free(tree_id);
6269 unlockerr = lock_worktree(worktree, LOCK_SH);
6270 if (unlockerr && err == NULL)
6271 err = unlockerr;
6272 return err;
6275 const struct got_error *
6276 got_worktree_integrate_abort(struct got_worktree *worktree,
6277 struct got_fileindex *fileindex, struct got_repository *repo,
6278 struct got_reference *branch_ref, struct got_reference *base_branch_ref)
6280 const struct got_error *err = NULL, *unlockerr = NULL;
6282 got_fileindex_free(fileindex);
6284 err = lock_worktree(worktree, LOCK_SH);
6286 unlockerr = got_ref_unlock(branch_ref);
6287 if (unlockerr && err == NULL)
6288 err = unlockerr;
6289 got_ref_close(branch_ref);
6291 unlockerr = got_ref_unlock(base_branch_ref);
6292 if (unlockerr && err == NULL)
6293 err = unlockerr;
6294 got_ref_close(base_branch_ref);
6296 return err;
6299 struct check_stage_ok_arg {
6300 struct got_object_id *head_commit_id;
6301 struct got_worktree *worktree;
6302 struct got_fileindex *fileindex;
6303 struct got_repository *repo;
6304 int have_changes;
6307 const struct got_error *
6308 check_stage_ok(void *arg, unsigned char status,
6309 unsigned char staged_status, const char *relpath,
6310 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
6311 struct got_object_id *commit_id, int dirfd, const char *de_name)
6313 struct check_stage_ok_arg *a = arg;
6314 const struct got_error *err = NULL;
6315 struct got_fileindex_entry *ie;
6316 struct got_object_id base_commit_id;
6317 struct got_object_id *base_commit_idp = NULL;
6318 char *in_repo_path = NULL, *p;
6320 if (status == GOT_STATUS_UNVERSIONED ||
6321 status == GOT_STATUS_NO_CHANGE)
6322 return NULL;
6323 if (status == GOT_STATUS_NONEXISTENT)
6324 return got_error_set_errno(ENOENT, relpath);
6326 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
6327 if (ie == NULL)
6328 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
6330 if (asprintf(&in_repo_path, "%s%s%s", a->worktree->path_prefix,
6331 got_path_is_root_dir(a->worktree->path_prefix) ? "" : "/",
6332 relpath) == -1)
6333 return got_error_from_errno("asprintf");
6335 if (got_fileindex_entry_has_commit(ie)) {
6336 memcpy(base_commit_id.sha1, ie->commit_sha1,
6337 SHA1_DIGEST_LENGTH);
6338 base_commit_idp = &base_commit_id;
6341 if (status == GOT_STATUS_CONFLICT) {
6342 err = got_error_path(ie->path, GOT_ERR_STAGE_CONFLICT);
6343 goto done;
6344 } else if (status != GOT_STATUS_ADD &&
6345 status != GOT_STATUS_MODIFY &&
6346 status != GOT_STATUS_DELETE) {
6347 err = got_error_path(ie->path, GOT_ERR_FILE_STATUS);
6348 goto done;
6351 a->have_changes = 1;
6353 p = in_repo_path;
6354 while (p[0] == '/')
6355 p++;
6356 err = check_out_of_date(p, status, staged_status,
6357 blob_id, base_commit_idp, a->head_commit_id, a->repo,
6358 GOT_ERR_STAGE_OUT_OF_DATE);
6359 done:
6360 free(in_repo_path);
6361 return err;
6364 struct stage_path_arg {
6365 struct got_worktree *worktree;
6366 struct got_fileindex *fileindex;
6367 struct got_repository *repo;
6368 got_worktree_status_cb status_cb;
6369 void *status_arg;
6370 got_worktree_patch_cb patch_cb;
6371 void *patch_arg;
6372 int staged_something;
6375 static const struct got_error *
6376 stage_path(void *arg, unsigned char status,
6377 unsigned char staged_status, const char *relpath,
6378 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
6379 struct got_object_id *commit_id, int dirfd, const char *de_name)
6381 struct stage_path_arg *a = arg;
6382 const struct got_error *err = NULL;
6383 struct got_fileindex_entry *ie;
6384 char *ondisk_path = NULL, *path_content = NULL;
6385 uint32_t stage;
6386 struct got_object_id *new_staged_blob_id = NULL;
6388 if (status == GOT_STATUS_UNVERSIONED)
6389 return NULL;
6391 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
6392 if (ie == NULL)
6393 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
6395 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path,
6396 relpath)== -1)
6397 return got_error_from_errno("asprintf");
6399 switch (status) {
6400 case GOT_STATUS_ADD:
6401 case GOT_STATUS_MODIFY:
6402 if (a->patch_cb) {
6403 if (status == GOT_STATUS_ADD) {
6404 int choice = GOT_PATCH_CHOICE_NONE;
6405 err = (*a->patch_cb)(&choice, a->patch_arg,
6406 status, ie->path, NULL, 1, 1);
6407 if (err)
6408 break;
6409 if (choice != GOT_PATCH_CHOICE_YES)
6410 break;
6411 } else {
6412 err = create_patched_content(&path_content, 0,
6413 staged_blob_id ? staged_blob_id : blob_id,
6414 ondisk_path, dirfd, de_name, ie->path,
6415 a->repo, a->patch_cb, a->patch_arg);
6416 if (err || path_content == NULL)
6417 break;
6420 err = got_object_blob_create(&new_staged_blob_id,
6421 path_content ? path_content : ondisk_path, a->repo);
6422 if (err)
6423 break;
6424 memcpy(ie->staged_blob_sha1, new_staged_blob_id->sha1,
6425 SHA1_DIGEST_LENGTH);
6426 if (status == GOT_STATUS_ADD || staged_status == GOT_STATUS_ADD)
6427 stage = GOT_FILEIDX_STAGE_ADD;
6428 else
6429 stage = GOT_FILEIDX_STAGE_MODIFY;
6430 got_fileindex_entry_stage_set(ie, stage);
6431 a->staged_something = 1;
6432 if (a->status_cb == NULL)
6433 break;
6434 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
6435 get_staged_status(ie), relpath, blob_id,
6436 new_staged_blob_id, NULL, dirfd, de_name);
6437 break;
6438 case GOT_STATUS_DELETE:
6439 if (staged_status == GOT_STATUS_DELETE)
6440 break;
6441 if (a->patch_cb) {
6442 int choice = GOT_PATCH_CHOICE_NONE;
6443 err = (*a->patch_cb)(&choice, a->patch_arg, status,
6444 ie->path, NULL, 1, 1);
6445 if (err)
6446 break;
6447 if (choice == GOT_PATCH_CHOICE_NO)
6448 break;
6449 if (choice != GOT_PATCH_CHOICE_YES) {
6450 err = got_error(GOT_ERR_PATCH_CHOICE);
6451 break;
6454 stage = GOT_FILEIDX_STAGE_DELETE;
6455 got_fileindex_entry_stage_set(ie, stage);
6456 a->staged_something = 1;
6457 if (a->status_cb == NULL)
6458 break;
6459 err = (*a->status_cb)(a->status_arg, GOT_STATUS_NO_CHANGE,
6460 get_staged_status(ie), relpath, NULL, NULL, NULL, dirfd,
6461 de_name);
6462 break;
6463 case GOT_STATUS_NO_CHANGE:
6464 break;
6465 case GOT_STATUS_CONFLICT:
6466 err = got_error_path(relpath, GOT_ERR_STAGE_CONFLICT);
6467 break;
6468 case GOT_STATUS_NONEXISTENT:
6469 err = got_error_set_errno(ENOENT, relpath);
6470 break;
6471 default:
6472 err = got_error_path(relpath, GOT_ERR_FILE_STATUS);
6473 break;
6476 if (path_content && unlink(path_content) == -1 && err == NULL)
6477 err = got_error_from_errno2("unlink", path_content);
6478 free(path_content);
6479 free(ondisk_path);
6480 free(new_staged_blob_id);
6481 return err;
6484 const struct got_error *
6485 got_worktree_stage(struct got_worktree *worktree,
6486 struct got_pathlist_head *paths,
6487 got_worktree_status_cb status_cb, void *status_arg,
6488 got_worktree_patch_cb patch_cb, void *patch_arg,
6489 struct got_repository *repo)
6491 const struct got_error *err = NULL, *sync_err, *unlockerr;
6492 struct got_pathlist_entry *pe;
6493 struct got_fileindex *fileindex = NULL;
6494 char *fileindex_path = NULL;
6495 struct got_reference *head_ref = NULL;
6496 struct got_object_id *head_commit_id = NULL;
6497 struct check_stage_ok_arg oka;
6498 struct stage_path_arg spa;
6500 err = lock_worktree(worktree, LOCK_EX);
6501 if (err)
6502 return err;
6504 err = got_ref_open(&head_ref, repo,
6505 got_worktree_get_head_ref_name(worktree), 0);
6506 if (err)
6507 goto done;
6508 err = got_ref_resolve(&head_commit_id, repo, head_ref);
6509 if (err)
6510 goto done;
6511 err = open_fileindex(&fileindex, &fileindex_path, worktree);
6512 if (err)
6513 goto done;
6515 /* Check pre-conditions before staging anything. */
6516 oka.head_commit_id = head_commit_id;
6517 oka.worktree = worktree;
6518 oka.fileindex = fileindex;
6519 oka.repo = repo;
6520 oka.have_changes = 0;
6521 TAILQ_FOREACH(pe, paths, entry) {
6522 err = worktree_status(worktree, pe->path, fileindex, repo,
6523 check_stage_ok, &oka, NULL, NULL, 0, 0);
6524 if (err)
6525 goto done;
6527 if (!oka.have_changes) {
6528 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
6529 goto done;
6532 spa.worktree = worktree;
6533 spa.fileindex = fileindex;
6534 spa.repo = repo;
6535 spa.patch_cb = patch_cb;
6536 spa.patch_arg = patch_arg;
6537 spa.status_cb = status_cb;
6538 spa.status_arg = status_arg;
6539 spa.staged_something = 0;
6540 TAILQ_FOREACH(pe, paths, entry) {
6541 err = worktree_status(worktree, pe->path, fileindex, repo,
6542 stage_path, &spa, NULL, NULL, 0, 0);
6543 if (err)
6544 goto done;
6546 if (!spa.staged_something) {
6547 err = got_error(GOT_ERR_STAGE_NO_CHANGE);
6548 goto done;
6551 sync_err = sync_fileindex(fileindex, fileindex_path);
6552 if (sync_err && err == NULL)
6553 err = sync_err;
6554 done:
6555 if (head_ref)
6556 got_ref_close(head_ref);
6557 free(head_commit_id);
6558 free(fileindex_path);
6559 if (fileindex)
6560 got_fileindex_free(fileindex);
6561 unlockerr = lock_worktree(worktree, LOCK_SH);
6562 if (unlockerr && err == NULL)
6563 err = unlockerr;
6564 return err;
6567 struct unstage_path_arg {
6568 struct got_worktree *worktree;
6569 struct got_fileindex *fileindex;
6570 struct got_repository *repo;
6571 got_worktree_checkout_cb progress_cb;
6572 void *progress_arg;
6573 got_worktree_patch_cb patch_cb;
6574 void *patch_arg;
6577 static const struct got_error *
6578 create_unstaged_content(char **path_unstaged_content,
6579 char **path_new_staged_content, struct got_object_id *blob_id,
6580 struct got_object_id *staged_blob_id, const char *relpath,
6581 struct got_repository *repo,
6582 got_worktree_patch_cb patch_cb, void *patch_arg)
6584 const struct got_error *err;
6585 struct got_blob_object *blob = NULL, *staged_blob = NULL;
6586 FILE *f1 = NULL, *f2 = NULL, *outfile = NULL, *rejectfile = NULL;
6587 char *path1 = NULL, *path2 = NULL, *label1 = NULL;
6588 struct stat sb1, sb2;
6589 struct got_diff_changes *changes = NULL;
6590 struct got_diff_state *ds = NULL;
6591 struct got_diff_args *args = NULL;
6592 struct got_diff_change *change;
6593 int diff_flags = 0, line_cur1 = 1, line_cur2 = 1, n = 0;
6594 int have_content = 0, have_rejected_content = 0;
6596 *path_unstaged_content = NULL;
6597 *path_new_staged_content = NULL;
6599 err = got_object_id_str(&label1, blob_id);
6600 if (err)
6601 return err;
6602 err = got_object_open_as_blob(&blob, repo, blob_id, 8192);
6603 if (err)
6604 goto done;
6606 err = got_opentemp_named(&path1, &f1, "got-unstage-blob-base");
6607 if (err)
6608 goto done;
6610 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f1, blob);
6611 if (err)
6612 goto done;
6614 err = got_object_open_as_blob(&staged_blob, repo, staged_blob_id, 8192);
6615 if (err)
6616 goto done;
6618 err = got_opentemp_named(&path2, &f2, "got-unstage-blob-staged");
6619 if (err)
6620 goto done;
6622 err = got_object_blob_dump_to_file(NULL, NULL, NULL, f2, staged_blob);
6623 if (err)
6624 goto done;
6626 if (stat(path1, &sb1) == -1) {
6627 err = got_error_from_errno2("stat", path1);
6628 goto done;
6631 if (stat(path2, &sb2) == -1) {
6632 err = got_error_from_errno2("stat", path2);
6633 goto done;
6636 err = got_diff_files(&changes, &ds, &args, &diff_flags,
6637 f1, sb1.st_size, label1, f2, sb2.st_size, path2, 3, NULL);
6638 if (err)
6639 goto done;
6641 err = got_opentemp_named(path_unstaged_content, &outfile,
6642 "got-unstaged-content");
6643 if (err)
6644 goto done;
6645 err = got_opentemp_named(path_new_staged_content, &rejectfile,
6646 "got-new-staged-content");
6647 if (err)
6648 goto done;
6650 if (fseek(f1, 0L, SEEK_SET) == -1) {
6651 err = got_ferror(f1, GOT_ERR_IO);
6652 goto done;
6654 if (fseek(f2, 0L, SEEK_SET) == -1) {
6655 err = got_ferror(f2, GOT_ERR_IO);
6656 goto done;
6658 SIMPLEQ_FOREACH(change, &changes->entries, entry) {
6659 int choice;
6660 err = apply_or_reject_change(&choice, change, ++n,
6661 changes->nchanges, ds, args, diff_flags, relpath,
6662 f1, f2, &line_cur1, &line_cur2,
6663 outfile, rejectfile, patch_cb, patch_arg);
6664 if (err)
6665 goto done;
6666 if (choice == GOT_PATCH_CHOICE_YES)
6667 have_content = 1;
6668 else
6669 have_rejected_content = 1;
6670 if (choice == GOT_PATCH_CHOICE_QUIT)
6671 break;
6673 if (have_content || have_rejected_content)
6674 err = copy_remaining_content(f1, f2, &line_cur1, &line_cur2,
6675 outfile, rejectfile);
6676 done:
6677 free(label1);
6678 if (blob)
6679 got_object_blob_close(blob);
6680 if (staged_blob)
6681 got_object_blob_close(staged_blob);
6682 if (f1 && fclose(f1) == EOF && err == NULL)
6683 err = got_error_from_errno2("fclose", path1);
6684 if (f2 && fclose(f2) == EOF && err == NULL)
6685 err = got_error_from_errno2("fclose", path2);
6686 if (outfile && fclose(outfile) == EOF && err == NULL)
6687 err = got_error_from_errno2("fclose", *path_unstaged_content);
6688 if (rejectfile && fclose(rejectfile) == EOF && err == NULL)
6689 err = got_error_from_errno2("fclose", *path_new_staged_content);
6690 if (path1 && unlink(path1) == -1 && err == NULL)
6691 err = got_error_from_errno2("unlink", path1);
6692 if (path2 && unlink(path2) == -1 && err == NULL)
6693 err = got_error_from_errno2("unlink", path2);
6694 if (err || !have_content) {
6695 if (*path_unstaged_content &&
6696 unlink(*path_unstaged_content) == -1 && err == NULL)
6697 err = got_error_from_errno2("unlink",
6698 *path_unstaged_content);
6699 free(*path_unstaged_content);
6700 *path_unstaged_content = NULL;
6702 if (err || !have_rejected_content) {
6703 if (*path_new_staged_content &&
6704 unlink(*path_new_staged_content) == -1 && err == NULL)
6705 err = got_error_from_errno2("unlink",
6706 *path_new_staged_content);
6707 free(*path_new_staged_content);
6708 *path_new_staged_content = NULL;
6710 free(args);
6711 if (ds) {
6712 got_diff_state_free(ds);
6713 free(ds);
6715 if (changes)
6716 got_diff_free_changes(changes);
6717 free(path1);
6718 free(path2);
6719 return err;
6722 static const struct got_error *
6723 unstage_path(void *arg, unsigned char status,
6724 unsigned char staged_status, const char *relpath,
6725 struct got_object_id *blob_id, struct got_object_id *staged_blob_id,
6726 struct got_object_id *commit_id, int dirfd, const char *de_name)
6728 const struct got_error *err = NULL;
6729 struct unstage_path_arg *a = arg;
6730 struct got_fileindex_entry *ie;
6731 struct got_blob_object *blob_base = NULL, *blob_staged = NULL;
6732 char *ondisk_path = NULL, *path_unstaged_content = NULL;
6733 char *path_new_staged_content = NULL;
6734 char *id_str = NULL, *label_orig = NULL;
6735 int local_changes_subsumed;
6736 struct stat sb;
6738 if (staged_status != GOT_STATUS_ADD &&
6739 staged_status != GOT_STATUS_MODIFY &&
6740 staged_status != GOT_STATUS_DELETE)
6741 return NULL;
6743 ie = got_fileindex_entry_get(a->fileindex, relpath, strlen(relpath));
6744 if (ie == NULL)
6745 return got_error_path(relpath, GOT_ERR_FILE_STATUS);
6747 if (asprintf(&ondisk_path, "%s/%s", a->worktree->root_path, relpath)
6748 == -1)
6749 return got_error_from_errno("asprintf");
6751 err = got_object_id_str(&id_str,
6752 commit_id ? commit_id : a->worktree->base_commit_id);
6753 if (err)
6754 goto done;
6755 if (asprintf(&label_orig, "%s: commit %s", GOT_MERGE_LABEL_BASE,
6756 id_str) == -1) {
6757 err = got_error_from_errno("asprintf");
6758 goto done;
6761 switch (staged_status) {
6762 case GOT_STATUS_MODIFY:
6763 err = got_object_open_as_blob(&blob_base, a->repo,
6764 blob_id, 8192);
6765 if (err)
6766 break;
6767 /* fall through */
6768 case GOT_STATUS_ADD:
6769 if (a->patch_cb) {
6770 if (staged_status == GOT_STATUS_ADD) {
6771 int choice = GOT_PATCH_CHOICE_NONE;
6772 err = (*a->patch_cb)(&choice, a->patch_arg,
6773 staged_status, ie->path, NULL, 1, 1);
6774 if (err)
6775 break;
6776 if (choice != GOT_PATCH_CHOICE_YES)
6777 break;
6778 } else {
6779 err = create_unstaged_content(
6780 &path_unstaged_content,
6781 &path_new_staged_content, blob_id,
6782 staged_blob_id, ie->path, a->repo,
6783 a->patch_cb, a->patch_arg);
6784 if (err || path_unstaged_content == NULL)
6785 break;
6786 if (path_new_staged_content) {
6787 err = got_object_blob_create(
6788 &staged_blob_id,
6789 path_new_staged_content,
6790 a->repo);
6791 if (err)
6792 break;
6793 memcpy(ie->staged_blob_sha1,
6794 staged_blob_id->sha1,
6795 SHA1_DIGEST_LENGTH);
6797 err = merge_file(&local_changes_subsumed,
6798 a->worktree, blob_base, ondisk_path,
6799 relpath, got_fileindex_perms_to_st(ie),
6800 path_unstaged_content, label_orig,
6801 "unstaged", a->repo, a->progress_cb,
6802 a->progress_arg);
6803 if (err == NULL &&
6804 path_new_staged_content == NULL)
6805 got_fileindex_entry_stage_set(ie,
6806 GOT_FILEIDX_STAGE_NONE);
6807 break; /* Done with this file. */
6810 err = got_object_open_as_blob(&blob_staged, a->repo,
6811 staged_blob_id, 8192);
6812 if (err)
6813 break;
6814 err = merge_blob(&local_changes_subsumed, a->worktree,
6815 blob_base, ondisk_path, relpath,
6816 got_fileindex_perms_to_st(ie), label_orig, blob_staged,
6817 commit_id ? commit_id : a->worktree->base_commit_id,
6818 a->repo, a->progress_cb, a->progress_arg);
6819 if (err == NULL)
6820 got_fileindex_entry_stage_set(ie,
6821 GOT_FILEIDX_STAGE_NONE);
6822 break;
6823 case GOT_STATUS_DELETE:
6824 if (a->patch_cb) {
6825 int choice = GOT_PATCH_CHOICE_NONE;
6826 err = (*a->patch_cb)(&choice, a->patch_arg,
6827 staged_status, ie->path, NULL, 1, 1);
6828 if (err)
6829 break;
6830 if (choice == GOT_PATCH_CHOICE_NO)
6831 break;
6832 if (choice != GOT_PATCH_CHOICE_YES) {
6833 err = got_error(GOT_ERR_PATCH_CHOICE);
6834 break;
6837 got_fileindex_entry_stage_set(ie, GOT_FILEIDX_STAGE_NONE);
6838 err = get_file_status(&status, &sb, ie, ondisk_path,
6839 dirfd, de_name, a->repo);
6840 if (err)
6841 break;
6842 err = (*a->progress_cb)(a->progress_arg, status, relpath);
6843 break;
6845 done:
6846 free(ondisk_path);
6847 if (path_unstaged_content &&
6848 unlink(path_unstaged_content) == -1 && err == NULL)
6849 err = got_error_from_errno2("unlink", path_unstaged_content);
6850 if (path_new_staged_content &&
6851 unlink(path_new_staged_content) == -1 && err == NULL)
6852 err = got_error_from_errno2("unlink", path_new_staged_content);
6853 free(path_unstaged_content);
6854 free(path_new_staged_content);
6855 if (blob_base)
6856 got_object_blob_close(blob_base);
6857 if (blob_staged)
6858 got_object_blob_close(blob_staged);
6859 free(id_str);
6860 free(label_orig);
6861 return err;
6864 const struct got_error *
6865 got_worktree_unstage(struct got_worktree *worktree,
6866 struct got_pathlist_head *paths,
6867 got_worktree_checkout_cb progress_cb, void *progress_arg,
6868 got_worktree_patch_cb patch_cb, void *patch_arg,
6869 struct got_repository *repo)
6871 const struct got_error *err = NULL, *sync_err, *unlockerr;
6872 struct got_pathlist_entry *pe;
6873 struct got_fileindex *fileindex = NULL;
6874 char *fileindex_path = NULL;
6875 struct unstage_path_arg upa;
6877 err = lock_worktree(worktree, LOCK_EX);
6878 if (err)
6879 return err;
6881 err = open_fileindex(&fileindex, &fileindex_path, worktree);
6882 if (err)
6883 goto done;
6885 upa.worktree = worktree;
6886 upa.fileindex = fileindex;
6887 upa.repo = repo;
6888 upa.progress_cb = progress_cb;
6889 upa.progress_arg = progress_arg;
6890 upa.patch_cb = patch_cb;
6891 upa.patch_arg = patch_arg;
6892 TAILQ_FOREACH(pe, paths, entry) {
6893 err = worktree_status(worktree, pe->path, fileindex, repo,
6894 unstage_path, &upa, NULL, NULL, 0, 0);
6895 if (err)
6896 goto done;
6899 sync_err = sync_fileindex(fileindex, fileindex_path);
6900 if (sync_err && err == NULL)
6901 err = sync_err;
6902 done:
6903 free(fileindex_path);
6904 if (fileindex)
6905 got_fileindex_free(fileindex);
6906 unlockerr = lock_worktree(worktree, LOCK_SH);
6907 if (unlockerr && err == NULL)
6908 err = unlockerr;
6909 return err;