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.
18 #include <sys/queue.h>
34 #include "got_compat.h"
36 #include "got_error.h"
37 #include "got_repository.h"
38 #include "got_reference.h"
39 #include "got_object.h"
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_sha1.h"
48 #include "got_lib_fileindex.h"
49 #include "got_lib_inflate.h"
50 #include "got_lib_delta.h"
51 #include "got_lib_object.h"
52 #include "got_lib_object_parse.h"
53 #include "got_lib_object_create.h"
54 #include "got_lib_object_idset.h"
55 #include "got_lib_diff.h"
56 #include "got_lib_gotconfig.h"
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"
65 static mode_t
apply_umask(mode_t
);
67 static const struct got_error
*
68 create_meta_file(const char *path_got
, const char *name
, const char *content
)
70 const struct got_error
*err
= NULL
;
73 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1)
74 return got_error_from_errno("asprintf");
76 err
= got_path_create_file(path
, content
);
81 static const struct got_error
*
82 update_meta_file(const char *path_got
, const char *name
, const char *content
)
84 const struct got_error
*err
= NULL
;
89 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1) {
90 err
= got_error_from_errno("asprintf");
95 err
= got_opentemp_named(&tmppath
, &tmpfile
, path
, "");
100 int len
= fprintf(tmpfile
, "%s\n", content
);
101 if (len
!= strlen(content
) + 1) {
102 err
= got_error_from_errno2("fprintf", tmppath
);
107 if (rename(tmppath
, path
) != 0) {
108 err
= got_error_from_errno3("rename", tmppath
, path
);
114 if (fclose(tmpfile
) == EOF
&& err
== NULL
)
115 err
= got_error_from_errno2("fclose", tmppath
);
120 static const struct got_error
*
121 write_head_ref(const char *path_got
, struct got_reference
*head_ref
)
123 const struct got_error
*err
= NULL
;
126 if (got_ref_is_symbolic(head_ref
)) {
127 refstr
= got_ref_to_str(head_ref
);
129 return got_error_from_errno("got_ref_to_str");
131 refstr
= strdup(got_ref_get_name(head_ref
));
133 return got_error_from_errno("strdup");
135 err
= update_meta_file(path_got
, GOT_WORKTREE_HEAD_REF
, refstr
);
140 const struct got_error
*
141 got_worktree_init(const char *path
, struct got_reference
*head_ref
,
142 const char *prefix
, struct got_repository
*repo
)
144 const struct got_error
*err
= NULL
;
145 struct got_object_id
*commit_id
= NULL
;
147 uint32_t uuid_status
;
149 char *path_got
= NULL
;
150 char *formatstr
= NULL
;
151 char *absprefix
= NULL
;
152 char *basestr
= NULL
;
153 char *uuidstr
= NULL
;
155 if (strcmp(path
, got_repo_get_path(repo
)) == 0) {
156 err
= got_error(GOT_ERR_WORKTREE_REPO
);
160 err
= got_ref_resolve(&commit_id
, repo
, head_ref
);
163 err
= got_object_get_type(&obj_type
, repo
, commit_id
);
166 if (obj_type
!= GOT_OBJ_TYPE_COMMIT
)
167 return got_error(GOT_ERR_OBJ_TYPE
);
169 if (!got_path_is_absolute(prefix
)) {
170 if (asprintf(&absprefix
, "/%s", prefix
) == -1)
171 return got_error_from_errno("asprintf");
174 /* Create top-level directory (may already exist). */
175 if (mkdir(path
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
176 err
= got_error_from_errno2("mkdir", path
);
180 /* Create .got directory (may already exist). */
181 if (asprintf(&path_got
, "%s/%s", path
, GOT_WORKTREE_GOT_DIR
) == -1) {
182 err
= got_error_from_errno("asprintf");
185 if (mkdir(path_got
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
186 err
= got_error_from_errno2("mkdir", path_got
);
190 /* Create an empty lock file. */
191 err
= create_meta_file(path_got
, GOT_WORKTREE_LOCK
, NULL
);
195 /* Create an empty file index. */
196 err
= create_meta_file(path_got
, GOT_WORKTREE_FILE_INDEX
, NULL
);
200 /* Write the HEAD reference. */
201 err
= write_head_ref(path_got
, head_ref
);
205 /* Record our base commit. */
206 err
= got_object_id_str(&basestr
, commit_id
);
209 err
= create_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, basestr
);
213 /* Store path to repository. */
214 err
= create_meta_file(path_got
, GOT_WORKTREE_REPOSITORY
,
215 got_repo_get_path(repo
));
219 /* Store in-repository path prefix. */
220 err
= create_meta_file(path_got
, GOT_WORKTREE_PATH_PREFIX
,
221 absprefix
? absprefix
: prefix
);
226 uuid_create(&uuid
, &uuid_status
);
227 if (uuid_status
!= uuid_s_ok
) {
228 err
= got_error_uuid(uuid_status
, "uuid_create");
231 uuid_to_string(&uuid
, &uuidstr
, &uuid_status
);
232 if (uuid_status
!= uuid_s_ok
) {
233 err
= got_error_uuid(uuid_status
, "uuid_to_string");
236 err
= create_meta_file(path_got
, GOT_WORKTREE_UUID
, uuidstr
);
240 /* Stamp work tree with format file. */
241 if (asprintf(&formatstr
, "%d", GOT_WORKTREE_FORMAT_VERSION
) == -1) {
242 err
= got_error_from_errno("asprintf");
245 err
= create_meta_file(path_got
, GOT_WORKTREE_FORMAT
, formatstr
);
259 const struct got_error
*
260 got_worktree_match_path_prefix(int *match
, struct got_worktree
*worktree
,
261 const char *path_prefix
)
263 char *absprefix
= NULL
;
265 if (!got_path_is_absolute(path_prefix
)) {
266 if (asprintf(&absprefix
, "/%s", path_prefix
) == -1)
267 return got_error_from_errno("asprintf");
269 *match
= (strcmp(absprefix
? absprefix
: path_prefix
,
270 worktree
->path_prefix
) == 0);
276 got_worktree_get_head_ref_name(struct got_worktree
*worktree
)
278 return worktree
->head_ref_name
;
281 const struct got_error
*
282 got_worktree_set_head_ref(struct got_worktree
*worktree
,
283 struct got_reference
*head_ref
)
285 const struct got_error
*err
= NULL
;
286 char *path_got
= NULL
, *head_ref_name
= NULL
;
288 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
289 GOT_WORKTREE_GOT_DIR
) == -1) {
290 err
= got_error_from_errno("asprintf");
295 head_ref_name
= strdup(got_ref_get_name(head_ref
));
296 if (head_ref_name
== NULL
) {
297 err
= got_error_from_errno("strdup");
301 err
= write_head_ref(path_got
, head_ref
);
305 free(worktree
->head_ref_name
);
306 worktree
->head_ref_name
= head_ref_name
;
314 struct got_object_id
*
315 got_worktree_get_base_commit_id(struct got_worktree
*worktree
)
317 return worktree
->base_commit_id
;
320 const struct got_error
*
321 got_worktree_set_base_commit_id(struct got_worktree
*worktree
,
322 struct got_repository
*repo
, struct got_object_id
*commit_id
)
324 const struct got_error
*err
;
325 struct got_object
*obj
= NULL
;
327 char *path_got
= NULL
;
329 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
330 GOT_WORKTREE_GOT_DIR
) == -1) {
331 err
= got_error_from_errno("asprintf");
336 err
= got_object_open(&obj
, repo
, commit_id
);
340 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
341 err
= got_error(GOT_ERR_OBJ_TYPE
);
345 /* Record our base commit. */
346 err
= got_object_id_str(&id_str
, commit_id
);
349 err
= update_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, id_str
);
353 free(worktree
->base_commit_id
);
354 worktree
->base_commit_id
= got_object_id_dup(commit_id
);
355 if (worktree
->base_commit_id
== NULL
) {
356 err
= got_error_from_errno("got_object_id_dup");
361 got_object_close(obj
);
367 const struct got_gotconfig
*
368 got_worktree_get_gotconfig(struct got_worktree
*worktree
)
370 return worktree
->gotconfig
;
373 static const struct got_error
*
374 lock_worktree(struct got_worktree
*worktree
, int operation
)
376 if (flock(worktree
->lockfd
, operation
| LOCK_NB
) == -1)
377 return (errno
== EWOULDBLOCK
? got_error(GOT_ERR_WORKTREE_BUSY
)
378 : got_error_from_errno2("flock",
379 got_worktree_get_root_path(worktree
)));
383 static const struct got_error
*
384 add_dir_on_disk(struct got_worktree
*worktree
, const char *path
)
386 const struct got_error
*err
= NULL
;
389 if (asprintf(&abspath
, "%s/%s", worktree
->root_path
, path
) == -1)
390 return got_error_from_errno("asprintf");
392 err
= got_path_mkdir(abspath
);
393 if (err
&& err
->code
== GOT_ERR_ERRNO
&& errno
== EEXIST
) {
396 if (lstat(abspath
, &sb
) == -1) {
397 err
= got_error_from_errno2("lstat", abspath
);
398 } else if (!S_ISDIR(sb
.st_mode
)) {
399 /* TODO directory is obstructed; do something */
400 err
= got_error_path(abspath
, GOT_ERR_FILE_OBSTRUCTED
);
407 static const struct got_error
*
408 check_file_contents_equal(int *same
, FILE *f1
, FILE *f2
)
410 const struct got_error
*err
= NULL
;
413 size_t flen1
= 0, flen2
= 0;
418 flen1
= fread(fbuf1
, 1, sizeof(fbuf1
), f1
);
419 if (flen1
== 0 && ferror(f1
)) {
420 err
= got_error_from_errno("fread");
423 flen2
= fread(fbuf2
, 1, sizeof(fbuf2
), f2
);
424 if (flen2
== 0 && ferror(f2
)) {
425 err
= got_error_from_errno("fread");
432 } else if (flen2
== 0) {
436 } else if (flen1
== flen2
) {
437 if (memcmp(fbuf1
, fbuf2
, flen2
) != 0) {
450 static const struct got_error
*
451 check_files_equal(int *same
, FILE *f1
, FILE *f2
)
458 if (fstat(fileno(f1
), &sb
) != 0)
459 return got_error_from_errno("fstat");
462 if (fstat(fileno(f2
), &sb
) != 0)
463 return got_error_from_errno("fstat");
466 if (size1
!= size2
) {
471 if (fseek(f1
, 0L, SEEK_SET
) == -1)
472 return got_ferror(f1
, GOT_ERR_IO
);
473 if (fseek(f2
, 0L, SEEK_SET
) == -1)
474 return got_ferror(f2
, GOT_ERR_IO
);
476 return check_file_contents_equal(same
, f1
, f2
);
479 static const struct got_error
*
480 copy_file_to_fd(off_t
*outsize
, FILE *f
, int outfd
)
488 if (fseek(f
, 0L, SEEK_SET
) == -1)
489 return got_ferror(f
, GOT_ERR_IO
);
492 flen
= fread(fbuf
, 1, sizeof(fbuf
), f
);
495 return got_error_from_errno("fread");
499 outlen
= write(outfd
, fbuf
, flen
);
501 return got_error_from_errno("write");
503 return got_error(GOT_ERR_IO
);
510 static const struct got_error
*
511 merge_binary_file(int *overlapcnt
, int merged_fd
,
512 FILE *f_deriv
, FILE *f_orig
, FILE *f_deriv2
,
513 const char *label_deriv
, const char *label_orig
, const char *label_deriv2
,
514 const char *ondisk_path
)
516 const struct got_error
*err
= NULL
;
517 int same_content
, changed_deriv
, changed_deriv2
;
518 int fd_orig
= -1, fd_deriv
= -1, fd_deriv2
= -1;
519 off_t size_orig
= 0, size_deriv
= 0, size_deriv2
= 0;
520 char *path_orig
= NULL
, *path_deriv
= NULL
, *path_deriv2
= NULL
;
521 char *base_path_orig
= NULL
, *base_path_deriv
= NULL
;
522 char *base_path_deriv2
= NULL
;
526 err
= check_files_equal(&same_content
, f_deriv
, f_deriv2
);
531 return copy_file_to_fd(&size_deriv
, f_deriv
, merged_fd
);
533 err
= check_files_equal(&same_content
, f_deriv
, f_orig
);
536 changed_deriv
= !same_content
;
537 err
= check_files_equal(&same_content
, f_deriv2
, f_orig
);
540 changed_deriv2
= !same_content
;
542 if (changed_deriv
&& changed_deriv2
) {
544 if (asprintf(&base_path_orig
, "%s-orig", ondisk_path
) == -1) {
545 err
= got_error_from_errno("asprintf");
548 if (asprintf(&base_path_deriv
, "%s-1", ondisk_path
) == -1) {
549 err
= got_error_from_errno("asprintf");
552 if (asprintf(&base_path_deriv2
, "%s-2", ondisk_path
) == -1) {
553 err
= got_error_from_errno("asprintf");
556 err
= got_opentemp_named_fd(&path_orig
, &fd_orig
,
560 err
= got_opentemp_named_fd(&path_deriv
, &fd_deriv
,
561 base_path_deriv
, "");
564 err
= got_opentemp_named_fd(&path_deriv2
, &fd_deriv2
,
565 base_path_deriv2
, "");
568 err
= copy_file_to_fd(&size_orig
, f_orig
, fd_orig
);
571 err
= copy_file_to_fd(&size_deriv
, f_deriv
, fd_deriv
);
574 err
= copy_file_to_fd(&size_deriv2
, f_deriv2
, fd_deriv2
);
577 if (dprintf(merged_fd
, "Binary files differ and cannot be "
578 "merged automatically:\n") < 0) {
579 err
= got_error_from_errno("dprintf");
582 if (dprintf(merged_fd
, "%s%s%s\nfile %s\n",
583 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
584 label_deriv
? " " : "",
585 label_deriv
? label_deriv
: "",
587 err
= got_error_from_errno("dprintf");
591 if (dprintf(merged_fd
, "%s%s%s\nfile %s\n",
592 GOT_DIFF_CONFLICT_MARKER_ORIG
,
593 label_orig
? " " : "",
594 label_orig
? label_orig
: "",
596 err
= got_error_from_errno("dprintf");
600 if (dprintf(merged_fd
, "%s\nfile %s\n%s%s%s\n",
601 GOT_DIFF_CONFLICT_MARKER_SEP
,
603 GOT_DIFF_CONFLICT_MARKER_END
,
604 label_deriv2
? " " : "",
605 label_deriv2
? label_deriv2
: "") < 0) {
606 err
= got_error_from_errno("dprintf");
609 } else if (changed_deriv
)
610 err
= copy_file_to_fd(&size_deriv
, f_deriv
, merged_fd
);
611 else if (changed_deriv2
)
612 err
= copy_file_to_fd(&size_deriv2
, f_deriv2
, merged_fd
);
614 if (size_orig
== 0 && path_orig
&& unlink(path_orig
) == -1 &&
616 err
= got_error_from_errno2("unlink", path_orig
);
617 if (fd_orig
!= -1 && close(fd_orig
) == -1 && err
== NULL
)
618 err
= got_error_from_errno2("close", path_orig
);
619 if (fd_deriv
!= -1 && close(fd_deriv
) == -1 && err
== NULL
)
620 err
= got_error_from_errno2("close", path_deriv
);
621 if (fd_deriv2
!= -1 && close(fd_deriv2
) == -1 && err
== NULL
)
622 err
= got_error_from_errno2("close", path_deriv2
);
626 free(base_path_orig
);
627 free(base_path_deriv
);
628 free(base_path_deriv2
);
633 * Perform a 3-way merge where the file f_orig acts as the common
634 * ancestor, the file f_deriv acts as the first derived version,
635 * and the file f_deriv2 acts as the second derived version.
636 * The merge result will be written to a new file at ondisk_path; any
637 * existing file at this path will be replaced.
639 static const struct got_error
*
640 merge_file(int *local_changes_subsumed
, struct got_worktree
*worktree
,
641 FILE *f_orig
, FILE *f_deriv
, FILE *f_deriv2
, const char *ondisk_path
,
642 const char *path
, uint16_t st_mode
,
643 const char *label_orig
, const char *label_deriv
, const char *label_deriv2
,
644 enum got_diff_algorithm diff_algo
, struct got_repository
*repo
,
645 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
647 const struct got_error
*err
= NULL
;
649 FILE *f_merged
= NULL
;
650 char *merged_path
= NULL
, *base_path
= NULL
;
654 *local_changes_subsumed
= 0;
656 err
= got_path_dirname(&parent
, ondisk_path
);
660 if (asprintf(&base_path
, "%s/got-merged", parent
) == -1) {
661 err
= got_error_from_errno("asprintf");
665 err
= got_opentemp_named_fd(&merged_path
, &merged_fd
, base_path
, "");
669 err
= got_merge_diff3(&overlapcnt
, merged_fd
, f_deriv
, f_orig
,
670 f_deriv2
, label_deriv
, label_orig
, label_deriv2
, diff_algo
);
672 if (err
->code
!= GOT_ERR_FILE_BINARY
)
674 err
= merge_binary_file(&overlapcnt
, merged_fd
, f_deriv
,
675 f_orig
, f_deriv2
, label_deriv
, label_orig
, label_deriv2
,
681 err
= (*progress_cb
)(progress_arg
,
682 overlapcnt
> 0 ? GOT_STATUS_CONFLICT
: GOT_STATUS_MERGE
, path
);
686 if (fsync(merged_fd
) != 0) {
687 err
= got_error_from_errno("fsync");
691 f_merged
= fdopen(merged_fd
, "r");
692 if (f_merged
== NULL
) {
693 err
= got_error_from_errno("fdopen");
698 /* Check if a clean merge has subsumed all local changes. */
699 if (overlapcnt
== 0) {
700 err
= check_files_equal(local_changes_subsumed
, f_deriv
,
706 if (fchmod(fileno(f_merged
), apply_umask(st_mode
)) != 0) {
707 err
= got_error_from_errno2("fchmod", merged_path
);
711 if (rename(merged_path
, ondisk_path
) != 0) {
712 err
= got_error_from_errno3("rename", merged_path
,
721 if (merged_fd
!= -1 && close(merged_fd
) == -1 && err
== NULL
)
722 err
= got_error_from_errno("close");
723 if (f_merged
&& fclose(f_merged
) == EOF
&& err
== NULL
)
724 err
= got_error_from_errno("fclose");
731 static const struct got_error
*
732 update_symlink(const char *ondisk_path
, const char *target_path
,
735 /* This is not atomic but matches what 'ln -sf' does. */
736 if (unlink(ondisk_path
) == -1)
737 return got_error_from_errno2("unlink", ondisk_path
);
738 if (symlink(target_path
, ondisk_path
) == -1)
739 return got_error_from_errno3("symlink", target_path
,
745 * Overwrite a symlink (or a regular file in case there was a "bad" symlink)
746 * in the work tree with a file that contains conflict markers and the
747 * conflicting target paths of the original version, a "derived version"
748 * of a symlink from an incoming change, and a local version of the symlink.
750 * The original versions's target path can be NULL if it is not available,
751 * such as if both derived versions added a new symlink at the same path.
753 * The incoming derived symlink target is NULL in case the incoming change
754 * has deleted this symlink.
756 static const struct got_error
*
757 install_symlink_conflict(const char *deriv_target
,
758 struct got_object_id
*deriv_base_commit_id
, const char *orig_target
,
759 const char *label_orig
, const char *local_target
, const char *ondisk_path
)
761 const struct got_error
*err
;
762 char *id_str
= NULL
, *label_deriv
= NULL
, *path
= NULL
;
765 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
767 return got_error_from_errno("asprintf");
769 if (asprintf(&label_deriv
, "%s: commit %s",
770 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
771 err
= got_error_from_errno("asprintf");
775 err
= got_opentemp_named(&path
, &f
, "got-symlink-conflict", "");
779 if (fchmod(fileno(f
), apply_umask(GOT_DEFAULT_FILE_MODE
)) == -1) {
780 err
= got_error_from_errno2("fchmod", path
);
784 if (fprintf(f
, "%s %s\n%s\n%s%s%s%s%s\n%s\n%s\n",
785 GOT_DIFF_CONFLICT_MARKER_BEGIN
, label_deriv
,
786 deriv_target
? deriv_target
: "(symlink was deleted)",
787 orig_target
? label_orig
: "",
788 orig_target
? "\n" : "",
789 orig_target
? orig_target
: "",
790 orig_target
? "\n" : "",
791 GOT_DIFF_CONFLICT_MARKER_SEP
,
792 local_target
, GOT_DIFF_CONFLICT_MARKER_END
) < 0) {
793 err
= got_error_from_errno2("fprintf", path
);
797 if (unlink(ondisk_path
) == -1) {
798 err
= got_error_from_errno2("unlink", ondisk_path
);
801 if (rename(path
, ondisk_path
) == -1) {
802 err
= got_error_from_errno3("rename", path
, ondisk_path
);
806 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
807 err
= got_error_from_errno2("fclose", path
);
814 /* forward declaration */
815 static const struct got_error
*
816 merge_blob(int *, struct got_worktree
*, struct got_blob_object
*,
817 const char *, const char *, uint16_t, const char *,
818 struct got_blob_object
*, struct got_object_id
*,
819 struct got_repository
*, got_worktree_checkout_cb
, void *);
822 * Merge a symlink into the work tree, where blob_orig acts as the common
823 * ancestor, deriv_target is the link target of the first derived version,
824 * and the symlink on disk acts as the second derived version.
825 * Assume that contents of both blobs represent symlinks.
827 static const struct got_error
*
828 merge_symlink(struct got_worktree
*worktree
,
829 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
830 const char *path
, const char *label_orig
, const char *deriv_target
,
831 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
832 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
834 const struct got_error
*err
= NULL
;
835 char *ancestor_target
= NULL
;
837 ssize_t ondisk_len
, deriv_len
;
838 char ondisk_target
[PATH_MAX
];
839 int have_local_change
= 0;
840 int have_incoming_change
= 0;
842 if (lstat(ondisk_path
, &sb
) == -1)
843 return got_error_from_errno2("lstat", ondisk_path
);
845 ondisk_len
= readlink(ondisk_path
, ondisk_target
,
846 sizeof(ondisk_target
));
847 if (ondisk_len
== -1) {
848 err
= got_error_from_errno2("readlink",
852 ondisk_target
[ondisk_len
] = '\0';
855 err
= got_object_blob_read_to_str(&ancestor_target
, blob_orig
);
860 if (ancestor_target
== NULL
||
861 (ondisk_len
!= strlen(ancestor_target
) ||
862 memcmp(ondisk_target
, ancestor_target
, ondisk_len
) != 0))
863 have_local_change
= 1;
865 deriv_len
= strlen(deriv_target
);
866 if (ancestor_target
== NULL
||
867 (deriv_len
!= strlen(ancestor_target
) ||
868 memcmp(deriv_target
, ancestor_target
, deriv_len
) != 0))
869 have_incoming_change
= 1;
871 if (!have_local_change
&& !have_incoming_change
) {
872 if (ancestor_target
) {
873 /* Both sides made the same change. */
874 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
876 } else if (deriv_len
== ondisk_len
&&
877 memcmp(ondisk_target
, deriv_target
, deriv_len
) == 0) {
878 /* Both sides added the same symlink. */
879 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
882 /* Both sides added symlinks which don't match. */
883 err
= install_symlink_conflict(deriv_target
,
884 deriv_base_commit_id
, ancestor_target
,
885 label_orig
, ondisk_target
, ondisk_path
);
888 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
891 } else if (!have_local_change
&& have_incoming_change
) {
892 /* Apply the incoming change. */
893 err
= update_symlink(ondisk_path
, deriv_target
,
894 strlen(deriv_target
));
897 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
898 } else if (have_local_change
&& have_incoming_change
) {
899 if (deriv_len
== ondisk_len
&&
900 memcmp(deriv_target
, ondisk_target
, deriv_len
) == 0) {
901 /* Both sides made the same change. */
902 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
905 err
= install_symlink_conflict(deriv_target
,
906 deriv_base_commit_id
, ancestor_target
, label_orig
,
907 ondisk_target
, ondisk_path
);
910 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
916 free(ancestor_target
);
920 static const struct got_error
*
921 dump_symlink_target_path_to_file(FILE **outfile
, const char *ondisk_path
)
923 const struct got_error
*err
= NULL
;
924 char target_path
[PATH_MAX
];
933 return got_error_from_errno("got_opentemp");
934 target_len
= readlink(ondisk_path
, target_path
, sizeof(target_path
));
935 if (target_len
== -1) {
936 err
= got_error_from_errno2("readlink", ondisk_path
);
939 n
= fwrite(target_path
, 1, target_len
, f
);
940 if (n
!= target_len
) {
941 err
= got_ferror(f
, GOT_ERR_IO
);
944 if (fflush(f
) == EOF
) {
945 err
= got_error_from_errno("fflush");
948 if (fseek(f
, 0L, SEEK_SET
) == -1) {
949 err
= got_ferror(f
, GOT_ERR_IO
);
961 * Perform a 3-way merge where blob_orig acts as the common ancestor,
962 * blob_deriv acts as the first derived version, and the file on disk
963 * acts as the second derived version.
965 static const struct got_error
*
966 merge_blob(int *local_changes_subsumed
, struct got_worktree
*worktree
,
967 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
968 const char *path
, uint16_t st_mode
, const char *label_orig
,
969 struct got_blob_object
*blob_deriv
,
970 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
971 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
973 const struct got_error
*err
= NULL
;
974 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
975 char *blob_orig_path
= NULL
;
976 char *blob_deriv_path
= NULL
, *base_path
= NULL
, *id_str
= NULL
;
977 char *label_deriv
= NULL
, *parent
= NULL
;
979 *local_changes_subsumed
= 0;
981 err
= got_path_dirname(&parent
, ondisk_path
);
986 if (asprintf(&base_path
, "%s/got-merge-blob-orig",
988 err
= got_error_from_errno("asprintf");
993 err
= got_opentemp_named(&blob_orig_path
, &f_orig
,
997 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_orig
,
1004 * No common ancestor exists. This is an "add vs add" conflict
1005 * and we simply use an empty ancestor file to make both files
1006 * appear in the merged result in their entirety.
1008 f_orig
= got_opentemp();
1009 if (f_orig
== NULL
) {
1010 err
= got_error_from_errno("got_opentemp");
1015 if (asprintf(&base_path
, "%s/got-merge-blob-deriv", parent
) == -1) {
1016 err
= got_error_from_errno("asprintf");
1021 err
= got_opentemp_named(&blob_deriv_path
, &f_deriv
, base_path
, "");
1024 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_deriv
,
1029 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
1032 if (asprintf(&label_deriv
, "%s: commit %s",
1033 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
1034 err
= got_error_from_errno("asprintf");
1039 * In order the run a 3-way merge with a symlink we copy the symlink's
1040 * target path into a temporary file and use that file with diff3.
1042 if (S_ISLNK(st_mode
)) {
1043 err
= dump_symlink_target_path_to_file(&f_deriv2
, ondisk_path
);
1048 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1050 err
= got_error_from_errno2("open", ondisk_path
);
1053 f_deriv2
= fdopen(fd
, "r");
1054 if (f_deriv2
== NULL
) {
1055 err
= got_error_from_errno2("fdopen", ondisk_path
);
1061 err
= merge_file(local_changes_subsumed
, worktree
, f_orig
, f_deriv
,
1062 f_deriv2
, ondisk_path
, path
, st_mode
, label_orig
, label_deriv
,
1063 NULL
, GOT_DIFF_ALGORITHM_MYERS
, repo
, progress_cb
, progress_arg
);
1065 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
1066 err
= got_error_from_errno("fclose");
1067 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
1068 err
= got_error_from_errno("fclose");
1069 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
1070 err
= got_error_from_errno("fclose");
1072 if (blob_orig_path
) {
1073 unlink(blob_orig_path
);
1074 free(blob_orig_path
);
1076 if (blob_deriv_path
) {
1077 unlink(blob_deriv_path
);
1078 free(blob_deriv_path
);
1086 static const struct got_error
*
1087 create_fileindex_entry(struct got_fileindex_entry
**new_iep
,
1088 struct got_fileindex
*fileindex
, struct got_object_id
*base_commit_id
,
1089 int wt_fd
, const char *path
, struct got_object_id
*blob_id
)
1091 const struct got_error
*err
= NULL
;
1092 struct got_fileindex_entry
*new_ie
;
1096 err
= got_fileindex_entry_alloc(&new_ie
, path
);
1100 err
= got_fileindex_entry_update(new_ie
, wt_fd
, path
,
1101 blob_id
->sha1
, base_commit_id
->sha1
, 1);
1105 err
= got_fileindex_entry_add(fileindex
, new_ie
);
1108 got_fileindex_entry_free(new_ie
);
1115 get_ondisk_perms(int executable
, mode_t st_mode
)
1117 mode_t xbits
= S_IXUSR
;
1120 /* Map read bits to execute bits. */
1121 if (st_mode
& S_IRGRP
)
1123 if (st_mode
& S_IROTH
)
1125 return st_mode
| xbits
;
1132 apply_umask(mode_t mode
)
1141 /* forward declaration */
1142 static const struct got_error
*
1143 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1144 const char *path
, mode_t te_mode
, mode_t st_mode
,
1145 struct got_blob_object
*blob
, int restoring_missing_file
,
1146 int reverting_versioned_file
, int installing_bad_symlink
,
1147 int path_is_unversioned
, struct got_repository
*repo
,
1148 got_worktree_checkout_cb progress_cb
, void *progress_arg
);
1151 * This function assumes that the provided symlink target points at a
1152 * safe location in the work tree!
1154 static const struct got_error
*
1155 replace_existing_symlink(int *did_something
, const char *ondisk_path
,
1156 const char *target_path
, size_t target_len
)
1158 const struct got_error
*err
= NULL
;
1160 char etarget
[PATH_MAX
];
1166 * "Bad" symlinks (those pointing outside the work tree or into the
1167 * .got directory) are installed in the work tree as a regular file
1168 * which contains the bad symlink target path.
1169 * The new symlink target has already been checked for safety by our
1170 * caller. If we can successfully open a regular file then we simply
1171 * replace this file with a symlink below.
1173 fd
= open(ondisk_path
, O_RDWR
| O_EXCL
| O_NOFOLLOW
| O_CLOEXEC
);
1175 if (!got_err_open_nofollow_on_symlink())
1176 return got_error_from_errno2("open", ondisk_path
);
1178 /* We are updating an existing on-disk symlink. */
1179 elen
= readlink(ondisk_path
, etarget
, sizeof(etarget
));
1181 return got_error_from_errno2("readlink", ondisk_path
);
1183 if (elen
== target_len
&&
1184 memcmp(etarget
, target_path
, target_len
) == 0)
1185 return NULL
; /* nothing to do */
1189 err
= update_symlink(ondisk_path
, target_path
, target_len
);
1190 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1191 err
= got_error_from_errno2("close", ondisk_path
);
1195 static const struct got_error
*
1196 is_bad_symlink_target(int *is_bad_symlink
, const char *target_path
,
1197 size_t target_len
, const char *ondisk_path
, const char *wtroot_path
)
1199 const struct got_error
*err
= NULL
;
1200 char canonpath
[PATH_MAX
];
1201 char *path_got
= NULL
;
1203 *is_bad_symlink
= 0;
1205 if (target_len
>= sizeof(canonpath
)) {
1206 *is_bad_symlink
= 1;
1211 * We do not use realpath(3) to resolve the symlink's target
1212 * path because we don't want to resolve symlinks recursively.
1213 * Instead we make the path absolute and then canonicalize it.
1214 * Relative symlink target lookup should begin at the directory
1215 * in which the blob object is being installed.
1217 if (!got_path_is_absolute(target_path
)) {
1218 char *abspath
, *parent
;
1219 err
= got_path_dirname(&parent
, ondisk_path
);
1222 if (asprintf(&abspath
, "%s/%s", parent
, target_path
) == -1) {
1224 return got_error_from_errno("asprintf");
1227 if (strlen(abspath
) >= sizeof(canonpath
)) {
1228 err
= got_error_path(abspath
, GOT_ERR_BAD_PATH
);
1232 err
= got_canonpath(abspath
, canonpath
, sizeof(canonpath
));
1237 err
= got_canonpath(target_path
, canonpath
, sizeof(canonpath
));
1242 /* Only allow symlinks pointing at paths within the work tree. */
1243 if (!got_path_is_child(canonpath
, wtroot_path
, strlen(wtroot_path
))) {
1244 *is_bad_symlink
= 1;
1248 /* Do not allow symlinks pointing into the .got directory. */
1249 if (asprintf(&path_got
, "%s/%s", wtroot_path
,
1250 GOT_WORKTREE_GOT_DIR
) == -1)
1251 return got_error_from_errno("asprintf");
1252 if (got_path_is_child(canonpath
, path_got
, strlen(path_got
)))
1253 *is_bad_symlink
= 1;
1259 static const struct got_error
*
1260 install_symlink(int *is_bad_symlink
, struct got_worktree
*worktree
,
1261 const char *ondisk_path
, const char *path
, struct got_blob_object
*blob
,
1262 int restoring_missing_file
, int reverting_versioned_file
,
1263 int path_is_unversioned
, int allow_bad_symlinks
,
1264 struct got_repository
*repo
,
1265 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1267 const struct got_error
*err
= NULL
;
1268 char target_path
[PATH_MAX
];
1269 size_t len
, target_len
= 0;
1270 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1271 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1273 *is_bad_symlink
= 0;
1276 * Blob object content specifies the target path of the link.
1277 * If a symbolic link cannot be installed we instead create
1278 * a regular file which contains the link target path stored
1279 * in the blob object.
1282 err
= got_object_blob_read_block(&len
, blob
);
1286 if (len
+ target_len
>= sizeof(target_path
)) {
1287 /* Path too long; install as a regular file. */
1288 *is_bad_symlink
= 1;
1289 got_object_blob_rewind(blob
);
1290 return install_blob(worktree
, ondisk_path
, path
,
1291 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1292 restoring_missing_file
, reverting_versioned_file
,
1293 1, path_is_unversioned
, repo
, progress_cb
,
1297 /* Skip blob object header first time around. */
1298 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1300 target_len
+= len
- hdrlen
;
1304 target_path
[target_len
] = '\0';
1306 err
= is_bad_symlink_target(is_bad_symlink
, target_path
, target_len
,
1307 ondisk_path
, worktree
->root_path
);
1311 if (*is_bad_symlink
&& !allow_bad_symlinks
) {
1312 /* install as a regular file */
1313 got_object_blob_rewind(blob
);
1314 err
= install_blob(worktree
, ondisk_path
, path
,
1315 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1316 restoring_missing_file
, reverting_versioned_file
, 1,
1317 path_is_unversioned
, repo
, progress_cb
, progress_arg
);
1321 if (symlink(target_path
, ondisk_path
) == -1) {
1322 if (errno
== EEXIST
) {
1323 int symlink_replaced
;
1324 if (path_is_unversioned
) {
1325 err
= (*progress_cb
)(progress_arg
,
1326 GOT_STATUS_UNVERSIONED
, path
);
1329 err
= replace_existing_symlink(&symlink_replaced
,
1330 ondisk_path
, target_path
, target_len
);
1334 if (symlink_replaced
) {
1335 err
= (*progress_cb
)(progress_arg
,
1336 reverting_versioned_file
?
1338 GOT_STATUS_UPDATE
, path
);
1340 err
= (*progress_cb
)(progress_arg
,
1341 GOT_STATUS_EXISTS
, path
);
1344 return err
; /* Nothing else to do. */
1347 if (errno
== ENOENT
) {
1349 err
= got_path_dirname(&parent
, ondisk_path
);
1352 err
= add_dir_on_disk(worktree
, parent
);
1357 * Retry, and fall through to error handling
1358 * below if this second attempt fails.
1360 if (symlink(target_path
, ondisk_path
) != -1) {
1361 err
= NULL
; /* success */
1366 /* Handle errors from first or second creation attempt. */
1367 if (errno
== ENAMETOOLONG
) {
1368 /* bad target path; install as a regular file */
1369 *is_bad_symlink
= 1;
1370 got_object_blob_rewind(blob
);
1371 err
= install_blob(worktree
, ondisk_path
, path
,
1372 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1373 restoring_missing_file
, reverting_versioned_file
, 1,
1374 path_is_unversioned
, repo
,
1375 progress_cb
, progress_arg
);
1376 } else if (errno
== ENOTDIR
) {
1377 err
= got_error_path(ondisk_path
,
1378 GOT_ERR_FILE_OBSTRUCTED
);
1380 err
= got_error_from_errno3("symlink",
1381 target_path
, ondisk_path
);
1383 } else if (progress_cb
)
1384 err
= (*progress_cb
)(progress_arg
, reverting_versioned_file
?
1385 GOT_STATUS_REVERT
: GOT_STATUS_ADD
, path
);
1389 static const struct got_error
*
1390 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1391 const char *path
, mode_t te_mode
, mode_t st_mode
,
1392 struct got_blob_object
*blob
, int restoring_missing_file
,
1393 int reverting_versioned_file
, int installing_bad_symlink
,
1394 int path_is_unversioned
, struct got_repository
*repo
,
1395 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1397 const struct got_error
*err
= NULL
;
1401 char *tmppath
= NULL
;
1404 mode
= get_ondisk_perms(te_mode
& S_IXUSR
, GOT_DEFAULT_FILE_MODE
);
1405 fd
= open(ondisk_path
, O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
|
1408 if (errno
== ENOENT
) {
1410 err
= got_path_dirname(&parent
, path
);
1413 err
= add_dir_on_disk(worktree
, parent
);
1417 fd
= open(ondisk_path
,
1418 O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
| O_CLOEXEC
,
1421 return got_error_from_errno2("open",
1423 } else if (errno
== EEXIST
) {
1424 if (path_is_unversioned
) {
1425 err
= (*progress_cb
)(progress_arg
,
1426 GOT_STATUS_UNVERSIONED
, path
);
1429 if (!(S_ISLNK(st_mode
) && S_ISREG(te_mode
)) &&
1430 !S_ISREG(st_mode
) && !installing_bad_symlink
) {
1431 /* TODO file is obstructed; do something */
1432 err
= got_error_path(ondisk_path
,
1433 GOT_ERR_FILE_OBSTRUCTED
);
1436 err
= got_opentemp_named_fd(&tmppath
, &fd
,
1442 if (fchmod(fd
, apply_umask(mode
)) == -1) {
1443 err
= got_error_from_errno2("fchmod",
1449 return got_error_from_errno2("open", ondisk_path
);
1453 if (restoring_missing_file
)
1454 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MISSING
,
1456 else if (reverting_versioned_file
)
1457 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_REVERT
,
1460 err
= (*progress_cb
)(progress_arg
,
1461 update
? GOT_STATUS_UPDATE
: GOT_STATUS_ADD
, path
);
1466 hdrlen
= got_object_blob_get_hdrlen(blob
);
1468 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1469 err
= got_object_blob_read_block(&len
, blob
);
1473 /* Skip blob object header first time around. */
1474 ssize_t outlen
= write(fd
, buf
+ hdrlen
, len
- hdrlen
);
1476 err
= got_error_from_errno("write");
1478 } else if (outlen
!= len
- hdrlen
) {
1479 err
= got_error(GOT_ERR_IO
);
1486 if (fsync(fd
) != 0) {
1487 err
= got_error_from_errno("fsync");
1492 if (S_ISLNK(st_mode
) && unlink(ondisk_path
) == -1) {
1493 err
= got_error_from_errno2("unlink", ondisk_path
);
1496 if (rename(tmppath
, ondisk_path
) != 0) {
1497 err
= got_error_from_errno3("rename", tmppath
,
1506 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1507 err
= got_error_from_errno("close");
1508 if (tmppath
!= NULL
&& unlink(tmppath
) == -1 && err
== NULL
)
1509 err
= got_error_from_errno2("unlink", tmppath
);
1514 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1515 static const struct got_error
*
1516 get_modified_file_content_status(unsigned char *status
, FILE *f
)
1518 const struct got_error
*err
= NULL
;
1519 const char *markers
[3] = {
1520 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
1521 GOT_DIFF_CONFLICT_MARKER_SEP
,
1522 GOT_DIFF_CONFLICT_MARKER_END
1526 size_t linesize
= 0;
1529 while (*status
== GOT_STATUS_MODIFY
) {
1530 linelen
= getline(&line
, &linesize
, f
);
1531 if (linelen
== -1) {
1534 err
= got_ferror(f
, GOT_ERR_IO
);
1538 if (strncmp(line
, markers
[i
], strlen(markers
[i
])) == 0) {
1539 if (strcmp(markers
[i
], GOT_DIFF_CONFLICT_MARKER_END
)
1541 *status
= GOT_STATUS_CONFLICT
;
1552 xbit_differs(struct got_fileindex_entry
*ie
, uint16_t st_mode
)
1554 mode_t ie_mode
= got_fileindex_perms_to_st(ie
);
1555 return ((ie_mode
& S_IXUSR
) != (st_mode
& S_IXUSR
));
1559 stat_info_differs(struct got_fileindex_entry
*ie
, struct stat
*sb
)
1561 return !(ie
->ctime_sec
== sb
->st_ctim
.tv_sec
&&
1562 ie
->ctime_nsec
== sb
->st_ctim
.tv_nsec
&&
1563 ie
->mtime_sec
== sb
->st_mtim
.tv_sec
&&
1564 ie
->mtime_nsec
== sb
->st_mtim
.tv_nsec
&&
1565 ie
->size
== (sb
->st_size
& 0xffffffff) &&
1566 !xbit_differs(ie
, sb
->st_mode
));
1569 static unsigned char
1570 get_staged_status(struct got_fileindex_entry
*ie
)
1572 switch (got_fileindex_entry_stage_get(ie
)) {
1573 case GOT_FILEIDX_STAGE_ADD
:
1574 return GOT_STATUS_ADD
;
1575 case GOT_FILEIDX_STAGE_DELETE
:
1576 return GOT_STATUS_DELETE
;
1577 case GOT_FILEIDX_STAGE_MODIFY
:
1578 return GOT_STATUS_MODIFY
;
1580 return GOT_STATUS_NO_CHANGE
;
1584 static const struct got_error
*
1585 get_symlink_modification_status(unsigned char *status
,
1586 struct got_fileindex_entry
*ie
, const char *abspath
,
1587 int dirfd
, const char *de_name
, struct got_blob_object
*blob
)
1589 const struct got_error
*err
= NULL
;
1590 char target_path
[PATH_MAX
];
1591 char etarget
[PATH_MAX
];
1593 size_t len
, target_len
= 0;
1594 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1595 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1597 *status
= GOT_STATUS_NO_CHANGE
;
1599 /* Blob object content specifies the target path of the link. */
1601 err
= got_object_blob_read_block(&len
, blob
);
1604 if (len
+ target_len
>= sizeof(target_path
)) {
1606 * Should not happen. The blob contents were OK
1607 * when this symlink was installed.
1609 return got_error(GOT_ERR_NO_SPACE
);
1612 /* Skip blob object header first time around. */
1613 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1615 target_len
+= len
- hdrlen
;
1619 target_path
[target_len
] = '\0';
1622 elen
= readlinkat(dirfd
, de_name
, etarget
, sizeof(etarget
));
1624 return got_error_from_errno2("readlinkat", abspath
);
1626 elen
= readlink(abspath
, etarget
, sizeof(etarget
));
1628 return got_error_from_errno2("readlink", abspath
);
1631 if (elen
!= target_len
|| memcmp(etarget
, target_path
, target_len
) != 0)
1632 *status
= GOT_STATUS_MODIFY
;
1637 static const struct got_error
*
1638 get_file_status(unsigned char *status
, struct stat
*sb
,
1639 struct got_fileindex_entry
*ie
, const char *abspath
,
1640 int dirfd
, const char *de_name
, struct got_repository
*repo
)
1642 const struct got_error
*err
= NULL
;
1643 struct got_object_id id
;
1645 int fd
= -1, fd1
= -1;
1648 struct got_blob_object
*blob
= NULL
;
1650 unsigned char staged_status
= get_staged_status(ie
);
1652 *status
= GOT_STATUS_NO_CHANGE
;
1653 memset(sb
, 0, sizeof(*sb
));
1656 * Whenever the caller provides a directory descriptor and a
1657 * directory entry name for the file, use them! This prevents
1658 * race conditions if filesystem paths change beneath our feet.
1661 if (fstatat(dirfd
, de_name
, sb
, AT_SYMLINK_NOFOLLOW
) == -1) {
1662 if (errno
== ENOENT
) {
1663 if (got_fileindex_entry_has_file_on_disk(ie
))
1664 *status
= GOT_STATUS_MISSING
;
1666 *status
= GOT_STATUS_DELETE
;
1669 err
= got_error_from_errno2("fstatat", abspath
);
1673 fd
= open(abspath
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1674 if (fd
== -1 && errno
!= ENOENT
&&
1675 !got_err_open_nofollow_on_symlink())
1676 return got_error_from_errno2("open", abspath
);
1677 else if (fd
== -1 && got_err_open_nofollow_on_symlink()) {
1678 if (lstat(abspath
, sb
) == -1)
1679 return got_error_from_errno2("lstat", abspath
);
1680 } else if (fd
== -1 || fstat(fd
, sb
) == -1) {
1681 if (errno
== ENOENT
) {
1682 if (got_fileindex_entry_has_file_on_disk(ie
))
1683 *status
= GOT_STATUS_MISSING
;
1685 *status
= GOT_STATUS_DELETE
;
1688 err
= got_error_from_errno2("fstat", abspath
);
1693 if (!S_ISREG(sb
->st_mode
) && !S_ISLNK(sb
->st_mode
)) {
1694 *status
= GOT_STATUS_OBSTRUCTED
;
1698 if (!got_fileindex_entry_has_file_on_disk(ie
)) {
1699 *status
= GOT_STATUS_DELETE
;
1701 } else if (!got_fileindex_entry_has_blob(ie
) &&
1702 staged_status
!= GOT_STATUS_ADD
) {
1703 *status
= GOT_STATUS_ADD
;
1707 if (!stat_info_differs(ie
, sb
))
1710 if (S_ISLNK(sb
->st_mode
) &&
1711 got_fileindex_entry_filetype_get(ie
) != GOT_FILEIDX_MODE_SYMLINK
) {
1712 *status
= GOT_STATUS_MODIFY
;
1716 if (staged_status
== GOT_STATUS_MODIFY
||
1717 staged_status
== GOT_STATUS_ADD
)
1718 memcpy(id
.sha1
, ie
->staged_blob_sha1
, sizeof(id
.sha1
));
1720 memcpy(id
.sha1
, ie
->blob_sha1
, sizeof(id
.sha1
));
1722 fd1
= got_opentempfd();
1724 err
= got_error_from_errno("got_opentempfd");
1727 err
= got_object_open_as_blob(&blob
, repo
, &id
, sizeof(fbuf
), fd1
);
1731 if (S_ISLNK(sb
->st_mode
)) {
1732 err
= get_symlink_modification_status(status
, ie
,
1733 abspath
, dirfd
, de_name
, blob
);
1738 fd
= openat(dirfd
, de_name
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1740 err
= got_error_from_errno2("openat", abspath
);
1745 f
= fdopen(fd
, "r");
1747 err
= got_error_from_errno2("fdopen", abspath
);
1751 hdrlen
= got_object_blob_get_hdrlen(blob
);
1753 const uint8_t *bbuf
= got_object_blob_get_read_buf(blob
);
1754 err
= got_object_blob_read_block(&blen
, blob
);
1757 /* Skip length of blob object header first time around. */
1758 flen
= fread(fbuf
, 1, sizeof(fbuf
) - hdrlen
, f
);
1759 if (flen
== 0 && ferror(f
)) {
1760 err
= got_error_from_errno("fread");
1763 if (blen
- hdrlen
== 0) {
1765 *status
= GOT_STATUS_MODIFY
;
1767 } else if (flen
== 0) {
1768 if (blen
- hdrlen
!= 0)
1769 *status
= GOT_STATUS_MODIFY
;
1771 } else if (blen
- hdrlen
== flen
) {
1772 /* Skip blob object header first time around. */
1773 if (memcmp(bbuf
+ hdrlen
, fbuf
, flen
) != 0) {
1774 *status
= GOT_STATUS_MODIFY
;
1778 *status
= GOT_STATUS_MODIFY
;
1784 if (*status
== GOT_STATUS_MODIFY
) {
1786 err
= get_modified_file_content_status(status
, f
);
1787 } else if (xbit_differs(ie
, sb
->st_mode
))
1788 *status
= GOT_STATUS_MODE_CHANGE
;
1790 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
1791 err
= got_error_from_errno("close");
1793 got_object_blob_close(blob
);
1794 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
1795 err
= got_error_from_errno2("fclose", abspath
);
1796 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1797 err
= got_error_from_errno2("close", abspath
);
1802 * Update timestamps in the file index if a file is unmodified and
1803 * we had to run a full content comparison to find out.
1805 static const struct got_error
*
1806 sync_timestamps(int wt_fd
, const char *path
, unsigned char status
,
1807 struct got_fileindex_entry
*ie
, struct stat
*sb
)
1809 if (status
== GOT_STATUS_NO_CHANGE
&& stat_info_differs(ie
, sb
))
1810 return got_fileindex_entry_update(ie
, wt_fd
, path
,
1811 ie
->blob_sha1
, ie
->commit_sha1
, 1);
1816 static const struct got_error
*
1817 update_blob(struct got_worktree
*worktree
,
1818 struct got_fileindex
*fileindex
, struct got_fileindex_entry
*ie
,
1819 struct got_tree_entry
*te
, const char *path
,
1820 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
1823 const struct got_error
*err
= NULL
;
1824 struct got_blob_object
*blob
= NULL
;
1825 char *ondisk_path
= NULL
;
1826 unsigned char status
= GOT_STATUS_NO_CHANGE
;
1828 int fd1
= -1, fd2
= -1;
1830 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, path
) == -1)
1831 return got_error_from_errno("asprintf");
1834 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
) {
1835 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
1838 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
1842 if (status
== GOT_STATUS_MISSING
|| status
== GOT_STATUS_DELETE
)
1843 sb
.st_mode
= got_fileindex_perms_to_st(ie
);
1845 if (stat(ondisk_path
, &sb
) == -1) {
1846 if (errno
!= ENOENT
) {
1847 err
= got_error_from_errno2("stat",
1851 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
1852 status
= GOT_STATUS_UNVERSIONED
;
1854 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
1855 status
= GOT_STATUS_UNVERSIONED
;
1857 status
= GOT_STATUS_OBSTRUCTED
;
1861 if (status
== GOT_STATUS_OBSTRUCTED
) {
1863 got_fileindex_entry_mark_skipped(ie
);
1864 err
= (*progress_cb
)(progress_arg
, status
, path
);
1867 if (status
== GOT_STATUS_CONFLICT
) {
1869 got_fileindex_entry_mark_skipped(ie
);
1870 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CANNOT_UPDATE
,
1875 if (ie
&& status
!= GOT_STATUS_MISSING
&& S_ISREG(sb
.st_mode
) &&
1876 (S_ISLNK(te
->mode
) ||
1877 (te
->mode
& S_IXUSR
) == (sb
.st_mode
& S_IXUSR
))) {
1879 * This is a regular file or an installed bad symlink.
1880 * If the file index indicates that this file is already
1881 * up-to-date with respect to the repository we can skip
1882 * updating contents of this file.
1884 if (got_fileindex_entry_has_commit(ie
) &&
1885 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
1886 SHA1_DIGEST_LENGTH
) == 0) {
1888 err
= sync_timestamps(worktree
->root_fd
,
1889 path
, status
, ie
, &sb
);
1892 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
1896 if (got_fileindex_entry_has_blob(ie
) &&
1897 memcmp(ie
->blob_sha1
, te
->id
.sha1
,
1898 SHA1_DIGEST_LENGTH
) == 0) {
1899 /* Different commit but the same blob. */
1900 err
= sync_timestamps(worktree
->root_fd
,
1901 path
, status
, ie
, &sb
);
1904 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
1910 fd1
= got_opentempfd();
1912 err
= got_error_from_errno("got_opentempfd");
1915 err
= got_object_open_as_blob(&blob
, repo
, &te
->id
, 8192, fd1
);
1919 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_ADD
) {
1920 int update_timestamps
;
1921 struct got_blob_object
*blob2
= NULL
;
1922 char *label_orig
= NULL
;
1923 if (got_fileindex_entry_has_blob(ie
)) {
1924 fd2
= got_opentempfd();
1926 err
= got_error_from_errno("got_opentempfd");
1929 struct got_object_id id2
;
1930 memcpy(id2
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
1931 err
= got_object_open_as_blob(&blob2
, repo
, &id2
, 8192,
1936 if (got_fileindex_entry_has_commit(ie
)) {
1937 char id_str
[SHA1_DIGEST_STRING_LENGTH
];
1938 if (got_sha1_digest_to_str(ie
->commit_sha1
, id_str
,
1939 sizeof(id_str
)) == NULL
) {
1940 err
= got_error_path(id_str
,
1941 GOT_ERR_BAD_OBJ_ID_STR
);
1944 if (asprintf(&label_orig
, "%s: commit %s",
1945 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
1946 err
= got_error_from_errno("asprintf");
1950 if (S_ISLNK(te
->mode
) && S_ISLNK(sb
.st_mode
)) {
1952 err
= got_object_blob_read_to_str(&link_target
, blob
);
1955 err
= merge_symlink(worktree
, blob2
, ondisk_path
, path
,
1956 label_orig
, link_target
, worktree
->base_commit_id
,
1957 repo
, progress_cb
, progress_arg
);
1960 err
= merge_blob(&update_timestamps
, worktree
, blob2
,
1961 ondisk_path
, path
, sb
.st_mode
, label_orig
, blob
,
1962 worktree
->base_commit_id
, repo
,
1963 progress_cb
, progress_arg
);
1966 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
) {
1967 err
= got_error_from_errno("close");
1971 got_object_blob_close(blob2
);
1975 * Do not update timestamps of files with local changes.
1976 * Otherwise, a future status walk would treat them as
1977 * unmodified files again.
1979 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
1980 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
,
1982 } else if (status
== GOT_STATUS_MODE_CHANGE
) {
1983 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
1984 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
1985 } else if (status
== GOT_STATUS_DELETE
) {
1986 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
1989 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
1990 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
1994 int is_bad_symlink
= 0;
1995 if (S_ISLNK(te
->mode
)) {
1996 err
= install_symlink(&is_bad_symlink
, worktree
,
1997 ondisk_path
, path
, blob
,
1998 status
== GOT_STATUS_MISSING
, 0,
1999 status
== GOT_STATUS_UNVERSIONED
, 0,
2000 repo
, progress_cb
, progress_arg
);
2002 err
= install_blob(worktree
, ondisk_path
, path
,
2003 te
->mode
, sb
.st_mode
, blob
,
2004 status
== GOT_STATUS_MISSING
, 0, 0,
2005 status
== GOT_STATUS_UNVERSIONED
, repo
,
2006 progress_cb
, progress_arg
);
2012 err
= got_fileindex_entry_update(ie
,
2013 worktree
->root_fd
, path
, blob
->id
.sha1
,
2014 worktree
->base_commit_id
->sha1
, 1);
2016 err
= create_fileindex_entry(&ie
, fileindex
,
2017 worktree
->base_commit_id
, worktree
->root_fd
, path
,
2023 if (is_bad_symlink
) {
2024 got_fileindex_entry_filetype_set(ie
,
2025 GOT_FILEIDX_MODE_BAD_SYMLINK
);
2029 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
) {
2030 err
= got_error_from_errno("close");
2033 got_object_blob_close(blob
);
2039 static const struct got_error
*
2040 remove_ondisk_file(const char *root_path
, const char *path
)
2042 const struct got_error
*err
= NULL
;
2043 char *ondisk_path
= NULL
, *parent
= NULL
;
2045 if (asprintf(&ondisk_path
, "%s/%s", root_path
, path
) == -1)
2046 return got_error_from_errno("asprintf");
2048 if (unlink(ondisk_path
) == -1) {
2049 if (errno
!= ENOENT
)
2050 err
= got_error_from_errno2("unlink", ondisk_path
);
2052 size_t root_len
= strlen(root_path
);
2053 err
= got_path_dirname(&parent
, ondisk_path
);
2056 while (got_path_cmp(parent
, root_path
,
2057 strlen(parent
), root_len
) != 0) {
2059 ondisk_path
= parent
;
2061 if (rmdir(ondisk_path
) == -1) {
2062 if (errno
!= ENOTEMPTY
)
2063 err
= got_error_from_errno2("rmdir",
2067 err
= got_path_dirname(&parent
, ondisk_path
);
2078 static const struct got_error
*
2079 delete_blob(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2080 struct got_fileindex_entry
*ie
, struct got_repository
*repo
,
2081 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2083 const struct got_error
*err
= NULL
;
2084 unsigned char status
;
2088 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
2089 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
2091 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, ie
->path
)
2093 return got_error_from_errno("asprintf");
2095 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, repo
);
2099 if (S_ISLNK(sb
.st_mode
) && status
!= GOT_STATUS_NO_CHANGE
) {
2100 char ondisk_target
[PATH_MAX
];
2101 ssize_t ondisk_len
= readlink(ondisk_path
, ondisk_target
,
2102 sizeof(ondisk_target
));
2103 if (ondisk_len
== -1) {
2104 err
= got_error_from_errno2("readlink", ondisk_path
);
2107 ondisk_target
[ondisk_len
] = '\0';
2108 err
= install_symlink_conflict(NULL
, worktree
->base_commit_id
,
2109 NULL
, NULL
, /* XXX pass common ancestor info? */
2110 ondisk_target
, ondisk_path
);
2113 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
2118 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_CONFLICT
||
2119 status
== GOT_STATUS_ADD
) {
2120 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, ie
->path
);
2124 * Preserve the working file and change the deleted blob's
2125 * entry into a schedule-add entry.
2127 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
,
2128 ie
->path
, NULL
, NULL
, 0);
2130 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_DELETE
, ie
->path
);
2133 if (status
== GOT_STATUS_NO_CHANGE
) {
2134 err
= remove_ondisk_file(worktree
->root_path
, ie
->path
);
2138 got_fileindex_entry_remove(fileindex
, ie
);
2145 struct diff_cb_arg
{
2146 struct got_fileindex
*fileindex
;
2147 struct got_worktree
*worktree
;
2148 struct got_repository
*repo
;
2149 got_worktree_checkout_cb progress_cb
;
2151 got_cancel_cb cancel_cb
;
2155 static const struct got_error
*
2156 diff_old_new(void *arg
, struct got_fileindex_entry
*ie
,
2157 struct got_tree_entry
*te
, const char *parent_path
)
2159 struct diff_cb_arg
*a
= arg
;
2161 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2162 return got_error(GOT_ERR_CANCELLED
);
2164 return update_blob(a
->worktree
, a
->fileindex
, ie
, te
,
2165 ie
->path
, a
->repo
, a
->progress_cb
, a
->progress_arg
);
2168 static const struct got_error
*
2169 diff_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
2171 struct diff_cb_arg
*a
= arg
;
2173 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2174 return got_error(GOT_ERR_CANCELLED
);
2176 return delete_blob(a
->worktree
, a
->fileindex
, ie
,
2177 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2180 static const struct got_error
*
2181 diff_new(void *arg
, struct got_tree_entry
*te
, const char *parent_path
)
2183 struct diff_cb_arg
*a
= arg
;
2184 const struct got_error
*err
;
2187 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2188 return got_error(GOT_ERR_CANCELLED
);
2190 if (got_object_tree_entry_is_submodule(te
))
2193 if (asprintf(&path
, "%s%s%s", parent_path
,
2194 parent_path
[0] ? "/" : "", te
->name
)
2196 return got_error_from_errno("asprintf");
2198 if (S_ISDIR(te
->mode
))
2199 err
= add_dir_on_disk(a
->worktree
, path
);
2201 err
= update_blob(a
->worktree
, a
->fileindex
, NULL
, te
, path
,
2202 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2208 const struct got_error
*
2209 got_worktree_get_uuid(char **uuidstr
, struct got_worktree
*worktree
)
2211 uint32_t uuid_status
;
2213 uuid_to_string(&worktree
->uuid
, uuidstr
, &uuid_status
);
2214 if (uuid_status
!= uuid_s_ok
) {
2216 return got_error_uuid(uuid_status
, "uuid_to_string");
2222 static const struct got_error
*
2223 get_ref_name(char **refname
, struct got_worktree
*worktree
, const char *prefix
)
2225 const struct got_error
*err
= NULL
;
2226 char *uuidstr
= NULL
;
2230 err
= got_worktree_get_uuid(&uuidstr
, worktree
);
2234 if (asprintf(refname
, "%s-%s", prefix
, uuidstr
) == -1) {
2235 err
= got_error_from_errno("asprintf");
2242 const struct got_error
*
2243 got_worktree_get_logmsg_ref_name(char **refname
, struct got_worktree
*worktree
,
2246 return get_ref_name(refname
, worktree
, prefix
);
2249 const struct got_error
*
2250 got_worktree_get_base_ref_name(char **refname
, struct got_worktree
*worktree
)
2252 return get_ref_name(refname
, worktree
, GOT_WORKTREE_BASE_REF_PREFIX
);
2255 static const struct got_error
*
2256 get_rebase_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2258 return get_ref_name(refname
, worktree
,
2259 GOT_WORKTREE_REBASE_TMP_REF_PREFIX
);
2262 static const struct got_error
*
2263 get_newbase_symref_name(char **refname
, struct got_worktree
*worktree
)
2265 return get_ref_name(refname
, worktree
, GOT_WORKTREE_NEWBASE_REF_PREFIX
);
2268 static const struct got_error
*
2269 get_rebase_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2271 return get_ref_name(refname
, worktree
,
2272 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX
);
2275 static const struct got_error
*
2276 get_rebase_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2278 return get_ref_name(refname
, worktree
,
2279 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX
);
2282 static const struct got_error
*
2283 get_histedit_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2285 return get_ref_name(refname
, worktree
,
2286 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX
);
2289 static const struct got_error
*
2290 get_histedit_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2292 return get_ref_name(refname
, worktree
,
2293 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX
);
2296 static const struct got_error
*
2297 get_histedit_base_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2299 return get_ref_name(refname
, worktree
,
2300 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX
);
2303 static const struct got_error
*
2304 get_histedit_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2306 return get_ref_name(refname
, worktree
,
2307 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX
);
2310 const struct got_error
*
2311 got_worktree_get_histedit_script_path(char **path
,
2312 struct got_worktree
*worktree
)
2314 if (asprintf(path
, "%s/%s/%s", worktree
->root_path
,
2315 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_HISTEDIT_SCRIPT
) == -1) {
2317 return got_error_from_errno("asprintf");
2322 static const struct got_error
*
2323 get_merge_branch_ref_name(char **refname
, struct got_worktree
*worktree
)
2325 return get_ref_name(refname
, worktree
,
2326 GOT_WORKTREE_MERGE_BRANCH_REF_PREFIX
);
2329 static const struct got_error
*
2330 get_merge_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2332 return get_ref_name(refname
, worktree
,
2333 GOT_WORKTREE_MERGE_COMMIT_REF_PREFIX
);
2337 * Prevent Git's garbage collector from deleting our base commit by
2338 * setting a reference to our base commit's ID.
2340 static const struct got_error
*
2341 ref_base_commit(struct got_worktree
*worktree
, struct got_repository
*repo
)
2343 const struct got_error
*err
= NULL
;
2344 struct got_reference
*ref
= NULL
;
2347 err
= got_worktree_get_base_ref_name(&refname
, worktree
);
2351 err
= got_ref_alloc(&ref
, refname
, worktree
->base_commit_id
);
2355 err
= got_ref_write(ref
, repo
);
2363 static const struct got_error
*
2364 get_fileindex_path(char **fileindex_path
, struct got_worktree
*worktree
)
2366 const struct got_error
*err
= NULL
;
2368 if (asprintf(fileindex_path
, "%s/%s/%s", worktree
->root_path
,
2369 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_FILE_INDEX
) == -1) {
2370 err
= got_error_from_errno("asprintf");
2371 *fileindex_path
= NULL
;
2377 static const struct got_error
*
2378 open_fileindex(struct got_fileindex
**fileindex
, char **fileindex_path
,
2379 struct got_worktree
*worktree
)
2381 const struct got_error
*err
= NULL
;
2384 *fileindex_path
= NULL
;
2385 *fileindex
= got_fileindex_alloc();
2386 if (*fileindex
== NULL
)
2387 return got_error_from_errno("got_fileindex_alloc");
2389 err
= get_fileindex_path(fileindex_path
, worktree
);
2393 index
= fopen(*fileindex_path
, "rbe");
2394 if (index
== NULL
) {
2395 if (errno
!= ENOENT
)
2396 err
= got_error_from_errno2("fopen", *fileindex_path
);
2398 err
= got_fileindex_read(*fileindex
, index
);
2399 if (fclose(index
) == EOF
&& err
== NULL
)
2400 err
= got_error_from_errno("fclose");
2404 free(*fileindex_path
);
2405 *fileindex_path
= NULL
;
2406 got_fileindex_free(*fileindex
);
2412 struct bump_base_commit_id_arg
{
2413 struct got_object_id
*base_commit_id
;
2416 const char *entry_name
;
2417 got_worktree_checkout_cb progress_cb
;
2421 /* Bump base commit ID of all files within an updated part of the work tree. */
2422 static const struct got_error
*
2423 bump_base_commit_id(void *arg
, struct got_fileindex_entry
*ie
)
2425 const struct got_error
*err
;
2426 struct bump_base_commit_id_arg
*a
= arg
;
2428 if (a
->entry_name
) {
2429 if (strcmp(ie
->path
, a
->path
) != 0)
2431 } else if (!got_path_is_child(ie
->path
, a
->path
, a
->path_len
))
2434 if (got_fileindex_entry_was_skipped(ie
))
2437 if (memcmp(ie
->commit_sha1
, a
->base_commit_id
->sha1
,
2438 SHA1_DIGEST_LENGTH
) == 0)
2441 if (a
->progress_cb
) {
2442 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_BUMP_BASE
,
2447 memcpy(ie
->commit_sha1
, a
->base_commit_id
->sha1
, SHA1_DIGEST_LENGTH
);
2451 static const struct got_error
*
2452 bump_base_commit_id_everywhere(struct got_worktree
*worktree
,
2453 struct got_fileindex
*fileindex
,
2454 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2456 struct bump_base_commit_id_arg bbc_arg
;
2458 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2459 bbc_arg
.entry_name
= NULL
;
2461 bbc_arg
.path_len
= 0;
2462 bbc_arg
.progress_cb
= progress_cb
;
2463 bbc_arg
.progress_arg
= progress_arg
;
2465 return got_fileindex_for_each_entry_safe(fileindex
,
2466 bump_base_commit_id
, &bbc_arg
);
2469 static const struct got_error
*
2470 sync_fileindex(struct got_fileindex
*fileindex
, const char *fileindex_path
)
2472 const struct got_error
*err
= NULL
;
2473 char *new_fileindex_path
= NULL
;
2474 FILE *new_index
= NULL
;
2475 struct timespec timeout
;
2477 err
= got_opentemp_named(&new_fileindex_path
, &new_index
,
2478 fileindex_path
, "");
2482 err
= got_fileindex_write(fileindex
, new_index
);
2486 if (rename(new_fileindex_path
, fileindex_path
) != 0) {
2487 err
= got_error_from_errno3("rename", new_fileindex_path
,
2489 unlink(new_fileindex_path
);
2493 * Sleep for a short amount of time to ensure that files modified after
2494 * this program exits have a different time stamp from the one which
2495 * was recorded in the file index.
2498 timeout
.tv_nsec
= 1;
2499 nanosleep(&timeout
, NULL
);
2503 free(new_fileindex_path
);
2507 static const struct got_error
*
2508 find_tree_entry_for_checkout(int *entry_type
, char **tree_relpath
,
2509 struct got_object_id
**tree_id
, const char *wt_relpath
,
2510 struct got_commit_object
*base_commit
, struct got_worktree
*worktree
,
2511 struct got_repository
*repo
)
2513 const struct got_error
*err
= NULL
;
2514 struct got_object_id
*id
= NULL
;
2515 char *in_repo_path
= NULL
;
2516 int is_root_wt
= got_path_is_root_dir(worktree
->path_prefix
);
2518 *entry_type
= GOT_OBJ_TYPE_ANY
;
2519 *tree_relpath
= NULL
;
2522 if (wt_relpath
[0] == '\0') {
2523 /* Check out all files within the work tree. */
2524 *entry_type
= GOT_OBJ_TYPE_TREE
;
2525 *tree_relpath
= strdup("");
2526 if (*tree_relpath
== NULL
) {
2527 err
= got_error_from_errno("strdup");
2530 err
= got_object_id_by_path(tree_id
, repo
, base_commit
,
2531 worktree
->path_prefix
);
2537 /* Check out a subset of files in the work tree. */
2539 if (asprintf(&in_repo_path
, "%s%s%s", worktree
->path_prefix
,
2540 is_root_wt
? "" : "/", wt_relpath
) == -1) {
2541 err
= got_error_from_errno("asprintf");
2545 err
= got_object_id_by_path(&id
, repo
, base_commit
, in_repo_path
);
2550 in_repo_path
= NULL
;
2552 err
= got_object_get_type(entry_type
, repo
, id
);
2556 if (*entry_type
== GOT_OBJ_TYPE_BLOB
) {
2557 /* Check out a single file. */
2558 if (strchr(wt_relpath
, '/') == NULL
) {
2559 /* Check out a single file in work tree's root dir. */
2560 in_repo_path
= strdup(worktree
->path_prefix
);
2561 if (in_repo_path
== NULL
) {
2562 err
= got_error_from_errno("strdup");
2565 *tree_relpath
= strdup("");
2566 if (*tree_relpath
== NULL
) {
2567 err
= got_error_from_errno("strdup");
2571 /* Check out a single file in a subdirectory. */
2572 err
= got_path_dirname(tree_relpath
, wt_relpath
);
2575 if (asprintf(&in_repo_path
, "%s%s%s",
2576 worktree
->path_prefix
, is_root_wt
? "" : "/",
2577 *tree_relpath
) == -1) {
2578 err
= got_error_from_errno("asprintf");
2582 err
= got_object_id_by_path(tree_id
, repo
,
2583 base_commit
, in_repo_path
);
2585 /* Check out all files within a subdirectory. */
2586 *tree_id
= got_object_id_dup(id
);
2587 if (*tree_id
== NULL
) {
2588 err
= got_error_from_errno("got_object_id_dup");
2591 *tree_relpath
= strdup(wt_relpath
);
2592 if (*tree_relpath
== NULL
) {
2593 err
= got_error_from_errno("strdup");
2601 *entry_type
= GOT_OBJ_TYPE_ANY
;
2602 free(*tree_relpath
);
2603 *tree_relpath
= NULL
;
2610 static const struct got_error
*
2611 checkout_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2612 const char *relpath
, struct got_object_id
*tree_id
, const char *entry_name
,
2613 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
2614 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
2616 const struct got_error
*err
= NULL
;
2617 struct got_commit_object
*commit
= NULL
;
2618 struct got_tree_object
*tree
= NULL
;
2619 struct got_fileindex_diff_tree_cb diff_cb
;
2620 struct diff_cb_arg arg
;
2622 err
= ref_base_commit(worktree
, repo
);
2624 if (!(err
->code
== GOT_ERR_ERRNO
&&
2625 (errno
== EACCES
|| errno
== EROFS
)))
2627 err
= (*progress_cb
)(progress_arg
,
2628 GOT_STATUS_BASE_REF_ERR
, worktree
->root_path
);
2633 err
= got_object_open_as_commit(&commit
, repo
,
2634 worktree
->base_commit_id
);
2638 err
= got_object_open_as_tree(&tree
, repo
, tree_id
);
2643 got_object_tree_find_entry(tree
, entry_name
) == NULL
) {
2644 err
= got_error_path(entry_name
, GOT_ERR_NO_TREE_ENTRY
);
2648 diff_cb
.diff_old_new
= diff_old_new
;
2649 diff_cb
.diff_old
= diff_old
;
2650 diff_cb
.diff_new
= diff_new
;
2651 arg
.fileindex
= fileindex
;
2652 arg
.worktree
= worktree
;
2654 arg
.progress_cb
= progress_cb
;
2655 arg
.progress_arg
= progress_arg
;
2656 arg
.cancel_cb
= cancel_cb
;
2657 arg
.cancel_arg
= cancel_arg
;
2658 err
= got_fileindex_diff_tree(fileindex
, tree
, relpath
,
2659 entry_name
, repo
, &diff_cb
, &arg
);
2662 got_object_tree_close(tree
);
2664 got_object_commit_close(commit
);
2668 const struct got_error
*
2669 got_worktree_checkout_files(struct got_worktree
*worktree
,
2670 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
2671 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
2672 got_cancel_cb cancel_cb
, void *cancel_arg
)
2674 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
2675 struct got_commit_object
*commit
= NULL
;
2676 struct got_tree_object
*tree
= NULL
;
2677 struct got_fileindex
*fileindex
= NULL
;
2678 char *fileindex_path
= NULL
;
2679 struct got_pathlist_entry
*pe
;
2680 struct tree_path_data
{
2681 STAILQ_ENTRY(tree_path_data
) entry
;
2682 struct got_object_id
*tree_id
;
2687 STAILQ_HEAD(tree_paths
, tree_path_data
) tree_paths
;
2689 STAILQ_INIT(&tree_paths
);
2691 err
= lock_worktree(worktree
, LOCK_EX
);
2695 err
= got_object_open_as_commit(&commit
, repo
,
2696 worktree
->base_commit_id
);
2700 /* Map all specified paths to in-repository trees. */
2701 TAILQ_FOREACH(pe
, paths
, entry
) {
2702 tpd
= malloc(sizeof(*tpd
));
2704 err
= got_error_from_errno("malloc");
2708 err
= find_tree_entry_for_checkout(&tpd
->entry_type
,
2709 &tpd
->relpath
, &tpd
->tree_id
, pe
->path
, commit
,
2716 if (tpd
->entry_type
== GOT_OBJ_TYPE_BLOB
) {
2717 err
= got_path_basename(&tpd
->entry_name
, pe
->path
);
2725 tpd
->entry_name
= NULL
;
2727 STAILQ_INSERT_TAIL(&tree_paths
, tpd
, entry
);
2731 * Read the file index.
2732 * Checking out files is supposed to be an idempotent operation.
2733 * If the on-disk file index is incomplete we will try to complete it.
2735 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
2739 tpd
= STAILQ_FIRST(&tree_paths
);
2740 TAILQ_FOREACH(pe
, paths
, entry
) {
2741 struct bump_base_commit_id_arg bbc_arg
;
2743 err
= checkout_files(worktree
, fileindex
, tpd
->relpath
,
2744 tpd
->tree_id
, tpd
->entry_name
, repo
,
2745 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
2749 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2750 bbc_arg
.entry_name
= tpd
->entry_name
;
2751 bbc_arg
.path
= pe
->path
;
2752 bbc_arg
.path_len
= pe
->path_len
;
2753 bbc_arg
.progress_cb
= progress_cb
;
2754 bbc_arg
.progress_arg
= progress_arg
;
2755 err
= got_fileindex_for_each_entry_safe(fileindex
,
2756 bump_base_commit_id
, &bbc_arg
);
2760 tpd
= STAILQ_NEXT(tpd
, entry
);
2762 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
2763 if (sync_err
&& err
== NULL
)
2766 free(fileindex_path
);
2768 got_object_tree_close(tree
);
2770 got_object_commit_close(commit
);
2772 got_fileindex_free(fileindex
);
2773 while (!STAILQ_EMPTY(&tree_paths
)) {
2774 tpd
= STAILQ_FIRST(&tree_paths
);
2775 STAILQ_REMOVE_HEAD(&tree_paths
, entry
);
2780 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
2781 if (unlockerr
&& err
== NULL
)
2786 struct merge_file_cb_arg
{
2787 struct got_worktree
*worktree
;
2788 struct got_fileindex
*fileindex
;
2789 got_worktree_checkout_cb progress_cb
;
2791 got_cancel_cb cancel_cb
;
2793 const char *label_orig
;
2794 struct got_object_id
*commit_id2
;
2795 int allow_bad_symlinks
;
2798 static const struct got_error
*
2799 merge_file_cb(void *arg
, struct got_blob_object
*blob1
,
2800 struct got_blob_object
*blob2
, FILE *f1
, FILE *f2
,
2801 struct got_object_id
*id1
, struct got_object_id
*id2
,
2802 const char *path1
, const char *path2
,
2803 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
2805 static const struct got_error
*err
= NULL
;
2806 struct merge_file_cb_arg
*a
= arg
;
2807 struct got_fileindex_entry
*ie
;
2808 char *ondisk_path
= NULL
;
2810 unsigned char status
;
2811 int local_changes_subsumed
;
2812 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
2813 char *id_str
= NULL
, *label_deriv2
= NULL
;
2815 if (blob1
&& blob2
) {
2816 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
2819 return (*a
->progress_cb
)(a
->progress_arg
,
2820 GOT_STATUS_MISSING
, path2
);
2822 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2824 return got_error_from_errno("asprintf");
2826 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2831 if (status
== GOT_STATUS_DELETE
) {
2832 err
= (*a
->progress_cb
)(a
->progress_arg
,
2833 GOT_STATUS_MERGE
, path2
);
2836 if (status
!= GOT_STATUS_NO_CHANGE
&&
2837 status
!= GOT_STATUS_MODIFY
&&
2838 status
!= GOT_STATUS_CONFLICT
&&
2839 status
!= GOT_STATUS_ADD
) {
2840 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path2
);
2844 if (S_ISLNK(mode1
) && S_ISLNK(mode2
)) {
2846 err
= got_object_blob_read_to_str(&link_target2
, blob2
);
2849 err
= merge_symlink(a
->worktree
, blob1
, ondisk_path
,
2850 path2
, a
->label_orig
, link_target2
, a
->commit_id2
,
2851 repo
, a
->progress_cb
, a
->progress_arg
);
2856 f_orig
= got_opentemp();
2857 if (f_orig
== NULL
) {
2858 err
= got_error_from_errno("got_opentemp");
2861 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2866 f_deriv2
= got_opentemp();
2867 if (f_deriv2
== NULL
)
2869 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2874 fd
= open(ondisk_path
,
2875 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
2877 err
= got_error_from_errno2("open",
2881 f_deriv
= fdopen(fd
, "r");
2882 if (f_deriv
== NULL
) {
2883 err
= got_error_from_errno2("fdopen",
2888 err
= got_object_id_str(&id_str
, a
->commit_id2
);
2891 if (asprintf(&label_deriv2
, "%s: commit %s",
2892 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
2893 err
= got_error_from_errno("asprintf");
2896 err
= merge_file(&local_changes_subsumed
, a
->worktree
,
2897 f_orig
, f_deriv
, f_deriv2
, ondisk_path
, path2
,
2898 mode2
, a
->label_orig
, NULL
, label_deriv2
,
2899 GOT_DIFF_ALGORITHM_PATIENCE
, repo
,
2900 a
->progress_cb
, a
->progress_arg
);
2903 ie
= got_fileindex_entry_get(a
->fileindex
, path1
,
2906 return (*a
->progress_cb
)(a
->progress_arg
,
2907 GOT_STATUS_MISSING
, path1
);
2909 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2911 return got_error_from_errno("asprintf");
2913 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2919 case GOT_STATUS_NO_CHANGE
:
2920 err
= (*a
->progress_cb
)(a
->progress_arg
,
2921 GOT_STATUS_DELETE
, path1
);
2924 err
= remove_ondisk_file(a
->worktree
->root_path
, path1
);
2928 got_fileindex_entry_mark_deleted_from_disk(ie
);
2930 case GOT_STATUS_DELETE
:
2931 case GOT_STATUS_MISSING
:
2932 err
= (*a
->progress_cb
)(a
->progress_arg
,
2933 GOT_STATUS_DELETE
, path1
);
2937 got_fileindex_entry_mark_deleted_from_disk(ie
);
2939 case GOT_STATUS_ADD
: {
2940 struct got_object_id
*id
;
2944 * Delete the added file only if its content already
2945 * exists in the repository.
2947 err
= got_object_blob_file_create(&id
, &blob1_f
,
2948 &blob1_size
, path1
);
2951 if (got_object_id_cmp(id
, id1
) == 0) {
2952 err
= (*a
->progress_cb
)(a
->progress_arg
,
2953 GOT_STATUS_DELETE
, path1
);
2956 err
= remove_ondisk_file(a
->worktree
->root_path
,
2961 got_fileindex_entry_remove(a
->fileindex
,
2964 err
= (*a
->progress_cb
)(a
->progress_arg
,
2965 GOT_STATUS_CANNOT_DELETE
, path1
);
2967 if (fclose(blob1_f
) == EOF
&& err
== NULL
)
2968 err
= got_error_from_errno("fclose");
2974 case GOT_STATUS_MODIFY
:
2975 case GOT_STATUS_CONFLICT
:
2976 err
= (*a
->progress_cb
)(a
->progress_arg
,
2977 GOT_STATUS_CANNOT_DELETE
, path1
);
2981 case GOT_STATUS_OBSTRUCTED
:
2982 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path1
);
2990 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2992 return got_error_from_errno("asprintf");
2993 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
2996 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
3000 if (status
!= GOT_STATUS_NO_CHANGE
&&
3001 status
!= GOT_STATUS_MODIFY
&&
3002 status
!= GOT_STATUS_CONFLICT
&&
3003 status
!= GOT_STATUS_ADD
) {
3004 err
= (*a
->progress_cb
)(a
->progress_arg
,
3008 if (S_ISLNK(mode2
) && S_ISLNK(sb
.st_mode
)) {
3010 err
= got_object_blob_read_to_str(&link_target2
,
3014 err
= merge_symlink(a
->worktree
, NULL
,
3015 ondisk_path
, path2
, a
->label_orig
,
3016 link_target2
, a
->commit_id2
, repo
,
3017 a
->progress_cb
, a
->progress_arg
);
3019 } else if (S_ISREG(sb
.st_mode
)) {
3020 err
= merge_blob(&local_changes_subsumed
,
3021 a
->worktree
, NULL
, ondisk_path
, path2
,
3022 sb
.st_mode
, a
->label_orig
, blob2
,
3023 a
->commit_id2
, repo
, a
->progress_cb
,
3026 err
= got_error_path(ondisk_path
,
3027 GOT_ERR_FILE_OBSTRUCTED
);
3031 if (status
== GOT_STATUS_DELETE
) {
3032 err
= got_fileindex_entry_update(ie
,
3033 a
->worktree
->root_fd
, path2
, blob2
->id
.sha1
,
3034 a
->worktree
->base_commit_id
->sha1
, 0);
3039 int is_bad_symlink
= 0;
3040 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
3041 if (S_ISLNK(mode2
)) {
3042 err
= install_symlink(&is_bad_symlink
,
3043 a
->worktree
, ondisk_path
, path2
, blob2
, 0,
3044 0, 1, a
->allow_bad_symlinks
, repo
,
3045 a
->progress_cb
, a
->progress_arg
);
3047 err
= install_blob(a
->worktree
, ondisk_path
, path2
,
3048 mode2
, sb
.st_mode
, blob2
, 0, 0, 0, 1, repo
,
3049 a
->progress_cb
, a
->progress_arg
);
3053 err
= got_fileindex_entry_alloc(&ie
, path2
);
3056 err
= got_fileindex_entry_update(ie
,
3057 a
->worktree
->root_fd
, path2
, NULL
, NULL
, 1);
3059 got_fileindex_entry_free(ie
);
3062 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
3064 got_fileindex_entry_free(ie
);
3067 if (is_bad_symlink
) {
3068 got_fileindex_entry_filetype_set(ie
,
3069 GOT_FILEIDX_MODE_BAD_SYMLINK
);
3074 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
3075 err
= got_error_from_errno("fclose");
3076 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
3077 err
= got_error_from_errno("fclose");
3078 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
3079 err
= got_error_from_errno("fclose");
3086 static const struct got_error
*
3087 check_mixed_commits(void *arg
, struct got_fileindex_entry
*ie
)
3089 struct got_worktree
*worktree
= arg
;
3091 /* Reject merges into a work tree with mixed base commits. */
3092 if (got_fileindex_entry_has_commit(ie
) &&
3093 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
3094 SHA1_DIGEST_LENGTH
) != 0)
3095 return got_error(GOT_ERR_MIXED_COMMITS
);
3100 struct check_merge_conflicts_arg
{
3101 struct got_worktree
*worktree
;
3102 struct got_fileindex
*fileindex
;
3103 struct got_repository
*repo
;
3106 static const struct got_error
*
3107 check_merge_conflicts(void *arg
, struct got_blob_object
*blob1
,
3108 struct got_blob_object
*blob2
, FILE *f1
, FILE *f2
,
3109 struct got_object_id
*id1
, struct got_object_id
*id2
,
3110 const char *path1
, const char *path2
,
3111 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
3113 const struct got_error
*err
= NULL
;
3114 struct check_merge_conflicts_arg
*a
= arg
;
3115 unsigned char status
;
3117 struct got_fileindex_entry
*ie
;
3118 const char *path
= path2
? path2
: path1
;
3119 struct got_object_id
*id
= id2
? id2
: id1
;
3125 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
3129 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
3131 return got_error_from_errno("asprintf");
3133 /* Reject merges into a work tree with conflicted files. */
3134 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
3138 if (status
== GOT_STATUS_CONFLICT
)
3139 return got_error(GOT_ERR_CONFLICTS
);
3144 static const struct got_error
*
3145 merge_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
3146 const char *fileindex_path
, struct got_object_id
*commit_id1
,
3147 struct got_object_id
*commit_id2
, struct got_repository
*repo
,
3148 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
3149 got_cancel_cb cancel_cb
, void *cancel_arg
)
3151 const struct got_error
*err
= NULL
, *sync_err
;
3152 struct got_object_id
*tree_id1
= NULL
, *tree_id2
= NULL
;
3153 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
3154 struct got_commit_object
*commit1
= NULL
, *commit2
= NULL
;
3155 struct check_merge_conflicts_arg cmc_arg
;
3156 struct merge_file_cb_arg arg
;
3157 char *label_orig
= NULL
;
3158 FILE *f1
= NULL
, *f2
= NULL
;
3159 int fd1
= -1, fd2
= -1;
3162 err
= got_object_open_as_commit(&commit1
, repo
, commit_id1
);
3165 err
= got_object_id_by_path(&tree_id1
, repo
, commit1
,
3166 worktree
->path_prefix
);
3167 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
3173 err
= got_object_open_as_tree(&tree1
, repo
, tree_id1
);
3177 err
= got_object_id_str(&id_str
, commit_id1
);
3181 if (asprintf(&label_orig
, "%s: commit %s",
3182 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
3183 err
= got_error_from_errno("asprintf");
3189 f1
= got_opentemp();
3191 err
= got_error_from_errno("got_opentemp");
3196 err
= got_object_open_as_commit(&commit2
, repo
, commit_id2
);
3200 err
= got_object_id_by_path(&tree_id2
, repo
, commit2
,
3201 worktree
->path_prefix
);
3205 err
= got_object_open_as_tree(&tree2
, repo
, tree_id2
);
3209 f2
= got_opentemp();
3211 err
= got_error_from_errno("got_opentemp");
3215 fd1
= got_opentempfd();
3217 err
= got_error_from_errno("got_opentempfd");
3221 fd2
= got_opentempfd();
3223 err
= got_error_from_errno("got_opentempfd");
3227 cmc_arg
.worktree
= worktree
;
3228 cmc_arg
.fileindex
= fileindex
;
3229 cmc_arg
.repo
= repo
;
3230 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
3231 check_merge_conflicts
, &cmc_arg
, 0);
3235 arg
.worktree
= worktree
;
3236 arg
.fileindex
= fileindex
;
3237 arg
.progress_cb
= progress_cb
;
3238 arg
.progress_arg
= progress_arg
;
3239 arg
.cancel_cb
= cancel_cb
;
3240 arg
.cancel_arg
= cancel_arg
;
3241 arg
.label_orig
= label_orig
;
3242 arg
.commit_id2
= commit_id2
;
3243 arg
.allow_bad_symlinks
= 1; /* preserve bad symlinks across merges */
3244 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
3245 merge_file_cb
, &arg
, 1);
3246 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
3247 if (sync_err
&& err
== NULL
)
3251 got_object_commit_close(commit1
);
3253 got_object_commit_close(commit2
);
3255 got_object_tree_close(tree1
);
3257 got_object_tree_close(tree2
);
3258 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
3259 err
= got_error_from_errno("fclose");
3260 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
3261 err
= got_error_from_errno("fclose");
3262 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
3263 err
= got_error_from_errno("close");
3264 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
3265 err
= got_error_from_errno("close");
3270 const struct got_error
*
3271 got_worktree_merge_files(struct got_worktree
*worktree
,
3272 struct got_object_id
*commit_id1
, struct got_object_id
*commit_id2
,
3273 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
3274 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
3276 const struct got_error
*err
, *unlockerr
;
3277 char *fileindex_path
= NULL
;
3278 struct got_fileindex
*fileindex
= NULL
;
3280 err
= lock_worktree(worktree
, LOCK_EX
);
3284 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3288 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
3293 err
= merge_files(worktree
, fileindex
, fileindex_path
, commit_id1
,
3294 commit_id2
, repo
, progress_cb
, progress_arg
,
3295 cancel_cb
, cancel_arg
);
3298 got_fileindex_free(fileindex
);
3299 free(fileindex_path
);
3300 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
3301 if (unlockerr
&& err
== NULL
)
3306 struct diff_dir_cb_arg
{
3307 struct got_fileindex
*fileindex
;
3308 struct got_worktree
*worktree
;
3309 const char *status_path
;
3310 size_t status_path_len
;
3311 struct got_repository
*repo
;
3312 got_worktree_status_cb status_cb
;
3314 got_cancel_cb cancel_cb
;
3316 /* A pathlist containing per-directory pathlists of ignore patterns. */
3317 struct got_pathlist_head
*ignores
;
3318 int report_unchanged
;
3322 static const struct got_error
*
3323 report_file_status(struct got_fileindex_entry
*ie
, const char *abspath
,
3324 int dirfd
, const char *de_name
,
3325 got_worktree_status_cb status_cb
, void *status_arg
,
3326 struct got_repository
*repo
, int report_unchanged
)
3328 const struct got_error
*err
= NULL
;
3329 unsigned char status
= GOT_STATUS_NO_CHANGE
;
3330 unsigned char staged_status
= get_staged_status(ie
);
3332 struct got_object_id blob_id
, commit_id
, staged_blob_id
;
3333 struct got_object_id
*blob_idp
= NULL
, *commit_idp
= NULL
;
3334 struct got_object_id
*staged_blob_idp
= NULL
;
3336 err
= get_file_status(&status
, &sb
, ie
, abspath
, dirfd
, de_name
, repo
);
3340 if (status
== GOT_STATUS_NO_CHANGE
&&
3341 staged_status
== GOT_STATUS_NO_CHANGE
&& !report_unchanged
)
3344 if (got_fileindex_entry_has_blob(ie
)) {
3345 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3346 blob_idp
= &blob_id
;
3348 if (got_fileindex_entry_has_commit(ie
)) {
3349 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3350 commit_idp
= &commit_id
;
3352 if (staged_status
== GOT_STATUS_ADD
||
3353 staged_status
== GOT_STATUS_MODIFY
) {
3354 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
3355 SHA1_DIGEST_LENGTH
);
3356 staged_blob_idp
= &staged_blob_id
;
3359 return (*status_cb
)(status_arg
, status
, staged_status
,
3360 ie
->path
, blob_idp
, staged_blob_idp
, commit_idp
, dirfd
, de_name
);
3363 static const struct got_error
*
3364 status_old_new(void *arg
, struct got_fileindex_entry
*ie
,
3365 struct dirent
*de
, const char *parent_path
, int dirfd
)
3367 const struct got_error
*err
= NULL
;
3368 struct diff_dir_cb_arg
*a
= arg
;
3371 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3372 return got_error(GOT_ERR_CANCELLED
);
3374 if (got_path_cmp(parent_path
, a
->status_path
,
3375 strlen(parent_path
), a
->status_path_len
) != 0 &&
3376 !got_path_is_child(parent_path
, a
->status_path
, a
->status_path_len
))
3379 if (parent_path
[0]) {
3380 if (asprintf(&abspath
, "%s/%s/%s", a
->worktree
->root_path
,
3381 parent_path
, de
->d_name
) == -1)
3382 return got_error_from_errno("asprintf");
3384 if (asprintf(&abspath
, "%s/%s", a
->worktree
->root_path
,
3386 return got_error_from_errno("asprintf");
3389 err
= report_file_status(ie
, abspath
, dirfd
, de
->d_name
,
3390 a
->status_cb
, a
->status_arg
, a
->repo
, a
->report_unchanged
);
3395 static const struct got_error
*
3396 status_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
3398 struct diff_dir_cb_arg
*a
= arg
;
3399 struct got_object_id blob_id
, commit_id
;
3400 unsigned char status
;
3402 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3403 return got_error(GOT_ERR_CANCELLED
);
3405 if (!got_path_is_child(ie
->path
, a
->status_path
, a
->status_path_len
))
3408 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3409 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3410 if (got_fileindex_entry_has_file_on_disk(ie
))
3411 status
= GOT_STATUS_MISSING
;
3413 status
= GOT_STATUS_DELETE
;
3414 return (*a
->status_cb
)(a
->status_arg
, status
, get_staged_status(ie
),
3415 ie
->path
, &blob_id
, NULL
, &commit_id
, -1, NULL
);
3419 free_ignores(struct got_pathlist_head
*ignores
)
3421 struct got_pathlist_entry
*pe
;
3423 TAILQ_FOREACH(pe
, ignores
, entry
) {
3424 struct got_pathlist_head
*ignorelist
= pe
->data
;
3426 got_pathlist_free(ignorelist
, GOT_PATHLIST_FREE_PATH
);
3428 got_pathlist_free(ignores
, GOT_PATHLIST_FREE_PATH
);
3431 static const struct got_error
*
3432 read_ignores(struct got_pathlist_head
*ignores
, const char *path
, FILE *f
)
3434 const struct got_error
*err
= NULL
;
3435 struct got_pathlist_entry
*pe
= NULL
;
3436 struct got_pathlist_head
*ignorelist
;
3437 char *line
= NULL
, *pattern
, *dirpath
= NULL
;
3438 size_t linesize
= 0;
3441 ignorelist
= calloc(1, sizeof(*ignorelist
));
3442 if (ignorelist
== NULL
)
3443 return got_error_from_errno("calloc");
3444 TAILQ_INIT(ignorelist
);
3446 while ((linelen
= getline(&line
, &linesize
, f
)) != -1) {
3447 if (linelen
> 0 && line
[linelen
- 1] == '\n')
3448 line
[linelen
- 1] = '\0';
3450 /* Git's ignores may contain comments. */
3454 /* Git's negated patterns are not (yet?) supported. */
3458 if (asprintf(&pattern
, "%s%s%s", path
, path
[0] ? "/" : "",
3460 err
= got_error_from_errno("asprintf");
3463 err
= got_pathlist_insert(NULL
, ignorelist
, pattern
, NULL
);
3468 err
= got_error_from_errno("getline");
3472 dirpath
= strdup(path
);
3473 if (dirpath
== NULL
) {
3474 err
= got_error_from_errno("strdup");
3477 err
= got_pathlist_insert(&pe
, ignores
, dirpath
, ignorelist
);
3480 if (err
|| pe
== NULL
) {
3482 got_pathlist_free(ignorelist
, GOT_PATHLIST_FREE_PATH
);
3488 match_ignores(struct got_pathlist_head
*ignores
, const char *path
)
3490 struct got_pathlist_entry
*pe
;
3492 /* Handle patterns which match in all directories. */
3493 TAILQ_FOREACH(pe
, ignores
, entry
) {
3494 struct got_pathlist_head
*ignorelist
= pe
->data
;
3495 struct got_pathlist_entry
*pi
;
3497 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3498 const char *p
, *pattern
= pi
->path
;
3500 if (strncmp(pattern
, "**/", 3) != 0)
3505 if (fnmatch(pattern
, p
,
3506 FNM_PATHNAME
| FNM_LEADING_DIR
)) {
3507 /* Retry in next directory. */
3508 while (*p
&& *p
!= '/')
3520 * The ignores pathlist contains ignore lists from children before
3521 * parents, so we can find the most specific ignorelist by walking
3522 * ignores backwards.
3524 pe
= TAILQ_LAST(ignores
, got_pathlist_head
);
3526 if (got_path_is_child(path
, pe
->path
, pe
->path_len
)) {
3527 struct got_pathlist_head
*ignorelist
= pe
->data
;
3528 struct got_pathlist_entry
*pi
;
3529 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3530 const char *pattern
= pi
->path
;
3531 int flags
= FNM_LEADING_DIR
;
3532 if (strstr(pattern
, "/**/") == NULL
)
3533 flags
|= FNM_PATHNAME
;
3534 if (fnmatch(pattern
, path
, flags
))
3539 pe
= TAILQ_PREV(pe
, got_pathlist_head
, entry
);
3545 static const struct got_error
*
3546 add_ignores(struct got_pathlist_head
*ignores
, const char *root_path
,
3547 const char *path
, int dirfd
, const char *ignores_filename
)
3549 const struct got_error
*err
= NULL
;
3552 FILE *ignoresfile
= NULL
;
3554 if (asprintf(&ignorespath
, "%s/%s%s%s", root_path
, path
,
3555 path
[0] ? "/" : "", ignores_filename
) == -1)
3556 return got_error_from_errno("asprintf");
3559 fd
= openat(dirfd
, ignores_filename
,
3560 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
3562 if (errno
!= ENOENT
&& errno
!= EACCES
)
3563 err
= got_error_from_errno2("openat",
3566 ignoresfile
= fdopen(fd
, "r");
3567 if (ignoresfile
== NULL
)
3568 err
= got_error_from_errno2("fdopen",
3572 err
= read_ignores(ignores
, path
, ignoresfile
);
3576 ignoresfile
= fopen(ignorespath
, "re");
3577 if (ignoresfile
== NULL
) {
3578 if (errno
!= ENOENT
&& errno
!= EACCES
)
3579 err
= got_error_from_errno2("fopen",
3582 err
= read_ignores(ignores
, path
, ignoresfile
);
3585 if (ignoresfile
&& fclose(ignoresfile
) == EOF
&& err
== NULL
)
3586 err
= got_error_from_errno2("fclose", path
);
3587 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3588 err
= got_error_from_errno2("close", path
);
3593 static const struct got_error
*
3594 status_new(int *ignore
, void *arg
, struct dirent
*de
, const char *parent_path
,
3597 const struct got_error
*err
= NULL
;
3598 struct diff_dir_cb_arg
*a
= arg
;
3604 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3605 return got_error(GOT_ERR_CANCELLED
);
3607 if (parent_path
[0]) {
3608 if (asprintf(&path
, "%s/%s", parent_path
, de
->d_name
) == -1)
3609 return got_error_from_errno("asprintf");
3614 if (de
->d_type
== DT_DIR
) {
3615 if (!a
->no_ignores
&& ignore
!= NULL
&&
3616 match_ignores(a
->ignores
, path
))
3618 } else if (!match_ignores(a
->ignores
, path
) &&
3619 got_path_is_child(path
, a
->status_path
, a
->status_path_len
))
3620 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_UNVERSIONED
,
3621 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3627 static const struct got_error
*
3628 status_traverse(void *arg
, const char *path
, int dirfd
)
3630 const struct got_error
*err
= NULL
;
3631 struct diff_dir_cb_arg
*a
= arg
;
3636 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
,
3637 path
, dirfd
, ".cvsignore");
3641 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
, path
,
3642 dirfd
, ".gitignore");
3647 static const struct got_error
*
3648 report_single_file_status(const char *path
, const char *ondisk_path
,
3649 struct got_fileindex
*fileindex
, got_worktree_status_cb status_cb
,
3650 void *status_arg
, struct got_repository
*repo
, int report_unchanged
,
3651 struct got_pathlist_head
*ignores
, int no_ignores
)
3653 struct got_fileindex_entry
*ie
;
3656 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
3658 return report_file_status(ie
, ondisk_path
, -1, NULL
,
3659 status_cb
, status_arg
, repo
, report_unchanged
);
3661 if (lstat(ondisk_path
, &sb
) == -1) {
3662 if (errno
!= ENOENT
)
3663 return got_error_from_errno2("lstat", ondisk_path
);
3664 return (*status_cb
)(status_arg
, GOT_STATUS_NONEXISTENT
,
3665 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3668 if (!no_ignores
&& match_ignores(ignores
, path
))
3671 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
3672 return (*status_cb
)(status_arg
, GOT_STATUS_UNVERSIONED
,
3673 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3678 static const struct got_error
*
3679 add_ignores_from_parent_paths(struct got_pathlist_head
*ignores
,
3680 const char *root_path
, const char *path
)
3682 const struct got_error
*err
;
3683 char *parent_path
, *next_parent_path
= NULL
;
3685 err
= add_ignores(ignores
, root_path
, "", -1,
3690 err
= add_ignores(ignores
, root_path
, "", -1,
3695 err
= got_path_dirname(&parent_path
, path
);
3697 if (err
->code
== GOT_ERR_BAD_PATH
)
3698 return NULL
; /* cannot traverse parent */
3702 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3706 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3710 err
= got_path_dirname(&next_parent_path
, parent_path
);
3712 if (err
->code
== GOT_ERR_BAD_PATH
)
3713 err
= NULL
; /* traversed everything */
3716 if (got_path_is_root_dir(parent_path
))
3719 parent_path
= next_parent_path
;
3720 next_parent_path
= NULL
;
3724 free(next_parent_path
);
3728 static const struct got_error
*
3729 worktree_status(struct got_worktree
*worktree
, const char *path
,
3730 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
3731 got_worktree_status_cb status_cb
, void *status_arg
,
3732 got_cancel_cb cancel_cb
, void *cancel_arg
, int no_ignores
,
3733 int report_unchanged
)
3735 const struct got_error
*err
= NULL
;
3737 struct got_fileindex_diff_dir_cb fdiff_cb
;
3738 struct diff_dir_cb_arg arg
;
3739 char *ondisk_path
= NULL
;
3740 struct got_pathlist_head ignores
;
3741 struct got_fileindex_entry
*ie
;
3743 TAILQ_INIT(&ignores
);
3745 if (asprintf(&ondisk_path
, "%s%s%s",
3746 worktree
->root_path
, path
[0] ? "/" : "", path
) == -1)
3747 return got_error_from_errno("asprintf");
3749 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
3751 err
= report_single_file_status(path
, ondisk_path
,
3752 fileindex
, status_cb
, status_arg
, repo
,
3753 report_unchanged
, &ignores
, no_ignores
);
3757 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_DIRECTORY
| O_CLOEXEC
);
3759 if (errno
!= ENOTDIR
&& errno
!= ENOENT
&& errno
!= EACCES
&&
3760 !got_err_open_nofollow_on_symlink())
3761 err
= got_error_from_errno2("open", ondisk_path
);
3764 err
= add_ignores_from_parent_paths(&ignores
,
3765 worktree
->root_path
, ondisk_path
);
3769 err
= report_single_file_status(path
, ondisk_path
,
3770 fileindex
, status_cb
, status_arg
, repo
,
3771 report_unchanged
, &ignores
, no_ignores
);
3774 fdiff_cb
.diff_old_new
= status_old_new
;
3775 fdiff_cb
.diff_old
= status_old
;
3776 fdiff_cb
.diff_new
= status_new
;
3777 fdiff_cb
.diff_traverse
= status_traverse
;
3778 arg
.fileindex
= fileindex
;
3779 arg
.worktree
= worktree
;
3780 arg
.status_path
= path
;
3781 arg
.status_path_len
= strlen(path
);
3783 arg
.status_cb
= status_cb
;
3784 arg
.status_arg
= status_arg
;
3785 arg
.cancel_cb
= cancel_cb
;
3786 arg
.cancel_arg
= cancel_arg
;
3787 arg
.report_unchanged
= report_unchanged
;
3788 arg
.no_ignores
= no_ignores
;
3790 err
= add_ignores_from_parent_paths(&ignores
,
3791 worktree
->root_path
, path
);
3795 arg
.ignores
= &ignores
;
3796 err
= got_fileindex_diff_dir(fileindex
, fd
,
3797 worktree
->root_path
, path
, repo
, &fdiff_cb
, &arg
);
3800 free_ignores(&ignores
);
3801 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3802 err
= got_error_from_errno("close");
3807 const struct got_error
*
3808 got_worktree_status(struct got_worktree
*worktree
,
3809 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
3810 int no_ignores
, got_worktree_status_cb status_cb
, void *status_arg
,
3811 got_cancel_cb cancel_cb
, void *cancel_arg
)
3813 const struct got_error
*err
= NULL
;
3814 char *fileindex_path
= NULL
;
3815 struct got_fileindex
*fileindex
= NULL
;
3816 struct got_pathlist_entry
*pe
;
3818 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3822 TAILQ_FOREACH(pe
, paths
, entry
) {
3823 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
3824 status_cb
, status_arg
, cancel_cb
, cancel_arg
,
3829 free(fileindex_path
);
3830 got_fileindex_free(fileindex
);
3834 const struct got_error
*
3835 got_worktree_resolve_path(char **wt_path
, struct got_worktree
*worktree
,
3838 const struct got_error
*err
= NULL
;
3839 char *resolved
= NULL
, *cwd
= NULL
, *path
= NULL
;
3842 char *abspath
= NULL
;
3843 char canonpath
[PATH_MAX
];
3847 cwd
= getcwd(NULL
, 0);
3849 return got_error_from_errno("getcwd");
3851 if (lstat(arg
, &sb
) == -1) {
3852 if (errno
!= ENOENT
) {
3853 err
= got_error_from_errno2("lstat", arg
);
3858 if (S_ISLNK(sb
.st_mode
)) {
3860 * We cannot use realpath(3) with symlinks since we want to
3861 * operate on the symlink itself.
3862 * But we can make the path absolute, assuming it is relative
3863 * to the current working directory, and then canonicalize it.
3865 if (!got_path_is_absolute(arg
)) {
3866 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3867 err
= got_error_from_errno("asprintf");
3872 err
= got_canonpath(abspath
? abspath
: arg
, canonpath
,
3876 resolved
= strdup(canonpath
);
3877 if (resolved
== NULL
) {
3878 err
= got_error_from_errno("strdup");
3882 resolved
= realpath(arg
, NULL
);
3883 if (resolved
== NULL
) {
3884 if (errno
!= ENOENT
) {
3885 err
= got_error_from_errno2("realpath", arg
);
3888 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3889 err
= got_error_from_errno("asprintf");
3892 err
= got_canonpath(abspath
, canonpath
,
3896 resolved
= strdup(canonpath
);
3897 if (resolved
== NULL
) {
3898 err
= got_error_from_errno("strdup");
3904 if (strncmp(got_worktree_get_root_path(worktree
), resolved
,
3905 strlen(got_worktree_get_root_path(worktree
)))) {
3906 err
= got_error_path(resolved
, GOT_ERR_BAD_PATH
);
3910 if (strlen(resolved
) > strlen(got_worktree_get_root_path(worktree
))) {
3911 err
= got_path_skip_common_ancestor(&path
,
3912 got_worktree_get_root_path(worktree
), resolved
);
3918 err
= got_error_from_errno("strdup");
3923 /* XXX status walk can't deal with trailing slash! */
3925 while (len
> 0 && path
[len
- 1] == '/') {
3926 path
[len
- 1] = '\0';
3940 struct schedule_addition_args
{
3941 struct got_worktree
*worktree
;
3942 struct got_fileindex
*fileindex
;
3943 got_worktree_checkout_cb progress_cb
;
3945 struct got_repository
*repo
;
3948 static const struct got_error
*
3949 schedule_addition(void *arg
, unsigned char status
, unsigned char staged_status
,
3950 const char *relpath
, struct got_object_id
*blob_id
,
3951 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
3952 int dirfd
, const char *de_name
)
3954 struct schedule_addition_args
*a
= arg
;
3955 const struct got_error
*err
= NULL
;
3956 struct got_fileindex_entry
*ie
;
3960 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3962 return got_error_from_errno("asprintf");
3964 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
3966 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
,
3970 /* Re-adding an existing entry is a no-op. */
3971 if (status
== GOT_STATUS_ADD
)
3973 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
3978 if (status
!= GOT_STATUS_UNVERSIONED
) {
3979 if (status
== GOT_STATUS_NONEXISTENT
)
3980 err
= got_error_set_errno(ENOENT
, ondisk_path
);
3982 err
= got_error_path(ondisk_path
, GOT_ERR_FILE_STATUS
);
3986 err
= got_fileindex_entry_alloc(&ie
, relpath
);
3989 err
= got_fileindex_entry_update(ie
, a
->worktree
->root_fd
,
3990 relpath
, NULL
, NULL
, 1);
3992 got_fileindex_entry_free(ie
);
3995 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
3997 got_fileindex_entry_free(ie
);
4004 if (status
== GOT_STATUS_ADD
)
4006 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_ADD
, relpath
);
4009 const struct got_error
*
4010 got_worktree_schedule_add(struct got_worktree
*worktree
,
4011 struct got_pathlist_head
*paths
,
4012 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4013 struct got_repository
*repo
, int no_ignores
)
4015 struct got_fileindex
*fileindex
= NULL
;
4016 char *fileindex_path
= NULL
;
4017 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4018 struct got_pathlist_entry
*pe
;
4019 struct schedule_addition_args saa
;
4021 err
= lock_worktree(worktree
, LOCK_EX
);
4025 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4029 saa
.worktree
= worktree
;
4030 saa
.fileindex
= fileindex
;
4031 saa
.progress_cb
= progress_cb
;
4032 saa
.progress_arg
= progress_arg
;
4035 TAILQ_FOREACH(pe
, paths
, entry
) {
4036 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4037 schedule_addition
, &saa
, NULL
, NULL
, no_ignores
, 0);
4041 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4042 if (sync_err
&& err
== NULL
)
4045 free(fileindex_path
);
4047 got_fileindex_free(fileindex
);
4048 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4049 if (unlockerr
&& err
== NULL
)
4054 struct schedule_deletion_args
{
4055 struct got_worktree
*worktree
;
4056 struct got_fileindex
*fileindex
;
4057 got_worktree_delete_cb progress_cb
;
4059 struct got_repository
*repo
;
4060 int delete_local_mods
;
4062 int ignore_missing_paths
;
4063 const char *status_codes
;
4066 static const struct got_error
*
4067 schedule_for_deletion(void *arg
, unsigned char status
,
4068 unsigned char staged_status
, const char *relpath
,
4069 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4070 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4072 struct schedule_deletion_args
*a
= arg
;
4073 const struct got_error
*err
= NULL
;
4074 struct got_fileindex_entry
*ie
= NULL
;
4078 if (status
== GOT_STATUS_NONEXISTENT
) {
4079 if (a
->ignore_missing_paths
)
4081 return got_error_set_errno(ENOENT
, relpath
);
4084 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4086 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4088 staged_status
= get_staged_status(ie
);
4089 if (staged_status
!= GOT_STATUS_NO_CHANGE
) {
4090 if (staged_status
== GOT_STATUS_DELETE
)
4092 return got_error_path(relpath
, GOT_ERR_FILE_STAGED
);
4095 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4097 return got_error_from_errno("asprintf");
4099 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
, de_name
,
4104 if (a
->status_codes
) {
4105 size_t ncodes
= strlen(a
->status_codes
);
4107 for (i
= 0; i
< ncodes
; i
++) {
4108 if (status
== a
->status_codes
[i
])
4112 /* Do not delete files in non-matching status. */
4116 if (a
->status_codes
[i
] != GOT_STATUS_MODIFY
&&
4117 a
->status_codes
[i
] != GOT_STATUS_MISSING
) {
4118 static char msg
[64];
4119 snprintf(msg
, sizeof(msg
),
4120 "invalid status code '%c'", a
->status_codes
[i
]);
4121 err
= got_error_msg(GOT_ERR_FILE_STATUS
, msg
);
4126 if (status
!= GOT_STATUS_NO_CHANGE
) {
4127 if (status
== GOT_STATUS_DELETE
)
4129 if (status
== GOT_STATUS_MODIFY
&& !a
->delete_local_mods
) {
4130 err
= got_error_path(relpath
, GOT_ERR_FILE_MODIFIED
);
4133 if (status
== GOT_STATUS_MISSING
&& !a
->ignore_missing_paths
) {
4134 err
= got_error_set_errno(ENOENT
, relpath
);
4137 if (status
!= GOT_STATUS_MODIFY
&&
4138 status
!= GOT_STATUS_MISSING
) {
4139 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4144 if (!a
->keep_on_disk
&& status
!= GOT_STATUS_MISSING
) {
4148 if (unlinkat(dirfd
, de_name
, 0) == -1) {
4149 err
= got_error_from_errno2("unlinkat",
4153 } else if (unlink(ondisk_path
) == -1) {
4154 err
= got_error_from_errno2("unlink", ondisk_path
);
4158 root_len
= strlen(a
->worktree
->root_path
);
4161 err
= got_path_dirname(&parent
, ondisk_path
);
4165 ondisk_path
= parent
;
4166 if (rmdir(ondisk_path
) == -1) {
4167 if (errno
!= ENOTEMPTY
)
4168 err
= got_error_from_errno2("rmdir",
4172 } while (got_path_cmp(ondisk_path
, a
->worktree
->root_path
,
4173 strlen(ondisk_path
), root_len
) != 0);
4176 got_fileindex_entry_mark_deleted_from_disk(ie
);
4181 if (status
== GOT_STATUS_DELETE
)
4183 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_DELETE
,
4184 staged_status
, relpath
);
4187 const struct got_error
*
4188 got_worktree_schedule_delete(struct got_worktree
*worktree
,
4189 struct got_pathlist_head
*paths
, int delete_local_mods
,
4190 const char *status_codes
,
4191 got_worktree_delete_cb progress_cb
, void *progress_arg
,
4192 struct got_repository
*repo
, int keep_on_disk
, int ignore_missing_paths
)
4194 struct got_fileindex
*fileindex
= NULL
;
4195 char *fileindex_path
= NULL
;
4196 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4197 struct got_pathlist_entry
*pe
;
4198 struct schedule_deletion_args sda
;
4200 err
= lock_worktree(worktree
, LOCK_EX
);
4204 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4208 sda
.worktree
= worktree
;
4209 sda
.fileindex
= fileindex
;
4210 sda
.progress_cb
= progress_cb
;
4211 sda
.progress_arg
= progress_arg
;
4213 sda
.delete_local_mods
= delete_local_mods
;
4214 sda
.keep_on_disk
= keep_on_disk
;
4215 sda
.ignore_missing_paths
= ignore_missing_paths
;
4216 sda
.status_codes
= status_codes
;
4218 TAILQ_FOREACH(pe
, paths
, entry
) {
4219 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4220 schedule_for_deletion
, &sda
, NULL
, NULL
, 1, 1);
4224 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4225 if (sync_err
&& err
== NULL
)
4228 free(fileindex_path
);
4230 got_fileindex_free(fileindex
);
4231 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4232 if (unlockerr
&& err
== NULL
)
4237 static const struct got_error
*
4238 copy_one_line(FILE *infile
, FILE *outfile
, FILE *rejectfile
)
4240 const struct got_error
*err
= NULL
;
4242 size_t linesize
= 0, n
;
4245 linelen
= getline(&line
, &linesize
, infile
);
4246 if (linelen
== -1) {
4247 if (ferror(infile
)) {
4248 err
= got_error_from_errno("getline");
4254 n
= fwrite(line
, 1, linelen
, outfile
);
4256 err
= got_ferror(outfile
, GOT_ERR_IO
);
4261 n
= fwrite(line
, 1, linelen
, rejectfile
);
4263 err
= got_ferror(rejectfile
, GOT_ERR_IO
);
4270 static const struct got_error
*
4271 skip_one_line(FILE *f
)
4274 size_t linesize
= 0;
4277 linelen
= getline(&line
, &linesize
, f
);
4278 if (linelen
== -1) {
4280 return got_error_from_errno("getline");
4287 static const struct got_error
*
4288 copy_change(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4289 int start_old
, int end_old
, int start_new
, int end_new
,
4290 FILE *outfile
, FILE *rejectfile
)
4292 const struct got_error
*err
;
4294 /* Copy old file's lines leading up to patch. */
4295 while (!feof(f1
) && *line_cur1
< start_old
) {
4296 err
= copy_one_line(f1
, outfile
, NULL
);
4301 /* Skip new file's lines leading up to patch. */
4302 while (!feof(f2
) && *line_cur2
< start_new
) {
4304 err
= copy_one_line(f2
, NULL
, rejectfile
);
4306 err
= skip_one_line(f2
);
4311 /* Copy patched lines. */
4312 while (!feof(f2
) && *line_cur2
<= end_new
) {
4313 err
= copy_one_line(f2
, outfile
, NULL
);
4318 /* Skip over old file's replaced lines. */
4319 while (!feof(f1
) && *line_cur1
<= end_old
) {
4321 err
= copy_one_line(f1
, NULL
, rejectfile
);
4323 err
= skip_one_line(f1
);
4332 static const struct got_error
*
4333 copy_remaining_content(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4334 FILE *outfile
, FILE *rejectfile
)
4336 const struct got_error
*err
;
4339 /* Copy old file's lines until EOF. */
4341 err
= copy_one_line(f1
, outfile
, NULL
);
4348 /* Copy new file's lines until EOF. */
4350 err
= copy_one_line(f2
, NULL
, rejectfile
);
4360 static const struct got_error
*
4361 apply_or_reject_change(int *choice
, int *nchunks_used
,
4362 struct diff_result
*diff_result
, int n
,
4363 const char *relpath
, FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4364 FILE *outfile
, FILE *rejectfile
, int changeno
, int nchanges
,
4365 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4367 const struct got_error
*err
= NULL
;
4368 struct diff_chunk_context cc
= {};
4369 int start_old
, end_old
, start_new
, end_new
;
4371 struct diff_output_unidiff_state
*diff_state
;
4372 struct diff_input_info diff_info
;
4375 *choice
= GOT_PATCH_CHOICE_NONE
;
4377 /* Get changed line numbers without context lines for copy_change(). */
4378 diff_chunk_context_load_change(&cc
, NULL
, diff_result
, n
, 0);
4379 start_old
= cc
.left
.start
;
4380 end_old
= cc
.left
.end
;
4381 start_new
= cc
.right
.start
;
4382 end_new
= cc
.right
.end
;
4384 /* Get the same change with context lines for display. */
4385 memset(&cc
, 0, sizeof(cc
));
4386 diff_chunk_context_load_change(&cc
, nchunks_used
, diff_result
, n
, 3);
4388 memset(&diff_info
, 0, sizeof(diff_info
));
4389 diff_info
.left_path
= relpath
;
4390 diff_info
.right_path
= relpath
;
4392 diff_state
= diff_output_unidiff_state_alloc();
4393 if (diff_state
== NULL
)
4394 return got_error_set_errno(ENOMEM
,
4395 "diff_output_unidiff_state_alloc");
4397 hunkfile
= got_opentemp();
4398 if (hunkfile
== NULL
) {
4399 err
= got_error_from_errno("got_opentemp");
4403 rc
= diff_output_unidiff_chunk(NULL
, hunkfile
, diff_state
, &diff_info
,
4405 if (rc
!= DIFF_RC_OK
) {
4406 err
= got_error_set_errno(rc
, "diff_output_unidiff_chunk");
4410 if (fseek(hunkfile
, 0L, SEEK_SET
) == -1) {
4411 err
= got_ferror(hunkfile
, GOT_ERR_IO
);
4415 err
= (*patch_cb
)(choice
, patch_arg
, GOT_STATUS_MODIFY
, relpath
,
4416 hunkfile
, changeno
, nchanges
);
4421 case GOT_PATCH_CHOICE_YES
:
4422 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4423 end_old
, start_new
, end_new
, outfile
, rejectfile
);
4425 case GOT_PATCH_CHOICE_NO
:
4426 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4427 end_old
, start_new
, end_new
, rejectfile
, outfile
);
4429 case GOT_PATCH_CHOICE_QUIT
:
4432 err
= got_error(GOT_ERR_PATCH_CHOICE
);
4436 diff_output_unidiff_state_free(diff_state
);
4437 if (hunkfile
&& fclose(hunkfile
) == EOF
&& err
== NULL
)
4438 err
= got_error_from_errno("fclose");
4442 struct revert_file_args
{
4443 struct got_worktree
*worktree
;
4444 struct got_fileindex
*fileindex
;
4445 got_worktree_checkout_cb progress_cb
;
4447 got_worktree_patch_cb patch_cb
;
4449 struct got_repository
*repo
;
4450 int unlink_added_files
;
4453 static const struct got_error
*
4454 create_patched_content(char **path_outfile
, int reverse_patch
,
4455 struct got_object_id
*blob_id
, const char *path2
,
4456 int dirfd2
, const char *de_name2
,
4457 const char *relpath
, struct got_repository
*repo
,
4458 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4460 const struct got_error
*err
, *free_err
;
4461 struct got_blob_object
*blob
= NULL
;
4462 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
;
4463 int fd
= -1, fd2
= -1;
4464 char link_target
[PATH_MAX
];
4465 ssize_t link_len
= 0;
4466 char *path1
= NULL
, *id_str
= NULL
;
4468 struct got_diffreg_result
*diffreg_result
= NULL
;
4469 int line_cur1
= 1, line_cur2
= 1, have_content
= 0;
4470 int i
= 0, n
= 0, nchunks_used
= 0, nchanges
= 0;
4472 *path_outfile
= NULL
;
4474 err
= got_object_id_str(&id_str
, blob_id
);
4479 fd2
= openat(dirfd2
, de_name2
,
4480 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
4482 if (!got_err_open_nofollow_on_symlink()) {
4483 err
= got_error_from_errno2("openat", path2
);
4486 link_len
= readlinkat(dirfd2
, de_name2
,
4487 link_target
, sizeof(link_target
));
4488 if (link_len
== -1) {
4489 return got_error_from_errno2("readlinkat",
4492 sb2
.st_mode
= S_IFLNK
;
4493 sb2
.st_size
= link_len
;
4496 fd2
= open(path2
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
4498 if (!got_err_open_nofollow_on_symlink()) {
4499 err
= got_error_from_errno2("open", path2
);
4502 link_len
= readlink(path2
, link_target
,
4503 sizeof(link_target
));
4505 return got_error_from_errno2("readlink", path2
);
4506 sb2
.st_mode
= S_IFLNK
;
4507 sb2
.st_size
= link_len
;
4511 if (fstat(fd2
, &sb2
) == -1) {
4512 err
= got_error_from_errno2("fstat", path2
);
4516 f2
= fdopen(fd2
, "r");
4518 err
= got_error_from_errno2("fdopen", path2
);
4524 f2
= got_opentemp();
4526 err
= got_error_from_errno2("got_opentemp", path2
);
4529 n
= fwrite(link_target
, 1, link_len
, f2
);
4530 if (n
!= link_len
) {
4531 err
= got_ferror(f2
, GOT_ERR_IO
);
4534 if (fflush(f2
) == EOF
) {
4535 err
= got_error_from_errno("fflush");
4541 fd
= got_opentempfd();
4543 err
= got_error_from_errno("got_opentempfd");
4547 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192, fd
);
4551 err
= got_opentemp_named(&path1
, &f1
, "got-patched-blob", "");
4555 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
4559 err
= got_diff_files(&diffreg_result
, f1
, 1, id_str
, f2
, 1, path2
,
4560 3, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
4564 err
= got_opentemp_named(path_outfile
, &outfile
, "got-patched-content",
4569 if (fseek(f1
, 0L, SEEK_SET
) == -1)
4570 return got_ferror(f1
, GOT_ERR_IO
);
4571 if (fseek(f2
, 0L, SEEK_SET
) == -1)
4572 return got_ferror(f2
, GOT_ERR_IO
);
4574 /* Count the number of actual changes in the diff result. */
4575 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4576 struct diff_chunk_context cc
= {};
4577 diff_chunk_context_load_change(&cc
, &nchunks_used
,
4578 diffreg_result
->result
, n
, 0);
4581 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4583 err
= apply_or_reject_change(&choice
, &nchunks_used
,
4584 diffreg_result
->result
, n
, relpath
, f1
, f2
,
4585 &line_cur1
, &line_cur2
,
4586 reverse_patch
? NULL
: outfile
,
4587 reverse_patch
? outfile
: NULL
,
4588 ++i
, nchanges
, patch_cb
, patch_arg
);
4591 if (choice
== GOT_PATCH_CHOICE_YES
)
4593 else if (choice
== GOT_PATCH_CHOICE_QUIT
)
4597 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
4598 reverse_patch
? NULL
: outfile
,
4599 reverse_patch
? outfile
: NULL
);
4603 if (!S_ISLNK(sb2
.st_mode
)) {
4606 mode
= apply_umask(sb2
.st_mode
);
4607 if (fchmod(fileno(outfile
), mode
) == -1) {
4608 err
= got_error_from_errno2("fchmod", path2
);
4615 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
4616 err
= got_error_from_errno("close");
4618 got_object_blob_close(blob
);
4619 free_err
= got_diffreg_result_free(diffreg_result
);
4622 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
4623 err
= got_error_from_errno2("fclose", path1
);
4624 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
4625 err
= got_error_from_errno2("fclose", path2
);
4626 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
4627 err
= got_error_from_errno2("close", path2
);
4628 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
4629 err
= got_error_from_errno2("fclose", *path_outfile
);
4630 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
4631 err
= got_error_from_errno2("unlink", path1
);
4632 if (err
|| !have_content
) {
4633 if (*path_outfile
&& unlink(*path_outfile
) == -1 && err
== NULL
)
4634 err
= got_error_from_errno2("unlink", *path_outfile
);
4635 free(*path_outfile
);
4636 *path_outfile
= NULL
;
4642 static const struct got_error
*
4643 revert_file(void *arg
, unsigned char status
, unsigned char staged_status
,
4644 const char *relpath
, struct got_object_id
*blob_id
,
4645 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
4646 int dirfd
, const char *de_name
)
4648 struct revert_file_args
*a
= arg
;
4649 const struct got_error
*err
= NULL
;
4650 char *parent_path
= NULL
;
4651 struct got_fileindex_entry
*ie
;
4652 struct got_commit_object
*base_commit
= NULL
;
4653 struct got_tree_object
*tree
= NULL
;
4654 struct got_object_id
*tree_id
= NULL
;
4655 const struct got_tree_entry
*te
= NULL
;
4656 char *tree_path
= NULL
, *te_name
;
4657 char *ondisk_path
= NULL
, *path_content
= NULL
;
4658 struct got_blob_object
*blob
= NULL
;
4661 /* Reverting a staged deletion is a no-op. */
4662 if (status
== GOT_STATUS_DELETE
&&
4663 staged_status
!= GOT_STATUS_NO_CHANGE
)
4666 if (status
== GOT_STATUS_UNVERSIONED
)
4667 return (*a
->progress_cb
)(a
->progress_arg
,
4668 GOT_STATUS_UNVERSIONED
, relpath
);
4670 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4672 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
4674 /* Construct in-repository path of tree which contains this blob. */
4675 err
= got_path_dirname(&parent_path
, ie
->path
);
4677 if (err
->code
!= GOT_ERR_BAD_PATH
)
4679 parent_path
= strdup("/");
4680 if (parent_path
== NULL
) {
4681 err
= got_error_from_errno("strdup");
4685 if (got_path_is_root_dir(a
->worktree
->path_prefix
)) {
4686 tree_path
= strdup(parent_path
);
4687 if (tree_path
== NULL
) {
4688 err
= got_error_from_errno("strdup");
4692 if (got_path_is_root_dir(parent_path
)) {
4693 tree_path
= strdup(a
->worktree
->path_prefix
);
4694 if (tree_path
== NULL
) {
4695 err
= got_error_from_errno("strdup");
4699 if (asprintf(&tree_path
, "%s/%s",
4700 a
->worktree
->path_prefix
, parent_path
) == -1) {
4701 err
= got_error_from_errno("asprintf");
4707 err
= got_object_open_as_commit(&base_commit
, a
->repo
,
4708 a
->worktree
->base_commit_id
);
4712 err
= got_object_id_by_path(&tree_id
, a
->repo
, base_commit
, tree_path
);
4714 if (!(err
->code
== GOT_ERR_NO_TREE_ENTRY
&&
4715 (status
== GOT_STATUS_ADD
||
4716 staged_status
== GOT_STATUS_ADD
)))
4719 err
= got_object_open_as_tree(&tree
, a
->repo
, tree_id
);
4723 err
= got_path_basename(&te_name
, ie
->path
);
4727 te
= got_object_tree_find_entry(tree
, te_name
);
4729 if (te
== NULL
&& status
!= GOT_STATUS_ADD
&&
4730 staged_status
!= GOT_STATUS_ADD
) {
4731 err
= got_error_path(ie
->path
, GOT_ERR_NO_TREE_ENTRY
);
4737 case GOT_STATUS_ADD
:
4739 int choice
= GOT_PATCH_CHOICE_NONE
;
4740 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4741 status
, ie
->path
, NULL
, 1, 1);
4744 if (choice
!= GOT_PATCH_CHOICE_YES
)
4747 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_REVERT
,
4751 got_fileindex_entry_remove(a
->fileindex
, ie
);
4752 if (a
->unlink_added_files
) {
4753 if (asprintf(&ondisk_path
, "%s/%s",
4754 got_worktree_get_root_path(a
->worktree
),
4756 err
= got_error_from_errno("asprintf");
4759 if (unlink(ondisk_path
) == -1) {
4760 err
= got_error_from_errno2("unlink",
4766 case GOT_STATUS_DELETE
:
4768 int choice
= GOT_PATCH_CHOICE_NONE
;
4769 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4770 status
, ie
->path
, NULL
, 1, 1);
4773 if (choice
!= GOT_PATCH_CHOICE_YES
)
4777 case GOT_STATUS_MODIFY
:
4778 case GOT_STATUS_MODE_CHANGE
:
4779 case GOT_STATUS_CONFLICT
:
4780 case GOT_STATUS_MISSING
: {
4781 struct got_object_id id
;
4782 if (staged_status
== GOT_STATUS_ADD
||
4783 staged_status
== GOT_STATUS_MODIFY
) {
4784 memcpy(id
.sha1
, ie
->staged_blob_sha1
,
4785 SHA1_DIGEST_LENGTH
);
4787 memcpy(id
.sha1
, ie
->blob_sha1
,
4788 SHA1_DIGEST_LENGTH
);
4789 fd
= got_opentempfd();
4791 err
= got_error_from_errno("got_opentempfd");
4795 err
= got_object_open_as_blob(&blob
, a
->repo
, &id
, 8192, fd
);
4799 if (asprintf(&ondisk_path
, "%s/%s",
4800 got_worktree_get_root_path(a
->worktree
), relpath
) == -1) {
4801 err
= got_error_from_errno("asprintf");
4805 if (a
->patch_cb
&& (status
== GOT_STATUS_MODIFY
||
4806 status
== GOT_STATUS_CONFLICT
)) {
4807 int is_bad_symlink
= 0;
4808 err
= create_patched_content(&path_content
, 1, &id
,
4809 ondisk_path
, dirfd
, de_name
, ie
->path
, a
->repo
,
4810 a
->patch_cb
, a
->patch_arg
);
4811 if (err
|| path_content
== NULL
)
4813 if (te
&& S_ISLNK(te
->mode
)) {
4814 if (unlink(path_content
) == -1) {
4815 err
= got_error_from_errno2("unlink",
4819 err
= install_symlink(&is_bad_symlink
,
4820 a
->worktree
, ondisk_path
, ie
->path
,
4821 blob
, 0, 1, 0, 0, a
->repo
,
4822 a
->progress_cb
, a
->progress_arg
);
4824 if (rename(path_content
, ondisk_path
) == -1) {
4825 err
= got_error_from_errno3("rename",
4826 path_content
, ondisk_path
);
4831 int is_bad_symlink
= 0;
4832 if (te
&& S_ISLNK(te
->mode
)) {
4833 err
= install_symlink(&is_bad_symlink
,
4834 a
->worktree
, ondisk_path
, ie
->path
,
4835 blob
, 0, 1, 0, 0, a
->repo
,
4836 a
->progress_cb
, a
->progress_arg
);
4838 err
= install_blob(a
->worktree
, ondisk_path
,
4840 te
? te
->mode
: GOT_DEFAULT_FILE_MODE
,
4841 got_fileindex_perms_to_st(ie
), blob
,
4842 0, 1, 0, 0, a
->repo
,
4843 a
->progress_cb
, a
->progress_arg
);
4847 if (status
== GOT_STATUS_DELETE
||
4848 status
== GOT_STATUS_MODE_CHANGE
) {
4849 err
= got_fileindex_entry_update(ie
,
4850 a
->worktree
->root_fd
, relpath
,
4852 a
->worktree
->base_commit_id
->sha1
, 1);
4856 if (is_bad_symlink
) {
4857 got_fileindex_entry_filetype_set(ie
,
4858 GOT_FILEIDX_MODE_BAD_SYMLINK
);
4871 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
4872 err
= got_error_from_errno("close");
4874 got_object_blob_close(blob
);
4876 got_object_tree_close(tree
);
4879 got_object_commit_close(base_commit
);
4883 const struct got_error
*
4884 got_worktree_revert(struct got_worktree
*worktree
,
4885 struct got_pathlist_head
*paths
,
4886 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4887 got_worktree_patch_cb patch_cb
, void *patch_arg
,
4888 struct got_repository
*repo
)
4890 struct got_fileindex
*fileindex
= NULL
;
4891 char *fileindex_path
= NULL
;
4892 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
4893 const struct got_error
*sync_err
= NULL
;
4894 struct got_pathlist_entry
*pe
;
4895 struct revert_file_args rfa
;
4897 err
= lock_worktree(worktree
, LOCK_EX
);
4901 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4905 rfa
.worktree
= worktree
;
4906 rfa
.fileindex
= fileindex
;
4907 rfa
.progress_cb
= progress_cb
;
4908 rfa
.progress_arg
= progress_arg
;
4909 rfa
.patch_cb
= patch_cb
;
4910 rfa
.patch_arg
= patch_arg
;
4912 rfa
.unlink_added_files
= 0;
4913 TAILQ_FOREACH(pe
, paths
, entry
) {
4914 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4915 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
4919 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4920 if (sync_err
&& err
== NULL
)
4923 free(fileindex_path
);
4925 got_fileindex_free(fileindex
);
4926 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4927 if (unlockerr
&& err
== NULL
)
4933 free_commitable(struct got_commitable
*ct
)
4936 free(ct
->in_repo_path
);
4937 free(ct
->ondisk_path
);
4939 free(ct
->base_blob_id
);
4940 free(ct
->staged_blob_id
);
4941 free(ct
->base_commit_id
);
4945 struct collect_commitables_arg
{
4946 struct got_pathlist_head
*commitable_paths
;
4947 struct got_repository
*repo
;
4948 struct got_worktree
*worktree
;
4949 struct got_fileindex
*fileindex
;
4950 int have_staged_files
;
4951 int allow_bad_symlinks
;
4952 int diff_header_shown
;
4959 * Create a file which contains the target path of a symlink so we can feed
4960 * it as content to the diff engine.
4962 static const struct got_error
*
4963 get_symlink_target_file(int *fd
, int dirfd
, const char *de_name
,
4964 const char *abspath
)
4966 const struct got_error
*err
= NULL
;
4967 char target_path
[PATH_MAX
];
4968 ssize_t target_len
, outlen
;
4973 target_len
= readlinkat(dirfd
, de_name
, target_path
, PATH_MAX
);
4974 if (target_len
== -1)
4975 return got_error_from_errno2("readlinkat", abspath
);
4977 target_len
= readlink(abspath
, target_path
, PATH_MAX
);
4978 if (target_len
== -1)
4979 return got_error_from_errno2("readlink", abspath
);
4982 *fd
= got_opentempfd();
4984 return got_error_from_errno("got_opentempfd");
4986 outlen
= write(*fd
, target_path
, target_len
);
4988 err
= got_error_from_errno("got_opentempfd");
4992 if (lseek(*fd
, 0, SEEK_SET
) == -1) {
4993 err
= got_error_from_errno2("lseek", abspath
);
5004 static const struct got_error
*
5005 append_ct_diff(struct got_commitable
*ct
, int *diff_header_shown
,
5006 FILE *diff_outfile
, FILE *f1
, FILE *f2
, int dirfd
, const char *de_name
,
5007 int diff_staged
, struct got_repository
*repo
, struct got_worktree
*worktree
)
5009 const struct got_error
*err
= NULL
;
5010 struct got_blob_object
*blob1
= NULL
;
5011 int fd
= -1, fd1
= -1, fd2
= -1;
5012 FILE *ondisk_file
= NULL
;
5013 char *label1
= NULL
;
5017 char *id_str
= NULL
;
5019 memset(&sb
, 0, sizeof(sb
));
5022 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
5023 ct
->staged_status
!= GOT_STATUS_ADD
&&
5024 ct
->staged_status
!= GOT_STATUS_DELETE
)
5027 if (ct
->status
!= GOT_STATUS_MODIFY
&&
5028 ct
->status
!= GOT_STATUS_ADD
&&
5029 ct
->status
!= GOT_STATUS_DELETE
)
5033 err
= got_opentemp_truncate(f1
);
5035 return got_error_from_errno("got_opentemp_truncate");
5036 err
= got_opentemp_truncate(f2
);
5038 return got_error_from_errno("got_opentemp_truncate");
5040 if (!*diff_header_shown
) {
5041 err
= got_object_id_str(&id_str
, worktree
->base_commit_id
);
5044 fprintf(diff_outfile
, "diff %s%s\n", diff_staged
? "-s " : "",
5045 got_worktree_get_root_path(worktree
));
5046 fprintf(diff_outfile
, "commit - %s\n", id_str
);
5047 fprintf(diff_outfile
, "path + %s%s\n",
5048 got_worktree_get_root_path(worktree
),
5049 diff_staged
? " (staged changes)" : "");
5050 *diff_header_shown
= 1;
5054 const char *label1
= NULL
, *label2
= NULL
;
5055 switch (ct
->staged_status
) {
5056 case GOT_STATUS_MODIFY
:
5060 case GOT_STATUS_ADD
:
5063 case GOT_STATUS_DELETE
:
5067 return got_error(GOT_ERR_FILE_STATUS
);
5069 fd1
= got_opentempfd();
5071 err
= got_error_from_errno("got_opentempfd");
5074 fd2
= got_opentempfd();
5076 err
= got_error_from_errno("got_opentempfd");
5079 err
= got_diff_objects_as_blobs(NULL
, NULL
, f1
, f2
,
5080 fd1
, fd2
, ct
->base_blob_id
, ct
->staged_blob_id
,
5081 label1
, label2
, GOT_DIFF_ALGORITHM_PATIENCE
, 3, 0, 0,
5082 NULL
, repo
, diff_outfile
);
5086 fd1
= got_opentempfd();
5088 err
= got_error_from_errno("got_opentempfd");
5092 if (ct
->status
!= GOT_STATUS_ADD
) {
5093 err
= got_object_open_as_blob(&blob1
, repo
, ct
->base_blob_id
,
5099 if (ct
->status
!= GOT_STATUS_DELETE
) {
5101 fd
= openat(dirfd
, de_name
,
5102 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
5104 if (!got_err_open_nofollow_on_symlink()) {
5105 err
= got_error_from_errno2("openat",
5109 err
= get_symlink_target_file(&fd
, dirfd
,
5110 de_name
, ct
->ondisk_path
);
5115 fd
= open(ct
->ondisk_path
,
5116 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
5118 if (!got_err_open_nofollow_on_symlink()) {
5119 err
= got_error_from_errno2("open",
5123 err
= get_symlink_target_file(&fd
, dirfd
,
5124 de_name
, ct
->ondisk_path
);
5129 if (fstatat(fd
, ct
->ondisk_path
, &sb
,
5130 AT_SYMLINK_NOFOLLOW
) == -1) {
5131 err
= got_error_from_errno2("fstatat", ct
->ondisk_path
);
5134 ondisk_file
= fdopen(fd
, "r");
5135 if (ondisk_file
== NULL
) {
5136 err
= got_error_from_errno2("fdopen", ct
->ondisk_path
);
5144 err
= got_object_blob_dump_to_file(&size1
, NULL
, NULL
,
5150 err
= got_diff_blob_file(blob1
, f1
, size1
, label1
,
5151 ondisk_file
? ondisk_file
: f2
, f2_exists
, &sb
, ct
->path
,
5152 GOT_DIFF_ALGORITHM_PATIENCE
, 3, 0, 0, NULL
, diff_outfile
);
5154 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
5155 err
= got_error_from_errno("close");
5156 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
5157 err
= got_error_from_errno("close");
5159 got_object_blob_close(blob1
);
5160 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
5161 err
= got_error_from_errno("close");
5162 if (ondisk_file
&& fclose(ondisk_file
) == EOF
&& err
== NULL
)
5163 err
= got_error_from_errno("fclose");
5167 static const struct got_error
*
5168 collect_commitables(void *arg
, unsigned char status
,
5169 unsigned char staged_status
, const char *relpath
,
5170 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
5171 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
5173 struct collect_commitables_arg
*a
= arg
;
5174 const struct got_error
*err
= NULL
;
5175 struct got_commitable
*ct
= NULL
;
5176 struct got_pathlist_entry
*new = NULL
;
5177 char *parent_path
= NULL
, *path
= NULL
;
5180 if (a
->have_staged_files
) {
5181 if (staged_status
!= GOT_STATUS_MODIFY
&&
5182 staged_status
!= GOT_STATUS_ADD
&&
5183 staged_status
!= GOT_STATUS_DELETE
)
5186 if (status
== GOT_STATUS_CONFLICT
)
5187 return got_error(GOT_ERR_COMMIT_CONFLICT
);
5189 if (status
!= GOT_STATUS_MODIFY
&&
5190 status
!= GOT_STATUS_MODE_CHANGE
&&
5191 status
!= GOT_STATUS_ADD
&&
5192 status
!= GOT_STATUS_DELETE
)
5196 if (asprintf(&path
, "/%s", relpath
) == -1) {
5197 err
= got_error_from_errno("asprintf");
5200 if (strcmp(path
, "/") == 0) {
5201 parent_path
= strdup("");
5202 if (parent_path
== NULL
)
5203 return got_error_from_errno("strdup");
5205 err
= got_path_dirname(&parent_path
, path
);
5210 ct
= calloc(1, sizeof(*ct
));
5212 err
= got_error_from_errno("calloc");
5216 if (asprintf(&ct
->ondisk_path
, "%s/%s", a
->worktree
->root_path
,
5218 err
= got_error_from_errno("asprintf");
5222 if (staged_status
== GOT_STATUS_ADD
||
5223 staged_status
== GOT_STATUS_MODIFY
) {
5224 struct got_fileindex_entry
*ie
;
5225 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
5226 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
5227 case GOT_FILEIDX_MODE_REGULAR_FILE
:
5228 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
5231 case GOT_FILEIDX_MODE_SYMLINK
:
5235 err
= got_error_path(path
, GOT_ERR_BAD_FILETYPE
);
5238 ct
->mode
|= got_fileindex_entry_perms_get(ie
);
5239 } else if (status
!= GOT_STATUS_DELETE
&&
5240 staged_status
!= GOT_STATUS_DELETE
) {
5242 if (fstatat(dirfd
, de_name
, &sb
,
5243 AT_SYMLINK_NOFOLLOW
) == -1) {
5244 err
= got_error_from_errno2("fstatat",
5248 } else if (lstat(ct
->ondisk_path
, &sb
) == -1) {
5249 err
= got_error_from_errno2("lstat", ct
->ondisk_path
);
5252 ct
->mode
= sb
.st_mode
;
5255 if (asprintf(&ct
->in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
5256 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
5258 err
= got_error_from_errno("asprintf");
5262 if (S_ISLNK(ct
->mode
) && staged_status
== GOT_STATUS_NO_CHANGE
&&
5263 status
== GOT_STATUS_ADD
&& !a
->allow_bad_symlinks
) {
5265 char target_path
[PATH_MAX
];
5267 target_len
= readlink(ct
->ondisk_path
, target_path
,
5268 sizeof(target_path
));
5269 if (target_len
== -1) {
5270 err
= got_error_from_errno2("readlink",
5274 err
= is_bad_symlink_target(&is_bad_symlink
, target_path
,
5275 target_len
, ct
->ondisk_path
, a
->worktree
->root_path
);
5278 if (is_bad_symlink
) {
5279 err
= got_error_path(ct
->ondisk_path
,
5280 GOT_ERR_BAD_SYMLINK
);
5286 ct
->status
= status
;
5287 ct
->staged_status
= staged_status
;
5288 ct
->blob_id
= NULL
; /* will be filled in when blob gets created */
5289 if (ct
->status
!= GOT_STATUS_ADD
&&
5290 ct
->staged_status
!= GOT_STATUS_ADD
) {
5291 ct
->base_blob_id
= got_object_id_dup(blob_id
);
5292 if (ct
->base_blob_id
== NULL
) {
5293 err
= got_error_from_errno("got_object_id_dup");
5296 ct
->base_commit_id
= got_object_id_dup(commit_id
);
5297 if (ct
->base_commit_id
== NULL
) {
5298 err
= got_error_from_errno("got_object_id_dup");
5302 if (ct
->staged_status
== GOT_STATUS_ADD
||
5303 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5304 ct
->staged_blob_id
= got_object_id_dup(staged_blob_id
);
5305 if (ct
->staged_blob_id
== NULL
) {
5306 err
= got_error_from_errno("got_object_id_dup");
5310 ct
->path
= strdup(path
);
5311 if (ct
->path
== NULL
) {
5312 err
= got_error_from_errno("strdup");
5315 err
= got_pathlist_insert(&new, a
->commitable_paths
, ct
->path
, ct
);
5319 if (a
->diff_outfile
&& ct
&& new != NULL
) {
5320 err
= append_ct_diff(ct
, &a
->diff_header_shown
,
5321 a
->diff_outfile
, a
->f1
, a
->f2
, dirfd
, de_name
,
5322 a
->have_staged_files
, a
->repo
, a
->worktree
);
5327 if (ct
&& (err
|| new == NULL
))
5328 free_commitable(ct
);
5334 static const struct got_error
*write_tree(struct got_object_id
**, int *,
5335 struct got_tree_object
*, const char *, struct got_pathlist_head
*,
5336 got_worktree_status_cb status_cb
, void *status_arg
,
5337 struct got_repository
*);
5339 static const struct got_error
*
5340 write_subtree(struct got_object_id
**new_subtree_id
, int *nentries
,
5341 struct got_tree_entry
*te
, const char *parent_path
,
5342 struct got_pathlist_head
*commitable_paths
,
5343 got_worktree_status_cb status_cb
, void *status_arg
,
5344 struct got_repository
*repo
)
5346 const struct got_error
*err
= NULL
;
5347 struct got_tree_object
*subtree
;
5350 if (asprintf(&subpath
, "%s%s%s", parent_path
,
5351 got_path_is_root_dir(parent_path
) ? "" : "/", te
->name
) == -1)
5352 return got_error_from_errno("asprintf");
5354 err
= got_object_open_as_tree(&subtree
, repo
, &te
->id
);
5358 err
= write_tree(new_subtree_id
, nentries
, subtree
, subpath
,
5359 commitable_paths
, status_cb
, status_arg
, repo
);
5360 got_object_tree_close(subtree
);
5365 static const struct got_error
*
5366 match_ct_parent_path(int *match
, struct got_commitable
*ct
, const char *path
)
5368 const struct got_error
*err
= NULL
;
5369 char *ct_parent_path
= NULL
;
5373 if (strchr(ct
->in_repo_path
, '/') == NULL
) {
5374 *match
= got_path_is_root_dir(path
);
5378 err
= got_path_dirname(&ct_parent_path
, ct
->in_repo_path
);
5381 *match
= (strcmp(path
, ct_parent_path
) == 0);
5382 free(ct_parent_path
);
5387 get_ct_file_mode(struct got_commitable
*ct
)
5389 if (S_ISLNK(ct
->mode
))
5392 return S_IFREG
| (ct
->mode
& ((S_IRWXU
| S_IRWXG
| S_IRWXO
)));
5395 static const struct got_error
*
5396 alloc_modified_blob_tree_entry(struct got_tree_entry
**new_te
,
5397 struct got_tree_entry
*te
, struct got_commitable
*ct
)
5399 const struct got_error
*err
= NULL
;
5403 err
= got_object_tree_entry_dup(new_te
, te
);
5407 (*new_te
)->mode
= get_ct_file_mode(ct
);
5409 if (ct
->staged_status
== GOT_STATUS_MODIFY
)
5410 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5411 sizeof((*new_te
)->id
));
5413 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5415 if (err
&& *new_te
) {
5422 static const struct got_error
*
5423 alloc_added_blob_tree_entry(struct got_tree_entry
**new_te
,
5424 struct got_commitable
*ct
)
5426 const struct got_error
*err
= NULL
;
5427 char *ct_name
= NULL
;
5431 *new_te
= calloc(1, sizeof(**new_te
));
5432 if (*new_te
== NULL
)
5433 return got_error_from_errno("calloc");
5435 err
= got_path_basename(&ct_name
, ct
->path
);
5438 if (strlcpy((*new_te
)->name
, ct_name
, sizeof((*new_te
)->name
)) >=
5439 sizeof((*new_te
)->name
)) {
5440 err
= got_error(GOT_ERR_NO_SPACE
);
5444 (*new_te
)->mode
= get_ct_file_mode(ct
);
5446 if (ct
->staged_status
== GOT_STATUS_ADD
)
5447 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5448 sizeof((*new_te
)->id
));
5450 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5453 if (err
&& *new_te
) {
5460 static const struct got_error
*
5461 insert_tree_entry(struct got_tree_entry
*new_te
,
5462 struct got_pathlist_head
*paths
)
5464 const struct got_error
*err
= NULL
;
5465 struct got_pathlist_entry
*new_pe
;
5467 err
= got_pathlist_insert(&new_pe
, paths
, new_te
->name
, new_te
);
5471 return got_error(GOT_ERR_TREE_DUP_ENTRY
);
5475 static const struct got_error
*
5476 report_ct_status(struct got_commitable
*ct
,
5477 got_worktree_status_cb status_cb
, void *status_arg
)
5479 const char *ct_path
= ct
->path
;
5480 unsigned char status
;
5482 if (status_cb
== NULL
) /* no commit progress output desired */
5485 while (ct_path
[0] == '/')
5488 if (ct
->staged_status
!= GOT_STATUS_NO_CHANGE
)
5489 status
= ct
->staged_status
;
5491 status
= ct
->status
;
5493 return (*status_cb
)(status_arg
, status
, GOT_STATUS_NO_CHANGE
,
5494 ct_path
, ct
->blob_id
, NULL
, NULL
, -1, NULL
);
5497 static const struct got_error
*
5498 match_modified_subtree(int *modified
, struct got_tree_entry
*te
,
5499 const char *base_tree_path
, struct got_pathlist_head
*commitable_paths
)
5501 const struct got_error
*err
= NULL
;
5502 struct got_pathlist_entry
*pe
;
5507 if (asprintf(&te_path
, "%s%s%s", base_tree_path
,
5508 got_path_is_root_dir(base_tree_path
) ? "" : "/",
5510 return got_error_from_errno("asprintf");
5512 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5513 struct got_commitable
*ct
= pe
->data
;
5514 *modified
= got_path_is_child(ct
->in_repo_path
, te_path
,
5524 static const struct got_error
*
5525 match_deleted_or_modified_ct(struct got_commitable
**ctp
,
5526 struct got_tree_entry
*te
, const char *base_tree_path
,
5527 struct got_pathlist_head
*commitable_paths
)
5529 const struct got_error
*err
= NULL
;
5530 struct got_pathlist_entry
*pe
;
5534 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5535 struct got_commitable
*ct
= pe
->data
;
5536 char *ct_name
= NULL
;
5539 if (ct
->staged_status
== GOT_STATUS_NO_CHANGE
) {
5540 if (ct
->status
!= GOT_STATUS_MODIFY
&&
5541 ct
->status
!= GOT_STATUS_MODE_CHANGE
&&
5542 ct
->status
!= GOT_STATUS_DELETE
)
5545 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
5546 ct
->staged_status
!= GOT_STATUS_DELETE
)
5550 if (got_object_id_cmp(ct
->base_blob_id
, &te
->id
) != 0)
5553 err
= match_ct_parent_path(&path_matches
, ct
, base_tree_path
);
5559 err
= got_path_basename(&ct_name
, pe
->path
);
5563 if (strcmp(te
->name
, ct_name
) != 0) {
5576 static const struct got_error
*
5577 make_subtree_for_added_blob(struct got_tree_entry
**new_tep
,
5578 const char *child_path
, const char *path_base_tree
,
5579 struct got_pathlist_head
*commitable_paths
,
5580 got_worktree_status_cb status_cb
, void *status_arg
,
5581 struct got_repository
*repo
)
5583 const struct got_error
*err
= NULL
;
5584 struct got_tree_entry
*new_te
;
5586 struct got_object_id
*id
= NULL
;
5591 if (asprintf(&subtree_path
, "%s%s%s", path_base_tree
,
5592 got_path_is_root_dir(path_base_tree
) ? "" : "/",
5594 return got_error_from_errno("asprintf");
5596 new_te
= calloc(1, sizeof(*new_te
));
5598 return got_error_from_errno("calloc");
5599 new_te
->mode
= S_IFDIR
;
5601 if (strlcpy(new_te
->name
, child_path
, sizeof(new_te
->name
)) >=
5602 sizeof(new_te
->name
)) {
5603 err
= got_error(GOT_ERR_NO_SPACE
);
5606 err
= write_tree(&id
, &nentries
, NULL
, subtree_path
,
5607 commitable_paths
, status_cb
, status_arg
, repo
);
5612 memcpy(&new_te
->id
, id
, sizeof(new_te
->id
));
5621 static const struct got_error
*
5622 write_tree(struct got_object_id
**new_tree_id
, int *nentries
,
5623 struct got_tree_object
*base_tree
, const char *path_base_tree
,
5624 struct got_pathlist_head
*commitable_paths
,
5625 got_worktree_status_cb status_cb
, void *status_arg
,
5626 struct got_repository
*repo
)
5628 const struct got_error
*err
= NULL
;
5629 struct got_pathlist_head paths
;
5630 struct got_tree_entry
*te
, *new_te
= NULL
;
5631 struct got_pathlist_entry
*pe
;
5636 /* Insert, and recurse into, newly added entries first. */
5637 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5638 struct got_commitable
*ct
= pe
->data
;
5639 char *child_path
= NULL
, *slash
;
5641 if ((ct
->status
!= GOT_STATUS_ADD
&&
5642 ct
->staged_status
!= GOT_STATUS_ADD
) ||
5643 (ct
->flags
& GOT_COMMITABLE_ADDED
))
5646 if (!got_path_is_child(ct
->in_repo_path
, path_base_tree
,
5647 strlen(path_base_tree
)))
5650 err
= got_path_skip_common_ancestor(&child_path
, path_base_tree
,
5655 slash
= strchr(child_path
, '/');
5656 if (slash
== NULL
) {
5657 err
= alloc_added_blob_tree_entry(&new_te
, ct
);
5660 err
= report_ct_status(ct
, status_cb
, status_arg
);
5663 ct
->flags
|= GOT_COMMITABLE_ADDED
;
5664 err
= insert_tree_entry(new_te
, &paths
);
5669 *slash
= '\0'; /* trim trailing path components */
5670 if (base_tree
== NULL
||
5671 got_object_tree_find_entry(base_tree
, child_path
)
5673 err
= make_subtree_for_added_blob(&new_te
,
5674 child_path
, path_base_tree
,
5675 commitable_paths
, status_cb
, status_arg
,
5679 err
= insert_tree_entry(new_te
, &paths
);
5688 int i
, nbase_entries
;
5689 /* Handle modified and deleted entries. */
5690 nbase_entries
= got_object_tree_get_nentries(base_tree
);
5691 for (i
= 0; i
< nbase_entries
; i
++) {
5692 struct got_commitable
*ct
= NULL
;
5694 te
= got_object_tree_get_entry(base_tree
, i
);
5695 if (got_object_tree_entry_is_submodule(te
)) {
5696 /* Entry is a submodule; just copy it. */
5697 err
= got_object_tree_entry_dup(&new_te
, te
);
5700 err
= insert_tree_entry(new_te
, &paths
);
5707 if (S_ISDIR(te
->mode
)) {
5709 err
= got_object_tree_entry_dup(&new_te
, te
);
5712 err
= match_modified_subtree(&modified
, te
,
5713 path_base_tree
, commitable_paths
);
5716 /* Avoid recursion into unmodified subtrees. */
5718 struct got_object_id
*new_id
;
5720 err
= write_subtree(&new_id
,
5722 path_base_tree
, commitable_paths
,
5723 status_cb
, status_arg
, repo
);
5726 if (nsubentries
== 0) {
5727 /* All entries were deleted. */
5731 memcpy(&new_te
->id
, new_id
,
5732 sizeof(new_te
->id
));
5735 err
= insert_tree_entry(new_te
, &paths
);
5742 err
= match_deleted_or_modified_ct(&ct
, te
,
5743 path_base_tree
, commitable_paths
);
5747 /* NB: Deleted entries get dropped here. */
5748 if (ct
->status
== GOT_STATUS_MODIFY
||
5749 ct
->status
== GOT_STATUS_MODE_CHANGE
||
5750 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5751 err
= alloc_modified_blob_tree_entry(
5755 err
= insert_tree_entry(new_te
, &paths
);
5760 err
= report_ct_status(ct
, status_cb
,
5765 /* Entry is unchanged; just copy it. */
5766 err
= got_object_tree_entry_dup(&new_te
, te
);
5769 err
= insert_tree_entry(new_te
, &paths
);
5777 /* Write new list of entries; deleted entries have been dropped. */
5778 err
= got_object_tree_create(new_tree_id
, &paths
, *nentries
, repo
);
5780 got_pathlist_free(&paths
, GOT_PATHLIST_FREE_NONE
);
5784 static const struct got_error
*
5785 update_fileindex_after_commit(struct got_worktree
*worktree
,
5786 struct got_pathlist_head
*commitable_paths
,
5787 struct got_object_id
*new_base_commit_id
,
5788 struct got_fileindex
*fileindex
, int have_staged_files
)
5790 const struct got_error
*err
= NULL
;
5791 struct got_pathlist_entry
*pe
;
5792 char *relpath
= NULL
;
5794 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5795 struct got_fileindex_entry
*ie
;
5796 struct got_commitable
*ct
= pe
->data
;
5798 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
5800 err
= got_path_skip_common_ancestor(&relpath
,
5801 worktree
->root_path
, ct
->ondisk_path
);
5806 if (ct
->status
== GOT_STATUS_DELETE
||
5807 ct
->staged_status
== GOT_STATUS_DELETE
) {
5808 got_fileindex_entry_remove(fileindex
, ie
);
5809 } else if (ct
->staged_status
== GOT_STATUS_ADD
||
5810 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5811 got_fileindex_entry_stage_set(ie
,
5812 GOT_FILEIDX_STAGE_NONE
);
5813 got_fileindex_entry_staged_filetype_set(ie
, 0);
5815 err
= got_fileindex_entry_update(ie
,
5816 worktree
->root_fd
, relpath
,
5817 ct
->staged_blob_id
->sha1
,
5818 new_base_commit_id
->sha1
,
5819 !have_staged_files
);
5821 err
= got_fileindex_entry_update(ie
,
5822 worktree
->root_fd
, relpath
,
5824 new_base_commit_id
->sha1
,
5825 !have_staged_files
);
5827 err
= got_fileindex_entry_alloc(&ie
, pe
->path
);
5830 err
= got_fileindex_entry_update(ie
,
5831 worktree
->root_fd
, relpath
, ct
->blob_id
->sha1
,
5832 new_base_commit_id
->sha1
, 1);
5834 got_fileindex_entry_free(ie
);
5837 err
= got_fileindex_entry_add(fileindex
, ie
);
5839 got_fileindex_entry_free(ie
);
5852 static const struct got_error
*
5853 check_out_of_date(const char *in_repo_path
, unsigned char status
,
5854 unsigned char staged_status
, struct got_object_id
*base_blob_id
,
5855 struct got_object_id
*base_commit_id
,
5856 struct got_object_id
*head_commit_id
, struct got_repository
*repo
,
5859 const struct got_error
*err
= NULL
;
5860 struct got_commit_object
*commit
= NULL
;
5861 struct got_object_id
*id
= NULL
;
5863 if (status
!= GOT_STATUS_ADD
&& staged_status
!= GOT_STATUS_ADD
) {
5864 /* Trivial case: base commit == head commit */
5865 if (got_object_id_cmp(base_commit_id
, head_commit_id
) == 0)
5868 * Ensure file content which local changes were based
5869 * on matches file content in the branch head.
5871 err
= got_object_open_as_commit(&commit
, repo
, head_commit_id
);
5874 err
= got_object_id_by_path(&id
, repo
, commit
, in_repo_path
);
5876 if (err
->code
== GOT_ERR_NO_TREE_ENTRY
)
5877 err
= got_error(ood_errcode
);
5879 } else if (got_object_id_cmp(id
, base_blob_id
) != 0)
5880 err
= got_error(ood_errcode
);
5882 /* Require that added files don't exist in the branch head. */
5883 err
= got_object_open_as_commit(&commit
, repo
, head_commit_id
);
5886 err
= got_object_id_by_path(&id
, repo
, commit
, in_repo_path
);
5887 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
5889 err
= id
? got_error(ood_errcode
) : NULL
;
5894 got_object_commit_close(commit
);
5898 static const struct got_error
*
5899 commit_worktree(struct got_object_id
**new_commit_id
,
5900 struct got_pathlist_head
*commitable_paths
,
5901 struct got_object_id
*head_commit_id
,
5902 struct got_object_id
*parent_id2
,
5903 struct got_worktree
*worktree
,
5904 const char *author
, const char *committer
, char *diff_path
,
5905 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
5906 got_worktree_status_cb status_cb
, void *status_arg
,
5907 struct got_repository
*repo
)
5909 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
5910 struct got_pathlist_entry
*pe
;
5911 const char *head_ref_name
= NULL
;
5912 struct got_commit_object
*head_commit
= NULL
;
5913 struct got_reference
*head_ref2
= NULL
;
5914 struct got_object_id
*head_commit_id2
= NULL
;
5915 struct got_tree_object
*head_tree
= NULL
;
5916 struct got_object_id
*new_tree_id
= NULL
;
5917 int nentries
, nparents
= 0;
5918 struct got_object_id_queue parent_ids
;
5919 struct got_object_qid
*pid
= NULL
;
5920 char *logmsg
= NULL
;
5923 *new_commit_id
= NULL
;
5925 STAILQ_INIT(&parent_ids
);
5927 err
= got_object_open_as_commit(&head_commit
, repo
, head_commit_id
);
5931 err
= got_object_open_as_tree(&head_tree
, repo
, head_commit
->tree_id
);
5935 if (commit_msg_cb
!= NULL
) {
5936 err
= commit_msg_cb(commitable_paths
, diff_path
,
5937 &logmsg
, commit_arg
);
5942 if (logmsg
== NULL
|| strlen(logmsg
) == 0) {
5943 err
= got_error(GOT_ERR_COMMIT_MSG_EMPTY
);
5947 /* Create blobs from added and modified files and record their IDs. */
5948 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5949 struct got_commitable
*ct
= pe
->data
;
5952 /* Blobs for staged files already exist. */
5953 if (ct
->staged_status
== GOT_STATUS_ADD
||
5954 ct
->staged_status
== GOT_STATUS_MODIFY
)
5957 if (ct
->status
!= GOT_STATUS_ADD
&&
5958 ct
->status
!= GOT_STATUS_MODIFY
&&
5959 ct
->status
!= GOT_STATUS_MODE_CHANGE
)
5962 if (asprintf(&ondisk_path
, "%s/%s",
5963 worktree
->root_path
, pe
->path
) == -1) {
5964 err
= got_error_from_errno("asprintf");
5967 err
= got_object_blob_create(&ct
->blob_id
, ondisk_path
, repo
);
5973 /* Recursively write new tree objects. */
5974 err
= write_tree(&new_tree_id
, &nentries
, head_tree
, "/",
5975 commitable_paths
, status_cb
, status_arg
, repo
);
5979 err
= got_object_qid_alloc(&pid
, worktree
->base_commit_id
);
5982 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
5985 err
= got_object_qid_alloc(&pid
, parent_id2
);
5988 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
5991 timestamp
= time(NULL
);
5992 err
= got_object_commit_create(new_commit_id
, new_tree_id
, &parent_ids
,
5993 nparents
, author
, timestamp
, committer
, timestamp
, logmsg
, repo
);
5999 /* Check if a concurrent commit to our branch has occurred. */
6000 head_ref_name
= got_worktree_get_head_ref_name(worktree
);
6001 if (head_ref_name
== NULL
) {
6002 err
= got_error_from_errno("got_worktree_get_head_ref_name");
6005 /* Lock the reference here to prevent concurrent modification. */
6006 err
= got_ref_open(&head_ref2
, repo
, head_ref_name
, 1);
6009 err
= got_ref_resolve(&head_commit_id2
, repo
, head_ref2
);
6012 if (got_object_id_cmp(head_commit_id
, head_commit_id2
) != 0) {
6013 err
= got_error(GOT_ERR_COMMIT_HEAD_CHANGED
);
6016 /* Update branch head in repository. */
6017 err
= got_ref_change_ref(head_ref2
, *new_commit_id
);
6020 err
= got_ref_write(head_ref2
, repo
);
6024 err
= got_worktree_set_base_commit_id(worktree
, repo
, *new_commit_id
);
6028 err
= ref_base_commit(worktree
, repo
);
6032 got_object_id_queue_free(&parent_ids
);
6034 got_object_tree_close(head_tree
);
6036 got_object_commit_close(head_commit
);
6037 free(head_commit_id2
);
6039 unlockerr
= got_ref_unlock(head_ref2
);
6040 if (unlockerr
&& err
== NULL
)
6042 got_ref_close(head_ref2
);
6047 static const struct got_error
*
6048 check_path_is_commitable(const char *path
,
6049 struct got_pathlist_head
*commitable_paths
)
6051 struct got_pathlist_entry
*cpe
= NULL
;
6052 size_t path_len
= strlen(path
);
6054 TAILQ_FOREACH(cpe
, commitable_paths
, entry
) {
6055 struct got_commitable
*ct
= cpe
->data
;
6056 const char *ct_path
= ct
->path
;
6058 while (ct_path
[0] == '/')
6061 if (strcmp(path
, ct_path
) == 0 ||
6062 got_path_is_child(ct_path
, path
, path_len
))
6067 return got_error_path(path
, GOT_ERR_BAD_PATH
);
6072 static const struct got_error
*
6073 check_staged_file(void *arg
, struct got_fileindex_entry
*ie
)
6075 int *have_staged_files
= arg
;
6077 if (got_fileindex_entry_stage_get(ie
) != GOT_FILEIDX_STAGE_NONE
) {
6078 *have_staged_files
= 1;
6079 return got_error(GOT_ERR_CANCELLED
);
6085 static const struct got_error
*
6086 check_non_staged_files(struct got_fileindex
*fileindex
,
6087 struct got_pathlist_head
*paths
)
6089 struct got_pathlist_entry
*pe
;
6090 struct got_fileindex_entry
*ie
;
6092 TAILQ_FOREACH(pe
, paths
, entry
) {
6093 if (pe
->path
[0] == '\0')
6095 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
6097 return got_error_path(pe
->path
, GOT_ERR_BAD_PATH
);
6098 if (got_fileindex_entry_stage_get(ie
) == GOT_FILEIDX_STAGE_NONE
)
6099 return got_error_path(pe
->path
,
6100 GOT_ERR_FILE_NOT_STAGED
);
6106 const struct got_error
*
6107 got_worktree_commit(struct got_object_id
**new_commit_id
,
6108 struct got_worktree
*worktree
, struct got_pathlist_head
*paths
,
6109 const char *author
, const char *committer
, int allow_bad_symlinks
,
6110 int show_diff
, got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
6111 got_worktree_status_cb status_cb
, void *status_arg
,
6112 struct got_repository
*repo
)
6114 const struct got_error
*err
= NULL
, *unlockerr
= NULL
, *sync_err
;
6115 struct got_fileindex
*fileindex
= NULL
;
6116 char *fileindex_path
= NULL
;
6117 struct got_pathlist_head commitable_paths
;
6118 struct collect_commitables_arg cc_arg
;
6119 struct got_pathlist_entry
*pe
;
6120 struct got_reference
*head_ref
= NULL
;
6121 struct got_object_id
*head_commit_id
= NULL
;
6122 char *diff_path
= NULL
;
6123 int have_staged_files
= 0;
6125 *new_commit_id
= NULL
;
6127 memset(&cc_arg
, 0, sizeof(cc_arg
));
6128 TAILQ_INIT(&commitable_paths
);
6130 err
= lock_worktree(worktree
, LOCK_EX
);
6134 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
6138 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
6142 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
6146 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
6147 &have_staged_files
);
6148 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6150 if (have_staged_files
) {
6151 err
= check_non_staged_files(fileindex
, paths
);
6156 cc_arg
.commitable_paths
= &commitable_paths
;
6157 cc_arg
.worktree
= worktree
;
6158 cc_arg
.fileindex
= fileindex
;
6160 cc_arg
.have_staged_files
= have_staged_files
;
6161 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
6162 cc_arg
.diff_header_shown
= 0;
6164 err
= got_opentemp_named(&diff_path
, &cc_arg
.diff_outfile
,
6165 GOT_TMPDIR_STR
"/got", ".diff");
6168 cc_arg
.f1
= got_opentemp();
6169 if (cc_arg
.f1
== NULL
) {
6170 err
= got_error_from_errno("got_opentemp");
6173 cc_arg
.f2
= got_opentemp();
6174 if (cc_arg
.f2
== NULL
) {
6175 err
= got_error_from_errno("got_opentemp");
6180 TAILQ_FOREACH(pe
, paths
, entry
) {
6181 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
6182 collect_commitables
, &cc_arg
, NULL
, NULL
, 0, 0);
6188 if (fflush(cc_arg
.diff_outfile
) == EOF
) {
6189 err
= got_error_from_errno("fflush");
6194 if (TAILQ_EMPTY(&commitable_paths
)) {
6195 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
6199 TAILQ_FOREACH(pe
, paths
, entry
) {
6200 err
= check_path_is_commitable(pe
->path
, &commitable_paths
);
6205 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
6206 struct got_commitable
*ct
= pe
->data
;
6207 const char *ct_path
= ct
->in_repo_path
;
6209 while (ct_path
[0] == '/')
6211 err
= check_out_of_date(ct_path
, ct
->status
,
6212 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
6213 head_commit_id
, repo
, GOT_ERR_COMMIT_OUT_OF_DATE
);
6219 err
= commit_worktree(new_commit_id
, &commitable_paths
,
6220 head_commit_id
, NULL
, worktree
, author
, committer
,
6221 (diff_path
&& cc_arg
.diff_header_shown
) ? diff_path
: NULL
,
6222 commit_msg_cb
, commit_arg
, status_cb
, status_arg
, repo
);
6226 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
6227 *new_commit_id
, fileindex
, have_staged_files
);
6228 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6229 if (sync_err
&& err
== NULL
)
6233 got_fileindex_free(fileindex
);
6234 free(fileindex_path
);
6235 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6236 if (unlockerr
&& err
== NULL
)
6238 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
6239 struct got_commitable
*ct
= pe
->data
;
6241 free_commitable(ct
);
6243 got_pathlist_free(&commitable_paths
, GOT_PATHLIST_FREE_NONE
);
6244 if (diff_path
&& unlink(diff_path
) == -1 && err
== NULL
)
6245 err
= got_error_from_errno2("unlink", diff_path
);
6247 if (cc_arg
.diff_outfile
&& fclose(cc_arg
.diff_outfile
) == EOF
&&
6249 err
= got_error_from_errno("fclose");
6254 got_commitable_get_path(struct got_commitable
*ct
)
6260 got_commitable_get_status(struct got_commitable
*ct
)
6265 struct check_rebase_ok_arg
{
6266 struct got_worktree
*worktree
;
6267 struct got_repository
*repo
;
6270 static const struct got_error
*
6271 check_rebase_ok(void *arg
, struct got_fileindex_entry
*ie
)
6273 const struct got_error
*err
= NULL
;
6274 struct check_rebase_ok_arg
*a
= arg
;
6275 unsigned char status
;
6279 /* Reject rebase of a work tree with mixed base commits. */
6280 if (memcmp(ie
->commit_sha1
, a
->worktree
->base_commit_id
->sha1
,
6281 SHA1_DIGEST_LENGTH
))
6282 return got_error(GOT_ERR_MIXED_COMMITS
);
6284 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
6286 return got_error_from_errno("asprintf");
6288 /* Reject rebase of a work tree with modified or staged files. */
6289 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
6294 if (status
!= GOT_STATUS_NO_CHANGE
)
6295 return got_error(GOT_ERR_MODIFIED
);
6296 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
6297 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
6302 const struct got_error
*
6303 got_worktree_rebase_prepare(struct got_reference
**new_base_branch_ref
,
6304 struct got_reference
**tmp_branch
, struct got_fileindex
**fileindex
,
6305 struct got_worktree
*worktree
, struct got_reference
*branch
,
6306 struct got_repository
*repo
)
6308 const struct got_error
*err
= NULL
;
6309 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6310 char *branch_ref_name
= NULL
;
6311 char *fileindex_path
= NULL
;
6312 struct check_rebase_ok_arg ok_arg
;
6313 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
6314 struct got_object_id
*wt_branch_tip
= NULL
;
6316 *new_base_branch_ref
= NULL
;
6320 err
= lock_worktree(worktree
, LOCK_EX
);
6324 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6328 ok_arg
.worktree
= worktree
;
6330 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6335 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6339 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6343 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6347 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6352 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
6355 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
6356 err
= got_error(GOT_ERR_REBASE_OUT_OF_DATE
);
6360 err
= got_ref_alloc_symref(new_base_branch_ref
,
6361 new_base_branch_ref_name
, wt_branch
);
6364 err
= got_ref_write(*new_base_branch_ref
, repo
);
6368 /* TODO Lock original branch's ref while rebasing? */
6370 err
= got_ref_alloc_symref(&branch_ref
, branch_ref_name
, branch
);
6374 err
= got_ref_write(branch_ref
, repo
);
6378 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6379 worktree
->base_commit_id
);
6382 err
= got_ref_write(*tmp_branch
, repo
);
6386 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6390 free(fileindex_path
);
6391 free(tmp_branch_name
);
6392 free(new_base_branch_ref_name
);
6393 free(branch_ref_name
);
6395 got_ref_close(branch_ref
);
6397 got_ref_close(wt_branch
);
6398 free(wt_branch_tip
);
6400 if (*new_base_branch_ref
) {
6401 got_ref_close(*new_base_branch_ref
);
6402 *new_base_branch_ref
= NULL
;
6405 got_ref_close(*tmp_branch
);
6409 got_fileindex_free(*fileindex
);
6412 lock_worktree(worktree
, LOCK_SH
);
6417 const struct got_error
*
6418 got_worktree_rebase_continue(struct got_object_id
**commit_id
,
6419 struct got_reference
**new_base_branch
, struct got_reference
**tmp_branch
,
6420 struct got_reference
**branch
, struct got_fileindex
**fileindex
,
6421 struct got_worktree
*worktree
, struct got_repository
*repo
)
6423 const struct got_error
*err
;
6424 char *commit_ref_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6425 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
6426 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
6427 char *fileindex_path
= NULL
;
6428 int have_staged_files
= 0;
6431 *new_base_branch
= NULL
;
6436 err
= lock_worktree(worktree
, LOCK_EX
);
6440 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6444 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
6445 &have_staged_files
);
6446 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6448 if (have_staged_files
) {
6449 err
= got_error(GOT_ERR_STAGED_PATHS
);
6453 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6457 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6461 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6465 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6469 err
= got_ref_open(&branch_ref
, repo
, branch_ref_name
, 0);
6473 err
= got_ref_open(branch
, repo
,
6474 got_ref_get_symref_target(branch_ref
), 0);
6478 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6482 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
6486 err
= got_ref_open(new_base_branch
, repo
,
6487 new_base_branch_ref_name
, 0);
6491 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
6495 free(commit_ref_name
);
6496 free(branch_ref_name
);
6497 free(fileindex_path
);
6499 got_ref_close(commit_ref
);
6501 got_ref_close(branch_ref
);
6506 got_ref_close(*tmp_branch
);
6509 if (*new_base_branch
) {
6510 got_ref_close(*new_base_branch
);
6511 *new_base_branch
= NULL
;
6514 got_ref_close(*branch
);
6518 got_fileindex_free(*fileindex
);
6521 lock_worktree(worktree
, LOCK_SH
);
6526 const struct got_error
*
6527 got_worktree_rebase_in_progress(int *in_progress
, struct got_worktree
*worktree
)
6529 const struct got_error
*err
;
6530 char *tmp_branch_name
= NULL
;
6532 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6536 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
6537 free(tmp_branch_name
);
6541 static const struct got_error
*
6542 collect_rebase_commit_msg(struct got_pathlist_head
*commitable_paths
,
6543 const char *diff_path
, char **logmsg
, void *arg
)
6549 static const struct got_error
*
6550 rebase_status(void *arg
, unsigned char status
, unsigned char staged_status
,
6551 const char *path
, struct got_object_id
*blob_id
,
6552 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
6553 int dirfd
, const char *de_name
)
6558 struct collect_merged_paths_arg
{
6559 got_worktree_checkout_cb progress_cb
;
6561 struct got_pathlist_head
*merged_paths
;
6564 static const struct got_error
*
6565 collect_merged_paths(void *arg
, unsigned char status
, const char *path
)
6567 const struct got_error
*err
;
6568 struct collect_merged_paths_arg
*a
= arg
;
6570 struct got_pathlist_entry
*new;
6572 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path
);
6576 if (status
!= GOT_STATUS_MERGE
&&
6577 status
!= GOT_STATUS_ADD
&&
6578 status
!= GOT_STATUS_DELETE
&&
6579 status
!= GOT_STATUS_CONFLICT
)
6584 return got_error_from_errno("strdup");
6586 err
= got_pathlist_insert(&new, a
->merged_paths
, p
, NULL
);
6587 if (err
|| new == NULL
)
6592 static const struct got_error
*
6593 store_commit_id(const char *commit_ref_name
, struct got_object_id
*commit_id
,
6594 int is_rebase
, struct got_repository
*repo
)
6596 const struct got_error
*err
;
6597 struct got_reference
*commit_ref
= NULL
;
6599 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6601 if (err
->code
!= GOT_ERR_NOT_REF
)
6603 err
= got_ref_alloc(&commit_ref
, commit_ref_name
, commit_id
);
6606 err
= got_ref_write(commit_ref
, repo
);
6609 } else if (is_rebase
) {
6610 struct got_object_id
*stored_id
;
6613 err
= got_ref_resolve(&stored_id
, repo
, commit_ref
);
6616 cmp
= got_object_id_cmp(commit_id
, stored_id
);
6619 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6625 got_ref_close(commit_ref
);
6629 static const struct got_error
*
6630 rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6631 const char *commit_ref_name
, struct got_worktree
*worktree
,
6632 struct got_fileindex
*fileindex
, struct got_object_id
*parent_commit_id
,
6633 struct got_object_id
*commit_id
, struct got_repository
*repo
,
6634 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6635 got_cancel_cb cancel_cb
, void *cancel_arg
)
6637 const struct got_error
*err
;
6638 struct got_reference
*commit_ref
= NULL
;
6639 struct collect_merged_paths_arg cmp_arg
;
6640 char *fileindex_path
;
6642 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6644 err
= get_fileindex_path(&fileindex_path
, worktree
);
6648 cmp_arg
.progress_cb
= progress_cb
;
6649 cmp_arg
.progress_arg
= progress_arg
;
6650 cmp_arg
.merged_paths
= merged_paths
;
6651 err
= merge_files(worktree
, fileindex
, fileindex_path
,
6652 parent_commit_id
, commit_id
, repo
, collect_merged_paths
,
6653 &cmp_arg
, cancel_cb
, cancel_arg
);
6655 got_ref_close(commit_ref
);
6659 const struct got_error
*
6660 got_worktree_rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6661 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6662 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
6663 struct got_repository
*repo
,
6664 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6665 got_cancel_cb cancel_cb
, void *cancel_arg
)
6667 const struct got_error
*err
;
6668 char *commit_ref_name
;
6670 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6674 err
= store_commit_id(commit_ref_name
, commit_id
, 1, repo
);
6678 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
6679 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
6680 progress_arg
, cancel_cb
, cancel_arg
);
6682 free(commit_ref_name
);
6686 const struct got_error
*
6687 got_worktree_histedit_merge_files(struct got_pathlist_head
*merged_paths
,
6688 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6689 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
6690 struct got_repository
*repo
,
6691 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6692 got_cancel_cb cancel_cb
, void *cancel_arg
)
6694 const struct got_error
*err
;
6695 char *commit_ref_name
;
6697 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6701 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
6705 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
6706 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
6707 progress_arg
, cancel_cb
, cancel_arg
);
6709 free(commit_ref_name
);
6713 static const struct got_error
*
6714 rebase_commit(struct got_object_id
**new_commit_id
,
6715 struct got_pathlist_head
*merged_paths
, struct got_reference
*commit_ref
,
6716 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6717 struct got_reference
*tmp_branch
, const char *committer
,
6718 struct got_commit_object
*orig_commit
, const char *new_logmsg
,
6719 struct got_repository
*repo
)
6721 const struct got_error
*err
, *sync_err
;
6722 struct got_pathlist_head commitable_paths
;
6723 struct collect_commitables_arg cc_arg
;
6724 char *fileindex_path
= NULL
;
6725 struct got_reference
*head_ref
= NULL
;
6726 struct got_object_id
*head_commit_id
= NULL
;
6727 char *logmsg
= NULL
;
6729 memset(&cc_arg
, 0, sizeof(cc_arg
));
6730 TAILQ_INIT(&commitable_paths
);
6731 *new_commit_id
= NULL
;
6733 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6735 err
= get_fileindex_path(&fileindex_path
, worktree
);
6739 cc_arg
.commitable_paths
= &commitable_paths
;
6740 cc_arg
.worktree
= worktree
;
6742 cc_arg
.have_staged_files
= 0;
6744 * If possible get the status of individual files directly to
6745 * avoid crawling the entire work tree once per rebased commit.
6747 * Ideally, merged_paths would contain a list of commitables
6748 * we could use so we could skip worktree_status() entirely.
6749 * However, we would then need carefully keep track of cumulative
6750 * effects of operations such as file additions and deletions
6751 * in 'got histedit -f' (folding multiple commits into one),
6752 * and this extra complexity is not really worth it.
6755 struct got_pathlist_entry
*pe
;
6756 TAILQ_FOREACH(pe
, merged_paths
, entry
) {
6757 err
= worktree_status(worktree
, pe
->path
, fileindex
,
6758 repo
, collect_commitables
, &cc_arg
, NULL
, NULL
, 1,
6764 err
= worktree_status(worktree
, "", fileindex
, repo
,
6765 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
6770 if (TAILQ_EMPTY(&commitable_paths
)) {
6771 /* No-op change; commit will be elided. */
6772 err
= got_ref_delete(commit_ref
, repo
);
6775 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
6779 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
6783 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
6788 logmsg
= strdup(new_logmsg
);
6789 if (logmsg
== NULL
) {
6790 err
= got_error_from_errno("strdup");
6794 err
= got_object_commit_get_logmsg(&logmsg
, orig_commit
);
6799 /* NB: commit_worktree will call free(logmsg) */
6800 err
= commit_worktree(new_commit_id
, &commitable_paths
, head_commit_id
,
6801 NULL
, worktree
, got_object_commit_get_author(orig_commit
),
6802 committer
? committer
:
6803 got_object_commit_get_committer(orig_commit
), NULL
,
6804 collect_rebase_commit_msg
, logmsg
, rebase_status
, NULL
, repo
);
6808 err
= got_ref_change_ref(tmp_branch
, *new_commit_id
);
6812 err
= got_ref_delete(commit_ref
, repo
);
6816 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
6817 *new_commit_id
, fileindex
, 0);
6818 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6819 if (sync_err
&& err
== NULL
)
6822 free(fileindex_path
);
6823 free(head_commit_id
);
6825 got_ref_close(head_ref
);
6827 free(*new_commit_id
);
6828 *new_commit_id
= NULL
;
6833 const struct got_error
*
6834 got_worktree_rebase_commit(struct got_object_id
**new_commit_id
,
6835 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6836 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6837 const char *committer
, struct got_commit_object
*orig_commit
,
6838 struct got_object_id
*orig_commit_id
, struct got_repository
*repo
)
6840 const struct got_error
*err
;
6841 char *commit_ref_name
;
6842 struct got_reference
*commit_ref
= NULL
;
6843 struct got_object_id
*commit_id
= NULL
;
6845 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6849 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6852 err
= got_ref_resolve(&commit_id
, repo
, commit_ref
);
6855 if (got_object_id_cmp(commit_id
, orig_commit_id
) != 0) {
6856 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6860 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6861 worktree
, fileindex
, tmp_branch
, committer
, orig_commit
,
6865 got_ref_close(commit_ref
);
6866 free(commit_ref_name
);
6871 const struct got_error
*
6872 got_worktree_histedit_commit(struct got_object_id
**new_commit_id
,
6873 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6874 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6875 const char *committer
, struct got_commit_object
*orig_commit
,
6876 struct got_object_id
*orig_commit_id
, const char *new_logmsg
,
6877 struct got_repository
*repo
)
6879 const struct got_error
*err
;
6880 char *commit_ref_name
;
6881 struct got_reference
*commit_ref
= NULL
;
6883 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6887 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6891 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6892 worktree
, fileindex
, tmp_branch
, committer
, orig_commit
,
6896 got_ref_close(commit_ref
);
6897 free(commit_ref_name
);
6901 const struct got_error
*
6902 got_worktree_rebase_postpone(struct got_worktree
*worktree
,
6903 struct got_fileindex
*fileindex
)
6906 got_fileindex_free(fileindex
);
6907 return lock_worktree(worktree
, LOCK_SH
);
6910 static const struct got_error
*
6911 delete_ref(const char *name
, struct got_repository
*repo
)
6913 const struct got_error
*err
;
6914 struct got_reference
*ref
;
6916 err
= got_ref_open(&ref
, repo
, name
, 0);
6918 if (err
->code
== GOT_ERR_NOT_REF
)
6923 err
= got_ref_delete(ref
, repo
);
6928 static const struct got_error
*
6929 delete_rebase_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
6931 const struct got_error
*err
;
6932 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6933 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
6935 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6938 err
= delete_ref(tmp_branch_name
, repo
);
6942 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6945 err
= delete_ref(new_base_branch_ref_name
, repo
);
6949 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6952 err
= delete_ref(branch_ref_name
, repo
);
6956 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6959 err
= delete_ref(commit_ref_name
, repo
);
6964 free(tmp_branch_name
);
6965 free(new_base_branch_ref_name
);
6966 free(branch_ref_name
);
6967 free(commit_ref_name
);
6971 static const struct got_error
*
6972 create_backup_ref(const char *backup_ref_prefix
, struct got_reference
*branch
,
6973 struct got_object_id
*new_commit_id
, struct got_repository
*repo
)
6975 const struct got_error
*err
;
6976 struct got_reference
*ref
= NULL
;
6977 struct got_object_id
*old_commit_id
= NULL
;
6978 const char *branch_name
= NULL
;
6979 char *new_id_str
= NULL
;
6980 char *refname
= NULL
;
6982 branch_name
= got_ref_get_name(branch
);
6983 if (strncmp(branch_name
, "refs/heads/", 11) != 0)
6984 return got_error(GOT_ERR_BAD_REF_NAME
); /* should not happen */
6987 err
= got_object_id_str(&new_id_str
, new_commit_id
);
6991 if (asprintf(&refname
, "%s/%s/%s", backup_ref_prefix
, branch_name
,
6992 new_id_str
) == -1) {
6993 err
= got_error_from_errno("asprintf");
6997 err
= got_ref_resolve(&old_commit_id
, repo
, branch
);
7001 err
= got_ref_alloc(&ref
, refname
, old_commit_id
);
7005 err
= got_ref_write(ref
, repo
);
7009 free(old_commit_id
);
7015 const struct got_error
*
7016 got_worktree_rebase_complete(struct got_worktree
*worktree
,
7017 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7018 struct got_reference
*rebased_branch
, struct got_repository
*repo
,
7021 const struct got_error
*err
, *unlockerr
, *sync_err
;
7022 struct got_object_id
*new_head_commit_id
= NULL
;
7023 char *fileindex_path
= NULL
;
7025 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
7029 if (create_backup
) {
7030 err
= create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX
,
7031 rebased_branch
, new_head_commit_id
, repo
);
7036 err
= got_ref_change_ref(rebased_branch
, new_head_commit_id
);
7040 err
= got_ref_write(rebased_branch
, repo
);
7044 err
= got_worktree_set_head_ref(worktree
, rebased_branch
);
7048 err
= delete_rebase_refs(worktree
, repo
);
7052 err
= get_fileindex_path(&fileindex_path
, worktree
);
7055 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7056 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7057 if (sync_err
&& err
== NULL
)
7060 got_fileindex_free(fileindex
);
7061 free(fileindex_path
);
7062 free(new_head_commit_id
);
7063 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7064 if (unlockerr
&& err
== NULL
)
7069 const struct got_error
*
7070 got_worktree_rebase_abort(struct got_worktree
*worktree
,
7071 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7072 struct got_reference
*new_base_branch
,
7073 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7075 const struct got_error
*err
, *unlockerr
, *sync_err
;
7076 struct got_reference
*resolved
= NULL
;
7077 struct got_object_id
*commit_id
= NULL
;
7078 struct got_commit_object
*commit
= NULL
;
7079 char *fileindex_path
= NULL
;
7080 struct revert_file_args rfa
;
7081 struct got_object_id
*tree_id
= NULL
;
7083 err
= lock_worktree(worktree
, LOCK_EX
);
7087 err
= got_object_open_as_commit(&commit
, repo
,
7088 worktree
->base_commit_id
);
7092 err
= got_ref_open(&resolved
, repo
,
7093 got_ref_get_symref_target(new_base_branch
), 0);
7097 err
= got_worktree_set_head_ref(worktree
, resolved
);
7102 * XXX commits to the base branch could have happened while
7103 * we were busy rebasing; should we store the original commit ID
7104 * when rebase begins and read it back here?
7106 err
= got_ref_resolve(&commit_id
, repo
, resolved
);
7110 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
7114 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
7115 worktree
->path_prefix
);
7119 err
= delete_rebase_refs(worktree
, repo
);
7123 err
= get_fileindex_path(&fileindex_path
, worktree
);
7127 rfa
.worktree
= worktree
;
7128 rfa
.fileindex
= fileindex
;
7129 rfa
.progress_cb
= progress_cb
;
7130 rfa
.progress_arg
= progress_arg
;
7131 rfa
.patch_cb
= NULL
;
7132 rfa
.patch_arg
= NULL
;
7134 rfa
.unlink_added_files
= 0;
7135 err
= worktree_status(worktree
, "", fileindex
, repo
,
7136 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
7140 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7141 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7143 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7144 if (sync_err
&& err
== NULL
)
7147 got_ref_close(resolved
);
7151 got_object_commit_close(commit
);
7153 got_fileindex_free(fileindex
);
7154 free(fileindex_path
);
7156 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7157 if (unlockerr
&& err
== NULL
)
7162 const struct got_error
*
7163 got_worktree_histedit_prepare(struct got_reference
**tmp_branch
,
7164 struct got_reference
**branch_ref
, struct got_object_id
**base_commit_id
,
7165 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
7166 struct got_repository
*repo
)
7168 const struct got_error
*err
= NULL
;
7169 char *tmp_branch_name
= NULL
;
7170 char *branch_ref_name
= NULL
;
7171 char *base_commit_ref_name
= NULL
;
7172 char *fileindex_path
= NULL
;
7173 struct check_rebase_ok_arg ok_arg
;
7174 struct got_reference
*wt_branch
= NULL
;
7175 struct got_reference
*base_commit_ref
= NULL
;
7179 *base_commit_id
= NULL
;
7182 err
= lock_worktree(worktree
, LOCK_EX
);
7186 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7190 ok_arg
.worktree
= worktree
;
7192 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7197 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7201 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7205 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7210 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
7215 err
= got_ref_alloc_symref(branch_ref
, branch_ref_name
, wt_branch
);
7219 err
= got_ref_write(*branch_ref
, repo
);
7223 err
= got_ref_alloc(&base_commit_ref
, base_commit_ref_name
,
7224 worktree
->base_commit_id
);
7227 err
= got_ref_write(base_commit_ref
, repo
);
7230 *base_commit_id
= got_object_id_dup(worktree
->base_commit_id
);
7231 if (*base_commit_id
== NULL
) {
7232 err
= got_error_from_errno("got_object_id_dup");
7236 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
7237 worktree
->base_commit_id
);
7240 err
= got_ref_write(*tmp_branch
, repo
);
7244 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
7248 free(fileindex_path
);
7249 free(tmp_branch_name
);
7250 free(branch_ref_name
);
7251 free(base_commit_ref_name
);
7253 got_ref_close(wt_branch
);
7256 got_ref_close(*branch_ref
);
7260 got_ref_close(*tmp_branch
);
7263 free(*base_commit_id
);
7265 got_fileindex_free(*fileindex
);
7268 lock_worktree(worktree
, LOCK_SH
);
7273 const struct got_error
*
7274 got_worktree_histedit_postpone(struct got_worktree
*worktree
,
7275 struct got_fileindex
*fileindex
)
7278 got_fileindex_free(fileindex
);
7279 return lock_worktree(worktree
, LOCK_SH
);
7282 const struct got_error
*
7283 got_worktree_histedit_in_progress(int *in_progress
,
7284 struct got_worktree
*worktree
)
7286 const struct got_error
*err
;
7287 char *tmp_branch_name
= NULL
;
7289 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7293 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
7294 free(tmp_branch_name
);
7298 const struct got_error
*
7299 got_worktree_histedit_continue(struct got_object_id
**commit_id
,
7300 struct got_reference
**tmp_branch
, struct got_reference
**branch_ref
,
7301 struct got_object_id
**base_commit_id
, struct got_fileindex
**fileindex
,
7302 struct got_worktree
*worktree
, struct got_repository
*repo
)
7304 const struct got_error
*err
;
7305 char *commit_ref_name
= NULL
, *base_commit_ref_name
= NULL
;
7306 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
7307 struct got_reference
*commit_ref
= NULL
;
7308 struct got_reference
*base_commit_ref
= NULL
;
7309 char *fileindex_path
= NULL
;
7310 int have_staged_files
= 0;
7314 *base_commit_id
= NULL
;
7317 err
= lock_worktree(worktree
, LOCK_EX
);
7321 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7325 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
7326 &have_staged_files
);
7327 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7329 if (have_staged_files
) {
7330 err
= got_error(GOT_ERR_STAGED_PATHS
);
7334 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7338 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7342 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7346 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7351 err
= got_ref_open(branch_ref
, repo
, branch_ref_name
, 0);
7355 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7358 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
7362 err
= got_ref_open(&base_commit_ref
, repo
, base_commit_ref_name
, 0);
7365 err
= got_ref_resolve(base_commit_id
, repo
, base_commit_ref
);
7369 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
7373 free(commit_ref_name
);
7374 free(branch_ref_name
);
7375 free(fileindex_path
);
7377 got_ref_close(commit_ref
);
7378 if (base_commit_ref
)
7379 got_ref_close(base_commit_ref
);
7383 free(*base_commit_id
);
7384 *base_commit_id
= NULL
;
7386 got_ref_close(*tmp_branch
);
7390 got_fileindex_free(*fileindex
);
7393 lock_worktree(worktree
, LOCK_EX
);
7398 static const struct got_error
*
7399 delete_histedit_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7401 const struct got_error
*err
;
7402 char *tmp_branch_name
= NULL
, *base_commit_ref_name
= NULL
;
7403 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
7405 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7408 err
= delete_ref(tmp_branch_name
, repo
);
7412 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7416 err
= delete_ref(base_commit_ref_name
, repo
);
7420 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7423 err
= delete_ref(branch_ref_name
, repo
);
7427 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7430 err
= delete_ref(commit_ref_name
, repo
);
7434 free(tmp_branch_name
);
7435 free(base_commit_ref_name
);
7436 free(branch_ref_name
);
7437 free(commit_ref_name
);
7441 const struct got_error
*
7442 got_worktree_histedit_abort(struct got_worktree
*worktree
,
7443 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7444 struct got_reference
*branch
, struct got_object_id
*base_commit_id
,
7445 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7447 const struct got_error
*err
, *unlockerr
, *sync_err
;
7448 struct got_reference
*resolved
= NULL
;
7449 char *fileindex_path
= NULL
;
7450 struct got_commit_object
*commit
= NULL
;
7451 struct got_object_id
*tree_id
= NULL
;
7452 struct revert_file_args rfa
;
7454 err
= lock_worktree(worktree
, LOCK_EX
);
7458 err
= got_object_open_as_commit(&commit
, repo
,
7459 worktree
->base_commit_id
);
7463 err
= got_ref_open(&resolved
, repo
,
7464 got_ref_get_symref_target(branch
), 0);
7468 err
= got_worktree_set_head_ref(worktree
, resolved
);
7472 err
= got_worktree_set_base_commit_id(worktree
, repo
, base_commit_id
);
7476 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
7477 worktree
->path_prefix
);
7481 err
= delete_histedit_refs(worktree
, repo
);
7485 err
= get_fileindex_path(&fileindex_path
, worktree
);
7489 rfa
.worktree
= worktree
;
7490 rfa
.fileindex
= fileindex
;
7491 rfa
.progress_cb
= progress_cb
;
7492 rfa
.progress_arg
= progress_arg
;
7493 rfa
.patch_cb
= NULL
;
7494 rfa
.patch_arg
= NULL
;
7496 rfa
.unlink_added_files
= 0;
7497 err
= worktree_status(worktree
, "", fileindex
, repo
,
7498 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
7502 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7503 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7505 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7506 if (sync_err
&& err
== NULL
)
7509 got_ref_close(resolved
);
7511 free(fileindex_path
);
7513 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7514 if (unlockerr
&& err
== NULL
)
7519 const struct got_error
*
7520 got_worktree_histedit_complete(struct got_worktree
*worktree
,
7521 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7522 struct got_reference
*edited_branch
, struct got_repository
*repo
)
7524 const struct got_error
*err
, *unlockerr
, *sync_err
;
7525 struct got_object_id
*new_head_commit_id
= NULL
;
7526 struct got_reference
*resolved
= NULL
;
7527 char *fileindex_path
= NULL
;
7529 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
7533 err
= got_ref_open(&resolved
, repo
,
7534 got_ref_get_symref_target(edited_branch
), 0);
7538 err
= create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX
,
7539 resolved
, new_head_commit_id
, repo
);
7543 err
= got_ref_change_ref(resolved
, new_head_commit_id
);
7547 err
= got_ref_write(resolved
, repo
);
7551 err
= got_worktree_set_head_ref(worktree
, resolved
);
7555 err
= delete_histedit_refs(worktree
, repo
);
7559 err
= get_fileindex_path(&fileindex_path
, worktree
);
7562 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7563 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7564 if (sync_err
&& err
== NULL
)
7567 got_fileindex_free(fileindex
);
7568 free(fileindex_path
);
7569 free(new_head_commit_id
);
7570 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7571 if (unlockerr
&& err
== NULL
)
7576 const struct got_error
*
7577 got_worktree_histedit_skip_commit(struct got_worktree
*worktree
,
7578 struct got_object_id
*commit_id
, struct got_repository
*repo
)
7580 const struct got_error
*err
;
7581 char *commit_ref_name
;
7583 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7587 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
7591 err
= delete_ref(commit_ref_name
, repo
);
7593 free(commit_ref_name
);
7597 const struct got_error
*
7598 got_worktree_integrate_prepare(struct got_fileindex
**fileindex
,
7599 struct got_reference
**branch_ref
, struct got_reference
**base_branch_ref
,
7600 struct got_worktree
*worktree
, const char *refname
,
7601 struct got_repository
*repo
)
7603 const struct got_error
*err
= NULL
;
7604 char *fileindex_path
= NULL
;
7605 struct check_rebase_ok_arg ok_arg
;
7609 *base_branch_ref
= NULL
;
7611 err
= lock_worktree(worktree
, LOCK_EX
);
7615 if (strcmp(refname
, got_worktree_get_head_ref_name(worktree
)) == 0) {
7616 err
= got_error_msg(GOT_ERR_SAME_BRANCH
,
7617 "cannot integrate a branch into itself; "
7618 "update -b or different branch name required");
7622 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7626 /* Preconditions are the same as for rebase. */
7627 ok_arg
.worktree
= worktree
;
7629 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7634 err
= got_ref_open(branch_ref
, repo
, refname
, 1);
7638 err
= got_ref_open(base_branch_ref
, repo
,
7639 got_worktree_get_head_ref_name(worktree
), 1);
7643 got_ref_close(*branch_ref
);
7646 if (*base_branch_ref
) {
7647 got_ref_close(*base_branch_ref
);
7648 *base_branch_ref
= NULL
;
7651 got_fileindex_free(*fileindex
);
7654 lock_worktree(worktree
, LOCK_SH
);
7659 const struct got_error
*
7660 got_worktree_integrate_continue(struct got_worktree
*worktree
,
7661 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7662 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
,
7663 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7664 got_cancel_cb cancel_cb
, void *cancel_arg
)
7666 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
7667 char *fileindex_path
= NULL
;
7668 struct got_object_id
*tree_id
= NULL
, *commit_id
= NULL
;
7669 struct got_commit_object
*commit
= NULL
;
7671 err
= get_fileindex_path(&fileindex_path
, worktree
);
7675 err
= got_ref_resolve(&commit_id
, repo
, branch_ref
);
7679 err
= got_object_open_as_commit(&commit
, repo
, commit_id
);
7683 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
7684 worktree
->path_prefix
);
7688 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
7692 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
, repo
,
7693 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
7697 err
= got_ref_change_ref(base_branch_ref
, commit_id
);
7701 err
= got_ref_write(base_branch_ref
, repo
);
7705 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7707 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7708 if (sync_err
&& err
== NULL
)
7712 unlockerr
= got_ref_unlock(branch_ref
);
7713 if (unlockerr
&& err
== NULL
)
7715 got_ref_close(branch_ref
);
7717 unlockerr
= got_ref_unlock(base_branch_ref
);
7718 if (unlockerr
&& err
== NULL
)
7720 got_ref_close(base_branch_ref
);
7722 got_fileindex_free(fileindex
);
7723 free(fileindex_path
);
7726 got_object_commit_close(commit
);
7728 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7729 if (unlockerr
&& err
== NULL
)
7734 const struct got_error
*
7735 got_worktree_integrate_abort(struct got_worktree
*worktree
,
7736 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7737 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
)
7739 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
7741 got_fileindex_free(fileindex
);
7743 err
= lock_worktree(worktree
, LOCK_SH
);
7745 unlockerr
= got_ref_unlock(branch_ref
);
7746 if (unlockerr
&& err
== NULL
)
7748 got_ref_close(branch_ref
);
7750 unlockerr
= got_ref_unlock(base_branch_ref
);
7751 if (unlockerr
&& err
== NULL
)
7753 got_ref_close(base_branch_ref
);
7758 const struct got_error
*
7759 got_worktree_merge_postpone(struct got_worktree
*worktree
,
7760 struct got_fileindex
*fileindex
)
7762 const struct got_error
*err
, *sync_err
;
7763 char *fileindex_path
= NULL
;
7765 err
= get_fileindex_path(&fileindex_path
, worktree
);
7769 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7771 err
= lock_worktree(worktree
, LOCK_SH
);
7772 if (sync_err
&& err
== NULL
)
7775 got_fileindex_free(fileindex
);
7776 free(fileindex_path
);
7780 static const struct got_error
*
7781 delete_merge_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7783 const struct got_error
*err
;
7784 char *branch_refname
= NULL
, *commit_refname
= NULL
;
7786 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7789 err
= delete_ref(branch_refname
, repo
);
7793 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7796 err
= delete_ref(commit_refname
, repo
);
7801 free(branch_refname
);
7802 free(commit_refname
);
7806 struct merge_commit_msg_arg
{
7807 struct got_worktree
*worktree
;
7808 const char *branch_name
;
7811 static const struct got_error
*
7812 merge_commit_msg_cb(struct got_pathlist_head
*commitable_paths
,
7813 const char *diff_path
, char **logmsg
, void *arg
)
7815 struct merge_commit_msg_arg
*a
= arg
;
7817 if (asprintf(logmsg
, "merge %s into %s\n", a
->branch_name
,
7818 got_worktree_get_head_ref_name(a
->worktree
)) == -1)
7819 return got_error_from_errno("asprintf");
7825 const struct got_error
*
7826 got_worktree_merge_branch(struct got_worktree
*worktree
,
7827 struct got_fileindex
*fileindex
,
7828 struct got_object_id
*yca_commit_id
,
7829 struct got_object_id
*branch_tip
,
7830 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
7831 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
7833 const struct got_error
*err
;
7834 char *fileindex_path
= NULL
;
7836 err
= get_fileindex_path(&fileindex_path
, worktree
);
7840 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
7845 err
= merge_files(worktree
, fileindex
, fileindex_path
, yca_commit_id
,
7846 branch_tip
, repo
, progress_cb
, progress_arg
,
7847 cancel_cb
, cancel_arg
);
7849 free(fileindex_path
);
7853 const struct got_error
*
7854 got_worktree_merge_commit(struct got_object_id
**new_commit_id
,
7855 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
7856 const char *author
, const char *committer
, int allow_bad_symlinks
,
7857 struct got_object_id
*branch_tip
, const char *branch_name
,
7858 struct got_repository
*repo
,
7859 got_worktree_status_cb status_cb
, void *status_arg
)
7862 const struct got_error
*err
= NULL
, *sync_err
;
7863 struct got_pathlist_head commitable_paths
;
7864 struct collect_commitables_arg cc_arg
;
7865 struct got_pathlist_entry
*pe
;
7866 struct got_reference
*head_ref
= NULL
;
7867 struct got_object_id
*head_commit_id
= NULL
;
7868 int have_staged_files
= 0;
7869 struct merge_commit_msg_arg mcm_arg
;
7870 char *fileindex_path
= NULL
;
7872 memset(&cc_arg
, 0, sizeof(cc_arg
));
7873 *new_commit_id
= NULL
;
7875 TAILQ_INIT(&commitable_paths
);
7877 err
= get_fileindex_path(&fileindex_path
, worktree
);
7881 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
7885 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
7889 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
7890 &have_staged_files
);
7891 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7893 if (have_staged_files
) {
7894 err
= got_error(GOT_ERR_MERGE_STAGED_PATHS
);
7898 cc_arg
.commitable_paths
= &commitable_paths
;
7899 cc_arg
.worktree
= worktree
;
7900 cc_arg
.fileindex
= fileindex
;
7902 cc_arg
.have_staged_files
= have_staged_files
;
7903 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
7904 err
= worktree_status(worktree
, "", fileindex
, repo
,
7905 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
7909 if (TAILQ_EMPTY(&commitable_paths
)) {
7910 err
= got_error_fmt(GOT_ERR_COMMIT_NO_CHANGES
,
7911 "merge of %s cannot proceed", branch_name
);
7915 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
7916 struct got_commitable
*ct
= pe
->data
;
7917 const char *ct_path
= ct
->in_repo_path
;
7919 while (ct_path
[0] == '/')
7921 err
= check_out_of_date(ct_path
, ct
->status
,
7922 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
7923 head_commit_id
, repo
, GOT_ERR_MERGE_COMMIT_OUT_OF_DATE
);
7929 mcm_arg
.worktree
= worktree
;
7930 mcm_arg
.branch_name
= branch_name
;
7931 err
= commit_worktree(new_commit_id
, &commitable_paths
,
7932 head_commit_id
, branch_tip
, worktree
, author
, committer
, NULL
,
7933 merge_commit_msg_cb
, &mcm_arg
, status_cb
, status_arg
, repo
);
7937 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
7938 *new_commit_id
, fileindex
, have_staged_files
);
7939 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7940 if (sync_err
&& err
== NULL
)
7943 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
7944 struct got_commitable
*ct
= pe
->data
;
7946 free_commitable(ct
);
7948 got_pathlist_free(&commitable_paths
, GOT_PATHLIST_FREE_NONE
);
7949 free(fileindex_path
);
7953 const struct got_error
*
7954 got_worktree_merge_complete(struct got_worktree
*worktree
,
7955 struct got_fileindex
*fileindex
, struct got_repository
*repo
)
7957 const struct got_error
*err
, *unlockerr
, *sync_err
;
7958 char *fileindex_path
= NULL
;
7960 err
= delete_merge_refs(worktree
, repo
);
7964 err
= get_fileindex_path(&fileindex_path
, worktree
);
7967 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7968 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7969 if (sync_err
&& err
== NULL
)
7972 got_fileindex_free(fileindex
);
7973 free(fileindex_path
);
7974 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7975 if (unlockerr
&& err
== NULL
)
7980 const struct got_error
*
7981 got_worktree_merge_in_progress(int *in_progress
, struct got_worktree
*worktree
,
7982 struct got_repository
*repo
)
7984 const struct got_error
*err
;
7985 char *branch_refname
= NULL
;
7986 struct got_reference
*branch_ref
= NULL
;
7990 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7993 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
7994 free(branch_refname
);
7996 if (err
->code
!= GOT_ERR_NOT_REF
)
8004 const struct got_error
*got_worktree_merge_prepare(
8005 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
8006 struct got_reference
*branch
, struct got_repository
*repo
)
8008 const struct got_error
*err
= NULL
;
8009 char *fileindex_path
= NULL
;
8010 char *branch_refname
= NULL
, *commit_refname
= NULL
;
8011 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
8012 struct got_reference
*commit_ref
= NULL
;
8013 struct got_object_id
*branch_tip
= NULL
, *wt_branch_tip
= NULL
;
8014 struct check_rebase_ok_arg ok_arg
;
8018 err
= lock_worktree(worktree
, LOCK_EX
);
8022 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
8026 /* Preconditions are the same as for rebase. */
8027 ok_arg
.worktree
= worktree
;
8029 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
8034 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8038 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
8042 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
8047 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
8051 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
8052 err
= got_error(GOT_ERR_MERGE_OUT_OF_DATE
);
8056 err
= got_ref_resolve(&branch_tip
, repo
, branch
);
8060 err
= got_ref_alloc_symref(&branch_ref
, branch_refname
, branch
);
8063 err
= got_ref_write(branch_ref
, repo
);
8067 err
= got_ref_alloc(&commit_ref
, commit_refname
, branch_tip
);
8070 err
= got_ref_write(commit_ref
, repo
);
8075 free(branch_refname
);
8076 free(commit_refname
);
8077 free(fileindex_path
);
8079 got_ref_close(branch_ref
);
8081 got_ref_close(commit_ref
);
8083 got_ref_close(wt_branch
);
8084 free(wt_branch_tip
);
8087 got_fileindex_free(*fileindex
);
8090 lock_worktree(worktree
, LOCK_SH
);
8095 const struct got_error
*
8096 got_worktree_merge_continue(char **branch_name
,
8097 struct got_object_id
**branch_tip
, struct got_fileindex
**fileindex
,
8098 struct got_worktree
*worktree
, struct got_repository
*repo
)
8100 const struct got_error
*err
;
8101 char *commit_refname
= NULL
, *branch_refname
= NULL
;
8102 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
8103 char *fileindex_path
= NULL
;
8104 int have_staged_files
= 0;
8106 *branch_name
= NULL
;
8110 err
= lock_worktree(worktree
, LOCK_EX
);
8114 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
8118 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
8119 &have_staged_files
);
8120 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
8122 if (have_staged_files
) {
8123 err
= got_error(GOT_ERR_STAGED_PATHS
);
8127 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
8131 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
8135 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
8139 if (!got_ref_is_symbolic(branch_ref
)) {
8140 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
8141 "%s is not a symbolic reference",
8142 got_ref_get_name(branch_ref
));
8145 *branch_name
= strdup(got_ref_get_symref_target(branch_ref
));
8146 if (*branch_name
== NULL
) {
8147 err
= got_error_from_errno("strdup");
8151 err
= got_ref_open(&commit_ref
, repo
, commit_refname
, 0);
8155 err
= got_ref_resolve(branch_tip
, repo
, commit_ref
);
8159 free(commit_refname
);
8160 free(branch_refname
);
8161 free(fileindex_path
);
8163 got_ref_close(commit_ref
);
8165 got_ref_close(branch_ref
);
8169 *branch_name
= NULL
;
8174 got_fileindex_free(*fileindex
);
8177 lock_worktree(worktree
, LOCK_SH
);
8182 const struct got_error
*
8183 got_worktree_merge_abort(struct got_worktree
*worktree
,
8184 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
8185 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
8187 const struct got_error
*err
, *unlockerr
, *sync_err
;
8188 struct got_object_id
*commit_id
= NULL
;
8189 struct got_commit_object
*commit
= NULL
;
8190 char *fileindex_path
= NULL
;
8191 struct revert_file_args rfa
;
8192 struct got_object_id
*tree_id
= NULL
;
8194 err
= got_object_open_as_commit(&commit
, repo
,
8195 worktree
->base_commit_id
);
8199 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
8200 worktree
->path_prefix
);
8204 err
= delete_merge_refs(worktree
, repo
);
8208 err
= get_fileindex_path(&fileindex_path
, worktree
);
8212 rfa
.worktree
= worktree
;
8213 rfa
.fileindex
= fileindex
;
8214 rfa
.progress_cb
= progress_cb
;
8215 rfa
.progress_arg
= progress_arg
;
8216 rfa
.patch_cb
= NULL
;
8217 rfa
.patch_arg
= NULL
;
8219 rfa
.unlink_added_files
= 1;
8220 err
= worktree_status(worktree
, "", fileindex
, repo
,
8221 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
8225 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
8226 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
8228 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8229 if (sync_err
&& err
== NULL
)
8235 got_object_commit_close(commit
);
8237 got_fileindex_free(fileindex
);
8238 free(fileindex_path
);
8240 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8241 if (unlockerr
&& err
== NULL
)
8246 struct check_stage_ok_arg
{
8247 struct got_object_id
*head_commit_id
;
8248 struct got_worktree
*worktree
;
8249 struct got_fileindex
*fileindex
;
8250 struct got_repository
*repo
;
8254 static const struct got_error
*
8255 check_stage_ok(void *arg
, unsigned char status
,
8256 unsigned char staged_status
, const char *relpath
,
8257 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
8258 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
8260 struct check_stage_ok_arg
*a
= arg
;
8261 const struct got_error
*err
= NULL
;
8262 struct got_fileindex_entry
*ie
;
8263 struct got_object_id base_commit_id
;
8264 struct got_object_id
*base_commit_idp
= NULL
;
8265 char *in_repo_path
= NULL
, *p
;
8267 if (status
== GOT_STATUS_UNVERSIONED
||
8268 status
== GOT_STATUS_NO_CHANGE
)
8270 if (status
== GOT_STATUS_NONEXISTENT
)
8271 return got_error_set_errno(ENOENT
, relpath
);
8273 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8275 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8277 if (asprintf(&in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
8278 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
8280 return got_error_from_errno("asprintf");
8282 if (got_fileindex_entry_has_commit(ie
)) {
8283 memcpy(base_commit_id
.sha1
, ie
->commit_sha1
,
8284 SHA1_DIGEST_LENGTH
);
8285 base_commit_idp
= &base_commit_id
;
8288 if (status
== GOT_STATUS_CONFLICT
) {
8289 err
= got_error_path(ie
->path
, GOT_ERR_STAGE_CONFLICT
);
8291 } else if (status
!= GOT_STATUS_ADD
&&
8292 status
!= GOT_STATUS_MODIFY
&&
8293 status
!= GOT_STATUS_DELETE
) {
8294 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STATUS
);
8298 a
->have_changes
= 1;
8303 err
= check_out_of_date(p
, status
, staged_status
,
8304 blob_id
, base_commit_idp
, a
->head_commit_id
, a
->repo
,
8305 GOT_ERR_STAGE_OUT_OF_DATE
);
8311 struct stage_path_arg
{
8312 struct got_worktree
*worktree
;
8313 struct got_fileindex
*fileindex
;
8314 struct got_repository
*repo
;
8315 got_worktree_status_cb status_cb
;
8317 got_worktree_patch_cb patch_cb
;
8319 int staged_something
;
8320 int allow_bad_symlinks
;
8323 static const struct got_error
*
8324 stage_path(void *arg
, unsigned char status
,
8325 unsigned char staged_status
, const char *relpath
,
8326 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
8327 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
8329 struct stage_path_arg
*a
= arg
;
8330 const struct got_error
*err
= NULL
;
8331 struct got_fileindex_entry
*ie
;
8332 char *ondisk_path
= NULL
, *path_content
= NULL
;
8334 struct got_object_id
*new_staged_blob_id
= NULL
;
8337 if (status
== GOT_STATUS_UNVERSIONED
)
8340 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8342 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8344 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
8346 return got_error_from_errno("asprintf");
8349 case GOT_STATUS_ADD
:
8350 case GOT_STATUS_MODIFY
:
8351 /* XXX could sb.st_mode be passed in by our caller? */
8352 if (lstat(ondisk_path
, &sb
) == -1) {
8353 err
= got_error_from_errno2("lstat", ondisk_path
);
8357 if (status
== GOT_STATUS_ADD
) {
8358 int choice
= GOT_PATCH_CHOICE_NONE
;
8359 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8360 status
, ie
->path
, NULL
, 1, 1);
8363 if (choice
!= GOT_PATCH_CHOICE_YES
)
8366 err
= create_patched_content(&path_content
, 0,
8367 staged_blob_id
? staged_blob_id
: blob_id
,
8368 ondisk_path
, dirfd
, de_name
, ie
->path
,
8369 a
->repo
, a
->patch_cb
, a
->patch_arg
);
8370 if (err
|| path_content
== NULL
)
8374 err
= got_object_blob_create(&new_staged_blob_id
,
8375 path_content
? path_content
: ondisk_path
, a
->repo
);
8378 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
8379 SHA1_DIGEST_LENGTH
);
8380 if (status
== GOT_STATUS_ADD
|| staged_status
== GOT_STATUS_ADD
)
8381 stage
= GOT_FILEIDX_STAGE_ADD
;
8383 stage
= GOT_FILEIDX_STAGE_MODIFY
;
8384 got_fileindex_entry_stage_set(ie
, stage
);
8385 if (S_ISLNK(sb
.st_mode
)) {
8386 int is_bad_symlink
= 0;
8387 if (!a
->allow_bad_symlinks
) {
8388 char target_path
[PATH_MAX
];
8390 target_len
= readlink(ondisk_path
, target_path
,
8391 sizeof(target_path
));
8392 if (target_len
== -1) {
8393 err
= got_error_from_errno2("readlink",
8397 err
= is_bad_symlink_target(&is_bad_symlink
,
8398 target_path
, target_len
, ondisk_path
,
8399 a
->worktree
->root_path
);
8402 if (is_bad_symlink
) {
8403 err
= got_error_path(ondisk_path
,
8404 GOT_ERR_BAD_SYMLINK
);
8409 got_fileindex_entry_staged_filetype_set(ie
,
8410 GOT_FILEIDX_MODE_BAD_SYMLINK
);
8412 got_fileindex_entry_staged_filetype_set(ie
,
8413 GOT_FILEIDX_MODE_SYMLINK
);
8415 got_fileindex_entry_staged_filetype_set(ie
,
8416 GOT_FILEIDX_MODE_REGULAR_FILE
);
8418 a
->staged_something
= 1;
8419 if (a
->status_cb
== NULL
)
8421 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
8422 get_staged_status(ie
), relpath
, blob_id
,
8423 new_staged_blob_id
, NULL
, dirfd
, de_name
);
8427 * When staging the reverse of the staged diff,
8428 * implicitly unstage the file.
8430 if (memcmp(ie
->staged_blob_sha1
, ie
->blob_sha1
,
8431 sizeof(ie
->blob_sha1
)) == 0) {
8432 got_fileindex_entry_stage_set(ie
,
8433 GOT_FILEIDX_STAGE_NONE
);
8436 case GOT_STATUS_DELETE
:
8437 if (staged_status
== GOT_STATUS_DELETE
)
8440 int choice
= GOT_PATCH_CHOICE_NONE
;
8441 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
, status
,
8442 ie
->path
, NULL
, 1, 1);
8445 if (choice
== GOT_PATCH_CHOICE_NO
)
8447 if (choice
!= GOT_PATCH_CHOICE_YES
) {
8448 err
= got_error(GOT_ERR_PATCH_CHOICE
);
8452 stage
= GOT_FILEIDX_STAGE_DELETE
;
8453 got_fileindex_entry_stage_set(ie
, stage
);
8454 a
->staged_something
= 1;
8455 if (a
->status_cb
== NULL
)
8457 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
8458 get_staged_status(ie
), relpath
, NULL
, NULL
, NULL
, dirfd
,
8461 case GOT_STATUS_NO_CHANGE
:
8463 case GOT_STATUS_CONFLICT
:
8464 err
= got_error_path(relpath
, GOT_ERR_STAGE_CONFLICT
);
8466 case GOT_STATUS_NONEXISTENT
:
8467 err
= got_error_set_errno(ENOENT
, relpath
);
8470 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8474 if (path_content
&& unlink(path_content
) == -1 && err
== NULL
)
8475 err
= got_error_from_errno2("unlink", path_content
);
8478 free(new_staged_blob_id
);
8482 const struct got_error
*
8483 got_worktree_stage(struct got_worktree
*worktree
,
8484 struct got_pathlist_head
*paths
,
8485 got_worktree_status_cb status_cb
, void *status_arg
,
8486 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8487 int allow_bad_symlinks
, struct got_repository
*repo
)
8489 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8490 struct got_pathlist_entry
*pe
;
8491 struct got_fileindex
*fileindex
= NULL
;
8492 char *fileindex_path
= NULL
;
8493 struct got_reference
*head_ref
= NULL
;
8494 struct got_object_id
*head_commit_id
= NULL
;
8495 struct check_stage_ok_arg oka
;
8496 struct stage_path_arg spa
;
8498 err
= lock_worktree(worktree
, LOCK_EX
);
8502 err
= got_ref_open(&head_ref
, repo
,
8503 got_worktree_get_head_ref_name(worktree
), 0);
8506 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
8509 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8513 /* Check pre-conditions before staging anything. */
8514 oka
.head_commit_id
= head_commit_id
;
8515 oka
.worktree
= worktree
;
8516 oka
.fileindex
= fileindex
;
8518 oka
.have_changes
= 0;
8519 TAILQ_FOREACH(pe
, paths
, entry
) {
8520 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8521 check_stage_ok
, &oka
, NULL
, NULL
, 1, 0);
8525 if (!oka
.have_changes
) {
8526 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
8530 spa
.worktree
= worktree
;
8531 spa
.fileindex
= fileindex
;
8533 spa
.patch_cb
= patch_cb
;
8534 spa
.patch_arg
= patch_arg
;
8535 spa
.status_cb
= status_cb
;
8536 spa
.status_arg
= status_arg
;
8537 spa
.staged_something
= 0;
8538 spa
.allow_bad_symlinks
= allow_bad_symlinks
;
8539 TAILQ_FOREACH(pe
, paths
, entry
) {
8540 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8541 stage_path
, &spa
, NULL
, NULL
, 1, 0);
8545 if (!spa
.staged_something
) {
8546 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
8550 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8551 if (sync_err
&& err
== NULL
)
8555 got_ref_close(head_ref
);
8556 free(head_commit_id
);
8557 free(fileindex_path
);
8559 got_fileindex_free(fileindex
);
8560 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8561 if (unlockerr
&& err
== NULL
)
8566 struct unstage_path_arg
{
8567 struct got_worktree
*worktree
;
8568 struct got_fileindex
*fileindex
;
8569 struct got_repository
*repo
;
8570 got_worktree_checkout_cb progress_cb
;
8572 got_worktree_patch_cb patch_cb
;
8576 static const struct got_error
*
8577 create_unstaged_content(char **path_unstaged_content
,
8578 char **path_new_staged_content
, struct got_object_id
*blob_id
,
8579 struct got_object_id
*staged_blob_id
, const char *relpath
,
8580 struct got_repository
*repo
,
8581 got_worktree_patch_cb patch_cb
, void *patch_arg
)
8583 const struct got_error
*err
, *free_err
;
8584 struct got_blob_object
*blob
= NULL
, *staged_blob
= NULL
;
8585 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
, *rejectfile
= NULL
;
8586 char *path1
= NULL
, *path2
= NULL
, *label1
= NULL
;
8587 struct got_diffreg_result
*diffreg_result
= NULL
;
8588 int line_cur1
= 1, line_cur2
= 1, n
= 0, nchunks_used
= 0;
8589 int have_content
= 0, have_rejected_content
= 0, i
= 0, nchanges
= 0;
8590 int fd1
= -1, fd2
= -1;
8592 *path_unstaged_content
= NULL
;
8593 *path_new_staged_content
= NULL
;
8595 err
= got_object_id_str(&label1
, blob_id
);
8599 fd1
= got_opentempfd();
8601 err
= got_error_from_errno("got_opentempfd");
8604 fd2
= got_opentempfd();
8606 err
= got_error_from_errno("got_opentempfd");
8610 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192, fd1
);
8614 err
= got_opentemp_named(&path1
, &f1
, "got-unstage-blob-base", "");
8618 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
8622 err
= got_object_open_as_blob(&staged_blob
, repo
, staged_blob_id
, 8192,
8627 err
= got_opentemp_named(&path2
, &f2
, "got-unstage-blob-staged", "");
8631 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f2
, staged_blob
);
8635 err
= got_diff_files(&diffreg_result
, f1
, 1, label1
, f2
, 1,
8636 path2
, 3, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
8640 err
= got_opentemp_named(path_unstaged_content
, &outfile
,
8641 "got-unstaged-content", "");
8644 err
= got_opentemp_named(path_new_staged_content
, &rejectfile
,
8645 "got-new-staged-content", "");
8649 if (fseek(f1
, 0L, SEEK_SET
) == -1) {
8650 err
= got_ferror(f1
, GOT_ERR_IO
);
8653 if (fseek(f2
, 0L, SEEK_SET
) == -1) {
8654 err
= got_ferror(f2
, GOT_ERR_IO
);
8657 /* Count the number of actual changes in the diff result. */
8658 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
8659 struct diff_chunk_context cc
= {};
8660 diff_chunk_context_load_change(&cc
, &nchunks_used
,
8661 diffreg_result
->result
, n
, 0);
8664 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
8666 err
= apply_or_reject_change(&choice
, &nchunks_used
,
8667 diffreg_result
->result
, n
, relpath
, f1
, f2
,
8668 &line_cur1
, &line_cur2
,
8669 outfile
, rejectfile
, ++i
, nchanges
, patch_cb
, patch_arg
);
8672 if (choice
== GOT_PATCH_CHOICE_YES
)
8675 have_rejected_content
= 1;
8676 if (choice
== GOT_PATCH_CHOICE_QUIT
)
8679 if (have_content
|| have_rejected_content
)
8680 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
8681 outfile
, rejectfile
);
8684 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
8685 err
= got_error_from_errno("close");
8687 got_object_blob_close(blob
);
8688 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
8689 err
= got_error_from_errno("close");
8691 got_object_blob_close(staged_blob
);
8692 free_err
= got_diffreg_result_free(diffreg_result
);
8693 if (free_err
&& err
== NULL
)
8695 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
8696 err
= got_error_from_errno2("fclose", path1
);
8697 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
8698 err
= got_error_from_errno2("fclose", path2
);
8699 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
8700 err
= got_error_from_errno2("fclose", *path_unstaged_content
);
8701 if (rejectfile
&& fclose(rejectfile
) == EOF
&& err
== NULL
)
8702 err
= got_error_from_errno2("fclose", *path_new_staged_content
);
8703 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
8704 err
= got_error_from_errno2("unlink", path1
);
8705 if (path2
&& unlink(path2
) == -1 && err
== NULL
)
8706 err
= got_error_from_errno2("unlink", path2
);
8707 if (err
|| !have_content
) {
8708 if (*path_unstaged_content
&&
8709 unlink(*path_unstaged_content
) == -1 && err
== NULL
)
8710 err
= got_error_from_errno2("unlink",
8711 *path_unstaged_content
);
8712 free(*path_unstaged_content
);
8713 *path_unstaged_content
= NULL
;
8715 if (err
|| !have_content
|| !have_rejected_content
) {
8716 if (*path_new_staged_content
&&
8717 unlink(*path_new_staged_content
) == -1 && err
== NULL
)
8718 err
= got_error_from_errno2("unlink",
8719 *path_new_staged_content
);
8720 free(*path_new_staged_content
);
8721 *path_new_staged_content
= NULL
;
8728 static const struct got_error
*
8729 unstage_hunks(struct got_object_id
*staged_blob_id
,
8730 struct got_blob_object
*blob_base
,
8731 struct got_object_id
*blob_id
, struct got_fileindex_entry
*ie
,
8732 const char *ondisk_path
, const char *label_orig
,
8733 struct got_worktree
*worktree
, struct got_repository
*repo
,
8734 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8735 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
8737 const struct got_error
*err
= NULL
;
8738 char *path_unstaged_content
= NULL
;
8739 char *path_new_staged_content
= NULL
;
8740 char *parent
= NULL
, *base_path
= NULL
;
8741 char *blob_base_path
= NULL
;
8742 struct got_object_id
*new_staged_blob_id
= NULL
;
8743 FILE *f
= NULL
, *f_base
= NULL
, *f_deriv2
= NULL
;
8746 err
= create_unstaged_content(&path_unstaged_content
,
8747 &path_new_staged_content
, blob_id
, staged_blob_id
,
8748 ie
->path
, repo
, patch_cb
, patch_arg
);
8752 if (path_unstaged_content
== NULL
)
8755 if (path_new_staged_content
) {
8756 err
= got_object_blob_create(&new_staged_blob_id
,
8757 path_new_staged_content
, repo
);
8762 f
= fopen(path_unstaged_content
, "re");
8764 err
= got_error_from_errno2("fopen",
8765 path_unstaged_content
);
8768 if (fstat(fileno(f
), &sb
) == -1) {
8769 err
= got_error_from_errno2("fstat", path_unstaged_content
);
8772 if (got_fileindex_entry_staged_filetype_get(ie
) ==
8773 GOT_FILEIDX_MODE_SYMLINK
&& sb
.st_size
< PATH_MAX
) {
8774 char link_target
[PATH_MAX
];
8776 r
= fread(link_target
, 1, sizeof(link_target
), f
);
8777 if (r
== 0 && ferror(f
)) {
8778 err
= got_error_from_errno("fread");
8781 if (r
>= sizeof(link_target
)) { /* should not happen */
8782 err
= got_error(GOT_ERR_NO_SPACE
);
8785 link_target
[r
] = '\0';
8786 err
= merge_symlink(worktree
, blob_base
,
8787 ondisk_path
, ie
->path
, label_orig
, link_target
,
8788 worktree
->base_commit_id
, repo
, progress_cb
,
8791 int local_changes_subsumed
;
8793 err
= got_path_dirname(&parent
, ondisk_path
);
8797 if (asprintf(&base_path
, "%s/got-unstage-blob-orig",
8799 err
= got_error_from_errno("asprintf");
8804 err
= got_opentemp_named(&blob_base_path
, &f_base
,
8808 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_base
,
8814 * In order the run a 3-way merge with a symlink we copy the symlink's
8815 * target path into a temporary file and use that file with diff3.
8817 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
8818 err
= dump_symlink_target_path_to_file(&f_deriv2
,
8824 fd
= open(ondisk_path
,
8825 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
8827 err
= got_error_from_errno2("open", ondisk_path
);
8830 f_deriv2
= fdopen(fd
, "r");
8831 if (f_deriv2
== NULL
) {
8832 err
= got_error_from_errno2("fdopen", ondisk_path
);
8838 err
= merge_file(&local_changes_subsumed
, worktree
,
8839 f_base
, f
, f_deriv2
, ondisk_path
, ie
->path
,
8840 got_fileindex_perms_to_st(ie
),
8841 label_orig
, "unstaged", NULL
, GOT_DIFF_ALGORITHM_MYERS
,
8842 repo
, progress_cb
, progress_arg
);
8847 if (new_staged_blob_id
) {
8848 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
8849 SHA1_DIGEST_LENGTH
);
8851 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
8852 got_fileindex_entry_staged_filetype_set(ie
, 0);
8855 free(new_staged_blob_id
);
8856 if (path_unstaged_content
&&
8857 unlink(path_unstaged_content
) == -1 && err
== NULL
)
8858 err
= got_error_from_errno2("unlink", path_unstaged_content
);
8859 if (path_new_staged_content
&&
8860 unlink(path_new_staged_content
) == -1 && err
== NULL
)
8861 err
= got_error_from_errno2("unlink", path_new_staged_content
);
8862 if (blob_base_path
&& unlink(blob_base_path
) == -1 && err
== NULL
)
8863 err
= got_error_from_errno2("unlink", blob_base_path
);
8864 if (f_base
&& fclose(f_base
) == EOF
&& err
== NULL
)
8865 err
= got_error_from_errno2("fclose", path_unstaged_content
);
8866 if (f
&& fclose(f
) == EOF
&& err
== NULL
)
8867 err
= got_error_from_errno2("fclose", path_unstaged_content
);
8868 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
8869 err
= got_error_from_errno2("fclose", ondisk_path
);
8870 free(path_unstaged_content
);
8871 free(path_new_staged_content
);
8872 free(blob_base_path
);
8878 static const struct got_error
*
8879 unstage_path(void *arg
, unsigned char status
,
8880 unsigned char staged_status
, const char *relpath
,
8881 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
8882 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
8884 const struct got_error
*err
= NULL
;
8885 struct unstage_path_arg
*a
= arg
;
8886 struct got_fileindex_entry
*ie
;
8887 struct got_blob_object
*blob_base
= NULL
, *blob_staged
= NULL
;
8888 char *ondisk_path
= NULL
;
8889 char *id_str
= NULL
, *label_orig
= NULL
;
8890 int local_changes_subsumed
;
8892 int fd1
= -1, fd2
= -1;
8894 if (staged_status
!= GOT_STATUS_ADD
&&
8895 staged_status
!= GOT_STATUS_MODIFY
&&
8896 staged_status
!= GOT_STATUS_DELETE
)
8899 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8901 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8903 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, relpath
)
8905 return got_error_from_errno("asprintf");
8907 err
= got_object_id_str(&id_str
,
8908 commit_id
? commit_id
: a
->worktree
->base_commit_id
);
8911 if (asprintf(&label_orig
, "%s: commit %s", GOT_MERGE_LABEL_BASE
,
8913 err
= got_error_from_errno("asprintf");
8917 fd1
= got_opentempfd();
8919 err
= got_error_from_errno("got_opentempfd");
8922 fd2
= got_opentempfd();
8924 err
= got_error_from_errno("got_opentempfd");
8928 switch (staged_status
) {
8929 case GOT_STATUS_MODIFY
:
8930 err
= got_object_open_as_blob(&blob_base
, a
->repo
,
8931 blob_id
, 8192, fd1
);
8935 case GOT_STATUS_ADD
:
8937 if (staged_status
== GOT_STATUS_ADD
) {
8938 int choice
= GOT_PATCH_CHOICE_NONE
;
8939 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8940 staged_status
, ie
->path
, NULL
, 1, 1);
8943 if (choice
!= GOT_PATCH_CHOICE_YES
)
8946 err
= unstage_hunks(staged_blob_id
,
8947 blob_base
, blob_id
, ie
, ondisk_path
,
8948 label_orig
, a
->worktree
, a
->repo
,
8949 a
->patch_cb
, a
->patch_arg
,
8950 a
->progress_cb
, a
->progress_arg
);
8951 break; /* Done with this file. */
8954 err
= got_object_open_as_blob(&blob_staged
, a
->repo
,
8955 staged_blob_id
, 8192, fd2
);
8958 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
8959 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
8960 case GOT_FILEIDX_MODE_REGULAR_FILE
:
8961 err
= merge_blob(&local_changes_subsumed
, a
->worktree
,
8962 blob_base
, ondisk_path
, relpath
,
8963 got_fileindex_perms_to_st(ie
), label_orig
,
8964 blob_staged
, commit_id
? commit_id
:
8965 a
->worktree
->base_commit_id
, a
->repo
,
8966 a
->progress_cb
, a
->progress_arg
);
8968 case GOT_FILEIDX_MODE_SYMLINK
:
8969 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
8970 char *staged_target
;
8971 err
= got_object_blob_read_to_str(
8972 &staged_target
, blob_staged
);
8975 err
= merge_symlink(a
->worktree
, blob_base
,
8976 ondisk_path
, relpath
, label_orig
,
8977 staged_target
, commit_id
? commit_id
:
8978 a
->worktree
->base_commit_id
,
8979 a
->repo
, a
->progress_cb
, a
->progress_arg
);
8980 free(staged_target
);
8982 err
= merge_blob(&local_changes_subsumed
,
8983 a
->worktree
, blob_base
, ondisk_path
,
8984 relpath
, got_fileindex_perms_to_st(ie
),
8985 label_orig
, blob_staged
,
8986 commit_id
? commit_id
:
8987 a
->worktree
->base_commit_id
, a
->repo
,
8988 a
->progress_cb
, a
->progress_arg
);
8992 err
= got_error_path(relpath
, GOT_ERR_BAD_FILETYPE
);
8996 got_fileindex_entry_stage_set(ie
,
8997 GOT_FILEIDX_STAGE_NONE
);
8998 got_fileindex_entry_staged_filetype_set(ie
, 0);
9001 case GOT_STATUS_DELETE
:
9003 int choice
= GOT_PATCH_CHOICE_NONE
;
9004 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
9005 staged_status
, ie
->path
, NULL
, 1, 1);
9008 if (choice
== GOT_PATCH_CHOICE_NO
)
9010 if (choice
!= GOT_PATCH_CHOICE_YES
) {
9011 err
= got_error(GOT_ERR_PATCH_CHOICE
);
9015 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
9016 got_fileindex_entry_staged_filetype_set(ie
, 0);
9017 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
9018 dirfd
, de_name
, a
->repo
);
9021 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, relpath
);
9026 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
9027 err
= got_error_from_errno("close");
9029 got_object_blob_close(blob_base
);
9030 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
9031 err
= got_error_from_errno("close");
9033 got_object_blob_close(blob_staged
);
9039 const struct got_error
*
9040 got_worktree_unstage(struct got_worktree
*worktree
,
9041 struct got_pathlist_head
*paths
,
9042 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
9043 got_worktree_patch_cb patch_cb
, void *patch_arg
,
9044 struct got_repository
*repo
)
9046 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
9047 struct got_pathlist_entry
*pe
;
9048 struct got_fileindex
*fileindex
= NULL
;
9049 char *fileindex_path
= NULL
;
9050 struct unstage_path_arg upa
;
9052 err
= lock_worktree(worktree
, LOCK_EX
);
9056 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
9060 upa
.worktree
= worktree
;
9061 upa
.fileindex
= fileindex
;
9063 upa
.progress_cb
= progress_cb
;
9064 upa
.progress_arg
= progress_arg
;
9065 upa
.patch_cb
= patch_cb
;
9066 upa
.patch_arg
= patch_arg
;
9067 TAILQ_FOREACH(pe
, paths
, entry
) {
9068 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
9069 unstage_path
, &upa
, NULL
, NULL
, 1, 0);
9074 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
9075 if (sync_err
&& err
== NULL
)
9078 free(fileindex_path
);
9080 got_fileindex_free(fileindex
);
9081 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
9082 if (unlockerr
&& err
== NULL
)
9087 struct report_file_info_arg
{
9088 struct got_worktree
*worktree
;
9089 got_worktree_path_info_cb info_cb
;
9091 struct got_pathlist_head
*paths
;
9092 got_cancel_cb cancel_cb
;
9096 static const struct got_error
*
9097 report_file_info(void *arg
, struct got_fileindex_entry
*ie
)
9099 struct report_file_info_arg
*a
= arg
;
9100 struct got_pathlist_entry
*pe
;
9101 struct got_object_id blob_id
, staged_blob_id
, commit_id
;
9102 struct got_object_id
*blob_idp
= NULL
, *staged_blob_idp
= NULL
;
9103 struct got_object_id
*commit_idp
= NULL
;
9106 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
9107 return got_error(GOT_ERR_CANCELLED
);
9109 TAILQ_FOREACH(pe
, a
->paths
, entry
) {
9110 if (pe
->path_len
== 0 || strcmp(pe
->path
, ie
->path
) == 0 ||
9111 got_path_is_child(ie
->path
, pe
->path
, pe
->path_len
))
9114 if (pe
== NULL
) /* not found */
9117 if (got_fileindex_entry_has_blob(ie
)) {
9118 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
9119 blob_idp
= &blob_id
;
9121 stage
= got_fileindex_entry_stage_get(ie
);
9122 if (stage
== GOT_FILEIDX_STAGE_MODIFY
||
9123 stage
== GOT_FILEIDX_STAGE_ADD
) {
9124 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
9125 SHA1_DIGEST_LENGTH
);
9126 staged_blob_idp
= &staged_blob_id
;
9129 if (got_fileindex_entry_has_commit(ie
)) {
9130 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
9131 commit_idp
= &commit_id
;
9134 return a
->info_cb(a
->info_arg
, ie
->path
, got_fileindex_perms_to_st(ie
),
9135 (time_t)ie
->mtime_sec
, blob_idp
, staged_blob_idp
, commit_idp
);
9138 const struct got_error
*
9139 got_worktree_path_info(struct got_worktree
*worktree
,
9140 struct got_pathlist_head
*paths
,
9141 got_worktree_path_info_cb info_cb
, void *info_arg
,
9142 got_cancel_cb cancel_cb
, void *cancel_arg
)
9145 const struct got_error
*err
= NULL
, *unlockerr
;
9146 struct got_fileindex
*fileindex
= NULL
;
9147 char *fileindex_path
= NULL
;
9148 struct report_file_info_arg arg
;
9150 err
= lock_worktree(worktree
, LOCK_SH
);
9154 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
9158 arg
.worktree
= worktree
;
9159 arg
.info_cb
= info_cb
;
9160 arg
.info_arg
= info_arg
;
9162 arg
.cancel_cb
= cancel_cb
;
9163 arg
.cancel_arg
= cancel_arg
;
9164 err
= got_fileindex_for_each_entry_safe(fileindex
, report_file_info
,
9167 free(fileindex_path
);
9169 got_fileindex_free(fileindex
);
9170 unlockerr
= lock_worktree(worktree
, LOCK_UN
);
9171 if (unlockerr
&& err
== NULL
)
9176 static const struct got_error
*
9177 patch_check_path(const char *p
, char **path
, unsigned char *status
,
9178 unsigned char *staged_status
, struct got_fileindex
*fileindex
,
9179 struct got_worktree
*worktree
, struct got_repository
*repo
)
9181 const struct got_error
*err
;
9182 struct got_fileindex_entry
*ie
;
9184 char *ondisk_path
= NULL
;
9186 err
= got_worktree_resolve_path(path
, worktree
, p
);
9190 if (asprintf(&ondisk_path
, "%s%s%s", worktree
->root_path
,
9191 *path
[0] ? "/" : "", *path
) == -1)
9192 return got_error_from_errno("asprintf");
9194 ie
= got_fileindex_entry_get(fileindex
, *path
, strlen(*path
));
9196 *staged_status
= get_staged_status(ie
);
9197 err
= get_file_status(status
, &sb
, ie
, ondisk_path
, -1, NULL
,
9202 *staged_status
= GOT_STATUS_NO_CHANGE
;
9203 *status
= GOT_STATUS_UNVERSIONED
;
9204 if (lstat(ondisk_path
, &sb
) == -1) {
9205 if (errno
!= ENOENT
) {
9206 err
= got_error_from_errno2("lstat",
9210 *status
= GOT_STATUS_NONEXISTENT
;
9219 static const struct got_error
*
9220 patch_can_rm(const char *path
, unsigned char status
,
9221 unsigned char staged_status
)
9223 if (status
== GOT_STATUS_NONEXISTENT
)
9224 return got_error_set_errno(ENOENT
, path
);
9225 if (status
!= GOT_STATUS_NO_CHANGE
&&
9226 status
!= GOT_STATUS_ADD
&&
9227 status
!= GOT_STATUS_MODIFY
&&
9228 status
!= GOT_STATUS_MODE_CHANGE
)
9229 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9230 if (staged_status
== GOT_STATUS_DELETE
)
9231 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9235 static const struct got_error
*
9236 patch_can_add(const char *path
, unsigned char status
)
9238 if (status
!= GOT_STATUS_NONEXISTENT
)
9239 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9243 static const struct got_error
*
9244 patch_can_edit(const char *path
, unsigned char status
,
9245 unsigned char staged_status
)
9247 if (status
== GOT_STATUS_NONEXISTENT
)
9248 return got_error_set_errno(ENOENT
, path
);
9249 if (status
!= GOT_STATUS_NO_CHANGE
&&
9250 status
!= GOT_STATUS_ADD
&&
9251 status
!= GOT_STATUS_MODIFY
)
9252 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9253 if (staged_status
== GOT_STATUS_DELETE
)
9254 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
9258 const struct got_error
*
9259 got_worktree_patch_prepare(struct got_fileindex
**fileindex
,
9260 char **fileindex_path
, struct got_worktree
*worktree
)
9262 return open_fileindex(fileindex
, fileindex_path
, worktree
);
9265 const struct got_error
*
9266 got_worktree_patch_check_path(const char *old
, const char *new,
9267 char **oldpath
, char **newpath
, struct got_worktree
*worktree
,
9268 struct got_repository
*repo
, struct got_fileindex
*fileindex
)
9270 const struct got_error
*err
= NULL
;
9271 int file_renamed
= 0;
9272 unsigned char status_old
, staged_status_old
;
9273 unsigned char status_new
, staged_status_new
;
9278 err
= patch_check_path(old
!= NULL
? old
: new, oldpath
,
9279 &status_old
, &staged_status_old
, fileindex
, worktree
, repo
);
9283 err
= patch_check_path(new != NULL
? new : old
, newpath
,
9284 &status_new
, &staged_status_new
, fileindex
, worktree
, repo
);
9288 if (old
!= NULL
&& new != NULL
&& strcmp(old
, new) != 0)
9291 if (old
!= NULL
&& new == NULL
)
9292 err
= patch_can_rm(*oldpath
, status_old
, staged_status_old
);
9293 else if (file_renamed
) {
9294 err
= patch_can_rm(*oldpath
, status_old
, staged_status_old
);
9296 err
= patch_can_add(*newpath
, status_new
);
9297 } else if (old
== NULL
)
9298 err
= patch_can_add(*newpath
, status_new
);
9300 err
= patch_can_edit(*newpath
, status_new
, staged_status_new
);
9312 const struct got_error
*
9313 got_worktree_patch_schedule_add(const char *path
, struct got_repository
*repo
,
9314 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
9315 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
9317 struct schedule_addition_args saa
;
9319 memset(&saa
, 0, sizeof(saa
));
9320 saa
.worktree
= worktree
;
9321 saa
.fileindex
= fileindex
;
9322 saa
.progress_cb
= progress_cb
;
9323 saa
.progress_arg
= progress_arg
;
9326 return worktree_status(worktree
, path
, fileindex
, repo
,
9327 schedule_addition
, &saa
, NULL
, NULL
, 1, 0);
9330 const struct got_error
*
9331 got_worktree_patch_schedule_rm(const char *path
, struct got_repository
*repo
,
9332 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
9333 got_worktree_delete_cb progress_cb
, void *progress_arg
)
9335 struct schedule_deletion_args sda
;
9337 memset(&sda
, 0, sizeof(sda
));
9338 sda
.worktree
= worktree
;
9339 sda
.fileindex
= fileindex
;
9340 sda
.progress_cb
= progress_cb
;
9341 sda
.progress_arg
= progress_arg
;
9343 sda
.delete_local_mods
= 0;
9344 sda
.keep_on_disk
= 0;
9345 sda
.ignore_missing_paths
= 0;
9346 sda
.status_codes
= NULL
;
9348 return worktree_status(worktree
, path
, fileindex
, repo
,
9349 schedule_for_deletion
, &sda
, NULL
, NULL
, 1, 1);
9352 const struct got_error
*
9353 got_worktree_patch_complete(struct got_fileindex
*fileindex
,
9354 const char *fileindex_path
)
9356 const struct got_error
*err
= NULL
;
9358 err
= sync_fileindex(fileindex
, fileindex_path
);
9359 got_fileindex_free(fileindex
);