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.
33 #include "got_compat.h"
35 #include "got_error.h"
36 #include "got_repository.h"
37 #include "got_reference.h"
38 #include "got_object.h"
40 #include "got_cancel.h"
41 #include "got_worktree.h"
42 #include "got_opentemp.h"
45 #include "got_lib_worktree.h"
46 #include "got_lib_sha1.h"
47 #include "got_lib_fileindex.h"
48 #include "got_lib_inflate.h"
49 #include "got_lib_delta.h"
50 #include "got_lib_object.h"
51 #include "got_lib_object_parse.h"
52 #include "got_lib_object_create.h"
53 #include "got_lib_object_idset.h"
54 #include "got_lib_diff.h"
55 #include "got_lib_gotconfig.h"
58 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
61 #define GOT_MERGE_LABEL_MERGED "merged change"
62 #define GOT_MERGE_LABEL_BASE "3-way merge base"
64 static const struct got_error
*
65 create_meta_file(const char *path_got
, const char *name
, const char *content
)
67 const struct got_error
*err
= NULL
;
70 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1)
71 return got_error_from_errno("asprintf");
73 err
= got_path_create_file(path
, content
);
78 static const struct got_error
*
79 update_meta_file(const char *path_got
, const char *name
, const char *content
)
81 const struct got_error
*err
= NULL
;
86 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1) {
87 err
= got_error_from_errno("asprintf");
92 err
= got_opentemp_named(&tmppath
, &tmpfile
, path
);
97 int len
= fprintf(tmpfile
, "%s\n", content
);
98 if (len
!= strlen(content
) + 1) {
99 err
= got_error_from_errno2("fprintf", tmppath
);
104 if (rename(tmppath
, path
) != 0) {
105 err
= got_error_from_errno3("rename", tmppath
, path
);
111 if (fclose(tmpfile
) == EOF
&& err
== NULL
)
112 err
= got_error_from_errno2("fclose", tmppath
);
117 static const struct got_error
*
118 write_head_ref(const char *path_got
, struct got_reference
*head_ref
)
120 const struct got_error
*err
= NULL
;
123 if (got_ref_is_symbolic(head_ref
)) {
124 refstr
= got_ref_to_str(head_ref
);
126 return got_error_from_errno("got_ref_to_str");
128 refstr
= strdup(got_ref_get_name(head_ref
));
130 return got_error_from_errno("strdup");
132 err
= update_meta_file(path_got
, GOT_WORKTREE_HEAD_REF
, refstr
);
137 const struct got_error
*
138 got_worktree_init(const char *path
, struct got_reference
*head_ref
,
139 const char *prefix
, struct got_repository
*repo
)
141 const struct got_error
*err
= NULL
;
142 struct got_object_id
*commit_id
= NULL
;
144 uint32_t uuid_status
;
146 char *path_got
= NULL
;
147 char *formatstr
= NULL
;
148 char *absprefix
= NULL
;
149 char *basestr
= NULL
;
150 char *uuidstr
= NULL
;
152 if (strcmp(path
, got_repo_get_path(repo
)) == 0) {
153 err
= got_error(GOT_ERR_WORKTREE_REPO
);
157 err
= got_ref_resolve(&commit_id
, repo
, head_ref
);
160 err
= got_object_get_type(&obj_type
, repo
, commit_id
);
163 if (obj_type
!= GOT_OBJ_TYPE_COMMIT
)
164 return got_error(GOT_ERR_OBJ_TYPE
);
166 if (!got_path_is_absolute(prefix
)) {
167 if (asprintf(&absprefix
, "/%s", prefix
) == -1)
168 return got_error_from_errno("asprintf");
171 /* Create top-level directory (may already exist). */
172 if (mkdir(path
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
173 err
= got_error_from_errno2("mkdir", path
);
177 /* Create .got directory (may already exist). */
178 if (asprintf(&path_got
, "%s/%s", path
, GOT_WORKTREE_GOT_DIR
) == -1) {
179 err
= got_error_from_errno("asprintf");
182 if (mkdir(path_got
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
183 err
= got_error_from_errno2("mkdir", path_got
);
187 /* Create an empty lock file. */
188 err
= create_meta_file(path_got
, GOT_WORKTREE_LOCK
, NULL
);
192 /* Create an empty file index. */
193 err
= create_meta_file(path_got
, GOT_WORKTREE_FILE_INDEX
, NULL
);
197 /* Write the HEAD reference. */
198 err
= write_head_ref(path_got
, head_ref
);
202 /* Record our base commit. */
203 err
= got_object_id_str(&basestr
, commit_id
);
206 err
= create_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, basestr
);
210 /* Store path to repository. */
211 err
= create_meta_file(path_got
, GOT_WORKTREE_REPOSITORY
,
212 got_repo_get_path(repo
));
216 /* Store in-repository path prefix. */
217 err
= create_meta_file(path_got
, GOT_WORKTREE_PATH_PREFIX
,
218 absprefix
? absprefix
: prefix
);
223 uuid_create(&uuid
, &uuid_status
);
224 if (uuid_status
!= uuid_s_ok
) {
225 err
= got_error_uuid(uuid_status
, "uuid_create");
228 uuid_to_string(&uuid
, &uuidstr
, &uuid_status
);
229 if (uuid_status
!= uuid_s_ok
) {
230 err
= got_error_uuid(uuid_status
, "uuid_to_string");
233 err
= create_meta_file(path_got
, GOT_WORKTREE_UUID
, uuidstr
);
237 /* Stamp work tree with format file. */
238 if (asprintf(&formatstr
, "%d", GOT_WORKTREE_FORMAT_VERSION
) == -1) {
239 err
= got_error_from_errno("asprintf");
242 err
= create_meta_file(path_got
, GOT_WORKTREE_FORMAT
, formatstr
);
256 const struct got_error
*
257 got_worktree_match_path_prefix(int *match
, struct got_worktree
*worktree
,
258 const char *path_prefix
)
260 char *absprefix
= NULL
;
262 if (!got_path_is_absolute(path_prefix
)) {
263 if (asprintf(&absprefix
, "/%s", path_prefix
) == -1)
264 return got_error_from_errno("asprintf");
266 *match
= (strcmp(absprefix
? absprefix
: path_prefix
,
267 worktree
->path_prefix
) == 0);
273 got_worktree_get_head_ref_name(struct got_worktree
*worktree
)
275 return worktree
->head_ref_name
;
278 const struct got_error
*
279 got_worktree_set_head_ref(struct got_worktree
*worktree
,
280 struct got_reference
*head_ref
)
282 const struct got_error
*err
= NULL
;
283 char *path_got
= NULL
, *head_ref_name
= NULL
;
285 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
286 GOT_WORKTREE_GOT_DIR
) == -1) {
287 err
= got_error_from_errno("asprintf");
292 head_ref_name
= strdup(got_ref_get_name(head_ref
));
293 if (head_ref_name
== NULL
) {
294 err
= got_error_from_errno("strdup");
298 err
= write_head_ref(path_got
, head_ref
);
302 free(worktree
->head_ref_name
);
303 worktree
->head_ref_name
= head_ref_name
;
311 struct got_object_id
*
312 got_worktree_get_base_commit_id(struct got_worktree
*worktree
)
314 return worktree
->base_commit_id
;
317 const struct got_error
*
318 got_worktree_set_base_commit_id(struct got_worktree
*worktree
,
319 struct got_repository
*repo
, struct got_object_id
*commit_id
)
321 const struct got_error
*err
;
322 struct got_object
*obj
= NULL
;
324 char *path_got
= NULL
;
326 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
327 GOT_WORKTREE_GOT_DIR
) == -1) {
328 err
= got_error_from_errno("asprintf");
333 err
= got_object_open(&obj
, repo
, commit_id
);
337 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
338 err
= got_error(GOT_ERR_OBJ_TYPE
);
342 /* Record our base commit. */
343 err
= got_object_id_str(&id_str
, commit_id
);
346 err
= update_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, id_str
);
350 free(worktree
->base_commit_id
);
351 worktree
->base_commit_id
= got_object_id_dup(commit_id
);
352 if (worktree
->base_commit_id
== NULL
) {
353 err
= got_error_from_errno("got_object_id_dup");
358 got_object_close(obj
);
364 const struct got_gotconfig
*
365 got_worktree_get_gotconfig(struct got_worktree
*worktree
)
367 return worktree
->gotconfig
;
370 static const struct got_error
*
371 lock_worktree(struct got_worktree
*worktree
, int operation
)
373 if (flock(worktree
->lockfd
, operation
| LOCK_NB
) == -1)
374 return (errno
== EWOULDBLOCK
? got_error(GOT_ERR_WORKTREE_BUSY
)
375 : got_error_from_errno2("flock",
376 got_worktree_get_root_path(worktree
)));
380 static const struct got_error
*
381 add_dir_on_disk(struct got_worktree
*worktree
, const char *path
)
383 const struct got_error
*err
= NULL
;
386 if (asprintf(&abspath
, "%s/%s", worktree
->root_path
, path
) == -1)
387 return got_error_from_errno("asprintf");
389 err
= got_path_mkdir(abspath
);
390 if (err
&& err
->code
== GOT_ERR_ERRNO
&& errno
== EEXIST
) {
393 if (lstat(abspath
, &sb
) == -1) {
394 err
= got_error_from_errno2("lstat", abspath
);
395 } else if (!S_ISDIR(sb
.st_mode
)) {
396 /* TODO directory is obstructed; do something */
397 err
= got_error_path(abspath
, GOT_ERR_FILE_OBSTRUCTED
);
404 static const struct got_error
*
405 check_file_contents_equal(int *same
, FILE *f1
, FILE *f2
)
407 const struct got_error
*err
= NULL
;
410 size_t flen1
= 0, flen2
= 0;
415 flen1
= fread(fbuf1
, 1, sizeof(fbuf1
), f1
);
416 if (flen1
== 0 && ferror(f1
)) {
417 err
= got_error_from_errno("fread");
420 flen2
= fread(fbuf2
, 1, sizeof(fbuf2
), f2
);
421 if (flen2
== 0 && ferror(f2
)) {
422 err
= got_error_from_errno("fread");
429 } else if (flen2
== 0) {
433 } else if (flen1
== flen2
) {
434 if (memcmp(fbuf1
, fbuf2
, flen2
) != 0) {
447 static const struct got_error
*
448 check_files_equal(int *same
, FILE *f1
, FILE *f2
)
455 if (fstat(fileno(f1
), &sb
) != 0)
456 return got_error_from_errno("fstat");
459 if (fstat(fileno(f2
), &sb
) != 0)
460 return got_error_from_errno("fstat");
463 if (size1
!= size2
) {
468 if (fseek(f1
, 0L, SEEK_SET
) == -1)
469 return got_ferror(f1
, GOT_ERR_IO
);
470 if (fseek(f2
, 0L, SEEK_SET
) == -1)
471 return got_ferror(f2
, GOT_ERR_IO
);
473 return check_file_contents_equal(same
, f1
, f2
);
476 static const struct got_error
*
477 copy_file_to_fd(off_t
*outsize
, FILE *f
, int outfd
)
485 if (fseek(f
, 0L, SEEK_SET
) == -1)
486 return got_ferror(f
, GOT_ERR_IO
);
489 flen
= fread(fbuf
, 1, sizeof(fbuf
), f
);
492 return got_error_from_errno("fread");
496 outlen
= write(outfd
, fbuf
, flen
);
498 return got_error_from_errno("write");
500 return got_error(GOT_ERR_IO
);
507 static const struct got_error
*
508 merge_binary_file(int *overlapcnt
, int merged_fd
,
509 FILE *f_deriv
, FILE *f_orig
, FILE *f_deriv2
,
510 const char *label_deriv
, const char *label_orig
, const char *label_deriv2
,
511 const char *ondisk_path
)
513 const struct got_error
*err
= NULL
;
514 int same_content
, changed_deriv
, changed_deriv2
;
515 int fd_orig
= -1, fd_deriv
= -1, fd_deriv2
= -1;
516 off_t size_orig
= 0, size_deriv
= 0, size_deriv2
= 0;
517 char *path_orig
= NULL
, *path_deriv
= NULL
, *path_deriv2
= NULL
;
518 char *base_path_orig
= NULL
, *base_path_deriv
= NULL
;
519 char *base_path_deriv2
= NULL
;
523 err
= check_files_equal(&same_content
, f_deriv
, f_deriv2
);
528 return copy_file_to_fd(&size_deriv
, f_deriv
, merged_fd
);
530 err
= check_files_equal(&same_content
, f_deriv
, f_orig
);
533 changed_deriv
= !same_content
;
534 err
= check_files_equal(&same_content
, f_deriv2
, f_orig
);
537 changed_deriv2
= !same_content
;
539 if (changed_deriv
&& changed_deriv2
) {
541 if (asprintf(&base_path_orig
, "%s-orig", ondisk_path
) == -1) {
542 err
= got_error_from_errno("asprintf");
545 if (asprintf(&base_path_deriv
, "%s-1", ondisk_path
) == -1) {
546 err
= got_error_from_errno("asprintf");
549 if (asprintf(&base_path_deriv2
, "%s-2", ondisk_path
) == -1) {
550 err
= got_error_from_errno("asprintf");
553 err
= got_opentemp_named_fd(&path_orig
, &fd_orig
,
557 err
= got_opentemp_named_fd(&path_deriv
, &fd_deriv
,
561 err
= got_opentemp_named_fd(&path_deriv2
, &fd_deriv2
,
565 err
= copy_file_to_fd(&size_orig
, f_orig
, fd_orig
);
568 err
= copy_file_to_fd(&size_deriv
, f_deriv
, fd_deriv
);
571 err
= copy_file_to_fd(&size_deriv2
, f_deriv2
, fd_deriv2
);
574 if (dprintf(merged_fd
, "Binary files differ and cannot be "
575 "merged automatically:\n") < 0) {
576 err
= got_error_from_errno("dprintf");
579 if (dprintf(merged_fd
, "%s%s%s\nfile %s\n",
580 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
581 label_deriv
? " " : "",
582 label_deriv
? label_deriv
: "",
584 err
= got_error_from_errno("dprintf");
588 if (dprintf(merged_fd
, "%s%s%s\nfile %s\n",
589 GOT_DIFF_CONFLICT_MARKER_ORIG
,
590 label_orig
? " " : "",
591 label_orig
? label_orig
: "",
593 err
= got_error_from_errno("dprintf");
597 if (dprintf(merged_fd
, "%s\nfile %s\n%s%s%s\n",
598 GOT_DIFF_CONFLICT_MARKER_SEP
,
600 GOT_DIFF_CONFLICT_MARKER_END
,
601 label_deriv2
? " " : "",
602 label_deriv2
? label_deriv2
: "") < 0) {
603 err
= got_error_from_errno("dprintf");
606 } else if (changed_deriv
)
607 err
= copy_file_to_fd(&size_deriv
, f_deriv
, merged_fd
);
608 else if (changed_deriv2
)
609 err
= copy_file_to_fd(&size_deriv2
, f_deriv2
, merged_fd
);
611 if (size_orig
== 0 && path_orig
&& unlink(path_orig
) == -1 &&
613 err
= got_error_from_errno2("unlink", path_orig
);
614 if (fd_orig
!= -1 && close(fd_orig
) == -1 && err
== NULL
)
615 err
= got_error_from_errno2("close", path_orig
);
616 if (fd_deriv
!= -1 && close(fd_deriv
) == -1 && err
== NULL
)
617 err
= got_error_from_errno2("close", path_deriv
);
618 if (fd_deriv2
!= -1 && close(fd_deriv2
) == -1 && err
== NULL
)
619 err
= got_error_from_errno2("close", path_deriv2
);
623 free(base_path_orig
);
624 free(base_path_deriv
);
625 free(base_path_deriv2
);
630 * Perform a 3-way merge where the file f_orig acts as the common
631 * ancestor, the file f_deriv acts as the first derived version,
632 * and the file f_deriv2 acts as the second derived version.
633 * The merge result will be written to a new file at ondisk_path; any
634 * existing file at this path will be replaced.
636 static const struct got_error
*
637 merge_file(int *local_changes_subsumed
, struct got_worktree
*worktree
,
638 FILE *f_orig
, FILE *f_deriv
, FILE *f_deriv2
, const char *ondisk_path
,
639 const char *path
, uint16_t st_mode
,
640 const char *label_orig
, const char *label_deriv
, const char *label_deriv2
,
641 enum got_diff_algorithm diff_algo
, struct got_repository
*repo
,
642 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
644 const struct got_error
*err
= NULL
;
646 FILE *f_merged
= NULL
;
647 char *merged_path
= NULL
, *base_path
= NULL
;
651 *local_changes_subsumed
= 0;
653 err
= got_path_dirname(&parent
, ondisk_path
);
657 if (asprintf(&base_path
, "%s/got-merged", parent
) == -1) {
658 err
= got_error_from_errno("asprintf");
662 err
= got_opentemp_named_fd(&merged_path
, &merged_fd
, base_path
);
666 err
= got_merge_diff3(&overlapcnt
, merged_fd
, f_deriv
, f_orig
,
667 f_deriv2
, label_deriv
, label_orig
, label_deriv2
, diff_algo
);
669 if (err
->code
!= GOT_ERR_FILE_BINARY
)
671 err
= merge_binary_file(&overlapcnt
, merged_fd
, f_deriv
,
672 f_orig
, f_deriv2
, label_deriv
, label_orig
, label_deriv2
,
678 err
= (*progress_cb
)(progress_arg
,
679 overlapcnt
> 0 ? GOT_STATUS_CONFLICT
: GOT_STATUS_MERGE
, path
);
683 if (fsync(merged_fd
) != 0) {
684 err
= got_error_from_errno("fsync");
688 f_merged
= fdopen(merged_fd
, "r");
689 if (f_merged
== NULL
) {
690 err
= got_error_from_errno("fdopen");
695 /* Check if a clean merge has subsumed all local changes. */
696 if (overlapcnt
== 0) {
697 err
= check_files_equal(local_changes_subsumed
, f_deriv
,
703 if (fchmod(fileno(f_merged
), st_mode
) != 0) {
704 err
= got_error_from_errno2("fchmod", merged_path
);
708 if (rename(merged_path
, ondisk_path
) != 0) {
709 err
= got_error_from_errno3("rename", merged_path
,
718 if (merged_fd
!= -1 && close(merged_fd
) == -1 && err
== NULL
)
719 err
= got_error_from_errno("close");
720 if (f_merged
&& fclose(f_merged
) == EOF
&& err
== NULL
)
721 err
= got_error_from_errno("fclose");
728 static const struct got_error
*
729 update_symlink(const char *ondisk_path
, const char *target_path
,
732 /* This is not atomic but matches what 'ln -sf' does. */
733 if (unlink(ondisk_path
) == -1)
734 return got_error_from_errno2("unlink", ondisk_path
);
735 if (symlink(target_path
, ondisk_path
) == -1)
736 return got_error_from_errno3("symlink", target_path
,
742 * Overwrite a symlink (or a regular file in case there was a "bad" symlink)
743 * in the work tree with a file that contains conflict markers and the
744 * conflicting target paths of the original version, a "derived version"
745 * of a symlink from an incoming change, and a local version of the symlink.
747 * The original versions's target path can be NULL if it is not available,
748 * such as if both derived versions added a new symlink at the same path.
750 * The incoming derived symlink target is NULL in case the incoming change
751 * has deleted this symlink.
753 static const struct got_error
*
754 install_symlink_conflict(const char *deriv_target
,
755 struct got_object_id
*deriv_base_commit_id
, const char *orig_target
,
756 const char *label_orig
, const char *local_target
, const char *ondisk_path
)
758 const struct got_error
*err
;
759 char *id_str
= NULL
, *label_deriv
= NULL
, *path
= NULL
;
762 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
764 return got_error_from_errno("asprintf");
766 if (asprintf(&label_deriv
, "%s: commit %s",
767 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
768 err
= got_error_from_errno("asprintf");
772 err
= got_opentemp_named(&path
, &f
, "got-symlink-conflict");
776 if (fchmod(fileno(f
), GOT_DEFAULT_FILE_MODE
) == -1) {
777 err
= got_error_from_errno2("fchmod", path
);
781 if (fprintf(f
, "%s %s\n%s\n%s%s%s%s%s\n%s\n%s\n",
782 GOT_DIFF_CONFLICT_MARKER_BEGIN
, label_deriv
,
783 deriv_target
? deriv_target
: "(symlink was deleted)",
784 orig_target
? label_orig
: "",
785 orig_target
? "\n" : "",
786 orig_target
? orig_target
: "",
787 orig_target
? "\n" : "",
788 GOT_DIFF_CONFLICT_MARKER_SEP
,
789 local_target
, GOT_DIFF_CONFLICT_MARKER_END
) < 0) {
790 err
= got_error_from_errno2("fprintf", path
);
794 if (unlink(ondisk_path
) == -1) {
795 err
= got_error_from_errno2("unlink", ondisk_path
);
798 if (rename(path
, ondisk_path
) == -1) {
799 err
= got_error_from_errno3("rename", path
, ondisk_path
);
803 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
804 err
= got_error_from_errno2("fclose", path
);
811 /* forward declaration */
812 static const struct got_error
*
813 merge_blob(int *, struct got_worktree
*, struct got_blob_object
*,
814 const char *, const char *, uint16_t, const char *,
815 struct got_blob_object
*, struct got_object_id
*,
816 struct got_repository
*, got_worktree_checkout_cb
, void *);
819 * Merge a symlink into the work tree, where blob_orig acts as the common
820 * ancestor, deriv_target is the link target of the first derived version,
821 * and the symlink on disk acts as the second derived version.
822 * Assume that contents of both blobs represent symlinks.
824 static const struct got_error
*
825 merge_symlink(struct got_worktree
*worktree
,
826 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
827 const char *path
, const char *label_orig
, const char *deriv_target
,
828 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
829 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
831 const struct got_error
*err
= NULL
;
832 char *ancestor_target
= NULL
;
834 ssize_t ondisk_len
, deriv_len
;
835 char ondisk_target
[PATH_MAX
];
836 int have_local_change
= 0;
837 int have_incoming_change
= 0;
839 if (lstat(ondisk_path
, &sb
) == -1)
840 return got_error_from_errno2("lstat", ondisk_path
);
842 ondisk_len
= readlink(ondisk_path
, ondisk_target
,
843 sizeof(ondisk_target
));
844 if (ondisk_len
== -1) {
845 err
= got_error_from_errno2("readlink",
849 ondisk_target
[ondisk_len
] = '\0';
852 err
= got_object_blob_read_to_str(&ancestor_target
, blob_orig
);
857 if (ancestor_target
== NULL
||
858 (ondisk_len
!= strlen(ancestor_target
) ||
859 memcmp(ondisk_target
, ancestor_target
, ondisk_len
) != 0))
860 have_local_change
= 1;
862 deriv_len
= strlen(deriv_target
);
863 if (ancestor_target
== NULL
||
864 (deriv_len
!= strlen(ancestor_target
) ||
865 memcmp(deriv_target
, ancestor_target
, deriv_len
) != 0))
866 have_incoming_change
= 1;
868 if (!have_local_change
&& !have_incoming_change
) {
869 if (ancestor_target
) {
870 /* Both sides made the same change. */
871 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
873 } else if (deriv_len
== ondisk_len
&&
874 memcmp(ondisk_target
, deriv_target
, deriv_len
) == 0) {
875 /* Both sides added the same symlink. */
876 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
879 /* Both sides added symlinks which don't match. */
880 err
= install_symlink_conflict(deriv_target
,
881 deriv_base_commit_id
, ancestor_target
,
882 label_orig
, ondisk_target
, ondisk_path
);
885 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
888 } else if (!have_local_change
&& have_incoming_change
) {
889 /* Apply the incoming change. */
890 err
= update_symlink(ondisk_path
, deriv_target
,
891 strlen(deriv_target
));
894 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
895 } else if (have_local_change
&& have_incoming_change
) {
896 if (deriv_len
== ondisk_len
&&
897 memcmp(deriv_target
, ondisk_target
, deriv_len
) == 0) {
898 /* Both sides made the same change. */
899 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
902 err
= install_symlink_conflict(deriv_target
,
903 deriv_base_commit_id
, ancestor_target
, label_orig
,
904 ondisk_target
, ondisk_path
);
907 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
913 free(ancestor_target
);
917 static const struct got_error
*
918 dump_symlink_target_path_to_file(FILE **outfile
, const char *ondisk_path
)
920 const struct got_error
*err
= NULL
;
921 char target_path
[PATH_MAX
];
930 return got_error_from_errno("got_opentemp");
931 target_len
= readlink(ondisk_path
, target_path
, sizeof(target_path
));
932 if (target_len
== -1) {
933 err
= got_error_from_errno2("readlink", ondisk_path
);
936 n
= fwrite(target_path
, 1, target_len
, f
);
937 if (n
!= target_len
) {
938 err
= got_ferror(f
, GOT_ERR_IO
);
941 if (fflush(f
) == EOF
) {
942 err
= got_error_from_errno("fflush");
945 if (fseek(f
, 0L, SEEK_SET
) == -1) {
946 err
= got_ferror(f
, GOT_ERR_IO
);
958 * Perform a 3-way merge where blob_orig acts as the common ancestor,
959 * blob_deriv acts as the first derived version, and the file on disk
960 * acts as the second derived version.
962 static const struct got_error
*
963 merge_blob(int *local_changes_subsumed
, struct got_worktree
*worktree
,
964 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
965 const char *path
, uint16_t st_mode
, const char *label_orig
,
966 struct got_blob_object
*blob_deriv
,
967 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
968 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
970 const struct got_error
*err
= NULL
;
971 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
972 char *blob_orig_path
= NULL
;
973 char *blob_deriv_path
= NULL
, *base_path
= NULL
, *id_str
= NULL
;
974 char *label_deriv
= NULL
, *parent
= NULL
;
976 *local_changes_subsumed
= 0;
978 err
= got_path_dirname(&parent
, ondisk_path
);
983 if (asprintf(&base_path
, "%s/got-merge-blob-orig",
985 err
= got_error_from_errno("asprintf");
990 err
= got_opentemp_named(&blob_orig_path
, &f_orig
, base_path
);
993 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_orig
,
1000 * No common ancestor exists. This is an "add vs add" conflict
1001 * and we simply use an empty ancestor file to make both files
1002 * appear in the merged result in their entirety.
1004 f_orig
= got_opentemp();
1005 if (f_orig
== NULL
) {
1006 err
= got_error_from_errno("got_opentemp");
1011 if (asprintf(&base_path
, "%s/got-merge-blob-deriv", parent
) == -1) {
1012 err
= got_error_from_errno("asprintf");
1017 err
= got_opentemp_named(&blob_deriv_path
, &f_deriv
, base_path
);
1020 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_deriv
,
1025 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
1028 if (asprintf(&label_deriv
, "%s: commit %s",
1029 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
1030 err
= got_error_from_errno("asprintf");
1035 * In order the run a 3-way merge with a symlink we copy the symlink's
1036 * target path into a temporary file and use that file with diff3.
1038 if (S_ISLNK(st_mode
)) {
1039 err
= dump_symlink_target_path_to_file(&f_deriv2
, ondisk_path
);
1044 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1046 err
= got_error_from_errno2("open", ondisk_path
);
1049 f_deriv2
= fdopen(fd
, "r");
1050 if (f_deriv2
== NULL
) {
1051 err
= got_error_from_errno2("fdopen", ondisk_path
);
1057 err
= merge_file(local_changes_subsumed
, worktree
, f_orig
, f_deriv
,
1058 f_deriv2
, ondisk_path
, path
, st_mode
, label_orig
, label_deriv
,
1059 NULL
, GOT_DIFF_ALGORITHM_MYERS
, repo
, progress_cb
, progress_arg
);
1061 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
1062 err
= got_error_from_errno("fclose");
1063 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
1064 err
= got_error_from_errno("fclose");
1065 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
1066 err
= got_error_from_errno("fclose");
1068 if (blob_orig_path
) {
1069 unlink(blob_orig_path
);
1070 free(blob_orig_path
);
1072 if (blob_deriv_path
) {
1073 unlink(blob_deriv_path
);
1074 free(blob_deriv_path
);
1082 static const struct got_error
*
1083 create_fileindex_entry(struct got_fileindex_entry
**new_iep
,
1084 struct got_fileindex
*fileindex
, struct got_object_id
*base_commit_id
,
1085 int wt_fd
, const char *path
, struct got_object_id
*blob_id
)
1087 const struct got_error
*err
= NULL
;
1088 struct got_fileindex_entry
*new_ie
;
1092 err
= got_fileindex_entry_alloc(&new_ie
, path
);
1096 err
= got_fileindex_entry_update(new_ie
, wt_fd
, path
,
1097 blob_id
->sha1
, base_commit_id
->sha1
, 1);
1101 err
= got_fileindex_entry_add(fileindex
, new_ie
);
1104 got_fileindex_entry_free(new_ie
);
1111 get_ondisk_perms(int executable
, mode_t st_mode
)
1113 mode_t xbits
= S_IXUSR
;
1116 /* Map read bits to execute bits. */
1117 if (st_mode
& S_IRGRP
)
1119 if (st_mode
& S_IROTH
)
1121 return st_mode
| xbits
;
1124 return (st_mode
& ~(S_IXUSR
| S_IXGRP
| S_IXOTH
));
1127 /* forward declaration */
1128 static const struct got_error
*
1129 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1130 const char *path
, mode_t te_mode
, mode_t st_mode
,
1131 struct got_blob_object
*blob
, int restoring_missing_file
,
1132 int reverting_versioned_file
, int installing_bad_symlink
,
1133 int path_is_unversioned
, struct got_repository
*repo
,
1134 got_worktree_checkout_cb progress_cb
, void *progress_arg
);
1137 * This function assumes that the provided symlink target points at a
1138 * safe location in the work tree!
1140 static const struct got_error
*
1141 replace_existing_symlink(int *did_something
, const char *ondisk_path
,
1142 const char *target_path
, size_t target_len
)
1144 const struct got_error
*err
= NULL
;
1146 char etarget
[PATH_MAX
];
1152 * "Bad" symlinks (those pointing outside the work tree or into the
1153 * .got directory) are installed in the work tree as a regular file
1154 * which contains the bad symlink target path.
1155 * The new symlink target has already been checked for safety by our
1156 * caller. If we can successfully open a regular file then we simply
1157 * replace this file with a symlink below.
1159 fd
= open(ondisk_path
, O_RDWR
| O_EXCL
| O_NOFOLLOW
| O_CLOEXEC
);
1161 if (!got_err_open_nofollow_on_symlink())
1162 return got_error_from_errno2("open", ondisk_path
);
1164 /* We are updating an existing on-disk symlink. */
1165 elen
= readlink(ondisk_path
, etarget
, sizeof(etarget
));
1167 return got_error_from_errno2("readlink", ondisk_path
);
1169 if (elen
== target_len
&&
1170 memcmp(etarget
, target_path
, target_len
) == 0)
1171 return NULL
; /* nothing to do */
1175 err
= update_symlink(ondisk_path
, target_path
, target_len
);
1176 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1177 err
= got_error_from_errno2("close", ondisk_path
);
1181 static const struct got_error
*
1182 is_bad_symlink_target(int *is_bad_symlink
, const char *target_path
,
1183 size_t target_len
, const char *ondisk_path
, const char *wtroot_path
)
1185 const struct got_error
*err
= NULL
;
1186 char canonpath
[PATH_MAX
];
1187 char *path_got
= NULL
;
1189 *is_bad_symlink
= 0;
1191 if (target_len
>= sizeof(canonpath
)) {
1192 *is_bad_symlink
= 1;
1197 * We do not use realpath(3) to resolve the symlink's target
1198 * path because we don't want to resolve symlinks recursively.
1199 * Instead we make the path absolute and then canonicalize it.
1200 * Relative symlink target lookup should begin at the directory
1201 * in which the blob object is being installed.
1203 if (!got_path_is_absolute(target_path
)) {
1204 char *abspath
, *parent
;
1205 err
= got_path_dirname(&parent
, ondisk_path
);
1208 if (asprintf(&abspath
, "%s/%s", parent
, target_path
) == -1) {
1210 return got_error_from_errno("asprintf");
1213 if (strlen(abspath
) >= sizeof(canonpath
)) {
1214 err
= got_error_path(abspath
, GOT_ERR_BAD_PATH
);
1218 err
= got_canonpath(abspath
, canonpath
, sizeof(canonpath
));
1223 err
= got_canonpath(target_path
, canonpath
, sizeof(canonpath
));
1228 /* Only allow symlinks pointing at paths within the work tree. */
1229 if (!got_path_is_child(canonpath
, wtroot_path
, strlen(wtroot_path
))) {
1230 *is_bad_symlink
= 1;
1234 /* Do not allow symlinks pointing into the .got directory. */
1235 if (asprintf(&path_got
, "%s/%s", wtroot_path
,
1236 GOT_WORKTREE_GOT_DIR
) == -1)
1237 return got_error_from_errno("asprintf");
1238 if (got_path_is_child(canonpath
, path_got
, strlen(path_got
)))
1239 *is_bad_symlink
= 1;
1245 static const struct got_error
*
1246 install_symlink(int *is_bad_symlink
, struct got_worktree
*worktree
,
1247 const char *ondisk_path
, const char *path
, struct got_blob_object
*blob
,
1248 int restoring_missing_file
, int reverting_versioned_file
,
1249 int path_is_unversioned
, int allow_bad_symlinks
,
1250 struct got_repository
*repo
,
1251 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1253 const struct got_error
*err
= NULL
;
1254 char target_path
[PATH_MAX
];
1255 size_t len
, target_len
= 0;
1256 char *path_got
= NULL
;
1257 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1258 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1260 *is_bad_symlink
= 0;
1263 * Blob object content specifies the target path of the link.
1264 * If a symbolic link cannot be installed we instead create
1265 * a regular file which contains the link target path stored
1266 * in the blob object.
1269 err
= got_object_blob_read_block(&len
, blob
);
1270 if (len
+ target_len
>= sizeof(target_path
)) {
1271 /* Path too long; install as a regular file. */
1272 *is_bad_symlink
= 1;
1273 got_object_blob_rewind(blob
);
1274 return install_blob(worktree
, ondisk_path
, path
,
1275 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1276 restoring_missing_file
, reverting_versioned_file
,
1277 1, path_is_unversioned
, repo
, progress_cb
,
1281 /* Skip blob object header first time around. */
1282 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1284 target_len
+= len
- hdrlen
;
1288 target_path
[target_len
] = '\0';
1290 err
= is_bad_symlink_target(is_bad_symlink
, target_path
, target_len
,
1291 ondisk_path
, worktree
->root_path
);
1295 if (*is_bad_symlink
&& !allow_bad_symlinks
) {
1296 /* install as a regular file */
1297 got_object_blob_rewind(blob
);
1298 err
= install_blob(worktree
, ondisk_path
, path
,
1299 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1300 restoring_missing_file
, reverting_versioned_file
, 1,
1301 path_is_unversioned
, repo
, progress_cb
, progress_arg
);
1305 if (symlink(target_path
, ondisk_path
) == -1) {
1306 if (errno
== EEXIST
) {
1307 int symlink_replaced
;
1308 if (path_is_unversioned
) {
1309 err
= (*progress_cb
)(progress_arg
,
1310 GOT_STATUS_UNVERSIONED
, path
);
1313 err
= replace_existing_symlink(&symlink_replaced
,
1314 ondisk_path
, target_path
, target_len
);
1318 if (symlink_replaced
) {
1319 err
= (*progress_cb
)(progress_arg
,
1320 reverting_versioned_file
?
1322 GOT_STATUS_UPDATE
, path
);
1324 err
= (*progress_cb
)(progress_arg
,
1325 GOT_STATUS_EXISTS
, path
);
1328 goto done
; /* Nothing else to do. */
1331 if (errno
== ENOENT
) {
1333 err
= got_path_dirname(&parent
, ondisk_path
);
1336 err
= add_dir_on_disk(worktree
, parent
);
1341 * Retry, and fall through to error handling
1342 * below if this second attempt fails.
1344 if (symlink(target_path
, ondisk_path
) != -1) {
1345 err
= NULL
; /* success */
1350 /* Handle errors from first or second creation attempt. */
1351 if (errno
== ENAMETOOLONG
) {
1352 /* bad target path; install as a regular file */
1353 *is_bad_symlink
= 1;
1354 got_object_blob_rewind(blob
);
1355 err
= install_blob(worktree
, ondisk_path
, path
,
1356 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1357 restoring_missing_file
, reverting_versioned_file
, 1,
1358 path_is_unversioned
, repo
,
1359 progress_cb
, progress_arg
);
1360 } else if (errno
== ENOTDIR
) {
1361 err
= got_error_path(ondisk_path
,
1362 GOT_ERR_FILE_OBSTRUCTED
);
1364 err
= got_error_from_errno3("symlink",
1365 target_path
, ondisk_path
);
1367 } else if (progress_cb
)
1368 err
= (*progress_cb
)(progress_arg
, reverting_versioned_file
?
1369 GOT_STATUS_REVERT
: GOT_STATUS_ADD
, path
);
1375 static const struct got_error
*
1376 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1377 const char *path
, mode_t te_mode
, mode_t st_mode
,
1378 struct got_blob_object
*blob
, int restoring_missing_file
,
1379 int reverting_versioned_file
, int installing_bad_symlink
,
1380 int path_is_unversioned
, struct got_repository
*repo
,
1381 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1383 const struct got_error
*err
= NULL
;
1387 char *tmppath
= NULL
;
1389 fd
= open(ondisk_path
, O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
|
1390 O_CLOEXEC
, GOT_DEFAULT_FILE_MODE
);
1392 if (errno
== ENOENT
) {
1394 err
= got_path_dirname(&parent
, path
);
1397 err
= add_dir_on_disk(worktree
, parent
);
1401 fd
= open(ondisk_path
,
1402 O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
| O_CLOEXEC
,
1403 GOT_DEFAULT_FILE_MODE
);
1405 return got_error_from_errno2("open",
1407 } else if (errno
== EEXIST
) {
1408 if (path_is_unversioned
) {
1409 err
= (*progress_cb
)(progress_arg
,
1410 GOT_STATUS_UNVERSIONED
, path
);
1413 if (!(S_ISLNK(st_mode
) && S_ISREG(te_mode
)) &&
1414 !S_ISREG(st_mode
) && !installing_bad_symlink
) {
1415 /* TODO file is obstructed; do something */
1416 err
= got_error_path(ondisk_path
,
1417 GOT_ERR_FILE_OBSTRUCTED
);
1420 err
= got_opentemp_named_fd(&tmppath
, &fd
,
1427 return got_error_from_errno2("open", ondisk_path
);
1430 if (fchmod(fd
, get_ondisk_perms(te_mode
& S_IXUSR
, st_mode
)) == -1) {
1431 err
= got_error_from_errno2("fchmod",
1432 update
? tmppath
: ondisk_path
);
1437 if (restoring_missing_file
)
1438 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MISSING
,
1440 else if (reverting_versioned_file
)
1441 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_REVERT
,
1444 err
= (*progress_cb
)(progress_arg
,
1445 update
? GOT_STATUS_UPDATE
: GOT_STATUS_ADD
, path
);
1450 hdrlen
= got_object_blob_get_hdrlen(blob
);
1452 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1453 err
= got_object_blob_read_block(&len
, blob
);
1457 /* Skip blob object header first time around. */
1458 ssize_t outlen
= write(fd
, buf
+ hdrlen
, len
- hdrlen
);
1460 err
= got_error_from_errno("write");
1462 } else if (outlen
!= len
- hdrlen
) {
1463 err
= got_error(GOT_ERR_IO
);
1470 if (fsync(fd
) != 0) {
1471 err
= got_error_from_errno("fsync");
1476 if (S_ISLNK(st_mode
) && unlink(ondisk_path
) == -1) {
1477 err
= got_error_from_errno2("unlink", ondisk_path
);
1480 if (rename(tmppath
, ondisk_path
) != 0) {
1481 err
= got_error_from_errno3("rename", tmppath
,
1490 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1491 err
= got_error_from_errno("close");
1492 if (tmppath
!= NULL
&& unlink(tmppath
) == -1 && err
== NULL
)
1493 err
= got_error_from_errno2("unlink", tmppath
);
1498 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1499 static const struct got_error
*
1500 get_modified_file_content_status(unsigned char *status
, FILE *f
)
1502 const struct got_error
*err
= NULL
;
1503 const char *markers
[3] = {
1504 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
1505 GOT_DIFF_CONFLICT_MARKER_SEP
,
1506 GOT_DIFF_CONFLICT_MARKER_END
1510 size_t linesize
= 0;
1513 while (*status
== GOT_STATUS_MODIFY
) {
1514 linelen
= getline(&line
, &linesize
, f
);
1515 if (linelen
== -1) {
1518 err
= got_ferror(f
, GOT_ERR_IO
);
1522 if (strncmp(line
, markers
[i
], strlen(markers
[i
])) == 0) {
1523 if (strcmp(markers
[i
], GOT_DIFF_CONFLICT_MARKER_END
)
1525 *status
= GOT_STATUS_CONFLICT
;
1536 xbit_differs(struct got_fileindex_entry
*ie
, uint16_t st_mode
)
1538 mode_t ie_mode
= got_fileindex_perms_to_st(ie
);
1539 return ((ie_mode
& S_IXUSR
) != (st_mode
& S_IXUSR
));
1543 stat_info_differs(struct got_fileindex_entry
*ie
, struct stat
*sb
)
1545 return !(ie
->ctime_sec
== sb
->st_ctim
.tv_sec
&&
1546 ie
->ctime_nsec
== sb
->st_ctim
.tv_nsec
&&
1547 ie
->mtime_sec
== sb
->st_mtim
.tv_sec
&&
1548 ie
->mtime_nsec
== sb
->st_mtim
.tv_nsec
&&
1549 ie
->size
== (sb
->st_size
& 0xffffffff) &&
1550 !xbit_differs(ie
, sb
->st_mode
));
1553 static unsigned char
1554 get_staged_status(struct got_fileindex_entry
*ie
)
1556 switch (got_fileindex_entry_stage_get(ie
)) {
1557 case GOT_FILEIDX_STAGE_ADD
:
1558 return GOT_STATUS_ADD
;
1559 case GOT_FILEIDX_STAGE_DELETE
:
1560 return GOT_STATUS_DELETE
;
1561 case GOT_FILEIDX_STAGE_MODIFY
:
1562 return GOT_STATUS_MODIFY
;
1564 return GOT_STATUS_NO_CHANGE
;
1568 static const struct got_error
*
1569 get_symlink_modification_status(unsigned char *status
,
1570 struct got_fileindex_entry
*ie
, const char *abspath
,
1571 int dirfd
, const char *de_name
, struct got_blob_object
*blob
)
1573 const struct got_error
*err
= NULL
;
1574 char target_path
[PATH_MAX
];
1575 char etarget
[PATH_MAX
];
1577 size_t len
, target_len
= 0;
1578 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1579 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1581 *status
= GOT_STATUS_NO_CHANGE
;
1583 /* Blob object content specifies the target path of the link. */
1585 err
= got_object_blob_read_block(&len
, blob
);
1588 if (len
+ target_len
>= sizeof(target_path
)) {
1590 * Should not happen. The blob contents were OK
1591 * when this symlink was installed.
1593 return got_error(GOT_ERR_NO_SPACE
);
1596 /* Skip blob object header first time around. */
1597 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1599 target_len
+= len
- hdrlen
;
1603 target_path
[target_len
] = '\0';
1606 elen
= readlinkat(dirfd
, de_name
, etarget
, sizeof(etarget
));
1608 return got_error_from_errno2("readlinkat", abspath
);
1610 elen
= readlink(abspath
, etarget
, sizeof(etarget
));
1612 return got_error_from_errno2("readlink", abspath
);
1615 if (elen
!= target_len
|| memcmp(etarget
, target_path
, target_len
) != 0)
1616 *status
= GOT_STATUS_MODIFY
;
1621 static const struct got_error
*
1622 get_file_status(unsigned char *status
, struct stat
*sb
,
1623 struct got_fileindex_entry
*ie
, const char *abspath
,
1624 int dirfd
, const char *de_name
, struct got_repository
*repo
)
1626 const struct got_error
*err
= NULL
;
1627 struct got_object_id id
;
1629 int fd
= -1, fd1
= -1;
1632 struct got_blob_object
*blob
= NULL
;
1634 unsigned char staged_status
= get_staged_status(ie
);
1636 *status
= GOT_STATUS_NO_CHANGE
;
1637 memset(sb
, 0, sizeof(*sb
));
1640 * Whenever the caller provides a directory descriptor and a
1641 * directory entry name for the file, use them! This prevents
1642 * race conditions if filesystem paths change beneath our feet.
1645 if (fstatat(dirfd
, de_name
, sb
, AT_SYMLINK_NOFOLLOW
) == -1) {
1646 if (errno
== ENOENT
) {
1647 if (got_fileindex_entry_has_file_on_disk(ie
))
1648 *status
= GOT_STATUS_MISSING
;
1650 *status
= GOT_STATUS_DELETE
;
1653 err
= got_error_from_errno2("fstatat", abspath
);
1657 fd
= open(abspath
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1658 if (fd
== -1 && errno
!= ENOENT
&&
1659 !got_err_open_nofollow_on_symlink())
1660 return got_error_from_errno2("open", abspath
);
1661 else if (fd
== -1 && got_err_open_nofollow_on_symlink()) {
1662 if (lstat(abspath
, sb
) == -1)
1663 return got_error_from_errno2("lstat", abspath
);
1664 } else if (fd
== -1 || fstat(fd
, sb
) == -1) {
1665 if (errno
== ENOENT
) {
1666 if (got_fileindex_entry_has_file_on_disk(ie
))
1667 *status
= GOT_STATUS_MISSING
;
1669 *status
= GOT_STATUS_DELETE
;
1672 err
= got_error_from_errno2("fstat", abspath
);
1677 if (!S_ISREG(sb
->st_mode
) && !S_ISLNK(sb
->st_mode
)) {
1678 *status
= GOT_STATUS_OBSTRUCTED
;
1682 if (!got_fileindex_entry_has_file_on_disk(ie
)) {
1683 *status
= GOT_STATUS_DELETE
;
1685 } else if (!got_fileindex_entry_has_blob(ie
) &&
1686 staged_status
!= GOT_STATUS_ADD
) {
1687 *status
= GOT_STATUS_ADD
;
1691 if (!stat_info_differs(ie
, sb
))
1694 if (S_ISLNK(sb
->st_mode
) &&
1695 got_fileindex_entry_filetype_get(ie
) != GOT_FILEIDX_MODE_SYMLINK
) {
1696 *status
= GOT_STATUS_MODIFY
;
1700 if (staged_status
== GOT_STATUS_MODIFY
||
1701 staged_status
== GOT_STATUS_ADD
)
1702 memcpy(id
.sha1
, ie
->staged_blob_sha1
, sizeof(id
.sha1
));
1704 memcpy(id
.sha1
, ie
->blob_sha1
, sizeof(id
.sha1
));
1706 fd1
= got_opentempfd();
1708 err
= got_error_from_errno("got_opentempfd");
1711 err
= got_object_open_as_blob(&blob
, repo
, &id
, sizeof(fbuf
), fd1
);
1715 if (S_ISLNK(sb
->st_mode
)) {
1716 err
= get_symlink_modification_status(status
, ie
,
1717 abspath
, dirfd
, de_name
, blob
);
1722 fd
= openat(dirfd
, de_name
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
1724 err
= got_error_from_errno2("openat", abspath
);
1729 f
= fdopen(fd
, "r");
1731 err
= got_error_from_errno2("fdopen", abspath
);
1735 hdrlen
= got_object_blob_get_hdrlen(blob
);
1737 const uint8_t *bbuf
= got_object_blob_get_read_buf(blob
);
1738 err
= got_object_blob_read_block(&blen
, blob
);
1741 /* Skip length of blob object header first time around. */
1742 flen
= fread(fbuf
, 1, sizeof(fbuf
) - hdrlen
, f
);
1743 if (flen
== 0 && ferror(f
)) {
1744 err
= got_error_from_errno("fread");
1747 if (blen
- hdrlen
== 0) {
1749 *status
= GOT_STATUS_MODIFY
;
1751 } else if (flen
== 0) {
1752 if (blen
- hdrlen
!= 0)
1753 *status
= GOT_STATUS_MODIFY
;
1755 } else if (blen
- hdrlen
== flen
) {
1756 /* Skip blob object header first time around. */
1757 if (memcmp(bbuf
+ hdrlen
, fbuf
, flen
) != 0) {
1758 *status
= GOT_STATUS_MODIFY
;
1762 *status
= GOT_STATUS_MODIFY
;
1768 if (*status
== GOT_STATUS_MODIFY
) {
1770 err
= get_modified_file_content_status(status
, f
);
1771 } else if (xbit_differs(ie
, sb
->st_mode
))
1772 *status
= GOT_STATUS_MODE_CHANGE
;
1774 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
1775 err
= got_error_from_errno("close");
1777 got_object_blob_close(blob
);
1778 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
1779 err
= got_error_from_errno2("fclose", abspath
);
1780 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1781 err
= got_error_from_errno2("close", abspath
);
1786 * Update timestamps in the file index if a file is unmodified and
1787 * we had to run a full content comparison to find out.
1789 static const struct got_error
*
1790 sync_timestamps(int wt_fd
, const char *path
, unsigned char status
,
1791 struct got_fileindex_entry
*ie
, struct stat
*sb
)
1793 if (status
== GOT_STATUS_NO_CHANGE
&& stat_info_differs(ie
, sb
))
1794 return got_fileindex_entry_update(ie
, wt_fd
, path
,
1795 ie
->blob_sha1
, ie
->commit_sha1
, 1);
1800 static const struct got_error
*
1801 update_blob(struct got_worktree
*worktree
,
1802 struct got_fileindex
*fileindex
, struct got_fileindex_entry
*ie
,
1803 struct got_tree_entry
*te
, const char *path
,
1804 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
1807 const struct got_error
*err
= NULL
;
1808 struct got_blob_object
*blob
= NULL
;
1809 char *ondisk_path
= NULL
;
1810 unsigned char status
= GOT_STATUS_NO_CHANGE
;
1812 int fd1
= -1, fd2
= -1;
1814 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, path
) == -1)
1815 return got_error_from_errno("asprintf");
1818 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
) {
1819 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
1822 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
1826 if (status
== GOT_STATUS_MISSING
|| status
== GOT_STATUS_DELETE
)
1827 sb
.st_mode
= got_fileindex_perms_to_st(ie
);
1829 if (stat(ondisk_path
, &sb
) == -1) {
1830 if (errno
!= ENOENT
) {
1831 err
= got_error_from_errno2("stat",
1835 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
1836 status
= GOT_STATUS_UNVERSIONED
;
1838 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
1839 status
= GOT_STATUS_UNVERSIONED
;
1841 status
= GOT_STATUS_OBSTRUCTED
;
1845 if (status
== GOT_STATUS_OBSTRUCTED
) {
1847 got_fileindex_entry_mark_skipped(ie
);
1848 err
= (*progress_cb
)(progress_arg
, status
, path
);
1851 if (status
== GOT_STATUS_CONFLICT
) {
1853 got_fileindex_entry_mark_skipped(ie
);
1854 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CANNOT_UPDATE
,
1859 if (ie
&& status
!= GOT_STATUS_MISSING
&& S_ISREG(sb
.st_mode
) &&
1860 (S_ISLNK(te
->mode
) ||
1861 (te
->mode
& S_IXUSR
) == (sb
.st_mode
& S_IXUSR
))) {
1863 * This is a regular file or an installed bad symlink.
1864 * If the file index indicates that this file is already
1865 * up-to-date with respect to the repository we can skip
1866 * updating contents of this file.
1868 if (got_fileindex_entry_has_commit(ie
) &&
1869 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
1870 SHA1_DIGEST_LENGTH
) == 0) {
1872 err
= sync_timestamps(worktree
->root_fd
,
1873 path
, status
, ie
, &sb
);
1876 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
1880 if (got_fileindex_entry_has_blob(ie
) &&
1881 memcmp(ie
->blob_sha1
, te
->id
.sha1
,
1882 SHA1_DIGEST_LENGTH
) == 0) {
1883 /* Different commit but the same blob. */
1884 err
= sync_timestamps(worktree
->root_fd
,
1885 path
, status
, ie
, &sb
);
1888 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
1894 fd1
= got_opentempfd();
1896 err
= got_error_from_errno("got_opentempfd");
1899 err
= got_object_open_as_blob(&blob
, repo
, &te
->id
, 8192, fd1
);
1903 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_ADD
) {
1904 int update_timestamps
;
1905 struct got_blob_object
*blob2
= NULL
;
1906 char *label_orig
= NULL
;
1907 if (got_fileindex_entry_has_blob(ie
)) {
1908 fd2
= got_opentempfd();
1910 err
= got_error_from_errno("got_opentempfd");
1913 struct got_object_id id2
;
1914 memcpy(id2
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
1915 err
= got_object_open_as_blob(&blob2
, repo
, &id2
, 8192,
1920 if (got_fileindex_entry_has_commit(ie
)) {
1921 char id_str
[SHA1_DIGEST_STRING_LENGTH
];
1922 if (got_sha1_digest_to_str(ie
->commit_sha1
, id_str
,
1923 sizeof(id_str
)) == NULL
) {
1924 err
= got_error_path(id_str
,
1925 GOT_ERR_BAD_OBJ_ID_STR
);
1928 if (asprintf(&label_orig
, "%s: commit %s",
1929 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
1930 err
= got_error_from_errno("asprintf");
1934 if (S_ISLNK(te
->mode
) && S_ISLNK(sb
.st_mode
)) {
1936 err
= got_object_blob_read_to_str(&link_target
, blob
);
1939 err
= merge_symlink(worktree
, blob2
, ondisk_path
, path
,
1940 label_orig
, link_target
, worktree
->base_commit_id
,
1941 repo
, progress_cb
, progress_arg
);
1944 err
= merge_blob(&update_timestamps
, worktree
, blob2
,
1945 ondisk_path
, path
, sb
.st_mode
, label_orig
, blob
,
1946 worktree
->base_commit_id
, repo
,
1947 progress_cb
, progress_arg
);
1950 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
) {
1951 err
= got_error_from_errno("close");
1955 got_object_blob_close(blob2
);
1959 * Do not update timestamps of files with local changes.
1960 * Otherwise, a future status walk would treat them as
1961 * unmodified files again.
1963 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
1964 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
,
1966 } else if (status
== GOT_STATUS_MODE_CHANGE
) {
1967 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
1968 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
1969 } else if (status
== GOT_STATUS_DELETE
) {
1970 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
1973 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
1974 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
1978 int is_bad_symlink
= 0;
1979 if (S_ISLNK(te
->mode
)) {
1980 err
= install_symlink(&is_bad_symlink
, worktree
,
1981 ondisk_path
, path
, blob
,
1982 status
== GOT_STATUS_MISSING
, 0,
1983 status
== GOT_STATUS_UNVERSIONED
, 0,
1984 repo
, progress_cb
, progress_arg
);
1986 err
= install_blob(worktree
, ondisk_path
, path
,
1987 te
->mode
, sb
.st_mode
, blob
,
1988 status
== GOT_STATUS_MISSING
, 0, 0,
1989 status
== GOT_STATUS_UNVERSIONED
, repo
,
1990 progress_cb
, progress_arg
);
1996 err
= got_fileindex_entry_update(ie
,
1997 worktree
->root_fd
, path
, blob
->id
.sha1
,
1998 worktree
->base_commit_id
->sha1
, 1);
2000 err
= create_fileindex_entry(&ie
, fileindex
,
2001 worktree
->base_commit_id
, worktree
->root_fd
, path
,
2007 if (is_bad_symlink
) {
2008 got_fileindex_entry_filetype_set(ie
,
2009 GOT_FILEIDX_MODE_BAD_SYMLINK
);
2013 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
) {
2014 err
= got_error_from_errno("close");
2017 got_object_blob_close(blob
);
2023 static const struct got_error
*
2024 remove_ondisk_file(const char *root_path
, const char *path
)
2026 const struct got_error
*err
= NULL
;
2027 char *ondisk_path
= NULL
, *parent
= NULL
;
2029 if (asprintf(&ondisk_path
, "%s/%s", root_path
, path
) == -1)
2030 return got_error_from_errno("asprintf");
2032 if (unlink(ondisk_path
) == -1) {
2033 if (errno
!= ENOENT
)
2034 err
= got_error_from_errno2("unlink", ondisk_path
);
2036 size_t root_len
= strlen(root_path
);
2037 err
= got_path_dirname(&parent
, ondisk_path
);
2040 while (got_path_cmp(parent
, root_path
,
2041 strlen(parent
), root_len
) != 0) {
2043 ondisk_path
= parent
;
2045 if (rmdir(ondisk_path
) == -1) {
2046 if (errno
!= ENOTEMPTY
)
2047 err
= got_error_from_errno2("rmdir",
2051 err
= got_path_dirname(&parent
, ondisk_path
);
2062 static const struct got_error
*
2063 delete_blob(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2064 struct got_fileindex_entry
*ie
, struct got_repository
*repo
,
2065 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2067 const struct got_error
*err
= NULL
;
2068 unsigned char status
;
2072 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
2073 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
2075 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, ie
->path
)
2077 return got_error_from_errno("asprintf");
2079 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, repo
);
2083 if (S_ISLNK(sb
.st_mode
) && status
!= GOT_STATUS_NO_CHANGE
) {
2084 char ondisk_target
[PATH_MAX
];
2085 ssize_t ondisk_len
= readlink(ondisk_path
, ondisk_target
,
2086 sizeof(ondisk_target
));
2087 if (ondisk_len
== -1) {
2088 err
= got_error_from_errno2("readlink", ondisk_path
);
2091 ondisk_target
[ondisk_len
] = '\0';
2092 err
= install_symlink_conflict(NULL
, worktree
->base_commit_id
,
2093 NULL
, NULL
, /* XXX pass common ancestor info? */
2094 ondisk_target
, ondisk_path
);
2097 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
2102 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_CONFLICT
||
2103 status
== GOT_STATUS_ADD
) {
2104 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, ie
->path
);
2108 * Preserve the working file and change the deleted blob's
2109 * entry into a schedule-add entry.
2111 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
,
2112 ie
->path
, NULL
, NULL
, 0);
2114 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_DELETE
, ie
->path
);
2117 if (status
== GOT_STATUS_NO_CHANGE
) {
2118 err
= remove_ondisk_file(worktree
->root_path
, ie
->path
);
2122 got_fileindex_entry_remove(fileindex
, ie
);
2129 struct diff_cb_arg
{
2130 struct got_fileindex
*fileindex
;
2131 struct got_worktree
*worktree
;
2132 struct got_repository
*repo
;
2133 got_worktree_checkout_cb progress_cb
;
2135 got_cancel_cb cancel_cb
;
2139 static const struct got_error
*
2140 diff_old_new(void *arg
, struct got_fileindex_entry
*ie
,
2141 struct got_tree_entry
*te
, const char *parent_path
)
2143 struct diff_cb_arg
*a
= arg
;
2145 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2146 return got_error(GOT_ERR_CANCELLED
);
2148 return update_blob(a
->worktree
, a
->fileindex
, ie
, te
,
2149 ie
->path
, a
->repo
, a
->progress_cb
, a
->progress_arg
);
2152 static const struct got_error
*
2153 diff_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
2155 struct diff_cb_arg
*a
= arg
;
2157 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2158 return got_error(GOT_ERR_CANCELLED
);
2160 return delete_blob(a
->worktree
, a
->fileindex
, ie
,
2161 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2164 static const struct got_error
*
2165 diff_new(void *arg
, struct got_tree_entry
*te
, const char *parent_path
)
2167 struct diff_cb_arg
*a
= arg
;
2168 const struct got_error
*err
;
2171 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2172 return got_error(GOT_ERR_CANCELLED
);
2174 if (got_object_tree_entry_is_submodule(te
))
2177 if (asprintf(&path
, "%s%s%s", parent_path
,
2178 parent_path
[0] ? "/" : "", te
->name
)
2180 return got_error_from_errno("asprintf");
2182 if (S_ISDIR(te
->mode
))
2183 err
= add_dir_on_disk(a
->worktree
, path
);
2185 err
= update_blob(a
->worktree
, a
->fileindex
, NULL
, te
, path
,
2186 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2192 const struct got_error
*
2193 got_worktree_get_uuid(char **uuidstr
, struct got_worktree
*worktree
)
2195 uint32_t uuid_status
;
2197 uuid_to_string(&worktree
->uuid
, uuidstr
, &uuid_status
);
2198 if (uuid_status
!= uuid_s_ok
) {
2200 return got_error_uuid(uuid_status
, "uuid_to_string");
2206 static const struct got_error
*
2207 get_ref_name(char **refname
, struct got_worktree
*worktree
, const char *prefix
)
2209 const struct got_error
*err
= NULL
;
2210 char *uuidstr
= NULL
;
2214 err
= got_worktree_get_uuid(&uuidstr
, worktree
);
2218 if (asprintf(refname
, "%s-%s", prefix
, uuidstr
) == -1) {
2219 err
= got_error_from_errno("asprintf");
2226 const struct got_error
*
2227 got_worktree_get_base_ref_name(char **refname
, struct got_worktree
*worktree
)
2229 return get_ref_name(refname
, worktree
, GOT_WORKTREE_BASE_REF_PREFIX
);
2232 static const struct got_error
*
2233 get_rebase_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2235 return get_ref_name(refname
, worktree
,
2236 GOT_WORKTREE_REBASE_TMP_REF_PREFIX
);
2239 static const struct got_error
*
2240 get_newbase_symref_name(char **refname
, struct got_worktree
*worktree
)
2242 return get_ref_name(refname
, worktree
, GOT_WORKTREE_NEWBASE_REF_PREFIX
);
2245 static const struct got_error
*
2246 get_rebase_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2248 return get_ref_name(refname
, worktree
,
2249 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX
);
2252 static const struct got_error
*
2253 get_rebase_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2255 return get_ref_name(refname
, worktree
,
2256 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX
);
2259 static const struct got_error
*
2260 get_histedit_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2262 return get_ref_name(refname
, worktree
,
2263 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX
);
2266 static const struct got_error
*
2267 get_histedit_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2269 return get_ref_name(refname
, worktree
,
2270 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX
);
2273 static const struct got_error
*
2274 get_histedit_base_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2276 return get_ref_name(refname
, worktree
,
2277 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX
);
2280 static const struct got_error
*
2281 get_histedit_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2283 return get_ref_name(refname
, worktree
,
2284 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX
);
2287 const struct got_error
*
2288 got_worktree_get_histedit_script_path(char **path
,
2289 struct got_worktree
*worktree
)
2291 if (asprintf(path
, "%s/%s/%s", worktree
->root_path
,
2292 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_HISTEDIT_SCRIPT
) == -1) {
2294 return got_error_from_errno("asprintf");
2299 static const struct got_error
*
2300 get_merge_branch_ref_name(char **refname
, struct got_worktree
*worktree
)
2302 return get_ref_name(refname
, worktree
,
2303 GOT_WORKTREE_MERGE_BRANCH_REF_PREFIX
);
2306 static const struct got_error
*
2307 get_merge_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2309 return get_ref_name(refname
, worktree
,
2310 GOT_WORKTREE_MERGE_COMMIT_REF_PREFIX
);
2314 * Prevent Git's garbage collector from deleting our base commit by
2315 * setting a reference to our base commit's ID.
2317 static const struct got_error
*
2318 ref_base_commit(struct got_worktree
*worktree
, struct got_repository
*repo
)
2320 const struct got_error
*err
= NULL
;
2321 struct got_reference
*ref
= NULL
;
2324 err
= got_worktree_get_base_ref_name(&refname
, worktree
);
2328 err
= got_ref_alloc(&ref
, refname
, worktree
->base_commit_id
);
2332 err
= got_ref_write(ref
, repo
);
2340 static const struct got_error
*
2341 get_fileindex_path(char **fileindex_path
, struct got_worktree
*worktree
)
2343 const struct got_error
*err
= NULL
;
2345 if (asprintf(fileindex_path
, "%s/%s/%s", worktree
->root_path
,
2346 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_FILE_INDEX
) == -1) {
2347 err
= got_error_from_errno("asprintf");
2348 *fileindex_path
= NULL
;
2354 static const struct got_error
*
2355 open_fileindex(struct got_fileindex
**fileindex
, char **fileindex_path
,
2356 struct got_worktree
*worktree
)
2358 const struct got_error
*err
= NULL
;
2361 *fileindex_path
= NULL
;
2362 *fileindex
= got_fileindex_alloc();
2363 if (*fileindex
== NULL
)
2364 return got_error_from_errno("got_fileindex_alloc");
2366 err
= get_fileindex_path(fileindex_path
, worktree
);
2370 index
= fopen(*fileindex_path
, "rbe");
2371 if (index
== NULL
) {
2372 if (errno
!= ENOENT
)
2373 err
= got_error_from_errno2("fopen", *fileindex_path
);
2375 err
= got_fileindex_read(*fileindex
, index
);
2376 if (fclose(index
) == EOF
&& err
== NULL
)
2377 err
= got_error_from_errno("fclose");
2381 free(*fileindex_path
);
2382 *fileindex_path
= NULL
;
2383 got_fileindex_free(*fileindex
);
2389 struct bump_base_commit_id_arg
{
2390 struct got_object_id
*base_commit_id
;
2393 const char *entry_name
;
2394 got_worktree_checkout_cb progress_cb
;
2398 /* Bump base commit ID of all files within an updated part of the work tree. */
2399 static const struct got_error
*
2400 bump_base_commit_id(void *arg
, struct got_fileindex_entry
*ie
)
2402 const struct got_error
*err
;
2403 struct bump_base_commit_id_arg
*a
= arg
;
2405 if (a
->entry_name
) {
2406 if (strcmp(ie
->path
, a
->path
) != 0)
2408 } else if (!got_path_is_child(ie
->path
, a
->path
, a
->path_len
))
2411 if (got_fileindex_entry_was_skipped(ie
))
2414 if (memcmp(ie
->commit_sha1
, a
->base_commit_id
->sha1
,
2415 SHA1_DIGEST_LENGTH
) == 0)
2418 if (a
->progress_cb
) {
2419 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_BUMP_BASE
,
2424 memcpy(ie
->commit_sha1
, a
->base_commit_id
->sha1
, SHA1_DIGEST_LENGTH
);
2428 static const struct got_error
*
2429 bump_base_commit_id_everywhere(struct got_worktree
*worktree
,
2430 struct got_fileindex
*fileindex
,
2431 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2433 struct bump_base_commit_id_arg bbc_arg
;
2435 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2436 bbc_arg
.entry_name
= NULL
;
2438 bbc_arg
.path_len
= 0;
2439 bbc_arg
.progress_cb
= progress_cb
;
2440 bbc_arg
.progress_arg
= progress_arg
;
2442 return got_fileindex_for_each_entry_safe(fileindex
,
2443 bump_base_commit_id
, &bbc_arg
);
2446 static const struct got_error
*
2447 sync_fileindex(struct got_fileindex
*fileindex
, const char *fileindex_path
)
2449 const struct got_error
*err
= NULL
;
2450 char *new_fileindex_path
= NULL
;
2451 FILE *new_index
= NULL
;
2452 struct timespec timeout
;
2454 err
= got_opentemp_named(&new_fileindex_path
, &new_index
,
2459 err
= got_fileindex_write(fileindex
, new_index
);
2463 if (rename(new_fileindex_path
, fileindex_path
) != 0) {
2464 err
= got_error_from_errno3("rename", new_fileindex_path
,
2466 unlink(new_fileindex_path
);
2470 * Sleep for a short amount of time to ensure that files modified after
2471 * this program exits have a different time stamp from the one which
2472 * was recorded in the file index.
2475 timeout
.tv_nsec
= 1;
2476 nanosleep(&timeout
, NULL
);
2480 free(new_fileindex_path
);
2484 static const struct got_error
*
2485 find_tree_entry_for_checkout(int *entry_type
, char **tree_relpath
,
2486 struct got_object_id
**tree_id
, const char *wt_relpath
,
2487 struct got_commit_object
*base_commit
, struct got_worktree
*worktree
,
2488 struct got_repository
*repo
)
2490 const struct got_error
*err
= NULL
;
2491 struct got_object_id
*id
= NULL
;
2492 char *in_repo_path
= NULL
;
2493 int is_root_wt
= got_path_is_root_dir(worktree
->path_prefix
);
2495 *entry_type
= GOT_OBJ_TYPE_ANY
;
2496 *tree_relpath
= NULL
;
2499 if (wt_relpath
[0] == '\0') {
2500 /* Check out all files within the work tree. */
2501 *entry_type
= GOT_OBJ_TYPE_TREE
;
2502 *tree_relpath
= strdup("");
2503 if (*tree_relpath
== NULL
) {
2504 err
= got_error_from_errno("strdup");
2507 err
= got_object_id_by_path(tree_id
, repo
, base_commit
,
2508 worktree
->path_prefix
);
2514 /* Check out a subset of files in the work tree. */
2516 if (asprintf(&in_repo_path
, "%s%s%s", worktree
->path_prefix
,
2517 is_root_wt
? "" : "/", wt_relpath
) == -1) {
2518 err
= got_error_from_errno("asprintf");
2522 err
= got_object_id_by_path(&id
, repo
, base_commit
, in_repo_path
);
2527 in_repo_path
= NULL
;
2529 err
= got_object_get_type(entry_type
, repo
, id
);
2533 if (*entry_type
== GOT_OBJ_TYPE_BLOB
) {
2534 /* Check out a single file. */
2535 if (strchr(wt_relpath
, '/') == NULL
) {
2536 /* Check out a single file in work tree's root dir. */
2537 in_repo_path
= strdup(worktree
->path_prefix
);
2538 if (in_repo_path
== NULL
) {
2539 err
= got_error_from_errno("strdup");
2542 *tree_relpath
= strdup("");
2543 if (*tree_relpath
== NULL
) {
2544 err
= got_error_from_errno("strdup");
2548 /* Check out a single file in a subdirectory. */
2549 err
= got_path_dirname(tree_relpath
, wt_relpath
);
2552 if (asprintf(&in_repo_path
, "%s%s%s",
2553 worktree
->path_prefix
, is_root_wt
? "" : "/",
2554 *tree_relpath
) == -1) {
2555 err
= got_error_from_errno("asprintf");
2559 err
= got_object_id_by_path(tree_id
, repo
,
2560 base_commit
, in_repo_path
);
2562 /* Check out all files within a subdirectory. */
2563 *tree_id
= got_object_id_dup(id
);
2564 if (*tree_id
== NULL
) {
2565 err
= got_error_from_errno("got_object_id_dup");
2568 *tree_relpath
= strdup(wt_relpath
);
2569 if (*tree_relpath
== NULL
) {
2570 err
= got_error_from_errno("strdup");
2578 *entry_type
= GOT_OBJ_TYPE_ANY
;
2579 free(*tree_relpath
);
2580 *tree_relpath
= NULL
;
2587 static const struct got_error
*
2588 checkout_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2589 const char *relpath
, struct got_object_id
*tree_id
, const char *entry_name
,
2590 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
2591 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
2593 const struct got_error
*err
= NULL
;
2594 struct got_commit_object
*commit
= NULL
;
2595 struct got_tree_object
*tree
= NULL
;
2596 struct got_fileindex_diff_tree_cb diff_cb
;
2597 struct diff_cb_arg arg
;
2599 err
= ref_base_commit(worktree
, repo
);
2601 if (!(err
->code
== GOT_ERR_ERRNO
&&
2602 (errno
== EACCES
|| errno
== EROFS
)))
2604 err
= (*progress_cb
)(progress_arg
,
2605 GOT_STATUS_BASE_REF_ERR
, worktree
->root_path
);
2610 err
= got_object_open_as_commit(&commit
, repo
,
2611 worktree
->base_commit_id
);
2615 err
= got_object_open_as_tree(&tree
, repo
, tree_id
);
2620 got_object_tree_find_entry(tree
, entry_name
) == NULL
) {
2621 err
= got_error_path(entry_name
, GOT_ERR_NO_TREE_ENTRY
);
2625 diff_cb
.diff_old_new
= diff_old_new
;
2626 diff_cb
.diff_old
= diff_old
;
2627 diff_cb
.diff_new
= diff_new
;
2628 arg
.fileindex
= fileindex
;
2629 arg
.worktree
= worktree
;
2631 arg
.progress_cb
= progress_cb
;
2632 arg
.progress_arg
= progress_arg
;
2633 arg
.cancel_cb
= cancel_cb
;
2634 arg
.cancel_arg
= cancel_arg
;
2635 err
= got_fileindex_diff_tree(fileindex
, tree
, relpath
,
2636 entry_name
, repo
, &diff_cb
, &arg
);
2639 got_object_tree_close(tree
);
2641 got_object_commit_close(commit
);
2645 const struct got_error
*
2646 got_worktree_checkout_files(struct got_worktree
*worktree
,
2647 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
2648 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
2649 got_cancel_cb cancel_cb
, void *cancel_arg
)
2651 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
2652 struct got_commit_object
*commit
= NULL
;
2653 struct got_tree_object
*tree
= NULL
;
2654 struct got_fileindex
*fileindex
= NULL
;
2655 char *fileindex_path
= NULL
;
2656 struct got_pathlist_entry
*pe
;
2657 struct tree_path_data
{
2658 STAILQ_ENTRY(tree_path_data
) entry
;
2659 struct got_object_id
*tree_id
;
2664 STAILQ_HEAD(tree_paths
, tree_path_data
) tree_paths
;
2666 STAILQ_INIT(&tree_paths
);
2668 err
= lock_worktree(worktree
, LOCK_EX
);
2672 err
= got_object_open_as_commit(&commit
, repo
,
2673 worktree
->base_commit_id
);
2677 /* Map all specified paths to in-repository trees. */
2678 TAILQ_FOREACH(pe
, paths
, entry
) {
2679 tpd
= malloc(sizeof(*tpd
));
2681 err
= got_error_from_errno("malloc");
2685 err
= find_tree_entry_for_checkout(&tpd
->entry_type
,
2686 &tpd
->relpath
, &tpd
->tree_id
, pe
->path
, commit
,
2693 if (tpd
->entry_type
== GOT_OBJ_TYPE_BLOB
) {
2694 err
= got_path_basename(&tpd
->entry_name
, pe
->path
);
2702 tpd
->entry_name
= NULL
;
2704 STAILQ_INSERT_TAIL(&tree_paths
, tpd
, entry
);
2708 * Read the file index.
2709 * Checking out files is supposed to be an idempotent operation.
2710 * If the on-disk file index is incomplete we will try to complete it.
2712 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
2716 tpd
= STAILQ_FIRST(&tree_paths
);
2717 TAILQ_FOREACH(pe
, paths
, entry
) {
2718 struct bump_base_commit_id_arg bbc_arg
;
2720 err
= checkout_files(worktree
, fileindex
, tpd
->relpath
,
2721 tpd
->tree_id
, tpd
->entry_name
, repo
,
2722 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
2726 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2727 bbc_arg
.entry_name
= tpd
->entry_name
;
2728 bbc_arg
.path
= pe
->path
;
2729 bbc_arg
.path_len
= pe
->path_len
;
2730 bbc_arg
.progress_cb
= progress_cb
;
2731 bbc_arg
.progress_arg
= progress_arg
;
2732 err
= got_fileindex_for_each_entry_safe(fileindex
,
2733 bump_base_commit_id
, &bbc_arg
);
2737 tpd
= STAILQ_NEXT(tpd
, entry
);
2739 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
2740 if (sync_err
&& err
== NULL
)
2743 free(fileindex_path
);
2745 got_object_tree_close(tree
);
2747 got_object_commit_close(commit
);
2749 got_fileindex_free(fileindex
);
2750 while (!STAILQ_EMPTY(&tree_paths
)) {
2751 tpd
= STAILQ_FIRST(&tree_paths
);
2752 STAILQ_REMOVE_HEAD(&tree_paths
, entry
);
2757 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
2758 if (unlockerr
&& err
== NULL
)
2763 struct merge_file_cb_arg
{
2764 struct got_worktree
*worktree
;
2765 struct got_fileindex
*fileindex
;
2766 got_worktree_checkout_cb progress_cb
;
2768 got_cancel_cb cancel_cb
;
2770 const char *label_orig
;
2771 struct got_object_id
*commit_id2
;
2772 int allow_bad_symlinks
;
2775 static const struct got_error
*
2776 merge_file_cb(void *arg
, struct got_blob_object
*blob1
,
2777 struct got_blob_object
*blob2
, FILE *f1
, FILE *f2
,
2778 struct got_object_id
*id1
, struct got_object_id
*id2
,
2779 const char *path1
, const char *path2
,
2780 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
2782 static const struct got_error
*err
= NULL
;
2783 struct merge_file_cb_arg
*a
= arg
;
2784 struct got_fileindex_entry
*ie
;
2785 char *ondisk_path
= NULL
;
2787 unsigned char status
;
2788 int local_changes_subsumed
;
2789 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
2790 char *id_str
= NULL
, *label_deriv2
= NULL
;
2792 if (blob1
&& blob2
) {
2793 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
2796 return (*a
->progress_cb
)(a
->progress_arg
,
2797 GOT_STATUS_MISSING
, path2
);
2799 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2801 return got_error_from_errno("asprintf");
2803 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2808 if (status
== GOT_STATUS_DELETE
) {
2809 err
= (*a
->progress_cb
)(a
->progress_arg
,
2810 GOT_STATUS_MERGE
, path2
);
2813 if (status
!= GOT_STATUS_NO_CHANGE
&&
2814 status
!= GOT_STATUS_MODIFY
&&
2815 status
!= GOT_STATUS_CONFLICT
&&
2816 status
!= GOT_STATUS_ADD
) {
2817 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path2
);
2821 if (S_ISLNK(mode1
) && S_ISLNK(mode2
)) {
2823 err
= got_object_blob_read_to_str(&link_target2
, blob2
);
2826 err
= merge_symlink(a
->worktree
, blob1
, ondisk_path
,
2827 path2
, a
->label_orig
, link_target2
, a
->commit_id2
,
2828 repo
, a
->progress_cb
, a
->progress_arg
);
2833 f_orig
= got_opentemp();
2834 if (f_orig
== NULL
) {
2835 err
= got_error_from_errno("got_opentemp");
2838 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2843 f_deriv2
= got_opentemp();
2844 if (f_deriv2
== NULL
)
2846 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2851 fd
= open(ondisk_path
,
2852 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
2854 err
= got_error_from_errno2("open",
2858 f_deriv
= fdopen(fd
, "r");
2859 if (f_deriv
== NULL
) {
2860 err
= got_error_from_errno2("fdopen",
2865 err
= got_object_id_str(&id_str
, a
->commit_id2
);
2868 if (asprintf(&label_deriv2
, "%s: commit %s",
2869 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
2870 err
= got_error_from_errno("asprintf");
2873 err
= merge_file(&local_changes_subsumed
, a
->worktree
,
2874 f_orig
, f_deriv
, f_deriv2
, ondisk_path
, path2
,
2875 sb
.st_mode
, a
->label_orig
, NULL
, label_deriv2
,
2876 GOT_DIFF_ALGORITHM_PATIENCE
, repo
,
2877 a
->progress_cb
, a
->progress_arg
);
2880 ie
= got_fileindex_entry_get(a
->fileindex
, path1
,
2883 return (*a
->progress_cb
)(a
->progress_arg
,
2884 GOT_STATUS_MISSING
, path1
);
2886 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2888 return got_error_from_errno("asprintf");
2890 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2896 case GOT_STATUS_NO_CHANGE
:
2897 err
= (*a
->progress_cb
)(a
->progress_arg
,
2898 GOT_STATUS_DELETE
, path1
);
2901 err
= remove_ondisk_file(a
->worktree
->root_path
, path1
);
2905 got_fileindex_entry_mark_deleted_from_disk(ie
);
2907 case GOT_STATUS_DELETE
:
2908 case GOT_STATUS_MISSING
:
2909 err
= (*a
->progress_cb
)(a
->progress_arg
,
2910 GOT_STATUS_DELETE
, path1
);
2914 got_fileindex_entry_mark_deleted_from_disk(ie
);
2916 case GOT_STATUS_ADD
: {
2917 struct got_object_id
*id
;
2921 * Delete the added file only if its content already
2922 * exists in the repository.
2924 err
= got_object_blob_file_create(&id
, &blob1_f
,
2925 &blob1_size
, path1
);
2928 if (got_object_id_cmp(id
, id1
) == 0) {
2929 err
= (*a
->progress_cb
)(a
->progress_arg
,
2930 GOT_STATUS_DELETE
, path1
);
2933 err
= remove_ondisk_file(a
->worktree
->root_path
,
2938 got_fileindex_entry_remove(a
->fileindex
,
2941 err
= (*a
->progress_cb
)(a
->progress_arg
,
2942 GOT_STATUS_CANNOT_DELETE
, path1
);
2944 if (fclose(blob1_f
) == EOF
&& err
== NULL
)
2945 err
= got_error_from_errno("fclose");
2951 case GOT_STATUS_MODIFY
:
2952 case GOT_STATUS_CONFLICT
:
2953 err
= (*a
->progress_cb
)(a
->progress_arg
,
2954 GOT_STATUS_CANNOT_DELETE
, path1
);
2958 case GOT_STATUS_OBSTRUCTED
:
2959 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path1
);
2967 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2969 return got_error_from_errno("asprintf");
2970 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
2973 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
2977 if (status
!= GOT_STATUS_NO_CHANGE
&&
2978 status
!= GOT_STATUS_MODIFY
&&
2979 status
!= GOT_STATUS_CONFLICT
&&
2980 status
!= GOT_STATUS_ADD
) {
2981 err
= (*a
->progress_cb
)(a
->progress_arg
,
2985 if (S_ISLNK(mode2
) && S_ISLNK(sb
.st_mode
)) {
2987 err
= got_object_blob_read_to_str(&link_target2
,
2991 err
= merge_symlink(a
->worktree
, NULL
,
2992 ondisk_path
, path2
, a
->label_orig
,
2993 link_target2
, a
->commit_id2
, repo
,
2994 a
->progress_cb
, a
->progress_arg
);
2996 } else if (S_ISREG(sb
.st_mode
)) {
2997 err
= merge_blob(&local_changes_subsumed
,
2998 a
->worktree
, NULL
, ondisk_path
, path2
,
2999 sb
.st_mode
, a
->label_orig
, blob2
,
3000 a
->commit_id2
, repo
, a
->progress_cb
,
3003 err
= got_error_path(ondisk_path
,
3004 GOT_ERR_FILE_OBSTRUCTED
);
3008 if (status
== GOT_STATUS_DELETE
) {
3009 err
= got_fileindex_entry_update(ie
,
3010 a
->worktree
->root_fd
, path2
, blob2
->id
.sha1
,
3011 a
->worktree
->base_commit_id
->sha1
, 0);
3016 int is_bad_symlink
= 0;
3017 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
3018 if (S_ISLNK(mode2
)) {
3019 err
= install_symlink(&is_bad_symlink
,
3020 a
->worktree
, ondisk_path
, path2
, blob2
, 0,
3021 0, 1, a
->allow_bad_symlinks
, repo
,
3022 a
->progress_cb
, a
->progress_arg
);
3024 err
= install_blob(a
->worktree
, ondisk_path
, path2
,
3025 mode2
, sb
.st_mode
, blob2
, 0, 0, 0, 1, repo
,
3026 a
->progress_cb
, a
->progress_arg
);
3030 err
= got_fileindex_entry_alloc(&ie
, path2
);
3033 err
= got_fileindex_entry_update(ie
,
3034 a
->worktree
->root_fd
, path2
, NULL
, NULL
, 1);
3036 got_fileindex_entry_free(ie
);
3039 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
3041 got_fileindex_entry_free(ie
);
3044 if (is_bad_symlink
) {
3045 got_fileindex_entry_filetype_set(ie
,
3046 GOT_FILEIDX_MODE_BAD_SYMLINK
);
3051 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
3052 err
= got_error_from_errno("fclose");
3053 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
3054 err
= got_error_from_errno("fclose");
3055 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
3056 err
= got_error_from_errno("fclose");
3063 static const struct got_error
*
3064 check_mixed_commits(void *arg
, struct got_fileindex_entry
*ie
)
3066 struct got_worktree
*worktree
= arg
;
3068 /* Reject merges into a work tree with mixed base commits. */
3069 if (got_fileindex_entry_has_commit(ie
) &&
3070 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
3071 SHA1_DIGEST_LENGTH
) != 0)
3072 return got_error(GOT_ERR_MIXED_COMMITS
);
3077 struct check_merge_conflicts_arg
{
3078 struct got_worktree
*worktree
;
3079 struct got_fileindex
*fileindex
;
3080 struct got_repository
*repo
;
3083 static const struct got_error
*
3084 check_merge_conflicts(void *arg
, struct got_blob_object
*blob1
,
3085 struct got_blob_object
*blob2
, FILE *f1
, FILE *f2
,
3086 struct got_object_id
*id1
, struct got_object_id
*id2
,
3087 const char *path1
, const char *path2
,
3088 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
3090 const struct got_error
*err
= NULL
;
3091 struct check_merge_conflicts_arg
*a
= arg
;
3092 unsigned char status
;
3094 struct got_fileindex_entry
*ie
;
3095 const char *path
= path2
? path2
: path1
;
3096 struct got_object_id
*id
= id2
? id2
: id1
;
3102 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
3106 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
3108 return got_error_from_errno("asprintf");
3110 /* Reject merges into a work tree with conflicted files. */
3111 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
3115 if (status
== GOT_STATUS_CONFLICT
)
3116 return got_error(GOT_ERR_CONFLICTS
);
3121 static const struct got_error
*
3122 merge_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
3123 const char *fileindex_path
, struct got_object_id
*commit_id1
,
3124 struct got_object_id
*commit_id2
, struct got_repository
*repo
,
3125 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
3126 got_cancel_cb cancel_cb
, void *cancel_arg
)
3128 const struct got_error
*err
= NULL
, *sync_err
;
3129 struct got_object_id
*tree_id1
= NULL
, *tree_id2
= NULL
;
3130 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
3131 struct got_commit_object
*commit1
= NULL
, *commit2
= NULL
;
3132 struct check_merge_conflicts_arg cmc_arg
;
3133 struct merge_file_cb_arg arg
;
3134 char *label_orig
= NULL
;
3135 FILE *f1
= NULL
, *f2
= NULL
;
3136 int fd1
= -1, fd2
= -1;
3139 err
= got_object_open_as_commit(&commit1
, repo
, commit_id1
);
3142 err
= got_object_id_by_path(&tree_id1
, repo
, commit1
,
3143 worktree
->path_prefix
);
3144 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
3150 err
= got_object_open_as_tree(&tree1
, repo
, tree_id1
);
3154 err
= got_object_id_str(&id_str
, commit_id1
);
3158 if (asprintf(&label_orig
, "%s: commit %s",
3159 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
3160 err
= got_error_from_errno("asprintf");
3166 f1
= got_opentemp();
3168 err
= got_error_from_errno("got_opentemp");
3173 err
= got_object_open_as_commit(&commit2
, repo
, commit_id2
);
3177 err
= got_object_id_by_path(&tree_id2
, repo
, commit2
,
3178 worktree
->path_prefix
);
3182 err
= got_object_open_as_tree(&tree2
, repo
, tree_id2
);
3186 f2
= got_opentemp();
3188 err
= got_error_from_errno("got_opentemp");
3192 fd1
= got_opentempfd();
3194 err
= got_error_from_errno("got_opentempfd");
3198 fd2
= got_opentempfd();
3200 err
= got_error_from_errno("got_opentempfd");
3204 cmc_arg
.worktree
= worktree
;
3205 cmc_arg
.fileindex
= fileindex
;
3206 cmc_arg
.repo
= repo
;
3207 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
3208 check_merge_conflicts
, &cmc_arg
, 0);
3212 arg
.worktree
= worktree
;
3213 arg
.fileindex
= fileindex
;
3214 arg
.progress_cb
= progress_cb
;
3215 arg
.progress_arg
= progress_arg
;
3216 arg
.cancel_cb
= cancel_cb
;
3217 arg
.cancel_arg
= cancel_arg
;
3218 arg
.label_orig
= label_orig
;
3219 arg
.commit_id2
= commit_id2
;
3220 arg
.allow_bad_symlinks
= 1; /* preserve bad symlinks across merges */
3221 err
= got_diff_tree(tree1
, tree2
, f1
, f2
, fd1
, fd2
, "", "", repo
,
3222 merge_file_cb
, &arg
, 1);
3223 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
3224 if (sync_err
&& err
== NULL
)
3228 got_object_commit_close(commit1
);
3230 got_object_commit_close(commit2
);
3232 got_object_tree_close(tree1
);
3234 got_object_tree_close(tree2
);
3235 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
3236 err
= got_error_from_errno("fclose");
3237 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
3238 err
= got_error_from_errno("fclose");
3239 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
3240 err
= got_error_from_errno("close");
3241 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
3242 err
= got_error_from_errno("close");
3247 const struct got_error
*
3248 got_worktree_merge_files(struct got_worktree
*worktree
,
3249 struct got_object_id
*commit_id1
, struct got_object_id
*commit_id2
,
3250 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
3251 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
3253 const struct got_error
*err
, *unlockerr
;
3254 char *fileindex_path
= NULL
;
3255 struct got_fileindex
*fileindex
= NULL
;
3257 err
= lock_worktree(worktree
, LOCK_EX
);
3261 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3265 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
3270 err
= merge_files(worktree
, fileindex
, fileindex_path
, commit_id1
,
3271 commit_id2
, repo
, progress_cb
, progress_arg
,
3272 cancel_cb
, cancel_arg
);
3275 got_fileindex_free(fileindex
);
3276 free(fileindex_path
);
3277 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
3278 if (unlockerr
&& err
== NULL
)
3283 struct diff_dir_cb_arg
{
3284 struct got_fileindex
*fileindex
;
3285 struct got_worktree
*worktree
;
3286 const char *status_path
;
3287 size_t status_path_len
;
3288 struct got_repository
*repo
;
3289 got_worktree_status_cb status_cb
;
3291 got_cancel_cb cancel_cb
;
3293 /* A pathlist containing per-directory pathlists of ignore patterns. */
3294 struct got_pathlist_head
*ignores
;
3295 int report_unchanged
;
3299 static const struct got_error
*
3300 report_file_status(struct got_fileindex_entry
*ie
, const char *abspath
,
3301 int dirfd
, const char *de_name
,
3302 got_worktree_status_cb status_cb
, void *status_arg
,
3303 struct got_repository
*repo
, int report_unchanged
)
3305 const struct got_error
*err
= NULL
;
3306 unsigned char status
= GOT_STATUS_NO_CHANGE
;
3307 unsigned char staged_status
= get_staged_status(ie
);
3309 struct got_object_id blob_id
, commit_id
, staged_blob_id
;
3310 struct got_object_id
*blob_idp
= NULL
, *commit_idp
= NULL
;
3311 struct got_object_id
*staged_blob_idp
= NULL
;
3313 err
= get_file_status(&status
, &sb
, ie
, abspath
, dirfd
, de_name
, repo
);
3317 if (status
== GOT_STATUS_NO_CHANGE
&&
3318 staged_status
== GOT_STATUS_NO_CHANGE
&& !report_unchanged
)
3321 if (got_fileindex_entry_has_blob(ie
)) {
3322 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3323 blob_idp
= &blob_id
;
3325 if (got_fileindex_entry_has_commit(ie
)) {
3326 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3327 commit_idp
= &commit_id
;
3329 if (staged_status
== GOT_STATUS_ADD
||
3330 staged_status
== GOT_STATUS_MODIFY
) {
3331 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
3332 SHA1_DIGEST_LENGTH
);
3333 staged_blob_idp
= &staged_blob_id
;
3336 return (*status_cb
)(status_arg
, status
, staged_status
,
3337 ie
->path
, blob_idp
, staged_blob_idp
, commit_idp
, dirfd
, de_name
);
3340 static const struct got_error
*
3341 status_old_new(void *arg
, struct got_fileindex_entry
*ie
,
3342 struct dirent
*de
, const char *parent_path
, int dirfd
)
3344 const struct got_error
*err
= NULL
;
3345 struct diff_dir_cb_arg
*a
= arg
;
3348 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3349 return got_error(GOT_ERR_CANCELLED
);
3351 if (got_path_cmp(parent_path
, a
->status_path
,
3352 strlen(parent_path
), a
->status_path_len
) != 0 &&
3353 !got_path_is_child(parent_path
, a
->status_path
, a
->status_path_len
))
3356 if (parent_path
[0]) {
3357 if (asprintf(&abspath
, "%s/%s/%s", a
->worktree
->root_path
,
3358 parent_path
, de
->d_name
) == -1)
3359 return got_error_from_errno("asprintf");
3361 if (asprintf(&abspath
, "%s/%s", a
->worktree
->root_path
,
3363 return got_error_from_errno("asprintf");
3366 err
= report_file_status(ie
, abspath
, dirfd
, de
->d_name
,
3367 a
->status_cb
, a
->status_arg
, a
->repo
, a
->report_unchanged
);
3372 static const struct got_error
*
3373 status_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
3375 struct diff_dir_cb_arg
*a
= arg
;
3376 struct got_object_id blob_id
, commit_id
;
3377 unsigned char status
;
3379 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3380 return got_error(GOT_ERR_CANCELLED
);
3382 if (!got_path_is_child(ie
->path
, a
->status_path
, a
->status_path_len
))
3385 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3386 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3387 if (got_fileindex_entry_has_file_on_disk(ie
))
3388 status
= GOT_STATUS_MISSING
;
3390 status
= GOT_STATUS_DELETE
;
3391 return (*a
->status_cb
)(a
->status_arg
, status
, get_staged_status(ie
),
3392 ie
->path
, &blob_id
, NULL
, &commit_id
, -1, NULL
);
3396 free_ignorelist(struct got_pathlist_head
*ignorelist
)
3398 struct got_pathlist_entry
*pe
;
3400 TAILQ_FOREACH(pe
, ignorelist
, entry
)
3401 free((char *)pe
->path
);
3402 got_pathlist_free(ignorelist
);
3406 free_ignores(struct got_pathlist_head
*ignores
)
3408 struct got_pathlist_entry
*pe
;
3410 TAILQ_FOREACH(pe
, ignores
, entry
) {
3411 struct got_pathlist_head
*ignorelist
= pe
->data
;
3412 free_ignorelist(ignorelist
);
3413 free((char *)pe
->path
);
3415 got_pathlist_free(ignores
);
3418 static const struct got_error
*
3419 read_ignores(struct got_pathlist_head
*ignores
, const char *path
, FILE *f
)
3421 const struct got_error
*err
= NULL
;
3422 struct got_pathlist_entry
*pe
= NULL
;
3423 struct got_pathlist_head
*ignorelist
;
3424 char *line
= NULL
, *pattern
, *dirpath
= NULL
;
3425 size_t linesize
= 0;
3428 ignorelist
= calloc(1, sizeof(*ignorelist
));
3429 if (ignorelist
== NULL
)
3430 return got_error_from_errno("calloc");
3431 TAILQ_INIT(ignorelist
);
3433 while ((linelen
= getline(&line
, &linesize
, f
)) != -1) {
3434 if (linelen
> 0 && line
[linelen
- 1] == '\n')
3435 line
[linelen
- 1] = '\0';
3437 /* Git's ignores may contain comments. */
3441 /* Git's negated patterns are not (yet?) supported. */
3445 if (asprintf(&pattern
, "%s%s%s", path
, path
[0] ? "/" : "",
3447 err
= got_error_from_errno("asprintf");
3450 err
= got_pathlist_insert(NULL
, ignorelist
, pattern
, NULL
);
3455 err
= got_error_from_errno("getline");
3459 dirpath
= strdup(path
);
3460 if (dirpath
== NULL
) {
3461 err
= got_error_from_errno("strdup");
3464 err
= got_pathlist_insert(&pe
, ignores
, dirpath
, ignorelist
);
3467 if (err
|| pe
== NULL
) {
3469 free_ignorelist(ignorelist
);
3475 match_ignores(struct got_pathlist_head
*ignores
, const char *path
)
3477 struct got_pathlist_entry
*pe
;
3479 /* Handle patterns which match in all directories. */
3480 TAILQ_FOREACH(pe
, ignores
, entry
) {
3481 struct got_pathlist_head
*ignorelist
= pe
->data
;
3482 struct got_pathlist_entry
*pi
;
3484 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3485 const char *p
, *pattern
= pi
->path
;
3487 if (strncmp(pattern
, "**/", 3) != 0)
3492 if (fnmatch(pattern
, p
,
3493 FNM_PATHNAME
| FNM_LEADING_DIR
)) {
3494 /* Retry in next directory. */
3495 while (*p
&& *p
!= '/')
3507 * The ignores pathlist contains ignore lists from children before
3508 * parents, so we can find the most specific ignorelist by walking
3509 * ignores backwards.
3511 pe
= TAILQ_LAST(ignores
, got_pathlist_head
);
3513 if (got_path_is_child(path
, pe
->path
, pe
->path_len
)) {
3514 struct got_pathlist_head
*ignorelist
= pe
->data
;
3515 struct got_pathlist_entry
*pi
;
3516 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3517 const char *pattern
= pi
->path
;
3518 int flags
= FNM_LEADING_DIR
;
3519 if (strstr(pattern
, "/**/") == NULL
)
3520 flags
|= FNM_PATHNAME
;
3521 if (fnmatch(pattern
, path
, flags
))
3526 pe
= TAILQ_PREV(pe
, got_pathlist_head
, entry
);
3532 static const struct got_error
*
3533 add_ignores(struct got_pathlist_head
*ignores
, const char *root_path
,
3534 const char *path
, int dirfd
, const char *ignores_filename
)
3536 const struct got_error
*err
= NULL
;
3539 FILE *ignoresfile
= NULL
;
3541 if (asprintf(&ignorespath
, "%s/%s%s%s", root_path
, path
,
3542 path
[0] ? "/" : "", ignores_filename
) == -1)
3543 return got_error_from_errno("asprintf");
3546 fd
= openat(dirfd
, ignores_filename
,
3547 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
3549 if (errno
!= ENOENT
&& errno
!= EACCES
)
3550 err
= got_error_from_errno2("openat",
3553 ignoresfile
= fdopen(fd
, "r");
3554 if (ignoresfile
== NULL
)
3555 err
= got_error_from_errno2("fdopen",
3559 err
= read_ignores(ignores
, path
, ignoresfile
);
3563 ignoresfile
= fopen(ignorespath
, "re");
3564 if (ignoresfile
== NULL
) {
3565 if (errno
!= ENOENT
&& errno
!= EACCES
)
3566 err
= got_error_from_errno2("fopen",
3569 err
= read_ignores(ignores
, path
, ignoresfile
);
3572 if (ignoresfile
&& fclose(ignoresfile
) == EOF
&& err
== NULL
)
3573 err
= got_error_from_errno2("fclose", path
);
3574 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3575 err
= got_error_from_errno2("close", path
);
3580 static const struct got_error
*
3581 status_new(int *ignore
, void *arg
, struct dirent
*de
, const char *parent_path
,
3584 const struct got_error
*err
= NULL
;
3585 struct diff_dir_cb_arg
*a
= arg
;
3591 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3592 return got_error(GOT_ERR_CANCELLED
);
3594 if (parent_path
[0]) {
3595 if (asprintf(&path
, "%s/%s", parent_path
, de
->d_name
) == -1)
3596 return got_error_from_errno("asprintf");
3601 if (de
->d_type
== DT_DIR
) {
3602 if (!a
->no_ignores
&& ignore
!= NULL
&&
3603 match_ignores(a
->ignores
, path
))
3605 } else if (!match_ignores(a
->ignores
, path
) &&
3606 got_path_is_child(path
, a
->status_path
, a
->status_path_len
))
3607 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_UNVERSIONED
,
3608 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3614 static const struct got_error
*
3615 status_traverse(void *arg
, const char *path
, int dirfd
)
3617 const struct got_error
*err
= NULL
;
3618 struct diff_dir_cb_arg
*a
= arg
;
3623 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
,
3624 path
, dirfd
, ".cvsignore");
3628 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
, path
,
3629 dirfd
, ".gitignore");
3634 static const struct got_error
*
3635 report_single_file_status(const char *path
, const char *ondisk_path
,
3636 struct got_fileindex
*fileindex
, got_worktree_status_cb status_cb
,
3637 void *status_arg
, struct got_repository
*repo
, int report_unchanged
,
3638 struct got_pathlist_head
*ignores
, int no_ignores
)
3640 struct got_fileindex_entry
*ie
;
3643 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
3645 return report_file_status(ie
, ondisk_path
, -1, NULL
,
3646 status_cb
, status_arg
, repo
, report_unchanged
);
3648 if (lstat(ondisk_path
, &sb
) == -1) {
3649 if (errno
!= ENOENT
)
3650 return got_error_from_errno2("lstat", ondisk_path
);
3651 return (*status_cb
)(status_arg
, GOT_STATUS_NONEXISTENT
,
3652 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3655 if (!no_ignores
&& match_ignores(ignores
, path
))
3658 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
3659 return (*status_cb
)(status_arg
, GOT_STATUS_UNVERSIONED
,
3660 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3665 static const struct got_error
*
3666 add_ignores_from_parent_paths(struct got_pathlist_head
*ignores
,
3667 const char *root_path
, const char *path
)
3669 const struct got_error
*err
;
3670 char *parent_path
, *next_parent_path
= NULL
;
3672 err
= add_ignores(ignores
, root_path
, "", -1,
3677 err
= add_ignores(ignores
, root_path
, "", -1,
3682 err
= got_path_dirname(&parent_path
, path
);
3684 if (err
->code
== GOT_ERR_BAD_PATH
)
3685 return NULL
; /* cannot traverse parent */
3689 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3693 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3697 err
= got_path_dirname(&next_parent_path
, parent_path
);
3699 if (err
->code
== GOT_ERR_BAD_PATH
)
3700 err
= NULL
; /* traversed everything */
3703 if (got_path_is_root_dir(parent_path
))
3706 parent_path
= next_parent_path
;
3707 next_parent_path
= NULL
;
3711 free(next_parent_path
);
3715 static const struct got_error
*
3716 worktree_status(struct got_worktree
*worktree
, const char *path
,
3717 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
3718 got_worktree_status_cb status_cb
, void *status_arg
,
3719 got_cancel_cb cancel_cb
, void *cancel_arg
, int no_ignores
,
3720 int report_unchanged
)
3722 const struct got_error
*err
= NULL
;
3724 struct got_fileindex_diff_dir_cb fdiff_cb
;
3725 struct diff_dir_cb_arg arg
;
3726 char *ondisk_path
= NULL
;
3727 struct got_pathlist_head ignores
;
3728 struct got_fileindex_entry
*ie
;
3730 TAILQ_INIT(&ignores
);
3732 if (asprintf(&ondisk_path
, "%s%s%s",
3733 worktree
->root_path
, path
[0] ? "/" : "", path
) == -1)
3734 return got_error_from_errno("asprintf");
3736 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
3738 err
= report_single_file_status(path
, ondisk_path
,
3739 fileindex
, status_cb
, status_arg
, repo
,
3740 report_unchanged
, &ignores
, no_ignores
);
3744 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_DIRECTORY
| O_CLOEXEC
);
3746 if (errno
!= ENOTDIR
&& errno
!= ENOENT
&& errno
!= EACCES
&&
3747 !got_err_open_nofollow_on_symlink())
3748 err
= got_error_from_errno2("open", ondisk_path
);
3751 err
= add_ignores_from_parent_paths(&ignores
,
3752 worktree
->root_path
, ondisk_path
);
3756 err
= report_single_file_status(path
, ondisk_path
,
3757 fileindex
, status_cb
, status_arg
, repo
,
3758 report_unchanged
, &ignores
, no_ignores
);
3761 fdiff_cb
.diff_old_new
= status_old_new
;
3762 fdiff_cb
.diff_old
= status_old
;
3763 fdiff_cb
.diff_new
= status_new
;
3764 fdiff_cb
.diff_traverse
= status_traverse
;
3765 arg
.fileindex
= fileindex
;
3766 arg
.worktree
= worktree
;
3767 arg
.status_path
= path
;
3768 arg
.status_path_len
= strlen(path
);
3770 arg
.status_cb
= status_cb
;
3771 arg
.status_arg
= status_arg
;
3772 arg
.cancel_cb
= cancel_cb
;
3773 arg
.cancel_arg
= cancel_arg
;
3774 arg
.report_unchanged
= report_unchanged
;
3775 arg
.no_ignores
= no_ignores
;
3777 err
= add_ignores_from_parent_paths(&ignores
,
3778 worktree
->root_path
, path
);
3782 arg
.ignores
= &ignores
;
3783 err
= got_fileindex_diff_dir(fileindex
, fd
,
3784 worktree
->root_path
, path
, repo
, &fdiff_cb
, &arg
);
3787 free_ignores(&ignores
);
3788 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3789 err
= got_error_from_errno("close");
3794 const struct got_error
*
3795 got_worktree_status(struct got_worktree
*worktree
,
3796 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
3797 int no_ignores
, got_worktree_status_cb status_cb
, void *status_arg
,
3798 got_cancel_cb cancel_cb
, void *cancel_arg
)
3800 const struct got_error
*err
= NULL
;
3801 char *fileindex_path
= NULL
;
3802 struct got_fileindex
*fileindex
= NULL
;
3803 struct got_pathlist_entry
*pe
;
3805 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3809 TAILQ_FOREACH(pe
, paths
, entry
) {
3810 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
3811 status_cb
, status_arg
, cancel_cb
, cancel_arg
,
3816 free(fileindex_path
);
3817 got_fileindex_free(fileindex
);
3821 const struct got_error
*
3822 got_worktree_resolve_path(char **wt_path
, struct got_worktree
*worktree
,
3825 const struct got_error
*err
= NULL
;
3826 char *resolved
= NULL
, *cwd
= NULL
, *path
= NULL
;
3829 char *abspath
= NULL
;
3830 char canonpath
[PATH_MAX
];
3834 cwd
= getcwd(NULL
, 0);
3836 return got_error_from_errno("getcwd");
3838 if (lstat(arg
, &sb
) == -1) {
3839 if (errno
!= ENOENT
) {
3840 err
= got_error_from_errno2("lstat", arg
);
3845 if (S_ISLNK(sb
.st_mode
)) {
3847 * We cannot use realpath(3) with symlinks since we want to
3848 * operate on the symlink itself.
3849 * But we can make the path absolute, assuming it is relative
3850 * to the current working directory, and then canonicalize it.
3852 if (!got_path_is_absolute(arg
)) {
3853 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3854 err
= got_error_from_errno("asprintf");
3859 err
= got_canonpath(abspath
? abspath
: arg
, canonpath
,
3863 resolved
= strdup(canonpath
);
3864 if (resolved
== NULL
) {
3865 err
= got_error_from_errno("strdup");
3869 resolved
= realpath(arg
, NULL
);
3870 if (resolved
== NULL
) {
3871 if (errno
!= ENOENT
) {
3872 err
= got_error_from_errno2("realpath", arg
);
3875 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3876 err
= got_error_from_errno("asprintf");
3879 err
= got_canonpath(abspath
, canonpath
,
3883 resolved
= strdup(canonpath
);
3884 if (resolved
== NULL
) {
3885 err
= got_error_from_errno("strdup");
3891 if (strncmp(got_worktree_get_root_path(worktree
), resolved
,
3892 strlen(got_worktree_get_root_path(worktree
)))) {
3893 err
= got_error_path(resolved
, GOT_ERR_BAD_PATH
);
3897 if (strlen(resolved
) > strlen(got_worktree_get_root_path(worktree
))) {
3898 err
= got_path_skip_common_ancestor(&path
,
3899 got_worktree_get_root_path(worktree
), resolved
);
3905 err
= got_error_from_errno("strdup");
3910 /* XXX status walk can't deal with trailing slash! */
3912 while (len
> 0 && path
[len
- 1] == '/') {
3913 path
[len
- 1] = '\0';
3927 struct schedule_addition_args
{
3928 struct got_worktree
*worktree
;
3929 struct got_fileindex
*fileindex
;
3930 got_worktree_checkout_cb progress_cb
;
3932 struct got_repository
*repo
;
3935 static const struct got_error
*
3936 schedule_addition(void *arg
, unsigned char status
, unsigned char staged_status
,
3937 const char *relpath
, struct got_object_id
*blob_id
,
3938 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
3939 int dirfd
, const char *de_name
)
3941 struct schedule_addition_args
*a
= arg
;
3942 const struct got_error
*err
= NULL
;
3943 struct got_fileindex_entry
*ie
;
3947 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3949 return got_error_from_errno("asprintf");
3951 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
3953 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
,
3957 /* Re-adding an existing entry is a no-op. */
3958 if (status
== GOT_STATUS_ADD
)
3960 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
3965 if (status
!= GOT_STATUS_UNVERSIONED
) {
3966 if (status
== GOT_STATUS_NONEXISTENT
)
3967 err
= got_error_set_errno(ENOENT
, ondisk_path
);
3969 err
= got_error_path(ondisk_path
, GOT_ERR_FILE_STATUS
);
3973 err
= got_fileindex_entry_alloc(&ie
, relpath
);
3976 err
= got_fileindex_entry_update(ie
, a
->worktree
->root_fd
,
3977 relpath
, NULL
, NULL
, 1);
3979 got_fileindex_entry_free(ie
);
3982 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
3984 got_fileindex_entry_free(ie
);
3991 if (status
== GOT_STATUS_ADD
)
3993 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_ADD
, relpath
);
3996 const struct got_error
*
3997 got_worktree_schedule_add(struct got_worktree
*worktree
,
3998 struct got_pathlist_head
*paths
,
3999 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4000 struct got_repository
*repo
, int no_ignores
)
4002 struct got_fileindex
*fileindex
= NULL
;
4003 char *fileindex_path
= NULL
;
4004 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4005 struct got_pathlist_entry
*pe
;
4006 struct schedule_addition_args saa
;
4008 err
= lock_worktree(worktree
, LOCK_EX
);
4012 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4016 saa
.worktree
= worktree
;
4017 saa
.fileindex
= fileindex
;
4018 saa
.progress_cb
= progress_cb
;
4019 saa
.progress_arg
= progress_arg
;
4022 TAILQ_FOREACH(pe
, paths
, entry
) {
4023 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4024 schedule_addition
, &saa
, NULL
, NULL
, no_ignores
, 0);
4028 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4029 if (sync_err
&& err
== NULL
)
4032 free(fileindex_path
);
4034 got_fileindex_free(fileindex
);
4035 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4036 if (unlockerr
&& err
== NULL
)
4041 struct schedule_deletion_args
{
4042 struct got_worktree
*worktree
;
4043 struct got_fileindex
*fileindex
;
4044 got_worktree_delete_cb progress_cb
;
4046 struct got_repository
*repo
;
4047 int delete_local_mods
;
4049 int ignore_missing_paths
;
4050 const char *status_codes
;
4053 static const struct got_error
*
4054 schedule_for_deletion(void *arg
, unsigned char status
,
4055 unsigned char staged_status
, const char *relpath
,
4056 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4057 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4059 struct schedule_deletion_args
*a
= arg
;
4060 const struct got_error
*err
= NULL
;
4061 struct got_fileindex_entry
*ie
= NULL
;
4065 if (status
== GOT_STATUS_NONEXISTENT
) {
4066 if (a
->ignore_missing_paths
)
4068 return got_error_set_errno(ENOENT
, relpath
);
4071 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4073 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4075 staged_status
= get_staged_status(ie
);
4076 if (staged_status
!= GOT_STATUS_NO_CHANGE
) {
4077 if (staged_status
== GOT_STATUS_DELETE
)
4079 return got_error_path(relpath
, GOT_ERR_FILE_STAGED
);
4082 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4084 return got_error_from_errno("asprintf");
4086 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
, de_name
,
4091 if (a
->status_codes
) {
4092 size_t ncodes
= strlen(a
->status_codes
);
4094 for (i
= 0; i
< ncodes
; i
++) {
4095 if (status
== a
->status_codes
[i
])
4099 /* Do not delete files in non-matching status. */
4103 if (a
->status_codes
[i
] != GOT_STATUS_MODIFY
&&
4104 a
->status_codes
[i
] != GOT_STATUS_MISSING
) {
4105 static char msg
[64];
4106 snprintf(msg
, sizeof(msg
),
4107 "invalid status code '%c'", a
->status_codes
[i
]);
4108 err
= got_error_msg(GOT_ERR_FILE_STATUS
, msg
);
4113 if (status
!= GOT_STATUS_NO_CHANGE
) {
4114 if (status
== GOT_STATUS_DELETE
)
4116 if (status
== GOT_STATUS_MODIFY
&& !a
->delete_local_mods
) {
4117 err
= got_error_path(relpath
, GOT_ERR_FILE_MODIFIED
);
4120 if (status
== GOT_STATUS_MISSING
&& !a
->ignore_missing_paths
) {
4121 err
= got_error_set_errno(ENOENT
, relpath
);
4124 if (status
!= GOT_STATUS_MODIFY
&&
4125 status
!= GOT_STATUS_MISSING
) {
4126 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4131 if (!a
->keep_on_disk
&& status
!= GOT_STATUS_MISSING
) {
4135 if (unlinkat(dirfd
, de_name
, 0) != 0) {
4136 err
= got_error_from_errno2("unlinkat",
4140 } else if (unlink(ondisk_path
) != 0) {
4141 err
= got_error_from_errno2("unlink", ondisk_path
);
4145 root_len
= strlen(a
->worktree
->root_path
);
4148 err
= got_path_dirname(&parent
, ondisk_path
);
4152 ondisk_path
= parent
;
4153 if (rmdir(ondisk_path
) == -1) {
4154 if (errno
!= ENOTEMPTY
)
4155 err
= got_error_from_errno2("rmdir",
4159 } while (got_path_cmp(ondisk_path
, a
->worktree
->root_path
,
4160 strlen(ondisk_path
), root_len
) != 0);
4163 got_fileindex_entry_mark_deleted_from_disk(ie
);
4168 if (status
== GOT_STATUS_DELETE
)
4170 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_DELETE
,
4171 staged_status
, relpath
);
4174 const struct got_error
*
4175 got_worktree_schedule_delete(struct got_worktree
*worktree
,
4176 struct got_pathlist_head
*paths
, int delete_local_mods
,
4177 const char *status_codes
,
4178 got_worktree_delete_cb progress_cb
, void *progress_arg
,
4179 struct got_repository
*repo
, int keep_on_disk
, int ignore_missing_paths
)
4181 struct got_fileindex
*fileindex
= NULL
;
4182 char *fileindex_path
= NULL
;
4183 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4184 struct got_pathlist_entry
*pe
;
4185 struct schedule_deletion_args sda
;
4187 err
= lock_worktree(worktree
, LOCK_EX
);
4191 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4195 sda
.worktree
= worktree
;
4196 sda
.fileindex
= fileindex
;
4197 sda
.progress_cb
= progress_cb
;
4198 sda
.progress_arg
= progress_arg
;
4200 sda
.delete_local_mods
= delete_local_mods
;
4201 sda
.keep_on_disk
= keep_on_disk
;
4202 sda
.ignore_missing_paths
= ignore_missing_paths
;
4203 sda
.status_codes
= status_codes
;
4205 TAILQ_FOREACH(pe
, paths
, entry
) {
4206 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4207 schedule_for_deletion
, &sda
, NULL
, NULL
, 1, 1);
4211 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4212 if (sync_err
&& err
== NULL
)
4215 free(fileindex_path
);
4217 got_fileindex_free(fileindex
);
4218 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4219 if (unlockerr
&& err
== NULL
)
4224 static const struct got_error
*
4225 copy_one_line(FILE *infile
, FILE *outfile
, FILE *rejectfile
)
4227 const struct got_error
*err
= NULL
;
4229 size_t linesize
= 0, n
;
4232 linelen
= getline(&line
, &linesize
, infile
);
4233 if (linelen
== -1) {
4234 if (ferror(infile
)) {
4235 err
= got_error_from_errno("getline");
4241 n
= fwrite(line
, 1, linelen
, outfile
);
4243 err
= got_ferror(outfile
, GOT_ERR_IO
);
4248 n
= fwrite(line
, 1, linelen
, rejectfile
);
4250 err
= got_ferror(outfile
, GOT_ERR_IO
);
4257 static const struct got_error
*
4258 skip_one_line(FILE *f
)
4261 size_t linesize
= 0;
4264 linelen
= getline(&line
, &linesize
, f
);
4265 if (linelen
== -1) {
4267 return got_error_from_errno("getline");
4274 static const struct got_error
*
4275 copy_change(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4276 int start_old
, int end_old
, int start_new
, int end_new
,
4277 FILE *outfile
, FILE *rejectfile
)
4279 const struct got_error
*err
;
4281 /* Copy old file's lines leading up to patch. */
4282 while (!feof(f1
) && *line_cur1
< start_old
) {
4283 err
= copy_one_line(f1
, outfile
, NULL
);
4288 /* Skip new file's lines leading up to patch. */
4289 while (!feof(f2
) && *line_cur2
< start_new
) {
4291 err
= copy_one_line(f2
, NULL
, rejectfile
);
4293 err
= skip_one_line(f2
);
4298 /* Copy patched lines. */
4299 while (!feof(f2
) && *line_cur2
<= end_new
) {
4300 err
= copy_one_line(f2
, outfile
, NULL
);
4305 /* Skip over old file's replaced lines. */
4306 while (!feof(f1
) && *line_cur1
<= end_old
) {
4308 err
= copy_one_line(f1
, NULL
, rejectfile
);
4310 err
= skip_one_line(f1
);
4319 static const struct got_error
*
4320 copy_remaining_content(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4321 FILE *outfile
, FILE *rejectfile
)
4323 const struct got_error
*err
;
4326 /* Copy old file's lines until EOF. */
4328 err
= copy_one_line(f1
, outfile
, NULL
);
4335 /* Copy new file's lines until EOF. */
4337 err
= copy_one_line(f2
, NULL
, rejectfile
);
4347 static const struct got_error
*
4348 apply_or_reject_change(int *choice
, int *nchunks_used
,
4349 struct diff_result
*diff_result
, int n
,
4350 const char *relpath
, FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4351 FILE *outfile
, FILE *rejectfile
, int changeno
, int nchanges
,
4352 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4354 const struct got_error
*err
= NULL
;
4355 struct diff_chunk_context cc
= {};
4356 int start_old
, end_old
, start_new
, end_new
;
4358 struct diff_output_unidiff_state
*diff_state
;
4359 struct diff_input_info diff_info
;
4362 *choice
= GOT_PATCH_CHOICE_NONE
;
4364 /* Get changed line numbers without context lines for copy_change(). */
4365 diff_chunk_context_load_change(&cc
, NULL
, diff_result
, n
, 0);
4366 start_old
= cc
.left
.start
;
4367 end_old
= cc
.left
.end
;
4368 start_new
= cc
.right
.start
;
4369 end_new
= cc
.right
.end
;
4371 /* Get the same change with context lines for display. */
4372 memset(&cc
, 0, sizeof(cc
));
4373 diff_chunk_context_load_change(&cc
, nchunks_used
, diff_result
, n
, 3);
4375 memset(&diff_info
, 0, sizeof(diff_info
));
4376 diff_info
.left_path
= relpath
;
4377 diff_info
.right_path
= relpath
;
4379 diff_state
= diff_output_unidiff_state_alloc();
4380 if (diff_state
== NULL
)
4381 return got_error_set_errno(ENOMEM
,
4382 "diff_output_unidiff_state_alloc");
4384 hunkfile
= got_opentemp();
4385 if (hunkfile
== NULL
) {
4386 err
= got_error_from_errno("got_opentemp");
4390 rc
= diff_output_unidiff_chunk(NULL
, hunkfile
, diff_state
, &diff_info
,
4392 if (rc
!= DIFF_RC_OK
) {
4393 err
= got_error_set_errno(rc
, "diff_output_unidiff_chunk");
4397 if (fseek(hunkfile
, 0L, SEEK_SET
) == -1) {
4398 err
= got_ferror(hunkfile
, GOT_ERR_IO
);
4402 err
= (*patch_cb
)(choice
, patch_arg
, GOT_STATUS_MODIFY
, relpath
,
4403 hunkfile
, changeno
, nchanges
);
4408 case GOT_PATCH_CHOICE_YES
:
4409 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4410 end_old
, start_new
, end_new
, outfile
, rejectfile
);
4412 case GOT_PATCH_CHOICE_NO
:
4413 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4414 end_old
, start_new
, end_new
, rejectfile
, outfile
);
4416 case GOT_PATCH_CHOICE_QUIT
:
4419 err
= got_error(GOT_ERR_PATCH_CHOICE
);
4423 diff_output_unidiff_state_free(diff_state
);
4424 if (hunkfile
&& fclose(hunkfile
) == EOF
&& err
== NULL
)
4425 err
= got_error_from_errno("fclose");
4429 struct revert_file_args
{
4430 struct got_worktree
*worktree
;
4431 struct got_fileindex
*fileindex
;
4432 got_worktree_checkout_cb progress_cb
;
4434 got_worktree_patch_cb patch_cb
;
4436 struct got_repository
*repo
;
4437 int unlink_added_files
;
4440 static const struct got_error
*
4441 create_patched_content(char **path_outfile
, int reverse_patch
,
4442 struct got_object_id
*blob_id
, const char *path2
,
4443 int dirfd2
, const char *de_name2
,
4444 const char *relpath
, struct got_repository
*repo
,
4445 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4447 const struct got_error
*err
, *free_err
;
4448 struct got_blob_object
*blob
= NULL
;
4449 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
;
4450 int fd
= -1, fd2
= -1;
4451 char link_target
[PATH_MAX
];
4452 ssize_t link_len
= 0;
4453 char *path1
= NULL
, *id_str
= NULL
;
4455 struct got_diffreg_result
*diffreg_result
= NULL
;
4456 int line_cur1
= 1, line_cur2
= 1, have_content
= 0;
4457 int i
= 0, n
= 0, nchunks_used
= 0, nchanges
= 0;
4459 *path_outfile
= NULL
;
4461 err
= got_object_id_str(&id_str
, blob_id
);
4466 fd2
= openat(dirfd2
, de_name2
,
4467 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
4469 if (!got_err_open_nofollow_on_symlink()) {
4470 err
= got_error_from_errno2("openat", path2
);
4473 link_len
= readlinkat(dirfd2
, de_name2
,
4474 link_target
, sizeof(link_target
));
4475 if (link_len
== -1) {
4476 return got_error_from_errno2("readlinkat",
4479 sb2
.st_mode
= S_IFLNK
;
4480 sb2
.st_size
= link_len
;
4483 fd2
= open(path2
, O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
4485 if (!got_err_open_nofollow_on_symlink()) {
4486 err
= got_error_from_errno2("open", path2
);
4489 link_len
= readlink(path2
, link_target
,
4490 sizeof(link_target
));
4492 return got_error_from_errno2("readlink", path2
);
4493 sb2
.st_mode
= S_IFLNK
;
4494 sb2
.st_size
= link_len
;
4498 if (fstat(fd2
, &sb2
) == -1) {
4499 err
= got_error_from_errno2("fstat", path2
);
4503 f2
= fdopen(fd2
, "r");
4505 err
= got_error_from_errno2("fdopen", path2
);
4511 f2
= got_opentemp();
4513 err
= got_error_from_errno2("got_opentemp", path2
);
4516 n
= fwrite(link_target
, 1, link_len
, f2
);
4517 if (n
!= link_len
) {
4518 err
= got_ferror(f2
, GOT_ERR_IO
);
4521 if (fflush(f2
) == EOF
) {
4522 err
= got_error_from_errno("fflush");
4528 fd
= got_opentempfd();
4530 err
= got_error_from_errno("got_opentempfd");
4534 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192, fd
);
4538 err
= got_opentemp_named(&path1
, &f1
, "got-patched-blob");
4542 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
4546 err
= got_diff_files(&diffreg_result
, f1
, 1, id_str
, f2
, 1, path2
,
4547 3, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
4551 err
= got_opentemp_named(path_outfile
, &outfile
, "got-patched-content");
4555 if (fseek(f1
, 0L, SEEK_SET
) == -1)
4556 return got_ferror(f1
, GOT_ERR_IO
);
4557 if (fseek(f2
, 0L, SEEK_SET
) == -1)
4558 return got_ferror(f2
, GOT_ERR_IO
);
4560 /* Count the number of actual changes in the diff result. */
4561 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4562 struct diff_chunk_context cc
= {};
4563 diff_chunk_context_load_change(&cc
, &nchunks_used
,
4564 diffreg_result
->result
, n
, 0);
4567 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4569 err
= apply_or_reject_change(&choice
, &nchunks_used
,
4570 diffreg_result
->result
, n
, relpath
, f1
, f2
,
4571 &line_cur1
, &line_cur2
,
4572 reverse_patch
? NULL
: outfile
,
4573 reverse_patch
? outfile
: NULL
,
4574 ++i
, nchanges
, patch_cb
, patch_arg
);
4577 if (choice
== GOT_PATCH_CHOICE_YES
)
4579 else if (choice
== GOT_PATCH_CHOICE_QUIT
)
4583 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
4584 reverse_patch
? NULL
: outfile
,
4585 reverse_patch
? outfile
: NULL
);
4589 if (!S_ISLNK(sb2
.st_mode
)) {
4590 if (fchmod(fileno(outfile
), sb2
.st_mode
) == -1) {
4591 err
= got_error_from_errno2("fchmod", path2
);
4598 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
4599 err
= got_error_from_errno("close");
4601 got_object_blob_close(blob
);
4602 free_err
= got_diffreg_result_free(diffreg_result
);
4605 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
4606 err
= got_error_from_errno2("fclose", path1
);
4607 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
4608 err
= got_error_from_errno2("fclose", path2
);
4609 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
4610 err
= got_error_from_errno2("close", path2
);
4611 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
4612 err
= got_error_from_errno2("fclose", *path_outfile
);
4613 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
4614 err
= got_error_from_errno2("unlink", path1
);
4615 if (err
|| !have_content
) {
4616 if (*path_outfile
&& unlink(*path_outfile
) == -1 && err
== NULL
)
4617 err
= got_error_from_errno2("unlink", *path_outfile
);
4618 free(*path_outfile
);
4619 *path_outfile
= NULL
;
4625 static const struct got_error
*
4626 revert_file(void *arg
, unsigned char status
, unsigned char staged_status
,
4627 const char *relpath
, struct got_object_id
*blob_id
,
4628 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
4629 int dirfd
, const char *de_name
)
4631 struct revert_file_args
*a
= arg
;
4632 const struct got_error
*err
= NULL
;
4633 char *parent_path
= NULL
;
4634 struct got_fileindex_entry
*ie
;
4635 struct got_commit_object
*base_commit
= NULL
;
4636 struct got_tree_object
*tree
= NULL
;
4637 struct got_object_id
*tree_id
= NULL
;
4638 const struct got_tree_entry
*te
= NULL
;
4639 char *tree_path
= NULL
, *te_name
;
4640 char *ondisk_path
= NULL
, *path_content
= NULL
;
4641 struct got_blob_object
*blob
= NULL
;
4644 /* Reverting a staged deletion is a no-op. */
4645 if (status
== GOT_STATUS_DELETE
&&
4646 staged_status
!= GOT_STATUS_NO_CHANGE
)
4649 if (status
== GOT_STATUS_UNVERSIONED
)
4650 return (*a
->progress_cb
)(a
->progress_arg
,
4651 GOT_STATUS_UNVERSIONED
, relpath
);
4653 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4655 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
4657 /* Construct in-repository path of tree which contains this blob. */
4658 err
= got_path_dirname(&parent_path
, ie
->path
);
4660 if (err
->code
!= GOT_ERR_BAD_PATH
)
4662 parent_path
= strdup("/");
4663 if (parent_path
== NULL
) {
4664 err
= got_error_from_errno("strdup");
4668 if (got_path_is_root_dir(a
->worktree
->path_prefix
)) {
4669 tree_path
= strdup(parent_path
);
4670 if (tree_path
== NULL
) {
4671 err
= got_error_from_errno("strdup");
4675 if (got_path_is_root_dir(parent_path
)) {
4676 tree_path
= strdup(a
->worktree
->path_prefix
);
4677 if (tree_path
== NULL
) {
4678 err
= got_error_from_errno("strdup");
4682 if (asprintf(&tree_path
, "%s/%s",
4683 a
->worktree
->path_prefix
, parent_path
) == -1) {
4684 err
= got_error_from_errno("asprintf");
4690 err
= got_object_open_as_commit(&base_commit
, a
->repo
,
4691 a
->worktree
->base_commit_id
);
4695 err
= got_object_id_by_path(&tree_id
, a
->repo
, base_commit
, tree_path
);
4697 if (!(err
->code
== GOT_ERR_NO_TREE_ENTRY
&&
4698 (status
== GOT_STATUS_ADD
||
4699 staged_status
== GOT_STATUS_ADD
)))
4702 err
= got_object_open_as_tree(&tree
, a
->repo
, tree_id
);
4706 err
= got_path_basename(&te_name
, ie
->path
);
4710 te
= got_object_tree_find_entry(tree
, te_name
);
4712 if (te
== NULL
&& status
!= GOT_STATUS_ADD
&&
4713 staged_status
!= GOT_STATUS_ADD
) {
4714 err
= got_error_path(ie
->path
, GOT_ERR_NO_TREE_ENTRY
);
4720 case GOT_STATUS_ADD
:
4722 int choice
= GOT_PATCH_CHOICE_NONE
;
4723 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4724 status
, ie
->path
, NULL
, 1, 1);
4727 if (choice
!= GOT_PATCH_CHOICE_YES
)
4730 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_REVERT
,
4734 got_fileindex_entry_remove(a
->fileindex
, ie
);
4735 if (a
->unlink_added_files
) {
4736 if (asprintf(&ondisk_path
, "%s/%s",
4737 got_worktree_get_root_path(a
->worktree
),
4739 err
= got_error_from_errno("asprintf");
4742 if (unlink(ondisk_path
) == -1) {
4743 err
= got_error_from_errno2("unlink",
4749 case GOT_STATUS_DELETE
:
4751 int choice
= GOT_PATCH_CHOICE_NONE
;
4752 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4753 status
, ie
->path
, NULL
, 1, 1);
4756 if (choice
!= GOT_PATCH_CHOICE_YES
)
4760 case GOT_STATUS_MODIFY
:
4761 case GOT_STATUS_MODE_CHANGE
:
4762 case GOT_STATUS_CONFLICT
:
4763 case GOT_STATUS_MISSING
: {
4764 struct got_object_id id
;
4765 if (staged_status
== GOT_STATUS_ADD
||
4766 staged_status
== GOT_STATUS_MODIFY
) {
4767 memcpy(id
.sha1
, ie
->staged_blob_sha1
,
4768 SHA1_DIGEST_LENGTH
);
4770 memcpy(id
.sha1
, ie
->blob_sha1
,
4771 SHA1_DIGEST_LENGTH
);
4772 fd
= got_opentempfd();
4774 err
= got_error_from_errno("got_opentempfd");
4778 err
= got_object_open_as_blob(&blob
, a
->repo
, &id
, 8192, fd
);
4782 if (asprintf(&ondisk_path
, "%s/%s",
4783 got_worktree_get_root_path(a
->worktree
), relpath
) == -1) {
4784 err
= got_error_from_errno("asprintf");
4788 if (a
->patch_cb
&& (status
== GOT_STATUS_MODIFY
||
4789 status
== GOT_STATUS_CONFLICT
)) {
4790 int is_bad_symlink
= 0;
4791 err
= create_patched_content(&path_content
, 1, &id
,
4792 ondisk_path
, dirfd
, de_name
, ie
->path
, a
->repo
,
4793 a
->patch_cb
, a
->patch_arg
);
4794 if (err
|| path_content
== NULL
)
4796 if (te
&& S_ISLNK(te
->mode
)) {
4797 if (unlink(path_content
) == -1) {
4798 err
= got_error_from_errno2("unlink",
4802 err
= install_symlink(&is_bad_symlink
,
4803 a
->worktree
, ondisk_path
, ie
->path
,
4804 blob
, 0, 1, 0, 0, a
->repo
,
4805 a
->progress_cb
, a
->progress_arg
);
4807 if (rename(path_content
, ondisk_path
) == -1) {
4808 err
= got_error_from_errno3("rename",
4809 path_content
, ondisk_path
);
4814 int is_bad_symlink
= 0;
4815 if (te
&& S_ISLNK(te
->mode
)) {
4816 err
= install_symlink(&is_bad_symlink
,
4817 a
->worktree
, ondisk_path
, ie
->path
,
4818 blob
, 0, 1, 0, 0, a
->repo
,
4819 a
->progress_cb
, a
->progress_arg
);
4821 err
= install_blob(a
->worktree
, ondisk_path
,
4823 te
? te
->mode
: GOT_DEFAULT_FILE_MODE
,
4824 got_fileindex_perms_to_st(ie
), blob
,
4825 0, 1, 0, 0, a
->repo
,
4826 a
->progress_cb
, a
->progress_arg
);
4830 if (status
== GOT_STATUS_DELETE
||
4831 status
== GOT_STATUS_MODE_CHANGE
) {
4832 err
= got_fileindex_entry_update(ie
,
4833 a
->worktree
->root_fd
, relpath
,
4835 a
->worktree
->base_commit_id
->sha1
, 1);
4839 if (is_bad_symlink
) {
4840 got_fileindex_entry_filetype_set(ie
,
4841 GOT_FILEIDX_MODE_BAD_SYMLINK
);
4854 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
4855 err
= got_error_from_errno("close");
4857 got_object_blob_close(blob
);
4859 got_object_tree_close(tree
);
4862 got_object_commit_close(base_commit
);
4866 const struct got_error
*
4867 got_worktree_revert(struct got_worktree
*worktree
,
4868 struct got_pathlist_head
*paths
,
4869 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4870 got_worktree_patch_cb patch_cb
, void *patch_arg
,
4871 struct got_repository
*repo
)
4873 struct got_fileindex
*fileindex
= NULL
;
4874 char *fileindex_path
= NULL
;
4875 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
4876 const struct got_error
*sync_err
= NULL
;
4877 struct got_pathlist_entry
*pe
;
4878 struct revert_file_args rfa
;
4880 err
= lock_worktree(worktree
, LOCK_EX
);
4884 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4888 rfa
.worktree
= worktree
;
4889 rfa
.fileindex
= fileindex
;
4890 rfa
.progress_cb
= progress_cb
;
4891 rfa
.progress_arg
= progress_arg
;
4892 rfa
.patch_cb
= patch_cb
;
4893 rfa
.patch_arg
= patch_arg
;
4895 rfa
.unlink_added_files
= 0;
4896 TAILQ_FOREACH(pe
, paths
, entry
) {
4897 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4898 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
4902 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4903 if (sync_err
&& err
== NULL
)
4906 free(fileindex_path
);
4908 got_fileindex_free(fileindex
);
4909 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4910 if (unlockerr
&& err
== NULL
)
4916 free_commitable(struct got_commitable
*ct
)
4919 free(ct
->in_repo_path
);
4920 free(ct
->ondisk_path
);
4922 free(ct
->base_blob_id
);
4923 free(ct
->staged_blob_id
);
4924 free(ct
->base_commit_id
);
4928 struct collect_commitables_arg
{
4929 struct got_pathlist_head
*commitable_paths
;
4930 struct got_repository
*repo
;
4931 struct got_worktree
*worktree
;
4932 struct got_fileindex
*fileindex
;
4933 int have_staged_files
;
4934 int allow_bad_symlinks
;
4937 static const struct got_error
*
4938 collect_commitables(void *arg
, unsigned char status
,
4939 unsigned char staged_status
, const char *relpath
,
4940 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4941 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4943 struct collect_commitables_arg
*a
= arg
;
4944 const struct got_error
*err
= NULL
;
4945 struct got_commitable
*ct
= NULL
;
4946 struct got_pathlist_entry
*new = NULL
;
4947 char *parent_path
= NULL
, *path
= NULL
;
4950 if (a
->have_staged_files
) {
4951 if (staged_status
!= GOT_STATUS_MODIFY
&&
4952 staged_status
!= GOT_STATUS_ADD
&&
4953 staged_status
!= GOT_STATUS_DELETE
)
4956 if (status
== GOT_STATUS_CONFLICT
)
4957 return got_error(GOT_ERR_COMMIT_CONFLICT
);
4959 if (status
!= GOT_STATUS_MODIFY
&&
4960 status
!= GOT_STATUS_MODE_CHANGE
&&
4961 status
!= GOT_STATUS_ADD
&&
4962 status
!= GOT_STATUS_DELETE
)
4966 if (asprintf(&path
, "/%s", relpath
) == -1) {
4967 err
= got_error_from_errno("asprintf");
4970 if (strcmp(path
, "/") == 0) {
4971 parent_path
= strdup("");
4972 if (parent_path
== NULL
)
4973 return got_error_from_errno("strdup");
4975 err
= got_path_dirname(&parent_path
, path
);
4980 ct
= calloc(1, sizeof(*ct
));
4982 err
= got_error_from_errno("calloc");
4986 if (asprintf(&ct
->ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4988 err
= got_error_from_errno("asprintf");
4992 if (staged_status
== GOT_STATUS_ADD
||
4993 staged_status
== GOT_STATUS_MODIFY
) {
4994 struct got_fileindex_entry
*ie
;
4995 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
4996 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
4997 case GOT_FILEIDX_MODE_REGULAR_FILE
:
4998 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
5001 case GOT_FILEIDX_MODE_SYMLINK
:
5005 err
= got_error_path(path
, GOT_ERR_BAD_FILETYPE
);
5008 ct
->mode
|= got_fileindex_entry_perms_get(ie
);
5009 } else if (status
!= GOT_STATUS_DELETE
&&
5010 staged_status
!= GOT_STATUS_DELETE
) {
5012 if (fstatat(dirfd
, de_name
, &sb
,
5013 AT_SYMLINK_NOFOLLOW
) == -1) {
5014 err
= got_error_from_errno2("fstatat",
5018 } else if (lstat(ct
->ondisk_path
, &sb
) == -1) {
5019 err
= got_error_from_errno2("lstat", ct
->ondisk_path
);
5022 ct
->mode
= sb
.st_mode
;
5025 if (asprintf(&ct
->in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
5026 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
5028 err
= got_error_from_errno("asprintf");
5032 if (S_ISLNK(ct
->mode
) && staged_status
== GOT_STATUS_NO_CHANGE
&&
5033 status
== GOT_STATUS_ADD
&& !a
->allow_bad_symlinks
) {
5035 char target_path
[PATH_MAX
];
5037 target_len
= readlink(ct
->ondisk_path
, target_path
,
5038 sizeof(target_path
));
5039 if (target_len
== -1) {
5040 err
= got_error_from_errno2("readlink",
5044 err
= is_bad_symlink_target(&is_bad_symlink
, target_path
,
5045 target_len
, ct
->ondisk_path
, a
->worktree
->root_path
);
5048 if (is_bad_symlink
) {
5049 err
= got_error_path(ct
->ondisk_path
,
5050 GOT_ERR_BAD_SYMLINK
);
5056 ct
->status
= status
;
5057 ct
->staged_status
= staged_status
;
5058 ct
->blob_id
= NULL
; /* will be filled in when blob gets created */
5059 if (ct
->status
!= GOT_STATUS_ADD
&&
5060 ct
->staged_status
!= GOT_STATUS_ADD
) {
5061 ct
->base_blob_id
= got_object_id_dup(blob_id
);
5062 if (ct
->base_blob_id
== NULL
) {
5063 err
= got_error_from_errno("got_object_id_dup");
5066 ct
->base_commit_id
= got_object_id_dup(commit_id
);
5067 if (ct
->base_commit_id
== NULL
) {
5068 err
= got_error_from_errno("got_object_id_dup");
5072 if (ct
->staged_status
== GOT_STATUS_ADD
||
5073 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5074 ct
->staged_blob_id
= got_object_id_dup(staged_blob_id
);
5075 if (ct
->staged_blob_id
== NULL
) {
5076 err
= got_error_from_errno("got_object_id_dup");
5080 ct
->path
= strdup(path
);
5081 if (ct
->path
== NULL
) {
5082 err
= got_error_from_errno("strdup");
5085 err
= got_pathlist_insert(&new, a
->commitable_paths
, ct
->path
, ct
);
5087 if (ct
&& (err
|| new == NULL
))
5088 free_commitable(ct
);
5094 static const struct got_error
*write_tree(struct got_object_id
**, int *,
5095 struct got_tree_object
*, const char *, struct got_pathlist_head
*,
5096 got_worktree_status_cb status_cb
, void *status_arg
,
5097 struct got_repository
*);
5099 static const struct got_error
*
5100 write_subtree(struct got_object_id
**new_subtree_id
, int *nentries
,
5101 struct got_tree_entry
*te
, const char *parent_path
,
5102 struct got_pathlist_head
*commitable_paths
,
5103 got_worktree_status_cb status_cb
, void *status_arg
,
5104 struct got_repository
*repo
)
5106 const struct got_error
*err
= NULL
;
5107 struct got_tree_object
*subtree
;
5110 if (asprintf(&subpath
, "%s%s%s", parent_path
,
5111 got_path_is_root_dir(parent_path
) ? "" : "/", te
->name
) == -1)
5112 return got_error_from_errno("asprintf");
5114 err
= got_object_open_as_tree(&subtree
, repo
, &te
->id
);
5118 err
= write_tree(new_subtree_id
, nentries
, subtree
, subpath
,
5119 commitable_paths
, status_cb
, status_arg
, repo
);
5120 got_object_tree_close(subtree
);
5125 static const struct got_error
*
5126 match_ct_parent_path(int *match
, struct got_commitable
*ct
, const char *path
)
5128 const struct got_error
*err
= NULL
;
5129 char *ct_parent_path
= NULL
;
5133 if (strchr(ct
->in_repo_path
, '/') == NULL
) {
5134 *match
= got_path_is_root_dir(path
);
5138 err
= got_path_dirname(&ct_parent_path
, ct
->in_repo_path
);
5141 *match
= (strcmp(path
, ct_parent_path
) == 0);
5142 free(ct_parent_path
);
5147 get_ct_file_mode(struct got_commitable
*ct
)
5149 if (S_ISLNK(ct
->mode
))
5152 return S_IFREG
| (ct
->mode
& ((S_IRWXU
| S_IRWXG
| S_IRWXO
)));
5155 static const struct got_error
*
5156 alloc_modified_blob_tree_entry(struct got_tree_entry
**new_te
,
5157 struct got_tree_entry
*te
, struct got_commitable
*ct
)
5159 const struct got_error
*err
= NULL
;
5163 err
= got_object_tree_entry_dup(new_te
, te
);
5167 (*new_te
)->mode
= get_ct_file_mode(ct
);
5169 if (ct
->staged_status
== GOT_STATUS_MODIFY
)
5170 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5171 sizeof((*new_te
)->id
));
5173 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5175 if (err
&& *new_te
) {
5182 static const struct got_error
*
5183 alloc_added_blob_tree_entry(struct got_tree_entry
**new_te
,
5184 struct got_commitable
*ct
)
5186 const struct got_error
*err
= NULL
;
5187 char *ct_name
= NULL
;
5191 *new_te
= calloc(1, sizeof(**new_te
));
5192 if (*new_te
== NULL
)
5193 return got_error_from_errno("calloc");
5195 err
= got_path_basename(&ct_name
, ct
->path
);
5198 if (strlcpy((*new_te
)->name
, ct_name
, sizeof((*new_te
)->name
)) >=
5199 sizeof((*new_te
)->name
)) {
5200 err
= got_error(GOT_ERR_NO_SPACE
);
5204 (*new_te
)->mode
= get_ct_file_mode(ct
);
5206 if (ct
->staged_status
== GOT_STATUS_ADD
)
5207 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5208 sizeof((*new_te
)->id
));
5210 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5213 if (err
&& *new_te
) {
5220 static const struct got_error
*
5221 insert_tree_entry(struct got_tree_entry
*new_te
,
5222 struct got_pathlist_head
*paths
)
5224 const struct got_error
*err
= NULL
;
5225 struct got_pathlist_entry
*new_pe
;
5227 err
= got_pathlist_insert(&new_pe
, paths
, new_te
->name
, new_te
);
5231 return got_error(GOT_ERR_TREE_DUP_ENTRY
);
5235 static const struct got_error
*
5236 report_ct_status(struct got_commitable
*ct
,
5237 got_worktree_status_cb status_cb
, void *status_arg
)
5239 const char *ct_path
= ct
->path
;
5240 unsigned char status
;
5242 if (status_cb
== NULL
) /* no commit progress output desired */
5245 while (ct_path
[0] == '/')
5248 if (ct
->staged_status
!= GOT_STATUS_NO_CHANGE
)
5249 status
= ct
->staged_status
;
5251 status
= ct
->status
;
5253 return (*status_cb
)(status_arg
, status
, GOT_STATUS_NO_CHANGE
,
5254 ct_path
, ct
->blob_id
, NULL
, NULL
, -1, NULL
);
5257 static const struct got_error
*
5258 match_modified_subtree(int *modified
, struct got_tree_entry
*te
,
5259 const char *base_tree_path
, struct got_pathlist_head
*commitable_paths
)
5261 const struct got_error
*err
= NULL
;
5262 struct got_pathlist_entry
*pe
;
5267 if (asprintf(&te_path
, "%s%s%s", base_tree_path
,
5268 got_path_is_root_dir(base_tree_path
) ? "" : "/",
5270 return got_error_from_errno("asprintf");
5272 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5273 struct got_commitable
*ct
= pe
->data
;
5274 *modified
= got_path_is_child(ct
->in_repo_path
, te_path
,
5284 static const struct got_error
*
5285 match_deleted_or_modified_ct(struct got_commitable
**ctp
,
5286 struct got_tree_entry
*te
, const char *base_tree_path
,
5287 struct got_pathlist_head
*commitable_paths
)
5289 const struct got_error
*err
= NULL
;
5290 struct got_pathlist_entry
*pe
;
5294 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5295 struct got_commitable
*ct
= pe
->data
;
5296 char *ct_name
= NULL
;
5299 if (ct
->staged_status
== GOT_STATUS_NO_CHANGE
) {
5300 if (ct
->status
!= GOT_STATUS_MODIFY
&&
5301 ct
->status
!= GOT_STATUS_MODE_CHANGE
&&
5302 ct
->status
!= GOT_STATUS_DELETE
)
5305 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
5306 ct
->staged_status
!= GOT_STATUS_DELETE
)
5310 if (got_object_id_cmp(ct
->base_blob_id
, &te
->id
) != 0)
5313 err
= match_ct_parent_path(&path_matches
, ct
, base_tree_path
);
5319 err
= got_path_basename(&ct_name
, pe
->path
);
5323 if (strcmp(te
->name
, ct_name
) != 0) {
5336 static const struct got_error
*
5337 make_subtree_for_added_blob(struct got_tree_entry
**new_tep
,
5338 const char *child_path
, const char *path_base_tree
,
5339 struct got_pathlist_head
*commitable_paths
,
5340 got_worktree_status_cb status_cb
, void *status_arg
,
5341 struct got_repository
*repo
)
5343 const struct got_error
*err
= NULL
;
5344 struct got_tree_entry
*new_te
;
5346 struct got_object_id
*id
= NULL
;
5351 if (asprintf(&subtree_path
, "%s%s%s", path_base_tree
,
5352 got_path_is_root_dir(path_base_tree
) ? "" : "/",
5354 return got_error_from_errno("asprintf");
5356 new_te
= calloc(1, sizeof(*new_te
));
5358 return got_error_from_errno("calloc");
5359 new_te
->mode
= S_IFDIR
;
5361 if (strlcpy(new_te
->name
, child_path
, sizeof(new_te
->name
)) >=
5362 sizeof(new_te
->name
)) {
5363 err
= got_error(GOT_ERR_NO_SPACE
);
5366 err
= write_tree(&id
, &nentries
, NULL
, subtree_path
,
5367 commitable_paths
, status_cb
, status_arg
, repo
);
5372 memcpy(&new_te
->id
, id
, sizeof(new_te
->id
));
5381 static const struct got_error
*
5382 write_tree(struct got_object_id
**new_tree_id
, int *nentries
,
5383 struct got_tree_object
*base_tree
, const char *path_base_tree
,
5384 struct got_pathlist_head
*commitable_paths
,
5385 got_worktree_status_cb status_cb
, void *status_arg
,
5386 struct got_repository
*repo
)
5388 const struct got_error
*err
= NULL
;
5389 struct got_pathlist_head paths
;
5390 struct got_tree_entry
*te
, *new_te
= NULL
;
5391 struct got_pathlist_entry
*pe
;
5396 /* Insert, and recurse into, newly added entries first. */
5397 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5398 struct got_commitable
*ct
= pe
->data
;
5399 char *child_path
= NULL
, *slash
;
5401 if ((ct
->status
!= GOT_STATUS_ADD
&&
5402 ct
->staged_status
!= GOT_STATUS_ADD
) ||
5403 (ct
->flags
& GOT_COMMITABLE_ADDED
))
5406 if (!got_path_is_child(ct
->in_repo_path
, path_base_tree
,
5407 strlen(path_base_tree
)))
5410 err
= got_path_skip_common_ancestor(&child_path
, path_base_tree
,
5415 slash
= strchr(child_path
, '/');
5416 if (slash
== NULL
) {
5417 err
= alloc_added_blob_tree_entry(&new_te
, ct
);
5420 err
= report_ct_status(ct
, status_cb
, status_arg
);
5423 ct
->flags
|= GOT_COMMITABLE_ADDED
;
5424 err
= insert_tree_entry(new_te
, &paths
);
5429 *slash
= '\0'; /* trim trailing path components */
5430 if (base_tree
== NULL
||
5431 got_object_tree_find_entry(base_tree
, child_path
)
5433 err
= make_subtree_for_added_blob(&new_te
,
5434 child_path
, path_base_tree
,
5435 commitable_paths
, status_cb
, status_arg
,
5439 err
= insert_tree_entry(new_te
, &paths
);
5448 int i
, nbase_entries
;
5449 /* Handle modified and deleted entries. */
5450 nbase_entries
= got_object_tree_get_nentries(base_tree
);
5451 for (i
= 0; i
< nbase_entries
; i
++) {
5452 struct got_commitable
*ct
= NULL
;
5454 te
= got_object_tree_get_entry(base_tree
, i
);
5455 if (got_object_tree_entry_is_submodule(te
)) {
5456 /* Entry is a submodule; just copy it. */
5457 err
= got_object_tree_entry_dup(&new_te
, te
);
5460 err
= insert_tree_entry(new_te
, &paths
);
5467 if (S_ISDIR(te
->mode
)) {
5469 err
= got_object_tree_entry_dup(&new_te
, te
);
5472 err
= match_modified_subtree(&modified
, te
,
5473 path_base_tree
, commitable_paths
);
5476 /* Avoid recursion into unmodified subtrees. */
5478 struct got_object_id
*new_id
;
5480 err
= write_subtree(&new_id
,
5482 path_base_tree
, commitable_paths
,
5483 status_cb
, status_arg
, repo
);
5486 if (nsubentries
== 0) {
5487 /* All entries were deleted. */
5491 memcpy(&new_te
->id
, new_id
,
5492 sizeof(new_te
->id
));
5495 err
= insert_tree_entry(new_te
, &paths
);
5502 err
= match_deleted_or_modified_ct(&ct
, te
,
5503 path_base_tree
, commitable_paths
);
5507 /* NB: Deleted entries get dropped here. */
5508 if (ct
->status
== GOT_STATUS_MODIFY
||
5509 ct
->status
== GOT_STATUS_MODE_CHANGE
||
5510 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5511 err
= alloc_modified_blob_tree_entry(
5515 err
= insert_tree_entry(new_te
, &paths
);
5520 err
= report_ct_status(ct
, status_cb
,
5525 /* Entry is unchanged; just copy it. */
5526 err
= got_object_tree_entry_dup(&new_te
, te
);
5529 err
= insert_tree_entry(new_te
, &paths
);
5537 /* Write new list of entries; deleted entries have been dropped. */
5538 err
= got_object_tree_create(new_tree_id
, &paths
, *nentries
, repo
);
5540 got_pathlist_free(&paths
);
5544 static const struct got_error
*
5545 update_fileindex_after_commit(struct got_worktree
*worktree
,
5546 struct got_pathlist_head
*commitable_paths
,
5547 struct got_object_id
*new_base_commit_id
,
5548 struct got_fileindex
*fileindex
, int have_staged_files
)
5550 const struct got_error
*err
= NULL
;
5551 struct got_pathlist_entry
*pe
;
5552 char *relpath
= NULL
;
5554 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5555 struct got_fileindex_entry
*ie
;
5556 struct got_commitable
*ct
= pe
->data
;
5558 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
5560 err
= got_path_skip_common_ancestor(&relpath
,
5561 worktree
->root_path
, ct
->ondisk_path
);
5566 if (ct
->status
== GOT_STATUS_DELETE
||
5567 ct
->staged_status
== GOT_STATUS_DELETE
) {
5568 got_fileindex_entry_remove(fileindex
, ie
);
5569 } else if (ct
->staged_status
== GOT_STATUS_ADD
||
5570 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5571 got_fileindex_entry_stage_set(ie
,
5572 GOT_FILEIDX_STAGE_NONE
);
5573 got_fileindex_entry_staged_filetype_set(ie
, 0);
5575 err
= got_fileindex_entry_update(ie
,
5576 worktree
->root_fd
, relpath
,
5577 ct
->staged_blob_id
->sha1
,
5578 new_base_commit_id
->sha1
,
5579 !have_staged_files
);
5581 err
= got_fileindex_entry_update(ie
,
5582 worktree
->root_fd
, relpath
,
5584 new_base_commit_id
->sha1
,
5585 !have_staged_files
);
5587 err
= got_fileindex_entry_alloc(&ie
, pe
->path
);
5590 err
= got_fileindex_entry_update(ie
,
5591 worktree
->root_fd
, relpath
, ct
->blob_id
->sha1
,
5592 new_base_commit_id
->sha1
, 1);
5594 got_fileindex_entry_free(ie
);
5597 err
= got_fileindex_entry_add(fileindex
, ie
);
5599 got_fileindex_entry_free(ie
);
5612 static const struct got_error
*
5613 check_out_of_date(const char *in_repo_path
, unsigned char status
,
5614 unsigned char staged_status
, struct got_object_id
*base_blob_id
,
5615 struct got_object_id
*base_commit_id
,
5616 struct got_object_id
*head_commit_id
, struct got_repository
*repo
,
5619 const struct got_error
*err
= NULL
;
5620 struct got_commit_object
*commit
= NULL
;
5621 struct got_object_id
*id
= NULL
;
5623 if (status
!= GOT_STATUS_ADD
&& staged_status
!= GOT_STATUS_ADD
) {
5624 /* Trivial case: base commit == head commit */
5625 if (got_object_id_cmp(base_commit_id
, head_commit_id
) == 0)
5628 * Ensure file content which local changes were based
5629 * on matches file content in the branch head.
5631 err
= got_object_open_as_commit(&commit
, repo
, head_commit_id
);
5634 err
= got_object_id_by_path(&id
, repo
, commit
, in_repo_path
);
5636 if (err
->code
== GOT_ERR_NO_TREE_ENTRY
)
5637 err
= got_error(ood_errcode
);
5639 } else if (got_object_id_cmp(id
, base_blob_id
) != 0)
5640 err
= got_error(ood_errcode
);
5642 /* Require that added files don't exist in the branch head. */
5643 err
= got_object_open_as_commit(&commit
, repo
, head_commit_id
);
5646 err
= got_object_id_by_path(&id
, repo
, commit
, in_repo_path
);
5647 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
5649 err
= id
? got_error(ood_errcode
) : NULL
;
5654 got_object_commit_close(commit
);
5658 static const struct got_error
*
5659 commit_worktree(struct got_object_id
**new_commit_id
,
5660 struct got_pathlist_head
*commitable_paths
,
5661 struct got_object_id
*head_commit_id
,
5662 struct got_object_id
*parent_id2
,
5663 struct got_worktree
*worktree
,
5664 const char *author
, const char *committer
,
5665 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
5666 got_worktree_status_cb status_cb
, void *status_arg
,
5667 struct got_repository
*repo
)
5669 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
5670 struct got_pathlist_entry
*pe
;
5671 const char *head_ref_name
= NULL
;
5672 struct got_commit_object
*head_commit
= NULL
;
5673 struct got_reference
*head_ref2
= NULL
;
5674 struct got_object_id
*head_commit_id2
= NULL
;
5675 struct got_tree_object
*head_tree
= NULL
;
5676 struct got_object_id
*new_tree_id
= NULL
;
5677 int nentries
, nparents
= 0;
5678 struct got_object_id_queue parent_ids
;
5679 struct got_object_qid
*pid
= NULL
;
5680 char *logmsg
= NULL
;
5682 *new_commit_id
= NULL
;
5684 STAILQ_INIT(&parent_ids
);
5686 err
= got_object_open_as_commit(&head_commit
, repo
, head_commit_id
);
5690 err
= got_object_open_as_tree(&head_tree
, repo
, head_commit
->tree_id
);
5694 if (commit_msg_cb
!= NULL
) {
5695 err
= commit_msg_cb(commitable_paths
, &logmsg
, commit_arg
);
5700 if (logmsg
== NULL
|| strlen(logmsg
) == 0) {
5701 err
= got_error(GOT_ERR_COMMIT_MSG_EMPTY
);
5705 /* Create blobs from added and modified files and record their IDs. */
5706 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5707 struct got_commitable
*ct
= pe
->data
;
5710 /* Blobs for staged files already exist. */
5711 if (ct
->staged_status
== GOT_STATUS_ADD
||
5712 ct
->staged_status
== GOT_STATUS_MODIFY
)
5715 if (ct
->status
!= GOT_STATUS_ADD
&&
5716 ct
->status
!= GOT_STATUS_MODIFY
&&
5717 ct
->status
!= GOT_STATUS_MODE_CHANGE
)
5720 if (asprintf(&ondisk_path
, "%s/%s",
5721 worktree
->root_path
, pe
->path
) == -1) {
5722 err
= got_error_from_errno("asprintf");
5725 err
= got_object_blob_create(&ct
->blob_id
, ondisk_path
, repo
);
5731 /* Recursively write new tree objects. */
5732 err
= write_tree(&new_tree_id
, &nentries
, head_tree
, "/",
5733 commitable_paths
, status_cb
, status_arg
, repo
);
5737 err
= got_object_qid_alloc(&pid
, worktree
->base_commit_id
);
5740 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
5743 err
= got_object_qid_alloc(&pid
, parent_id2
);
5746 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
5749 err
= got_object_commit_create(new_commit_id
, new_tree_id
, &parent_ids
,
5750 nparents
, author
, time(NULL
), committer
, time(NULL
), logmsg
, repo
);
5756 /* Check if a concurrent commit to our branch has occurred. */
5757 head_ref_name
= got_worktree_get_head_ref_name(worktree
);
5758 if (head_ref_name
== NULL
) {
5759 err
= got_error_from_errno("got_worktree_get_head_ref_name");
5762 /* Lock the reference here to prevent concurrent modification. */
5763 err
= got_ref_open(&head_ref2
, repo
, head_ref_name
, 1);
5766 err
= got_ref_resolve(&head_commit_id2
, repo
, head_ref2
);
5769 if (got_object_id_cmp(head_commit_id
, head_commit_id2
) != 0) {
5770 err
= got_error(GOT_ERR_COMMIT_HEAD_CHANGED
);
5773 /* Update branch head in repository. */
5774 err
= got_ref_change_ref(head_ref2
, *new_commit_id
);
5777 err
= got_ref_write(head_ref2
, repo
);
5781 err
= got_worktree_set_base_commit_id(worktree
, repo
, *new_commit_id
);
5785 err
= ref_base_commit(worktree
, repo
);
5789 got_object_id_queue_free(&parent_ids
);
5791 got_object_tree_close(head_tree
);
5793 got_object_commit_close(head_commit
);
5794 free(head_commit_id2
);
5796 unlockerr
= got_ref_unlock(head_ref2
);
5797 if (unlockerr
&& err
== NULL
)
5799 got_ref_close(head_ref2
);
5804 static const struct got_error
*
5805 check_path_is_commitable(const char *path
,
5806 struct got_pathlist_head
*commitable_paths
)
5808 struct got_pathlist_entry
*cpe
= NULL
;
5809 size_t path_len
= strlen(path
);
5811 TAILQ_FOREACH(cpe
, commitable_paths
, entry
) {
5812 struct got_commitable
*ct
= cpe
->data
;
5813 const char *ct_path
= ct
->path
;
5815 while (ct_path
[0] == '/')
5818 if (strcmp(path
, ct_path
) == 0 ||
5819 got_path_is_child(ct_path
, path
, path_len
))
5824 return got_error_path(path
, GOT_ERR_BAD_PATH
);
5829 static const struct got_error
*
5830 check_staged_file(void *arg
, struct got_fileindex_entry
*ie
)
5832 int *have_staged_files
= arg
;
5834 if (got_fileindex_entry_stage_get(ie
) != GOT_FILEIDX_STAGE_NONE
) {
5835 *have_staged_files
= 1;
5836 return got_error(GOT_ERR_CANCELLED
);
5842 static const struct got_error
*
5843 check_non_staged_files(struct got_fileindex
*fileindex
,
5844 struct got_pathlist_head
*paths
)
5846 struct got_pathlist_entry
*pe
;
5847 struct got_fileindex_entry
*ie
;
5849 TAILQ_FOREACH(pe
, paths
, entry
) {
5850 if (pe
->path
[0] == '\0')
5852 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
5854 return got_error_path(pe
->path
, GOT_ERR_BAD_PATH
);
5855 if (got_fileindex_entry_stage_get(ie
) == GOT_FILEIDX_STAGE_NONE
)
5856 return got_error_path(pe
->path
,
5857 GOT_ERR_FILE_NOT_STAGED
);
5863 const struct got_error
*
5864 got_worktree_commit(struct got_object_id
**new_commit_id
,
5865 struct got_worktree
*worktree
, struct got_pathlist_head
*paths
,
5866 const char *author
, const char *committer
, int allow_bad_symlinks
,
5867 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
5868 got_worktree_status_cb status_cb
, void *status_arg
,
5869 struct got_repository
*repo
)
5871 const struct got_error
*err
= NULL
, *unlockerr
= NULL
, *sync_err
;
5872 struct got_fileindex
*fileindex
= NULL
;
5873 char *fileindex_path
= NULL
;
5874 struct got_pathlist_head commitable_paths
;
5875 struct collect_commitables_arg cc_arg
;
5876 struct got_pathlist_entry
*pe
;
5877 struct got_reference
*head_ref
= NULL
;
5878 struct got_object_id
*head_commit_id
= NULL
;
5879 int have_staged_files
= 0;
5881 *new_commit_id
= NULL
;
5883 TAILQ_INIT(&commitable_paths
);
5885 err
= lock_worktree(worktree
, LOCK_EX
);
5889 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
5893 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
5897 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
5901 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
5902 &have_staged_files
);
5903 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
5905 if (have_staged_files
) {
5906 err
= check_non_staged_files(fileindex
, paths
);
5911 cc_arg
.commitable_paths
= &commitable_paths
;
5912 cc_arg
.worktree
= worktree
;
5913 cc_arg
.fileindex
= fileindex
;
5915 cc_arg
.have_staged_files
= have_staged_files
;
5916 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
5917 TAILQ_FOREACH(pe
, paths
, entry
) {
5918 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
5919 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
5924 if (TAILQ_EMPTY(&commitable_paths
)) {
5925 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
5929 TAILQ_FOREACH(pe
, paths
, entry
) {
5930 err
= check_path_is_commitable(pe
->path
, &commitable_paths
);
5935 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
5936 struct got_commitable
*ct
= pe
->data
;
5937 const char *ct_path
= ct
->in_repo_path
;
5939 while (ct_path
[0] == '/')
5941 err
= check_out_of_date(ct_path
, ct
->status
,
5942 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
5943 head_commit_id
, repo
, GOT_ERR_COMMIT_OUT_OF_DATE
);
5949 err
= commit_worktree(new_commit_id
, &commitable_paths
,
5950 head_commit_id
, NULL
, worktree
, author
, committer
,
5951 commit_msg_cb
, commit_arg
, status_cb
, status_arg
, repo
);
5955 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
5956 *new_commit_id
, fileindex
, have_staged_files
);
5957 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
5958 if (sync_err
&& err
== NULL
)
5962 got_fileindex_free(fileindex
);
5963 free(fileindex_path
);
5964 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
5965 if (unlockerr
&& err
== NULL
)
5967 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
5968 struct got_commitable
*ct
= pe
->data
;
5969 free_commitable(ct
);
5971 got_pathlist_free(&commitable_paths
);
5976 got_commitable_get_path(struct got_commitable
*ct
)
5982 got_commitable_get_status(struct got_commitable
*ct
)
5987 struct check_rebase_ok_arg
{
5988 struct got_worktree
*worktree
;
5989 struct got_repository
*repo
;
5992 static const struct got_error
*
5993 check_rebase_ok(void *arg
, struct got_fileindex_entry
*ie
)
5995 const struct got_error
*err
= NULL
;
5996 struct check_rebase_ok_arg
*a
= arg
;
5997 unsigned char status
;
6001 /* Reject rebase of a work tree with mixed base commits. */
6002 if (memcmp(ie
->commit_sha1
, a
->worktree
->base_commit_id
->sha1
,
6003 SHA1_DIGEST_LENGTH
))
6004 return got_error(GOT_ERR_MIXED_COMMITS
);
6006 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
6008 return got_error_from_errno("asprintf");
6010 /* Reject rebase of a work tree with modified or staged files. */
6011 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
6016 if (status
!= GOT_STATUS_NO_CHANGE
)
6017 return got_error(GOT_ERR_MODIFIED
);
6018 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
6019 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
6024 const struct got_error
*
6025 got_worktree_rebase_prepare(struct got_reference
**new_base_branch_ref
,
6026 struct got_reference
**tmp_branch
, struct got_fileindex
**fileindex
,
6027 struct got_worktree
*worktree
, struct got_reference
*branch
,
6028 struct got_repository
*repo
)
6030 const struct got_error
*err
= NULL
;
6031 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6032 char *branch_ref_name
= NULL
;
6033 char *fileindex_path
= NULL
;
6034 struct check_rebase_ok_arg ok_arg
;
6035 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
6036 struct got_object_id
*wt_branch_tip
= NULL
;
6038 *new_base_branch_ref
= NULL
;
6042 err
= lock_worktree(worktree
, LOCK_EX
);
6046 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6050 ok_arg
.worktree
= worktree
;
6052 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6057 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6061 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6065 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6069 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6074 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
6077 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
6078 err
= got_error(GOT_ERR_REBASE_OUT_OF_DATE
);
6082 err
= got_ref_alloc_symref(new_base_branch_ref
,
6083 new_base_branch_ref_name
, wt_branch
);
6086 err
= got_ref_write(*new_base_branch_ref
, repo
);
6090 /* TODO Lock original branch's ref while rebasing? */
6092 err
= got_ref_alloc_symref(&branch_ref
, branch_ref_name
, branch
);
6096 err
= got_ref_write(branch_ref
, repo
);
6100 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6101 worktree
->base_commit_id
);
6104 err
= got_ref_write(*tmp_branch
, repo
);
6108 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6112 free(fileindex_path
);
6113 free(tmp_branch_name
);
6114 free(new_base_branch_ref_name
);
6115 free(branch_ref_name
);
6117 got_ref_close(branch_ref
);
6119 got_ref_close(wt_branch
);
6120 free(wt_branch_tip
);
6122 if (*new_base_branch_ref
) {
6123 got_ref_close(*new_base_branch_ref
);
6124 *new_base_branch_ref
= NULL
;
6127 got_ref_close(*tmp_branch
);
6131 got_fileindex_free(*fileindex
);
6134 lock_worktree(worktree
, LOCK_SH
);
6139 const struct got_error
*
6140 got_worktree_rebase_continue(struct got_object_id
**commit_id
,
6141 struct got_reference
**new_base_branch
, struct got_reference
**tmp_branch
,
6142 struct got_reference
**branch
, struct got_fileindex
**fileindex
,
6143 struct got_worktree
*worktree
, struct got_repository
*repo
)
6145 const struct got_error
*err
;
6146 char *commit_ref_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6147 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
6148 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
6149 char *fileindex_path
= NULL
;
6150 int have_staged_files
= 0;
6153 *new_base_branch
= NULL
;
6158 err
= lock_worktree(worktree
, LOCK_EX
);
6162 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6166 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
6167 &have_staged_files
);
6168 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6170 if (have_staged_files
) {
6171 err
= got_error(GOT_ERR_STAGED_PATHS
);
6175 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6179 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6183 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6187 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6191 err
= got_ref_open(&branch_ref
, repo
, branch_ref_name
, 0);
6195 err
= got_ref_open(branch
, repo
,
6196 got_ref_get_symref_target(branch_ref
), 0);
6200 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6204 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
6208 err
= got_ref_open(new_base_branch
, repo
,
6209 new_base_branch_ref_name
, 0);
6213 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
6217 free(commit_ref_name
);
6218 free(branch_ref_name
);
6219 free(fileindex_path
);
6221 got_ref_close(commit_ref
);
6223 got_ref_close(branch_ref
);
6228 got_ref_close(*tmp_branch
);
6231 if (*new_base_branch
) {
6232 got_ref_close(*new_base_branch
);
6233 *new_base_branch
= NULL
;
6236 got_ref_close(*branch
);
6240 got_fileindex_free(*fileindex
);
6243 lock_worktree(worktree
, LOCK_SH
);
6248 const struct got_error
*
6249 got_worktree_rebase_in_progress(int *in_progress
, struct got_worktree
*worktree
)
6251 const struct got_error
*err
;
6252 char *tmp_branch_name
= NULL
;
6254 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6258 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
6259 free(tmp_branch_name
);
6263 static const struct got_error
*
6264 collect_rebase_commit_msg(struct got_pathlist_head
*commitable_paths
,
6265 char **logmsg
, void *arg
)
6271 static const struct got_error
*
6272 rebase_status(void *arg
, unsigned char status
, unsigned char staged_status
,
6273 const char *path
, struct got_object_id
*blob_id
,
6274 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
6275 int dirfd
, const char *de_name
)
6280 struct collect_merged_paths_arg
{
6281 got_worktree_checkout_cb progress_cb
;
6283 struct got_pathlist_head
*merged_paths
;
6286 static const struct got_error
*
6287 collect_merged_paths(void *arg
, unsigned char status
, const char *path
)
6289 const struct got_error
*err
;
6290 struct collect_merged_paths_arg
*a
= arg
;
6292 struct got_pathlist_entry
*new;
6294 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path
);
6298 if (status
!= GOT_STATUS_MERGE
&&
6299 status
!= GOT_STATUS_ADD
&&
6300 status
!= GOT_STATUS_DELETE
&&
6301 status
!= GOT_STATUS_CONFLICT
)
6306 return got_error_from_errno("strdup");
6308 err
= got_pathlist_insert(&new, a
->merged_paths
, p
, NULL
);
6309 if (err
|| new == NULL
)
6315 got_worktree_rebase_pathlist_free(struct got_pathlist_head
*merged_paths
)
6317 struct got_pathlist_entry
*pe
;
6319 TAILQ_FOREACH(pe
, merged_paths
, entry
)
6320 free((char *)pe
->path
);
6322 got_pathlist_free(merged_paths
);
6325 static const struct got_error
*
6326 store_commit_id(const char *commit_ref_name
, struct got_object_id
*commit_id
,
6327 int is_rebase
, struct got_repository
*repo
)
6329 const struct got_error
*err
;
6330 struct got_reference
*commit_ref
= NULL
;
6332 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6334 if (err
->code
!= GOT_ERR_NOT_REF
)
6336 err
= got_ref_alloc(&commit_ref
, commit_ref_name
, commit_id
);
6339 err
= got_ref_write(commit_ref
, repo
);
6342 } else if (is_rebase
) {
6343 struct got_object_id
*stored_id
;
6346 err
= got_ref_resolve(&stored_id
, repo
, commit_ref
);
6349 cmp
= got_object_id_cmp(commit_id
, stored_id
);
6352 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6358 got_ref_close(commit_ref
);
6362 static const struct got_error
*
6363 rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6364 const char *commit_ref_name
, struct got_worktree
*worktree
,
6365 struct got_fileindex
*fileindex
, struct got_object_id
*parent_commit_id
,
6366 struct got_object_id
*commit_id
, struct got_repository
*repo
,
6367 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6368 got_cancel_cb cancel_cb
, void *cancel_arg
)
6370 const struct got_error
*err
;
6371 struct got_reference
*commit_ref
= NULL
;
6372 struct collect_merged_paths_arg cmp_arg
;
6373 char *fileindex_path
;
6375 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6377 err
= get_fileindex_path(&fileindex_path
, worktree
);
6381 cmp_arg
.progress_cb
= progress_cb
;
6382 cmp_arg
.progress_arg
= progress_arg
;
6383 cmp_arg
.merged_paths
= merged_paths
;
6384 err
= merge_files(worktree
, fileindex
, fileindex_path
,
6385 parent_commit_id
, commit_id
, repo
, collect_merged_paths
,
6386 &cmp_arg
, cancel_cb
, cancel_arg
);
6388 got_ref_close(commit_ref
);
6392 const struct got_error
*
6393 got_worktree_rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6394 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6395 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
6396 struct got_repository
*repo
,
6397 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6398 got_cancel_cb cancel_cb
, void *cancel_arg
)
6400 const struct got_error
*err
;
6401 char *commit_ref_name
;
6403 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6407 err
= store_commit_id(commit_ref_name
, commit_id
, 1, repo
);
6411 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
6412 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
6413 progress_arg
, cancel_cb
, cancel_arg
);
6415 free(commit_ref_name
);
6419 const struct got_error
*
6420 got_worktree_histedit_merge_files(struct got_pathlist_head
*merged_paths
,
6421 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6422 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
6423 struct got_repository
*repo
,
6424 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6425 got_cancel_cb cancel_cb
, void *cancel_arg
)
6427 const struct got_error
*err
;
6428 char *commit_ref_name
;
6430 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6434 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
6438 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
6439 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
6440 progress_arg
, cancel_cb
, cancel_arg
);
6442 free(commit_ref_name
);
6446 static const struct got_error
*
6447 rebase_commit(struct got_object_id
**new_commit_id
,
6448 struct got_pathlist_head
*merged_paths
, struct got_reference
*commit_ref
,
6449 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6450 struct got_reference
*tmp_branch
, struct got_commit_object
*orig_commit
,
6451 const char *new_logmsg
, struct got_repository
*repo
)
6453 const struct got_error
*err
, *sync_err
;
6454 struct got_pathlist_head commitable_paths
;
6455 struct collect_commitables_arg cc_arg
;
6456 char *fileindex_path
= NULL
;
6457 struct got_reference
*head_ref
= NULL
;
6458 struct got_object_id
*head_commit_id
= NULL
;
6459 char *logmsg
= NULL
;
6461 TAILQ_INIT(&commitable_paths
);
6462 *new_commit_id
= NULL
;
6464 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6466 err
= get_fileindex_path(&fileindex_path
, worktree
);
6470 cc_arg
.commitable_paths
= &commitable_paths
;
6471 cc_arg
.worktree
= worktree
;
6473 cc_arg
.have_staged_files
= 0;
6475 * If possible get the status of individual files directly to
6476 * avoid crawling the entire work tree once per rebased commit.
6478 * Ideally, merged_paths would contain a list of commitables
6479 * we could use so we could skip worktree_status() entirely.
6480 * However, we would then need carefully keep track of cumulative
6481 * effects of operations such as file additions and deletions
6482 * in 'got histedit -f' (folding multiple commits into one),
6483 * and this extra complexity is not really worth it.
6486 struct got_pathlist_entry
*pe
;
6487 TAILQ_FOREACH(pe
, merged_paths
, entry
) {
6488 err
= worktree_status(worktree
, pe
->path
, fileindex
,
6489 repo
, collect_commitables
, &cc_arg
, NULL
, NULL
, 1,
6495 err
= worktree_status(worktree
, "", fileindex
, repo
,
6496 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
6501 if (TAILQ_EMPTY(&commitable_paths
)) {
6502 /* No-op change; commit will be elided. */
6503 err
= got_ref_delete(commit_ref
, repo
);
6506 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
6510 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
6514 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
6519 logmsg
= strdup(new_logmsg
);
6520 if (logmsg
== NULL
) {
6521 err
= got_error_from_errno("strdup");
6525 err
= got_object_commit_get_logmsg(&logmsg
, orig_commit
);
6530 /* NB: commit_worktree will call free(logmsg) */
6531 err
= commit_worktree(new_commit_id
, &commitable_paths
, head_commit_id
,
6532 NULL
, worktree
, got_object_commit_get_author(orig_commit
),
6533 got_object_commit_get_committer(orig_commit
),
6534 collect_rebase_commit_msg
, logmsg
, rebase_status
, NULL
, repo
);
6538 err
= got_ref_change_ref(tmp_branch
, *new_commit_id
);
6542 err
= got_ref_delete(commit_ref
, repo
);
6546 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
6547 *new_commit_id
, fileindex
, 0);
6548 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6549 if (sync_err
&& err
== NULL
)
6552 free(fileindex_path
);
6553 free(head_commit_id
);
6555 got_ref_close(head_ref
);
6557 free(*new_commit_id
);
6558 *new_commit_id
= NULL
;
6563 const struct got_error
*
6564 got_worktree_rebase_commit(struct got_object_id
**new_commit_id
,
6565 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6566 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6567 struct got_commit_object
*orig_commit
,
6568 struct got_object_id
*orig_commit_id
, struct got_repository
*repo
)
6570 const struct got_error
*err
;
6571 char *commit_ref_name
;
6572 struct got_reference
*commit_ref
= NULL
;
6573 struct got_object_id
*commit_id
= NULL
;
6575 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6579 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6582 err
= got_ref_resolve(&commit_id
, repo
, commit_ref
);
6585 if (got_object_id_cmp(commit_id
, orig_commit_id
) != 0) {
6586 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6590 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6591 worktree
, fileindex
, tmp_branch
, orig_commit
, NULL
, repo
);
6594 got_ref_close(commit_ref
);
6595 free(commit_ref_name
);
6600 const struct got_error
*
6601 got_worktree_histedit_commit(struct got_object_id
**new_commit_id
,
6602 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6603 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6604 struct got_commit_object
*orig_commit
,
6605 struct got_object_id
*orig_commit_id
, const char *new_logmsg
,
6606 struct got_repository
*repo
)
6608 const struct got_error
*err
;
6609 char *commit_ref_name
;
6610 struct got_reference
*commit_ref
= NULL
;
6612 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6616 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6620 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6621 worktree
, fileindex
, tmp_branch
, orig_commit
, new_logmsg
, repo
);
6624 got_ref_close(commit_ref
);
6625 free(commit_ref_name
);
6629 const struct got_error
*
6630 got_worktree_rebase_postpone(struct got_worktree
*worktree
,
6631 struct got_fileindex
*fileindex
)
6634 got_fileindex_free(fileindex
);
6635 return lock_worktree(worktree
, LOCK_SH
);
6638 static const struct got_error
*
6639 delete_ref(const char *name
, struct got_repository
*repo
)
6641 const struct got_error
*err
;
6642 struct got_reference
*ref
;
6644 err
= got_ref_open(&ref
, repo
, name
, 0);
6646 if (err
->code
== GOT_ERR_NOT_REF
)
6651 err
= got_ref_delete(ref
, repo
);
6656 static const struct got_error
*
6657 delete_rebase_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
6659 const struct got_error
*err
;
6660 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6661 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
6663 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6666 err
= delete_ref(tmp_branch_name
, repo
);
6670 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6673 err
= delete_ref(new_base_branch_ref_name
, repo
);
6677 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6680 err
= delete_ref(branch_ref_name
, repo
);
6684 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6687 err
= delete_ref(commit_ref_name
, repo
);
6692 free(tmp_branch_name
);
6693 free(new_base_branch_ref_name
);
6694 free(branch_ref_name
);
6695 free(commit_ref_name
);
6699 static const struct got_error
*
6700 create_backup_ref(const char *backup_ref_prefix
, struct got_reference
*branch
,
6701 struct got_object_id
*new_commit_id
, struct got_repository
*repo
)
6703 const struct got_error
*err
;
6704 struct got_reference
*ref
= NULL
;
6705 struct got_object_id
*old_commit_id
= NULL
;
6706 const char *branch_name
= NULL
;
6707 char *new_id_str
= NULL
;
6708 char *refname
= NULL
;
6710 branch_name
= got_ref_get_name(branch
);
6711 if (strncmp(branch_name
, "refs/heads/", 11) != 0)
6712 return got_error(GOT_ERR_BAD_REF_NAME
); /* should not happen */
6715 err
= got_object_id_str(&new_id_str
, new_commit_id
);
6719 if (asprintf(&refname
, "%s/%s/%s", backup_ref_prefix
, branch_name
,
6720 new_id_str
) == -1) {
6721 err
= got_error_from_errno("asprintf");
6725 err
= got_ref_resolve(&old_commit_id
, repo
, branch
);
6729 err
= got_ref_alloc(&ref
, refname
, old_commit_id
);
6733 err
= got_ref_write(ref
, repo
);
6737 free(old_commit_id
);
6743 const struct got_error
*
6744 got_worktree_rebase_complete(struct got_worktree
*worktree
,
6745 struct got_fileindex
*fileindex
, struct got_reference
*new_base_branch
,
6746 struct got_reference
*tmp_branch
, struct got_reference
*rebased_branch
,
6747 struct got_repository
*repo
, int create_backup
)
6749 const struct got_error
*err
, *unlockerr
, *sync_err
;
6750 struct got_object_id
*new_head_commit_id
= NULL
;
6751 char *fileindex_path
= NULL
;
6753 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
6757 if (create_backup
) {
6758 err
= create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX
,
6759 rebased_branch
, new_head_commit_id
, repo
);
6764 err
= got_ref_change_ref(rebased_branch
, new_head_commit_id
);
6768 err
= got_ref_write(rebased_branch
, repo
);
6772 err
= got_worktree_set_head_ref(worktree
, rebased_branch
);
6776 err
= delete_rebase_refs(worktree
, repo
);
6780 err
= get_fileindex_path(&fileindex_path
, worktree
);
6783 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
6784 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6785 if (sync_err
&& err
== NULL
)
6788 got_fileindex_free(fileindex
);
6789 free(fileindex_path
);
6790 free(new_head_commit_id
);
6791 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6792 if (unlockerr
&& err
== NULL
)
6797 const struct got_error
*
6798 got_worktree_rebase_abort(struct got_worktree
*worktree
,
6799 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
6800 struct got_reference
*new_base_branch
,
6801 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
6803 const struct got_error
*err
, *unlockerr
, *sync_err
;
6804 struct got_reference
*resolved
= NULL
;
6805 struct got_object_id
*commit_id
= NULL
;
6806 struct got_commit_object
*commit
= NULL
;
6807 char *fileindex_path
= NULL
;
6808 struct revert_file_args rfa
;
6809 struct got_object_id
*tree_id
= NULL
;
6811 err
= lock_worktree(worktree
, LOCK_EX
);
6815 err
= got_object_open_as_commit(&commit
, repo
,
6816 worktree
->base_commit_id
);
6820 err
= got_ref_open(&resolved
, repo
,
6821 got_ref_get_symref_target(new_base_branch
), 0);
6825 err
= got_worktree_set_head_ref(worktree
, resolved
);
6830 * XXX commits to the base branch could have happened while
6831 * we were busy rebasing; should we store the original commit ID
6832 * when rebase begins and read it back here?
6834 err
= got_ref_resolve(&commit_id
, repo
, resolved
);
6838 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
6842 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
6843 worktree
->path_prefix
);
6847 err
= delete_rebase_refs(worktree
, repo
);
6851 err
= get_fileindex_path(&fileindex_path
, worktree
);
6855 rfa
.worktree
= worktree
;
6856 rfa
.fileindex
= fileindex
;
6857 rfa
.progress_cb
= progress_cb
;
6858 rfa
.progress_arg
= progress_arg
;
6859 rfa
.patch_cb
= NULL
;
6860 rfa
.patch_arg
= NULL
;
6862 rfa
.unlink_added_files
= 0;
6863 err
= worktree_status(worktree
, "", fileindex
, repo
,
6864 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
6868 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
6869 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
6871 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6872 if (sync_err
&& err
== NULL
)
6875 got_ref_close(resolved
);
6879 got_object_commit_close(commit
);
6881 got_fileindex_free(fileindex
);
6882 free(fileindex_path
);
6884 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6885 if (unlockerr
&& err
== NULL
)
6890 const struct got_error
*
6891 got_worktree_histedit_prepare(struct got_reference
**tmp_branch
,
6892 struct got_reference
**branch_ref
, struct got_object_id
**base_commit_id
,
6893 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
6894 struct got_repository
*repo
)
6896 const struct got_error
*err
= NULL
;
6897 char *tmp_branch_name
= NULL
;
6898 char *branch_ref_name
= NULL
;
6899 char *base_commit_ref_name
= NULL
;
6900 char *fileindex_path
= NULL
;
6901 struct check_rebase_ok_arg ok_arg
;
6902 struct got_reference
*wt_branch
= NULL
;
6903 struct got_reference
*base_commit_ref
= NULL
;
6907 *base_commit_id
= NULL
;
6910 err
= lock_worktree(worktree
, LOCK_EX
);
6914 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6918 ok_arg
.worktree
= worktree
;
6920 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6925 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
6929 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
6933 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
6938 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6943 err
= got_ref_alloc_symref(branch_ref
, branch_ref_name
, wt_branch
);
6947 err
= got_ref_write(*branch_ref
, repo
);
6951 err
= got_ref_alloc(&base_commit_ref
, base_commit_ref_name
,
6952 worktree
->base_commit_id
);
6955 err
= got_ref_write(base_commit_ref
, repo
);
6958 *base_commit_id
= got_object_id_dup(worktree
->base_commit_id
);
6959 if (*base_commit_id
== NULL
) {
6960 err
= got_error_from_errno("got_object_id_dup");
6964 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6965 worktree
->base_commit_id
);
6968 err
= got_ref_write(*tmp_branch
, repo
);
6972 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6976 free(fileindex_path
);
6977 free(tmp_branch_name
);
6978 free(branch_ref_name
);
6979 free(base_commit_ref_name
);
6981 got_ref_close(wt_branch
);
6984 got_ref_close(*branch_ref
);
6988 got_ref_close(*tmp_branch
);
6991 free(*base_commit_id
);
6993 got_fileindex_free(*fileindex
);
6996 lock_worktree(worktree
, LOCK_SH
);
7001 const struct got_error
*
7002 got_worktree_histedit_postpone(struct got_worktree
*worktree
,
7003 struct got_fileindex
*fileindex
)
7006 got_fileindex_free(fileindex
);
7007 return lock_worktree(worktree
, LOCK_SH
);
7010 const struct got_error
*
7011 got_worktree_histedit_in_progress(int *in_progress
,
7012 struct got_worktree
*worktree
)
7014 const struct got_error
*err
;
7015 char *tmp_branch_name
= NULL
;
7017 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7021 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
7022 free(tmp_branch_name
);
7026 const struct got_error
*
7027 got_worktree_histedit_continue(struct got_object_id
**commit_id
,
7028 struct got_reference
**tmp_branch
, struct got_reference
**branch_ref
,
7029 struct got_object_id
**base_commit_id
, struct got_fileindex
**fileindex
,
7030 struct got_worktree
*worktree
, struct got_repository
*repo
)
7032 const struct got_error
*err
;
7033 char *commit_ref_name
= NULL
, *base_commit_ref_name
= NULL
;
7034 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
7035 struct got_reference
*commit_ref
= NULL
;
7036 struct got_reference
*base_commit_ref
= NULL
;
7037 char *fileindex_path
= NULL
;
7038 int have_staged_files
= 0;
7042 *base_commit_id
= NULL
;
7045 err
= lock_worktree(worktree
, LOCK_EX
);
7049 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7053 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
7054 &have_staged_files
);
7055 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7057 if (have_staged_files
) {
7058 err
= got_error(GOT_ERR_STAGED_PATHS
);
7062 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7066 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7070 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7074 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7079 err
= got_ref_open(branch_ref
, repo
, branch_ref_name
, 0);
7083 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7086 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
7090 err
= got_ref_open(&base_commit_ref
, repo
, base_commit_ref_name
, 0);
7093 err
= got_ref_resolve(base_commit_id
, repo
, base_commit_ref
);
7097 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
7101 free(commit_ref_name
);
7102 free(branch_ref_name
);
7103 free(fileindex_path
);
7105 got_ref_close(commit_ref
);
7106 if (base_commit_ref
)
7107 got_ref_close(base_commit_ref
);
7111 free(*base_commit_id
);
7112 *base_commit_id
= NULL
;
7114 got_ref_close(*tmp_branch
);
7118 got_fileindex_free(*fileindex
);
7121 lock_worktree(worktree
, LOCK_EX
);
7126 static const struct got_error
*
7127 delete_histedit_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7129 const struct got_error
*err
;
7130 char *tmp_branch_name
= NULL
, *base_commit_ref_name
= NULL
;
7131 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
7133 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7136 err
= delete_ref(tmp_branch_name
, repo
);
7140 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7144 err
= delete_ref(base_commit_ref_name
, repo
);
7148 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7151 err
= delete_ref(branch_ref_name
, repo
);
7155 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7158 err
= delete_ref(commit_ref_name
, repo
);
7162 free(tmp_branch_name
);
7163 free(base_commit_ref_name
);
7164 free(branch_ref_name
);
7165 free(commit_ref_name
);
7169 const struct got_error
*
7170 got_worktree_histedit_abort(struct got_worktree
*worktree
,
7171 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7172 struct got_reference
*branch
, struct got_object_id
*base_commit_id
,
7173 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7175 const struct got_error
*err
, *unlockerr
, *sync_err
;
7176 struct got_reference
*resolved
= NULL
;
7177 char *fileindex_path
= NULL
;
7178 struct got_commit_object
*commit
= NULL
;
7179 struct got_object_id
*tree_id
= NULL
;
7180 struct revert_file_args rfa
;
7182 err
= lock_worktree(worktree
, LOCK_EX
);
7186 err
= got_object_open_as_commit(&commit
, repo
,
7187 worktree
->base_commit_id
);
7191 err
= got_ref_open(&resolved
, repo
,
7192 got_ref_get_symref_target(branch
), 0);
7196 err
= got_worktree_set_head_ref(worktree
, resolved
);
7200 err
= got_worktree_set_base_commit_id(worktree
, repo
, base_commit_id
);
7204 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
7205 worktree
->path_prefix
);
7209 err
= delete_histedit_refs(worktree
, repo
);
7213 err
= get_fileindex_path(&fileindex_path
, worktree
);
7217 rfa
.worktree
= worktree
;
7218 rfa
.fileindex
= fileindex
;
7219 rfa
.progress_cb
= progress_cb
;
7220 rfa
.progress_arg
= progress_arg
;
7221 rfa
.patch_cb
= NULL
;
7222 rfa
.patch_arg
= NULL
;
7224 rfa
.unlink_added_files
= 0;
7225 err
= worktree_status(worktree
, "", fileindex
, repo
,
7226 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
7230 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7231 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7233 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7234 if (sync_err
&& err
== NULL
)
7237 got_ref_close(resolved
);
7239 free(fileindex_path
);
7241 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7242 if (unlockerr
&& err
== NULL
)
7247 const struct got_error
*
7248 got_worktree_histedit_complete(struct got_worktree
*worktree
,
7249 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7250 struct got_reference
*edited_branch
, struct got_repository
*repo
)
7252 const struct got_error
*err
, *unlockerr
, *sync_err
;
7253 struct got_object_id
*new_head_commit_id
= NULL
;
7254 struct got_reference
*resolved
= NULL
;
7255 char *fileindex_path
= NULL
;
7257 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
7261 err
= got_ref_open(&resolved
, repo
,
7262 got_ref_get_symref_target(edited_branch
), 0);
7266 err
= create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX
,
7267 resolved
, new_head_commit_id
, repo
);
7271 err
= got_ref_change_ref(resolved
, new_head_commit_id
);
7275 err
= got_ref_write(resolved
, repo
);
7279 err
= got_worktree_set_head_ref(worktree
, resolved
);
7283 err
= delete_histedit_refs(worktree
, repo
);
7287 err
= get_fileindex_path(&fileindex_path
, worktree
);
7290 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7291 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7292 if (sync_err
&& err
== NULL
)
7295 got_fileindex_free(fileindex
);
7296 free(fileindex_path
);
7297 free(new_head_commit_id
);
7298 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7299 if (unlockerr
&& err
== NULL
)
7304 const struct got_error
*
7305 got_worktree_histedit_skip_commit(struct got_worktree
*worktree
,
7306 struct got_object_id
*commit_id
, struct got_repository
*repo
)
7308 const struct got_error
*err
;
7309 char *commit_ref_name
;
7311 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7315 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
7319 err
= delete_ref(commit_ref_name
, repo
);
7321 free(commit_ref_name
);
7325 const struct got_error
*
7326 got_worktree_integrate_prepare(struct got_fileindex
**fileindex
,
7327 struct got_reference
**branch_ref
, struct got_reference
**base_branch_ref
,
7328 struct got_worktree
*worktree
, const char *refname
,
7329 struct got_repository
*repo
)
7331 const struct got_error
*err
= NULL
;
7332 char *fileindex_path
= NULL
;
7333 struct check_rebase_ok_arg ok_arg
;
7337 *base_branch_ref
= NULL
;
7339 err
= lock_worktree(worktree
, LOCK_EX
);
7343 if (strcmp(refname
, got_worktree_get_head_ref_name(worktree
)) == 0) {
7344 err
= got_error_msg(GOT_ERR_SAME_BRANCH
,
7345 "cannot integrate a branch into itself; "
7346 "update -b or different branch name required");
7350 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7354 /* Preconditions are the same as for rebase. */
7355 ok_arg
.worktree
= worktree
;
7357 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7362 err
= got_ref_open(branch_ref
, repo
, refname
, 1);
7366 err
= got_ref_open(base_branch_ref
, repo
,
7367 got_worktree_get_head_ref_name(worktree
), 1);
7371 got_ref_close(*branch_ref
);
7374 if (*base_branch_ref
) {
7375 got_ref_close(*base_branch_ref
);
7376 *base_branch_ref
= NULL
;
7379 got_fileindex_free(*fileindex
);
7382 lock_worktree(worktree
, LOCK_SH
);
7387 const struct got_error
*
7388 got_worktree_integrate_continue(struct got_worktree
*worktree
,
7389 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7390 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
,
7391 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7392 got_cancel_cb cancel_cb
, void *cancel_arg
)
7394 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
7395 char *fileindex_path
= NULL
;
7396 struct got_object_id
*tree_id
= NULL
, *commit_id
= NULL
;
7397 struct got_commit_object
*commit
= NULL
;
7399 err
= get_fileindex_path(&fileindex_path
, worktree
);
7403 err
= got_ref_resolve(&commit_id
, repo
, branch_ref
);
7407 err
= got_object_open_as_commit(&commit
, repo
, commit_id
);
7411 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
7412 worktree
->path_prefix
);
7416 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
7420 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
, repo
,
7421 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
7425 err
= got_ref_change_ref(base_branch_ref
, commit_id
);
7429 err
= got_ref_write(base_branch_ref
, repo
);
7433 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7435 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7436 if (sync_err
&& err
== NULL
)
7440 unlockerr
= got_ref_unlock(branch_ref
);
7441 if (unlockerr
&& err
== NULL
)
7443 got_ref_close(branch_ref
);
7445 unlockerr
= got_ref_unlock(base_branch_ref
);
7446 if (unlockerr
&& err
== NULL
)
7448 got_ref_close(base_branch_ref
);
7450 got_fileindex_free(fileindex
);
7451 free(fileindex_path
);
7454 got_object_commit_close(commit
);
7456 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7457 if (unlockerr
&& err
== NULL
)
7462 const struct got_error
*
7463 got_worktree_integrate_abort(struct got_worktree
*worktree
,
7464 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7465 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
)
7467 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
7469 got_fileindex_free(fileindex
);
7471 err
= lock_worktree(worktree
, LOCK_SH
);
7473 unlockerr
= got_ref_unlock(branch_ref
);
7474 if (unlockerr
&& err
== NULL
)
7476 got_ref_close(branch_ref
);
7478 unlockerr
= got_ref_unlock(base_branch_ref
);
7479 if (unlockerr
&& err
== NULL
)
7481 got_ref_close(base_branch_ref
);
7486 const struct got_error
*
7487 got_worktree_merge_postpone(struct got_worktree
*worktree
,
7488 struct got_fileindex
*fileindex
)
7490 const struct got_error
*err
, *sync_err
;
7491 char *fileindex_path
= NULL
;
7493 err
= get_fileindex_path(&fileindex_path
, worktree
);
7497 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7499 err
= lock_worktree(worktree
, LOCK_SH
);
7500 if (sync_err
&& err
== NULL
)
7503 got_fileindex_free(fileindex
);
7504 free(fileindex_path
);
7508 static const struct got_error
*
7509 delete_merge_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7511 const struct got_error
*err
;
7512 char *branch_refname
= NULL
, *commit_refname
= NULL
;
7514 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7517 err
= delete_ref(branch_refname
, repo
);
7521 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7524 err
= delete_ref(commit_refname
, repo
);
7529 free(branch_refname
);
7530 free(commit_refname
);
7534 struct merge_commit_msg_arg
{
7535 struct got_worktree
*worktree
;
7536 const char *branch_name
;
7539 static const struct got_error
*
7540 merge_commit_msg_cb(struct got_pathlist_head
*commitable_paths
, char **logmsg
,
7543 struct merge_commit_msg_arg
*a
= arg
;
7545 if (asprintf(logmsg
, "merge %s into %s\n", a
->branch_name
,
7546 got_worktree_get_head_ref_name(a
->worktree
)) == -1)
7547 return got_error_from_errno("asprintf");
7553 const struct got_error
*
7554 got_worktree_merge_branch(struct got_worktree
*worktree
,
7555 struct got_fileindex
*fileindex
,
7556 struct got_object_id
*yca_commit_id
,
7557 struct got_object_id
*branch_tip
,
7558 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
7559 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
7561 const struct got_error
*err
;
7562 char *fileindex_path
= NULL
;
7564 err
= get_fileindex_path(&fileindex_path
, worktree
);
7568 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
7573 err
= merge_files(worktree
, fileindex
, fileindex_path
, yca_commit_id
,
7574 branch_tip
, repo
, progress_cb
, progress_arg
,
7575 cancel_cb
, cancel_arg
);
7577 free(fileindex_path
);
7581 const struct got_error
*
7582 got_worktree_merge_commit(struct got_object_id
**new_commit_id
,
7583 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
7584 const char *author
, const char *committer
, int allow_bad_symlinks
,
7585 struct got_object_id
*branch_tip
, const char *branch_name
,
7586 struct got_repository
*repo
,
7587 got_worktree_status_cb status_cb
, void *status_arg
)
7590 const struct got_error
*err
= NULL
, *sync_err
;
7591 struct got_pathlist_head commitable_paths
;
7592 struct collect_commitables_arg cc_arg
;
7593 struct got_pathlist_entry
*pe
;
7594 struct got_reference
*head_ref
= NULL
;
7595 struct got_object_id
*head_commit_id
= NULL
;
7596 int have_staged_files
= 0;
7597 struct merge_commit_msg_arg mcm_arg
;
7598 char *fileindex_path
= NULL
;
7600 *new_commit_id
= NULL
;
7602 TAILQ_INIT(&commitable_paths
);
7604 err
= get_fileindex_path(&fileindex_path
, worktree
);
7608 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
7612 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
7616 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
7617 &have_staged_files
);
7618 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7620 if (have_staged_files
) {
7621 err
= got_error(GOT_ERR_MERGE_STAGED_PATHS
);
7625 cc_arg
.commitable_paths
= &commitable_paths
;
7626 cc_arg
.worktree
= worktree
;
7627 cc_arg
.fileindex
= fileindex
;
7629 cc_arg
.have_staged_files
= have_staged_files
;
7630 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
7631 err
= worktree_status(worktree
, "", fileindex
, repo
,
7632 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
7636 if (TAILQ_EMPTY(&commitable_paths
)) {
7637 err
= got_error_fmt(GOT_ERR_COMMIT_NO_CHANGES
,
7638 "merge of %s cannot proceed", branch_name
);
7642 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
7643 struct got_commitable
*ct
= pe
->data
;
7644 const char *ct_path
= ct
->in_repo_path
;
7646 while (ct_path
[0] == '/')
7648 err
= check_out_of_date(ct_path
, ct
->status
,
7649 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
7650 head_commit_id
, repo
, GOT_ERR_MERGE_COMMIT_OUT_OF_DATE
);
7656 mcm_arg
.worktree
= worktree
;
7657 mcm_arg
.branch_name
= branch_name
;
7658 err
= commit_worktree(new_commit_id
, &commitable_paths
,
7659 head_commit_id
, branch_tip
, worktree
, author
, committer
,
7660 merge_commit_msg_cb
, &mcm_arg
, status_cb
, status_arg
, repo
);
7664 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
7665 *new_commit_id
, fileindex
, have_staged_files
);
7666 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7667 if (sync_err
&& err
== NULL
)
7670 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
7671 struct got_commitable
*ct
= pe
->data
;
7672 free_commitable(ct
);
7674 got_pathlist_free(&commitable_paths
);
7675 free(fileindex_path
);
7679 const struct got_error
*
7680 got_worktree_merge_complete(struct got_worktree
*worktree
,
7681 struct got_fileindex
*fileindex
, struct got_repository
*repo
)
7683 const struct got_error
*err
, *unlockerr
, *sync_err
;
7684 char *fileindex_path
= NULL
;
7686 err
= delete_merge_refs(worktree
, repo
);
7690 err
= get_fileindex_path(&fileindex_path
, worktree
);
7693 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7694 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7695 if (sync_err
&& err
== NULL
)
7698 got_fileindex_free(fileindex
);
7699 free(fileindex_path
);
7700 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7701 if (unlockerr
&& err
== NULL
)
7706 const struct got_error
*
7707 got_worktree_merge_in_progress(int *in_progress
, struct got_worktree
*worktree
,
7708 struct got_repository
*repo
)
7710 const struct got_error
*err
;
7711 char *branch_refname
= NULL
;
7712 struct got_reference
*branch_ref
= NULL
;
7716 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7719 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
7720 free(branch_refname
);
7722 if (err
->code
!= GOT_ERR_NOT_REF
)
7730 const struct got_error
*got_worktree_merge_prepare(
7731 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
7732 struct got_reference
*branch
, struct got_repository
*repo
)
7734 const struct got_error
*err
= NULL
;
7735 char *fileindex_path
= NULL
;
7736 char *branch_refname
= NULL
, *commit_refname
= NULL
;
7737 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
7738 struct got_reference
*commit_ref
= NULL
;
7739 struct got_object_id
*branch_tip
= NULL
, *wt_branch_tip
= NULL
;
7740 struct check_rebase_ok_arg ok_arg
;
7744 err
= lock_worktree(worktree
, LOCK_EX
);
7748 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7752 /* Preconditions are the same as for rebase. */
7753 ok_arg
.worktree
= worktree
;
7755 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7760 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7764 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7768 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
7773 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
7777 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
7778 err
= got_error(GOT_ERR_MERGE_OUT_OF_DATE
);
7782 err
= got_ref_resolve(&branch_tip
, repo
, branch
);
7786 err
= got_ref_alloc_symref(&branch_ref
, branch_refname
, branch
);
7789 err
= got_ref_write(branch_ref
, repo
);
7793 err
= got_ref_alloc(&commit_ref
, commit_refname
, branch_tip
);
7796 err
= got_ref_write(commit_ref
, repo
);
7801 free(branch_refname
);
7802 free(commit_refname
);
7803 free(fileindex_path
);
7805 got_ref_close(branch_ref
);
7807 got_ref_close(commit_ref
);
7809 got_ref_close(wt_branch
);
7810 free(wt_branch_tip
);
7813 got_fileindex_free(*fileindex
);
7816 lock_worktree(worktree
, LOCK_SH
);
7821 const struct got_error
*
7822 got_worktree_merge_continue(char **branch_name
,
7823 struct got_object_id
**branch_tip
, struct got_fileindex
**fileindex
,
7824 struct got_worktree
*worktree
, struct got_repository
*repo
)
7826 const struct got_error
*err
;
7827 char *commit_refname
= NULL
, *branch_refname
= NULL
;
7828 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
7829 char *fileindex_path
= NULL
;
7830 int have_staged_files
= 0;
7832 *branch_name
= NULL
;
7836 err
= lock_worktree(worktree
, LOCK_EX
);
7840 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7844 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
7845 &have_staged_files
);
7846 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7848 if (have_staged_files
) {
7849 err
= got_error(GOT_ERR_STAGED_PATHS
);
7853 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7857 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7861 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
7865 if (!got_ref_is_symbolic(branch_ref
)) {
7866 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
7867 "%s is not a symbolic reference",
7868 got_ref_get_name(branch_ref
));
7871 *branch_name
= strdup(got_ref_get_symref_target(branch_ref
));
7872 if (*branch_name
== NULL
) {
7873 err
= got_error_from_errno("strdup");
7877 err
= got_ref_open(&commit_ref
, repo
, commit_refname
, 0);
7881 err
= got_ref_resolve(branch_tip
, repo
, commit_ref
);
7885 free(commit_refname
);
7886 free(branch_refname
);
7887 free(fileindex_path
);
7889 got_ref_close(commit_ref
);
7891 got_ref_close(branch_ref
);
7895 *branch_name
= NULL
;
7900 got_fileindex_free(*fileindex
);
7903 lock_worktree(worktree
, LOCK_SH
);
7908 const struct got_error
*
7909 got_worktree_merge_abort(struct got_worktree
*worktree
,
7910 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7911 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7913 const struct got_error
*err
, *unlockerr
, *sync_err
;
7914 struct got_object_id
*commit_id
= NULL
;
7915 struct got_commit_object
*commit
= NULL
;
7916 char *fileindex_path
= NULL
;
7917 struct revert_file_args rfa
;
7918 struct got_object_id
*tree_id
= NULL
;
7920 err
= got_object_open_as_commit(&commit
, repo
,
7921 worktree
->base_commit_id
);
7925 err
= got_object_id_by_path(&tree_id
, repo
, commit
,
7926 worktree
->path_prefix
);
7930 err
= delete_merge_refs(worktree
, repo
);
7934 err
= get_fileindex_path(&fileindex_path
, worktree
);
7938 rfa
.worktree
= worktree
;
7939 rfa
.fileindex
= fileindex
;
7940 rfa
.progress_cb
= progress_cb
;
7941 rfa
.progress_arg
= progress_arg
;
7942 rfa
.patch_cb
= NULL
;
7943 rfa
.patch_arg
= NULL
;
7945 rfa
.unlink_added_files
= 1;
7946 err
= worktree_status(worktree
, "", fileindex
, repo
,
7947 revert_file
, &rfa
, NULL
, NULL
, 1, 0);
7951 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7952 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7954 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7955 if (sync_err
&& err
== NULL
)
7961 got_object_commit_close(commit
);
7963 got_fileindex_free(fileindex
);
7964 free(fileindex_path
);
7966 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7967 if (unlockerr
&& err
== NULL
)
7972 struct check_stage_ok_arg
{
7973 struct got_object_id
*head_commit_id
;
7974 struct got_worktree
*worktree
;
7975 struct got_fileindex
*fileindex
;
7976 struct got_repository
*repo
;
7980 static const struct got_error
*
7981 check_stage_ok(void *arg
, unsigned char status
,
7982 unsigned char staged_status
, const char *relpath
,
7983 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
7984 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
7986 struct check_stage_ok_arg
*a
= arg
;
7987 const struct got_error
*err
= NULL
;
7988 struct got_fileindex_entry
*ie
;
7989 struct got_object_id base_commit_id
;
7990 struct got_object_id
*base_commit_idp
= NULL
;
7991 char *in_repo_path
= NULL
, *p
;
7993 if (status
== GOT_STATUS_UNVERSIONED
||
7994 status
== GOT_STATUS_NO_CHANGE
)
7996 if (status
== GOT_STATUS_NONEXISTENT
)
7997 return got_error_set_errno(ENOENT
, relpath
);
7999 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8001 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8003 if (asprintf(&in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
8004 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
8006 return got_error_from_errno("asprintf");
8008 if (got_fileindex_entry_has_commit(ie
)) {
8009 memcpy(base_commit_id
.sha1
, ie
->commit_sha1
,
8010 SHA1_DIGEST_LENGTH
);
8011 base_commit_idp
= &base_commit_id
;
8014 if (status
== GOT_STATUS_CONFLICT
) {
8015 err
= got_error_path(ie
->path
, GOT_ERR_STAGE_CONFLICT
);
8017 } else if (status
!= GOT_STATUS_ADD
&&
8018 status
!= GOT_STATUS_MODIFY
&&
8019 status
!= GOT_STATUS_DELETE
) {
8020 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STATUS
);
8024 a
->have_changes
= 1;
8029 err
= check_out_of_date(p
, status
, staged_status
,
8030 blob_id
, base_commit_idp
, a
->head_commit_id
, a
->repo
,
8031 GOT_ERR_STAGE_OUT_OF_DATE
);
8037 struct stage_path_arg
{
8038 struct got_worktree
*worktree
;
8039 struct got_fileindex
*fileindex
;
8040 struct got_repository
*repo
;
8041 got_worktree_status_cb status_cb
;
8043 got_worktree_patch_cb patch_cb
;
8045 int staged_something
;
8046 int allow_bad_symlinks
;
8049 static const struct got_error
*
8050 stage_path(void *arg
, unsigned char status
,
8051 unsigned char staged_status
, const char *relpath
,
8052 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
8053 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
8055 struct stage_path_arg
*a
= arg
;
8056 const struct got_error
*err
= NULL
;
8057 struct got_fileindex_entry
*ie
;
8058 char *ondisk_path
= NULL
, *path_content
= NULL
;
8060 struct got_object_id
*new_staged_blob_id
= NULL
;
8063 if (status
== GOT_STATUS_UNVERSIONED
)
8066 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8068 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8070 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
8072 return got_error_from_errno("asprintf");
8075 case GOT_STATUS_ADD
:
8076 case GOT_STATUS_MODIFY
:
8077 /* XXX could sb.st_mode be passed in by our caller? */
8078 if (lstat(ondisk_path
, &sb
) == -1) {
8079 err
= got_error_from_errno2("lstat", ondisk_path
);
8083 if (status
== GOT_STATUS_ADD
) {
8084 int choice
= GOT_PATCH_CHOICE_NONE
;
8085 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8086 status
, ie
->path
, NULL
, 1, 1);
8089 if (choice
!= GOT_PATCH_CHOICE_YES
)
8092 err
= create_patched_content(&path_content
, 0,
8093 staged_blob_id
? staged_blob_id
: blob_id
,
8094 ondisk_path
, dirfd
, de_name
, ie
->path
,
8095 a
->repo
, a
->patch_cb
, a
->patch_arg
);
8096 if (err
|| path_content
== NULL
)
8100 err
= got_object_blob_create(&new_staged_blob_id
,
8101 path_content
? path_content
: ondisk_path
, a
->repo
);
8104 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
8105 SHA1_DIGEST_LENGTH
);
8106 if (status
== GOT_STATUS_ADD
|| staged_status
== GOT_STATUS_ADD
)
8107 stage
= GOT_FILEIDX_STAGE_ADD
;
8109 stage
= GOT_FILEIDX_STAGE_MODIFY
;
8110 got_fileindex_entry_stage_set(ie
, stage
);
8111 if (S_ISLNK(sb
.st_mode
)) {
8112 int is_bad_symlink
= 0;
8113 if (!a
->allow_bad_symlinks
) {
8114 char target_path
[PATH_MAX
];
8116 target_len
= readlink(ondisk_path
, target_path
,
8117 sizeof(target_path
));
8118 if (target_len
== -1) {
8119 err
= got_error_from_errno2("readlink",
8123 err
= is_bad_symlink_target(&is_bad_symlink
,
8124 target_path
, target_len
, ondisk_path
,
8125 a
->worktree
->root_path
);
8128 if (is_bad_symlink
) {
8129 err
= got_error_path(ondisk_path
,
8130 GOT_ERR_BAD_SYMLINK
);
8135 got_fileindex_entry_staged_filetype_set(ie
,
8136 GOT_FILEIDX_MODE_BAD_SYMLINK
);
8138 got_fileindex_entry_staged_filetype_set(ie
,
8139 GOT_FILEIDX_MODE_SYMLINK
);
8141 got_fileindex_entry_staged_filetype_set(ie
,
8142 GOT_FILEIDX_MODE_REGULAR_FILE
);
8144 a
->staged_something
= 1;
8145 if (a
->status_cb
== NULL
)
8147 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
8148 get_staged_status(ie
), relpath
, blob_id
,
8149 new_staged_blob_id
, NULL
, dirfd
, de_name
);
8153 * When staging the reverse of the staged diff,
8154 * implicitly unstage the file.
8156 if (memcmp(ie
->staged_blob_sha1
, ie
->blob_sha1
,
8157 sizeof(ie
->blob_sha1
)) == 0) {
8158 got_fileindex_entry_stage_set(ie
,
8159 GOT_FILEIDX_STAGE_NONE
);
8162 case GOT_STATUS_DELETE
:
8163 if (staged_status
== GOT_STATUS_DELETE
)
8166 int choice
= GOT_PATCH_CHOICE_NONE
;
8167 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
, status
,
8168 ie
->path
, NULL
, 1, 1);
8171 if (choice
== GOT_PATCH_CHOICE_NO
)
8173 if (choice
!= GOT_PATCH_CHOICE_YES
) {
8174 err
= got_error(GOT_ERR_PATCH_CHOICE
);
8178 stage
= GOT_FILEIDX_STAGE_DELETE
;
8179 got_fileindex_entry_stage_set(ie
, stage
);
8180 a
->staged_something
= 1;
8181 if (a
->status_cb
== NULL
)
8183 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
8184 get_staged_status(ie
), relpath
, NULL
, NULL
, NULL
, dirfd
,
8187 case GOT_STATUS_NO_CHANGE
:
8189 case GOT_STATUS_CONFLICT
:
8190 err
= got_error_path(relpath
, GOT_ERR_STAGE_CONFLICT
);
8192 case GOT_STATUS_NONEXISTENT
:
8193 err
= got_error_set_errno(ENOENT
, relpath
);
8196 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8200 if (path_content
&& unlink(path_content
) == -1 && err
== NULL
)
8201 err
= got_error_from_errno2("unlink", path_content
);
8204 free(new_staged_blob_id
);
8208 const struct got_error
*
8209 got_worktree_stage(struct got_worktree
*worktree
,
8210 struct got_pathlist_head
*paths
,
8211 got_worktree_status_cb status_cb
, void *status_arg
,
8212 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8213 int allow_bad_symlinks
, struct got_repository
*repo
)
8215 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8216 struct got_pathlist_entry
*pe
;
8217 struct got_fileindex
*fileindex
= NULL
;
8218 char *fileindex_path
= NULL
;
8219 struct got_reference
*head_ref
= NULL
;
8220 struct got_object_id
*head_commit_id
= NULL
;
8221 struct check_stage_ok_arg oka
;
8222 struct stage_path_arg spa
;
8224 err
= lock_worktree(worktree
, LOCK_EX
);
8228 err
= got_ref_open(&head_ref
, repo
,
8229 got_worktree_get_head_ref_name(worktree
), 0);
8232 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
8235 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8239 /* Check pre-conditions before staging anything. */
8240 oka
.head_commit_id
= head_commit_id
;
8241 oka
.worktree
= worktree
;
8242 oka
.fileindex
= fileindex
;
8244 oka
.have_changes
= 0;
8245 TAILQ_FOREACH(pe
, paths
, entry
) {
8246 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8247 check_stage_ok
, &oka
, NULL
, NULL
, 1, 0);
8251 if (!oka
.have_changes
) {
8252 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
8256 spa
.worktree
= worktree
;
8257 spa
.fileindex
= fileindex
;
8259 spa
.patch_cb
= patch_cb
;
8260 spa
.patch_arg
= patch_arg
;
8261 spa
.status_cb
= status_cb
;
8262 spa
.status_arg
= status_arg
;
8263 spa
.staged_something
= 0;
8264 spa
.allow_bad_symlinks
= allow_bad_symlinks
;
8265 TAILQ_FOREACH(pe
, paths
, entry
) {
8266 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8267 stage_path
, &spa
, NULL
, NULL
, 1, 0);
8271 if (!spa
.staged_something
) {
8272 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
8276 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8277 if (sync_err
&& err
== NULL
)
8281 got_ref_close(head_ref
);
8282 free(head_commit_id
);
8283 free(fileindex_path
);
8285 got_fileindex_free(fileindex
);
8286 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8287 if (unlockerr
&& err
== NULL
)
8292 struct unstage_path_arg
{
8293 struct got_worktree
*worktree
;
8294 struct got_fileindex
*fileindex
;
8295 struct got_repository
*repo
;
8296 got_worktree_checkout_cb progress_cb
;
8298 got_worktree_patch_cb patch_cb
;
8302 static const struct got_error
*
8303 create_unstaged_content(char **path_unstaged_content
,
8304 char **path_new_staged_content
, struct got_object_id
*blob_id
,
8305 struct got_object_id
*staged_blob_id
, const char *relpath
,
8306 struct got_repository
*repo
,
8307 got_worktree_patch_cb patch_cb
, void *patch_arg
)
8309 const struct got_error
*err
, *free_err
;
8310 struct got_blob_object
*blob
= NULL
, *staged_blob
= NULL
;
8311 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
, *rejectfile
= NULL
;
8312 char *path1
= NULL
, *path2
= NULL
, *label1
= NULL
;
8313 struct got_diffreg_result
*diffreg_result
= NULL
;
8314 int line_cur1
= 1, line_cur2
= 1, n
= 0, nchunks_used
= 0;
8315 int have_content
= 0, have_rejected_content
= 0, i
= 0, nchanges
= 0;
8316 int fd1
= -1, fd2
= -1;
8318 *path_unstaged_content
= NULL
;
8319 *path_new_staged_content
= NULL
;
8321 err
= got_object_id_str(&label1
, blob_id
);
8325 fd1
= got_opentempfd();
8327 err
= got_error_from_errno("got_opentempfd");
8330 fd2
= got_opentempfd();
8332 err
= got_error_from_errno("got_opentempfd");
8336 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192, fd1
);
8340 err
= got_opentemp_named(&path1
, &f1
, "got-unstage-blob-base");
8344 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
8348 err
= got_object_open_as_blob(&staged_blob
, repo
, staged_blob_id
, 8192,
8353 err
= got_opentemp_named(&path2
, &f2
, "got-unstage-blob-staged");
8357 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f2
, staged_blob
);
8361 err
= got_diff_files(&diffreg_result
, f1
, 1, label1
, f2
, 1,
8362 path2
, 3, 0, 1, NULL
, GOT_DIFF_ALGORITHM_MYERS
);
8366 err
= got_opentemp_named(path_unstaged_content
, &outfile
,
8367 "got-unstaged-content");
8370 err
= got_opentemp_named(path_new_staged_content
, &rejectfile
,
8371 "got-new-staged-content");
8375 if (fseek(f1
, 0L, SEEK_SET
) == -1) {
8376 err
= got_ferror(f1
, GOT_ERR_IO
);
8379 if (fseek(f2
, 0L, SEEK_SET
) == -1) {
8380 err
= got_ferror(f2
, GOT_ERR_IO
);
8383 /* Count the number of actual changes in the diff result. */
8384 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
8385 struct diff_chunk_context cc
= {};
8386 diff_chunk_context_load_change(&cc
, &nchunks_used
,
8387 diffreg_result
->result
, n
, 0);
8390 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
8392 err
= apply_or_reject_change(&choice
, &nchunks_used
,
8393 diffreg_result
->result
, n
, relpath
, f1
, f2
,
8394 &line_cur1
, &line_cur2
,
8395 outfile
, rejectfile
, ++i
, nchanges
, patch_cb
, patch_arg
);
8398 if (choice
== GOT_PATCH_CHOICE_YES
)
8401 have_rejected_content
= 1;
8402 if (choice
== GOT_PATCH_CHOICE_QUIT
)
8405 if (have_content
|| have_rejected_content
)
8406 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
8407 outfile
, rejectfile
);
8410 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
8411 err
= got_error_from_errno("close");
8413 got_object_blob_close(blob
);
8414 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
8415 err
= got_error_from_errno("close");
8417 got_object_blob_close(staged_blob
);
8418 free_err
= got_diffreg_result_free(diffreg_result
);
8419 if (free_err
&& err
== NULL
)
8421 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
8422 err
= got_error_from_errno2("fclose", path1
);
8423 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
8424 err
= got_error_from_errno2("fclose", path2
);
8425 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
8426 err
= got_error_from_errno2("fclose", *path_unstaged_content
);
8427 if (rejectfile
&& fclose(rejectfile
) == EOF
&& err
== NULL
)
8428 err
= got_error_from_errno2("fclose", *path_new_staged_content
);
8429 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
8430 err
= got_error_from_errno2("unlink", path1
);
8431 if (path2
&& unlink(path2
) == -1 && err
== NULL
)
8432 err
= got_error_from_errno2("unlink", path2
);
8433 if (err
|| !have_content
) {
8434 if (*path_unstaged_content
&&
8435 unlink(*path_unstaged_content
) == -1 && err
== NULL
)
8436 err
= got_error_from_errno2("unlink",
8437 *path_unstaged_content
);
8438 free(*path_unstaged_content
);
8439 *path_unstaged_content
= NULL
;
8441 if (err
|| !have_content
|| !have_rejected_content
) {
8442 if (*path_new_staged_content
&&
8443 unlink(*path_new_staged_content
) == -1 && err
== NULL
)
8444 err
= got_error_from_errno2("unlink",
8445 *path_new_staged_content
);
8446 free(*path_new_staged_content
);
8447 *path_new_staged_content
= NULL
;
8454 static const struct got_error
*
8455 unstage_hunks(struct got_object_id
*staged_blob_id
,
8456 struct got_blob_object
*blob_base
,
8457 struct got_object_id
*blob_id
, struct got_fileindex_entry
*ie
,
8458 const char *ondisk_path
, const char *label_orig
,
8459 struct got_worktree
*worktree
, struct got_repository
*repo
,
8460 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8461 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
8463 const struct got_error
*err
= NULL
;
8464 char *path_unstaged_content
= NULL
;
8465 char *path_new_staged_content
= NULL
;
8466 char *parent
= NULL
, *base_path
= NULL
;
8467 char *blob_base_path
= NULL
;
8468 struct got_object_id
*new_staged_blob_id
= NULL
;
8469 FILE *f
= NULL
, *f_base
= NULL
, *f_deriv2
= NULL
;
8472 err
= create_unstaged_content(&path_unstaged_content
,
8473 &path_new_staged_content
, blob_id
, staged_blob_id
,
8474 ie
->path
, repo
, patch_cb
, patch_arg
);
8478 if (path_unstaged_content
== NULL
)
8481 if (path_new_staged_content
) {
8482 err
= got_object_blob_create(&new_staged_blob_id
,
8483 path_new_staged_content
, repo
);
8488 f
= fopen(path_unstaged_content
, "re");
8490 err
= got_error_from_errno2("fopen",
8491 path_unstaged_content
);
8494 if (fstat(fileno(f
), &sb
) == -1) {
8495 err
= got_error_from_errno2("fstat", path_unstaged_content
);
8498 if (got_fileindex_entry_staged_filetype_get(ie
) ==
8499 GOT_FILEIDX_MODE_SYMLINK
&& sb
.st_size
< PATH_MAX
) {
8500 char link_target
[PATH_MAX
];
8502 r
= fread(link_target
, 1, sizeof(link_target
), f
);
8503 if (r
== 0 && ferror(f
)) {
8504 err
= got_error_from_errno("fread");
8507 if (r
>= sizeof(link_target
)) { /* should not happen */
8508 err
= got_error(GOT_ERR_NO_SPACE
);
8511 link_target
[r
] = '\0';
8512 err
= merge_symlink(worktree
, blob_base
,
8513 ondisk_path
, ie
->path
, label_orig
, link_target
,
8514 worktree
->base_commit_id
, repo
, progress_cb
,
8517 int local_changes_subsumed
;
8519 err
= got_path_dirname(&parent
, ondisk_path
);
8523 if (asprintf(&base_path
, "%s/got-unstage-blob-orig",
8525 err
= got_error_from_errno("asprintf");
8530 err
= got_opentemp_named(&blob_base_path
, &f_base
, base_path
);
8533 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_base
,
8539 * In order the run a 3-way merge with a symlink we copy the symlink's
8540 * target path into a temporary file and use that file with diff3.
8542 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
8543 err
= dump_symlink_target_path_to_file(&f_deriv2
,
8549 fd
= open(ondisk_path
,
8550 O_RDONLY
| O_NOFOLLOW
| O_CLOEXEC
);
8552 err
= got_error_from_errno2("open", ondisk_path
);
8555 f_deriv2
= fdopen(fd
, "r");
8556 if (f_deriv2
== NULL
) {
8557 err
= got_error_from_errno2("fdopen", ondisk_path
);
8563 err
= merge_file(&local_changes_subsumed
, worktree
,
8564 f_base
, f
, f_deriv2
, ondisk_path
, ie
->path
,
8565 got_fileindex_perms_to_st(ie
),
8566 label_orig
, "unstaged", NULL
, GOT_DIFF_ALGORITHM_MYERS
,
8567 repo
, progress_cb
, progress_arg
);
8572 if (new_staged_blob_id
) {
8573 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
8574 SHA1_DIGEST_LENGTH
);
8576 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
8577 got_fileindex_entry_staged_filetype_set(ie
, 0);
8580 free(new_staged_blob_id
);
8581 if (path_unstaged_content
&&
8582 unlink(path_unstaged_content
) == -1 && err
== NULL
)
8583 err
= got_error_from_errno2("unlink", path_unstaged_content
);
8584 if (path_new_staged_content
&&
8585 unlink(path_new_staged_content
) == -1 && err
== NULL
)
8586 err
= got_error_from_errno2("unlink", path_new_staged_content
);
8587 if (blob_base_path
&& unlink(blob_base_path
) == -1 && err
== NULL
)
8588 err
= got_error_from_errno2("unlink", blob_base_path
);
8589 if (f_base
&& fclose(f_base
) == EOF
&& err
== NULL
)
8590 err
= got_error_from_errno2("fclose", path_unstaged_content
);
8591 if (f
&& fclose(f
) == EOF
&& err
== NULL
)
8592 err
= got_error_from_errno2("fclose", path_unstaged_content
);
8593 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
8594 err
= got_error_from_errno2("fclose", ondisk_path
);
8595 free(path_unstaged_content
);
8596 free(path_new_staged_content
);
8597 free(blob_base_path
);
8603 static const struct got_error
*
8604 unstage_path(void *arg
, unsigned char status
,
8605 unsigned char staged_status
, const char *relpath
,
8606 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
8607 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
8609 const struct got_error
*err
= NULL
;
8610 struct unstage_path_arg
*a
= arg
;
8611 struct got_fileindex_entry
*ie
;
8612 struct got_blob_object
*blob_base
= NULL
, *blob_staged
= NULL
;
8613 char *ondisk_path
= NULL
;
8614 char *id_str
= NULL
, *label_orig
= NULL
;
8615 int local_changes_subsumed
;
8617 int fd1
= -1, fd2
= -1;
8619 if (staged_status
!= GOT_STATUS_ADD
&&
8620 staged_status
!= GOT_STATUS_MODIFY
&&
8621 staged_status
!= GOT_STATUS_DELETE
)
8624 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8626 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8628 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, relpath
)
8630 return got_error_from_errno("asprintf");
8632 err
= got_object_id_str(&id_str
,
8633 commit_id
? commit_id
: a
->worktree
->base_commit_id
);
8636 if (asprintf(&label_orig
, "%s: commit %s", GOT_MERGE_LABEL_BASE
,
8638 err
= got_error_from_errno("asprintf");
8642 fd1
= got_opentempfd();
8644 err
= got_error_from_errno("got_opentempfd");
8647 fd2
= got_opentempfd();
8649 err
= got_error_from_errno("got_opentempfd");
8653 switch (staged_status
) {
8654 case GOT_STATUS_MODIFY
:
8655 err
= got_object_open_as_blob(&blob_base
, a
->repo
,
8656 blob_id
, 8192, fd1
);
8660 case GOT_STATUS_ADD
:
8662 if (staged_status
== GOT_STATUS_ADD
) {
8663 int choice
= GOT_PATCH_CHOICE_NONE
;
8664 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8665 staged_status
, ie
->path
, NULL
, 1, 1);
8668 if (choice
!= GOT_PATCH_CHOICE_YES
)
8671 err
= unstage_hunks(staged_blob_id
,
8672 blob_base
, blob_id
, ie
, ondisk_path
,
8673 label_orig
, a
->worktree
, a
->repo
,
8674 a
->patch_cb
, a
->patch_arg
,
8675 a
->progress_cb
, a
->progress_arg
);
8676 break; /* Done with this file. */
8679 err
= got_object_open_as_blob(&blob_staged
, a
->repo
,
8680 staged_blob_id
, 8192, fd2
);
8683 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
8684 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
8685 case GOT_FILEIDX_MODE_REGULAR_FILE
:
8686 err
= merge_blob(&local_changes_subsumed
, a
->worktree
,
8687 blob_base
, ondisk_path
, relpath
,
8688 got_fileindex_perms_to_st(ie
), label_orig
,
8689 blob_staged
, commit_id
? commit_id
:
8690 a
->worktree
->base_commit_id
, a
->repo
,
8691 a
->progress_cb
, a
->progress_arg
);
8693 case GOT_FILEIDX_MODE_SYMLINK
:
8694 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
8695 char *staged_target
;
8696 err
= got_object_blob_read_to_str(
8697 &staged_target
, blob_staged
);
8700 err
= merge_symlink(a
->worktree
, blob_base
,
8701 ondisk_path
, relpath
, label_orig
,
8702 staged_target
, commit_id
? commit_id
:
8703 a
->worktree
->base_commit_id
,
8704 a
->repo
, a
->progress_cb
, a
->progress_arg
);
8705 free(staged_target
);
8707 err
= merge_blob(&local_changes_subsumed
,
8708 a
->worktree
, blob_base
, ondisk_path
,
8709 relpath
, got_fileindex_perms_to_st(ie
),
8710 label_orig
, blob_staged
,
8711 commit_id
? commit_id
:
8712 a
->worktree
->base_commit_id
, a
->repo
,
8713 a
->progress_cb
, a
->progress_arg
);
8717 err
= got_error_path(relpath
, GOT_ERR_BAD_FILETYPE
);
8721 got_fileindex_entry_stage_set(ie
,
8722 GOT_FILEIDX_STAGE_NONE
);
8723 got_fileindex_entry_staged_filetype_set(ie
, 0);
8726 case GOT_STATUS_DELETE
:
8728 int choice
= GOT_PATCH_CHOICE_NONE
;
8729 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8730 staged_status
, ie
->path
, NULL
, 1, 1);
8733 if (choice
== GOT_PATCH_CHOICE_NO
)
8735 if (choice
!= GOT_PATCH_CHOICE_YES
) {
8736 err
= got_error(GOT_ERR_PATCH_CHOICE
);
8740 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
8741 got_fileindex_entry_staged_filetype_set(ie
, 0);
8742 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
8743 dirfd
, de_name
, a
->repo
);
8746 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, relpath
);
8751 if (fd1
!= -1 && close(fd1
) == -1 && err
== NULL
)
8752 err
= got_error_from_errno("close");
8754 got_object_blob_close(blob_base
);
8755 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
8756 err
= got_error_from_errno("close");
8758 got_object_blob_close(blob_staged
);
8764 const struct got_error
*
8765 got_worktree_unstage(struct got_worktree
*worktree
,
8766 struct got_pathlist_head
*paths
,
8767 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
8768 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8769 struct got_repository
*repo
)
8771 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8772 struct got_pathlist_entry
*pe
;
8773 struct got_fileindex
*fileindex
= NULL
;
8774 char *fileindex_path
= NULL
;
8775 struct unstage_path_arg upa
;
8777 err
= lock_worktree(worktree
, LOCK_EX
);
8781 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8785 upa
.worktree
= worktree
;
8786 upa
.fileindex
= fileindex
;
8788 upa
.progress_cb
= progress_cb
;
8789 upa
.progress_arg
= progress_arg
;
8790 upa
.patch_cb
= patch_cb
;
8791 upa
.patch_arg
= patch_arg
;
8792 TAILQ_FOREACH(pe
, paths
, entry
) {
8793 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8794 unstage_path
, &upa
, NULL
, NULL
, 1, 0);
8799 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8800 if (sync_err
&& err
== NULL
)
8803 free(fileindex_path
);
8805 got_fileindex_free(fileindex
);
8806 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8807 if (unlockerr
&& err
== NULL
)
8812 struct report_file_info_arg
{
8813 struct got_worktree
*worktree
;
8814 got_worktree_path_info_cb info_cb
;
8816 struct got_pathlist_head
*paths
;
8817 got_cancel_cb cancel_cb
;
8821 static const struct got_error
*
8822 report_file_info(void *arg
, struct got_fileindex_entry
*ie
)
8824 struct report_file_info_arg
*a
= arg
;
8825 struct got_pathlist_entry
*pe
;
8826 struct got_object_id blob_id
, staged_blob_id
, commit_id
;
8827 struct got_object_id
*blob_idp
= NULL
, *staged_blob_idp
= NULL
;
8828 struct got_object_id
*commit_idp
= NULL
;
8831 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
8832 return got_error(GOT_ERR_CANCELLED
);
8834 TAILQ_FOREACH(pe
, a
->paths
, entry
) {
8835 if (pe
->path_len
== 0 || strcmp(pe
->path
, ie
->path
) == 0 ||
8836 got_path_is_child(ie
->path
, pe
->path
, pe
->path_len
))
8839 if (pe
== NULL
) /* not found */
8842 if (got_fileindex_entry_has_blob(ie
)) {
8843 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
8844 blob_idp
= &blob_id
;
8846 stage
= got_fileindex_entry_stage_get(ie
);
8847 if (stage
== GOT_FILEIDX_STAGE_MODIFY
||
8848 stage
== GOT_FILEIDX_STAGE_ADD
) {
8849 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
8850 SHA1_DIGEST_LENGTH
);
8851 staged_blob_idp
= &staged_blob_id
;
8854 if (got_fileindex_entry_has_commit(ie
)) {
8855 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
8856 commit_idp
= &commit_id
;
8859 return a
->info_cb(a
->info_arg
, ie
->path
, got_fileindex_perms_to_st(ie
),
8860 (time_t)ie
->mtime_sec
, blob_idp
, staged_blob_idp
, commit_idp
);
8863 const struct got_error
*
8864 got_worktree_path_info(struct got_worktree
*worktree
,
8865 struct got_pathlist_head
*paths
,
8866 got_worktree_path_info_cb info_cb
, void *info_arg
,
8867 got_cancel_cb cancel_cb
, void *cancel_arg
)
8870 const struct got_error
*err
= NULL
, *unlockerr
;
8871 struct got_fileindex
*fileindex
= NULL
;
8872 char *fileindex_path
= NULL
;
8873 struct report_file_info_arg arg
;
8875 err
= lock_worktree(worktree
, LOCK_SH
);
8879 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8883 arg
.worktree
= worktree
;
8884 arg
.info_cb
= info_cb
;
8885 arg
.info_arg
= info_arg
;
8887 arg
.cancel_cb
= cancel_cb
;
8888 arg
.cancel_arg
= cancel_arg
;
8889 err
= got_fileindex_for_each_entry_safe(fileindex
, report_file_info
,
8892 free(fileindex_path
);
8894 got_fileindex_free(fileindex
);
8895 unlockerr
= lock_worktree(worktree
, LOCK_UN
);
8896 if (unlockerr
&& err
== NULL
)
8901 static const struct got_error
*
8902 patch_check_path(const char *p
, char **path
, unsigned char *status
,
8903 unsigned char *staged_status
, struct got_fileindex
*fileindex
,
8904 struct got_worktree
*worktree
, struct got_repository
*repo
)
8906 const struct got_error
*err
;
8907 struct got_fileindex_entry
*ie
;
8909 char *ondisk_path
= NULL
;
8911 err
= got_worktree_resolve_path(path
, worktree
, p
);
8915 if (asprintf(&ondisk_path
, "%s%s%s", worktree
->root_path
,
8916 *path
[0] ? "/" : "", *path
) == -1)
8917 return got_error_from_errno("asprintf");
8919 ie
= got_fileindex_entry_get(fileindex
, *path
, strlen(*path
));
8921 *staged_status
= get_staged_status(ie
);
8922 err
= get_file_status(status
, &sb
, ie
, ondisk_path
, -1, NULL
,
8927 *staged_status
= GOT_STATUS_NO_CHANGE
;
8928 *status
= GOT_STATUS_UNVERSIONED
;
8929 if (lstat(ondisk_path
, &sb
) == -1) {
8930 if (errno
!= ENOENT
) {
8931 err
= got_error_from_errno2("lstat",
8935 *status
= GOT_STATUS_NONEXISTENT
;
8944 static const struct got_error
*
8945 patch_can_rm(const char *path
, unsigned char status
,
8946 unsigned char staged_status
)
8948 if (status
== GOT_STATUS_NONEXISTENT
)
8949 return got_error_set_errno(ENOENT
, path
);
8950 if (status
!= GOT_STATUS_NO_CHANGE
&&
8951 status
!= GOT_STATUS_ADD
&&
8952 status
!= GOT_STATUS_MODIFY
&&
8953 status
!= GOT_STATUS_MODE_CHANGE
)
8954 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
8955 if (staged_status
== GOT_STATUS_DELETE
)
8956 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
8960 static const struct got_error
*
8961 patch_can_add(const char *path
, unsigned char status
)
8963 if (status
!= GOT_STATUS_NONEXISTENT
)
8964 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
8968 static const struct got_error
*
8969 patch_can_edit(const char *path
, unsigned char status
,
8970 unsigned char staged_status
)
8972 if (status
== GOT_STATUS_NONEXISTENT
)
8973 return got_error_set_errno(ENOENT
, path
);
8974 if (status
!= GOT_STATUS_NO_CHANGE
&&
8975 status
!= GOT_STATUS_ADD
&&
8976 status
!= GOT_STATUS_MODIFY
)
8977 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
8978 if (staged_status
== GOT_STATUS_DELETE
)
8979 return got_error_path(path
, GOT_ERR_FILE_STATUS
);
8983 const struct got_error
*
8984 got_worktree_patch_prepare(struct got_fileindex
**fileindex
,
8985 char **fileindex_path
, struct got_worktree
*worktree
)
8987 return open_fileindex(fileindex
, fileindex_path
, worktree
);
8990 const struct got_error
*
8991 got_worktree_patch_check_path(const char *old
, const char *new,
8992 char **oldpath
, char **newpath
, struct got_worktree
*worktree
,
8993 struct got_repository
*repo
, struct got_fileindex
*fileindex
)
8995 const struct got_error
*err
= NULL
;
8996 int file_renamed
= 0;
8997 unsigned char status_old
, staged_status_old
;
8998 unsigned char status_new
, staged_status_new
;
9003 err
= patch_check_path(old
!= NULL
? old
: new, oldpath
,
9004 &status_old
, &staged_status_old
, fileindex
, worktree
, repo
);
9008 err
= patch_check_path(new != NULL
? new : old
, newpath
,
9009 &status_new
, &staged_status_new
, fileindex
, worktree
, repo
);
9013 if (old
!= NULL
&& new != NULL
&& strcmp(old
, new) != 0)
9016 if (old
!= NULL
&& new == NULL
)
9017 err
= patch_can_rm(*oldpath
, status_old
, staged_status_old
);
9018 else if (file_renamed
) {
9019 err
= patch_can_rm(*oldpath
, status_old
, staged_status_old
);
9021 err
= patch_can_add(*newpath
, status_new
);
9022 } else if (old
== NULL
)
9023 err
= patch_can_add(*newpath
, status_new
);
9025 err
= patch_can_edit(*newpath
, status_new
, staged_status_new
);
9037 const struct got_error
*
9038 got_worktree_patch_schedule_add(const char *path
, struct got_repository
*repo
,
9039 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
9040 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
9042 struct schedule_addition_args saa
;
9044 memset(&saa
, 0, sizeof(saa
));
9045 saa
.worktree
= worktree
;
9046 saa
.fileindex
= fileindex
;
9047 saa
.progress_cb
= progress_cb
;
9048 saa
.progress_arg
= progress_arg
;
9051 return worktree_status(worktree
, path
, fileindex
, repo
,
9052 schedule_addition
, &saa
, NULL
, NULL
, 1, 0);
9055 const struct got_error
*
9056 got_worktree_patch_schedule_rm(const char *path
, struct got_repository
*repo
,
9057 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
9058 got_worktree_delete_cb progress_cb
, void *progress_arg
)
9060 struct schedule_deletion_args sda
;
9062 memset(&sda
, 0, sizeof(sda
));
9063 sda
.worktree
= worktree
;
9064 sda
.fileindex
= fileindex
;
9065 sda
.progress_cb
= progress_cb
;
9066 sda
.progress_arg
= progress_arg
;
9068 sda
.delete_local_mods
= 0;
9069 sda
.keep_on_disk
= 0;
9070 sda
.ignore_missing_paths
= 0;
9071 sda
.status_codes
= NULL
;
9073 return worktree_status(worktree
, path
, fileindex
, repo
,
9074 schedule_for_deletion
, &sda
, NULL
, NULL
, 1, 1);
9077 const struct got_error
*
9078 got_worktree_patch_complete(struct got_fileindex
*fileindex
,
9079 const char *fileindex_path
)
9081 const struct got_error
*err
= NULL
;
9083 err
= sync_fileindex(fileindex
, fileindex_path
);
9084 got_fileindex_free(fileindex
);