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.
34 #include "got_compat.h"
36 #include "got_error.h"
37 #include "got_repository.h"
38 #include "got_reference.h"
39 #include "got_object.h"
41 #include "got_cancel.h"
42 #include "got_worktree.h"
43 #include "got_opentemp.h"
46 #include "got_lib_worktree.h"
47 #include "got_lib_sha1.h"
48 #include "got_lib_fileindex.h"
49 #include "got_lib_inflate.h"
50 #include "got_lib_delta.h"
51 #include "got_lib_object.h"
52 #include "got_lib_object_parse.h"
53 #include "got_lib_object_create.h"
54 #include "got_lib_object_idset.h"
55 #include "got_lib_diff.h"
56 #include "got_lib_gotconfig.h"
59 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
62 #define GOT_MERGE_LABEL_MERGED "merged change"
63 #define GOT_MERGE_LABEL_BASE "3-way merge base"
65 static const struct got_error
*
66 create_meta_file(const char *path_got
, const char *name
, const char *content
)
68 const struct got_error
*err
= NULL
;
71 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1)
72 return got_error_from_errno("asprintf");
74 err
= got_path_create_file(path
, content
);
79 static const struct got_error
*
80 update_meta_file(const char *path_got
, const char *name
, const char *content
)
82 const struct got_error
*err
= NULL
;
87 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1) {
88 err
= got_error_from_errno("asprintf");
93 err
= got_opentemp_named(&tmppath
, &tmpfile
, path
);
98 int len
= fprintf(tmpfile
, "%s\n", content
);
99 if (len
!= strlen(content
) + 1) {
100 err
= got_error_from_errno2("fprintf", tmppath
);
105 if (rename(tmppath
, path
) != 0) {
106 err
= got_error_from_errno3("rename", tmppath
, path
);
112 if (fclose(tmpfile
) == EOF
&& err
== NULL
)
113 err
= got_error_from_errno2("fclose", tmppath
);
118 static const struct got_error
*
119 read_meta_file(char **content
, const char *path_got
, const char *name
)
121 const struct got_error
*err
= NULL
;
129 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1) {
130 err
= got_error_from_errno("asprintf");
135 fd
= open(path
, O_RDONLY
| O_NOFOLLOW
);
138 err
= got_error_path(path
, GOT_ERR_WORKTREE_META
);
140 err
= got_error_from_errno2("open", path
);
143 if (flock(fd
, LOCK_SH
| LOCK_NB
) == -1) {
144 err
= (errno
== EWOULDBLOCK
? got_error(GOT_ERR_WORKTREE_BUSY
)
145 : got_error_from_errno2("flock", path
));
149 if (fstat(fd
, &sb
) != 0) {
150 err
= got_error_from_errno2("fstat", path
);
153 *content
= calloc(1, sb
.st_size
);
154 if (*content
== NULL
) {
155 err
= got_error_from_errno("calloc");
159 n
= read(fd
, *content
, sb
.st_size
);
160 if (n
!= sb
.st_size
) {
161 err
= (n
== -1 ? got_error_from_errno2("read", path
) :
162 got_error_path(path
, GOT_ERR_WORKTREE_META
));
165 if ((*content
)[sb
.st_size
- 1] != '\n') {
166 err
= got_error_path(path
, GOT_ERR_WORKTREE_META
);
169 (*content
)[sb
.st_size
- 1] = '\0';
172 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
173 err
= got_error_from_errno2("close", path_got
);
182 static const struct got_error
*
183 write_head_ref(const char *path_got
, struct got_reference
*head_ref
)
185 const struct got_error
*err
= NULL
;
188 if (got_ref_is_symbolic(head_ref
)) {
189 refstr
= got_ref_to_str(head_ref
);
191 return got_error_from_errno("got_ref_to_str");
193 refstr
= strdup(got_ref_get_name(head_ref
));
195 return got_error_from_errno("strdup");
197 err
= update_meta_file(path_got
, GOT_WORKTREE_HEAD_REF
, refstr
);
202 const struct got_error
*
203 got_worktree_init(const char *path
, struct got_reference
*head_ref
,
204 const char *prefix
, struct got_repository
*repo
)
206 const struct got_error
*err
= NULL
;
207 struct got_object_id
*commit_id
= NULL
;
209 uint32_t uuid_status
;
211 char *path_got
= NULL
;
212 char *formatstr
= NULL
;
213 char *absprefix
= NULL
;
214 char *basestr
= NULL
;
215 char *uuidstr
= NULL
;
217 if (strcmp(path
, got_repo_get_path(repo
)) == 0) {
218 err
= got_error(GOT_ERR_WORKTREE_REPO
);
222 err
= got_ref_resolve(&commit_id
, repo
, head_ref
);
225 err
= got_object_get_type(&obj_type
, repo
, commit_id
);
228 if (obj_type
!= GOT_OBJ_TYPE_COMMIT
)
229 return got_error(GOT_ERR_OBJ_TYPE
);
231 if (!got_path_is_absolute(prefix
)) {
232 if (asprintf(&absprefix
, "/%s", prefix
) == -1)
233 return got_error_from_errno("asprintf");
236 /* Create top-level directory (may already exist). */
237 if (mkdir(path
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
238 err
= got_error_from_errno2("mkdir", path
);
242 /* Create .got directory (may already exist). */
243 if (asprintf(&path_got
, "%s/%s", path
, GOT_WORKTREE_GOT_DIR
) == -1) {
244 err
= got_error_from_errno("asprintf");
247 if (mkdir(path_got
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
248 err
= got_error_from_errno2("mkdir", path_got
);
252 /* Create an empty lock file. */
253 err
= create_meta_file(path_got
, GOT_WORKTREE_LOCK
, NULL
);
257 /* Create an empty file index. */
258 err
= create_meta_file(path_got
, GOT_WORKTREE_FILE_INDEX
, NULL
);
262 /* Write the HEAD reference. */
263 err
= write_head_ref(path_got
, head_ref
);
267 /* Record our base commit. */
268 err
= got_object_id_str(&basestr
, commit_id
);
271 err
= create_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, basestr
);
275 /* Store path to repository. */
276 err
= create_meta_file(path_got
, GOT_WORKTREE_REPOSITORY
,
277 got_repo_get_path(repo
));
281 /* Store in-repository path prefix. */
282 err
= create_meta_file(path_got
, GOT_WORKTREE_PATH_PREFIX
,
283 absprefix
? absprefix
: prefix
);
288 uuid_create(&uuid
, &uuid_status
);
289 if (uuid_status
!= uuid_s_ok
) {
290 err
= got_error_uuid(uuid_status
, "uuid_create");
293 uuid_to_string(&uuid
, &uuidstr
, &uuid_status
);
294 if (uuid_status
!= uuid_s_ok
) {
295 err
= got_error_uuid(uuid_status
, "uuid_to_string");
298 err
= create_meta_file(path_got
, GOT_WORKTREE_UUID
, uuidstr
);
302 /* Stamp work tree with format file. */
303 if (asprintf(&formatstr
, "%d", GOT_WORKTREE_FORMAT_VERSION
) == -1) {
304 err
= got_error_from_errno("asprintf");
307 err
= create_meta_file(path_got
, GOT_WORKTREE_FORMAT
, formatstr
);
321 static const struct got_error
*
322 open_worktree(struct got_worktree
**worktree
, const char *path
)
324 const struct got_error
*err
= NULL
;
326 char *formatstr
= NULL
;
327 char *uuidstr
= NULL
;
328 char *path_lock
= NULL
;
329 char *base_commit_id_str
= NULL
;
330 int version
, fd
= -1;
332 struct got_repository
*repo
= NULL
;
333 uint32_t uuid_status
;
337 if (asprintf(&path_got
, "%s/%s", path
, GOT_WORKTREE_GOT_DIR
) == -1) {
338 err
= got_error_from_errno("asprintf");
343 if (asprintf(&path_lock
, "%s/%s", path_got
, GOT_WORKTREE_LOCK
) == -1) {
344 err
= got_error_from_errno("asprintf");
349 fd
= open(path_lock
, O_RDWR
| O_EXLOCK
| O_NONBLOCK
);
351 err
= (errno
== EWOULDBLOCK
? got_error(GOT_ERR_WORKTREE_BUSY
)
352 : got_error_from_errno2("open", path_lock
));
356 err
= read_meta_file(&formatstr
, path_got
, GOT_WORKTREE_FORMAT
);
360 version
= strtonum(formatstr
, 1, INT_MAX
, &errstr
);
362 err
= got_error_msg(GOT_ERR_WORKTREE_META
,
363 "could not parse work tree format version number");
366 if (version
!= GOT_WORKTREE_FORMAT_VERSION
) {
367 err
= got_error(GOT_ERR_WORKTREE_VERS
);
371 *worktree
= calloc(1, sizeof(**worktree
));
372 if (*worktree
== NULL
) {
373 err
= got_error_from_errno("calloc");
376 (*worktree
)->lockfd
= -1;
378 (*worktree
)->root_path
= realpath(path
, NULL
);
379 if ((*worktree
)->root_path
== NULL
) {
380 err
= got_error_from_errno2("realpath", path
);
383 err
= read_meta_file(&(*worktree
)->repo_path
, path_got
,
384 GOT_WORKTREE_REPOSITORY
);
388 err
= read_meta_file(&(*worktree
)->path_prefix
, path_got
,
389 GOT_WORKTREE_PATH_PREFIX
);
393 err
= read_meta_file(&base_commit_id_str
, path_got
,
394 GOT_WORKTREE_BASE_COMMIT
);
398 err
= read_meta_file(&uuidstr
, path_got
, GOT_WORKTREE_UUID
);
401 uuid_from_string(uuidstr
, &(*worktree
)->uuid
, &uuid_status
);
402 if (uuid_status
!= uuid_s_ok
) {
403 err
= got_error_uuid(uuid_status
, "uuid_from_string");
407 err
= got_repo_open(&repo
, (*worktree
)->repo_path
, NULL
);
411 err
= got_object_resolve_id_str(&(*worktree
)->base_commit_id
, repo
,
416 err
= read_meta_file(&(*worktree
)->head_ref_name
, path_got
,
417 GOT_WORKTREE_HEAD_REF
);
421 if (asprintf(&(*worktree
)->gotconfig_path
, "%s/%s/%s",
422 (*worktree
)->root_path
,
423 GOT_WORKTREE_GOT_DIR
, GOT_GOTCONFIG_FILENAME
) == -1) {
424 err
= got_error_from_errno("asprintf");
428 err
= got_gotconfig_read(&(*worktree
)->gotconfig
,
429 (*worktree
)->gotconfig_path
);
431 (*worktree
)->root_fd
= open((*worktree
)->root_path
, O_DIRECTORY
);
432 if ((*worktree
)->root_fd
== -1) {
433 err
= got_error_from_errno2("open", (*worktree
)->root_path
);
438 const struct got_error
*close_err
= got_repo_close(repo
);
444 free(base_commit_id_str
);
450 if (*worktree
!= NULL
)
451 got_worktree_close(*worktree
);
454 (*worktree
)->lockfd
= fd
;
459 const struct got_error
*
460 got_worktree_open(struct got_worktree
**worktree
, const char *path
)
462 const struct got_error
*err
= NULL
;
465 worktree_path
= strdup(path
);
466 if (worktree_path
== NULL
)
467 return got_error_from_errno("strdup");
472 err
= open_worktree(worktree
, worktree_path
);
473 if (err
&& !(err
->code
== GOT_ERR_ERRNO
&& errno
== ENOENT
)) {
481 if (worktree_path
[0] == '/' && worktree_path
[1] == '\0')
483 err
= got_path_dirname(&parent_path
, worktree_path
);
485 if (err
->code
!= GOT_ERR_BAD_PATH
) {
492 worktree_path
= parent_path
;
496 return got_error(GOT_ERR_NOT_WORKTREE
);
499 const struct got_error
*
500 got_worktree_close(struct got_worktree
*worktree
)
502 const struct got_error
*err
= NULL
;
504 if (worktree
->lockfd
!= -1) {
505 if (close(worktree
->lockfd
) == -1)
506 err
= got_error_from_errno2("close",
507 got_worktree_get_root_path(worktree
));
509 if (close(worktree
->root_fd
) == -1 && err
== NULL
)
510 err
= got_error_from_errno2("close",
511 got_worktree_get_root_path(worktree
));
512 free(worktree
->repo_path
);
513 free(worktree
->path_prefix
);
514 free(worktree
->base_commit_id
);
515 free(worktree
->head_ref_name
);
516 free(worktree
->root_path
);
517 free(worktree
->gotconfig_path
);
518 got_gotconfig_free(worktree
->gotconfig
);
524 got_worktree_get_root_path(struct got_worktree
*worktree
)
526 return worktree
->root_path
;
530 got_worktree_get_repo_path(struct got_worktree
*worktree
)
532 return worktree
->repo_path
;
535 got_worktree_get_path_prefix(struct got_worktree
*worktree
)
537 return worktree
->path_prefix
;
540 const struct got_error
*
541 got_worktree_match_path_prefix(int *match
, struct got_worktree
*worktree
,
542 const char *path_prefix
)
544 char *absprefix
= NULL
;
546 if (!got_path_is_absolute(path_prefix
)) {
547 if (asprintf(&absprefix
, "/%s", path_prefix
) == -1)
548 return got_error_from_errno("asprintf");
550 *match
= (strcmp(absprefix
? absprefix
: path_prefix
,
551 worktree
->path_prefix
) == 0);
557 got_worktree_get_head_ref_name(struct got_worktree
*worktree
)
559 return worktree
->head_ref_name
;
562 const struct got_error
*
563 got_worktree_set_head_ref(struct got_worktree
*worktree
,
564 struct got_reference
*head_ref
)
566 const struct got_error
*err
= NULL
;
567 char *path_got
= NULL
, *head_ref_name
= NULL
;
569 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
570 GOT_WORKTREE_GOT_DIR
) == -1) {
571 err
= got_error_from_errno("asprintf");
576 head_ref_name
= strdup(got_ref_get_name(head_ref
));
577 if (head_ref_name
== NULL
) {
578 err
= got_error_from_errno("strdup");
582 err
= write_head_ref(path_got
, head_ref
);
586 free(worktree
->head_ref_name
);
587 worktree
->head_ref_name
= head_ref_name
;
595 struct got_object_id
*
596 got_worktree_get_base_commit_id(struct got_worktree
*worktree
)
598 return worktree
->base_commit_id
;
601 const struct got_error
*
602 got_worktree_set_base_commit_id(struct got_worktree
*worktree
,
603 struct got_repository
*repo
, struct got_object_id
*commit_id
)
605 const struct got_error
*err
;
606 struct got_object
*obj
= NULL
;
608 char *path_got
= NULL
;
610 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
611 GOT_WORKTREE_GOT_DIR
) == -1) {
612 err
= got_error_from_errno("asprintf");
617 err
= got_object_open(&obj
, repo
, commit_id
);
621 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
622 err
= got_error(GOT_ERR_OBJ_TYPE
);
626 /* Record our base commit. */
627 err
= got_object_id_str(&id_str
, commit_id
);
630 err
= update_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, id_str
);
634 free(worktree
->base_commit_id
);
635 worktree
->base_commit_id
= got_object_id_dup(commit_id
);
636 if (worktree
->base_commit_id
== NULL
) {
637 err
= got_error_from_errno("got_object_id_dup");
642 got_object_close(obj
);
648 const struct got_gotconfig
*
649 got_worktree_get_gotconfig(struct got_worktree
*worktree
)
651 return worktree
->gotconfig
;
654 static const struct got_error
*
655 lock_worktree(struct got_worktree
*worktree
, int operation
)
657 if (flock(worktree
->lockfd
, operation
| LOCK_NB
) == -1)
658 return (errno
== EWOULDBLOCK
? got_error(GOT_ERR_WORKTREE_BUSY
)
659 : got_error_from_errno2("flock",
660 got_worktree_get_root_path(worktree
)));
664 static const struct got_error
*
665 add_dir_on_disk(struct got_worktree
*worktree
, const char *path
)
667 const struct got_error
*err
= NULL
;
670 if (asprintf(&abspath
, "%s/%s", worktree
->root_path
, path
) == -1)
671 return got_error_from_errno("asprintf");
673 err
= got_path_mkdir(abspath
);
674 if (err
&& err
->code
== GOT_ERR_ERRNO
&& errno
== EEXIST
) {
677 if (lstat(abspath
, &sb
) == -1) {
678 err
= got_error_from_errno2("lstat", abspath
);
679 } else if (!S_ISDIR(sb
.st_mode
)) {
680 /* TODO directory is obstructed; do something */
681 err
= got_error_path(abspath
, GOT_ERR_FILE_OBSTRUCTED
);
688 static const struct got_error
*
689 check_file_contents_equal(int *same
, FILE *f1
, FILE *f2
)
691 const struct got_error
*err
= NULL
;
694 size_t flen1
= 0, flen2
= 0;
699 flen1
= fread(fbuf1
, 1, sizeof(fbuf1
), f1
);
700 if (flen1
== 0 && ferror(f1
)) {
701 err
= got_error_from_errno("fread");
704 flen2
= fread(fbuf2
, 1, sizeof(fbuf2
), f2
);
705 if (flen2
== 0 && ferror(f2
)) {
706 err
= got_error_from_errno("fread");
713 } else if (flen2
== 0) {
717 } else if (flen1
== flen2
) {
718 if (memcmp(fbuf1
, fbuf2
, flen2
) != 0) {
731 static const struct got_error
*
732 check_files_equal(int *same
, FILE *f1
, FILE *f2
)
739 if (fstat(fileno(f1
), &sb
) != 0)
740 return got_error_from_errno("fstat");
743 if (fstat(fileno(f2
), &sb
) != 0)
744 return got_error_from_errno("fstat");
747 if (size1
!= size2
) {
752 if (fseek(f1
, 0L, SEEK_SET
) == -1)
753 return got_ferror(f1
, GOT_ERR_IO
);
754 if (fseek(f2
, 0L, SEEK_SET
) == -1)
755 return got_ferror(f2
, GOT_ERR_IO
);
757 return check_file_contents_equal(same
, f1
, f2
);
761 * Perform a 3-way merge where the file f_orig acts as the common
762 * ancestor, the file f_deriv acts as the first derived version,
763 * and the file f_deriv2 acts as the second derived version.
764 * The merge result will be written to a new file at ondisk_path; any
765 * existing file at this path will be replaced.
767 static const struct got_error
*
768 merge_file(int *local_changes_subsumed
, struct got_worktree
*worktree
,
769 FILE *f_orig
, FILE *f_deriv
, FILE *f_deriv2
, const char *ondisk_path
,
770 const char *path
, uint16_t st_mode
,
771 const char *label_orig
, const char *label_deriv
, const char *label_deriv2
,
772 enum got_diff_algorithm diff_algo
, struct got_repository
*repo
,
773 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
775 const struct got_error
*err
= NULL
;
777 FILE *f_merged
= NULL
;
778 char *merged_path
= NULL
, *base_path
= NULL
;
782 *local_changes_subsumed
= 0;
784 err
= got_path_dirname(&parent
, ondisk_path
);
788 if (asprintf(&base_path
, "%s/got-merged", parent
) == -1) {
789 err
= got_error_from_errno("asprintf");
793 err
= got_opentemp_named_fd(&merged_path
, &merged_fd
, base_path
);
797 err
= got_merge_diff3(&overlapcnt
, merged_fd
, f_deriv
, f_orig
,
798 f_deriv2
, label_deriv
, label_orig
, label_deriv2
, diff_algo
);
802 err
= (*progress_cb
)(progress_arg
,
803 overlapcnt
> 0 ? GOT_STATUS_CONFLICT
: GOT_STATUS_MERGE
, path
);
807 if (fsync(merged_fd
) != 0) {
808 err
= got_error_from_errno("fsync");
812 f_merged
= fdopen(merged_fd
, "r");
813 if (f_merged
== NULL
) {
814 err
= got_error_from_errno("fdopen");
819 /* Check if a clean merge has subsumed all local changes. */
820 if (overlapcnt
== 0) {
821 err
= check_files_equal(local_changes_subsumed
, f_deriv
,
827 if (fchmod(fileno(f_merged
), st_mode
) != 0) {
828 err
= got_error_from_errno2("fchmod", merged_path
);
832 if (rename(merged_path
, ondisk_path
) != 0) {
833 err
= got_error_from_errno3("rename", merged_path
,
842 if (merged_fd
!= -1 && close(merged_fd
) == -1 && err
== NULL
)
843 err
= got_error_from_errno("close");
844 if (f_merged
&& fclose(f_merged
) == EOF
&& err
== NULL
)
845 err
= got_error_from_errno("fclose");
852 static const struct got_error
*
853 update_symlink(const char *ondisk_path
, const char *target_path
,
856 /* This is not atomic but matches what 'ln -sf' does. */
857 if (unlink(ondisk_path
) == -1)
858 return got_error_from_errno2("unlink", ondisk_path
);
859 if (symlink(target_path
, ondisk_path
) == -1)
860 return got_error_from_errno3("symlink", target_path
,
866 * Overwrite a symlink (or a regular file in case there was a "bad" symlink)
867 * in the work tree with a file that contains conflict markers and the
868 * conflicting target paths of the original version, a "derived version"
869 * of a symlink from an incoming change, and a local version of the symlink.
871 * The original versions's target path can be NULL if it is not available,
872 * such as if both derived versions added a new symlink at the same path.
874 * The incoming derived symlink target is NULL in case the incoming change
875 * has deleted this symlink.
877 static const struct got_error
*
878 install_symlink_conflict(const char *deriv_target
,
879 struct got_object_id
*deriv_base_commit_id
, const char *orig_target
,
880 const char *label_orig
, const char *local_target
, const char *ondisk_path
)
882 const struct got_error
*err
;
883 char *id_str
= NULL
, *label_deriv
= NULL
, *path
= NULL
;
886 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
888 return got_error_from_errno("asprintf");
890 if (asprintf(&label_deriv
, "%s: commit %s",
891 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
892 err
= got_error_from_errno("asprintf");
896 err
= got_opentemp_named(&path
, &f
, "got-symlink-conflict");
900 if (fchmod(fileno(f
), GOT_DEFAULT_FILE_MODE
) == -1) {
901 err
= got_error_from_errno2("fchmod", path
);
905 if (fprintf(f
, "%s %s\n%s\n%s%s%s%s%s\n%s\n%s\n",
906 GOT_DIFF_CONFLICT_MARKER_BEGIN
, label_deriv
,
907 deriv_target
? deriv_target
: "(symlink was deleted)",
908 orig_target
? label_orig
: "",
909 orig_target
? "\n" : "",
910 orig_target
? orig_target
: "",
911 orig_target
? "\n" : "",
912 GOT_DIFF_CONFLICT_MARKER_SEP
,
913 local_target
, GOT_DIFF_CONFLICT_MARKER_END
) < 0) {
914 err
= got_error_from_errno2("fprintf", path
);
918 if (unlink(ondisk_path
) == -1) {
919 err
= got_error_from_errno2("unlink", ondisk_path
);
922 if (rename(path
, ondisk_path
) == -1) {
923 err
= got_error_from_errno3("rename", path
, ondisk_path
);
927 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
928 err
= got_error_from_errno2("fclose", path
);
935 /* forward declaration */
936 static const struct got_error
*
937 merge_blob(int *, struct got_worktree
*, struct got_blob_object
*,
938 const char *, const char *, uint16_t, const char *,
939 struct got_blob_object
*, struct got_object_id
*,
940 struct got_repository
*, got_worktree_checkout_cb
, void *);
943 * Merge a symlink into the work tree, where blob_orig acts as the common
944 * ancestor, deriv_target is the link target of the first derived version,
945 * and the symlink on disk acts as the second derived version.
946 * Assume that contents of both blobs represent symlinks.
948 static const struct got_error
*
949 merge_symlink(struct got_worktree
*worktree
,
950 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
951 const char *path
, const char *label_orig
, const char *deriv_target
,
952 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
953 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
955 const struct got_error
*err
= NULL
;
956 char *ancestor_target
= NULL
;
958 ssize_t ondisk_len
, deriv_len
;
959 char ondisk_target
[PATH_MAX
];
960 int have_local_change
= 0;
961 int have_incoming_change
= 0;
963 if (lstat(ondisk_path
, &sb
) == -1)
964 return got_error_from_errno2("lstat", ondisk_path
);
966 ondisk_len
= readlink(ondisk_path
, ondisk_target
,
967 sizeof(ondisk_target
));
968 if (ondisk_len
== -1) {
969 err
= got_error_from_errno2("readlink",
973 ondisk_target
[ondisk_len
] = '\0';
976 err
= got_object_blob_read_to_str(&ancestor_target
, blob_orig
);
981 if (ancestor_target
== NULL
||
982 (ondisk_len
!= strlen(ancestor_target
) ||
983 memcmp(ondisk_target
, ancestor_target
, ondisk_len
) != 0))
984 have_local_change
= 1;
986 deriv_len
= strlen(deriv_target
);
987 if (ancestor_target
== NULL
||
988 (deriv_len
!= strlen(ancestor_target
) ||
989 memcmp(deriv_target
, ancestor_target
, deriv_len
) != 0))
990 have_incoming_change
= 1;
992 if (!have_local_change
&& !have_incoming_change
) {
993 if (ancestor_target
) {
994 /* Both sides made the same change. */
995 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
997 } else if (deriv_len
== ondisk_len
&&
998 memcmp(ondisk_target
, deriv_target
, deriv_len
) == 0) {
999 /* Both sides added the same symlink. */
1000 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
1003 /* Both sides added symlinks which don't match. */
1004 err
= install_symlink_conflict(deriv_target
,
1005 deriv_base_commit_id
, ancestor_target
,
1006 label_orig
, ondisk_target
, ondisk_path
);
1009 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
1012 } else if (!have_local_change
&& have_incoming_change
) {
1013 /* Apply the incoming change. */
1014 err
= update_symlink(ondisk_path
, deriv_target
,
1015 strlen(deriv_target
));
1018 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
1019 } else if (have_local_change
&& have_incoming_change
) {
1020 if (deriv_len
== ondisk_len
&&
1021 memcmp(deriv_target
, ondisk_target
, deriv_len
) == 0) {
1022 /* Both sides made the same change. */
1023 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
1026 err
= install_symlink_conflict(deriv_target
,
1027 deriv_base_commit_id
, ancestor_target
, label_orig
,
1028 ondisk_target
, ondisk_path
);
1031 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
1037 free(ancestor_target
);
1041 static const struct got_error
*
1042 dump_symlink_target_path_to_file(FILE **outfile
, const char *ondisk_path
)
1044 const struct got_error
*err
= NULL
;
1045 char target_path
[PATH_MAX
];
1054 return got_error_from_errno("got_opentemp");
1055 target_len
= readlink(ondisk_path
, target_path
, sizeof(target_path
));
1056 if (target_len
== -1) {
1057 err
= got_error_from_errno2("readlink", ondisk_path
);
1060 n
= fwrite(target_path
, 1, target_len
, f
);
1061 if (n
!= target_len
) {
1062 err
= got_ferror(f
, GOT_ERR_IO
);
1065 if (fflush(f
) == EOF
) {
1066 err
= got_error_from_errno("fflush");
1069 if (fseek(f
, 0L, SEEK_SET
) == -1) {
1070 err
= got_ferror(f
, GOT_ERR_IO
);
1082 * Perform a 3-way merge where blob_orig acts as the common ancestor,
1083 * blob_deriv acts as the first derived version, and the file on disk
1084 * acts as the second derived version.
1086 static const struct got_error
*
1087 merge_blob(int *local_changes_subsumed
, struct got_worktree
*worktree
,
1088 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
1089 const char *path
, uint16_t st_mode
, const char *label_orig
,
1090 struct got_blob_object
*blob_deriv
,
1091 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
1092 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1094 const struct got_error
*err
= NULL
;
1095 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
1096 char *blob_orig_path
= NULL
;
1097 char *blob_deriv_path
= NULL
, *base_path
= NULL
, *id_str
= NULL
;
1098 char *label_deriv
= NULL
, *parent
= NULL
;
1100 *local_changes_subsumed
= 0;
1102 err
= got_path_dirname(&parent
, ondisk_path
);
1107 if (asprintf(&base_path
, "%s/got-merge-blob-orig",
1109 err
= got_error_from_errno("asprintf");
1114 err
= got_opentemp_named(&blob_orig_path
, &f_orig
, base_path
);
1117 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_orig
,
1124 * No common ancestor exists. This is an "add vs add" conflict
1125 * and we simply use an empty ancestor file to make both files
1126 * appear in the merged result in their entirety.
1128 f_orig
= got_opentemp();
1129 if (f_orig
== NULL
) {
1130 err
= got_error_from_errno("got_opentemp");
1135 if (asprintf(&base_path
, "%s/got-merge-blob-deriv", parent
) == -1) {
1136 err
= got_error_from_errno("asprintf");
1141 err
= got_opentemp_named(&blob_deriv_path
, &f_deriv
, base_path
);
1144 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_deriv
,
1149 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
1152 if (asprintf(&label_deriv
, "%s: commit %s",
1153 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
1154 err
= got_error_from_errno("asprintf");
1159 * In order the run a 3-way merge with a symlink we copy the symlink's
1160 * target path into a temporary file and use that file with diff3.
1162 if (S_ISLNK(st_mode
)) {
1163 err
= dump_symlink_target_path_to_file(&f_deriv2
, ondisk_path
);
1168 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
);
1170 err
= got_error_from_errno2("open", ondisk_path
);
1173 f_deriv2
= fdopen(fd
, "r");
1174 if (f_deriv2
== NULL
) {
1175 err
= got_error_from_errno2("fdopen", ondisk_path
);
1181 err
= merge_file(local_changes_subsumed
, worktree
, f_orig
, f_deriv
,
1182 f_deriv2
, ondisk_path
, path
, st_mode
, label_orig
, label_deriv
,
1183 NULL
, GOT_DIFF_ALGORITHM_MYERS
, repo
, progress_cb
, progress_arg
);
1185 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
1186 err
= got_error_from_errno("fclose");
1187 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
1188 err
= got_error_from_errno("fclose");
1189 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
1190 err
= got_error_from_errno("fclose");
1192 if (blob_orig_path
) {
1193 unlink(blob_orig_path
);
1194 free(blob_orig_path
);
1196 if (blob_deriv_path
) {
1197 unlink(blob_deriv_path
);
1198 free(blob_deriv_path
);
1206 static const struct got_error
*
1207 create_fileindex_entry(struct got_fileindex_entry
**new_iep
,
1208 struct got_fileindex
*fileindex
, struct got_object_id
*base_commit_id
,
1209 int wt_fd
, const char *path
, struct got_object_id
*blob_id
)
1211 const struct got_error
*err
= NULL
;
1212 struct got_fileindex_entry
*new_ie
;
1216 err
= got_fileindex_entry_alloc(&new_ie
, path
);
1220 err
= got_fileindex_entry_update(new_ie
, wt_fd
, path
,
1221 blob_id
->sha1
, base_commit_id
->sha1
, 1);
1225 err
= got_fileindex_entry_add(fileindex
, new_ie
);
1228 got_fileindex_entry_free(new_ie
);
1235 get_ondisk_perms(int executable
, mode_t st_mode
)
1237 mode_t xbits
= S_IXUSR
;
1240 /* Map read bits to execute bits. */
1241 if (st_mode
& S_IRGRP
)
1243 if (st_mode
& S_IROTH
)
1245 return st_mode
| xbits
;
1248 return (st_mode
& ~(S_IXUSR
| S_IXGRP
| S_IXOTH
));
1251 /* forward declaration */
1252 static const struct got_error
*
1253 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1254 const char *path
, mode_t te_mode
, mode_t st_mode
,
1255 struct got_blob_object
*blob
, int restoring_missing_file
,
1256 int reverting_versioned_file
, int installing_bad_symlink
,
1257 int path_is_unversioned
, struct got_repository
*repo
,
1258 got_worktree_checkout_cb progress_cb
, void *progress_arg
);
1261 * This function assumes that the provided symlink target points at a
1262 * safe location in the work tree!
1264 static const struct got_error
*
1265 replace_existing_symlink(int *did_something
, const char *ondisk_path
,
1266 const char *target_path
, size_t target_len
)
1268 const struct got_error
*err
= NULL
;
1270 char etarget
[PATH_MAX
];
1276 * "Bad" symlinks (those pointing outside the work tree or into the
1277 * .got directory) are installed in the work tree as a regular file
1278 * which contains the bad symlink target path.
1279 * The new symlink target has already been checked for safety by our
1280 * caller. If we can successfully open a regular file then we simply
1281 * replace this file with a symlink below.
1283 fd
= open(ondisk_path
, O_RDWR
| O_EXCL
| O_NOFOLLOW
);
1285 if (!got_err_open_nofollow_on_symlink())
1286 return got_error_from_errno2("open", ondisk_path
);
1288 /* We are updating an existing on-disk symlink. */
1289 elen
= readlink(ondisk_path
, etarget
, sizeof(etarget
));
1291 return got_error_from_errno2("readlink", ondisk_path
);
1293 if (elen
== target_len
&&
1294 memcmp(etarget
, target_path
, target_len
) == 0)
1295 return NULL
; /* nothing to do */
1299 err
= update_symlink(ondisk_path
, target_path
, target_len
);
1300 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1301 err
= got_error_from_errno2("close", ondisk_path
);
1305 static const struct got_error
*
1306 is_bad_symlink_target(int *is_bad_symlink
, const char *target_path
,
1307 size_t target_len
, const char *ondisk_path
, const char *wtroot_path
)
1309 const struct got_error
*err
= NULL
;
1310 char canonpath
[PATH_MAX
];
1311 char *path_got
= NULL
;
1313 *is_bad_symlink
= 0;
1315 if (target_len
>= sizeof(canonpath
)) {
1316 *is_bad_symlink
= 1;
1321 * We do not use realpath(3) to resolve the symlink's target
1322 * path because we don't want to resolve symlinks recursively.
1323 * Instead we make the path absolute and then canonicalize it.
1324 * Relative symlink target lookup should begin at the directory
1325 * in which the blob object is being installed.
1327 if (!got_path_is_absolute(target_path
)) {
1328 char *abspath
, *parent
;
1329 err
= got_path_dirname(&parent
, ondisk_path
);
1332 if (asprintf(&abspath
, "%s/%s", parent
, target_path
) == -1) {
1334 return got_error_from_errno("asprintf");
1337 if (strlen(abspath
) >= sizeof(canonpath
)) {
1338 err
= got_error_path(abspath
, GOT_ERR_BAD_PATH
);
1342 err
= got_canonpath(abspath
, canonpath
, sizeof(canonpath
));
1347 err
= got_canonpath(target_path
, canonpath
, sizeof(canonpath
));
1352 /* Only allow symlinks pointing at paths within the work tree. */
1353 if (!got_path_is_child(canonpath
, wtroot_path
, strlen(wtroot_path
))) {
1354 *is_bad_symlink
= 1;
1358 /* Do not allow symlinks pointing into the .got directory. */
1359 if (asprintf(&path_got
, "%s/%s", wtroot_path
,
1360 GOT_WORKTREE_GOT_DIR
) == -1)
1361 return got_error_from_errno("asprintf");
1362 if (got_path_is_child(canonpath
, path_got
, strlen(path_got
)))
1363 *is_bad_symlink
= 1;
1369 static const struct got_error
*
1370 install_symlink(int *is_bad_symlink
, struct got_worktree
*worktree
,
1371 const char *ondisk_path
, const char *path
, struct got_blob_object
*blob
,
1372 int restoring_missing_file
, int reverting_versioned_file
,
1373 int path_is_unversioned
, int allow_bad_symlinks
,
1374 struct got_repository
*repo
,
1375 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1377 const struct got_error
*err
= NULL
;
1378 char target_path
[PATH_MAX
];
1379 size_t len
, target_len
= 0;
1380 char *path_got
= NULL
;
1381 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1382 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1384 *is_bad_symlink
= 0;
1387 * Blob object content specifies the target path of the link.
1388 * If a symbolic link cannot be installed we instead create
1389 * a regular file which contains the link target path stored
1390 * in the blob object.
1393 err
= got_object_blob_read_block(&len
, blob
);
1394 if (len
+ target_len
>= sizeof(target_path
)) {
1395 /* Path too long; install as a regular file. */
1396 *is_bad_symlink
= 1;
1397 got_object_blob_rewind(blob
);
1398 return install_blob(worktree
, ondisk_path
, path
,
1399 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1400 restoring_missing_file
, reverting_versioned_file
,
1401 1, path_is_unversioned
, repo
, progress_cb
,
1405 /* Skip blob object header first time around. */
1406 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1408 target_len
+= len
- hdrlen
;
1412 target_path
[target_len
] = '\0';
1414 err
= is_bad_symlink_target(is_bad_symlink
, target_path
, target_len
,
1415 ondisk_path
, worktree
->root_path
);
1419 if (*is_bad_symlink
&& !allow_bad_symlinks
) {
1420 /* install as a regular file */
1421 got_object_blob_rewind(blob
);
1422 err
= install_blob(worktree
, ondisk_path
, path
,
1423 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1424 restoring_missing_file
, reverting_versioned_file
, 1,
1425 path_is_unversioned
, repo
, progress_cb
, progress_arg
);
1429 if (symlink(target_path
, ondisk_path
) == -1) {
1430 if (errno
== EEXIST
) {
1431 int symlink_replaced
;
1432 if (path_is_unversioned
) {
1433 err
= (*progress_cb
)(progress_arg
,
1434 GOT_STATUS_UNVERSIONED
, path
);
1437 err
= replace_existing_symlink(&symlink_replaced
,
1438 ondisk_path
, target_path
, target_len
);
1442 if (symlink_replaced
) {
1443 err
= (*progress_cb
)(progress_arg
,
1444 reverting_versioned_file
?
1446 GOT_STATUS_UPDATE
, path
);
1448 err
= (*progress_cb
)(progress_arg
,
1449 GOT_STATUS_EXISTS
, path
);
1452 goto done
; /* Nothing else to do. */
1455 if (errno
== ENOENT
) {
1457 err
= got_path_dirname(&parent
, ondisk_path
);
1460 err
= add_dir_on_disk(worktree
, parent
);
1465 * Retry, and fall through to error handling
1466 * below if this second attempt fails.
1468 if (symlink(target_path
, ondisk_path
) != -1) {
1469 err
= NULL
; /* success */
1474 /* Handle errors from first or second creation attempt. */
1475 if (errno
== ENAMETOOLONG
) {
1476 /* bad target path; install as a regular file */
1477 *is_bad_symlink
= 1;
1478 got_object_blob_rewind(blob
);
1479 err
= install_blob(worktree
, ondisk_path
, path
,
1480 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1481 restoring_missing_file
, reverting_versioned_file
, 1,
1482 path_is_unversioned
, repo
,
1483 progress_cb
, progress_arg
);
1484 } else if (errno
== ENOTDIR
) {
1485 err
= got_error_path(ondisk_path
,
1486 GOT_ERR_FILE_OBSTRUCTED
);
1488 err
= got_error_from_errno3("symlink",
1489 target_path
, ondisk_path
);
1491 } else if (progress_cb
)
1492 err
= (*progress_cb
)(progress_arg
, reverting_versioned_file
?
1493 GOT_STATUS_REVERT
: GOT_STATUS_ADD
, path
);
1499 static const struct got_error
*
1500 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1501 const char *path
, mode_t te_mode
, mode_t st_mode
,
1502 struct got_blob_object
*blob
, int restoring_missing_file
,
1503 int reverting_versioned_file
, int installing_bad_symlink
,
1504 int path_is_unversioned
, struct got_repository
*repo
,
1505 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1507 const struct got_error
*err
= NULL
;
1511 char *tmppath
= NULL
;
1513 fd
= open(ondisk_path
, O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
,
1514 GOT_DEFAULT_FILE_MODE
);
1516 if (errno
== ENOENT
) {
1518 err
= got_path_dirname(&parent
, path
);
1521 err
= add_dir_on_disk(worktree
, parent
);
1525 fd
= open(ondisk_path
,
1526 O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
,
1527 GOT_DEFAULT_FILE_MODE
);
1529 return got_error_from_errno2("open",
1531 } else if (errno
== EEXIST
) {
1532 if (path_is_unversioned
) {
1533 err
= (*progress_cb
)(progress_arg
,
1534 GOT_STATUS_UNVERSIONED
, path
);
1537 if (!(S_ISLNK(st_mode
) && S_ISREG(te_mode
)) &&
1538 !S_ISREG(st_mode
) && !installing_bad_symlink
) {
1539 /* TODO file is obstructed; do something */
1540 err
= got_error_path(ondisk_path
,
1541 GOT_ERR_FILE_OBSTRUCTED
);
1544 err
= got_opentemp_named_fd(&tmppath
, &fd
,
1551 return got_error_from_errno2("open", ondisk_path
);
1554 if (fchmod(fd
, get_ondisk_perms(te_mode
& S_IXUSR
, st_mode
)) == -1) {
1555 err
= got_error_from_errno2("fchmod",
1556 update
? tmppath
: ondisk_path
);
1561 if (restoring_missing_file
)
1562 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MISSING
,
1564 else if (reverting_versioned_file
)
1565 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_REVERT
,
1568 err
= (*progress_cb
)(progress_arg
,
1569 update
? GOT_STATUS_UPDATE
: GOT_STATUS_ADD
, path
);
1574 hdrlen
= got_object_blob_get_hdrlen(blob
);
1576 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1577 err
= got_object_blob_read_block(&len
, blob
);
1581 /* Skip blob object header first time around. */
1582 ssize_t outlen
= write(fd
, buf
+ hdrlen
, len
- hdrlen
);
1584 err
= got_error_from_errno("write");
1586 } else if (outlen
!= len
- hdrlen
) {
1587 err
= got_error(GOT_ERR_IO
);
1594 if (fsync(fd
) != 0) {
1595 err
= got_error_from_errno("fsync");
1600 if (S_ISLNK(st_mode
) && unlink(ondisk_path
) == -1) {
1601 err
= got_error_from_errno2("unlink", ondisk_path
);
1604 if (rename(tmppath
, ondisk_path
) != 0) {
1605 err
= got_error_from_errno3("rename", tmppath
,
1614 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1615 err
= got_error_from_errno("close");
1616 if (tmppath
!= NULL
&& unlink(tmppath
) == -1 && err
== NULL
)
1617 err
= got_error_from_errno2("unlink", tmppath
);
1622 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1623 static const struct got_error
*
1624 get_modified_file_content_status(unsigned char *status
, FILE *f
)
1626 const struct got_error
*err
= NULL
;
1627 const char *markers
[3] = {
1628 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
1629 GOT_DIFF_CONFLICT_MARKER_SEP
,
1630 GOT_DIFF_CONFLICT_MARKER_END
1634 size_t linesize
= 0;
1637 while (*status
== GOT_STATUS_MODIFY
) {
1638 linelen
= getline(&line
, &linesize
, f
);
1639 if (linelen
== -1) {
1642 err
= got_ferror(f
, GOT_ERR_IO
);
1646 if (strncmp(line
, markers
[i
], strlen(markers
[i
])) == 0) {
1647 if (strcmp(markers
[i
], GOT_DIFF_CONFLICT_MARKER_END
)
1649 *status
= GOT_STATUS_CONFLICT
;
1660 xbit_differs(struct got_fileindex_entry
*ie
, uint16_t st_mode
)
1662 mode_t ie_mode
= got_fileindex_perms_to_st(ie
);
1663 return ((ie_mode
& S_IXUSR
) != (st_mode
& S_IXUSR
));
1667 stat_info_differs(struct got_fileindex_entry
*ie
, struct stat
*sb
)
1669 return !(ie
->ctime_sec
== sb
->st_ctim
.tv_sec
&&
1670 ie
->ctime_nsec
== sb
->st_ctim
.tv_nsec
&&
1671 ie
->mtime_sec
== sb
->st_mtim
.tv_sec
&&
1672 ie
->mtime_nsec
== sb
->st_mtim
.tv_nsec
&&
1673 ie
->size
== (sb
->st_size
& 0xffffffff) &&
1674 !xbit_differs(ie
, sb
->st_mode
));
1677 static unsigned char
1678 get_staged_status(struct got_fileindex_entry
*ie
)
1680 switch (got_fileindex_entry_stage_get(ie
)) {
1681 case GOT_FILEIDX_STAGE_ADD
:
1682 return GOT_STATUS_ADD
;
1683 case GOT_FILEIDX_STAGE_DELETE
:
1684 return GOT_STATUS_DELETE
;
1685 case GOT_FILEIDX_STAGE_MODIFY
:
1686 return GOT_STATUS_MODIFY
;
1688 return GOT_STATUS_NO_CHANGE
;
1692 static const struct got_error
*
1693 get_symlink_modification_status(unsigned char *status
,
1694 struct got_fileindex_entry
*ie
, const char *abspath
,
1695 int dirfd
, const char *de_name
, struct got_blob_object
*blob
)
1697 const struct got_error
*err
= NULL
;
1698 char target_path
[PATH_MAX
];
1699 char etarget
[PATH_MAX
];
1701 size_t len
, target_len
= 0;
1702 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1703 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1705 *status
= GOT_STATUS_NO_CHANGE
;
1707 /* Blob object content specifies the target path of the link. */
1709 err
= got_object_blob_read_block(&len
, blob
);
1712 if (len
+ target_len
>= sizeof(target_path
)) {
1714 * Should not happen. The blob contents were OK
1715 * when this symlink was installed.
1717 return got_error(GOT_ERR_NO_SPACE
);
1720 /* Skip blob object header first time around. */
1721 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1723 target_len
+= len
- hdrlen
;
1727 target_path
[target_len
] = '\0';
1730 elen
= readlinkat(dirfd
, de_name
, etarget
, sizeof(etarget
));
1732 return got_error_from_errno2("readlinkat", abspath
);
1734 elen
= readlink(abspath
, etarget
, sizeof(etarget
));
1736 return got_error_from_errno2("readlink", abspath
);
1739 if (elen
!= target_len
|| memcmp(etarget
, target_path
, target_len
) != 0)
1740 *status
= GOT_STATUS_MODIFY
;
1745 static const struct got_error
*
1746 get_file_status(unsigned char *status
, struct stat
*sb
,
1747 struct got_fileindex_entry
*ie
, const char *abspath
,
1748 int dirfd
, const char *de_name
, struct got_repository
*repo
)
1750 const struct got_error
*err
= NULL
;
1751 struct got_object_id id
;
1756 struct got_blob_object
*blob
= NULL
;
1758 unsigned char staged_status
= get_staged_status(ie
);
1760 *status
= GOT_STATUS_NO_CHANGE
;
1761 memset(sb
, 0, sizeof(*sb
));
1764 * Whenever the caller provides a directory descriptor and a
1765 * directory entry name for the file, use them! This prevents
1766 * race conditions if filesystem paths change beneath our feet.
1769 if (fstatat(dirfd
, de_name
, sb
, AT_SYMLINK_NOFOLLOW
) == -1) {
1770 if (errno
== ENOENT
) {
1771 if (got_fileindex_entry_has_file_on_disk(ie
))
1772 *status
= GOT_STATUS_MISSING
;
1774 *status
= GOT_STATUS_DELETE
;
1777 err
= got_error_from_errno2("fstatat", abspath
);
1781 fd
= open(abspath
, O_RDONLY
| O_NOFOLLOW
);
1782 if (fd
== -1 && errno
!= ENOENT
&&
1783 !got_err_open_nofollow_on_symlink())
1784 return got_error_from_errno2("open", abspath
);
1785 else if (fd
== -1 && got_err_open_nofollow_on_symlink()) {
1786 if (lstat(abspath
, sb
) == -1)
1787 return got_error_from_errno2("lstat", abspath
);
1788 } else if (fd
== -1 || fstat(fd
, sb
) == -1) {
1789 if (errno
== ENOENT
) {
1790 if (got_fileindex_entry_has_file_on_disk(ie
))
1791 *status
= GOT_STATUS_MISSING
;
1793 *status
= GOT_STATUS_DELETE
;
1796 err
= got_error_from_errno2("fstat", abspath
);
1801 if (!S_ISREG(sb
->st_mode
) && !S_ISLNK(sb
->st_mode
)) {
1802 *status
= GOT_STATUS_OBSTRUCTED
;
1806 if (!got_fileindex_entry_has_file_on_disk(ie
)) {
1807 *status
= GOT_STATUS_DELETE
;
1809 } else if (!got_fileindex_entry_has_blob(ie
) &&
1810 staged_status
!= GOT_STATUS_ADD
) {
1811 *status
= GOT_STATUS_ADD
;
1815 if (!stat_info_differs(ie
, sb
))
1818 if (S_ISLNK(sb
->st_mode
) &&
1819 got_fileindex_entry_filetype_get(ie
) != GOT_FILEIDX_MODE_SYMLINK
) {
1820 *status
= GOT_STATUS_MODIFY
;
1824 if (staged_status
== GOT_STATUS_MODIFY
||
1825 staged_status
== GOT_STATUS_ADD
)
1826 memcpy(id
.sha1
, ie
->staged_blob_sha1
, sizeof(id
.sha1
));
1828 memcpy(id
.sha1
, ie
->blob_sha1
, sizeof(id
.sha1
));
1830 err
= got_object_open_as_blob(&blob
, repo
, &id
, sizeof(fbuf
));
1834 if (S_ISLNK(sb
->st_mode
)) {
1835 err
= get_symlink_modification_status(status
, ie
,
1836 abspath
, dirfd
, de_name
, blob
);
1841 fd
= openat(dirfd
, de_name
, O_RDONLY
| O_NOFOLLOW
);
1843 err
= got_error_from_errno2("openat", abspath
);
1848 f
= fdopen(fd
, "r");
1850 err
= got_error_from_errno2("fdopen", abspath
);
1854 hdrlen
= got_object_blob_get_hdrlen(blob
);
1856 const uint8_t *bbuf
= got_object_blob_get_read_buf(blob
);
1857 err
= got_object_blob_read_block(&blen
, blob
);
1860 /* Skip length of blob object header first time around. */
1861 flen
= fread(fbuf
, 1, sizeof(fbuf
) - hdrlen
, f
);
1862 if (flen
== 0 && ferror(f
)) {
1863 err
= got_error_from_errno("fread");
1866 if (blen
- hdrlen
== 0) {
1868 *status
= GOT_STATUS_MODIFY
;
1870 } else if (flen
== 0) {
1871 if (blen
- hdrlen
!= 0)
1872 *status
= GOT_STATUS_MODIFY
;
1874 } else if (blen
- hdrlen
== flen
) {
1875 /* Skip blob object header first time around. */
1876 if (memcmp(bbuf
+ hdrlen
, fbuf
, flen
) != 0) {
1877 *status
= GOT_STATUS_MODIFY
;
1881 *status
= GOT_STATUS_MODIFY
;
1887 if (*status
== GOT_STATUS_MODIFY
) {
1889 err
= get_modified_file_content_status(status
, f
);
1890 } else if (xbit_differs(ie
, sb
->st_mode
))
1891 *status
= GOT_STATUS_MODE_CHANGE
;
1894 got_object_blob_close(blob
);
1895 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
1896 err
= got_error_from_errno2("fclose", abspath
);
1897 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1898 err
= got_error_from_errno2("close", abspath
);
1903 * Update timestamps in the file index if a file is unmodified and
1904 * we had to run a full content comparison to find out.
1906 static const struct got_error
*
1907 sync_timestamps(int wt_fd
, const char *path
, unsigned char status
,
1908 struct got_fileindex_entry
*ie
, struct stat
*sb
)
1910 if (status
== GOT_STATUS_NO_CHANGE
&& stat_info_differs(ie
, sb
))
1911 return got_fileindex_entry_update(ie
, wt_fd
, path
,
1912 ie
->blob_sha1
, ie
->commit_sha1
, 1);
1917 static const struct got_error
*
1918 update_blob(struct got_worktree
*worktree
,
1919 struct got_fileindex
*fileindex
, struct got_fileindex_entry
*ie
,
1920 struct got_tree_entry
*te
, const char *path
,
1921 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
1924 const struct got_error
*err
= NULL
;
1925 struct got_blob_object
*blob
= NULL
;
1927 unsigned char status
= GOT_STATUS_NO_CHANGE
;
1930 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, path
) == -1)
1931 return got_error_from_errno("asprintf");
1934 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
) {
1935 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
1938 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
1942 if (status
== GOT_STATUS_MISSING
|| status
== GOT_STATUS_DELETE
)
1943 sb
.st_mode
= got_fileindex_perms_to_st(ie
);
1945 if (stat(ondisk_path
, &sb
) == -1) {
1946 if (errno
!= ENOENT
) {
1947 err
= got_error_from_errno2("stat",
1951 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
1952 status
= GOT_STATUS_UNVERSIONED
;
1954 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
1955 status
= GOT_STATUS_UNVERSIONED
;
1957 status
= GOT_STATUS_OBSTRUCTED
;
1961 if (status
== GOT_STATUS_OBSTRUCTED
) {
1963 got_fileindex_entry_mark_skipped(ie
);
1964 err
= (*progress_cb
)(progress_arg
, status
, path
);
1967 if (status
== GOT_STATUS_CONFLICT
) {
1969 got_fileindex_entry_mark_skipped(ie
);
1970 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CANNOT_UPDATE
,
1975 if (ie
&& status
!= GOT_STATUS_MISSING
&& S_ISREG(sb
.st_mode
) &&
1976 (S_ISLNK(te
->mode
) ||
1977 (te
->mode
& S_IXUSR
) == (sb
.st_mode
& S_IXUSR
))) {
1979 * This is a regular file or an installed bad symlink.
1980 * If the file index indicates that this file is already
1981 * up-to-date with respect to the repository we can skip
1982 * updating contents of this file.
1984 if (got_fileindex_entry_has_commit(ie
) &&
1985 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
1986 SHA1_DIGEST_LENGTH
) == 0) {
1988 err
= sync_timestamps(worktree
->root_fd
,
1989 path
, status
, ie
, &sb
);
1992 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
1996 if (got_fileindex_entry_has_blob(ie
) &&
1997 memcmp(ie
->blob_sha1
, te
->id
.sha1
,
1998 SHA1_DIGEST_LENGTH
) == 0) {
1999 /* Different commit but the same blob. */
2000 err
= sync_timestamps(worktree
->root_fd
,
2001 path
, status
, ie
, &sb
);
2004 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
2010 err
= got_object_open_as_blob(&blob
, repo
, &te
->id
, 8192);
2014 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_ADD
) {
2015 int update_timestamps
;
2016 struct got_blob_object
*blob2
= NULL
;
2017 char *label_orig
= NULL
;
2018 if (got_fileindex_entry_has_blob(ie
)) {
2019 struct got_object_id id2
;
2020 memcpy(id2
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
2021 err
= got_object_open_as_blob(&blob2
, repo
, &id2
, 8192);
2025 if (got_fileindex_entry_has_commit(ie
)) {
2026 char id_str
[SHA1_DIGEST_STRING_LENGTH
];
2027 if (got_sha1_digest_to_str(ie
->commit_sha1
, id_str
,
2028 sizeof(id_str
)) == NULL
) {
2029 err
= got_error_path(id_str
,
2030 GOT_ERR_BAD_OBJ_ID_STR
);
2033 if (asprintf(&label_orig
, "%s: commit %s",
2034 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
2035 err
= got_error_from_errno("asprintf");
2039 if (S_ISLNK(te
->mode
) && S_ISLNK(sb
.st_mode
)) {
2041 err
= got_object_blob_read_to_str(&link_target
, blob
);
2044 err
= merge_symlink(worktree
, blob2
, ondisk_path
, path
,
2045 label_orig
, link_target
, worktree
->base_commit_id
,
2046 repo
, progress_cb
, progress_arg
);
2049 err
= merge_blob(&update_timestamps
, worktree
, blob2
,
2050 ondisk_path
, path
, sb
.st_mode
, label_orig
, blob
,
2051 worktree
->base_commit_id
, repo
,
2052 progress_cb
, progress_arg
);
2056 got_object_blob_close(blob2
);
2060 * Do not update timestamps of files with local changes.
2061 * Otherwise, a future status walk would treat them as
2062 * unmodified files again.
2064 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2065 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
,
2067 } else if (status
== GOT_STATUS_MODE_CHANGE
) {
2068 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2069 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
2070 } else if (status
== GOT_STATUS_DELETE
) {
2071 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
2074 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2075 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
2079 int is_bad_symlink
= 0;
2080 if (S_ISLNK(te
->mode
)) {
2081 err
= install_symlink(&is_bad_symlink
, worktree
,
2082 ondisk_path
, path
, blob
,
2083 status
== GOT_STATUS_MISSING
, 0,
2084 status
== GOT_STATUS_UNVERSIONED
, 0,
2085 repo
, progress_cb
, progress_arg
);
2087 err
= install_blob(worktree
, ondisk_path
, path
,
2088 te
->mode
, sb
.st_mode
, blob
,
2089 status
== GOT_STATUS_MISSING
, 0, 0,
2090 status
== GOT_STATUS_UNVERSIONED
, repo
,
2091 progress_cb
, progress_arg
);
2097 err
= got_fileindex_entry_update(ie
,
2098 worktree
->root_fd
, path
, blob
->id
.sha1
,
2099 worktree
->base_commit_id
->sha1
, 1);
2101 err
= create_fileindex_entry(&ie
, fileindex
,
2102 worktree
->base_commit_id
, worktree
->root_fd
, path
,
2108 if (is_bad_symlink
) {
2109 got_fileindex_entry_filetype_set(ie
,
2110 GOT_FILEIDX_MODE_BAD_SYMLINK
);
2113 got_object_blob_close(blob
);
2119 static const struct got_error
*
2120 remove_ondisk_file(const char *root_path
, const char *path
)
2122 const struct got_error
*err
= NULL
;
2123 char *ondisk_path
= NULL
, *parent
= NULL
;
2125 if (asprintf(&ondisk_path
, "%s/%s", root_path
, path
) == -1)
2126 return got_error_from_errno("asprintf");
2128 if (unlink(ondisk_path
) == -1) {
2129 if (errno
!= ENOENT
)
2130 err
= got_error_from_errno2("unlink", ondisk_path
);
2132 size_t root_len
= strlen(root_path
);
2133 err
= got_path_dirname(&parent
, ondisk_path
);
2136 while (got_path_cmp(parent
, root_path
,
2137 strlen(parent
), root_len
) != 0) {
2139 ondisk_path
= parent
;
2141 if (rmdir(ondisk_path
) == -1) {
2142 if (errno
!= ENOTEMPTY
)
2143 err
= got_error_from_errno2("rmdir",
2147 err
= got_path_dirname(&parent
, ondisk_path
);
2158 static const struct got_error
*
2159 delete_blob(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2160 struct got_fileindex_entry
*ie
, struct got_repository
*repo
,
2161 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2163 const struct got_error
*err
= NULL
;
2164 unsigned char status
;
2168 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
2169 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
2171 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, ie
->path
)
2173 return got_error_from_errno("asprintf");
2175 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, repo
);
2179 if (S_ISLNK(sb
.st_mode
) && status
!= GOT_STATUS_NO_CHANGE
) {
2180 char ondisk_target
[PATH_MAX
];
2181 ssize_t ondisk_len
= readlink(ondisk_path
, ondisk_target
,
2182 sizeof(ondisk_target
));
2183 if (ondisk_len
== -1) {
2184 err
= got_error_from_errno2("readlink", ondisk_path
);
2187 ondisk_target
[ondisk_len
] = '\0';
2188 err
= install_symlink_conflict(NULL
, worktree
->base_commit_id
,
2189 NULL
, NULL
, /* XXX pass common ancestor info? */
2190 ondisk_target
, ondisk_path
);
2193 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
2198 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_CONFLICT
||
2199 status
== GOT_STATUS_ADD
) {
2200 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, ie
->path
);
2204 * Preserve the working file and change the deleted blob's
2205 * entry into a schedule-add entry.
2207 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
,
2208 ie
->path
, NULL
, NULL
, 0);
2210 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_DELETE
, ie
->path
);
2213 if (status
== GOT_STATUS_NO_CHANGE
) {
2214 err
= remove_ondisk_file(worktree
->root_path
, ie
->path
);
2218 got_fileindex_entry_remove(fileindex
, ie
);
2225 struct diff_cb_arg
{
2226 struct got_fileindex
*fileindex
;
2227 struct got_worktree
*worktree
;
2228 struct got_repository
*repo
;
2229 got_worktree_checkout_cb progress_cb
;
2231 got_cancel_cb cancel_cb
;
2235 static const struct got_error
*
2236 diff_old_new(void *arg
, struct got_fileindex_entry
*ie
,
2237 struct got_tree_entry
*te
, const char *parent_path
)
2239 struct diff_cb_arg
*a
= arg
;
2241 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2242 return got_error(GOT_ERR_CANCELLED
);
2244 return update_blob(a
->worktree
, a
->fileindex
, ie
, te
,
2245 ie
->path
, a
->repo
, a
->progress_cb
, a
->progress_arg
);
2248 static const struct got_error
*
2249 diff_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
2251 struct diff_cb_arg
*a
= arg
;
2253 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2254 return got_error(GOT_ERR_CANCELLED
);
2256 return delete_blob(a
->worktree
, a
->fileindex
, ie
,
2257 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2260 static const struct got_error
*
2261 diff_new(void *arg
, struct got_tree_entry
*te
, const char *parent_path
)
2263 struct diff_cb_arg
*a
= arg
;
2264 const struct got_error
*err
;
2267 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2268 return got_error(GOT_ERR_CANCELLED
);
2270 if (got_object_tree_entry_is_submodule(te
))
2273 if (asprintf(&path
, "%s%s%s", parent_path
,
2274 parent_path
[0] ? "/" : "", te
->name
)
2276 return got_error_from_errno("asprintf");
2278 if (S_ISDIR(te
->mode
))
2279 err
= add_dir_on_disk(a
->worktree
, path
);
2281 err
= update_blob(a
->worktree
, a
->fileindex
, NULL
, te
, path
,
2282 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2288 const struct got_error
*
2289 got_worktree_get_uuid(char **uuidstr
, struct got_worktree
*worktree
)
2291 uint32_t uuid_status
;
2293 uuid_to_string(&worktree
->uuid
, uuidstr
, &uuid_status
);
2294 if (uuid_status
!= uuid_s_ok
) {
2296 return got_error_uuid(uuid_status
, "uuid_to_string");
2302 static const struct got_error
*
2303 get_ref_name(char **refname
, struct got_worktree
*worktree
, const char *prefix
)
2305 const struct got_error
*err
= NULL
;
2306 char *uuidstr
= NULL
;
2310 err
= got_worktree_get_uuid(&uuidstr
, worktree
);
2314 if (asprintf(refname
, "%s-%s", prefix
, uuidstr
) == -1) {
2315 err
= got_error_from_errno("asprintf");
2322 const struct got_error
*
2323 got_worktree_get_base_ref_name(char **refname
, struct got_worktree
*worktree
)
2325 return get_ref_name(refname
, worktree
, GOT_WORKTREE_BASE_REF_PREFIX
);
2328 static const struct got_error
*
2329 get_rebase_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2331 return get_ref_name(refname
, worktree
,
2332 GOT_WORKTREE_REBASE_TMP_REF_PREFIX
);
2335 static const struct got_error
*
2336 get_newbase_symref_name(char **refname
, struct got_worktree
*worktree
)
2338 return get_ref_name(refname
, worktree
, GOT_WORKTREE_NEWBASE_REF_PREFIX
);
2341 static const struct got_error
*
2342 get_rebase_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2344 return get_ref_name(refname
, worktree
,
2345 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX
);
2348 static const struct got_error
*
2349 get_rebase_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2351 return get_ref_name(refname
, worktree
,
2352 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX
);
2355 static const struct got_error
*
2356 get_histedit_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2358 return get_ref_name(refname
, worktree
,
2359 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX
);
2362 static const struct got_error
*
2363 get_histedit_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2365 return get_ref_name(refname
, worktree
,
2366 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX
);
2369 static const struct got_error
*
2370 get_histedit_base_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2372 return get_ref_name(refname
, worktree
,
2373 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX
);
2376 static const struct got_error
*
2377 get_histedit_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2379 return get_ref_name(refname
, worktree
,
2380 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX
);
2383 const struct got_error
*
2384 got_worktree_get_histedit_script_path(char **path
,
2385 struct got_worktree
*worktree
)
2387 if (asprintf(path
, "%s/%s/%s", worktree
->root_path
,
2388 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_HISTEDIT_SCRIPT
) == -1) {
2390 return got_error_from_errno("asprintf");
2395 static const struct got_error
*
2396 get_merge_branch_ref_name(char **refname
, struct got_worktree
*worktree
)
2398 return get_ref_name(refname
, worktree
,
2399 GOT_WORKTREE_MERGE_BRANCH_REF_PREFIX
);
2402 static const struct got_error
*
2403 get_merge_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2405 return get_ref_name(refname
, worktree
,
2406 GOT_WORKTREE_MERGE_COMMIT_REF_PREFIX
);
2410 * Prevent Git's garbage collector from deleting our base commit by
2411 * setting a reference to our base commit's ID.
2413 static const struct got_error
*
2414 ref_base_commit(struct got_worktree
*worktree
, struct got_repository
*repo
)
2416 const struct got_error
*err
= NULL
;
2417 struct got_reference
*ref
= NULL
;
2420 err
= got_worktree_get_base_ref_name(&refname
, worktree
);
2424 err
= got_ref_alloc(&ref
, refname
, worktree
->base_commit_id
);
2428 err
= got_ref_write(ref
, repo
);
2436 static const struct got_error
*
2437 get_fileindex_path(char **fileindex_path
, struct got_worktree
*worktree
)
2439 const struct got_error
*err
= NULL
;
2441 if (asprintf(fileindex_path
, "%s/%s/%s", worktree
->root_path
,
2442 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_FILE_INDEX
) == -1) {
2443 err
= got_error_from_errno("asprintf");
2444 *fileindex_path
= NULL
;
2450 static const struct got_error
*
2451 open_fileindex(struct got_fileindex
**fileindex
, char **fileindex_path
,
2452 struct got_worktree
*worktree
)
2454 const struct got_error
*err
= NULL
;
2457 *fileindex_path
= NULL
;
2458 *fileindex
= got_fileindex_alloc();
2459 if (*fileindex
== NULL
)
2460 return got_error_from_errno("got_fileindex_alloc");
2462 err
= get_fileindex_path(fileindex_path
, worktree
);
2466 index
= fopen(*fileindex_path
, "rb");
2467 if (index
== NULL
) {
2468 if (errno
!= ENOENT
)
2469 err
= got_error_from_errno2("fopen", *fileindex_path
);
2471 err
= got_fileindex_read(*fileindex
, index
);
2472 if (fclose(index
) == EOF
&& err
== NULL
)
2473 err
= got_error_from_errno("fclose");
2477 free(*fileindex_path
);
2478 *fileindex_path
= NULL
;
2479 got_fileindex_free(*fileindex
);
2485 struct bump_base_commit_id_arg
{
2486 struct got_object_id
*base_commit_id
;
2489 const char *entry_name
;
2490 got_worktree_checkout_cb progress_cb
;
2494 /* Bump base commit ID of all files within an updated part of the work tree. */
2495 static const struct got_error
*
2496 bump_base_commit_id(void *arg
, struct got_fileindex_entry
*ie
)
2498 const struct got_error
*err
;
2499 struct bump_base_commit_id_arg
*a
= arg
;
2501 if (a
->entry_name
) {
2502 if (strcmp(ie
->path
, a
->path
) != 0)
2504 } else if (!got_path_is_child(ie
->path
, a
->path
, a
->path_len
))
2507 if (got_fileindex_entry_was_skipped(ie
))
2510 if (memcmp(ie
->commit_sha1
, a
->base_commit_id
->sha1
,
2511 SHA1_DIGEST_LENGTH
) == 0)
2514 if (a
->progress_cb
) {
2515 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_BUMP_BASE
,
2520 memcpy(ie
->commit_sha1
, a
->base_commit_id
->sha1
, SHA1_DIGEST_LENGTH
);
2524 static const struct got_error
*
2525 bump_base_commit_id_everywhere(struct got_worktree
*worktree
,
2526 struct got_fileindex
*fileindex
,
2527 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2529 struct bump_base_commit_id_arg bbc_arg
;
2531 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2532 bbc_arg
.entry_name
= NULL
;
2534 bbc_arg
.path_len
= 0;
2535 bbc_arg
.progress_cb
= progress_cb
;
2536 bbc_arg
.progress_arg
= progress_arg
;
2538 return got_fileindex_for_each_entry_safe(fileindex
,
2539 bump_base_commit_id
, &bbc_arg
);
2542 static const struct got_error
*
2543 sync_fileindex(struct got_fileindex
*fileindex
, const char *fileindex_path
)
2545 const struct got_error
*err
= NULL
;
2546 char *new_fileindex_path
= NULL
;
2547 FILE *new_index
= NULL
;
2548 struct timespec timeout
;
2550 err
= got_opentemp_named(&new_fileindex_path
, &new_index
,
2555 err
= got_fileindex_write(fileindex
, new_index
);
2559 if (rename(new_fileindex_path
, fileindex_path
) != 0) {
2560 err
= got_error_from_errno3("rename", new_fileindex_path
,
2562 unlink(new_fileindex_path
);
2566 * Sleep for a short amount of time to ensure that files modified after
2567 * this program exits have a different time stamp from the one which
2568 * was recorded in the file index.
2571 timeout
.tv_nsec
= 1;
2572 nanosleep(&timeout
, NULL
);
2576 free(new_fileindex_path
);
2580 static const struct got_error
*
2581 find_tree_entry_for_checkout(int *entry_type
, char **tree_relpath
,
2582 struct got_object_id
**tree_id
, const char *wt_relpath
,
2583 struct got_worktree
*worktree
, struct got_repository
*repo
)
2585 const struct got_error
*err
= NULL
;
2586 struct got_object_id
*id
= NULL
;
2587 char *in_repo_path
= NULL
;
2588 int is_root_wt
= got_path_is_root_dir(worktree
->path_prefix
);
2590 *entry_type
= GOT_OBJ_TYPE_ANY
;
2591 *tree_relpath
= NULL
;
2594 if (wt_relpath
[0] == '\0') {
2595 /* Check out all files within the work tree. */
2596 *entry_type
= GOT_OBJ_TYPE_TREE
;
2597 *tree_relpath
= strdup("");
2598 if (*tree_relpath
== NULL
) {
2599 err
= got_error_from_errno("strdup");
2602 err
= got_object_id_by_path(tree_id
, repo
,
2603 worktree
->base_commit_id
, worktree
->path_prefix
);
2609 /* Check out a subset of files in the work tree. */
2611 if (asprintf(&in_repo_path
, "%s%s%s", worktree
->path_prefix
,
2612 is_root_wt
? "" : "/", wt_relpath
) == -1) {
2613 err
= got_error_from_errno("asprintf");
2617 err
= got_object_id_by_path(&id
, repo
, worktree
->base_commit_id
,
2623 in_repo_path
= NULL
;
2625 err
= got_object_get_type(entry_type
, repo
, id
);
2629 if (*entry_type
== GOT_OBJ_TYPE_BLOB
) {
2630 /* Check out a single file. */
2631 if (strchr(wt_relpath
, '/') == NULL
) {
2632 /* Check out a single file in work tree's root dir. */
2633 in_repo_path
= strdup(worktree
->path_prefix
);
2634 if (in_repo_path
== NULL
) {
2635 err
= got_error_from_errno("strdup");
2638 *tree_relpath
= strdup("");
2639 if (*tree_relpath
== NULL
) {
2640 err
= got_error_from_errno("strdup");
2644 /* Check out a single file in a subdirectory. */
2645 err
= got_path_dirname(tree_relpath
, wt_relpath
);
2648 if (asprintf(&in_repo_path
, "%s%s%s",
2649 worktree
->path_prefix
, is_root_wt
? "" : "/",
2650 *tree_relpath
) == -1) {
2651 err
= got_error_from_errno("asprintf");
2655 err
= got_object_id_by_path(tree_id
, repo
,
2656 worktree
->base_commit_id
, in_repo_path
);
2658 /* Check out all files within a subdirectory. */
2659 *tree_id
= got_object_id_dup(id
);
2660 if (*tree_id
== NULL
) {
2661 err
= got_error_from_errno("got_object_id_dup");
2664 *tree_relpath
= strdup(wt_relpath
);
2665 if (*tree_relpath
== NULL
) {
2666 err
= got_error_from_errno("strdup");
2674 *entry_type
= GOT_OBJ_TYPE_ANY
;
2675 free(*tree_relpath
);
2676 *tree_relpath
= NULL
;
2683 static const struct got_error
*
2684 checkout_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2685 const char *relpath
, struct got_object_id
*tree_id
, const char *entry_name
,
2686 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
2687 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
2689 const struct got_error
*err
= NULL
;
2690 struct got_commit_object
*commit
= NULL
;
2691 struct got_tree_object
*tree
= NULL
;
2692 struct got_fileindex_diff_tree_cb diff_cb
;
2693 struct diff_cb_arg arg
;
2695 err
= ref_base_commit(worktree
, repo
);
2697 if (!(err
->code
== GOT_ERR_ERRNO
&&
2698 (errno
== EACCES
|| errno
== EROFS
)))
2700 err
= (*progress_cb
)(progress_arg
,
2701 GOT_STATUS_BASE_REF_ERR
, worktree
->root_path
);
2706 err
= got_object_open_as_commit(&commit
, repo
,
2707 worktree
->base_commit_id
);
2711 err
= got_object_open_as_tree(&tree
, repo
, tree_id
);
2716 got_object_tree_find_entry(tree
, entry_name
) == NULL
) {
2717 err
= got_error_path(entry_name
, GOT_ERR_NO_TREE_ENTRY
);
2721 diff_cb
.diff_old_new
= diff_old_new
;
2722 diff_cb
.diff_old
= diff_old
;
2723 diff_cb
.diff_new
= diff_new
;
2724 arg
.fileindex
= fileindex
;
2725 arg
.worktree
= worktree
;
2727 arg
.progress_cb
= progress_cb
;
2728 arg
.progress_arg
= progress_arg
;
2729 arg
.cancel_cb
= cancel_cb
;
2730 arg
.cancel_arg
= cancel_arg
;
2731 err
= got_fileindex_diff_tree(fileindex
, tree
, relpath
,
2732 entry_name
, repo
, &diff_cb
, &arg
);
2735 got_object_tree_close(tree
);
2737 got_object_commit_close(commit
);
2741 const struct got_error
*
2742 got_worktree_checkout_files(struct got_worktree
*worktree
,
2743 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
2744 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
2745 got_cancel_cb cancel_cb
, void *cancel_arg
)
2747 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
2748 struct got_commit_object
*commit
= NULL
;
2749 struct got_tree_object
*tree
= NULL
;
2750 struct got_fileindex
*fileindex
= NULL
;
2751 char *fileindex_path
= NULL
;
2752 struct got_pathlist_entry
*pe
;
2753 struct tree_path_data
{
2754 STAILQ_ENTRY(tree_path_data
) entry
;
2755 struct got_object_id
*tree_id
;
2760 STAILQ_HEAD(tree_paths
, tree_path_data
) tree_paths
;
2762 STAILQ_INIT(&tree_paths
);
2764 err
= lock_worktree(worktree
, LOCK_EX
);
2768 /* Map all specified paths to in-repository trees. */
2769 TAILQ_FOREACH(pe
, paths
, entry
) {
2770 tpd
= malloc(sizeof(*tpd
));
2772 err
= got_error_from_errno("malloc");
2776 err
= find_tree_entry_for_checkout(&tpd
->entry_type
,
2777 &tpd
->relpath
, &tpd
->tree_id
, pe
->path
, worktree
, repo
);
2783 if (tpd
->entry_type
== GOT_OBJ_TYPE_BLOB
) {
2784 err
= got_path_basename(&tpd
->entry_name
, pe
->path
);
2792 tpd
->entry_name
= NULL
;
2794 STAILQ_INSERT_TAIL(&tree_paths
, tpd
, entry
);
2798 * Read the file index.
2799 * Checking out files is supposed to be an idempotent operation.
2800 * If the on-disk file index is incomplete we will try to complete it.
2802 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
2806 tpd
= STAILQ_FIRST(&tree_paths
);
2807 TAILQ_FOREACH(pe
, paths
, entry
) {
2808 struct bump_base_commit_id_arg bbc_arg
;
2810 err
= checkout_files(worktree
, fileindex
, tpd
->relpath
,
2811 tpd
->tree_id
, tpd
->entry_name
, repo
,
2812 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
2816 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2817 bbc_arg
.entry_name
= tpd
->entry_name
;
2818 bbc_arg
.path
= pe
->path
;
2819 bbc_arg
.path_len
= pe
->path_len
;
2820 bbc_arg
.progress_cb
= progress_cb
;
2821 bbc_arg
.progress_arg
= progress_arg
;
2822 err
= got_fileindex_for_each_entry_safe(fileindex
,
2823 bump_base_commit_id
, &bbc_arg
);
2827 tpd
= STAILQ_NEXT(tpd
, entry
);
2829 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
2830 if (sync_err
&& err
== NULL
)
2833 free(fileindex_path
);
2835 got_object_tree_close(tree
);
2837 got_object_commit_close(commit
);
2839 got_fileindex_free(fileindex
);
2840 while (!STAILQ_EMPTY(&tree_paths
)) {
2841 tpd
= STAILQ_FIRST(&tree_paths
);
2842 STAILQ_REMOVE_HEAD(&tree_paths
, entry
);
2847 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
2848 if (unlockerr
&& err
== NULL
)
2853 struct merge_file_cb_arg
{
2854 struct got_worktree
*worktree
;
2855 struct got_fileindex
*fileindex
;
2856 got_worktree_checkout_cb progress_cb
;
2858 got_cancel_cb cancel_cb
;
2860 const char *label_orig
;
2861 struct got_object_id
*commit_id2
;
2862 int allow_bad_symlinks
;
2865 static const struct got_error
*
2866 merge_file_cb(void *arg
, struct got_blob_object
*blob1
,
2867 struct got_blob_object
*blob2
, struct got_object_id
*id1
,
2868 struct got_object_id
*id2
, const char *path1
, const char *path2
,
2869 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
2871 static const struct got_error
*err
= NULL
;
2872 struct merge_file_cb_arg
*a
= arg
;
2873 struct got_fileindex_entry
*ie
;
2874 char *ondisk_path
= NULL
;
2876 unsigned char status
;
2877 int local_changes_subsumed
;
2878 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
2879 char *id_str
= NULL
, *label_deriv2
= NULL
;
2881 if (blob1
&& blob2
) {
2882 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
2885 return (*a
->progress_cb
)(a
->progress_arg
,
2886 GOT_STATUS_MISSING
, path2
);
2888 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2890 return got_error_from_errno("asprintf");
2892 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2897 if (status
== GOT_STATUS_DELETE
) {
2898 err
= (*a
->progress_cb
)(a
->progress_arg
,
2899 GOT_STATUS_MERGE
, path2
);
2902 if (status
!= GOT_STATUS_NO_CHANGE
&&
2903 status
!= GOT_STATUS_MODIFY
&&
2904 status
!= GOT_STATUS_CONFLICT
&&
2905 status
!= GOT_STATUS_ADD
) {
2906 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path2
);
2910 if (S_ISLNK(mode1
) && S_ISLNK(mode2
)) {
2912 err
= got_object_blob_read_to_str(&link_target2
, blob2
);
2915 err
= merge_symlink(a
->worktree
, blob1
, ondisk_path
,
2916 path2
, a
->label_orig
, link_target2
, a
->commit_id2
,
2917 repo
, a
->progress_cb
, a
->progress_arg
);
2922 f_orig
= got_opentemp();
2923 if (f_orig
== NULL
) {
2924 err
= got_error_from_errno("got_opentemp");
2927 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2932 f_deriv2
= got_opentemp();
2933 if (f_deriv2
== NULL
)
2935 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2940 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
);
2942 err
= got_error_from_errno2("open",
2946 f_deriv
= fdopen(fd
, "r");
2947 if (f_deriv
== NULL
) {
2948 err
= got_error_from_errno2("fdopen",
2953 err
= got_object_id_str(&id_str
, a
->commit_id2
);
2956 if (asprintf(&label_deriv2
, "%s: commit %s",
2957 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
2958 err
= got_error_from_errno("asprintf");
2961 err
= merge_file(&local_changes_subsumed
, a
->worktree
,
2962 f_orig
, f_deriv
, f_deriv2
, ondisk_path
, path2
,
2963 sb
.st_mode
, a
->label_orig
, NULL
, label_deriv2
,
2964 GOT_DIFF_ALGORITHM_PATIENCE
, repo
,
2965 a
->progress_cb
, a
->progress_arg
);
2968 ie
= got_fileindex_entry_get(a
->fileindex
, path1
,
2971 return (*a
->progress_cb
)(a
->progress_arg
,
2972 GOT_STATUS_MISSING
, path1
);
2974 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2976 return got_error_from_errno("asprintf");
2978 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2984 case GOT_STATUS_NO_CHANGE
:
2985 err
= (*a
->progress_cb
)(a
->progress_arg
,
2986 GOT_STATUS_DELETE
, path1
);
2989 err
= remove_ondisk_file(a
->worktree
->root_path
, path1
);
2993 got_fileindex_entry_mark_deleted_from_disk(ie
);
2995 case GOT_STATUS_DELETE
:
2996 case GOT_STATUS_MISSING
:
2997 err
= (*a
->progress_cb
)(a
->progress_arg
,
2998 GOT_STATUS_DELETE
, path1
);
3002 got_fileindex_entry_mark_deleted_from_disk(ie
);
3004 case GOT_STATUS_ADD
: {
3005 struct got_object_id
*id
;
3008 * Delete the added file only if its content already
3009 * exists in the repository.
3011 err
= got_object_blob_file_create(&id
, &blob1_f
, path1
);
3014 if (got_object_id_cmp(id
, id1
) == 0) {
3015 err
= (*a
->progress_cb
)(a
->progress_arg
,
3016 GOT_STATUS_DELETE
, path1
);
3019 err
= remove_ondisk_file(a
->worktree
->root_path
,
3024 got_fileindex_entry_remove(a
->fileindex
,
3027 err
= (*a
->progress_cb
)(a
->progress_arg
,
3028 GOT_STATUS_CANNOT_DELETE
, path1
);
3030 if (fclose(blob1_f
) == EOF
&& err
== NULL
)
3031 err
= got_error_from_errno("fclose");
3037 case GOT_STATUS_MODIFY
:
3038 case GOT_STATUS_CONFLICT
:
3039 err
= (*a
->progress_cb
)(a
->progress_arg
,
3040 GOT_STATUS_CANNOT_DELETE
, path1
);
3044 case GOT_STATUS_OBSTRUCTED
:
3045 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path1
);
3053 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3055 return got_error_from_errno("asprintf");
3056 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
3059 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
3063 if (status
!= GOT_STATUS_NO_CHANGE
&&
3064 status
!= GOT_STATUS_MODIFY
&&
3065 status
!= GOT_STATUS_CONFLICT
&&
3066 status
!= GOT_STATUS_ADD
) {
3067 err
= (*a
->progress_cb
)(a
->progress_arg
,
3071 if (S_ISLNK(mode2
) && S_ISLNK(sb
.st_mode
)) {
3073 err
= got_object_blob_read_to_str(&link_target2
,
3077 err
= merge_symlink(a
->worktree
, NULL
,
3078 ondisk_path
, path2
, a
->label_orig
,
3079 link_target2
, a
->commit_id2
, repo
,
3080 a
->progress_cb
, a
->progress_arg
);
3082 } else if (S_ISREG(sb
.st_mode
)) {
3083 err
= merge_blob(&local_changes_subsumed
,
3084 a
->worktree
, NULL
, ondisk_path
, path2
,
3085 sb
.st_mode
, a
->label_orig
, blob2
,
3086 a
->commit_id2
, repo
, a
->progress_cb
,
3089 err
= got_error_path(ondisk_path
,
3090 GOT_ERR_FILE_OBSTRUCTED
);
3094 if (status
== GOT_STATUS_DELETE
) {
3095 err
= got_fileindex_entry_update(ie
,
3096 a
->worktree
->root_fd
, path2
, blob2
->id
.sha1
,
3097 a
->worktree
->base_commit_id
->sha1
, 0);
3102 int is_bad_symlink
= 0;
3103 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
3104 if (S_ISLNK(mode2
)) {
3105 err
= install_symlink(&is_bad_symlink
,
3106 a
->worktree
, ondisk_path
, path2
, blob2
, 0,
3107 0, 1, a
->allow_bad_symlinks
, repo
,
3108 a
->progress_cb
, a
->progress_arg
);
3110 err
= install_blob(a
->worktree
, ondisk_path
, path2
,
3111 mode2
, sb
.st_mode
, blob2
, 0, 0, 0, 1, repo
,
3112 a
->progress_cb
, a
->progress_arg
);
3116 err
= got_fileindex_entry_alloc(&ie
, path2
);
3119 err
= got_fileindex_entry_update(ie
,
3120 a
->worktree
->root_fd
, path2
, NULL
, NULL
, 1);
3122 got_fileindex_entry_free(ie
);
3125 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
3127 got_fileindex_entry_free(ie
);
3130 if (is_bad_symlink
) {
3131 got_fileindex_entry_filetype_set(ie
,
3132 GOT_FILEIDX_MODE_BAD_SYMLINK
);
3137 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
3138 err
= got_error_from_errno("fclose");
3139 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
3140 err
= got_error_from_errno("fclose");
3141 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
3142 err
= got_error_from_errno("fclose");
3149 static const struct got_error
*
3150 check_mixed_commits(void *arg
, struct got_fileindex_entry
*ie
)
3152 struct got_worktree
*worktree
= arg
;
3154 /* Reject merges into a work tree with mixed base commits. */
3155 if (got_fileindex_entry_has_commit(ie
) &&
3156 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
3157 SHA1_DIGEST_LENGTH
) != 0)
3158 return got_error(GOT_ERR_MIXED_COMMITS
);
3163 struct check_merge_conflicts_arg
{
3164 struct got_worktree
*worktree
;
3165 struct got_fileindex
*fileindex
;
3166 struct got_repository
*repo
;
3169 static const struct got_error
*
3170 check_merge_conflicts(void *arg
, struct got_blob_object
*blob1
,
3171 struct got_blob_object
*blob2
, struct got_object_id
*id1
,
3172 struct got_object_id
*id2
, const char *path1
, const char *path2
,
3173 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
3175 const struct got_error
*err
= NULL
;
3176 struct check_merge_conflicts_arg
*a
= arg
;
3177 unsigned char status
;
3179 struct got_fileindex_entry
*ie
;
3180 const char *path
= path2
? path2
: path1
;
3181 struct got_object_id
*id
= id2
? id2
: id1
;
3187 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
3191 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
3193 return got_error_from_errno("asprintf");
3195 /* Reject merges into a work tree with conflicted files. */
3196 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
3200 if (status
== GOT_STATUS_CONFLICT
)
3201 return got_error(GOT_ERR_CONFLICTS
);
3206 static const struct got_error
*
3207 merge_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
3208 const char *fileindex_path
, struct got_object_id
*commit_id1
,
3209 struct got_object_id
*commit_id2
, struct got_repository
*repo
,
3210 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
3211 got_cancel_cb cancel_cb
, void *cancel_arg
)
3213 const struct got_error
*err
= NULL
, *sync_err
;
3214 struct got_object_id
*tree_id1
= NULL
, *tree_id2
= NULL
;
3215 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
3216 struct check_merge_conflicts_arg cmc_arg
;
3217 struct merge_file_cb_arg arg
;
3218 char *label_orig
= NULL
;
3221 err
= got_object_id_by_path(&tree_id1
, repo
, commit_id1
,
3222 worktree
->path_prefix
);
3223 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
3229 err
= got_object_open_as_tree(&tree1
, repo
, tree_id1
);
3233 err
= got_object_id_str(&id_str
, commit_id1
);
3237 if (asprintf(&label_orig
, "%s: commit %s",
3238 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
3239 err
= got_error_from_errno("asprintf");
3246 err
= got_object_id_by_path(&tree_id2
, repo
, commit_id2
,
3247 worktree
->path_prefix
);
3251 err
= got_object_open_as_tree(&tree2
, repo
, tree_id2
);
3255 cmc_arg
.worktree
= worktree
;
3256 cmc_arg
.fileindex
= fileindex
;
3257 cmc_arg
.repo
= repo
;
3258 err
= got_diff_tree(tree1
, tree2
, "", "", repo
,
3259 check_merge_conflicts
, &cmc_arg
, 0);
3263 arg
.worktree
= worktree
;
3264 arg
.fileindex
= fileindex
;
3265 arg
.progress_cb
= progress_cb
;
3266 arg
.progress_arg
= progress_arg
;
3267 arg
.cancel_cb
= cancel_cb
;
3268 arg
.cancel_arg
= cancel_arg
;
3269 arg
.label_orig
= label_orig
;
3270 arg
.commit_id2
= commit_id2
;
3271 arg
.allow_bad_symlinks
= 1; /* preserve bad symlinks across merges */
3272 err
= got_diff_tree(tree1
, tree2
, "", "", repo
, merge_file_cb
, &arg
, 1);
3273 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
3274 if (sync_err
&& err
== NULL
)
3278 got_object_tree_close(tree1
);
3280 got_object_tree_close(tree2
);
3285 const struct got_error
*
3286 got_worktree_merge_files(struct got_worktree
*worktree
,
3287 struct got_object_id
*commit_id1
, struct got_object_id
*commit_id2
,
3288 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
3289 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
3291 const struct got_error
*err
, *unlockerr
;
3292 char *fileindex_path
= NULL
;
3293 struct got_fileindex
*fileindex
= NULL
;
3295 err
= lock_worktree(worktree
, LOCK_EX
);
3299 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3303 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
3308 err
= merge_files(worktree
, fileindex
, fileindex_path
, commit_id1
,
3309 commit_id2
, repo
, progress_cb
, progress_arg
,
3310 cancel_cb
, cancel_arg
);
3313 got_fileindex_free(fileindex
);
3314 free(fileindex_path
);
3315 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
3316 if (unlockerr
&& err
== NULL
)
3321 struct diff_dir_cb_arg
{
3322 struct got_fileindex
*fileindex
;
3323 struct got_worktree
*worktree
;
3324 const char *status_path
;
3325 size_t status_path_len
;
3326 struct got_repository
*repo
;
3327 got_worktree_status_cb status_cb
;
3329 got_cancel_cb cancel_cb
;
3331 /* A pathlist containing per-directory pathlists of ignore patterns. */
3332 struct got_pathlist_head
*ignores
;
3333 int report_unchanged
;
3337 static const struct got_error
*
3338 report_file_status(struct got_fileindex_entry
*ie
, const char *abspath
,
3339 int dirfd
, const char *de_name
,
3340 got_worktree_status_cb status_cb
, void *status_arg
,
3341 struct got_repository
*repo
, int report_unchanged
)
3343 const struct got_error
*err
= NULL
;
3344 unsigned char status
= GOT_STATUS_NO_CHANGE
;
3345 unsigned char staged_status
= get_staged_status(ie
);
3347 struct got_object_id blob_id
, commit_id
, staged_blob_id
;
3348 struct got_object_id
*blob_idp
= NULL
, *commit_idp
= NULL
;
3349 struct got_object_id
*staged_blob_idp
= NULL
;
3351 err
= get_file_status(&status
, &sb
, ie
, abspath
, dirfd
, de_name
, repo
);
3355 if (status
== GOT_STATUS_NO_CHANGE
&&
3356 staged_status
== GOT_STATUS_NO_CHANGE
&& !report_unchanged
)
3359 if (got_fileindex_entry_has_blob(ie
)) {
3360 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3361 blob_idp
= &blob_id
;
3363 if (got_fileindex_entry_has_commit(ie
)) {
3364 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3365 commit_idp
= &commit_id
;
3367 if (staged_status
== GOT_STATUS_ADD
||
3368 staged_status
== GOT_STATUS_MODIFY
) {
3369 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
3370 SHA1_DIGEST_LENGTH
);
3371 staged_blob_idp
= &staged_blob_id
;
3374 return (*status_cb
)(status_arg
, status
, staged_status
,
3375 ie
->path
, blob_idp
, staged_blob_idp
, commit_idp
, dirfd
, de_name
);
3378 static const struct got_error
*
3379 status_old_new(void *arg
, struct got_fileindex_entry
*ie
,
3380 struct dirent
*de
, const char *parent_path
, int dirfd
)
3382 const struct got_error
*err
= NULL
;
3383 struct diff_dir_cb_arg
*a
= arg
;
3386 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3387 return got_error(GOT_ERR_CANCELLED
);
3389 if (got_path_cmp(parent_path
, a
->status_path
,
3390 strlen(parent_path
), a
->status_path_len
) != 0 &&
3391 !got_path_is_child(parent_path
, a
->status_path
, a
->status_path_len
))
3394 if (parent_path
[0]) {
3395 if (asprintf(&abspath
, "%s/%s/%s", a
->worktree
->root_path
,
3396 parent_path
, de
->d_name
) == -1)
3397 return got_error_from_errno("asprintf");
3399 if (asprintf(&abspath
, "%s/%s", a
->worktree
->root_path
,
3401 return got_error_from_errno("asprintf");
3404 err
= report_file_status(ie
, abspath
, dirfd
, de
->d_name
,
3405 a
->status_cb
, a
->status_arg
, a
->repo
, a
->report_unchanged
);
3410 static const struct got_error
*
3411 status_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
3413 struct diff_dir_cb_arg
*a
= arg
;
3414 struct got_object_id blob_id
, commit_id
;
3415 unsigned char status
;
3417 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3418 return got_error(GOT_ERR_CANCELLED
);
3420 if (!got_path_is_child(ie
->path
, a
->status_path
, a
->status_path_len
))
3423 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3424 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3425 if (got_fileindex_entry_has_file_on_disk(ie
))
3426 status
= GOT_STATUS_MISSING
;
3428 status
= GOT_STATUS_DELETE
;
3429 return (*a
->status_cb
)(a
->status_arg
, status
, get_staged_status(ie
),
3430 ie
->path
, &blob_id
, NULL
, &commit_id
, -1, NULL
);
3434 free_ignorelist(struct got_pathlist_head
*ignorelist
)
3436 struct got_pathlist_entry
*pe
;
3438 TAILQ_FOREACH(pe
, ignorelist
, entry
)
3439 free((char *)pe
->path
);
3440 got_pathlist_free(ignorelist
);
3444 free_ignores(struct got_pathlist_head
*ignores
)
3446 struct got_pathlist_entry
*pe
;
3448 TAILQ_FOREACH(pe
, ignores
, entry
) {
3449 struct got_pathlist_head
*ignorelist
= pe
->data
;
3450 free_ignorelist(ignorelist
);
3451 free((char *)pe
->path
);
3453 got_pathlist_free(ignores
);
3456 static const struct got_error
*
3457 read_ignores(struct got_pathlist_head
*ignores
, const char *path
, FILE *f
)
3459 const struct got_error
*err
= NULL
;
3460 struct got_pathlist_entry
*pe
= NULL
;
3461 struct got_pathlist_head
*ignorelist
;
3462 char *line
= NULL
, *pattern
, *dirpath
= NULL
;
3463 size_t linesize
= 0;
3466 ignorelist
= calloc(1, sizeof(*ignorelist
));
3467 if (ignorelist
== NULL
)
3468 return got_error_from_errno("calloc");
3469 TAILQ_INIT(ignorelist
);
3471 while ((linelen
= getline(&line
, &linesize
, f
)) != -1) {
3472 if (linelen
> 0 && line
[linelen
- 1] == '\n')
3473 line
[linelen
- 1] = '\0';
3475 /* Git's ignores may contain comments. */
3479 /* Git's negated patterns are not (yet?) supported. */
3483 if (asprintf(&pattern
, "%s%s%s", path
, path
[0] ? "/" : "",
3485 err
= got_error_from_errno("asprintf");
3488 err
= got_pathlist_insert(NULL
, ignorelist
, pattern
, NULL
);
3493 err
= got_error_from_errno("getline");
3497 dirpath
= strdup(path
);
3498 if (dirpath
== NULL
) {
3499 err
= got_error_from_errno("strdup");
3502 err
= got_pathlist_insert(&pe
, ignores
, dirpath
, ignorelist
);
3505 if (err
|| pe
== NULL
) {
3507 free_ignorelist(ignorelist
);
3513 match_ignores(struct got_pathlist_head
*ignores
, const char *path
)
3515 struct got_pathlist_entry
*pe
;
3517 /* Handle patterns which match in all directories. */
3518 TAILQ_FOREACH(pe
, ignores
, entry
) {
3519 struct got_pathlist_head
*ignorelist
= pe
->data
;
3520 struct got_pathlist_entry
*pi
;
3522 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3523 const char *p
, *pattern
= pi
->path
;
3525 if (strncmp(pattern
, "**/", 3) != 0)
3530 if (fnmatch(pattern
, p
,
3531 FNM_PATHNAME
| FNM_LEADING_DIR
)) {
3532 /* Retry in next directory. */
3533 while (*p
&& *p
!= '/')
3545 * The ignores pathlist contains ignore lists from children before
3546 * parents, so we can find the most specific ignorelist by walking
3547 * ignores backwards.
3549 pe
= TAILQ_LAST(ignores
, got_pathlist_head
);
3551 if (got_path_is_child(path
, pe
->path
, pe
->path_len
)) {
3552 struct got_pathlist_head
*ignorelist
= pe
->data
;
3553 struct got_pathlist_entry
*pi
;
3554 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3555 const char *pattern
= pi
->path
;
3556 int flags
= FNM_LEADING_DIR
;
3557 if (strstr(pattern
, "/**/") == NULL
)
3558 flags
|= FNM_PATHNAME
;
3559 if (fnmatch(pattern
, path
, flags
))
3564 pe
= TAILQ_PREV(pe
, got_pathlist_head
, entry
);
3570 static const struct got_error
*
3571 add_ignores(struct got_pathlist_head
*ignores
, const char *root_path
,
3572 const char *path
, int dirfd
, const char *ignores_filename
)
3574 const struct got_error
*err
= NULL
;
3577 FILE *ignoresfile
= NULL
;
3579 if (asprintf(&ignorespath
, "%s/%s%s%s", root_path
, path
,
3580 path
[0] ? "/" : "", ignores_filename
) == -1)
3581 return got_error_from_errno("asprintf");
3584 fd
= openat(dirfd
, ignores_filename
, O_RDONLY
| O_NOFOLLOW
);
3586 if (errno
!= ENOENT
&& errno
!= EACCES
)
3587 err
= got_error_from_errno2("openat",
3590 ignoresfile
= fdopen(fd
, "r");
3591 if (ignoresfile
== NULL
)
3592 err
= got_error_from_errno2("fdopen",
3596 err
= read_ignores(ignores
, path
, ignoresfile
);
3600 ignoresfile
= fopen(ignorespath
, "r");
3601 if (ignoresfile
== NULL
) {
3602 if (errno
!= ENOENT
&& errno
!= EACCES
)
3603 err
= got_error_from_errno2("fopen",
3606 err
= read_ignores(ignores
, path
, ignoresfile
);
3609 if (ignoresfile
&& fclose(ignoresfile
) == EOF
&& err
== NULL
)
3610 err
= got_error_from_errno2("fclose", path
);
3611 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3612 err
= got_error_from_errno2("close", path
);
3617 static const struct got_error
*
3618 status_new(void *arg
, struct dirent
*de
, const char *parent_path
, int dirfd
)
3620 const struct got_error
*err
= NULL
;
3621 struct diff_dir_cb_arg
*a
= arg
;
3624 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3625 return got_error(GOT_ERR_CANCELLED
);
3627 if (parent_path
[0]) {
3628 if (asprintf(&path
, "%s/%s", parent_path
, de
->d_name
) == -1)
3629 return got_error_from_errno("asprintf");
3634 if (de
->d_type
!= DT_DIR
&&
3635 got_path_is_child(path
, a
->status_path
, a
->status_path_len
)
3636 && !match_ignores(a
->ignores
, path
))
3637 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_UNVERSIONED
,
3638 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3644 static const struct got_error
*
3645 status_traverse(void *arg
, const char *path
, int dirfd
)
3647 const struct got_error
*err
= NULL
;
3648 struct diff_dir_cb_arg
*a
= arg
;
3653 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
,
3654 path
, dirfd
, ".cvsignore");
3658 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
, path
,
3659 dirfd
, ".gitignore");
3664 static const struct got_error
*
3665 report_single_file_status(const char *path
, const char *ondisk_path
,
3666 struct got_fileindex
*fileindex
, got_worktree_status_cb status_cb
,
3667 void *status_arg
, struct got_repository
*repo
, int report_unchanged
,
3668 struct got_pathlist_head
*ignores
, int no_ignores
)
3670 struct got_fileindex_entry
*ie
;
3673 if (!no_ignores
&& match_ignores(ignores
, path
))
3676 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
3678 return report_file_status(ie
, ondisk_path
, -1, NULL
,
3679 status_cb
, status_arg
, repo
, report_unchanged
);
3681 if (lstat(ondisk_path
, &sb
) == -1) {
3682 if (errno
!= ENOENT
)
3683 return got_error_from_errno2("lstat", ondisk_path
);
3684 return (*status_cb
)(status_arg
, GOT_STATUS_NONEXISTENT
,
3685 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3689 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
3690 return (*status_cb
)(status_arg
, GOT_STATUS_UNVERSIONED
,
3691 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3696 static const struct got_error
*
3697 add_ignores_from_parent_paths(struct got_pathlist_head
*ignores
,
3698 const char *root_path
, const char *path
)
3700 const struct got_error
*err
;
3701 char *parent_path
, *next_parent_path
= NULL
;
3703 err
= add_ignores(ignores
, root_path
, "", -1,
3708 err
= add_ignores(ignores
, root_path
, "", -1,
3713 err
= got_path_dirname(&parent_path
, path
);
3715 if (err
->code
== GOT_ERR_BAD_PATH
)
3716 return NULL
; /* cannot traverse parent */
3720 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3724 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3728 err
= got_path_dirname(&next_parent_path
, parent_path
);
3730 if (err
->code
== GOT_ERR_BAD_PATH
)
3731 err
= NULL
; /* traversed everything */
3734 if (got_path_is_root_dir(parent_path
))
3737 parent_path
= next_parent_path
;
3738 next_parent_path
= NULL
;
3742 free(next_parent_path
);
3746 static const struct got_error
*
3747 worktree_status(struct got_worktree
*worktree
, const char *path
,
3748 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
3749 got_worktree_status_cb status_cb
, void *status_arg
,
3750 got_cancel_cb cancel_cb
, void *cancel_arg
, int no_ignores
,
3751 int report_unchanged
)
3753 const struct got_error
*err
= NULL
;
3755 struct got_fileindex_diff_dir_cb fdiff_cb
;
3756 struct diff_dir_cb_arg arg
;
3757 char *ondisk_path
= NULL
;
3758 struct got_pathlist_head ignores
;
3760 TAILQ_INIT(&ignores
);
3762 if (asprintf(&ondisk_path
, "%s%s%s",
3763 worktree
->root_path
, path
[0] ? "/" : "", path
) == -1)
3764 return got_error_from_errno("asprintf");
3766 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_DIRECTORY
);
3768 if (errno
!= ENOTDIR
&& errno
!= ENOENT
&& errno
!= EACCES
&&
3769 !got_err_open_nofollow_on_symlink())
3770 err
= got_error_from_errno2("open", ondisk_path
);
3773 err
= add_ignores_from_parent_paths(&ignores
,
3774 worktree
->root_path
, ondisk_path
);
3778 err
= report_single_file_status(path
, ondisk_path
,
3779 fileindex
, status_cb
, status_arg
, repo
,
3780 report_unchanged
, &ignores
, no_ignores
);
3783 fdiff_cb
.diff_old_new
= status_old_new
;
3784 fdiff_cb
.diff_old
= status_old
;
3785 fdiff_cb
.diff_new
= status_new
;
3786 fdiff_cb
.diff_traverse
= status_traverse
;
3787 arg
.fileindex
= fileindex
;
3788 arg
.worktree
= worktree
;
3789 arg
.status_path
= path
;
3790 arg
.status_path_len
= strlen(path
);
3792 arg
.status_cb
= status_cb
;
3793 arg
.status_arg
= status_arg
;
3794 arg
.cancel_cb
= cancel_cb
;
3795 arg
.cancel_arg
= cancel_arg
;
3796 arg
.report_unchanged
= report_unchanged
;
3797 arg
.no_ignores
= no_ignores
;
3799 err
= add_ignores_from_parent_paths(&ignores
,
3800 worktree
->root_path
, path
);
3804 arg
.ignores
= &ignores
;
3805 err
= got_fileindex_diff_dir(fileindex
, fd
,
3806 worktree
->root_path
, path
, repo
, &fdiff_cb
, &arg
);
3809 free_ignores(&ignores
);
3810 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3811 err
= got_error_from_errno("close");
3816 const struct got_error
*
3817 got_worktree_status(struct got_worktree
*worktree
,
3818 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
3819 int no_ignores
, got_worktree_status_cb status_cb
, void *status_arg
,
3820 got_cancel_cb cancel_cb
, void *cancel_arg
)
3822 const struct got_error
*err
= NULL
;
3823 char *fileindex_path
= NULL
;
3824 struct got_fileindex
*fileindex
= NULL
;
3825 struct got_pathlist_entry
*pe
;
3827 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3831 TAILQ_FOREACH(pe
, paths
, entry
) {
3832 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
3833 status_cb
, status_arg
, cancel_cb
, cancel_arg
,
3838 free(fileindex_path
);
3839 got_fileindex_free(fileindex
);
3843 const struct got_error
*
3844 got_worktree_resolve_path(char **wt_path
, struct got_worktree
*worktree
,
3847 const struct got_error
*err
= NULL
;
3848 char *resolved
= NULL
, *cwd
= NULL
, *path
= NULL
;
3851 char *abspath
= NULL
;
3852 char canonpath
[PATH_MAX
];
3856 cwd
= getcwd(NULL
, 0);
3858 return got_error_from_errno("getcwd");
3860 if (lstat(arg
, &sb
) == -1) {
3861 if (errno
!= ENOENT
) {
3862 err
= got_error_from_errno2("lstat", arg
);
3867 if (S_ISLNK(sb
.st_mode
)) {
3869 * We cannot use realpath(3) with symlinks since we want to
3870 * operate on the symlink itself.
3871 * But we can make the path absolute, assuming it is relative
3872 * to the current working directory, and then canonicalize it.
3874 if (!got_path_is_absolute(arg
)) {
3875 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3876 err
= got_error_from_errno("asprintf");
3881 err
= got_canonpath(abspath
? abspath
: arg
, canonpath
,
3885 resolved
= strdup(canonpath
);
3886 if (resolved
== NULL
) {
3887 err
= got_error_from_errno("strdup");
3891 resolved
= realpath(arg
, NULL
);
3892 if (resolved
== NULL
) {
3893 if (errno
!= ENOENT
) {
3894 err
= got_error_from_errno2("realpath", arg
);
3897 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3898 err
= got_error_from_errno("asprintf");
3901 err
= got_canonpath(abspath
, canonpath
,
3905 resolved
= strdup(canonpath
);
3906 if (resolved
== NULL
) {
3907 err
= got_error_from_errno("strdup");
3913 if (strncmp(got_worktree_get_root_path(worktree
), resolved
,
3914 strlen(got_worktree_get_root_path(worktree
)))) {
3915 err
= got_error_path(resolved
, GOT_ERR_BAD_PATH
);
3919 if (strlen(resolved
) > strlen(got_worktree_get_root_path(worktree
))) {
3920 err
= got_path_skip_common_ancestor(&path
,
3921 got_worktree_get_root_path(worktree
), resolved
);
3927 err
= got_error_from_errno("strdup");
3932 /* XXX status walk can't deal with trailing slash! */
3934 while (len
> 0 && path
[len
- 1] == '/') {
3935 path
[len
- 1] = '\0';
3949 struct schedule_addition_args
{
3950 struct got_worktree
*worktree
;
3951 struct got_fileindex
*fileindex
;
3952 got_worktree_checkout_cb progress_cb
;
3954 struct got_repository
*repo
;
3957 static const struct got_error
*
3958 schedule_addition(void *arg
, unsigned char status
, unsigned char staged_status
,
3959 const char *relpath
, struct got_object_id
*blob_id
,
3960 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
3961 int dirfd
, const char *de_name
)
3963 struct schedule_addition_args
*a
= arg
;
3964 const struct got_error
*err
= NULL
;
3965 struct got_fileindex_entry
*ie
;
3969 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3971 return got_error_from_errno("asprintf");
3973 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
3975 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
,
3979 /* Re-adding an existing entry is a no-op. */
3980 if (status
== GOT_STATUS_ADD
)
3982 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
3987 if (status
!= GOT_STATUS_UNVERSIONED
) {
3988 err
= got_error_path(ondisk_path
, GOT_ERR_FILE_STATUS
);
3992 err
= got_fileindex_entry_alloc(&ie
, relpath
);
3995 err
= got_fileindex_entry_update(ie
, a
->worktree
->root_fd
,
3996 relpath
, NULL
, NULL
, 1);
3998 got_fileindex_entry_free(ie
);
4001 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
4003 got_fileindex_entry_free(ie
);
4010 if (status
== GOT_STATUS_ADD
)
4012 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_ADD
, relpath
);
4015 const struct got_error
*
4016 got_worktree_schedule_add(struct got_worktree
*worktree
,
4017 struct got_pathlist_head
*paths
,
4018 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4019 struct got_repository
*repo
, int no_ignores
)
4021 struct got_fileindex
*fileindex
= NULL
;
4022 char *fileindex_path
= NULL
;
4023 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4024 struct got_pathlist_entry
*pe
;
4025 struct schedule_addition_args saa
;
4027 err
= lock_worktree(worktree
, LOCK_EX
);
4031 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4035 saa
.worktree
= worktree
;
4036 saa
.fileindex
= fileindex
;
4037 saa
.progress_cb
= progress_cb
;
4038 saa
.progress_arg
= progress_arg
;
4041 TAILQ_FOREACH(pe
, paths
, entry
) {
4042 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4043 schedule_addition
, &saa
, NULL
, NULL
, no_ignores
, 0);
4047 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4048 if (sync_err
&& err
== NULL
)
4051 free(fileindex_path
);
4053 got_fileindex_free(fileindex
);
4054 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4055 if (unlockerr
&& err
== NULL
)
4060 struct schedule_deletion_args
{
4061 struct got_worktree
*worktree
;
4062 struct got_fileindex
*fileindex
;
4063 got_worktree_delete_cb progress_cb
;
4065 struct got_repository
*repo
;
4066 int delete_local_mods
;
4068 const char *status_codes
;
4071 static const struct got_error
*
4072 schedule_for_deletion(void *arg
, unsigned char status
,
4073 unsigned char staged_status
, const char *relpath
,
4074 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4075 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4077 struct schedule_deletion_args
*a
= arg
;
4078 const struct got_error
*err
= NULL
;
4079 struct got_fileindex_entry
*ie
= NULL
;
4083 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4085 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
4087 staged_status
= get_staged_status(ie
);
4088 if (staged_status
!= GOT_STATUS_NO_CHANGE
) {
4089 if (staged_status
== GOT_STATUS_DELETE
)
4091 return got_error_path(relpath
, GOT_ERR_FILE_STAGED
);
4094 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4096 return got_error_from_errno("asprintf");
4098 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
, de_name
,
4103 if (a
->status_codes
) {
4104 size_t ncodes
= strlen(a
->status_codes
);
4106 for (i
= 0; i
< ncodes
; i
++) {
4107 if (status
== a
->status_codes
[i
])
4111 /* Do not delete files in non-matching status. */
4115 if (a
->status_codes
[i
] != GOT_STATUS_MODIFY
&&
4116 a
->status_codes
[i
] != GOT_STATUS_MISSING
) {
4117 static char msg
[64];
4118 snprintf(msg
, sizeof(msg
),
4119 "invalid status code '%c'", a
->status_codes
[i
]);
4120 err
= got_error_msg(GOT_ERR_FILE_STATUS
, msg
);
4125 if (status
!= GOT_STATUS_NO_CHANGE
) {
4126 if (status
== GOT_STATUS_DELETE
)
4128 if (status
== GOT_STATUS_MODIFY
&& !a
->delete_local_mods
) {
4129 err
= got_error_path(relpath
, GOT_ERR_FILE_MODIFIED
);
4132 if (status
!= GOT_STATUS_MODIFY
&&
4133 status
!= GOT_STATUS_MISSING
) {
4134 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4139 if (!a
->keep_on_disk
&& status
!= GOT_STATUS_MISSING
) {
4143 if (unlinkat(dirfd
, de_name
, 0) != 0) {
4144 err
= got_error_from_errno2("unlinkat",
4148 } else if (unlink(ondisk_path
) != 0) {
4149 err
= got_error_from_errno2("unlink", ondisk_path
);
4153 root_len
= strlen(a
->worktree
->root_path
);
4156 err
= got_path_dirname(&parent
, ondisk_path
);
4160 ondisk_path
= parent
;
4161 if (rmdir(ondisk_path
) == -1) {
4162 if (errno
!= ENOTEMPTY
)
4163 err
= got_error_from_errno2("rmdir",
4167 } while (got_path_cmp(ondisk_path
, a
->worktree
->root_path
,
4168 strlen(ondisk_path
), root_len
) != 0);
4171 got_fileindex_entry_mark_deleted_from_disk(ie
);
4176 if (status
== GOT_STATUS_DELETE
)
4178 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_DELETE
,
4179 staged_status
, relpath
);
4182 const struct got_error
*
4183 got_worktree_schedule_delete(struct got_worktree
*worktree
,
4184 struct got_pathlist_head
*paths
, int delete_local_mods
,
4185 const char *status_codes
,
4186 got_worktree_delete_cb progress_cb
, void *progress_arg
,
4187 struct got_repository
*repo
, int keep_on_disk
)
4189 struct got_fileindex
*fileindex
= NULL
;
4190 char *fileindex_path
= NULL
;
4191 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4192 struct got_pathlist_entry
*pe
;
4193 struct schedule_deletion_args sda
;
4195 err
= lock_worktree(worktree
, LOCK_EX
);
4199 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4203 sda
.worktree
= worktree
;
4204 sda
.fileindex
= fileindex
;
4205 sda
.progress_cb
= progress_cb
;
4206 sda
.progress_arg
= progress_arg
;
4208 sda
.delete_local_mods
= delete_local_mods
;
4209 sda
.keep_on_disk
= keep_on_disk
;
4210 sda
.status_codes
= status_codes
;
4212 TAILQ_FOREACH(pe
, paths
, entry
) {
4213 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4214 schedule_for_deletion
, &sda
, NULL
, NULL
, 0, 1);
4218 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4219 if (sync_err
&& err
== NULL
)
4222 free(fileindex_path
);
4224 got_fileindex_free(fileindex
);
4225 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4226 if (unlockerr
&& err
== NULL
)
4231 static const struct got_error
*
4232 copy_one_line(FILE *infile
, FILE *outfile
, FILE *rejectfile
)
4234 const struct got_error
*err
= NULL
;
4236 size_t linesize
= 0, n
;
4239 linelen
= getline(&line
, &linesize
, infile
);
4240 if (linelen
== -1) {
4241 if (ferror(infile
)) {
4242 err
= got_error_from_errno("getline");
4248 n
= fwrite(line
, 1, linelen
, outfile
);
4250 err
= got_ferror(outfile
, GOT_ERR_IO
);
4255 n
= fwrite(line
, 1, linelen
, rejectfile
);
4257 err
= got_ferror(outfile
, GOT_ERR_IO
);
4264 static const struct got_error
*
4265 skip_one_line(FILE *f
)
4268 size_t linesize
= 0;
4271 linelen
= getline(&line
, &linesize
, f
);
4272 if (linelen
== -1) {
4274 return got_error_from_errno("getline");
4281 static const struct got_error
*
4282 copy_change(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4283 int start_old
, int end_old
, int start_new
, int end_new
,
4284 FILE *outfile
, FILE *rejectfile
)
4286 const struct got_error
*err
;
4288 /* Copy old file's lines leading up to patch. */
4289 while (!feof(f1
) && *line_cur1
< start_old
) {
4290 err
= copy_one_line(f1
, outfile
, NULL
);
4295 /* Skip new file's lines leading up to patch. */
4296 while (!feof(f2
) && *line_cur2
< start_new
) {
4298 err
= copy_one_line(f2
, NULL
, rejectfile
);
4300 err
= skip_one_line(f2
);
4305 /* Copy patched lines. */
4306 while (!feof(f2
) && *line_cur2
<= end_new
) {
4307 err
= copy_one_line(f2
, outfile
, NULL
);
4312 /* Skip over old file's replaced lines. */
4313 while (!feof(f1
) && *line_cur1
<= end_old
) {
4315 err
= copy_one_line(f1
, NULL
, rejectfile
);
4317 err
= skip_one_line(f1
);
4326 static const struct got_error
*
4327 copy_remaining_content(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4328 FILE *outfile
, FILE *rejectfile
)
4330 const struct got_error
*err
;
4333 /* Copy old file's lines until EOF. */
4335 err
= copy_one_line(f1
, outfile
, NULL
);
4342 /* Copy new file's lines until EOF. */
4344 err
= copy_one_line(f2
, NULL
, rejectfile
);
4354 static const struct got_error
*
4355 apply_or_reject_change(int *choice
, int *nchunks_used
,
4356 struct diff_result
*diff_result
, int n
,
4357 const char *relpath
, FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4358 FILE *outfile
, FILE *rejectfile
, int changeno
, int nchanges
,
4359 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4361 const struct got_error
*err
= NULL
;
4362 struct diff_chunk_context cc
= {};
4363 int start_old
, end_old
, start_new
, end_new
;
4365 struct diff_output_unidiff_state
*diff_state
;
4366 struct diff_input_info diff_info
;
4369 *choice
= GOT_PATCH_CHOICE_NONE
;
4371 /* Get changed line numbers without context lines for copy_change(). */
4372 diff_chunk_context_load_change(&cc
, NULL
, diff_result
, n
, 0);
4373 start_old
= cc
.left
.start
;
4374 end_old
= cc
.left
.end
;
4375 start_new
= cc
.right
.start
;
4376 end_new
= cc
.right
.end
;
4378 /* Get the same change with context lines for display. */
4379 memset(&cc
, 0, sizeof(cc
));
4380 diff_chunk_context_load_change(&cc
, nchunks_used
, diff_result
, n
, 3);
4382 memset(&diff_info
, 0, sizeof(diff_info
));
4383 diff_info
.left_path
= relpath
;
4384 diff_info
.right_path
= relpath
;
4386 diff_state
= diff_output_unidiff_state_alloc();
4387 if (diff_state
== NULL
)
4388 return got_error_set_errno(ENOMEM
,
4389 "diff_output_unidiff_state_alloc");
4391 hunkfile
= got_opentemp();
4392 if (hunkfile
== NULL
) {
4393 err
= got_error_from_errno("got_opentemp");
4397 rc
= diff_output_unidiff_chunk(NULL
, hunkfile
, diff_state
, &diff_info
,
4399 if (rc
!= DIFF_RC_OK
) {
4400 err
= got_error_set_errno(rc
, "diff_output_unidiff_chunk");
4404 if (fseek(hunkfile
, 0L, SEEK_SET
) == -1) {
4405 err
= got_ferror(hunkfile
, GOT_ERR_IO
);
4409 err
= (*patch_cb
)(choice
, patch_arg
, GOT_STATUS_MODIFY
, relpath
,
4410 hunkfile
, changeno
, nchanges
);
4415 case GOT_PATCH_CHOICE_YES
:
4416 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4417 end_old
, start_new
, end_new
, outfile
, rejectfile
);
4419 case GOT_PATCH_CHOICE_NO
:
4420 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4421 end_old
, start_new
, end_new
, rejectfile
, outfile
);
4423 case GOT_PATCH_CHOICE_QUIT
:
4426 err
= got_error(GOT_ERR_PATCH_CHOICE
);
4430 diff_output_unidiff_state_free(diff_state
);
4431 if (hunkfile
&& fclose(hunkfile
) == EOF
&& err
== NULL
)
4432 err
= got_error_from_errno("fclose");
4436 struct revert_file_args
{
4437 struct got_worktree
*worktree
;
4438 struct got_fileindex
*fileindex
;
4439 got_worktree_checkout_cb progress_cb
;
4441 got_worktree_patch_cb patch_cb
;
4443 struct got_repository
*repo
;
4444 int unlink_added_files
;
4447 static const struct got_error
*
4448 create_patched_content(char **path_outfile
, int reverse_patch
,
4449 struct got_object_id
*blob_id
, const char *path2
,
4450 int dirfd2
, const char *de_name2
,
4451 const char *relpath
, struct got_repository
*repo
,
4452 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4454 const struct got_error
*err
, *free_err
;
4455 struct got_blob_object
*blob
= NULL
;
4456 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
;
4458 char link_target
[PATH_MAX
];
4459 ssize_t link_len
= 0;
4460 char *path1
= NULL
, *id_str
= NULL
;
4462 struct got_diffreg_result
*diffreg_result
= NULL
;
4463 int line_cur1
= 1, line_cur2
= 1, have_content
= 0;
4464 int i
= 0, n
= 0, nchunks_used
= 0, nchanges
= 0;
4466 *path_outfile
= NULL
;
4468 err
= got_object_id_str(&id_str
, blob_id
);
4473 fd2
= openat(dirfd2
, de_name2
, O_RDONLY
| O_NOFOLLOW
);
4475 if (!got_err_open_nofollow_on_symlink()) {
4476 err
= got_error_from_errno2("openat", path2
);
4479 link_len
= readlinkat(dirfd2
, de_name2
,
4480 link_target
, sizeof(link_target
));
4482 return got_error_from_errno2("readlinkat", path2
);
4483 sb2
.st_mode
= S_IFLNK
;
4484 sb2
.st_size
= link_len
;
4487 fd2
= open(path2
, O_RDONLY
| O_NOFOLLOW
);
4489 if (!got_err_open_nofollow_on_symlink()) {
4490 err
= got_error_from_errno2("open", path2
);
4493 link_len
= readlink(path2
, link_target
,
4494 sizeof(link_target
));
4496 return got_error_from_errno2("readlink", path2
);
4497 sb2
.st_mode
= S_IFLNK
;
4498 sb2
.st_size
= link_len
;
4502 if (fstat(fd2
, &sb2
) == -1) {
4503 err
= got_error_from_errno2("fstat", path2
);
4507 f2
= fdopen(fd2
, "r");
4509 err
= got_error_from_errno2("fdopen", path2
);
4515 f2
= got_opentemp();
4517 err
= got_error_from_errno2("got_opentemp", path2
);
4520 n
= fwrite(link_target
, 1, link_len
, f2
);
4521 if (n
!= link_len
) {
4522 err
= got_ferror(f2
, GOT_ERR_IO
);
4525 if (fflush(f2
) == EOF
) {
4526 err
= got_error_from_errno("fflush");
4532 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192);
4536 err
= got_opentemp_named(&path1
, &f1
, "got-patched-blob");
4540 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
4544 err
= got_diff_files(&diffreg_result
, f1
, id_str
, f2
, path2
, 3, 0, 1,
4549 err
= got_opentemp_named(path_outfile
, &outfile
, "got-patched-content");
4553 if (fseek(f1
, 0L, SEEK_SET
) == -1)
4554 return got_ferror(f1
, GOT_ERR_IO
);
4555 if (fseek(f2
, 0L, SEEK_SET
) == -1)
4556 return got_ferror(f2
, GOT_ERR_IO
);
4558 /* Count the number of actual changes in the diff result. */
4559 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4560 struct diff_chunk_context cc
= {};
4561 diff_chunk_context_load_change(&cc
, &nchunks_used
,
4562 diffreg_result
->result
, n
, 0);
4565 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4567 err
= apply_or_reject_change(&choice
, &nchunks_used
,
4568 diffreg_result
->result
, n
, relpath
, f1
, f2
,
4569 &line_cur1
, &line_cur2
,
4570 reverse_patch
? NULL
: outfile
,
4571 reverse_patch
? outfile
: NULL
,
4572 ++i
, nchanges
, patch_cb
, patch_arg
);
4575 if (choice
== GOT_PATCH_CHOICE_YES
)
4577 else if (choice
== GOT_PATCH_CHOICE_QUIT
)
4581 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
4582 reverse_patch
? NULL
: outfile
,
4583 reverse_patch
? outfile
: NULL
);
4587 if (!S_ISLNK(sb2
.st_mode
)) {
4588 if (fchmod(fileno(outfile
), sb2
.st_mode
) == -1) {
4589 err
= got_error_from_errno2("fchmod", path2
);
4597 got_object_blob_close(blob
);
4598 free_err
= got_diffreg_result_free(diffreg_result
);
4601 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
4602 err
= got_error_from_errno2("fclose", path1
);
4603 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
4604 err
= got_error_from_errno2("fclose", path2
);
4605 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
4606 err
= got_error_from_errno2("close", path2
);
4607 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
4608 err
= got_error_from_errno2("fclose", *path_outfile
);
4609 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
4610 err
= got_error_from_errno2("unlink", path1
);
4611 if (err
|| !have_content
) {
4612 if (*path_outfile
&& unlink(*path_outfile
) == -1 && err
== NULL
)
4613 err
= got_error_from_errno2("unlink", *path_outfile
);
4614 free(*path_outfile
);
4615 *path_outfile
= NULL
;
4621 static const struct got_error
*
4622 revert_file(void *arg
, unsigned char status
, unsigned char staged_status
,
4623 const char *relpath
, struct got_object_id
*blob_id
,
4624 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
4625 int dirfd
, const char *de_name
)
4627 struct revert_file_args
*a
= arg
;
4628 const struct got_error
*err
= NULL
;
4629 char *parent_path
= NULL
;
4630 struct got_fileindex_entry
*ie
;
4631 struct got_tree_object
*tree
= NULL
;
4632 struct got_object_id
*tree_id
= NULL
;
4633 const struct got_tree_entry
*te
= NULL
;
4634 char *tree_path
= NULL
, *te_name
;
4635 char *ondisk_path
= NULL
, *path_content
= NULL
;
4636 struct got_blob_object
*blob
= NULL
;
4638 /* Reverting a staged deletion is a no-op. */
4639 if (status
== GOT_STATUS_DELETE
&&
4640 staged_status
!= GOT_STATUS_NO_CHANGE
)
4643 if (status
== GOT_STATUS_UNVERSIONED
)
4644 return (*a
->progress_cb
)(a
->progress_arg
,
4645 GOT_STATUS_UNVERSIONED
, relpath
);
4647 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4649 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
4651 /* Construct in-repository path of tree which contains this blob. */
4652 err
= got_path_dirname(&parent_path
, ie
->path
);
4654 if (err
->code
!= GOT_ERR_BAD_PATH
)
4656 parent_path
= strdup("/");
4657 if (parent_path
== NULL
) {
4658 err
= got_error_from_errno("strdup");
4662 if (got_path_is_root_dir(a
->worktree
->path_prefix
)) {
4663 tree_path
= strdup(parent_path
);
4664 if (tree_path
== NULL
) {
4665 err
= got_error_from_errno("strdup");
4669 if (got_path_is_root_dir(parent_path
)) {
4670 tree_path
= strdup(a
->worktree
->path_prefix
);
4671 if (tree_path
== NULL
) {
4672 err
= got_error_from_errno("strdup");
4676 if (asprintf(&tree_path
, "%s/%s",
4677 a
->worktree
->path_prefix
, parent_path
) == -1) {
4678 err
= got_error_from_errno("asprintf");
4684 err
= got_object_id_by_path(&tree_id
, a
->repo
,
4685 a
->worktree
->base_commit_id
, tree_path
);
4687 if (!(err
->code
== GOT_ERR_NO_TREE_ENTRY
&&
4688 (status
== GOT_STATUS_ADD
||
4689 staged_status
== GOT_STATUS_ADD
)))
4692 err
= got_object_open_as_tree(&tree
, a
->repo
, tree_id
);
4696 err
= got_path_basename(&te_name
, ie
->path
);
4700 te
= got_object_tree_find_entry(tree
, te_name
);
4702 if (te
== NULL
&& status
!= GOT_STATUS_ADD
&&
4703 staged_status
!= GOT_STATUS_ADD
) {
4704 err
= got_error_path(ie
->path
, GOT_ERR_NO_TREE_ENTRY
);
4710 case GOT_STATUS_ADD
:
4712 int choice
= GOT_PATCH_CHOICE_NONE
;
4713 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4714 status
, ie
->path
, NULL
, 1, 1);
4717 if (choice
!= GOT_PATCH_CHOICE_YES
)
4720 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_REVERT
,
4724 got_fileindex_entry_remove(a
->fileindex
, ie
);
4725 if (a
->unlink_added_files
) {
4726 if (asprintf(&ondisk_path
, "%s/%s",
4727 got_worktree_get_root_path(a
->worktree
),
4729 err
= got_error_from_errno("asprintf");
4732 if (unlink(ondisk_path
) == -1) {
4733 err
= got_error_from_errno2("unlink",
4739 case GOT_STATUS_DELETE
:
4741 int choice
= GOT_PATCH_CHOICE_NONE
;
4742 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4743 status
, ie
->path
, NULL
, 1, 1);
4746 if (choice
!= GOT_PATCH_CHOICE_YES
)
4750 case GOT_STATUS_MODIFY
:
4751 case GOT_STATUS_MODE_CHANGE
:
4752 case GOT_STATUS_CONFLICT
:
4753 case GOT_STATUS_MISSING
: {
4754 struct got_object_id id
;
4755 if (staged_status
== GOT_STATUS_ADD
||
4756 staged_status
== GOT_STATUS_MODIFY
) {
4757 memcpy(id
.sha1
, ie
->staged_blob_sha1
,
4758 SHA1_DIGEST_LENGTH
);
4760 memcpy(id
.sha1
, ie
->blob_sha1
,
4761 SHA1_DIGEST_LENGTH
);
4762 err
= got_object_open_as_blob(&blob
, a
->repo
, &id
, 8192);
4766 if (asprintf(&ondisk_path
, "%s/%s",
4767 got_worktree_get_root_path(a
->worktree
), relpath
) == -1) {
4768 err
= got_error_from_errno("asprintf");
4772 if (a
->patch_cb
&& (status
== GOT_STATUS_MODIFY
||
4773 status
== GOT_STATUS_CONFLICT
)) {
4774 int is_bad_symlink
= 0;
4775 err
= create_patched_content(&path_content
, 1, &id
,
4776 ondisk_path
, dirfd
, de_name
, ie
->path
, a
->repo
,
4777 a
->patch_cb
, a
->patch_arg
);
4778 if (err
|| path_content
== NULL
)
4780 if (te
&& S_ISLNK(te
->mode
)) {
4781 if (unlink(path_content
) == -1) {
4782 err
= got_error_from_errno2("unlink",
4786 err
= install_symlink(&is_bad_symlink
,
4787 a
->worktree
, ondisk_path
, ie
->path
,
4788 blob
, 0, 1, 0, 0, a
->repo
,
4789 a
->progress_cb
, a
->progress_arg
);
4791 if (rename(path_content
, ondisk_path
) == -1) {
4792 err
= got_error_from_errno3("rename",
4793 path_content
, ondisk_path
);
4798 int is_bad_symlink
= 0;
4799 if (te
&& S_ISLNK(te
->mode
)) {
4800 err
= install_symlink(&is_bad_symlink
,
4801 a
->worktree
, ondisk_path
, ie
->path
,
4802 blob
, 0, 1, 0, 0, a
->repo
,
4803 a
->progress_cb
, a
->progress_arg
);
4805 err
= install_blob(a
->worktree
, ondisk_path
,
4807 te
? te
->mode
: GOT_DEFAULT_FILE_MODE
,
4808 got_fileindex_perms_to_st(ie
), blob
,
4809 0, 1, 0, 0, a
->repo
,
4810 a
->progress_cb
, a
->progress_arg
);
4814 if (status
== GOT_STATUS_DELETE
||
4815 status
== GOT_STATUS_MODE_CHANGE
) {
4816 err
= got_fileindex_entry_update(ie
,
4817 a
->worktree
->root_fd
, relpath
,
4819 a
->worktree
->base_commit_id
->sha1
, 1);
4823 if (is_bad_symlink
) {
4824 got_fileindex_entry_filetype_set(ie
,
4825 GOT_FILEIDX_MODE_BAD_SYMLINK
);
4839 got_object_blob_close(blob
);
4841 got_object_tree_close(tree
);
4846 const struct got_error
*
4847 got_worktree_revert(struct got_worktree
*worktree
,
4848 struct got_pathlist_head
*paths
,
4849 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4850 got_worktree_patch_cb patch_cb
, void *patch_arg
,
4851 struct got_repository
*repo
)
4853 struct got_fileindex
*fileindex
= NULL
;
4854 char *fileindex_path
= NULL
;
4855 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
4856 const struct got_error
*sync_err
= NULL
;
4857 struct got_pathlist_entry
*pe
;
4858 struct revert_file_args rfa
;
4860 err
= lock_worktree(worktree
, LOCK_EX
);
4864 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4868 rfa
.worktree
= worktree
;
4869 rfa
.fileindex
= fileindex
;
4870 rfa
.progress_cb
= progress_cb
;
4871 rfa
.progress_arg
= progress_arg
;
4872 rfa
.patch_cb
= patch_cb
;
4873 rfa
.patch_arg
= patch_arg
;
4875 rfa
.unlink_added_files
= 0;
4876 TAILQ_FOREACH(pe
, paths
, entry
) {
4877 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4878 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
4882 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4883 if (sync_err
&& err
== NULL
)
4886 free(fileindex_path
);
4888 got_fileindex_free(fileindex
);
4889 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4890 if (unlockerr
&& err
== NULL
)
4896 free_commitable(struct got_commitable
*ct
)
4899 free(ct
->in_repo_path
);
4900 free(ct
->ondisk_path
);
4902 free(ct
->base_blob_id
);
4903 free(ct
->staged_blob_id
);
4904 free(ct
->base_commit_id
);
4908 struct collect_commitables_arg
{
4909 struct got_pathlist_head
*commitable_paths
;
4910 struct got_repository
*repo
;
4911 struct got_worktree
*worktree
;
4912 struct got_fileindex
*fileindex
;
4913 int have_staged_files
;
4914 int allow_bad_symlinks
;
4917 static const struct got_error
*
4918 collect_commitables(void *arg
, unsigned char status
,
4919 unsigned char staged_status
, const char *relpath
,
4920 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4921 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4923 struct collect_commitables_arg
*a
= arg
;
4924 const struct got_error
*err
= NULL
;
4925 struct got_commitable
*ct
= NULL
;
4926 struct got_pathlist_entry
*new = NULL
;
4927 char *parent_path
= NULL
, *path
= NULL
;
4930 if (a
->have_staged_files
) {
4931 if (staged_status
!= GOT_STATUS_MODIFY
&&
4932 staged_status
!= GOT_STATUS_ADD
&&
4933 staged_status
!= GOT_STATUS_DELETE
)
4936 if (status
== GOT_STATUS_CONFLICT
)
4937 return got_error(GOT_ERR_COMMIT_CONFLICT
);
4939 if (status
!= GOT_STATUS_MODIFY
&&
4940 status
!= GOT_STATUS_MODE_CHANGE
&&
4941 status
!= GOT_STATUS_ADD
&&
4942 status
!= GOT_STATUS_DELETE
)
4946 if (asprintf(&path
, "/%s", relpath
) == -1) {
4947 err
= got_error_from_errno("asprintf");
4950 if (strcmp(path
, "/") == 0) {
4951 parent_path
= strdup("");
4952 if (parent_path
== NULL
)
4953 return got_error_from_errno("strdup");
4955 err
= got_path_dirname(&parent_path
, path
);
4960 ct
= calloc(1, sizeof(*ct
));
4962 err
= got_error_from_errno("calloc");
4966 if (asprintf(&ct
->ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4968 err
= got_error_from_errno("asprintf");
4972 if (staged_status
== GOT_STATUS_ADD
||
4973 staged_status
== GOT_STATUS_MODIFY
) {
4974 struct got_fileindex_entry
*ie
;
4975 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
4976 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
4977 case GOT_FILEIDX_MODE_REGULAR_FILE
:
4978 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
4981 case GOT_FILEIDX_MODE_SYMLINK
:
4985 err
= got_error_path(path
, GOT_ERR_BAD_FILETYPE
);
4988 ct
->mode
|= got_fileindex_entry_perms_get(ie
);
4989 } else if (status
!= GOT_STATUS_DELETE
&&
4990 staged_status
!= GOT_STATUS_DELETE
) {
4992 if (fstatat(dirfd
, de_name
, &sb
,
4993 AT_SYMLINK_NOFOLLOW
) == -1) {
4994 err
= got_error_from_errno2("fstatat",
4998 } else if (lstat(ct
->ondisk_path
, &sb
) == -1) {
4999 err
= got_error_from_errno2("lstat", ct
->ondisk_path
);
5002 ct
->mode
= sb
.st_mode
;
5005 if (asprintf(&ct
->in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
5006 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
5008 err
= got_error_from_errno("asprintf");
5012 if (S_ISLNK(ct
->mode
) && staged_status
== GOT_STATUS_NO_CHANGE
&&
5013 status
== GOT_STATUS_ADD
&& !a
->allow_bad_symlinks
) {
5015 char target_path
[PATH_MAX
];
5017 target_len
= readlink(ct
->ondisk_path
, target_path
,
5018 sizeof(target_path
));
5019 if (target_len
== -1) {
5020 err
= got_error_from_errno2("readlink",
5024 err
= is_bad_symlink_target(&is_bad_symlink
, target_path
,
5025 target_len
, ct
->ondisk_path
, a
->worktree
->root_path
);
5028 if (is_bad_symlink
) {
5029 err
= got_error_path(ct
->ondisk_path
,
5030 GOT_ERR_BAD_SYMLINK
);
5036 ct
->status
= status
;
5037 ct
->staged_status
= staged_status
;
5038 ct
->blob_id
= NULL
; /* will be filled in when blob gets created */
5039 if (ct
->status
!= GOT_STATUS_ADD
&&
5040 ct
->staged_status
!= GOT_STATUS_ADD
) {
5041 ct
->base_blob_id
= got_object_id_dup(blob_id
);
5042 if (ct
->base_blob_id
== NULL
) {
5043 err
= got_error_from_errno("got_object_id_dup");
5046 ct
->base_commit_id
= got_object_id_dup(commit_id
);
5047 if (ct
->base_commit_id
== NULL
) {
5048 err
= got_error_from_errno("got_object_id_dup");
5052 if (ct
->staged_status
== GOT_STATUS_ADD
||
5053 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5054 ct
->staged_blob_id
= got_object_id_dup(staged_blob_id
);
5055 if (ct
->staged_blob_id
== NULL
) {
5056 err
= got_error_from_errno("got_object_id_dup");
5060 ct
->path
= strdup(path
);
5061 if (ct
->path
== NULL
) {
5062 err
= got_error_from_errno("strdup");
5065 err
= got_pathlist_insert(&new, a
->commitable_paths
, ct
->path
, ct
);
5067 if (ct
&& (err
|| new == NULL
))
5068 free_commitable(ct
);
5074 static const struct got_error
*write_tree(struct got_object_id
**, int *,
5075 struct got_tree_object
*, const char *, struct got_pathlist_head
*,
5076 got_worktree_status_cb status_cb
, void *status_arg
,
5077 struct got_repository
*);
5079 static const struct got_error
*
5080 write_subtree(struct got_object_id
**new_subtree_id
, int *nentries
,
5081 struct got_tree_entry
*te
, const char *parent_path
,
5082 struct got_pathlist_head
*commitable_paths
,
5083 got_worktree_status_cb status_cb
, void *status_arg
,
5084 struct got_repository
*repo
)
5086 const struct got_error
*err
= NULL
;
5087 struct got_tree_object
*subtree
;
5090 if (asprintf(&subpath
, "%s%s%s", parent_path
,
5091 got_path_is_root_dir(parent_path
) ? "" : "/", te
->name
) == -1)
5092 return got_error_from_errno("asprintf");
5094 err
= got_object_open_as_tree(&subtree
, repo
, &te
->id
);
5098 err
= write_tree(new_subtree_id
, nentries
, subtree
, subpath
,
5099 commitable_paths
, status_cb
, status_arg
, repo
);
5100 got_object_tree_close(subtree
);
5105 static const struct got_error
*
5106 match_ct_parent_path(int *match
, struct got_commitable
*ct
, const char *path
)
5108 const struct got_error
*err
= NULL
;
5109 char *ct_parent_path
= NULL
;
5113 if (strchr(ct
->in_repo_path
, '/') == NULL
) {
5114 *match
= got_path_is_root_dir(path
);
5118 err
= got_path_dirname(&ct_parent_path
, ct
->in_repo_path
);
5121 *match
= (strcmp(path
, ct_parent_path
) == 0);
5122 free(ct_parent_path
);
5127 get_ct_file_mode(struct got_commitable
*ct
)
5129 if (S_ISLNK(ct
->mode
))
5132 return S_IFREG
| (ct
->mode
& ((S_IRWXU
| S_IRWXG
| S_IRWXO
)));
5135 static const struct got_error
*
5136 alloc_modified_blob_tree_entry(struct got_tree_entry
**new_te
,
5137 struct got_tree_entry
*te
, struct got_commitable
*ct
)
5139 const struct got_error
*err
= NULL
;
5143 err
= got_object_tree_entry_dup(new_te
, te
);
5147 (*new_te
)->mode
= get_ct_file_mode(ct
);
5149 if (ct
->staged_status
== GOT_STATUS_MODIFY
)
5150 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5151 sizeof((*new_te
)->id
));
5153 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5155 if (err
&& *new_te
) {
5162 static const struct got_error
*
5163 alloc_added_blob_tree_entry(struct got_tree_entry
**new_te
,
5164 struct got_commitable
*ct
)
5166 const struct got_error
*err
= NULL
;
5167 char *ct_name
= NULL
;
5171 *new_te
= calloc(1, sizeof(**new_te
));
5172 if (*new_te
== NULL
)
5173 return got_error_from_errno("calloc");
5175 err
= got_path_basename(&ct_name
, ct
->path
);
5178 if (strlcpy((*new_te
)->name
, ct_name
, sizeof((*new_te
)->name
)) >=
5179 sizeof((*new_te
)->name
)) {
5180 err
= got_error(GOT_ERR_NO_SPACE
);
5184 (*new_te
)->mode
= get_ct_file_mode(ct
);
5186 if (ct
->staged_status
== GOT_STATUS_ADD
)
5187 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5188 sizeof((*new_te
)->id
));
5190 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5193 if (err
&& *new_te
) {
5200 static const struct got_error
*
5201 insert_tree_entry(struct got_tree_entry
*new_te
,
5202 struct got_pathlist_head
*paths
)
5204 const struct got_error
*err
= NULL
;
5205 struct got_pathlist_entry
*new_pe
;
5207 err
= got_pathlist_insert(&new_pe
, paths
, new_te
->name
, new_te
);
5211 return got_error(GOT_ERR_TREE_DUP_ENTRY
);
5215 static const struct got_error
*
5216 report_ct_status(struct got_commitable
*ct
,
5217 got_worktree_status_cb status_cb
, void *status_arg
)
5219 const char *ct_path
= ct
->path
;
5220 unsigned char status
;
5222 if (status_cb
== NULL
) /* no commit progress output desired */
5225 while (ct_path
[0] == '/')
5228 if (ct
->staged_status
!= GOT_STATUS_NO_CHANGE
)
5229 status
= ct
->staged_status
;
5231 status
= ct
->status
;
5233 return (*status_cb
)(status_arg
, status
, GOT_STATUS_NO_CHANGE
,
5234 ct_path
, ct
->blob_id
, NULL
, NULL
, -1, NULL
);
5237 static const struct got_error
*
5238 match_modified_subtree(int *modified
, struct got_tree_entry
*te
,
5239 const char *base_tree_path
, struct got_pathlist_head
*commitable_paths
)
5241 const struct got_error
*err
= NULL
;
5242 struct got_pathlist_entry
*pe
;
5247 if (asprintf(&te_path
, "%s%s%s", base_tree_path
,
5248 got_path_is_root_dir(base_tree_path
) ? "" : "/",
5250 return got_error_from_errno("asprintf");
5252 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5253 struct got_commitable
*ct
= pe
->data
;
5254 *modified
= got_path_is_child(ct
->in_repo_path
, te_path
,
5264 static const struct got_error
*
5265 match_deleted_or_modified_ct(struct got_commitable
**ctp
,
5266 struct got_tree_entry
*te
, const char *base_tree_path
,
5267 struct got_pathlist_head
*commitable_paths
)
5269 const struct got_error
*err
= NULL
;
5270 struct got_pathlist_entry
*pe
;
5274 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5275 struct got_commitable
*ct
= pe
->data
;
5276 char *ct_name
= NULL
;
5279 if (ct
->staged_status
== GOT_STATUS_NO_CHANGE
) {
5280 if (ct
->status
!= GOT_STATUS_MODIFY
&&
5281 ct
->status
!= GOT_STATUS_MODE_CHANGE
&&
5282 ct
->status
!= GOT_STATUS_DELETE
)
5285 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
5286 ct
->staged_status
!= GOT_STATUS_DELETE
)
5290 if (got_object_id_cmp(ct
->base_blob_id
, &te
->id
) != 0)
5293 err
= match_ct_parent_path(&path_matches
, ct
, base_tree_path
);
5299 err
= got_path_basename(&ct_name
, pe
->path
);
5303 if (strcmp(te
->name
, ct_name
) != 0) {
5316 static const struct got_error
*
5317 make_subtree_for_added_blob(struct got_tree_entry
**new_tep
,
5318 const char *child_path
, const char *path_base_tree
,
5319 struct got_pathlist_head
*commitable_paths
,
5320 got_worktree_status_cb status_cb
, void *status_arg
,
5321 struct got_repository
*repo
)
5323 const struct got_error
*err
= NULL
;
5324 struct got_tree_entry
*new_te
;
5326 struct got_object_id
*id
= NULL
;
5331 if (asprintf(&subtree_path
, "%s%s%s", path_base_tree
,
5332 got_path_is_root_dir(path_base_tree
) ? "" : "/",
5334 return got_error_from_errno("asprintf");
5336 new_te
= calloc(1, sizeof(*new_te
));
5338 return got_error_from_errno("calloc");
5339 new_te
->mode
= S_IFDIR
;
5341 if (strlcpy(new_te
->name
, child_path
, sizeof(new_te
->name
)) >=
5342 sizeof(new_te
->name
)) {
5343 err
= got_error(GOT_ERR_NO_SPACE
);
5346 err
= write_tree(&id
, &nentries
, NULL
, subtree_path
,
5347 commitable_paths
, status_cb
, status_arg
, repo
);
5352 memcpy(&new_te
->id
, id
, sizeof(new_te
->id
));
5361 static const struct got_error
*
5362 write_tree(struct got_object_id
**new_tree_id
, int *nentries
,
5363 struct got_tree_object
*base_tree
, const char *path_base_tree
,
5364 struct got_pathlist_head
*commitable_paths
,
5365 got_worktree_status_cb status_cb
, void *status_arg
,
5366 struct got_repository
*repo
)
5368 const struct got_error
*err
= NULL
;
5369 struct got_pathlist_head paths
;
5370 struct got_tree_entry
*te
, *new_te
= NULL
;
5371 struct got_pathlist_entry
*pe
;
5376 /* Insert, and recurse into, newly added entries first. */
5377 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5378 struct got_commitable
*ct
= pe
->data
;
5379 char *child_path
= NULL
, *slash
;
5381 if ((ct
->status
!= GOT_STATUS_ADD
&&
5382 ct
->staged_status
!= GOT_STATUS_ADD
) ||
5383 (ct
->flags
& GOT_COMMITABLE_ADDED
))
5386 if (!got_path_is_child(ct
->in_repo_path
, path_base_tree
,
5387 strlen(path_base_tree
)))
5390 err
= got_path_skip_common_ancestor(&child_path
, path_base_tree
,
5395 slash
= strchr(child_path
, '/');
5396 if (slash
== NULL
) {
5397 err
= alloc_added_blob_tree_entry(&new_te
, ct
);
5400 err
= report_ct_status(ct
, status_cb
, status_arg
);
5403 ct
->flags
|= GOT_COMMITABLE_ADDED
;
5404 err
= insert_tree_entry(new_te
, &paths
);
5409 *slash
= '\0'; /* trim trailing path components */
5410 if (base_tree
== NULL
||
5411 got_object_tree_find_entry(base_tree
, child_path
)
5413 err
= make_subtree_for_added_blob(&new_te
,
5414 child_path
, path_base_tree
,
5415 commitable_paths
, status_cb
, status_arg
,
5419 err
= insert_tree_entry(new_te
, &paths
);
5428 int i
, nbase_entries
;
5429 /* Handle modified and deleted entries. */
5430 nbase_entries
= got_object_tree_get_nentries(base_tree
);
5431 for (i
= 0; i
< nbase_entries
; i
++) {
5432 struct got_commitable
*ct
= NULL
;
5434 te
= got_object_tree_get_entry(base_tree
, i
);
5435 if (got_object_tree_entry_is_submodule(te
)) {
5436 /* Entry is a submodule; just copy it. */
5437 err
= got_object_tree_entry_dup(&new_te
, te
);
5440 err
= insert_tree_entry(new_te
, &paths
);
5447 if (S_ISDIR(te
->mode
)) {
5449 err
= got_object_tree_entry_dup(&new_te
, te
);
5452 err
= match_modified_subtree(&modified
, te
,
5453 path_base_tree
, commitable_paths
);
5456 /* Avoid recursion into unmodified subtrees. */
5458 struct got_object_id
*new_id
;
5460 err
= write_subtree(&new_id
,
5462 path_base_tree
, commitable_paths
,
5463 status_cb
, status_arg
, repo
);
5466 if (nsubentries
== 0) {
5467 /* All entries were deleted. */
5471 memcpy(&new_te
->id
, new_id
,
5472 sizeof(new_te
->id
));
5475 err
= insert_tree_entry(new_te
, &paths
);
5482 err
= match_deleted_or_modified_ct(&ct
, te
,
5483 path_base_tree
, commitable_paths
);
5487 /* NB: Deleted entries get dropped here. */
5488 if (ct
->status
== GOT_STATUS_MODIFY
||
5489 ct
->status
== GOT_STATUS_MODE_CHANGE
||
5490 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5491 err
= alloc_modified_blob_tree_entry(
5495 err
= insert_tree_entry(new_te
, &paths
);
5500 err
= report_ct_status(ct
, status_cb
,
5505 /* Entry is unchanged; just copy it. */
5506 err
= got_object_tree_entry_dup(&new_te
, te
);
5509 err
= insert_tree_entry(new_te
, &paths
);
5517 /* Write new list of entries; deleted entries have been dropped. */
5518 err
= got_object_tree_create(new_tree_id
, &paths
, *nentries
, repo
);
5520 got_pathlist_free(&paths
);
5524 static const struct got_error
*
5525 update_fileindex_after_commit(struct got_worktree
*worktree
,
5526 struct got_pathlist_head
*commitable_paths
,
5527 struct got_object_id
*new_base_commit_id
,
5528 struct got_fileindex
*fileindex
, int have_staged_files
)
5530 const struct got_error
*err
= NULL
;
5531 struct got_pathlist_entry
*pe
;
5532 char *relpath
= NULL
;
5534 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5535 struct got_fileindex_entry
*ie
;
5536 struct got_commitable
*ct
= pe
->data
;
5538 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
5540 err
= got_path_skip_common_ancestor(&relpath
,
5541 worktree
->root_path
, ct
->ondisk_path
);
5546 if (ct
->status
== GOT_STATUS_DELETE
||
5547 ct
->staged_status
== GOT_STATUS_DELETE
) {
5548 got_fileindex_entry_remove(fileindex
, ie
);
5549 } else if (ct
->staged_status
== GOT_STATUS_ADD
||
5550 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5551 got_fileindex_entry_stage_set(ie
,
5552 GOT_FILEIDX_STAGE_NONE
);
5553 got_fileindex_entry_staged_filetype_set(ie
, 0);
5555 err
= got_fileindex_entry_update(ie
,
5556 worktree
->root_fd
, relpath
,
5557 ct
->staged_blob_id
->sha1
,
5558 new_base_commit_id
->sha1
,
5559 !have_staged_files
);
5561 err
= got_fileindex_entry_update(ie
,
5562 worktree
->root_fd
, relpath
,
5564 new_base_commit_id
->sha1
,
5565 !have_staged_files
);
5567 err
= got_fileindex_entry_alloc(&ie
, pe
->path
);
5570 err
= got_fileindex_entry_update(ie
,
5571 worktree
->root_fd
, relpath
, ct
->blob_id
->sha1
,
5572 new_base_commit_id
->sha1
, 1);
5574 got_fileindex_entry_free(ie
);
5577 err
= got_fileindex_entry_add(fileindex
, ie
);
5579 got_fileindex_entry_free(ie
);
5592 static const struct got_error
*
5593 check_out_of_date(const char *in_repo_path
, unsigned char status
,
5594 unsigned char staged_status
, struct got_object_id
*base_blob_id
,
5595 struct got_object_id
*base_commit_id
,
5596 struct got_object_id
*head_commit_id
, struct got_repository
*repo
,
5599 const struct got_error
*err
= NULL
;
5600 struct got_object_id
*id
= NULL
;
5602 if (status
!= GOT_STATUS_ADD
&& staged_status
!= GOT_STATUS_ADD
) {
5603 /* Trivial case: base commit == head commit */
5604 if (got_object_id_cmp(base_commit_id
, head_commit_id
) == 0)
5607 * Ensure file content which local changes were based
5608 * on matches file content in the branch head.
5610 err
= got_object_id_by_path(&id
, repo
, head_commit_id
,
5613 if (err
->code
== GOT_ERR_NO_TREE_ENTRY
)
5614 err
= got_error(ood_errcode
);
5616 } else if (got_object_id_cmp(id
, base_blob_id
) != 0)
5617 err
= got_error(ood_errcode
);
5619 /* Require that added files don't exist in the branch head. */
5620 err
= got_object_id_by_path(&id
, repo
, head_commit_id
,
5622 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
5624 err
= id
? got_error(ood_errcode
) : NULL
;
5631 const struct got_error
*
5632 commit_worktree(struct got_object_id
**new_commit_id
,
5633 struct got_pathlist_head
*commitable_paths
,
5634 struct got_object_id
*head_commit_id
,
5635 struct got_object_id
*parent_id2
,
5636 struct got_worktree
*worktree
,
5637 const char *author
, const char *committer
,
5638 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
5639 got_worktree_status_cb status_cb
, void *status_arg
,
5640 struct got_repository
*repo
)
5642 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
5643 struct got_pathlist_entry
*pe
;
5644 const char *head_ref_name
= NULL
;
5645 struct got_commit_object
*head_commit
= NULL
;
5646 struct got_reference
*head_ref2
= NULL
;
5647 struct got_object_id
*head_commit_id2
= NULL
;
5648 struct got_tree_object
*head_tree
= NULL
;
5649 struct got_object_id
*new_tree_id
= NULL
;
5650 int nentries
, nparents
= 0;
5651 struct got_object_id_queue parent_ids
;
5652 struct got_object_qid
*pid
= NULL
;
5653 char *logmsg
= NULL
;
5655 *new_commit_id
= NULL
;
5657 STAILQ_INIT(&parent_ids
);
5659 err
= got_object_open_as_commit(&head_commit
, repo
, head_commit_id
);
5663 err
= got_object_open_as_tree(&head_tree
, repo
, head_commit
->tree_id
);
5667 if (commit_msg_cb
!= NULL
) {
5668 err
= commit_msg_cb(commitable_paths
, &logmsg
, commit_arg
);
5673 if (logmsg
== NULL
|| strlen(logmsg
) == 0) {
5674 err
= got_error(GOT_ERR_COMMIT_MSG_EMPTY
);
5678 /* Create blobs from added and modified files and record their IDs. */
5679 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5680 struct got_commitable
*ct
= pe
->data
;
5683 /* Blobs for staged files already exist. */
5684 if (ct
->staged_status
== GOT_STATUS_ADD
||
5685 ct
->staged_status
== GOT_STATUS_MODIFY
)
5688 if (ct
->status
!= GOT_STATUS_ADD
&&
5689 ct
->status
!= GOT_STATUS_MODIFY
&&
5690 ct
->status
!= GOT_STATUS_MODE_CHANGE
)
5693 if (asprintf(&ondisk_path
, "%s/%s",
5694 worktree
->root_path
, pe
->path
) == -1) {
5695 err
= got_error_from_errno("asprintf");
5698 err
= got_object_blob_create(&ct
->blob_id
, ondisk_path
, repo
);
5704 /* Recursively write new tree objects. */
5705 err
= write_tree(&new_tree_id
, &nentries
, head_tree
, "/",
5706 commitable_paths
, status_cb
, status_arg
, repo
);
5710 err
= got_object_qid_alloc(&pid
, worktree
->base_commit_id
);
5713 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
5716 err
= got_object_qid_alloc(&pid
, parent_id2
);
5719 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
5722 err
= got_object_commit_create(new_commit_id
, new_tree_id
, &parent_ids
,
5723 nparents
, author
, time(NULL
), committer
, time(NULL
), logmsg
, repo
);
5729 /* Check if a concurrent commit to our branch has occurred. */
5730 head_ref_name
= got_worktree_get_head_ref_name(worktree
);
5731 if (head_ref_name
== NULL
) {
5732 err
= got_error_from_errno("got_worktree_get_head_ref_name");
5735 /* Lock the reference here to prevent concurrent modification. */
5736 err
= got_ref_open(&head_ref2
, repo
, head_ref_name
, 1);
5739 err
= got_ref_resolve(&head_commit_id2
, repo
, head_ref2
);
5742 if (got_object_id_cmp(head_commit_id
, head_commit_id2
) != 0) {
5743 err
= got_error(GOT_ERR_COMMIT_HEAD_CHANGED
);
5746 /* Update branch head in repository. */
5747 err
= got_ref_change_ref(head_ref2
, *new_commit_id
);
5750 err
= got_ref_write(head_ref2
, repo
);
5754 err
= got_worktree_set_base_commit_id(worktree
, repo
, *new_commit_id
);
5758 err
= ref_base_commit(worktree
, repo
);
5762 got_object_id_queue_free(&parent_ids
);
5764 got_object_tree_close(head_tree
);
5766 got_object_commit_close(head_commit
);
5767 free(head_commit_id2
);
5769 unlockerr
= got_ref_unlock(head_ref2
);
5770 if (unlockerr
&& err
== NULL
)
5772 got_ref_close(head_ref2
);
5777 static const struct got_error
*
5778 check_path_is_commitable(const char *path
,
5779 struct got_pathlist_head
*commitable_paths
)
5781 struct got_pathlist_entry
*cpe
= NULL
;
5782 size_t path_len
= strlen(path
);
5784 TAILQ_FOREACH(cpe
, commitable_paths
, entry
) {
5785 struct got_commitable
*ct
= cpe
->data
;
5786 const char *ct_path
= ct
->path
;
5788 while (ct_path
[0] == '/')
5791 if (strcmp(path
, ct_path
) == 0 ||
5792 got_path_is_child(ct_path
, path
, path_len
))
5797 return got_error_path(path
, GOT_ERR_BAD_PATH
);
5802 static const struct got_error
*
5803 check_staged_file(void *arg
, struct got_fileindex_entry
*ie
)
5805 int *have_staged_files
= arg
;
5807 if (got_fileindex_entry_stage_get(ie
) != GOT_FILEIDX_STAGE_NONE
) {
5808 *have_staged_files
= 1;
5809 return got_error(GOT_ERR_CANCELLED
);
5815 static const struct got_error
*
5816 check_non_staged_files(struct got_fileindex
*fileindex
,
5817 struct got_pathlist_head
*paths
)
5819 struct got_pathlist_entry
*pe
;
5820 struct got_fileindex_entry
*ie
;
5822 TAILQ_FOREACH(pe
, paths
, entry
) {
5823 if (pe
->path
[0] == '\0')
5825 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
5827 return got_error_path(pe
->path
, GOT_ERR_BAD_PATH
);
5828 if (got_fileindex_entry_stage_get(ie
) == GOT_FILEIDX_STAGE_NONE
)
5829 return got_error_path(pe
->path
,
5830 GOT_ERR_FILE_NOT_STAGED
);
5836 const struct got_error
*
5837 got_worktree_commit(struct got_object_id
**new_commit_id
,
5838 struct got_worktree
*worktree
, struct got_pathlist_head
*paths
,
5839 const char *author
, const char *committer
, int allow_bad_symlinks
,
5840 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
5841 got_worktree_status_cb status_cb
, void *status_arg
,
5842 struct got_repository
*repo
)
5844 const struct got_error
*err
= NULL
, *unlockerr
= NULL
, *sync_err
;
5845 struct got_fileindex
*fileindex
= NULL
;
5846 char *fileindex_path
= NULL
;
5847 struct got_pathlist_head commitable_paths
;
5848 struct collect_commitables_arg cc_arg
;
5849 struct got_pathlist_entry
*pe
;
5850 struct got_reference
*head_ref
= NULL
;
5851 struct got_object_id
*head_commit_id
= NULL
;
5852 int have_staged_files
= 0;
5854 *new_commit_id
= NULL
;
5856 TAILQ_INIT(&commitable_paths
);
5858 err
= lock_worktree(worktree
, LOCK_EX
);
5862 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
5866 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
5870 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
5874 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
5875 &have_staged_files
);
5876 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
5878 if (have_staged_files
) {
5879 err
= check_non_staged_files(fileindex
, paths
);
5884 cc_arg
.commitable_paths
= &commitable_paths
;
5885 cc_arg
.worktree
= worktree
;
5886 cc_arg
.fileindex
= fileindex
;
5888 cc_arg
.have_staged_files
= have_staged_files
;
5889 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
5890 TAILQ_FOREACH(pe
, paths
, entry
) {
5891 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
5892 collect_commitables
, &cc_arg
, NULL
, NULL
, 0, 0);
5897 if (TAILQ_EMPTY(&commitable_paths
)) {
5898 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
5902 TAILQ_FOREACH(pe
, paths
, entry
) {
5903 err
= check_path_is_commitable(pe
->path
, &commitable_paths
);
5908 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
5909 struct got_commitable
*ct
= pe
->data
;
5910 const char *ct_path
= ct
->in_repo_path
;
5912 while (ct_path
[0] == '/')
5914 err
= check_out_of_date(ct_path
, ct
->status
,
5915 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
5916 head_commit_id
, repo
, GOT_ERR_COMMIT_OUT_OF_DATE
);
5922 err
= commit_worktree(new_commit_id
, &commitable_paths
,
5923 head_commit_id
, NULL
, worktree
, author
, committer
,
5924 commit_msg_cb
, commit_arg
, status_cb
, status_arg
, repo
);
5928 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
5929 *new_commit_id
, fileindex
, have_staged_files
);
5930 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
5931 if (sync_err
&& err
== NULL
)
5935 got_fileindex_free(fileindex
);
5936 free(fileindex_path
);
5937 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
5938 if (unlockerr
&& err
== NULL
)
5940 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
5941 struct got_commitable
*ct
= pe
->data
;
5942 free_commitable(ct
);
5944 got_pathlist_free(&commitable_paths
);
5949 got_commitable_get_path(struct got_commitable
*ct
)
5955 got_commitable_get_status(struct got_commitable
*ct
)
5960 struct check_rebase_ok_arg
{
5961 struct got_worktree
*worktree
;
5962 struct got_repository
*repo
;
5965 static const struct got_error
*
5966 check_rebase_ok(void *arg
, struct got_fileindex_entry
*ie
)
5968 const struct got_error
*err
= NULL
;
5969 struct check_rebase_ok_arg
*a
= arg
;
5970 unsigned char status
;
5974 /* Reject rebase of a work tree with mixed base commits. */
5975 if (memcmp(ie
->commit_sha1
, a
->worktree
->base_commit_id
->sha1
,
5976 SHA1_DIGEST_LENGTH
))
5977 return got_error(GOT_ERR_MIXED_COMMITS
);
5979 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
5981 return got_error_from_errno("asprintf");
5983 /* Reject rebase of a work tree with modified or staged files. */
5984 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
5989 if (status
!= GOT_STATUS_NO_CHANGE
)
5990 return got_error(GOT_ERR_MODIFIED
);
5991 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
5992 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
5997 const struct got_error
*
5998 got_worktree_rebase_prepare(struct got_reference
**new_base_branch_ref
,
5999 struct got_reference
**tmp_branch
, struct got_fileindex
**fileindex
,
6000 struct got_worktree
*worktree
, struct got_reference
*branch
,
6001 struct got_repository
*repo
)
6003 const struct got_error
*err
= NULL
;
6004 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6005 char *branch_ref_name
= NULL
;
6006 char *fileindex_path
= NULL
;
6007 struct check_rebase_ok_arg ok_arg
;
6008 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
6009 struct got_object_id
*wt_branch_tip
= NULL
;
6011 *new_base_branch_ref
= NULL
;
6015 err
= lock_worktree(worktree
, LOCK_EX
);
6019 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6023 ok_arg
.worktree
= worktree
;
6025 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6030 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6034 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6038 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6042 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6047 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
6050 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
6051 err
= got_error(GOT_ERR_REBASE_OUT_OF_DATE
);
6055 err
= got_ref_alloc_symref(new_base_branch_ref
,
6056 new_base_branch_ref_name
, wt_branch
);
6059 err
= got_ref_write(*new_base_branch_ref
, repo
);
6063 /* TODO Lock original branch's ref while rebasing? */
6065 err
= got_ref_alloc_symref(&branch_ref
, branch_ref_name
, branch
);
6069 err
= got_ref_write(branch_ref
, repo
);
6073 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6074 worktree
->base_commit_id
);
6077 err
= got_ref_write(*tmp_branch
, repo
);
6081 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6085 free(fileindex_path
);
6086 free(tmp_branch_name
);
6087 free(new_base_branch_ref_name
);
6088 free(branch_ref_name
);
6090 got_ref_close(branch_ref
);
6092 got_ref_close(wt_branch
);
6093 free(wt_branch_tip
);
6095 if (*new_base_branch_ref
) {
6096 got_ref_close(*new_base_branch_ref
);
6097 *new_base_branch_ref
= NULL
;
6100 got_ref_close(*tmp_branch
);
6104 got_fileindex_free(*fileindex
);
6107 lock_worktree(worktree
, LOCK_SH
);
6112 const struct got_error
*
6113 got_worktree_rebase_continue(struct got_object_id
**commit_id
,
6114 struct got_reference
**new_base_branch
, struct got_reference
**tmp_branch
,
6115 struct got_reference
**branch
, struct got_fileindex
**fileindex
,
6116 struct got_worktree
*worktree
, struct got_repository
*repo
)
6118 const struct got_error
*err
;
6119 char *commit_ref_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6120 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
6121 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
6122 char *fileindex_path
= NULL
;
6123 int have_staged_files
= 0;
6126 *new_base_branch
= NULL
;
6131 err
= lock_worktree(worktree
, LOCK_EX
);
6135 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6139 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
6140 &have_staged_files
);
6141 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6143 if (have_staged_files
) {
6144 err
= got_error(GOT_ERR_STAGED_PATHS
);
6148 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6152 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6156 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6160 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6164 err
= got_ref_open(&branch_ref
, repo
, branch_ref_name
, 0);
6168 err
= got_ref_open(branch
, repo
,
6169 got_ref_get_symref_target(branch_ref
), 0);
6173 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6177 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
6181 err
= got_ref_open(new_base_branch
, repo
,
6182 new_base_branch_ref_name
, 0);
6186 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
6190 free(commit_ref_name
);
6191 free(branch_ref_name
);
6192 free(fileindex_path
);
6194 got_ref_close(commit_ref
);
6196 got_ref_close(branch_ref
);
6201 got_ref_close(*tmp_branch
);
6204 if (*new_base_branch
) {
6205 got_ref_close(*new_base_branch
);
6206 *new_base_branch
= NULL
;
6209 got_ref_close(*branch
);
6213 got_fileindex_free(*fileindex
);
6216 lock_worktree(worktree
, LOCK_SH
);
6221 const struct got_error
*
6222 got_worktree_rebase_in_progress(int *in_progress
, struct got_worktree
*worktree
)
6224 const struct got_error
*err
;
6225 char *tmp_branch_name
= NULL
;
6227 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6231 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
6232 free(tmp_branch_name
);
6236 static const struct got_error
*
6237 collect_rebase_commit_msg(struct got_pathlist_head
*commitable_paths
,
6238 char **logmsg
, void *arg
)
6244 static const struct got_error
*
6245 rebase_status(void *arg
, unsigned char status
, unsigned char staged_status
,
6246 const char *path
, struct got_object_id
*blob_id
,
6247 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
6248 int dirfd
, const char *de_name
)
6253 struct collect_merged_paths_arg
{
6254 got_worktree_checkout_cb progress_cb
;
6256 struct got_pathlist_head
*merged_paths
;
6259 static const struct got_error
*
6260 collect_merged_paths(void *arg
, unsigned char status
, const char *path
)
6262 const struct got_error
*err
;
6263 struct collect_merged_paths_arg
*a
= arg
;
6265 struct got_pathlist_entry
*new;
6267 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path
);
6271 if (status
!= GOT_STATUS_MERGE
&&
6272 status
!= GOT_STATUS_ADD
&&
6273 status
!= GOT_STATUS_DELETE
&&
6274 status
!= GOT_STATUS_CONFLICT
)
6279 return got_error_from_errno("strdup");
6281 err
= got_pathlist_insert(&new, a
->merged_paths
, p
, NULL
);
6282 if (err
|| new == NULL
)
6288 got_worktree_rebase_pathlist_free(struct got_pathlist_head
*merged_paths
)
6290 struct got_pathlist_entry
*pe
;
6292 TAILQ_FOREACH(pe
, merged_paths
, entry
)
6293 free((char *)pe
->path
);
6295 got_pathlist_free(merged_paths
);
6298 static const struct got_error
*
6299 store_commit_id(const char *commit_ref_name
, struct got_object_id
*commit_id
,
6300 int is_rebase
, struct got_repository
*repo
)
6302 const struct got_error
*err
;
6303 struct got_reference
*commit_ref
= NULL
;
6305 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6307 if (err
->code
!= GOT_ERR_NOT_REF
)
6309 err
= got_ref_alloc(&commit_ref
, commit_ref_name
, commit_id
);
6312 err
= got_ref_write(commit_ref
, repo
);
6315 } else if (is_rebase
) {
6316 struct got_object_id
*stored_id
;
6319 err
= got_ref_resolve(&stored_id
, repo
, commit_ref
);
6322 cmp
= got_object_id_cmp(commit_id
, stored_id
);
6325 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6331 got_ref_close(commit_ref
);
6335 static const struct got_error
*
6336 rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6337 const char *commit_ref_name
, struct got_worktree
*worktree
,
6338 struct got_fileindex
*fileindex
, struct got_object_id
*parent_commit_id
,
6339 struct got_object_id
*commit_id
, struct got_repository
*repo
,
6340 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6341 got_cancel_cb cancel_cb
, void *cancel_arg
)
6343 const struct got_error
*err
;
6344 struct got_reference
*commit_ref
= NULL
;
6345 struct collect_merged_paths_arg cmp_arg
;
6346 char *fileindex_path
;
6348 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6350 err
= get_fileindex_path(&fileindex_path
, worktree
);
6354 cmp_arg
.progress_cb
= progress_cb
;
6355 cmp_arg
.progress_arg
= progress_arg
;
6356 cmp_arg
.merged_paths
= merged_paths
;
6357 err
= merge_files(worktree
, fileindex
, fileindex_path
,
6358 parent_commit_id
, commit_id
, repo
, collect_merged_paths
,
6359 &cmp_arg
, cancel_cb
, cancel_arg
);
6361 got_ref_close(commit_ref
);
6365 const struct got_error
*
6366 got_worktree_rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6367 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6368 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
6369 struct got_repository
*repo
,
6370 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6371 got_cancel_cb cancel_cb
, void *cancel_arg
)
6373 const struct got_error
*err
;
6374 char *commit_ref_name
;
6376 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6380 err
= store_commit_id(commit_ref_name
, commit_id
, 1, repo
);
6384 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
6385 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
6386 progress_arg
, cancel_cb
, cancel_arg
);
6388 free(commit_ref_name
);
6392 const struct got_error
*
6393 got_worktree_histedit_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_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6407 err
= store_commit_id(commit_ref_name
, commit_id
, 0, 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 static const struct got_error
*
6420 rebase_commit(struct got_object_id
**new_commit_id
,
6421 struct got_pathlist_head
*merged_paths
, struct got_reference
*commit_ref
,
6422 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6423 struct got_reference
*tmp_branch
, struct got_commit_object
*orig_commit
,
6424 const char *new_logmsg
, struct got_repository
*repo
)
6426 const struct got_error
*err
, *sync_err
;
6427 struct got_pathlist_head commitable_paths
;
6428 struct collect_commitables_arg cc_arg
;
6429 char *fileindex_path
= NULL
;
6430 struct got_reference
*head_ref
= NULL
;
6431 struct got_object_id
*head_commit_id
= NULL
;
6432 char *logmsg
= NULL
;
6434 TAILQ_INIT(&commitable_paths
);
6435 *new_commit_id
= NULL
;
6437 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6439 err
= get_fileindex_path(&fileindex_path
, worktree
);
6443 cc_arg
.commitable_paths
= &commitable_paths
;
6444 cc_arg
.worktree
= worktree
;
6446 cc_arg
.have_staged_files
= 0;
6448 * If possible get the status of individual files directly to
6449 * avoid crawling the entire work tree once per rebased commit.
6451 * Ideally, merged_paths would contain a list of commitables
6452 * we could use so we could skip worktree_status() entirely.
6453 * However, we would then need carefully keep track of cumulative
6454 * effects of operations such as file additions and deletions
6455 * in 'got histedit -f' (folding multiple commits into one),
6456 * and this extra complexity is not really worth it.
6459 struct got_pathlist_entry
*pe
;
6460 TAILQ_FOREACH(pe
, merged_paths
, entry
) {
6461 err
= worktree_status(worktree
, pe
->path
, fileindex
,
6462 repo
, collect_commitables
, &cc_arg
, NULL
, NULL
, 1,
6468 err
= worktree_status(worktree
, "", fileindex
, repo
,
6469 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
6474 if (TAILQ_EMPTY(&commitable_paths
)) {
6475 /* No-op change; commit will be elided. */
6476 err
= got_ref_delete(commit_ref
, repo
);
6479 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
6483 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
6487 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
6492 logmsg
= strdup(new_logmsg
);
6493 if (logmsg
== NULL
) {
6494 err
= got_error_from_errno("strdup");
6498 err
= got_object_commit_get_logmsg(&logmsg
, orig_commit
);
6503 /* NB: commit_worktree will call free(logmsg) */
6504 err
= commit_worktree(new_commit_id
, &commitable_paths
, head_commit_id
,
6505 NULL
, worktree
, got_object_commit_get_author(orig_commit
),
6506 got_object_commit_get_committer(orig_commit
),
6507 collect_rebase_commit_msg
, logmsg
, rebase_status
, NULL
, repo
);
6511 err
= got_ref_change_ref(tmp_branch
, *new_commit_id
);
6515 err
= got_ref_delete(commit_ref
, repo
);
6519 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
6520 *new_commit_id
, fileindex
, 0);
6521 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6522 if (sync_err
&& err
== NULL
)
6525 free(fileindex_path
);
6526 free(head_commit_id
);
6528 got_ref_close(head_ref
);
6530 free(*new_commit_id
);
6531 *new_commit_id
= NULL
;
6536 const struct got_error
*
6537 got_worktree_rebase_commit(struct got_object_id
**new_commit_id
,
6538 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6539 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6540 struct got_commit_object
*orig_commit
,
6541 struct got_object_id
*orig_commit_id
, struct got_repository
*repo
)
6543 const struct got_error
*err
;
6544 char *commit_ref_name
;
6545 struct got_reference
*commit_ref
= NULL
;
6546 struct got_object_id
*commit_id
= NULL
;
6548 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6552 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6555 err
= got_ref_resolve(&commit_id
, repo
, commit_ref
);
6558 if (got_object_id_cmp(commit_id
, orig_commit_id
) != 0) {
6559 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6563 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6564 worktree
, fileindex
, tmp_branch
, orig_commit
, NULL
, repo
);
6567 got_ref_close(commit_ref
);
6568 free(commit_ref_name
);
6573 const struct got_error
*
6574 got_worktree_histedit_commit(struct got_object_id
**new_commit_id
,
6575 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6576 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6577 struct got_commit_object
*orig_commit
,
6578 struct got_object_id
*orig_commit_id
, const char *new_logmsg
,
6579 struct got_repository
*repo
)
6581 const struct got_error
*err
;
6582 char *commit_ref_name
;
6583 struct got_reference
*commit_ref
= NULL
;
6585 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6589 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6593 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6594 worktree
, fileindex
, tmp_branch
, orig_commit
, new_logmsg
, repo
);
6597 got_ref_close(commit_ref
);
6598 free(commit_ref_name
);
6602 const struct got_error
*
6603 got_worktree_rebase_postpone(struct got_worktree
*worktree
,
6604 struct got_fileindex
*fileindex
)
6607 got_fileindex_free(fileindex
);
6608 return lock_worktree(worktree
, LOCK_SH
);
6611 static const struct got_error
*
6612 delete_ref(const char *name
, struct got_repository
*repo
)
6614 const struct got_error
*err
;
6615 struct got_reference
*ref
;
6617 err
= got_ref_open(&ref
, repo
, name
, 0);
6619 if (err
->code
== GOT_ERR_NOT_REF
)
6624 err
= got_ref_delete(ref
, repo
);
6629 static const struct got_error
*
6630 delete_rebase_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
6632 const struct got_error
*err
;
6633 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6634 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
6636 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6639 err
= delete_ref(tmp_branch_name
, repo
);
6643 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6646 err
= delete_ref(new_base_branch_ref_name
, repo
);
6650 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6653 err
= delete_ref(branch_ref_name
, repo
);
6657 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6660 err
= delete_ref(commit_ref_name
, repo
);
6665 free(tmp_branch_name
);
6666 free(new_base_branch_ref_name
);
6667 free(branch_ref_name
);
6668 free(commit_ref_name
);
6672 const struct got_error
*
6673 create_backup_ref(const char *backup_ref_prefix
, struct got_reference
*branch
,
6674 struct got_object_id
*new_commit_id
, struct got_repository
*repo
)
6676 const struct got_error
*err
;
6677 struct got_reference
*ref
= NULL
;
6678 struct got_object_id
*old_commit_id
= NULL
;
6679 const char *branch_name
= NULL
;
6680 char *new_id_str
= NULL
;
6681 char *refname
= NULL
;
6683 branch_name
= got_ref_get_name(branch
);
6684 if (strncmp(branch_name
, "refs/heads/", 11) != 0)
6685 return got_error(GOT_ERR_BAD_REF_NAME
); /* should not happen */
6688 err
= got_object_id_str(&new_id_str
, new_commit_id
);
6692 if (asprintf(&refname
, "%s/%s/%s", backup_ref_prefix
, branch_name
,
6693 new_id_str
) == -1) {
6694 err
= got_error_from_errno("asprintf");
6698 err
= got_ref_resolve(&old_commit_id
, repo
, branch
);
6702 err
= got_ref_alloc(&ref
, refname
, old_commit_id
);
6706 err
= got_ref_write(ref
, repo
);
6710 free(old_commit_id
);
6716 const struct got_error
*
6717 got_worktree_rebase_complete(struct got_worktree
*worktree
,
6718 struct got_fileindex
*fileindex
, struct got_reference
*new_base_branch
,
6719 struct got_reference
*tmp_branch
, struct got_reference
*rebased_branch
,
6720 struct got_repository
*repo
, int create_backup
)
6722 const struct got_error
*err
, *unlockerr
, *sync_err
;
6723 struct got_object_id
*new_head_commit_id
= NULL
;
6724 char *fileindex_path
= NULL
;
6726 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
6730 if (create_backup
) {
6731 err
= create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX
,
6732 rebased_branch
, new_head_commit_id
, repo
);
6737 err
= got_ref_change_ref(rebased_branch
, new_head_commit_id
);
6741 err
= got_ref_write(rebased_branch
, repo
);
6745 err
= got_worktree_set_head_ref(worktree
, rebased_branch
);
6749 err
= delete_rebase_refs(worktree
, repo
);
6753 err
= get_fileindex_path(&fileindex_path
, worktree
);
6756 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
6757 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6758 if (sync_err
&& err
== NULL
)
6761 got_fileindex_free(fileindex
);
6762 free(fileindex_path
);
6763 free(new_head_commit_id
);
6764 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6765 if (unlockerr
&& err
== NULL
)
6770 const struct got_error
*
6771 got_worktree_rebase_abort(struct got_worktree
*worktree
,
6772 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
6773 struct got_reference
*new_base_branch
,
6774 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
6776 const struct got_error
*err
, *unlockerr
, *sync_err
;
6777 struct got_reference
*resolved
= NULL
;
6778 struct got_object_id
*commit_id
= NULL
;
6779 char *fileindex_path
= NULL
;
6780 struct revert_file_args rfa
;
6781 struct got_object_id
*tree_id
= NULL
;
6783 err
= lock_worktree(worktree
, LOCK_EX
);
6787 err
= got_ref_open(&resolved
, repo
,
6788 got_ref_get_symref_target(new_base_branch
), 0);
6792 err
= got_worktree_set_head_ref(worktree
, resolved
);
6797 * XXX commits to the base branch could have happened while
6798 * we were busy rebasing; should we store the original commit ID
6799 * when rebase begins and read it back here?
6801 err
= got_ref_resolve(&commit_id
, repo
, resolved
);
6805 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
6809 err
= got_object_id_by_path(&tree_id
, repo
,
6810 worktree
->base_commit_id
, worktree
->path_prefix
);
6814 err
= delete_rebase_refs(worktree
, repo
);
6818 err
= get_fileindex_path(&fileindex_path
, worktree
);
6822 rfa
.worktree
= worktree
;
6823 rfa
.fileindex
= fileindex
;
6824 rfa
.progress_cb
= progress_cb
;
6825 rfa
.progress_arg
= progress_arg
;
6826 rfa
.patch_cb
= NULL
;
6827 rfa
.patch_arg
= NULL
;
6829 rfa
.unlink_added_files
= 0;
6830 err
= worktree_status(worktree
, "", fileindex
, repo
,
6831 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
6835 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
6836 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
6838 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6839 if (sync_err
&& err
== NULL
)
6842 got_ref_close(resolved
);
6846 got_fileindex_free(fileindex
);
6847 free(fileindex_path
);
6849 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6850 if (unlockerr
&& err
== NULL
)
6855 const struct got_error
*
6856 got_worktree_histedit_prepare(struct got_reference
**tmp_branch
,
6857 struct got_reference
**branch_ref
, struct got_object_id
**base_commit_id
,
6858 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
6859 struct got_repository
*repo
)
6861 const struct got_error
*err
= NULL
;
6862 char *tmp_branch_name
= NULL
;
6863 char *branch_ref_name
= NULL
;
6864 char *base_commit_ref_name
= NULL
;
6865 char *fileindex_path
= NULL
;
6866 struct check_rebase_ok_arg ok_arg
;
6867 struct got_reference
*wt_branch
= NULL
;
6868 struct got_reference
*base_commit_ref
= NULL
;
6872 *base_commit_id
= NULL
;
6875 err
= lock_worktree(worktree
, LOCK_EX
);
6879 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6883 ok_arg
.worktree
= worktree
;
6885 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6890 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
6894 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
6898 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
6903 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6908 err
= got_ref_alloc_symref(branch_ref
, branch_ref_name
, wt_branch
);
6912 err
= got_ref_write(*branch_ref
, repo
);
6916 err
= got_ref_alloc(&base_commit_ref
, base_commit_ref_name
,
6917 worktree
->base_commit_id
);
6920 err
= got_ref_write(base_commit_ref
, repo
);
6923 *base_commit_id
= got_object_id_dup(worktree
->base_commit_id
);
6924 if (*base_commit_id
== NULL
) {
6925 err
= got_error_from_errno("got_object_id_dup");
6929 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6930 worktree
->base_commit_id
);
6933 err
= got_ref_write(*tmp_branch
, repo
);
6937 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6941 free(fileindex_path
);
6942 free(tmp_branch_name
);
6943 free(branch_ref_name
);
6944 free(base_commit_ref_name
);
6946 got_ref_close(wt_branch
);
6949 got_ref_close(*branch_ref
);
6953 got_ref_close(*tmp_branch
);
6956 free(*base_commit_id
);
6958 got_fileindex_free(*fileindex
);
6961 lock_worktree(worktree
, LOCK_SH
);
6966 const struct got_error
*
6967 got_worktree_histedit_postpone(struct got_worktree
*worktree
,
6968 struct got_fileindex
*fileindex
)
6971 got_fileindex_free(fileindex
);
6972 return lock_worktree(worktree
, LOCK_SH
);
6975 const struct got_error
*
6976 got_worktree_histedit_in_progress(int *in_progress
,
6977 struct got_worktree
*worktree
)
6979 const struct got_error
*err
;
6980 char *tmp_branch_name
= NULL
;
6982 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
6986 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
6987 free(tmp_branch_name
);
6991 const struct got_error
*
6992 got_worktree_histedit_continue(struct got_object_id
**commit_id
,
6993 struct got_reference
**tmp_branch
, struct got_reference
**branch_ref
,
6994 struct got_object_id
**base_commit_id
, struct got_fileindex
**fileindex
,
6995 struct got_worktree
*worktree
, struct got_repository
*repo
)
6997 const struct got_error
*err
;
6998 char *commit_ref_name
= NULL
, *base_commit_ref_name
= NULL
;
6999 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
7000 struct got_reference
*commit_ref
= NULL
;
7001 struct got_reference
*base_commit_ref
= NULL
;
7002 char *fileindex_path
= NULL
;
7003 int have_staged_files
= 0;
7007 *base_commit_id
= NULL
;
7010 err
= lock_worktree(worktree
, LOCK_EX
);
7014 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7018 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
7019 &have_staged_files
);
7020 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7022 if (have_staged_files
) {
7023 err
= got_error(GOT_ERR_STAGED_PATHS
);
7027 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7031 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7035 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7039 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7044 err
= got_ref_open(branch_ref
, repo
, branch_ref_name
, 0);
7048 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7051 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
7055 err
= got_ref_open(&base_commit_ref
, repo
, base_commit_ref_name
, 0);
7058 err
= got_ref_resolve(base_commit_id
, repo
, base_commit_ref
);
7062 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
7066 free(commit_ref_name
);
7067 free(branch_ref_name
);
7068 free(fileindex_path
);
7070 got_ref_close(commit_ref
);
7071 if (base_commit_ref
)
7072 got_ref_close(base_commit_ref
);
7076 free(*base_commit_id
);
7077 *base_commit_id
= NULL
;
7079 got_ref_close(*tmp_branch
);
7083 got_fileindex_free(*fileindex
);
7086 lock_worktree(worktree
, LOCK_EX
);
7091 static const struct got_error
*
7092 delete_histedit_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7094 const struct got_error
*err
;
7095 char *tmp_branch_name
= NULL
, *base_commit_ref_name
= NULL
;
7096 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
7098 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7101 err
= delete_ref(tmp_branch_name
, repo
);
7105 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7109 err
= delete_ref(base_commit_ref_name
, repo
);
7113 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7116 err
= delete_ref(branch_ref_name
, repo
);
7120 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7123 err
= delete_ref(commit_ref_name
, repo
);
7127 free(tmp_branch_name
);
7128 free(base_commit_ref_name
);
7129 free(branch_ref_name
);
7130 free(commit_ref_name
);
7134 const struct got_error
*
7135 got_worktree_histedit_abort(struct got_worktree
*worktree
,
7136 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7137 struct got_reference
*branch
, struct got_object_id
*base_commit_id
,
7138 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7140 const struct got_error
*err
, *unlockerr
, *sync_err
;
7141 struct got_reference
*resolved
= NULL
;
7142 char *fileindex_path
= NULL
;
7143 struct got_object_id
*tree_id
= NULL
;
7144 struct revert_file_args rfa
;
7146 err
= lock_worktree(worktree
, LOCK_EX
);
7150 err
= got_ref_open(&resolved
, repo
,
7151 got_ref_get_symref_target(branch
), 0);
7155 err
= got_worktree_set_head_ref(worktree
, resolved
);
7159 err
= got_worktree_set_base_commit_id(worktree
, repo
, base_commit_id
);
7163 err
= got_object_id_by_path(&tree_id
, repo
, base_commit_id
,
7164 worktree
->path_prefix
);
7168 err
= delete_histedit_refs(worktree
, repo
);
7172 err
= get_fileindex_path(&fileindex_path
, worktree
);
7176 rfa
.worktree
= worktree
;
7177 rfa
.fileindex
= fileindex
;
7178 rfa
.progress_cb
= progress_cb
;
7179 rfa
.progress_arg
= progress_arg
;
7180 rfa
.patch_cb
= NULL
;
7181 rfa
.patch_arg
= NULL
;
7183 rfa
.unlink_added_files
= 0;
7184 err
= worktree_status(worktree
, "", fileindex
, repo
,
7185 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
7189 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7190 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7192 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7193 if (sync_err
&& err
== NULL
)
7196 got_ref_close(resolved
);
7198 free(fileindex_path
);
7200 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7201 if (unlockerr
&& err
== NULL
)
7206 const struct got_error
*
7207 got_worktree_histedit_complete(struct got_worktree
*worktree
,
7208 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7209 struct got_reference
*edited_branch
, struct got_repository
*repo
)
7211 const struct got_error
*err
, *unlockerr
, *sync_err
;
7212 struct got_object_id
*new_head_commit_id
= NULL
;
7213 struct got_reference
*resolved
= NULL
;
7214 char *fileindex_path
= NULL
;
7216 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
7220 err
= got_ref_open(&resolved
, repo
,
7221 got_ref_get_symref_target(edited_branch
), 0);
7225 err
= create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX
,
7226 resolved
, new_head_commit_id
, repo
);
7230 err
= got_ref_change_ref(resolved
, new_head_commit_id
);
7234 err
= got_ref_write(resolved
, repo
);
7238 err
= got_worktree_set_head_ref(worktree
, resolved
);
7242 err
= delete_histedit_refs(worktree
, repo
);
7246 err
= get_fileindex_path(&fileindex_path
, worktree
);
7249 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7250 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7251 if (sync_err
&& err
== NULL
)
7254 got_fileindex_free(fileindex
);
7255 free(fileindex_path
);
7256 free(new_head_commit_id
);
7257 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7258 if (unlockerr
&& err
== NULL
)
7263 const struct got_error
*
7264 got_worktree_histedit_skip_commit(struct got_worktree
*worktree
,
7265 struct got_object_id
*commit_id
, struct got_repository
*repo
)
7267 const struct got_error
*err
;
7268 char *commit_ref_name
;
7270 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7274 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
7278 err
= delete_ref(commit_ref_name
, repo
);
7280 free(commit_ref_name
);
7284 const struct got_error
*
7285 got_worktree_integrate_prepare(struct got_fileindex
**fileindex
,
7286 struct got_reference
**branch_ref
, struct got_reference
**base_branch_ref
,
7287 struct got_worktree
*worktree
, const char *refname
,
7288 struct got_repository
*repo
)
7290 const struct got_error
*err
= NULL
;
7291 char *fileindex_path
= NULL
;
7292 struct check_rebase_ok_arg ok_arg
;
7296 *base_branch_ref
= NULL
;
7298 err
= lock_worktree(worktree
, LOCK_EX
);
7302 if (strcmp(refname
, got_worktree_get_head_ref_name(worktree
)) == 0) {
7303 err
= got_error_msg(GOT_ERR_SAME_BRANCH
,
7304 "cannot integrate a branch into itself; "
7305 "update -b or different branch name required");
7309 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7313 /* Preconditions are the same as for rebase. */
7314 ok_arg
.worktree
= worktree
;
7316 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7321 err
= got_ref_open(branch_ref
, repo
, refname
, 1);
7325 err
= got_ref_open(base_branch_ref
, repo
,
7326 got_worktree_get_head_ref_name(worktree
), 1);
7330 got_ref_close(*branch_ref
);
7333 if (*base_branch_ref
) {
7334 got_ref_close(*base_branch_ref
);
7335 *base_branch_ref
= NULL
;
7338 got_fileindex_free(*fileindex
);
7341 lock_worktree(worktree
, LOCK_SH
);
7346 const struct got_error
*
7347 got_worktree_integrate_continue(struct got_worktree
*worktree
,
7348 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7349 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
,
7350 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7351 got_cancel_cb cancel_cb
, void *cancel_arg
)
7353 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
7354 char *fileindex_path
= NULL
;
7355 struct got_object_id
*tree_id
= NULL
, *commit_id
= NULL
;
7357 err
= get_fileindex_path(&fileindex_path
, worktree
);
7361 err
= got_ref_resolve(&commit_id
, repo
, branch_ref
);
7365 err
= got_object_id_by_path(&tree_id
, repo
, commit_id
,
7366 worktree
->path_prefix
);
7370 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
7374 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
, repo
,
7375 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
7379 err
= got_ref_change_ref(base_branch_ref
, commit_id
);
7383 err
= got_ref_write(base_branch_ref
, repo
);
7387 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7389 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7390 if (sync_err
&& err
== NULL
)
7394 unlockerr
= got_ref_unlock(branch_ref
);
7395 if (unlockerr
&& err
== NULL
)
7397 got_ref_close(branch_ref
);
7399 unlockerr
= got_ref_unlock(base_branch_ref
);
7400 if (unlockerr
&& err
== NULL
)
7402 got_ref_close(base_branch_ref
);
7404 got_fileindex_free(fileindex
);
7405 free(fileindex_path
);
7408 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7409 if (unlockerr
&& err
== NULL
)
7414 const struct got_error
*
7415 got_worktree_integrate_abort(struct got_worktree
*worktree
,
7416 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7417 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
)
7419 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
7421 got_fileindex_free(fileindex
);
7423 err
= lock_worktree(worktree
, LOCK_SH
);
7425 unlockerr
= got_ref_unlock(branch_ref
);
7426 if (unlockerr
&& err
== NULL
)
7428 got_ref_close(branch_ref
);
7430 unlockerr
= got_ref_unlock(base_branch_ref
);
7431 if (unlockerr
&& err
== NULL
)
7433 got_ref_close(base_branch_ref
);
7438 const struct got_error
*
7439 got_worktree_merge_postpone(struct got_worktree
*worktree
,
7440 struct got_fileindex
*fileindex
)
7442 const struct got_error
*err
, *sync_err
;
7443 char *fileindex_path
= NULL
;
7445 err
= get_fileindex_path(&fileindex_path
, worktree
);
7449 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7451 err
= lock_worktree(worktree
, LOCK_SH
);
7452 if (sync_err
&& err
== NULL
)
7455 got_fileindex_free(fileindex
);
7456 free(fileindex_path
);
7460 static const struct got_error
*
7461 delete_merge_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7463 const struct got_error
*err
;
7464 char *branch_refname
= NULL
, *commit_refname
= NULL
;
7466 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7469 err
= delete_ref(branch_refname
, repo
);
7473 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7476 err
= delete_ref(commit_refname
, repo
);
7481 free(branch_refname
);
7482 free(commit_refname
);
7486 struct merge_commit_msg_arg
{
7487 struct got_worktree
*worktree
;
7488 const char *branch_name
;
7491 static const struct got_error
*
7492 merge_commit_msg_cb(struct got_pathlist_head
*commitable_paths
, char **logmsg
,
7495 struct merge_commit_msg_arg
*a
= arg
;
7497 if (asprintf(logmsg
, "merge %s into %s\n", a
->branch_name
,
7498 got_worktree_get_head_ref_name(a
->worktree
)) == -1)
7499 return got_error_from_errno("asprintf");
7505 const struct got_error
*
7506 got_worktree_merge_branch(struct got_worktree
*worktree
,
7507 struct got_fileindex
*fileindex
,
7508 struct got_object_id
*yca_commit_id
,
7509 struct got_object_id
*branch_tip
,
7510 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
7511 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
7513 const struct got_error
*err
;
7514 char *fileindex_path
= NULL
;
7516 err
= get_fileindex_path(&fileindex_path
, worktree
);
7520 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
7525 err
= merge_files(worktree
, fileindex
, fileindex_path
, yca_commit_id
,
7526 branch_tip
, repo
, progress_cb
, progress_arg
,
7527 cancel_cb
, cancel_arg
);
7529 free(fileindex_path
);
7533 const struct got_error
*
7534 got_worktree_merge_commit(struct got_object_id
**new_commit_id
,
7535 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
7536 const char *author
, const char *committer
, int allow_bad_symlinks
,
7537 struct got_object_id
*branch_tip
, const char *branch_name
,
7538 struct got_repository
*repo
,
7539 got_worktree_status_cb status_cb
, void *status_arg
)
7542 const struct got_error
*err
= NULL
, *sync_err
;
7543 struct got_pathlist_head commitable_paths
;
7544 struct collect_commitables_arg cc_arg
;
7545 struct got_pathlist_entry
*pe
;
7546 struct got_reference
*head_ref
= NULL
;
7547 struct got_object_id
*head_commit_id
= NULL
;
7548 int have_staged_files
= 0;
7549 struct merge_commit_msg_arg mcm_arg
;
7550 char *fileindex_path
= NULL
;
7552 *new_commit_id
= NULL
;
7554 TAILQ_INIT(&commitable_paths
);
7556 err
= get_fileindex_path(&fileindex_path
, worktree
);
7560 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
7564 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
7568 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
7569 &have_staged_files
);
7570 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7572 if (have_staged_files
) {
7573 err
= got_error(GOT_ERR_MERGE_STAGED_PATHS
);
7577 cc_arg
.commitable_paths
= &commitable_paths
;
7578 cc_arg
.worktree
= worktree
;
7579 cc_arg
.fileindex
= fileindex
;
7581 cc_arg
.have_staged_files
= have_staged_files
;
7582 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
7583 err
= worktree_status(worktree
, "", fileindex
, repo
,
7584 collect_commitables
, &cc_arg
, NULL
, NULL
, 0, 0);
7588 if (TAILQ_EMPTY(&commitable_paths
)) {
7589 err
= got_error_fmt(GOT_ERR_COMMIT_NO_CHANGES
,
7590 "merge of %s cannot proceed", branch_name
);
7594 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
7595 struct got_commitable
*ct
= pe
->data
;
7596 const char *ct_path
= ct
->in_repo_path
;
7598 while (ct_path
[0] == '/')
7600 err
= check_out_of_date(ct_path
, ct
->status
,
7601 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
7602 head_commit_id
, repo
, GOT_ERR_MERGE_COMMIT_OUT_OF_DATE
);
7608 mcm_arg
.worktree
= worktree
;
7609 mcm_arg
.branch_name
= branch_name
;
7610 err
= commit_worktree(new_commit_id
, &commitable_paths
,
7611 head_commit_id
, branch_tip
, worktree
, author
, committer
,
7612 merge_commit_msg_cb
, &mcm_arg
, status_cb
, status_arg
, repo
);
7616 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
7617 *new_commit_id
, fileindex
, have_staged_files
);
7618 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7619 if (sync_err
&& err
== NULL
)
7622 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
7623 struct got_commitable
*ct
= pe
->data
;
7624 free_commitable(ct
);
7626 got_pathlist_free(&commitable_paths
);
7627 free(fileindex_path
);
7631 const struct got_error
*
7632 got_worktree_merge_complete(struct got_worktree
*worktree
,
7633 struct got_fileindex
*fileindex
, struct got_repository
*repo
)
7635 const struct got_error
*err
, *unlockerr
, *sync_err
;
7636 char *fileindex_path
= NULL
;
7638 err
= delete_merge_refs(worktree
, repo
);
7642 err
= get_fileindex_path(&fileindex_path
, worktree
);
7645 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7646 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7647 if (sync_err
&& err
== NULL
)
7650 got_fileindex_free(fileindex
);
7651 free(fileindex_path
);
7652 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7653 if (unlockerr
&& err
== NULL
)
7658 const struct got_error
*
7659 got_worktree_merge_in_progress(int *in_progress
, struct got_worktree
*worktree
,
7660 struct got_repository
*repo
)
7662 const struct got_error
*err
;
7663 char *branch_refname
= NULL
;
7664 struct got_reference
*branch_ref
= NULL
;
7668 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7671 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
7672 free(branch_refname
);
7674 if (err
->code
!= GOT_ERR_NOT_REF
)
7682 const struct got_error
*got_worktree_merge_prepare(
7683 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
7684 struct got_reference
*branch
, struct got_repository
*repo
)
7686 const struct got_error
*err
= NULL
;
7687 char *fileindex_path
= NULL
;
7688 char *branch_refname
= NULL
, *commit_refname
= NULL
;
7689 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
7690 struct got_reference
*commit_ref
= NULL
;
7691 struct got_object_id
*branch_tip
= NULL
, *wt_branch_tip
= NULL
;
7692 struct check_rebase_ok_arg ok_arg
;
7696 err
= lock_worktree(worktree
, LOCK_EX
);
7700 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7704 /* Preconditions are the same as for rebase. */
7705 ok_arg
.worktree
= worktree
;
7707 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7712 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7716 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7720 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
7725 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
7729 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
7730 err
= got_error(GOT_ERR_MERGE_OUT_OF_DATE
);
7734 err
= got_ref_resolve(&branch_tip
, repo
, branch
);
7738 err
= got_ref_alloc_symref(&branch_ref
, branch_refname
, branch
);
7741 err
= got_ref_write(branch_ref
, repo
);
7745 err
= got_ref_alloc(&commit_ref
, commit_refname
, branch_tip
);
7748 err
= got_ref_write(commit_ref
, repo
);
7753 free(branch_refname
);
7754 free(commit_refname
);
7755 free(fileindex_path
);
7757 got_ref_close(branch_ref
);
7759 got_ref_close(commit_ref
);
7761 got_ref_close(wt_branch
);
7762 free(wt_branch_tip
);
7765 got_fileindex_free(*fileindex
);
7768 lock_worktree(worktree
, LOCK_SH
);
7773 const struct got_error
*
7774 got_worktree_merge_continue(char **branch_name
,
7775 struct got_object_id
**branch_tip
, struct got_fileindex
**fileindex
,
7776 struct got_worktree
*worktree
, struct got_repository
*repo
)
7778 const struct got_error
*err
;
7779 char *commit_refname
= NULL
, *branch_refname
= NULL
;
7780 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
7781 char *fileindex_path
= NULL
;
7782 int have_staged_files
= 0;
7784 *branch_name
= NULL
;
7788 err
= lock_worktree(worktree
, LOCK_EX
);
7792 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7796 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
7797 &have_staged_files
);
7798 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7800 if (have_staged_files
) {
7801 err
= got_error(GOT_ERR_STAGED_PATHS
);
7805 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7809 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7813 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
7817 if (!got_ref_is_symbolic(branch_ref
)) {
7818 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
7819 "%s is not a symbolic reference",
7820 got_ref_get_name(branch_ref
));
7823 *branch_name
= strdup(got_ref_get_symref_target(branch_ref
));
7824 if (*branch_name
== NULL
) {
7825 err
= got_error_from_errno("strdup");
7829 err
= got_ref_open(&commit_ref
, repo
, commit_refname
, 0);
7833 err
= got_ref_resolve(branch_tip
, repo
, commit_ref
);
7837 free(commit_refname
);
7838 free(branch_refname
);
7839 free(fileindex_path
);
7841 got_ref_close(commit_ref
);
7843 got_ref_close(branch_ref
);
7847 *branch_name
= NULL
;
7852 got_fileindex_free(*fileindex
);
7855 lock_worktree(worktree
, LOCK_SH
);
7860 const struct got_error
*
7861 got_worktree_merge_abort(struct got_worktree
*worktree
,
7862 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7863 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7865 const struct got_error
*err
, *unlockerr
, *sync_err
;
7866 struct got_object_id
*commit_id
= NULL
;
7867 char *fileindex_path
= NULL
;
7868 struct revert_file_args rfa
;
7869 struct got_object_id
*tree_id
= NULL
;
7871 err
= got_object_id_by_path(&tree_id
, repo
,
7872 worktree
->base_commit_id
, worktree
->path_prefix
);
7876 err
= delete_merge_refs(worktree
, repo
);
7880 err
= get_fileindex_path(&fileindex_path
, worktree
);
7884 rfa
.worktree
= worktree
;
7885 rfa
.fileindex
= fileindex
;
7886 rfa
.progress_cb
= progress_cb
;
7887 rfa
.progress_arg
= progress_arg
;
7888 rfa
.patch_cb
= NULL
;
7889 rfa
.patch_arg
= NULL
;
7891 rfa
.unlink_added_files
= 1;
7892 err
= worktree_status(worktree
, "", fileindex
, repo
,
7893 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
7897 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7898 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7900 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7901 if (sync_err
&& err
== NULL
)
7907 got_fileindex_free(fileindex
);
7908 free(fileindex_path
);
7910 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7911 if (unlockerr
&& err
== NULL
)
7916 struct check_stage_ok_arg
{
7917 struct got_object_id
*head_commit_id
;
7918 struct got_worktree
*worktree
;
7919 struct got_fileindex
*fileindex
;
7920 struct got_repository
*repo
;
7924 const struct got_error
*
7925 check_stage_ok(void *arg
, unsigned char status
,
7926 unsigned char staged_status
, const char *relpath
,
7927 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
7928 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
7930 struct check_stage_ok_arg
*a
= arg
;
7931 const struct got_error
*err
= NULL
;
7932 struct got_fileindex_entry
*ie
;
7933 struct got_object_id base_commit_id
;
7934 struct got_object_id
*base_commit_idp
= NULL
;
7935 char *in_repo_path
= NULL
, *p
;
7937 if (status
== GOT_STATUS_UNVERSIONED
||
7938 status
== GOT_STATUS_NO_CHANGE
)
7940 if (status
== GOT_STATUS_NONEXISTENT
)
7941 return got_error_set_errno(ENOENT
, relpath
);
7943 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
7945 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
7947 if (asprintf(&in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
7948 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
7950 return got_error_from_errno("asprintf");
7952 if (got_fileindex_entry_has_commit(ie
)) {
7953 memcpy(base_commit_id
.sha1
, ie
->commit_sha1
,
7954 SHA1_DIGEST_LENGTH
);
7955 base_commit_idp
= &base_commit_id
;
7958 if (status
== GOT_STATUS_CONFLICT
) {
7959 err
= got_error_path(ie
->path
, GOT_ERR_STAGE_CONFLICT
);
7961 } else if (status
!= GOT_STATUS_ADD
&&
7962 status
!= GOT_STATUS_MODIFY
&&
7963 status
!= GOT_STATUS_DELETE
) {
7964 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STATUS
);
7968 a
->have_changes
= 1;
7973 err
= check_out_of_date(p
, status
, staged_status
,
7974 blob_id
, base_commit_idp
, a
->head_commit_id
, a
->repo
,
7975 GOT_ERR_STAGE_OUT_OF_DATE
);
7981 struct stage_path_arg
{
7982 struct got_worktree
*worktree
;
7983 struct got_fileindex
*fileindex
;
7984 struct got_repository
*repo
;
7985 got_worktree_status_cb status_cb
;
7987 got_worktree_patch_cb patch_cb
;
7989 int staged_something
;
7990 int allow_bad_symlinks
;
7993 static const struct got_error
*
7994 stage_path(void *arg
, unsigned char status
,
7995 unsigned char staged_status
, const char *relpath
,
7996 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
7997 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
7999 struct stage_path_arg
*a
= arg
;
8000 const struct got_error
*err
= NULL
;
8001 struct got_fileindex_entry
*ie
;
8002 char *ondisk_path
= NULL
, *path_content
= NULL
;
8004 struct got_object_id
*new_staged_blob_id
= NULL
;
8007 if (status
== GOT_STATUS_UNVERSIONED
)
8010 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8012 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8014 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
8016 return got_error_from_errno("asprintf");
8019 case GOT_STATUS_ADD
:
8020 case GOT_STATUS_MODIFY
:
8021 /* XXX could sb.st_mode be passed in by our caller? */
8022 if (lstat(ondisk_path
, &sb
) == -1) {
8023 err
= got_error_from_errno2("lstat", ondisk_path
);
8027 if (status
== GOT_STATUS_ADD
) {
8028 int choice
= GOT_PATCH_CHOICE_NONE
;
8029 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8030 status
, ie
->path
, NULL
, 1, 1);
8033 if (choice
!= GOT_PATCH_CHOICE_YES
)
8036 err
= create_patched_content(&path_content
, 0,
8037 staged_blob_id
? staged_blob_id
: blob_id
,
8038 ondisk_path
, dirfd
, de_name
, ie
->path
,
8039 a
->repo
, a
->patch_cb
, a
->patch_arg
);
8040 if (err
|| path_content
== NULL
)
8044 err
= got_object_blob_create(&new_staged_blob_id
,
8045 path_content
? path_content
: ondisk_path
, a
->repo
);
8048 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
8049 SHA1_DIGEST_LENGTH
);
8050 if (status
== GOT_STATUS_ADD
|| staged_status
== GOT_STATUS_ADD
)
8051 stage
= GOT_FILEIDX_STAGE_ADD
;
8053 stage
= GOT_FILEIDX_STAGE_MODIFY
;
8054 got_fileindex_entry_stage_set(ie
, stage
);
8055 if (S_ISLNK(sb
.st_mode
)) {
8056 int is_bad_symlink
= 0;
8057 if (!a
->allow_bad_symlinks
) {
8058 char target_path
[PATH_MAX
];
8060 target_len
= readlink(ondisk_path
, target_path
,
8061 sizeof(target_path
));
8062 if (target_len
== -1) {
8063 err
= got_error_from_errno2("readlink",
8067 err
= is_bad_symlink_target(&is_bad_symlink
,
8068 target_path
, target_len
, ondisk_path
,
8069 a
->worktree
->root_path
);
8072 if (is_bad_symlink
) {
8073 err
= got_error_path(ondisk_path
,
8074 GOT_ERR_BAD_SYMLINK
);
8079 got_fileindex_entry_staged_filetype_set(ie
,
8080 GOT_FILEIDX_MODE_BAD_SYMLINK
);
8082 got_fileindex_entry_staged_filetype_set(ie
,
8083 GOT_FILEIDX_MODE_SYMLINK
);
8085 got_fileindex_entry_staged_filetype_set(ie
,
8086 GOT_FILEIDX_MODE_REGULAR_FILE
);
8088 a
->staged_something
= 1;
8089 if (a
->status_cb
== NULL
)
8091 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
8092 get_staged_status(ie
), relpath
, blob_id
,
8093 new_staged_blob_id
, NULL
, dirfd
, de_name
);
8095 case GOT_STATUS_DELETE
:
8096 if (staged_status
== GOT_STATUS_DELETE
)
8099 int choice
= GOT_PATCH_CHOICE_NONE
;
8100 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
, status
,
8101 ie
->path
, NULL
, 1, 1);
8104 if (choice
== GOT_PATCH_CHOICE_NO
)
8106 if (choice
!= GOT_PATCH_CHOICE_YES
) {
8107 err
= got_error(GOT_ERR_PATCH_CHOICE
);
8111 stage
= GOT_FILEIDX_STAGE_DELETE
;
8112 got_fileindex_entry_stage_set(ie
, stage
);
8113 a
->staged_something
= 1;
8114 if (a
->status_cb
== NULL
)
8116 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
8117 get_staged_status(ie
), relpath
, NULL
, NULL
, NULL
, dirfd
,
8120 case GOT_STATUS_NO_CHANGE
:
8122 case GOT_STATUS_CONFLICT
:
8123 err
= got_error_path(relpath
, GOT_ERR_STAGE_CONFLICT
);
8125 case GOT_STATUS_NONEXISTENT
:
8126 err
= got_error_set_errno(ENOENT
, relpath
);
8129 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8133 if (path_content
&& unlink(path_content
) == -1 && err
== NULL
)
8134 err
= got_error_from_errno2("unlink", path_content
);
8137 free(new_staged_blob_id
);
8141 const struct got_error
*
8142 got_worktree_stage(struct got_worktree
*worktree
,
8143 struct got_pathlist_head
*paths
,
8144 got_worktree_status_cb status_cb
, void *status_arg
,
8145 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8146 int allow_bad_symlinks
, struct got_repository
*repo
)
8148 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8149 struct got_pathlist_entry
*pe
;
8150 struct got_fileindex
*fileindex
= NULL
;
8151 char *fileindex_path
= NULL
;
8152 struct got_reference
*head_ref
= NULL
;
8153 struct got_object_id
*head_commit_id
= NULL
;
8154 struct check_stage_ok_arg oka
;
8155 struct stage_path_arg spa
;
8157 err
= lock_worktree(worktree
, LOCK_EX
);
8161 err
= got_ref_open(&head_ref
, repo
,
8162 got_worktree_get_head_ref_name(worktree
), 0);
8165 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
8168 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8172 /* Check pre-conditions before staging anything. */
8173 oka
.head_commit_id
= head_commit_id
;
8174 oka
.worktree
= worktree
;
8175 oka
.fileindex
= fileindex
;
8177 oka
.have_changes
= 0;
8178 TAILQ_FOREACH(pe
, paths
, entry
) {
8179 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8180 check_stage_ok
, &oka
, NULL
, NULL
, 0, 0);
8184 if (!oka
.have_changes
) {
8185 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
8189 spa
.worktree
= worktree
;
8190 spa
.fileindex
= fileindex
;
8192 spa
.patch_cb
= patch_cb
;
8193 spa
.patch_arg
= patch_arg
;
8194 spa
.status_cb
= status_cb
;
8195 spa
.status_arg
= status_arg
;
8196 spa
.staged_something
= 0;
8197 spa
.allow_bad_symlinks
= allow_bad_symlinks
;
8198 TAILQ_FOREACH(pe
, paths
, entry
) {
8199 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8200 stage_path
, &spa
, NULL
, NULL
, 0, 0);
8204 if (!spa
.staged_something
) {
8205 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
8209 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8210 if (sync_err
&& err
== NULL
)
8214 got_ref_close(head_ref
);
8215 free(head_commit_id
);
8216 free(fileindex_path
);
8218 got_fileindex_free(fileindex
);
8219 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8220 if (unlockerr
&& err
== NULL
)
8225 struct unstage_path_arg
{
8226 struct got_worktree
*worktree
;
8227 struct got_fileindex
*fileindex
;
8228 struct got_repository
*repo
;
8229 got_worktree_checkout_cb progress_cb
;
8231 got_worktree_patch_cb patch_cb
;
8235 static const struct got_error
*
8236 create_unstaged_content(char **path_unstaged_content
,
8237 char **path_new_staged_content
, struct got_object_id
*blob_id
,
8238 struct got_object_id
*staged_blob_id
, const char *relpath
,
8239 struct got_repository
*repo
,
8240 got_worktree_patch_cb patch_cb
, void *patch_arg
)
8242 const struct got_error
*err
, *free_err
;
8243 struct got_blob_object
*blob
= NULL
, *staged_blob
= NULL
;
8244 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
, *rejectfile
= NULL
;
8245 char *path1
= NULL
, *path2
= NULL
, *label1
= NULL
;
8246 struct got_diffreg_result
*diffreg_result
= NULL
;
8247 int line_cur1
= 1, line_cur2
= 1, n
= 0, nchunks_used
= 0;
8248 int have_content
= 0, have_rejected_content
= 0, i
= 0, nchanges
= 0;
8250 *path_unstaged_content
= NULL
;
8251 *path_new_staged_content
= NULL
;
8253 err
= got_object_id_str(&label1
, blob_id
);
8256 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192);
8260 err
= got_opentemp_named(&path1
, &f1
, "got-unstage-blob-base");
8264 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
8268 err
= got_object_open_as_blob(&staged_blob
, repo
, staged_blob_id
, 8192);
8272 err
= got_opentemp_named(&path2
, &f2
, "got-unstage-blob-staged");
8276 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f2
, staged_blob
);
8280 err
= got_diff_files(&diffreg_result
, f1
, label1
, f2
,
8281 path2
, 3, 0, 1, NULL
);
8285 err
= got_opentemp_named(path_unstaged_content
, &outfile
,
8286 "got-unstaged-content");
8289 err
= got_opentemp_named(path_new_staged_content
, &rejectfile
,
8290 "got-new-staged-content");
8294 if (fseek(f1
, 0L, SEEK_SET
) == -1) {
8295 err
= got_ferror(f1
, GOT_ERR_IO
);
8298 if (fseek(f2
, 0L, SEEK_SET
) == -1) {
8299 err
= got_ferror(f2
, GOT_ERR_IO
);
8302 /* Count the number of actual changes in the diff result. */
8303 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
8304 struct diff_chunk_context cc
= {};
8305 diff_chunk_context_load_change(&cc
, &nchunks_used
,
8306 diffreg_result
->result
, n
, 0);
8309 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
8311 err
= apply_or_reject_change(&choice
, &nchunks_used
,
8312 diffreg_result
->result
, n
, relpath
, f1
, f2
,
8313 &line_cur1
, &line_cur2
,
8314 outfile
, rejectfile
, ++i
, nchanges
, patch_cb
, patch_arg
);
8317 if (choice
== GOT_PATCH_CHOICE_YES
)
8320 have_rejected_content
= 1;
8321 if (choice
== GOT_PATCH_CHOICE_QUIT
)
8324 if (have_content
|| have_rejected_content
)
8325 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
8326 outfile
, rejectfile
);
8330 got_object_blob_close(blob
);
8332 got_object_blob_close(staged_blob
);
8333 free_err
= got_diffreg_result_free(diffreg_result
);
8334 if (free_err
&& err
== NULL
)
8336 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
8337 err
= got_error_from_errno2("fclose", path1
);
8338 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
8339 err
= got_error_from_errno2("fclose", path2
);
8340 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
8341 err
= got_error_from_errno2("fclose", *path_unstaged_content
);
8342 if (rejectfile
&& fclose(rejectfile
) == EOF
&& err
== NULL
)
8343 err
= got_error_from_errno2("fclose", *path_new_staged_content
);
8344 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
8345 err
= got_error_from_errno2("unlink", path1
);
8346 if (path2
&& unlink(path2
) == -1 && err
== NULL
)
8347 err
= got_error_from_errno2("unlink", path2
);
8348 if (err
|| !have_content
) {
8349 if (*path_unstaged_content
&&
8350 unlink(*path_unstaged_content
) == -1 && err
== NULL
)
8351 err
= got_error_from_errno2("unlink",
8352 *path_unstaged_content
);
8353 free(*path_unstaged_content
);
8354 *path_unstaged_content
= NULL
;
8356 if (err
|| !have_content
|| !have_rejected_content
) {
8357 if (*path_new_staged_content
&&
8358 unlink(*path_new_staged_content
) == -1 && err
== NULL
)
8359 err
= got_error_from_errno2("unlink",
8360 *path_new_staged_content
);
8361 free(*path_new_staged_content
);
8362 *path_new_staged_content
= NULL
;
8369 static const struct got_error
*
8370 unstage_hunks(struct got_object_id
*staged_blob_id
,
8371 struct got_blob_object
*blob_base
,
8372 struct got_object_id
*blob_id
, struct got_fileindex_entry
*ie
,
8373 const char *ondisk_path
, const char *label_orig
,
8374 struct got_worktree
*worktree
, struct got_repository
*repo
,
8375 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8376 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
8378 const struct got_error
*err
= NULL
;
8379 char *path_unstaged_content
= NULL
;
8380 char *path_new_staged_content
= NULL
;
8381 char *parent
= NULL
, *base_path
= NULL
;
8382 char *blob_base_path
= NULL
;
8383 struct got_object_id
*new_staged_blob_id
= NULL
;
8384 FILE *f
= NULL
, *f_base
= NULL
, *f_deriv2
= NULL
;
8387 err
= create_unstaged_content(&path_unstaged_content
,
8388 &path_new_staged_content
, blob_id
, staged_blob_id
,
8389 ie
->path
, repo
, patch_cb
, patch_arg
);
8393 if (path_unstaged_content
== NULL
)
8396 if (path_new_staged_content
) {
8397 err
= got_object_blob_create(&new_staged_blob_id
,
8398 path_new_staged_content
, repo
);
8403 f
= fopen(path_unstaged_content
, "r");
8405 err
= got_error_from_errno2("fopen",
8406 path_unstaged_content
);
8409 if (fstat(fileno(f
), &sb
) == -1) {
8410 err
= got_error_from_errno2("fstat", path_unstaged_content
);
8413 if (got_fileindex_entry_staged_filetype_get(ie
) ==
8414 GOT_FILEIDX_MODE_SYMLINK
&& sb
.st_size
< PATH_MAX
) {
8415 char link_target
[PATH_MAX
];
8417 r
= fread(link_target
, 1, sizeof(link_target
), f
);
8418 if (r
== 0 && ferror(f
)) {
8419 err
= got_error_from_errno("fread");
8422 if (r
>= sizeof(link_target
)) { /* should not happen */
8423 err
= got_error(GOT_ERR_NO_SPACE
);
8426 link_target
[r
] = '\0';
8427 err
= merge_symlink(worktree
, blob_base
,
8428 ondisk_path
, ie
->path
, label_orig
, link_target
,
8429 worktree
->base_commit_id
, repo
, progress_cb
,
8432 int local_changes_subsumed
;
8434 err
= got_path_dirname(&parent
, ondisk_path
);
8438 if (asprintf(&base_path
, "%s/got-unstage-blob-orig",
8440 err
= got_error_from_errno("asprintf");
8445 err
= got_opentemp_named(&blob_base_path
, &f_base
, base_path
);
8448 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_base
,
8454 * In order the run a 3-way merge with a symlink we copy the symlink's
8455 * target path into a temporary file and use that file with diff3.
8457 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
8458 err
= dump_symlink_target_path_to_file(&f_deriv2
,
8464 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
);
8466 err
= got_error_from_errno2("open", ondisk_path
);
8469 f_deriv2
= fdopen(fd
, "r");
8470 if (f_deriv2
== NULL
) {
8471 err
= got_error_from_errno2("fdopen", ondisk_path
);
8477 err
= merge_file(&local_changes_subsumed
, worktree
,
8478 f_base
, f
, f_deriv2
, ondisk_path
, ie
->path
,
8479 got_fileindex_perms_to_st(ie
),
8480 label_orig
, "unstaged", NULL
, GOT_DIFF_ALGORITHM_MYERS
,
8481 repo
, progress_cb
, progress_arg
);
8486 if (new_staged_blob_id
) {
8487 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
8488 SHA1_DIGEST_LENGTH
);
8490 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
8491 got_fileindex_entry_staged_filetype_set(ie
, 0);
8494 free(new_staged_blob_id
);
8495 if (path_unstaged_content
&&
8496 unlink(path_unstaged_content
) == -1 && err
== NULL
)
8497 err
= got_error_from_errno2("unlink", path_unstaged_content
);
8498 if (path_new_staged_content
&&
8499 unlink(path_new_staged_content
) == -1 && err
== NULL
)
8500 err
= got_error_from_errno2("unlink", path_new_staged_content
);
8501 if (blob_base_path
&& unlink(blob_base_path
) == -1 && err
== NULL
)
8502 err
= got_error_from_errno2("unlink", blob_base_path
);
8503 if (f_base
&& fclose(f_base
) == EOF
&& err
== NULL
)
8504 err
= got_error_from_errno2("fclose", path_unstaged_content
);
8505 if (f
&& fclose(f
) == EOF
&& err
== NULL
)
8506 err
= got_error_from_errno2("fclose", path_unstaged_content
);
8507 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
8508 err
= got_error_from_errno2("fclose", ondisk_path
);
8509 free(path_unstaged_content
);
8510 free(path_new_staged_content
);
8511 free(blob_base_path
);
8517 static const struct got_error
*
8518 unstage_path(void *arg
, unsigned char status
,
8519 unsigned char staged_status
, const char *relpath
,
8520 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
8521 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
8523 const struct got_error
*err
= NULL
;
8524 struct unstage_path_arg
*a
= arg
;
8525 struct got_fileindex_entry
*ie
;
8526 struct got_blob_object
*blob_base
= NULL
, *blob_staged
= NULL
;
8527 char *ondisk_path
= NULL
;
8528 char *id_str
= NULL
, *label_orig
= NULL
;
8529 int local_changes_subsumed
;
8532 if (staged_status
!= GOT_STATUS_ADD
&&
8533 staged_status
!= GOT_STATUS_MODIFY
&&
8534 staged_status
!= GOT_STATUS_DELETE
)
8537 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8539 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8541 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, relpath
)
8543 return got_error_from_errno("asprintf");
8545 err
= got_object_id_str(&id_str
,
8546 commit_id
? commit_id
: a
->worktree
->base_commit_id
);
8549 if (asprintf(&label_orig
, "%s: commit %s", GOT_MERGE_LABEL_BASE
,
8551 err
= got_error_from_errno("asprintf");
8555 switch (staged_status
) {
8556 case GOT_STATUS_MODIFY
:
8557 err
= got_object_open_as_blob(&blob_base
, a
->repo
,
8562 case GOT_STATUS_ADD
:
8564 if (staged_status
== GOT_STATUS_ADD
) {
8565 int choice
= GOT_PATCH_CHOICE_NONE
;
8566 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8567 staged_status
, ie
->path
, NULL
, 1, 1);
8570 if (choice
!= GOT_PATCH_CHOICE_YES
)
8573 err
= unstage_hunks(staged_blob_id
,
8574 blob_base
, blob_id
, ie
, ondisk_path
,
8575 label_orig
, a
->worktree
, a
->repo
,
8576 a
->patch_cb
, a
->patch_arg
,
8577 a
->progress_cb
, a
->progress_arg
);
8578 break; /* Done with this file. */
8581 err
= got_object_open_as_blob(&blob_staged
, a
->repo
,
8582 staged_blob_id
, 8192);
8585 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
8586 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
8587 case GOT_FILEIDX_MODE_REGULAR_FILE
:
8588 err
= merge_blob(&local_changes_subsumed
, a
->worktree
,
8589 blob_base
, ondisk_path
, relpath
,
8590 got_fileindex_perms_to_st(ie
), label_orig
,
8591 blob_staged
, commit_id
? commit_id
:
8592 a
->worktree
->base_commit_id
, a
->repo
,
8593 a
->progress_cb
, a
->progress_arg
);
8595 case GOT_FILEIDX_MODE_SYMLINK
:
8596 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
8597 char *staged_target
;
8598 err
= got_object_blob_read_to_str(
8599 &staged_target
, blob_staged
);
8602 err
= merge_symlink(a
->worktree
, blob_base
,
8603 ondisk_path
, relpath
, label_orig
,
8604 staged_target
, commit_id
? commit_id
:
8605 a
->worktree
->base_commit_id
,
8606 a
->repo
, a
->progress_cb
, a
->progress_arg
);
8607 free(staged_target
);
8609 err
= merge_blob(&local_changes_subsumed
,
8610 a
->worktree
, blob_base
, ondisk_path
,
8611 relpath
, got_fileindex_perms_to_st(ie
),
8612 label_orig
, blob_staged
,
8613 commit_id
? commit_id
:
8614 a
->worktree
->base_commit_id
, a
->repo
,
8615 a
->progress_cb
, a
->progress_arg
);
8619 err
= got_error_path(relpath
, GOT_ERR_BAD_FILETYPE
);
8623 got_fileindex_entry_stage_set(ie
,
8624 GOT_FILEIDX_STAGE_NONE
);
8625 got_fileindex_entry_staged_filetype_set(ie
, 0);
8628 case GOT_STATUS_DELETE
:
8630 int choice
= GOT_PATCH_CHOICE_NONE
;
8631 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8632 staged_status
, ie
->path
, NULL
, 1, 1);
8635 if (choice
== GOT_PATCH_CHOICE_NO
)
8637 if (choice
!= GOT_PATCH_CHOICE_YES
) {
8638 err
= got_error(GOT_ERR_PATCH_CHOICE
);
8642 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
8643 got_fileindex_entry_staged_filetype_set(ie
, 0);
8644 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
8645 dirfd
, de_name
, a
->repo
);
8648 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, relpath
);
8654 got_object_blob_close(blob_base
);
8656 got_object_blob_close(blob_staged
);
8662 const struct got_error
*
8663 got_worktree_unstage(struct got_worktree
*worktree
,
8664 struct got_pathlist_head
*paths
,
8665 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
8666 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8667 struct got_repository
*repo
)
8669 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8670 struct got_pathlist_entry
*pe
;
8671 struct got_fileindex
*fileindex
= NULL
;
8672 char *fileindex_path
= NULL
;
8673 struct unstage_path_arg upa
;
8675 err
= lock_worktree(worktree
, LOCK_EX
);
8679 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8683 upa
.worktree
= worktree
;
8684 upa
.fileindex
= fileindex
;
8686 upa
.progress_cb
= progress_cb
;
8687 upa
.progress_arg
= progress_arg
;
8688 upa
.patch_cb
= patch_cb
;
8689 upa
.patch_arg
= patch_arg
;
8690 TAILQ_FOREACH(pe
, paths
, entry
) {
8691 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8692 unstage_path
, &upa
, NULL
, NULL
, 0, 0);
8697 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8698 if (sync_err
&& err
== NULL
)
8701 free(fileindex_path
);
8703 got_fileindex_free(fileindex
);
8704 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8705 if (unlockerr
&& err
== NULL
)
8710 struct report_file_info_arg
{
8711 struct got_worktree
*worktree
;
8712 got_worktree_path_info_cb info_cb
;
8714 struct got_pathlist_head
*paths
;
8715 got_cancel_cb cancel_cb
;
8719 static const struct got_error
*
8720 report_file_info(void *arg
, struct got_fileindex_entry
*ie
)
8722 struct report_file_info_arg
*a
= arg
;
8723 struct got_pathlist_entry
*pe
;
8724 struct got_object_id blob_id
, staged_blob_id
, commit_id
;
8725 struct got_object_id
*blob_idp
= NULL
, *staged_blob_idp
= NULL
;
8726 struct got_object_id
*commit_idp
= NULL
;
8729 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
8730 return got_error(GOT_ERR_CANCELLED
);
8732 TAILQ_FOREACH(pe
, a
->paths
, entry
) {
8733 if (pe
->path_len
== 0 || strcmp(pe
->path
, ie
->path
) == 0 ||
8734 got_path_is_child(ie
->path
, pe
->path
, pe
->path_len
))
8737 if (pe
== NULL
) /* not found */
8740 if (got_fileindex_entry_has_blob(ie
)) {
8741 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
8742 blob_idp
= &blob_id
;
8744 stage
= got_fileindex_entry_stage_get(ie
);
8745 if (stage
== GOT_FILEIDX_STAGE_MODIFY
||
8746 stage
== GOT_FILEIDX_STAGE_ADD
) {
8747 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
8748 SHA1_DIGEST_LENGTH
);
8749 staged_blob_idp
= &staged_blob_id
;
8752 if (got_fileindex_entry_has_commit(ie
)) {
8753 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
8754 commit_idp
= &commit_id
;
8757 return a
->info_cb(a
->info_arg
, ie
->path
, got_fileindex_perms_to_st(ie
),
8758 (time_t)ie
->mtime_sec
, blob_idp
, staged_blob_idp
, commit_idp
);
8761 const struct got_error
*
8762 got_worktree_path_info(struct got_worktree
*worktree
,
8763 struct got_pathlist_head
*paths
,
8764 got_worktree_path_info_cb info_cb
, void *info_arg
,
8765 got_cancel_cb cancel_cb
, void *cancel_arg
)
8768 const struct got_error
*err
= NULL
, *unlockerr
;
8769 struct got_fileindex
*fileindex
= NULL
;
8770 char *fileindex_path
= NULL
;
8771 struct report_file_info_arg arg
;
8773 err
= lock_worktree(worktree
, LOCK_SH
);
8777 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8781 arg
.worktree
= worktree
;
8782 arg
.info_cb
= info_cb
;
8783 arg
.info_arg
= info_arg
;
8785 arg
.cancel_cb
= cancel_cb
;
8786 arg
.cancel_arg
= cancel_arg
;
8787 err
= got_fileindex_for_each_entry_safe(fileindex
, report_file_info
,
8790 free(fileindex_path
);
8792 got_fileindex_free(fileindex
);
8793 unlockerr
= lock_worktree(worktree
, LOCK_UN
);
8794 if (unlockerr
&& err
== NULL
)