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
)
1106 const struct got_error
*err
= NULL
;
1107 struct got_fileindex_entry
*new_ie
;
1111 err
= got_fileindex_entry_alloc(&new_ie
, path
);
1115 err
= got_fileindex_entry_update(new_ie
, wt_fd
, path
,
1116 blob_id
->sha1
, base_commit_id
->sha1
, 1);
1120 err
= got_fileindex_entry_add(fileindex
, new_ie
);
1123 got_fileindex_entry_free(new_ie
);
1130 get_ondisk_perms(int executable
, mode_t st_mode
)
1132 mode_t xbits
= S_IXUSR
;
1135 /* Map read bits to execute bits. */
1136 if (st_mode
& S_IRGRP
)
1138 if (st_mode
& S_IROTH
)
1140 return st_mode
| xbits
;
1146 /* forward declaration */
1147 static const struct got_error
*
1148 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1149 const char *path
, mode_t te_mode
, mode_t st_mode
,
1150 struct got_blob_object
*blob
, int restoring_missing_file
,
1151 int reverting_versioned_file
, int installing_bad_symlink
,
1152 int path_is_unversioned
, struct got_repository
*repo
,
1153 got_worktree_checkout_cb progress_cb
, void *progress_arg
);
1156 * This function assumes that the provided symlink target points at a
1157 * safe location in the work tree!
1159 static const struct got_error
*
1160 replace_existing_symlink(int *did_something
, const char *ondisk_path
,
1161 const char *target_path
, size_t target_len
)
1163 const struct got_error
*err
= NULL
;
1165 char etarget
[PATH_MAX
];
1171 * "Bad" symlinks (those pointing outside the work tree or into the
1172 * .got directory) are installed in the work tree as a regular file
1173 * which contains the bad symlink target path.
1174 * The new symlink target has already been checked for safety by our
1175 * caller. If we can successfully open a regular file then we simply
1176 * replace this file with a symlink below.
1178 fd
= open(ondisk_path
, O_RDWR
| O_EXCL
| O_NOFOLLOW
| O_CLOEXEC
);
1180 if (!got_err_open_nofollow_on_symlink())
1181 return got_error_from_errno2("open", ondisk_path
);
1183 /* We are updating an existing on-disk symlink. */
1184 elen
= readlink(ondisk_path
, etarget
, sizeof(etarget
));
1186 return got_error_from_errno2("readlink", ondisk_path
);
1188 if (elen
== target_len
&&
1189 memcmp(etarget
, target_path
, target_len
) == 0)
1190 return NULL
; /* nothing to do */
1194 err
= update_symlink(ondisk_path
, target_path
, target_len
);
1195 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1196 err
= got_error_from_errno2("close", ondisk_path
);
1200 static const struct got_error
*
1201 is_bad_symlink_target(int *is_bad_symlink
, const char *target_path
,
1202 size_t target_len
, const char *ondisk_path
, const char *wtroot_path
,
1203 const char *meta_dir
)
1205 const struct got_error
*err
= NULL
;
1206 char canonpath
[PATH_MAX
];
1207 char *path_got
= NULL
;
1209 *is_bad_symlink
= 0;
1211 if (target_len
>= sizeof(canonpath
)) {
1212 *is_bad_symlink
= 1;
1217 * We do not use realpath(3) to resolve the symlink's target
1218 * path because we don't want to resolve symlinks recursively.
1219 * Instead we make the path absolute and then canonicalize it.
1220 * Relative symlink target lookup should begin at the directory
1221 * in which the blob object is being installed.
1223 if (!got_path_is_absolute(target_path
)) {
1224 char *abspath
, *parent
;
1225 err
= got_path_dirname(&parent
, ondisk_path
);
1228 if (asprintf(&abspath
, "%s/%s", parent
, target_path
) == -1) {
1230 return got_error_from_errno("asprintf");
1233 if (strlen(abspath
) >= sizeof(canonpath
)) {
1234 err
= got_error_path(abspath
, GOT_ERR_BAD_PATH
);
1238 err
= got_canonpath(abspath
, canonpath
, sizeof(canonpath
));
1243 err
= got_canonpath(target_path
, canonpath
, sizeof(canonpath
));
1248 /* Only allow symlinks pointing at paths within the work tree. */
1249 if (!got_path_is_child(canonpath
, wtroot_path
, strlen(wtroot_path
))) {
1250 *is_bad_symlink
= 1;
1254 /* Do not allow symlinks pointing into the meta directory. */
1255 if (asprintf(&path_got
, "%s/%s", wtroot_path
, meta_dir
) == -1)
1256 return got_error_from_errno("asprintf");
1257 if (got_path_is_child(canonpath
, path_got
, strlen(path_got
)))
1258 *is_bad_symlink
= 1;
1264 static const struct got_error
*
1265 install_symlink(int *is_bad_symlink
, struct got_worktree
*worktree
,
1266 const char *ondisk_path
, const char *path
, struct got_blob_object
*blob
,
1267 int restoring_missing_file
, int reverting_versioned_file
,
1268 int path_is_unversioned
, int allow_bad_symlinks
,
1269 struct got_repository
*repo
,
1270 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1272 const struct got_error
*err
= NULL
;
1273 char target_path
[PATH_MAX
];
1274 size_t len
, target_len
= 0;
1275 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1276 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1278 *is_bad_symlink
= 0;
1281 * Blob object content specifies the target path of the link.
1282 * If a symbolic link cannot be installed we instead create
1283 * a regular file which contains the link target path stored
1284 * in the blob object.
1287 err
= got_object_blob_read_block(&len
, blob
);
1291 if (len
+ target_len
>= sizeof(target_path
)) {
1292 /* Path too long; install as a regular file. */
1293 *is_bad_symlink
= 1;
1294 got_object_blob_rewind(blob
);
1295 return install_blob(worktree
, ondisk_path
, path
,
1296 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1297 restoring_missing_file
, reverting_versioned_file
,
1298 1, path_is_unversioned
, repo
, progress_cb
,
1302 /* Skip blob object header first time around. */
1303 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1305 target_len
+= len
- hdrlen
;
1309 target_path
[target_len
] = '\0';
1311 err
= is_bad_symlink_target(is_bad_symlink
, target_path
, target_len
,
1312 ondisk_path
, worktree
->root_path
, worktree
->meta_dir
);
1316 if (*is_bad_symlink
&& !allow_bad_symlinks
) {
1317 /* install as a regular file */
1318 got_object_blob_rewind(blob
);
1319 err
= install_blob(worktree
, ondisk_path
, path
,
1320 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1321 restoring_missing_file
, reverting_versioned_file
, 1,
1322 path_is_unversioned
, repo
, progress_cb
, progress_arg
);
1326 if (symlink(target_path
, ondisk_path
) == -1) {
1327 if (errno
== EEXIST
) {
1328 int symlink_replaced
;
1329 if (path_is_unversioned
) {
1330 err
= (*progress_cb
)(progress_arg
,
1331 GOT_STATUS_UNVERSIONED
, path
);
1334 err
= replace_existing_symlink(&symlink_replaced
,
1335 ondisk_path
, target_path
, target_len
);
1339 if (symlink_replaced
) {
1340 err
= (*progress_cb
)(progress_arg
,
1341 reverting_versioned_file
?
1343 GOT_STATUS_UPDATE
, path
);
1345 err
= (*progress_cb
)(progress_arg
,
1346 GOT_STATUS_EXISTS
, path
);
1349 return err
; /* Nothing else to do. */
1352 if (errno
== ENOENT
) {
1354 err
= got_path_dirname(&parent
, ondisk_path
);
1357 err
= got_path_mkdir(parent
);
1362 * Retry, and fall through to error handling
1363 * below if this second attempt fails.
1365 if (symlink(target_path
, ondisk_path
) != -1) {
1366 err
= NULL
; /* success */
1368 err
= (*progress_cb
)(progress_arg
,
1369 reverting_versioned_file
?
1370 GOT_STATUS_REVERT
: GOT_STATUS_ADD
,
1377 /* Handle errors from first or second creation attempt. */
1378 if (errno
== ENAMETOOLONG
) {
1379 /* bad target path; install as a regular file */
1380 *is_bad_symlink
= 1;
1381 got_object_blob_rewind(blob
);
1382 err
= install_blob(worktree
, ondisk_path
, path
,
1383 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1384 restoring_missing_file
, reverting_versioned_file
, 1,
1385 path_is_unversioned
, repo
,
1386 progress_cb
, progress_arg
);
1387 } else if (errno
== ENOTDIR
) {
1388 err
= got_error_path(ondisk_path
,
1389 GOT_ERR_FILE_OBSTRUCTED
);
1391 err
= got_error_from_errno3("symlink",
1392 target_path
, ondisk_path
);
1394 } else if (progress_cb
)
1395 err
= (*progress_cb
)(progress_arg
, reverting_versioned_file
?
1396 GOT_STATUS_REVERT
: GOT_STATUS_ADD
, path
);
1400 static const struct got_error
*
1401 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1402 const char *path
, mode_t te_mode
, mode_t st_mode
,
1403 struct got_blob_object
*blob
, int restoring_missing_file
,
1404 int reverting_versioned_file
, int installing_bad_symlink
,
1405 int path_is_unversioned
, struct got_repository
*repo
,
1406 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1408 const struct got_error
*err
= NULL
;
1412 char *tmppath
= NULL
;
1415 mode
= get_ondisk_perms(te_mode
& S_IXUSR
, GOT_DEFAULT_FILE_MODE
);
1416 fd
= open(ondisk_path
, O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
|
1419 if (errno
== ENOENT
|| errno
== ENOTDIR
) {
1421 err
= got_path_dirname(&parent
, path
);
1424 err
= add_dir_on_disk(worktree
, parent
);
1425 if (err
&& err
->code
== GOT_ERR_FILE_OBSTRUCTED
)
1426 err
= got_error_path(path
, err
->code
);
1430 fd
= open(ondisk_path
,
1431 O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
| O_CLOEXEC
,
1434 return got_error_from_errno2("open",
1436 } else if (errno
== EEXIST
) {
1437 if (path_is_unversioned
) {
1438 err
= (*progress_cb
)(progress_arg
,
1439 GOT_STATUS_UNVERSIONED
, path
);
1442 if (!(S_ISLNK(st_mode
) && S_ISREG(te_mode
)) &&
1443 !S_ISREG(st_mode
) && !installing_bad_symlink
) {
1444 /* TODO file is obstructed; do something */
1445 err
= got_error_path(ondisk_path
,
1446 GOT_ERR_FILE_OBSTRUCTED
);
1449 err
= got_opentemp_named_fd(&tmppath
, &fd
,
1455 if (fchmod(fd
, apply_umask(mode
)) == -1) {
1456 err
= got_error_from_errno2("fchmod",
1462 return got_error_from_errno2("open", ondisk_path
);
1466 if (restoring_missing_file
)
1467 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MISSING
,
1469 else if (reverting_versioned_file
)
1470 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_REVERT
,
1473 err
= (*progress_cb
)(progress_arg
,
1474 update
? GOT_STATUS_UPDATE
: GOT_STATUS_ADD
, path
);
1479 hdrlen
= got_object_blob_get_hdrlen(blob
);
1481 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1482 err
= got_object_blob_read_block(&len
, blob
);
1486 /* Skip blob object header first time around. */
1487 ssize_t outlen
= write(fd
, buf
+ hdrlen
, len
- hdrlen
);
1489 err
= got_error_from_errno("write");
1491 } else if (outlen
!= len
- hdrlen
) {
1492 err
= got_error(GOT_ERR_IO
);
1499 if (fsync(fd
) != 0) {
1500 err
= got_error_from_errno("fsync");
1505 if (S_ISLNK(st_mode
) && unlink(ondisk_path
) == -1) {
1506 err
= got_error_from_errno2("unlink", ondisk_path
);
1509 if (rename(tmppath
, ondisk_path
) != 0) {
1510 err
= got_error_from_errno3("rename", tmppath
,
1519 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1520 err
= got_error_from_errno("close");
1521 if (tmppath
!= NULL
&& unlink(tmppath
) == -1 && err
== NULL
)
1522 err
= got_error_from_errno2("unlink", tmppath
);
1528 * Upgrade STATUS_MODIFY to STATUS_CONFLICT if a
1529 * conflict marker is found in newly added lines only.
1531 static const struct got_error
*
1532 get_modified_file_content_status(unsigned char *status
,
1533 struct got_blob_object
*blob
, const char *path
, struct stat
*sb
,
1536 const struct got_error
*err
, *free_err
;
1537 const char *markers
[3] = {
1538 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
1539 GOT_DIFF_CONFLICT_MARKER_SEP
,
1540 GOT_DIFF_CONFLICT_MARKER_END
1543 struct got_diffreg_result
*diffreg_result
= NULL
;
1544 struct diff_result
*r
;
1545 int nchunks_parsed
, n
, i
= 0, ln
= 0;
1547 size_t linesize
= 0;
1550 if (*status
!= GOT_STATUS_MODIFY
)
1553 f1
= got_opentemp();
1555 return got_error_from_errno("got_opentemp");
1558 got_object_blob_rewind(blob
);
1559 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
1564 err
= got_diff_files(&diffreg_result
, f1
, 1, NULL
, ondisk_file
,
1565 1, NULL
, 0, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
1569 r
= diffreg_result
->result
;
1571 for (n
= 0; n
< r
->chunks
.len
; n
+= nchunks_parsed
) {
1572 struct diff_chunk
*c
;
1573 struct diff_chunk_context cc
= {};
1577 * We can optimise a little by advancing straight
1578 * to the next chunk if this one has no added lines.
1580 c
= diff_chunk_get(r
, n
);
1582 if (diff_chunk_type(c
) != CHUNK_PLUS
) {
1584 continue; /* removed or unchanged lines */
1587 pos
= diff_chunk_get_right_start_pos(c
);
1588 if (fseek(ondisk_file
, pos
, SEEK_SET
) == -1) {
1589 err
= got_ferror(ondisk_file
, GOT_ERR_IO
);
1593 diff_chunk_context_load_change(&cc
, &nchunks_parsed
, r
, n
, 0);
1594 ln
= cc
.right
.start
;
1596 while (ln
< cc
.right
.end
) {
1597 linelen
= getline(&line
, &linesize
, ondisk_file
);
1598 if (linelen
== -1) {
1599 if (feof(ondisk_file
))
1601 err
= got_ferror(ondisk_file
, GOT_ERR_IO
);
1605 if (line
&& strncmp(line
, markers
[i
],
1606 strlen(markers
[i
])) == 0) {
1607 if (strcmp(markers
[i
],
1608 GOT_DIFF_CONFLICT_MARKER_END
) == 0) {
1609 *status
= GOT_STATUS_CONFLICT
;
1620 if (f1
!= NULL
&& fclose(f1
) == EOF
&& err
== NULL
)
1621 err
= got_error_from_errno("fclose");
1622 free_err
= got_diffreg_result_free(diffreg_result
);
1630 xbit_differs(struct got_fileindex_entry
*ie
, uint16_t st_mode
)
1632 mode_t ie_mode
= got_fileindex_perms_to_st(ie
);
1633 return ((ie_mode
& S_IXUSR
) != (st_mode
& S_IXUSR
));
1637 stat_info_differs(struct got_fileindex_entry
*ie
, struct stat
*sb
)
1639 return !(ie
->ctime_sec
== sb
->st_ctim
.tv_sec
&&
1640 ie
->ctime_nsec
== sb
->st_ctim
.tv_nsec
&&
1641 ie
->mtime_sec
== sb
->st_mtim
.tv_sec
&&
1642 ie
->mtime_nsec
== sb
->st_mtim
.tv_nsec
&&
1643 ie
->size
== (sb
->st_size
& 0xffffffff) &&
1644 !xbit_differs(ie
, sb
->st_mode
));
1647 static unsigned char
1648 get_staged_status(struct got_fileindex_entry
*ie
)
1650 switch (got_fileindex_entry_stage_get(ie
)) {
1651 case GOT_FILEIDX_STAGE_ADD
:
1652 return GOT_STATUS_ADD
;
1653 case GOT_FILEIDX_STAGE_DELETE
:
1654 return GOT_STATUS_DELETE
;
1655 case GOT_FILEIDX_STAGE_MODIFY
:
1656 return GOT_STATUS_MODIFY
;
1658 return GOT_STATUS_NO_CHANGE
;
1662 static const struct got_error
*
1663 get_symlink_modification_status(unsigned char *status
,
1664 struct got_fileindex_entry
*ie
, const char *abspath
,
1665 int dirfd
, const char *de_name
, struct got_blob_object
*blob
)
1667 const struct got_error
*err
= NULL
;
1668 char target_path
[PATH_MAX
];
1669 char etarget
[PATH_MAX
];
1671 size_t len
, target_len
= 0;
1672 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1673 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1675 *status
= GOT_STATUS_NO_CHANGE
;
1677 /* Blob object content specifies the target path of the link. */
1679 err
= got_object_blob_read_block(&len
, blob
);
1682 if (len
+ target_len
>= sizeof(target_path
)) {
1684 * Should not happen. The blob contents were OK
1685 * when this symlink was installed.
1687 return got_error(GOT_ERR_NO_SPACE
);
1690 /* Skip blob object header first time around. */
1691 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1693 target_len
+= len
- hdrlen
;
1697 target_path
[target_len
] = '\0';
1700 elen
= readlinkat(dirfd
, de_name
, etarget
, sizeof(etarget
));
1702 return got_error_from_errno2("readlinkat", abspath
);
1704 elen
= readlink(abspath
, etarget
, sizeof(etarget
));
1706 return got_error_from_errno2("readlink", abspath
);
1709 if (elen
!= target_len
|| memcmp(etarget
, target_path
, target_len
) != 0)
1710 *status
= GOT_STATUS_MODIFY
;
1715 static const struct got_error
*
1716 get_file_status(unsigned char *status
, struct stat
*sb
,
1717 struct got_fileindex_entry
*ie
, const char *abspath
,
1718 int dirfd
, const char *de_name
, struct got_repository
*repo
)
1720 const struct got_error
*err
= NULL
;
1721 struct got_object_id id
;
1723 int fd
= -1, fd1
= -1;
1726 struct got_blob_object
*blob
= NULL
;
1728 unsigned char staged_status
;
1730 staged_status
= get_staged_status(ie
);
1731 *status
= GOT_STATUS_NO_CHANGE
;
1732 memset(sb
, 0, sizeof(*sb
));
1735 * Whenever the caller provides a directory descriptor and a
1736 * directory entry name for the file, use them! This prevents
1737 * race conditions if filesystem paths change beneath our feet.
1740 if (fstatat(dirfd
, de_name
, sb
, AT_SYMLINK_NOFOLLOW
) == -1) {
1741 if (errno
== ENOENT
) {
1742 if (got_fileindex_entry_has_file_on_disk(ie
))
1743 *status
= GOT_STATUS_MISSING
;
1745 *status
= GOT_STATUS_DELETE
;
1748 err
= got_error_from_errno2("fstatat", abspath
);
1752 fd
= open(abspath
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1753 if (fd
== -1 && errno
!= ENOENT
&&
1754 !got_err_open_nofollow_on_symlink())
1755 return got_error_from_errno2("open", abspath
);
1756 else if (fd
== -1 && got_err_open_nofollow_on_symlink()) {
1757 if (lstat(abspath
, sb
) == -1)
1758 return got_error_from_errno2("lstat", abspath
);
1759 } else if (fd
== -1 || fstat(fd
, sb
) == -1) {
1760 if (errno
== ENOENT
) {
1761 if (got_fileindex_entry_has_file_on_disk(ie
))
1762 *status
= GOT_STATUS_MISSING
;
1764 *status
= GOT_STATUS_DELETE
;
1767 err
= got_error_from_errno2("fstat", abspath
);
1772 if (!S_ISREG(sb
->st_mode
) && !S_ISLNK(sb
->st_mode
)) {
1773 *status
= GOT_STATUS_OBSTRUCTED
;
1777 if (!got_fileindex_entry_has_file_on_disk(ie
)) {
1778 *status
= GOT_STATUS_DELETE
;
1780 } else if (!got_fileindex_entry_has_blob(ie
) &&
1781 staged_status
!= GOT_STATUS_ADD
) {
1782 *status
= GOT_STATUS_ADD
;
1786 if (!stat_info_differs(ie
, sb
))
1789 if (S_ISLNK(sb
->st_mode
) &&
1790 got_fileindex_entry_filetype_get(ie
) != GOT_FILEIDX_MODE_SYMLINK
) {
1791 *status
= GOT_STATUS_MODIFY
;
1795 if (staged_status
== GOT_STATUS_MODIFY
||
1796 staged_status
== GOT_STATUS_ADD
)
1797 got_fileindex_entry_get_staged_blob_id(&id
, ie
);
1799 got_fileindex_entry_get_blob_id(&id
, ie
);
1801 fd1
= got_opentempfd();
1803 err
= got_error_from_errno("got_opentempfd");
1806 err
= got_object_open_as_blob(&blob
, repo
, &id
, sizeof(fbuf
), fd1
);
1810 if (S_ISLNK(sb
->st_mode
)) {
1811 err
= get_symlink_modification_status(status
, ie
,
1812 abspath
, dirfd
, de_name
, blob
);
1817 fd
= openat(dirfd
, de_name
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1819 err
= got_error_from_errno2("openat", abspath
);
1824 f
= fdopen(fd
, "r");
1826 err
= got_error_from_errno2("fdopen", abspath
);
1830 hdrlen
= got_object_blob_get_hdrlen(blob
);
1832 const uint8_t *bbuf
= got_object_blob_get_read_buf(blob
);
1833 err
= got_object_blob_read_block(&blen
, blob
);
1836 /* Skip length of blob object header first time around. */
1837 flen
= fread(fbuf
, 1, sizeof(fbuf
) - hdrlen
, f
);
1838 if (flen
== 0 && ferror(f
)) {
1839 err
= got_error_from_errno("fread");
1842 if (blen
- hdrlen
== 0) {
1844 *status
= GOT_STATUS_MODIFY
;
1846 } else if (flen
== 0) {
1847 if (blen
- hdrlen
!= 0)
1848 *status
= GOT_STATUS_MODIFY
;
1850 } else if (blen
- hdrlen
== flen
) {
1851 /* Skip blob object header first time around. */
1852 if (memcmp(bbuf
+ hdrlen
, fbuf
, flen
) != 0) {
1853 *status
= GOT_STATUS_MODIFY
;
1857 *status
= GOT_STATUS_MODIFY
;
1863 if (*status
== GOT_STATUS_MODIFY
) {
1865 err
= get_modified_file_content_status(status
, blob
, ie
->path
,
1867 } else if (xbit_differs(ie
, sb
->st_mode
))
1868 *status
= GOT_STATUS_MODE_CHANGE
;
1870 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
1871 err
= got_error_from_errno("close");
1873 got_object_blob_close(blob
);
1874 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
1875 err
= got_error_from_errno2("fclose", abspath
);
1876 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1877 err
= got_error_from_errno2("close", abspath
);
1882 * Update timestamps in the file index if a file is unmodified and
1883 * we had to run a full content comparison to find out.
1885 static const struct got_error
*
1886 sync_timestamps(int wt_fd
, const char *path
, unsigned char status
,
1887 struct got_fileindex_entry
*ie
, struct stat
*sb
)
1889 if (status
== GOT_STATUS_NO_CHANGE
&& stat_info_differs(ie
, sb
))
1890 return got_fileindex_entry_update(ie
, wt_fd
, path
,
1891 ie
->blob_sha1
, ie
->commit_sha1
, 1);
1896 static const struct got_error
*remove_ondisk_file(const char *, const char *);
1898 static const struct got_error
*
1899 update_blob(struct got_worktree
*worktree
,
1900 struct got_fileindex
*fileindex
, struct got_fileindex_entry
*ie
,
1901 struct got_tree_entry
*te
, const char *path
,
1902 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
1905 const struct got_error
*err
= NULL
;
1906 struct got_blob_object
*blob
= NULL
;
1907 char *ondisk_path
= NULL
;
1908 unsigned char status
= GOT_STATUS_NO_CHANGE
;
1910 int fd1
= -1, fd2
= -1;
1912 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, path
) == -1)
1913 return got_error_from_errno("asprintf");
1916 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
) {
1917 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
1920 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
1924 if (status
== GOT_STATUS_MISSING
|| status
== GOT_STATUS_DELETE
)
1925 sb
.st_mode
= got_fileindex_perms_to_st(ie
);
1927 if (stat(ondisk_path
, &sb
) == -1) {
1928 if (errno
!= ENOENT
&& errno
!= ENOTDIR
) {
1929 err
= got_error_from_errno2("stat",
1933 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
1934 status
= GOT_STATUS_UNVERSIONED
;
1936 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
1937 status
= GOT_STATUS_UNVERSIONED
;
1939 status
= GOT_STATUS_OBSTRUCTED
;
1943 if (status
== GOT_STATUS_OBSTRUCTED
) {
1945 got_fileindex_entry_mark_skipped(ie
);
1946 err
= (*progress_cb
)(progress_arg
, status
, path
);
1949 if (status
== GOT_STATUS_CONFLICT
) {
1951 got_fileindex_entry_mark_skipped(ie
);
1952 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CANNOT_UPDATE
,
1957 if (S_ISDIR(te
->mode
)) { /* file changing into a directory */
1958 if (status
== GOT_STATUS_UNVERSIONED
) {
1959 err
= (*progress_cb
)(progress_arg
, status
, path
);
1960 } else if (status
!= GOT_STATUS_NO_CHANGE
&&
1961 status
!= GOT_STATUS_DELETE
&&
1962 status
!= GOT_STATUS_NONEXISTENT
&&
1963 status
!= GOT_STATUS_MISSING
) {
1964 err
= (*progress_cb
)(progress_arg
,
1965 GOT_STATUS_CANNOT_DELETE
, path
);
1967 if (status
!= GOT_STATUS_DELETE
&&
1968 status
!= GOT_STATUS_NONEXISTENT
&&
1969 status
!= GOT_STATUS_MISSING
) {
1970 err
= remove_ondisk_file(worktree
->root_path
,
1972 if (err
&& !(err
->code
== GOT_ERR_ERRNO
&&
1976 got_fileindex_entry_remove(fileindex
, ie
);
1977 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_DELETE
,
1980 goto done
; /* nothing else to do */
1983 if (ie
&& status
!= GOT_STATUS_MISSING
&& S_ISREG(sb
.st_mode
) &&
1984 (S_ISLNK(te
->mode
) ||
1985 (te
->mode
& S_IXUSR
) == (sb
.st_mode
& S_IXUSR
))) {
1987 * This is a regular file or an installed bad symlink.
1988 * If the file index indicates that this file is already
1989 * up-to-date with respect to the repository we can skip
1990 * updating contents of this file.
1992 if (got_fileindex_entry_has_commit(ie
) &&
1993 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
1994 SHA1_DIGEST_LENGTH
) == 0) {
1996 err
= sync_timestamps(worktree
->root_fd
,
1997 path
, status
, ie
, &sb
);
2000 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
2004 if (got_fileindex_entry_has_blob(ie
) &&
2005 memcmp(ie
->blob_sha1
, te
->id
.sha1
,
2006 SHA1_DIGEST_LENGTH
) == 0) {
2007 /* Different commit but the same blob. */
2008 if (got_fileindex_entry_has_commit(ie
)) {
2009 /* Update the base commit ID of this file. */
2010 memcpy(ie
->commit_sha1
,
2011 worktree
->base_commit_id
->sha1
,
2012 sizeof(ie
->commit_sha1
));
2014 err
= sync_timestamps(worktree
->root_fd
,
2015 path
, status
, ie
, &sb
);
2018 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
2024 fd1
= got_opentempfd();
2026 err
= got_error_from_errno("got_opentempfd");
2029 err
= got_object_open_as_blob(&blob
, repo
, &te
->id
, 8192, fd1
);
2033 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_ADD
) {
2034 int update_timestamps
;
2035 struct got_blob_object
*blob2
= NULL
;
2036 char *label_orig
= NULL
;
2037 if (got_fileindex_entry_has_blob(ie
)) {
2038 fd2
= got_opentempfd();
2040 err
= got_error_from_errno("got_opentempfd");
2043 struct got_object_id id2
;
2044 got_fileindex_entry_get_blob_id(&id2
, ie
);
2045 err
= got_object_open_as_blob(&blob2
, repo
, &id2
, 8192,
2050 if (got_fileindex_entry_has_commit(ie
)) {
2051 char id_str
[SHA1_DIGEST_STRING_LENGTH
];
2052 if (got_sha1_digest_to_str(ie
->commit_sha1
, id_str
,
2053 sizeof(id_str
)) == NULL
) {
2054 err
= got_error_path(id_str
,
2055 GOT_ERR_BAD_OBJ_ID_STR
);
2058 if (asprintf(&label_orig
, "%s: commit %s",
2059 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
2060 err
= got_error_from_errno("asprintf");
2064 if (S_ISLNK(te
->mode
) && S_ISLNK(sb
.st_mode
)) {
2066 err
= got_object_blob_read_to_str(&link_target
, blob
);
2069 err
= merge_symlink(worktree
, blob2
, ondisk_path
, path
,
2070 label_orig
, link_target
, worktree
->base_commit_id
,
2071 repo
, progress_cb
, progress_arg
);
2074 err
= merge_blob(&update_timestamps
, worktree
, blob2
,
2075 ondisk_path
, path
, sb
.st_mode
, label_orig
, blob
,
2076 worktree
->base_commit_id
, repo
,
2077 progress_cb
, progress_arg
);
2080 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
) {
2081 err
= got_error_from_errno("close");
2085 got_object_blob_close(blob2
);
2089 * Do not update timestamps of files with local changes.
2090 * Otherwise, a future status walk would treat them as
2091 * unmodified files again.
2093 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2094 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
,
2096 } else if (status
== GOT_STATUS_MODE_CHANGE
) {
2097 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2098 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
2099 } else if (status
== GOT_STATUS_DELETE
) {
2100 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
2103 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2104 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
2108 int is_bad_symlink
= 0;
2109 if (S_ISLNK(te
->mode
)) {
2110 err
= install_symlink(&is_bad_symlink
, worktree
,
2111 ondisk_path
, path
, blob
,
2112 status
== GOT_STATUS_MISSING
, 0,
2113 status
== GOT_STATUS_UNVERSIONED
, 0,
2114 repo
, progress_cb
, progress_arg
);
2116 err
= install_blob(worktree
, ondisk_path
, path
,
2117 te
->mode
, sb
.st_mode
, blob
,
2118 status
== GOT_STATUS_MISSING
, 0, 0,
2119 status
== GOT_STATUS_UNVERSIONED
, repo
,
2120 progress_cb
, progress_arg
);
2126 err
= got_fileindex_entry_update(ie
,
2127 worktree
->root_fd
, path
, blob
->id
.sha1
,
2128 worktree
->base_commit_id
->sha1
, 1);
2130 err
= create_fileindex_entry(&ie
, fileindex
,
2131 worktree
->base_commit_id
, worktree
->root_fd
, path
,
2137 if (is_bad_symlink
) {
2138 got_fileindex_entry_filetype_set(ie
,
2139 GOT_FILEIDX_MODE_BAD_SYMLINK
);
2143 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
) {
2144 err
= got_error_from_errno("close");
2147 got_object_blob_close(blob
);
2153 static const struct got_error
*
2154 remove_ondisk_file(const char *root_path
, const char *path
)
2156 const struct got_error
*err
= NULL
;
2157 char *ondisk_path
= NULL
, *parent
= NULL
;
2159 if (asprintf(&ondisk_path
, "%s/%s", root_path
, path
) == -1)
2160 return got_error_from_errno("asprintf");
2162 if (unlink(ondisk_path
) == -1) {
2163 if (errno
!= ENOENT
)
2164 err
= got_error_from_errno2("unlink", ondisk_path
);
2166 size_t root_len
= strlen(root_path
);
2167 err
= got_path_dirname(&parent
, ondisk_path
);
2170 while (got_path_cmp(parent
, root_path
,
2171 strlen(parent
), root_len
) != 0) {
2173 ondisk_path
= parent
;
2175 if (rmdir(ondisk_path
) == -1) {
2176 if (errno
!= ENOTEMPTY
)
2177 err
= got_error_from_errno2("rmdir",
2181 err
= got_path_dirname(&parent
, ondisk_path
);
2192 static const struct got_error
*
2193 delete_blob(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2194 struct got_fileindex_entry
*ie
, struct got_repository
*repo
,
2195 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2197 const struct got_error
*err
= NULL
;
2198 unsigned char status
;
2202 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
2203 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
2205 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, ie
->path
)
2207 return got_error_from_errno("asprintf");
2209 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, repo
);
2213 if (S_ISLNK(sb
.st_mode
) && status
!= GOT_STATUS_NO_CHANGE
) {
2214 char ondisk_target
[PATH_MAX
];
2215 ssize_t ondisk_len
= readlink(ondisk_path
, ondisk_target
,
2216 sizeof(ondisk_target
));
2217 if (ondisk_len
== -1) {
2218 err
= got_error_from_errno2("readlink", ondisk_path
);
2221 ondisk_target
[ondisk_len
] = '\0';
2222 err
= install_symlink_conflict(NULL
, worktree
->base_commit_id
,
2223 NULL
, NULL
, /* XXX pass common ancestor info? */
2224 ondisk_target
, ondisk_path
);
2227 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
2232 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_CONFLICT
||
2233 status
== GOT_STATUS_ADD
) {
2234 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, ie
->path
);
2238 * Preserve the working file and change the deleted blob's
2239 * entry into a schedule-add entry.
2241 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
,
2242 ie
->path
, NULL
, NULL
, 0);
2244 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_DELETE
, ie
->path
);
2247 if (status
== GOT_STATUS_NO_CHANGE
) {
2248 err
= remove_ondisk_file(worktree
->root_path
, ie
->path
);
2252 got_fileindex_entry_remove(fileindex
, ie
);
2259 struct diff_cb_arg
{
2260 struct got_fileindex
*fileindex
;
2261 struct got_worktree
*worktree
;
2262 struct got_repository
*repo
;
2263 got_worktree_checkout_cb progress_cb
;
2265 got_cancel_cb cancel_cb
;
2269 static const struct got_error
*
2270 diff_old_new(void *arg
, struct got_fileindex_entry
*ie
,
2271 struct got_tree_entry
*te
, const char *parent_path
)
2273 const struct got_error
*err
= NULL
;
2274 struct diff_cb_arg
*a
= arg
;
2277 err
= a
->cancel_cb(a
->cancel_arg
);
2282 return update_blob(a
->worktree
, a
->fileindex
, ie
, te
,
2283 ie
->path
, a
->repo
, a
->progress_cb
, a
->progress_arg
);
2286 static const struct got_error
*
2287 diff_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
2289 const struct got_error
*err
= NULL
;
2290 struct diff_cb_arg
*a
= arg
;
2293 err
= a
->cancel_cb(a
->cancel_arg
);
2298 return delete_blob(a
->worktree
, a
->fileindex
, ie
,
2299 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2302 static const struct got_error
*
2303 diff_new(void *arg
, struct got_tree_entry
*te
, const char *parent_path
)
2305 const struct got_error
*err
= NULL
;
2306 struct diff_cb_arg
*a
= arg
;
2310 err
= a
->cancel_cb(a
->cancel_arg
);
2315 if (got_object_tree_entry_is_submodule(te
))
2318 if (!S_ISREG(te
->mode
) && !S_ISLNK(te
->mode
))
2321 if (asprintf(&path
, "%s%s%s", parent_path
,
2322 parent_path
[0] ? "/" : "", te
->name
)
2324 return got_error_from_errno("asprintf");
2326 err
= update_blob(a
->worktree
, a
->fileindex
, NULL
, te
, path
,
2327 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2333 const struct got_error
*
2334 got_worktree_get_uuid(char **uuidstr
, struct got_worktree
*worktree
)
2336 uint32_t uuid_status
;
2338 uuid_to_string(&worktree
->uuid
, uuidstr
, &uuid_status
);
2339 if (uuid_status
!= uuid_s_ok
) {
2341 return got_error_uuid(uuid_status
, "uuid_to_string");
2347 static const struct got_error
*
2348 get_ref_name(char **refname
, struct got_worktree
*worktree
, const char *prefix
)
2350 const struct got_error
*err
= NULL
;
2351 char *uuidstr
= NULL
;
2355 err
= got_worktree_get_uuid(&uuidstr
, worktree
);
2359 if (asprintf(refname
, "%s-%s", prefix
, uuidstr
) == -1) {
2360 err
= got_error_from_errno("asprintf");
2367 const struct got_error
*
2368 got_worktree_get_logmsg_ref_name(char **refname
, struct got_worktree
*worktree
,
2371 return get_ref_name(refname
, worktree
, prefix
);
2374 static const struct got_error
*
2375 get_base_ref_name(char **refname
, struct got_worktree
*worktree
)
2377 return get_ref_name(refname
, worktree
, GOT_WORKTREE_BASE_REF_PREFIX
);
2380 static const struct got_error
*
2381 get_rebase_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2383 return get_ref_name(refname
, worktree
,
2384 GOT_WORKTREE_REBASE_TMP_REF_PREFIX
);
2387 static const struct got_error
*
2388 get_newbase_symref_name(char **refname
, struct got_worktree
*worktree
)
2390 return get_ref_name(refname
, worktree
, GOT_WORKTREE_NEWBASE_REF_PREFIX
);
2393 static const struct got_error
*
2394 get_rebase_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2396 return get_ref_name(refname
, worktree
,
2397 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX
);
2400 static const struct got_error
*
2401 get_rebase_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2403 return get_ref_name(refname
, worktree
,
2404 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX
);
2407 static const struct got_error
*
2408 get_histedit_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2410 return get_ref_name(refname
, worktree
,
2411 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX
);
2414 static const struct got_error
*
2415 get_histedit_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2417 return get_ref_name(refname
, worktree
,
2418 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX
);
2421 static const struct got_error
*
2422 get_histedit_base_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2424 return get_ref_name(refname
, worktree
,
2425 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX
);
2428 static const struct got_error
*
2429 get_histedit_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2431 return get_ref_name(refname
, worktree
,
2432 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX
);
2435 const struct got_error
*
2436 got_worktree_get_histedit_script_path(char **path
,
2437 struct got_worktree
*worktree
)
2439 if (asprintf(path
, "%s/%s/%s", worktree
->root_path
,
2440 worktree
->meta_dir
, GOT_WORKTREE_HISTEDIT_SCRIPT
) == -1) {
2442 return got_error_from_errno("asprintf");
2447 static const struct got_error
*
2448 get_merge_branch_ref_name(char **refname
, struct got_worktree
*worktree
)
2450 return get_ref_name(refname
, worktree
,
2451 GOT_WORKTREE_MERGE_BRANCH_REF_PREFIX
);
2454 static const struct got_error
*
2455 get_merge_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2457 return get_ref_name(refname
, worktree
,
2458 GOT_WORKTREE_MERGE_COMMIT_REF_PREFIX
);
2462 * Prevent Git's garbage collector from deleting our base commit by
2463 * setting a reference to our base commit's ID.
2465 static const struct got_error
*
2466 ref_base_commit(struct got_worktree
*worktree
, struct got_repository
*repo
)
2468 const struct got_error
*err
= NULL
;
2469 struct got_reference
*ref
= NULL
;
2472 err
= get_base_ref_name(&refname
, worktree
);
2476 err
= got_ref_alloc(&ref
, refname
, worktree
->base_commit_id
);
2480 err
= got_ref_write(ref
, repo
);
2488 static const struct got_error
*
2489 get_fileindex_path(char **fileindex_path
, struct got_worktree
*worktree
)
2491 const struct got_error
*err
= NULL
;
2493 if (asprintf(fileindex_path
, "%s/%s/%s", worktree
->root_path
,
2494 worktree
->meta_dir
, GOT_WORKTREE_FILE_INDEX
) == -1) {
2495 err
= got_error_from_errno("asprintf");
2496 *fileindex_path
= NULL
;
2502 static const struct got_error
*
2503 open_fileindex(struct got_fileindex
**fileindex
, char **fileindex_path
,
2504 struct got_worktree
*worktree
)
2506 const struct got_error
*err
= NULL
;
2509 *fileindex_path
= NULL
;
2510 *fileindex
= got_fileindex_alloc();
2511 if (*fileindex
== NULL
)
2512 return got_error_from_errno("got_fileindex_alloc");
2514 err
= get_fileindex_path(fileindex_path
, worktree
);
2518 index
= fopen(*fileindex_path
, "rbe");
2519 if (index
== NULL
) {
2520 if (errno
!= ENOENT
)
2521 err
= got_error_from_errno2("fopen", *fileindex_path
);
2523 err
= got_fileindex_read(*fileindex
, index
);
2524 if (fclose(index
) == EOF
&& err
== NULL
)
2525 err
= got_error_from_errno("fclose");
2529 free(*fileindex_path
);
2530 *fileindex_path
= NULL
;
2531 got_fileindex_free(*fileindex
);
2537 struct bump_base_commit_id_arg
{
2538 struct got_object_id
*base_commit_id
;
2541 const char *entry_name
;
2542 got_worktree_checkout_cb progress_cb
;
2546 static const struct got_error
*
2547 bump_base_commit_id(void *arg
, struct got_fileindex_entry
*ie
)
2549 const struct got_error
*err
;
2550 struct bump_base_commit_id_arg
*a
= arg
;
2552 if (a
->entry_name
) {
2553 if (strcmp(ie
->path
, a
->path
) != 0)
2555 } else if (!got_path_is_child(ie
->path
, a
->path
, a
->path_len
))
2558 if (got_fileindex_entry_was_skipped(ie
))
2561 if (memcmp(ie
->commit_sha1
, a
->base_commit_id
->sha1
,
2562 SHA1_DIGEST_LENGTH
) == 0)
2565 if (a
->progress_cb
) {
2566 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_BUMP_BASE
,
2571 memcpy(ie
->commit_sha1
, a
->base_commit_id
->sha1
, SHA1_DIGEST_LENGTH
);
2575 /* Bump base commit ID of all files within an updated part of the work tree. */
2576 static const struct got_error
*
2577 bump_base_commit_id_everywhere(struct got_worktree
*worktree
,
2578 struct got_fileindex
*fileindex
,
2579 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2581 struct bump_base_commit_id_arg bbc_arg
;
2583 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2584 bbc_arg
.entry_name
= NULL
;
2586 bbc_arg
.path_len
= 0;
2587 bbc_arg
.progress_cb
= progress_cb
;
2588 bbc_arg
.progress_arg
= progress_arg
;
2590 return got_fileindex_for_each_entry_safe(fileindex
,
2591 bump_base_commit_id
, &bbc_arg
);
2594 static const struct got_error
*
2595 sync_fileindex(struct got_fileindex
*fileindex
, const char *fileindex_path
)
2597 const struct got_error
*err
= NULL
;
2598 char *new_fileindex_path
= NULL
;
2599 FILE *new_index
= NULL
;
2600 struct timespec timeout
;
2602 err
= got_opentemp_named(&new_fileindex_path
, &new_index
,
2603 fileindex_path
, "");
2607 err
= got_fileindex_write(fileindex
, new_index
);
2611 if (rename(new_fileindex_path
, fileindex_path
) != 0) {
2612 err
= got_error_from_errno3("rename", new_fileindex_path
,
2614 unlink(new_fileindex_path
);
2618 * Sleep for a short amount of time to ensure that files modified after
2619 * this program exits have a different time stamp from the one which
2620 * was recorded in the file index.
2623 timeout
.tv_nsec
= 1;
2624 nanosleep(&timeout
, NULL
);
2628 free(new_fileindex_path
);
2632 static const struct got_error
*
2633 find_tree_entry_for_checkout(int *entry_type
, char **tree_relpath
,
2634 struct got_object_id
**tree_id
, const char *wt_relpath
,
2635 struct got_commit_object
*base_commit
, struct got_worktree
*worktree
,
2636 struct got_repository
*repo
)
2638 const struct got_error
*err
= NULL
;
2639 struct got_object_id
*id
= NULL
;
2640 char *in_repo_path
= NULL
;
2641 int is_root_wt
= got_path_is_root_dir(worktree
->path_prefix
);
2643 *entry_type
= GOT_OBJ_TYPE_ANY
;
2644 *tree_relpath
= NULL
;
2647 if (wt_relpath
[0] == '\0') {
2648 /* Check out all files within the work tree. */
2649 *entry_type
= GOT_OBJ_TYPE_TREE
;
2650 *tree_relpath
= strdup("");
2651 if (*tree_relpath
== NULL
) {
2652 err
= got_error_from_errno("strdup");
2655 err
= got_object_id_by_path(tree_id
, repo
, base_commit
,
2656 worktree
->path_prefix
);
2662 /* Check out a subset of files in the work tree. */
2664 if (asprintf(&in_repo_path
, "%s%s%s", worktree
->path_prefix
,
2665 is_root_wt
? "" : "/", wt_relpath
) == -1) {
2666 err
= got_error_from_errno("asprintf");
2670 err
= got_object_id_by_path(&id
, repo
, base_commit
, in_repo_path
);
2675 in_repo_path
= NULL
;
2677 err
= got_object_get_type(entry_type
, repo
, id
);
2681 if (*entry_type
== GOT_OBJ_TYPE_BLOB
) {
2682 /* Check out a single file. */
2683 if (strchr(wt_relpath
, '/') == NULL
) {
2684 /* Check out a single file in work tree's root dir. */
2685 in_repo_path
= strdup(worktree
->path_prefix
);
2686 if (in_repo_path
== NULL
) {
2687 err
= got_error_from_errno("strdup");
2690 *tree_relpath
= strdup("");
2691 if (*tree_relpath
== NULL
) {
2692 err
= got_error_from_errno("strdup");
2696 /* Check out a single file in a subdirectory. */
2697 err
= got_path_dirname(tree_relpath
, wt_relpath
);
2700 if (asprintf(&in_repo_path
, "%s%s%s",
2701 worktree
->path_prefix
, is_root_wt
? "" : "/",
2702 *tree_relpath
) == -1) {
2703 err
= got_error_from_errno("asprintf");
2707 err
= got_object_id_by_path(tree_id
, repo
,
2708 base_commit
, in_repo_path
);
2710 /* Check out all files within a subdirectory. */
2711 *tree_id
= got_object_id_dup(id
);
2712 if (*tree_id
== NULL
) {
2713 err
= got_error_from_errno("got_object_id_dup");
2716 *tree_relpath
= strdup(wt_relpath
);
2717 if (*tree_relpath
== NULL
) {
2718 err
= got_error_from_errno("strdup");
2726 *entry_type
= GOT_OBJ_TYPE_ANY
;
2727 free(*tree_relpath
);
2728 *tree_relpath
= NULL
;
2735 static const struct got_error
*
2736 checkout_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2737 const char *relpath
, struct got_object_id
*tree_id
, const char *entry_name
,
2738 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
2739 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
2741 const struct got_error
*err
= NULL
;
2742 struct got_commit_object
*commit
= NULL
;
2743 struct got_tree_object
*tree
= NULL
;
2744 struct got_fileindex_diff_tree_cb diff_cb
;
2745 struct diff_cb_arg arg
;
2747 err
= ref_base_commit(worktree
, repo
);
2749 if (!(err
->code
== GOT_ERR_ERRNO
&&
2750 (errno
== EACCES
|| errno
== EROFS
)))
2752 err
= (*progress_cb
)(progress_arg
,
2753 GOT_STATUS_BASE_REF_ERR
, worktree
->root_path
);
2758 err
= got_object_open_as_commit(&commit
, repo
,
2759 worktree
->base_commit_id
);
2763 err
= got_object_open_as_tree(&tree
, repo
, tree_id
);
2768 got_object_tree_find_entry(tree
, entry_name
) == NULL
) {
2769 err
= got_error_path(entry_name
, GOT_ERR_NO_TREE_ENTRY
);
2773 diff_cb
.diff_old_new
= diff_old_new
;
2774 diff_cb
.diff_old
= diff_old
;
2775 diff_cb
.diff_new
= diff_new
;
2776 arg
.fileindex
= fileindex
;
2777 arg
.worktree
= worktree
;
2779 arg
.progress_cb
= progress_cb
;
2780 arg
.progress_arg
= progress_arg
;
2781 arg
.cancel_cb
= cancel_cb
;
2782 arg
.cancel_arg
= cancel_arg
;
2783 err
= got_fileindex_diff_tree(fileindex
, tree
, relpath
,
2784 entry_name
, repo
, &diff_cb
, &arg
);
2787 got_object_tree_close(tree
);
2789 got_object_commit_close(commit
);
2793 const struct got_error
*
2794 got_worktree_checkout_files(struct got_worktree
*worktree
,
2795 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
2796 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
2797 got_cancel_cb cancel_cb
, void *cancel_arg
)
2799 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
2800 struct got_commit_object
*commit
= NULL
;
2801 struct got_tree_object
*tree
= NULL
;
2802 struct got_fileindex
*fileindex
= NULL
;
2803 char *fileindex_path
= NULL
;
2804 struct got_pathlist_entry
*pe
;
2805 struct tree_path_data
{
2806 STAILQ_ENTRY(tree_path_data
) entry
;
2807 struct got_object_id
*tree_id
;
2812 STAILQ_HEAD(tree_paths
, tree_path_data
) tree_paths
;
2814 STAILQ_INIT(&tree_paths
);
2816 err
= lock_worktree(worktree
, LOCK_EX
);
2820 err
= got_object_open_as_commit(&commit
, repo
,
2821 worktree
->base_commit_id
);
2825 /* Map all specified paths to in-repository trees. */
2826 TAILQ_FOREACH(pe
, paths
, entry
) {
2827 tpd
= malloc(sizeof(*tpd
));
2829 err
= got_error_from_errno("malloc");
2833 err
= find_tree_entry_for_checkout(&tpd
->entry_type
,
2834 &tpd
->relpath
, &tpd
->tree_id
, pe
->path
, commit
,
2841 if (tpd
->entry_type
== GOT_OBJ_TYPE_BLOB
) {
2842 err
= got_path_basename(&tpd
->entry_name
, pe
->path
);
2850 tpd
->entry_name
= NULL
;
2852 STAILQ_INSERT_TAIL(&tree_paths
, tpd
, entry
);
2856 * Read the file index.
2857 * Checking out files is supposed to be an idempotent operation.
2858 * If the on-disk file index is incomplete we will try to complete it.
2860 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
2864 tpd
= STAILQ_FIRST(&tree_paths
);
2865 TAILQ_FOREACH(pe
, paths
, entry
) {
2866 struct bump_base_commit_id_arg bbc_arg
;
2868 err
= checkout_files(worktree
, fileindex
, tpd
->relpath
,
2869 tpd
->tree_id
, tpd
->entry_name
, repo
,
2870 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
2874 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2875 bbc_arg
.entry_name
= tpd
->entry_name
;
2876 bbc_arg
.path
= pe
->path
;
2877 bbc_arg
.path_len
= pe
->path_len
;
2878 bbc_arg
.progress_cb
= progress_cb
;
2879 bbc_arg
.progress_arg
= progress_arg
;
2880 err
= got_fileindex_for_each_entry_safe(fileindex
,
2881 bump_base_commit_id
, &bbc_arg
);
2885 tpd
= STAILQ_NEXT(tpd
, entry
);
2887 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
2888 if (sync_err
&& err
== NULL
)
2891 free(fileindex_path
);
2893 got_object_tree_close(tree
);
2895 got_object_commit_close(commit
);
2897 got_fileindex_free(fileindex
);
2898 while (!STAILQ_EMPTY(&tree_paths
)) {
2899 tpd
= STAILQ_FIRST(&tree_paths
);
2900 STAILQ_REMOVE_HEAD(&tree_paths
, entry
);
2905 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
2906 if (unlockerr
&& err
== NULL
)
2911 static const struct got_error
*
2912 add_file(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2913 struct got_fileindex_entry
*ie
, const char *ondisk_path
,
2914 const char *path2
, struct got_blob_object
*blob2
, mode_t mode2
,
2915 int restoring_missing_file
, int reverting_versioned_file
,
2916 int path_is_unversioned
, int allow_bad_symlinks
,
2917 struct got_repository
*repo
,
2918 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2920 const struct got_error
*err
= NULL
;
2921 int is_bad_symlink
= 0;
2923 if (S_ISLNK(mode2
)) {
2924 err
= install_symlink(&is_bad_symlink
,
2925 worktree
, ondisk_path
, path2
, blob2
,
2926 restoring_missing_file
,
2927 reverting_versioned_file
,
2928 path_is_unversioned
, allow_bad_symlinks
,
2929 repo
, progress_cb
, progress_arg
);
2931 err
= install_blob(worktree
, ondisk_path
, path2
,
2932 mode2
, GOT_DEFAULT_FILE_MODE
, blob2
,
2933 restoring_missing_file
, reverting_versioned_file
, 0,
2934 path_is_unversioned
, repo
, progress_cb
, progress_arg
);
2939 /* Adding an unversioned file. */
2940 err
= got_fileindex_entry_alloc(&ie
, path2
);
2943 err
= got_fileindex_entry_update(ie
,
2944 worktree
->root_fd
, path2
, NULL
, NULL
, 1);
2946 got_fileindex_entry_free(ie
);
2949 err
= got_fileindex_entry_add(fileindex
, ie
);
2951 got_fileindex_entry_free(ie
);
2955 /* Re-adding a locally deleted file. */
2956 err
= got_fileindex_entry_update(ie
,
2957 worktree
->root_fd
, path2
, ie
->blob_sha1
,
2958 worktree
->base_commit_id
->sha1
, 0);
2963 if (is_bad_symlink
) {
2964 got_fileindex_entry_filetype_set(ie
,
2965 GOT_FILEIDX_MODE_BAD_SYMLINK
);
2971 struct merge_file_cb_arg
{
2972 struct got_worktree
*worktree
;
2973 struct got_fileindex
*fileindex
;
2974 got_worktree_checkout_cb progress_cb
;
2976 got_cancel_cb cancel_cb
;
2978 const char *label_orig
;
2979 struct got_object_id
*commit_id2
;
2980 int allow_bad_symlinks
;
2983 static const struct got_error
*
2984 merge_file_cb(void *arg
, struct got_blob_object
*blob1
,
2985 struct got_blob_object
*blob2
, FILE *f1
, FILE *f2
,
2986 struct got_object_id
*id1
, struct got_object_id
*id2
,
2987 const char *path1
, const char *path2
,
2988 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
2990 static const struct got_error
*err
= NULL
;
2991 struct merge_file_cb_arg
*a
= arg
;
2992 struct got_fileindex_entry
*ie
;
2993 char *ondisk_path
= NULL
;
2995 unsigned char status
;
2996 int local_changes_subsumed
;
2997 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
2998 char *id_str
= NULL
, *label_deriv2
= NULL
;
2999 struct got_object_id
*id
= NULL
;
3001 if (blob1
&& blob2
) {
3002 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
3005 return (*a
->progress_cb
)(a
->progress_arg
,
3006 GOT_STATUS_MISSING
, path2
);
3008 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3010 return got_error_from_errno("asprintf");
3012 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
3017 if (status
== GOT_STATUS_DELETE
) {
3018 err
= (*a
->progress_cb
)(a
->progress_arg
,
3019 GOT_STATUS_MERGE
, path2
);
3022 if (status
!= GOT_STATUS_NO_CHANGE
&&
3023 status
!= GOT_STATUS_MODIFY
&&
3024 status
!= GOT_STATUS_CONFLICT
&&
3025 status
!= GOT_STATUS_ADD
) {
3026 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path2
);
3030 if (S_ISLNK(mode1
) && S_ISLNK(mode2
)) {
3032 err
= got_object_blob_read_to_str(&link_target2
, blob2
);
3035 err
= merge_symlink(a
->worktree
, blob1
, ondisk_path
,
3036 path2
, a
->label_orig
, link_target2
, a
->commit_id2
,
3037 repo
, a
->progress_cb
, a
->progress_arg
);
3042 f_orig
= got_opentemp();
3043 if (f_orig
== NULL
) {
3044 err
= got_error_from_errno("got_opentemp");
3047 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
3052 f_deriv2
= got_opentemp();
3053 if (f_deriv2
== NULL
)
3055 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
3060 fd
= open(ondisk_path
,
3061 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
3063 err
= got_error_from_errno2("open",
3067 f_deriv
= fdopen(fd
, "r");
3068 if (f_deriv
== NULL
) {
3069 err
= got_error_from_errno2("fdopen",
3074 err
= got_object_id_str(&id_str
, a
->commit_id2
);
3077 if (asprintf(&label_deriv2
, "%s: commit %s",
3078 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
3079 err
= got_error_from_errno("asprintf");
3082 err
= merge_file(&local_changes_subsumed
, a
->worktree
,
3083 f_orig
, f_deriv
, f_deriv2
, ondisk_path
, path2
,
3084 mode2
, a
->label_orig
, NULL
, label_deriv2
,
3085 GOT_DIFF_ALGORITHM_PATIENCE
, repo
,
3086 a
->progress_cb
, a
->progress_arg
);
3089 ie
= got_fileindex_entry_get(a
->fileindex
, path1
,
3092 return (*a
->progress_cb
)(a
->progress_arg
,
3093 GOT_STATUS_MISSING
, path1
);
3095 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3097 return got_error_from_errno("asprintf");
3099 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
3105 case GOT_STATUS_NO_CHANGE
:
3106 err
= (*a
->progress_cb
)(a
->progress_arg
,
3107 GOT_STATUS_DELETE
, path1
);
3110 err
= remove_ondisk_file(a
->worktree
->root_path
, path1
);
3114 got_fileindex_entry_mark_deleted_from_disk(ie
);
3116 case GOT_STATUS_DELETE
:
3117 case GOT_STATUS_MISSING
:
3118 err
= (*a
->progress_cb
)(a
->progress_arg
,
3119 GOT_STATUS_DELETE
, path1
);
3123 got_fileindex_entry_mark_deleted_from_disk(ie
);
3125 case GOT_STATUS_MODIFY
: {
3130 * Delete the file only if its content already
3131 * exists in the repository.
3133 err
= got_object_blob_file_create(&id
, &blob1_f
,
3134 &blob1_size
, path1
);
3137 if (fclose(blob1_f
) == EOF
) {
3138 err
= got_error_from_errno("fclose");
3142 /* Implied existence check. */
3143 err
= got_object_get_type(&obj_type
, repo
, id
);
3145 if (err
->code
!= GOT_ERR_NO_OBJ
)
3147 err
= (*a
->progress_cb
)(a
->progress_arg
,
3148 GOT_STATUS_CANNOT_DELETE
, path1
);
3150 } else if (obj_type
!= GOT_OBJ_TYPE_BLOB
) {
3151 err
= (*a
->progress_cb
)(a
->progress_arg
,
3152 GOT_STATUS_CANNOT_DELETE
, path1
);
3155 err
= (*a
->progress_cb
)(a
->progress_arg
,
3156 GOT_STATUS_DELETE
, path1
);
3159 err
= remove_ondisk_file(a
->worktree
->root_path
,
3164 got_fileindex_entry_mark_deleted_from_disk(ie
);
3167 case GOT_STATUS_ADD
: {
3171 * Delete the file only if its content already
3172 * exists in the repository.
3174 err
= got_object_blob_file_create(&id
, &blob1_f
,
3175 &blob1_size
, path1
);
3178 if (fclose(blob1_f
) == EOF
) {
3179 err
= got_error_from_errno("fclose");
3182 if (got_object_id_cmp(id
, id1
) == 0) {
3183 err
= (*a
->progress_cb
)(a
->progress_arg
,
3184 GOT_STATUS_DELETE
, path1
);
3187 err
= remove_ondisk_file(a
->worktree
->root_path
,
3192 got_fileindex_entry_remove(a
->fileindex
,
3195 err
= (*a
->progress_cb
)(a
->progress_arg
,
3196 GOT_STATUS_CANNOT_DELETE
, path1
);
3202 case GOT_STATUS_CONFLICT
:
3203 err
= (*a
->progress_cb
)(a
->progress_arg
,
3204 GOT_STATUS_CANNOT_DELETE
, path1
);
3208 case GOT_STATUS_OBSTRUCTED
:
3209 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path1
);
3217 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3219 return got_error_from_errno("asprintf");
3220 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
3223 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
3227 if (status
!= GOT_STATUS_NO_CHANGE
&&
3228 status
!= GOT_STATUS_MODIFY
&&
3229 status
!= GOT_STATUS_CONFLICT
&&
3230 status
!= GOT_STATUS_ADD
&&
3231 status
!= GOT_STATUS_DELETE
) {
3232 err
= (*a
->progress_cb
)(a
->progress_arg
,
3236 if (S_ISLNK(mode2
) && S_ISLNK(sb
.st_mode
)) {
3238 err
= got_object_blob_read_to_str(&link_target2
,
3242 err
= merge_symlink(a
->worktree
, NULL
,
3243 ondisk_path
, path2
, a
->label_orig
,
3244 link_target2
, a
->commit_id2
, repo
,
3245 a
->progress_cb
, a
->progress_arg
);
3247 } else if (S_ISREG(sb
.st_mode
)) {
3248 err
= merge_blob(&local_changes_subsumed
,
3249 a
->worktree
, NULL
, ondisk_path
, path2
,
3250 sb
.st_mode
, a
->label_orig
, blob2
,
3251 a
->commit_id2
, repo
, a
->progress_cb
,
3253 } else if (status
!= GOT_STATUS_DELETE
) {
3254 err
= got_error_path(ondisk_path
,
3255 GOT_ERR_FILE_OBSTRUCTED
);
3259 if (status
== GOT_STATUS_DELETE
) {
3260 /* Re-add file with content from new blob. */
3261 err
= add_file(a
->worktree
, a
->fileindex
, ie
,
3262 ondisk_path
, path2
, blob2
, mode2
,
3263 0, 0, 0, a
->allow_bad_symlinks
,
3264 repo
, a
->progress_cb
, a
->progress_arg
);
3269 err
= add_file(a
->worktree
, a
->fileindex
, NULL
,
3270 ondisk_path
, path2
, blob2
, mode2
,
3271 0, 0, 1, a
->allow_bad_symlinks
,
3272 repo
, a
->progress_cb
, a
->progress_arg
);
3278 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
3279 err
= got_error_from_errno("fclose");
3280 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
3281 err
= got_error_from_errno("fclose");
3282 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
3283 err
= got_error_from_errno("fclose");
3291 struct check_mixed_commits_args
{
3292 struct got_worktree
*worktree
;
3293 got_cancel_cb cancel_cb
;
3297 static const struct got_error
*
3298 check_mixed_commits(void *arg
, struct got_fileindex_entry
*ie
)
3300 const struct got_error
*err
= NULL
;
3301 struct check_mixed_commits_args
*a
= arg
;
3304 err
= a
->cancel_cb(a
->cancel_arg
);
3309 /* Reject merges into a work tree with mixed base commits. */
3310 if (got_fileindex_entry_has_commit(ie
) &&
3311 memcmp(ie
->commit_sha1
, a
->worktree
->base_commit_id
->sha1
,
3312 SHA1_DIGEST_LENGTH
) != 0)
3313 return got_error(GOT_ERR_MIXED_COMMITS
);
3318 const struct got_error
*
3319 got_worktree_get_state(char *state
, struct got_repository
*repo
,
3320 struct got_worktree
*worktree
,
3321 got_cancel_cb cancel_cb
, void *cancel_arg
)
3323 const struct got_error
*err
;
3324 struct got_object_id
*base_id
, *head_id
= NULL
;
3325 struct got_reference
*head_ref
;
3326 struct got_fileindex
*fileindex
= NULL
;
3327 char *fileindex_path
= NULL
;
3328 struct check_mixed_commits_args cma
;
3330 if (worktree
== NULL
)
3331 return got_error(GOT_ERR_NOT_WORKTREE
);
3333 err
= got_ref_open(&head_ref
, repo
,
3334 got_worktree_get_head_ref_name(worktree
), 0);
3338 err
= got_ref_resolve(&head_id
, repo
, head_ref
);
3342 *state
= GOT_WORKTREE_STATE_UNKNOWN
;
3343 base_id
= got_worktree_get_base_commit_id(worktree
);
3345 cma
.worktree
= worktree
;
3346 cma
.cancel_cb
= cancel_cb
;
3347 cma
.cancel_arg
= cancel_arg
;
3349 if (got_object_id_cmp(base_id
, head_id
) == 0) {
3350 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3354 err
= got_fileindex_for_each_entry_safe(fileindex
,
3355 check_mixed_commits
, &cma
);
3357 *state
= GOT_WORKTREE_STATE_UPTODATE
;
3358 else if (err
->code
== GOT_ERR_MIXED_COMMITS
) {
3359 *state
= GOT_WORKTREE_STATE_OUTOFDATE
;
3363 *state
= GOT_WORKTREE_STATE_OUTOFDATE
;
3367 free(fileindex_path
);
3368 got_ref_close(head_ref
);
3369 if (fileindex
!= NULL
)
3370 got_fileindex_free(fileindex
);
3374 struct check_merge_conflicts_arg
{
3375 struct got_worktree
*worktree
;
3376 struct got_fileindex
*fileindex
;
3377 struct got_repository
*repo
;
3380 static const struct got_error
*
3381 check_merge_conflicts(void *arg
, struct got_blob_object
*blob1
,
3382 struct got_blob_object
*blob2
, FILE *f1
, FILE *f2
,
3383 struct got_object_id
*id1
, struct got_object_id
*id2
,
3384 const char *path1
, const char *path2
,
3385 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
3387 const struct got_error
*err
= NULL
;
3388 struct check_merge_conflicts_arg
*a
= arg
;
3389 unsigned char status
;
3391 struct got_fileindex_entry
*ie
;
3392 const char *path
= path2
? path2
: path1
;
3393 struct got_object_id
*id
= id2
? id2
: id1
;
3399 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
3403 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
3405 return got_error_from_errno("asprintf");
3407 /* Reject merges into a work tree with conflicted files. */
3408 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
3412 if (status
== GOT_STATUS_CONFLICT
)
3413 return got_error(GOT_ERR_CONFLICTS
);
3418 static const struct got_error
*
3419 merge_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
3420 const char *fileindex_path
, struct got_object_id
*commit_id1
,
3421 struct got_object_id
*commit_id2
, struct got_repository
*repo
,
3422 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
3423 got_cancel_cb cancel_cb
, void *cancel_arg
)
3425 const struct got_error
*err
= NULL
, *sync_err
;
3426 struct got_object_id
*tree_id1
= NULL
, *tree_id2
= NULL
;
3427 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
3428 struct got_commit_object
*commit1
= NULL
, *commit2
= NULL
;
3429 struct check_merge_conflicts_arg cmc_arg
;
3430 struct merge_file_cb_arg arg
;
3431 char *label_orig
= NULL
;
3432 FILE *f1
= NULL
, *f2
= NULL
;
3433 int fd1
= -1, fd2
= -1;
3436 err
= got_object_open_as_commit(&commit1
, repo
, commit_id1
);
3439 err
= got_object_id_by_path(&tree_id1
, repo
, commit1
,
3440 worktree
->path_prefix
);
3441 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
3447 err
= got_object_open_as_tree(&tree1
, repo
, tree_id1
);
3451 err
= got_object_id_str(&id_str
, commit_id1
);
3455 if (asprintf(&label_orig
, "%s: commit %s",
3456 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
3457 err
= got_error_from_errno("asprintf");
3463 f1
= got_opentemp();
3465 err
= got_error_from_errno("got_opentemp");
3470 err
= got_object_open_as_commit(&commit2
, repo
, commit_id2
);
3474 err
= got_object_id_by_path(&tree_id2
, repo
, commit2
,
3475 worktree
->path_prefix
);
3479 err
= got_object_open_as_tree(&tree2
, repo
, tree_id2
);
3483 f2
= got_opentemp();
3485 err
= got_error_from_errno("got_opentemp");
3489 fd1
= got_opentempfd();
3491 err
= got_error_from_errno("got_opentempfd");
3495 fd2
= got_opentempfd();
3497 err
= got_error_from_errno("got_opentempfd");
3501 cmc_arg
.worktree
= worktree
;
3502 cmc_arg
.fileindex
= fileindex
;
3503 cmc_arg
.repo
= repo
;
3504 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
3505 check_merge_conflicts
, &cmc_arg
, 0);
3509 arg
.worktree
= worktree
;
3510 arg
.fileindex
= fileindex
;
3511 arg
.progress_cb
= progress_cb
;
3512 arg
.progress_arg
= progress_arg
;
3513 arg
.cancel_cb
= cancel_cb
;
3514 arg
.cancel_arg
= cancel_arg
;
3515 arg
.label_orig
= label_orig
;
3516 arg
.commit_id2
= commit_id2
;
3517 arg
.allow_bad_symlinks
= 1; /* preserve bad symlinks across merges */
3518 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
3519 merge_file_cb
, &arg
, 1);
3520 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
3521 if (sync_err
&& err
== NULL
)
3525 got_object_commit_close(commit1
);
3527 got_object_commit_close(commit2
);
3529 got_object_tree_close(tree1
);
3531 got_object_tree_close(tree2
);
3532 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
3533 err
= got_error_from_errno("fclose");
3534 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
3535 err
= got_error_from_errno("fclose");
3536 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
3537 err
= got_error_from_errno("close");
3538 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
3539 err
= got_error_from_errno("close");
3544 const struct got_error
*
3545 got_worktree_merge_files(struct got_worktree
*worktree
,
3546 struct got_object_id
*commit_id1
, struct got_object_id
*commit_id2
,
3547 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
3548 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
3550 const struct got_error
*err
, *unlockerr
;
3551 char *fileindex_path
= NULL
;
3552 struct got_fileindex
*fileindex
= NULL
;
3553 struct check_mixed_commits_args cma
;
3555 err
= lock_worktree(worktree
, LOCK_EX
);
3559 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3563 cma
.worktree
= worktree
;
3564 cma
.cancel_cb
= cancel_cb
;
3565 cma
.cancel_arg
= cancel_arg
;
3567 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
3572 err
= merge_files(worktree
, fileindex
, fileindex_path
, commit_id1
,
3573 commit_id2
, repo
, progress_cb
, progress_arg
,
3574 cancel_cb
, cancel_arg
);
3577 got_fileindex_free(fileindex
);
3578 free(fileindex_path
);
3579 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
3580 if (unlockerr
&& err
== NULL
)
3585 struct diff_dir_cb_arg
{
3586 struct got_fileindex
*fileindex
;
3587 struct got_worktree
*worktree
;
3588 const char *status_path
;
3589 size_t status_path_len
;
3590 struct got_repository
*repo
;
3591 got_worktree_status_cb status_cb
;
3593 got_cancel_cb cancel_cb
;
3595 /* A pathlist containing per-directory pathlists of ignore patterns. */
3596 struct got_pathlist_head
*ignores
;
3597 int report_unchanged
;
3601 static const struct got_error
*
3602 report_file_status(struct got_fileindex_entry
*ie
, const char *abspath
,
3603 int dirfd
, const char *de_name
,
3604 got_worktree_status_cb status_cb
, void *status_arg
,
3605 struct got_repository
*repo
, int report_unchanged
)
3607 const struct got_error
*err
= NULL
;
3608 unsigned char status
= GOT_STATUS_NO_CHANGE
;
3609 unsigned char staged_status
;
3611 struct got_object_id blob_id
, commit_id
, staged_blob_id
;
3612 struct got_object_id
*blob_idp
= NULL
, *commit_idp
= NULL
;
3613 struct got_object_id
*staged_blob_idp
= NULL
;
3615 staged_status
= get_staged_status(ie
);
3616 err
= get_file_status(&status
, &sb
, ie
, abspath
, dirfd
, de_name
, repo
);
3620 if (status
== GOT_STATUS_NO_CHANGE
&&
3621 staged_status
== GOT_STATUS_NO_CHANGE
&& !report_unchanged
)
3624 if (got_fileindex_entry_has_blob(ie
))
3625 blob_idp
= got_fileindex_entry_get_blob_id(&blob_id
, ie
);
3626 if (got_fileindex_entry_has_commit(ie
))
3627 commit_idp
= got_fileindex_entry_get_commit_id(&commit_id
, ie
);
3628 if (staged_status
== GOT_STATUS_ADD
||
3629 staged_status
== GOT_STATUS_MODIFY
) {
3630 staged_blob_idp
= got_fileindex_entry_get_staged_blob_id(
3631 &staged_blob_id
, ie
);
3634 return (*status_cb
)(status_arg
, status
, staged_status
,
3635 ie
->path
, blob_idp
, staged_blob_idp
, commit_idp
, dirfd
, de_name
);
3638 static const struct got_error
*
3639 status_old_new(void *arg
, struct got_fileindex_entry
*ie
,
3640 struct dirent
*de
, const char *parent_path
, int dirfd
)
3642 const struct got_error
*err
= NULL
;
3643 struct diff_dir_cb_arg
*a
= arg
;
3647 err
= a
->cancel_cb(a
->cancel_arg
);
3652 if (got_path_cmp(parent_path
, a
->status_path
,
3653 strlen(parent_path
), a
->status_path_len
) != 0 &&
3654 !got_path_is_child(parent_path
, a
->status_path
, a
->status_path_len
))
3657 if (parent_path
[0]) {
3658 if (asprintf(&abspath
, "%s/%s/%s", a
->worktree
->root_path
,
3659 parent_path
, de
->d_name
) == -1)
3660 return got_error_from_errno("asprintf");
3662 if (asprintf(&abspath
, "%s/%s", a
->worktree
->root_path
,
3664 return got_error_from_errno("asprintf");
3667 err
= report_file_status(ie
, abspath
, dirfd
, de
->d_name
,
3668 a
->status_cb
, a
->status_arg
, a
->repo
, a
->report_unchanged
);
3673 static const struct got_error
*
3674 status_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
3676 const struct got_error
*err
;
3677 struct diff_dir_cb_arg
*a
= arg
;
3678 struct got_object_id blob_id
, commit_id
;
3679 unsigned char status
;
3682 err
= a
->cancel_cb(a
->cancel_arg
);
3687 if (!got_path_is_child(ie
->path
, a
->status_path
, a
->status_path_len
))
3690 got_fileindex_entry_get_blob_id(&blob_id
, ie
);
3691 got_fileindex_entry_get_commit_id(&commit_id
, ie
);
3692 if (got_fileindex_entry_has_file_on_disk(ie
))
3693 status
= GOT_STATUS_MISSING
;
3695 status
= GOT_STATUS_DELETE
;
3696 return (*a
->status_cb
)(a
->status_arg
, status
, get_staged_status(ie
),
3697 ie
->path
, &blob_id
, NULL
, &commit_id
, -1, NULL
);
3701 free_ignores(struct got_pathlist_head
*ignores
)
3703 struct got_pathlist_entry
*pe
;
3705 TAILQ_FOREACH(pe
, ignores
, entry
) {
3706 struct got_pathlist_head
*ignorelist
= pe
->data
;
3708 got_pathlist_free(ignorelist
, GOT_PATHLIST_FREE_PATH
);
3710 got_pathlist_free(ignores
, GOT_PATHLIST_FREE_PATH
);
3713 static const struct got_error
*
3714 read_ignores(struct got_pathlist_head
*ignores
, const char *path
, FILE *f
)
3716 const struct got_error
*err
= NULL
;
3717 struct got_pathlist_entry
*pe
= NULL
;
3718 struct got_pathlist_head
*ignorelist
;
3719 char *line
= NULL
, *pattern
, *dirpath
= NULL
;
3720 size_t linesize
= 0;
3723 ignorelist
= calloc(1, sizeof(*ignorelist
));
3724 if (ignorelist
== NULL
)
3725 return got_error_from_errno("calloc");
3726 TAILQ_INIT(ignorelist
);
3728 while ((linelen
= getline(&line
, &linesize
, f
)) != -1) {
3729 if (linelen
> 0 && line
[linelen
- 1] == '\n')
3730 line
[linelen
- 1] = '\0';
3732 /* Git's ignores may contain comments. */
3736 /* Git's negated patterns are not (yet?) supported. */
3740 if (asprintf(&pattern
, "%s%s%s", path
, path
[0] ? "/" : "",
3742 err
= got_error_from_errno("asprintf");
3745 err
= got_pathlist_insert(NULL
, ignorelist
, pattern
, NULL
);
3750 err
= got_error_from_errno("getline");
3754 dirpath
= strdup(path
);
3755 if (dirpath
== NULL
) {
3756 err
= got_error_from_errno("strdup");
3759 err
= got_pathlist_insert(&pe
, ignores
, dirpath
, ignorelist
);
3762 if (err
|| pe
== NULL
) {
3764 got_pathlist_free(ignorelist
, GOT_PATHLIST_FREE_PATH
);
3770 match_path(const char *pattern
, size_t pattern_len
, const char *path
,
3776 * Trailing slashes signify directories.
3777 * Append a * to make such patterns conform to fnmatch rules.
3779 if (pattern_len
> 0 && pattern
[pattern_len
- 1] == '/') {
3780 if (snprintf(buf
, sizeof(buf
), "%s*", pattern
) >= sizeof(buf
))
3781 return FNM_NOMATCH
; /* XXX */
3783 return fnmatch(buf
, path
, flags
);
3786 return fnmatch(pattern
, path
, flags
);
3790 match_ignores(struct got_pathlist_head
*ignores
, const char *path
)
3792 struct got_pathlist_entry
*pe
;
3794 /* Handle patterns which match in all directories. */
3795 TAILQ_FOREACH(pe
, ignores
, entry
) {
3796 struct got_pathlist_head
*ignorelist
= pe
->data
;
3797 struct got_pathlist_entry
*pi
;
3799 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3802 if (pi
->path_len
< 3 ||
3803 strncmp(pi
->path
, "**/", 3) != 0)
3807 if (match_path(pi
->path
+ 3,
3808 pi
->path_len
- 3, p
,
3809 FNM_PATHNAME
| FNM_LEADING_DIR
)) {
3810 /* Retry in next directory. */
3811 while (*p
&& *p
!= '/')
3823 * The ignores pathlist contains ignore lists from children before
3824 * parents, so we can find the most specific ignorelist by walking
3825 * ignores backwards.
3827 pe
= TAILQ_LAST(ignores
, got_pathlist_head
);
3829 if (got_path_is_child(path
, pe
->path
, pe
->path_len
)) {
3830 struct got_pathlist_head
*ignorelist
= pe
->data
;
3831 struct got_pathlist_entry
*pi
;
3832 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3833 int flags
= FNM_LEADING_DIR
;
3834 if (strstr(pi
->path
, "/**/") == NULL
)
3835 flags
|= FNM_PATHNAME
;
3836 if (match_path(pi
->path
, pi
->path_len
,
3842 pe
= TAILQ_PREV(pe
, got_pathlist_head
, entry
);
3848 static const struct got_error
*
3849 add_ignores(struct got_pathlist_head
*ignores
, const char *root_path
,
3850 const char *path
, int dirfd
, const char *ignores_filename
)
3852 const struct got_error
*err
= NULL
;
3855 FILE *ignoresfile
= NULL
;
3857 if (asprintf(&ignorespath
, "%s/%s%s%s", root_path
, path
,
3858 path
[0] ? "/" : "", ignores_filename
) == -1)
3859 return got_error_from_errno("asprintf");
3862 fd
= openat(dirfd
, ignores_filename
,
3863 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
3865 if (errno
!= ENOENT
&& errno
!= EACCES
)
3866 err
= got_error_from_errno2("openat",
3869 ignoresfile
= fdopen(fd
, "r");
3870 if (ignoresfile
== NULL
)
3871 err
= got_error_from_errno2("fdopen",
3875 err
= read_ignores(ignores
, path
, ignoresfile
);
3879 ignoresfile
= fopen(ignorespath
, "re");
3880 if (ignoresfile
== NULL
) {
3881 if (errno
!= ENOENT
&& errno
!= EACCES
)
3882 err
= got_error_from_errno2("fopen",
3885 err
= read_ignores(ignores
, path
, ignoresfile
);
3888 if (ignoresfile
&& fclose(ignoresfile
) == EOF
&& err
== NULL
)
3889 err
= got_error_from_errno2("fclose", path
);
3890 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3891 err
= got_error_from_errno2("close", path
);
3896 static const struct got_error
*
3897 status_new(int *ignore
, void *arg
, struct dirent
*de
, const char *parent_path
,
3900 const struct got_error
*err
= NULL
;
3901 struct diff_dir_cb_arg
*a
= arg
;
3908 err
= a
->cancel_cb(a
->cancel_arg
);
3913 if (parent_path
[0]) {
3914 if (asprintf(&path
, "%s/%s", parent_path
, de
->d_name
) == -1)
3915 return got_error_from_errno("asprintf");
3920 if (de
->d_type
== DT_DIR
) {
3921 if (!a
->no_ignores
&& ignore
!= NULL
&&
3922 match_ignores(a
->ignores
, path
))
3924 } else if (!match_ignores(a
->ignores
, path
) &&
3925 got_path_is_child(path
, a
->status_path
, a
->status_path_len
))
3926 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_UNVERSIONED
,
3927 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3933 static const struct got_error
*
3934 status_traverse(void *arg
, const char *path
, int dirfd
)
3936 const struct got_error
*err
= NULL
;
3937 struct diff_dir_cb_arg
*a
= arg
;
3942 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
,
3943 path
, dirfd
, ".cvsignore");
3947 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
, path
,
3948 dirfd
, ".gitignore");
3953 static const struct got_error
*
3954 report_single_file_status(const char *path
, const char *ondisk_path
,
3955 struct got_fileindex
*fileindex
, got_worktree_status_cb status_cb
,
3956 void *status_arg
, struct got_repository
*repo
, int report_unchanged
,
3957 struct got_pathlist_head
*ignores
, int no_ignores
)
3959 struct got_fileindex_entry
*ie
;
3962 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
3964 return report_file_status(ie
, ondisk_path
, -1, NULL
,
3965 status_cb
, status_arg
, repo
, report_unchanged
);
3967 if (lstat(ondisk_path
, &sb
) == -1) {
3968 if (errno
!= ENOENT
)
3969 return got_error_from_errno2("lstat", ondisk_path
);
3970 return (*status_cb
)(status_arg
, GOT_STATUS_NONEXISTENT
,
3971 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3974 if (!no_ignores
&& match_ignores(ignores
, path
))
3977 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
3978 return (*status_cb
)(status_arg
, GOT_STATUS_UNVERSIONED
,
3979 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3984 static const struct got_error
*
3985 add_ignores_from_parent_paths(struct got_pathlist_head
*ignores
,
3986 const char *root_path
, const char *path
)
3988 const struct got_error
*err
;
3989 char *parent_path
, *next_parent_path
= NULL
;
3991 err
= add_ignores(ignores
, root_path
, "", -1,
3996 err
= add_ignores(ignores
, root_path
, "", -1,
4001 err
= got_path_dirname(&parent_path
, path
);
4003 if (err
->code
== GOT_ERR_BAD_PATH
)
4004 return NULL
; /* cannot traverse parent */
4008 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
4012 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
4016 err
= got_path_dirname(&next_parent_path
, parent_path
);
4018 if (err
->code
== GOT_ERR_BAD_PATH
)
4019 err
= NULL
; /* traversed everything */
4022 if (got_path_is_root_dir(parent_path
))
4025 parent_path
= next_parent_path
;
4026 next_parent_path
= NULL
;
4030 free(next_parent_path
);
4034 struct find_missing_children_args
{
4035 const char *parent_path
;
4037 struct got_pathlist_head
*children
;
4038 got_cancel_cb cancel_cb
;
4042 static const struct got_error
*
4043 find_missing_children(void *arg
, struct got_fileindex_entry
*ie
)
4045 const struct got_error
*err
= NULL
;
4046 struct find_missing_children_args
*a
= arg
;
4049 err
= a
->cancel_cb(a
->cancel_arg
);
4054 if (got_path_is_child(ie
->path
, a
->parent_path
, a
->parent_len
))
4055 err
= got_pathlist_append(a
->children
, ie
->path
, NULL
);
4060 static const struct got_error
*
4061 report_children(struct got_pathlist_head
*children
,
4062 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
4063 struct got_repository
*repo
, int is_root_dir
, int report_unchanged
,
4064 struct got_pathlist_head
*ignores
, int no_ignores
,
4065 got_worktree_status_cb status_cb
, void *status_arg
,
4066 got_cancel_cb cancel_cb
, void *cancel_arg
)
4068 const struct got_error
*err
= NULL
;
4069 struct got_pathlist_entry
*pe
;
4070 char *ondisk_path
= NULL
;
4072 TAILQ_FOREACH(pe
, children
, entry
) {
4074 err
= cancel_cb(cancel_arg
);
4079 if (asprintf(&ondisk_path
, "%s%s%s", worktree
->root_path
,
4080 !is_root_dir
? "/" : "", pe
->path
) == -1) {
4081 err
= got_error_from_errno("asprintf");
4086 err
= report_single_file_status(pe
->path
, ondisk_path
,
4087 fileindex
, status_cb
, status_arg
, repo
, report_unchanged
,
4088 ignores
, no_ignores
);
4100 static const struct got_error
*
4101 worktree_status(struct got_worktree
*worktree
, const char *path
,
4102 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
4103 got_worktree_status_cb status_cb
, void *status_arg
,
4104 got_cancel_cb cancel_cb
, void *cancel_arg
, int no_ignores
,
4105 int report_unchanged
)
4107 const struct got_error
*err
= NULL
;
4109 struct got_fileindex_diff_dir_cb fdiff_cb
;
4110 struct diff_dir_cb_arg arg
;
4111 char *ondisk_path
= NULL
;
4112 struct got_pathlist_head ignores
, missing_children
;
4113 struct got_fileindex_entry
*ie
;
4115 TAILQ_INIT(&ignores
);
4116 TAILQ_INIT(&missing_children
);
4118 if (asprintf(&ondisk_path
, "%s%s%s",
4119 worktree
->root_path
, path
[0] ? "/" : "", path
) == -1)
4120 return got_error_from_errno("asprintf");
4122 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
4124 err
= report_single_file_status(path
, ondisk_path
,
4125 fileindex
, status_cb
, status_arg
, repo
,
4126 report_unchanged
, &ignores
, no_ignores
);
4129 struct find_missing_children_args fmca
;
4130 fmca
.parent_path
= path
;
4131 fmca
.parent_len
= strlen(path
);
4132 fmca
.children
= &missing_children
;
4133 fmca
.cancel_cb
= cancel_cb
;
4134 fmca
.cancel_arg
= cancel_arg
;
4135 err
= got_fileindex_for_each_entry_safe(fileindex
,
4136 find_missing_children
, &fmca
);
4141 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_DIRECTORY
| O_CLOEXEC
);
4143 if (errno
!= ENOTDIR
&& errno
!= ENOENT
&& errno
!= EACCES
&&
4144 !got_err_open_nofollow_on_symlink())
4145 err
= got_error_from_errno2("open", ondisk_path
);
4148 err
= add_ignores_from_parent_paths(&ignores
,
4149 worktree
->root_path
, ondisk_path
);
4153 if (TAILQ_EMPTY(&missing_children
)) {
4154 err
= report_single_file_status(path
,
4155 ondisk_path
, fileindex
,
4156 status_cb
, status_arg
, repo
,
4157 report_unchanged
, &ignores
, no_ignores
);
4161 err
= report_children(&missing_children
,
4162 worktree
, fileindex
, repo
,
4163 (path
[0] == '\0'), report_unchanged
,
4164 &ignores
, no_ignores
,
4165 status_cb
, status_arg
,
4166 cancel_cb
, cancel_arg
);
4172 fdiff_cb
.diff_old_new
= status_old_new
;
4173 fdiff_cb
.diff_old
= status_old
;
4174 fdiff_cb
.diff_new
= status_new
;
4175 fdiff_cb
.diff_traverse
= status_traverse
;
4176 arg
.fileindex
= fileindex
;
4177 arg
.worktree
= worktree
;
4178 arg
.status_path
= path
;
4179 arg
.status_path_len
= strlen(path
);
4181 arg
.status_cb
= status_cb
;
4182 arg
.status_arg
= status_arg
;
4183 arg
.cancel_cb
= cancel_cb
;
4184 arg
.cancel_arg
= cancel_arg
;
4185 arg
.report_unchanged
= report_unchanged
;
4186 arg
.no_ignores
= no_ignores
;
4188 err
= add_ignores_from_parent_paths(&ignores
,
4189 worktree
->root_path
, path
);
4193 arg
.ignores
= &ignores
;
4194 err
= got_fileindex_diff_dir(fileindex
, fd
,
4195 worktree
->root_path
, path
, repo
, &fdiff_cb
, &arg
);
4198 free_ignores(&ignores
);
4199 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
4200 err
= got_error_from_errno("close");
4205 const struct got_error
*
4206 got_worktree_status(struct got_worktree
*worktree
,
4207 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
4208 int no_ignores
, got_worktree_status_cb status_cb
, void *status_arg
,
4209 got_cancel_cb cancel_cb
, void *cancel_arg
)
4211 const struct got_error
*err
= NULL
;
4212 char *fileindex_path
= NULL
;
4213 struct got_fileindex
*fileindex
= NULL
;
4214 struct got_pathlist_entry
*pe
;
4216 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4220 TAILQ_FOREACH(pe
, paths
, entry
) {
4221 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4222 status_cb
, status_arg
, cancel_cb
, cancel_arg
,
4227 free(fileindex_path
);
4228 got_fileindex_free(fileindex
);
4232 const struct got_error
*
4233 got_worktree_resolve_path(char **wt_path
, struct got_worktree
*worktree
,
4236 const struct got_error
*err
= NULL
;
4237 char *resolved
= NULL
, *cwd
= NULL
, *path
= NULL
;
4240 char *abspath
= NULL
;
4241 char canonpath
[PATH_MAX
];
4245 cwd
= getcwd(NULL
, 0);
4247 return got_error_from_errno("getcwd");
4249 if (lstat(arg
, &sb
) == -1) {
4250 if (errno
!= ENOENT
) {
4251 err
= got_error_from_errno2("lstat", arg
);
4256 if (S_ISLNK(sb
.st_mode
)) {
4258 * We cannot use realpath(3) with symlinks since we want to
4259 * operate on the symlink itself.
4260 * But we can make the path absolute, assuming it is relative
4261 * to the current working directory, and then canonicalize it.
4263 if (!got_path_is_absolute(arg
)) {
4264 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
4265 err
= got_error_from_errno("asprintf");
4270 err
= got_canonpath(abspath
? abspath
: arg
, canonpath
,
4274 resolved
= strdup(canonpath
);
4275 if (resolved
== NULL
) {
4276 err
= got_error_from_errno("strdup");
4280 resolved
= realpath(arg
, NULL
);
4281 if (resolved
== NULL
) {
4282 if (errno
!= ENOENT
) {
4283 err
= got_error_from_errno2("realpath", arg
);
4286 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
4287 err
= got_error_from_errno("asprintf");
4290 err
= got_canonpath(abspath
, canonpath
,
4294 resolved
= strdup(canonpath
);
4295 if (resolved
== NULL
) {
4296 err
= got_error_from_errno("strdup");
4302 if (strncmp(got_worktree_get_root_path(worktree
), resolved
,
4303 strlen(got_worktree_get_root_path(worktree
)))) {
4304 err
= got_error_path(resolved
, GOT_ERR_BAD_PATH
);
4308 if (strlen(resolved
) > strlen(got_worktree_get_root_path(worktree
))) {
4309 err
= got_path_skip_common_ancestor(&path
,
4310 got_worktree_get_root_path(worktree
), resolved
);
4316 err
= got_error_from_errno("strdup");
4321 /* XXX status walk can't deal with trailing slash! */
4323 while (len
> 0 && path
[len
- 1] == '/') {
4324 path
[len
- 1] = '\0';
4338 struct schedule_addition_args
{
4339 struct got_worktree
*worktree
;
4340 struct got_fileindex
*fileindex
;
4341 got_worktree_checkout_cb progress_cb
;
4343 struct got_repository
*repo
;
4347 add_noop_status(unsigned char status
)
4349 return (status
== GOT_STATUS_ADD
||
4350 status
== GOT_STATUS_MODIFY
||
4351 status
== GOT_STATUS_CONFLICT
||
4352 status
== GOT_STATUS_MODE_CHANGE
||
4353 status
== GOT_STATUS_NO_CHANGE
);
4356 static const struct got_error
*
4357 schedule_addition(void *arg
, unsigned char status
, unsigned char staged_status
,
4358 const char *relpath
, struct got_object_id
*blob_id
,
4359 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
4360 int dirfd
, const char *de_name
)
4362 struct schedule_addition_args
*a
= arg
;
4363 const struct got_error
*err
= NULL
;
4364 struct got_fileindex_entry
*ie
;
4368 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4370 return got_error_from_errno("asprintf");
4372 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4374 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
,
4378 /* Re-adding an existing entry is a no-op. */
4379 if (staged_status
== GOT_STATUS_NO_CHANGE
&&
4380 add_noop_status(status
))
4382 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4387 if (status
!= GOT_STATUS_UNVERSIONED
) {
4388 if (status
== GOT_STATUS_NONEXISTENT
)
4389 err
= got_error_set_errno(ENOENT
, ondisk_path
);
4391 err
= got_error_path(ondisk_path
, GOT_ERR_FILE_STATUS
);
4395 err
= got_fileindex_entry_alloc(&ie
, relpath
);
4398 err
= got_fileindex_entry_update(ie
, a
->worktree
->root_fd
,
4399 relpath
, NULL
, NULL
, 1);
4401 got_fileindex_entry_free(ie
);
4404 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
4406 got_fileindex_entry_free(ie
);
4413 if (staged_status
== GOT_STATUS_NO_CHANGE
&& add_noop_status(status
))
4415 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_ADD
, relpath
);
4418 const struct got_error
*
4419 got_worktree_schedule_add(struct got_worktree
*worktree
,
4420 struct got_pathlist_head
*paths
,
4421 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4422 struct got_repository
*repo
, int no_ignores
)
4424 struct got_fileindex
*fileindex
= NULL
;
4425 char *fileindex_path
= NULL
;
4426 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4427 struct got_pathlist_entry
*pe
;
4428 struct schedule_addition_args saa
;
4430 err
= lock_worktree(worktree
, LOCK_EX
);
4434 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4438 saa
.worktree
= worktree
;
4439 saa
.fileindex
= fileindex
;
4440 saa
.progress_cb
= progress_cb
;
4441 saa
.progress_arg
= progress_arg
;
4444 TAILQ_FOREACH(pe
, paths
, entry
) {
4445 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4446 schedule_addition
, &saa
, NULL
, NULL
, no_ignores
, 0);
4450 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4451 if (sync_err
&& err
== NULL
)
4454 free(fileindex_path
);
4456 got_fileindex_free(fileindex
);
4457 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4458 if (unlockerr
&& err
== NULL
)
4463 struct schedule_deletion_args
{
4464 struct got_worktree
*worktree
;
4465 struct got_fileindex
*fileindex
;
4466 got_worktree_delete_cb progress_cb
;
4468 struct got_repository
*repo
;
4469 int delete_local_mods
;
4471 int ignore_missing_paths
;
4472 const char *status_path
;
4473 size_t status_path_len
;
4474 const char *status_codes
;
4477 static const struct got_error
*
4478 schedule_for_deletion(void *arg
, unsigned char status
,
4479 unsigned char staged_status
, const char *relpath
,
4480 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4481 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4483 struct schedule_deletion_args
*a
= arg
;
4484 const struct got_error
*err
= NULL
;
4485 struct got_fileindex_entry
*ie
= NULL
;
4489 if (status
== GOT_STATUS_NONEXISTENT
) {
4490 if (a
->ignore_missing_paths
)
4492 return got_error_set_errno(ENOENT
, relpath
);
4495 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4497 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4499 staged_status
= get_staged_status(ie
);
4500 if (staged_status
!= GOT_STATUS_NO_CHANGE
) {
4501 if (staged_status
== GOT_STATUS_DELETE
)
4503 return got_error_path(relpath
, GOT_ERR_FILE_STAGED
);
4506 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4508 return got_error_from_errno("asprintf");
4510 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
, de_name
,
4515 if (a
->status_codes
) {
4516 size_t ncodes
= strlen(a
->status_codes
);
4518 for (i
= 0; i
< ncodes
; i
++) {
4519 if (status
== a
->status_codes
[i
])
4523 /* Do not delete files in non-matching status. */
4527 if (a
->status_codes
[i
] != GOT_STATUS_MODIFY
&&
4528 a
->status_codes
[i
] != GOT_STATUS_MISSING
) {
4529 static char msg
[64];
4530 snprintf(msg
, sizeof(msg
),
4531 "invalid status code '%c'", a
->status_codes
[i
]);
4532 err
= got_error_msg(GOT_ERR_FILE_STATUS
, msg
);
4537 if (status
!= GOT_STATUS_NO_CHANGE
) {
4538 if (status
== GOT_STATUS_DELETE
)
4540 if (status
== GOT_STATUS_MODIFY
&& !a
->delete_local_mods
) {
4541 err
= got_error_path(relpath
, GOT_ERR_FILE_MODIFIED
);
4544 if (status
== GOT_STATUS_MISSING
&& !a
->ignore_missing_paths
) {
4545 err
= got_error_set_errno(ENOENT
, relpath
);
4548 if (status
!= GOT_STATUS_MODIFY
&&
4549 status
!= GOT_STATUS_MISSING
) {
4550 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4555 if (!a
->keep_on_disk
&& status
!= GOT_STATUS_MISSING
) {
4559 if (unlinkat(dirfd
, de_name
, 0) == -1) {
4560 err
= got_error_from_errno2("unlinkat",
4564 } else if (unlink(ondisk_path
) == -1) {
4565 err
= got_error_from_errno2("unlink", ondisk_path
);
4569 root_len
= strlen(a
->worktree
->root_path
);
4573 err
= got_path_dirname(&parent
, ondisk_path
);
4577 ondisk_path
= parent
;
4578 if (got_path_cmp(ondisk_path
, a
->status_path
,
4579 strlen(ondisk_path
), a
->status_path_len
) != 0 &&
4580 !got_path_is_child(ondisk_path
, a
->status_path
,
4581 a
->status_path_len
))
4583 if (rmdir(ondisk_path
) == -1) {
4584 if (errno
!= ENOTEMPTY
)
4585 err
= got_error_from_errno2("rmdir",
4589 } while (got_path_cmp(ondisk_path
, a
->worktree
->root_path
,
4590 strlen(ondisk_path
), root_len
) != 0);
4593 if (got_fileindex_entry_has_blob(ie
))
4594 got_fileindex_entry_mark_deleted_from_disk(ie
);
4596 got_fileindex_entry_remove(a
->fileindex
, ie
);
4601 if (status
== GOT_STATUS_DELETE
)
4603 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_DELETE
,
4604 staged_status
, relpath
);
4607 const struct got_error
*
4608 got_worktree_schedule_delete(struct got_worktree
*worktree
,
4609 struct got_pathlist_head
*paths
, int delete_local_mods
,
4610 const char *status_codes
,
4611 got_worktree_delete_cb progress_cb
, void *progress_arg
,
4612 struct got_repository
*repo
, int keep_on_disk
, int ignore_missing_paths
)
4614 struct got_fileindex
*fileindex
= NULL
;
4615 char *fileindex_path
= NULL
;
4616 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4617 struct got_pathlist_entry
*pe
;
4618 struct schedule_deletion_args sda
;
4620 err
= lock_worktree(worktree
, LOCK_EX
);
4624 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4628 sda
.worktree
= worktree
;
4629 sda
.fileindex
= fileindex
;
4630 sda
.progress_cb
= progress_cb
;
4631 sda
.progress_arg
= progress_arg
;
4633 sda
.delete_local_mods
= delete_local_mods
;
4634 sda
.keep_on_disk
= keep_on_disk
;
4635 sda
.ignore_missing_paths
= ignore_missing_paths
;
4636 sda
.status_codes
= status_codes
;
4638 TAILQ_FOREACH(pe
, paths
, entry
) {
4639 char *ondisk_status_path
;
4641 if (asprintf(&ondisk_status_path
, "%s%s%s",
4642 got_worktree_get_root_path(worktree
),
4643 pe
->path
[0] == '\0' ? "" : "/", pe
->path
) == -1) {
4644 err
= got_error_from_errno("asprintf");
4647 sda
.status_path
= ondisk_status_path
;
4648 sda
.status_path_len
= strlen(ondisk_status_path
);
4649 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4650 schedule_for_deletion
, &sda
, NULL
, NULL
, 1, 1);
4651 free(ondisk_status_path
);
4655 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4656 if (sync_err
&& err
== NULL
)
4659 free(fileindex_path
);
4661 got_fileindex_free(fileindex
);
4662 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4663 if (unlockerr
&& err
== NULL
)
4668 static const struct got_error
*
4669 copy_one_line(FILE *infile
, FILE *outfile
, FILE *rejectfile
)
4671 const struct got_error
*err
= NULL
;
4673 size_t linesize
= 0, n
;
4676 linelen
= getline(&line
, &linesize
, infile
);
4677 if (linelen
== -1) {
4678 if (ferror(infile
)) {
4679 err
= got_error_from_errno("getline");
4685 n
= fwrite(line
, 1, linelen
, outfile
);
4687 err
= got_ferror(outfile
, GOT_ERR_IO
);
4692 n
= fwrite(line
, 1, linelen
, rejectfile
);
4694 err
= got_ferror(rejectfile
, GOT_ERR_IO
);
4701 static const struct got_error
*
4702 skip_one_line(FILE *f
)
4705 size_t linesize
= 0;
4708 linelen
= getline(&line
, &linesize
, f
);
4709 if (linelen
== -1) {
4711 return got_error_from_errno("getline");
4718 static const struct got_error
*
4719 copy_change(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4720 int start_old
, int end_old
, int start_new
, int end_new
,
4721 FILE *outfile
, FILE *rejectfile
)
4723 const struct got_error
*err
;
4725 /* Copy old file's lines leading up to patch. */
4726 while (!feof(f1
) && *line_cur1
< start_old
) {
4727 err
= copy_one_line(f1
, outfile
, NULL
);
4732 /* Skip new file's lines leading up to patch. */
4733 while (!feof(f2
) && *line_cur2
< start_new
) {
4735 err
= copy_one_line(f2
, NULL
, rejectfile
);
4737 err
= skip_one_line(f2
);
4742 /* Copy patched lines. */
4743 while (!feof(f2
) && *line_cur2
<= end_new
) {
4744 err
= copy_one_line(f2
, outfile
, NULL
);
4749 /* Skip over old file's replaced lines. */
4750 while (!feof(f1
) && *line_cur1
<= end_old
) {
4752 err
= copy_one_line(f1
, NULL
, rejectfile
);
4754 err
= skip_one_line(f1
);
4763 static const struct got_error
*
4764 copy_remaining_content(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4765 FILE *outfile
, FILE *rejectfile
)
4767 const struct got_error
*err
;
4770 /* Copy old file's lines until EOF. */
4772 err
= copy_one_line(f1
, outfile
, NULL
);
4779 /* Copy new file's lines until EOF. */
4781 err
= copy_one_line(f2
, NULL
, rejectfile
);
4791 static const struct got_error
*
4792 apply_or_reject_change(int *choice
, int *nchunks_used
,
4793 struct diff_result
*diff_result
, int n
,
4794 const char *relpath
, FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4795 FILE *outfile
, FILE *rejectfile
, int changeno
, int nchanges
,
4796 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4798 const struct got_error
*err
= NULL
;
4799 struct diff_chunk_context cc
= {};
4800 int start_old
, end_old
, start_new
, end_new
;
4802 struct diff_output_unidiff_state
*diff_state
;
4803 struct diff_input_info diff_info
;
4806 *choice
= GOT_PATCH_CHOICE_NONE
;
4808 /* Get changed line numbers without context lines for copy_change(). */
4809 diff_chunk_context_load_change(&cc
, NULL
, diff_result
, n
, 0);
4810 start_old
= cc
.left
.start
;
4811 end_old
= cc
.left
.end
;
4812 start_new
= cc
.right
.start
;
4813 end_new
= cc
.right
.end
;
4815 /* Get the same change with context lines for display. */
4816 memset(&cc
, 0, sizeof(cc
));
4817 diff_chunk_context_load_change(&cc
, nchunks_used
, diff_result
, n
, 3);
4819 memset(&diff_info
, 0, sizeof(diff_info
));
4820 diff_info
.left_path
= relpath
;
4821 diff_info
.right_path
= relpath
;
4823 diff_state
= diff_output_unidiff_state_alloc();
4824 if (diff_state
== NULL
)
4825 return got_error_set_errno(ENOMEM
,
4826 "diff_output_unidiff_state_alloc");
4828 hunkfile
= got_opentemp();
4829 if (hunkfile
== NULL
) {
4830 err
= got_error_from_errno("got_opentemp");
4834 rc
= diff_output_unidiff_chunk(NULL
, hunkfile
, diff_state
, &diff_info
,
4836 if (rc
!= DIFF_RC_OK
) {
4837 err
= got_error_set_errno(rc
, "diff_output_unidiff_chunk");
4841 if (fseek(hunkfile
, 0L, SEEK_SET
) == -1) {
4842 err
= got_ferror(hunkfile
, GOT_ERR_IO
);
4846 err
= (*patch_cb
)(choice
, patch_arg
, GOT_STATUS_MODIFY
, relpath
,
4847 hunkfile
, changeno
, nchanges
);
4852 case GOT_PATCH_CHOICE_YES
:
4853 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4854 end_old
, start_new
, end_new
, outfile
, rejectfile
);
4856 case GOT_PATCH_CHOICE_NO
:
4857 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4858 end_old
, start_new
, end_new
, rejectfile
, outfile
);
4860 case GOT_PATCH_CHOICE_QUIT
:
4863 err
= got_error(GOT_ERR_PATCH_CHOICE
);
4867 diff_output_unidiff_state_free(diff_state
);
4868 if (hunkfile
&& fclose(hunkfile
) == EOF
&& err
== NULL
)
4869 err
= got_error_from_errno("fclose");
4873 struct revert_file_args
{
4874 struct got_worktree
*worktree
;
4875 struct got_fileindex
*fileindex
;
4876 got_worktree_checkout_cb progress_cb
;
4878 got_worktree_patch_cb patch_cb
;
4880 struct got_repository
*repo
;
4881 int unlink_added_files
;
4882 struct got_pathlist_head
*added_files_to_unlink
;
4885 static const struct got_error
*
4886 create_patched_content(char **path_outfile
, int reverse_patch
,
4887 struct got_object_id
*blob_id
, const char *path2
,
4888 int dirfd2
, const char *de_name2
,
4889 const char *relpath
, struct got_repository
*repo
,
4890 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4892 const struct got_error
*err
, *free_err
;
4893 struct got_blob_object
*blob
= NULL
;
4894 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
;
4895 int fd
= -1, fd2
= -1;
4896 char link_target
[PATH_MAX
];
4897 ssize_t link_len
= 0;
4898 char *path1
= NULL
, *id_str
= NULL
;
4900 struct got_diffreg_result
*diffreg_result
= NULL
;
4901 int line_cur1
= 1, line_cur2
= 1, have_content
= 0;
4902 int i
= 0, n
= 0, nchunks_used
= 0, nchanges
= 0;
4904 *path_outfile
= NULL
;
4906 err
= got_object_id_str(&id_str
, blob_id
);
4911 fd2
= openat(dirfd2
, de_name2
,
4912 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
4914 if (!got_err_open_nofollow_on_symlink()) {
4915 err
= got_error_from_errno2("openat", path2
);
4918 link_len
= readlinkat(dirfd2
, de_name2
,
4919 link_target
, sizeof(link_target
));
4920 if (link_len
== -1) {
4921 return got_error_from_errno2("readlinkat",
4924 sb2
.st_mode
= S_IFLNK
;
4925 sb2
.st_size
= link_len
;
4928 fd2
= open(path2
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
4930 if (!got_err_open_nofollow_on_symlink()) {
4931 err
= got_error_from_errno2("open", path2
);
4934 link_len
= readlink(path2
, link_target
,
4935 sizeof(link_target
));
4937 return got_error_from_errno2("readlink", path2
);
4938 sb2
.st_mode
= S_IFLNK
;
4939 sb2
.st_size
= link_len
;
4943 if (fstat(fd2
, &sb2
) == -1) {
4944 err
= got_error_from_errno2("fstat", path2
);
4948 f2
= fdopen(fd2
, "r");
4950 err
= got_error_from_errno2("fdopen", path2
);
4956 f2
= got_opentemp();
4958 err
= got_error_from_errno2("got_opentemp", path2
);
4961 n
= fwrite(link_target
, 1, link_len
, f2
);
4962 if (n
!= link_len
) {
4963 err
= got_ferror(f2
, GOT_ERR_IO
);
4966 if (fflush(f2
) == EOF
) {
4967 err
= got_error_from_errno("fflush");
4973 fd
= got_opentempfd();
4975 err
= got_error_from_errno("got_opentempfd");
4979 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192, fd
);
4983 err
= got_opentemp_named(&path1
, &f1
, "got-patched-blob", "");
4987 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
4991 err
= got_diff_files(&diffreg_result
, f1
, 1, id_str
, f2
, 1, path2
,
4992 3, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
4996 err
= got_opentemp_named(path_outfile
, &outfile
, "got-patched-content",
5001 if (fseek(f1
, 0L, SEEK_SET
) == -1)
5002 return got_ferror(f1
, GOT_ERR_IO
);
5003 if (fseek(f2
, 0L, SEEK_SET
) == -1)
5004 return got_ferror(f2
, GOT_ERR_IO
);
5006 /* Count the number of actual changes in the diff result. */
5007 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
5008 struct diff_chunk_context cc
= {};
5009 diff_chunk_context_load_change(&cc
, &nchunks_used
,
5010 diffreg_result
->result
, n
, 0);
5013 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
5015 err
= apply_or_reject_change(&choice
, &nchunks_used
,
5016 diffreg_result
->result
, n
, relpath
, f1
, f2
,
5017 &line_cur1
, &line_cur2
,
5018 reverse_patch
? NULL
: outfile
,
5019 reverse_patch
? outfile
: NULL
,
5020 ++i
, nchanges
, patch_cb
, patch_arg
);
5023 if (choice
== GOT_PATCH_CHOICE_YES
)
5025 else if (choice
== GOT_PATCH_CHOICE_QUIT
)
5029 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
5030 reverse_patch
? NULL
: outfile
,
5031 reverse_patch
? outfile
: NULL
);
5035 if (!S_ISLNK(sb2
.st_mode
)) {
5038 mode
= apply_umask(sb2
.st_mode
);
5039 if (fchmod(fileno(outfile
), mode
) == -1) {
5040 err
= got_error_from_errno2("fchmod", path2
);
5047 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
5048 err
= got_error_from_errno("close");
5050 got_object_blob_close(blob
);
5051 free_err
= got_diffreg_result_free(diffreg_result
);
5054 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
5055 err
= got_error_from_errno2("fclose", path1
);
5056 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
5057 err
= got_error_from_errno2("fclose", path2
);
5058 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
5059 err
= got_error_from_errno2("close", path2
);
5060 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
5061 err
= got_error_from_errno2("fclose", *path_outfile
);
5062 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
5063 err
= got_error_from_errno2("unlink", path1
);
5064 if (err
|| !have_content
) {
5065 if (*path_outfile
&& unlink(*path_outfile
) == -1 && err
== NULL
)
5066 err
= got_error_from_errno2("unlink", *path_outfile
);
5067 free(*path_outfile
);
5068 *path_outfile
= NULL
;
5074 static const struct got_error
*
5075 revert_file(void *arg
, unsigned char status
, unsigned char staged_status
,
5076 const char *relpath
, struct got_object_id
*blob_id
,
5077 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
5078 int dirfd
, const char *de_name
)
5080 struct revert_file_args
*a
= arg
;
5081 const struct got_error
*err
= NULL
;
5082 char *parent_path
= NULL
;
5083 struct got_fileindex_entry
*ie
;
5084 struct got_commit_object
*base_commit
= NULL
;
5085 struct got_tree_object
*tree
= NULL
;
5086 struct got_object_id
*tree_id
= NULL
;
5087 const struct got_tree_entry
*te
= NULL
;
5088 char *tree_path
= NULL
, *te_name
;
5089 char *ondisk_path
= NULL
, *path_content
= NULL
;
5090 struct got_blob_object
*blob
= NULL
;
5093 /* Reverting a staged deletion is a no-op. */
5094 if (status
== GOT_STATUS_DELETE
&&
5095 staged_status
!= GOT_STATUS_NO_CHANGE
)
5098 if (status
== GOT_STATUS_UNVERSIONED
)
5099 return (*a
->progress_cb
)(a
->progress_arg
,
5100 GOT_STATUS_UNVERSIONED
, relpath
);
5102 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
5104 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
5106 /* Construct in-repository path of tree which contains this blob. */
5107 err
= got_path_dirname(&parent_path
, ie
->path
);
5109 if (err
->code
!= GOT_ERR_BAD_PATH
)
5111 parent_path
= strdup("/");
5112 if (parent_path
== NULL
) {
5113 err
= got_error_from_errno("strdup");
5117 if (got_path_is_root_dir(a
->worktree
->path_prefix
)) {
5118 tree_path
= strdup(parent_path
);
5119 if (tree_path
== NULL
) {
5120 err
= got_error_from_errno("strdup");
5124 if (got_path_is_root_dir(parent_path
)) {
5125 tree_path
= strdup(a
->worktree
->path_prefix
);
5126 if (tree_path
== NULL
) {
5127 err
= got_error_from_errno("strdup");
5131 if (asprintf(&tree_path
, "%s/%s",
5132 a
->worktree
->path_prefix
, parent_path
) == -1) {
5133 err
= got_error_from_errno("asprintf");
5139 err
= got_object_open_as_commit(&base_commit
, a
->repo
,
5140 a
->worktree
->base_commit_id
);
5144 err
= got_object_id_by_path(&tree_id
, a
->repo
, base_commit
, tree_path
);
5146 if (!(err
->code
== GOT_ERR_NO_TREE_ENTRY
&&
5147 (status
== GOT_STATUS_ADD
||
5148 staged_status
== GOT_STATUS_ADD
)))
5151 err
= got_object_open_as_tree(&tree
, a
->repo
, tree_id
);
5155 err
= got_path_basename(&te_name
, ie
->path
);
5159 te
= got_object_tree_find_entry(tree
, te_name
);
5161 if (te
== NULL
&& status
!= GOT_STATUS_ADD
&&
5162 staged_status
!= GOT_STATUS_ADD
) {
5163 err
= got_error_path(ie
->path
, GOT_ERR_NO_TREE_ENTRY
);
5169 case GOT_STATUS_ADD
:
5171 int choice
= GOT_PATCH_CHOICE_NONE
;
5172 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
5173 status
, ie
->path
, NULL
, 1, 1);
5176 if (choice
!= GOT_PATCH_CHOICE_YES
)
5179 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_REVERT
,
5183 got_fileindex_entry_remove(a
->fileindex
, ie
);
5184 if (a
->unlink_added_files
) {
5185 int do_unlink
= a
->added_files_to_unlink
? 0 : 1;
5187 if (a
->added_files_to_unlink
) {
5188 struct got_pathlist_entry
*pe
;
5190 TAILQ_FOREACH(pe
, a
->added_files_to_unlink
,
5192 if (got_path_cmp(pe
->path
, relpath
,
5193 pe
->path_len
, strlen(relpath
)))
5201 if (asprintf(&ondisk_path
, "%s/%s",
5202 got_worktree_get_root_path(a
->worktree
),
5204 err
= got_error_from_errno("asprintf");
5207 if (unlink(ondisk_path
) == -1) {
5208 err
= got_error_from_errno2("unlink",
5215 case GOT_STATUS_DELETE
:
5217 int choice
= GOT_PATCH_CHOICE_NONE
;
5218 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
5219 status
, ie
->path
, NULL
, 1, 1);
5222 if (choice
!= GOT_PATCH_CHOICE_YES
)
5226 case GOT_STATUS_MODIFY
:
5227 case GOT_STATUS_MODE_CHANGE
:
5228 case GOT_STATUS_CONFLICT
:
5229 case GOT_STATUS_MISSING
: {
5230 struct got_object_id id
;
5231 if (staged_status
== GOT_STATUS_ADD
||
5232 staged_status
== GOT_STATUS_MODIFY
)
5233 got_fileindex_entry_get_staged_blob_id(&id
, ie
);
5235 got_fileindex_entry_get_blob_id(&id
, ie
);
5236 fd
= got_opentempfd();
5238 err
= got_error_from_errno("got_opentempfd");
5242 err
= got_object_open_as_blob(&blob
, a
->repo
, &id
, 8192, fd
);
5246 if (asprintf(&ondisk_path
, "%s/%s",
5247 got_worktree_get_root_path(a
->worktree
), relpath
) == -1) {
5248 err
= got_error_from_errno("asprintf");
5252 if (a
->patch_cb
&& (status
== GOT_STATUS_MODIFY
||
5253 status
== GOT_STATUS_CONFLICT
)) {
5254 int is_bad_symlink
= 0;
5255 err
= create_patched_content(&path_content
, 1, &id
,
5256 ondisk_path
, dirfd
, de_name
, ie
->path
, a
->repo
,
5257 a
->patch_cb
, a
->patch_arg
);
5258 if (err
|| path_content
== NULL
)
5260 if (te
&& S_ISLNK(te
->mode
)) {
5261 if (unlink(path_content
) == -1) {
5262 err
= got_error_from_errno2("unlink",
5266 err
= install_symlink(&is_bad_symlink
,
5267 a
->worktree
, ondisk_path
, ie
->path
,
5268 blob
, 0, 1, 0, 0, a
->repo
,
5269 a
->progress_cb
, a
->progress_arg
);
5271 if (rename(path_content
, ondisk_path
) == -1) {
5272 err
= got_error_from_errno3("rename",
5273 path_content
, ondisk_path
);
5278 int is_bad_symlink
= 0;
5279 if (te
&& S_ISLNK(te
->mode
)) {
5280 err
= install_symlink(&is_bad_symlink
,
5281 a
->worktree
, ondisk_path
, ie
->path
,
5282 blob
, 0, 1, 0, 0, a
->repo
,
5283 a
->progress_cb
, a
->progress_arg
);
5285 err
= install_blob(a
->worktree
, ondisk_path
,
5287 te
? te
->mode
: GOT_DEFAULT_FILE_MODE
,
5288 got_fileindex_perms_to_st(ie
), blob
,
5289 0, 1, 0, 0, a
->repo
,
5290 a
->progress_cb
, a
->progress_arg
);
5294 if (status
== GOT_STATUS_DELETE
||
5295 status
== GOT_STATUS_MODE_CHANGE
) {
5296 err
= got_fileindex_entry_update(ie
,
5297 a
->worktree
->root_fd
, relpath
,
5299 a
->worktree
->base_commit_id
->sha1
, 1);
5303 if (is_bad_symlink
) {
5304 got_fileindex_entry_filetype_set(ie
,
5305 GOT_FILEIDX_MODE_BAD_SYMLINK
);
5318 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
5319 err
= got_error_from_errno("close");
5321 got_object_blob_close(blob
);
5323 got_object_tree_close(tree
);
5326 got_object_commit_close(base_commit
);
5330 const struct got_error
*
5331 got_worktree_revert(struct got_worktree
*worktree
,
5332 struct got_pathlist_head
*paths
,
5333 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
5334 got_worktree_patch_cb patch_cb
, void *patch_arg
,
5335 struct got_repository
*repo
)
5337 struct got_fileindex
*fileindex
= NULL
;
5338 char *fileindex_path
= NULL
;
5339 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
5340 const struct got_error
*sync_err
= NULL
;
5341 struct got_pathlist_entry
*pe
;
5342 struct revert_file_args rfa
;
5344 err
= lock_worktree(worktree
, LOCK_EX
);
5348 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
5352 rfa
.worktree
= worktree
;
5353 rfa
.fileindex
= fileindex
;
5354 rfa
.progress_cb
= progress_cb
;
5355 rfa
.progress_arg
= progress_arg
;
5356 rfa
.patch_cb
= patch_cb
;
5357 rfa
.patch_arg
= patch_arg
;
5359 rfa
.unlink_added_files
= 0;
5360 TAILQ_FOREACH(pe
, paths
, entry
) {
5361 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
5362 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
5366 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
5367 if (sync_err
&& err
== NULL
)
5370 free(fileindex_path
);
5372 got_fileindex_free(fileindex
);
5373 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
5374 if (unlockerr
&& err
== NULL
)
5380 free_commitable(struct got_commitable
*ct
)
5383 free(ct
->in_repo_path
);
5384 free(ct
->ondisk_path
);
5386 free(ct
->base_blob_id
);
5387 free(ct
->staged_blob_id
);
5388 free(ct
->base_commit_id
);
5392 struct collect_commitables_arg
{
5393 struct got_pathlist_head
*commitable_paths
;
5394 struct got_repository
*repo
;
5395 struct got_worktree
*worktree
;
5396 struct got_fileindex
*fileindex
;
5397 int have_staged_files
;
5398 int allow_bad_symlinks
;
5399 int diff_header_shown
;
5400 int commit_conflicts
;
5407 * Create a file which contains the target path of a symlink so we can feed
5408 * it as content to the diff engine.
5410 static const struct got_error
*
5411 get_symlink_target_file(int *fd
, int dirfd
, const char *de_name
,
5412 const char *abspath
)
5414 const struct got_error
*err
= NULL
;
5415 char target_path
[PATH_MAX
];
5416 ssize_t target_len
, outlen
;
5421 target_len
= readlinkat(dirfd
, de_name
, target_path
, PATH_MAX
);
5422 if (target_len
== -1)
5423 return got_error_from_errno2("readlinkat", abspath
);
5425 target_len
= readlink(abspath
, target_path
, PATH_MAX
);
5426 if (target_len
== -1)
5427 return got_error_from_errno2("readlink", abspath
);
5430 *fd
= got_opentempfd();
5432 return got_error_from_errno("got_opentempfd");
5434 outlen
= write(*fd
, target_path
, target_len
);
5436 err
= got_error_from_errno("got_opentempfd");
5440 if (lseek(*fd
, 0, SEEK_SET
) == -1) {
5441 err
= got_error_from_errno2("lseek", abspath
);
5452 static const struct got_error
*
5453 append_ct_diff(struct got_commitable
*ct
, int *diff_header_shown
,
5454 FILE *diff_outfile
, FILE *f1
, FILE *f2
, int dirfd
, const char *de_name
,
5455 int diff_staged
, struct got_repository
*repo
, struct got_worktree
*worktree
)
5457 const struct got_error
*err
= NULL
;
5458 struct got_blob_object
*blob1
= NULL
;
5459 int fd
= -1, fd1
= -1, fd2
= -1;
5460 FILE *ondisk_file
= NULL
;
5461 char *label1
= NULL
;
5465 char *id_str
= NULL
;
5467 memset(&sb
, 0, sizeof(sb
));
5470 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
5471 ct
->staged_status
!= GOT_STATUS_ADD
&&
5472 ct
->staged_status
!= GOT_STATUS_DELETE
)
5475 if (ct
->status
!= GOT_STATUS_MODIFY
&&
5476 ct
->status
!= GOT_STATUS_ADD
&&
5477 ct
->status
!= GOT_STATUS_DELETE
&&
5478 ct
->status
!= GOT_STATUS_CONFLICT
)
5482 err
= got_opentemp_truncate(f1
);
5484 return got_error_from_errno("got_opentemp_truncate");
5485 err
= got_opentemp_truncate(f2
);
5487 return got_error_from_errno("got_opentemp_truncate");
5489 if (!*diff_header_shown
) {
5490 err
= got_object_id_str(&id_str
, worktree
->base_commit_id
);
5493 fprintf(diff_outfile
, "diff %s%s\n", diff_staged
? "-s " : "",
5494 got_worktree_get_root_path(worktree
));
5495 fprintf(diff_outfile
, "commit - %s\n", id_str
);
5496 fprintf(diff_outfile
, "path + %s%s\n",
5497 got_worktree_get_root_path(worktree
),
5498 diff_staged
? " (staged changes)" : "");
5499 *diff_header_shown
= 1;
5503 const char *label1
= NULL
, *label2
= NULL
;
5504 switch (ct
->staged_status
) {
5505 case GOT_STATUS_MODIFY
:
5509 case GOT_STATUS_ADD
:
5512 case GOT_STATUS_DELETE
:
5516 return got_error(GOT_ERR_FILE_STATUS
);
5518 fd1
= got_opentempfd();
5520 err
= got_error_from_errno("got_opentempfd");
5523 fd2
= got_opentempfd();
5525 err
= got_error_from_errno("got_opentempfd");
5528 err
= got_diff_objects_as_blobs(NULL
, NULL
, f1
, f2
,
5529 fd1
, fd2
, ct
->base_blob_id
, ct
->staged_blob_id
,
5530 label1
, label2
, GOT_DIFF_ALGORITHM_PATIENCE
, 3, 0, 0,
5531 NULL
, repo
, diff_outfile
);
5535 fd1
= got_opentempfd();
5537 err
= got_error_from_errno("got_opentempfd");
5541 if (ct
->status
!= GOT_STATUS_ADD
) {
5542 err
= got_object_open_as_blob(&blob1
, repo
, ct
->base_blob_id
,
5548 if (ct
->status
!= GOT_STATUS_DELETE
) {
5550 fd
= openat(dirfd
, de_name
,
5551 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
5553 if (!got_err_open_nofollow_on_symlink()) {
5554 err
= got_error_from_errno2("openat",
5558 err
= get_symlink_target_file(&fd
, dirfd
,
5559 de_name
, ct
->ondisk_path
);
5564 fd
= open(ct
->ondisk_path
,
5565 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
5567 if (!got_err_open_nofollow_on_symlink()) {
5568 err
= got_error_from_errno2("open",
5572 err
= get_symlink_target_file(&fd
, dirfd
,
5573 de_name
, ct
->ondisk_path
);
5578 if (fstatat(fd
, ct
->ondisk_path
, &sb
,
5579 AT_SYMLINK_NOFOLLOW
) == -1) {
5580 err
= got_error_from_errno2("fstatat", ct
->ondisk_path
);
5583 ondisk_file
= fdopen(fd
, "r");
5584 if (ondisk_file
== NULL
) {
5585 err
= got_error_from_errno2("fdopen", ct
->ondisk_path
);
5593 err
= got_object_blob_dump_to_file(&size1
, NULL
, NULL
,
5599 err
= got_diff_blob_file(blob1
, f1
, size1
, label1
,
5600 ondisk_file
? ondisk_file
: f2
, f2_exists
, &sb
, ct
->path
,
5601 GOT_DIFF_ALGORITHM_PATIENCE
, 3, 0, 0, NULL
, diff_outfile
);
5603 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
5604 err
= got_error_from_errno("close");
5605 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
5606 err
= got_error_from_errno("close");
5608 got_object_blob_close(blob1
);
5609 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
5610 err
= got_error_from_errno("close");
5611 if (ondisk_file
&& fclose(ondisk_file
) == EOF
&& err
== NULL
)
5612 err
= got_error_from_errno("fclose");
5616 static const struct got_error
*
5617 collect_commitables(void *arg
, unsigned char status
,
5618 unsigned char staged_status
, const char *relpath
,
5619 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
5620 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
5622 struct collect_commitables_arg
*a
= arg
;
5623 const struct got_error
*err
= NULL
;
5624 struct got_commitable
*ct
= NULL
;
5625 struct got_pathlist_entry
*new = NULL
;
5626 char *parent_path
= NULL
, *path
= NULL
;
5629 if (a
->have_staged_files
) {
5630 if (staged_status
!= GOT_STATUS_MODIFY
&&
5631 staged_status
!= GOT_STATUS_ADD
&&
5632 staged_status
!= GOT_STATUS_DELETE
)
5635 if (status
== GOT_STATUS_CONFLICT
&& !a
->commit_conflicts
) {
5636 printf("C %s\n", relpath
);
5637 return got_error(GOT_ERR_COMMIT_CONFLICT
);
5640 if (status
!= GOT_STATUS_MODIFY
&&
5641 status
!= GOT_STATUS_MODE_CHANGE
&&
5642 status
!= GOT_STATUS_ADD
&&
5643 status
!= GOT_STATUS_DELETE
&&
5644 status
!= GOT_STATUS_CONFLICT
)
5648 if (asprintf(&path
, "/%s", relpath
) == -1) {
5649 err
= got_error_from_errno("asprintf");
5652 if (strcmp(path
, "/") == 0) {
5653 parent_path
= strdup("");
5654 if (parent_path
== NULL
)
5655 return got_error_from_errno("strdup");
5657 err
= got_path_dirname(&parent_path
, path
);
5662 ct
= calloc(1, sizeof(*ct
));
5664 err
= got_error_from_errno("calloc");
5668 if (asprintf(&ct
->ondisk_path
, "%s/%s", a
->worktree
->root_path
,
5670 err
= got_error_from_errno("asprintf");
5674 if (staged_status
== GOT_STATUS_ADD
||
5675 staged_status
== GOT_STATUS_MODIFY
) {
5676 struct got_fileindex_entry
*ie
;
5677 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
5678 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
5679 case GOT_FILEIDX_MODE_REGULAR_FILE
:
5680 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
5683 case GOT_FILEIDX_MODE_SYMLINK
:
5687 err
= got_error_path(path
, GOT_ERR_BAD_FILETYPE
);
5690 ct
->mode
|= got_fileindex_entry_perms_get(ie
);
5691 } else if (status
!= GOT_STATUS_DELETE
&&
5692 staged_status
!= GOT_STATUS_DELETE
) {
5694 if (fstatat(dirfd
, de_name
, &sb
,
5695 AT_SYMLINK_NOFOLLOW
) == -1) {
5696 err
= got_error_from_errno2("fstatat",
5700 } else if (lstat(ct
->ondisk_path
, &sb
) == -1) {
5701 err
= got_error_from_errno2("lstat", ct
->ondisk_path
);
5704 ct
->mode
= sb
.st_mode
;
5707 if (asprintf(&ct
->in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
5708 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
5710 err
= got_error_from_errno("asprintf");
5714 if (S_ISLNK(ct
->mode
) && staged_status
== GOT_STATUS_NO_CHANGE
&&
5715 status
== GOT_STATUS_ADD
&& !a
->allow_bad_symlinks
) {
5717 char target_path
[PATH_MAX
];
5719 target_len
= readlink(ct
->ondisk_path
, target_path
,
5720 sizeof(target_path
));
5721 if (target_len
== -1) {
5722 err
= got_error_from_errno2("readlink",
5726 err
= is_bad_symlink_target(&is_bad_symlink
, target_path
,
5727 target_len
, ct
->ondisk_path
, a
->worktree
->root_path
,
5728 a
->worktree
->meta_dir
);
5731 if (is_bad_symlink
) {
5732 err
= got_error_path(ct
->ondisk_path
,
5733 GOT_ERR_BAD_SYMLINK
);
5739 ct
->status
= status
;
5740 ct
->staged_status
= staged_status
;
5741 ct
->blob_id
= NULL
; /* will be filled in when blob gets created */
5742 if (ct
->status
!= GOT_STATUS_ADD
&&
5743 ct
->staged_status
!= GOT_STATUS_ADD
) {
5744 ct
->base_blob_id
= got_object_id_dup(blob_id
);
5745 if (ct
->base_blob_id
== NULL
) {
5746 err
= got_error_from_errno("got_object_id_dup");
5749 ct
->base_commit_id
= got_object_id_dup(commit_id
);
5750 if (ct
->base_commit_id
== NULL
) {
5751 err
= got_error_from_errno("got_object_id_dup");
5755 if (ct
->staged_status
== GOT_STATUS_ADD
||
5756 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5757 ct
->staged_blob_id
= got_object_id_dup(staged_blob_id
);
5758 if (ct
->staged_blob_id
== NULL
) {
5759 err
= got_error_from_errno("got_object_id_dup");
5763 ct
->path
= strdup(path
);
5764 if (ct
->path
== NULL
) {
5765 err
= got_error_from_errno("strdup");
5769 if (a
->diff_outfile
) {
5770 err
= append_ct_diff(ct
, &a
->diff_header_shown
,
5771 a
->diff_outfile
, a
->f1
, a
->f2
, dirfd
, de_name
,
5772 a
->have_staged_files
, a
->repo
, a
->worktree
);
5777 err
= got_pathlist_insert(&new, a
->commitable_paths
, ct
->path
, ct
);
5779 if (ct
&& (err
|| new == NULL
))
5780 free_commitable(ct
);
5786 static const struct got_error
*write_tree(struct got_object_id
**, int *,
5787 struct got_tree_object
*, const char *, struct got_pathlist_head
*,
5788 got_worktree_status_cb status_cb
, void *status_arg
,
5789 struct got_repository
*);
5791 static const struct got_error
*
5792 write_subtree(struct got_object_id
**new_subtree_id
, int *nentries
,
5793 struct got_tree_entry
*te
, const char *parent_path
,
5794 struct got_pathlist_head
*commitable_paths
,
5795 got_worktree_status_cb status_cb
, void *status_arg
,
5796 struct got_repository
*repo
)
5798 const struct got_error
*err
= NULL
;
5799 struct got_tree_object
*subtree
;
5802 if (asprintf(&subpath
, "%s%s%s", parent_path
,
5803 got_path_is_root_dir(parent_path
) ? "" : "/", te
->name
) == -1)
5804 return got_error_from_errno("asprintf");
5806 err
= got_object_open_as_tree(&subtree
, repo
, &te
->id
);
5810 err
= write_tree(new_subtree_id
, nentries
, subtree
, subpath
,
5811 commitable_paths
, status_cb
, status_arg
, repo
);
5812 got_object_tree_close(subtree
);
5817 static const struct got_error
*
5818 match_ct_parent_path(int *match
, struct got_commitable
*ct
, const char *path
)
5820 const struct got_error
*err
= NULL
;
5821 char *ct_parent_path
= NULL
;
5825 if (strchr(ct
->in_repo_path
, '/') == NULL
) {
5826 *match
= got_path_is_root_dir(path
);
5830 err
= got_path_dirname(&ct_parent_path
, ct
->in_repo_path
);
5833 *match
= (strcmp(path
, ct_parent_path
) == 0);
5834 free(ct_parent_path
);
5839 get_ct_file_mode(struct got_commitable
*ct
)
5841 if (S_ISLNK(ct
->mode
))
5844 return S_IFREG
| (ct
->mode
& ((S_IRWXU
| S_IRWXG
| S_IRWXO
)));
5847 static const struct got_error
*
5848 alloc_modified_blob_tree_entry(struct got_tree_entry
**new_te
,
5849 struct got_tree_entry
*te
, struct got_commitable
*ct
)
5851 const struct got_error
*err
= NULL
;
5855 err
= got_object_tree_entry_dup(new_te
, te
);
5859 (*new_te
)->mode
= get_ct_file_mode(ct
);
5861 if (ct
->staged_status
== GOT_STATUS_MODIFY
)
5862 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5863 sizeof((*new_te
)->id
));
5865 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5867 if (err
&& *new_te
) {
5874 static const struct got_error
*
5875 alloc_added_blob_tree_entry(struct got_tree_entry
**new_te
,
5876 struct got_commitable
*ct
)
5878 const struct got_error
*err
= NULL
;
5879 char *ct_name
= NULL
;
5883 *new_te
= calloc(1, sizeof(**new_te
));
5884 if (*new_te
== NULL
)
5885 return got_error_from_errno("calloc");
5887 err
= got_path_basename(&ct_name
, ct
->path
);
5890 if (strlcpy((*new_te
)->name
, ct_name
, sizeof((*new_te
)->name
)) >=
5891 sizeof((*new_te
)->name
)) {
5892 err
= got_error(GOT_ERR_NO_SPACE
);
5896 (*new_te
)->mode
= get_ct_file_mode(ct
);
5898 if (ct
->staged_status
== GOT_STATUS_ADD
)
5899 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5900 sizeof((*new_te
)->id
));
5902 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5905 if (err
&& *new_te
) {
5912 static const struct got_error
*
5913 insert_tree_entry(struct got_tree_entry
*new_te
,
5914 struct got_pathlist_head
*paths
)
5916 const struct got_error
*err
= NULL
;
5917 struct got_pathlist_entry
*new_pe
;
5919 err
= got_pathlist_insert(&new_pe
, paths
, new_te
->name
, new_te
);
5923 return got_error(GOT_ERR_TREE_DUP_ENTRY
);
5927 static const struct got_error
*
5928 report_ct_status(struct got_commitable
*ct
,
5929 got_worktree_status_cb status_cb
, void *status_arg
)
5931 const char *ct_path
= ct
->path
;
5932 unsigned char status
;
5934 if (status_cb
== NULL
) /* no commit progress output desired */
5937 while (ct_path
[0] == '/')
5940 if (ct
->staged_status
!= GOT_STATUS_NO_CHANGE
)
5941 status
= ct
->staged_status
;
5943 status
= ct
->status
;
5945 return (*status_cb
)(status_arg
, status
, GOT_STATUS_NO_CHANGE
,
5946 ct_path
, ct
->blob_id
, NULL
, NULL
, -1, NULL
);
5949 static const struct got_error
*
5950 match_modified_subtree(int *modified
, struct got_tree_entry
*te
,
5951 const char *base_tree_path
, struct got_pathlist_head
*commitable_paths
)
5953 const struct got_error
*err
= NULL
;
5954 struct got_pathlist_entry
*pe
;
5959 if (asprintf(&te_path
, "%s%s%s", base_tree_path
,
5960 got_path_is_root_dir(base_tree_path
) ? "" : "/",
5962 return got_error_from_errno("asprintf");
5964 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5965 struct got_commitable
*ct
= pe
->data
;
5966 *modified
= got_path_is_child(ct
->in_repo_path
, te_path
,
5976 static const struct got_error
*
5977 match_deleted_or_modified_ct(struct got_commitable
**ctp
,
5978 struct got_tree_entry
*te
, const char *base_tree_path
,
5979 struct got_pathlist_head
*commitable_paths
)
5981 const struct got_error
*err
= NULL
;
5982 struct got_pathlist_entry
*pe
;
5986 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5987 struct got_commitable
*ct
= pe
->data
;
5988 char *ct_name
= NULL
;
5991 if (ct
->staged_status
== GOT_STATUS_NO_CHANGE
) {
5992 if (ct
->status
!= GOT_STATUS_MODIFY
&&
5993 ct
->status
!= GOT_STATUS_MODE_CHANGE
&&
5994 ct
->status
!= GOT_STATUS_DELETE
&&
5995 ct
->status
!= GOT_STATUS_CONFLICT
)
5998 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
5999 ct
->staged_status
!= GOT_STATUS_DELETE
)
6003 if (got_object_id_cmp(ct
->base_blob_id
, &te
->id
) != 0)
6006 err
= match_ct_parent_path(&path_matches
, ct
, base_tree_path
);
6012 err
= got_path_basename(&ct_name
, pe
->path
);
6016 if (strcmp(te
->name
, ct_name
) != 0) {
6029 static const struct got_error
*
6030 make_subtree_for_added_blob(struct got_tree_entry
**new_tep
,
6031 const char *child_path
, const char *path_base_tree
,
6032 struct got_pathlist_head
*commitable_paths
,
6033 got_worktree_status_cb status_cb
, void *status_arg
,
6034 struct got_repository
*repo
)
6036 const struct got_error
*err
= NULL
;
6037 struct got_tree_entry
*new_te
;
6039 struct got_object_id
*id
= NULL
;
6044 if (asprintf(&subtree_path
, "%s%s%s", path_base_tree
,
6045 got_path_is_root_dir(path_base_tree
) ? "" : "/",
6047 return got_error_from_errno("asprintf");
6049 new_te
= calloc(1, sizeof(*new_te
));
6051 return got_error_from_errno("calloc");
6052 new_te
->mode
= S_IFDIR
;
6054 if (strlcpy(new_te
->name
, child_path
, sizeof(new_te
->name
)) >=
6055 sizeof(new_te
->name
)) {
6056 err
= got_error(GOT_ERR_NO_SPACE
);
6059 err
= write_tree(&id
, &nentries
, NULL
, subtree_path
,
6060 commitable_paths
, status_cb
, status_arg
, repo
);
6065 memcpy(&new_te
->id
, id
, sizeof(new_te
->id
));
6074 static const struct got_error
*
6075 write_tree(struct got_object_id
**new_tree_id
, int *nentries
,
6076 struct got_tree_object
*base_tree
, const char *path_base_tree
,
6077 struct got_pathlist_head
*commitable_paths
,
6078 got_worktree_status_cb status_cb
, void *status_arg
,
6079 struct got_repository
*repo
)
6081 const struct got_error
*err
= NULL
;
6082 struct got_pathlist_head paths
;
6083 struct got_tree_entry
*te
, *new_te
= NULL
;
6084 struct got_pathlist_entry
*pe
;
6089 /* Insert, and recurse into, newly added entries first. */
6090 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
6091 struct got_commitable
*ct
= pe
->data
;
6092 char *child_path
= NULL
, *slash
;
6094 if ((ct
->status
!= GOT_STATUS_ADD
&&
6095 ct
->staged_status
!= GOT_STATUS_ADD
) ||
6096 (ct
->flags
& GOT_COMMITABLE_ADDED
))
6099 if (!got_path_is_child(ct
->in_repo_path
, path_base_tree
,
6100 strlen(path_base_tree
)))
6103 err
= got_path_skip_common_ancestor(&child_path
, path_base_tree
,
6108 slash
= strchr(child_path
, '/');
6109 if (slash
== NULL
) {
6110 err
= alloc_added_blob_tree_entry(&new_te
, ct
);
6113 err
= report_ct_status(ct
, status_cb
, status_arg
);
6116 ct
->flags
|= GOT_COMMITABLE_ADDED
;
6117 err
= insert_tree_entry(new_te
, &paths
);
6122 *slash
= '\0'; /* trim trailing path components */
6123 if (base_tree
== NULL
||
6124 got_object_tree_find_entry(base_tree
, child_path
)
6126 err
= make_subtree_for_added_blob(&new_te
,
6127 child_path
, path_base_tree
,
6128 commitable_paths
, status_cb
, status_arg
,
6132 err
= insert_tree_entry(new_te
, &paths
);
6141 int i
, nbase_entries
;
6142 /* Handle modified and deleted entries. */
6143 nbase_entries
= got_object_tree_get_nentries(base_tree
);
6144 for (i
= 0; i
< nbase_entries
; i
++) {
6145 struct got_commitable
*ct
= NULL
;
6147 te
= got_object_tree_get_entry(base_tree
, i
);
6148 if (got_object_tree_entry_is_submodule(te
)) {
6149 /* Entry is a submodule; just copy it. */
6150 err
= got_object_tree_entry_dup(&new_te
, te
);
6153 err
= insert_tree_entry(new_te
, &paths
);
6160 if (S_ISDIR(te
->mode
)) {
6162 err
= got_object_tree_entry_dup(&new_te
, te
);
6165 err
= match_modified_subtree(&modified
, te
,
6166 path_base_tree
, commitable_paths
);
6169 /* Avoid recursion into unmodified subtrees. */
6171 struct got_object_id
*new_id
;
6173 err
= write_subtree(&new_id
,
6175 path_base_tree
, commitable_paths
,
6176 status_cb
, status_arg
, repo
);
6179 if (nsubentries
== 0) {
6180 /* All entries were deleted. */
6184 memcpy(&new_te
->id
, new_id
,
6185 sizeof(new_te
->id
));
6188 err
= insert_tree_entry(new_te
, &paths
);
6195 err
= match_deleted_or_modified_ct(&ct
, te
,
6196 path_base_tree
, commitable_paths
);
6200 /* NB: Deleted entries get dropped here. */
6201 if (ct
->status
== GOT_STATUS_MODIFY
||
6202 ct
->status
== GOT_STATUS_MODE_CHANGE
||
6203 ct
->status
== GOT_STATUS_CONFLICT
||
6204 ct
->staged_status
== GOT_STATUS_MODIFY
) {
6205 err
= alloc_modified_blob_tree_entry(
6209 err
= insert_tree_entry(new_te
, &paths
);
6214 err
= report_ct_status(ct
, status_cb
,
6219 /* Entry is unchanged; just copy it. */
6220 err
= got_object_tree_entry_dup(&new_te
, te
);
6223 err
= insert_tree_entry(new_te
, &paths
);
6231 /* Write new list of entries; deleted entries have been dropped. */
6232 err
= got_object_tree_create(new_tree_id
, &paths
, *nentries
, repo
);
6234 got_pathlist_free(&paths
, GOT_PATHLIST_FREE_NONE
);
6238 static const struct got_error
*
6239 update_fileindex_after_commit(struct got_worktree
*worktree
,
6240 struct got_pathlist_head
*commitable_paths
,
6241 struct got_object_id
*new_base_commit_id
,
6242 struct got_fileindex
*fileindex
, int have_staged_files
)
6244 const struct got_error
*err
= NULL
;
6245 struct got_pathlist_entry
*pe
;
6246 char *relpath
= NULL
;
6248 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
6249 struct got_fileindex_entry
*ie
;
6250 struct got_commitable
*ct
= pe
->data
;
6252 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
6254 err
= got_path_skip_common_ancestor(&relpath
,
6255 worktree
->root_path
, ct
->ondisk_path
);
6260 if (ct
->status
== GOT_STATUS_DELETE
||
6261 ct
->staged_status
== GOT_STATUS_DELETE
) {
6262 got_fileindex_entry_remove(fileindex
, ie
);
6263 } else if (ct
->staged_status
== GOT_STATUS_ADD
||
6264 ct
->staged_status
== GOT_STATUS_MODIFY
) {
6265 got_fileindex_entry_stage_set(ie
,
6266 GOT_FILEIDX_STAGE_NONE
);
6267 got_fileindex_entry_staged_filetype_set(ie
, 0);
6269 err
= got_fileindex_entry_update(ie
,
6270 worktree
->root_fd
, relpath
,
6271 ct
->staged_blob_id
->sha1
,
6272 new_base_commit_id
->sha1
,
6273 !have_staged_files
);
6275 err
= got_fileindex_entry_update(ie
,
6276 worktree
->root_fd
, relpath
,
6278 new_base_commit_id
->sha1
,
6279 !have_staged_files
);
6281 err
= got_fileindex_entry_alloc(&ie
, pe
->path
);
6284 err
= got_fileindex_entry_update(ie
,
6285 worktree
->root_fd
, relpath
, ct
->blob_id
->sha1
,
6286 new_base_commit_id
->sha1
, 1);
6288 got_fileindex_entry_free(ie
);
6291 err
= got_fileindex_entry_add(fileindex
, ie
);
6293 got_fileindex_entry_free(ie
);
6306 static const struct got_error
*
6307 check_out_of_date(const char *in_repo_path
, unsigned char status
,
6308 unsigned char staged_status
, struct got_object_id
*base_blob_id
,
6309 struct got_object_id
*base_commit_id
,
6310 struct got_object_id
*head_commit_id
, struct got_repository
*repo
,
6313 const struct got_error
*err
= NULL
;
6314 struct got_commit_object
*commit
= NULL
;
6315 struct got_object_id
*id
= NULL
;
6317 if (status
!= GOT_STATUS_ADD
&& staged_status
!= GOT_STATUS_ADD
) {
6318 /* Trivial case: base commit == head commit */
6319 if (got_object_id_cmp(base_commit_id
, head_commit_id
) == 0)
6322 * Ensure file content which local changes were based
6323 * on matches file content in the branch head.
6325 err
= got_object_open_as_commit(&commit
, repo
, head_commit_id
);
6328 err
= got_object_id_by_path(&id
, repo
, commit
, in_repo_path
);
6330 if (err
->code
== GOT_ERR_NO_TREE_ENTRY
)
6331 err
= got_error(ood_errcode
);
6333 } else if (got_object_id_cmp(id
, base_blob_id
) != 0)
6334 err
= got_error(ood_errcode
);
6336 /* Require that added files don't exist in the branch head. */
6337 err
= got_object_open_as_commit(&commit
, repo
, head_commit_id
);
6340 err
= got_object_id_by_path(&id
, repo
, commit
, in_repo_path
);
6341 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
6343 err
= id
? got_error(ood_errcode
) : NULL
;
6348 got_object_commit_close(commit
);
6352 static const struct got_error
*
6353 commit_worktree(struct got_object_id
**new_commit_id
,
6354 struct got_pathlist_head
*commitable_paths
,
6355 struct got_object_id
*head_commit_id
,
6356 struct got_object_id
*parent_id2
,
6357 struct got_worktree
*worktree
,
6358 const char *author
, const char *committer
, char *diff_path
,
6359 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
6360 got_worktree_status_cb status_cb
, void *status_arg
,
6361 struct got_repository
*repo
)
6363 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
6364 struct got_pathlist_entry
*pe
;
6365 const char *head_ref_name
= NULL
;
6366 struct got_commit_object
*head_commit
= NULL
;
6367 struct got_reference
*head_ref2
= NULL
;
6368 struct got_object_id
*head_commit_id2
= NULL
;
6369 struct got_tree_object
*head_tree
= NULL
;
6370 struct got_object_id
*new_tree_id
= NULL
;
6371 int nentries
, nparents
= 0;
6372 struct got_object_id_queue parent_ids
;
6373 struct got_object_qid
*pid
= NULL
;
6374 char *logmsg
= NULL
;
6377 *new_commit_id
= NULL
;
6379 STAILQ_INIT(&parent_ids
);
6381 err
= got_object_open_as_commit(&head_commit
, repo
, head_commit_id
);
6385 err
= got_object_open_as_tree(&head_tree
, repo
, head_commit
->tree_id
);
6389 if (commit_msg_cb
!= NULL
) {
6390 err
= commit_msg_cb(commitable_paths
, diff_path
,
6391 &logmsg
, commit_arg
);
6396 if (logmsg
== NULL
|| strlen(logmsg
) == 0) {
6397 err
= got_error(GOT_ERR_COMMIT_MSG_EMPTY
);
6401 /* Create blobs from added and modified files and record their IDs. */
6402 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
6403 struct got_commitable
*ct
= pe
->data
;
6406 /* Blobs for staged files already exist. */
6407 if (ct
->staged_status
== GOT_STATUS_ADD
||
6408 ct
->staged_status
== GOT_STATUS_MODIFY
)
6411 if (ct
->status
!= GOT_STATUS_ADD
&&
6412 ct
->status
!= GOT_STATUS_MODIFY
&&
6413 ct
->status
!= GOT_STATUS_MODE_CHANGE
&&
6414 ct
->status
!= GOT_STATUS_CONFLICT
)
6417 if (asprintf(&ondisk_path
, "%s/%s",
6418 worktree
->root_path
, pe
->path
) == -1) {
6419 err
= got_error_from_errno("asprintf");
6422 err
= got_object_blob_create(&ct
->blob_id
, ondisk_path
, repo
);
6428 /* Recursively write new tree objects. */
6429 err
= write_tree(&new_tree_id
, &nentries
, head_tree
, "/",
6430 commitable_paths
, status_cb
, status_arg
, repo
);
6434 err
= got_object_qid_alloc(&pid
, head_commit_id
);
6437 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
6440 err
= got_object_qid_alloc(&pid
, parent_id2
);
6443 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
6446 timestamp
= time(NULL
);
6447 err
= got_object_commit_create(new_commit_id
, new_tree_id
, &parent_ids
,
6448 nparents
, author
, timestamp
, committer
, timestamp
, logmsg
, repo
);
6454 /* Check if a concurrent commit to our branch has occurred. */
6455 head_ref_name
= got_worktree_get_head_ref_name(worktree
);
6456 if (head_ref_name
== NULL
) {
6457 err
= got_error_from_errno("got_worktree_get_head_ref_name");
6460 /* Lock the reference here to prevent concurrent modification. */
6461 err
= got_ref_open(&head_ref2
, repo
, head_ref_name
, 1);
6464 err
= got_ref_resolve(&head_commit_id2
, repo
, head_ref2
);
6467 if (got_object_id_cmp(head_commit_id
, head_commit_id2
) != 0) {
6468 err
= got_error(GOT_ERR_COMMIT_HEAD_CHANGED
);
6471 /* Update branch head in repository. */
6472 err
= got_ref_change_ref(head_ref2
, *new_commit_id
);
6475 err
= got_ref_write(head_ref2
, repo
);
6479 err
= got_worktree_set_base_commit_id(worktree
, repo
, *new_commit_id
);
6483 err
= ref_base_commit(worktree
, repo
);
6487 got_object_id_queue_free(&parent_ids
);
6489 got_object_tree_close(head_tree
);
6491 got_object_commit_close(head_commit
);
6492 free(head_commit_id2
);
6494 unlockerr
= got_ref_unlock(head_ref2
);
6495 if (unlockerr
&& err
== NULL
)
6497 got_ref_close(head_ref2
);
6502 static const struct got_error
*
6503 check_path_is_commitable(const char *path
,
6504 struct got_pathlist_head
*commitable_paths
)
6506 struct got_pathlist_entry
*cpe
= NULL
;
6507 size_t path_len
= strlen(path
);
6509 TAILQ_FOREACH(cpe
, commitable_paths
, entry
) {
6510 struct got_commitable
*ct
= cpe
->data
;
6511 const char *ct_path
= ct
->path
;
6513 while (ct_path
[0] == '/')
6516 if (strcmp(path
, ct_path
) == 0 ||
6517 got_path_is_child(ct_path
, path
, path_len
))
6522 return got_error_path(path
, GOT_ERR_BAD_PATH
);
6527 static const struct got_error
*
6528 check_staged_file(void *arg
, struct got_fileindex_entry
*ie
)
6530 int *have_staged_files
= arg
;
6532 if (got_fileindex_entry_stage_get(ie
) != GOT_FILEIDX_STAGE_NONE
) {
6533 *have_staged_files
= 1;
6534 return got_error(GOT_ERR_CANCELLED
);
6540 static const struct got_error
*
6541 check_non_staged_files(struct got_fileindex
*fileindex
,
6542 struct got_pathlist_head
*paths
)
6544 struct got_pathlist_entry
*pe
;
6545 struct got_fileindex_entry
*ie
;
6547 TAILQ_FOREACH(pe
, paths
, entry
) {
6548 if (pe
->path
[0] == '\0')
6550 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
6552 return got_error_path(pe
->path
, GOT_ERR_BAD_PATH
);
6553 if (got_fileindex_entry_stage_get(ie
) == GOT_FILEIDX_STAGE_NONE
)
6554 return got_error_path(pe
->path
,
6555 GOT_ERR_FILE_NOT_STAGED
);
6561 const struct got_error
*
6562 got_worktree_commit(struct got_object_id
**new_commit_id
,
6563 struct got_worktree
*worktree
, struct got_pathlist_head
*paths
,
6564 const char *author
, const char *committer
, int allow_bad_symlinks
,
6565 int show_diff
, int commit_conflicts
,
6566 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
6567 got_worktree_status_cb status_cb
, void *status_arg
,
6568 struct got_repository
*repo
)
6570 const struct got_error
*err
= NULL
, *unlockerr
= NULL
, *sync_err
;
6571 struct got_fileindex
*fileindex
= NULL
;
6572 char *fileindex_path
= NULL
;
6573 struct got_pathlist_head commitable_paths
;
6574 struct collect_commitables_arg cc_arg
;
6575 struct got_pathlist_entry
*pe
;
6576 struct got_reference
*head_ref
= NULL
;
6577 struct got_object_id
*head_commit_id
= NULL
;
6578 char *diff_path
= NULL
;
6579 int have_staged_files
= 0;
6581 *new_commit_id
= NULL
;
6583 memset(&cc_arg
, 0, sizeof(cc_arg
));
6584 TAILQ_INIT(&commitable_paths
);
6586 err
= lock_worktree(worktree
, LOCK_EX
);
6590 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
6594 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
6598 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
6602 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
6603 &have_staged_files
);
6604 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6606 if (have_staged_files
) {
6607 err
= check_non_staged_files(fileindex
, paths
);
6612 cc_arg
.commitable_paths
= &commitable_paths
;
6613 cc_arg
.worktree
= worktree
;
6614 cc_arg
.fileindex
= fileindex
;
6616 cc_arg
.have_staged_files
= have_staged_files
;
6617 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
6618 cc_arg
.diff_header_shown
= 0;
6619 cc_arg
.commit_conflicts
= commit_conflicts
;
6621 err
= got_opentemp_named(&diff_path
, &cc_arg
.diff_outfile
,
6622 GOT_TMPDIR_STR
"/got", ".diff");
6625 cc_arg
.f1
= got_opentemp();
6626 if (cc_arg
.f1
== NULL
) {
6627 err
= got_error_from_errno("got_opentemp");
6630 cc_arg
.f2
= got_opentemp();
6631 if (cc_arg
.f2
== NULL
) {
6632 err
= got_error_from_errno("got_opentemp");
6637 TAILQ_FOREACH(pe
, paths
, entry
) {
6638 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
6639 collect_commitables
, &cc_arg
, NULL
, NULL
, 0, 0);
6645 if (fflush(cc_arg
.diff_outfile
) == EOF
) {
6646 err
= got_error_from_errno("fflush");
6651 if (TAILQ_EMPTY(&commitable_paths
)) {
6652 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
6656 TAILQ_FOREACH(pe
, paths
, entry
) {
6657 err
= check_path_is_commitable(pe
->path
, &commitable_paths
);
6662 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
6663 struct got_commitable
*ct
= pe
->data
;
6664 const char *ct_path
= ct
->in_repo_path
;
6666 while (ct_path
[0] == '/')
6668 err
= check_out_of_date(ct_path
, ct
->status
,
6669 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
6670 head_commit_id
, repo
, GOT_ERR_COMMIT_OUT_OF_DATE
);
6676 err
= commit_worktree(new_commit_id
, &commitable_paths
,
6677 head_commit_id
, NULL
, worktree
, author
, committer
,
6678 (diff_path
&& cc_arg
.diff_header_shown
) ? diff_path
: NULL
,
6679 commit_msg_cb
, commit_arg
, status_cb
, status_arg
, repo
);
6683 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
6684 *new_commit_id
, fileindex
, have_staged_files
);
6685 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6686 if (sync_err
&& err
== NULL
)
6690 got_fileindex_free(fileindex
);
6691 free(fileindex_path
);
6692 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6693 if (unlockerr
&& err
== NULL
)
6695 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
6696 struct got_commitable
*ct
= pe
->data
;
6698 free_commitable(ct
);
6700 got_pathlist_free(&commitable_paths
, GOT_PATHLIST_FREE_NONE
);
6701 if (diff_path
&& unlink(diff_path
) == -1 && err
== NULL
)
6702 err
= got_error_from_errno2("unlink", diff_path
);
6704 if (cc_arg
.diff_outfile
&& fclose(cc_arg
.diff_outfile
) == EOF
&&
6706 err
= got_error_from_errno("fclose");
6711 got_commitable_get_path(struct got_commitable
*ct
)
6717 got_commitable_get_status(struct got_commitable
*ct
)
6722 struct check_rebase_ok_arg
{
6723 struct got_worktree
*worktree
;
6724 struct got_repository
*repo
;
6727 static const struct got_error
*
6728 check_rebase_ok(void *arg
, struct got_fileindex_entry
*ie
)
6730 const struct got_error
*err
= NULL
;
6731 struct check_rebase_ok_arg
*a
= arg
;
6732 unsigned char status
;
6736 /* Reject rebase of a work tree with mixed base commits. */
6737 if (memcmp(ie
->commit_sha1
, a
->worktree
->base_commit_id
->sha1
,
6738 SHA1_DIGEST_LENGTH
))
6739 return got_error(GOT_ERR_MIXED_COMMITS
);
6741 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
6743 return got_error_from_errno("asprintf");
6745 /* Reject rebase of a work tree with modified or staged files. */
6746 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
6751 if (status
!= GOT_STATUS_NO_CHANGE
)
6752 return got_error(GOT_ERR_MODIFIED
);
6753 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
6754 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
6759 const struct got_error
*
6760 got_worktree_rebase_prepare(struct got_reference
**new_base_branch_ref
,
6761 struct got_reference
**tmp_branch
, struct got_fileindex
**fileindex
,
6762 struct got_worktree
*worktree
, struct got_reference
*branch
,
6763 struct got_repository
*repo
)
6765 const struct got_error
*err
= NULL
;
6766 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6767 char *branch_ref_name
= NULL
;
6768 char *fileindex_path
= NULL
;
6769 struct check_rebase_ok_arg ok_arg
;
6770 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
6771 struct got_object_id
*wt_branch_tip
= NULL
;
6773 *new_base_branch_ref
= NULL
;
6777 err
= lock_worktree(worktree
, LOCK_EX
);
6781 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6785 ok_arg
.worktree
= worktree
;
6787 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6792 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6796 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6800 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6804 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6809 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
6812 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
6813 err
= got_error(GOT_ERR_REBASE_OUT_OF_DATE
);
6817 err
= got_ref_alloc_symref(new_base_branch_ref
,
6818 new_base_branch_ref_name
, wt_branch
);
6821 err
= got_ref_write(*new_base_branch_ref
, repo
);
6825 /* TODO Lock original branch's ref while rebasing? */
6827 err
= got_ref_alloc_symref(&branch_ref
, branch_ref_name
, branch
);
6831 err
= got_ref_write(branch_ref
, repo
);
6835 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6836 worktree
->base_commit_id
);
6839 err
= got_ref_write(*tmp_branch
, repo
);
6843 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6847 free(fileindex_path
);
6848 free(tmp_branch_name
);
6849 free(new_base_branch_ref_name
);
6850 free(branch_ref_name
);
6852 got_ref_close(branch_ref
);
6854 got_ref_close(wt_branch
);
6855 free(wt_branch_tip
);
6857 if (*new_base_branch_ref
) {
6858 got_ref_close(*new_base_branch_ref
);
6859 *new_base_branch_ref
= NULL
;
6862 got_ref_close(*tmp_branch
);
6866 got_fileindex_free(*fileindex
);
6869 lock_worktree(worktree
, LOCK_SH
);
6874 const struct got_error
*
6875 got_worktree_rebase_continue(struct got_object_id
**commit_id
,
6876 struct got_reference
**new_base_branch
, struct got_reference
**tmp_branch
,
6877 struct got_reference
**branch
, struct got_fileindex
**fileindex
,
6878 struct got_worktree
*worktree
, struct got_repository
*repo
)
6880 const struct got_error
*err
;
6881 char *commit_ref_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6882 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
6883 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
6884 char *fileindex_path
= NULL
;
6885 int have_staged_files
= 0;
6888 *new_base_branch
= NULL
;
6893 err
= lock_worktree(worktree
, LOCK_EX
);
6897 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6901 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
6902 &have_staged_files
);
6903 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6905 if (have_staged_files
) {
6906 err
= got_error(GOT_ERR_STAGED_PATHS
);
6910 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6914 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6918 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6922 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6926 err
= got_ref_open(&branch_ref
, repo
, branch_ref_name
, 0);
6930 err
= got_ref_open(branch
, repo
,
6931 got_ref_get_symref_target(branch_ref
), 0);
6935 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6939 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
6943 err
= got_ref_open(new_base_branch
, repo
,
6944 new_base_branch_ref_name
, 0);
6948 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
6952 free(commit_ref_name
);
6953 free(branch_ref_name
);
6954 free(fileindex_path
);
6956 got_ref_close(commit_ref
);
6958 got_ref_close(branch_ref
);
6963 got_ref_close(*tmp_branch
);
6966 if (*new_base_branch
) {
6967 got_ref_close(*new_base_branch
);
6968 *new_base_branch
= NULL
;
6971 got_ref_close(*branch
);
6975 got_fileindex_free(*fileindex
);
6978 lock_worktree(worktree
, LOCK_SH
);
6983 const struct got_error
*
6984 got_worktree_rebase_in_progress(int *in_progress
, struct got_worktree
*worktree
)
6986 const struct got_error
*err
;
6987 char *tmp_branch_name
= NULL
;
6989 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6993 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
6994 free(tmp_branch_name
);
6998 static const struct got_error
*
6999 collect_rebase_commit_msg(struct got_pathlist_head
*commitable_paths
,
7000 const char *diff_path
, char **logmsg
, void *arg
)
7006 static const struct got_error
*
7007 rebase_status(void *arg
, unsigned char status
, unsigned char staged_status
,
7008 const char *path
, struct got_object_id
*blob_id
,
7009 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
7010 int dirfd
, const char *de_name
)
7015 struct collect_merged_paths_arg
{
7016 got_worktree_checkout_cb progress_cb
;
7018 struct got_pathlist_head
*merged_paths
;
7021 static const struct got_error
*
7022 collect_merged_paths(void *arg
, unsigned char status
, const char *path
)
7024 const struct got_error
*err
;
7025 struct collect_merged_paths_arg
*a
= arg
;
7027 struct got_pathlist_entry
*new;
7029 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path
);
7033 if (status
!= GOT_STATUS_MERGE
&&
7034 status
!= GOT_STATUS_ADD
&&
7035 status
!= GOT_STATUS_DELETE
&&
7036 status
!= GOT_STATUS_CONFLICT
)
7041 return got_error_from_errno("strdup");
7043 err
= got_pathlist_insert(&new, a
->merged_paths
, p
, NULL
);
7044 if (err
|| new == NULL
)
7049 static const struct got_error
*
7050 store_commit_id(const char *commit_ref_name
, struct got_object_id
*commit_id
,
7051 int is_rebase
, struct got_repository
*repo
)
7053 const struct got_error
*err
;
7054 struct got_reference
*commit_ref
= NULL
;
7056 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7058 if (err
->code
!= GOT_ERR_NOT_REF
)
7060 err
= got_ref_alloc(&commit_ref
, commit_ref_name
, commit_id
);
7063 err
= got_ref_write(commit_ref
, repo
);
7066 } else if (is_rebase
) {
7067 struct got_object_id
*stored_id
;
7070 err
= got_ref_resolve(&stored_id
, repo
, commit_ref
);
7073 cmp
= got_object_id_cmp(commit_id
, stored_id
);
7076 err
= got_error(GOT_ERR_REBASE_COMMITID
);
7082 got_ref_close(commit_ref
);
7086 static const struct got_error
*
7087 rebase_merge_files(struct got_pathlist_head
*merged_paths
,
7088 const char *commit_ref_name
, struct got_worktree
*worktree
,
7089 struct got_fileindex
*fileindex
, struct got_object_id
*parent_commit_id
,
7090 struct got_object_id
*commit_id
, struct got_repository
*repo
,
7091 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7092 got_cancel_cb cancel_cb
, void *cancel_arg
)
7094 const struct got_error
*err
;
7095 struct got_reference
*commit_ref
= NULL
;
7096 struct collect_merged_paths_arg cmp_arg
;
7097 char *fileindex_path
;
7099 /* Work tree is locked/unlocked during rebase preparation/teardown. */
7101 err
= get_fileindex_path(&fileindex_path
, worktree
);
7105 cmp_arg
.progress_cb
= progress_cb
;
7106 cmp_arg
.progress_arg
= progress_arg
;
7107 cmp_arg
.merged_paths
= merged_paths
;
7108 err
= merge_files(worktree
, fileindex
, fileindex_path
,
7109 parent_commit_id
, commit_id
, repo
, collect_merged_paths
,
7110 &cmp_arg
, cancel_cb
, cancel_arg
);
7112 got_ref_close(commit_ref
);
7116 const struct got_error
*
7117 got_worktree_rebase_merge_files(struct got_pathlist_head
*merged_paths
,
7118 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
7119 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
7120 struct got_repository
*repo
,
7121 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7122 got_cancel_cb cancel_cb
, void *cancel_arg
)
7124 const struct got_error
*err
;
7125 char *commit_ref_name
;
7127 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
7131 err
= store_commit_id(commit_ref_name
, commit_id
, 1, repo
);
7135 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
7136 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
7137 progress_arg
, cancel_cb
, cancel_arg
);
7139 free(commit_ref_name
);
7143 const struct got_error
*
7144 got_worktree_histedit_merge_files(struct got_pathlist_head
*merged_paths
,
7145 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
7146 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
7147 struct got_repository
*repo
,
7148 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7149 got_cancel_cb cancel_cb
, void *cancel_arg
)
7151 const struct got_error
*err
;
7152 char *commit_ref_name
;
7154 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7158 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
7162 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
7163 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
7164 progress_arg
, cancel_cb
, cancel_arg
);
7166 free(commit_ref_name
);
7170 static const struct got_error
*
7171 rebase_commit(struct got_object_id
**new_commit_id
,
7172 struct got_pathlist_head
*merged_paths
, struct got_reference
*commit_ref
,
7173 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
7174 struct got_reference
*tmp_branch
, const char *committer
,
7175 struct got_commit_object
*orig_commit
, const char *new_logmsg
,
7176 int allow_conflict
, struct got_repository
*repo
)
7178 const struct got_error
*err
, *sync_err
;
7179 struct got_pathlist_head commitable_paths
;
7180 struct collect_commitables_arg cc_arg
;
7181 char *fileindex_path
= NULL
;
7182 struct got_reference
*head_ref
= NULL
;
7183 struct got_object_id
*head_commit_id
= NULL
;
7184 char *logmsg
= NULL
;
7186 memset(&cc_arg
, 0, sizeof(cc_arg
));
7187 TAILQ_INIT(&commitable_paths
);
7188 *new_commit_id
= NULL
;
7190 /* Work tree is locked/unlocked during rebase preparation/teardown. */
7192 err
= get_fileindex_path(&fileindex_path
, worktree
);
7196 cc_arg
.commitable_paths
= &commitable_paths
;
7197 cc_arg
.worktree
= worktree
;
7199 cc_arg
.have_staged_files
= 0;
7200 cc_arg
.commit_conflicts
= allow_conflict
;
7202 * If possible get the status of individual files directly to
7203 * avoid crawling the entire work tree once per rebased commit.
7205 * Ideally, merged_paths would contain a list of commitables
7206 * we could use so we could skip worktree_status() entirely.
7207 * However, we would then need carefully keep track of cumulative
7208 * effects of operations such as file additions and deletions
7209 * in 'got histedit -f' (folding multiple commits into one),
7210 * and this extra complexity is not really worth it.
7213 struct got_pathlist_entry
*pe
;
7214 TAILQ_FOREACH(pe
, merged_paths
, entry
) {
7215 err
= worktree_status(worktree
, pe
->path
, fileindex
,
7216 repo
, collect_commitables
, &cc_arg
, NULL
, NULL
, 1,
7222 err
= worktree_status(worktree
, "", fileindex
, repo
,
7223 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
7228 if (TAILQ_EMPTY(&commitable_paths
)) {
7229 /* No-op change; commit will be elided. */
7230 err
= got_ref_delete(commit_ref
, repo
);
7233 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
7237 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
7241 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
7246 logmsg
= strdup(new_logmsg
);
7247 if (logmsg
== NULL
) {
7248 err
= got_error_from_errno("strdup");
7252 err
= got_object_commit_get_logmsg(&logmsg
, orig_commit
);
7257 /* NB: commit_worktree will call free(logmsg) */
7258 err
= commit_worktree(new_commit_id
, &commitable_paths
, head_commit_id
,
7259 NULL
, worktree
, got_object_commit_get_author(orig_commit
),
7260 committer
? committer
:
7261 got_object_commit_get_committer(orig_commit
), NULL
,
7262 collect_rebase_commit_msg
, logmsg
, rebase_status
, NULL
, repo
);
7266 err
= got_ref_change_ref(tmp_branch
, *new_commit_id
);
7270 err
= got_ref_delete(commit_ref
, repo
);
7274 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
7275 *new_commit_id
, fileindex
, 0);
7276 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7277 if (sync_err
&& err
== NULL
)
7280 free(fileindex_path
);
7281 free(head_commit_id
);
7283 got_ref_close(head_ref
);
7285 free(*new_commit_id
);
7286 *new_commit_id
= NULL
;
7291 const struct got_error
*
7292 got_worktree_rebase_commit(struct got_object_id
**new_commit_id
,
7293 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
7294 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7295 const char *committer
, struct got_commit_object
*orig_commit
,
7296 struct got_object_id
*orig_commit_id
, int allow_conflict
,
7297 struct got_repository
*repo
)
7299 const struct got_error
*err
;
7300 char *commit_ref_name
;
7301 struct got_reference
*commit_ref
= NULL
;
7302 struct got_object_id
*commit_id
= NULL
;
7304 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
7308 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7311 err
= got_ref_resolve(&commit_id
, repo
, commit_ref
);
7314 if (got_object_id_cmp(commit_id
, orig_commit_id
) != 0) {
7315 err
= got_error(GOT_ERR_REBASE_COMMITID
);
7319 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
7320 worktree
, fileindex
, tmp_branch
, committer
, orig_commit
,
7321 NULL
, allow_conflict
, repo
);
7324 got_ref_close(commit_ref
);
7325 free(commit_ref_name
);
7330 const struct got_error
*
7331 got_worktree_histedit_commit(struct got_object_id
**new_commit_id
,
7332 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
7333 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7334 const char *committer
, struct got_commit_object
*orig_commit
,
7335 struct got_object_id
*orig_commit_id
, const char *new_logmsg
,
7336 int allow_conflict
, struct got_repository
*repo
)
7338 const struct got_error
*err
;
7339 char *commit_ref_name
;
7340 struct got_reference
*commit_ref
= NULL
;
7342 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7346 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7350 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
7351 worktree
, fileindex
, tmp_branch
, committer
, orig_commit
,
7352 new_logmsg
, allow_conflict
, repo
);
7355 got_ref_close(commit_ref
);
7356 free(commit_ref_name
);
7360 const struct got_error
*
7361 got_worktree_rebase_postpone(struct got_worktree
*worktree
,
7362 struct got_fileindex
*fileindex
)
7365 got_fileindex_free(fileindex
);
7366 return lock_worktree(worktree
, LOCK_SH
);
7369 static const struct got_error
*
7370 delete_ref(const char *name
, struct got_repository
*repo
)
7372 const struct got_error
*err
;
7373 struct got_reference
*ref
;
7375 err
= got_ref_open(&ref
, repo
, name
, 0);
7377 if (err
->code
== GOT_ERR_NOT_REF
)
7382 err
= got_ref_delete(ref
, repo
);
7387 static const struct got_error
*
7388 delete_rebase_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7390 const struct got_error
*err
;
7391 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
7392 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
7394 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
7397 err
= delete_ref(tmp_branch_name
, repo
);
7401 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
7404 err
= delete_ref(new_base_branch_ref_name
, repo
);
7408 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
7411 err
= delete_ref(branch_ref_name
, repo
);
7415 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
7418 err
= delete_ref(commit_ref_name
, repo
);
7423 free(tmp_branch_name
);
7424 free(new_base_branch_ref_name
);
7425 free(branch_ref_name
);
7426 free(commit_ref_name
);
7430 static const struct got_error
*
7431 create_backup_ref(const char *backup_ref_prefix
, struct got_reference
*branch
,
7432 struct got_object_id
*new_commit_id
, struct got_repository
*repo
)
7434 const struct got_error
*err
;
7435 struct got_reference
*ref
= NULL
;
7436 struct got_object_id
*old_commit_id
= NULL
;
7437 const char *branch_name
= NULL
;
7438 char *new_id_str
= NULL
;
7439 char *refname
= NULL
;
7441 branch_name
= got_ref_get_name(branch
);
7442 if (strncmp(branch_name
, "refs/heads/", 11) != 0)
7443 return got_error(GOT_ERR_BAD_REF_NAME
); /* should not happen */
7446 err
= got_object_id_str(&new_id_str
, new_commit_id
);
7450 if (asprintf(&refname
, "%s/%s/%s", backup_ref_prefix
, branch_name
,
7451 new_id_str
) == -1) {
7452 err
= got_error_from_errno("asprintf");
7456 err
= got_ref_resolve(&old_commit_id
, repo
, branch
);
7460 err
= got_ref_alloc(&ref
, refname
, old_commit_id
);
7464 err
= got_ref_write(ref
, repo
);
7468 free(old_commit_id
);
7474 const struct got_error
*
7475 got_worktree_rebase_complete(struct got_worktree
*worktree
,
7476 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7477 struct got_reference
*rebased_branch
, struct got_repository
*repo
,
7480 const struct got_error
*err
, *unlockerr
, *sync_err
;
7481 struct got_object_id
*new_head_commit_id
= NULL
;
7482 char *fileindex_path
= NULL
;
7484 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
7488 if (create_backup
) {
7489 err
= create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX
,
7490 rebased_branch
, new_head_commit_id
, repo
);
7495 err
= got_ref_change_ref(rebased_branch
, new_head_commit_id
);
7499 err
= got_ref_write(rebased_branch
, repo
);
7503 err
= got_worktree_set_head_ref(worktree
, rebased_branch
);
7507 err
= delete_rebase_refs(worktree
, repo
);
7511 err
= get_fileindex_path(&fileindex_path
, worktree
);
7514 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7515 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7516 if (sync_err
&& err
== NULL
)
7519 got_fileindex_free(fileindex
);
7520 free(fileindex_path
);
7521 free(new_head_commit_id
);
7522 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7523 if (unlockerr
&& err
== NULL
)
7528 static const struct got_error
*
7529 get_paths_changed_between_commits(struct got_pathlist_head
*paths
,
7530 struct got_object_id
*id1
, struct got_object_id
*id2
,
7531 struct got_repository
*repo
)
7533 const struct got_error
*err
;
7534 struct got_commit_object
*commit1
= NULL
, *commit2
= NULL
;
7535 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
7538 err
= got_object_open_as_commit(&commit1
, repo
, id1
);
7542 err
= got_object_open_as_tree(&tree1
, repo
,
7543 got_object_commit_get_tree_id(commit1
));
7549 err
= got_object_open_as_commit(&commit2
, repo
, id2
);
7553 err
= got_object_open_as_tree(&tree2
, repo
,
7554 got_object_commit_get_tree_id(commit2
));
7559 err
= got_diff_tree(tree1
, tree2
, NULL
, NULL
, -1, -1, "", "", repo
,
7560 got_diff_tree_collect_changed_paths
, paths
, 0);
7565 got_object_commit_close(commit1
);
7567 got_object_commit_close(commit2
);
7569 got_object_tree_close(tree1
);
7571 got_object_tree_close(tree2
);
7575 static const struct got_error
*
7576 get_paths_added_between_commits(struct got_pathlist_head
*added_paths
,
7577 struct got_object_id
*id1
, struct got_object_id
*id2
,
7578 const char *path_prefix
, struct got_repository
*repo
)
7580 const struct got_error
*err
;
7581 struct got_pathlist_head merged_paths
;
7582 struct got_pathlist_entry
*pe
;
7583 char *abspath
= NULL
, *wt_path
= NULL
;
7585 TAILQ_INIT(&merged_paths
);
7587 err
= get_paths_changed_between_commits(&merged_paths
, id1
, id2
, repo
);
7591 TAILQ_FOREACH(pe
, &merged_paths
, entry
) {
7592 struct got_diff_changed_path
*change
= pe
->data
;
7594 if (change
->status
!= GOT_STATUS_ADD
)
7597 if (got_path_is_root_dir(path_prefix
)) {
7598 wt_path
= strdup(pe
->path
);
7599 if (wt_path
== NULL
) {
7600 err
= got_error_from_errno("strdup");
7604 if (asprintf(&abspath
, "/%s", pe
->path
) == -1) {
7605 err
= got_error_from_errno("asprintf");
7609 err
= got_path_skip_common_ancestor(&wt_path
,
7610 path_prefix
, abspath
);
7617 err
= got_pathlist_append(added_paths
, wt_path
, NULL
);
7624 got_pathlist_free(&merged_paths
, GOT_PATHLIST_FREE_ALL
);
7630 static const struct got_error
*
7631 get_paths_added_in_commit(struct got_pathlist_head
*added_paths
,
7632 struct got_object_id
*id
, const char *path_prefix
,
7633 struct got_repository
*repo
)
7635 const struct got_error
*err
;
7636 struct got_commit_object
*commit
= NULL
;
7637 struct got_object_qid
*pid
;
7639 err
= got_object_open_as_commit(&commit
, repo
, id
);
7643 pid
= STAILQ_FIRST(got_object_commit_get_parent_ids(commit
));
7645 err
= get_paths_added_between_commits(added_paths
,
7646 pid
? &pid
->id
: NULL
, id
, path_prefix
, repo
);
7651 got_object_commit_close(commit
);
7655 const struct got_error
*
7656 got_worktree_rebase_abort(struct got_worktree
*worktree
,
7657 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7658 struct got_reference
*new_base_branch
,
7659 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7661 const struct got_error
*err
, *unlockerr
, *sync_err
;
7662 struct got_reference
*resolved
= NULL
;
7663 struct got_object_id
*commit_id
= NULL
;
7664 struct got_object_id
*merged_commit_id
= NULL
;
7665 struct got_commit_object
*commit
= NULL
;
7666 char *fileindex_path
= NULL
;
7667 char *commit_ref_name
= NULL
;
7668 struct got_reference
*commit_ref
= NULL
;
7669 struct revert_file_args rfa
;
7670 struct got_object_id
*tree_id
= NULL
;
7671 struct got_pathlist_head added_paths
;
7673 TAILQ_INIT(&added_paths
);
7675 err
= lock_worktree(worktree
, LOCK_EX
);
7679 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
7683 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7687 err
= got_ref_resolve(&merged_commit_id
, repo
, commit_ref
);
7692 * Determine which files in added status can be safely removed
7693 * from disk while reverting changes in the work tree.
7694 * We want to avoid deleting unrelated files which were added by
7695 * the user for conflict resolution purposes.
7697 err
= get_paths_added_in_commit(&added_paths
, merged_commit_id
,
7698 got_worktree_get_path_prefix(worktree
), repo
);
7702 err
= got_ref_open(&resolved
, repo
,
7703 got_ref_get_symref_target(new_base_branch
), 0);
7707 err
= got_worktree_set_head_ref(worktree
, resolved
);
7712 * XXX commits to the base branch could have happened while
7713 * we were busy rebasing; should we store the original commit ID
7714 * when rebase begins and read it back here?
7716 err
= got_ref_resolve(&commit_id
, repo
, resolved
);
7720 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
7724 err
= got_object_open_as_commit(&commit
, repo
,
7725 worktree
->base_commit_id
);
7729 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
7730 worktree
->path_prefix
);
7734 err
= delete_rebase_refs(worktree
, repo
);
7738 err
= get_fileindex_path(&fileindex_path
, worktree
);
7742 rfa
.worktree
= worktree
;
7743 rfa
.fileindex
= fileindex
;
7744 rfa
.progress_cb
= progress_cb
;
7745 rfa
.progress_arg
= progress_arg
;
7746 rfa
.patch_cb
= NULL
;
7747 rfa
.patch_arg
= NULL
;
7749 rfa
.unlink_added_files
= 1;
7750 rfa
.added_files_to_unlink
= &added_paths
;
7751 err
= worktree_status(worktree
, "", fileindex
, repo
,
7752 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
7756 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7757 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7759 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7760 if (sync_err
&& err
== NULL
)
7763 got_pathlist_free(&added_paths
, GOT_PATHLIST_FREE_PATH
);
7764 got_ref_close(resolved
);
7767 free(merged_commit_id
);
7769 got_object_commit_close(commit
);
7771 got_fileindex_free(fileindex
);
7772 free(fileindex_path
);
7773 free(commit_ref_name
);
7775 got_ref_close(commit_ref
);
7777 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7778 if (unlockerr
&& err
== NULL
)
7783 const struct got_error
*
7784 got_worktree_histedit_prepare(struct got_reference
**tmp_branch
,
7785 struct got_reference
**branch_ref
, struct got_object_id
**base_commit_id
,
7786 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
7787 struct got_repository
*repo
)
7789 const struct got_error
*err
= NULL
;
7790 char *tmp_branch_name
= NULL
;
7791 char *branch_ref_name
= NULL
;
7792 char *base_commit_ref_name
= NULL
;
7793 char *fileindex_path
= NULL
;
7794 struct check_rebase_ok_arg ok_arg
;
7795 struct got_reference
*wt_branch
= NULL
;
7796 struct got_reference
*base_commit_ref
= NULL
;
7800 *base_commit_id
= NULL
;
7803 err
= lock_worktree(worktree
, LOCK_EX
);
7807 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7811 ok_arg
.worktree
= worktree
;
7813 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7818 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7822 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7826 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7831 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
7836 err
= got_ref_alloc_symref(branch_ref
, branch_ref_name
, wt_branch
);
7840 err
= got_ref_write(*branch_ref
, repo
);
7844 err
= got_ref_alloc(&base_commit_ref
, base_commit_ref_name
,
7845 worktree
->base_commit_id
);
7848 err
= got_ref_write(base_commit_ref
, repo
);
7851 *base_commit_id
= got_object_id_dup(worktree
->base_commit_id
);
7852 if (*base_commit_id
== NULL
) {
7853 err
= got_error_from_errno("got_object_id_dup");
7857 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
7858 worktree
->base_commit_id
);
7861 err
= got_ref_write(*tmp_branch
, repo
);
7865 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
7869 free(fileindex_path
);
7870 free(tmp_branch_name
);
7871 free(branch_ref_name
);
7872 free(base_commit_ref_name
);
7874 got_ref_close(wt_branch
);
7877 got_ref_close(*branch_ref
);
7881 got_ref_close(*tmp_branch
);
7884 free(*base_commit_id
);
7886 got_fileindex_free(*fileindex
);
7889 lock_worktree(worktree
, LOCK_SH
);
7894 const struct got_error
*
7895 got_worktree_histedit_postpone(struct got_worktree
*worktree
,
7896 struct got_fileindex
*fileindex
)
7899 got_fileindex_free(fileindex
);
7900 return lock_worktree(worktree
, LOCK_SH
);
7903 const struct got_error
*
7904 got_worktree_histedit_in_progress(int *in_progress
,
7905 struct got_worktree
*worktree
)
7907 const struct got_error
*err
;
7908 char *tmp_branch_name
= NULL
;
7910 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7914 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
7915 free(tmp_branch_name
);
7919 const struct got_error
*
7920 got_worktree_histedit_continue(struct got_object_id
**commit_id
,
7921 struct got_reference
**tmp_branch
, struct got_reference
**branch_ref
,
7922 struct got_object_id
**base_commit_id
, struct got_fileindex
**fileindex
,
7923 struct got_worktree
*worktree
, struct got_repository
*repo
)
7925 const struct got_error
*err
;
7926 char *commit_ref_name
= NULL
, *base_commit_ref_name
= NULL
;
7927 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
7928 struct got_reference
*commit_ref
= NULL
;
7929 struct got_reference
*base_commit_ref
= NULL
;
7930 char *fileindex_path
= NULL
;
7931 int have_staged_files
= 0;
7935 *base_commit_id
= NULL
;
7938 err
= lock_worktree(worktree
, LOCK_EX
);
7942 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7946 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
7947 &have_staged_files
);
7948 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7950 if (have_staged_files
) {
7951 err
= got_error(GOT_ERR_STAGED_PATHS
);
7955 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7959 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7963 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7967 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7972 err
= got_ref_open(branch_ref
, repo
, branch_ref_name
, 0);
7976 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7979 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
7983 err
= got_ref_open(&base_commit_ref
, repo
, base_commit_ref_name
, 0);
7986 err
= got_ref_resolve(base_commit_id
, repo
, base_commit_ref
);
7990 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
7994 free(commit_ref_name
);
7995 free(branch_ref_name
);
7996 free(fileindex_path
);
7998 got_ref_close(commit_ref
);
7999 if (base_commit_ref
)
8000 got_ref_close(base_commit_ref
);
8004 free(*base_commit_id
);
8005 *base_commit_id
= NULL
;
8007 got_ref_close(*tmp_branch
);
8011 got_fileindex_free(*fileindex
);
8014 lock_worktree(worktree
, LOCK_EX
);
8019 static const struct got_error
*
8020 delete_histedit_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
8022 const struct got_error
*err
;
8023 char *tmp_branch_name
= NULL
, *base_commit_ref_name
= NULL
;
8024 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
8026 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
8029 err
= delete_ref(tmp_branch_name
, repo
);
8033 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
8037 err
= delete_ref(base_commit_ref_name
, repo
);
8041 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
8044 err
= delete_ref(branch_ref_name
, repo
);
8048 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
8051 err
= delete_ref(commit_ref_name
, repo
);
8055 free(tmp_branch_name
);
8056 free(base_commit_ref_name
);
8057 free(branch_ref_name
);
8058 free(commit_ref_name
);
8062 const struct got_error
*
8063 got_worktree_histedit_abort(struct got_worktree
*worktree
,
8064 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
8065 struct got_reference
*branch
, struct got_object_id
*base_commit_id
,
8066 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
8068 const struct got_error
*err
, *unlockerr
, *sync_err
;
8069 struct got_reference
*resolved
= NULL
;
8070 char *fileindex_path
= NULL
;
8071 struct got_object_id
*merged_commit_id
= NULL
;
8072 struct got_commit_object
*commit
= NULL
;
8073 char *commit_ref_name
= NULL
;
8074 struct got_reference
*commit_ref
= NULL
;
8075 struct got_object_id
*tree_id
= NULL
;
8076 struct revert_file_args rfa
;
8077 struct got_pathlist_head added_paths
;
8079 TAILQ_INIT(&added_paths
);
8081 err
= lock_worktree(worktree
, LOCK_EX
);
8085 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
8089 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
8091 if (err
->code
!= GOT_ERR_NOT_REF
)
8093 /* Can happen on early abort due to invalid histedit script. */
8098 err
= got_ref_resolve(&merged_commit_id
, repo
, commit_ref
);
8103 * Determine which files in added status can be safely removed
8104 * from disk while reverting changes in the work tree.
8105 * We want to avoid deleting unrelated files added by the
8106 * user during conflict resolution or during histedit -e.
8108 err
= get_paths_added_in_commit(&added_paths
, merged_commit_id
,
8109 got_worktree_get_path_prefix(worktree
), repo
);
8114 err
= got_ref_open(&resolved
, repo
,
8115 got_ref_get_symref_target(branch
), 0);
8119 err
= got_worktree_set_head_ref(worktree
, resolved
);
8123 err
= got_worktree_set_base_commit_id(worktree
, repo
, base_commit_id
);
8127 err
= got_object_open_as_commit(&commit
, repo
,
8128 worktree
->base_commit_id
);
8132 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
8133 worktree
->path_prefix
);
8137 err
= delete_histedit_refs(worktree
, repo
);
8141 err
= get_fileindex_path(&fileindex_path
, worktree
);
8145 rfa
.worktree
= worktree
;
8146 rfa
.fileindex
= fileindex
;
8147 rfa
.progress_cb
= progress_cb
;
8148 rfa
.progress_arg
= progress_arg
;
8149 rfa
.patch_cb
= NULL
;
8150 rfa
.patch_arg
= NULL
;
8152 rfa
.unlink_added_files
= 1;
8153 rfa
.added_files_to_unlink
= &added_paths
;
8154 err
= worktree_status(worktree
, "", fileindex
, repo
,
8155 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
8159 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
8160 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
8162 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8163 if (sync_err
&& err
== NULL
)
8167 got_ref_close(resolved
);
8169 got_ref_close(commit_ref
);
8170 free(merged_commit_id
);
8172 free(fileindex_path
);
8173 free(commit_ref_name
);
8175 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8176 if (unlockerr
&& err
== NULL
)
8181 const struct got_error
*
8182 got_worktree_histedit_complete(struct got_worktree
*worktree
,
8183 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
8184 struct got_reference
*edited_branch
, struct got_repository
*repo
)
8186 const struct got_error
*err
, *unlockerr
, *sync_err
;
8187 struct got_object_id
*new_head_commit_id
= NULL
;
8188 struct got_reference
*resolved
= NULL
;
8189 char *fileindex_path
= NULL
;
8191 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
8195 err
= got_ref_open(&resolved
, repo
,
8196 got_ref_get_symref_target(edited_branch
), 0);
8200 err
= create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX
,
8201 resolved
, new_head_commit_id
, repo
);
8205 err
= got_ref_change_ref(resolved
, new_head_commit_id
);
8209 err
= got_ref_write(resolved
, repo
);
8213 err
= got_worktree_set_head_ref(worktree
, resolved
);
8217 err
= delete_histedit_refs(worktree
, repo
);
8221 err
= get_fileindex_path(&fileindex_path
, worktree
);
8224 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
8225 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8226 if (sync_err
&& err
== NULL
)
8229 got_fileindex_free(fileindex
);
8230 free(fileindex_path
);
8231 free(new_head_commit_id
);
8232 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8233 if (unlockerr
&& err
== NULL
)
8238 const struct got_error
*
8239 got_worktree_histedit_skip_commit(struct got_worktree
*worktree
,
8240 struct got_object_id
*commit_id
, struct got_repository
*repo
)
8242 const struct got_error
*err
;
8243 char *commit_ref_name
;
8245 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
8249 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
8253 err
= delete_ref(commit_ref_name
, repo
);
8255 free(commit_ref_name
);
8259 const struct got_error
*
8260 got_worktree_integrate_prepare(struct got_fileindex
**fileindex
,
8261 struct got_reference
**branch_ref
, struct got_reference
**base_branch_ref
,
8262 struct got_worktree
*worktree
, const char *refname
,
8263 struct got_repository
*repo
)
8265 const struct got_error
*err
= NULL
;
8266 char *fileindex_path
= NULL
;
8267 struct check_rebase_ok_arg ok_arg
;
8271 *base_branch_ref
= NULL
;
8273 err
= lock_worktree(worktree
, LOCK_EX
);
8277 if (strcmp(refname
, got_worktree_get_head_ref_name(worktree
)) == 0) {
8278 err
= got_error_msg(GOT_ERR_SAME_BRANCH
,
8279 "cannot integrate a branch into itself; "
8280 "update -b or different branch name required");
8284 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
8288 /* Preconditions are the same as for rebase. */
8289 ok_arg
.worktree
= worktree
;
8291 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
8296 err
= got_ref_open(branch_ref
, repo
, refname
, 1);
8300 err
= got_ref_open(base_branch_ref
, repo
,
8301 got_worktree_get_head_ref_name(worktree
), 1);
8305 got_ref_close(*branch_ref
);
8308 if (*base_branch_ref
) {
8309 got_ref_close(*base_branch_ref
);
8310 *base_branch_ref
= NULL
;
8313 got_fileindex_free(*fileindex
);
8316 lock_worktree(worktree
, LOCK_SH
);
8321 const struct got_error
*
8322 got_worktree_integrate_continue(struct got_worktree
*worktree
,
8323 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
8324 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
,
8325 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
8326 got_cancel_cb cancel_cb
, void *cancel_arg
)
8328 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8329 char *fileindex_path
= NULL
;
8330 struct got_object_id
*tree_id
= NULL
, *commit_id
= NULL
;
8331 struct got_commit_object
*commit
= NULL
;
8333 err
= get_fileindex_path(&fileindex_path
, worktree
);
8337 err
= got_ref_resolve(&commit_id
, repo
, branch_ref
);
8341 err
= got_object_open_as_commit(&commit
, repo
, commit_id
);
8345 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
8346 worktree
->path_prefix
);
8350 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
8354 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
, repo
,
8355 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
8359 err
= got_ref_change_ref(base_branch_ref
, commit_id
);
8363 err
= got_ref_write(base_branch_ref
, repo
);
8367 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
8369 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8370 if (sync_err
&& err
== NULL
)
8374 unlockerr
= got_ref_unlock(branch_ref
);
8375 if (unlockerr
&& err
== NULL
)
8377 got_ref_close(branch_ref
);
8379 unlockerr
= got_ref_unlock(base_branch_ref
);
8380 if (unlockerr
&& err
== NULL
)
8382 got_ref_close(base_branch_ref
);
8384 got_fileindex_free(fileindex
);
8385 free(fileindex_path
);
8388 got_object_commit_close(commit
);
8390 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8391 if (unlockerr
&& err
== NULL
)
8396 const struct got_error
*
8397 got_worktree_integrate_abort(struct got_worktree
*worktree
,
8398 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
8399 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
)
8401 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
8403 got_fileindex_free(fileindex
);
8405 err
= lock_worktree(worktree
, LOCK_SH
);
8407 unlockerr
= got_ref_unlock(branch_ref
);
8408 if (unlockerr
&& err
== NULL
)
8410 got_ref_close(branch_ref
);
8412 unlockerr
= got_ref_unlock(base_branch_ref
);
8413 if (unlockerr
&& err
== NULL
)
8415 got_ref_close(base_branch_ref
);
8420 const struct got_error
*
8421 got_worktree_merge_postpone(struct got_worktree
*worktree
,
8422 struct got_fileindex
*fileindex
)
8424 const struct got_error
*err
, *sync_err
;
8425 char *fileindex_path
= NULL
;
8427 err
= get_fileindex_path(&fileindex_path
, worktree
);
8431 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8433 err
= lock_worktree(worktree
, LOCK_SH
);
8434 if (sync_err
&& err
== NULL
)
8437 got_fileindex_free(fileindex
);
8438 free(fileindex_path
);
8442 static const struct got_error
*
8443 delete_merge_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
8445 const struct got_error
*err
;
8446 char *branch_refname
= NULL
, *commit_refname
= NULL
;
8448 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8451 err
= delete_ref(branch_refname
, repo
);
8455 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
8458 err
= delete_ref(commit_refname
, repo
);
8463 free(branch_refname
);
8464 free(commit_refname
);
8468 struct merge_commit_msg_arg
{
8469 struct got_worktree
*worktree
;
8470 const char *branch_name
;
8473 static const struct got_error
*
8474 merge_commit_msg_cb(struct got_pathlist_head
*commitable_paths
,
8475 const char *diff_path
, char **logmsg
, void *arg
)
8477 struct merge_commit_msg_arg
*a
= arg
;
8479 if (asprintf(logmsg
, "merge %s into %s\n", a
->branch_name
,
8480 got_worktree_get_head_ref_name(a
->worktree
)) == -1)
8481 return got_error_from_errno("asprintf");
8487 const struct got_error
*
8488 got_worktree_merge_branch(struct got_worktree
*worktree
,
8489 struct got_fileindex
*fileindex
,
8490 struct got_object_id
*yca_commit_id
,
8491 struct got_object_id
*branch_tip
,
8492 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
8493 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
8495 const struct got_error
*err
;
8496 char *fileindex_path
= NULL
;
8497 struct check_mixed_commits_args cma
;
8499 err
= get_fileindex_path(&fileindex_path
, worktree
);
8503 cma
.worktree
= worktree
;
8504 cma
.cancel_cb
= cancel_cb
;
8505 cma
.cancel_arg
= cancel_arg
;
8507 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
8512 err
= merge_files(worktree
, fileindex
, fileindex_path
, yca_commit_id
,
8513 branch_tip
, repo
, progress_cb
, progress_arg
,
8514 cancel_cb
, cancel_arg
);
8516 free(fileindex_path
);
8520 const struct got_error
*
8521 got_worktree_merge_commit(struct got_object_id
**new_commit_id
,
8522 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
8523 const char *author
, const char *committer
, int allow_bad_symlinks
,
8524 struct got_object_id
*branch_tip
, const char *branch_name
,
8525 int allow_conflict
, struct got_repository
*repo
,
8526 got_worktree_status_cb status_cb
, void *status_arg
)
8529 const struct got_error
*err
= NULL
, *sync_err
;
8530 struct got_pathlist_head commitable_paths
;
8531 struct collect_commitables_arg cc_arg
;
8532 struct got_pathlist_entry
*pe
;
8533 struct got_reference
*head_ref
= NULL
;
8534 struct got_object_id
*head_commit_id
= NULL
;
8535 int have_staged_files
= 0;
8536 struct merge_commit_msg_arg mcm_arg
;
8537 char *fileindex_path
= NULL
;
8539 memset(&cc_arg
, 0, sizeof(cc_arg
));
8540 *new_commit_id
= NULL
;
8542 TAILQ_INIT(&commitable_paths
);
8544 err
= get_fileindex_path(&fileindex_path
, worktree
);
8548 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
8552 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
8556 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
8557 &have_staged_files
);
8558 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
8560 if (have_staged_files
) {
8561 err
= got_error(GOT_ERR_MERGE_STAGED_PATHS
);
8565 cc_arg
.commitable_paths
= &commitable_paths
;
8566 cc_arg
.worktree
= worktree
;
8567 cc_arg
.fileindex
= fileindex
;
8569 cc_arg
.have_staged_files
= have_staged_files
;
8570 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
8571 cc_arg
.commit_conflicts
= allow_conflict
;
8572 err
= worktree_status(worktree
, "", fileindex
, repo
,
8573 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
8577 mcm_arg
.worktree
= worktree
;
8578 mcm_arg
.branch_name
= branch_name
;
8579 err
= commit_worktree(new_commit_id
, &commitable_paths
,
8580 head_commit_id
, branch_tip
, worktree
, author
, committer
, NULL
,
8581 merge_commit_msg_cb
, &mcm_arg
, status_cb
, status_arg
, repo
);
8585 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
8586 *new_commit_id
, fileindex
, have_staged_files
);
8587 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8588 if (sync_err
&& err
== NULL
)
8591 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
8592 struct got_commitable
*ct
= pe
->data
;
8594 free_commitable(ct
);
8596 got_pathlist_free(&commitable_paths
, GOT_PATHLIST_FREE_NONE
);
8597 free(fileindex_path
);
8601 const struct got_error
*
8602 got_worktree_merge_complete(struct got_worktree
*worktree
,
8603 struct got_fileindex
*fileindex
, struct got_repository
*repo
)
8605 const struct got_error
*err
, *unlockerr
, *sync_err
;
8606 char *fileindex_path
= NULL
;
8608 err
= delete_merge_refs(worktree
, repo
);
8612 err
= get_fileindex_path(&fileindex_path
, worktree
);
8615 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
8616 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8617 if (sync_err
&& err
== NULL
)
8620 got_fileindex_free(fileindex
);
8621 free(fileindex_path
);
8622 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8623 if (unlockerr
&& err
== NULL
)
8628 const struct got_error
*
8629 got_worktree_merge_in_progress(int *in_progress
, struct got_worktree
*worktree
,
8630 struct got_repository
*repo
)
8632 const struct got_error
*err
;
8633 char *branch_refname
= NULL
;
8634 struct got_reference
*branch_ref
= NULL
;
8638 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8641 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
8642 free(branch_refname
);
8644 if (err
->code
!= GOT_ERR_NOT_REF
)
8652 const struct got_error
*got_worktree_merge_prepare(
8653 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
8654 struct got_repository
*repo
)
8656 const struct got_error
*err
= NULL
;
8657 char *fileindex_path
= NULL
;
8658 struct got_reference
*wt_branch
= NULL
;
8659 struct got_object_id
*wt_branch_tip
= NULL
;
8660 struct check_rebase_ok_arg ok_arg
;
8664 err
= lock_worktree(worktree
, LOCK_EX
);
8668 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
8672 /* Preconditions are the same as for rebase. */
8673 ok_arg
.worktree
= worktree
;
8675 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
8680 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
8685 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
8689 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
8690 err
= got_error(GOT_ERR_MERGE_OUT_OF_DATE
);
8695 free(fileindex_path
);
8697 got_ref_close(wt_branch
);
8698 free(wt_branch_tip
);
8701 got_fileindex_free(*fileindex
);
8704 lock_worktree(worktree
, LOCK_SH
);
8709 const struct got_error
*got_worktree_merge_write_refs(
8710 struct got_worktree
*worktree
, struct got_reference
*branch
,
8711 struct got_repository
*repo
)
8713 const struct got_error
*err
= NULL
;
8714 char *branch_refname
= NULL
, *commit_refname
= NULL
;
8715 struct got_reference
*branch_ref
= NULL
, *commit_ref
= NULL
;
8716 struct got_object_id
*branch_tip
= NULL
;
8718 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8722 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
8726 err
= got_ref_resolve(&branch_tip
, repo
, branch
);
8730 err
= got_ref_alloc_symref(&branch_ref
, branch_refname
, branch
);
8733 err
= got_ref_write(branch_ref
, repo
);
8737 err
= got_ref_alloc(&commit_ref
, commit_refname
, branch_tip
);
8740 err
= got_ref_write(commit_ref
, repo
);
8745 free(branch_refname
);
8746 free(commit_refname
);
8748 got_ref_close(branch_ref
);
8750 got_ref_close(commit_ref
);
8755 const struct got_error
*
8756 got_worktree_merge_continue(char **branch_name
,
8757 struct got_object_id
**branch_tip
, struct got_fileindex
**fileindex
,
8758 struct got_worktree
*worktree
, struct got_repository
*repo
)
8760 const struct got_error
*err
;
8761 char *commit_refname
= NULL
, *branch_refname
= NULL
;
8762 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
8763 char *fileindex_path
= NULL
;
8764 int have_staged_files
= 0;
8766 *branch_name
= NULL
;
8770 err
= lock_worktree(worktree
, LOCK_EX
);
8774 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
8778 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
8779 &have_staged_files
);
8780 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
8782 if (have_staged_files
) {
8783 err
= got_error(GOT_ERR_STAGED_PATHS
);
8787 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8791 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
8795 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
8799 if (!got_ref_is_symbolic(branch_ref
)) {
8800 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
8801 "%s is not a symbolic reference",
8802 got_ref_get_name(branch_ref
));
8805 *branch_name
= strdup(got_ref_get_symref_target(branch_ref
));
8806 if (*branch_name
== NULL
) {
8807 err
= got_error_from_errno("strdup");
8811 err
= got_ref_open(&commit_ref
, repo
, commit_refname
, 0);
8815 err
= got_ref_resolve(branch_tip
, repo
, commit_ref
);
8819 free(commit_refname
);
8820 free(branch_refname
);
8821 free(fileindex_path
);
8823 got_ref_close(commit_ref
);
8825 got_ref_close(branch_ref
);
8829 *branch_name
= NULL
;
8834 got_fileindex_free(*fileindex
);
8837 lock_worktree(worktree
, LOCK_SH
);
8842 const struct got_error
*
8843 got_worktree_merge_abort(struct got_worktree
*worktree
,
8844 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
8845 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
8847 const struct got_error
*err
, *unlockerr
, *sync_err
;
8848 struct got_commit_object
*commit
= NULL
;
8849 char *fileindex_path
= NULL
;
8850 struct revert_file_args rfa
;
8851 char *commit_ref_name
= NULL
;
8852 struct got_reference
*commit_ref
= NULL
;
8853 struct got_object_id
*merged_commit_id
= NULL
;
8854 struct got_object_id
*tree_id
= NULL
;
8855 struct got_pathlist_head added_paths
;
8857 TAILQ_INIT(&added_paths
);
8859 err
= get_merge_commit_ref_name(&commit_ref_name
, worktree
);
8863 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
8867 err
= got_ref_resolve(&merged_commit_id
, repo
, commit_ref
);
8872 * Determine which files in added status can be safely removed
8873 * from disk while reverting changes in the work tree.
8874 * We want to avoid deleting unrelated files which were added by
8875 * the user for conflict resolution purposes.
8877 err
= get_paths_added_between_commits(&added_paths
,
8878 got_worktree_get_base_commit_id(worktree
), merged_commit_id
,
8879 got_worktree_get_path_prefix(worktree
), repo
);
8884 err
= got_object_open_as_commit(&commit
, repo
,
8885 worktree
->base_commit_id
);
8889 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
8890 worktree
->path_prefix
);
8894 err
= delete_merge_refs(worktree
, repo
);
8898 err
= get_fileindex_path(&fileindex_path
, worktree
);
8902 rfa
.worktree
= worktree
;
8903 rfa
.fileindex
= fileindex
;
8904 rfa
.progress_cb
= progress_cb
;
8905 rfa
.progress_arg
= progress_arg
;
8906 rfa
.patch_cb
= NULL
;
8907 rfa
.patch_arg
= NULL
;
8909 rfa
.unlink_added_files
= 1;
8910 rfa
.added_files_to_unlink
= &added_paths
;
8911 err
= worktree_status(worktree
, "", fileindex
, repo
,
8912 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
8916 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
8917 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
8919 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8920 if (sync_err
&& err
== NULL
)
8924 free(merged_commit_id
);
8926 got_object_commit_close(commit
);
8928 got_fileindex_free(fileindex
);
8929 free(fileindex_path
);
8931 got_ref_close(commit_ref
);
8932 free(commit_ref_name
);
8934 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8935 if (unlockerr
&& err
== NULL
)
8940 struct check_stage_ok_arg
{
8941 struct got_object_id
*head_commit_id
;
8942 struct got_worktree
*worktree
;
8943 struct got_fileindex
*fileindex
;
8944 struct got_repository
*repo
;
8948 static const struct got_error
*
8949 check_stage_ok(void *arg
, unsigned char status
,
8950 unsigned char staged_status
, const char *relpath
,
8951 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
8952 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
8954 struct check_stage_ok_arg
*a
= arg
;
8955 const struct got_error
*err
= NULL
;
8956 struct got_fileindex_entry
*ie
;
8957 struct got_object_id base_commit_id
;
8958 struct got_object_id
*base_commit_idp
= NULL
;
8959 char *in_repo_path
= NULL
, *p
;
8961 if (status
== GOT_STATUS_UNVERSIONED
||
8962 status
== GOT_STATUS_NO_CHANGE
)
8964 if (status
== GOT_STATUS_NONEXISTENT
)
8965 return got_error_set_errno(ENOENT
, relpath
);
8967 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8969 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8971 if (asprintf(&in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
8972 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
8974 return got_error_from_errno("asprintf");
8976 if (got_fileindex_entry_has_commit(ie
)) {
8977 base_commit_idp
= got_fileindex_entry_get_commit_id(
8978 &base_commit_id
, ie
);
8981 if (status
== GOT_STATUS_CONFLICT
) {
8982 err
= got_error_path(ie
->path
, GOT_ERR_STAGE_CONFLICT
);
8984 } else if (status
!= GOT_STATUS_ADD
&&
8985 status
!= GOT_STATUS_MODIFY
&&
8986 status
!= GOT_STATUS_DELETE
) {
8987 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STATUS
);
8991 a
->have_changes
= 1;
8996 err
= check_out_of_date(p
, status
, staged_status
,
8997 blob_id
, base_commit_idp
, a
->head_commit_id
, a
->repo
,
8998 GOT_ERR_STAGE_OUT_OF_DATE
);
9004 struct stage_path_arg
{
9005 struct got_worktree
*worktree
;
9006 struct got_fileindex
*fileindex
;
9007 struct got_repository
*repo
;
9008 got_worktree_status_cb status_cb
;
9010 got_worktree_patch_cb patch_cb
;
9012 int staged_something
;
9013 int allow_bad_symlinks
;
9016 static const struct got_error
*
9017 stage_path(void *arg
, unsigned char status
,
9018 unsigned char staged_status
, const char *relpath
,
9019 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
9020 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
9022 struct stage_path_arg
*a
= arg
;
9023 const struct got_error
*err
= NULL
;
9024 struct got_fileindex_entry
*ie
;
9025 char *ondisk_path
= NULL
, *path_content
= NULL
;
9027 struct got_object_id
*new_staged_blob_id
= NULL
;
9030 if (status
== GOT_STATUS_UNVERSIONED
)
9033 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
9035 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
9037 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
9039 return got_error_from_errno("asprintf");
9042 case GOT_STATUS_ADD
:
9043 case GOT_STATUS_MODIFY
:
9044 /* XXX could sb.st_mode be passed in by our caller? */
9045 if (lstat(ondisk_path
, &sb
) == -1) {
9046 err
= got_error_from_errno2("lstat", ondisk_path
);
9050 if (status
== GOT_STATUS_ADD
) {
9051 int choice
= GOT_PATCH_CHOICE_NONE
;
9052 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
9053 status
, ie
->path
, NULL
, 1, 1);
9056 if (choice
!= GOT_PATCH_CHOICE_YES
)
9059 err
= create_patched_content(&path_content
, 0,
9060 staged_blob_id
? staged_blob_id
: blob_id
,
9061 ondisk_path
, dirfd
, de_name
, ie
->path
,
9062 a
->repo
, a
->patch_cb
, a
->patch_arg
);
9063 if (err
|| path_content
== NULL
)
9067 err
= got_object_blob_create(&new_staged_blob_id
,
9068 path_content
? path_content
: ondisk_path
, a
->repo
);
9071 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
9072 SHA1_DIGEST_LENGTH
);
9073 if (status
== GOT_STATUS_ADD
|| staged_status
== GOT_STATUS_ADD
)
9074 stage
= GOT_FILEIDX_STAGE_ADD
;
9076 stage
= GOT_FILEIDX_STAGE_MODIFY
;
9077 got_fileindex_entry_stage_set(ie
, stage
);
9078 if (S_ISLNK(sb
.st_mode
)) {
9079 int is_bad_symlink
= 0;
9080 if (!a
->allow_bad_symlinks
) {
9081 char target_path
[PATH_MAX
];
9083 target_len
= readlink(ondisk_path
, target_path
,
9084 sizeof(target_path
));
9085 if (target_len
== -1) {
9086 err
= got_error_from_errno2("readlink",
9090 err
= is_bad_symlink_target(&is_bad_symlink
,
9091 target_path
, target_len
, ondisk_path
,
9092 a
->worktree
->root_path
,
9093 a
->worktree
->meta_dir
);
9096 if (is_bad_symlink
) {
9097 err
= got_error_path(ondisk_path
,
9098 GOT_ERR_BAD_SYMLINK
);
9103 got_fileindex_entry_staged_filetype_set(ie
,
9104 GOT_FILEIDX_MODE_BAD_SYMLINK
);
9106 got_fileindex_entry_staged_filetype_set(ie
,
9107 GOT_FILEIDX_MODE_SYMLINK
);
9109 got_fileindex_entry_staged_filetype_set(ie
,
9110 GOT_FILEIDX_MODE_REGULAR_FILE
);
9112 a
->staged_something
= 1;
9113 if (a
->status_cb
== NULL
)
9115 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
9116 get_staged_status(ie
), relpath
, blob_id
,
9117 new_staged_blob_id
, NULL
, dirfd
, de_name
);
9121 * When staging the reverse of the staged diff,
9122 * implicitly unstage the file.
9124 if (memcmp(ie
->staged_blob_sha1
, ie
->blob_sha1
,
9125 sizeof(ie
->blob_sha1
)) == 0) {
9126 got_fileindex_entry_stage_set(ie
,
9127 GOT_FILEIDX_STAGE_NONE
);
9130 case GOT_STATUS_DELETE
:
9131 if (staged_status
== GOT_STATUS_DELETE
)
9134 int choice
= GOT_PATCH_CHOICE_NONE
;
9135 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
, status
,
9136 ie
->path
, NULL
, 1, 1);
9139 if (choice
== GOT_PATCH_CHOICE_NO
)
9141 if (choice
!= GOT_PATCH_CHOICE_YES
) {
9142 err
= got_error(GOT_ERR_PATCH_CHOICE
);
9146 stage
= GOT_FILEIDX_STAGE_DELETE
;
9147 got_fileindex_entry_stage_set(ie
, stage
);
9148 a
->staged_something
= 1;
9149 if (a
->status_cb
== NULL
)
9151 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
9152 get_staged_status(ie
), relpath
, NULL
, NULL
, NULL
, dirfd
,
9155 case GOT_STATUS_NO_CHANGE
:
9157 case GOT_STATUS_CONFLICT
:
9158 err
= got_error_path(relpath
, GOT_ERR_STAGE_CONFLICT
);
9160 case GOT_STATUS_NONEXISTENT
:
9161 err
= got_error_set_errno(ENOENT
, relpath
);
9164 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
9168 if (path_content
&& unlink(path_content
) == -1 && err
== NULL
)
9169 err
= got_error_from_errno2("unlink", path_content
);
9172 free(new_staged_blob_id
);
9176 const struct got_error
*
9177 got_worktree_stage(struct got_worktree
*worktree
,
9178 struct got_pathlist_head
*paths
,
9179 got_worktree_status_cb status_cb
, void *status_arg
,
9180 got_worktree_patch_cb patch_cb
, void *patch_arg
,
9181 int allow_bad_symlinks
, struct got_repository
*repo
)
9183 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
9184 struct got_pathlist_entry
*pe
;
9185 struct got_fileindex
*fileindex
= NULL
;
9186 char *fileindex_path
= NULL
;
9187 struct got_reference
*head_ref
= NULL
;
9188 struct got_object_id
*head_commit_id
= NULL
;
9189 struct check_stage_ok_arg oka
;
9190 struct stage_path_arg spa
;
9192 err
= lock_worktree(worktree
, LOCK_EX
);
9196 err
= got_ref_open(&head_ref
, repo
,
9197 got_worktree_get_head_ref_name(worktree
), 0);
9200 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
9203 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
9207 /* Check pre-conditions before staging anything. */
9208 oka
.head_commit_id
= head_commit_id
;
9209 oka
.worktree
= worktree
;
9210 oka
.fileindex
= fileindex
;
9212 oka
.have_changes
= 0;
9213 TAILQ_FOREACH(pe
, paths
, entry
) {
9214 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
9215 check_stage_ok
, &oka
, NULL
, NULL
, 1, 0);
9219 if (!oka
.have_changes
) {
9220 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
9224 spa
.worktree
= worktree
;
9225 spa
.fileindex
= fileindex
;
9227 spa
.patch_cb
= patch_cb
;
9228 spa
.patch_arg
= patch_arg
;
9229 spa
.status_cb
= status_cb
;
9230 spa
.status_arg
= status_arg
;
9231 spa
.staged_something
= 0;
9232 spa
.allow_bad_symlinks
= allow_bad_symlinks
;
9233 TAILQ_FOREACH(pe
, paths
, entry
) {
9234 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
9235 stage_path
, &spa
, NULL
, NULL
, 1, 0);
9239 if (!spa
.staged_something
) {
9240 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
9244 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
9245 if (sync_err
&& err
== NULL
)
9249 got_ref_close(head_ref
);
9250 free(head_commit_id
);
9251 free(fileindex_path
);
9253 got_fileindex_free(fileindex
);
9254 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
9255 if (unlockerr
&& err
== NULL
)
9260 struct unstage_path_arg
{
9261 struct got_worktree
*worktree
;
9262 struct got_fileindex
*fileindex
;
9263 struct got_repository
*repo
;
9264 got_worktree_checkout_cb progress_cb
;
9266 got_worktree_patch_cb patch_cb
;
9270 static const struct got_error
*
9271 create_unstaged_content(char **path_unstaged_content
,
9272 char **path_new_staged_content
, struct got_object_id
*blob_id
,
9273 struct got_object_id
*staged_blob_id
, const char *relpath
,
9274 struct got_repository
*repo
,
9275 got_worktree_patch_cb patch_cb
, void *patch_arg
)
9277 const struct got_error
*err
, *free_err
;
9278 struct got_blob_object
*blob
= NULL
, *staged_blob
= NULL
;
9279 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
, *rejectfile
= NULL
;
9280 char *path1
= NULL
, *path2
= NULL
, *label1
= NULL
;
9281 struct got_diffreg_result
*diffreg_result
= NULL
;
9282 int line_cur1
= 1, line_cur2
= 1, n
= 0, nchunks_used
= 0;
9283 int have_content
= 0, have_rejected_content
= 0, i
= 0, nchanges
= 0;
9284 int fd1
= -1, fd2
= -1;
9286 *path_unstaged_content
= NULL
;
9287 *path_new_staged_content
= NULL
;
9289 err
= got_object_id_str(&label1
, blob_id
);
9293 fd1
= got_opentempfd();
9295 err
= got_error_from_errno("got_opentempfd");
9298 fd2
= got_opentempfd();
9300 err
= got_error_from_errno("got_opentempfd");
9304 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192, fd1
);
9308 err
= got_opentemp_named(&path1
, &f1
, "got-unstage-blob-base", "");
9312 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
9316 err
= got_object_open_as_blob(&staged_blob
, repo
, staged_blob_id
, 8192,
9321 err
= got_opentemp_named(&path2
, &f2
, "got-unstage-blob-staged", "");
9325 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f2
, staged_blob
);
9329 err
= got_diff_files(&diffreg_result
, f1
, 1, label1
, f2
, 1,
9330 path2
, 3, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
9334 err
= got_opentemp_named(path_unstaged_content
, &outfile
,
9335 "got-unstaged-content", "");
9338 err
= got_opentemp_named(path_new_staged_content
, &rejectfile
,
9339 "got-new-staged-content", "");
9343 if (fseek(f1
, 0L, SEEK_SET
) == -1) {
9344 err
= got_ferror(f1
, GOT_ERR_IO
);
9347 if (fseek(f2
, 0L, SEEK_SET
) == -1) {
9348 err
= got_ferror(f2
, GOT_ERR_IO
);
9351 /* Count the number of actual changes in the diff result. */
9352 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
9353 struct diff_chunk_context cc
= {};
9354 diff_chunk_context_load_change(&cc
, &nchunks_used
,
9355 diffreg_result
->result
, n
, 0);
9358 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
9360 err
= apply_or_reject_change(&choice
, &nchunks_used
,
9361 diffreg_result
->result
, n
, relpath
, f1
, f2
,
9362 &line_cur1
, &line_cur2
,
9363 outfile
, rejectfile
, ++i
, nchanges
, patch_cb
, patch_arg
);
9366 if (choice
== GOT_PATCH_CHOICE_YES
)
9369 have_rejected_content
= 1;
9370 if (choice
== GOT_PATCH_CHOICE_QUIT
)
9373 if (have_content
|| have_rejected_content
)
9374 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
9375 outfile
, rejectfile
);
9378 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
9379 err
= got_error_from_errno("close");
9381 got_object_blob_close(blob
);
9382 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
9383 err
= got_error_from_errno("close");
9385 got_object_blob_close(staged_blob
);
9386 free_err
= got_diffreg_result_free(diffreg_result
);
9387 if (free_err
&& err
== NULL
)
9389 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
9390 err
= got_error_from_errno2("fclose", path1
);
9391 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
9392 err
= got_error_from_errno2("fclose", path2
);
9393 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
9394 err
= got_error_from_errno2("fclose", *path_unstaged_content
);
9395 if (rejectfile
&& fclose(rejectfile
) == EOF
&& err
== NULL
)
9396 err
= got_error_from_errno2("fclose", *path_new_staged_content
);
9397 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
9398 err
= got_error_from_errno2("unlink", path1
);
9399 if (path2
&& unlink(path2
) == -1 && err
== NULL
)
9400 err
= got_error_from_errno2("unlink", path2
);
9401 if (err
|| !have_content
) {
9402 if (*path_unstaged_content
&&
9403 unlink(*path_unstaged_content
) == -1 && err
== NULL
)
9404 err
= got_error_from_errno2("unlink",
9405 *path_unstaged_content
);
9406 free(*path_unstaged_content
);
9407 *path_unstaged_content
= NULL
;
9409 if (err
|| !have_content
|| !have_rejected_content
) {
9410 if (*path_new_staged_content
&&
9411 unlink(*path_new_staged_content
) == -1 && err
== NULL
)
9412 err
= got_error_from_errno2("unlink",
9413 *path_new_staged_content
);
9414 free(*path_new_staged_content
);
9415 *path_new_staged_content
= NULL
;
9422 static const struct got_error
*
9423 unstage_hunks(struct got_object_id
*staged_blob_id
,
9424 struct got_blob_object
*blob_base
,
9425 struct got_object_id
*blob_id
, struct got_fileindex_entry
*ie
,
9426 const char *ondisk_path
, const char *label_orig
,
9427 struct got_worktree
*worktree
, struct got_repository
*repo
,
9428 got_worktree_patch_cb patch_cb
, void *patch_arg
,
9429 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
9431 const struct got_error
*err
= NULL
;
9432 char *path_unstaged_content
= NULL
;
9433 char *path_new_staged_content
= NULL
;
9434 char *parent
= NULL
, *base_path
= NULL
;
9435 char *blob_base_path
= NULL
;
9436 struct got_object_id
*new_staged_blob_id
= NULL
;
9437 FILE *f
= NULL
, *f_base
= NULL
, *f_deriv2
= NULL
;
9440 err
= create_unstaged_content(&path_unstaged_content
,
9441 &path_new_staged_content
, blob_id
, staged_blob_id
,
9442 ie
->path
, repo
, patch_cb
, patch_arg
);
9446 if (path_unstaged_content
== NULL
)
9449 if (path_new_staged_content
) {
9450 err
= got_object_blob_create(&new_staged_blob_id
,
9451 path_new_staged_content
, repo
);
9456 f
= fopen(path_unstaged_content
, "re");
9458 err
= got_error_from_errno2("fopen",
9459 path_unstaged_content
);
9462 if (fstat(fileno(f
), &sb
) == -1) {
9463 err
= got_error_from_errno2("fstat", path_unstaged_content
);
9466 if (got_fileindex_entry_staged_filetype_get(ie
) ==
9467 GOT_FILEIDX_MODE_SYMLINK
&& sb
.st_size
< PATH_MAX
) {
9468 char link_target
[PATH_MAX
];
9470 r
= fread(link_target
, 1, sizeof(link_target
), f
);
9471 if (r
== 0 && ferror(f
)) {
9472 err
= got_error_from_errno("fread");
9475 if (r
>= sizeof(link_target
)) { /* should not happen */
9476 err
= got_error(GOT_ERR_NO_SPACE
);
9479 link_target
[r
] = '\0';
9480 err
= merge_symlink(worktree
, blob_base
,
9481 ondisk_path
, ie
->path
, label_orig
, link_target
,
9482 worktree
->base_commit_id
, repo
, progress_cb
,
9485 int local_changes_subsumed
;
9487 err
= got_path_dirname(&parent
, ondisk_path
);
9491 if (asprintf(&base_path
, "%s/got-unstage-blob-orig",
9493 err
= got_error_from_errno("asprintf");
9498 err
= got_opentemp_named(&blob_base_path
, &f_base
,
9502 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_base
,
9508 * In order the run a 3-way merge with a symlink we copy the symlink's
9509 * target path into a temporary file and use that file with diff3.
9511 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
9512 err
= dump_symlink_target_path_to_file(&f_deriv2
,
9518 fd
= open(ondisk_path
,
9519 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
9521 err
= got_error_from_errno2("open", ondisk_path
);
9524 f_deriv2
= fdopen(fd
, "r");
9525 if (f_deriv2
== NULL
) {
9526 err
= got_error_from_errno2("fdopen", ondisk_path
);
9532 err
= merge_file(&local_changes_subsumed
, worktree
,
9533 f_base
, f
, f_deriv2
, ondisk_path
, ie
->path
,
9534 got_fileindex_perms_to_st(ie
),
9535 label_orig
, "unstaged", NULL
, GOT_DIFF_ALGORITHM_MYERS
,
9536 repo
, progress_cb
, progress_arg
);
9541 if (new_staged_blob_id
) {
9542 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
9543 SHA1_DIGEST_LENGTH
);
9545 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
9546 got_fileindex_entry_staged_filetype_set(ie
, 0);
9549 free(new_staged_blob_id
);
9550 if (path_unstaged_content
&&
9551 unlink(path_unstaged_content
) == -1 && err
== NULL
)
9552 err
= got_error_from_errno2("unlink", path_unstaged_content
);
9553 if (path_new_staged_content
&&
9554 unlink(path_new_staged_content
) == -1 && err
== NULL
)
9555 err
= got_error_from_errno2("unlink", path_new_staged_content
);
9556 if (blob_base_path
&& unlink(blob_base_path
) == -1 && err
== NULL
)
9557 err
= got_error_from_errno2("unlink", blob_base_path
);
9558 if (f_base
&& fclose(f_base
) == EOF
&& err
== NULL
)
9559 err
= got_error_from_errno2("fclose", path_unstaged_content
);
9560 if (f
&& fclose(f
) == EOF
&& err
== NULL
)
9561 err
= got_error_from_errno2("fclose", path_unstaged_content
);
9562 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
9563 err
= got_error_from_errno2("fclose", ondisk_path
);
9564 free(path_unstaged_content
);
9565 free(path_new_staged_content
);
9566 free(blob_base_path
);
9572 static const struct got_error
*
9573 unstage_path(void *arg
, unsigned char status
,
9574 unsigned char staged_status
, const char *relpath
,
9575 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
9576 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
9578 const struct got_error
*err
= NULL
;
9579 struct unstage_path_arg
*a
= arg
;
9580 struct got_fileindex_entry
*ie
;
9581 struct got_blob_object
*blob_base
= NULL
, *blob_staged
= NULL
;
9582 char *ondisk_path
= NULL
;
9583 char *id_str
= NULL
, *label_orig
= NULL
;
9584 int local_changes_subsumed
;
9586 int fd1
= -1, fd2
= -1;
9588 if (staged_status
!= GOT_STATUS_ADD
&&
9589 staged_status
!= GOT_STATUS_MODIFY
&&
9590 staged_status
!= GOT_STATUS_DELETE
)
9593 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
9595 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
9597 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, relpath
)
9599 return got_error_from_errno("asprintf");
9601 err
= got_object_id_str(&id_str
,
9602 commit_id
? commit_id
: a
->worktree
->base_commit_id
);
9605 if (asprintf(&label_orig
, "%s: commit %s", GOT_MERGE_LABEL_BASE
,
9607 err
= got_error_from_errno("asprintf");
9611 fd1
= got_opentempfd();
9613 err
= got_error_from_errno("got_opentempfd");
9616 fd2
= got_opentempfd();
9618 err
= got_error_from_errno("got_opentempfd");
9622 switch (staged_status
) {
9623 case GOT_STATUS_MODIFY
:
9624 err
= got_object_open_as_blob(&blob_base
, a
->repo
,
9625 blob_id
, 8192, fd1
);
9629 case GOT_STATUS_ADD
:
9631 if (staged_status
== GOT_STATUS_ADD
) {
9632 int choice
= GOT_PATCH_CHOICE_NONE
;
9633 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
9634 staged_status
, ie
->path
, NULL
, 1, 1);
9637 if (choice
!= GOT_PATCH_CHOICE_YES
)
9640 err
= unstage_hunks(staged_blob_id
,
9641 blob_base
, blob_id
, ie
, ondisk_path
,
9642 label_orig
, a
->worktree
, a
->repo
,
9643 a
->patch_cb
, a
->patch_arg
,
9644 a
->progress_cb
, a
->progress_arg
);
9645 break; /* Done with this file. */
9648 err
= got_object_open_as_blob(&blob_staged
, a
->repo
,
9649 staged_blob_id
, 8192, fd2
);
9652 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
9653 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
9654 case GOT_FILEIDX_MODE_REGULAR_FILE
:
9655 err
= merge_blob(&local_changes_subsumed
, a
->worktree
,
9656 blob_base
, ondisk_path
, relpath
,
9657 got_fileindex_perms_to_st(ie
), label_orig
,
9658 blob_staged
, commit_id
? commit_id
:
9659 a
->worktree
->base_commit_id
, a
->repo
,
9660 a
->progress_cb
, a
->progress_arg
);
9662 case GOT_FILEIDX_MODE_SYMLINK
:
9663 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
9664 char *staged_target
;
9665 err
= got_object_blob_read_to_str(
9666 &staged_target
, blob_staged
);
9669 err
= merge_symlink(a
->worktree
, blob_base
,
9670 ondisk_path
, relpath
, label_orig
,
9671 staged_target
, commit_id
? commit_id
:
9672 a
->worktree
->base_commit_id
,
9673 a
->repo
, a
->progress_cb
, a
->progress_arg
);
9674 free(staged_target
);
9676 err
= merge_blob(&local_changes_subsumed
,
9677 a
->worktree
, blob_base
, ondisk_path
,
9678 relpath
, got_fileindex_perms_to_st(ie
),
9679 label_orig
, blob_staged
,
9680 commit_id
? commit_id
:
9681 a
->worktree
->base_commit_id
, a
->repo
,
9682 a
->progress_cb
, a
->progress_arg
);
9686 err
= got_error_path(relpath
, GOT_ERR_BAD_FILETYPE
);
9690 got_fileindex_entry_stage_set(ie
,
9691 GOT_FILEIDX_STAGE_NONE
);
9692 got_fileindex_entry_staged_filetype_set(ie
, 0);
9695 case GOT_STATUS_DELETE
:
9697 int choice
= GOT_PATCH_CHOICE_NONE
;
9698 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
9699 staged_status
, ie
->path
, NULL
, 1, 1);
9702 if (choice
== GOT_PATCH_CHOICE_NO
)
9704 if (choice
!= GOT_PATCH_CHOICE_YES
) {
9705 err
= got_error(GOT_ERR_PATCH_CHOICE
);
9709 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
9710 got_fileindex_entry_staged_filetype_set(ie
, 0);
9711 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
9712 dirfd
, de_name
, a
->repo
);
9715 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, relpath
);
9720 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
9721 err
= got_error_from_errno("close");
9723 got_object_blob_close(blob_base
);
9724 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
9725 err
= got_error_from_errno("close");
9727 got_object_blob_close(blob_staged
);
9733 const struct got_error
*
9734 got_worktree_unstage(struct got_worktree
*worktree
,
9735 struct got_pathlist_head
*paths
,
9736 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
9737 got_worktree_patch_cb patch_cb
, void *patch_arg
,
9738 struct got_repository
*repo
)
9740 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
9741 struct got_pathlist_entry
*pe
;
9742 struct got_fileindex
*fileindex
= NULL
;
9743 char *fileindex_path
= NULL
;
9744 struct unstage_path_arg upa
;
9746 err
= lock_worktree(worktree
, LOCK_EX
);
9750 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
9754 upa
.worktree
= worktree
;
9755 upa
.fileindex
= fileindex
;
9757 upa
.progress_cb
= progress_cb
;
9758 upa
.progress_arg
= progress_arg
;
9759 upa
.patch_cb
= patch_cb
;
9760 upa
.patch_arg
= patch_arg
;
9761 TAILQ_FOREACH(pe
, paths
, entry
) {
9762 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
9763 unstage_path
, &upa
, NULL
, NULL
, 1, 0);
9768 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
9769 if (sync_err
&& err
== NULL
)
9772 free(fileindex_path
);
9774 got_fileindex_free(fileindex
);
9775 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
9776 if (unlockerr
&& err
== NULL
)
9781 struct report_file_info_arg
{
9782 struct got_worktree
*worktree
;
9783 got_worktree_path_info_cb info_cb
;
9785 struct got_pathlist_head
*paths
;
9786 got_cancel_cb cancel_cb
;
9790 static const struct got_error
*
9791 report_file_info(void *arg
, struct got_fileindex_entry
*ie
)
9793 const struct got_error
*err
;
9794 struct report_file_info_arg
*a
= arg
;
9795 struct got_pathlist_entry
*pe
;
9796 struct got_object_id blob_id
, staged_blob_id
, commit_id
;
9797 struct got_object_id
*blob_idp
= NULL
, *staged_blob_idp
= NULL
;
9798 struct got_object_id
*commit_idp
= NULL
;
9802 err
= a
->cancel_cb(a
->cancel_arg
);
9807 TAILQ_FOREACH(pe
, a
->paths
, entry
) {
9808 if (pe
->path_len
== 0 || strcmp(pe
->path
, ie
->path
) == 0 ||
9809 got_path_is_child(ie
->path
, pe
->path
, pe
->path_len
))
9812 if (pe
== NULL
) /* not found */
9815 if (got_fileindex_entry_has_blob(ie
))
9816 blob_idp
= got_fileindex_entry_get_blob_id(&blob_id
, ie
);
9817 stage
= got_fileindex_entry_stage_get(ie
);
9818 if (stage
== GOT_FILEIDX_STAGE_MODIFY
||
9819 stage
== GOT_FILEIDX_STAGE_ADD
) {
9820 staged_blob_idp
= got_fileindex_entry_get_staged_blob_id(
9821 &staged_blob_id
, ie
);
9824 if (got_fileindex_entry_has_commit(ie
))
9825 commit_idp
= got_fileindex_entry_get_commit_id(&commit_id
, ie
);
9827 return a
->info_cb(a
->info_arg
, ie
->path
, got_fileindex_perms_to_st(ie
),
9828 (time_t)ie
->mtime_sec
, blob_idp
, staged_blob_idp
, commit_idp
);
9831 const struct got_error
*
9832 got_worktree_path_info(struct got_worktree
*worktree
,
9833 struct got_pathlist_head
*paths
,
9834 got_worktree_path_info_cb info_cb
, void *info_arg
,
9835 got_cancel_cb cancel_cb
, void *cancel_arg
)
9838 const struct got_error
*err
= NULL
, *unlockerr
;
9839 struct got_fileindex
*fileindex
= NULL
;
9840 char *fileindex_path
= NULL
;
9841 struct report_file_info_arg arg
;
9843 err
= lock_worktree(worktree
, LOCK_SH
);
9847 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
9851 arg
.worktree
= worktree
;
9852 arg
.info_cb
= info_cb
;
9853 arg
.info_arg
= info_arg
;
9855 arg
.cancel_cb
= cancel_cb
;
9856 arg
.cancel_arg
= cancel_arg
;
9857 err
= got_fileindex_for_each_entry_safe(fileindex
, report_file_info
,
9860 free(fileindex_path
);
9862 got_fileindex_free(fileindex
);
9863 unlockerr
= lock_worktree(worktree
, LOCK_UN
);
9864 if (unlockerr
&& err
== NULL
)
9869 static const struct got_error
*
9870 patch_check_path(const char *p
, char **path
, unsigned char *status
,
9871 unsigned char *staged_status
, struct got_fileindex
*fileindex
,
9872 struct got_worktree
*worktree
, struct got_repository
*repo
)
9874 const struct got_error
*err
;
9875 struct got_fileindex_entry
*ie
;
9877 char *ondisk_path
= NULL
;
9879 err
= got_worktree_resolve_path(path
, worktree
, p
);
9883 if (asprintf(&ondisk_path
, "%s%s%s", worktree
->root_path
,
9884 *path
[0] ? "/" : "", *path
) == -1)
9885 return got_error_from_errno("asprintf");
9887 ie
= got_fileindex_entry_get(fileindex
, *path
, strlen(*path
));
9889 *staged_status
= get_staged_status(ie
);
9890 err
= get_file_status(status
, &sb
, ie
, ondisk_path
, -1, NULL
,
9895 *staged_status
= GOT_STATUS_NO_CHANGE
;
9896 *status
= GOT_STATUS_UNVERSIONED
;
9897 if (lstat(ondisk_path
, &sb
) == -1) {
9898 if (errno
!= ENOENT
) {
9899 err
= got_error_from_errno2("lstat",
9903 *status
= GOT_STATUS_NONEXISTENT
;
9912 static const struct got_error
*
9913 patch_can_rm(const char *path
, unsigned char status
,
9914 unsigned char staged_status
)
9916 if (status
== GOT_STATUS_NONEXISTENT
)
9917 return got_error_set_errno(ENOENT
, path
);
9918 if (status
!= GOT_STATUS_NO_CHANGE
&&
9919 status
!= GOT_STATUS_ADD
&&
9920 status
!= GOT_STATUS_MODIFY
&&
9921 status
!= GOT_STATUS_MODE_CHANGE
)
9922 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9923 if (staged_status
== GOT_STATUS_DELETE
)
9924 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9928 static const struct got_error
*
9929 patch_can_add(const char *path
, unsigned char status
)
9931 if (status
!= GOT_STATUS_NONEXISTENT
)
9932 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9936 static const struct got_error
*
9937 patch_can_edit(const char *path
, unsigned char status
,
9938 unsigned char staged_status
)
9940 if (status
== GOT_STATUS_NONEXISTENT
)
9941 return got_error_set_errno(ENOENT
, path
);
9942 if (status
!= GOT_STATUS_NO_CHANGE
&&
9943 status
!= GOT_STATUS_ADD
&&
9944 status
!= GOT_STATUS_MODIFY
)
9945 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9946 if (staged_status
== GOT_STATUS_DELETE
)
9947 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9951 const struct got_error
*
9952 got_worktree_patch_prepare(struct got_fileindex
**fileindex
,
9953 char **fileindex_path
, struct got_worktree
*worktree
)
9955 return open_fileindex(fileindex
, fileindex_path
, worktree
);
9958 const struct got_error
*
9959 got_worktree_patch_check_path(const char *old
, const char *new,
9960 char **oldpath
, char **newpath
, struct got_worktree
*worktree
,
9961 struct got_repository
*repo
, struct got_fileindex
*fileindex
)
9963 const struct got_error
*err
= NULL
;
9964 int file_renamed
= 0;
9965 unsigned char status_old
, staged_status_old
;
9966 unsigned char status_new
, staged_status_new
;
9971 err
= patch_check_path(old
!= NULL
? old
: new, oldpath
,
9972 &status_old
, &staged_status_old
, fileindex
, worktree
, repo
);
9976 err
= patch_check_path(new != NULL
? new : old
, newpath
,
9977 &status_new
, &staged_status_new
, fileindex
, worktree
, repo
);
9981 if (old
!= NULL
&& new != NULL
&& strcmp(old
, new) != 0)
9984 if (old
!= NULL
&& new == NULL
)
9985 err
= patch_can_rm(*oldpath
, status_old
, staged_status_old
);
9986 else if (file_renamed
) {
9987 err
= patch_can_rm(*oldpath
, status_old
, staged_status_old
);
9989 err
= patch_can_add(*newpath
, status_new
);
9990 } else if (old
== NULL
)
9991 err
= patch_can_add(*newpath
, status_new
);
9993 err
= patch_can_edit(*newpath
, status_new
, staged_status_new
);
10005 const struct got_error
*
10006 got_worktree_patch_schedule_add(const char *path
, struct got_repository
*repo
,
10007 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
10008 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
10010 struct schedule_addition_args saa
;
10012 memset(&saa
, 0, sizeof(saa
));
10013 saa
.worktree
= worktree
;
10014 saa
.fileindex
= fileindex
;
10015 saa
.progress_cb
= progress_cb
;
10016 saa
.progress_arg
= progress_arg
;
10019 return worktree_status(worktree
, path
, fileindex
, repo
,
10020 schedule_addition
, &saa
, NULL
, NULL
, 1, 0);
10023 const struct got_error
*
10024 got_worktree_patch_schedule_rm(const char *path
, struct got_repository
*repo
,
10025 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
10026 got_worktree_delete_cb progress_cb
, void *progress_arg
)
10028 const struct got_error
*err
;
10029 struct schedule_deletion_args sda
;
10030 char *ondisk_status_path
;
10032 memset(&sda
, 0, sizeof(sda
));
10033 sda
.worktree
= worktree
;
10034 sda
.fileindex
= fileindex
;
10035 sda
.progress_cb
= progress_cb
;
10036 sda
.progress_arg
= progress_arg
;
10038 sda
.delete_local_mods
= 0;
10039 sda
.keep_on_disk
= 0;
10040 sda
.ignore_missing_paths
= 0;
10041 sda
.status_codes
= NULL
;
10042 if (asprintf(&ondisk_status_path
, "%s/%s",
10043 got_worktree_get_root_path(worktree
), path
) == -1)
10044 return got_error_from_errno("asprintf");
10045 sda
.status_path
= ondisk_status_path
;
10046 sda
.status_path_len
= strlen(ondisk_status_path
);
10048 err
= worktree_status(worktree
, path
, fileindex
, repo
,
10049 schedule_for_deletion
, &sda
, NULL
, NULL
, 1, 1);
10050 free(ondisk_status_path
);
10054 const struct got_error
*
10055 got_worktree_patch_complete(struct got_fileindex
*fileindex
,
10056 const char *fileindex_path
)
10058 const struct got_error
*err
= NULL
;
10060 err
= sync_fileindex(fileindex
, fileindex_path
);
10061 got_fileindex_free(fileindex
);