2 * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include "got_compat.h"
20 #include <sys/queue.h>
36 #include "got_error.h"
37 #include "got_repository.h"
38 #include "got_reference.h"
39 #include "got_object.h"
41 #include "got_cancel.h"
42 #include "got_worktree.h"
43 #include "got_opentemp.h"
46 #include "got_lib_worktree.h"
47 #include "got_lib_hash.h"
48 #include "got_lib_fileindex.h"
49 #include "got_lib_inflate.h"
50 #include "got_lib_delta.h"
51 #include "got_lib_object.h"
52 #include "got_lib_object_parse.h"
53 #include "got_lib_object_create.h"
54 #include "got_lib_object_idset.h"
55 #include "got_lib_diff.h"
56 #include "got_lib_gotconfig.h"
59 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
62 #define GOT_MERGE_LABEL_MERGED "merged change"
63 #define GOT_MERGE_LABEL_BASE "3-way merge base"
66 apply_umask(mode_t mode
)
75 static const struct got_error
*
76 create_meta_file(const char *path_got
, const char *name
, const char *content
)
78 const struct got_error
*err
= NULL
;
81 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1)
82 return got_error_from_errno("asprintf");
84 err
= got_path_create_file(path
, content
);
89 static const struct got_error
*
90 update_meta_file(const char *path_got
, const char *name
, const char *content
)
92 const struct got_error
*err
= NULL
;
97 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1) {
98 err
= got_error_from_errno("asprintf");
103 err
= got_opentemp_named(&tmppath
, &tmpfile
, path
, "");
108 int len
= fprintf(tmpfile
, "%s\n", content
);
109 if (len
!= strlen(content
) + 1) {
110 err
= got_error_from_errno2("fprintf", tmppath
);
115 if (rename(tmppath
, path
) != 0) {
116 err
= got_error_from_errno3("rename", tmppath
, path
);
122 if (fclose(tmpfile
) == EOF
&& err
== NULL
)
123 err
= got_error_from_errno2("fclose", tmppath
);
128 static const struct got_error
*
129 write_head_ref(const char *path_got
, struct got_reference
*head_ref
)
131 const struct got_error
*err
= NULL
;
134 if (got_ref_is_symbolic(head_ref
)) {
135 refstr
= got_ref_to_str(head_ref
);
137 return got_error_from_errno("got_ref_to_str");
139 refstr
= strdup(got_ref_get_name(head_ref
));
141 return got_error_from_errno("strdup");
143 err
= update_meta_file(path_got
, GOT_WORKTREE_HEAD_REF
, refstr
);
148 const struct got_error
*
149 got_worktree_init(const char *path
, struct got_reference
*head_ref
,
150 const char *prefix
, const char *meta_dir
, struct got_repository
*repo
)
152 const struct got_error
*err
= NULL
;
153 struct got_object_id
*commit_id
= NULL
;
155 uint32_t uuid_status
;
157 char *path_got
= NULL
;
158 char *formatstr
= NULL
;
159 char *absprefix
= NULL
;
160 char *basestr
= NULL
;
161 char *uuidstr
= NULL
;
163 if (strcmp(path
, got_repo_get_path(repo
)) == 0) {
164 err
= got_error(GOT_ERR_WORKTREE_REPO
);
168 err
= got_ref_resolve(&commit_id
, repo
, head_ref
);
171 err
= got_object_get_type(&obj_type
, repo
, commit_id
);
174 if (obj_type
!= GOT_OBJ_TYPE_COMMIT
)
175 return got_error(GOT_ERR_OBJ_TYPE
);
177 if (!got_path_is_absolute(prefix
)) {
178 if (asprintf(&absprefix
, "/%s", prefix
) == -1)
179 return got_error_from_errno("asprintf");
182 /* Create top-level directory (may already exist). */
183 if (mkdir(path
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
184 err
= got_error_from_errno2("mkdir", path
);
188 /* Create .got/.cvg directory (may already exist). */
189 if (asprintf(&path_got
, "%s/%s", path
, meta_dir
) == -1) {
190 err
= got_error_from_errno("asprintf");
193 if (mkdir(path_got
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
194 err
= got_error_from_errno2("mkdir", path_got
);
198 /* Create an empty lock file. */
199 err
= create_meta_file(path_got
, GOT_WORKTREE_LOCK
, NULL
);
203 /* Create an empty file index. */
204 err
= create_meta_file(path_got
, GOT_WORKTREE_FILE_INDEX
, NULL
);
208 /* Write the HEAD reference. */
209 err
= write_head_ref(path_got
, head_ref
);
213 /* Record our base commit. */
214 err
= got_object_id_str(&basestr
, commit_id
);
217 err
= create_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, basestr
);
221 /* Store path to repository. */
222 err
= create_meta_file(path_got
, GOT_WORKTREE_REPOSITORY
,
223 got_repo_get_path(repo
));
227 /* Store in-repository path prefix. */
228 err
= create_meta_file(path_got
, GOT_WORKTREE_PATH_PREFIX
,
229 absprefix
? absprefix
: prefix
);
234 uuid_create(&uuid
, &uuid_status
);
235 if (uuid_status
!= uuid_s_ok
) {
236 err
= got_error_uuid(uuid_status
, "uuid_create");
239 uuid_to_string(&uuid
, &uuidstr
, &uuid_status
);
240 if (uuid_status
!= uuid_s_ok
) {
241 err
= got_error_uuid(uuid_status
, "uuid_to_string");
244 err
= create_meta_file(path_got
, GOT_WORKTREE_UUID
, uuidstr
);
248 /* Stamp work tree with format file. */
249 if (asprintf(&formatstr
, "%d", GOT_WORKTREE_FORMAT_VERSION
) == -1) {
250 err
= got_error_from_errno("asprintf");
253 err
= create_meta_file(path_got
, GOT_WORKTREE_FORMAT
, formatstr
);
267 const struct got_error
*
268 got_worktree_match_path_prefix(int *match
, struct got_worktree
*worktree
,
269 const char *path_prefix
)
271 char *absprefix
= NULL
;
273 if (!got_path_is_absolute(path_prefix
)) {
274 if (asprintf(&absprefix
, "/%s", path_prefix
) == -1)
275 return got_error_from_errno("asprintf");
277 *match
= (strcmp(absprefix
? absprefix
: path_prefix
,
278 worktree
->path_prefix
) == 0);
284 got_worktree_get_head_ref_name(struct got_worktree
*worktree
)
286 return worktree
->head_ref_name
;
289 const struct got_error
*
290 got_worktree_set_head_ref(struct got_worktree
*worktree
,
291 struct got_reference
*head_ref
)
293 const struct got_error
*err
= NULL
;
294 char *path_got
= NULL
, *head_ref_name
= NULL
;
296 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
297 worktree
->meta_dir
) == -1) {
298 err
= got_error_from_errno("asprintf");
303 head_ref_name
= strdup(got_ref_get_name(head_ref
));
304 if (head_ref_name
== NULL
) {
305 err
= got_error_from_errno("strdup");
309 err
= write_head_ref(path_got
, head_ref
);
313 free(worktree
->head_ref_name
);
314 worktree
->head_ref_name
= head_ref_name
;
322 struct got_object_id
*
323 got_worktree_get_base_commit_id(struct got_worktree
*worktree
)
325 return worktree
->base_commit_id
;
328 const struct got_error
*
329 got_worktree_set_base_commit_id(struct got_worktree
*worktree
,
330 struct got_repository
*repo
, struct got_object_id
*commit_id
)
332 const struct got_error
*err
;
333 struct got_object
*obj
= NULL
;
335 char *path_got
= NULL
;
337 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
338 worktree
->meta_dir
) == -1) {
339 err
= got_error_from_errno("asprintf");
344 err
= got_object_open(&obj
, repo
, commit_id
);
348 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
349 err
= got_error(GOT_ERR_OBJ_TYPE
);
353 /* Record our base commit. */
354 err
= got_object_id_str(&id_str
, commit_id
);
357 err
= update_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, id_str
);
361 free(worktree
->base_commit_id
);
362 worktree
->base_commit_id
= got_object_id_dup(commit_id
);
363 if (worktree
->base_commit_id
== NULL
) {
364 err
= got_error_from_errno("got_object_id_dup");
369 got_object_close(obj
);
375 const struct got_gotconfig
*
376 got_worktree_get_gotconfig(struct got_worktree
*worktree
)
378 return worktree
->gotconfig
;
381 static const struct got_error
*
382 lock_worktree(struct got_worktree
*worktree
, int operation
)
384 if (flock(worktree
->lockfd
, operation
| LOCK_NB
) == -1)
385 return (errno
== EWOULDBLOCK
? got_error(GOT_ERR_WORKTREE_BUSY
)
386 : got_error_from_errno2("flock",
387 got_worktree_get_root_path(worktree
)));
391 static const struct got_error
*
392 add_dir_on_disk(struct got_worktree
*worktree
, const char *path
)
394 const struct got_error
*err
= NULL
;
397 /* We only accept worktree-relative paths here. */
398 if (got_path_is_absolute(path
)) {
399 return got_error_fmt(GOT_ERR_BAD_PATH
,
400 "%s does not accept absolute paths: %s",
404 if (asprintf(&abspath
, "%s/%s", worktree
->root_path
, path
) == -1)
405 return got_error_from_errno("asprintf");
407 err
= got_path_mkdir(abspath
);
408 if (err
&& err
->code
== GOT_ERR_ERRNO
&& errno
== EEXIST
) {
411 if (lstat(abspath
, &sb
) == -1) {
412 err
= got_error_from_errno2("lstat", abspath
);
413 } else if (!S_ISDIR(sb
.st_mode
)) {
414 /* TODO directory is obstructed; do something */
415 err
= got_error_path(abspath
, GOT_ERR_FILE_OBSTRUCTED
);
422 static const struct got_error
*
423 check_file_contents_equal(int *same
, FILE *f1
, FILE *f2
)
425 const struct got_error
*err
= NULL
;
428 size_t flen1
= 0, flen2
= 0;
433 flen1
= fread(fbuf1
, 1, sizeof(fbuf1
), f1
);
434 if (flen1
== 0 && ferror(f1
)) {
435 err
= got_error_from_errno("fread");
438 flen2
= fread(fbuf2
, 1, sizeof(fbuf2
), f2
);
439 if (flen2
== 0 && ferror(f2
)) {
440 err
= got_error_from_errno("fread");
447 } else if (flen2
== 0) {
451 } else if (flen1
== flen2
) {
452 if (memcmp(fbuf1
, fbuf2
, flen2
) != 0) {
465 static const struct got_error
*
466 check_files_equal(int *same
, FILE *f1
, FILE *f2
)
473 if (fstat(fileno(f1
), &sb
) != 0)
474 return got_error_from_errno("fstat");
477 if (fstat(fileno(f2
), &sb
) != 0)
478 return got_error_from_errno("fstat");
481 if (size1
!= size2
) {
486 if (fseek(f1
, 0L, SEEK_SET
) == -1)
487 return got_ferror(f1
, GOT_ERR_IO
);
488 if (fseek(f2
, 0L, SEEK_SET
) == -1)
489 return got_ferror(f2
, GOT_ERR_IO
);
491 return check_file_contents_equal(same
, f1
, f2
);
494 static const struct got_error
*
495 copy_file_to_fd(off_t
*outsize
, FILE *f
, int outfd
)
503 if (fseek(f
, 0L, SEEK_SET
) == -1)
504 return got_ferror(f
, GOT_ERR_IO
);
507 flen
= fread(fbuf
, 1, sizeof(fbuf
), f
);
510 return got_error_from_errno("fread");
514 outlen
= write(outfd
, fbuf
, flen
);
516 return got_error_from_errno("write");
518 return got_error(GOT_ERR_IO
);
525 static const struct got_error
*
526 merge_binary_file(int *overlapcnt
, int merged_fd
,
527 FILE *f_deriv
, FILE *f_orig
, FILE *f_deriv2
,
528 const char *label_deriv
, const char *label_orig
, const char *label_deriv2
,
529 const char *ondisk_path
)
531 const struct got_error
*err
= NULL
;
532 int same_content
, changed_deriv
, changed_deriv2
;
533 int fd_orig
= -1, fd_deriv
= -1, fd_deriv2
= -1;
534 off_t size_orig
= 0, size_deriv
= 0, size_deriv2
= 0;
535 char *path_orig
= NULL
, *path_deriv
= NULL
, *path_deriv2
= NULL
;
536 char *base_path_orig
= NULL
, *base_path_deriv
= NULL
;
537 char *base_path_deriv2
= NULL
;
541 err
= check_files_equal(&same_content
, f_deriv
, f_deriv2
);
546 return copy_file_to_fd(&size_deriv
, f_deriv
, merged_fd
);
548 err
= check_files_equal(&same_content
, f_deriv
, f_orig
);
551 changed_deriv
= !same_content
;
552 err
= check_files_equal(&same_content
, f_deriv2
, f_orig
);
555 changed_deriv2
= !same_content
;
557 if (changed_deriv
&& changed_deriv2
) {
559 if (asprintf(&base_path_orig
, "%s-orig", ondisk_path
) == -1) {
560 err
= got_error_from_errno("asprintf");
563 if (asprintf(&base_path_deriv
, "%s-1", ondisk_path
) == -1) {
564 err
= got_error_from_errno("asprintf");
567 if (asprintf(&base_path_deriv2
, "%s-2", ondisk_path
) == -1) {
568 err
= got_error_from_errno("asprintf");
571 err
= got_opentemp_named_fd(&path_orig
, &fd_orig
,
575 err
= got_opentemp_named_fd(&path_deriv
, &fd_deriv
,
576 base_path_deriv
, "");
579 err
= got_opentemp_named_fd(&path_deriv2
, &fd_deriv2
,
580 base_path_deriv2
, "");
583 err
= copy_file_to_fd(&size_orig
, f_orig
, fd_orig
);
586 err
= copy_file_to_fd(&size_deriv
, f_deriv
, fd_deriv
);
589 err
= copy_file_to_fd(&size_deriv2
, f_deriv2
, fd_deriv2
);
592 if (dprintf(merged_fd
, "Binary files differ and cannot be "
593 "merged automatically:\n") < 0) {
594 err
= got_error_from_errno("dprintf");
597 if (dprintf(merged_fd
, "%s%s%s\nfile %s\n",
598 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
599 label_deriv
? " " : "",
600 label_deriv
? label_deriv
: "",
602 err
= got_error_from_errno("dprintf");
606 if (dprintf(merged_fd
, "%s%s%s\nfile %s\n",
607 GOT_DIFF_CONFLICT_MARKER_ORIG
,
608 label_orig
? " " : "",
609 label_orig
? label_orig
: "",
611 err
= got_error_from_errno("dprintf");
615 if (dprintf(merged_fd
, "%s\nfile %s\n%s%s%s\n",
616 GOT_DIFF_CONFLICT_MARKER_SEP
,
618 GOT_DIFF_CONFLICT_MARKER_END
,
619 label_deriv2
? " " : "",
620 label_deriv2
? label_deriv2
: "") < 0) {
621 err
= got_error_from_errno("dprintf");
624 } else if (changed_deriv
)
625 err
= copy_file_to_fd(&size_deriv
, f_deriv
, merged_fd
);
626 else if (changed_deriv2
)
627 err
= copy_file_to_fd(&size_deriv2
, f_deriv2
, merged_fd
);
629 if (size_orig
== 0 && path_orig
&& unlink(path_orig
) == -1 &&
631 err
= got_error_from_errno2("unlink", path_orig
);
632 if (fd_orig
!= -1 && close(fd_orig
) == -1 && err
== NULL
)
633 err
= got_error_from_errno2("close", path_orig
);
634 if (fd_deriv
!= -1 && close(fd_deriv
) == -1 && err
== NULL
)
635 err
= got_error_from_errno2("close", path_deriv
);
636 if (fd_deriv2
!= -1 && close(fd_deriv2
) == -1 && err
== NULL
)
637 err
= got_error_from_errno2("close", path_deriv2
);
641 free(base_path_orig
);
642 free(base_path_deriv
);
643 free(base_path_deriv2
);
648 * Perform a 3-way merge where the file f_orig acts as the common
649 * ancestor, the file f_deriv acts as the first derived version,
650 * and the file f_deriv2 acts as the second derived version.
651 * The merge result will be written to a new file at ondisk_path; any
652 * existing file at this path will be replaced.
654 static const struct got_error
*
655 merge_file(int *local_changes_subsumed
, struct got_worktree
*worktree
,
656 FILE *f_orig
, FILE *f_deriv
, FILE *f_deriv2
, const char *ondisk_path
,
657 const char *path
, uint16_t st_mode
,
658 const char *label_orig
, const char *label_deriv
, const char *label_deriv2
,
659 enum got_diff_algorithm diff_algo
, struct got_repository
*repo
,
660 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
662 const struct got_error
*err
= NULL
;
664 FILE *f_merged
= NULL
;
665 char *merged_path
= NULL
, *base_path
= NULL
;
669 *local_changes_subsumed
= 0;
671 err
= got_path_dirname(&parent
, ondisk_path
);
675 if (asprintf(&base_path
, "%s/got-merged", parent
) == -1) {
676 err
= got_error_from_errno("asprintf");
680 err
= got_opentemp_named_fd(&merged_path
, &merged_fd
, base_path
, "");
684 err
= got_merge_diff3(&overlapcnt
, merged_fd
, f_deriv
, f_orig
,
685 f_deriv2
, label_deriv
, label_orig
, label_deriv2
, diff_algo
);
687 if (err
->code
!= GOT_ERR_FILE_BINARY
)
689 err
= merge_binary_file(&overlapcnt
, merged_fd
, f_deriv
,
690 f_orig
, f_deriv2
, label_deriv
, label_orig
, label_deriv2
,
696 err
= (*progress_cb
)(progress_arg
,
697 overlapcnt
> 0 ? GOT_STATUS_CONFLICT
: GOT_STATUS_MERGE
, path
);
701 if (fsync(merged_fd
) != 0) {
702 err
= got_error_from_errno("fsync");
706 f_merged
= fdopen(merged_fd
, "r");
707 if (f_merged
== NULL
) {
708 err
= got_error_from_errno("fdopen");
713 /* Check if a clean merge has subsumed all local changes. */
714 if (overlapcnt
== 0) {
715 err
= check_files_equal(local_changes_subsumed
, f_deriv
,
721 if (fchmod(fileno(f_merged
), apply_umask(st_mode
)) != 0) {
722 err
= got_error_from_errno2("fchmod", merged_path
);
726 if (rename(merged_path
, ondisk_path
) != 0) {
727 err
= got_error_from_errno3("rename", merged_path
,
736 if (merged_fd
!= -1 && close(merged_fd
) == -1 && err
== NULL
)
737 err
= got_error_from_errno("close");
738 if (f_merged
&& fclose(f_merged
) == EOF
&& err
== NULL
)
739 err
= got_error_from_errno("fclose");
746 static const struct got_error
*
747 update_symlink(const char *ondisk_path
, const char *target_path
,
750 /* This is not atomic but matches what 'ln -sf' does. */
751 if (unlink(ondisk_path
) == -1)
752 return got_error_from_errno2("unlink", ondisk_path
);
753 if (symlink(target_path
, ondisk_path
) == -1)
754 return got_error_from_errno3("symlink", target_path
,
760 * Overwrite a symlink (or a regular file in case there was a "bad" symlink)
761 * in the work tree with a file that contains conflict markers and the
762 * conflicting target paths of the original version, a "derived version"
763 * of a symlink from an incoming change, and a local version of the symlink.
765 * The original versions's target path can be NULL if it is not available,
766 * such as if both derived versions added a new symlink at the same path.
768 * The incoming derived symlink target is NULL in case the incoming change
769 * has deleted this symlink.
771 static const struct got_error
*
772 install_symlink_conflict(const char *deriv_target
,
773 struct got_object_id
*deriv_base_commit_id
, const char *orig_target
,
774 const char *label_orig
, const char *local_target
, const char *ondisk_path
)
776 const struct got_error
*err
;
777 char *id_str
= NULL
, *label_deriv
= NULL
, *path
= NULL
;
780 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
782 return got_error_from_errno("asprintf");
784 if (asprintf(&label_deriv
, "%s: commit %s",
785 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
786 err
= got_error_from_errno("asprintf");
790 err
= got_opentemp_named(&path
, &f
, "got-symlink-conflict", "");
794 if (fchmod(fileno(f
), apply_umask(GOT_DEFAULT_FILE_MODE
)) == -1) {
795 err
= got_error_from_errno2("fchmod", path
);
799 if (fprintf(f
, "%s %s\n%s\n%s%s%s%s%s\n%s\n%s\n",
800 GOT_DIFF_CONFLICT_MARKER_BEGIN
, label_deriv
,
801 deriv_target
? deriv_target
: "(symlink was deleted)",
802 orig_target
? label_orig
: "",
803 orig_target
? "\n" : "",
804 orig_target
? orig_target
: "",
805 orig_target
? "\n" : "",
806 GOT_DIFF_CONFLICT_MARKER_SEP
,
807 local_target
, GOT_DIFF_CONFLICT_MARKER_END
) < 0) {
808 err
= got_error_from_errno2("fprintf", path
);
812 if (unlink(ondisk_path
) == -1) {
813 err
= got_error_from_errno2("unlink", ondisk_path
);
816 if (rename(path
, ondisk_path
) == -1) {
817 err
= got_error_from_errno3("rename", path
, ondisk_path
);
821 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
822 err
= got_error_from_errno2("fclose", path
);
829 /* forward declaration */
830 static const struct got_error
*
831 merge_blob(int *, struct got_worktree
*, struct got_blob_object
*,
832 const char *, const char *, uint16_t, const char *,
833 struct got_blob_object
*, struct got_object_id
*,
834 struct got_repository
*, got_worktree_checkout_cb
, void *);
837 * Merge a symlink into the work tree, where blob_orig acts as the common
838 * ancestor, deriv_target is the link target of the first derived version,
839 * and the symlink on disk acts as the second derived version.
840 * Assume that contents of both blobs represent symlinks.
842 static const struct got_error
*
843 merge_symlink(struct got_worktree
*worktree
,
844 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
845 const char *path
, const char *label_orig
, const char *deriv_target
,
846 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
847 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
849 const struct got_error
*err
= NULL
;
850 char *ancestor_target
= NULL
;
852 ssize_t ondisk_len
, deriv_len
;
853 char ondisk_target
[PATH_MAX
];
854 int have_local_change
= 0;
855 int have_incoming_change
= 0;
857 if (lstat(ondisk_path
, &sb
) == -1)
858 return got_error_from_errno2("lstat", ondisk_path
);
860 ondisk_len
= readlink(ondisk_path
, ondisk_target
,
861 sizeof(ondisk_target
));
862 if (ondisk_len
== -1) {
863 err
= got_error_from_errno2("readlink",
867 ondisk_target
[ondisk_len
] = '\0';
870 err
= got_object_blob_read_to_str(&ancestor_target
, blob_orig
);
875 if (ancestor_target
== NULL
||
876 (ondisk_len
!= strlen(ancestor_target
) ||
877 memcmp(ondisk_target
, ancestor_target
, ondisk_len
) != 0))
878 have_local_change
= 1;
880 deriv_len
= strlen(deriv_target
);
881 if (ancestor_target
== NULL
||
882 (deriv_len
!= strlen(ancestor_target
) ||
883 memcmp(deriv_target
, ancestor_target
, deriv_len
) != 0))
884 have_incoming_change
= 1;
886 if (!have_local_change
&& !have_incoming_change
) {
887 if (ancestor_target
) {
888 /* Both sides made the same change. */
889 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
891 } else if (deriv_len
== ondisk_len
&&
892 memcmp(ondisk_target
, deriv_target
, deriv_len
) == 0) {
893 /* Both sides added the same symlink. */
894 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
897 /* Both sides added symlinks which don't match. */
898 err
= install_symlink_conflict(deriv_target
,
899 deriv_base_commit_id
, ancestor_target
,
900 label_orig
, ondisk_target
, ondisk_path
);
903 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
906 } else if (!have_local_change
&& have_incoming_change
) {
907 /* Apply the incoming change. */
908 err
= update_symlink(ondisk_path
, deriv_target
,
909 strlen(deriv_target
));
912 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
913 } else if (have_local_change
&& have_incoming_change
) {
914 if (deriv_len
== ondisk_len
&&
915 memcmp(deriv_target
, ondisk_target
, deriv_len
) == 0) {
916 /* Both sides made the same change. */
917 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
920 err
= install_symlink_conflict(deriv_target
,
921 deriv_base_commit_id
, ancestor_target
, label_orig
,
922 ondisk_target
, ondisk_path
);
925 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
931 free(ancestor_target
);
935 static const struct got_error
*
936 dump_symlink_target_path_to_file(FILE **outfile
, const char *ondisk_path
)
938 const struct got_error
*err
= NULL
;
939 char target_path
[PATH_MAX
];
948 return got_error_from_errno("got_opentemp");
949 target_len
= readlink(ondisk_path
, target_path
, sizeof(target_path
));
950 if (target_len
== -1) {
951 err
= got_error_from_errno2("readlink", ondisk_path
);
954 n
= fwrite(target_path
, 1, target_len
, f
);
955 if (n
!= target_len
) {
956 err
= got_ferror(f
, GOT_ERR_IO
);
959 if (fflush(f
) == EOF
) {
960 err
= got_error_from_errno("fflush");
963 if (fseek(f
, 0L, SEEK_SET
) == -1) {
964 err
= got_ferror(f
, GOT_ERR_IO
);
976 * Perform a 3-way merge where blob_orig acts as the common ancestor,
977 * blob_deriv acts as the first derived version, and the file on disk
978 * acts as the second derived version.
980 static const struct got_error
*
981 merge_blob(int *local_changes_subsumed
, struct got_worktree
*worktree
,
982 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
983 const char *path
, uint16_t st_mode
, const char *label_orig
,
984 struct got_blob_object
*blob_deriv
,
985 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
986 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
988 const struct got_error
*err
= NULL
;
989 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
990 char *blob_orig_path
= NULL
;
991 char *blob_deriv_path
= NULL
, *base_path
= NULL
, *id_str
= NULL
;
992 char *label_deriv
= NULL
, *parent
= NULL
;
994 *local_changes_subsumed
= 0;
996 err
= got_path_dirname(&parent
, ondisk_path
);
1001 if (asprintf(&base_path
, "%s/got-merge-blob-orig",
1003 err
= got_error_from_errno("asprintf");
1008 err
= got_opentemp_named(&blob_orig_path
, &f_orig
,
1012 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_orig
,
1019 * No common ancestor exists. This is an "add vs add" conflict
1020 * and we simply use an empty ancestor file to make both files
1021 * appear in the merged result in their entirety.
1023 f_orig
= got_opentemp();
1024 if (f_orig
== NULL
) {
1025 err
= got_error_from_errno("got_opentemp");
1030 if (asprintf(&base_path
, "%s/got-merge-blob-deriv", parent
) == -1) {
1031 err
= got_error_from_errno("asprintf");
1036 err
= got_opentemp_named(&blob_deriv_path
, &f_deriv
, base_path
, "");
1039 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_deriv
,
1044 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
1047 if (asprintf(&label_deriv
, "%s: commit %s",
1048 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
1049 err
= got_error_from_errno("asprintf");
1054 * In order the run a 3-way merge with a symlink we copy the symlink's
1055 * target path into a temporary file and use that file with diff3.
1057 if (S_ISLNK(st_mode
)) {
1058 err
= dump_symlink_target_path_to_file(&f_deriv2
, ondisk_path
);
1063 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1065 err
= got_error_from_errno2("open", ondisk_path
);
1068 f_deriv2
= fdopen(fd
, "r");
1069 if (f_deriv2
== NULL
) {
1070 err
= got_error_from_errno2("fdopen", ondisk_path
);
1076 err
= merge_file(local_changes_subsumed
, worktree
, f_orig
, f_deriv
,
1077 f_deriv2
, ondisk_path
, path
, st_mode
, label_orig
, label_deriv
,
1078 NULL
, GOT_DIFF_ALGORITHM_MYERS
, repo
, progress_cb
, progress_arg
);
1080 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
1081 err
= got_error_from_errno("fclose");
1082 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
1083 err
= got_error_from_errno("fclose");
1084 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
1085 err
= got_error_from_errno("fclose");
1087 if (blob_orig_path
) {
1088 unlink(blob_orig_path
);
1089 free(blob_orig_path
);
1091 if (blob_deriv_path
) {
1092 unlink(blob_deriv_path
);
1093 free(blob_deriv_path
);
1101 static const struct got_error
*
1102 create_fileindex_entry(struct got_fileindex_entry
**new_iep
,
1103 struct got_fileindex
*fileindex
, struct got_object_id
*base_commit_id
,
1104 int wt_fd
, const char *path
, struct got_object_id
*blob_id
,
1105 int update_timestamps
)
1107 const struct got_error
*err
= NULL
;
1108 struct got_fileindex_entry
*new_ie
;
1112 err
= got_fileindex_entry_alloc(&new_ie
, path
);
1116 err
= got_fileindex_entry_update(new_ie
, wt_fd
, path
,
1117 blob_id
, base_commit_id
, update_timestamps
);
1121 err
= got_fileindex_entry_add(fileindex
, new_ie
);
1124 got_fileindex_entry_free(new_ie
);
1131 get_ondisk_perms(int executable
, mode_t st_mode
)
1133 mode_t xbits
= S_IXUSR
;
1136 /* Map read bits to execute bits. */
1137 if (st_mode
& S_IRGRP
)
1139 if (st_mode
& S_IROTH
)
1141 return st_mode
| xbits
;
1147 /* forward declaration */
1148 static const struct got_error
*
1149 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1150 const char *path
, mode_t te_mode
, mode_t st_mode
,
1151 struct got_blob_object
*blob
, int restoring_missing_file
,
1152 int reverting_versioned_file
, int installing_bad_symlink
,
1153 int path_is_unversioned
, int *update_timestamps
,
1154 struct got_repository
*repo
,
1155 got_worktree_checkout_cb progress_cb
, void *progress_arg
);
1158 * This function assumes that the provided symlink target points at a
1159 * safe location in the work tree!
1161 static const struct got_error
*
1162 replace_existing_symlink(int *did_something
, const char *ondisk_path
,
1163 const char *target_path
, size_t target_len
)
1165 const struct got_error
*err
= NULL
;
1167 char etarget
[PATH_MAX
];
1173 * "Bad" symlinks (those pointing outside the work tree or into the
1174 * .got directory) are installed in the work tree as a regular file
1175 * which contains the bad symlink target path.
1176 * The new symlink target has already been checked for safety by our
1177 * caller. If we can successfully open a regular file then we simply
1178 * replace this file with a symlink below.
1180 fd
= open(ondisk_path
, O_RDWR
| O_EXCL
| O_NOFOLLOW
| O_CLOEXEC
);
1182 if (!got_err_open_nofollow_on_symlink())
1183 return got_error_from_errno2("open", ondisk_path
);
1185 /* We are updating an existing on-disk symlink. */
1186 elen
= readlink(ondisk_path
, etarget
, sizeof(etarget
));
1188 return got_error_from_errno2("readlink", ondisk_path
);
1190 if (elen
== target_len
&&
1191 memcmp(etarget
, target_path
, target_len
) == 0)
1192 return NULL
; /* nothing to do */
1196 err
= update_symlink(ondisk_path
, target_path
, target_len
);
1197 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1198 err
= got_error_from_errno2("close", ondisk_path
);
1202 static const struct got_error
*
1203 is_bad_symlink_target(int *is_bad_symlink
, const char *target_path
,
1204 size_t target_len
, const char *ondisk_path
, const char *wtroot_path
,
1205 const char *meta_dir
)
1207 const struct got_error
*err
= NULL
;
1208 char canonpath
[PATH_MAX
];
1209 char *path_got
= NULL
;
1211 *is_bad_symlink
= 0;
1213 if (target_len
>= sizeof(canonpath
)) {
1214 *is_bad_symlink
= 1;
1219 * We do not use realpath(3) to resolve the symlink's target
1220 * path because we don't want to resolve symlinks recursively.
1221 * Instead we make the path absolute and then canonicalize it.
1222 * Relative symlink target lookup should begin at the directory
1223 * in which the blob object is being installed.
1225 if (!got_path_is_absolute(target_path
)) {
1226 char *abspath
, *parent
;
1227 err
= got_path_dirname(&parent
, ondisk_path
);
1230 if (asprintf(&abspath
, "%s/%s", parent
, target_path
) == -1) {
1232 return got_error_from_errno("asprintf");
1235 if (strlen(abspath
) >= sizeof(canonpath
)) {
1236 err
= got_error_path(abspath
, GOT_ERR_BAD_PATH
);
1240 err
= got_canonpath(abspath
, canonpath
, sizeof(canonpath
));
1245 err
= got_canonpath(target_path
, canonpath
, sizeof(canonpath
));
1250 /* Only allow symlinks pointing at paths within the work tree. */
1251 if (!got_path_is_child(canonpath
, wtroot_path
, strlen(wtroot_path
))) {
1252 *is_bad_symlink
= 1;
1256 /* Do not allow symlinks pointing into the meta directory. */
1257 if (asprintf(&path_got
, "%s/%s", wtroot_path
, meta_dir
) == -1)
1258 return got_error_from_errno("asprintf");
1259 if (got_path_is_child(canonpath
, path_got
, strlen(path_got
)))
1260 *is_bad_symlink
= 1;
1266 static const struct got_error
*
1267 install_symlink(int *is_bad_symlink
, struct got_worktree
*worktree
,
1268 const char *ondisk_path
, const char *path
, struct got_blob_object
*blob
,
1269 int restoring_missing_file
, int reverting_versioned_file
,
1270 int path_is_unversioned
, int allow_bad_symlinks
,
1271 struct got_repository
*repo
,
1272 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1274 const struct got_error
*err
= NULL
;
1275 char target_path
[PATH_MAX
];
1276 size_t len
, target_len
= 0;
1277 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1278 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1280 *is_bad_symlink
= 0;
1283 * Blob object content specifies the target path of the link.
1284 * If a symbolic link cannot be installed we instead create
1285 * a regular file which contains the link target path stored
1286 * in the blob object.
1289 err
= got_object_blob_read_block(&len
, blob
);
1293 if (len
+ target_len
>= sizeof(target_path
)) {
1294 /* Path too long; install as a regular file. */
1295 *is_bad_symlink
= 1;
1296 got_object_blob_rewind(blob
);
1297 return install_blob(worktree
, ondisk_path
, path
,
1298 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1299 restoring_missing_file
, reverting_versioned_file
,
1300 1, path_is_unversioned
, NULL
, repo
, progress_cb
,
1304 /* Skip blob object header first time around. */
1305 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1307 target_len
+= len
- hdrlen
;
1311 target_path
[target_len
] = '\0';
1313 err
= is_bad_symlink_target(is_bad_symlink
, target_path
, target_len
,
1314 ondisk_path
, worktree
->root_path
, worktree
->meta_dir
);
1318 if (*is_bad_symlink
&& !allow_bad_symlinks
) {
1319 /* install as a regular file */
1320 got_object_blob_rewind(blob
);
1321 err
= install_blob(worktree
, ondisk_path
, path
,
1322 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1323 restoring_missing_file
, reverting_versioned_file
, 1,
1324 path_is_unversioned
, NULL
, repo
,
1325 progress_cb
, progress_arg
);
1329 if (symlink(target_path
, ondisk_path
) == -1) {
1330 if (errno
== EEXIST
) {
1331 int symlink_replaced
;
1332 if (path_is_unversioned
) {
1333 err
= (*progress_cb
)(progress_arg
,
1334 GOT_STATUS_UNVERSIONED
, path
);
1337 err
= replace_existing_symlink(&symlink_replaced
,
1338 ondisk_path
, target_path
, target_len
);
1342 if (symlink_replaced
) {
1343 err
= (*progress_cb
)(progress_arg
,
1344 reverting_versioned_file
?
1346 GOT_STATUS_UPDATE
, path
);
1348 err
= (*progress_cb
)(progress_arg
,
1349 GOT_STATUS_EXISTS
, path
);
1352 return err
; /* Nothing else to do. */
1355 if (errno
== ENOENT
) {
1357 err
= got_path_dirname(&parent
, ondisk_path
);
1360 err
= got_path_mkdir(parent
);
1365 * Retry, and fall through to error handling
1366 * below if this second attempt fails.
1368 if (symlink(target_path
, ondisk_path
) != -1) {
1369 err
= NULL
; /* success */
1371 err
= (*progress_cb
)(progress_arg
,
1372 reverting_versioned_file
?
1373 GOT_STATUS_REVERT
: GOT_STATUS_ADD
,
1380 /* Handle errors from first or second creation attempt. */
1381 if (errno
== ENAMETOOLONG
) {
1382 /* bad target path; install as a regular file */
1383 *is_bad_symlink
= 1;
1384 got_object_blob_rewind(blob
);
1385 err
= install_blob(worktree
, ondisk_path
, path
,
1386 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1387 restoring_missing_file
, reverting_versioned_file
, 1,
1388 path_is_unversioned
, NULL
, repo
,
1389 progress_cb
, progress_arg
);
1390 } else if (errno
== ENOTDIR
) {
1391 err
= got_error_path(ondisk_path
,
1392 GOT_ERR_FILE_OBSTRUCTED
);
1394 err
= got_error_from_errno3("symlink",
1395 target_path
, ondisk_path
);
1397 } else if (progress_cb
)
1398 err
= (*progress_cb
)(progress_arg
, reverting_versioned_file
?
1399 GOT_STATUS_REVERT
: GOT_STATUS_ADD
, path
);
1403 static const struct got_error
*
1404 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1405 const char *path
, mode_t te_mode
, mode_t st_mode
,
1406 struct got_blob_object
*blob
, int restoring_missing_file
,
1407 int reverting_versioned_file
, int installing_bad_symlink
,
1408 int path_is_unversioned
, int *update_timestamps
,
1409 struct got_repository
*repo
,
1410 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1412 const struct got_error
*err
= NULL
;
1416 char *tmppath
= NULL
;
1419 if (update_timestamps
)
1420 *update_timestamps
= 1;
1422 mode
= get_ondisk_perms(te_mode
& S_IXUSR
, GOT_DEFAULT_FILE_MODE
);
1423 fd
= open(ondisk_path
, O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
|
1426 if (errno
== ENOENT
|| errno
== ENOTDIR
) {
1428 err
= got_path_dirname(&parent
, path
);
1431 err
= add_dir_on_disk(worktree
, parent
);
1432 if (err
&& err
->code
== GOT_ERR_FILE_OBSTRUCTED
)
1433 err
= got_error_path(path
, err
->code
);
1437 fd
= open(ondisk_path
,
1438 O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
| O_CLOEXEC
,
1441 return got_error_from_errno2("open",
1443 } else if (errno
== EEXIST
) {
1444 if (path_is_unversioned
) {
1445 if (update_timestamps
)
1446 *update_timestamps
= 0;
1447 err
= (*progress_cb
)(progress_arg
,
1448 GOT_STATUS_EXISTS
, path
);
1451 if (!(S_ISLNK(st_mode
) && S_ISREG(te_mode
)) &&
1452 !S_ISREG(st_mode
) && !installing_bad_symlink
) {
1453 /* TODO file is obstructed; do something */
1454 err
= got_error_path(ondisk_path
,
1455 GOT_ERR_FILE_OBSTRUCTED
);
1458 err
= got_opentemp_named_fd(&tmppath
, &fd
,
1464 if (fchmod(fd
, apply_umask(mode
)) == -1) {
1465 err
= got_error_from_errno2("fchmod",
1471 return got_error_from_errno2("open", ondisk_path
);
1475 if (restoring_missing_file
)
1476 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MISSING
,
1478 else if (reverting_versioned_file
)
1479 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_REVERT
,
1482 err
= (*progress_cb
)(progress_arg
,
1483 update
? GOT_STATUS_UPDATE
: GOT_STATUS_ADD
, path
);
1488 hdrlen
= got_object_blob_get_hdrlen(blob
);
1490 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1491 err
= got_object_blob_read_block(&len
, blob
);
1495 /* Skip blob object header first time around. */
1496 ssize_t outlen
= write(fd
, buf
+ hdrlen
, len
- hdrlen
);
1498 err
= got_error_from_errno("write");
1500 } else if (outlen
!= len
- hdrlen
) {
1501 err
= got_error(GOT_ERR_IO
);
1508 if (fsync(fd
) != 0) {
1509 err
= got_error_from_errno("fsync");
1514 if (S_ISLNK(st_mode
) && unlink(ondisk_path
) == -1) {
1515 err
= got_error_from_errno2("unlink", ondisk_path
);
1518 if (rename(tmppath
, ondisk_path
) != 0) {
1519 err
= got_error_from_errno3("rename", tmppath
,
1528 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1529 err
= got_error_from_errno("close");
1530 if (tmppath
!= NULL
&& unlink(tmppath
) == -1 && err
== NULL
)
1531 err
= got_error_from_errno2("unlink", tmppath
);
1537 * Upgrade STATUS_MODIFY to STATUS_CONFLICT if a
1538 * conflict marker is found in newly added lines only.
1540 static const struct got_error
*
1541 get_modified_file_content_status(unsigned char *status
,
1542 struct got_blob_object
*blob
, const char *path
, struct stat
*sb
,
1545 const struct got_error
*err
, *free_err
;
1546 const char *markers
[3] = {
1547 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
1548 GOT_DIFF_CONFLICT_MARKER_SEP
,
1549 GOT_DIFF_CONFLICT_MARKER_END
1552 struct got_diffreg_result
*diffreg_result
= NULL
;
1553 struct diff_result
*r
;
1554 int nchunks_parsed
, n
, i
= 0, ln
= 0;
1556 size_t linesize
= 0;
1559 if (*status
!= GOT_STATUS_MODIFY
)
1562 f1
= got_opentemp();
1564 return got_error_from_errno("got_opentemp");
1567 got_object_blob_rewind(blob
);
1568 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
1573 err
= got_diff_files(&diffreg_result
, f1
, 1, NULL
, ondisk_file
,
1574 1, NULL
, 0, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
1578 r
= diffreg_result
->result
;
1580 for (n
= 0; n
< r
->chunks
.len
; n
+= nchunks_parsed
) {
1581 struct diff_chunk
*c
;
1582 struct diff_chunk_context cc
= {};
1586 * We can optimise a little by advancing straight
1587 * to the next chunk if this one has no added lines.
1589 c
= diff_chunk_get(r
, n
);
1591 if (diff_chunk_type(c
) != CHUNK_PLUS
) {
1593 continue; /* removed or unchanged lines */
1596 pos
= diff_chunk_get_right_start_pos(c
);
1597 if (fseek(ondisk_file
, pos
, SEEK_SET
) == -1) {
1598 err
= got_ferror(ondisk_file
, GOT_ERR_IO
);
1602 diff_chunk_context_load_change(&cc
, &nchunks_parsed
, r
, n
, 0);
1603 ln
= cc
.right
.start
;
1605 while (ln
< cc
.right
.end
) {
1606 linelen
= getline(&line
, &linesize
, ondisk_file
);
1607 if (linelen
== -1) {
1608 if (feof(ondisk_file
))
1610 err
= got_ferror(ondisk_file
, GOT_ERR_IO
);
1614 if (line
&& strncmp(line
, markers
[i
],
1615 strlen(markers
[i
])) == 0) {
1616 if (strcmp(markers
[i
],
1617 GOT_DIFF_CONFLICT_MARKER_END
) == 0) {
1618 *status
= GOT_STATUS_CONFLICT
;
1629 if (f1
!= NULL
&& fclose(f1
) == EOF
&& err
== NULL
)
1630 err
= got_error_from_errno("fclose");
1631 free_err
= got_diffreg_result_free(diffreg_result
);
1639 xbit_differs(struct got_fileindex_entry
*ie
, uint16_t st_mode
)
1641 mode_t ie_mode
= got_fileindex_perms_to_st(ie
);
1642 return ((ie_mode
& S_IXUSR
) != (st_mode
& S_IXUSR
));
1646 stat_info_differs(struct got_fileindex_entry
*ie
, struct stat
*sb
)
1648 return !(ie
->ctime_sec
== sb
->st_ctim
.tv_sec
&&
1649 ie
->ctime_nsec
== sb
->st_ctim
.tv_nsec
&&
1650 ie
->mtime_sec
== sb
->st_mtim
.tv_sec
&&
1651 ie
->mtime_nsec
== sb
->st_mtim
.tv_nsec
&&
1652 ie
->size
== (sb
->st_size
& 0xffffffff) &&
1653 !xbit_differs(ie
, sb
->st_mode
));
1656 static unsigned char
1657 get_staged_status(struct got_fileindex_entry
*ie
)
1659 switch (got_fileindex_entry_stage_get(ie
)) {
1660 case GOT_FILEIDX_STAGE_ADD
:
1661 return GOT_STATUS_ADD
;
1662 case GOT_FILEIDX_STAGE_DELETE
:
1663 return GOT_STATUS_DELETE
;
1664 case GOT_FILEIDX_STAGE_MODIFY
:
1665 return GOT_STATUS_MODIFY
;
1667 return GOT_STATUS_NO_CHANGE
;
1671 static const struct got_error
*
1672 get_symlink_modification_status(unsigned char *status
,
1673 struct got_fileindex_entry
*ie
, const char *abspath
,
1674 int dirfd
, const char *de_name
, struct got_blob_object
*blob
)
1676 const struct got_error
*err
= NULL
;
1677 char target_path
[PATH_MAX
];
1678 char etarget
[PATH_MAX
];
1680 size_t len
, target_len
= 0;
1681 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1682 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1684 *status
= GOT_STATUS_NO_CHANGE
;
1686 /* Blob object content specifies the target path of the link. */
1688 err
= got_object_blob_read_block(&len
, blob
);
1691 if (len
+ target_len
>= sizeof(target_path
)) {
1693 * Should not happen. The blob contents were OK
1694 * when this symlink was installed.
1696 return got_error(GOT_ERR_NO_SPACE
);
1699 /* Skip blob object header first time around. */
1700 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1702 target_len
+= len
- hdrlen
;
1706 target_path
[target_len
] = '\0';
1709 elen
= readlinkat(dirfd
, de_name
, etarget
, sizeof(etarget
));
1711 return got_error_from_errno2("readlinkat", abspath
);
1713 elen
= readlink(abspath
, etarget
, sizeof(etarget
));
1715 return got_error_from_errno2("readlink", abspath
);
1718 if (elen
!= target_len
|| memcmp(etarget
, target_path
, target_len
) != 0)
1719 *status
= GOT_STATUS_MODIFY
;
1724 static const struct got_error
*
1725 get_file_status(unsigned char *status
, struct stat
*sb
,
1726 struct got_fileindex_entry
*ie
, const char *abspath
,
1727 int dirfd
, const char *de_name
, struct got_repository
*repo
)
1729 const struct got_error
*err
= NULL
;
1730 struct got_object_id id
;
1732 int fd
= -1, fd1
= -1;
1735 struct got_blob_object
*blob
= NULL
;
1737 unsigned char staged_status
;
1739 staged_status
= get_staged_status(ie
);
1740 *status
= GOT_STATUS_NO_CHANGE
;
1741 memset(sb
, 0, sizeof(*sb
));
1744 * Whenever the caller provides a directory descriptor and a
1745 * directory entry name for the file, use them! This prevents
1746 * race conditions if filesystem paths change beneath our feet.
1749 if (fstatat(dirfd
, de_name
, sb
, AT_SYMLINK_NOFOLLOW
) == -1) {
1750 if (errno
== ENOENT
) {
1751 if (got_fileindex_entry_has_file_on_disk(ie
))
1752 *status
= GOT_STATUS_MISSING
;
1754 *status
= GOT_STATUS_DELETE
;
1757 err
= got_error_from_errno2("fstatat", abspath
);
1761 fd
= open(abspath
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1762 if (fd
== -1 && errno
!= ENOENT
&&
1763 !got_err_open_nofollow_on_symlink())
1764 return got_error_from_errno2("open", abspath
);
1765 else if (fd
== -1 && got_err_open_nofollow_on_symlink()) {
1766 if (lstat(abspath
, sb
) == -1)
1767 return got_error_from_errno2("lstat", abspath
);
1768 } else if (fd
== -1 || fstat(fd
, sb
) == -1) {
1769 if (errno
== ENOENT
) {
1770 if (got_fileindex_entry_has_file_on_disk(ie
))
1771 *status
= GOT_STATUS_MISSING
;
1773 *status
= GOT_STATUS_DELETE
;
1776 err
= got_error_from_errno2("fstat", abspath
);
1781 if (!S_ISREG(sb
->st_mode
) && !S_ISLNK(sb
->st_mode
)) {
1782 *status
= GOT_STATUS_OBSTRUCTED
;
1786 if (!got_fileindex_entry_has_file_on_disk(ie
)) {
1787 *status
= GOT_STATUS_DELETE
;
1789 } else if (!got_fileindex_entry_has_blob(ie
) &&
1790 staged_status
!= GOT_STATUS_ADD
) {
1791 *status
= GOT_STATUS_ADD
;
1795 if (!stat_info_differs(ie
, sb
))
1798 if (S_ISLNK(sb
->st_mode
) &&
1799 got_fileindex_entry_filetype_get(ie
) != GOT_FILEIDX_MODE_SYMLINK
) {
1800 *status
= GOT_STATUS_MODIFY
;
1804 if (staged_status
== GOT_STATUS_MODIFY
||
1805 staged_status
== GOT_STATUS_ADD
)
1806 got_fileindex_entry_get_staged_blob_id(&id
, ie
);
1808 got_fileindex_entry_get_blob_id(&id
, ie
);
1810 fd1
= got_opentempfd();
1812 err
= got_error_from_errno("got_opentempfd");
1815 err
= got_object_open_as_blob(&blob
, repo
, &id
, sizeof(fbuf
), fd1
);
1819 if (S_ISLNK(sb
->st_mode
)) {
1820 err
= get_symlink_modification_status(status
, ie
,
1821 abspath
, dirfd
, de_name
, blob
);
1826 fd
= openat(dirfd
, de_name
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1828 err
= got_error_from_errno2("openat", abspath
);
1833 f
= fdopen(fd
, "r");
1835 err
= got_error_from_errno2("fdopen", abspath
);
1839 hdrlen
= got_object_blob_get_hdrlen(blob
);
1841 const uint8_t *bbuf
= got_object_blob_get_read_buf(blob
);
1842 err
= got_object_blob_read_block(&blen
, blob
);
1845 /* Skip length of blob object header first time around. */
1846 flen
= fread(fbuf
, 1, sizeof(fbuf
) - hdrlen
, f
);
1847 if (flen
== 0 && ferror(f
)) {
1848 err
= got_error_from_errno("fread");
1851 if (blen
- hdrlen
== 0) {
1853 *status
= GOT_STATUS_MODIFY
;
1855 } else if (flen
== 0) {
1856 if (blen
- hdrlen
!= 0)
1857 *status
= GOT_STATUS_MODIFY
;
1859 } else if (blen
- hdrlen
== flen
) {
1860 /* Skip blob object header first time around. */
1861 if (memcmp(bbuf
+ hdrlen
, fbuf
, flen
) != 0) {
1862 *status
= GOT_STATUS_MODIFY
;
1866 *status
= GOT_STATUS_MODIFY
;
1872 if (*status
== GOT_STATUS_MODIFY
) {
1874 err
= get_modified_file_content_status(status
, blob
, ie
->path
,
1876 } else if (xbit_differs(ie
, sb
->st_mode
))
1877 *status
= GOT_STATUS_MODE_CHANGE
;
1879 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
1880 err
= got_error_from_errno("close");
1882 got_object_blob_close(blob
);
1883 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
1884 err
= got_error_from_errno2("fclose", abspath
);
1885 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1886 err
= got_error_from_errno2("close", abspath
);
1891 * Update timestamps in the file index if a file is unmodified and
1892 * we had to run a full content comparison to find out.
1894 static const struct got_error
*
1895 sync_timestamps(int wt_fd
, const char *path
, unsigned char status
,
1896 struct got_fileindex_entry
*ie
, struct stat
*sb
)
1898 if (status
== GOT_STATUS_NO_CHANGE
&& stat_info_differs(ie
, sb
))
1899 return got_fileindex_entry_update(ie
, wt_fd
, path
,
1900 &ie
->blob
, &ie
->commit
, 1);
1905 static const struct got_error
*remove_ondisk_file(const char *, const char *);
1907 static const struct got_error
*
1908 update_blob(struct got_worktree
*worktree
,
1909 struct got_fileindex
*fileindex
, struct got_fileindex_entry
*ie
,
1910 struct got_tree_entry
*te
, const char *path
,
1911 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
1914 const struct got_error
*err
= NULL
;
1915 struct got_blob_object
*blob
= NULL
;
1916 char *ondisk_path
= NULL
;
1917 unsigned char status
= GOT_STATUS_NO_CHANGE
;
1919 int fd1
= -1, fd2
= -1;
1920 int update_timestamps
= 0;
1922 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, path
) == -1)
1923 return got_error_from_errno("asprintf");
1926 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
) {
1927 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
1930 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
1934 if (status
== GOT_STATUS_MISSING
|| status
== GOT_STATUS_DELETE
)
1935 sb
.st_mode
= got_fileindex_perms_to_st(ie
);
1937 if (stat(ondisk_path
, &sb
) == -1) {
1938 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
1939 err
= got_error_from_errno2("stat",
1943 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
1944 status
= GOT_STATUS_UNVERSIONED
;
1946 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
1947 status
= GOT_STATUS_UNVERSIONED
;
1949 status
= GOT_STATUS_OBSTRUCTED
;
1953 if (status
== GOT_STATUS_OBSTRUCTED
) {
1955 got_fileindex_entry_mark_skipped(ie
);
1956 err
= (*progress_cb
)(progress_arg
, status
, path
);
1959 if (status
== GOT_STATUS_CONFLICT
) {
1961 got_fileindex_entry_mark_skipped(ie
);
1962 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CANNOT_UPDATE
,
1967 if (S_ISDIR(te
->mode
)) { /* file changing into a directory */
1968 if (status
== GOT_STATUS_UNVERSIONED
) {
1969 err
= (*progress_cb
)(progress_arg
, status
, path
);
1970 } else if (status
!= GOT_STATUS_NO_CHANGE
&&
1971 status
!= GOT_STATUS_DELETE
&&
1972 status
!= GOT_STATUS_NONEXISTENT
&&
1973 status
!= GOT_STATUS_MISSING
) {
1974 err
= (*progress_cb
)(progress_arg
,
1975 GOT_STATUS_CANNOT_DELETE
, path
);
1977 if (status
!= GOT_STATUS_DELETE
&&
1978 status
!= GOT_STATUS_NONEXISTENT
&&
1979 status
!= GOT_STATUS_MISSING
) {
1980 err
= remove_ondisk_file(worktree
->root_path
,
1982 if (err
&& !(err
->code
== GOT_ERR_ERRNO
&&
1986 got_fileindex_entry_remove(fileindex
, ie
);
1987 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_DELETE
,
1990 goto done
; /* nothing else to do */
1993 if (ie
&& status
!= GOT_STATUS_MISSING
&& S_ISREG(sb
.st_mode
) &&
1994 (S_ISLNK(te
->mode
) ||
1995 (te
->mode
& S_IXUSR
) == (sb
.st_mode
& S_IXUSR
))) {
1997 * This is a regular file or an installed bad symlink.
1998 * If the file index indicates that this file is already
1999 * up-to-date with respect to the repository we can skip
2000 * updating contents of this file.
2002 if (got_fileindex_entry_has_commit(ie
) &&
2003 got_object_id_cmp(&ie
->commit
,
2004 worktree
->base_commit_id
) == 0) {
2006 err
= sync_timestamps(worktree
->root_fd
,
2007 path
, status
, ie
, &sb
);
2010 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
2014 if (got_fileindex_entry_has_blob(ie
) &&
2015 got_object_id_cmp(&ie
->blob
, &te
->id
) == 0) {
2016 /* Different commit but the same blob. */
2017 if (got_fileindex_entry_has_commit(ie
)) {
2018 /* Update the base commit ID of this file. */
2019 memcpy(&ie
->commit
, worktree
->base_commit_id
,
2020 sizeof(ie
->commit
));
2022 err
= sync_timestamps(worktree
->root_fd
,
2023 path
, status
, ie
, &sb
);
2026 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
2032 fd1
= got_opentempfd();
2034 err
= got_error_from_errno("got_opentempfd");
2037 err
= got_object_open_as_blob(&blob
, repo
, &te
->id
, 8192, fd1
);
2041 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_ADD
) {
2042 struct got_blob_object
*blob2
= NULL
;
2043 char *label_orig
= NULL
;
2044 if (got_fileindex_entry_has_blob(ie
)) {
2045 fd2
= got_opentempfd();
2047 err
= got_error_from_errno("got_opentempfd");
2050 struct got_object_id id2
;
2051 got_fileindex_entry_get_blob_id(&id2
, ie
);
2052 err
= got_object_open_as_blob(&blob2
, repo
, &id2
, 8192,
2057 if (got_fileindex_entry_has_commit(ie
)) {
2058 char id_str
[GOT_HASH_DIGEST_STRING_MAXLEN
];
2060 if (got_hash_digest_to_str(ie
->commit
.hash
, id_str
,
2061 sizeof(id_str
), ie
->commit
.algo
) == NULL
) {
2062 err
= got_error_path(id_str
,
2063 GOT_ERR_BAD_OBJ_ID_STR
);
2066 if (asprintf(&label_orig
, "%s: commit %s",
2067 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
2068 err
= got_error_from_errno("asprintf");
2072 if (S_ISLNK(te
->mode
) && S_ISLNK(sb
.st_mode
)) {
2074 err
= got_object_blob_read_to_str(&link_target
, blob
);
2077 err
= merge_symlink(worktree
, blob2
, ondisk_path
, path
,
2078 label_orig
, link_target
, worktree
->base_commit_id
,
2079 repo
, progress_cb
, progress_arg
);
2082 err
= merge_blob(&update_timestamps
, worktree
, blob2
,
2083 ondisk_path
, path
, sb
.st_mode
, label_orig
, blob
,
2084 worktree
->base_commit_id
, repo
,
2085 progress_cb
, progress_arg
);
2088 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
) {
2089 err
= got_error_from_errno("close");
2093 got_object_blob_close(blob2
);
2097 * Do not update timestamps of files with local changes.
2098 * Otherwise, a future status walk would treat them as
2099 * unmodified files again.
2101 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2102 &blob
->id
, worktree
->base_commit_id
, update_timestamps
);
2103 } else if (status
== GOT_STATUS_MODE_CHANGE
) {
2104 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2105 &blob
->id
, worktree
->base_commit_id
, 0);
2106 } else if (status
== GOT_STATUS_DELETE
) {
2107 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
2110 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2111 &blob
->id
, worktree
->base_commit_id
, 0);
2115 int is_bad_symlink
= 0;
2116 if (S_ISLNK(te
->mode
)) {
2117 err
= install_symlink(&is_bad_symlink
, worktree
,
2118 ondisk_path
, path
, blob
,
2119 status
== GOT_STATUS_MISSING
, 0,
2120 status
== GOT_STATUS_UNVERSIONED
, 0,
2121 repo
, progress_cb
, progress_arg
);
2123 err
= install_blob(worktree
, ondisk_path
, path
,
2124 te
->mode
, sb
.st_mode
, blob
,
2125 status
== GOT_STATUS_MISSING
, 0, 0,
2126 status
== GOT_STATUS_UNVERSIONED
,
2128 repo
, progress_cb
, progress_arg
);
2134 err
= got_fileindex_entry_update(ie
,
2135 worktree
->root_fd
, path
, &blob
->id
,
2136 worktree
->base_commit_id
, 1);
2138 err
= create_fileindex_entry(&ie
, fileindex
,
2139 worktree
->base_commit_id
, worktree
->root_fd
, path
,
2140 &blob
->id
, update_timestamps
);
2145 if (is_bad_symlink
) {
2146 got_fileindex_entry_filetype_set(ie
,
2147 GOT_FILEIDX_MODE_BAD_SYMLINK
);
2151 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
) {
2152 err
= got_error_from_errno("close");
2155 got_object_blob_close(blob
);
2161 static const struct got_error
*
2162 remove_ondisk_file(const char *root_path
, const char *path
)
2164 const struct got_error
*err
= NULL
;
2165 char *ondisk_path
= NULL
, *parent
= NULL
;
2167 if (asprintf(&ondisk_path
, "%s/%s", root_path
, path
) == -1)
2168 return got_error_from_errno("asprintf");
2170 if (unlink(ondisk_path
) == -1) {
2171 if (errno
!= ENOENT
)
2172 err
= got_error_from_errno2("unlink", ondisk_path
);
2174 size_t root_len
= strlen(root_path
);
2175 err
= got_path_dirname(&parent
, ondisk_path
);
2178 while (got_path_cmp(parent
, root_path
,
2179 strlen(parent
), root_len
) != 0) {
2181 ondisk_path
= parent
;
2183 if (rmdir(ondisk_path
) == -1) {
2184 if (errno
!= ENOTEMPTY
)
2185 err
= got_error_from_errno2("rmdir",
2189 err
= got_path_dirname(&parent
, ondisk_path
);
2200 static const struct got_error
*
2201 delete_blob(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2202 struct got_fileindex_entry
*ie
, struct got_repository
*repo
,
2203 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2205 const struct got_error
*err
= NULL
;
2206 unsigned char status
;
2210 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
2211 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
2213 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, ie
->path
)
2215 return got_error_from_errno("asprintf");
2217 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, repo
);
2221 if (S_ISLNK(sb
.st_mode
) && status
!= GOT_STATUS_NO_CHANGE
) {
2222 char ondisk_target
[PATH_MAX
];
2223 ssize_t ondisk_len
= readlink(ondisk_path
, ondisk_target
,
2224 sizeof(ondisk_target
));
2225 if (ondisk_len
== -1) {
2226 err
= got_error_from_errno2("readlink", ondisk_path
);
2229 ondisk_target
[ondisk_len
] = '\0';
2230 err
= install_symlink_conflict(NULL
, worktree
->base_commit_id
,
2231 NULL
, NULL
, /* XXX pass common ancestor info? */
2232 ondisk_target
, ondisk_path
);
2235 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
2240 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_CONFLICT
||
2241 status
== GOT_STATUS_ADD
) {
2242 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, ie
->path
);
2246 * Preserve the working file and change the deleted blob's
2247 * entry into a schedule-add entry.
2249 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
,
2250 ie
->path
, NULL
, NULL
, 0);
2252 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_DELETE
, ie
->path
);
2255 if (status
== GOT_STATUS_NO_CHANGE
) {
2256 err
= remove_ondisk_file(worktree
->root_path
, ie
->path
);
2260 got_fileindex_entry_remove(fileindex
, ie
);
2267 struct diff_cb_arg
{
2268 struct got_fileindex
*fileindex
;
2269 struct got_worktree
*worktree
;
2270 struct got_repository
*repo
;
2271 got_worktree_checkout_cb progress_cb
;
2273 got_cancel_cb cancel_cb
;
2277 static const struct got_error
*
2278 diff_old_new(void *arg
, struct got_fileindex_entry
*ie
,
2279 struct got_tree_entry
*te
, const char *parent_path
)
2281 const struct got_error
*err
= NULL
;
2282 struct diff_cb_arg
*a
= arg
;
2285 err
= a
->cancel_cb(a
->cancel_arg
);
2290 return update_blob(a
->worktree
, a
->fileindex
, ie
, te
,
2291 ie
->path
, a
->repo
, a
->progress_cb
, a
->progress_arg
);
2294 static const struct got_error
*
2295 diff_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
2297 const struct got_error
*err
= NULL
;
2298 struct diff_cb_arg
*a
= arg
;
2301 err
= a
->cancel_cb(a
->cancel_arg
);
2306 return delete_blob(a
->worktree
, a
->fileindex
, ie
,
2307 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2310 static const struct got_error
*
2311 diff_new(void *arg
, struct got_tree_entry
*te
, const char *parent_path
)
2313 const struct got_error
*err
= NULL
;
2314 struct diff_cb_arg
*a
= arg
;
2318 err
= a
->cancel_cb(a
->cancel_arg
);
2323 if (got_object_tree_entry_is_submodule(te
))
2326 if (!S_ISREG(te
->mode
) && !S_ISLNK(te
->mode
))
2329 if (asprintf(&path
, "%s%s%s", parent_path
,
2330 parent_path
[0] ? "/" : "", te
->name
)
2332 return got_error_from_errno("asprintf");
2334 err
= update_blob(a
->worktree
, a
->fileindex
, NULL
, te
, path
,
2335 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2341 const struct got_error
*
2342 got_worktree_get_uuid(char **uuidstr
, struct got_worktree
*worktree
)
2344 uint32_t uuid_status
;
2346 uuid_to_string(&worktree
->uuid
, uuidstr
, &uuid_status
);
2347 if (uuid_status
!= uuid_s_ok
) {
2349 return got_error_uuid(uuid_status
, "uuid_to_string");
2355 static const struct got_error
*
2356 get_ref_name(char **refname
, struct got_worktree
*worktree
, const char *prefix
)
2358 const struct got_error
*err
= NULL
;
2359 char *uuidstr
= NULL
;
2363 err
= got_worktree_get_uuid(&uuidstr
, worktree
);
2367 if (asprintf(refname
, "%s-%s", prefix
, uuidstr
) == -1) {
2368 err
= got_error_from_errno("asprintf");
2375 const struct got_error
*
2376 got_worktree_get_logmsg_ref_name(char **refname
, struct got_worktree
*worktree
,
2379 return get_ref_name(refname
, worktree
, prefix
);
2382 static const struct got_error
*
2383 get_base_ref_name(char **refname
, struct got_worktree
*worktree
)
2385 return get_ref_name(refname
, worktree
, GOT_WORKTREE_BASE_REF_PREFIX
);
2388 static const struct got_error
*
2389 get_rebase_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2391 return get_ref_name(refname
, worktree
,
2392 GOT_WORKTREE_REBASE_TMP_REF_PREFIX
);
2395 static const struct got_error
*
2396 get_newbase_symref_name(char **refname
, struct got_worktree
*worktree
)
2398 return get_ref_name(refname
, worktree
, GOT_WORKTREE_NEWBASE_REF_PREFIX
);
2401 static const struct got_error
*
2402 get_rebase_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2404 return get_ref_name(refname
, worktree
,
2405 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX
);
2408 static const struct got_error
*
2409 get_rebase_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2411 return get_ref_name(refname
, worktree
,
2412 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX
);
2415 static const struct got_error
*
2416 get_histedit_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2418 return get_ref_name(refname
, worktree
,
2419 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX
);
2422 static const struct got_error
*
2423 get_histedit_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2425 return get_ref_name(refname
, worktree
,
2426 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX
);
2429 static const struct got_error
*
2430 get_histedit_base_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2432 return get_ref_name(refname
, worktree
,
2433 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX
);
2436 static const struct got_error
*
2437 get_histedit_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2439 return get_ref_name(refname
, worktree
,
2440 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX
);
2443 const struct got_error
*
2444 got_worktree_get_histedit_script_path(char **path
,
2445 struct got_worktree
*worktree
)
2447 if (asprintf(path
, "%s/%s/%s", worktree
->root_path
,
2448 worktree
->meta_dir
, GOT_WORKTREE_HISTEDIT_SCRIPT
) == -1) {
2450 return got_error_from_errno("asprintf");
2455 static const struct got_error
*
2456 get_merge_branch_ref_name(char **refname
, struct got_worktree
*worktree
)
2458 return get_ref_name(refname
, worktree
,
2459 GOT_WORKTREE_MERGE_BRANCH_REF_PREFIX
);
2462 static const struct got_error
*
2463 get_merge_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2465 return get_ref_name(refname
, worktree
,
2466 GOT_WORKTREE_MERGE_COMMIT_REF_PREFIX
);
2470 * Prevent Git's garbage collector from deleting our base commit by
2471 * setting a reference to our base commit's ID.
2473 static const struct got_error
*
2474 ref_base_commit(struct got_worktree
*worktree
, struct got_repository
*repo
)
2476 const struct got_error
*err
= NULL
;
2477 struct got_reference
*ref
= NULL
;
2480 err
= get_base_ref_name(&refname
, worktree
);
2484 err
= got_ref_alloc(&ref
, refname
, worktree
->base_commit_id
);
2488 err
= got_ref_write(ref
, repo
);
2496 static const struct got_error
*
2497 get_fileindex_path(char **fileindex_path
, struct got_worktree
*worktree
)
2499 const struct got_error
*err
= NULL
;
2501 if (asprintf(fileindex_path
, "%s/%s/%s", worktree
->root_path
,
2502 worktree
->meta_dir
, GOT_WORKTREE_FILE_INDEX
) == -1) {
2503 err
= got_error_from_errno("asprintf");
2504 *fileindex_path
= NULL
;
2510 static const struct got_error
*
2511 open_fileindex(struct got_fileindex
**fileindex
, char **fileindex_path
,
2512 struct got_worktree
*worktree
, enum got_hash_algorithm algo
)
2514 const struct got_error
*err
= NULL
;
2517 *fileindex
= got_fileindex_alloc(algo
);
2518 *fileindex_path
= NULL
;
2519 if (*fileindex
== NULL
)
2520 return got_error_from_errno("got_fileindex_alloc");
2522 err
= get_fileindex_path(fileindex_path
, worktree
);
2526 index
= fopen(*fileindex_path
, "rbe");
2527 if (index
== NULL
) {
2528 if (errno
!= ENOENT
)
2529 err
= got_error_from_errno2("fopen", *fileindex_path
);
2531 err
= got_fileindex_read(*fileindex
, index
, algo
);
2532 if (fclose(index
) == EOF
&& err
== NULL
)
2533 err
= got_error_from_errno("fclose");
2537 free(*fileindex_path
);
2538 *fileindex_path
= NULL
;
2539 got_fileindex_free(*fileindex
);
2545 struct bump_base_commit_id_arg
{
2546 struct got_object_id
*base_commit_id
;
2549 const char *entry_name
;
2550 got_worktree_checkout_cb progress_cb
;
2554 static const struct got_error
*
2555 bump_base_commit_id(void *arg
, struct got_fileindex_entry
*ie
)
2557 const struct got_error
*err
;
2558 struct bump_base_commit_id_arg
*a
= arg
;
2560 if (a
->entry_name
) {
2561 if (strcmp(ie
->path
, a
->path
) != 0)
2563 } else if (!got_path_is_child(ie
->path
, a
->path
, a
->path_len
))
2566 if (got_fileindex_entry_was_skipped(ie
))
2569 if (got_object_id_cmp(&ie
->commit
, a
->base_commit_id
) == 0)
2572 if (a
->progress_cb
) {
2573 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_BUMP_BASE
,
2578 memcpy(&ie
->commit
, a
->base_commit_id
, sizeof(ie
->commit
));
2582 /* Bump base commit ID of all files within an updated part of the work tree. */
2583 static const struct got_error
*
2584 bump_base_commit_id_everywhere(struct got_worktree
*worktree
,
2585 struct got_fileindex
*fileindex
,
2586 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2588 struct bump_base_commit_id_arg bbc_arg
;
2590 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2591 bbc_arg
.entry_name
= NULL
;
2593 bbc_arg
.path_len
= 0;
2594 bbc_arg
.progress_cb
= progress_cb
;
2595 bbc_arg
.progress_arg
= progress_arg
;
2597 return got_fileindex_for_each_entry_safe(fileindex
,
2598 bump_base_commit_id
, &bbc_arg
);
2601 static const struct got_error
*
2602 sync_fileindex(struct got_fileindex
*fileindex
, const char *fileindex_path
)
2604 const struct got_error
*err
= NULL
;
2605 char *new_fileindex_path
= NULL
;
2606 FILE *new_index
= NULL
;
2607 struct timespec timeout
;
2609 err
= got_opentemp_named(&new_fileindex_path
, &new_index
,
2610 fileindex_path
, "");
2614 err
= got_fileindex_write(fileindex
, new_index
);
2618 if (rename(new_fileindex_path
, fileindex_path
) != 0) {
2619 err
= got_error_from_errno3("rename", new_fileindex_path
,
2621 unlink(new_fileindex_path
);
2625 * Sleep for a short amount of time to ensure that files modified after
2626 * this program exits have a different time stamp from the one which
2627 * was recorded in the file index.
2630 timeout
.tv_nsec
= 1;
2631 nanosleep(&timeout
, NULL
);
2635 free(new_fileindex_path
);
2639 static const struct got_error
*
2640 find_tree_entry_for_checkout(int *entry_type
, char **tree_relpath
,
2641 struct got_object_id
**tree_id
, const char *wt_relpath
,
2642 struct got_commit_object
*base_commit
, struct got_worktree
*worktree
,
2643 struct got_repository
*repo
)
2645 const struct got_error
*err
= NULL
;
2646 struct got_object_id
*id
= NULL
;
2647 char *in_repo_path
= NULL
;
2648 int is_root_wt
= got_path_is_root_dir(worktree
->path_prefix
);
2650 *entry_type
= GOT_OBJ_TYPE_ANY
;
2651 *tree_relpath
= NULL
;
2654 if (wt_relpath
[0] == '\0') {
2655 /* Check out all files within the work tree. */
2656 *entry_type
= GOT_OBJ_TYPE_TREE
;
2657 *tree_relpath
= strdup("");
2658 if (*tree_relpath
== NULL
) {
2659 err
= got_error_from_errno("strdup");
2662 err
= got_object_id_by_path(tree_id
, repo
, base_commit
,
2663 worktree
->path_prefix
);
2669 /* Check out a subset of files in the work tree. */
2671 if (asprintf(&in_repo_path
, "%s%s%s", worktree
->path_prefix
,
2672 is_root_wt
? "" : "/", wt_relpath
) == -1) {
2673 err
= got_error_from_errno("asprintf");
2677 err
= got_object_id_by_path(&id
, repo
, base_commit
, in_repo_path
);
2682 in_repo_path
= NULL
;
2684 err
= got_object_get_type(entry_type
, repo
, id
);
2688 if (*entry_type
== GOT_OBJ_TYPE_BLOB
) {
2689 /* Check out a single file. */
2690 if (strchr(wt_relpath
, '/') == NULL
) {
2691 /* Check out a single file in work tree's root dir. */
2692 in_repo_path
= strdup(worktree
->path_prefix
);
2693 if (in_repo_path
== NULL
) {
2694 err
= got_error_from_errno("strdup");
2697 *tree_relpath
= strdup("");
2698 if (*tree_relpath
== NULL
) {
2699 err
= got_error_from_errno("strdup");
2703 /* Check out a single file in a subdirectory. */
2704 err
= got_path_dirname(tree_relpath
, wt_relpath
);
2707 if (asprintf(&in_repo_path
, "%s%s%s",
2708 worktree
->path_prefix
, is_root_wt
? "" : "/",
2709 *tree_relpath
) == -1) {
2710 err
= got_error_from_errno("asprintf");
2714 err
= got_object_id_by_path(tree_id
, repo
,
2715 base_commit
, in_repo_path
);
2717 /* Check out all files within a subdirectory. */
2718 *tree_id
= got_object_id_dup(id
);
2719 if (*tree_id
== NULL
) {
2720 err
= got_error_from_errno("got_object_id_dup");
2723 *tree_relpath
= strdup(wt_relpath
);
2724 if (*tree_relpath
== NULL
) {
2725 err
= got_error_from_errno("strdup");
2733 *entry_type
= GOT_OBJ_TYPE_ANY
;
2734 free(*tree_relpath
);
2735 *tree_relpath
= NULL
;
2742 static const struct got_error
*
2743 checkout_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2744 const char *relpath
, struct got_object_id
*tree_id
, const char *entry_name
,
2745 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
2746 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
2748 const struct got_error
*err
= NULL
;
2749 struct got_commit_object
*commit
= NULL
;
2750 struct got_tree_object
*tree
= NULL
;
2751 struct got_fileindex_diff_tree_cb diff_cb
;
2752 struct diff_cb_arg arg
;
2754 err
= ref_base_commit(worktree
, repo
);
2756 if (!(err
->code
== GOT_ERR_ERRNO
&&
2757 (errno
== EACCES
|| errno
== EROFS
)))
2759 err
= (*progress_cb
)(progress_arg
,
2760 GOT_STATUS_BASE_REF_ERR
, worktree
->root_path
);
2765 err
= got_object_open_as_commit(&commit
, repo
,
2766 worktree
->base_commit_id
);
2770 err
= got_object_open_as_tree(&tree
, repo
, tree_id
);
2775 got_object_tree_find_entry(tree
, entry_name
) == NULL
) {
2776 err
= got_error_path(entry_name
, GOT_ERR_NO_TREE_ENTRY
);
2780 diff_cb
.diff_old_new
= diff_old_new
;
2781 diff_cb
.diff_old
= diff_old
;
2782 diff_cb
.diff_new
= diff_new
;
2783 arg
.fileindex
= fileindex
;
2784 arg
.worktree
= worktree
;
2786 arg
.progress_cb
= progress_cb
;
2787 arg
.progress_arg
= progress_arg
;
2788 arg
.cancel_cb
= cancel_cb
;
2789 arg
.cancel_arg
= cancel_arg
;
2790 err
= got_fileindex_diff_tree(fileindex
, tree
, relpath
,
2791 entry_name
, repo
, &diff_cb
, &arg
);
2794 got_object_tree_close(tree
);
2796 got_object_commit_close(commit
);
2800 const struct got_error
*
2801 got_worktree_checkout_files(struct got_worktree
*worktree
,
2802 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
2803 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
2804 got_cancel_cb cancel_cb
, void *cancel_arg
)
2806 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
2807 struct got_commit_object
*commit
= NULL
;
2808 struct got_tree_object
*tree
= NULL
;
2809 struct got_fileindex
*fileindex
= NULL
;
2810 char *fileindex_path
= NULL
;
2811 struct got_pathlist_entry
*pe
;
2812 struct tree_path_data
{
2813 STAILQ_ENTRY(tree_path_data
) entry
;
2814 struct got_object_id
*tree_id
;
2819 STAILQ_HEAD(tree_paths
, tree_path_data
) tree_paths
;
2821 STAILQ_INIT(&tree_paths
);
2823 err
= lock_worktree(worktree
, LOCK_EX
);
2827 err
= got_object_open_as_commit(&commit
, repo
,
2828 worktree
->base_commit_id
);
2832 /* Map all specified paths to in-repository trees. */
2833 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
2834 tpd
= malloc(sizeof(*tpd
));
2836 err
= got_error_from_errno("malloc");
2840 err
= find_tree_entry_for_checkout(&tpd
->entry_type
,
2841 &tpd
->relpath
, &tpd
->tree_id
, pe
->path
, commit
,
2848 if (tpd
->entry_type
== GOT_OBJ_TYPE_BLOB
) {
2849 err
= got_path_basename(&tpd
->entry_name
, pe
->path
);
2857 tpd
->entry_name
= NULL
;
2859 STAILQ_INSERT_TAIL(&tree_paths
, tpd
, entry
);
2863 * Read the file index.
2864 * Checking out files is supposed to be an idempotent operation.
2865 * If the on-disk file index is incomplete we will try to complete it.
2867 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
2868 got_repo_get_object_format(repo
));
2872 tpd
= STAILQ_FIRST(&tree_paths
);
2873 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
2874 struct bump_base_commit_id_arg bbc_arg
;
2876 err
= checkout_files(worktree
, fileindex
, tpd
->relpath
,
2877 tpd
->tree_id
, tpd
->entry_name
, repo
,
2878 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
2882 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2883 bbc_arg
.entry_name
= tpd
->entry_name
;
2884 bbc_arg
.path
= pe
->path
;
2885 bbc_arg
.path_len
= pe
->path_len
;
2886 bbc_arg
.progress_cb
= progress_cb
;
2887 bbc_arg
.progress_arg
= progress_arg
;
2888 err
= got_fileindex_for_each_entry_safe(fileindex
,
2889 bump_base_commit_id
, &bbc_arg
);
2893 tpd
= STAILQ_NEXT(tpd
, entry
);
2895 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
2896 if (sync_err
&& err
== NULL
)
2899 free(fileindex_path
);
2901 got_object_tree_close(tree
);
2903 got_object_commit_close(commit
);
2905 got_fileindex_free(fileindex
);
2906 while (!STAILQ_EMPTY(&tree_paths
)) {
2907 tpd
= STAILQ_FIRST(&tree_paths
);
2908 STAILQ_REMOVE_HEAD(&tree_paths
, entry
);
2913 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
2914 if (unlockerr
&& err
== NULL
)
2919 static const struct got_error
*
2920 add_file(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2921 struct got_fileindex_entry
*ie
, const char *ondisk_path
,
2922 const char *path2
, struct got_blob_object
*blob2
, mode_t mode2
,
2923 int restoring_missing_file
, int reverting_versioned_file
,
2924 int path_is_unversioned
, int allow_bad_symlinks
,
2925 struct got_repository
*repo
,
2926 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2928 const struct got_error
*err
= NULL
;
2929 int is_bad_symlink
= 0;
2931 if (S_ISLNK(mode2
)) {
2932 err
= install_symlink(&is_bad_symlink
,
2933 worktree
, ondisk_path
, path2
, blob2
,
2934 restoring_missing_file
,
2935 reverting_versioned_file
,
2936 path_is_unversioned
, allow_bad_symlinks
,
2937 repo
, progress_cb
, progress_arg
);
2939 err
= install_blob(worktree
, ondisk_path
, path2
,
2940 mode2
, GOT_DEFAULT_FILE_MODE
, blob2
,
2941 restoring_missing_file
, reverting_versioned_file
, 0,
2942 path_is_unversioned
, NULL
, repo
,
2943 progress_cb
, progress_arg
);
2948 /* Adding an unversioned file. */
2949 err
= got_fileindex_entry_alloc(&ie
, path2
);
2952 err
= got_fileindex_entry_update(ie
,
2953 worktree
->root_fd
, path2
, NULL
, NULL
, 1);
2955 got_fileindex_entry_free(ie
);
2958 err
= got_fileindex_entry_add(fileindex
, ie
);
2960 got_fileindex_entry_free(ie
);
2964 /* Re-adding a locally deleted file. */
2965 err
= got_fileindex_entry_update(ie
,
2966 worktree
->root_fd
, path2
, &ie
->blob
,
2967 worktree
->base_commit_id
, 0);
2972 if (is_bad_symlink
) {
2973 got_fileindex_entry_filetype_set(ie
,
2974 GOT_FILEIDX_MODE_BAD_SYMLINK
);
2980 struct merge_file_cb_arg
{
2981 struct got_worktree
*worktree
;
2982 struct got_fileindex
*fileindex
;
2983 got_worktree_checkout_cb progress_cb
;
2985 got_cancel_cb cancel_cb
;
2987 const char *label_orig
;
2988 struct got_object_id
*commit_id2
;
2989 int allow_bad_symlinks
;
2992 static const struct got_error
*
2993 merge_file_cb(void *arg
, struct got_blob_object
*blob1
,
2994 struct got_blob_object
*blob2
, FILE *f1
, FILE *f2
,
2995 struct got_object_id
*id1
, struct got_object_id
*id2
,
2996 const char *path1
, const char *path2
,
2997 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
2999 static const struct got_error
*err
= NULL
;
3000 struct merge_file_cb_arg
*a
= arg
;
3001 struct got_fileindex_entry
*ie
;
3002 char *ondisk_path
= NULL
;
3004 unsigned char status
;
3005 int local_changes_subsumed
;
3006 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
3007 char *id_str
= NULL
, *label_deriv2
= NULL
;
3008 struct got_object_id
*id
= NULL
;
3010 if (blob1
&& blob2
) {
3011 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
3014 return (*a
->progress_cb
)(a
->progress_arg
,
3015 GOT_STATUS_MISSING
, path2
);
3017 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3019 return got_error_from_errno("asprintf");
3021 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
3026 if (status
== GOT_STATUS_DELETE
) {
3027 err
= (*a
->progress_cb
)(a
->progress_arg
,
3028 GOT_STATUS_MERGE
, path2
);
3031 if (status
!= GOT_STATUS_NO_CHANGE
&&
3032 status
!= GOT_STATUS_MODIFY
&&
3033 status
!= GOT_STATUS_CONFLICT
&&
3034 status
!= GOT_STATUS_ADD
) {
3035 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path2
);
3039 if (S_ISLNK(mode1
) && S_ISLNK(mode2
)) {
3041 err
= got_object_blob_read_to_str(&link_target2
, blob2
);
3044 err
= merge_symlink(a
->worktree
, blob1
, ondisk_path
,
3045 path2
, a
->label_orig
, link_target2
, a
->commit_id2
,
3046 repo
, a
->progress_cb
, a
->progress_arg
);
3051 f_orig
= got_opentemp();
3052 if (f_orig
== NULL
) {
3053 err
= got_error_from_errno("got_opentemp");
3056 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
3061 f_deriv2
= got_opentemp();
3062 if (f_deriv2
== NULL
)
3064 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
3069 fd
= open(ondisk_path
,
3070 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
3072 err
= got_error_from_errno2("open",
3076 f_deriv
= fdopen(fd
, "r");
3077 if (f_deriv
== NULL
) {
3078 err
= got_error_from_errno2("fdopen",
3083 err
= got_object_id_str(&id_str
, a
->commit_id2
);
3086 if (asprintf(&label_deriv2
, "%s: commit %s",
3087 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
3088 err
= got_error_from_errno("asprintf");
3091 err
= merge_file(&local_changes_subsumed
, a
->worktree
,
3092 f_orig
, f_deriv
, f_deriv2
, ondisk_path
, path2
,
3093 mode2
, a
->label_orig
, NULL
, label_deriv2
,
3094 GOT_DIFF_ALGORITHM_PATIENCE
, repo
,
3095 a
->progress_cb
, a
->progress_arg
);
3098 ie
= got_fileindex_entry_get(a
->fileindex
, path1
,
3101 return (*a
->progress_cb
)(a
->progress_arg
,
3102 GOT_STATUS_MISSING
, path1
);
3104 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3106 return got_error_from_errno("asprintf");
3108 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
3114 case GOT_STATUS_NO_CHANGE
:
3115 err
= (*a
->progress_cb
)(a
->progress_arg
,
3116 GOT_STATUS_DELETE
, path1
);
3119 err
= remove_ondisk_file(a
->worktree
->root_path
, path1
);
3123 got_fileindex_entry_mark_deleted_from_disk(ie
);
3125 case GOT_STATUS_DELETE
:
3126 case GOT_STATUS_MISSING
:
3127 err
= (*a
->progress_cb
)(a
->progress_arg
,
3128 GOT_STATUS_DELETE
, path1
);
3132 got_fileindex_entry_mark_deleted_from_disk(ie
);
3134 case GOT_STATUS_MODIFY
: {
3139 * Delete the file only if its content already
3140 * exists in the repository.
3142 err
= got_object_blob_file_create(&id
, &blob1_f
,
3143 &blob1_size
, path1
, repo
);
3146 if (fclose(blob1_f
) == EOF
) {
3147 err
= got_error_from_errno("fclose");
3151 /* Implied existence check. */
3152 err
= got_object_get_type(&obj_type
, repo
, id
);
3154 if (err
->code
!= GOT_ERR_NO_OBJ
)
3156 err
= (*a
->progress_cb
)(a
->progress_arg
,
3157 GOT_STATUS_CANNOT_DELETE
, path1
);
3159 } else if (obj_type
!= GOT_OBJ_TYPE_BLOB
) {
3160 err
= (*a
->progress_cb
)(a
->progress_arg
,
3161 GOT_STATUS_CANNOT_DELETE
, path1
);
3164 err
= (*a
->progress_cb
)(a
->progress_arg
,
3165 GOT_STATUS_DELETE
, path1
);
3168 err
= remove_ondisk_file(a
->worktree
->root_path
,
3173 got_fileindex_entry_mark_deleted_from_disk(ie
);
3176 case GOT_STATUS_ADD
: {
3180 * Delete the file only if its content already
3181 * exists in the repository.
3183 err
= got_object_blob_file_create(&id
, &blob1_f
,
3184 &blob1_size
, path1
, repo
);
3187 if (fclose(blob1_f
) == EOF
) {
3188 err
= got_error_from_errno("fclose");
3191 if (got_object_id_cmp(id
, id1
) == 0) {
3192 err
= (*a
->progress_cb
)(a
->progress_arg
,
3193 GOT_STATUS_DELETE
, path1
);
3196 err
= remove_ondisk_file(a
->worktree
->root_path
,
3201 got_fileindex_entry_remove(a
->fileindex
,
3204 err
= (*a
->progress_cb
)(a
->progress_arg
,
3205 GOT_STATUS_CANNOT_DELETE
, path1
);
3211 case GOT_STATUS_CONFLICT
:
3212 err
= (*a
->progress_cb
)(a
->progress_arg
,
3213 GOT_STATUS_CANNOT_DELETE
, path1
);
3217 case GOT_STATUS_OBSTRUCTED
:
3218 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path1
);
3226 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3228 return got_error_from_errno("asprintf");
3229 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
3232 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
3236 if (status
!= GOT_STATUS_NO_CHANGE
&&
3237 status
!= GOT_STATUS_MODIFY
&&
3238 status
!= GOT_STATUS_CONFLICT
&&
3239 status
!= GOT_STATUS_ADD
&&
3240 status
!= GOT_STATUS_DELETE
) {
3241 err
= (*a
->progress_cb
)(a
->progress_arg
,
3245 if (S_ISLNK(mode2
) && S_ISLNK(sb
.st_mode
)) {
3247 err
= got_object_blob_read_to_str(&link_target2
,
3251 err
= merge_symlink(a
->worktree
, NULL
,
3252 ondisk_path
, path2
, a
->label_orig
,
3253 link_target2
, a
->commit_id2
, repo
,
3254 a
->progress_cb
, a
->progress_arg
);
3256 } else if (S_ISREG(sb
.st_mode
)) {
3257 err
= merge_blob(&local_changes_subsumed
,
3258 a
->worktree
, NULL
, ondisk_path
, path2
,
3259 sb
.st_mode
, a
->label_orig
, blob2
,
3260 a
->commit_id2
, repo
, a
->progress_cb
,
3262 } else if (status
!= GOT_STATUS_DELETE
) {
3263 err
= got_error_path(ondisk_path
,
3264 GOT_ERR_FILE_OBSTRUCTED
);
3268 if (status
== GOT_STATUS_DELETE
) {
3269 /* Re-add file with content from new blob. */
3270 err
= add_file(a
->worktree
, a
->fileindex
, ie
,
3271 ondisk_path
, path2
, blob2
, mode2
,
3272 0, 0, 0, a
->allow_bad_symlinks
,
3273 repo
, a
->progress_cb
, a
->progress_arg
);
3278 err
= add_file(a
->worktree
, a
->fileindex
, NULL
,
3279 ondisk_path
, path2
, blob2
, mode2
,
3280 0, 0, 1, a
->allow_bad_symlinks
,
3281 repo
, a
->progress_cb
, a
->progress_arg
);
3287 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
3288 err
= got_error_from_errno("fclose");
3289 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
3290 err
= got_error_from_errno("fclose");
3291 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
3292 err
= got_error_from_errno("fclose");
3300 struct check_mixed_commits_args
{
3301 struct got_worktree
*worktree
;
3302 got_cancel_cb cancel_cb
;
3306 static const struct got_error
*
3307 check_mixed_commits(void *arg
, struct got_fileindex_entry
*ie
)
3309 const struct got_error
*err
= NULL
;
3310 struct check_mixed_commits_args
*a
= arg
;
3313 err
= a
->cancel_cb(a
->cancel_arg
);
3318 /* Reject merges into a work tree with mixed base commits. */
3319 if (got_fileindex_entry_has_commit(ie
) &&
3320 got_object_id_cmp(&ie
->commit
, a
->worktree
->base_commit_id
) != 0)
3321 return got_error(GOT_ERR_MIXED_COMMITS
);
3326 const struct got_error
*
3327 got_worktree_get_state(char *state
, struct got_repository
*repo
,
3328 struct got_worktree
*worktree
,
3329 got_cancel_cb cancel_cb
, void *cancel_arg
)
3331 const struct got_error
*err
;
3332 struct got_object_id
*base_id
, *head_id
= NULL
;
3333 struct got_reference
*head_ref
;
3334 struct got_fileindex
*fileindex
= NULL
;
3335 char *fileindex_path
= NULL
;
3336 struct check_mixed_commits_args cma
;
3338 if (worktree
== NULL
)
3339 return got_error(GOT_ERR_NOT_WORKTREE
);
3341 err
= got_ref_open(&head_ref
, repo
,
3342 got_worktree_get_head_ref_name(worktree
), 0);
3346 err
= got_ref_resolve(&head_id
, repo
, head_ref
);
3350 *state
= GOT_WORKTREE_STATE_UNKNOWN
;
3351 base_id
= got_worktree_get_base_commit_id(worktree
);
3353 cma
.worktree
= worktree
;
3354 cma
.cancel_cb
= cancel_cb
;
3355 cma
.cancel_arg
= cancel_arg
;
3357 if (got_object_id_cmp(base_id
, head_id
) == 0) {
3358 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
3359 got_repo_get_object_format(repo
));
3363 err
= got_fileindex_for_each_entry_safe(fileindex
,
3364 check_mixed_commits
, &cma
);
3366 *state
= GOT_WORKTREE_STATE_UPTODATE
;
3367 else if (err
->code
== GOT_ERR_MIXED_COMMITS
) {
3368 *state
= GOT_WORKTREE_STATE_OUTOFDATE
;
3372 *state
= GOT_WORKTREE_STATE_OUTOFDATE
;
3376 free(fileindex_path
);
3377 got_ref_close(head_ref
);
3378 if (fileindex
!= NULL
)
3379 got_fileindex_free(fileindex
);
3383 struct check_merge_conflicts_arg
{
3384 struct got_worktree
*worktree
;
3385 struct got_fileindex
*fileindex
;
3386 struct got_repository
*repo
;
3389 static const struct got_error
*
3390 check_merge_conflicts(void *arg
, struct got_blob_object
*blob1
,
3391 struct got_blob_object
*blob2
, FILE *f1
, FILE *f2
,
3392 struct got_object_id
*id1
, struct got_object_id
*id2
,
3393 const char *path1
, const char *path2
,
3394 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
3396 const struct got_error
*err
= NULL
;
3397 struct check_merge_conflicts_arg
*a
= arg
;
3398 unsigned char status
;
3400 struct got_fileindex_entry
*ie
;
3401 const char *path
= path2
? path2
: path1
;
3402 struct got_object_id
*id
= id2
? id2
: id1
;
3408 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
3412 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
3414 return got_error_from_errno("asprintf");
3416 /* Reject merges into a work tree with conflicted files. */
3417 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
3421 if (status
== GOT_STATUS_CONFLICT
)
3422 return got_error(GOT_ERR_CONFLICTS
);
3427 static const struct got_error
*
3428 merge_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
3429 const char *fileindex_path
, struct got_object_id
*commit_id1
,
3430 struct got_object_id
*commit_id2
, struct got_repository
*repo
,
3431 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
3432 got_cancel_cb cancel_cb
, void *cancel_arg
)
3434 const struct got_error
*err
= NULL
, *sync_err
;
3435 struct got_object_id
*tree_id1
= NULL
, *tree_id2
= NULL
;
3436 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
3437 struct got_commit_object
*commit1
= NULL
, *commit2
= NULL
;
3438 struct check_merge_conflicts_arg cmc_arg
;
3439 struct merge_file_cb_arg arg
;
3440 char *label_orig
= NULL
;
3441 FILE *f1
= NULL
, *f2
= NULL
;
3442 int fd1
= -1, fd2
= -1;
3445 err
= got_object_open_as_commit(&commit1
, repo
, commit_id1
);
3448 err
= got_object_id_by_path(&tree_id1
, repo
, commit1
,
3449 worktree
->path_prefix
);
3450 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
3456 err
= got_object_open_as_tree(&tree1
, repo
, tree_id1
);
3460 err
= got_object_id_str(&id_str
, commit_id1
);
3464 if (asprintf(&label_orig
, "%s: commit %s",
3465 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
3466 err
= got_error_from_errno("asprintf");
3472 f1
= got_opentemp();
3474 err
= got_error_from_errno("got_opentemp");
3479 err
= got_object_open_as_commit(&commit2
, repo
, commit_id2
);
3483 err
= got_object_id_by_path(&tree_id2
, repo
, commit2
,
3484 worktree
->path_prefix
);
3488 err
= got_object_open_as_tree(&tree2
, repo
, tree_id2
);
3492 f2
= got_opentemp();
3494 err
= got_error_from_errno("got_opentemp");
3498 fd1
= got_opentempfd();
3500 err
= got_error_from_errno("got_opentempfd");
3504 fd2
= got_opentempfd();
3506 err
= got_error_from_errno("got_opentempfd");
3510 cmc_arg
.worktree
= worktree
;
3511 cmc_arg
.fileindex
= fileindex
;
3512 cmc_arg
.repo
= repo
;
3513 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
3514 check_merge_conflicts
, &cmc_arg
, 0);
3518 arg
.worktree
= worktree
;
3519 arg
.fileindex
= fileindex
;
3520 arg
.progress_cb
= progress_cb
;
3521 arg
.progress_arg
= progress_arg
;
3522 arg
.cancel_cb
= cancel_cb
;
3523 arg
.cancel_arg
= cancel_arg
;
3524 arg
.label_orig
= label_orig
;
3525 arg
.commit_id2
= commit_id2
;
3526 arg
.allow_bad_symlinks
= 1; /* preserve bad symlinks across merges */
3527 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
3528 merge_file_cb
, &arg
, 1);
3529 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
3530 if (sync_err
&& err
== NULL
)
3534 got_object_commit_close(commit1
);
3536 got_object_commit_close(commit2
);
3538 got_object_tree_close(tree1
);
3540 got_object_tree_close(tree2
);
3541 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
3542 err
= got_error_from_errno("fclose");
3543 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
3544 err
= got_error_from_errno("fclose");
3545 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
3546 err
= got_error_from_errno("close");
3547 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
3548 err
= got_error_from_errno("close");
3553 const struct got_error
*
3554 got_worktree_merge_files(struct got_worktree
*worktree
,
3555 struct got_object_id
*commit_id1
, struct got_object_id
*commit_id2
,
3556 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
3557 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
3559 const struct got_error
*err
, *unlockerr
;
3560 char *fileindex_path
= NULL
;
3561 struct got_fileindex
*fileindex
= NULL
;
3562 struct check_mixed_commits_args cma
;
3564 err
= lock_worktree(worktree
, LOCK_EX
);
3568 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
3569 got_repo_get_object_format(repo
));
3573 cma
.worktree
= worktree
;
3574 cma
.cancel_cb
= cancel_cb
;
3575 cma
.cancel_arg
= cancel_arg
;
3577 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
3582 err
= merge_files(worktree
, fileindex
, fileindex_path
, commit_id1
,
3583 commit_id2
, repo
, progress_cb
, progress_arg
,
3584 cancel_cb
, cancel_arg
);
3587 got_fileindex_free(fileindex
);
3588 free(fileindex_path
);
3589 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
3590 if (unlockerr
&& err
== NULL
)
3595 struct diff_dir_cb_arg
{
3596 struct got_fileindex
*fileindex
;
3597 struct got_worktree
*worktree
;
3598 const char *status_path
;
3599 size_t status_path_len
;
3600 struct got_repository
*repo
;
3601 got_worktree_status_cb status_cb
;
3603 got_cancel_cb cancel_cb
;
3605 /* A pathlist containing per-directory pathlists of ignore patterns. */
3606 struct got_pathlist_head
*ignores
;
3607 int report_unchanged
;
3611 static const struct got_error
*
3612 report_file_status(struct got_fileindex_entry
*ie
, const char *abspath
,
3613 int dirfd
, const char *de_name
,
3614 got_worktree_status_cb status_cb
, void *status_arg
,
3615 struct got_repository
*repo
, int report_unchanged
)
3617 const struct got_error
*err
= NULL
;
3618 unsigned char status
= GOT_STATUS_NO_CHANGE
;
3619 unsigned char staged_status
;
3621 struct got_object_id blob_id
, commit_id
, staged_blob_id
;
3622 struct got_object_id
*blob_idp
= NULL
, *commit_idp
= NULL
;
3623 struct got_object_id
*staged_blob_idp
= NULL
;
3625 staged_status
= get_staged_status(ie
);
3626 err
= get_file_status(&status
, &sb
, ie
, abspath
, dirfd
, de_name
, repo
);
3630 if (status
== GOT_STATUS_NO_CHANGE
&&
3631 staged_status
== GOT_STATUS_NO_CHANGE
&& !report_unchanged
)
3634 if (got_fileindex_entry_has_blob(ie
))
3635 blob_idp
= got_fileindex_entry_get_blob_id(&blob_id
, ie
);
3636 if (got_fileindex_entry_has_commit(ie
))
3637 commit_idp
= got_fileindex_entry_get_commit_id(&commit_id
, ie
);
3638 if (staged_status
== GOT_STATUS_ADD
||
3639 staged_status
== GOT_STATUS_MODIFY
) {
3640 staged_blob_idp
= got_fileindex_entry_get_staged_blob_id(
3641 &staged_blob_id
, ie
);
3644 return (*status_cb
)(status_arg
, status
, staged_status
,
3645 ie
->path
, blob_idp
, staged_blob_idp
, commit_idp
, dirfd
, de_name
);
3648 static const struct got_error
*
3649 status_old_new(void *arg
, struct got_fileindex_entry
*ie
,
3650 struct dirent
*de
, const char *parent_path
, int dirfd
)
3652 const struct got_error
*err
= NULL
;
3653 struct diff_dir_cb_arg
*a
= arg
;
3657 err
= a
->cancel_cb(a
->cancel_arg
);
3662 if (got_path_cmp(parent_path
, a
->status_path
,
3663 strlen(parent_path
), a
->status_path_len
) != 0 &&
3664 !got_path_is_child(parent_path
, a
->status_path
, a
->status_path_len
))
3667 if (parent_path
[0]) {
3668 if (asprintf(&abspath
, "%s/%s/%s", a
->worktree
->root_path
,
3669 parent_path
, de
->d_name
) == -1)
3670 return got_error_from_errno("asprintf");
3672 if (asprintf(&abspath
, "%s/%s", a
->worktree
->root_path
,
3674 return got_error_from_errno("asprintf");
3677 err
= report_file_status(ie
, abspath
, dirfd
, de
->d_name
,
3678 a
->status_cb
, a
->status_arg
, a
->repo
, a
->report_unchanged
);
3683 static const struct got_error
*
3684 status_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
3686 const struct got_error
*err
;
3687 struct diff_dir_cb_arg
*a
= arg
;
3688 struct got_object_id blob_id
, commit_id
;
3689 unsigned char status
;
3692 err
= a
->cancel_cb(a
->cancel_arg
);
3697 if (!got_path_is_child(ie
->path
, a
->status_path
, a
->status_path_len
))
3700 got_fileindex_entry_get_blob_id(&blob_id
, ie
);
3701 got_fileindex_entry_get_commit_id(&commit_id
, ie
);
3702 if (got_fileindex_entry_has_file_on_disk(ie
))
3703 status
= GOT_STATUS_MISSING
;
3705 status
= GOT_STATUS_DELETE
;
3706 return (*a
->status_cb
)(a
->status_arg
, status
, get_staged_status(ie
),
3707 ie
->path
, &blob_id
, NULL
, &commit_id
, -1, NULL
);
3711 free_ignores(struct got_pathlist_head
*ignores
)
3713 struct got_pathlist_entry
*pe
;
3715 RB_FOREACH(pe
, got_pathlist_head
, ignores
) {
3716 struct got_pathlist_head
*ignorelist
= pe
->data
;
3718 got_pathlist_free(ignorelist
, GOT_PATHLIST_FREE_PATH
);
3720 got_pathlist_free(ignores
, GOT_PATHLIST_FREE_ALL
);
3723 static const struct got_error
*
3724 read_ignores(struct got_pathlist_head
*ignores
, const char *path
, FILE *f
)
3726 const struct got_error
*err
= NULL
;
3727 struct got_pathlist_entry
*pe
= NULL
;
3728 struct got_pathlist_head
*ignorelist
;
3729 char *line
= NULL
, *pattern
, *dirpath
= NULL
;
3730 size_t linesize
= 0;
3733 ignorelist
= calloc(1, sizeof(*ignorelist
));
3734 if (ignorelist
== NULL
)
3735 return got_error_from_errno("calloc");
3736 RB_INIT(ignorelist
);
3738 while ((linelen
= getline(&line
, &linesize
, f
)) != -1) {
3739 if (linelen
> 0 && line
[linelen
- 1] == '\n')
3740 line
[linelen
- 1] = '\0';
3742 /* Skip blank lines. */
3743 if (line
[0] == '\0')
3746 /* Git's ignores may contain comments. */
3750 /* Git's negated patterns are not (yet?) supported. */
3754 if (asprintf(&pattern
, "%s%s%s", path
, path
[0] ? "/" : "",
3756 err
= got_error_from_errno("asprintf");
3759 err
= got_pathlist_insert(NULL
, ignorelist
, pattern
, NULL
);
3764 err
= got_error_from_errno("getline");
3768 dirpath
= strdup(path
);
3769 if (dirpath
== NULL
) {
3770 err
= got_error_from_errno("strdup");
3773 err
= got_pathlist_insert(&pe
, ignores
, dirpath
, ignorelist
);
3776 if (err
|| pe
== NULL
) {
3778 got_pathlist_free(ignorelist
, GOT_PATHLIST_FREE_PATH
);
3785 match_path(const char *pattern
, size_t pattern_len
, const char *path
,
3791 * Trailing slashes signify directories.
3792 * Append a * to make such patterns conform to fnmatch rules.
3794 if (pattern_len
> 0 && pattern
[pattern_len
- 1] == '/') {
3795 if (snprintf(buf
, sizeof(buf
), "%s*", pattern
) >= sizeof(buf
))
3796 return FNM_NOMATCH
; /* XXX */
3798 return fnmatch(buf
, path
, flags
);
3801 return fnmatch(pattern
, path
, flags
);
3805 match_ignores(struct got_pathlist_head
*ignores
, const char *path
)
3807 struct got_pathlist_entry
*pe
;
3809 /* Handle patterns which match in all directories. */
3810 RB_FOREACH(pe
, got_pathlist_head
, ignores
) {
3811 struct got_pathlist_head
*ignorelist
= pe
->data
;
3812 struct got_pathlist_entry
*pi
;
3814 RB_FOREACH(pi
, got_pathlist_head
, ignorelist
) {
3817 if (pi
->path_len
< 3 ||
3818 strncmp(pi
->path
, "**/", 3) != 0)
3822 if (match_path(pi
->path
+ 3,
3823 pi
->path_len
- 3, p
,
3824 FNM_PATHNAME
| FNM_LEADING_DIR
)) {
3825 /* Retry in next directory. */
3826 while (*p
&& *p
!= '/')
3838 * The ignores pathlist contains ignore lists from children before
3839 * parents, so we can find the most specific ignorelist by walking
3840 * ignores backwards.
3842 pe
= RB_MAX(got_pathlist_head
, ignores
);
3844 if (got_path_is_child(path
, pe
->path
, pe
->path_len
)) {
3845 struct got_pathlist_head
*ignorelist
= pe
->data
;
3846 struct got_pathlist_entry
*pi
;
3847 RB_FOREACH(pi
, got_pathlist_head
, ignorelist
) {
3848 int flags
= FNM_LEADING_DIR
;
3849 if (strstr(pi
->path
, "/**/") == NULL
)
3850 flags
|= FNM_PATHNAME
;
3851 if (match_path(pi
->path
, pi
->path_len
,
3857 pe
= RB_PREV(got_pathlist_head
, ignores
, pe
);
3863 static const struct got_error
*
3864 add_ignores(struct got_pathlist_head
*ignores
, const char *root_path
,
3865 const char *path
, int dirfd
, const char *ignores_filename
)
3867 const struct got_error
*err
= NULL
;
3870 FILE *ignoresfile
= NULL
;
3872 if (asprintf(&ignorespath
, "%s/%s%s%s", root_path
, path
,
3873 path
[0] ? "/" : "", ignores_filename
) == -1)
3874 return got_error_from_errno("asprintf");
3877 fd
= openat(dirfd
, ignores_filename
,
3878 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
3880 if (errno
!= ENOENT
&& errno
!= EACCES
)
3881 err
= got_error_from_errno2("openat",
3884 ignoresfile
= fdopen(fd
, "r");
3885 if (ignoresfile
== NULL
)
3886 err
= got_error_from_errno2("fdopen",
3890 err
= read_ignores(ignores
, path
, ignoresfile
);
3894 ignoresfile
= fopen(ignorespath
, "re");
3895 if (ignoresfile
== NULL
) {
3896 if (errno
!= ENOENT
&& errno
!= EACCES
)
3897 err
= got_error_from_errno2("fopen",
3900 err
= read_ignores(ignores
, path
, ignoresfile
);
3903 if (ignoresfile
&& fclose(ignoresfile
) == EOF
&& err
== NULL
)
3904 err
= got_error_from_errno2("fclose", path
);
3905 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3906 err
= got_error_from_errno2("close", path
);
3911 static const struct got_error
*
3912 status_new(int *ignore
, void *arg
, struct dirent
*de
, const char *parent_path
,
3915 const struct got_error
*err
= NULL
;
3916 struct diff_dir_cb_arg
*a
= arg
;
3923 err
= a
->cancel_cb(a
->cancel_arg
);
3928 if (parent_path
[0]) {
3929 if (asprintf(&path
, "%s/%s", parent_path
, de
->d_name
) == -1)
3930 return got_error_from_errno("asprintf");
3935 if (de
->d_type
== DT_DIR
) {
3936 if (!a
->no_ignores
&& ignore
!= NULL
&&
3937 match_ignores(a
->ignores
, path
))
3939 } else if (!match_ignores(a
->ignores
, path
) &&
3940 got_path_is_child(path
, a
->status_path
, a
->status_path_len
))
3941 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_UNVERSIONED
,
3942 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3948 static const struct got_error
*
3949 status_traverse(void *arg
, const char *path
, int dirfd
)
3951 const struct got_error
*err
= NULL
;
3952 struct diff_dir_cb_arg
*a
= arg
;
3957 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
,
3958 path
, dirfd
, ".cvsignore");
3962 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
, path
,
3963 dirfd
, ".gitignore");
3968 static const struct got_error
*
3969 report_single_file_status(const char *path
, const char *ondisk_path
,
3970 struct got_fileindex
*fileindex
, got_worktree_status_cb status_cb
,
3971 void *status_arg
, struct got_repository
*repo
, int report_unchanged
,
3972 struct got_pathlist_head
*ignores
, int no_ignores
)
3974 struct got_fileindex_entry
*ie
;
3977 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
3979 return report_file_status(ie
, ondisk_path
, -1, NULL
,
3980 status_cb
, status_arg
, repo
, report_unchanged
);
3982 if (lstat(ondisk_path
, &sb
) == -1) {
3983 if (errno
!= ENOENT
)
3984 return got_error_from_errno2("lstat", ondisk_path
);
3985 return (*status_cb
)(status_arg
, GOT_STATUS_NONEXISTENT
,
3986 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3989 if (!no_ignores
&& match_ignores(ignores
, path
))
3992 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
3993 return (*status_cb
)(status_arg
, GOT_STATUS_UNVERSIONED
,
3994 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3999 static const struct got_error
*
4000 add_ignores_from_parent_paths(struct got_pathlist_head
*ignores
,
4001 const char *root_path
, const char *path
)
4003 const struct got_error
*err
;
4004 char *parent_path
, *next_parent_path
= NULL
;
4006 err
= add_ignores(ignores
, root_path
, "", -1,
4011 err
= add_ignores(ignores
, root_path
, "", -1,
4016 err
= got_path_dirname(&parent_path
, path
);
4018 if (err
->code
== GOT_ERR_BAD_PATH
)
4019 return NULL
; /* cannot traverse parent */
4023 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
4027 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
4031 err
= got_path_dirname(&next_parent_path
, parent_path
);
4033 if (err
->code
== GOT_ERR_BAD_PATH
)
4034 err
= NULL
; /* traversed everything */
4037 if (got_path_is_root_dir(parent_path
))
4040 parent_path
= next_parent_path
;
4041 next_parent_path
= NULL
;
4045 free(next_parent_path
);
4049 struct find_missing_children_args
{
4050 const char *parent_path
;
4052 struct got_pathlist_head
*children
;
4053 got_cancel_cb cancel_cb
;
4057 static const struct got_error
*
4058 find_missing_children(void *arg
, struct got_fileindex_entry
*ie
)
4060 const struct got_error
*err
= NULL
;
4061 struct find_missing_children_args
*a
= arg
;
4064 err
= a
->cancel_cb(a
->cancel_arg
);
4069 if (got_path_is_child(ie
->path
, a
->parent_path
, a
->parent_len
))
4070 err
= got_pathlist_insert(NULL
, a
->children
, ie
->path
, NULL
);
4075 static const struct got_error
*
4076 report_children(struct got_pathlist_head
*children
,
4077 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
4078 struct got_repository
*repo
, int is_root_dir
, int report_unchanged
,
4079 struct got_pathlist_head
*ignores
, int no_ignores
,
4080 got_worktree_status_cb status_cb
, void *status_arg
,
4081 got_cancel_cb cancel_cb
, void *cancel_arg
)
4083 const struct got_error
*err
= NULL
;
4084 struct got_pathlist_entry
*pe
;
4085 char *ondisk_path
= NULL
;
4087 RB_FOREACH(pe
, got_pathlist_head
, children
) {
4089 err
= cancel_cb(cancel_arg
);
4094 if (asprintf(&ondisk_path
, "%s%s%s", worktree
->root_path
,
4095 !is_root_dir
? "/" : "", pe
->path
) == -1) {
4096 err
= got_error_from_errno("asprintf");
4101 err
= report_single_file_status(pe
->path
, ondisk_path
,
4102 fileindex
, status_cb
, status_arg
, repo
, report_unchanged
,
4103 ignores
, no_ignores
);
4115 static const struct got_error
*
4116 worktree_status(struct got_worktree
*worktree
, const char *path
,
4117 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
4118 got_worktree_status_cb status_cb
, void *status_arg
,
4119 got_cancel_cb cancel_cb
, void *cancel_arg
, int no_ignores
,
4120 int report_unchanged
)
4122 const struct got_error
*err
= NULL
;
4124 struct got_fileindex_diff_dir_cb fdiff_cb
;
4125 struct diff_dir_cb_arg arg
;
4126 char *ondisk_path
= NULL
;
4127 struct got_pathlist_head ignores
, missing_children
;
4128 struct got_fileindex_entry
*ie
;
4131 RB_INIT(&missing_children
);
4133 if (asprintf(&ondisk_path
, "%s%s%s",
4134 worktree
->root_path
, path
[0] ? "/" : "", path
) == -1)
4135 return got_error_from_errno("asprintf");
4137 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
4139 err
= report_single_file_status(path
, ondisk_path
,
4140 fileindex
, status_cb
, status_arg
, repo
,
4141 report_unchanged
, &ignores
, no_ignores
);
4144 struct find_missing_children_args fmca
;
4145 fmca
.parent_path
= path
;
4146 fmca
.parent_len
= strlen(path
);
4147 fmca
.children
= &missing_children
;
4148 fmca
.cancel_cb
= cancel_cb
;
4149 fmca
.cancel_arg
= cancel_arg
;
4150 err
= got_fileindex_for_each_entry_safe(fileindex
,
4151 find_missing_children
, &fmca
);
4156 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_DIRECTORY
| O_CLOEXEC
);
4158 if (errno
!= ENOTDIR
&& errno
!= ENOENT
&& errno
!= EACCES
&&
4159 !got_err_open_nofollow_on_symlink())
4160 err
= got_error_from_errno2("open", ondisk_path
);
4163 err
= add_ignores_from_parent_paths(&ignores
,
4164 worktree
->root_path
, ondisk_path
);
4168 if (RB_EMPTY(&missing_children
)) {
4169 err
= report_single_file_status(path
,
4170 ondisk_path
, fileindex
,
4171 status_cb
, status_arg
, repo
,
4172 report_unchanged
, &ignores
, no_ignores
);
4176 err
= report_children(&missing_children
,
4177 worktree
, fileindex
, repo
,
4178 (path
[0] == '\0'), report_unchanged
,
4179 &ignores
, no_ignores
,
4180 status_cb
, status_arg
,
4181 cancel_cb
, cancel_arg
);
4187 fdiff_cb
.diff_old_new
= status_old_new
;
4188 fdiff_cb
.diff_old
= status_old
;
4189 fdiff_cb
.diff_new
= status_new
;
4190 fdiff_cb
.diff_traverse
= status_traverse
;
4191 arg
.fileindex
= fileindex
;
4192 arg
.worktree
= worktree
;
4193 arg
.status_path
= path
;
4194 arg
.status_path_len
= strlen(path
);
4196 arg
.status_cb
= status_cb
;
4197 arg
.status_arg
= status_arg
;
4198 arg
.cancel_cb
= cancel_cb
;
4199 arg
.cancel_arg
= cancel_arg
;
4200 arg
.report_unchanged
= report_unchanged
;
4201 arg
.no_ignores
= no_ignores
;
4203 err
= add_ignores_from_parent_paths(&ignores
,
4204 worktree
->root_path
, path
);
4208 arg
.ignores
= &ignores
;
4209 err
= got_fileindex_diff_dir(fileindex
, fd
,
4210 worktree
->root_path
, path
, repo
, &fdiff_cb
, &arg
);
4213 free_ignores(&ignores
);
4214 got_pathlist_free(&missing_children
, GOT_PATHLIST_FREE_NONE
);
4215 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
4216 err
= got_error_from_errno("close");
4221 const struct got_error
*
4222 got_worktree_status(struct got_worktree
*worktree
,
4223 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
4224 int no_ignores
, got_worktree_status_cb status_cb
, void *status_arg
,
4225 got_cancel_cb cancel_cb
, void *cancel_arg
)
4227 const struct got_error
*err
= NULL
;
4228 char *fileindex_path
= NULL
;
4229 struct got_fileindex
*fileindex
= NULL
;
4230 struct got_pathlist_entry
*pe
;
4232 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
4233 got_repo_get_object_format(repo
));
4237 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
4238 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4239 status_cb
, status_arg
, cancel_cb
, cancel_arg
,
4244 free(fileindex_path
);
4245 got_fileindex_free(fileindex
);
4249 const struct got_error
*
4250 got_worktree_resolve_path(char **wt_path
, struct got_worktree
*worktree
,
4253 const struct got_error
*err
= NULL
;
4254 char *resolved
= NULL
, *cwd
= NULL
, *path
= NULL
;
4257 char *abspath
= NULL
;
4258 char canonpath
[PATH_MAX
];
4262 cwd
= getcwd(NULL
, 0);
4264 return got_error_from_errno("getcwd");
4266 if (lstat(arg
, &sb
) == -1) {
4267 if (errno
!= ENOENT
) {
4268 err
= got_error_from_errno2("lstat", arg
);
4273 if (S_ISLNK(sb
.st_mode
)) {
4275 * We cannot use realpath(3) with symlinks since we want to
4276 * operate on the symlink itself.
4277 * But we can make the path absolute, assuming it is relative
4278 * to the current working directory, and then canonicalize it.
4280 if (!got_path_is_absolute(arg
)) {
4281 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
4282 err
= got_error_from_errno("asprintf");
4287 err
= got_canonpath(abspath
? abspath
: arg
, canonpath
,
4291 resolved
= strdup(canonpath
);
4292 if (resolved
== NULL
) {
4293 err
= got_error_from_errno("strdup");
4297 resolved
= realpath(arg
, NULL
);
4298 if (resolved
== NULL
) {
4299 if (errno
!= ENOENT
) {
4300 err
= got_error_from_errno2("realpath", arg
);
4303 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
4304 err
= got_error_from_errno("asprintf");
4307 err
= got_canonpath(abspath
, canonpath
,
4311 resolved
= strdup(canonpath
);
4312 if (resolved
== NULL
) {
4313 err
= got_error_from_errno("strdup");
4319 if (strncmp(got_worktree_get_root_path(worktree
), resolved
,
4320 strlen(got_worktree_get_root_path(worktree
)))) {
4321 err
= got_error_path(resolved
, GOT_ERR_BAD_PATH
);
4325 if (strlen(resolved
) > strlen(got_worktree_get_root_path(worktree
))) {
4326 err
= got_path_skip_common_ancestor(&path
,
4327 got_worktree_get_root_path(worktree
), resolved
);
4333 err
= got_error_from_errno("strdup");
4338 /* XXX status walk can't deal with trailing slash! */
4340 while (len
> 0 && path
[len
- 1] == '/') {
4341 path
[len
- 1] = '\0';
4355 struct schedule_addition_args
{
4356 struct got_worktree
*worktree
;
4357 struct got_fileindex
*fileindex
;
4358 got_worktree_checkout_cb progress_cb
;
4360 struct got_repository
*repo
;
4364 add_noop_status(unsigned char status
)
4366 return (status
== GOT_STATUS_ADD
||
4367 status
== GOT_STATUS_MODIFY
||
4368 status
== GOT_STATUS_CONFLICT
||
4369 status
== GOT_STATUS_MODE_CHANGE
||
4370 status
== GOT_STATUS_NO_CHANGE
);
4373 static const struct got_error
*
4374 schedule_addition(void *arg
, unsigned char status
, unsigned char staged_status
,
4375 const char *relpath
, struct got_object_id
*blob_id
,
4376 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
4377 int dirfd
, const char *de_name
)
4379 struct schedule_addition_args
*a
= arg
;
4380 const struct got_error
*err
= NULL
;
4381 struct got_fileindex_entry
*ie
;
4385 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4387 return got_error_from_errno("asprintf");
4389 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4391 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
,
4395 /* Re-adding an existing entry is a no-op. */
4396 if (staged_status
== GOT_STATUS_NO_CHANGE
&&
4397 add_noop_status(status
))
4399 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4404 if (status
!= GOT_STATUS_UNVERSIONED
) {
4405 if (status
== GOT_STATUS_NONEXISTENT
)
4406 err
= got_error_set_errno(ENOENT
, ondisk_path
);
4408 err
= got_error_path(ondisk_path
, GOT_ERR_FILE_STATUS
);
4412 err
= got_fileindex_entry_alloc(&ie
, relpath
);
4415 err
= got_fileindex_entry_update(ie
, a
->worktree
->root_fd
,
4416 relpath
, NULL
, NULL
, 1);
4418 got_fileindex_entry_free(ie
);
4421 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
4423 got_fileindex_entry_free(ie
);
4430 if (staged_status
== GOT_STATUS_NO_CHANGE
&& add_noop_status(status
))
4432 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_ADD
, relpath
);
4435 const struct got_error
*
4436 got_worktree_schedule_add(struct got_worktree
*worktree
,
4437 struct got_pathlist_head
*paths
,
4438 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4439 struct got_repository
*repo
, int no_ignores
)
4441 struct got_fileindex
*fileindex
= NULL
;
4442 char *fileindex_path
= NULL
;
4443 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4444 struct got_pathlist_entry
*pe
;
4445 struct schedule_addition_args saa
;
4447 err
= lock_worktree(worktree
, LOCK_EX
);
4451 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
4452 got_repo_get_object_format(repo
));
4456 saa
.worktree
= worktree
;
4457 saa
.fileindex
= fileindex
;
4458 saa
.progress_cb
= progress_cb
;
4459 saa
.progress_arg
= progress_arg
;
4462 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
4463 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4464 schedule_addition
, &saa
, NULL
, NULL
, no_ignores
, 0);
4468 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4469 if (sync_err
&& err
== NULL
)
4472 free(fileindex_path
);
4474 got_fileindex_free(fileindex
);
4475 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4476 if (unlockerr
&& err
== NULL
)
4481 struct schedule_deletion_args
{
4482 struct got_worktree
*worktree
;
4483 struct got_fileindex
*fileindex
;
4484 got_worktree_delete_cb progress_cb
;
4486 struct got_repository
*repo
;
4487 int delete_local_mods
;
4489 int ignore_missing_paths
;
4490 const char *status_path
;
4491 size_t status_path_len
;
4492 const char *status_codes
;
4495 static const struct got_error
*
4496 schedule_for_deletion(void *arg
, unsigned char status
,
4497 unsigned char staged_status
, const char *relpath
,
4498 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4499 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4501 struct schedule_deletion_args
*a
= arg
;
4502 const struct got_error
*err
= NULL
;
4503 struct got_fileindex_entry
*ie
= NULL
;
4507 if (status
== GOT_STATUS_NONEXISTENT
) {
4508 if (a
->ignore_missing_paths
)
4510 return got_error_set_errno(ENOENT
, relpath
);
4513 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4515 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4517 staged_status
= get_staged_status(ie
);
4518 if (staged_status
!= GOT_STATUS_NO_CHANGE
) {
4519 if (staged_status
== GOT_STATUS_DELETE
)
4521 return got_error_path(relpath
, GOT_ERR_FILE_STAGED
);
4524 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4526 return got_error_from_errno("asprintf");
4528 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
, de_name
,
4533 if (a
->status_codes
) {
4534 size_t ncodes
= strlen(a
->status_codes
);
4536 for (i
= 0; i
< ncodes
; i
++) {
4537 if (status
== a
->status_codes
[i
])
4541 /* Do not delete files in non-matching status. */
4545 if (a
->status_codes
[i
] != GOT_STATUS_MODIFY
&&
4546 a
->status_codes
[i
] != GOT_STATUS_MISSING
) {
4547 static char msg
[64];
4548 snprintf(msg
, sizeof(msg
),
4549 "invalid status code '%c'", a
->status_codes
[i
]);
4550 err
= got_error_msg(GOT_ERR_FILE_STATUS
, msg
);
4555 if (status
!= GOT_STATUS_NO_CHANGE
) {
4556 if (status
== GOT_STATUS_DELETE
)
4558 if (status
== GOT_STATUS_MODIFY
&& !a
->delete_local_mods
) {
4559 err
= got_error_path(relpath
, GOT_ERR_FILE_MODIFIED
);
4562 if (status
== GOT_STATUS_MISSING
&& !a
->ignore_missing_paths
) {
4563 err
= got_error_set_errno(ENOENT
, relpath
);
4566 if (status
!= GOT_STATUS_MODIFY
&&
4567 status
!= GOT_STATUS_MISSING
) {
4568 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4573 if (!a
->keep_on_disk
&& status
!= GOT_STATUS_MISSING
) {
4577 if (unlinkat(dirfd
, de_name
, 0) == -1) {
4578 err
= got_error_from_errno2("unlinkat",
4582 } else if (unlink(ondisk_path
) == -1) {
4583 err
= got_error_from_errno2("unlink", ondisk_path
);
4587 root_len
= strlen(a
->worktree
->root_path
);
4591 err
= got_path_dirname(&parent
, ondisk_path
);
4595 ondisk_path
= parent
;
4596 if (got_path_cmp(ondisk_path
, a
->status_path
,
4597 strlen(ondisk_path
), a
->status_path_len
) != 0 &&
4598 !got_path_is_child(ondisk_path
, a
->status_path
,
4599 a
->status_path_len
))
4601 if (rmdir(ondisk_path
) == -1) {
4602 if (errno
!= ENOTEMPTY
)
4603 err
= got_error_from_errno2("rmdir",
4607 } while (got_path_cmp(ondisk_path
, a
->worktree
->root_path
,
4608 strlen(ondisk_path
), root_len
) != 0);
4611 if (got_fileindex_entry_has_blob(ie
))
4612 got_fileindex_entry_mark_deleted_from_disk(ie
);
4614 got_fileindex_entry_remove(a
->fileindex
, ie
);
4619 if (status
== GOT_STATUS_DELETE
)
4621 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_DELETE
,
4622 staged_status
, relpath
);
4625 const struct got_error
*
4626 got_worktree_schedule_delete(struct got_worktree
*worktree
,
4627 struct got_pathlist_head
*paths
, int delete_local_mods
,
4628 const char *status_codes
,
4629 got_worktree_delete_cb progress_cb
, void *progress_arg
,
4630 struct got_repository
*repo
, int keep_on_disk
, int ignore_missing_paths
)
4632 struct got_fileindex
*fileindex
= NULL
;
4633 char *fileindex_path
= NULL
;
4634 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4635 struct got_pathlist_entry
*pe
;
4636 struct schedule_deletion_args sda
;
4638 err
= lock_worktree(worktree
, LOCK_EX
);
4642 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
4643 got_repo_get_object_format(repo
));
4647 sda
.worktree
= worktree
;
4648 sda
.fileindex
= fileindex
;
4649 sda
.progress_cb
= progress_cb
;
4650 sda
.progress_arg
= progress_arg
;
4652 sda
.delete_local_mods
= delete_local_mods
;
4653 sda
.keep_on_disk
= keep_on_disk
;
4654 sda
.ignore_missing_paths
= ignore_missing_paths
;
4655 sda
.status_codes
= status_codes
;
4657 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
4658 char *ondisk_status_path
;
4660 if (asprintf(&ondisk_status_path
, "%s%s%s",
4661 got_worktree_get_root_path(worktree
),
4662 pe
->path
[0] == '\0' ? "" : "/", pe
->path
) == -1) {
4663 err
= got_error_from_errno("asprintf");
4666 sda
.status_path
= ondisk_status_path
;
4667 sda
.status_path_len
= strlen(ondisk_status_path
);
4668 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4669 schedule_for_deletion
, &sda
, NULL
, NULL
, 1, 1);
4670 free(ondisk_status_path
);
4674 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4675 if (sync_err
&& err
== NULL
)
4678 free(fileindex_path
);
4680 got_fileindex_free(fileindex
);
4681 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4682 if (unlockerr
&& err
== NULL
)
4687 static const struct got_error
*
4688 copy_one_line(FILE *infile
, FILE *outfile
, FILE *rejectfile
)
4690 const struct got_error
*err
= NULL
;
4692 size_t linesize
= 0, n
;
4695 linelen
= getline(&line
, &linesize
, infile
);
4696 if (linelen
== -1) {
4697 if (ferror(infile
)) {
4698 err
= got_error_from_errno("getline");
4704 n
= fwrite(line
, 1, linelen
, outfile
);
4706 err
= got_ferror(outfile
, GOT_ERR_IO
);
4711 n
= fwrite(line
, 1, linelen
, rejectfile
);
4713 err
= got_ferror(rejectfile
, GOT_ERR_IO
);
4720 static const struct got_error
*
4721 skip_one_line(FILE *f
)
4724 size_t linesize
= 0;
4727 linelen
= getline(&line
, &linesize
, f
);
4728 if (linelen
== -1) {
4730 return got_error_from_errno("getline");
4737 static const struct got_error
*
4738 copy_change(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4739 int start_old
, int end_old
, int start_new
, int end_new
,
4740 FILE *outfile
, FILE *rejectfile
)
4742 const struct got_error
*err
;
4744 /* Copy old file's lines leading up to patch. */
4745 while (!feof(f1
) && *line_cur1
< start_old
) {
4746 err
= copy_one_line(f1
, outfile
, NULL
);
4751 /* Skip new file's lines leading up to patch. */
4752 while (!feof(f2
) && *line_cur2
< start_new
) {
4754 err
= copy_one_line(f2
, NULL
, rejectfile
);
4756 err
= skip_one_line(f2
);
4761 /* Copy patched lines. */
4762 while (!feof(f2
) && *line_cur2
<= end_new
) {
4763 err
= copy_one_line(f2
, outfile
, NULL
);
4768 /* Skip over old file's replaced lines. */
4769 while (!feof(f1
) && *line_cur1
<= end_old
) {
4771 err
= copy_one_line(f1
, NULL
, rejectfile
);
4773 err
= skip_one_line(f1
);
4782 static const struct got_error
*
4783 copy_remaining_content(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4784 FILE *outfile
, FILE *rejectfile
)
4786 const struct got_error
*err
;
4789 /* Copy old file's lines until EOF. */
4791 err
= copy_one_line(f1
, outfile
, NULL
);
4798 /* Copy new file's lines until EOF. */
4800 err
= copy_one_line(f2
, NULL
, rejectfile
);
4810 static const struct got_error
*
4811 accept_or_reject_binary_change(int *choice
, const char *path
,
4812 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4814 const struct got_error
*err
;
4817 *choice
= GOT_PATCH_CHOICE_NONE
;
4821 return got_error_from_errno("got_opentemp");
4823 if (fprintf(f
, "Binary files %s and %s differ\n", path
, path
) < 0) {
4824 err
= got_error_msg(GOT_ERR_IO
, "fprintf");
4827 if (fseeko(f
, 0L, SEEK_SET
) == -1) {
4828 err
= got_error_from_errno("fseeko");
4832 err
= (*patch_cb
)(choice
, patch_arg
, GOT_STATUS_MODIFY
, path
, f
, 1, 1);
4835 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
4836 err
= got_error_from_errno("fclose");
4841 diff_result_has_binary(struct diff_result
*r
)
4843 return (r
->left
->atomizer_flags
| r
->right
->atomizer_flags
) &
4844 DIFF_ATOMIZER_FOUND_BINARY_DATA
;
4847 static const struct got_error
*
4848 apply_or_reject_change(int *choice
, int *nchunks_used
,
4849 struct diff_result
*diff_result
, int n
,
4850 const char *relpath
, FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4851 FILE *outfile
, FILE *rejectfile
, int changeno
, int nchanges
,
4852 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4854 const struct got_error
*err
= NULL
;
4855 struct diff_chunk_context cc
= {};
4856 int start_old
, end_old
, start_new
, end_new
;
4858 struct diff_output_unidiff_state
*diff_state
;
4859 struct diff_input_info diff_info
;
4862 *choice
= GOT_PATCH_CHOICE_NONE
;
4864 /* Get changed line numbers without context lines for copy_change(). */
4865 diff_chunk_context_load_change(&cc
, NULL
, diff_result
, n
, 0);
4866 start_old
= cc
.left
.start
;
4867 end_old
= cc
.left
.end
;
4868 start_new
= cc
.right
.start
;
4869 end_new
= cc
.right
.end
;
4871 /* Get the same change with context lines for display. */
4872 memset(&cc
, 0, sizeof(cc
));
4873 diff_chunk_context_load_change(&cc
, nchunks_used
, diff_result
, n
, 3);
4875 memset(&diff_info
, 0, sizeof(diff_info
));
4876 diff_info
.left_path
= relpath
;
4877 diff_info
.right_path
= relpath
;
4879 diff_state
= diff_output_unidiff_state_alloc();
4880 if (diff_state
== NULL
)
4881 return got_error_set_errno(ENOMEM
,
4882 "diff_output_unidiff_state_alloc");
4884 hunkfile
= got_opentemp();
4885 if (hunkfile
== NULL
) {
4886 err
= got_error_from_errno("got_opentemp");
4890 rc
= diff_output_unidiff_chunk(NULL
, hunkfile
, diff_state
, &diff_info
,
4892 if (rc
!= DIFF_RC_OK
) {
4893 err
= got_error_set_errno(rc
, "diff_output_unidiff_chunk");
4897 if (fseek(hunkfile
, 0L, SEEK_SET
) == -1) {
4898 err
= got_ferror(hunkfile
, GOT_ERR_IO
);
4902 err
= (*patch_cb
)(choice
, patch_arg
, GOT_STATUS_MODIFY
, relpath
,
4903 hunkfile
, changeno
, nchanges
);
4908 case GOT_PATCH_CHOICE_YES
:
4909 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4910 end_old
, start_new
, end_new
, outfile
, rejectfile
);
4912 case GOT_PATCH_CHOICE_NO
:
4913 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4914 end_old
, start_new
, end_new
, rejectfile
, outfile
);
4916 case GOT_PATCH_CHOICE_QUIT
:
4919 err
= got_error(GOT_ERR_PATCH_CHOICE
);
4923 diff_output_unidiff_state_free(diff_state
);
4924 if (hunkfile
&& fclose(hunkfile
) == EOF
&& err
== NULL
)
4925 err
= got_error_from_errno("fclose");
4929 struct revert_file_args
{
4930 struct got_worktree
*worktree
;
4931 struct got_fileindex
*fileindex
;
4932 got_worktree_checkout_cb progress_cb
;
4934 got_worktree_patch_cb patch_cb
;
4936 struct got_repository
*repo
;
4937 int unlink_added_files
;
4938 struct got_pathlist_head
*added_files_to_unlink
;
4941 static const struct got_error
*
4942 create_patched_content(char **path_outfile
, int *confirm_binary_change
,
4943 int reverse_patch
, struct got_object_id
*blob_id
, const char *path2
,
4944 int dirfd2
, const char *de_name2
,
4945 const char *relpath
, struct got_repository
*repo
,
4946 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4948 const struct got_error
*err
, *free_err
;
4949 struct got_blob_object
*blob
= NULL
;
4950 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
;
4951 int fd
= -1, fd2
= -1;
4952 char link_target
[PATH_MAX
];
4953 ssize_t link_len
= 0;
4954 char *path1
= NULL
, *id_str
= NULL
;
4956 struct got_diffreg_result
*diffreg_result
= NULL
;
4957 int choice
, line_cur1
= 1, line_cur2
= 1, have_content
= 0;
4958 int i
= 0, n
= 0, nchunks_used
= 0, nchanges
= 0;
4960 *path_outfile
= NULL
;
4961 *confirm_binary_change
= 0;
4963 err
= got_object_id_str(&id_str
, blob_id
);
4968 fd2
= openat(dirfd2
, de_name2
,
4969 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
4971 if (!got_err_open_nofollow_on_symlink()) {
4972 err
= got_error_from_errno2("openat", path2
);
4975 link_len
= readlinkat(dirfd2
, de_name2
,
4976 link_target
, sizeof(link_target
));
4977 if (link_len
== -1) {
4978 return got_error_from_errno2("readlinkat",
4981 sb2
.st_mode
= S_IFLNK
;
4982 sb2
.st_size
= link_len
;
4985 fd2
= open(path2
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
4987 if (!got_err_open_nofollow_on_symlink()) {
4988 err
= got_error_from_errno2("open", path2
);
4991 link_len
= readlink(path2
, link_target
,
4992 sizeof(link_target
));
4994 return got_error_from_errno2("readlink", path2
);
4995 sb2
.st_mode
= S_IFLNK
;
4996 sb2
.st_size
= link_len
;
5000 if (fstat(fd2
, &sb2
) == -1) {
5001 err
= got_error_from_errno2("fstat", path2
);
5005 f2
= fdopen(fd2
, "r");
5007 err
= got_error_from_errno2("fdopen", path2
);
5013 f2
= got_opentemp();
5015 err
= got_error_from_errno2("got_opentemp", path2
);
5018 n
= fwrite(link_target
, 1, link_len
, f2
);
5019 if (n
!= link_len
) {
5020 err
= got_ferror(f2
, GOT_ERR_IO
);
5023 if (fflush(f2
) == EOF
) {
5024 err
= got_error_from_errno("fflush");
5030 fd
= got_opentempfd();
5032 err
= got_error_from_errno("got_opentempfd");
5036 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192, fd
);
5040 err
= got_opentemp_named(&path1
, &f1
, "got-patched-blob", "");
5044 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
5048 err
= got_diff_files(&diffreg_result
, f1
, 1, id_str
, f2
, 1, path2
,
5049 3, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
5053 if (diff_result_has_binary(diffreg_result
->result
)) {
5054 err
= accept_or_reject_binary_change(&choice
, relpath
,
5055 patch_cb
, patch_arg
);
5056 if (err
== NULL
&& choice
== GOT_PATCH_CHOICE_YES
)
5057 *confirm_binary_change
= 1;
5061 err
= got_opentemp_named(path_outfile
, &outfile
, "got-patched-content",
5066 if (fseek(f1
, 0L, SEEK_SET
) == -1)
5067 return got_ferror(f1
, GOT_ERR_IO
);
5068 if (fseek(f2
, 0L, SEEK_SET
) == -1)
5069 return got_ferror(f2
, GOT_ERR_IO
);
5071 /* Count the number of actual changes in the diff result. */
5072 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
5073 struct diff_chunk_context cc
= {};
5074 diff_chunk_context_load_change(&cc
, &nchunks_used
,
5075 diffreg_result
->result
, n
, 0);
5078 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
5079 err
= apply_or_reject_change(&choice
, &nchunks_used
,
5080 diffreg_result
->result
, n
, relpath
, f1
, f2
,
5081 &line_cur1
, &line_cur2
,
5082 reverse_patch
? NULL
: outfile
,
5083 reverse_patch
? outfile
: NULL
,
5084 ++i
, nchanges
, patch_cb
, patch_arg
);
5087 if (choice
== GOT_PATCH_CHOICE_YES
)
5089 else if (choice
== GOT_PATCH_CHOICE_QUIT
)
5093 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
5094 reverse_patch
? NULL
: outfile
,
5095 reverse_patch
? outfile
: NULL
);
5099 if (!S_ISLNK(sb2
.st_mode
)) {
5102 mode
= apply_umask(sb2
.st_mode
);
5103 if (fchmod(fileno(outfile
), mode
) == -1) {
5104 err
= got_error_from_errno2("fchmod", path2
);
5111 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
5112 err
= got_error_from_errno("close");
5114 got_object_blob_close(blob
);
5115 free_err
= got_diffreg_result_free(diffreg_result
);
5118 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
5119 err
= got_error_from_errno2("fclose", path1
);
5120 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
5121 err
= got_error_from_errno2("fclose", path2
);
5122 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
5123 err
= got_error_from_errno2("close", path2
);
5124 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
5125 err
= got_error_from_errno2("fclose", *path_outfile
);
5126 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
5127 err
= got_error_from_errno2("unlink", path1
);
5128 if (err
|| !have_content
) {
5129 if (*path_outfile
&& unlink(*path_outfile
) == -1 && err
== NULL
)
5130 err
= got_error_from_errno2("unlink", *path_outfile
);
5131 free(*path_outfile
);
5132 *path_outfile
= NULL
;
5138 static const struct got_error
*
5139 revert_file(void *arg
, unsigned char status
, unsigned char staged_status
,
5140 const char *relpath
, struct got_object_id
*blob_id
,
5141 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
5142 int dirfd
, const char *de_name
)
5144 struct revert_file_args
*a
= arg
;
5145 const struct got_error
*err
= NULL
;
5146 char *parent_path
= NULL
;
5147 struct got_fileindex_entry
*ie
;
5148 struct got_commit_object
*base_commit
= NULL
;
5149 struct got_tree_object
*tree
= NULL
;
5150 struct got_object_id
*tree_id
= NULL
;
5151 const struct got_tree_entry
*te
= NULL
;
5152 char *tree_path
= NULL
, *te_name
;
5153 char *ondisk_path
= NULL
, *path_content
= NULL
;
5154 struct got_blob_object
*blob
= NULL
;
5157 /* Reverting a staged deletion is a no-op. */
5158 if (status
== GOT_STATUS_DELETE
&&
5159 staged_status
!= GOT_STATUS_NO_CHANGE
)
5162 if (status
== GOT_STATUS_UNVERSIONED
)
5163 return (*a
->progress_cb
)(a
->progress_arg
,
5164 GOT_STATUS_UNVERSIONED
, relpath
);
5166 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
5168 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
5170 /* Construct in-repository path of tree which contains this blob. */
5171 err
= got_path_dirname(&parent_path
, ie
->path
);
5173 if (err
->code
!= GOT_ERR_BAD_PATH
)
5175 parent_path
= strdup("/");
5176 if (parent_path
== NULL
) {
5177 err
= got_error_from_errno("strdup");
5181 if (got_path_is_root_dir(a
->worktree
->path_prefix
)) {
5182 tree_path
= strdup(parent_path
);
5183 if (tree_path
== NULL
) {
5184 err
= got_error_from_errno("strdup");
5188 if (got_path_is_root_dir(parent_path
)) {
5189 tree_path
= strdup(a
->worktree
->path_prefix
);
5190 if (tree_path
== NULL
) {
5191 err
= got_error_from_errno("strdup");
5195 if (asprintf(&tree_path
, "%s/%s",
5196 a
->worktree
->path_prefix
, parent_path
) == -1) {
5197 err
= got_error_from_errno("asprintf");
5203 err
= got_object_open_as_commit(&base_commit
, a
->repo
,
5204 a
->worktree
->base_commit_id
);
5208 err
= got_object_id_by_path(&tree_id
, a
->repo
, base_commit
, tree_path
);
5210 if (!(err
->code
== GOT_ERR_NO_TREE_ENTRY
&&
5211 (status
== GOT_STATUS_ADD
||
5212 staged_status
== GOT_STATUS_ADD
)))
5215 err
= got_object_open_as_tree(&tree
, a
->repo
, tree_id
);
5219 err
= got_path_basename(&te_name
, ie
->path
);
5223 te
= got_object_tree_find_entry(tree
, te_name
);
5225 if (te
== NULL
&& status
!= GOT_STATUS_ADD
&&
5226 staged_status
!= GOT_STATUS_ADD
) {
5227 err
= got_error_path(ie
->path
, GOT_ERR_NO_TREE_ENTRY
);
5233 case GOT_STATUS_ADD
:
5235 int choice
= GOT_PATCH_CHOICE_NONE
;
5236 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
5237 status
, ie
->path
, NULL
, 1, 1);
5240 if (choice
!= GOT_PATCH_CHOICE_YES
)
5243 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_REVERT
,
5247 got_fileindex_entry_remove(a
->fileindex
, ie
);
5248 if (a
->unlink_added_files
) {
5249 int do_unlink
= a
->added_files_to_unlink
? 0 : 1;
5251 if (a
->added_files_to_unlink
) {
5252 struct got_pathlist_entry
*pe
;
5254 RB_FOREACH(pe
, got_pathlist_head
,
5255 a
->added_files_to_unlink
) {
5256 if (got_path_cmp(pe
->path
, relpath
,
5257 pe
->path_len
, strlen(relpath
)))
5265 if (asprintf(&ondisk_path
, "%s/%s",
5266 got_worktree_get_root_path(a
->worktree
),
5268 err
= got_error_from_errno("asprintf");
5271 if (unlink(ondisk_path
) == -1) {
5272 err
= got_error_from_errno2("unlink",
5279 case GOT_STATUS_DELETE
:
5281 int choice
= GOT_PATCH_CHOICE_NONE
;
5282 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
5283 status
, ie
->path
, NULL
, 1, 1);
5286 if (choice
!= GOT_PATCH_CHOICE_YES
)
5290 case GOT_STATUS_MODIFY
:
5291 case GOT_STATUS_MODE_CHANGE
:
5292 case GOT_STATUS_CONFLICT
:
5293 case GOT_STATUS_MISSING
: {
5294 struct got_object_id id
;
5295 if (staged_status
== GOT_STATUS_ADD
||
5296 staged_status
== GOT_STATUS_MODIFY
)
5297 got_fileindex_entry_get_staged_blob_id(&id
, ie
);
5299 got_fileindex_entry_get_blob_id(&id
, ie
);
5300 fd
= got_opentempfd();
5302 err
= got_error_from_errno("got_opentempfd");
5306 err
= got_object_open_as_blob(&blob
, a
->repo
, &id
, 8192, fd
);
5310 if (asprintf(&ondisk_path
, "%s/%s",
5311 got_worktree_get_root_path(a
->worktree
), relpath
) == -1) {
5312 err
= got_error_from_errno("asprintf");
5316 if (a
->patch_cb
&& (status
== GOT_STATUS_MODIFY
||
5317 status
== GOT_STATUS_CONFLICT
)) {
5318 int is_bad_symlink
= 0, revert_binary_file
= 0;
5320 err
= create_patched_content(&path_content
,
5321 &revert_binary_file
, 1, &id
, ondisk_path
, dirfd
,
5322 de_name
, ie
->path
, a
->repo
,
5323 a
->patch_cb
, a
->patch_arg
);
5326 if (revert_binary_file
){
5327 err
= install_blob(a
->worktree
, ondisk_path
,
5329 te
? te
->mode
: GOT_DEFAULT_FILE_MODE
,
5330 got_fileindex_perms_to_st(ie
), blob
,
5331 0, 1, 0, 0, NULL
, a
->repo
,
5332 a
->progress_cb
, a
->progress_arg
);
5336 if (path_content
== NULL
)
5338 if (te
&& S_ISLNK(te
->mode
)) {
5339 if (unlink(path_content
) == -1) {
5340 err
= got_error_from_errno2("unlink",
5344 err
= install_symlink(&is_bad_symlink
,
5345 a
->worktree
, ondisk_path
, ie
->path
,
5346 blob
, 0, 1, 0, 0, a
->repo
,
5347 a
->progress_cb
, a
->progress_arg
);
5349 if (rename(path_content
, ondisk_path
) == -1) {
5350 err
= got_error_from_errno3("rename",
5351 path_content
, ondisk_path
);
5356 int is_bad_symlink
= 0;
5357 if (te
&& S_ISLNK(te
->mode
)) {
5358 err
= install_symlink(&is_bad_symlink
,
5359 a
->worktree
, ondisk_path
, ie
->path
,
5360 blob
, 0, 1, 0, 0, a
->repo
,
5361 a
->progress_cb
, a
->progress_arg
);
5363 err
= install_blob(a
->worktree
, ondisk_path
,
5365 te
? te
->mode
: GOT_DEFAULT_FILE_MODE
,
5366 got_fileindex_perms_to_st(ie
), blob
,
5367 0, 1, 0, 0, NULL
, a
->repo
,
5368 a
->progress_cb
, a
->progress_arg
);
5372 if (status
== GOT_STATUS_DELETE
||
5373 status
== GOT_STATUS_MODE_CHANGE
) {
5374 err
= got_fileindex_entry_update(ie
,
5375 a
->worktree
->root_fd
, relpath
,
5376 &blob
->id
, a
->worktree
->base_commit_id
, 1);
5380 if (is_bad_symlink
) {
5381 got_fileindex_entry_filetype_set(ie
,
5382 GOT_FILEIDX_MODE_BAD_SYMLINK
);
5395 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
5396 err
= got_error_from_errno("close");
5398 got_object_blob_close(blob
);
5400 got_object_tree_close(tree
);
5403 got_object_commit_close(base_commit
);
5407 const struct got_error
*
5408 got_worktree_revert(struct got_worktree
*worktree
,
5409 struct got_pathlist_head
*paths
,
5410 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
5411 got_worktree_patch_cb patch_cb
, void *patch_arg
,
5412 struct got_repository
*repo
)
5414 struct got_fileindex
*fileindex
= NULL
;
5415 char *fileindex_path
= NULL
;
5416 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
5417 const struct got_error
*sync_err
= NULL
;
5418 struct got_pathlist_entry
*pe
;
5419 struct revert_file_args rfa
;
5421 err
= lock_worktree(worktree
, LOCK_EX
);
5425 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
5426 got_repo_get_object_format(repo
));
5430 rfa
.worktree
= worktree
;
5431 rfa
.fileindex
= fileindex
;
5432 rfa
.progress_cb
= progress_cb
;
5433 rfa
.progress_arg
= progress_arg
;
5434 rfa
.patch_cb
= patch_cb
;
5435 rfa
.patch_arg
= patch_arg
;
5437 rfa
.unlink_added_files
= 0;
5438 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
5439 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
5440 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
5444 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
5445 if (sync_err
&& err
== NULL
)
5448 free(fileindex_path
);
5450 got_fileindex_free(fileindex
);
5451 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
5452 if (unlockerr
&& err
== NULL
)
5458 free_commitable(struct got_commitable
*ct
)
5461 free(ct
->in_repo_path
);
5462 free(ct
->ondisk_path
);
5464 free(ct
->base_blob_id
);
5465 free(ct
->staged_blob_id
);
5466 free(ct
->base_commit_id
);
5470 struct collect_commitables_arg
{
5471 struct got_pathlist_head
*commitable_paths
;
5472 struct got_repository
*repo
;
5473 struct got_worktree
*worktree
;
5474 struct got_fileindex
*fileindex
;
5475 int have_staged_files
;
5476 int allow_bad_symlinks
;
5477 int diff_header_shown
;
5478 int commit_conflicts
;
5485 * Create a file which contains the target path of a symlink so we can feed
5486 * it as content to the diff engine.
5488 static const struct got_error
*
5489 get_symlink_target_file(int *fd
, int dirfd
, const char *de_name
,
5490 const char *abspath
)
5492 const struct got_error
*err
= NULL
;
5493 char target_path
[PATH_MAX
];
5494 ssize_t target_len
, outlen
;
5499 target_len
= readlinkat(dirfd
, de_name
, target_path
, PATH_MAX
);
5500 if (target_len
== -1)
5501 return got_error_from_errno2("readlinkat", abspath
);
5503 target_len
= readlink(abspath
, target_path
, PATH_MAX
);
5504 if (target_len
== -1)
5505 return got_error_from_errno2("readlink", abspath
);
5508 *fd
= got_opentempfd();
5510 return got_error_from_errno("got_opentempfd");
5512 outlen
= write(*fd
, target_path
, target_len
);
5514 err
= got_error_from_errno("got_opentempfd");
5518 if (lseek(*fd
, 0, SEEK_SET
) == -1) {
5519 err
= got_error_from_errno2("lseek", abspath
);
5530 static const struct got_error
*
5531 append_ct_diff(struct got_commitable
*ct
, int *diff_header_shown
,
5532 FILE *diff_outfile
, FILE *f1
, FILE *f2
, int dirfd
, const char *de_name
,
5533 int diff_staged
, struct got_repository
*repo
, struct got_worktree
*worktree
)
5535 const struct got_error
*err
= NULL
;
5536 struct got_blob_object
*blob1
= NULL
;
5537 int fd
= -1, fd1
= -1, fd2
= -1;
5538 FILE *ondisk_file
= NULL
;
5539 char *label1
= NULL
;
5543 char *id_str
= NULL
;
5545 memset(&sb
, 0, sizeof(sb
));
5548 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
5549 ct
->staged_status
!= GOT_STATUS_ADD
&&
5550 ct
->staged_status
!= GOT_STATUS_DELETE
)
5553 if (ct
->status
!= GOT_STATUS_MODIFY
&&
5554 ct
->status
!= GOT_STATUS_ADD
&&
5555 ct
->status
!= GOT_STATUS_DELETE
&&
5556 ct
->status
!= GOT_STATUS_CONFLICT
)
5560 err
= got_opentemp_truncate(f1
);
5562 return got_error_from_errno("got_opentemp_truncate");
5563 err
= got_opentemp_truncate(f2
);
5565 return got_error_from_errno("got_opentemp_truncate");
5567 if (!*diff_header_shown
) {
5568 err
= got_object_id_str(&id_str
, worktree
->base_commit_id
);
5571 fprintf(diff_outfile
, "diff %s%s\n", diff_staged
? "-s " : "",
5572 got_worktree_get_root_path(worktree
));
5573 fprintf(diff_outfile
, "commit - %s\n", id_str
);
5574 fprintf(diff_outfile
, "path + %s%s\n",
5575 got_worktree_get_root_path(worktree
),
5576 diff_staged
? " (staged changes)" : "");
5577 *diff_header_shown
= 1;
5581 const char *label1
= NULL
, *label2
= NULL
;
5582 switch (ct
->staged_status
) {
5583 case GOT_STATUS_MODIFY
:
5587 case GOT_STATUS_ADD
:
5590 case GOT_STATUS_DELETE
:
5594 return got_error(GOT_ERR_FILE_STATUS
);
5596 fd1
= got_opentempfd();
5598 err
= got_error_from_errno("got_opentempfd");
5601 fd2
= got_opentempfd();
5603 err
= got_error_from_errno("got_opentempfd");
5606 err
= got_diff_objects_as_blobs(NULL
, NULL
, f1
, f2
,
5607 fd1
, fd2
, ct
->base_blob_id
, ct
->staged_blob_id
,
5608 label1
, label2
, GOT_DIFF_ALGORITHM_PATIENCE
, 3, 0, 0,
5609 NULL
, repo
, diff_outfile
);
5613 fd1
= got_opentempfd();
5615 err
= got_error_from_errno("got_opentempfd");
5619 if (ct
->status
!= GOT_STATUS_ADD
) {
5620 err
= got_object_open_as_blob(&blob1
, repo
, ct
->base_blob_id
,
5626 if (ct
->status
!= GOT_STATUS_DELETE
) {
5628 fd
= openat(dirfd
, de_name
,
5629 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
5631 if (!got_err_open_nofollow_on_symlink()) {
5632 err
= got_error_from_errno2("openat",
5636 err
= get_symlink_target_file(&fd
, dirfd
,
5637 de_name
, ct
->ondisk_path
);
5642 fd
= open(ct
->ondisk_path
,
5643 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
5645 if (!got_err_open_nofollow_on_symlink()) {
5646 err
= got_error_from_errno2("open",
5650 err
= get_symlink_target_file(&fd
, dirfd
,
5651 de_name
, ct
->ondisk_path
);
5656 if (fstatat(fd
, ct
->ondisk_path
, &sb
,
5657 AT_SYMLINK_NOFOLLOW
) == -1) {
5658 err
= got_error_from_errno2("fstatat", ct
->ondisk_path
);
5661 ondisk_file
= fdopen(fd
, "r");
5662 if (ondisk_file
== NULL
) {
5663 err
= got_error_from_errno2("fdopen", ct
->ondisk_path
);
5671 err
= got_object_blob_dump_to_file(&size1
, NULL
, NULL
,
5677 err
= got_diff_blob_file(NULL
, NULL
, blob1
, f1
, size1
, label1
,
5678 ondisk_file
? ondisk_file
: f2
, f2_exists
, &sb
, ct
->path
,
5679 GOT_DIFF_ALGORITHM_PATIENCE
, 3, 0, 0, NULL
, diff_outfile
);
5681 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
5682 err
= got_error_from_errno("close");
5683 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
5684 err
= got_error_from_errno("close");
5686 got_object_blob_close(blob1
);
5687 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
5688 err
= got_error_from_errno("close");
5689 if (ondisk_file
&& fclose(ondisk_file
) == EOF
&& err
== NULL
)
5690 err
= got_error_from_errno("fclose");
5694 static const struct got_error
*
5695 collect_commitables(void *arg
, unsigned char status
,
5696 unsigned char staged_status
, const char *relpath
,
5697 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
5698 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
5700 struct collect_commitables_arg
*a
= arg
;
5701 const struct got_error
*err
= NULL
;
5702 struct got_commitable
*ct
= NULL
;
5703 struct got_pathlist_entry
*new = NULL
;
5704 char *parent_path
= NULL
, *path
= NULL
;
5707 if (a
->have_staged_files
) {
5708 if (staged_status
!= GOT_STATUS_MODIFY
&&
5709 staged_status
!= GOT_STATUS_ADD
&&
5710 staged_status
!= GOT_STATUS_DELETE
)
5713 if (status
== GOT_STATUS_CONFLICT
&& !a
->commit_conflicts
) {
5714 printf("C %s\n", relpath
);
5715 return got_error(GOT_ERR_COMMIT_CONFLICT
);
5718 if (status
!= GOT_STATUS_MODIFY
&&
5719 status
!= GOT_STATUS_MODE_CHANGE
&&
5720 status
!= GOT_STATUS_ADD
&&
5721 status
!= GOT_STATUS_DELETE
&&
5722 status
!= GOT_STATUS_CONFLICT
)
5726 if (asprintf(&path
, "/%s", relpath
) == -1) {
5727 err
= got_error_from_errno("asprintf");
5730 if (strcmp(path
, "/") == 0) {
5731 parent_path
= strdup("");
5732 if (parent_path
== NULL
)
5733 return got_error_from_errno("strdup");
5735 err
= got_path_dirname(&parent_path
, path
);
5740 ct
= calloc(1, sizeof(*ct
));
5742 err
= got_error_from_errno("calloc");
5746 if (asprintf(&ct
->ondisk_path
, "%s/%s", a
->worktree
->root_path
,
5748 err
= got_error_from_errno("asprintf");
5752 if (staged_status
== GOT_STATUS_ADD
||
5753 staged_status
== GOT_STATUS_MODIFY
) {
5754 struct got_fileindex_entry
*ie
;
5755 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
5756 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
5757 case GOT_FILEIDX_MODE_REGULAR_FILE
:
5758 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
5761 case GOT_FILEIDX_MODE_SYMLINK
:
5765 err
= got_error_path(path
, GOT_ERR_BAD_FILETYPE
);
5768 ct
->mode
|= got_fileindex_entry_perms_get(ie
);
5769 } else if (status
!= GOT_STATUS_DELETE
&&
5770 staged_status
!= GOT_STATUS_DELETE
) {
5772 if (fstatat(dirfd
, de_name
, &sb
,
5773 AT_SYMLINK_NOFOLLOW
) == -1) {
5774 err
= got_error_from_errno2("fstatat",
5778 } else if (lstat(ct
->ondisk_path
, &sb
) == -1) {
5779 err
= got_error_from_errno2("lstat", ct
->ondisk_path
);
5782 ct
->mode
= sb
.st_mode
;
5785 if (asprintf(&ct
->in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
5786 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
5788 err
= got_error_from_errno("asprintf");
5792 if (S_ISLNK(ct
->mode
) && staged_status
== GOT_STATUS_NO_CHANGE
&&
5793 status
== GOT_STATUS_ADD
&& !a
->allow_bad_symlinks
) {
5795 char target_path
[PATH_MAX
];
5797 target_len
= readlink(ct
->ondisk_path
, target_path
,
5798 sizeof(target_path
));
5799 if (target_len
== -1) {
5800 err
= got_error_from_errno2("readlink",
5804 err
= is_bad_symlink_target(&is_bad_symlink
, target_path
,
5805 target_len
, ct
->ondisk_path
, a
->worktree
->root_path
,
5806 a
->worktree
->meta_dir
);
5809 if (is_bad_symlink
) {
5810 err
= got_error_path(ct
->ondisk_path
,
5811 GOT_ERR_BAD_SYMLINK
);
5817 ct
->status
= status
;
5818 ct
->staged_status
= staged_status
;
5819 ct
->blob_id
= NULL
; /* will be filled in when blob gets created */
5820 if (ct
->status
!= GOT_STATUS_ADD
&&
5821 ct
->staged_status
!= GOT_STATUS_ADD
) {
5822 ct
->base_blob_id
= got_object_id_dup(blob_id
);
5823 if (ct
->base_blob_id
== NULL
) {
5824 err
= got_error_from_errno("got_object_id_dup");
5827 ct
->base_commit_id
= got_object_id_dup(commit_id
);
5828 if (ct
->base_commit_id
== NULL
) {
5829 err
= got_error_from_errno("got_object_id_dup");
5833 if (ct
->staged_status
== GOT_STATUS_ADD
||
5834 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5835 ct
->staged_blob_id
= got_object_id_dup(staged_blob_id
);
5836 if (ct
->staged_blob_id
== NULL
) {
5837 err
= got_error_from_errno("got_object_id_dup");
5841 ct
->path
= strdup(path
);
5842 if (ct
->path
== NULL
) {
5843 err
= got_error_from_errno("strdup");
5847 if (a
->diff_outfile
) {
5848 err
= append_ct_diff(ct
, &a
->diff_header_shown
,
5849 a
->diff_outfile
, a
->f1
, a
->f2
, dirfd
, de_name
,
5850 a
->have_staged_files
, a
->repo
, a
->worktree
);
5855 err
= got_pathlist_insert(&new, a
->commitable_paths
, ct
->path
, ct
);
5857 if (ct
&& (err
|| new == NULL
))
5858 free_commitable(ct
);
5864 static const struct got_error
*write_tree(struct got_object_id
**, int *,
5865 struct got_tree_object
*, const char *, struct got_pathlist_head
*,
5866 got_worktree_status_cb status_cb
, void *status_arg
,
5867 struct got_repository
*);
5869 static const struct got_error
*
5870 write_subtree(struct got_object_id
**new_subtree_id
, int *nentries
,
5871 struct got_tree_entry
*te
, const char *parent_path
,
5872 struct got_pathlist_head
*commitable_paths
,
5873 got_worktree_status_cb status_cb
, void *status_arg
,
5874 struct got_repository
*repo
)
5876 const struct got_error
*err
= NULL
;
5877 struct got_tree_object
*subtree
;
5880 if (asprintf(&subpath
, "%s%s%s", parent_path
,
5881 got_path_is_root_dir(parent_path
) ? "" : "/", te
->name
) == -1)
5882 return got_error_from_errno("asprintf");
5884 err
= got_object_open_as_tree(&subtree
, repo
, &te
->id
);
5888 err
= write_tree(new_subtree_id
, nentries
, subtree
, subpath
,
5889 commitable_paths
, status_cb
, status_arg
, repo
);
5890 got_object_tree_close(subtree
);
5895 static const struct got_error
*
5896 match_ct_parent_path(int *match
, struct got_commitable
*ct
, const char *path
)
5898 const struct got_error
*err
= NULL
;
5899 char *ct_parent_path
= NULL
;
5903 if (strchr(ct
->in_repo_path
, '/') == NULL
) {
5904 *match
= got_path_is_root_dir(path
);
5908 err
= got_path_dirname(&ct_parent_path
, ct
->in_repo_path
);
5911 *match
= (strcmp(path
, ct_parent_path
) == 0);
5912 free(ct_parent_path
);
5917 get_ct_file_mode(struct got_commitable
*ct
)
5919 if (S_ISLNK(ct
->mode
))
5922 return S_IFREG
| (ct
->mode
& ((S_IRWXU
| S_IRWXG
| S_IRWXO
)));
5925 static const struct got_error
*
5926 alloc_modified_blob_tree_entry(struct got_tree_entry
**new_te
,
5927 struct got_tree_entry
*te
, struct got_commitable
*ct
)
5929 const struct got_error
*err
= NULL
;
5933 err
= got_object_tree_entry_dup(new_te
, te
);
5937 (*new_te
)->mode
= get_ct_file_mode(ct
);
5939 if (ct
->staged_status
== GOT_STATUS_MODIFY
)
5940 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5941 sizeof((*new_te
)->id
));
5943 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5945 if (err
&& *new_te
) {
5952 static const struct got_error
*
5953 alloc_added_blob_tree_entry(struct got_tree_entry
**new_te
,
5954 struct got_commitable
*ct
)
5956 const struct got_error
*err
= NULL
;
5957 char *ct_name
= NULL
;
5961 *new_te
= calloc(1, sizeof(**new_te
));
5962 if (*new_te
== NULL
)
5963 return got_error_from_errno("calloc");
5965 err
= got_path_basename(&ct_name
, ct
->path
);
5968 if (strlcpy((*new_te
)->name
, ct_name
, sizeof((*new_te
)->name
)) >=
5969 sizeof((*new_te
)->name
)) {
5970 err
= got_error(GOT_ERR_NO_SPACE
);
5974 (*new_te
)->mode
= get_ct_file_mode(ct
);
5976 if (ct
->staged_status
== GOT_STATUS_ADD
)
5977 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5978 sizeof((*new_te
)->id
));
5980 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5983 if (err
&& *new_te
) {
5990 static const struct got_error
*
5991 insert_tree_entry(struct got_tree_entry
*new_te
,
5992 struct got_pathlist_head
*paths
)
5994 const struct got_error
*err
= NULL
;
5995 struct got_pathlist_entry
*new_pe
;
5997 err
= got_pathlist_insert(&new_pe
, paths
, new_te
->name
, new_te
);
6001 return got_error(GOT_ERR_TREE_DUP_ENTRY
);
6005 static const struct got_error
*
6006 report_ct_status(struct got_commitable
*ct
,
6007 got_worktree_status_cb status_cb
, void *status_arg
)
6009 const char *ct_path
= ct
->path
;
6010 unsigned char status
;
6012 if (status_cb
== NULL
) /* no commit progress output desired */
6015 while (ct_path
[0] == '/')
6018 if (ct
->staged_status
!= GOT_STATUS_NO_CHANGE
)
6019 status
= ct
->staged_status
;
6021 status
= ct
->status
;
6023 return (*status_cb
)(status_arg
, status
, GOT_STATUS_NO_CHANGE
,
6024 ct_path
, ct
->blob_id
, NULL
, NULL
, -1, NULL
);
6027 static const struct got_error
*
6028 match_modified_subtree(int *modified
, struct got_tree_entry
*te
,
6029 const char *base_tree_path
, struct got_pathlist_head
*commitable_paths
)
6031 const struct got_error
*err
= NULL
;
6032 struct got_pathlist_entry
*pe
;
6037 if (asprintf(&te_path
, "%s%s%s", base_tree_path
,
6038 got_path_is_root_dir(base_tree_path
) ? "" : "/",
6040 return got_error_from_errno("asprintf");
6042 RB_FOREACH(pe
, got_pathlist_head
, commitable_paths
) {
6043 struct got_commitable
*ct
= pe
->data
;
6044 *modified
= got_path_is_child(ct
->in_repo_path
, te_path
,
6054 static const struct got_error
*
6055 match_deleted_or_modified_ct(struct got_commitable
**ctp
,
6056 struct got_tree_entry
*te
, const char *base_tree_path
,
6057 struct got_pathlist_head
*commitable_paths
)
6059 const struct got_error
*err
= NULL
;
6060 struct got_pathlist_entry
*pe
;
6064 RB_FOREACH(pe
, got_pathlist_head
, commitable_paths
) {
6065 struct got_commitable
*ct
= pe
->data
;
6066 char *ct_name
= NULL
;
6069 if (ct
->staged_status
== GOT_STATUS_NO_CHANGE
) {
6070 if (ct
->status
!= GOT_STATUS_MODIFY
&&
6071 ct
->status
!= GOT_STATUS_MODE_CHANGE
&&
6072 ct
->status
!= GOT_STATUS_DELETE
&&
6073 ct
->status
!= GOT_STATUS_CONFLICT
)
6076 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
6077 ct
->staged_status
!= GOT_STATUS_DELETE
)
6081 if (got_object_id_cmp(ct
->base_blob_id
, &te
->id
) != 0)
6084 err
= match_ct_parent_path(&path_matches
, ct
, base_tree_path
);
6090 err
= got_path_basename(&ct_name
, pe
->path
);
6094 if (strcmp(te
->name
, ct_name
) != 0) {
6107 static const struct got_error
*
6108 make_subtree_for_added_blob(struct got_tree_entry
**new_tep
,
6109 const char *child_path
, const char *path_base_tree
,
6110 struct got_pathlist_head
*commitable_paths
,
6111 got_worktree_status_cb status_cb
, void *status_arg
,
6112 struct got_repository
*repo
)
6114 const struct got_error
*err
= NULL
;
6115 struct got_tree_entry
*new_te
;
6117 struct got_object_id
*id
= NULL
;
6122 if (asprintf(&subtree_path
, "%s%s%s", path_base_tree
,
6123 got_path_is_root_dir(path_base_tree
) ? "" : "/",
6125 return got_error_from_errno("asprintf");
6127 new_te
= calloc(1, sizeof(*new_te
));
6129 return got_error_from_errno("calloc");
6130 new_te
->mode
= S_IFDIR
;
6132 if (strlcpy(new_te
->name
, child_path
, sizeof(new_te
->name
)) >=
6133 sizeof(new_te
->name
)) {
6134 err
= got_error(GOT_ERR_NO_SPACE
);
6137 err
= write_tree(&id
, &nentries
, NULL
, subtree_path
,
6138 commitable_paths
, status_cb
, status_arg
, repo
);
6143 memcpy(&new_te
->id
, id
, sizeof(new_te
->id
));
6152 static const struct got_error
*
6153 write_tree(struct got_object_id
**new_tree_id
, int *nentries
,
6154 struct got_tree_object
*base_tree
, const char *path_base_tree
,
6155 struct got_pathlist_head
*commitable_paths
,
6156 got_worktree_status_cb status_cb
, void *status_arg
,
6157 struct got_repository
*repo
)
6159 const struct got_error
*err
= NULL
;
6160 struct got_pathlist_head paths
;
6161 struct got_tree_entry
*te
, *new_te
= NULL
;
6162 struct got_pathlist_entry
*pe
;
6167 /* Insert, and recurse into, newly added entries first. */
6168 RB_FOREACH(pe
, got_pathlist_head
, commitable_paths
) {
6169 struct got_commitable
*ct
= pe
->data
;
6170 char *child_path
= NULL
, *slash
;
6172 if ((ct
->status
!= GOT_STATUS_ADD
&&
6173 ct
->staged_status
!= GOT_STATUS_ADD
) ||
6174 (ct
->flags
& GOT_COMMITABLE_ADDED
))
6177 if (!got_path_is_child(ct
->in_repo_path
, path_base_tree
,
6178 strlen(path_base_tree
)))
6181 err
= got_path_skip_common_ancestor(&child_path
, path_base_tree
,
6186 slash
= strchr(child_path
, '/');
6187 if (slash
== NULL
) {
6188 err
= alloc_added_blob_tree_entry(&new_te
, ct
);
6191 err
= report_ct_status(ct
, status_cb
, status_arg
);
6194 ct
->flags
|= GOT_COMMITABLE_ADDED
;
6195 err
= insert_tree_entry(new_te
, &paths
);
6200 *slash
= '\0'; /* trim trailing path components */
6201 if (base_tree
== NULL
||
6202 got_object_tree_find_entry(base_tree
, child_path
)
6204 err
= make_subtree_for_added_blob(&new_te
,
6205 child_path
, path_base_tree
,
6206 commitable_paths
, status_cb
, status_arg
,
6210 err
= insert_tree_entry(new_te
, &paths
);
6219 int i
, nbase_entries
;
6220 /* Handle modified and deleted entries. */
6221 nbase_entries
= got_object_tree_get_nentries(base_tree
);
6222 for (i
= 0; i
< nbase_entries
; i
++) {
6223 struct got_commitable
*ct
= NULL
;
6225 te
= got_object_tree_get_entry(base_tree
, i
);
6226 if (got_object_tree_entry_is_submodule(te
)) {
6227 /* Entry is a submodule; just copy it. */
6228 err
= got_object_tree_entry_dup(&new_te
, te
);
6231 err
= insert_tree_entry(new_te
, &paths
);
6238 if (S_ISDIR(te
->mode
)) {
6240 err
= got_object_tree_entry_dup(&new_te
, te
);
6243 err
= match_modified_subtree(&modified
, te
,
6244 path_base_tree
, commitable_paths
);
6247 /* Avoid recursion into unmodified subtrees. */
6249 struct got_object_id
*new_id
;
6251 err
= write_subtree(&new_id
,
6253 path_base_tree
, commitable_paths
,
6254 status_cb
, status_arg
, repo
);
6257 if (nsubentries
== 0) {
6258 /* All entries were deleted. */
6262 memcpy(&new_te
->id
, new_id
,
6263 sizeof(new_te
->id
));
6266 err
= insert_tree_entry(new_te
, &paths
);
6273 err
= match_deleted_or_modified_ct(&ct
, te
,
6274 path_base_tree
, commitable_paths
);
6278 /* NB: Deleted entries get dropped here. */
6279 if (ct
->status
== GOT_STATUS_MODIFY
||
6280 ct
->status
== GOT_STATUS_MODE_CHANGE
||
6281 ct
->status
== GOT_STATUS_CONFLICT
||
6282 ct
->staged_status
== GOT_STATUS_MODIFY
) {
6283 err
= alloc_modified_blob_tree_entry(
6287 err
= insert_tree_entry(new_te
, &paths
);
6292 err
= report_ct_status(ct
, status_cb
,
6297 /* Entry is unchanged; just copy it. */
6298 err
= got_object_tree_entry_dup(&new_te
, te
);
6301 err
= insert_tree_entry(new_te
, &paths
);
6309 /* Write new list of entries; deleted entries have been dropped. */
6310 err
= got_object_tree_create(new_tree_id
, &paths
, *nentries
, repo
);
6312 got_pathlist_free(&paths
, GOT_PATHLIST_FREE_NONE
);
6316 static const struct got_error
*
6317 update_fileindex_after_commit(struct got_worktree
*worktree
,
6318 struct got_pathlist_head
*commitable_paths
,
6319 struct got_object_id
*new_base_commit_id
,
6320 struct got_fileindex
*fileindex
, int have_staged_files
)
6322 const struct got_error
*err
= NULL
;
6323 struct got_pathlist_entry
*pe
;
6324 char *relpath
= NULL
;
6326 RB_FOREACH(pe
, got_pathlist_head
, commitable_paths
) {
6327 struct got_fileindex_entry
*ie
;
6328 struct got_commitable
*ct
= pe
->data
;
6330 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
6332 err
= got_path_skip_common_ancestor(&relpath
,
6333 worktree
->root_path
, ct
->ondisk_path
);
6338 if (ct
->status
== GOT_STATUS_DELETE
||
6339 ct
->staged_status
== GOT_STATUS_DELETE
) {
6340 got_fileindex_entry_remove(fileindex
, ie
);
6341 } else if (ct
->staged_status
== GOT_STATUS_ADD
||
6342 ct
->staged_status
== GOT_STATUS_MODIFY
) {
6343 got_fileindex_entry_stage_set(ie
,
6344 GOT_FILEIDX_STAGE_NONE
);
6345 got_fileindex_entry_staged_filetype_set(ie
, 0);
6347 err
= got_fileindex_entry_update(ie
,
6348 worktree
->root_fd
, relpath
,
6349 ct
->staged_blob_id
, new_base_commit_id
,
6350 !have_staged_files
);
6352 err
= got_fileindex_entry_update(ie
,
6353 worktree
->root_fd
, relpath
,
6354 ct
->blob_id
, new_base_commit_id
,
6355 !have_staged_files
);
6357 err
= got_fileindex_entry_alloc(&ie
, pe
->path
);
6360 err
= got_fileindex_entry_update(ie
,
6361 worktree
->root_fd
, relpath
, ct
->blob_id
,
6362 new_base_commit_id
, 1);
6364 got_fileindex_entry_free(ie
);
6367 err
= got_fileindex_entry_add(fileindex
, ie
);
6369 got_fileindex_entry_free(ie
);
6382 static const struct got_error
*
6383 check_out_of_date(const char *in_repo_path
, unsigned char status
,
6384 unsigned char staged_status
, struct got_object_id
*base_blob_id
,
6385 struct got_object_id
*base_commit_id
,
6386 struct got_object_id
*head_commit_id
, struct got_repository
*repo
,
6389 const struct got_error
*err
= NULL
;
6390 struct got_commit_object
*commit
= NULL
;
6391 struct got_object_id
*id
= NULL
;
6393 if (status
!= GOT_STATUS_ADD
&& staged_status
!= GOT_STATUS_ADD
) {
6394 /* Trivial case: base commit == head commit */
6395 if (got_object_id_cmp(base_commit_id
, head_commit_id
) == 0)
6398 * Ensure file content which local changes were based
6399 * on matches file content in the branch head.
6401 err
= got_object_open_as_commit(&commit
, repo
, head_commit_id
);
6404 err
= got_object_id_by_path(&id
, repo
, commit
, in_repo_path
);
6406 if (err
->code
== GOT_ERR_NO_TREE_ENTRY
)
6407 err
= got_error(ood_errcode
);
6409 } else if (got_object_id_cmp(id
, base_blob_id
) != 0)
6410 err
= got_error(ood_errcode
);
6412 /* Require that added files don't exist in the branch head. */
6413 err
= got_object_open_as_commit(&commit
, repo
, head_commit_id
);
6416 err
= got_object_id_by_path(&id
, repo
, commit
, in_repo_path
);
6417 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
6419 err
= id
? got_error(ood_errcode
) : NULL
;
6424 got_object_commit_close(commit
);
6428 static const struct got_error
*
6429 commit_worktree(struct got_object_id
**new_commit_id
,
6430 struct got_pathlist_head
*commitable_paths
,
6431 struct got_object_id
*head_commit_id
,
6432 struct got_object_id
*parent_id2
,
6433 struct got_worktree
*worktree
,
6434 const char *author
, const char *committer
, char *diff_path
,
6435 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
6436 got_worktree_status_cb status_cb
, void *status_arg
,
6437 struct got_repository
*repo
)
6439 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
6440 struct got_pathlist_entry
*pe
;
6441 const char *head_ref_name
= NULL
;
6442 struct got_commit_object
*head_commit
= NULL
;
6443 struct got_reference
*head_ref2
= NULL
;
6444 struct got_object_id
*head_commit_id2
= NULL
;
6445 struct got_tree_object
*head_tree
= NULL
;
6446 struct got_object_id
*new_tree_id
= NULL
;
6447 int nentries
, nparents
= 0;
6448 struct got_object_id_queue parent_ids
;
6449 struct got_object_qid
*pid
= NULL
;
6450 char *logmsg
= NULL
;
6453 *new_commit_id
= NULL
;
6455 STAILQ_INIT(&parent_ids
);
6457 err
= got_object_open_as_commit(&head_commit
, repo
, head_commit_id
);
6461 err
= got_object_open_as_tree(&head_tree
, repo
, head_commit
->tree_id
);
6465 if (commit_msg_cb
!= NULL
) {
6466 err
= commit_msg_cb(commitable_paths
, diff_path
,
6467 &logmsg
, commit_arg
);
6472 if (logmsg
== NULL
|| strlen(logmsg
) == 0) {
6473 err
= got_error(GOT_ERR_COMMIT_MSG_EMPTY
);
6477 /* Create blobs from added and modified files and record their IDs. */
6478 RB_FOREACH(pe
, got_pathlist_head
, commitable_paths
) {
6479 struct got_commitable
*ct
= pe
->data
;
6482 /* Blobs for staged files already exist. */
6483 if (ct
->staged_status
== GOT_STATUS_ADD
||
6484 ct
->staged_status
== GOT_STATUS_MODIFY
)
6487 if (ct
->status
!= GOT_STATUS_ADD
&&
6488 ct
->status
!= GOT_STATUS_MODIFY
&&
6489 ct
->status
!= GOT_STATUS_MODE_CHANGE
&&
6490 ct
->status
!= GOT_STATUS_CONFLICT
)
6493 if (asprintf(&ondisk_path
, "%s/%s",
6494 worktree
->root_path
, pe
->path
) == -1) {
6495 err
= got_error_from_errno("asprintf");
6498 err
= got_object_blob_create(&ct
->blob_id
, ondisk_path
, repo
);
6504 /* Recursively write new tree objects. */
6505 err
= write_tree(&new_tree_id
, &nentries
, head_tree
, "/",
6506 commitable_paths
, status_cb
, status_arg
, repo
);
6510 err
= got_object_qid_alloc(&pid
, head_commit_id
);
6513 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
6516 err
= got_object_qid_alloc(&pid
, parent_id2
);
6519 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
6522 timestamp
= time(NULL
);
6523 err
= got_object_commit_create(new_commit_id
, new_tree_id
, &parent_ids
,
6524 nparents
, author
, timestamp
, committer
, timestamp
, logmsg
, repo
);
6530 /* Check if a concurrent commit to our branch has occurred. */
6531 head_ref_name
= got_worktree_get_head_ref_name(worktree
);
6532 if (head_ref_name
== NULL
) {
6533 err
= got_error_from_errno("got_worktree_get_head_ref_name");
6536 /* Lock the reference here to prevent concurrent modification. */
6537 err
= got_ref_open(&head_ref2
, repo
, head_ref_name
, 1);
6540 err
= got_ref_resolve(&head_commit_id2
, repo
, head_ref2
);
6543 if (got_object_id_cmp(head_commit_id
, head_commit_id2
) != 0) {
6544 err
= got_error(GOT_ERR_COMMIT_HEAD_CHANGED
);
6547 /* Update branch head in repository. */
6548 err
= got_ref_change_ref(head_ref2
, *new_commit_id
);
6551 err
= got_ref_write(head_ref2
, repo
);
6555 err
= got_worktree_set_base_commit_id(worktree
, repo
, *new_commit_id
);
6559 err
= ref_base_commit(worktree
, repo
);
6563 got_object_id_queue_free(&parent_ids
);
6565 got_object_tree_close(head_tree
);
6567 got_object_commit_close(head_commit
);
6568 free(head_commit_id2
);
6570 unlockerr
= got_ref_unlock(head_ref2
);
6571 if (unlockerr
&& err
== NULL
)
6573 got_ref_close(head_ref2
);
6578 static const struct got_error
*
6579 check_path_is_commitable(const char *path
,
6580 struct got_pathlist_head
*commitable_paths
)
6582 struct got_pathlist_entry
*cpe
= NULL
;
6583 size_t path_len
= strlen(path
);
6585 RB_FOREACH(cpe
, got_pathlist_head
, commitable_paths
) {
6586 struct got_commitable
*ct
= cpe
->data
;
6587 const char *ct_path
= ct
->path
;
6589 while (ct_path
[0] == '/')
6592 if (strcmp(path
, ct_path
) == 0 ||
6593 got_path_is_child(ct_path
, path
, path_len
))
6598 return got_error_path(path
, GOT_ERR_COMMIT_NO_CHANGES
);
6603 static const struct got_error
*
6604 check_staged_file(void *arg
, struct got_fileindex_entry
*ie
)
6606 int *have_staged_files
= arg
;
6608 if (got_fileindex_entry_stage_get(ie
) != GOT_FILEIDX_STAGE_NONE
) {
6609 *have_staged_files
= 1;
6610 return got_error(GOT_ERR_CANCELLED
);
6616 static const struct got_error
*
6617 check_non_staged_files(struct got_fileindex
*fileindex
,
6618 struct got_pathlist_head
*paths
)
6620 struct got_pathlist_entry
*pe
;
6621 struct got_fileindex_entry
*ie
;
6623 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
6624 if (pe
->path
[0] == '\0')
6626 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
6628 return got_error_path(pe
->path
, GOT_ERR_BAD_PATH
);
6629 if (got_fileindex_entry_stage_get(ie
) == GOT_FILEIDX_STAGE_NONE
)
6630 return got_error_path(pe
->path
,
6631 GOT_ERR_FILE_NOT_STAGED
);
6637 const struct got_error
*
6638 got_worktree_commit(struct got_object_id
**new_commit_id
,
6639 struct got_worktree
*worktree
, struct got_pathlist_head
*paths
,
6640 const char *author
, const char *committer
, int allow_bad_symlinks
,
6641 int show_diff
, int commit_conflicts
,
6642 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
6643 got_worktree_status_cb status_cb
, void *status_arg
,
6644 struct got_repository
*repo
)
6646 const struct got_error
*err
= NULL
, *unlockerr
= NULL
, *sync_err
;
6647 struct got_fileindex
*fileindex
= NULL
;
6648 char *fileindex_path
= NULL
;
6649 struct got_pathlist_head commitable_paths
;
6650 struct collect_commitables_arg cc_arg
;
6651 struct got_pathlist_entry
*pe
;
6652 struct got_reference
*head_ref
= NULL
;
6653 struct got_object_id
*head_commit_id
= NULL
;
6654 char *diff_path
= NULL
;
6655 int have_staged_files
= 0;
6657 *new_commit_id
= NULL
;
6659 memset(&cc_arg
, 0, sizeof(cc_arg
));
6660 RB_INIT(&commitable_paths
);
6662 err
= lock_worktree(worktree
, LOCK_EX
);
6666 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
6670 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
6674 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
6675 got_repo_get_object_format(repo
));
6679 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
6680 &have_staged_files
);
6681 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6683 if (have_staged_files
) {
6684 err
= check_non_staged_files(fileindex
, paths
);
6689 cc_arg
.commitable_paths
= &commitable_paths
;
6690 cc_arg
.worktree
= worktree
;
6691 cc_arg
.fileindex
= fileindex
;
6693 cc_arg
.have_staged_files
= have_staged_files
;
6694 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
6695 cc_arg
.diff_header_shown
= 0;
6696 cc_arg
.commit_conflicts
= commit_conflicts
;
6698 err
= got_opentemp_named(&diff_path
, &cc_arg
.diff_outfile
,
6699 GOT_TMPDIR_STR
"/got", ".diff");
6702 cc_arg
.f1
= got_opentemp();
6703 if (cc_arg
.f1
== NULL
) {
6704 err
= got_error_from_errno("got_opentemp");
6707 cc_arg
.f2
= got_opentemp();
6708 if (cc_arg
.f2
== NULL
) {
6709 err
= got_error_from_errno("got_opentemp");
6714 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
6715 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
6716 collect_commitables
, &cc_arg
, NULL
, NULL
, 0, 0);
6722 if (fflush(cc_arg
.diff_outfile
) == EOF
) {
6723 err
= got_error_from_errno("fflush");
6728 if (RB_EMPTY(&commitable_paths
)) {
6729 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
6733 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
6734 err
= check_path_is_commitable(pe
->path
, &commitable_paths
);
6739 RB_FOREACH(pe
, got_pathlist_head
, &commitable_paths
) {
6740 struct got_commitable
*ct
= pe
->data
;
6741 const char *ct_path
= ct
->in_repo_path
;
6743 while (ct_path
[0] == '/')
6745 err
= check_out_of_date(ct_path
, ct
->status
,
6746 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
6747 head_commit_id
, repo
, GOT_ERR_COMMIT_OUT_OF_DATE
);
6753 err
= commit_worktree(new_commit_id
, &commitable_paths
,
6754 head_commit_id
, NULL
, worktree
, author
, committer
,
6755 (diff_path
&& cc_arg
.diff_header_shown
) ? diff_path
: NULL
,
6756 commit_msg_cb
, commit_arg
, status_cb
, status_arg
, repo
);
6760 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
6761 *new_commit_id
, fileindex
, have_staged_files
);
6762 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6763 if (sync_err
&& err
== NULL
)
6767 got_fileindex_free(fileindex
);
6768 free(fileindex_path
);
6769 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6770 if (unlockerr
&& err
== NULL
)
6772 RB_FOREACH(pe
, got_pathlist_head
, &commitable_paths
) {
6773 struct got_commitable
*ct
= pe
->data
;
6775 free_commitable(ct
);
6777 got_pathlist_free(&commitable_paths
, GOT_PATHLIST_FREE_NONE
);
6778 if (diff_path
&& unlink(diff_path
) == -1 && err
== NULL
)
6779 err
= got_error_from_errno2("unlink", diff_path
);
6781 if (cc_arg
.diff_outfile
&& fclose(cc_arg
.diff_outfile
) == EOF
&&
6783 err
= got_error_from_errno("fclose");
6788 got_commitable_get_path(struct got_commitable
*ct
)
6794 got_commitable_get_status(struct got_commitable
*ct
)
6799 struct check_rebase_ok_arg
{
6800 struct got_worktree
*worktree
;
6801 struct got_repository
*repo
;
6804 static const struct got_error
*
6805 check_rebase_ok(void *arg
, struct got_fileindex_entry
*ie
)
6807 const struct got_error
*err
= NULL
;
6808 struct check_rebase_ok_arg
*a
= arg
;
6809 unsigned char status
;
6813 /* Reject rebase of a work tree with mixed base commits. */
6814 if (got_object_id_cmp(&ie
->commit
, a
->worktree
->base_commit_id
))
6815 return got_error(GOT_ERR_MIXED_COMMITS
);
6817 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
6819 return got_error_from_errno("asprintf");
6821 /* Reject rebase of a work tree with modified or staged files. */
6822 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
6827 if (status
!= GOT_STATUS_NO_CHANGE
)
6828 return got_error(GOT_ERR_MODIFIED
);
6829 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
6830 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
6835 const struct got_error
*
6836 got_worktree_rebase_prepare(struct got_reference
**new_base_branch_ref
,
6837 struct got_reference
**tmp_branch
, struct got_fileindex
**fileindex
,
6838 struct got_worktree
*worktree
, struct got_reference
*branch
,
6839 struct got_repository
*repo
)
6841 const struct got_error
*err
= NULL
;
6842 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6843 char *branch_ref_name
= NULL
;
6844 char *fileindex_path
= NULL
;
6845 struct check_rebase_ok_arg ok_arg
;
6846 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
6847 struct got_object_id
*wt_branch_tip
= NULL
;
6849 *new_base_branch_ref
= NULL
;
6853 err
= lock_worktree(worktree
, LOCK_EX
);
6857 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
,
6858 got_repo_get_object_format(repo
));
6862 ok_arg
.worktree
= worktree
;
6864 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6869 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6873 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6877 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6881 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6886 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
6889 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
6890 err
= got_error(GOT_ERR_REBASE_OUT_OF_DATE
);
6894 err
= got_ref_alloc_symref(new_base_branch_ref
,
6895 new_base_branch_ref_name
, wt_branch
);
6898 err
= got_ref_write(*new_base_branch_ref
, repo
);
6902 /* TODO Lock original branch's ref while rebasing? */
6904 err
= got_ref_alloc_symref(&branch_ref
, branch_ref_name
, branch
);
6908 err
= got_ref_write(branch_ref
, repo
);
6912 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6913 worktree
->base_commit_id
);
6916 err
= got_ref_write(*tmp_branch
, repo
);
6920 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6924 free(fileindex_path
);
6925 free(tmp_branch_name
);
6926 free(new_base_branch_ref_name
);
6927 free(branch_ref_name
);
6929 got_ref_close(branch_ref
);
6931 got_ref_close(wt_branch
);
6932 free(wt_branch_tip
);
6934 if (*new_base_branch_ref
) {
6935 got_ref_close(*new_base_branch_ref
);
6936 *new_base_branch_ref
= NULL
;
6939 got_ref_close(*tmp_branch
);
6943 got_fileindex_free(*fileindex
);
6946 lock_worktree(worktree
, LOCK_SH
);
6951 const struct got_error
*
6952 got_worktree_rebase_continue(struct got_object_id
**commit_id
,
6953 struct got_reference
**new_base_branch
, struct got_reference
**tmp_branch
,
6954 struct got_reference
**branch
, struct got_fileindex
**fileindex
,
6955 struct got_worktree
*worktree
, struct got_repository
*repo
)
6957 const struct got_error
*err
;
6958 char *commit_ref_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6959 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
6960 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
6961 char *fileindex_path
= NULL
;
6962 int have_staged_files
= 0;
6965 *new_base_branch
= NULL
;
6970 err
= lock_worktree(worktree
, LOCK_EX
);
6974 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
,
6975 got_repo_get_object_format(repo
));
6979 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
6980 &have_staged_files
);
6981 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6983 if (have_staged_files
) {
6984 err
= got_error(GOT_ERR_STAGED_PATHS
);
6988 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6992 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6996 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
7000 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
7004 err
= got_ref_open(&branch_ref
, repo
, branch_ref_name
, 0);
7008 err
= got_ref_open(branch
, repo
,
7009 got_ref_get_symref_target(branch_ref
), 0);
7013 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7017 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
7021 err
= got_ref_open(new_base_branch
, repo
,
7022 new_base_branch_ref_name
, 0);
7026 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
7030 free(commit_ref_name
);
7031 free(branch_ref_name
);
7032 free(fileindex_path
);
7034 got_ref_close(commit_ref
);
7036 got_ref_close(branch_ref
);
7041 got_ref_close(*tmp_branch
);
7044 if (*new_base_branch
) {
7045 got_ref_close(*new_base_branch
);
7046 *new_base_branch
= NULL
;
7049 got_ref_close(*branch
);
7053 got_fileindex_free(*fileindex
);
7056 lock_worktree(worktree
, LOCK_SH
);
7061 const struct got_error
*
7062 got_worktree_rebase_in_progress(int *in_progress
, struct got_worktree
*worktree
)
7064 const struct got_error
*err
;
7065 char *tmp_branch_name
= NULL
;
7067 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
7071 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
7072 free(tmp_branch_name
);
7076 const struct got_error
*
7077 got_worktree_rebase_info(char **new_base_branch_name
, char **branch_name
,
7078 struct got_worktree
*worktree
, struct got_repository
*repo
)
7080 const struct got_error
*err
;
7081 char *new_base_branch_ref_name
= NULL
;
7082 char *branch_ref_name
= NULL
;
7083 struct got_reference
*branch_ref
= NULL
, *branch
= NULL
;
7084 struct got_reference
*new_base_branch
= NULL
;
7086 *new_base_branch_name
= NULL
;
7087 *branch_name
= NULL
;
7089 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
7093 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
7097 err
= got_ref_open(&branch_ref
, repo
, branch_ref_name
, 0);
7101 err
= got_ref_open(&branch
, repo
,
7102 got_ref_get_symref_target(branch_ref
), 0);
7106 err
= got_ref_open(&new_base_branch
, repo
,
7107 new_base_branch_ref_name
, 0);
7111 if (!got_ref_is_symbolic(new_base_branch
)) {
7112 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
7113 "%s is not a symbolic reference",
7114 got_ref_get_name(branch_ref
));
7118 *new_base_branch_name
= strdup(got_ref_get_symref_target(
7120 if (*new_base_branch_name
== NULL
) {
7121 err
= got_error_from_errno("strdup");
7124 *branch_name
= strdup(got_ref_get_name(branch
));
7125 if (*branch_name
== NULL
) {
7126 err
= got_error_from_errno("strdup");
7130 free(branch_ref_name
);
7132 got_ref_close(branch_ref
);
7133 if (new_base_branch
)
7134 got_ref_close(new_base_branch
);
7136 got_ref_close(branch
);
7140 static const struct got_error
*
7141 collect_rebase_commit_msg(struct got_pathlist_head
*commitable_paths
,
7142 const char *diff_path
, char **logmsg
, void *arg
)
7148 static const struct got_error
*
7149 rebase_status(void *arg
, unsigned char status
, unsigned char staged_status
,
7150 const char *path
, struct got_object_id
*blob_id
,
7151 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
7152 int dirfd
, const char *de_name
)
7157 struct collect_merged_paths_arg
{
7158 got_worktree_checkout_cb progress_cb
;
7160 struct got_pathlist_head
*merged_paths
;
7163 static const struct got_error
*
7164 collect_merged_paths(void *arg
, unsigned char status
, const char *path
)
7166 const struct got_error
*err
;
7167 struct collect_merged_paths_arg
*a
= arg
;
7169 struct got_pathlist_entry
*new;
7171 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path
);
7175 if (status
!= GOT_STATUS_MERGE
&&
7176 status
!= GOT_STATUS_ADD
&&
7177 status
!= GOT_STATUS_DELETE
&&
7178 status
!= GOT_STATUS_CONFLICT
)
7183 return got_error_from_errno("strdup");
7185 err
= got_pathlist_insert(&new, a
->merged_paths
, p
, NULL
);
7186 if (err
|| new == NULL
)
7191 static const struct got_error
*
7192 store_commit_id(const char *commit_ref_name
, struct got_object_id
*commit_id
,
7193 int is_rebase
, struct got_repository
*repo
)
7195 const struct got_error
*err
;
7196 struct got_reference
*commit_ref
= NULL
;
7198 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7200 if (err
->code
!= GOT_ERR_NOT_REF
)
7202 err
= got_ref_alloc(&commit_ref
, commit_ref_name
, commit_id
);
7205 err
= got_ref_write(commit_ref
, repo
);
7208 } else if (is_rebase
) {
7209 struct got_object_id
*stored_id
;
7212 err
= got_ref_resolve(&stored_id
, repo
, commit_ref
);
7215 cmp
= got_object_id_cmp(commit_id
, stored_id
);
7218 err
= got_error(GOT_ERR_REBASE_COMMITID
);
7224 got_ref_close(commit_ref
);
7228 static const struct got_error
*
7229 rebase_merge_files(struct got_pathlist_head
*merged_paths
,
7230 const char *commit_ref_name
, struct got_worktree
*worktree
,
7231 struct got_fileindex
*fileindex
, struct got_object_id
*parent_commit_id
,
7232 struct got_object_id
*commit_id
, struct got_repository
*repo
,
7233 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7234 got_cancel_cb cancel_cb
, void *cancel_arg
)
7236 const struct got_error
*err
;
7237 struct got_reference
*commit_ref
= NULL
;
7238 struct collect_merged_paths_arg cmp_arg
;
7239 char *fileindex_path
;
7241 /* Work tree is locked/unlocked during rebase preparation/teardown. */
7243 err
= get_fileindex_path(&fileindex_path
, worktree
);
7247 cmp_arg
.progress_cb
= progress_cb
;
7248 cmp_arg
.progress_arg
= progress_arg
;
7249 cmp_arg
.merged_paths
= merged_paths
;
7250 err
= merge_files(worktree
, fileindex
, fileindex_path
,
7251 parent_commit_id
, commit_id
, repo
, collect_merged_paths
,
7252 &cmp_arg
, cancel_cb
, cancel_arg
);
7254 got_ref_close(commit_ref
);
7258 const struct got_error
*
7259 got_worktree_rebase_merge_files(struct got_pathlist_head
*merged_paths
,
7260 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
7261 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
7262 struct got_repository
*repo
,
7263 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7264 got_cancel_cb cancel_cb
, void *cancel_arg
)
7266 const struct got_error
*err
;
7267 char *commit_ref_name
;
7269 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
7273 err
= store_commit_id(commit_ref_name
, commit_id
, 1, repo
);
7277 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
7278 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
7279 progress_arg
, cancel_cb
, cancel_arg
);
7281 free(commit_ref_name
);
7285 const struct got_error
*
7286 got_worktree_histedit_merge_files(struct got_pathlist_head
*merged_paths
,
7287 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
7288 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
7289 struct got_repository
*repo
,
7290 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7291 got_cancel_cb cancel_cb
, void *cancel_arg
)
7293 const struct got_error
*err
;
7294 char *commit_ref_name
;
7296 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7300 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
7304 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
7305 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
7306 progress_arg
, cancel_cb
, cancel_arg
);
7308 free(commit_ref_name
);
7312 static const struct got_error
*
7313 rebase_commit(struct got_object_id
**new_commit_id
,
7314 struct got_pathlist_head
*merged_paths
, struct got_reference
*commit_ref
,
7315 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
7316 struct got_reference
*tmp_branch
, const char *committer
,
7317 struct got_commit_object
*orig_commit
, const char *new_logmsg
,
7318 int allow_conflict
, struct got_repository
*repo
)
7320 const struct got_error
*err
, *sync_err
;
7321 struct got_pathlist_head commitable_paths
;
7322 struct collect_commitables_arg cc_arg
;
7323 char *fileindex_path
= NULL
;
7324 struct got_reference
*head_ref
= NULL
;
7325 struct got_object_id
*head_commit_id
= NULL
;
7326 char *logmsg
= NULL
;
7328 memset(&cc_arg
, 0, sizeof(cc_arg
));
7329 RB_INIT(&commitable_paths
);
7330 *new_commit_id
= NULL
;
7332 /* Work tree is locked/unlocked during rebase preparation/teardown. */
7334 err
= get_fileindex_path(&fileindex_path
, worktree
);
7338 cc_arg
.commitable_paths
= &commitable_paths
;
7339 cc_arg
.worktree
= worktree
;
7341 cc_arg
.have_staged_files
= 0;
7342 cc_arg
.commit_conflicts
= allow_conflict
;
7344 * If possible get the status of individual files directly to
7345 * avoid crawling the entire work tree once per rebased commit.
7347 * Ideally, merged_paths would contain a list of commitables
7348 * we could use so we could skip worktree_status() entirely.
7349 * However, we would then need carefully keep track of cumulative
7350 * effects of operations such as file additions and deletions
7351 * in 'got histedit -f' (folding multiple commits into one),
7352 * and this extra complexity is not really worth it.
7355 struct got_pathlist_entry
*pe
;
7356 RB_FOREACH(pe
, got_pathlist_head
, merged_paths
) {
7357 err
= worktree_status(worktree
, pe
->path
, fileindex
,
7358 repo
, collect_commitables
, &cc_arg
, NULL
, NULL
, 1,
7364 err
= worktree_status(worktree
, "", fileindex
, repo
,
7365 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
7370 if (RB_EMPTY(&commitable_paths
)) {
7371 /* No-op change; commit will be elided. */
7372 err
= got_ref_delete(commit_ref
, repo
);
7375 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
7379 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
7383 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
7388 logmsg
= strdup(new_logmsg
);
7389 if (logmsg
== NULL
) {
7390 err
= got_error_from_errno("strdup");
7394 err
= got_object_commit_get_logmsg(&logmsg
, orig_commit
);
7399 /* NB: commit_worktree will call free(logmsg) */
7400 err
= commit_worktree(new_commit_id
, &commitable_paths
, head_commit_id
,
7401 NULL
, worktree
, got_object_commit_get_author(orig_commit
),
7402 committer
? committer
:
7403 got_object_commit_get_committer(orig_commit
), NULL
,
7404 collect_rebase_commit_msg
, logmsg
, rebase_status
, NULL
, repo
);
7408 err
= got_ref_change_ref(tmp_branch
, *new_commit_id
);
7412 err
= got_ref_delete(commit_ref
, repo
);
7416 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
7417 *new_commit_id
, fileindex
, 0);
7418 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7419 if (sync_err
&& err
== NULL
)
7422 free(fileindex_path
);
7423 free(head_commit_id
);
7425 got_ref_close(head_ref
);
7427 free(*new_commit_id
);
7428 *new_commit_id
= NULL
;
7433 const struct got_error
*
7434 got_worktree_rebase_commit(struct got_object_id
**new_commit_id
,
7435 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
7436 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7437 const char *committer
, struct got_commit_object
*orig_commit
,
7438 struct got_object_id
*orig_commit_id
, int allow_conflict
,
7439 struct got_repository
*repo
)
7441 const struct got_error
*err
;
7442 char *commit_ref_name
;
7443 struct got_reference
*commit_ref
= NULL
;
7444 struct got_object_id
*commit_id
= NULL
;
7446 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
7450 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7453 err
= got_ref_resolve(&commit_id
, repo
, commit_ref
);
7456 if (got_object_id_cmp(commit_id
, orig_commit_id
) != 0) {
7457 err
= got_error(GOT_ERR_REBASE_COMMITID
);
7461 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
7462 worktree
, fileindex
, tmp_branch
, committer
, orig_commit
,
7463 NULL
, allow_conflict
, repo
);
7466 got_ref_close(commit_ref
);
7467 free(commit_ref_name
);
7472 const struct got_error
*
7473 got_worktree_histedit_commit(struct got_object_id
**new_commit_id
,
7474 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
7475 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7476 const char *committer
, struct got_commit_object
*orig_commit
,
7477 struct got_object_id
*orig_commit_id
, const char *new_logmsg
,
7478 int allow_conflict
, struct got_repository
*repo
)
7480 const struct got_error
*err
;
7481 char *commit_ref_name
;
7482 struct got_reference
*commit_ref
= NULL
;
7484 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7488 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7492 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
7493 worktree
, fileindex
, tmp_branch
, committer
, orig_commit
,
7494 new_logmsg
, allow_conflict
, repo
);
7497 got_ref_close(commit_ref
);
7498 free(commit_ref_name
);
7502 const struct got_error
*
7503 got_worktree_rebase_postpone(struct got_worktree
*worktree
,
7504 struct got_fileindex
*fileindex
)
7507 got_fileindex_free(fileindex
);
7508 return lock_worktree(worktree
, LOCK_SH
);
7511 static const struct got_error
*
7512 delete_ref(const char *name
, struct got_repository
*repo
)
7514 const struct got_error
*err
;
7515 struct got_reference
*ref
;
7517 err
= got_ref_open(&ref
, repo
, name
, 0);
7519 if (err
->code
== GOT_ERR_NOT_REF
)
7524 err
= got_ref_delete(ref
, repo
);
7529 static const struct got_error
*
7530 delete_rebase_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7532 const struct got_error
*err
;
7533 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
7534 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
7536 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
7539 err
= delete_ref(tmp_branch_name
, repo
);
7543 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
7546 err
= delete_ref(new_base_branch_ref_name
, repo
);
7550 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
7553 err
= delete_ref(branch_ref_name
, repo
);
7557 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
7560 err
= delete_ref(commit_ref_name
, repo
);
7565 free(tmp_branch_name
);
7566 free(new_base_branch_ref_name
);
7567 free(branch_ref_name
);
7568 free(commit_ref_name
);
7572 static const struct got_error
*
7573 create_backup_ref(const char *backup_ref_prefix
, struct got_reference
*branch
,
7574 struct got_object_id
*new_commit_id
, struct got_repository
*repo
)
7576 const struct got_error
*err
;
7577 struct got_reference
*ref
= NULL
;
7578 struct got_object_id
*old_commit_id
= NULL
;
7579 const char *branch_name
= NULL
;
7580 char *new_id_str
= NULL
;
7581 char *refname
= NULL
;
7583 branch_name
= got_ref_get_name(branch
);
7584 if (strncmp(branch_name
, "refs/heads/", 11) != 0)
7585 return got_error(GOT_ERR_BAD_REF_NAME
); /* should not happen */
7588 err
= got_object_id_str(&new_id_str
, new_commit_id
);
7592 if (asprintf(&refname
, "%s/%s/%s", backup_ref_prefix
, branch_name
,
7593 new_id_str
) == -1) {
7594 err
= got_error_from_errno("asprintf");
7598 err
= got_ref_resolve(&old_commit_id
, repo
, branch
);
7602 err
= got_ref_alloc(&ref
, refname
, old_commit_id
);
7606 err
= got_ref_write(ref
, repo
);
7610 free(old_commit_id
);
7616 const struct got_error
*
7617 got_worktree_rebase_complete(struct got_worktree
*worktree
,
7618 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7619 struct got_reference
*rebased_branch
, struct got_repository
*repo
,
7622 const struct got_error
*err
, *unlockerr
, *sync_err
;
7623 struct got_object_id
*new_head_commit_id
= NULL
;
7624 char *fileindex_path
= NULL
;
7626 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
7630 if (create_backup
) {
7631 err
= create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX
,
7632 rebased_branch
, new_head_commit_id
, repo
);
7637 err
= got_ref_change_ref(rebased_branch
, new_head_commit_id
);
7641 err
= got_ref_write(rebased_branch
, repo
);
7645 err
= got_worktree_set_head_ref(worktree
, rebased_branch
);
7649 err
= delete_rebase_refs(worktree
, repo
);
7653 err
= get_fileindex_path(&fileindex_path
, worktree
);
7656 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7657 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7658 if (sync_err
&& err
== NULL
)
7661 got_fileindex_free(fileindex
);
7662 free(fileindex_path
);
7663 free(new_head_commit_id
);
7664 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7665 if (unlockerr
&& err
== NULL
)
7670 static const struct got_error
*
7671 get_paths_changed_between_commits(struct got_pathlist_head
*paths
,
7672 struct got_object_id
*id1
, struct got_object_id
*id2
,
7673 struct got_repository
*repo
)
7675 const struct got_error
*err
;
7676 struct got_commit_object
*commit1
= NULL
, *commit2
= NULL
;
7677 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
7680 err
= got_object_open_as_commit(&commit1
, repo
, id1
);
7684 err
= got_object_open_as_tree(&tree1
, repo
,
7685 got_object_commit_get_tree_id(commit1
));
7691 err
= got_object_open_as_commit(&commit2
, repo
, id2
);
7695 err
= got_object_open_as_tree(&tree2
, repo
,
7696 got_object_commit_get_tree_id(commit2
));
7701 err
= got_diff_tree(tree1
, tree2
, NULL
, NULL
, -1, -1, "", "", repo
,
7702 got_diff_tree_collect_changed_paths
, paths
, 0);
7707 got_object_commit_close(commit1
);
7709 got_object_commit_close(commit2
);
7711 got_object_tree_close(tree1
);
7713 got_object_tree_close(tree2
);
7717 static const struct got_error
*
7718 get_paths_added_between_commits(struct got_pathlist_head
*added_paths
,
7719 struct got_object_id
*id1
, struct got_object_id
*id2
,
7720 const char *path_prefix
, struct got_repository
*repo
)
7722 const struct got_error
*err
;
7723 struct got_pathlist_head merged_paths
;
7724 struct got_pathlist_entry
*pe
;
7725 char *abspath
= NULL
, *wt_path
= NULL
;
7727 RB_INIT(&merged_paths
);
7729 err
= get_paths_changed_between_commits(&merged_paths
, id1
, id2
, repo
);
7733 RB_FOREACH(pe
, got_pathlist_head
, &merged_paths
) {
7734 struct got_diff_changed_path
*change
= pe
->data
;
7736 if (change
->status
!= GOT_STATUS_ADD
)
7739 if (got_path_is_root_dir(path_prefix
)) {
7740 wt_path
= strdup(pe
->path
);
7741 if (wt_path
== NULL
) {
7742 err
= got_error_from_errno("strdup");
7746 if (asprintf(&abspath
, "/%s", pe
->path
) == -1) {
7747 err
= got_error_from_errno("asprintf");
7751 err
= got_path_skip_common_ancestor(&wt_path
,
7752 path_prefix
, abspath
);
7759 err
= got_pathlist_insert(NULL
, added_paths
, wt_path
, NULL
);
7766 got_pathlist_free(&merged_paths
, GOT_PATHLIST_FREE_ALL
);
7772 static const struct got_error
*
7773 get_paths_added_in_commit(struct got_pathlist_head
*added_paths
,
7774 struct got_object_id
*id
, const char *path_prefix
,
7775 struct got_repository
*repo
)
7777 const struct got_error
*err
;
7778 struct got_commit_object
*commit
= NULL
;
7779 struct got_object_qid
*pid
;
7781 err
= got_object_open_as_commit(&commit
, repo
, id
);
7785 pid
= STAILQ_FIRST(got_object_commit_get_parent_ids(commit
));
7787 err
= get_paths_added_between_commits(added_paths
,
7788 pid
? &pid
->id
: NULL
, id
, path_prefix
, repo
);
7793 got_object_commit_close(commit
);
7797 const struct got_error
*
7798 got_worktree_rebase_abort(struct got_worktree
*worktree
,
7799 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7800 struct got_reference
*new_base_branch
,
7801 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7803 const struct got_error
*err
, *unlockerr
, *sync_err
;
7804 struct got_reference
*resolved
= NULL
;
7805 struct got_object_id
*commit_id
= NULL
;
7806 struct got_object_id
*merged_commit_id
= NULL
;
7807 struct got_commit_object
*commit
= NULL
;
7808 char *fileindex_path
= NULL
;
7809 char *commit_ref_name
= NULL
;
7810 struct got_reference
*commit_ref
= NULL
;
7811 struct revert_file_args rfa
;
7812 struct got_object_id
*tree_id
= NULL
;
7813 struct got_pathlist_head added_paths
;
7815 RB_INIT(&added_paths
);
7817 err
= lock_worktree(worktree
, LOCK_EX
);
7821 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
7825 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7829 err
= got_ref_resolve(&merged_commit_id
, repo
, commit_ref
);
7834 * Determine which files in added status can be safely removed
7835 * from disk while reverting changes in the work tree.
7836 * We want to avoid deleting unrelated files which were added by
7837 * the user for conflict resolution purposes.
7839 err
= get_paths_added_in_commit(&added_paths
, merged_commit_id
,
7840 got_worktree_get_path_prefix(worktree
), repo
);
7844 err
= got_ref_open(&resolved
, repo
,
7845 got_ref_get_symref_target(new_base_branch
), 0);
7849 err
= got_worktree_set_head_ref(worktree
, resolved
);
7854 * XXX commits to the base branch could have happened while
7855 * we were busy rebasing; should we store the original commit ID
7856 * when rebase begins and read it back here?
7858 err
= got_ref_resolve(&commit_id
, repo
, resolved
);
7862 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
7866 err
= got_object_open_as_commit(&commit
, repo
,
7867 worktree
->base_commit_id
);
7871 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
7872 worktree
->path_prefix
);
7876 err
= delete_rebase_refs(worktree
, repo
);
7880 err
= get_fileindex_path(&fileindex_path
, worktree
);
7884 rfa
.worktree
= worktree
;
7885 rfa
.fileindex
= fileindex
;
7886 rfa
.progress_cb
= progress_cb
;
7887 rfa
.progress_arg
= progress_arg
;
7888 rfa
.patch_cb
= NULL
;
7889 rfa
.patch_arg
= NULL
;
7891 rfa
.unlink_added_files
= 1;
7892 rfa
.added_files_to_unlink
= &added_paths
;
7893 err
= worktree_status(worktree
, "", fileindex
, repo
,
7894 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
7898 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7899 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7901 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7902 if (sync_err
&& err
== NULL
)
7905 got_pathlist_free(&added_paths
, GOT_PATHLIST_FREE_PATH
);
7906 got_ref_close(resolved
);
7909 free(merged_commit_id
);
7911 got_object_commit_close(commit
);
7913 got_fileindex_free(fileindex
);
7914 free(fileindex_path
);
7915 free(commit_ref_name
);
7917 got_ref_close(commit_ref
);
7919 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7920 if (unlockerr
&& err
== NULL
)
7925 const struct got_error
*
7926 got_worktree_histedit_prepare(struct got_reference
**tmp_branch
,
7927 struct got_reference
**branch_ref
, struct got_object_id
**base_commit_id
,
7928 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
7929 struct got_repository
*repo
)
7931 const struct got_error
*err
= NULL
;
7932 char *tmp_branch_name
= NULL
;
7933 char *branch_ref_name
= NULL
;
7934 char *base_commit_ref_name
= NULL
;
7935 char *fileindex_path
= NULL
;
7936 struct check_rebase_ok_arg ok_arg
;
7937 struct got_reference
*wt_branch
= NULL
;
7938 struct got_reference
*base_commit_ref
= NULL
;
7942 *base_commit_id
= NULL
;
7945 err
= lock_worktree(worktree
, LOCK_EX
);
7949 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
,
7950 got_repo_get_object_format(repo
));
7954 ok_arg
.worktree
= worktree
;
7956 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7961 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7965 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7969 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7974 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
7979 err
= got_ref_alloc_symref(branch_ref
, branch_ref_name
, wt_branch
);
7983 err
= got_ref_write(*branch_ref
, repo
);
7987 err
= got_ref_alloc(&base_commit_ref
, base_commit_ref_name
,
7988 worktree
->base_commit_id
);
7991 err
= got_ref_write(base_commit_ref
, repo
);
7994 *base_commit_id
= got_object_id_dup(worktree
->base_commit_id
);
7995 if (*base_commit_id
== NULL
) {
7996 err
= got_error_from_errno("got_object_id_dup");
8000 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
8001 worktree
->base_commit_id
);
8004 err
= got_ref_write(*tmp_branch
, repo
);
8008 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
8012 free(fileindex_path
);
8013 free(tmp_branch_name
);
8014 free(branch_ref_name
);
8015 free(base_commit_ref_name
);
8017 got_ref_close(wt_branch
);
8020 got_ref_close(*branch_ref
);
8024 got_ref_close(*tmp_branch
);
8027 free(*base_commit_id
);
8029 got_fileindex_free(*fileindex
);
8032 lock_worktree(worktree
, LOCK_SH
);
8037 const struct got_error
*
8038 got_worktree_histedit_postpone(struct got_worktree
*worktree
,
8039 struct got_fileindex
*fileindex
)
8042 got_fileindex_free(fileindex
);
8043 return lock_worktree(worktree
, LOCK_SH
);
8046 const struct got_error
*
8047 got_worktree_histedit_in_progress(int *in_progress
,
8048 struct got_worktree
*worktree
)
8050 const struct got_error
*err
;
8051 char *tmp_branch_name
= NULL
;
8053 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
8057 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
8058 free(tmp_branch_name
);
8062 const struct got_error
*
8063 got_worktree_histedit_continue(struct got_object_id
**commit_id
,
8064 struct got_reference
**tmp_branch
, struct got_reference
**branch_ref
,
8065 struct got_object_id
**base_commit_id
, struct got_fileindex
**fileindex
,
8066 struct got_worktree
*worktree
, struct got_repository
*repo
)
8068 const struct got_error
*err
;
8069 char *commit_ref_name
= NULL
, *base_commit_ref_name
= NULL
;
8070 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
8071 struct got_reference
*commit_ref
= NULL
;
8072 struct got_reference
*base_commit_ref
= NULL
;
8073 char *fileindex_path
= NULL
;
8074 int have_staged_files
= 0;
8079 *base_commit_id
= NULL
;
8082 err
= lock_worktree(worktree
, LOCK_EX
);
8086 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
,
8087 got_repo_get_object_format(repo
));
8091 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
8092 &have_staged_files
);
8093 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
8095 if (have_staged_files
) {
8096 err
= got_error(GOT_ERR_STAGED_PATHS
);
8100 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
8104 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
8108 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
8112 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
8117 err
= got_ref_open(branch_ref
, repo
, branch_ref_name
, 0);
8121 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
8124 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
8128 err
= got_ref_open(&base_commit_ref
, repo
, base_commit_ref_name
, 0);
8131 err
= got_ref_resolve(base_commit_id
, repo
, base_commit_ref
);
8135 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
8139 free(commit_ref_name
);
8140 free(branch_ref_name
);
8141 free(fileindex_path
);
8143 got_ref_close(commit_ref
);
8144 if (base_commit_ref
)
8145 got_ref_close(base_commit_ref
);
8149 free(*base_commit_id
);
8150 *base_commit_id
= NULL
;
8152 got_ref_close(*tmp_branch
);
8156 got_ref_close(*branch_ref
);
8160 got_fileindex_free(*fileindex
);
8163 lock_worktree(worktree
, LOCK_EX
);
8168 const struct got_error
*
8169 got_worktree_histedit_info(char **branch_name
,
8170 struct got_worktree
*worktree
, struct got_repository
*repo
)
8172 const struct got_error
*err
;
8173 struct got_reference
*branch_ref
= NULL
;
8174 char *branch_ref_name
= NULL
;
8176 *branch_name
= NULL
;
8178 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
8182 err
= got_ref_open(&branch_ref
, repo
, branch_ref_name
, 0);
8186 if (!got_ref_is_symbolic(branch_ref
)) {
8187 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
8188 "%s is not a symbolic reference",
8189 got_ref_get_name(branch_ref
));
8193 *branch_name
= strdup(got_ref_get_symref_target(branch_ref
));
8194 if (*branch_name
== NULL
) {
8195 err
= got_error_from_errno("strdup");
8199 free(branch_ref_name
);
8201 got_ref_close(branch_ref
);
8204 *branch_name
= NULL
;
8209 static const struct got_error
*
8210 delete_histedit_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
8212 const struct got_error
*err
;
8213 char *tmp_branch_name
= NULL
, *base_commit_ref_name
= NULL
;
8214 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
8216 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
8219 err
= delete_ref(tmp_branch_name
, repo
);
8223 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
8227 err
= delete_ref(base_commit_ref_name
, repo
);
8231 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
8234 err
= delete_ref(branch_ref_name
, repo
);
8238 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
8241 err
= delete_ref(commit_ref_name
, repo
);
8245 free(tmp_branch_name
);
8246 free(base_commit_ref_name
);
8247 free(branch_ref_name
);
8248 free(commit_ref_name
);
8252 const struct got_error
*
8253 got_worktree_histedit_abort(struct got_worktree
*worktree
,
8254 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
8255 struct got_reference
*branch
, struct got_object_id
*base_commit_id
,
8256 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
8258 const struct got_error
*err
, *unlockerr
, *sync_err
;
8259 struct got_reference
*resolved
= NULL
;
8260 char *fileindex_path
= NULL
;
8261 struct got_object_id
*merged_commit_id
= NULL
;
8262 struct got_commit_object
*commit
= NULL
;
8263 char *commit_ref_name
= NULL
;
8264 struct got_reference
*commit_ref
= NULL
;
8265 struct got_object_id
*tree_id
= NULL
;
8266 struct revert_file_args rfa
;
8267 struct got_pathlist_head added_paths
;
8269 RB_INIT(&added_paths
);
8271 err
= lock_worktree(worktree
, LOCK_EX
);
8275 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
8279 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
8281 if (err
->code
!= GOT_ERR_NOT_REF
)
8283 /* Can happen on early abort due to invalid histedit script. */
8288 err
= got_ref_resolve(&merged_commit_id
, repo
, commit_ref
);
8293 * Determine which files in added status can be safely removed
8294 * from disk while reverting changes in the work tree.
8295 * We want to avoid deleting unrelated files added by the
8296 * user during conflict resolution or during histedit -e.
8298 err
= get_paths_added_in_commit(&added_paths
, merged_commit_id
,
8299 got_worktree_get_path_prefix(worktree
), repo
);
8304 err
= got_ref_open(&resolved
, repo
,
8305 got_ref_get_symref_target(branch
), 0);
8309 err
= got_worktree_set_head_ref(worktree
, resolved
);
8313 err
= got_worktree_set_base_commit_id(worktree
, repo
, base_commit_id
);
8317 err
= got_object_open_as_commit(&commit
, repo
,
8318 worktree
->base_commit_id
);
8322 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
8323 worktree
->path_prefix
);
8327 err
= delete_histedit_refs(worktree
, repo
);
8331 err
= get_fileindex_path(&fileindex_path
, worktree
);
8335 rfa
.worktree
= worktree
;
8336 rfa
.fileindex
= fileindex
;
8337 rfa
.progress_cb
= progress_cb
;
8338 rfa
.progress_arg
= progress_arg
;
8339 rfa
.patch_cb
= NULL
;
8340 rfa
.patch_arg
= NULL
;
8342 rfa
.unlink_added_files
= 1;
8343 rfa
.added_files_to_unlink
= &added_paths
;
8344 err
= worktree_status(worktree
, "", fileindex
, repo
,
8345 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
8349 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
8350 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
8352 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8353 if (sync_err
&& err
== NULL
)
8357 got_ref_close(resolved
);
8359 got_ref_close(commit_ref
);
8360 free(merged_commit_id
);
8362 free(fileindex_path
);
8363 free(commit_ref_name
);
8365 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8366 if (unlockerr
&& err
== NULL
)
8371 const struct got_error
*
8372 got_worktree_histedit_complete(struct got_worktree
*worktree
,
8373 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
8374 struct got_reference
*edited_branch
, struct got_repository
*repo
)
8376 const struct got_error
*err
, *unlockerr
, *sync_err
;
8377 struct got_object_id
*new_head_commit_id
= NULL
;
8378 struct got_reference
*resolved
= NULL
;
8379 char *fileindex_path
= NULL
;
8381 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
8385 err
= got_ref_open(&resolved
, repo
,
8386 got_ref_get_symref_target(edited_branch
), 0);
8390 err
= create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX
,
8391 resolved
, new_head_commit_id
, repo
);
8395 err
= got_ref_change_ref(resolved
, new_head_commit_id
);
8399 err
= got_ref_write(resolved
, repo
);
8403 err
= got_worktree_set_head_ref(worktree
, resolved
);
8407 err
= delete_histedit_refs(worktree
, repo
);
8411 err
= get_fileindex_path(&fileindex_path
, worktree
);
8414 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
8415 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8416 if (sync_err
&& err
== NULL
)
8419 got_fileindex_free(fileindex
);
8420 free(fileindex_path
);
8421 free(new_head_commit_id
);
8422 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8423 if (unlockerr
&& err
== NULL
)
8428 const struct got_error
*
8429 got_worktree_histedit_skip_commit(struct got_worktree
*worktree
,
8430 struct got_object_id
*commit_id
, struct got_repository
*repo
)
8432 const struct got_error
*err
;
8433 char *commit_ref_name
;
8435 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
8439 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
8443 err
= delete_ref(commit_ref_name
, repo
);
8445 free(commit_ref_name
);
8449 const struct got_error
*
8450 got_worktree_integrate_prepare(struct got_fileindex
**fileindex
,
8451 struct got_reference
**branch_ref
, struct got_reference
**base_branch_ref
,
8452 struct got_worktree
*worktree
, const char *refname
,
8453 struct got_repository
*repo
)
8455 const struct got_error
*err
= NULL
;
8456 char *fileindex_path
= NULL
;
8457 struct check_rebase_ok_arg ok_arg
;
8461 *base_branch_ref
= NULL
;
8463 err
= lock_worktree(worktree
, LOCK_EX
);
8467 if (strcmp(refname
, got_worktree_get_head_ref_name(worktree
)) == 0) {
8468 err
= got_error_msg(GOT_ERR_SAME_BRANCH
,
8469 "cannot integrate a branch into itself; "
8470 "update -b or different branch name required");
8474 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
,
8475 got_repo_get_object_format(repo
));
8479 /* Preconditions are the same as for rebase. */
8480 ok_arg
.worktree
= worktree
;
8482 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
8487 err
= got_ref_open(branch_ref
, repo
, refname
, 1);
8491 err
= got_ref_open(base_branch_ref
, repo
,
8492 got_worktree_get_head_ref_name(worktree
), 1);
8496 got_ref_close(*branch_ref
);
8499 if (*base_branch_ref
) {
8500 got_ref_close(*base_branch_ref
);
8501 *base_branch_ref
= NULL
;
8504 got_fileindex_free(*fileindex
);
8507 lock_worktree(worktree
, LOCK_SH
);
8512 const struct got_error
*
8513 got_worktree_integrate_continue(struct got_worktree
*worktree
,
8514 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
8515 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
,
8516 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
8517 got_cancel_cb cancel_cb
, void *cancel_arg
)
8519 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8520 char *fileindex_path
= NULL
;
8521 struct got_object_id
*tree_id
= NULL
, *commit_id
= NULL
;
8522 struct got_commit_object
*commit
= NULL
;
8524 err
= get_fileindex_path(&fileindex_path
, worktree
);
8528 err
= got_ref_resolve(&commit_id
, repo
, branch_ref
);
8532 err
= got_object_open_as_commit(&commit
, repo
, commit_id
);
8536 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
8537 worktree
->path_prefix
);
8541 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
8545 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
, repo
,
8546 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
8550 err
= got_ref_change_ref(base_branch_ref
, commit_id
);
8554 err
= got_ref_write(base_branch_ref
, repo
);
8558 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
8560 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8561 if (sync_err
&& err
== NULL
)
8565 unlockerr
= got_ref_unlock(branch_ref
);
8566 if (unlockerr
&& err
== NULL
)
8568 got_ref_close(branch_ref
);
8570 unlockerr
= got_ref_unlock(base_branch_ref
);
8571 if (unlockerr
&& err
== NULL
)
8573 got_ref_close(base_branch_ref
);
8575 got_fileindex_free(fileindex
);
8576 free(fileindex_path
);
8579 got_object_commit_close(commit
);
8581 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8582 if (unlockerr
&& err
== NULL
)
8587 const struct got_error
*
8588 got_worktree_integrate_abort(struct got_worktree
*worktree
,
8589 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
8590 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
)
8592 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
8594 got_fileindex_free(fileindex
);
8596 err
= lock_worktree(worktree
, LOCK_SH
);
8598 unlockerr
= got_ref_unlock(branch_ref
);
8599 if (unlockerr
&& err
== NULL
)
8601 got_ref_close(branch_ref
);
8603 unlockerr
= got_ref_unlock(base_branch_ref
);
8604 if (unlockerr
&& err
== NULL
)
8606 got_ref_close(base_branch_ref
);
8611 const struct got_error
*
8612 got_worktree_merge_postpone(struct got_worktree
*worktree
,
8613 struct got_fileindex
*fileindex
)
8615 const struct got_error
*err
, *sync_err
;
8616 char *fileindex_path
= NULL
;
8618 err
= get_fileindex_path(&fileindex_path
, worktree
);
8622 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8624 err
= lock_worktree(worktree
, LOCK_SH
);
8625 if (sync_err
&& err
== NULL
)
8628 got_fileindex_free(fileindex
);
8629 free(fileindex_path
);
8633 static const struct got_error
*
8634 delete_merge_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
8636 const struct got_error
*err
;
8637 char *branch_refname
= NULL
, *commit_refname
= NULL
;
8639 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8642 err
= delete_ref(branch_refname
, repo
);
8646 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
8649 err
= delete_ref(commit_refname
, repo
);
8654 free(branch_refname
);
8655 free(commit_refname
);
8659 struct merge_commit_msg_arg
{
8660 struct got_worktree
*worktree
;
8661 const char *branch_name
;
8664 static const struct got_error
*
8665 merge_commit_msg_cb(struct got_pathlist_head
*commitable_paths
,
8666 const char *diff_path
, char **logmsg
, void *arg
)
8668 struct merge_commit_msg_arg
*a
= arg
;
8670 if (asprintf(logmsg
, "merge %s into %s\n", a
->branch_name
,
8671 got_worktree_get_head_ref_name(a
->worktree
)) == -1)
8672 return got_error_from_errno("asprintf");
8678 const struct got_error
*
8679 got_worktree_merge_branch(struct got_worktree
*worktree
,
8680 struct got_fileindex
*fileindex
,
8681 struct got_object_id
*yca_commit_id
,
8682 struct got_object_id
*branch_tip
,
8683 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
8684 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
8686 const struct got_error
*err
;
8687 char *fileindex_path
= NULL
;
8688 struct check_mixed_commits_args cma
;
8690 err
= get_fileindex_path(&fileindex_path
, worktree
);
8694 cma
.worktree
= worktree
;
8695 cma
.cancel_cb
= cancel_cb
;
8696 cma
.cancel_arg
= cancel_arg
;
8698 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
8703 err
= merge_files(worktree
, fileindex
, fileindex_path
, yca_commit_id
,
8704 branch_tip
, repo
, progress_cb
, progress_arg
,
8705 cancel_cb
, cancel_arg
);
8707 free(fileindex_path
);
8711 const struct got_error
*
8712 got_worktree_merge_commit(struct got_object_id
**new_commit_id
,
8713 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
8714 const char *author
, const char *committer
, int allow_bad_symlinks
,
8715 struct got_object_id
*branch_tip
, const char *branch_name
,
8716 int allow_conflict
, struct got_repository
*repo
,
8717 got_worktree_status_cb status_cb
, void *status_arg
)
8720 const struct got_error
*err
= NULL
, *sync_err
;
8721 struct got_pathlist_head commitable_paths
;
8722 struct collect_commitables_arg cc_arg
;
8723 struct got_pathlist_entry
*pe
;
8724 struct got_reference
*head_ref
= NULL
;
8725 struct got_object_id
*head_commit_id
= NULL
;
8726 int have_staged_files
= 0;
8727 struct merge_commit_msg_arg mcm_arg
;
8728 char *fileindex_path
= NULL
;
8730 memset(&cc_arg
, 0, sizeof(cc_arg
));
8731 *new_commit_id
= NULL
;
8733 RB_INIT(&commitable_paths
);
8735 err
= get_fileindex_path(&fileindex_path
, worktree
);
8739 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
8743 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
8747 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
8748 &have_staged_files
);
8749 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
8751 if (have_staged_files
) {
8752 err
= got_error(GOT_ERR_MERGE_STAGED_PATHS
);
8756 cc_arg
.commitable_paths
= &commitable_paths
;
8757 cc_arg
.worktree
= worktree
;
8758 cc_arg
.fileindex
= fileindex
;
8760 cc_arg
.have_staged_files
= have_staged_files
;
8761 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
8762 cc_arg
.commit_conflicts
= allow_conflict
;
8763 err
= worktree_status(worktree
, "", fileindex
, repo
,
8764 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
8768 mcm_arg
.worktree
= worktree
;
8769 mcm_arg
.branch_name
= branch_name
;
8770 err
= commit_worktree(new_commit_id
, &commitable_paths
,
8771 head_commit_id
, branch_tip
, worktree
, author
, committer
, NULL
,
8772 merge_commit_msg_cb
, &mcm_arg
, status_cb
, status_arg
, repo
);
8776 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
8777 *new_commit_id
, fileindex
, have_staged_files
);
8778 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8779 if (sync_err
&& err
== NULL
)
8782 RB_FOREACH(pe
, got_pathlist_head
, &commitable_paths
) {
8783 struct got_commitable
*ct
= pe
->data
;
8785 free_commitable(ct
);
8787 got_pathlist_free(&commitable_paths
, GOT_PATHLIST_FREE_NONE
);
8788 free(fileindex_path
);
8792 const struct got_error
*
8793 got_worktree_merge_complete(struct got_worktree
*worktree
,
8794 struct got_fileindex
*fileindex
, struct got_repository
*repo
)
8796 const struct got_error
*err
, *unlockerr
, *sync_err
;
8797 char *fileindex_path
= NULL
;
8799 err
= delete_merge_refs(worktree
, repo
);
8803 err
= get_fileindex_path(&fileindex_path
, worktree
);
8806 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
8807 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8808 if (sync_err
&& err
== NULL
)
8811 got_fileindex_free(fileindex
);
8812 free(fileindex_path
);
8813 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8814 if (unlockerr
&& err
== NULL
)
8819 const struct got_error
*
8820 got_worktree_merge_in_progress(int *in_progress
, struct got_worktree
*worktree
,
8821 struct got_repository
*repo
)
8823 const struct got_error
*err
;
8824 char *branch_refname
= NULL
;
8825 struct got_reference
*branch_ref
= NULL
;
8829 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8832 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
8833 free(branch_refname
);
8835 if (err
->code
!= GOT_ERR_NOT_REF
)
8843 const struct got_error
*got_worktree_merge_prepare(
8844 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
8845 struct got_repository
*repo
)
8847 const struct got_error
*err
= NULL
;
8848 char *fileindex_path
= NULL
;
8849 struct got_reference
*wt_branch
= NULL
;
8850 struct got_object_id
*wt_branch_tip
= NULL
;
8851 struct check_rebase_ok_arg ok_arg
;
8855 err
= lock_worktree(worktree
, LOCK_EX
);
8859 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
,
8860 got_repo_get_object_format(repo
));
8864 /* Preconditions are the same as for rebase. */
8865 ok_arg
.worktree
= worktree
;
8867 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
8872 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
8877 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
8881 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
8882 err
= got_error(GOT_ERR_MERGE_OUT_OF_DATE
);
8887 free(fileindex_path
);
8889 got_ref_close(wt_branch
);
8890 free(wt_branch_tip
);
8893 got_fileindex_free(*fileindex
);
8896 lock_worktree(worktree
, LOCK_SH
);
8901 const struct got_error
*got_worktree_merge_write_refs(
8902 struct got_worktree
*worktree
, struct got_reference
*branch
,
8903 struct got_repository
*repo
)
8905 const struct got_error
*err
= NULL
;
8906 char *branch_refname
= NULL
, *commit_refname
= NULL
;
8907 struct got_reference
*branch_ref
= NULL
, *commit_ref
= NULL
;
8908 struct got_object_id
*branch_tip
= NULL
;
8910 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8914 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
8918 err
= got_ref_resolve(&branch_tip
, repo
, branch
);
8922 err
= got_ref_alloc_symref(&branch_ref
, branch_refname
, branch
);
8925 err
= got_ref_write(branch_ref
, repo
);
8929 err
= got_ref_alloc(&commit_ref
, commit_refname
, branch_tip
);
8932 err
= got_ref_write(commit_ref
, repo
);
8937 free(branch_refname
);
8938 free(commit_refname
);
8940 got_ref_close(branch_ref
);
8942 got_ref_close(commit_ref
);
8947 const struct got_error
*
8948 got_worktree_merge_continue(char **branch_name
,
8949 struct got_object_id
**branch_tip
, struct got_fileindex
**fileindex
,
8950 struct got_worktree
*worktree
, struct got_repository
*repo
)
8952 const struct got_error
*err
;
8953 char *commit_refname
= NULL
, *branch_refname
= NULL
;
8954 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
8955 char *fileindex_path
= NULL
;
8956 int have_staged_files
= 0;
8958 *branch_name
= NULL
;
8962 err
= lock_worktree(worktree
, LOCK_EX
);
8966 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
,
8967 got_repo_get_object_format(repo
));
8971 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
8972 &have_staged_files
);
8973 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
8975 if (have_staged_files
) {
8976 err
= got_error(GOT_ERR_STAGED_PATHS
);
8980 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8984 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
8988 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
8992 if (!got_ref_is_symbolic(branch_ref
)) {
8993 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
8994 "%s is not a symbolic reference",
8995 got_ref_get_name(branch_ref
));
8998 *branch_name
= strdup(got_ref_get_symref_target(branch_ref
));
8999 if (*branch_name
== NULL
) {
9000 err
= got_error_from_errno("strdup");
9004 err
= got_ref_open(&commit_ref
, repo
, commit_refname
, 0);
9008 err
= got_ref_resolve(branch_tip
, repo
, commit_ref
);
9012 free(commit_refname
);
9013 free(branch_refname
);
9014 free(fileindex_path
);
9016 got_ref_close(commit_ref
);
9018 got_ref_close(branch_ref
);
9022 *branch_name
= NULL
;
9027 got_fileindex_free(*fileindex
);
9030 lock_worktree(worktree
, LOCK_SH
);
9035 const struct got_error
*
9036 got_worktree_merge_info(char **branch_name
, struct got_worktree
*worktree
,
9037 struct got_repository
*repo
)
9039 const struct got_error
*err
;
9040 char *branch_refname
= NULL
;
9041 struct got_reference
*branch_ref
= NULL
;
9043 *branch_name
= NULL
;
9045 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
9049 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
9053 if (!got_ref_is_symbolic(branch_ref
)) {
9054 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
9055 "%s is not a symbolic reference",
9056 got_ref_get_name(branch_ref
));
9059 *branch_name
= strdup(got_ref_get_symref_target(branch_ref
));
9060 if (*branch_name
== NULL
) {
9061 err
= got_error_from_errno("strdup");
9066 free(branch_refname
);
9068 got_ref_close(branch_ref
);
9072 *branch_name
= NULL
;
9078 const struct got_error
*
9079 got_worktree_merge_abort(struct got_worktree
*worktree
,
9080 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
9081 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
9083 const struct got_error
*err
, *unlockerr
, *sync_err
;
9084 struct got_commit_object
*commit
= NULL
;
9085 char *fileindex_path
= NULL
;
9086 struct revert_file_args rfa
;
9087 char *commit_ref_name
= NULL
;
9088 struct got_reference
*commit_ref
= NULL
;
9089 struct got_object_id
*merged_commit_id
= NULL
;
9090 struct got_object_id
*tree_id
= NULL
;
9091 struct got_pathlist_head added_paths
;
9093 RB_INIT(&added_paths
);
9095 err
= get_merge_commit_ref_name(&commit_ref_name
, worktree
);
9099 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
9103 err
= got_ref_resolve(&merged_commit_id
, repo
, commit_ref
);
9108 * Determine which files in added status can be safely removed
9109 * from disk while reverting changes in the work tree.
9110 * We want to avoid deleting unrelated files which were added by
9111 * the user for conflict resolution purposes.
9113 err
= get_paths_added_between_commits(&added_paths
,
9114 got_worktree_get_base_commit_id(worktree
), merged_commit_id
,
9115 got_worktree_get_path_prefix(worktree
), repo
);
9120 err
= got_object_open_as_commit(&commit
, repo
,
9121 worktree
->base_commit_id
);
9125 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
9126 worktree
->path_prefix
);
9130 err
= delete_merge_refs(worktree
, repo
);
9134 err
= get_fileindex_path(&fileindex_path
, worktree
);
9138 rfa
.worktree
= worktree
;
9139 rfa
.fileindex
= fileindex
;
9140 rfa
.progress_cb
= progress_cb
;
9141 rfa
.progress_arg
= progress_arg
;
9142 rfa
.patch_cb
= NULL
;
9143 rfa
.patch_arg
= NULL
;
9145 rfa
.unlink_added_files
= 1;
9146 rfa
.added_files_to_unlink
= &added_paths
;
9147 err
= worktree_status(worktree
, "", fileindex
, repo
,
9148 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
9152 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
9153 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
9155 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
9156 if (sync_err
&& err
== NULL
)
9160 free(merged_commit_id
);
9162 got_object_commit_close(commit
);
9164 got_fileindex_free(fileindex
);
9165 free(fileindex_path
);
9167 got_ref_close(commit_ref
);
9168 free(commit_ref_name
);
9170 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
9171 if (unlockerr
&& err
== NULL
)
9176 struct check_stage_ok_arg
{
9177 struct got_object_id
*head_commit_id
;
9178 struct got_worktree
*worktree
;
9179 struct got_fileindex
*fileindex
;
9180 struct got_repository
*repo
;
9184 static const struct got_error
*
9185 check_stage_ok(void *arg
, unsigned char status
,
9186 unsigned char staged_status
, const char *relpath
,
9187 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
9188 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
9190 struct check_stage_ok_arg
*a
= arg
;
9191 const struct got_error
*err
= NULL
;
9192 struct got_fileindex_entry
*ie
;
9193 struct got_object_id base_commit_id
;
9194 struct got_object_id
*base_commit_idp
= NULL
;
9195 char *in_repo_path
= NULL
, *p
;
9197 if (status
== GOT_STATUS_UNVERSIONED
||
9198 status
== GOT_STATUS_NO_CHANGE
)
9200 if (status
== GOT_STATUS_NONEXISTENT
)
9201 return got_error_set_errno(ENOENT
, relpath
);
9203 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
9205 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
9207 if (asprintf(&in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
9208 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
9210 return got_error_from_errno("asprintf");
9212 if (got_fileindex_entry_has_commit(ie
)) {
9213 base_commit_idp
= got_fileindex_entry_get_commit_id(
9214 &base_commit_id
, ie
);
9217 if (status
== GOT_STATUS_CONFLICT
) {
9218 err
= got_error_path(ie
->path
, GOT_ERR_STAGE_CONFLICT
);
9220 } else if (status
!= GOT_STATUS_ADD
&&
9221 status
!= GOT_STATUS_MODIFY
&&
9222 status
!= GOT_STATUS_DELETE
) {
9223 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STATUS
);
9227 a
->have_changes
= 1;
9232 err
= check_out_of_date(p
, status
, staged_status
,
9233 blob_id
, base_commit_idp
, a
->head_commit_id
, a
->repo
,
9234 GOT_ERR_STAGE_OUT_OF_DATE
);
9240 struct stage_path_arg
{
9241 struct got_worktree
*worktree
;
9242 struct got_fileindex
*fileindex
;
9243 struct got_repository
*repo
;
9244 got_worktree_status_cb status_cb
;
9246 got_worktree_patch_cb patch_cb
;
9248 int staged_something
;
9249 int allow_bad_symlinks
;
9252 static const struct got_error
*
9253 stage_path(void *arg
, unsigned char status
,
9254 unsigned char staged_status
, const char *relpath
,
9255 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
9256 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
9258 struct stage_path_arg
*a
= arg
;
9259 const struct got_error
*err
= NULL
;
9260 struct got_fileindex_entry
*ie
;
9261 char *ondisk_path
= NULL
, *path_content
= NULL
;
9263 struct got_object_id
*new_staged_blob_id
= NULL
;
9266 if (status
== GOT_STATUS_UNVERSIONED
)
9269 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
9271 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
9273 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
9275 return got_error_from_errno("asprintf");
9278 case GOT_STATUS_ADD
:
9279 case GOT_STATUS_MODIFY
:
9280 /* XXX could sb.st_mode be passed in by our caller? */
9281 if (lstat(ondisk_path
, &sb
) == -1) {
9282 err
= got_error_from_errno2("lstat", ondisk_path
);
9286 if (status
== GOT_STATUS_ADD
) {
9287 int choice
= GOT_PATCH_CHOICE_NONE
;
9288 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
9289 status
, ie
->path
, NULL
, 1, 1);
9292 if (choice
!= GOT_PATCH_CHOICE_YES
)
9295 int stage_binary_file
= 0;
9297 err
= create_patched_content(&path_content
,
9298 &stage_binary_file
, 0,
9299 staged_blob_id
? staged_blob_id
: blob_id
,
9300 ondisk_path
, dirfd
, de_name
, ie
->path
,
9301 a
->repo
, a
->patch_cb
, a
->patch_arg
);
9302 if (!stage_binary_file
&&
9303 (err
|| path_content
== NULL
))
9307 err
= got_object_blob_create(&new_staged_blob_id
,
9308 path_content
? path_content
: ondisk_path
, a
->repo
);
9311 memcpy(&ie
->staged_blob
, new_staged_blob_id
,
9312 sizeof(ie
->staged_blob
));
9313 if (status
== GOT_STATUS_ADD
|| staged_status
== GOT_STATUS_ADD
)
9314 stage
= GOT_FILEIDX_STAGE_ADD
;
9316 stage
= GOT_FILEIDX_STAGE_MODIFY
;
9317 got_fileindex_entry_stage_set(ie
, stage
);
9318 if (S_ISLNK(sb
.st_mode
)) {
9319 int is_bad_symlink
= 0;
9320 if (!a
->allow_bad_symlinks
) {
9321 char target_path
[PATH_MAX
];
9323 target_len
= readlink(ondisk_path
, target_path
,
9324 sizeof(target_path
));
9325 if (target_len
== -1) {
9326 err
= got_error_from_errno2("readlink",
9330 err
= is_bad_symlink_target(&is_bad_symlink
,
9331 target_path
, target_len
, ondisk_path
,
9332 a
->worktree
->root_path
,
9333 a
->worktree
->meta_dir
);
9336 if (is_bad_symlink
) {
9337 err
= got_error_path(ondisk_path
,
9338 GOT_ERR_BAD_SYMLINK
);
9343 got_fileindex_entry_staged_filetype_set(ie
,
9344 GOT_FILEIDX_MODE_BAD_SYMLINK
);
9346 got_fileindex_entry_staged_filetype_set(ie
,
9347 GOT_FILEIDX_MODE_SYMLINK
);
9349 got_fileindex_entry_staged_filetype_set(ie
,
9350 GOT_FILEIDX_MODE_REGULAR_FILE
);
9352 a
->staged_something
= 1;
9353 if (a
->status_cb
== NULL
)
9355 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
9356 get_staged_status(ie
), relpath
, blob_id
,
9357 new_staged_blob_id
, NULL
, dirfd
, de_name
);
9361 * When staging the reverse of the staged diff,
9362 * implicitly unstage the file.
9364 if (got_object_id_cmp(&ie
->staged_blob
, &ie
->blob
) == 0) {
9365 got_fileindex_entry_stage_set(ie
,
9366 GOT_FILEIDX_STAGE_NONE
);
9369 case GOT_STATUS_DELETE
:
9370 if (staged_status
== GOT_STATUS_DELETE
)
9373 int choice
= GOT_PATCH_CHOICE_NONE
;
9374 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
, status
,
9375 ie
->path
, NULL
, 1, 1);
9378 if (choice
== GOT_PATCH_CHOICE_NO
)
9380 if (choice
!= GOT_PATCH_CHOICE_YES
) {
9381 err
= got_error(GOT_ERR_PATCH_CHOICE
);
9385 stage
= GOT_FILEIDX_STAGE_DELETE
;
9386 got_fileindex_entry_stage_set(ie
, stage
);
9387 a
->staged_something
= 1;
9388 if (a
->status_cb
== NULL
)
9390 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
9391 get_staged_status(ie
), relpath
, NULL
, NULL
, NULL
, dirfd
,
9394 case GOT_STATUS_NO_CHANGE
:
9396 case GOT_STATUS_CONFLICT
:
9397 err
= got_error_path(relpath
, GOT_ERR_STAGE_CONFLICT
);
9399 case GOT_STATUS_NONEXISTENT
:
9400 err
= got_error_set_errno(ENOENT
, relpath
);
9403 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
9407 if (path_content
&& unlink(path_content
) == -1 && err
== NULL
)
9408 err
= got_error_from_errno2("unlink", path_content
);
9411 free(new_staged_blob_id
);
9415 const struct got_error
*
9416 got_worktree_stage(struct got_worktree
*worktree
,
9417 struct got_pathlist_head
*paths
,
9418 got_worktree_status_cb status_cb
, void *status_arg
,
9419 got_worktree_patch_cb patch_cb
, void *patch_arg
,
9420 int allow_bad_symlinks
, struct got_repository
*repo
)
9422 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
9423 struct got_pathlist_entry
*pe
;
9424 struct got_fileindex
*fileindex
= NULL
;
9425 char *fileindex_path
= NULL
;
9426 struct got_reference
*head_ref
= NULL
;
9427 struct got_object_id
*head_commit_id
= NULL
;
9428 struct check_stage_ok_arg oka
;
9429 struct stage_path_arg spa
;
9431 err
= lock_worktree(worktree
, LOCK_EX
);
9435 err
= got_ref_open(&head_ref
, repo
,
9436 got_worktree_get_head_ref_name(worktree
), 0);
9439 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
9442 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
9443 got_repo_get_object_format(repo
));
9447 /* Check pre-conditions before staging anything. */
9448 oka
.head_commit_id
= head_commit_id
;
9449 oka
.worktree
= worktree
;
9450 oka
.fileindex
= fileindex
;
9452 oka
.have_changes
= 0;
9453 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
9454 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
9455 check_stage_ok
, &oka
, NULL
, NULL
, 1, 0);
9459 if (!oka
.have_changes
) {
9460 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
9464 spa
.worktree
= worktree
;
9465 spa
.fileindex
= fileindex
;
9467 spa
.patch_cb
= patch_cb
;
9468 spa
.patch_arg
= patch_arg
;
9469 spa
.status_cb
= status_cb
;
9470 spa
.status_arg
= status_arg
;
9471 spa
.staged_something
= 0;
9472 spa
.allow_bad_symlinks
= allow_bad_symlinks
;
9473 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
9474 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
9475 stage_path
, &spa
, NULL
, NULL
, 1, 0);
9479 if (!spa
.staged_something
) {
9480 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
9484 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
9485 if (sync_err
&& err
== NULL
)
9489 got_ref_close(head_ref
);
9490 free(head_commit_id
);
9491 free(fileindex_path
);
9493 got_fileindex_free(fileindex
);
9494 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
9495 if (unlockerr
&& err
== NULL
)
9500 struct unstage_path_arg
{
9501 struct got_worktree
*worktree
;
9502 struct got_fileindex
*fileindex
;
9503 struct got_repository
*repo
;
9504 got_worktree_checkout_cb progress_cb
;
9506 got_worktree_patch_cb patch_cb
;
9510 static const struct got_error
*
9511 create_unstaged_content(char **path_unstaged_content
,
9512 char **path_new_staged_content
, int *confirm_binary_change
,
9513 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
9514 const char *relpath
, struct got_repository
*repo
,
9515 got_worktree_patch_cb patch_cb
, void *patch_arg
)
9517 const struct got_error
*err
, *free_err
;
9518 struct got_blob_object
*blob
= NULL
, *staged_blob
= NULL
;
9519 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
, *rejectfile
= NULL
;
9520 char *path1
= NULL
, *path2
= NULL
, *label1
= NULL
;
9521 struct got_diffreg_result
*diffreg_result
= NULL
;
9522 int choice
, line_cur1
= 1, line_cur2
= 1, n
= 0, nchunks_used
= 0;
9523 int have_content
= 0, have_rejected_content
= 0, i
= 0, nchanges
= 0;
9524 int fd1
= -1, fd2
= -1;
9526 *confirm_binary_change
= 0;
9527 *path_unstaged_content
= NULL
;
9528 *path_new_staged_content
= NULL
;
9530 err
= got_object_id_str(&label1
, blob_id
);
9534 fd1
= got_opentempfd();
9536 err
= got_error_from_errno("got_opentempfd");
9539 fd2
= got_opentempfd();
9541 err
= got_error_from_errno("got_opentempfd");
9545 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192, fd1
);
9549 err
= got_opentemp_named(&path1
, &f1
, "got-unstage-blob-base", "");
9553 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
9557 err
= got_object_open_as_blob(&staged_blob
, repo
, staged_blob_id
, 8192,
9562 err
= got_opentemp_named(&path2
, &f2
, "got-unstage-blob-staged", "");
9566 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f2
, staged_blob
);
9570 err
= got_diff_files(&diffreg_result
, f1
, 1, label1
, f2
, 1,
9571 path2
, 3, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
9575 if (diff_result_has_binary(diffreg_result
->result
)) {
9576 err
= accept_or_reject_binary_change(&choice
, relpath
,
9577 patch_cb
, patch_arg
);
9578 if (err
== NULL
&& choice
== GOT_PATCH_CHOICE_YES
)
9579 *confirm_binary_change
= 1;
9583 err
= got_opentemp_named(path_unstaged_content
, &outfile
,
9584 "got-unstaged-content", "");
9587 err
= got_opentemp_named(path_new_staged_content
, &rejectfile
,
9588 "got-new-staged-content", "");
9592 if (fseek(f1
, 0L, SEEK_SET
) == -1) {
9593 err
= got_ferror(f1
, GOT_ERR_IO
);
9596 if (fseek(f2
, 0L, SEEK_SET
) == -1) {
9597 err
= got_ferror(f2
, GOT_ERR_IO
);
9600 /* Count the number of actual changes in the diff result. */
9601 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
9602 struct diff_chunk_context cc
= {};
9603 diff_chunk_context_load_change(&cc
, &nchunks_used
,
9604 diffreg_result
->result
, n
, 0);
9607 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
9608 err
= apply_or_reject_change(&choice
, &nchunks_used
,
9609 diffreg_result
->result
, n
, relpath
, f1
, f2
,
9610 &line_cur1
, &line_cur2
,
9611 outfile
, rejectfile
, ++i
, nchanges
, patch_cb
, patch_arg
);
9614 if (choice
== GOT_PATCH_CHOICE_YES
)
9617 have_rejected_content
= 1;
9618 if (choice
== GOT_PATCH_CHOICE_QUIT
)
9621 if (have_content
|| have_rejected_content
)
9622 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
9623 outfile
, rejectfile
);
9626 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
9627 err
= got_error_from_errno("close");
9629 got_object_blob_close(blob
);
9630 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
9631 err
= got_error_from_errno("close");
9633 got_object_blob_close(staged_blob
);
9634 free_err
= got_diffreg_result_free(diffreg_result
);
9635 if (free_err
&& err
== NULL
)
9637 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
9638 err
= got_error_from_errno2("fclose", path1
);
9639 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
9640 err
= got_error_from_errno2("fclose", path2
);
9641 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
9642 err
= got_error_from_errno2("fclose", *path_unstaged_content
);
9643 if (rejectfile
&& fclose(rejectfile
) == EOF
&& err
== NULL
)
9644 err
= got_error_from_errno2("fclose", *path_new_staged_content
);
9645 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
9646 err
= got_error_from_errno2("unlink", path1
);
9647 if (path2
&& unlink(path2
) == -1 && err
== NULL
)
9648 err
= got_error_from_errno2("unlink", path2
);
9649 if (err
|| !have_content
) {
9650 if (*path_unstaged_content
&&
9651 unlink(*path_unstaged_content
) == -1 && err
== NULL
)
9652 err
= got_error_from_errno2("unlink",
9653 *path_unstaged_content
);
9654 free(*path_unstaged_content
);
9655 *path_unstaged_content
= NULL
;
9657 if (err
|| !have_content
|| !have_rejected_content
) {
9658 if (*path_new_staged_content
&&
9659 unlink(*path_new_staged_content
) == -1 && err
== NULL
)
9660 err
= got_error_from_errno2("unlink",
9661 *path_new_staged_content
);
9662 free(*path_new_staged_content
);
9663 *path_new_staged_content
= NULL
;
9670 static const struct got_error
*
9671 unstage_hunks(int *confirm_binary_change
, struct got_object_id
*staged_blob_id
,
9672 struct got_blob_object
*blob_base
, struct got_object_id
*blob_id
,
9673 struct got_fileindex_entry
*ie
, const char *ondisk_path
,
9674 const char *label_orig
, struct got_worktree
*worktree
,
9675 struct got_repository
*repo
,
9676 got_worktree_patch_cb patch_cb
, void *patch_arg
,
9677 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
9679 const struct got_error
*err
= NULL
;
9680 char *path_unstaged_content
= NULL
;
9681 char *path_new_staged_content
= NULL
;
9682 char *parent
= NULL
, *base_path
= NULL
;
9683 char *blob_base_path
= NULL
;
9684 struct got_object_id
*new_staged_blob_id
= NULL
;
9685 FILE *f
= NULL
, *f_base
= NULL
, *f_deriv2
= NULL
;
9688 err
= create_unstaged_content(&path_unstaged_content
,
9689 &path_new_staged_content
, confirm_binary_change
,
9690 blob_id
, staged_blob_id
, ie
->path
, repo
, patch_cb
, patch_arg
);
9694 if (path_unstaged_content
== NULL
)
9697 if (path_new_staged_content
) {
9698 err
= got_object_blob_create(&new_staged_blob_id
,
9699 path_new_staged_content
, repo
);
9704 f
= fopen(path_unstaged_content
, "re");
9706 err
= got_error_from_errno2("fopen",
9707 path_unstaged_content
);
9710 if (fstat(fileno(f
), &sb
) == -1) {
9711 err
= got_error_from_errno2("fstat", path_unstaged_content
);
9714 if (got_fileindex_entry_staged_filetype_get(ie
) ==
9715 GOT_FILEIDX_MODE_SYMLINK
&& sb
.st_size
< PATH_MAX
) {
9716 char link_target
[PATH_MAX
];
9718 r
= fread(link_target
, 1, sizeof(link_target
), f
);
9719 if (r
== 0 && ferror(f
)) {
9720 err
= got_error_from_errno("fread");
9723 if (r
>= sizeof(link_target
)) { /* should not happen */
9724 err
= got_error(GOT_ERR_NO_SPACE
);
9727 link_target
[r
] = '\0';
9728 err
= merge_symlink(worktree
, blob_base
,
9729 ondisk_path
, ie
->path
, label_orig
, link_target
,
9730 worktree
->base_commit_id
, repo
, progress_cb
,
9733 int local_changes_subsumed
;
9735 err
= got_path_dirname(&parent
, ondisk_path
);
9739 if (asprintf(&base_path
, "%s/got-unstage-blob-orig",
9741 err
= got_error_from_errno("asprintf");
9746 err
= got_opentemp_named(&blob_base_path
, &f_base
,
9750 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_base
,
9756 * In order the run a 3-way merge with a symlink we copy the symlink's
9757 * target path into a temporary file and use that file with diff3.
9759 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
9760 err
= dump_symlink_target_path_to_file(&f_deriv2
,
9766 fd
= open(ondisk_path
,
9767 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
9769 err
= got_error_from_errno2("open", ondisk_path
);
9772 f_deriv2
= fdopen(fd
, "r");
9773 if (f_deriv2
== NULL
) {
9774 err
= got_error_from_errno2("fdopen", ondisk_path
);
9780 err
= merge_file(&local_changes_subsumed
, worktree
,
9781 f_base
, f
, f_deriv2
, ondisk_path
, ie
->path
,
9782 got_fileindex_perms_to_st(ie
),
9783 label_orig
, "unstaged", NULL
, GOT_DIFF_ALGORITHM_MYERS
,
9784 repo
, progress_cb
, progress_arg
);
9789 if (new_staged_blob_id
) {
9790 memcpy(&ie
->staged_blob
, new_staged_blob_id
,
9791 sizeof(ie
->staged_blob
));
9793 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
9794 got_fileindex_entry_staged_filetype_set(ie
, 0);
9797 free(new_staged_blob_id
);
9798 if (path_unstaged_content
&&
9799 unlink(path_unstaged_content
) == -1 && err
== NULL
)
9800 err
= got_error_from_errno2("unlink", path_unstaged_content
);
9801 if (path_new_staged_content
&&
9802 unlink(path_new_staged_content
) == -1 && err
== NULL
)
9803 err
= got_error_from_errno2("unlink", path_new_staged_content
);
9804 if (blob_base_path
&& unlink(blob_base_path
) == -1 && err
== NULL
)
9805 err
= got_error_from_errno2("unlink", blob_base_path
);
9806 if (f_base
&& fclose(f_base
) == EOF
&& err
== NULL
)
9807 err
= got_error_from_errno2("fclose", path_unstaged_content
);
9808 if (f
&& fclose(f
) == EOF
&& err
== NULL
)
9809 err
= got_error_from_errno2("fclose", path_unstaged_content
);
9810 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
9811 err
= got_error_from_errno2("fclose", ondisk_path
);
9812 free(path_unstaged_content
);
9813 free(path_new_staged_content
);
9814 free(blob_base_path
);
9820 static const struct got_error
*
9821 unstage_path(void *arg
, unsigned char status
,
9822 unsigned char staged_status
, const char *relpath
,
9823 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
9824 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
9826 const struct got_error
*err
= NULL
;
9827 struct unstage_path_arg
*a
= arg
;
9828 struct got_fileindex_entry
*ie
;
9829 struct got_blob_object
*blob_base
= NULL
, *blob_staged
= NULL
;
9830 char *ondisk_path
= NULL
;
9831 char *id_str
= NULL
, *label_orig
= NULL
;
9832 int local_changes_subsumed
;
9834 int fd1
= -1, fd2
= -1;
9836 if (staged_status
!= GOT_STATUS_ADD
&&
9837 staged_status
!= GOT_STATUS_MODIFY
&&
9838 staged_status
!= GOT_STATUS_DELETE
)
9841 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
9843 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
9845 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, relpath
)
9847 return got_error_from_errno("asprintf");
9849 err
= got_object_id_str(&id_str
,
9850 commit_id
? commit_id
: a
->worktree
->base_commit_id
);
9853 if (asprintf(&label_orig
, "%s: commit %s", GOT_MERGE_LABEL_BASE
,
9855 err
= got_error_from_errno("asprintf");
9859 fd1
= got_opentempfd();
9861 err
= got_error_from_errno("got_opentempfd");
9864 fd2
= got_opentempfd();
9866 err
= got_error_from_errno("got_opentempfd");
9870 switch (staged_status
) {
9871 case GOT_STATUS_MODIFY
:
9872 err
= got_object_open_as_blob(&blob_base
, a
->repo
,
9873 blob_id
, 8192, fd1
);
9877 case GOT_STATUS_ADD
:
9878 if (status
== GOT_STATUS_MISSING
) {
9879 /* Cannot merge changes into missing files. */
9880 err
= (*a
->progress_cb
)(a
->progress_arg
, status
,
9885 if (staged_status
== GOT_STATUS_ADD
) {
9886 int choice
= GOT_PATCH_CHOICE_NONE
;
9887 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
9888 staged_status
, ie
->path
, NULL
, 1, 1);
9891 if (choice
!= GOT_PATCH_CHOICE_YES
)
9894 int unstage_binary_file
= 0;
9896 err
= unstage_hunks(&unstage_binary_file
,
9897 staged_blob_id
, blob_base
, blob_id
,
9898 ie
, ondisk_path
, label_orig
,
9899 a
->worktree
, a
->repo
,
9900 a
->patch_cb
, a
->patch_arg
,
9901 a
->progress_cb
, a
->progress_arg
);
9902 if (!unstage_binary_file
)
9903 break; /* Done with this file. */
9906 err
= got_object_open_as_blob(&blob_staged
, a
->repo
,
9907 staged_blob_id
, 8192, fd2
);
9910 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
9911 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
9912 case GOT_FILEIDX_MODE_REGULAR_FILE
:
9913 err
= merge_blob(&local_changes_subsumed
, a
->worktree
,
9914 blob_base
, ondisk_path
, relpath
,
9915 got_fileindex_perms_to_st(ie
), label_orig
,
9916 blob_staged
, commit_id
? commit_id
:
9917 a
->worktree
->base_commit_id
, a
->repo
,
9918 a
->progress_cb
, a
->progress_arg
);
9920 case GOT_FILEIDX_MODE_SYMLINK
:
9921 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
9922 char *staged_target
;
9923 err
= got_object_blob_read_to_str(
9924 &staged_target
, blob_staged
);
9927 err
= merge_symlink(a
->worktree
, blob_base
,
9928 ondisk_path
, relpath
, label_orig
,
9929 staged_target
, commit_id
? commit_id
:
9930 a
->worktree
->base_commit_id
,
9931 a
->repo
, a
->progress_cb
, a
->progress_arg
);
9932 free(staged_target
);
9934 err
= merge_blob(&local_changes_subsumed
,
9935 a
->worktree
, blob_base
, ondisk_path
,
9936 relpath
, got_fileindex_perms_to_st(ie
),
9937 label_orig
, blob_staged
,
9938 commit_id
? commit_id
:
9939 a
->worktree
->base_commit_id
, a
->repo
,
9940 a
->progress_cb
, a
->progress_arg
);
9944 err
= got_error_path(relpath
, GOT_ERR_BAD_FILETYPE
);
9948 got_fileindex_entry_stage_set(ie
,
9949 GOT_FILEIDX_STAGE_NONE
);
9950 got_fileindex_entry_staged_filetype_set(ie
, 0);
9953 case GOT_STATUS_DELETE
:
9955 int choice
= GOT_PATCH_CHOICE_NONE
;
9956 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
9957 staged_status
, ie
->path
, NULL
, 1, 1);
9960 if (choice
== GOT_PATCH_CHOICE_NO
)
9962 if (choice
!= GOT_PATCH_CHOICE_YES
) {
9963 err
= got_error(GOT_ERR_PATCH_CHOICE
);
9967 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
9968 got_fileindex_entry_staged_filetype_set(ie
, 0);
9969 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
9970 dirfd
, de_name
, a
->repo
);
9973 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, relpath
);
9978 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
9979 err
= got_error_from_errno("close");
9981 got_object_blob_close(blob_base
);
9982 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
9983 err
= got_error_from_errno("close");
9985 got_object_blob_close(blob_staged
);
9991 const struct got_error
*
9992 got_worktree_unstage(struct got_worktree
*worktree
,
9993 struct got_pathlist_head
*paths
,
9994 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
9995 got_worktree_patch_cb patch_cb
, void *patch_arg
,
9996 struct got_repository
*repo
)
9998 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
9999 struct got_pathlist_entry
*pe
;
10000 struct got_fileindex
*fileindex
= NULL
;
10001 char *fileindex_path
= NULL
;
10002 struct unstage_path_arg upa
;
10004 err
= lock_worktree(worktree
, LOCK_EX
);
10008 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
,
10009 got_repo_get_object_format(repo
));
10013 upa
.worktree
= worktree
;
10014 upa
.fileindex
= fileindex
;
10016 upa
.progress_cb
= progress_cb
;
10017 upa
.progress_arg
= progress_arg
;
10018 upa
.patch_cb
= patch_cb
;
10019 upa
.patch_arg
= patch_arg
;
10020 RB_FOREACH(pe
, got_pathlist_head
, paths
) {
10021 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
10022 unstage_path
, &upa
, NULL
, NULL
, 1, 0);
10027 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
10028 if (sync_err
&& err
== NULL
)
10031 free(fileindex_path
);
10033 got_fileindex_free(fileindex
);
10034 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
10035 if (unlockerr
&& err
== NULL
)
10040 struct report_file_info_arg
{
10041 struct got_worktree
*worktree
;
10042 got_worktree_path_info_cb info_cb
;
10044 struct got_pathlist_head
*paths
;
10045 got_cancel_cb cancel_cb
;
10049 static const struct got_error
*
10050 report_file_info(void *arg
, struct got_fileindex_entry
*ie
)
10052 const struct got_error
*err
;
10053 struct report_file_info_arg
*a
= arg
;
10054 struct got_pathlist_entry
*pe
;
10055 struct got_object_id blob_id
, staged_blob_id
, commit_id
;
10056 struct got_object_id
*blob_idp
= NULL
, *staged_blob_idp
= NULL
;
10057 struct got_object_id
*commit_idp
= NULL
;
10060 if (a
->cancel_cb
) {
10061 err
= a
->cancel_cb(a
->cancel_arg
);
10066 RB_FOREACH(pe
, got_pathlist_head
, a
->paths
) {
10067 if (pe
->path_len
== 0 || strcmp(pe
->path
, ie
->path
) == 0 ||
10068 got_path_is_child(ie
->path
, pe
->path
, pe
->path_len
))
10071 if (pe
== NULL
) /* not found */
10074 if (got_fileindex_entry_has_blob(ie
))
10075 blob_idp
= got_fileindex_entry_get_blob_id(&blob_id
, ie
);
10076 stage
= got_fileindex_entry_stage_get(ie
);
10077 if (stage
== GOT_FILEIDX_STAGE_MODIFY
||
10078 stage
== GOT_FILEIDX_STAGE_ADD
) {
10079 staged_blob_idp
= got_fileindex_entry_get_staged_blob_id(
10080 &staged_blob_id
, ie
);
10083 if (got_fileindex_entry_has_commit(ie
))
10084 commit_idp
= got_fileindex_entry_get_commit_id(&commit_id
, ie
);
10086 return a
->info_cb(a
->info_arg
, ie
->path
, got_fileindex_perms_to_st(ie
),
10087 (time_t)ie
->mtime_sec
, blob_idp
, staged_blob_idp
, commit_idp
);
10090 const struct got_error
*
10091 got_worktree_path_info_prepare(struct got_fileindex
**fileindex
,
10092 struct got_worktree
*worktree
, struct got_repository
*repo
)
10094 const struct got_error
*err
;
10095 char *fileindex_path
;
10097 err
= lock_worktree(worktree
, LOCK_SH
);
10101 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
,
10102 got_repo_get_object_format(repo
));
10103 free(fileindex_path
);
10108 got_worktree_get_fileindex_version(struct got_fileindex
*fileindex
)
10110 return got_fileindex_get_version(fileindex
);
10113 const struct got_error
*
10114 got_worktree_path_info(struct got_worktree
*worktree
,
10115 struct got_fileindex
*fileindex
,
10116 struct got_pathlist_head
*paths
,
10117 got_worktree_path_info_cb info_cb
, void *info_arg
,
10118 got_cancel_cb cancel_cb
, void *cancel_arg
)
10121 struct report_file_info_arg arg
;
10123 arg
.worktree
= worktree
;
10124 arg
.info_cb
= info_cb
;
10125 arg
.info_arg
= info_arg
;
10127 arg
.cancel_cb
= cancel_cb
;
10128 arg
.cancel_arg
= cancel_arg
;
10129 return got_fileindex_for_each_entry_safe(fileindex
, report_file_info
,
10133 const struct got_error
*
10134 got_worktree_path_info_complete(struct got_fileindex
*fileindex
,
10135 struct got_worktree
*worktree
)
10138 got_fileindex_free(fileindex
);
10139 return lock_worktree(worktree
, LOCK_UN
);
10142 static const struct got_error
*
10143 patch_check_path(const char *p
, char **path
, unsigned char *status
,
10144 unsigned char *staged_status
, struct got_fileindex
*fileindex
,
10145 struct got_worktree
*worktree
, struct got_repository
*repo
)
10147 const struct got_error
*err
;
10148 struct got_fileindex_entry
*ie
;
10150 char *ondisk_path
= NULL
;
10152 err
= got_worktree_resolve_path(path
, worktree
, p
);
10156 if (asprintf(&ondisk_path
, "%s%s%s", worktree
->root_path
,
10157 *path
[0] ? "/" : "", *path
) == -1)
10158 return got_error_from_errno("asprintf");
10160 ie
= got_fileindex_entry_get(fileindex
, *path
, strlen(*path
));
10162 *staged_status
= get_staged_status(ie
);
10163 err
= get_file_status(status
, &sb
, ie
, ondisk_path
, -1, NULL
,
10168 *staged_status
= GOT_STATUS_NO_CHANGE
;
10169 *status
= GOT_STATUS_UNVERSIONED
;
10170 if (lstat(ondisk_path
, &sb
) == -1) {
10171 if (errno
!= ENOENT
) {
10172 err
= got_error_from_errno2("lstat",
10176 *status
= GOT_STATUS_NONEXISTENT
;
10185 static const struct got_error
*
10186 patch_can_rm(const char *path
, unsigned char status
,
10187 unsigned char staged_status
)
10189 if (status
== GOT_STATUS_NONEXISTENT
)
10190 return got_error_set_errno(ENOENT
, path
);
10191 if (status
!= GOT_STATUS_NO_CHANGE
&&
10192 status
!= GOT_STATUS_ADD
&&
10193 status
!= GOT_STATUS_MODIFY
&&
10194 status
!= GOT_STATUS_MODE_CHANGE
)
10195 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
10196 if (staged_status
== GOT_STATUS_DELETE
)
10197 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
10201 static const struct got_error
*
10202 patch_can_add(const char *path
, unsigned char status
)
10204 if (status
!= GOT_STATUS_NONEXISTENT
)
10205 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
10209 static const struct got_error
*
10210 patch_can_edit(const char *path
, unsigned char status
,
10211 unsigned char staged_status
)
10213 if (status
== GOT_STATUS_NONEXISTENT
)
10214 return got_error_set_errno(ENOENT
, path
);
10215 if (status
!= GOT_STATUS_NO_CHANGE
&&
10216 status
!= GOT_STATUS_ADD
&&
10217 status
!= GOT_STATUS_MODIFY
)
10218 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
10219 if (staged_status
== GOT_STATUS_DELETE
)
10220 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
10224 const struct got_error
*
10225 got_worktree_patch_prepare(struct got_fileindex
**fileindex
,
10226 char **fileindex_path
, struct got_worktree
*worktree
,
10227 struct got_repository
*repo
)
10229 const struct got_error
*err
;
10231 err
= lock_worktree(worktree
, LOCK_EX
);
10235 return open_fileindex(fileindex
, fileindex_path
, worktree
,
10236 got_repo_get_object_format(repo
));
10239 const struct got_error
*
10240 got_worktree_patch_check_path(const char *old
, const char *new,
10241 char **oldpath
, char **newpath
, struct got_worktree
*worktree
,
10242 struct got_repository
*repo
, struct got_fileindex
*fileindex
)
10244 const struct got_error
*err
= NULL
;
10245 int file_renamed
= 0;
10246 unsigned char status_old
, staged_status_old
;
10247 unsigned char status_new
, staged_status_new
;
10252 err
= patch_check_path(old
!= NULL
? old
: new, oldpath
,
10253 &status_old
, &staged_status_old
, fileindex
, worktree
, repo
);
10257 err
= patch_check_path(new != NULL
? new : old
, newpath
,
10258 &status_new
, &staged_status_new
, fileindex
, worktree
, repo
);
10262 if (old
!= NULL
&& new != NULL
&& strcmp(old
, new) != 0)
10265 if (old
!= NULL
&& new == NULL
)
10266 err
= patch_can_rm(*oldpath
, status_old
, staged_status_old
);
10267 else if (file_renamed
) {
10268 err
= patch_can_rm(*oldpath
, status_old
, staged_status_old
);
10270 err
= patch_can_add(*newpath
, status_new
);
10271 } else if (old
== NULL
)
10272 err
= patch_can_add(*newpath
, status_new
);
10274 err
= patch_can_edit(*newpath
, status_new
, staged_status_new
);
10286 const struct got_error
*
10287 got_worktree_patch_schedule_add(const char *path
, struct got_repository
*repo
,
10288 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
10289 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
10291 struct schedule_addition_args saa
;
10293 memset(&saa
, 0, sizeof(saa
));
10294 saa
.worktree
= worktree
;
10295 saa
.fileindex
= fileindex
;
10296 saa
.progress_cb
= progress_cb
;
10297 saa
.progress_arg
= progress_arg
;
10300 return worktree_status(worktree
, path
, fileindex
, repo
,
10301 schedule_addition
, &saa
, NULL
, NULL
, 1, 0);
10304 const struct got_error
*
10305 got_worktree_patch_schedule_rm(const char *path
, struct got_repository
*repo
,
10306 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
10307 got_worktree_delete_cb progress_cb
, void *progress_arg
)
10309 const struct got_error
*err
;
10310 struct schedule_deletion_args sda
;
10311 char *ondisk_status_path
;
10313 memset(&sda
, 0, sizeof(sda
));
10314 sda
.worktree
= worktree
;
10315 sda
.fileindex
= fileindex
;
10316 sda
.progress_cb
= progress_cb
;
10317 sda
.progress_arg
= progress_arg
;
10319 sda
.delete_local_mods
= 0;
10320 sda
.keep_on_disk
= 0;
10321 sda
.ignore_missing_paths
= 0;
10322 sda
.status_codes
= NULL
;
10323 if (asprintf(&ondisk_status_path
, "%s/%s",
10324 got_worktree_get_root_path(worktree
), path
) == -1)
10325 return got_error_from_errno("asprintf");
10326 sda
.status_path
= ondisk_status_path
;
10327 sda
.status_path_len
= strlen(ondisk_status_path
);
10329 err
= worktree_status(worktree
, path
, fileindex
, repo
,
10330 schedule_for_deletion
, &sda
, NULL
, NULL
, 1, 1);
10331 free(ondisk_status_path
);
10335 const struct got_error
*
10336 got_worktree_patch_complete(struct got_worktree
*worktree
,
10337 struct got_fileindex
*fileindex
,
10338 const char *fileindex_path
)
10340 const struct got_error
*err
= NULL
, *unlock_err
;
10343 err
= sync_fileindex(fileindex
, fileindex_path
);
10344 got_fileindex_free(fileindex
);
10347 unlock_err
= lock_worktree(worktree
, LOCK_UN
);
10348 if (unlock_err
&& err
== NULL
)