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
);
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
, struct got_repository
*repo
,
1374 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1376 const struct got_error
*err
= NULL
;
1377 char target_path
[PATH_MAX
];
1378 size_t len
, target_len
= 0;
1379 char *path_got
= NULL
;
1380 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1381 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1383 *is_bad_symlink
= 0;
1386 * Blob object content specifies the target path of the link.
1387 * If a symbolic link cannot be installed we instead create
1388 * a regular file which contains the link target path stored
1389 * in the blob object.
1392 err
= got_object_blob_read_block(&len
, blob
);
1393 if (len
+ target_len
>= sizeof(target_path
)) {
1394 /* Path too long; install as a regular file. */
1395 *is_bad_symlink
= 1;
1396 got_object_blob_rewind(blob
);
1397 return install_blob(worktree
, ondisk_path
, path
,
1398 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1399 restoring_missing_file
, reverting_versioned_file
,
1400 1, path_is_unversioned
, repo
, progress_cb
,
1404 /* Skip blob object header first time around. */
1405 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1407 target_len
+= len
- hdrlen
;
1411 target_path
[target_len
] = '\0';
1413 err
= is_bad_symlink_target(is_bad_symlink
, target_path
, target_len
,
1414 ondisk_path
, worktree
->root_path
);
1418 if (*is_bad_symlink
) {
1419 /* install as a regular file */
1420 got_object_blob_rewind(blob
);
1421 err
= install_blob(worktree
, ondisk_path
, path
,
1422 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1423 restoring_missing_file
, reverting_versioned_file
, 1,
1424 path_is_unversioned
, repo
, progress_cb
, progress_arg
);
1428 if (symlink(target_path
, ondisk_path
) == -1) {
1429 if (errno
== EEXIST
) {
1430 int symlink_replaced
;
1431 if (path_is_unversioned
) {
1432 err
= (*progress_cb
)(progress_arg
,
1433 GOT_STATUS_UNVERSIONED
, path
);
1436 err
= replace_existing_symlink(&symlink_replaced
,
1437 ondisk_path
, target_path
, target_len
);
1441 if (symlink_replaced
) {
1442 err
= (*progress_cb
)(progress_arg
,
1443 reverting_versioned_file
?
1445 GOT_STATUS_UPDATE
, path
);
1447 err
= (*progress_cb
)(progress_arg
,
1448 GOT_STATUS_EXISTS
, path
);
1451 goto done
; /* Nothing else to do. */
1454 if (errno
== ENOENT
) {
1456 err
= got_path_dirname(&parent
, ondisk_path
);
1459 err
= add_dir_on_disk(worktree
, parent
);
1464 * Retry, and fall through to error handling
1465 * below if this second attempt fails.
1467 if (symlink(target_path
, ondisk_path
) != -1) {
1468 err
= NULL
; /* success */
1473 /* Handle errors from first or second creation attempt. */
1474 if (errno
== ENAMETOOLONG
) {
1475 /* bad target path; install as a regular file */
1476 *is_bad_symlink
= 1;
1477 got_object_blob_rewind(blob
);
1478 err
= install_blob(worktree
, ondisk_path
, path
,
1479 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1480 restoring_missing_file
, reverting_versioned_file
, 1,
1481 path_is_unversioned
, repo
,
1482 progress_cb
, progress_arg
);
1483 } else if (errno
== ENOTDIR
) {
1484 err
= got_error_path(ondisk_path
,
1485 GOT_ERR_FILE_OBSTRUCTED
);
1487 err
= got_error_from_errno3("symlink",
1488 target_path
, ondisk_path
);
1490 } else if (progress_cb
)
1491 err
= (*progress_cb
)(progress_arg
, reverting_versioned_file
?
1492 GOT_STATUS_REVERT
: GOT_STATUS_ADD
, path
);
1498 static const struct got_error
*
1499 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1500 const char *path
, mode_t te_mode
, mode_t st_mode
,
1501 struct got_blob_object
*blob
, int restoring_missing_file
,
1502 int reverting_versioned_file
, int installing_bad_symlink
,
1503 int path_is_unversioned
, struct got_repository
*repo
,
1504 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1506 const struct got_error
*err
= NULL
;
1510 char *tmppath
= NULL
;
1512 fd
= open(ondisk_path
, O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
,
1513 GOT_DEFAULT_FILE_MODE
);
1515 if (errno
== ENOENT
) {
1517 err
= got_path_dirname(&parent
, path
);
1520 err
= add_dir_on_disk(worktree
, parent
);
1524 fd
= open(ondisk_path
,
1525 O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
,
1526 GOT_DEFAULT_FILE_MODE
);
1528 return got_error_from_errno2("open",
1530 } else if (errno
== EEXIST
) {
1531 if (path_is_unversioned
) {
1532 err
= (*progress_cb
)(progress_arg
,
1533 GOT_STATUS_UNVERSIONED
, path
);
1536 if (!(S_ISLNK(st_mode
) && S_ISREG(te_mode
)) &&
1537 !S_ISREG(st_mode
) && !installing_bad_symlink
) {
1538 /* TODO file is obstructed; do something */
1539 err
= got_error_path(ondisk_path
,
1540 GOT_ERR_FILE_OBSTRUCTED
);
1543 err
= got_opentemp_named_fd(&tmppath
, &fd
,
1550 return got_error_from_errno2("open", ondisk_path
);
1553 if (fchmod(fd
, get_ondisk_perms(te_mode
& S_IXUSR
, st_mode
)) == -1) {
1554 err
= got_error_from_errno2("fchmod",
1555 update
? tmppath
: ondisk_path
);
1560 if (restoring_missing_file
)
1561 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MISSING
,
1563 else if (reverting_versioned_file
)
1564 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_REVERT
,
1567 err
= (*progress_cb
)(progress_arg
,
1568 update
? GOT_STATUS_UPDATE
: GOT_STATUS_ADD
, path
);
1573 hdrlen
= got_object_blob_get_hdrlen(blob
);
1575 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1576 err
= got_object_blob_read_block(&len
, blob
);
1580 /* Skip blob object header first time around. */
1581 ssize_t outlen
= write(fd
, buf
+ hdrlen
, len
- hdrlen
);
1583 err
= got_error_from_errno("write");
1585 } else if (outlen
!= len
- hdrlen
) {
1586 err
= got_error(GOT_ERR_IO
);
1593 if (fsync(fd
) != 0) {
1594 err
= got_error_from_errno("fsync");
1599 if (S_ISLNK(st_mode
) && unlink(ondisk_path
) == -1) {
1600 err
= got_error_from_errno2("unlink", ondisk_path
);
1603 if (rename(tmppath
, ondisk_path
) != 0) {
1604 err
= got_error_from_errno3("rename", tmppath
,
1613 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1614 err
= got_error_from_errno("close");
1615 if (tmppath
!= NULL
&& unlink(tmppath
) == -1 && err
== NULL
)
1616 err
= got_error_from_errno2("unlink", tmppath
);
1621 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1622 static const struct got_error
*
1623 get_modified_file_content_status(unsigned char *status
, FILE *f
)
1625 const struct got_error
*err
= NULL
;
1626 const char *markers
[3] = {
1627 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
1628 GOT_DIFF_CONFLICT_MARKER_SEP
,
1629 GOT_DIFF_CONFLICT_MARKER_END
1633 size_t linesize
= 0;
1636 while (*status
== GOT_STATUS_MODIFY
) {
1637 linelen
= getline(&line
, &linesize
, f
);
1638 if (linelen
== -1) {
1641 err
= got_ferror(f
, GOT_ERR_IO
);
1645 if (strncmp(line
, markers
[i
], strlen(markers
[i
])) == 0) {
1646 if (strcmp(markers
[i
], GOT_DIFF_CONFLICT_MARKER_END
)
1648 *status
= GOT_STATUS_CONFLICT
;
1659 xbit_differs(struct got_fileindex_entry
*ie
, uint16_t st_mode
)
1661 mode_t ie_mode
= got_fileindex_perms_to_st(ie
);
1662 return ((ie_mode
& S_IXUSR
) != (st_mode
& S_IXUSR
));
1666 stat_info_differs(struct got_fileindex_entry
*ie
, struct stat
*sb
)
1668 return !(ie
->ctime_sec
== sb
->st_ctim
.tv_sec
&&
1669 ie
->ctime_nsec
== sb
->st_ctim
.tv_nsec
&&
1670 ie
->mtime_sec
== sb
->st_mtim
.tv_sec
&&
1671 ie
->mtime_nsec
== sb
->st_mtim
.tv_nsec
&&
1672 ie
->size
== (sb
->st_size
& 0xffffffff) &&
1673 !xbit_differs(ie
, sb
->st_mode
));
1676 static unsigned char
1677 get_staged_status(struct got_fileindex_entry
*ie
)
1679 switch (got_fileindex_entry_stage_get(ie
)) {
1680 case GOT_FILEIDX_STAGE_ADD
:
1681 return GOT_STATUS_ADD
;
1682 case GOT_FILEIDX_STAGE_DELETE
:
1683 return GOT_STATUS_DELETE
;
1684 case GOT_FILEIDX_STAGE_MODIFY
:
1685 return GOT_STATUS_MODIFY
;
1687 return GOT_STATUS_NO_CHANGE
;
1691 static const struct got_error
*
1692 get_symlink_modification_status(unsigned char *status
,
1693 struct got_fileindex_entry
*ie
, const char *abspath
,
1694 int dirfd
, const char *de_name
, struct got_blob_object
*blob
)
1696 const struct got_error
*err
= NULL
;
1697 char target_path
[PATH_MAX
];
1698 char etarget
[PATH_MAX
];
1700 size_t len
, target_len
= 0;
1701 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1702 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1704 *status
= GOT_STATUS_NO_CHANGE
;
1706 /* Blob object content specifies the target path of the link. */
1708 err
= got_object_blob_read_block(&len
, blob
);
1711 if (len
+ target_len
>= sizeof(target_path
)) {
1713 * Should not happen. The blob contents were OK
1714 * when this symlink was installed.
1716 return got_error(GOT_ERR_NO_SPACE
);
1719 /* Skip blob object header first time around. */
1720 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1722 target_len
+= len
- hdrlen
;
1726 target_path
[target_len
] = '\0';
1729 elen
= readlinkat(dirfd
, de_name
, etarget
, sizeof(etarget
));
1731 return got_error_from_errno2("readlinkat", abspath
);
1733 elen
= readlink(abspath
, etarget
, sizeof(etarget
));
1735 return got_error_from_errno2("readlink", abspath
);
1738 if (elen
!= target_len
|| memcmp(etarget
, target_path
, target_len
) != 0)
1739 *status
= GOT_STATUS_MODIFY
;
1744 static const struct got_error
*
1745 get_file_status(unsigned char *status
, struct stat
*sb
,
1746 struct got_fileindex_entry
*ie
, const char *abspath
,
1747 int dirfd
, const char *de_name
, struct got_repository
*repo
)
1749 const struct got_error
*err
= NULL
;
1750 struct got_object_id id
;
1755 struct got_blob_object
*blob
= NULL
;
1757 unsigned char staged_status
= get_staged_status(ie
);
1759 *status
= GOT_STATUS_NO_CHANGE
;
1760 memset(sb
, 0, sizeof(*sb
));
1763 * Whenever the caller provides a directory descriptor and a
1764 * directory entry name for the file, use them! This prevents
1765 * race conditions if filesystem paths change beneath our feet.
1768 if (fstatat(dirfd
, de_name
, sb
, AT_SYMLINK_NOFOLLOW
) == -1) {
1769 if (errno
== ENOENT
) {
1770 if (got_fileindex_entry_has_file_on_disk(ie
))
1771 *status
= GOT_STATUS_MISSING
;
1773 *status
= GOT_STATUS_DELETE
;
1776 err
= got_error_from_errno2("fstatat", abspath
);
1780 fd
= open(abspath
, O_RDONLY
| O_NOFOLLOW
);
1781 if (fd
== -1 && errno
!= ENOENT
&& errno
!= ELOOP
)
1782 return got_error_from_errno2("open", abspath
);
1783 else if (fd
== -1 && errno
== ELOOP
) {
1784 if (lstat(abspath
, sb
) == -1)
1785 return got_error_from_errno2("lstat", abspath
);
1786 } else if (fd
== -1 || fstat(fd
, sb
) == -1) {
1787 if (errno
== ENOENT
) {
1788 if (got_fileindex_entry_has_file_on_disk(ie
))
1789 *status
= GOT_STATUS_MISSING
;
1791 *status
= GOT_STATUS_DELETE
;
1794 err
= got_error_from_errno2("fstat", abspath
);
1799 if (!S_ISREG(sb
->st_mode
) && !S_ISLNK(sb
->st_mode
)) {
1800 *status
= GOT_STATUS_OBSTRUCTED
;
1804 if (!got_fileindex_entry_has_file_on_disk(ie
)) {
1805 *status
= GOT_STATUS_DELETE
;
1807 } else if (!got_fileindex_entry_has_blob(ie
) &&
1808 staged_status
!= GOT_STATUS_ADD
) {
1809 *status
= GOT_STATUS_ADD
;
1813 if (!stat_info_differs(ie
, sb
))
1816 if (S_ISLNK(sb
->st_mode
) &&
1817 got_fileindex_entry_filetype_get(ie
) != GOT_FILEIDX_MODE_SYMLINK
) {
1818 *status
= GOT_STATUS_MODIFY
;
1822 if (staged_status
== GOT_STATUS_MODIFY
||
1823 staged_status
== GOT_STATUS_ADD
)
1824 memcpy(id
.sha1
, ie
->staged_blob_sha1
, sizeof(id
.sha1
));
1826 memcpy(id
.sha1
, ie
->blob_sha1
, sizeof(id
.sha1
));
1828 err
= got_object_open_as_blob(&blob
, repo
, &id
, sizeof(fbuf
));
1832 if (S_ISLNK(sb
->st_mode
)) {
1833 err
= get_symlink_modification_status(status
, ie
,
1834 abspath
, dirfd
, de_name
, blob
);
1839 fd
= openat(dirfd
, de_name
, O_RDONLY
| O_NOFOLLOW
);
1841 err
= got_error_from_errno2("openat", abspath
);
1846 f
= fdopen(fd
, "r");
1848 err
= got_error_from_errno2("fdopen", abspath
);
1852 hdrlen
= got_object_blob_get_hdrlen(blob
);
1854 const uint8_t *bbuf
= got_object_blob_get_read_buf(blob
);
1855 err
= got_object_blob_read_block(&blen
, blob
);
1858 /* Skip length of blob object header first time around. */
1859 flen
= fread(fbuf
, 1, sizeof(fbuf
) - hdrlen
, f
);
1860 if (flen
== 0 && ferror(f
)) {
1861 err
= got_error_from_errno("fread");
1864 if (blen
- hdrlen
== 0) {
1866 *status
= GOT_STATUS_MODIFY
;
1868 } else if (flen
== 0) {
1869 if (blen
- hdrlen
!= 0)
1870 *status
= GOT_STATUS_MODIFY
;
1872 } else if (blen
- hdrlen
== flen
) {
1873 /* Skip blob object header first time around. */
1874 if (memcmp(bbuf
+ hdrlen
, fbuf
, flen
) != 0) {
1875 *status
= GOT_STATUS_MODIFY
;
1879 *status
= GOT_STATUS_MODIFY
;
1885 if (*status
== GOT_STATUS_MODIFY
) {
1887 err
= get_modified_file_content_status(status
, f
);
1888 } else if (xbit_differs(ie
, sb
->st_mode
))
1889 *status
= GOT_STATUS_MODE_CHANGE
;
1892 got_object_blob_close(blob
);
1893 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
1894 err
= got_error_from_errno2("fclose", abspath
);
1895 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1896 err
= got_error_from_errno2("close", abspath
);
1901 * Update timestamps in the file index if a file is unmodified and
1902 * we had to run a full content comparison to find out.
1904 static const struct got_error
*
1905 sync_timestamps(int wt_fd
, const char *path
, unsigned char status
,
1906 struct got_fileindex_entry
*ie
, struct stat
*sb
)
1908 if (status
== GOT_STATUS_NO_CHANGE
&& stat_info_differs(ie
, sb
))
1909 return got_fileindex_entry_update(ie
, wt_fd
, path
,
1910 ie
->blob_sha1
, ie
->commit_sha1
, 1);
1915 static const struct got_error
*
1916 update_blob(struct got_worktree
*worktree
,
1917 struct got_fileindex
*fileindex
, struct got_fileindex_entry
*ie
,
1918 struct got_tree_entry
*te
, const char *path
,
1919 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
1922 const struct got_error
*err
= NULL
;
1923 struct got_blob_object
*blob
= NULL
;
1925 unsigned char status
= GOT_STATUS_NO_CHANGE
;
1928 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, path
) == -1)
1929 return got_error_from_errno("asprintf");
1932 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
) {
1933 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
1936 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
1940 if (status
== GOT_STATUS_MISSING
|| status
== GOT_STATUS_DELETE
)
1941 sb
.st_mode
= got_fileindex_perms_to_st(ie
);
1943 if (stat(ondisk_path
, &sb
) == -1) {
1944 if (errno
!= ENOENT
) {
1945 err
= got_error_from_errno2("stat",
1949 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
1950 status
= GOT_STATUS_UNVERSIONED
;
1952 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
1953 status
= GOT_STATUS_UNVERSIONED
;
1955 status
= GOT_STATUS_OBSTRUCTED
;
1959 if (status
== GOT_STATUS_OBSTRUCTED
) {
1961 got_fileindex_entry_mark_skipped(ie
);
1962 err
= (*progress_cb
)(progress_arg
, status
, path
);
1965 if (status
== GOT_STATUS_CONFLICT
) {
1967 got_fileindex_entry_mark_skipped(ie
);
1968 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CANNOT_UPDATE
,
1973 if (ie
&& status
!= GOT_STATUS_MISSING
&& S_ISREG(sb
.st_mode
) &&
1974 (S_ISLNK(te
->mode
) ||
1975 (te
->mode
& S_IXUSR
) == (sb
.st_mode
& S_IXUSR
))) {
1977 * This is a regular file or an installed bad symlink.
1978 * If the file index indicates that this file is already
1979 * up-to-date with respect to the repository we can skip
1980 * updating contents of this file.
1982 if (got_fileindex_entry_has_commit(ie
) &&
1983 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
1984 SHA1_DIGEST_LENGTH
) == 0) {
1986 err
= sync_timestamps(worktree
->root_fd
,
1987 path
, status
, ie
, &sb
);
1990 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
1994 if (got_fileindex_entry_has_blob(ie
) &&
1995 memcmp(ie
->blob_sha1
, te
->id
.sha1
,
1996 SHA1_DIGEST_LENGTH
) == 0) {
1997 /* Different commit but the same blob. */
1998 err
= sync_timestamps(worktree
->root_fd
,
1999 path
, status
, ie
, &sb
);
2002 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
2008 err
= got_object_open_as_blob(&blob
, repo
, &te
->id
, 8192);
2012 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_ADD
) {
2013 int update_timestamps
;
2014 struct got_blob_object
*blob2
= NULL
;
2015 char *label_orig
= NULL
;
2016 if (got_fileindex_entry_has_blob(ie
)) {
2017 struct got_object_id id2
;
2018 memcpy(id2
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
2019 err
= got_object_open_as_blob(&blob2
, repo
, &id2
, 8192);
2023 if (got_fileindex_entry_has_commit(ie
)) {
2024 char id_str
[SHA1_DIGEST_STRING_LENGTH
];
2025 if (got_sha1_digest_to_str(ie
->commit_sha1
, id_str
,
2026 sizeof(id_str
)) == NULL
) {
2027 err
= got_error_path(id_str
,
2028 GOT_ERR_BAD_OBJ_ID_STR
);
2031 if (asprintf(&label_orig
, "%s: commit %s",
2032 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
2033 err
= got_error_from_errno("asprintf");
2037 if (S_ISLNK(te
->mode
) && S_ISLNK(sb
.st_mode
)) {
2039 err
= got_object_blob_read_to_str(&link_target
, blob
);
2042 err
= merge_symlink(worktree
, blob2
, ondisk_path
, path
,
2043 label_orig
, link_target
, worktree
->base_commit_id
,
2044 repo
, progress_cb
, progress_arg
);
2047 err
= merge_blob(&update_timestamps
, worktree
, blob2
,
2048 ondisk_path
, path
, sb
.st_mode
, label_orig
, blob
,
2049 worktree
->base_commit_id
, repo
,
2050 progress_cb
, progress_arg
);
2054 got_object_blob_close(blob2
);
2058 * Do not update timestamps of files with local changes.
2059 * Otherwise, a future status walk would treat them as
2060 * unmodified files again.
2062 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2063 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
,
2065 } else if (status
== GOT_STATUS_MODE_CHANGE
) {
2066 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2067 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
2068 } else if (status
== GOT_STATUS_DELETE
) {
2069 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
2072 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2073 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
2077 int is_bad_symlink
= 0;
2078 if (S_ISLNK(te
->mode
)) {
2079 err
= install_symlink(&is_bad_symlink
, worktree
,
2080 ondisk_path
, path
, blob
,
2081 status
== GOT_STATUS_MISSING
, 0,
2082 status
== GOT_STATUS_UNVERSIONED
, repo
,
2083 progress_cb
, progress_arg
);
2085 err
= install_blob(worktree
, ondisk_path
, path
,
2086 te
->mode
, sb
.st_mode
, blob
,
2087 status
== GOT_STATUS_MISSING
, 0, 0,
2088 status
== GOT_STATUS_UNVERSIONED
, repo
,
2089 progress_cb
, progress_arg
);
2095 err
= got_fileindex_entry_update(ie
,
2096 worktree
->root_fd
, path
, blob
->id
.sha1
,
2097 worktree
->base_commit_id
->sha1
, 1);
2099 err
= create_fileindex_entry(&ie
, fileindex
,
2100 worktree
->base_commit_id
, worktree
->root_fd
, path
,
2106 if (is_bad_symlink
) {
2107 got_fileindex_entry_filetype_set(ie
,
2108 GOT_FILEIDX_MODE_BAD_SYMLINK
);
2111 got_object_blob_close(blob
);
2117 static const struct got_error
*
2118 remove_ondisk_file(const char *root_path
, const char *path
)
2120 const struct got_error
*err
= NULL
;
2121 char *ondisk_path
= NULL
, *parent
= NULL
;
2123 if (asprintf(&ondisk_path
, "%s/%s", root_path
, path
) == -1)
2124 return got_error_from_errno("asprintf");
2126 if (unlink(ondisk_path
) == -1) {
2127 if (errno
!= ENOENT
)
2128 err
= got_error_from_errno2("unlink", ondisk_path
);
2130 size_t root_len
= strlen(root_path
);
2131 err
= got_path_dirname(&parent
, ondisk_path
);
2134 while (got_path_cmp(parent
, root_path
,
2135 strlen(parent
), root_len
) != 0) {
2137 ondisk_path
= parent
;
2139 if (rmdir(ondisk_path
) == -1) {
2140 if (errno
!= ENOTEMPTY
)
2141 err
= got_error_from_errno2("rmdir",
2145 err
= got_path_dirname(&parent
, ondisk_path
);
2156 static const struct got_error
*
2157 delete_blob(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2158 struct got_fileindex_entry
*ie
, struct got_repository
*repo
,
2159 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2161 const struct got_error
*err
= NULL
;
2162 unsigned char status
;
2166 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
2167 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
2169 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, ie
->path
)
2171 return got_error_from_errno("asprintf");
2173 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, repo
);
2177 if (S_ISLNK(sb
.st_mode
) && status
!= GOT_STATUS_NO_CHANGE
) {
2178 char ondisk_target
[PATH_MAX
];
2179 ssize_t ondisk_len
= readlink(ondisk_path
, ondisk_target
,
2180 sizeof(ondisk_target
));
2181 if (ondisk_len
== -1) {
2182 err
= got_error_from_errno2("readlink", ondisk_path
);
2185 ondisk_target
[ondisk_len
] = '\0';
2186 err
= install_symlink_conflict(NULL
, worktree
->base_commit_id
,
2187 NULL
, NULL
, /* XXX pass common ancestor info? */
2188 ondisk_target
, ondisk_path
);
2191 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
2196 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_CONFLICT
||
2197 status
== GOT_STATUS_ADD
) {
2198 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, ie
->path
);
2202 * Preserve the working file and change the deleted blob's
2203 * entry into a schedule-add entry.
2205 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
,
2206 ie
->path
, NULL
, NULL
, 0);
2208 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_DELETE
, ie
->path
);
2211 if (status
== GOT_STATUS_NO_CHANGE
) {
2212 err
= remove_ondisk_file(worktree
->root_path
, ie
->path
);
2216 got_fileindex_entry_remove(fileindex
, ie
);
2223 struct diff_cb_arg
{
2224 struct got_fileindex
*fileindex
;
2225 struct got_worktree
*worktree
;
2226 struct got_repository
*repo
;
2227 got_worktree_checkout_cb progress_cb
;
2229 got_cancel_cb cancel_cb
;
2233 static const struct got_error
*
2234 diff_old_new(void *arg
, struct got_fileindex_entry
*ie
,
2235 struct got_tree_entry
*te
, const char *parent_path
)
2237 struct diff_cb_arg
*a
= arg
;
2239 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2240 return got_error(GOT_ERR_CANCELLED
);
2242 return update_blob(a
->worktree
, a
->fileindex
, ie
, te
,
2243 ie
->path
, a
->repo
, a
->progress_cb
, a
->progress_arg
);
2246 static const struct got_error
*
2247 diff_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
2249 struct diff_cb_arg
*a
= arg
;
2251 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2252 return got_error(GOT_ERR_CANCELLED
);
2254 return delete_blob(a
->worktree
, a
->fileindex
, ie
,
2255 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2258 static const struct got_error
*
2259 diff_new(void *arg
, struct got_tree_entry
*te
, const char *parent_path
)
2261 struct diff_cb_arg
*a
= arg
;
2262 const struct got_error
*err
;
2265 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2266 return got_error(GOT_ERR_CANCELLED
);
2268 if (got_object_tree_entry_is_submodule(te
))
2271 if (asprintf(&path
, "%s%s%s", parent_path
,
2272 parent_path
[0] ? "/" : "", te
->name
)
2274 return got_error_from_errno("asprintf");
2276 if (S_ISDIR(te
->mode
))
2277 err
= add_dir_on_disk(a
->worktree
, path
);
2279 err
= update_blob(a
->worktree
, a
->fileindex
, NULL
, te
, path
,
2280 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2286 const struct got_error
*
2287 got_worktree_get_uuid(char **uuidstr
, struct got_worktree
*worktree
)
2289 uint32_t uuid_status
;
2291 uuid_to_string(&worktree
->uuid
, uuidstr
, &uuid_status
);
2292 if (uuid_status
!= uuid_s_ok
) {
2294 return got_error_uuid(uuid_status
, "uuid_to_string");
2300 static const struct got_error
*
2301 get_ref_name(char **refname
, struct got_worktree
*worktree
, const char *prefix
)
2303 const struct got_error
*err
= NULL
;
2304 char *uuidstr
= NULL
;
2308 err
= got_worktree_get_uuid(&uuidstr
, worktree
);
2312 if (asprintf(refname
, "%s-%s", prefix
, uuidstr
) == -1) {
2313 err
= got_error_from_errno("asprintf");
2320 const struct got_error
*
2321 got_worktree_get_base_ref_name(char **refname
, struct got_worktree
*worktree
)
2323 return get_ref_name(refname
, worktree
, GOT_WORKTREE_BASE_REF_PREFIX
);
2326 static const struct got_error
*
2327 get_rebase_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2329 return get_ref_name(refname
, worktree
,
2330 GOT_WORKTREE_REBASE_TMP_REF_PREFIX
);
2333 static const struct got_error
*
2334 get_newbase_symref_name(char **refname
, struct got_worktree
*worktree
)
2336 return get_ref_name(refname
, worktree
, GOT_WORKTREE_NEWBASE_REF_PREFIX
);
2339 static const struct got_error
*
2340 get_rebase_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2342 return get_ref_name(refname
, worktree
,
2343 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX
);
2346 static const struct got_error
*
2347 get_rebase_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2349 return get_ref_name(refname
, worktree
,
2350 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX
);
2353 static const struct got_error
*
2354 get_histedit_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2356 return get_ref_name(refname
, worktree
,
2357 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX
);
2360 static const struct got_error
*
2361 get_histedit_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2363 return get_ref_name(refname
, worktree
,
2364 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX
);
2367 static const struct got_error
*
2368 get_histedit_base_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2370 return get_ref_name(refname
, worktree
,
2371 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX
);
2374 static const struct got_error
*
2375 get_histedit_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2377 return get_ref_name(refname
, worktree
,
2378 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX
);
2381 const struct got_error
*
2382 got_worktree_get_histedit_script_path(char **path
,
2383 struct got_worktree
*worktree
)
2385 if (asprintf(path
, "%s/%s/%s", worktree
->root_path
,
2386 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_HISTEDIT_SCRIPT
) == -1) {
2388 return got_error_from_errno("asprintf");
2393 static const struct got_error
*
2394 get_merge_branch_ref_name(char **refname
, struct got_worktree
*worktree
)
2396 return get_ref_name(refname
, worktree
,
2397 GOT_WORKTREE_MERGE_BRANCH_REF_PREFIX
);
2400 static const struct got_error
*
2401 get_merge_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2403 return get_ref_name(refname
, worktree
,
2404 GOT_WORKTREE_MERGE_COMMIT_REF_PREFIX
);
2408 * Prevent Git's garbage collector from deleting our base commit by
2409 * setting a reference to our base commit's ID.
2411 static const struct got_error
*
2412 ref_base_commit(struct got_worktree
*worktree
, struct got_repository
*repo
)
2414 const struct got_error
*err
= NULL
;
2415 struct got_reference
*ref
= NULL
;
2418 err
= got_worktree_get_base_ref_name(&refname
, worktree
);
2422 err
= got_ref_alloc(&ref
, refname
, worktree
->base_commit_id
);
2426 err
= got_ref_write(ref
, repo
);
2434 static const struct got_error
*
2435 get_fileindex_path(char **fileindex_path
, struct got_worktree
*worktree
)
2437 const struct got_error
*err
= NULL
;
2439 if (asprintf(fileindex_path
, "%s/%s/%s", worktree
->root_path
,
2440 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_FILE_INDEX
) == -1) {
2441 err
= got_error_from_errno("asprintf");
2442 *fileindex_path
= NULL
;
2448 static const struct got_error
*
2449 open_fileindex(struct got_fileindex
**fileindex
, char **fileindex_path
,
2450 struct got_worktree
*worktree
)
2452 const struct got_error
*err
= NULL
;
2455 *fileindex_path
= NULL
;
2456 *fileindex
= got_fileindex_alloc();
2457 if (*fileindex
== NULL
)
2458 return got_error_from_errno("got_fileindex_alloc");
2460 err
= get_fileindex_path(fileindex_path
, worktree
);
2464 index
= fopen(*fileindex_path
, "rb");
2465 if (index
== NULL
) {
2466 if (errno
!= ENOENT
)
2467 err
= got_error_from_errno2("fopen", *fileindex_path
);
2469 err
= got_fileindex_read(*fileindex
, index
);
2470 if (fclose(index
) == EOF
&& err
== NULL
)
2471 err
= got_error_from_errno("fclose");
2475 free(*fileindex_path
);
2476 *fileindex_path
= NULL
;
2477 got_fileindex_free(*fileindex
);
2483 struct bump_base_commit_id_arg
{
2484 struct got_object_id
*base_commit_id
;
2487 const char *entry_name
;
2488 got_worktree_checkout_cb progress_cb
;
2492 /* Bump base commit ID of all files within an updated part of the work tree. */
2493 static const struct got_error
*
2494 bump_base_commit_id(void *arg
, struct got_fileindex_entry
*ie
)
2496 const struct got_error
*err
;
2497 struct bump_base_commit_id_arg
*a
= arg
;
2499 if (a
->entry_name
) {
2500 if (strcmp(ie
->path
, a
->path
) != 0)
2502 } else if (!got_path_is_child(ie
->path
, a
->path
, a
->path_len
))
2505 if (got_fileindex_entry_was_skipped(ie
))
2508 if (memcmp(ie
->commit_sha1
, a
->base_commit_id
->sha1
,
2509 SHA1_DIGEST_LENGTH
) == 0)
2512 if (a
->progress_cb
) {
2513 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_BUMP_BASE
,
2518 memcpy(ie
->commit_sha1
, a
->base_commit_id
->sha1
, SHA1_DIGEST_LENGTH
);
2522 static const struct got_error
*
2523 bump_base_commit_id_everywhere(struct got_worktree
*worktree
,
2524 struct got_fileindex
*fileindex
,
2525 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2527 struct bump_base_commit_id_arg bbc_arg
;
2529 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2530 bbc_arg
.entry_name
= NULL
;
2532 bbc_arg
.path_len
= 0;
2533 bbc_arg
.progress_cb
= progress_cb
;
2534 bbc_arg
.progress_arg
= progress_arg
;
2536 return got_fileindex_for_each_entry_safe(fileindex
,
2537 bump_base_commit_id
, &bbc_arg
);
2540 static const struct got_error
*
2541 sync_fileindex(struct got_fileindex
*fileindex
, const char *fileindex_path
)
2543 const struct got_error
*err
= NULL
;
2544 char *new_fileindex_path
= NULL
;
2545 FILE *new_index
= NULL
;
2546 struct timespec timeout
;
2548 err
= got_opentemp_named(&new_fileindex_path
, &new_index
,
2553 err
= got_fileindex_write(fileindex
, new_index
);
2557 if (rename(new_fileindex_path
, fileindex_path
) != 0) {
2558 err
= got_error_from_errno3("rename", new_fileindex_path
,
2560 unlink(new_fileindex_path
);
2564 * Sleep for a short amount of time to ensure that files modified after
2565 * this program exits have a different time stamp from the one which
2566 * was recorded in the file index.
2569 timeout
.tv_nsec
= 1;
2570 nanosleep(&timeout
, NULL
);
2574 free(new_fileindex_path
);
2578 static const struct got_error
*
2579 find_tree_entry_for_checkout(int *entry_type
, char **tree_relpath
,
2580 struct got_object_id
**tree_id
, const char *wt_relpath
,
2581 struct got_worktree
*worktree
, struct got_repository
*repo
)
2583 const struct got_error
*err
= NULL
;
2584 struct got_object_id
*id
= NULL
;
2585 char *in_repo_path
= NULL
;
2586 int is_root_wt
= got_path_is_root_dir(worktree
->path_prefix
);
2588 *entry_type
= GOT_OBJ_TYPE_ANY
;
2589 *tree_relpath
= NULL
;
2592 if (wt_relpath
[0] == '\0') {
2593 /* Check out all files within the work tree. */
2594 *entry_type
= GOT_OBJ_TYPE_TREE
;
2595 *tree_relpath
= strdup("");
2596 if (*tree_relpath
== NULL
) {
2597 err
= got_error_from_errno("strdup");
2600 err
= got_object_id_by_path(tree_id
, repo
,
2601 worktree
->base_commit_id
, worktree
->path_prefix
);
2607 /* Check out a subset of files in the work tree. */
2609 if (asprintf(&in_repo_path
, "%s%s%s", worktree
->path_prefix
,
2610 is_root_wt
? "" : "/", wt_relpath
) == -1) {
2611 err
= got_error_from_errno("asprintf");
2615 err
= got_object_id_by_path(&id
, repo
, worktree
->base_commit_id
,
2621 in_repo_path
= NULL
;
2623 err
= got_object_get_type(entry_type
, repo
, id
);
2627 if (*entry_type
== GOT_OBJ_TYPE_BLOB
) {
2628 /* Check out a single file. */
2629 if (strchr(wt_relpath
, '/') == NULL
) {
2630 /* Check out a single file in work tree's root dir. */
2631 in_repo_path
= strdup(worktree
->path_prefix
);
2632 if (in_repo_path
== NULL
) {
2633 err
= got_error_from_errno("strdup");
2636 *tree_relpath
= strdup("");
2637 if (*tree_relpath
== NULL
) {
2638 err
= got_error_from_errno("strdup");
2642 /* Check out a single file in a subdirectory. */
2643 err
= got_path_dirname(tree_relpath
, wt_relpath
);
2646 if (asprintf(&in_repo_path
, "%s%s%s",
2647 worktree
->path_prefix
, is_root_wt
? "" : "/",
2648 *tree_relpath
) == -1) {
2649 err
= got_error_from_errno("asprintf");
2653 err
= got_object_id_by_path(tree_id
, repo
,
2654 worktree
->base_commit_id
, in_repo_path
);
2656 /* Check out all files within a subdirectory. */
2657 *tree_id
= got_object_id_dup(id
);
2658 if (*tree_id
== NULL
) {
2659 err
= got_error_from_errno("got_object_id_dup");
2662 *tree_relpath
= strdup(wt_relpath
);
2663 if (*tree_relpath
== NULL
) {
2664 err
= got_error_from_errno("strdup");
2672 *entry_type
= GOT_OBJ_TYPE_ANY
;
2673 free(*tree_relpath
);
2674 *tree_relpath
= NULL
;
2681 static const struct got_error
*
2682 checkout_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2683 const char *relpath
, struct got_object_id
*tree_id
, const char *entry_name
,
2684 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
2685 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
2687 const struct got_error
*err
= NULL
;
2688 struct got_commit_object
*commit
= NULL
;
2689 struct got_tree_object
*tree
= NULL
;
2690 struct got_fileindex_diff_tree_cb diff_cb
;
2691 struct diff_cb_arg arg
;
2693 err
= ref_base_commit(worktree
, repo
);
2695 if (!(err
->code
== GOT_ERR_ERRNO
&&
2696 (errno
== EACCES
|| errno
== EROFS
)))
2698 err
= (*progress_cb
)(progress_arg
,
2699 GOT_STATUS_BASE_REF_ERR
, worktree
->root_path
);
2704 err
= got_object_open_as_commit(&commit
, repo
,
2705 worktree
->base_commit_id
);
2709 err
= got_object_open_as_tree(&tree
, repo
, tree_id
);
2714 got_object_tree_find_entry(tree
, entry_name
) == NULL
) {
2715 err
= got_error_path(entry_name
, GOT_ERR_NO_TREE_ENTRY
);
2719 diff_cb
.diff_old_new
= diff_old_new
;
2720 diff_cb
.diff_old
= diff_old
;
2721 diff_cb
.diff_new
= diff_new
;
2722 arg
.fileindex
= fileindex
;
2723 arg
.worktree
= worktree
;
2725 arg
.progress_cb
= progress_cb
;
2726 arg
.progress_arg
= progress_arg
;
2727 arg
.cancel_cb
= cancel_cb
;
2728 arg
.cancel_arg
= cancel_arg
;
2729 err
= got_fileindex_diff_tree(fileindex
, tree
, relpath
,
2730 entry_name
, repo
, &diff_cb
, &arg
);
2733 got_object_tree_close(tree
);
2735 got_object_commit_close(commit
);
2739 const struct got_error
*
2740 got_worktree_checkout_files(struct got_worktree
*worktree
,
2741 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
2742 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
2743 got_cancel_cb cancel_cb
, void *cancel_arg
)
2745 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
2746 struct got_commit_object
*commit
= NULL
;
2747 struct got_tree_object
*tree
= NULL
;
2748 struct got_fileindex
*fileindex
= NULL
;
2749 char *fileindex_path
= NULL
;
2750 struct got_pathlist_entry
*pe
;
2751 struct tree_path_data
{
2752 STAILQ_ENTRY(tree_path_data
) entry
;
2753 struct got_object_id
*tree_id
;
2758 STAILQ_HEAD(tree_paths
, tree_path_data
) tree_paths
;
2760 STAILQ_INIT(&tree_paths
);
2762 err
= lock_worktree(worktree
, LOCK_EX
);
2766 /* Map all specified paths to in-repository trees. */
2767 TAILQ_FOREACH(pe
, paths
, entry
) {
2768 tpd
= malloc(sizeof(*tpd
));
2770 err
= got_error_from_errno("malloc");
2774 err
= find_tree_entry_for_checkout(&tpd
->entry_type
,
2775 &tpd
->relpath
, &tpd
->tree_id
, pe
->path
, worktree
, repo
);
2781 if (tpd
->entry_type
== GOT_OBJ_TYPE_BLOB
) {
2782 err
= got_path_basename(&tpd
->entry_name
, pe
->path
);
2790 tpd
->entry_name
= NULL
;
2792 STAILQ_INSERT_TAIL(&tree_paths
, tpd
, entry
);
2796 * Read the file index.
2797 * Checking out files is supposed to be an idempotent operation.
2798 * If the on-disk file index is incomplete we will try to complete it.
2800 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
2804 tpd
= STAILQ_FIRST(&tree_paths
);
2805 TAILQ_FOREACH(pe
, paths
, entry
) {
2806 struct bump_base_commit_id_arg bbc_arg
;
2808 err
= checkout_files(worktree
, fileindex
, tpd
->relpath
,
2809 tpd
->tree_id
, tpd
->entry_name
, repo
,
2810 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
2814 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2815 bbc_arg
.entry_name
= tpd
->entry_name
;
2816 bbc_arg
.path
= pe
->path
;
2817 bbc_arg
.path_len
= pe
->path_len
;
2818 bbc_arg
.progress_cb
= progress_cb
;
2819 bbc_arg
.progress_arg
= progress_arg
;
2820 err
= got_fileindex_for_each_entry_safe(fileindex
,
2821 bump_base_commit_id
, &bbc_arg
);
2825 tpd
= STAILQ_NEXT(tpd
, entry
);
2827 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
2828 if (sync_err
&& err
== NULL
)
2831 free(fileindex_path
);
2833 got_object_tree_close(tree
);
2835 got_object_commit_close(commit
);
2837 got_fileindex_free(fileindex
);
2838 while (!STAILQ_EMPTY(&tree_paths
)) {
2839 tpd
= STAILQ_FIRST(&tree_paths
);
2840 STAILQ_REMOVE_HEAD(&tree_paths
, entry
);
2845 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
2846 if (unlockerr
&& err
== NULL
)
2851 struct merge_file_cb_arg
{
2852 struct got_worktree
*worktree
;
2853 struct got_fileindex
*fileindex
;
2854 got_worktree_checkout_cb progress_cb
;
2856 got_cancel_cb cancel_cb
;
2858 const char *label_orig
;
2859 struct got_object_id
*commit_id2
;
2862 static const struct got_error
*
2863 merge_file_cb(void *arg
, struct got_blob_object
*blob1
,
2864 struct got_blob_object
*blob2
, struct got_object_id
*id1
,
2865 struct got_object_id
*id2
, const char *path1
, const char *path2
,
2866 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
2868 static const struct got_error
*err
= NULL
;
2869 struct merge_file_cb_arg
*a
= arg
;
2870 struct got_fileindex_entry
*ie
;
2871 char *ondisk_path
= NULL
;
2873 unsigned char status
;
2874 int local_changes_subsumed
;
2875 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
2876 char *id_str
= NULL
, *label_deriv2
= NULL
;
2878 if (blob1
&& blob2
) {
2879 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
2882 return (*a
->progress_cb
)(a
->progress_arg
,
2883 GOT_STATUS_MISSING
, path2
);
2885 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2887 return got_error_from_errno("asprintf");
2889 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2894 if (status
== GOT_STATUS_DELETE
) {
2895 err
= (*a
->progress_cb
)(a
->progress_arg
,
2896 GOT_STATUS_MERGE
, path2
);
2899 if (status
!= GOT_STATUS_NO_CHANGE
&&
2900 status
!= GOT_STATUS_MODIFY
&&
2901 status
!= GOT_STATUS_CONFLICT
&&
2902 status
!= GOT_STATUS_ADD
) {
2903 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path2
);
2907 if (S_ISLNK(mode1
) && S_ISLNK(mode2
)) {
2909 err
= got_object_blob_read_to_str(&link_target2
, blob2
);
2912 err
= merge_symlink(a
->worktree
, blob1
, ondisk_path
,
2913 path2
, a
->label_orig
, link_target2
, a
->commit_id2
,
2914 repo
, a
->progress_cb
, a
->progress_arg
);
2919 f_orig
= got_opentemp();
2920 if (f_orig
== NULL
) {
2921 err
= got_error_from_errno("got_opentemp");
2924 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2929 f_deriv2
= got_opentemp();
2930 if (f_deriv2
== NULL
)
2932 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2937 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
);
2939 err
= got_error_from_errno2("open",
2943 f_deriv
= fdopen(fd
, "r");
2944 if (f_deriv
== NULL
) {
2945 err
= got_error_from_errno2("fdopen",
2950 err
= got_object_id_str(&id_str
, a
->commit_id2
);
2953 if (asprintf(&label_deriv2
, "%s: commit %s",
2954 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
2955 err
= got_error_from_errno("asprintf");
2958 err
= merge_file(&local_changes_subsumed
, a
->worktree
,
2959 f_orig
, f_deriv
, f_deriv2
, ondisk_path
, path2
,
2960 sb
.st_mode
, a
->label_orig
, NULL
, label_deriv2
,
2961 GOT_DIFF_ALGORITHM_PATIENCE
, repo
,
2962 a
->progress_cb
, a
->progress_arg
);
2965 ie
= got_fileindex_entry_get(a
->fileindex
, path1
,
2968 return (*a
->progress_cb
)(a
->progress_arg
,
2969 GOT_STATUS_MISSING
, path1
);
2971 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2973 return got_error_from_errno("asprintf");
2975 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2981 case GOT_STATUS_NO_CHANGE
:
2982 err
= (*a
->progress_cb
)(a
->progress_arg
,
2983 GOT_STATUS_DELETE
, path1
);
2986 err
= remove_ondisk_file(a
->worktree
->root_path
, path1
);
2990 got_fileindex_entry_mark_deleted_from_disk(ie
);
2992 case GOT_STATUS_DELETE
:
2993 case GOT_STATUS_MISSING
:
2994 err
= (*a
->progress_cb
)(a
->progress_arg
,
2995 GOT_STATUS_DELETE
, path1
);
2999 got_fileindex_entry_mark_deleted_from_disk(ie
);
3001 case GOT_STATUS_ADD
: {
3002 struct got_object_id
*id
;
3005 * Delete the added file only if its content already
3006 * exists in the repository.
3008 err
= got_object_blob_file_create(&id
, &blob1_f
, path1
);
3011 if (got_object_id_cmp(id
, id1
) == 0) {
3012 err
= (*a
->progress_cb
)(a
->progress_arg
,
3013 GOT_STATUS_DELETE
, path1
);
3016 err
= remove_ondisk_file(a
->worktree
->root_path
,
3021 got_fileindex_entry_remove(a
->fileindex
,
3024 err
= (*a
->progress_cb
)(a
->progress_arg
,
3025 GOT_STATUS_CANNOT_DELETE
, path1
);
3027 if (fclose(blob1_f
) == EOF
&& err
== NULL
)
3028 err
= got_error_from_errno("fclose");
3034 case GOT_STATUS_MODIFY
:
3035 case GOT_STATUS_CONFLICT
:
3036 err
= (*a
->progress_cb
)(a
->progress_arg
,
3037 GOT_STATUS_CANNOT_DELETE
, path1
);
3041 case GOT_STATUS_OBSTRUCTED
:
3042 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path1
);
3050 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3052 return got_error_from_errno("asprintf");
3053 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
3056 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
3060 if (status
!= GOT_STATUS_NO_CHANGE
&&
3061 status
!= GOT_STATUS_MODIFY
&&
3062 status
!= GOT_STATUS_CONFLICT
&&
3063 status
!= GOT_STATUS_ADD
) {
3064 err
= (*a
->progress_cb
)(a
->progress_arg
,
3068 if (S_ISLNK(mode2
) && S_ISLNK(sb
.st_mode
)) {
3070 err
= got_object_blob_read_to_str(&link_target2
,
3074 err
= merge_symlink(a
->worktree
, NULL
,
3075 ondisk_path
, path2
, a
->label_orig
,
3076 link_target2
, a
->commit_id2
, repo
,
3077 a
->progress_cb
, a
->progress_arg
);
3079 } else if (S_ISREG(sb
.st_mode
)) {
3080 err
= merge_blob(&local_changes_subsumed
,
3081 a
->worktree
, NULL
, ondisk_path
, path2
,
3082 sb
.st_mode
, a
->label_orig
, blob2
,
3083 a
->commit_id2
, repo
, a
->progress_cb
,
3086 err
= got_error_path(ondisk_path
,
3087 GOT_ERR_FILE_OBSTRUCTED
);
3091 if (status
== GOT_STATUS_DELETE
) {
3092 err
= got_fileindex_entry_update(ie
,
3093 a
->worktree
->root_fd
, path2
, blob2
->id
.sha1
,
3094 a
->worktree
->base_commit_id
->sha1
, 0);
3099 int is_bad_symlink
= 0;
3100 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
3101 if (S_ISLNK(mode2
)) {
3102 err
= install_symlink(&is_bad_symlink
,
3103 a
->worktree
, ondisk_path
, path2
, blob2
, 0,
3104 0, 1, repo
, a
->progress_cb
, a
->progress_arg
);
3106 err
= install_blob(a
->worktree
, ondisk_path
, path2
,
3107 mode2
, sb
.st_mode
, blob2
, 0, 0, 0, 1, repo
,
3108 a
->progress_cb
, a
->progress_arg
);
3112 err
= got_fileindex_entry_alloc(&ie
, path2
);
3115 err
= got_fileindex_entry_update(ie
,
3116 a
->worktree
->root_fd
, path2
, NULL
, NULL
, 1);
3118 got_fileindex_entry_free(ie
);
3121 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
3123 got_fileindex_entry_free(ie
);
3126 if (is_bad_symlink
) {
3127 got_fileindex_entry_filetype_set(ie
,
3128 GOT_FILEIDX_MODE_BAD_SYMLINK
);
3133 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
3134 err
= got_error_from_errno("fclose");
3135 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
3136 err
= got_error_from_errno("fclose");
3137 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
3138 err
= got_error_from_errno("fclose");
3145 static const struct got_error
*
3146 check_mixed_commits(void *arg
, struct got_fileindex_entry
*ie
)
3148 struct got_worktree
*worktree
= arg
;
3150 /* Reject merges into a work tree with mixed base commits. */
3151 if (got_fileindex_entry_has_commit(ie
) &&
3152 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
3153 SHA1_DIGEST_LENGTH
) != 0)
3154 return got_error(GOT_ERR_MIXED_COMMITS
);
3159 struct check_merge_conflicts_arg
{
3160 struct got_worktree
*worktree
;
3161 struct got_fileindex
*fileindex
;
3162 struct got_repository
*repo
;
3165 static const struct got_error
*
3166 check_merge_conflicts(void *arg
, struct got_blob_object
*blob1
,
3167 struct got_blob_object
*blob2
, struct got_object_id
*id1
,
3168 struct got_object_id
*id2
, const char *path1
, const char *path2
,
3169 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
3171 const struct got_error
*err
= NULL
;
3172 struct check_merge_conflicts_arg
*a
= arg
;
3173 unsigned char status
;
3175 struct got_fileindex_entry
*ie
;
3176 const char *path
= path2
? path2
: path1
;
3177 struct got_object_id
*id
= id2
? id2
: id1
;
3183 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
3187 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
3189 return got_error_from_errno("asprintf");
3191 /* Reject merges into a work tree with conflicted files. */
3192 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
3196 if (status
== GOT_STATUS_CONFLICT
)
3197 return got_error(GOT_ERR_CONFLICTS
);
3202 static const struct got_error
*
3203 merge_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
3204 const char *fileindex_path
, struct got_object_id
*commit_id1
,
3205 struct got_object_id
*commit_id2
, struct got_repository
*repo
,
3206 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
3207 got_cancel_cb cancel_cb
, void *cancel_arg
)
3209 const struct got_error
*err
= NULL
, *sync_err
;
3210 struct got_object_id
*tree_id1
= NULL
, *tree_id2
= NULL
;
3211 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
3212 struct check_merge_conflicts_arg cmc_arg
;
3213 struct merge_file_cb_arg arg
;
3214 char *label_orig
= NULL
;
3217 err
= got_object_id_by_path(&tree_id1
, repo
, commit_id1
,
3218 worktree
->path_prefix
);
3219 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
3225 err
= got_object_open_as_tree(&tree1
, repo
, tree_id1
);
3229 err
= got_object_id_str(&id_str
, commit_id1
);
3233 if (asprintf(&label_orig
, "%s: commit %s",
3234 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
3235 err
= got_error_from_errno("asprintf");
3242 err
= got_object_id_by_path(&tree_id2
, repo
, commit_id2
,
3243 worktree
->path_prefix
);
3247 err
= got_object_open_as_tree(&tree2
, repo
, tree_id2
);
3251 cmc_arg
.worktree
= worktree
;
3252 cmc_arg
.fileindex
= fileindex
;
3253 cmc_arg
.repo
= repo
;
3254 err
= got_diff_tree(tree1
, tree2
, "", "", repo
,
3255 check_merge_conflicts
, &cmc_arg
, 0);
3259 arg
.worktree
= worktree
;
3260 arg
.fileindex
= fileindex
;
3261 arg
.progress_cb
= progress_cb
;
3262 arg
.progress_arg
= progress_arg
;
3263 arg
.cancel_cb
= cancel_cb
;
3264 arg
.cancel_arg
= cancel_arg
;
3265 arg
.label_orig
= label_orig
;
3266 arg
.commit_id2
= commit_id2
;
3267 err
= got_diff_tree(tree1
, tree2
, "", "", repo
, merge_file_cb
, &arg
, 1);
3268 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
3269 if (sync_err
&& err
== NULL
)
3273 got_object_tree_close(tree1
);
3275 got_object_tree_close(tree2
);
3280 const struct got_error
*
3281 got_worktree_merge_files(struct got_worktree
*worktree
,
3282 struct got_object_id
*commit_id1
, struct got_object_id
*commit_id2
,
3283 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
3284 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
3286 const struct got_error
*err
, *unlockerr
;
3287 char *fileindex_path
= NULL
;
3288 struct got_fileindex
*fileindex
= NULL
;
3290 err
= lock_worktree(worktree
, LOCK_EX
);
3294 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3298 err
= got_fileindex_for_each_entry_safe(fileindex
, check_mixed_commits
,
3303 err
= merge_files(worktree
, fileindex
, fileindex_path
, commit_id1
,
3304 commit_id2
, repo
, progress_cb
, progress_arg
,
3305 cancel_cb
, cancel_arg
);
3308 got_fileindex_free(fileindex
);
3309 free(fileindex_path
);
3310 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
3311 if (unlockerr
&& err
== NULL
)
3316 struct diff_dir_cb_arg
{
3317 struct got_fileindex
*fileindex
;
3318 struct got_worktree
*worktree
;
3319 const char *status_path
;
3320 size_t status_path_len
;
3321 struct got_repository
*repo
;
3322 got_worktree_status_cb status_cb
;
3324 got_cancel_cb cancel_cb
;
3326 /* A pathlist containing per-directory pathlists of ignore patterns. */
3327 struct got_pathlist_head
*ignores
;
3328 int report_unchanged
;
3332 static const struct got_error
*
3333 report_file_status(struct got_fileindex_entry
*ie
, const char *abspath
,
3334 int dirfd
, const char *de_name
,
3335 got_worktree_status_cb status_cb
, void *status_arg
,
3336 struct got_repository
*repo
, int report_unchanged
)
3338 const struct got_error
*err
= NULL
;
3339 unsigned char status
= GOT_STATUS_NO_CHANGE
;
3340 unsigned char staged_status
= get_staged_status(ie
);
3342 struct got_object_id blob_id
, commit_id
, staged_blob_id
;
3343 struct got_object_id
*blob_idp
= NULL
, *commit_idp
= NULL
;
3344 struct got_object_id
*staged_blob_idp
= NULL
;
3346 err
= get_file_status(&status
, &sb
, ie
, abspath
, dirfd
, de_name
, repo
);
3350 if (status
== GOT_STATUS_NO_CHANGE
&&
3351 staged_status
== GOT_STATUS_NO_CHANGE
&& !report_unchanged
)
3354 if (got_fileindex_entry_has_blob(ie
)) {
3355 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3356 blob_idp
= &blob_id
;
3358 if (got_fileindex_entry_has_commit(ie
)) {
3359 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3360 commit_idp
= &commit_id
;
3362 if (staged_status
== GOT_STATUS_ADD
||
3363 staged_status
== GOT_STATUS_MODIFY
) {
3364 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
3365 SHA1_DIGEST_LENGTH
);
3366 staged_blob_idp
= &staged_blob_id
;
3369 return (*status_cb
)(status_arg
, status
, staged_status
,
3370 ie
->path
, blob_idp
, staged_blob_idp
, commit_idp
, dirfd
, de_name
);
3373 static const struct got_error
*
3374 status_old_new(void *arg
, struct got_fileindex_entry
*ie
,
3375 struct dirent
*de
, const char *parent_path
, int dirfd
)
3377 const struct got_error
*err
= NULL
;
3378 struct diff_dir_cb_arg
*a
= arg
;
3381 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3382 return got_error(GOT_ERR_CANCELLED
);
3384 if (got_path_cmp(parent_path
, a
->status_path
,
3385 strlen(parent_path
), a
->status_path_len
) != 0 &&
3386 !got_path_is_child(parent_path
, a
->status_path
, a
->status_path_len
))
3389 if (parent_path
[0]) {
3390 if (asprintf(&abspath
, "%s/%s/%s", a
->worktree
->root_path
,
3391 parent_path
, de
->d_name
) == -1)
3392 return got_error_from_errno("asprintf");
3394 if (asprintf(&abspath
, "%s/%s", a
->worktree
->root_path
,
3396 return got_error_from_errno("asprintf");
3399 err
= report_file_status(ie
, abspath
, dirfd
, de
->d_name
,
3400 a
->status_cb
, a
->status_arg
, a
->repo
, a
->report_unchanged
);
3405 static const struct got_error
*
3406 status_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
3408 struct diff_dir_cb_arg
*a
= arg
;
3409 struct got_object_id blob_id
, commit_id
;
3410 unsigned char status
;
3412 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3413 return got_error(GOT_ERR_CANCELLED
);
3415 if (!got_path_is_child(ie
->path
, a
->status_path
, a
->status_path_len
))
3418 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3419 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3420 if (got_fileindex_entry_has_file_on_disk(ie
))
3421 status
= GOT_STATUS_MISSING
;
3423 status
= GOT_STATUS_DELETE
;
3424 return (*a
->status_cb
)(a
->status_arg
, status
, get_staged_status(ie
),
3425 ie
->path
, &blob_id
, NULL
, &commit_id
, -1, NULL
);
3429 free_ignorelist(struct got_pathlist_head
*ignorelist
)
3431 struct got_pathlist_entry
*pe
;
3433 TAILQ_FOREACH(pe
, ignorelist
, entry
)
3434 free((char *)pe
->path
);
3435 got_pathlist_free(ignorelist
);
3439 free_ignores(struct got_pathlist_head
*ignores
)
3441 struct got_pathlist_entry
*pe
;
3443 TAILQ_FOREACH(pe
, ignores
, entry
) {
3444 struct got_pathlist_head
*ignorelist
= pe
->data
;
3445 free_ignorelist(ignorelist
);
3446 free((char *)pe
->path
);
3448 got_pathlist_free(ignores
);
3451 static const struct got_error
*
3452 read_ignores(struct got_pathlist_head
*ignores
, const char *path
, FILE *f
)
3454 const struct got_error
*err
= NULL
;
3455 struct got_pathlist_entry
*pe
= NULL
;
3456 struct got_pathlist_head
*ignorelist
;
3457 char *line
= NULL
, *pattern
, *dirpath
= NULL
;
3458 size_t linesize
= 0;
3461 ignorelist
= calloc(1, sizeof(*ignorelist
));
3462 if (ignorelist
== NULL
)
3463 return got_error_from_errno("calloc");
3464 TAILQ_INIT(ignorelist
);
3466 while ((linelen
= getline(&line
, &linesize
, f
)) != -1) {
3467 if (linelen
> 0 && line
[linelen
- 1] == '\n')
3468 line
[linelen
- 1] = '\0';
3470 /* Git's ignores may contain comments. */
3474 /* Git's negated patterns are not (yet?) supported. */
3478 if (asprintf(&pattern
, "%s%s%s", path
, path
[0] ? "/" : "",
3480 err
= got_error_from_errno("asprintf");
3483 err
= got_pathlist_insert(NULL
, ignorelist
, pattern
, NULL
);
3488 err
= got_error_from_errno("getline");
3492 dirpath
= strdup(path
);
3493 if (dirpath
== NULL
) {
3494 err
= got_error_from_errno("strdup");
3497 err
= got_pathlist_insert(&pe
, ignores
, dirpath
, ignorelist
);
3500 if (err
|| pe
== NULL
) {
3502 free_ignorelist(ignorelist
);
3508 match_ignores(struct got_pathlist_head
*ignores
, const char *path
)
3510 struct got_pathlist_entry
*pe
;
3512 /* Handle patterns which match in all directories. */
3513 TAILQ_FOREACH(pe
, ignores
, entry
) {
3514 struct got_pathlist_head
*ignorelist
= pe
->data
;
3515 struct got_pathlist_entry
*pi
;
3517 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3518 const char *p
, *pattern
= pi
->path
;
3520 if (strncmp(pattern
, "**/", 3) != 0)
3525 if (fnmatch(pattern
, p
,
3526 FNM_PATHNAME
| FNM_LEADING_DIR
)) {
3527 /* Retry in next directory. */
3528 while (*p
&& *p
!= '/')
3540 * The ignores pathlist contains ignore lists from children before
3541 * parents, so we can find the most specific ignorelist by walking
3542 * ignores backwards.
3544 pe
= TAILQ_LAST(ignores
, got_pathlist_head
);
3546 if (got_path_is_child(path
, pe
->path
, pe
->path_len
)) {
3547 struct got_pathlist_head
*ignorelist
= pe
->data
;
3548 struct got_pathlist_entry
*pi
;
3549 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3550 const char *pattern
= pi
->path
;
3551 int flags
= FNM_LEADING_DIR
;
3552 if (strstr(pattern
, "/**/") == NULL
)
3553 flags
|= FNM_PATHNAME
;
3554 if (fnmatch(pattern
, path
, flags
))
3559 pe
= TAILQ_PREV(pe
, got_pathlist_head
, entry
);
3565 static const struct got_error
*
3566 add_ignores(struct got_pathlist_head
*ignores
, const char *root_path
,
3567 const char *path
, int dirfd
, const char *ignores_filename
)
3569 const struct got_error
*err
= NULL
;
3572 FILE *ignoresfile
= NULL
;
3574 if (asprintf(&ignorespath
, "%s/%s%s%s", root_path
, path
,
3575 path
[0] ? "/" : "", ignores_filename
) == -1)
3576 return got_error_from_errno("asprintf");
3579 fd
= openat(dirfd
, ignores_filename
, O_RDONLY
| O_NOFOLLOW
);
3581 if (errno
!= ENOENT
&& errno
!= EACCES
)
3582 err
= got_error_from_errno2("openat",
3585 ignoresfile
= fdopen(fd
, "r");
3586 if (ignoresfile
== NULL
)
3587 err
= got_error_from_errno2("fdopen",
3591 err
= read_ignores(ignores
, path
, ignoresfile
);
3595 ignoresfile
= fopen(ignorespath
, "r");
3596 if (ignoresfile
== NULL
) {
3597 if (errno
!= ENOENT
&& errno
!= EACCES
)
3598 err
= got_error_from_errno2("fopen",
3601 err
= read_ignores(ignores
, path
, ignoresfile
);
3604 if (ignoresfile
&& fclose(ignoresfile
) == EOF
&& err
== NULL
)
3605 err
= got_error_from_errno2("fclose", path
);
3606 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3607 err
= got_error_from_errno2("close", path
);
3612 static const struct got_error
*
3613 status_new(void *arg
, struct dirent
*de
, const char *parent_path
, int dirfd
)
3615 const struct got_error
*err
= NULL
;
3616 struct diff_dir_cb_arg
*a
= arg
;
3619 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3620 return got_error(GOT_ERR_CANCELLED
);
3622 if (parent_path
[0]) {
3623 if (asprintf(&path
, "%s/%s", parent_path
, de
->d_name
) == -1)
3624 return got_error_from_errno("asprintf");
3629 if (de
->d_type
!= DT_DIR
&&
3630 got_path_is_child(path
, a
->status_path
, a
->status_path_len
)
3631 && !match_ignores(a
->ignores
, path
))
3632 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_UNVERSIONED
,
3633 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3639 static const struct got_error
*
3640 status_traverse(void *arg
, const char *path
, int dirfd
)
3642 const struct got_error
*err
= NULL
;
3643 struct diff_dir_cb_arg
*a
= arg
;
3648 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
,
3649 path
, dirfd
, ".cvsignore");
3653 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
, path
,
3654 dirfd
, ".gitignore");
3659 static const struct got_error
*
3660 report_single_file_status(const char *path
, const char *ondisk_path
,
3661 struct got_fileindex
*fileindex
, got_worktree_status_cb status_cb
,
3662 void *status_arg
, struct got_repository
*repo
, int report_unchanged
,
3663 struct got_pathlist_head
*ignores
, int no_ignores
)
3665 struct got_fileindex_entry
*ie
;
3668 if (!no_ignores
&& match_ignores(ignores
, path
))
3671 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
3673 return report_file_status(ie
, ondisk_path
, -1, NULL
,
3674 status_cb
, status_arg
, repo
, report_unchanged
);
3676 if (lstat(ondisk_path
, &sb
) == -1) {
3677 if (errno
!= ENOENT
)
3678 return got_error_from_errno2("lstat", ondisk_path
);
3679 return (*status_cb
)(status_arg
, GOT_STATUS_NONEXISTENT
,
3680 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3684 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
3685 return (*status_cb
)(status_arg
, GOT_STATUS_UNVERSIONED
,
3686 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3691 static const struct got_error
*
3692 add_ignores_from_parent_paths(struct got_pathlist_head
*ignores
,
3693 const char *root_path
, const char *path
)
3695 const struct got_error
*err
;
3696 char *parent_path
, *next_parent_path
= NULL
;
3698 err
= add_ignores(ignores
, root_path
, "", -1,
3703 err
= add_ignores(ignores
, root_path
, "", -1,
3708 err
= got_path_dirname(&parent_path
, path
);
3710 if (err
->code
== GOT_ERR_BAD_PATH
)
3711 return NULL
; /* cannot traverse parent */
3715 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3719 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3723 err
= got_path_dirname(&next_parent_path
, parent_path
);
3725 if (err
->code
== GOT_ERR_BAD_PATH
)
3726 err
= NULL
; /* traversed everything */
3729 if (got_path_is_root_dir(parent_path
))
3732 parent_path
= next_parent_path
;
3733 next_parent_path
= NULL
;
3737 free(next_parent_path
);
3741 static const struct got_error
*
3742 worktree_status(struct got_worktree
*worktree
, const char *path
,
3743 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
3744 got_worktree_status_cb status_cb
, void *status_arg
,
3745 got_cancel_cb cancel_cb
, void *cancel_arg
, int no_ignores
,
3746 int report_unchanged
)
3748 const struct got_error
*err
= NULL
;
3750 struct got_fileindex_diff_dir_cb fdiff_cb
;
3751 struct diff_dir_cb_arg arg
;
3752 char *ondisk_path
= NULL
;
3753 struct got_pathlist_head ignores
;
3755 TAILQ_INIT(&ignores
);
3757 if (asprintf(&ondisk_path
, "%s%s%s",
3758 worktree
->root_path
, path
[0] ? "/" : "", path
) == -1)
3759 return got_error_from_errno("asprintf");
3761 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_DIRECTORY
);
3763 if (errno
!= ENOTDIR
&& errno
!= ENOENT
&& errno
!= EACCES
&&
3765 err
= got_error_from_errno2("open", ondisk_path
);
3768 err
= add_ignores_from_parent_paths(&ignores
,
3769 worktree
->root_path
, ondisk_path
);
3773 err
= report_single_file_status(path
, ondisk_path
,
3774 fileindex
, status_cb
, status_arg
, repo
,
3775 report_unchanged
, &ignores
, no_ignores
);
3778 fdiff_cb
.diff_old_new
= status_old_new
;
3779 fdiff_cb
.diff_old
= status_old
;
3780 fdiff_cb
.diff_new
= status_new
;
3781 fdiff_cb
.diff_traverse
= status_traverse
;
3782 arg
.fileindex
= fileindex
;
3783 arg
.worktree
= worktree
;
3784 arg
.status_path
= path
;
3785 arg
.status_path_len
= strlen(path
);
3787 arg
.status_cb
= status_cb
;
3788 arg
.status_arg
= status_arg
;
3789 arg
.cancel_cb
= cancel_cb
;
3790 arg
.cancel_arg
= cancel_arg
;
3791 arg
.report_unchanged
= report_unchanged
;
3792 arg
.no_ignores
= no_ignores
;
3794 err
= add_ignores_from_parent_paths(&ignores
,
3795 worktree
->root_path
, path
);
3799 arg
.ignores
= &ignores
;
3800 err
= got_fileindex_diff_dir(fileindex
, fd
,
3801 worktree
->root_path
, path
, repo
, &fdiff_cb
, &arg
);
3804 free_ignores(&ignores
);
3805 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3806 err
= got_error_from_errno("close");
3811 const struct got_error
*
3812 got_worktree_status(struct got_worktree
*worktree
,
3813 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
3814 int no_ignores
, got_worktree_status_cb status_cb
, void *status_arg
,
3815 got_cancel_cb cancel_cb
, void *cancel_arg
)
3817 const struct got_error
*err
= NULL
;
3818 char *fileindex_path
= NULL
;
3819 struct got_fileindex
*fileindex
= NULL
;
3820 struct got_pathlist_entry
*pe
;
3822 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3826 TAILQ_FOREACH(pe
, paths
, entry
) {
3827 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
3828 status_cb
, status_arg
, cancel_cb
, cancel_arg
,
3833 free(fileindex_path
);
3834 got_fileindex_free(fileindex
);
3838 const struct got_error
*
3839 got_worktree_resolve_path(char **wt_path
, struct got_worktree
*worktree
,
3842 const struct got_error
*err
= NULL
;
3843 char *resolved
= NULL
, *cwd
= NULL
, *path
= NULL
;
3846 char *abspath
= NULL
;
3847 char canonpath
[PATH_MAX
];
3851 cwd
= getcwd(NULL
, 0);
3853 return got_error_from_errno("getcwd");
3855 if (lstat(arg
, &sb
) == -1) {
3856 if (errno
!= ENOENT
) {
3857 err
= got_error_from_errno2("lstat", arg
);
3862 if (S_ISLNK(sb
.st_mode
)) {
3864 * We cannot use realpath(3) with symlinks since we want to
3865 * operate on the symlink itself.
3866 * But we can make the path absolute, assuming it is relative
3867 * to the current working directory, and then canonicalize it.
3869 if (!got_path_is_absolute(arg
)) {
3870 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3871 err
= got_error_from_errno("asprintf");
3876 err
= got_canonpath(abspath
? abspath
: arg
, canonpath
,
3880 resolved
= strdup(canonpath
);
3881 if (resolved
== NULL
) {
3882 err
= got_error_from_errno("strdup");
3886 resolved
= realpath(arg
, NULL
);
3887 if (resolved
== NULL
) {
3888 if (errno
!= ENOENT
) {
3889 err
= got_error_from_errno2("realpath", arg
);
3892 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3893 err
= got_error_from_errno("asprintf");
3896 err
= got_canonpath(abspath
, canonpath
,
3900 resolved
= strdup(canonpath
);
3901 if (resolved
== NULL
) {
3902 err
= got_error_from_errno("strdup");
3908 if (strncmp(got_worktree_get_root_path(worktree
), resolved
,
3909 strlen(got_worktree_get_root_path(worktree
)))) {
3910 err
= got_error_path(resolved
, GOT_ERR_BAD_PATH
);
3914 if (strlen(resolved
) > strlen(got_worktree_get_root_path(worktree
))) {
3915 err
= got_path_skip_common_ancestor(&path
,
3916 got_worktree_get_root_path(worktree
), resolved
);
3922 err
= got_error_from_errno("strdup");
3927 /* XXX status walk can't deal with trailing slash! */
3929 while (len
> 0 && path
[len
- 1] == '/') {
3930 path
[len
- 1] = '\0';
3944 struct schedule_addition_args
{
3945 struct got_worktree
*worktree
;
3946 struct got_fileindex
*fileindex
;
3947 got_worktree_checkout_cb progress_cb
;
3949 struct got_repository
*repo
;
3952 static const struct got_error
*
3953 schedule_addition(void *arg
, unsigned char status
, unsigned char staged_status
,
3954 const char *relpath
, struct got_object_id
*blob_id
,
3955 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
3956 int dirfd
, const char *de_name
)
3958 struct schedule_addition_args
*a
= arg
;
3959 const struct got_error
*err
= NULL
;
3960 struct got_fileindex_entry
*ie
;
3964 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3966 return got_error_from_errno("asprintf");
3968 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
3970 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
,
3974 /* Re-adding an existing entry is a no-op. */
3975 if (status
== GOT_STATUS_ADD
)
3977 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
3982 if (status
!= GOT_STATUS_UNVERSIONED
) {
3983 err
= got_error_path(ondisk_path
, GOT_ERR_FILE_STATUS
);
3987 err
= got_fileindex_entry_alloc(&ie
, relpath
);
3990 err
= got_fileindex_entry_update(ie
, a
->worktree
->root_fd
,
3991 relpath
, NULL
, NULL
, 1);
3993 got_fileindex_entry_free(ie
);
3996 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
3998 got_fileindex_entry_free(ie
);
4005 if (status
== GOT_STATUS_ADD
)
4007 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_ADD
, relpath
);
4010 const struct got_error
*
4011 got_worktree_schedule_add(struct got_worktree
*worktree
,
4012 struct got_pathlist_head
*paths
,
4013 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4014 struct got_repository
*repo
, int no_ignores
)
4016 struct got_fileindex
*fileindex
= NULL
;
4017 char *fileindex_path
= NULL
;
4018 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4019 struct got_pathlist_entry
*pe
;
4020 struct schedule_addition_args saa
;
4022 err
= lock_worktree(worktree
, LOCK_EX
);
4026 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4030 saa
.worktree
= worktree
;
4031 saa
.fileindex
= fileindex
;
4032 saa
.progress_cb
= progress_cb
;
4033 saa
.progress_arg
= progress_arg
;
4036 TAILQ_FOREACH(pe
, paths
, entry
) {
4037 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4038 schedule_addition
, &saa
, NULL
, NULL
, no_ignores
, 0);
4042 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4043 if (sync_err
&& err
== NULL
)
4046 free(fileindex_path
);
4048 got_fileindex_free(fileindex
);
4049 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4050 if (unlockerr
&& err
== NULL
)
4055 struct schedule_deletion_args
{
4056 struct got_worktree
*worktree
;
4057 struct got_fileindex
*fileindex
;
4058 got_worktree_delete_cb progress_cb
;
4060 struct got_repository
*repo
;
4061 int delete_local_mods
;
4063 const char *status_codes
;
4066 static const struct got_error
*
4067 schedule_for_deletion(void *arg
, unsigned char status
,
4068 unsigned char staged_status
, const char *relpath
,
4069 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4070 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4072 struct schedule_deletion_args
*a
= arg
;
4073 const struct got_error
*err
= NULL
;
4074 struct got_fileindex_entry
*ie
= NULL
;
4078 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4080 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
4082 staged_status
= get_staged_status(ie
);
4083 if (staged_status
!= GOT_STATUS_NO_CHANGE
) {
4084 if (staged_status
== GOT_STATUS_DELETE
)
4086 return got_error_path(relpath
, GOT_ERR_FILE_STAGED
);
4089 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4091 return got_error_from_errno("asprintf");
4093 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
, de_name
,
4098 if (a
->status_codes
) {
4099 size_t ncodes
= strlen(a
->status_codes
);
4101 for (i
= 0; i
< ncodes
; i
++) {
4102 if (status
== a
->status_codes
[i
])
4106 /* Do not delete files in non-matching status. */
4110 if (a
->status_codes
[i
] != GOT_STATUS_MODIFY
&&
4111 a
->status_codes
[i
] != GOT_STATUS_MISSING
) {
4112 static char msg
[64];
4113 snprintf(msg
, sizeof(msg
),
4114 "invalid status code '%c'", a
->status_codes
[i
]);
4115 err
= got_error_msg(GOT_ERR_FILE_STATUS
, msg
);
4120 if (status
!= GOT_STATUS_NO_CHANGE
) {
4121 if (status
== GOT_STATUS_DELETE
)
4123 if (status
== GOT_STATUS_MODIFY
&& !a
->delete_local_mods
) {
4124 err
= got_error_path(relpath
, GOT_ERR_FILE_MODIFIED
);
4127 if (status
!= GOT_STATUS_MODIFY
&&
4128 status
!= GOT_STATUS_MISSING
) {
4129 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4134 if (!a
->keep_on_disk
&& status
!= GOT_STATUS_MISSING
) {
4138 if (unlinkat(dirfd
, de_name
, 0) != 0) {
4139 err
= got_error_from_errno2("unlinkat",
4143 } else if (unlink(ondisk_path
) != 0) {
4144 err
= got_error_from_errno2("unlink", ondisk_path
);
4148 root_len
= strlen(a
->worktree
->root_path
);
4151 err
= got_path_dirname(&parent
, ondisk_path
);
4155 ondisk_path
= parent
;
4156 if (rmdir(ondisk_path
) == -1) {
4157 if (errno
!= ENOTEMPTY
)
4158 err
= got_error_from_errno2("rmdir",
4162 } while (got_path_cmp(ondisk_path
, a
->worktree
->root_path
,
4163 strlen(ondisk_path
), root_len
) != 0);
4166 got_fileindex_entry_mark_deleted_from_disk(ie
);
4171 if (status
== GOT_STATUS_DELETE
)
4173 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_DELETE
,
4174 staged_status
, relpath
);
4177 const struct got_error
*
4178 got_worktree_schedule_delete(struct got_worktree
*worktree
,
4179 struct got_pathlist_head
*paths
, int delete_local_mods
,
4180 const char *status_codes
,
4181 got_worktree_delete_cb progress_cb
, void *progress_arg
,
4182 struct got_repository
*repo
, int keep_on_disk
)
4184 struct got_fileindex
*fileindex
= NULL
;
4185 char *fileindex_path
= NULL
;
4186 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4187 struct got_pathlist_entry
*pe
;
4188 struct schedule_deletion_args sda
;
4190 err
= lock_worktree(worktree
, LOCK_EX
);
4194 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4198 sda
.worktree
= worktree
;
4199 sda
.fileindex
= fileindex
;
4200 sda
.progress_cb
= progress_cb
;
4201 sda
.progress_arg
= progress_arg
;
4203 sda
.delete_local_mods
= delete_local_mods
;
4204 sda
.keep_on_disk
= keep_on_disk
;
4205 sda
.status_codes
= status_codes
;
4207 TAILQ_FOREACH(pe
, paths
, entry
) {
4208 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4209 schedule_for_deletion
, &sda
, NULL
, NULL
, 0, 1);
4213 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4214 if (sync_err
&& err
== NULL
)
4217 free(fileindex_path
);
4219 got_fileindex_free(fileindex
);
4220 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4221 if (unlockerr
&& err
== NULL
)
4226 static const struct got_error
*
4227 copy_one_line(FILE *infile
, FILE *outfile
, FILE *rejectfile
)
4229 const struct got_error
*err
= NULL
;
4231 size_t linesize
= 0, n
;
4234 linelen
= getline(&line
, &linesize
, infile
);
4235 if (linelen
== -1) {
4236 if (ferror(infile
)) {
4237 err
= got_error_from_errno("getline");
4243 n
= fwrite(line
, 1, linelen
, outfile
);
4245 err
= got_ferror(outfile
, GOT_ERR_IO
);
4250 n
= fwrite(line
, 1, linelen
, rejectfile
);
4252 err
= got_ferror(outfile
, GOT_ERR_IO
);
4259 static const struct got_error
*
4260 skip_one_line(FILE *f
)
4263 size_t linesize
= 0;
4266 linelen
= getline(&line
, &linesize
, f
);
4267 if (linelen
== -1) {
4269 return got_error_from_errno("getline");
4276 static const struct got_error
*
4277 copy_change(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4278 int start_old
, int end_old
, int start_new
, int end_new
,
4279 FILE *outfile
, FILE *rejectfile
)
4281 const struct got_error
*err
;
4283 /* Copy old file's lines leading up to patch. */
4284 while (!feof(f1
) && *line_cur1
< start_old
) {
4285 err
= copy_one_line(f1
, outfile
, NULL
);
4290 /* Skip new file's lines leading up to patch. */
4291 while (!feof(f2
) && *line_cur2
< start_new
) {
4293 err
= copy_one_line(f2
, NULL
, rejectfile
);
4295 err
= skip_one_line(f2
);
4300 /* Copy patched lines. */
4301 while (!feof(f2
) && *line_cur2
<= end_new
) {
4302 err
= copy_one_line(f2
, outfile
, NULL
);
4307 /* Skip over old file's replaced lines. */
4308 while (!feof(f1
) && *line_cur1
<= end_old
) {
4310 err
= copy_one_line(f1
, NULL
, rejectfile
);
4312 err
= skip_one_line(f1
);
4321 static const struct got_error
*
4322 copy_remaining_content(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4323 FILE *outfile
, FILE *rejectfile
)
4325 const struct got_error
*err
;
4328 /* Copy old file's lines until EOF. */
4330 err
= copy_one_line(f1
, outfile
, NULL
);
4337 /* Copy new file's lines until EOF. */
4339 err
= copy_one_line(f2
, NULL
, rejectfile
);
4349 static const struct got_error
*
4350 apply_or_reject_change(int *choice
, int *nchunks_used
,
4351 struct diff_result
*diff_result
, int n
,
4352 const char *relpath
, FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4353 FILE *outfile
, FILE *rejectfile
, int changeno
, int nchanges
,
4354 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4356 const struct got_error
*err
= NULL
;
4357 struct diff_chunk_context cc
= {};
4358 int start_old
, end_old
, start_new
, end_new
;
4360 struct diff_output_unidiff_state
*diff_state
;
4361 struct diff_input_info diff_info
;
4364 *choice
= GOT_PATCH_CHOICE_NONE
;
4366 /* Get changed line numbers without context lines for copy_change(). */
4367 diff_chunk_context_load_change(&cc
, NULL
, diff_result
, n
, 0);
4368 start_old
= cc
.left
.start
;
4369 end_old
= cc
.left
.end
;
4370 start_new
= cc
.right
.start
;
4371 end_new
= cc
.right
.end
;
4373 /* Get the same change with context lines for display. */
4374 memset(&cc
, 0, sizeof(cc
));
4375 diff_chunk_context_load_change(&cc
, nchunks_used
, diff_result
, n
, 3);
4377 memset(&diff_info
, 0, sizeof(diff_info
));
4378 diff_info
.left_path
= relpath
;
4379 diff_info
.right_path
= relpath
;
4381 diff_state
= diff_output_unidiff_state_alloc();
4382 if (diff_state
== NULL
)
4383 return got_error_set_errno(ENOMEM
,
4384 "diff_output_unidiff_state_alloc");
4386 hunkfile
= got_opentemp();
4387 if (hunkfile
== NULL
) {
4388 err
= got_error_from_errno("got_opentemp");
4392 rc
= diff_output_unidiff_chunk(NULL
, hunkfile
, diff_state
, &diff_info
,
4394 if (rc
!= DIFF_RC_OK
) {
4395 err
= got_error_set_errno(rc
, "diff_output_unidiff_chunk");
4399 if (fseek(hunkfile
, 0L, SEEK_SET
) == -1) {
4400 err
= got_ferror(hunkfile
, GOT_ERR_IO
);
4404 err
= (*patch_cb
)(choice
, patch_arg
, GOT_STATUS_MODIFY
, relpath
,
4405 hunkfile
, changeno
, nchanges
);
4410 case GOT_PATCH_CHOICE_YES
:
4411 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4412 end_old
, start_new
, end_new
, outfile
, rejectfile
);
4414 case GOT_PATCH_CHOICE_NO
:
4415 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4416 end_old
, start_new
, end_new
, rejectfile
, outfile
);
4418 case GOT_PATCH_CHOICE_QUIT
:
4421 err
= got_error(GOT_ERR_PATCH_CHOICE
);
4425 diff_output_unidiff_state_free(diff_state
);
4426 if (hunkfile
&& fclose(hunkfile
) == EOF
&& err
== NULL
)
4427 err
= got_error_from_errno("fclose");
4431 struct revert_file_args
{
4432 struct got_worktree
*worktree
;
4433 struct got_fileindex
*fileindex
;
4434 got_worktree_checkout_cb progress_cb
;
4436 got_worktree_patch_cb patch_cb
;
4438 struct got_repository
*repo
;
4439 int unlink_added_files
;
4442 static const struct got_error
*
4443 create_patched_content(char **path_outfile
, int reverse_patch
,
4444 struct got_object_id
*blob_id
, const char *path2
,
4445 int dirfd2
, const char *de_name2
,
4446 const char *relpath
, struct got_repository
*repo
,
4447 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4449 const struct got_error
*err
, *free_err
;
4450 struct got_blob_object
*blob
= NULL
;
4451 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
;
4453 char link_target
[PATH_MAX
];
4454 ssize_t link_len
= 0;
4455 char *path1
= NULL
, *id_str
= NULL
;
4457 struct got_diffreg_result
*diffreg_result
= NULL
;
4458 int line_cur1
= 1, line_cur2
= 1, have_content
= 0;
4459 int i
= 0, n
= 0, nchunks_used
= 0, nchanges
= 0;
4461 *path_outfile
= NULL
;
4463 err
= got_object_id_str(&id_str
, blob_id
);
4468 fd2
= openat(dirfd2
, de_name2
, O_RDONLY
| O_NOFOLLOW
);
4470 if (errno
!= ELOOP
) {
4471 err
= got_error_from_errno2("openat", path2
);
4474 link_len
= readlinkat(dirfd2
, de_name2
,
4475 link_target
, sizeof(link_target
));
4477 return got_error_from_errno2("readlinkat", path2
);
4478 sb2
.st_mode
= S_IFLNK
;
4479 sb2
.st_size
= link_len
;
4482 fd2
= open(path2
, O_RDONLY
| O_NOFOLLOW
);
4484 if (errno
!= ELOOP
) {
4485 err
= got_error_from_errno2("open", path2
);
4488 link_len
= readlink(path2
, link_target
,
4489 sizeof(link_target
));
4491 return got_error_from_errno2("readlink", path2
);
4492 sb2
.st_mode
= S_IFLNK
;
4493 sb2
.st_size
= link_len
;
4497 if (fstat(fd2
, &sb2
) == -1) {
4498 err
= got_error_from_errno2("fstat", path2
);
4502 f2
= fdopen(fd2
, "r");
4504 err
= got_error_from_errno2("fdopen", path2
);
4510 f2
= got_opentemp();
4512 err
= got_error_from_errno2("got_opentemp", path2
);
4515 n
= fwrite(link_target
, 1, link_len
, f2
);
4516 if (n
!= link_len
) {
4517 err
= got_ferror(f2
, GOT_ERR_IO
);
4520 if (fflush(f2
) == EOF
) {
4521 err
= got_error_from_errno("fflush");
4527 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192);
4531 err
= got_opentemp_named(&path1
, &f1
, "got-patched-blob");
4535 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
4539 err
= got_diff_files(&diffreg_result
, f1
, id_str
, f2
, path2
, 3, 0, 1,
4544 err
= got_opentemp_named(path_outfile
, &outfile
, "got-patched-content");
4548 if (fseek(f1
, 0L, SEEK_SET
) == -1)
4549 return got_ferror(f1
, GOT_ERR_IO
);
4550 if (fseek(f2
, 0L, SEEK_SET
) == -1)
4551 return got_ferror(f2
, GOT_ERR_IO
);
4553 /* Count the number of actual changes in the diff result. */
4554 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4555 struct diff_chunk_context cc
= {};
4556 diff_chunk_context_load_change(&cc
, &nchunks_used
,
4557 diffreg_result
->result
, n
, 0);
4560 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4562 err
= apply_or_reject_change(&choice
, &nchunks_used
,
4563 diffreg_result
->result
, n
, relpath
, f1
, f2
,
4564 &line_cur1
, &line_cur2
,
4565 reverse_patch
? NULL
: outfile
,
4566 reverse_patch
? outfile
: NULL
,
4567 ++i
, nchanges
, patch_cb
, patch_arg
);
4570 if (choice
== GOT_PATCH_CHOICE_YES
)
4572 else if (choice
== GOT_PATCH_CHOICE_QUIT
)
4576 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
4577 reverse_patch
? NULL
: outfile
,
4578 reverse_patch
? outfile
: NULL
);
4582 if (!S_ISLNK(sb2
.st_mode
)) {
4583 if (fchmod(fileno(outfile
), sb2
.st_mode
) == -1) {
4584 err
= got_error_from_errno2("fchmod", path2
);
4592 got_object_blob_close(blob
);
4593 free_err
= got_diffreg_result_free(diffreg_result
);
4596 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
4597 err
= got_error_from_errno2("fclose", path1
);
4598 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
4599 err
= got_error_from_errno2("fclose", path2
);
4600 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
4601 err
= got_error_from_errno2("close", path2
);
4602 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
4603 err
= got_error_from_errno2("fclose", *path_outfile
);
4604 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
4605 err
= got_error_from_errno2("unlink", path1
);
4606 if (err
|| !have_content
) {
4607 if (*path_outfile
&& unlink(*path_outfile
) == -1 && err
== NULL
)
4608 err
= got_error_from_errno2("unlink", *path_outfile
);
4609 free(*path_outfile
);
4610 *path_outfile
= NULL
;
4616 static const struct got_error
*
4617 revert_file(void *arg
, unsigned char status
, unsigned char staged_status
,
4618 const char *relpath
, struct got_object_id
*blob_id
,
4619 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
4620 int dirfd
, const char *de_name
)
4622 struct revert_file_args
*a
= arg
;
4623 const struct got_error
*err
= NULL
;
4624 char *parent_path
= NULL
;
4625 struct got_fileindex_entry
*ie
;
4626 struct got_tree_object
*tree
= NULL
;
4627 struct got_object_id
*tree_id
= NULL
;
4628 const struct got_tree_entry
*te
= NULL
;
4629 char *tree_path
= NULL
, *te_name
;
4630 char *ondisk_path
= NULL
, *path_content
= NULL
;
4631 struct got_blob_object
*blob
= NULL
;
4633 /* Reverting a staged deletion is a no-op. */
4634 if (status
== GOT_STATUS_DELETE
&&
4635 staged_status
!= GOT_STATUS_NO_CHANGE
)
4638 if (status
== GOT_STATUS_UNVERSIONED
)
4639 return (*a
->progress_cb
)(a
->progress_arg
,
4640 GOT_STATUS_UNVERSIONED
, relpath
);
4642 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4644 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
4646 /* Construct in-repository path of tree which contains this blob. */
4647 err
= got_path_dirname(&parent_path
, ie
->path
);
4649 if (err
->code
!= GOT_ERR_BAD_PATH
)
4651 parent_path
= strdup("/");
4652 if (parent_path
== NULL
) {
4653 err
= got_error_from_errno("strdup");
4657 if (got_path_is_root_dir(a
->worktree
->path_prefix
)) {
4658 tree_path
= strdup(parent_path
);
4659 if (tree_path
== NULL
) {
4660 err
= got_error_from_errno("strdup");
4664 if (got_path_is_root_dir(parent_path
)) {
4665 tree_path
= strdup(a
->worktree
->path_prefix
);
4666 if (tree_path
== NULL
) {
4667 err
= got_error_from_errno("strdup");
4671 if (asprintf(&tree_path
, "%s/%s",
4672 a
->worktree
->path_prefix
, parent_path
) == -1) {
4673 err
= got_error_from_errno("asprintf");
4679 err
= got_object_id_by_path(&tree_id
, a
->repo
,
4680 a
->worktree
->base_commit_id
, tree_path
);
4682 if (!(err
->code
== GOT_ERR_NO_TREE_ENTRY
&&
4683 (status
== GOT_STATUS_ADD
||
4684 staged_status
== GOT_STATUS_ADD
)))
4687 err
= got_object_open_as_tree(&tree
, a
->repo
, tree_id
);
4691 err
= got_path_basename(&te_name
, ie
->path
);
4695 te
= got_object_tree_find_entry(tree
, te_name
);
4697 if (te
== NULL
&& status
!= GOT_STATUS_ADD
&&
4698 staged_status
!= GOT_STATUS_ADD
) {
4699 err
= got_error_path(ie
->path
, GOT_ERR_NO_TREE_ENTRY
);
4705 case GOT_STATUS_ADD
:
4707 int choice
= GOT_PATCH_CHOICE_NONE
;
4708 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4709 status
, ie
->path
, NULL
, 1, 1);
4712 if (choice
!= GOT_PATCH_CHOICE_YES
)
4715 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_REVERT
,
4719 got_fileindex_entry_remove(a
->fileindex
, ie
);
4720 if (a
->unlink_added_files
) {
4721 if (asprintf(&ondisk_path
, "%s/%s",
4722 got_worktree_get_root_path(a
->worktree
),
4724 err
= got_error_from_errno("asprintf");
4727 if (unlink(ondisk_path
) == -1) {
4728 err
= got_error_from_errno2("unlink",
4734 case GOT_STATUS_DELETE
:
4736 int choice
= GOT_PATCH_CHOICE_NONE
;
4737 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4738 status
, ie
->path
, NULL
, 1, 1);
4741 if (choice
!= GOT_PATCH_CHOICE_YES
)
4745 case GOT_STATUS_MODIFY
:
4746 case GOT_STATUS_MODE_CHANGE
:
4747 case GOT_STATUS_CONFLICT
:
4748 case GOT_STATUS_MISSING
: {
4749 struct got_object_id id
;
4750 if (staged_status
== GOT_STATUS_ADD
||
4751 staged_status
== GOT_STATUS_MODIFY
) {
4752 memcpy(id
.sha1
, ie
->staged_blob_sha1
,
4753 SHA1_DIGEST_LENGTH
);
4755 memcpy(id
.sha1
, ie
->blob_sha1
,
4756 SHA1_DIGEST_LENGTH
);
4757 err
= got_object_open_as_blob(&blob
, a
->repo
, &id
, 8192);
4761 if (asprintf(&ondisk_path
, "%s/%s",
4762 got_worktree_get_root_path(a
->worktree
), relpath
) == -1) {
4763 err
= got_error_from_errno("asprintf");
4767 if (a
->patch_cb
&& (status
== GOT_STATUS_MODIFY
||
4768 status
== GOT_STATUS_CONFLICT
)) {
4769 int is_bad_symlink
= 0;
4770 err
= create_patched_content(&path_content
, 1, &id
,
4771 ondisk_path
, dirfd
, de_name
, ie
->path
, a
->repo
,
4772 a
->patch_cb
, a
->patch_arg
);
4773 if (err
|| path_content
== NULL
)
4775 if (te
&& S_ISLNK(te
->mode
)) {
4776 if (unlink(path_content
) == -1) {
4777 err
= got_error_from_errno2("unlink",
4781 err
= install_symlink(&is_bad_symlink
,
4782 a
->worktree
, ondisk_path
, ie
->path
,
4783 blob
, 0, 1, 0, a
->repo
,
4784 a
->progress_cb
, a
->progress_arg
);
4786 if (rename(path_content
, ondisk_path
) == -1) {
4787 err
= got_error_from_errno3("rename",
4788 path_content
, ondisk_path
);
4793 int is_bad_symlink
= 0;
4794 if (te
&& S_ISLNK(te
->mode
)) {
4795 err
= install_symlink(&is_bad_symlink
,
4796 a
->worktree
, ondisk_path
, ie
->path
,
4797 blob
, 0, 1, 0, a
->repo
,
4798 a
->progress_cb
, a
->progress_arg
);
4800 err
= install_blob(a
->worktree
, ondisk_path
,
4802 te
? te
->mode
: GOT_DEFAULT_FILE_MODE
,
4803 got_fileindex_perms_to_st(ie
), blob
,
4804 0, 1, 0, 0, a
->repo
,
4805 a
->progress_cb
, a
->progress_arg
);
4809 if (status
== GOT_STATUS_DELETE
||
4810 status
== GOT_STATUS_MODE_CHANGE
) {
4811 err
= got_fileindex_entry_update(ie
,
4812 a
->worktree
->root_fd
, relpath
,
4814 a
->worktree
->base_commit_id
->sha1
, 1);
4818 if (is_bad_symlink
) {
4819 got_fileindex_entry_filetype_set(ie
,
4820 GOT_FILEIDX_MODE_BAD_SYMLINK
);
4834 got_object_blob_close(blob
);
4836 got_object_tree_close(tree
);
4841 const struct got_error
*
4842 got_worktree_revert(struct got_worktree
*worktree
,
4843 struct got_pathlist_head
*paths
,
4844 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4845 got_worktree_patch_cb patch_cb
, void *patch_arg
,
4846 struct got_repository
*repo
)
4848 struct got_fileindex
*fileindex
= NULL
;
4849 char *fileindex_path
= NULL
;
4850 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
4851 const struct got_error
*sync_err
= NULL
;
4852 struct got_pathlist_entry
*pe
;
4853 struct revert_file_args rfa
;
4855 err
= lock_worktree(worktree
, LOCK_EX
);
4859 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4863 rfa
.worktree
= worktree
;
4864 rfa
.fileindex
= fileindex
;
4865 rfa
.progress_cb
= progress_cb
;
4866 rfa
.progress_arg
= progress_arg
;
4867 rfa
.patch_cb
= patch_cb
;
4868 rfa
.patch_arg
= patch_arg
;
4870 rfa
.unlink_added_files
= 0;
4871 TAILQ_FOREACH(pe
, paths
, entry
) {
4872 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4873 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
4877 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4878 if (sync_err
&& err
== NULL
)
4881 free(fileindex_path
);
4883 got_fileindex_free(fileindex
);
4884 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4885 if (unlockerr
&& err
== NULL
)
4891 free_commitable(struct got_commitable
*ct
)
4894 free(ct
->in_repo_path
);
4895 free(ct
->ondisk_path
);
4897 free(ct
->base_blob_id
);
4898 free(ct
->staged_blob_id
);
4899 free(ct
->base_commit_id
);
4903 struct collect_commitables_arg
{
4904 struct got_pathlist_head
*commitable_paths
;
4905 struct got_repository
*repo
;
4906 struct got_worktree
*worktree
;
4907 struct got_fileindex
*fileindex
;
4908 int have_staged_files
;
4909 int allow_bad_symlinks
;
4912 static const struct got_error
*
4913 collect_commitables(void *arg
, unsigned char status
,
4914 unsigned char staged_status
, const char *relpath
,
4915 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4916 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4918 struct collect_commitables_arg
*a
= arg
;
4919 const struct got_error
*err
= NULL
;
4920 struct got_commitable
*ct
= NULL
;
4921 struct got_pathlist_entry
*new = NULL
;
4922 char *parent_path
= NULL
, *path
= NULL
;
4925 if (a
->have_staged_files
) {
4926 if (staged_status
!= GOT_STATUS_MODIFY
&&
4927 staged_status
!= GOT_STATUS_ADD
&&
4928 staged_status
!= GOT_STATUS_DELETE
)
4931 if (status
== GOT_STATUS_CONFLICT
)
4932 return got_error(GOT_ERR_COMMIT_CONFLICT
);
4934 if (status
!= GOT_STATUS_MODIFY
&&
4935 status
!= GOT_STATUS_MODE_CHANGE
&&
4936 status
!= GOT_STATUS_ADD
&&
4937 status
!= GOT_STATUS_DELETE
)
4941 if (asprintf(&path
, "/%s", relpath
) == -1) {
4942 err
= got_error_from_errno("asprintf");
4945 if (strcmp(path
, "/") == 0) {
4946 parent_path
= strdup("");
4947 if (parent_path
== NULL
)
4948 return got_error_from_errno("strdup");
4950 err
= got_path_dirname(&parent_path
, path
);
4955 ct
= calloc(1, sizeof(*ct
));
4957 err
= got_error_from_errno("calloc");
4961 if (asprintf(&ct
->ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4963 err
= got_error_from_errno("asprintf");
4967 if (staged_status
== GOT_STATUS_ADD
||
4968 staged_status
== GOT_STATUS_MODIFY
) {
4969 struct got_fileindex_entry
*ie
;
4970 ie
= got_fileindex_entry_get(a
->fileindex
, path
, strlen(path
));
4971 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
4972 case GOT_FILEIDX_MODE_REGULAR_FILE
:
4973 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
4976 case GOT_FILEIDX_MODE_SYMLINK
:
4980 err
= got_error_path(path
, GOT_ERR_BAD_FILETYPE
);
4983 ct
->mode
|= got_fileindex_entry_perms_get(ie
);
4984 } else if (status
!= GOT_STATUS_DELETE
&&
4985 staged_status
!= GOT_STATUS_DELETE
) {
4987 if (fstatat(dirfd
, de_name
, &sb
,
4988 AT_SYMLINK_NOFOLLOW
) == -1) {
4989 err
= got_error_from_errno2("fstatat",
4993 } else if (lstat(ct
->ondisk_path
, &sb
) == -1) {
4994 err
= got_error_from_errno2("lstat", ct
->ondisk_path
);
4997 ct
->mode
= sb
.st_mode
;
5000 if (asprintf(&ct
->in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
5001 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
5003 err
= got_error_from_errno("asprintf");
5007 if (S_ISLNK(ct
->mode
) && staged_status
== GOT_STATUS_NO_CHANGE
&&
5008 status
== GOT_STATUS_ADD
&& !a
->allow_bad_symlinks
) {
5010 char target_path
[PATH_MAX
];
5012 target_len
= readlink(ct
->ondisk_path
, target_path
,
5013 sizeof(target_path
));
5014 if (target_len
== -1) {
5015 err
= got_error_from_errno2("readlink",
5019 err
= is_bad_symlink_target(&is_bad_symlink
, target_path
,
5020 target_len
, ct
->ondisk_path
, a
->worktree
->root_path
);
5023 if (is_bad_symlink
) {
5024 err
= got_error_path(ct
->ondisk_path
,
5025 GOT_ERR_BAD_SYMLINK
);
5031 ct
->status
= status
;
5032 ct
->staged_status
= staged_status
;
5033 ct
->blob_id
= NULL
; /* will be filled in when blob gets created */
5034 if (ct
->status
!= GOT_STATUS_ADD
&&
5035 ct
->staged_status
!= GOT_STATUS_ADD
) {
5036 ct
->base_blob_id
= got_object_id_dup(blob_id
);
5037 if (ct
->base_blob_id
== NULL
) {
5038 err
= got_error_from_errno("got_object_id_dup");
5041 ct
->base_commit_id
= got_object_id_dup(commit_id
);
5042 if (ct
->base_commit_id
== NULL
) {
5043 err
= got_error_from_errno("got_object_id_dup");
5047 if (ct
->staged_status
== GOT_STATUS_ADD
||
5048 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5049 ct
->staged_blob_id
= got_object_id_dup(staged_blob_id
);
5050 if (ct
->staged_blob_id
== NULL
) {
5051 err
= got_error_from_errno("got_object_id_dup");
5055 ct
->path
= strdup(path
);
5056 if (ct
->path
== NULL
) {
5057 err
= got_error_from_errno("strdup");
5060 err
= got_pathlist_insert(&new, a
->commitable_paths
, ct
->path
, ct
);
5062 if (ct
&& (err
|| new == NULL
))
5063 free_commitable(ct
);
5069 static const struct got_error
*write_tree(struct got_object_id
**, int *,
5070 struct got_tree_object
*, const char *, struct got_pathlist_head
*,
5071 got_worktree_status_cb status_cb
, void *status_arg
,
5072 struct got_repository
*);
5074 static const struct got_error
*
5075 write_subtree(struct got_object_id
**new_subtree_id
, int *nentries
,
5076 struct got_tree_entry
*te
, const char *parent_path
,
5077 struct got_pathlist_head
*commitable_paths
,
5078 got_worktree_status_cb status_cb
, void *status_arg
,
5079 struct got_repository
*repo
)
5081 const struct got_error
*err
= NULL
;
5082 struct got_tree_object
*subtree
;
5085 if (asprintf(&subpath
, "%s%s%s", parent_path
,
5086 got_path_is_root_dir(parent_path
) ? "" : "/", te
->name
) == -1)
5087 return got_error_from_errno("asprintf");
5089 err
= got_object_open_as_tree(&subtree
, repo
, &te
->id
);
5093 err
= write_tree(new_subtree_id
, nentries
, subtree
, subpath
,
5094 commitable_paths
, status_cb
, status_arg
, repo
);
5095 got_object_tree_close(subtree
);
5100 static const struct got_error
*
5101 match_ct_parent_path(int *match
, struct got_commitable
*ct
, const char *path
)
5103 const struct got_error
*err
= NULL
;
5104 char *ct_parent_path
= NULL
;
5108 if (strchr(ct
->in_repo_path
, '/') == NULL
) {
5109 *match
= got_path_is_root_dir(path
);
5113 err
= got_path_dirname(&ct_parent_path
, ct
->in_repo_path
);
5116 *match
= (strcmp(path
, ct_parent_path
) == 0);
5117 free(ct_parent_path
);
5122 get_ct_file_mode(struct got_commitable
*ct
)
5124 if (S_ISLNK(ct
->mode
))
5127 return S_IFREG
| (ct
->mode
& ((S_IRWXU
| S_IRWXG
| S_IRWXO
)));
5130 static const struct got_error
*
5131 alloc_modified_blob_tree_entry(struct got_tree_entry
**new_te
,
5132 struct got_tree_entry
*te
, struct got_commitable
*ct
)
5134 const struct got_error
*err
= NULL
;
5138 err
= got_object_tree_entry_dup(new_te
, te
);
5142 (*new_te
)->mode
= get_ct_file_mode(ct
);
5144 if (ct
->staged_status
== GOT_STATUS_MODIFY
)
5145 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5146 sizeof((*new_te
)->id
));
5148 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5150 if (err
&& *new_te
) {
5157 static const struct got_error
*
5158 alloc_added_blob_tree_entry(struct got_tree_entry
**new_te
,
5159 struct got_commitable
*ct
)
5161 const struct got_error
*err
= NULL
;
5162 char *ct_name
= NULL
;
5166 *new_te
= calloc(1, sizeof(**new_te
));
5167 if (*new_te
== NULL
)
5168 return got_error_from_errno("calloc");
5170 err
= got_path_basename(&ct_name
, ct
->path
);
5173 if (strlcpy((*new_te
)->name
, ct_name
, sizeof((*new_te
)->name
)) >=
5174 sizeof((*new_te
)->name
)) {
5175 err
= got_error(GOT_ERR_NO_SPACE
);
5179 (*new_te
)->mode
= get_ct_file_mode(ct
);
5181 if (ct
->staged_status
== GOT_STATUS_ADD
)
5182 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5183 sizeof((*new_te
)->id
));
5185 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5188 if (err
&& *new_te
) {
5195 static const struct got_error
*
5196 insert_tree_entry(struct got_tree_entry
*new_te
,
5197 struct got_pathlist_head
*paths
)
5199 const struct got_error
*err
= NULL
;
5200 struct got_pathlist_entry
*new_pe
;
5202 err
= got_pathlist_insert(&new_pe
, paths
, new_te
->name
, new_te
);
5206 return got_error(GOT_ERR_TREE_DUP_ENTRY
);
5210 static const struct got_error
*
5211 report_ct_status(struct got_commitable
*ct
,
5212 got_worktree_status_cb status_cb
, void *status_arg
)
5214 const char *ct_path
= ct
->path
;
5215 unsigned char status
;
5217 while (ct_path
[0] == '/')
5220 if (ct
->staged_status
!= GOT_STATUS_NO_CHANGE
)
5221 status
= ct
->staged_status
;
5223 status
= ct
->status
;
5225 return (*status_cb
)(status_arg
, status
, GOT_STATUS_NO_CHANGE
,
5226 ct_path
, ct
->blob_id
, NULL
, NULL
, -1, NULL
);
5229 static const struct got_error
*
5230 match_modified_subtree(int *modified
, struct got_tree_entry
*te
,
5231 const char *base_tree_path
, struct got_pathlist_head
*commitable_paths
)
5233 const struct got_error
*err
= NULL
;
5234 struct got_pathlist_entry
*pe
;
5239 if (asprintf(&te_path
, "%s%s%s", base_tree_path
,
5240 got_path_is_root_dir(base_tree_path
) ? "" : "/",
5242 return got_error_from_errno("asprintf");
5244 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5245 struct got_commitable
*ct
= pe
->data
;
5246 *modified
= got_path_is_child(ct
->in_repo_path
, te_path
,
5256 static const struct got_error
*
5257 match_deleted_or_modified_ct(struct got_commitable
**ctp
,
5258 struct got_tree_entry
*te
, const char *base_tree_path
,
5259 struct got_pathlist_head
*commitable_paths
)
5261 const struct got_error
*err
= NULL
;
5262 struct got_pathlist_entry
*pe
;
5266 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5267 struct got_commitable
*ct
= pe
->data
;
5268 char *ct_name
= NULL
;
5271 if (ct
->staged_status
== GOT_STATUS_NO_CHANGE
) {
5272 if (ct
->status
!= GOT_STATUS_MODIFY
&&
5273 ct
->status
!= GOT_STATUS_MODE_CHANGE
&&
5274 ct
->status
!= GOT_STATUS_DELETE
)
5277 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
5278 ct
->staged_status
!= GOT_STATUS_DELETE
)
5282 if (got_object_id_cmp(ct
->base_blob_id
, &te
->id
) != 0)
5285 err
= match_ct_parent_path(&path_matches
, ct
, base_tree_path
);
5291 err
= got_path_basename(&ct_name
, pe
->path
);
5295 if (strcmp(te
->name
, ct_name
) != 0) {
5308 static const struct got_error
*
5309 make_subtree_for_added_blob(struct got_tree_entry
**new_tep
,
5310 const char *child_path
, const char *path_base_tree
,
5311 struct got_pathlist_head
*commitable_paths
,
5312 got_worktree_status_cb status_cb
, void *status_arg
,
5313 struct got_repository
*repo
)
5315 const struct got_error
*err
= NULL
;
5316 struct got_tree_entry
*new_te
;
5318 struct got_object_id
*id
= NULL
;
5323 if (asprintf(&subtree_path
, "%s%s%s", path_base_tree
,
5324 got_path_is_root_dir(path_base_tree
) ? "" : "/",
5326 return got_error_from_errno("asprintf");
5328 new_te
= calloc(1, sizeof(*new_te
));
5330 return got_error_from_errno("calloc");
5331 new_te
->mode
= S_IFDIR
;
5333 if (strlcpy(new_te
->name
, child_path
, sizeof(new_te
->name
)) >=
5334 sizeof(new_te
->name
)) {
5335 err
= got_error(GOT_ERR_NO_SPACE
);
5338 err
= write_tree(&id
, &nentries
, NULL
, subtree_path
,
5339 commitable_paths
, status_cb
, status_arg
, repo
);
5344 memcpy(&new_te
->id
, id
, sizeof(new_te
->id
));
5353 static const struct got_error
*
5354 write_tree(struct got_object_id
**new_tree_id
, int *nentries
,
5355 struct got_tree_object
*base_tree
, const char *path_base_tree
,
5356 struct got_pathlist_head
*commitable_paths
,
5357 got_worktree_status_cb status_cb
, void *status_arg
,
5358 struct got_repository
*repo
)
5360 const struct got_error
*err
= NULL
;
5361 struct got_pathlist_head paths
;
5362 struct got_tree_entry
*te
, *new_te
= NULL
;
5363 struct got_pathlist_entry
*pe
;
5368 /* Insert, and recurse into, newly added entries first. */
5369 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5370 struct got_commitable
*ct
= pe
->data
;
5371 char *child_path
= NULL
, *slash
;
5373 if ((ct
->status
!= GOT_STATUS_ADD
&&
5374 ct
->staged_status
!= GOT_STATUS_ADD
) ||
5375 (ct
->flags
& GOT_COMMITABLE_ADDED
))
5378 if (!got_path_is_child(ct
->in_repo_path
, path_base_tree
,
5379 strlen(path_base_tree
)))
5382 err
= got_path_skip_common_ancestor(&child_path
, path_base_tree
,
5387 slash
= strchr(child_path
, '/');
5388 if (slash
== NULL
) {
5389 err
= alloc_added_blob_tree_entry(&new_te
, ct
);
5392 err
= report_ct_status(ct
, status_cb
, status_arg
);
5395 ct
->flags
|= GOT_COMMITABLE_ADDED
;
5396 err
= insert_tree_entry(new_te
, &paths
);
5401 *slash
= '\0'; /* trim trailing path components */
5402 if (base_tree
== NULL
||
5403 got_object_tree_find_entry(base_tree
, child_path
)
5405 err
= make_subtree_for_added_blob(&new_te
,
5406 child_path
, path_base_tree
,
5407 commitable_paths
, status_cb
, status_arg
,
5411 err
= insert_tree_entry(new_te
, &paths
);
5420 int i
, nbase_entries
;
5421 /* Handle modified and deleted entries. */
5422 nbase_entries
= got_object_tree_get_nentries(base_tree
);
5423 for (i
= 0; i
< nbase_entries
; i
++) {
5424 struct got_commitable
*ct
= NULL
;
5426 te
= got_object_tree_get_entry(base_tree
, i
);
5427 if (got_object_tree_entry_is_submodule(te
)) {
5428 /* Entry is a submodule; just copy it. */
5429 err
= got_object_tree_entry_dup(&new_te
, te
);
5432 err
= insert_tree_entry(new_te
, &paths
);
5439 if (S_ISDIR(te
->mode
)) {
5441 err
= got_object_tree_entry_dup(&new_te
, te
);
5444 err
= match_modified_subtree(&modified
, te
,
5445 path_base_tree
, commitable_paths
);
5448 /* Avoid recursion into unmodified subtrees. */
5450 struct got_object_id
*new_id
;
5452 err
= write_subtree(&new_id
,
5454 path_base_tree
, commitable_paths
,
5455 status_cb
, status_arg
, repo
);
5458 if (nsubentries
== 0) {
5459 /* All entries were deleted. */
5463 memcpy(&new_te
->id
, new_id
,
5464 sizeof(new_te
->id
));
5467 err
= insert_tree_entry(new_te
, &paths
);
5474 err
= match_deleted_or_modified_ct(&ct
, te
,
5475 path_base_tree
, commitable_paths
);
5479 /* NB: Deleted entries get dropped here. */
5480 if (ct
->status
== GOT_STATUS_MODIFY
||
5481 ct
->status
== GOT_STATUS_MODE_CHANGE
||
5482 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5483 err
= alloc_modified_blob_tree_entry(
5487 err
= insert_tree_entry(new_te
, &paths
);
5492 err
= report_ct_status(ct
, status_cb
,
5497 /* Entry is unchanged; just copy it. */
5498 err
= got_object_tree_entry_dup(&new_te
, te
);
5501 err
= insert_tree_entry(new_te
, &paths
);
5509 /* Write new list of entries; deleted entries have been dropped. */
5510 err
= got_object_tree_create(new_tree_id
, &paths
, *nentries
, repo
);
5512 got_pathlist_free(&paths
);
5516 static const struct got_error
*
5517 update_fileindex_after_commit(struct got_worktree
*worktree
,
5518 struct got_pathlist_head
*commitable_paths
,
5519 struct got_object_id
*new_base_commit_id
,
5520 struct got_fileindex
*fileindex
, int have_staged_files
)
5522 const struct got_error
*err
= NULL
;
5523 struct got_pathlist_entry
*pe
;
5524 char *relpath
= NULL
;
5526 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5527 struct got_fileindex_entry
*ie
;
5528 struct got_commitable
*ct
= pe
->data
;
5530 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
5532 err
= got_path_skip_common_ancestor(&relpath
,
5533 worktree
->root_path
, ct
->ondisk_path
);
5538 if (ct
->status
== GOT_STATUS_DELETE
||
5539 ct
->staged_status
== GOT_STATUS_DELETE
) {
5540 got_fileindex_entry_remove(fileindex
, ie
);
5541 } else if (ct
->staged_status
== GOT_STATUS_ADD
||
5542 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5543 got_fileindex_entry_stage_set(ie
,
5544 GOT_FILEIDX_STAGE_NONE
);
5545 got_fileindex_entry_staged_filetype_set(ie
, 0);
5547 err
= got_fileindex_entry_update(ie
,
5548 worktree
->root_fd
, relpath
,
5549 ct
->staged_blob_id
->sha1
,
5550 new_base_commit_id
->sha1
,
5551 !have_staged_files
);
5553 err
= got_fileindex_entry_update(ie
,
5554 worktree
->root_fd
, relpath
,
5556 new_base_commit_id
->sha1
,
5557 !have_staged_files
);
5559 err
= got_fileindex_entry_alloc(&ie
, pe
->path
);
5562 err
= got_fileindex_entry_update(ie
,
5563 worktree
->root_fd
, relpath
, ct
->blob_id
->sha1
,
5564 new_base_commit_id
->sha1
, 1);
5566 got_fileindex_entry_free(ie
);
5569 err
= got_fileindex_entry_add(fileindex
, ie
);
5571 got_fileindex_entry_free(ie
);
5584 static const struct got_error
*
5585 check_out_of_date(const char *in_repo_path
, unsigned char status
,
5586 unsigned char staged_status
, struct got_object_id
*base_blob_id
,
5587 struct got_object_id
*base_commit_id
,
5588 struct got_object_id
*head_commit_id
, struct got_repository
*repo
,
5591 const struct got_error
*err
= NULL
;
5592 struct got_object_id
*id
= NULL
;
5594 if (status
!= GOT_STATUS_ADD
&& staged_status
!= GOT_STATUS_ADD
) {
5595 /* Trivial case: base commit == head commit */
5596 if (got_object_id_cmp(base_commit_id
, head_commit_id
) == 0)
5599 * Ensure file content which local changes were based
5600 * on matches file content in the branch head.
5602 err
= got_object_id_by_path(&id
, repo
, head_commit_id
,
5605 if (err
->code
== GOT_ERR_NO_TREE_ENTRY
)
5606 err
= got_error(ood_errcode
);
5608 } else if (got_object_id_cmp(id
, base_blob_id
) != 0)
5609 err
= got_error(ood_errcode
);
5611 /* Require that added files don't exist in the branch head. */
5612 err
= got_object_id_by_path(&id
, repo
, head_commit_id
,
5614 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
5616 err
= id
? got_error(ood_errcode
) : NULL
;
5623 const struct got_error
*
5624 commit_worktree(struct got_object_id
**new_commit_id
,
5625 struct got_pathlist_head
*commitable_paths
,
5626 struct got_object_id
*head_commit_id
,
5627 struct got_object_id
*parent_id2
,
5628 struct got_worktree
*worktree
,
5629 const char *author
, const char *committer
,
5630 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
5631 got_worktree_status_cb status_cb
, void *status_arg
,
5632 struct got_repository
*repo
)
5634 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
5635 struct got_pathlist_entry
*pe
;
5636 const char *head_ref_name
= NULL
;
5637 struct got_commit_object
*head_commit
= NULL
;
5638 struct got_reference
*head_ref2
= NULL
;
5639 struct got_object_id
*head_commit_id2
= NULL
;
5640 struct got_tree_object
*head_tree
= NULL
;
5641 struct got_object_id
*new_tree_id
= NULL
;
5642 int nentries
, nparents
= 0;
5643 struct got_object_id_queue parent_ids
;
5644 struct got_object_qid
*pid
= NULL
;
5645 char *logmsg
= NULL
;
5647 *new_commit_id
= NULL
;
5649 STAILQ_INIT(&parent_ids
);
5651 err
= got_object_open_as_commit(&head_commit
, repo
, head_commit_id
);
5655 err
= got_object_open_as_tree(&head_tree
, repo
, head_commit
->tree_id
);
5659 if (commit_msg_cb
!= NULL
) {
5660 err
= commit_msg_cb(commitable_paths
, &logmsg
, commit_arg
);
5665 if (logmsg
== NULL
|| strlen(logmsg
) == 0) {
5666 err
= got_error(GOT_ERR_COMMIT_MSG_EMPTY
);
5670 /* Create blobs from added and modified files and record their IDs. */
5671 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5672 struct got_commitable
*ct
= pe
->data
;
5675 /* Blobs for staged files already exist. */
5676 if (ct
->staged_status
== GOT_STATUS_ADD
||
5677 ct
->staged_status
== GOT_STATUS_MODIFY
)
5680 if (ct
->status
!= GOT_STATUS_ADD
&&
5681 ct
->status
!= GOT_STATUS_MODIFY
&&
5682 ct
->status
!= GOT_STATUS_MODE_CHANGE
)
5685 if (asprintf(&ondisk_path
, "%s/%s",
5686 worktree
->root_path
, pe
->path
) == -1) {
5687 err
= got_error_from_errno("asprintf");
5690 err
= got_object_blob_create(&ct
->blob_id
, ondisk_path
, repo
);
5696 /* Recursively write new tree objects. */
5697 err
= write_tree(&new_tree_id
, &nentries
, head_tree
, "/",
5698 commitable_paths
, status_cb
, status_arg
, repo
);
5702 err
= got_object_qid_alloc(&pid
, worktree
->base_commit_id
);
5705 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
5708 err
= got_object_qid_alloc(&pid
, parent_id2
);
5711 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
5714 err
= got_object_commit_create(new_commit_id
, new_tree_id
, &parent_ids
,
5715 nparents
, author
, time(NULL
), committer
, time(NULL
), logmsg
, repo
);
5721 /* Check if a concurrent commit to our branch has occurred. */
5722 head_ref_name
= got_worktree_get_head_ref_name(worktree
);
5723 if (head_ref_name
== NULL
) {
5724 err
= got_error_from_errno("got_worktree_get_head_ref_name");
5727 /* Lock the reference here to prevent concurrent modification. */
5728 err
= got_ref_open(&head_ref2
, repo
, head_ref_name
, 1);
5731 err
= got_ref_resolve(&head_commit_id2
, repo
, head_ref2
);
5734 if (got_object_id_cmp(head_commit_id
, head_commit_id2
) != 0) {
5735 err
= got_error(GOT_ERR_COMMIT_HEAD_CHANGED
);
5738 /* Update branch head in repository. */
5739 err
= got_ref_change_ref(head_ref2
, *new_commit_id
);
5742 err
= got_ref_write(head_ref2
, repo
);
5746 err
= got_worktree_set_base_commit_id(worktree
, repo
, *new_commit_id
);
5750 err
= ref_base_commit(worktree
, repo
);
5754 got_object_id_queue_free(&parent_ids
);
5756 got_object_tree_close(head_tree
);
5758 got_object_commit_close(head_commit
);
5759 free(head_commit_id2
);
5761 unlockerr
= got_ref_unlock(head_ref2
);
5762 if (unlockerr
&& err
== NULL
)
5764 got_ref_close(head_ref2
);
5769 static const struct got_error
*
5770 check_path_is_commitable(const char *path
,
5771 struct got_pathlist_head
*commitable_paths
)
5773 struct got_pathlist_entry
*cpe
= NULL
;
5774 size_t path_len
= strlen(path
);
5776 TAILQ_FOREACH(cpe
, commitable_paths
, entry
) {
5777 struct got_commitable
*ct
= cpe
->data
;
5778 const char *ct_path
= ct
->path
;
5780 while (ct_path
[0] == '/')
5783 if (strcmp(path
, ct_path
) == 0 ||
5784 got_path_is_child(ct_path
, path
, path_len
))
5789 return got_error_path(path
, GOT_ERR_BAD_PATH
);
5794 static const struct got_error
*
5795 check_staged_file(void *arg
, struct got_fileindex_entry
*ie
)
5797 int *have_staged_files
= arg
;
5799 if (got_fileindex_entry_stage_get(ie
) != GOT_FILEIDX_STAGE_NONE
) {
5800 *have_staged_files
= 1;
5801 return got_error(GOT_ERR_CANCELLED
);
5807 static const struct got_error
*
5808 check_non_staged_files(struct got_fileindex
*fileindex
,
5809 struct got_pathlist_head
*paths
)
5811 struct got_pathlist_entry
*pe
;
5812 struct got_fileindex_entry
*ie
;
5814 TAILQ_FOREACH(pe
, paths
, entry
) {
5815 if (pe
->path
[0] == '\0')
5817 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
5819 return got_error_path(pe
->path
, GOT_ERR_BAD_PATH
);
5820 if (got_fileindex_entry_stage_get(ie
) == GOT_FILEIDX_STAGE_NONE
)
5821 return got_error_path(pe
->path
,
5822 GOT_ERR_FILE_NOT_STAGED
);
5828 const struct got_error
*
5829 got_worktree_commit(struct got_object_id
**new_commit_id
,
5830 struct got_worktree
*worktree
, struct got_pathlist_head
*paths
,
5831 const char *author
, const char *committer
, int allow_bad_symlinks
,
5832 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
5833 got_worktree_status_cb status_cb
, void *status_arg
,
5834 struct got_repository
*repo
)
5836 const struct got_error
*err
= NULL
, *unlockerr
= NULL
, *sync_err
;
5837 struct got_fileindex
*fileindex
= NULL
;
5838 char *fileindex_path
= NULL
;
5839 struct got_pathlist_head commitable_paths
;
5840 struct collect_commitables_arg cc_arg
;
5841 struct got_pathlist_entry
*pe
;
5842 struct got_reference
*head_ref
= NULL
;
5843 struct got_object_id
*head_commit_id
= NULL
;
5844 int have_staged_files
= 0;
5846 *new_commit_id
= NULL
;
5848 TAILQ_INIT(&commitable_paths
);
5850 err
= lock_worktree(worktree
, LOCK_EX
);
5854 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
5858 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
5862 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
5866 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
5867 &have_staged_files
);
5868 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
5870 if (have_staged_files
) {
5871 err
= check_non_staged_files(fileindex
, paths
);
5876 cc_arg
.commitable_paths
= &commitable_paths
;
5877 cc_arg
.worktree
= worktree
;
5878 cc_arg
.fileindex
= fileindex
;
5880 cc_arg
.have_staged_files
= have_staged_files
;
5881 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
5882 TAILQ_FOREACH(pe
, paths
, entry
) {
5883 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
5884 collect_commitables
, &cc_arg
, NULL
, NULL
, 0, 0);
5889 if (TAILQ_EMPTY(&commitable_paths
)) {
5890 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
5894 TAILQ_FOREACH(pe
, paths
, entry
) {
5895 err
= check_path_is_commitable(pe
->path
, &commitable_paths
);
5900 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
5901 struct got_commitable
*ct
= pe
->data
;
5902 const char *ct_path
= ct
->in_repo_path
;
5904 while (ct_path
[0] == '/')
5906 err
= check_out_of_date(ct_path
, ct
->status
,
5907 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
5908 head_commit_id
, repo
, GOT_ERR_COMMIT_OUT_OF_DATE
);
5914 err
= commit_worktree(new_commit_id
, &commitable_paths
,
5915 head_commit_id
, NULL
, worktree
, author
, committer
,
5916 commit_msg_cb
, commit_arg
, status_cb
, status_arg
, repo
);
5920 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
5921 *new_commit_id
, fileindex
, have_staged_files
);
5922 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
5923 if (sync_err
&& err
== NULL
)
5927 got_fileindex_free(fileindex
);
5928 free(fileindex_path
);
5929 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
5930 if (unlockerr
&& err
== NULL
)
5932 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
5933 struct got_commitable
*ct
= pe
->data
;
5934 free_commitable(ct
);
5936 got_pathlist_free(&commitable_paths
);
5941 got_commitable_get_path(struct got_commitable
*ct
)
5947 got_commitable_get_status(struct got_commitable
*ct
)
5952 struct check_rebase_ok_arg
{
5953 struct got_worktree
*worktree
;
5954 struct got_repository
*repo
;
5957 static const struct got_error
*
5958 check_rebase_ok(void *arg
, struct got_fileindex_entry
*ie
)
5960 const struct got_error
*err
= NULL
;
5961 struct check_rebase_ok_arg
*a
= arg
;
5962 unsigned char status
;
5966 /* Reject rebase of a work tree with mixed base commits. */
5967 if (memcmp(ie
->commit_sha1
, a
->worktree
->base_commit_id
->sha1
,
5968 SHA1_DIGEST_LENGTH
))
5969 return got_error(GOT_ERR_MIXED_COMMITS
);
5971 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
5973 return got_error_from_errno("asprintf");
5975 /* Reject rebase of a work tree with modified or staged files. */
5976 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
5981 if (status
!= GOT_STATUS_NO_CHANGE
)
5982 return got_error(GOT_ERR_MODIFIED
);
5983 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
5984 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
5989 const struct got_error
*
5990 got_worktree_rebase_prepare(struct got_reference
**new_base_branch_ref
,
5991 struct got_reference
**tmp_branch
, struct got_fileindex
**fileindex
,
5992 struct got_worktree
*worktree
, struct got_reference
*branch
,
5993 struct got_repository
*repo
)
5995 const struct got_error
*err
= NULL
;
5996 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
5997 char *branch_ref_name
= NULL
;
5998 char *fileindex_path
= NULL
;
5999 struct check_rebase_ok_arg ok_arg
;
6000 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
6001 struct got_object_id
*wt_branch_tip
= NULL
;
6003 *new_base_branch_ref
= NULL
;
6007 err
= lock_worktree(worktree
, LOCK_EX
);
6011 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6015 ok_arg
.worktree
= worktree
;
6017 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6022 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6026 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6030 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6034 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6039 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
6042 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
6043 err
= got_error(GOT_ERR_REBASE_OUT_OF_DATE
);
6047 err
= got_ref_alloc_symref(new_base_branch_ref
,
6048 new_base_branch_ref_name
, wt_branch
);
6051 err
= got_ref_write(*new_base_branch_ref
, repo
);
6055 /* TODO Lock original branch's ref while rebasing? */
6057 err
= got_ref_alloc_symref(&branch_ref
, branch_ref_name
, branch
);
6061 err
= got_ref_write(branch_ref
, repo
);
6065 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6066 worktree
->base_commit_id
);
6069 err
= got_ref_write(*tmp_branch
, repo
);
6073 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6077 free(fileindex_path
);
6078 free(tmp_branch_name
);
6079 free(new_base_branch_ref_name
);
6080 free(branch_ref_name
);
6082 got_ref_close(branch_ref
);
6084 got_ref_close(wt_branch
);
6085 free(wt_branch_tip
);
6087 if (*new_base_branch_ref
) {
6088 got_ref_close(*new_base_branch_ref
);
6089 *new_base_branch_ref
= NULL
;
6092 got_ref_close(*tmp_branch
);
6096 got_fileindex_free(*fileindex
);
6099 lock_worktree(worktree
, LOCK_SH
);
6104 const struct got_error
*
6105 got_worktree_rebase_continue(struct got_object_id
**commit_id
,
6106 struct got_reference
**new_base_branch
, struct got_reference
**tmp_branch
,
6107 struct got_reference
**branch
, struct got_fileindex
**fileindex
,
6108 struct got_worktree
*worktree
, struct got_repository
*repo
)
6110 const struct got_error
*err
;
6111 char *commit_ref_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6112 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
6113 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
6114 char *fileindex_path
= NULL
;
6115 int have_staged_files
= 0;
6118 *new_base_branch
= NULL
;
6123 err
= lock_worktree(worktree
, LOCK_EX
);
6127 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6131 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
6132 &have_staged_files
);
6133 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6135 if (have_staged_files
) {
6136 err
= got_error(GOT_ERR_STAGED_PATHS
);
6140 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6144 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6148 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6152 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6156 err
= got_ref_open(&branch_ref
, repo
, branch_ref_name
, 0);
6160 err
= got_ref_open(branch
, repo
,
6161 got_ref_get_symref_target(branch_ref
), 0);
6165 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6169 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
6173 err
= got_ref_open(new_base_branch
, repo
,
6174 new_base_branch_ref_name
, 0);
6178 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
6182 free(commit_ref_name
);
6183 free(branch_ref_name
);
6184 free(fileindex_path
);
6186 got_ref_close(commit_ref
);
6188 got_ref_close(branch_ref
);
6193 got_ref_close(*tmp_branch
);
6196 if (*new_base_branch
) {
6197 got_ref_close(*new_base_branch
);
6198 *new_base_branch
= NULL
;
6201 got_ref_close(*branch
);
6205 got_fileindex_free(*fileindex
);
6208 lock_worktree(worktree
, LOCK_SH
);
6213 const struct got_error
*
6214 got_worktree_rebase_in_progress(int *in_progress
, struct got_worktree
*worktree
)
6216 const struct got_error
*err
;
6217 char *tmp_branch_name
= NULL
;
6219 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6223 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
6224 free(tmp_branch_name
);
6228 static const struct got_error
*
6229 collect_rebase_commit_msg(struct got_pathlist_head
*commitable_paths
,
6230 char **logmsg
, void *arg
)
6236 static const struct got_error
*
6237 rebase_status(void *arg
, unsigned char status
, unsigned char staged_status
,
6238 const char *path
, struct got_object_id
*blob_id
,
6239 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
6240 int dirfd
, const char *de_name
)
6245 struct collect_merged_paths_arg
{
6246 got_worktree_checkout_cb progress_cb
;
6248 struct got_pathlist_head
*merged_paths
;
6251 static const struct got_error
*
6252 collect_merged_paths(void *arg
, unsigned char status
, const char *path
)
6254 const struct got_error
*err
;
6255 struct collect_merged_paths_arg
*a
= arg
;
6257 struct got_pathlist_entry
*new;
6259 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path
);
6263 if (status
!= GOT_STATUS_MERGE
&&
6264 status
!= GOT_STATUS_ADD
&&
6265 status
!= GOT_STATUS_DELETE
&&
6266 status
!= GOT_STATUS_CONFLICT
)
6271 return got_error_from_errno("strdup");
6273 err
= got_pathlist_insert(&new, a
->merged_paths
, p
, NULL
);
6274 if (err
|| new == NULL
)
6280 got_worktree_rebase_pathlist_free(struct got_pathlist_head
*merged_paths
)
6282 struct got_pathlist_entry
*pe
;
6284 TAILQ_FOREACH(pe
, merged_paths
, entry
)
6285 free((char *)pe
->path
);
6287 got_pathlist_free(merged_paths
);
6290 static const struct got_error
*
6291 store_commit_id(const char *commit_ref_name
, struct got_object_id
*commit_id
,
6292 int is_rebase
, struct got_repository
*repo
)
6294 const struct got_error
*err
;
6295 struct got_reference
*commit_ref
= NULL
;
6297 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6299 if (err
->code
!= GOT_ERR_NOT_REF
)
6301 err
= got_ref_alloc(&commit_ref
, commit_ref_name
, commit_id
);
6304 err
= got_ref_write(commit_ref
, repo
);
6307 } else if (is_rebase
) {
6308 struct got_object_id
*stored_id
;
6311 err
= got_ref_resolve(&stored_id
, repo
, commit_ref
);
6314 cmp
= got_object_id_cmp(commit_id
, stored_id
);
6317 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6323 got_ref_close(commit_ref
);
6327 static const struct got_error
*
6328 rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6329 const char *commit_ref_name
, struct got_worktree
*worktree
,
6330 struct got_fileindex
*fileindex
, struct got_object_id
*parent_commit_id
,
6331 struct got_object_id
*commit_id
, struct got_repository
*repo
,
6332 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6333 got_cancel_cb cancel_cb
, void *cancel_arg
)
6335 const struct got_error
*err
;
6336 struct got_reference
*commit_ref
= NULL
;
6337 struct collect_merged_paths_arg cmp_arg
;
6338 char *fileindex_path
;
6340 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6342 err
= get_fileindex_path(&fileindex_path
, worktree
);
6346 cmp_arg
.progress_cb
= progress_cb
;
6347 cmp_arg
.progress_arg
= progress_arg
;
6348 cmp_arg
.merged_paths
= merged_paths
;
6349 err
= merge_files(worktree
, fileindex
, fileindex_path
,
6350 parent_commit_id
, commit_id
, repo
, collect_merged_paths
,
6351 &cmp_arg
, cancel_cb
, cancel_arg
);
6353 got_ref_close(commit_ref
);
6357 const struct got_error
*
6358 got_worktree_rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6359 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6360 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
6361 struct got_repository
*repo
,
6362 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6363 got_cancel_cb cancel_cb
, void *cancel_arg
)
6365 const struct got_error
*err
;
6366 char *commit_ref_name
;
6368 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6372 err
= store_commit_id(commit_ref_name
, commit_id
, 1, repo
);
6376 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
6377 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
6378 progress_arg
, cancel_cb
, cancel_arg
);
6380 free(commit_ref_name
);
6384 const struct got_error
*
6385 got_worktree_histedit_merge_files(struct got_pathlist_head
*merged_paths
,
6386 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6387 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
6388 struct got_repository
*repo
,
6389 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6390 got_cancel_cb cancel_cb
, void *cancel_arg
)
6392 const struct got_error
*err
;
6393 char *commit_ref_name
;
6395 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6399 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
6403 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
6404 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
6405 progress_arg
, cancel_cb
, cancel_arg
);
6407 free(commit_ref_name
);
6411 static const struct got_error
*
6412 rebase_commit(struct got_object_id
**new_commit_id
,
6413 struct got_pathlist_head
*merged_paths
, struct got_reference
*commit_ref
,
6414 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6415 struct got_reference
*tmp_branch
, struct got_commit_object
*orig_commit
,
6416 const char *new_logmsg
, struct got_repository
*repo
)
6418 const struct got_error
*err
, *sync_err
;
6419 struct got_pathlist_head commitable_paths
;
6420 struct collect_commitables_arg cc_arg
;
6421 char *fileindex_path
= NULL
;
6422 struct got_reference
*head_ref
= NULL
;
6423 struct got_object_id
*head_commit_id
= NULL
;
6424 char *logmsg
= NULL
;
6426 TAILQ_INIT(&commitable_paths
);
6427 *new_commit_id
= NULL
;
6429 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6431 err
= get_fileindex_path(&fileindex_path
, worktree
);
6435 cc_arg
.commitable_paths
= &commitable_paths
;
6436 cc_arg
.worktree
= worktree
;
6438 cc_arg
.have_staged_files
= 0;
6440 * If possible get the status of individual files directly to
6441 * avoid crawling the entire work tree once per rebased commit.
6443 * Ideally, merged_paths would contain a list of commitables
6444 * we could use so we could skip worktree_status() entirely.
6445 * However, we would then need carefully keep track of cumulative
6446 * effects of operations such as file additions and deletions
6447 * in 'got histedit -f' (folding multiple commits into one),
6448 * and this extra complexity is not really worth it.
6451 struct got_pathlist_entry
*pe
;
6452 TAILQ_FOREACH(pe
, merged_paths
, entry
) {
6453 err
= worktree_status(worktree
, pe
->path
, fileindex
,
6454 repo
, collect_commitables
, &cc_arg
, NULL
, NULL
, 1,
6460 err
= worktree_status(worktree
, "", fileindex
, repo
,
6461 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
6466 if (TAILQ_EMPTY(&commitable_paths
)) {
6467 /* No-op change; commit will be elided. */
6468 err
= got_ref_delete(commit_ref
, repo
);
6471 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
6475 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
6479 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
6484 logmsg
= strdup(new_logmsg
);
6485 if (logmsg
== NULL
) {
6486 err
= got_error_from_errno("strdup");
6490 err
= got_object_commit_get_logmsg(&logmsg
, orig_commit
);
6495 /* NB: commit_worktree will call free(logmsg) */
6496 err
= commit_worktree(new_commit_id
, &commitable_paths
, head_commit_id
,
6497 NULL
, worktree
, got_object_commit_get_author(orig_commit
),
6498 got_object_commit_get_committer(orig_commit
),
6499 collect_rebase_commit_msg
, logmsg
, rebase_status
, NULL
, repo
);
6503 err
= got_ref_change_ref(tmp_branch
, *new_commit_id
);
6507 err
= got_ref_delete(commit_ref
, repo
);
6511 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
6512 *new_commit_id
, fileindex
, 0);
6513 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6514 if (sync_err
&& err
== NULL
)
6517 free(fileindex_path
);
6518 free(head_commit_id
);
6520 got_ref_close(head_ref
);
6522 free(*new_commit_id
);
6523 *new_commit_id
= NULL
;
6528 const struct got_error
*
6529 got_worktree_rebase_commit(struct got_object_id
**new_commit_id
,
6530 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6531 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6532 struct got_commit_object
*orig_commit
,
6533 struct got_object_id
*orig_commit_id
, struct got_repository
*repo
)
6535 const struct got_error
*err
;
6536 char *commit_ref_name
;
6537 struct got_reference
*commit_ref
= NULL
;
6538 struct got_object_id
*commit_id
= NULL
;
6540 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6544 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6547 err
= got_ref_resolve(&commit_id
, repo
, commit_ref
);
6550 if (got_object_id_cmp(commit_id
, orig_commit_id
) != 0) {
6551 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6555 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6556 worktree
, fileindex
, tmp_branch
, orig_commit
, NULL
, repo
);
6559 got_ref_close(commit_ref
);
6560 free(commit_ref_name
);
6565 const struct got_error
*
6566 got_worktree_histedit_commit(struct got_object_id
**new_commit_id
,
6567 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6568 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6569 struct got_commit_object
*orig_commit
,
6570 struct got_object_id
*orig_commit_id
, const char *new_logmsg
,
6571 struct got_repository
*repo
)
6573 const struct got_error
*err
;
6574 char *commit_ref_name
;
6575 struct got_reference
*commit_ref
= NULL
;
6577 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6581 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6585 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6586 worktree
, fileindex
, tmp_branch
, orig_commit
, new_logmsg
, repo
);
6589 got_ref_close(commit_ref
);
6590 free(commit_ref_name
);
6594 const struct got_error
*
6595 got_worktree_rebase_postpone(struct got_worktree
*worktree
,
6596 struct got_fileindex
*fileindex
)
6599 got_fileindex_free(fileindex
);
6600 return lock_worktree(worktree
, LOCK_SH
);
6603 static const struct got_error
*
6604 delete_ref(const char *name
, struct got_repository
*repo
)
6606 const struct got_error
*err
;
6607 struct got_reference
*ref
;
6609 err
= got_ref_open(&ref
, repo
, name
, 0);
6611 if (err
->code
== GOT_ERR_NOT_REF
)
6616 err
= got_ref_delete(ref
, repo
);
6621 static const struct got_error
*
6622 delete_rebase_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
6624 const struct got_error
*err
;
6625 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6626 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
6628 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6631 err
= delete_ref(tmp_branch_name
, repo
);
6635 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6638 err
= delete_ref(new_base_branch_ref_name
, repo
);
6642 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6645 err
= delete_ref(branch_ref_name
, repo
);
6649 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6652 err
= delete_ref(commit_ref_name
, repo
);
6657 free(tmp_branch_name
);
6658 free(new_base_branch_ref_name
);
6659 free(branch_ref_name
);
6660 free(commit_ref_name
);
6664 const struct got_error
*
6665 create_backup_ref(const char *backup_ref_prefix
, struct got_reference
*branch
,
6666 struct got_object_id
*new_commit_id
, struct got_repository
*repo
)
6668 const struct got_error
*err
;
6669 struct got_reference
*ref
= NULL
;
6670 struct got_object_id
*old_commit_id
= NULL
;
6671 const char *branch_name
= NULL
;
6672 char *new_id_str
= NULL
;
6673 char *refname
= NULL
;
6675 branch_name
= got_ref_get_name(branch
);
6676 if (strncmp(branch_name
, "refs/heads/", 11) != 0)
6677 return got_error(GOT_ERR_BAD_REF_NAME
); /* should not happen */
6680 err
= got_object_id_str(&new_id_str
, new_commit_id
);
6684 if (asprintf(&refname
, "%s/%s/%s", backup_ref_prefix
, branch_name
,
6685 new_id_str
) == -1) {
6686 err
= got_error_from_errno("asprintf");
6690 err
= got_ref_resolve(&old_commit_id
, repo
, branch
);
6694 err
= got_ref_alloc(&ref
, refname
, old_commit_id
);
6698 err
= got_ref_write(ref
, repo
);
6702 free(old_commit_id
);
6708 const struct got_error
*
6709 got_worktree_rebase_complete(struct got_worktree
*worktree
,
6710 struct got_fileindex
*fileindex
, struct got_reference
*new_base_branch
,
6711 struct got_reference
*tmp_branch
, struct got_reference
*rebased_branch
,
6712 struct got_repository
*repo
, int create_backup
)
6714 const struct got_error
*err
, *unlockerr
, *sync_err
;
6715 struct got_object_id
*new_head_commit_id
= NULL
;
6716 char *fileindex_path
= NULL
;
6718 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
6722 if (create_backup
) {
6723 err
= create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX
,
6724 rebased_branch
, new_head_commit_id
, repo
);
6729 err
= got_ref_change_ref(rebased_branch
, new_head_commit_id
);
6733 err
= got_ref_write(rebased_branch
, repo
);
6737 err
= got_worktree_set_head_ref(worktree
, rebased_branch
);
6741 err
= delete_rebase_refs(worktree
, repo
);
6745 err
= get_fileindex_path(&fileindex_path
, worktree
);
6748 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
6749 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6750 if (sync_err
&& err
== NULL
)
6753 got_fileindex_free(fileindex
);
6754 free(fileindex_path
);
6755 free(new_head_commit_id
);
6756 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6757 if (unlockerr
&& err
== NULL
)
6762 const struct got_error
*
6763 got_worktree_rebase_abort(struct got_worktree
*worktree
,
6764 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
6765 struct got_reference
*new_base_branch
,
6766 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
6768 const struct got_error
*err
, *unlockerr
, *sync_err
;
6769 struct got_reference
*resolved
= NULL
;
6770 struct got_object_id
*commit_id
= NULL
;
6771 char *fileindex_path
= NULL
;
6772 struct revert_file_args rfa
;
6773 struct got_object_id
*tree_id
= NULL
;
6775 err
= lock_worktree(worktree
, LOCK_EX
);
6779 err
= got_ref_open(&resolved
, repo
,
6780 got_ref_get_symref_target(new_base_branch
), 0);
6784 err
= got_worktree_set_head_ref(worktree
, resolved
);
6789 * XXX commits to the base branch could have happened while
6790 * we were busy rebasing; should we store the original commit ID
6791 * when rebase begins and read it back here?
6793 err
= got_ref_resolve(&commit_id
, repo
, resolved
);
6797 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
6801 err
= got_object_id_by_path(&tree_id
, repo
,
6802 worktree
->base_commit_id
, worktree
->path_prefix
);
6806 err
= delete_rebase_refs(worktree
, repo
);
6810 err
= get_fileindex_path(&fileindex_path
, worktree
);
6814 rfa
.worktree
= worktree
;
6815 rfa
.fileindex
= fileindex
;
6816 rfa
.progress_cb
= progress_cb
;
6817 rfa
.progress_arg
= progress_arg
;
6818 rfa
.patch_cb
= NULL
;
6819 rfa
.patch_arg
= NULL
;
6821 rfa
.unlink_added_files
= 0;
6822 err
= worktree_status(worktree
, "", fileindex
, repo
,
6823 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
6827 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
6828 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
6830 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6831 if (sync_err
&& err
== NULL
)
6834 got_ref_close(resolved
);
6838 got_fileindex_free(fileindex
);
6839 free(fileindex_path
);
6841 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6842 if (unlockerr
&& err
== NULL
)
6847 const struct got_error
*
6848 got_worktree_histedit_prepare(struct got_reference
**tmp_branch
,
6849 struct got_reference
**branch_ref
, struct got_object_id
**base_commit_id
,
6850 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
6851 struct got_repository
*repo
)
6853 const struct got_error
*err
= NULL
;
6854 char *tmp_branch_name
= NULL
;
6855 char *branch_ref_name
= NULL
;
6856 char *base_commit_ref_name
= NULL
;
6857 char *fileindex_path
= NULL
;
6858 struct check_rebase_ok_arg ok_arg
;
6859 struct got_reference
*wt_branch
= NULL
;
6860 struct got_reference
*base_commit_ref
= NULL
;
6864 *base_commit_id
= NULL
;
6867 err
= lock_worktree(worktree
, LOCK_EX
);
6871 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6875 ok_arg
.worktree
= worktree
;
6877 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6882 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
6886 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
6890 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
6895 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6900 err
= got_ref_alloc_symref(branch_ref
, branch_ref_name
, wt_branch
);
6904 err
= got_ref_write(*branch_ref
, repo
);
6908 err
= got_ref_alloc(&base_commit_ref
, base_commit_ref_name
,
6909 worktree
->base_commit_id
);
6912 err
= got_ref_write(base_commit_ref
, repo
);
6915 *base_commit_id
= got_object_id_dup(worktree
->base_commit_id
);
6916 if (*base_commit_id
== NULL
) {
6917 err
= got_error_from_errno("got_object_id_dup");
6921 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6922 worktree
->base_commit_id
);
6925 err
= got_ref_write(*tmp_branch
, repo
);
6929 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6933 free(fileindex_path
);
6934 free(tmp_branch_name
);
6935 free(branch_ref_name
);
6936 free(base_commit_ref_name
);
6938 got_ref_close(wt_branch
);
6941 got_ref_close(*branch_ref
);
6945 got_ref_close(*tmp_branch
);
6948 free(*base_commit_id
);
6950 got_fileindex_free(*fileindex
);
6953 lock_worktree(worktree
, LOCK_SH
);
6958 const struct got_error
*
6959 got_worktree_histedit_postpone(struct got_worktree
*worktree
,
6960 struct got_fileindex
*fileindex
)
6963 got_fileindex_free(fileindex
);
6964 return lock_worktree(worktree
, LOCK_SH
);
6967 const struct got_error
*
6968 got_worktree_histedit_in_progress(int *in_progress
,
6969 struct got_worktree
*worktree
)
6971 const struct got_error
*err
;
6972 char *tmp_branch_name
= NULL
;
6974 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
6978 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
6979 free(tmp_branch_name
);
6983 const struct got_error
*
6984 got_worktree_histedit_continue(struct got_object_id
**commit_id
,
6985 struct got_reference
**tmp_branch
, struct got_reference
**branch_ref
,
6986 struct got_object_id
**base_commit_id
, struct got_fileindex
**fileindex
,
6987 struct got_worktree
*worktree
, struct got_repository
*repo
)
6989 const struct got_error
*err
;
6990 char *commit_ref_name
= NULL
, *base_commit_ref_name
= NULL
;
6991 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
6992 struct got_reference
*commit_ref
= NULL
;
6993 struct got_reference
*base_commit_ref
= NULL
;
6994 char *fileindex_path
= NULL
;
6995 int have_staged_files
= 0;
6999 *base_commit_id
= NULL
;
7002 err
= lock_worktree(worktree
, LOCK_EX
);
7006 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7010 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
7011 &have_staged_files
);
7012 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7014 if (have_staged_files
) {
7015 err
= got_error(GOT_ERR_STAGED_PATHS
);
7019 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7023 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7027 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7031 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7036 err
= got_ref_open(branch_ref
, repo
, branch_ref_name
, 0);
7040 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
7043 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
7047 err
= got_ref_open(&base_commit_ref
, repo
, base_commit_ref_name
, 0);
7050 err
= got_ref_resolve(base_commit_id
, repo
, base_commit_ref
);
7054 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
7058 free(commit_ref_name
);
7059 free(branch_ref_name
);
7060 free(fileindex_path
);
7062 got_ref_close(commit_ref
);
7063 if (base_commit_ref
)
7064 got_ref_close(base_commit_ref
);
7068 free(*base_commit_id
);
7069 *base_commit_id
= NULL
;
7071 got_ref_close(*tmp_branch
);
7075 got_fileindex_free(*fileindex
);
7078 lock_worktree(worktree
, LOCK_EX
);
7083 static const struct got_error
*
7084 delete_histedit_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7086 const struct got_error
*err
;
7087 char *tmp_branch_name
= NULL
, *base_commit_ref_name
= NULL
;
7088 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
7090 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7093 err
= delete_ref(tmp_branch_name
, repo
);
7097 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7101 err
= delete_ref(base_commit_ref_name
, repo
);
7105 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7108 err
= delete_ref(branch_ref_name
, repo
);
7112 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7115 err
= delete_ref(commit_ref_name
, repo
);
7119 free(tmp_branch_name
);
7120 free(base_commit_ref_name
);
7121 free(branch_ref_name
);
7122 free(commit_ref_name
);
7126 const struct got_error
*
7127 got_worktree_histedit_abort(struct got_worktree
*worktree
,
7128 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7129 struct got_reference
*branch
, struct got_object_id
*base_commit_id
,
7130 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7132 const struct got_error
*err
, *unlockerr
, *sync_err
;
7133 struct got_reference
*resolved
= NULL
;
7134 char *fileindex_path
= NULL
;
7135 struct got_object_id
*tree_id
= NULL
;
7136 struct revert_file_args rfa
;
7138 err
= lock_worktree(worktree
, LOCK_EX
);
7142 err
= got_ref_open(&resolved
, repo
,
7143 got_ref_get_symref_target(branch
), 0);
7147 err
= got_worktree_set_head_ref(worktree
, resolved
);
7151 err
= got_worktree_set_base_commit_id(worktree
, repo
, base_commit_id
);
7155 err
= got_object_id_by_path(&tree_id
, repo
, base_commit_id
,
7156 worktree
->path_prefix
);
7160 err
= delete_histedit_refs(worktree
, repo
);
7164 err
= get_fileindex_path(&fileindex_path
, worktree
);
7168 rfa
.worktree
= worktree
;
7169 rfa
.fileindex
= fileindex
;
7170 rfa
.progress_cb
= progress_cb
;
7171 rfa
.progress_arg
= progress_arg
;
7172 rfa
.patch_cb
= NULL
;
7173 rfa
.patch_arg
= NULL
;
7175 rfa
.unlink_added_files
= 0;
7176 err
= worktree_status(worktree
, "", fileindex
, repo
,
7177 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
7181 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7182 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7184 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7185 if (sync_err
&& err
== NULL
)
7188 got_ref_close(resolved
);
7190 free(fileindex_path
);
7192 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7193 if (unlockerr
&& err
== NULL
)
7198 const struct got_error
*
7199 got_worktree_histedit_complete(struct got_worktree
*worktree
,
7200 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7201 struct got_reference
*edited_branch
, struct got_repository
*repo
)
7203 const struct got_error
*err
, *unlockerr
, *sync_err
;
7204 struct got_object_id
*new_head_commit_id
= NULL
;
7205 struct got_reference
*resolved
= NULL
;
7206 char *fileindex_path
= NULL
;
7208 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
7212 err
= got_ref_open(&resolved
, repo
,
7213 got_ref_get_symref_target(edited_branch
), 0);
7217 err
= create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX
,
7218 resolved
, new_head_commit_id
, repo
);
7222 err
= got_ref_change_ref(resolved
, new_head_commit_id
);
7226 err
= got_ref_write(resolved
, repo
);
7230 err
= got_worktree_set_head_ref(worktree
, resolved
);
7234 err
= delete_histedit_refs(worktree
, repo
);
7238 err
= get_fileindex_path(&fileindex_path
, worktree
);
7241 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7242 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7243 if (sync_err
&& err
== NULL
)
7246 got_fileindex_free(fileindex
);
7247 free(fileindex_path
);
7248 free(new_head_commit_id
);
7249 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7250 if (unlockerr
&& err
== NULL
)
7255 const struct got_error
*
7256 got_worktree_histedit_skip_commit(struct got_worktree
*worktree
,
7257 struct got_object_id
*commit_id
, struct got_repository
*repo
)
7259 const struct got_error
*err
;
7260 char *commit_ref_name
;
7262 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7266 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
7270 err
= delete_ref(commit_ref_name
, repo
);
7272 free(commit_ref_name
);
7276 const struct got_error
*
7277 got_worktree_integrate_prepare(struct got_fileindex
**fileindex
,
7278 struct got_reference
**branch_ref
, struct got_reference
**base_branch_ref
,
7279 struct got_worktree
*worktree
, const char *refname
,
7280 struct got_repository
*repo
)
7282 const struct got_error
*err
= NULL
;
7283 char *fileindex_path
= NULL
;
7284 struct check_rebase_ok_arg ok_arg
;
7288 *base_branch_ref
= NULL
;
7290 err
= lock_worktree(worktree
, LOCK_EX
);
7294 if (strcmp(refname
, got_worktree_get_head_ref_name(worktree
)) == 0) {
7295 err
= got_error_msg(GOT_ERR_SAME_BRANCH
,
7296 "cannot integrate a branch into itself; "
7297 "update -b or different branch name required");
7301 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7305 /* Preconditions are the same as for rebase. */
7306 ok_arg
.worktree
= worktree
;
7308 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7313 err
= got_ref_open(branch_ref
, repo
, refname
, 1);
7317 err
= got_ref_open(base_branch_ref
, repo
,
7318 got_worktree_get_head_ref_name(worktree
), 1);
7322 got_ref_close(*branch_ref
);
7325 if (*base_branch_ref
) {
7326 got_ref_close(*base_branch_ref
);
7327 *base_branch_ref
= NULL
;
7330 got_fileindex_free(*fileindex
);
7333 lock_worktree(worktree
, LOCK_SH
);
7338 const struct got_error
*
7339 got_worktree_integrate_continue(struct got_worktree
*worktree
,
7340 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7341 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
,
7342 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7343 got_cancel_cb cancel_cb
, void *cancel_arg
)
7345 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
7346 char *fileindex_path
= NULL
;
7347 struct got_object_id
*tree_id
= NULL
, *commit_id
= NULL
;
7349 err
= get_fileindex_path(&fileindex_path
, worktree
);
7353 err
= got_ref_resolve(&commit_id
, repo
, branch_ref
);
7357 err
= got_object_id_by_path(&tree_id
, repo
, commit_id
,
7358 worktree
->path_prefix
);
7362 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
7366 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
, repo
,
7367 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
7371 err
= got_ref_change_ref(base_branch_ref
, commit_id
);
7375 err
= got_ref_write(base_branch_ref
, repo
);
7379 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7381 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7382 if (sync_err
&& err
== NULL
)
7386 unlockerr
= got_ref_unlock(branch_ref
);
7387 if (unlockerr
&& err
== NULL
)
7389 got_ref_close(branch_ref
);
7391 unlockerr
= got_ref_unlock(base_branch_ref
);
7392 if (unlockerr
&& err
== NULL
)
7394 got_ref_close(base_branch_ref
);
7396 got_fileindex_free(fileindex
);
7397 free(fileindex_path
);
7400 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7401 if (unlockerr
&& err
== NULL
)
7406 const struct got_error
*
7407 got_worktree_integrate_abort(struct got_worktree
*worktree
,
7408 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7409 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
)
7411 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
7413 got_fileindex_free(fileindex
);
7415 err
= lock_worktree(worktree
, LOCK_SH
);
7417 unlockerr
= got_ref_unlock(branch_ref
);
7418 if (unlockerr
&& err
== NULL
)
7420 got_ref_close(branch_ref
);
7422 unlockerr
= got_ref_unlock(base_branch_ref
);
7423 if (unlockerr
&& err
== NULL
)
7425 got_ref_close(base_branch_ref
);
7430 const struct got_error
*
7431 got_worktree_merge_postpone(struct got_worktree
*worktree
,
7432 struct got_fileindex
*fileindex
)
7434 const struct got_error
*err
, *sync_err
;
7435 char *fileindex_path
= NULL
;
7437 err
= get_fileindex_path(&fileindex_path
, worktree
);
7441 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7443 err
= lock_worktree(worktree
, LOCK_SH
);
7444 if (sync_err
&& err
== NULL
)
7447 got_fileindex_free(fileindex
);
7448 free(fileindex_path
);
7452 static const struct got_error
*
7453 delete_merge_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7455 const struct got_error
*err
;
7456 char *branch_refname
= NULL
, *commit_refname
= NULL
;
7458 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7461 err
= delete_ref(branch_refname
, repo
);
7465 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7468 err
= delete_ref(commit_refname
, repo
);
7473 free(branch_refname
);
7474 free(commit_refname
);
7478 struct merge_commit_msg_arg
{
7479 struct got_worktree
*worktree
;
7480 const char *branch_name
;
7483 static const struct got_error
*
7484 merge_commit_msg_cb(struct got_pathlist_head
*commitable_paths
, char **logmsg
,
7487 struct merge_commit_msg_arg
*a
= arg
;
7489 if (asprintf(logmsg
, "merge %s into %s\n", a
->branch_name
,
7490 got_worktree_get_head_ref_name(a
->worktree
)) == -1)
7491 return got_error_from_errno("asprintf");
7496 static const struct got_error
*
7497 merge_status_cb(void *arg
, unsigned char status
, unsigned char staged_status
,
7498 const char *path
, struct got_object_id
*blob_id
,
7499 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
7500 int dirfd
, const char *de_name
)
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
)
7540 const struct got_error
*err
= NULL
, *sync_err
;
7541 struct got_pathlist_head commitable_paths
;
7542 struct collect_commitables_arg cc_arg
;
7543 struct got_pathlist_entry
*pe
;
7544 struct got_reference
*head_ref
= NULL
;
7545 struct got_object_id
*head_commit_id
= NULL
;
7546 int have_staged_files
= 0;
7547 struct merge_commit_msg_arg mcm_arg
;
7548 char *fileindex_path
= NULL
;
7550 *new_commit_id
= NULL
;
7552 TAILQ_INIT(&commitable_paths
);
7554 err
= get_fileindex_path(&fileindex_path
, worktree
);
7558 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
7562 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
7566 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
7567 &have_staged_files
);
7568 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7570 if (have_staged_files
) {
7571 err
= got_error(GOT_ERR_MERGE_STAGED_PATHS
);
7575 cc_arg
.commitable_paths
= &commitable_paths
;
7576 cc_arg
.worktree
= worktree
;
7577 cc_arg
.fileindex
= fileindex
;
7579 cc_arg
.have_staged_files
= have_staged_files
;
7580 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
7581 err
= worktree_status(worktree
, "", fileindex
, repo
,
7582 collect_commitables
, &cc_arg
, NULL
, NULL
, 0, 0);
7586 if (TAILQ_EMPTY(&commitable_paths
)) {
7587 err
= got_error_fmt(GOT_ERR_COMMIT_NO_CHANGES
,
7588 "merge of %s cannot proceed", branch_name
);
7592 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
7593 struct got_commitable
*ct
= pe
->data
;
7594 const char *ct_path
= ct
->in_repo_path
;
7596 while (ct_path
[0] == '/')
7598 err
= check_out_of_date(ct_path
, ct
->status
,
7599 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
7600 head_commit_id
, repo
, GOT_ERR_MERGE_COMMIT_OUT_OF_DATE
);
7606 mcm_arg
.worktree
= worktree
;
7607 mcm_arg
.branch_name
= branch_name
;
7608 err
= commit_worktree(new_commit_id
, &commitable_paths
,
7609 head_commit_id
, branch_tip
, worktree
, author
, committer
,
7610 merge_commit_msg_cb
, &mcm_arg
, merge_status_cb
, NULL
, repo
);
7614 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
7615 *new_commit_id
, fileindex
, have_staged_files
);
7616 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7617 if (sync_err
&& err
== NULL
)
7620 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
7621 struct got_commitable
*ct
= pe
->data
;
7622 free_commitable(ct
);
7624 got_pathlist_free(&commitable_paths
);
7625 free(fileindex_path
);
7629 const struct got_error
*
7630 got_worktree_merge_complete(struct got_worktree
*worktree
,
7631 struct got_fileindex
*fileindex
, struct got_repository
*repo
)
7633 const struct got_error
*err
, *unlockerr
, *sync_err
;
7634 char *fileindex_path
= NULL
;
7636 err
= delete_merge_refs(worktree
, repo
);
7640 err
= get_fileindex_path(&fileindex_path
, worktree
);
7643 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7644 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7645 if (sync_err
&& err
== NULL
)
7648 got_fileindex_free(fileindex
);
7649 free(fileindex_path
);
7650 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7651 if (unlockerr
&& err
== NULL
)
7656 const struct got_error
*
7657 got_worktree_merge_in_progress(int *in_progress
, struct got_worktree
*worktree
,
7658 struct got_repository
*repo
)
7660 const struct got_error
*err
;
7661 char *branch_refname
= NULL
;
7662 struct got_reference
*branch_ref
= NULL
;
7666 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7669 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
7670 free(branch_refname
);
7672 if (err
->code
!= GOT_ERR_NOT_REF
)
7680 const struct got_error
*got_worktree_merge_prepare(
7681 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
7682 struct got_reference
*branch
, struct got_repository
*repo
)
7684 const struct got_error
*err
= NULL
;
7685 char *fileindex_path
= NULL
;
7686 char *branch_refname
= NULL
, *commit_refname
= NULL
;
7687 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
7688 struct got_reference
*commit_ref
= NULL
;
7689 struct got_object_id
*branch_tip
= NULL
, *wt_branch_tip
= NULL
;
7690 struct check_rebase_ok_arg ok_arg
;
7694 err
= lock_worktree(worktree
, LOCK_EX
);
7698 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7702 /* Preconditions are the same as for rebase. */
7703 ok_arg
.worktree
= worktree
;
7705 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7710 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7714 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7718 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
7723 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
7727 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
7728 err
= got_error(GOT_ERR_MERGE_OUT_OF_DATE
);
7732 err
= got_ref_resolve(&branch_tip
, repo
, branch
);
7736 err
= got_ref_alloc_symref(&branch_ref
, branch_refname
, branch
);
7739 err
= got_ref_write(branch_ref
, repo
);
7743 err
= got_ref_alloc(&commit_ref
, commit_refname
, branch_tip
);
7746 err
= got_ref_write(commit_ref
, repo
);
7751 free(branch_refname
);
7752 free(commit_refname
);
7753 free(fileindex_path
);
7755 got_ref_close(branch_ref
);
7757 got_ref_close(commit_ref
);
7759 got_ref_close(wt_branch
);
7760 free(wt_branch_tip
);
7763 got_fileindex_free(*fileindex
);
7766 lock_worktree(worktree
, LOCK_SH
);
7771 const struct got_error
*
7772 got_worktree_merge_continue(char **branch_name
,
7773 struct got_object_id
**branch_tip
, struct got_fileindex
**fileindex
,
7774 struct got_worktree
*worktree
, struct got_repository
*repo
)
7776 const struct got_error
*err
;
7777 char *commit_refname
= NULL
, *branch_refname
= NULL
;
7778 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
7779 char *fileindex_path
= NULL
;
7780 int have_staged_files
= 0;
7782 *branch_name
= NULL
;
7786 err
= lock_worktree(worktree
, LOCK_EX
);
7790 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7794 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
7795 &have_staged_files
);
7796 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
7798 if (have_staged_files
) {
7799 err
= got_error(GOT_ERR_STAGED_PATHS
);
7803 err
= get_merge_branch_ref_name(&branch_refname
, worktree
);
7807 err
= get_merge_commit_ref_name(&commit_refname
, worktree
);
7811 err
= got_ref_open(&branch_ref
, repo
, branch_refname
, 0);
7815 if (!got_ref_is_symbolic(branch_ref
)) {
7816 err
= got_error_fmt(GOT_ERR_BAD_REF_TYPE
,
7817 "%s is not a symbolic reference",
7818 got_ref_get_name(branch_ref
));
7821 *branch_name
= strdup(got_ref_get_symref_target(branch_ref
));
7822 if (*branch_name
== NULL
) {
7823 err
= got_error_from_errno("strdup");
7827 err
= got_ref_open(&commit_ref
, repo
, commit_refname
, 0);
7831 err
= got_ref_resolve(branch_tip
, repo
, commit_ref
);
7835 free(commit_refname
);
7836 free(branch_refname
);
7837 free(fileindex_path
);
7839 got_ref_close(commit_ref
);
7841 got_ref_close(branch_ref
);
7845 *branch_name
= NULL
;
7850 got_fileindex_free(*fileindex
);
7853 lock_worktree(worktree
, LOCK_SH
);
7858 const struct got_error
*
7859 got_worktree_merge_abort(struct got_worktree
*worktree
,
7860 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7861 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7863 const struct got_error
*err
, *unlockerr
, *sync_err
;
7864 struct got_object_id
*commit_id
= NULL
;
7865 char *fileindex_path
= NULL
;
7866 struct revert_file_args rfa
;
7867 struct got_object_id
*tree_id
= NULL
;
7869 err
= got_object_id_by_path(&tree_id
, repo
,
7870 worktree
->base_commit_id
, worktree
->path_prefix
);
7874 err
= delete_merge_refs(worktree
, repo
);
7878 err
= get_fileindex_path(&fileindex_path
, worktree
);
7882 rfa
.worktree
= worktree
;
7883 rfa
.fileindex
= fileindex
;
7884 rfa
.progress_cb
= progress_cb
;
7885 rfa
.progress_arg
= progress_arg
;
7886 rfa
.patch_cb
= NULL
;
7887 rfa
.patch_arg
= NULL
;
7889 rfa
.unlink_added_files
= 1;
7890 err
= worktree_status(worktree
, "", fileindex
, repo
,
7891 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
7895 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7896 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7898 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7899 if (sync_err
&& err
== NULL
)
7905 got_fileindex_free(fileindex
);
7906 free(fileindex_path
);
7908 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7909 if (unlockerr
&& err
== NULL
)
7914 struct check_stage_ok_arg
{
7915 struct got_object_id
*head_commit_id
;
7916 struct got_worktree
*worktree
;
7917 struct got_fileindex
*fileindex
;
7918 struct got_repository
*repo
;
7922 const struct got_error
*
7923 check_stage_ok(void *arg
, unsigned char status
,
7924 unsigned char staged_status
, const char *relpath
,
7925 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
7926 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
7928 struct check_stage_ok_arg
*a
= arg
;
7929 const struct got_error
*err
= NULL
;
7930 struct got_fileindex_entry
*ie
;
7931 struct got_object_id base_commit_id
;
7932 struct got_object_id
*base_commit_idp
= NULL
;
7933 char *in_repo_path
= NULL
, *p
;
7935 if (status
== GOT_STATUS_UNVERSIONED
||
7936 status
== GOT_STATUS_NO_CHANGE
)
7938 if (status
== GOT_STATUS_NONEXISTENT
)
7939 return got_error_set_errno(ENOENT
, relpath
);
7941 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
7943 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
7945 if (asprintf(&in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
7946 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
7948 return got_error_from_errno("asprintf");
7950 if (got_fileindex_entry_has_commit(ie
)) {
7951 memcpy(base_commit_id
.sha1
, ie
->commit_sha1
,
7952 SHA1_DIGEST_LENGTH
);
7953 base_commit_idp
= &base_commit_id
;
7956 if (status
== GOT_STATUS_CONFLICT
) {
7957 err
= got_error_path(ie
->path
, GOT_ERR_STAGE_CONFLICT
);
7959 } else if (status
!= GOT_STATUS_ADD
&&
7960 status
!= GOT_STATUS_MODIFY
&&
7961 status
!= GOT_STATUS_DELETE
) {
7962 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STATUS
);
7966 a
->have_changes
= 1;
7971 err
= check_out_of_date(p
, status
, staged_status
,
7972 blob_id
, base_commit_idp
, a
->head_commit_id
, a
->repo
,
7973 GOT_ERR_STAGE_OUT_OF_DATE
);
7979 struct stage_path_arg
{
7980 struct got_worktree
*worktree
;
7981 struct got_fileindex
*fileindex
;
7982 struct got_repository
*repo
;
7983 got_worktree_status_cb status_cb
;
7985 got_worktree_patch_cb patch_cb
;
7987 int staged_something
;
7988 int allow_bad_symlinks
;
7991 static const struct got_error
*
7992 stage_path(void *arg
, unsigned char status
,
7993 unsigned char staged_status
, const char *relpath
,
7994 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
7995 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
7997 struct stage_path_arg
*a
= arg
;
7998 const struct got_error
*err
= NULL
;
7999 struct got_fileindex_entry
*ie
;
8000 char *ondisk_path
= NULL
, *path_content
= NULL
;
8002 struct got_object_id
*new_staged_blob_id
= NULL
;
8005 if (status
== GOT_STATUS_UNVERSIONED
)
8008 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8010 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8012 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
8014 return got_error_from_errno("asprintf");
8017 case GOT_STATUS_ADD
:
8018 case GOT_STATUS_MODIFY
:
8019 /* XXX could sb.st_mode be passed in by our caller? */
8020 if (lstat(ondisk_path
, &sb
) == -1) {
8021 err
= got_error_from_errno2("lstat", ondisk_path
);
8025 if (status
== GOT_STATUS_ADD
) {
8026 int choice
= GOT_PATCH_CHOICE_NONE
;
8027 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8028 status
, ie
->path
, NULL
, 1, 1);
8031 if (choice
!= GOT_PATCH_CHOICE_YES
)
8034 err
= create_patched_content(&path_content
, 0,
8035 staged_blob_id
? staged_blob_id
: blob_id
,
8036 ondisk_path
, dirfd
, de_name
, ie
->path
,
8037 a
->repo
, a
->patch_cb
, a
->patch_arg
);
8038 if (err
|| path_content
== NULL
)
8042 err
= got_object_blob_create(&new_staged_blob_id
,
8043 path_content
? path_content
: ondisk_path
, a
->repo
);
8046 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
8047 SHA1_DIGEST_LENGTH
);
8048 if (status
== GOT_STATUS_ADD
|| staged_status
== GOT_STATUS_ADD
)
8049 stage
= GOT_FILEIDX_STAGE_ADD
;
8051 stage
= GOT_FILEIDX_STAGE_MODIFY
;
8052 got_fileindex_entry_stage_set(ie
, stage
);
8053 if (S_ISLNK(sb
.st_mode
)) {
8054 int is_bad_symlink
= 0;
8055 if (!a
->allow_bad_symlinks
) {
8056 char target_path
[PATH_MAX
];
8058 target_len
= readlink(ondisk_path
, target_path
,
8059 sizeof(target_path
));
8060 if (target_len
== -1) {
8061 err
= got_error_from_errno2("readlink",
8065 err
= is_bad_symlink_target(&is_bad_symlink
,
8066 target_path
, target_len
, ondisk_path
,
8067 a
->worktree
->root_path
);
8070 if (is_bad_symlink
) {
8071 err
= got_error_path(ondisk_path
,
8072 GOT_ERR_BAD_SYMLINK
);
8077 got_fileindex_entry_staged_filetype_set(ie
,
8078 GOT_FILEIDX_MODE_BAD_SYMLINK
);
8080 got_fileindex_entry_staged_filetype_set(ie
,
8081 GOT_FILEIDX_MODE_SYMLINK
);
8083 got_fileindex_entry_staged_filetype_set(ie
,
8084 GOT_FILEIDX_MODE_REGULAR_FILE
);
8086 a
->staged_something
= 1;
8087 if (a
->status_cb
== NULL
)
8089 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
8090 get_staged_status(ie
), relpath
, blob_id
,
8091 new_staged_blob_id
, NULL
, dirfd
, de_name
);
8093 case GOT_STATUS_DELETE
:
8094 if (staged_status
== GOT_STATUS_DELETE
)
8097 int choice
= GOT_PATCH_CHOICE_NONE
;
8098 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
, status
,
8099 ie
->path
, NULL
, 1, 1);
8102 if (choice
== GOT_PATCH_CHOICE_NO
)
8104 if (choice
!= GOT_PATCH_CHOICE_YES
) {
8105 err
= got_error(GOT_ERR_PATCH_CHOICE
);
8109 stage
= GOT_FILEIDX_STAGE_DELETE
;
8110 got_fileindex_entry_stage_set(ie
, stage
);
8111 a
->staged_something
= 1;
8112 if (a
->status_cb
== NULL
)
8114 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
8115 get_staged_status(ie
), relpath
, NULL
, NULL
, NULL
, dirfd
,
8118 case GOT_STATUS_NO_CHANGE
:
8120 case GOT_STATUS_CONFLICT
:
8121 err
= got_error_path(relpath
, GOT_ERR_STAGE_CONFLICT
);
8123 case GOT_STATUS_NONEXISTENT
:
8124 err
= got_error_set_errno(ENOENT
, relpath
);
8127 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8131 if (path_content
&& unlink(path_content
) == -1 && err
== NULL
)
8132 err
= got_error_from_errno2("unlink", path_content
);
8135 free(new_staged_blob_id
);
8139 const struct got_error
*
8140 got_worktree_stage(struct got_worktree
*worktree
,
8141 struct got_pathlist_head
*paths
,
8142 got_worktree_status_cb status_cb
, void *status_arg
,
8143 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8144 int allow_bad_symlinks
, struct got_repository
*repo
)
8146 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8147 struct got_pathlist_entry
*pe
;
8148 struct got_fileindex
*fileindex
= NULL
;
8149 char *fileindex_path
= NULL
;
8150 struct got_reference
*head_ref
= NULL
;
8151 struct got_object_id
*head_commit_id
= NULL
;
8152 struct check_stage_ok_arg oka
;
8153 struct stage_path_arg spa
;
8155 err
= lock_worktree(worktree
, LOCK_EX
);
8159 err
= got_ref_open(&head_ref
, repo
,
8160 got_worktree_get_head_ref_name(worktree
), 0);
8163 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
8166 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8170 /* Check pre-conditions before staging anything. */
8171 oka
.head_commit_id
= head_commit_id
;
8172 oka
.worktree
= worktree
;
8173 oka
.fileindex
= fileindex
;
8175 oka
.have_changes
= 0;
8176 TAILQ_FOREACH(pe
, paths
, entry
) {
8177 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8178 check_stage_ok
, &oka
, NULL
, NULL
, 0, 0);
8182 if (!oka
.have_changes
) {
8183 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
8187 spa
.worktree
= worktree
;
8188 spa
.fileindex
= fileindex
;
8190 spa
.patch_cb
= patch_cb
;
8191 spa
.patch_arg
= patch_arg
;
8192 spa
.status_cb
= status_cb
;
8193 spa
.status_arg
= status_arg
;
8194 spa
.staged_something
= 0;
8195 spa
.allow_bad_symlinks
= allow_bad_symlinks
;
8196 TAILQ_FOREACH(pe
, paths
, entry
) {
8197 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8198 stage_path
, &spa
, NULL
, NULL
, 0, 0);
8202 if (!spa
.staged_something
) {
8203 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
8207 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8208 if (sync_err
&& err
== NULL
)
8212 got_ref_close(head_ref
);
8213 free(head_commit_id
);
8214 free(fileindex_path
);
8216 got_fileindex_free(fileindex
);
8217 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8218 if (unlockerr
&& err
== NULL
)
8223 struct unstage_path_arg
{
8224 struct got_worktree
*worktree
;
8225 struct got_fileindex
*fileindex
;
8226 struct got_repository
*repo
;
8227 got_worktree_checkout_cb progress_cb
;
8229 got_worktree_patch_cb patch_cb
;
8233 static const struct got_error
*
8234 create_unstaged_content(char **path_unstaged_content
,
8235 char **path_new_staged_content
, struct got_object_id
*blob_id
,
8236 struct got_object_id
*staged_blob_id
, const char *relpath
,
8237 struct got_repository
*repo
,
8238 got_worktree_patch_cb patch_cb
, void *patch_arg
)
8240 const struct got_error
*err
, *free_err
;
8241 struct got_blob_object
*blob
= NULL
, *staged_blob
= NULL
;
8242 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
, *rejectfile
= NULL
;
8243 char *path1
= NULL
, *path2
= NULL
, *label1
= NULL
;
8244 struct got_diffreg_result
*diffreg_result
= NULL
;
8245 int line_cur1
= 1, line_cur2
= 1, n
= 0, nchunks_used
= 0;
8246 int have_content
= 0, have_rejected_content
= 0, i
= 0, nchanges
= 0;
8248 *path_unstaged_content
= NULL
;
8249 *path_new_staged_content
= NULL
;
8251 err
= got_object_id_str(&label1
, blob_id
);
8254 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192);
8258 err
= got_opentemp_named(&path1
, &f1
, "got-unstage-blob-base");
8262 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
8266 err
= got_object_open_as_blob(&staged_blob
, repo
, staged_blob_id
, 8192);
8270 err
= got_opentemp_named(&path2
, &f2
, "got-unstage-blob-staged");
8274 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f2
, staged_blob
);
8278 err
= got_diff_files(&diffreg_result
, f1
, label1
, f2
,
8279 path2
, 3, 0, 1, NULL
);
8283 err
= got_opentemp_named(path_unstaged_content
, &outfile
,
8284 "got-unstaged-content");
8287 err
= got_opentemp_named(path_new_staged_content
, &rejectfile
,
8288 "got-new-staged-content");
8292 if (fseek(f1
, 0L, SEEK_SET
) == -1) {
8293 err
= got_ferror(f1
, GOT_ERR_IO
);
8296 if (fseek(f2
, 0L, SEEK_SET
) == -1) {
8297 err
= got_ferror(f2
, GOT_ERR_IO
);
8300 /* Count the number of actual changes in the diff result. */
8301 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
8302 struct diff_chunk_context cc
= {};
8303 diff_chunk_context_load_change(&cc
, &nchunks_used
,
8304 diffreg_result
->result
, n
, 0);
8307 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
8309 err
= apply_or_reject_change(&choice
, &nchunks_used
,
8310 diffreg_result
->result
, n
, relpath
, f1
, f2
,
8311 &line_cur1
, &line_cur2
,
8312 outfile
, rejectfile
, ++i
, nchanges
, patch_cb
, patch_arg
);
8315 if (choice
== GOT_PATCH_CHOICE_YES
)
8318 have_rejected_content
= 1;
8319 if (choice
== GOT_PATCH_CHOICE_QUIT
)
8322 if (have_content
|| have_rejected_content
)
8323 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
8324 outfile
, rejectfile
);
8328 got_object_blob_close(blob
);
8330 got_object_blob_close(staged_blob
);
8331 free_err
= got_diffreg_result_free(diffreg_result
);
8332 if (free_err
&& err
== NULL
)
8334 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
8335 err
= got_error_from_errno2("fclose", path1
);
8336 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
8337 err
= got_error_from_errno2("fclose", path2
);
8338 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
8339 err
= got_error_from_errno2("fclose", *path_unstaged_content
);
8340 if (rejectfile
&& fclose(rejectfile
) == EOF
&& err
== NULL
)
8341 err
= got_error_from_errno2("fclose", *path_new_staged_content
);
8342 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
8343 err
= got_error_from_errno2("unlink", path1
);
8344 if (path2
&& unlink(path2
) == -1 && err
== NULL
)
8345 err
= got_error_from_errno2("unlink", path2
);
8346 if (err
|| !have_content
) {
8347 if (*path_unstaged_content
&&
8348 unlink(*path_unstaged_content
) == -1 && err
== NULL
)
8349 err
= got_error_from_errno2("unlink",
8350 *path_unstaged_content
);
8351 free(*path_unstaged_content
);
8352 *path_unstaged_content
= NULL
;
8354 if (err
|| !have_content
|| !have_rejected_content
) {
8355 if (*path_new_staged_content
&&
8356 unlink(*path_new_staged_content
) == -1 && err
== NULL
)
8357 err
= got_error_from_errno2("unlink",
8358 *path_new_staged_content
);
8359 free(*path_new_staged_content
);
8360 *path_new_staged_content
= NULL
;
8367 static const struct got_error
*
8368 unstage_hunks(struct got_object_id
*staged_blob_id
,
8369 struct got_blob_object
*blob_base
,
8370 struct got_object_id
*blob_id
, struct got_fileindex_entry
*ie
,
8371 const char *ondisk_path
, const char *label_orig
,
8372 struct got_worktree
*worktree
, struct got_repository
*repo
,
8373 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8374 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
8376 const struct got_error
*err
= NULL
;
8377 char *path_unstaged_content
= NULL
;
8378 char *path_new_staged_content
= NULL
;
8379 char *parent
= NULL
, *base_path
= NULL
;
8380 char *blob_base_path
= NULL
;
8381 struct got_object_id
*new_staged_blob_id
= NULL
;
8382 FILE *f
= NULL
, *f_base
= NULL
, *f_deriv2
= NULL
;
8385 err
= create_unstaged_content(&path_unstaged_content
,
8386 &path_new_staged_content
, blob_id
, staged_blob_id
,
8387 ie
->path
, repo
, patch_cb
, patch_arg
);
8391 if (path_unstaged_content
== NULL
)
8394 if (path_new_staged_content
) {
8395 err
= got_object_blob_create(&new_staged_blob_id
,
8396 path_new_staged_content
, repo
);
8401 f
= fopen(path_unstaged_content
, "r");
8403 err
= got_error_from_errno2("fopen",
8404 path_unstaged_content
);
8407 if (fstat(fileno(f
), &sb
) == -1) {
8408 err
= got_error_from_errno2("fstat", path_unstaged_content
);
8411 if (got_fileindex_entry_staged_filetype_get(ie
) ==
8412 GOT_FILEIDX_MODE_SYMLINK
&& sb
.st_size
< PATH_MAX
) {
8413 char link_target
[PATH_MAX
];
8415 r
= fread(link_target
, 1, sizeof(link_target
), f
);
8416 if (r
== 0 && ferror(f
)) {
8417 err
= got_error_from_errno("fread");
8420 if (r
>= sizeof(link_target
)) { /* should not happen */
8421 err
= got_error(GOT_ERR_NO_SPACE
);
8424 link_target
[r
] = '\0';
8425 err
= merge_symlink(worktree
, blob_base
,
8426 ondisk_path
, ie
->path
, label_orig
, link_target
,
8427 worktree
->base_commit_id
, repo
, progress_cb
,
8430 int local_changes_subsumed
;
8432 err
= got_path_dirname(&parent
, ondisk_path
);
8436 if (asprintf(&base_path
, "%s/got-unstage-blob-orig",
8438 err
= got_error_from_errno("asprintf");
8443 err
= got_opentemp_named(&blob_base_path
, &f_base
, base_path
);
8446 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_base
,
8452 * In order the run a 3-way merge with a symlink we copy the symlink's
8453 * target path into a temporary file and use that file with diff3.
8455 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
8456 err
= dump_symlink_target_path_to_file(&f_deriv2
,
8462 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
);
8464 err
= got_error_from_errno2("open", ondisk_path
);
8467 f_deriv2
= fdopen(fd
, "r");
8468 if (f_deriv2
== NULL
) {
8469 err
= got_error_from_errno2("fdopen", ondisk_path
);
8475 err
= merge_file(&local_changes_subsumed
, worktree
,
8476 f_base
, f
, f_deriv2
, ondisk_path
, ie
->path
,
8477 got_fileindex_perms_to_st(ie
),
8478 label_orig
, "unstaged", NULL
, GOT_DIFF_ALGORITHM_MYERS
,
8479 repo
, progress_cb
, progress_arg
);
8484 if (new_staged_blob_id
) {
8485 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
8486 SHA1_DIGEST_LENGTH
);
8488 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
8489 got_fileindex_entry_staged_filetype_set(ie
, 0);
8492 free(new_staged_blob_id
);
8493 if (path_unstaged_content
&&
8494 unlink(path_unstaged_content
) == -1 && err
== NULL
)
8495 err
= got_error_from_errno2("unlink", path_unstaged_content
);
8496 if (path_new_staged_content
&&
8497 unlink(path_new_staged_content
) == -1 && err
== NULL
)
8498 err
= got_error_from_errno2("unlink", path_new_staged_content
);
8499 if (blob_base_path
&& unlink(blob_base_path
) == -1 && err
== NULL
)
8500 err
= got_error_from_errno2("unlink", blob_base_path
);
8501 if (f_base
&& fclose(f_base
) == EOF
&& err
== NULL
)
8502 err
= got_error_from_errno2("fclose", path_unstaged_content
);
8503 if (f
&& fclose(f
) == EOF
&& err
== NULL
)
8504 err
= got_error_from_errno2("fclose", path_unstaged_content
);
8505 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
8506 err
= got_error_from_errno2("fclose", ondisk_path
);
8507 free(path_unstaged_content
);
8508 free(path_new_staged_content
);
8509 free(blob_base_path
);
8515 static const struct got_error
*
8516 unstage_path(void *arg
, unsigned char status
,
8517 unsigned char staged_status
, const char *relpath
,
8518 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
8519 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
8521 const struct got_error
*err
= NULL
;
8522 struct unstage_path_arg
*a
= arg
;
8523 struct got_fileindex_entry
*ie
;
8524 struct got_blob_object
*blob_base
= NULL
, *blob_staged
= NULL
;
8525 char *ondisk_path
= NULL
;
8526 char *id_str
= NULL
, *label_orig
= NULL
;
8527 int local_changes_subsumed
;
8530 if (staged_status
!= GOT_STATUS_ADD
&&
8531 staged_status
!= GOT_STATUS_MODIFY
&&
8532 staged_status
!= GOT_STATUS_DELETE
)
8535 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
8537 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
8539 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, relpath
)
8541 return got_error_from_errno("asprintf");
8543 err
= got_object_id_str(&id_str
,
8544 commit_id
? commit_id
: a
->worktree
->base_commit_id
);
8547 if (asprintf(&label_orig
, "%s: commit %s", GOT_MERGE_LABEL_BASE
,
8549 err
= got_error_from_errno("asprintf");
8553 switch (staged_status
) {
8554 case GOT_STATUS_MODIFY
:
8555 err
= got_object_open_as_blob(&blob_base
, a
->repo
,
8560 case GOT_STATUS_ADD
:
8562 if (staged_status
== GOT_STATUS_ADD
) {
8563 int choice
= GOT_PATCH_CHOICE_NONE
;
8564 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8565 staged_status
, ie
->path
, NULL
, 1, 1);
8568 if (choice
!= GOT_PATCH_CHOICE_YES
)
8571 err
= unstage_hunks(staged_blob_id
,
8572 blob_base
, blob_id
, ie
, ondisk_path
,
8573 label_orig
, a
->worktree
, a
->repo
,
8574 a
->patch_cb
, a
->patch_arg
,
8575 a
->progress_cb
, a
->progress_arg
);
8576 break; /* Done with this file. */
8579 err
= got_object_open_as_blob(&blob_staged
, a
->repo
,
8580 staged_blob_id
, 8192);
8583 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
8584 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
8585 case GOT_FILEIDX_MODE_REGULAR_FILE
:
8586 err
= merge_blob(&local_changes_subsumed
, a
->worktree
,
8587 blob_base
, ondisk_path
, relpath
,
8588 got_fileindex_perms_to_st(ie
), label_orig
,
8589 blob_staged
, commit_id
? commit_id
:
8590 a
->worktree
->base_commit_id
, a
->repo
,
8591 a
->progress_cb
, a
->progress_arg
);
8593 case GOT_FILEIDX_MODE_SYMLINK
:
8594 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
8595 char *staged_target
;
8596 err
= got_object_blob_read_to_str(
8597 &staged_target
, blob_staged
);
8600 err
= merge_symlink(a
->worktree
, blob_base
,
8601 ondisk_path
, relpath
, label_orig
,
8602 staged_target
, commit_id
? commit_id
:
8603 a
->worktree
->base_commit_id
,
8604 a
->repo
, a
->progress_cb
, a
->progress_arg
);
8605 free(staged_target
);
8607 err
= merge_blob(&local_changes_subsumed
,
8608 a
->worktree
, blob_base
, ondisk_path
,
8609 relpath
, got_fileindex_perms_to_st(ie
),
8610 label_orig
, blob_staged
,
8611 commit_id
? commit_id
:
8612 a
->worktree
->base_commit_id
, a
->repo
,
8613 a
->progress_cb
, a
->progress_arg
);
8617 err
= got_error_path(relpath
, GOT_ERR_BAD_FILETYPE
);
8621 got_fileindex_entry_stage_set(ie
,
8622 GOT_FILEIDX_STAGE_NONE
);
8623 got_fileindex_entry_staged_filetype_set(ie
, 0);
8626 case GOT_STATUS_DELETE
:
8628 int choice
= GOT_PATCH_CHOICE_NONE
;
8629 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8630 staged_status
, ie
->path
, NULL
, 1, 1);
8633 if (choice
== GOT_PATCH_CHOICE_NO
)
8635 if (choice
!= GOT_PATCH_CHOICE_YES
) {
8636 err
= got_error(GOT_ERR_PATCH_CHOICE
);
8640 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
8641 got_fileindex_entry_staged_filetype_set(ie
, 0);
8642 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
8643 dirfd
, de_name
, a
->repo
);
8646 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, relpath
);
8652 got_object_blob_close(blob_base
);
8654 got_object_blob_close(blob_staged
);
8660 const struct got_error
*
8661 got_worktree_unstage(struct got_worktree
*worktree
,
8662 struct got_pathlist_head
*paths
,
8663 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
8664 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8665 struct got_repository
*repo
)
8667 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8668 struct got_pathlist_entry
*pe
;
8669 struct got_fileindex
*fileindex
= NULL
;
8670 char *fileindex_path
= NULL
;
8671 struct unstage_path_arg upa
;
8673 err
= lock_worktree(worktree
, LOCK_EX
);
8677 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8681 upa
.worktree
= worktree
;
8682 upa
.fileindex
= fileindex
;
8684 upa
.progress_cb
= progress_cb
;
8685 upa
.progress_arg
= progress_arg
;
8686 upa
.patch_cb
= patch_cb
;
8687 upa
.patch_arg
= patch_arg
;
8688 TAILQ_FOREACH(pe
, paths
, entry
) {
8689 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8690 unstage_path
, &upa
, NULL
, NULL
, 0, 0);
8695 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8696 if (sync_err
&& err
== NULL
)
8699 free(fileindex_path
);
8701 got_fileindex_free(fileindex
);
8702 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8703 if (unlockerr
&& err
== NULL
)
8708 struct report_file_info_arg
{
8709 struct got_worktree
*worktree
;
8710 got_worktree_path_info_cb info_cb
;
8712 struct got_pathlist_head
*paths
;
8713 got_cancel_cb cancel_cb
;
8717 static const struct got_error
*
8718 report_file_info(void *arg
, struct got_fileindex_entry
*ie
)
8720 struct report_file_info_arg
*a
= arg
;
8721 struct got_pathlist_entry
*pe
;
8722 struct got_object_id blob_id
, staged_blob_id
, commit_id
;
8723 struct got_object_id
*blob_idp
= NULL
, *staged_blob_idp
= NULL
;
8724 struct got_object_id
*commit_idp
= NULL
;
8727 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
8728 return got_error(GOT_ERR_CANCELLED
);
8730 TAILQ_FOREACH(pe
, a
->paths
, entry
) {
8731 if (pe
->path_len
== 0 || strcmp(pe
->path
, ie
->path
) == 0 ||
8732 got_path_is_child(ie
->path
, pe
->path
, pe
->path_len
))
8735 if (pe
== NULL
) /* not found */
8738 if (got_fileindex_entry_has_blob(ie
)) {
8739 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
8740 blob_idp
= &blob_id
;
8742 stage
= got_fileindex_entry_stage_get(ie
);
8743 if (stage
== GOT_FILEIDX_STAGE_MODIFY
||
8744 stage
== GOT_FILEIDX_STAGE_ADD
) {
8745 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
8746 SHA1_DIGEST_LENGTH
);
8747 staged_blob_idp
= &staged_blob_id
;
8750 if (got_fileindex_entry_has_commit(ie
)) {
8751 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
8752 commit_idp
= &commit_id
;
8755 return a
->info_cb(a
->info_arg
, ie
->path
, got_fileindex_perms_to_st(ie
),
8756 (time_t)ie
->mtime_sec
, blob_idp
, staged_blob_idp
, commit_idp
);
8759 const struct got_error
*
8760 got_worktree_path_info(struct got_worktree
*worktree
,
8761 struct got_pathlist_head
*paths
,
8762 got_worktree_path_info_cb info_cb
, void *info_arg
,
8763 got_cancel_cb cancel_cb
, void *cancel_arg
)
8766 const struct got_error
*err
= NULL
, *unlockerr
;
8767 struct got_fileindex
*fileindex
= NULL
;
8768 char *fileindex_path
= NULL
;
8769 struct report_file_info_arg arg
;
8771 err
= lock_worktree(worktree
, LOCK_SH
);
8775 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8779 arg
.worktree
= worktree
;
8780 arg
.info_cb
= info_cb
;
8781 arg
.info_arg
= info_arg
;
8783 arg
.cancel_cb
= cancel_cb
;
8784 arg
.cancel_arg
= cancel_arg
;
8785 err
= got_fileindex_for_each_entry_safe(fileindex
, report_file_info
,
8788 free(fileindex_path
);
8790 got_fileindex_free(fileindex
);
8791 unlockerr
= lock_worktree(worktree
, LOCK_UN
);
8792 if (unlockerr
&& err
== NULL
)