2 * Copyright (c) 2018, 2019, 2020 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <sys/queue.h>
38 #include "got_error.h"
39 #include "got_repository.h"
40 #include "got_reference.h"
41 #include "got_object.h"
43 #include "got_cancel.h"
44 #include "got_worktree.h"
45 #include "got_opentemp.h"
48 #include "got_lib_worktree.h"
49 #include "got_lib_sha1.h"
50 #include "got_lib_fileindex.h"
51 #include "got_lib_inflate.h"
52 #include "got_lib_delta.h"
53 #include "got_lib_object.h"
54 #include "got_lib_object_parse.h"
55 #include "got_lib_object_create.h"
56 #include "got_lib_object_idset.h"
57 #include "got_lib_diff.h"
58 #include "got_lib_gotconfig.h"
61 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
64 #define GOT_MERGE_LABEL_MERGED "merged change"
65 #define GOT_MERGE_LABEL_BASE "3-way merge base"
67 static const struct got_error
*
68 create_meta_file(const char *path_got
, const char *name
, const char *content
)
70 const struct got_error
*err
= NULL
;
73 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1)
74 return got_error_from_errno("asprintf");
76 err
= got_path_create_file(path
, content
);
81 static const struct got_error
*
82 update_meta_file(const char *path_got
, const char *name
, const char *content
)
84 const struct got_error
*err
= NULL
;
89 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1) {
90 err
= got_error_from_errno("asprintf");
95 err
= got_opentemp_named(&tmppath
, &tmpfile
, path
);
100 int len
= fprintf(tmpfile
, "%s\n", content
);
101 if (len
!= strlen(content
) + 1) {
102 err
= got_error_from_errno2("fprintf", tmppath
);
107 if (rename(tmppath
, path
) != 0) {
108 err
= got_error_from_errno3("rename", tmppath
, path
);
114 if (fclose(tmpfile
) == EOF
&& err
== NULL
)
115 err
= got_error_from_errno2("fclose", tmppath
);
120 static const struct got_error
*
121 read_meta_file(char **content
, const char *path_got
, const char *name
)
123 const struct got_error
*err
= NULL
;
131 if (asprintf(&path
, "%s/%s", path_got
, name
) == -1) {
132 err
= got_error_from_errno("asprintf");
137 fd
= open(path
, O_RDONLY
| O_NOFOLLOW
);
140 err
= got_error_path(path
, GOT_ERR_WORKTREE_META
);
142 err
= got_error_from_errno2("open", path
);
145 if (flock(fd
, LOCK_SH
| LOCK_NB
) == -1) {
146 err
= (errno
== EWOULDBLOCK
? got_error(GOT_ERR_WORKTREE_BUSY
)
147 : got_error_from_errno2("flock", path
));
151 if (fstat(fd
, &sb
) != 0) {
152 err
= got_error_from_errno2("fstat", path
);
155 *content
= calloc(1, sb
.st_size
);
156 if (*content
== NULL
) {
157 err
= got_error_from_errno("calloc");
161 n
= read(fd
, *content
, sb
.st_size
);
162 if (n
!= sb
.st_size
) {
163 err
= (n
== -1 ? got_error_from_errno2("read", path
) :
164 got_error_path(path
, GOT_ERR_WORKTREE_META
));
167 if ((*content
)[sb
.st_size
- 1] != '\n') {
168 err
= got_error_path(path
, GOT_ERR_WORKTREE_META
);
171 (*content
)[sb
.st_size
- 1] = '\0';
174 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
175 err
= got_error_from_errno2("close", path_got
);
184 static const struct got_error
*
185 write_head_ref(const char *path_got
, struct got_reference
*head_ref
)
187 const struct got_error
*err
= NULL
;
190 if (got_ref_is_symbolic(head_ref
)) {
191 refstr
= got_ref_to_str(head_ref
);
193 return got_error_from_errno("got_ref_to_str");
195 refstr
= strdup(got_ref_get_name(head_ref
));
197 return got_error_from_errno("strdup");
199 err
= update_meta_file(path_got
, GOT_WORKTREE_HEAD_REF
, refstr
);
204 const struct got_error
*
205 got_worktree_init(const char *path
, struct got_reference
*head_ref
,
206 const char *prefix
, struct got_repository
*repo
)
208 const struct got_error
*err
= NULL
;
209 struct got_object_id
*commit_id
= NULL
;
211 uint32_t uuid_status
;
213 char *path_got
= NULL
;
214 char *formatstr
= NULL
;
215 char *absprefix
= NULL
;
216 char *basestr
= NULL
;
217 char *uuidstr
= NULL
;
219 if (strcmp(path
, got_repo_get_path(repo
)) == 0) {
220 err
= got_error(GOT_ERR_WORKTREE_REPO
);
224 err
= got_ref_resolve(&commit_id
, repo
, head_ref
);
227 err
= got_object_get_type(&obj_type
, repo
, commit_id
);
230 if (obj_type
!= GOT_OBJ_TYPE_COMMIT
)
231 return got_error(GOT_ERR_OBJ_TYPE
);
233 if (!got_path_is_absolute(prefix
)) {
234 if (asprintf(&absprefix
, "/%s", prefix
) == -1)
235 return got_error_from_errno("asprintf");
238 /* Create top-level directory (may already exist). */
239 if (mkdir(path
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
240 err
= got_error_from_errno2("mkdir", path
);
244 /* Create .got directory (may already exist). */
245 if (asprintf(&path_got
, "%s/%s", path
, GOT_WORKTREE_GOT_DIR
) == -1) {
246 err
= got_error_from_errno("asprintf");
249 if (mkdir(path_got
, GOT_DEFAULT_DIR_MODE
) == -1 && errno
!= EEXIST
) {
250 err
= got_error_from_errno2("mkdir", path_got
);
254 /* Create an empty lock file. */
255 err
= create_meta_file(path_got
, GOT_WORKTREE_LOCK
, NULL
);
259 /* Create an empty file index. */
260 err
= create_meta_file(path_got
, GOT_WORKTREE_FILE_INDEX
, NULL
);
264 /* Write the HEAD reference. */
265 err
= write_head_ref(path_got
, head_ref
);
269 /* Record our base commit. */
270 err
= got_object_id_str(&basestr
, commit_id
);
273 err
= create_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, basestr
);
277 /* Store path to repository. */
278 err
= create_meta_file(path_got
, GOT_WORKTREE_REPOSITORY
,
279 got_repo_get_path(repo
));
283 /* Store in-repository path prefix. */
284 err
= create_meta_file(path_got
, GOT_WORKTREE_PATH_PREFIX
,
285 absprefix
? absprefix
: prefix
);
290 uuid_create(&uuid
, &uuid_status
);
291 if (uuid_status
!= uuid_s_ok
) {
292 err
= got_error_uuid(uuid_status
, "uuid_create");
295 uuid_to_string(&uuid
, &uuidstr
, &uuid_status
);
296 if (uuid_status
!= uuid_s_ok
) {
297 err
= got_error_uuid(uuid_status
, "uuid_to_string");
300 err
= create_meta_file(path_got
, GOT_WORKTREE_UUID
, uuidstr
);
304 /* Stamp work tree with format file. */
305 if (asprintf(&formatstr
, "%d", GOT_WORKTREE_FORMAT_VERSION
) == -1) {
306 err
= got_error_from_errno("asprintf");
309 err
= create_meta_file(path_got
, GOT_WORKTREE_FORMAT
, formatstr
);
323 static const struct got_error
*
324 open_worktree(struct got_worktree
**worktree
, const char *path
)
326 const struct got_error
*err
= NULL
;
328 char *formatstr
= NULL
;
329 char *uuidstr
= NULL
;
330 char *path_lock
= NULL
;
331 char *base_commit_id_str
= NULL
;
332 int version
, fd
= -1;
334 struct got_repository
*repo
= NULL
;
335 uint32_t uuid_status
;
339 if (asprintf(&path_got
, "%s/%s", path
, GOT_WORKTREE_GOT_DIR
) == -1) {
340 err
= got_error_from_errno("asprintf");
345 if (asprintf(&path_lock
, "%s/%s", path_got
, GOT_WORKTREE_LOCK
) == -1) {
346 err
= got_error_from_errno("asprintf");
351 fd
= open(path_lock
, O_RDWR
| O_EXLOCK
| O_NONBLOCK
);
353 err
= (errno
== EWOULDBLOCK
? got_error(GOT_ERR_WORKTREE_BUSY
)
354 : got_error_from_errno2("open", path_lock
));
358 err
= read_meta_file(&formatstr
, path_got
, GOT_WORKTREE_FORMAT
);
362 version
= strtonum(formatstr
, 1, INT_MAX
, &errstr
);
364 err
= got_error_msg(GOT_ERR_WORKTREE_META
,
365 "could not parse work tree format version number");
368 if (version
!= GOT_WORKTREE_FORMAT_VERSION
) {
369 err
= got_error(GOT_ERR_WORKTREE_VERS
);
373 *worktree
= calloc(1, sizeof(**worktree
));
374 if (*worktree
== NULL
) {
375 err
= got_error_from_errno("calloc");
378 (*worktree
)->lockfd
= -1;
380 (*worktree
)->root_path
= realpath(path
, NULL
);
381 if ((*worktree
)->root_path
== NULL
) {
382 err
= got_error_from_errno2("realpath", path
);
385 err
= read_meta_file(&(*worktree
)->repo_path
, path_got
,
386 GOT_WORKTREE_REPOSITORY
);
390 err
= read_meta_file(&(*worktree
)->path_prefix
, path_got
,
391 GOT_WORKTREE_PATH_PREFIX
);
395 err
= read_meta_file(&base_commit_id_str
, path_got
,
396 GOT_WORKTREE_BASE_COMMIT
);
400 err
= read_meta_file(&uuidstr
, path_got
, GOT_WORKTREE_UUID
);
403 uuid_from_string(uuidstr
, &(*worktree
)->uuid
, &uuid_status
);
404 if (uuid_status
!= uuid_s_ok
) {
405 err
= got_error_uuid(uuid_status
, "uuid_from_string");
409 err
= got_repo_open(&repo
, (*worktree
)->repo_path
, NULL
);
413 err
= got_object_resolve_id_str(&(*worktree
)->base_commit_id
, repo
,
418 err
= read_meta_file(&(*worktree
)->head_ref_name
, path_got
,
419 GOT_WORKTREE_HEAD_REF
);
423 if (asprintf(&(*worktree
)->gotconfig_path
, "%s/%s/%s",
424 (*worktree
)->root_path
,
425 GOT_WORKTREE_GOT_DIR
, GOT_GOTCONFIG_FILENAME
) == -1) {
426 err
= got_error_from_errno("asprintf");
430 err
= got_gotconfig_read(&(*worktree
)->gotconfig
,
431 (*worktree
)->gotconfig_path
);
433 (*worktree
)->root_fd
= open((*worktree
)->root_path
, O_DIRECTORY
);
434 if ((*worktree
)->root_fd
== -1) {
435 err
= got_error_from_errno2("open", (*worktree
)->root_path
);
440 const struct got_error
*close_err
= got_repo_close(repo
);
446 free(base_commit_id_str
);
452 if (*worktree
!= NULL
)
453 got_worktree_close(*worktree
);
456 (*worktree
)->lockfd
= fd
;
461 const struct got_error
*
462 got_worktree_open(struct got_worktree
**worktree
, const char *path
)
464 const struct got_error
*err
= NULL
;
467 worktree_path
= strdup(path
);
468 if (worktree_path
== NULL
)
469 return got_error_from_errno("strdup");
474 err
= open_worktree(worktree
, worktree_path
);
475 if (err
&& !(err
->code
== GOT_ERR_ERRNO
&& errno
== ENOENT
)) {
483 if (worktree_path
[0] == '/' && worktree_path
[1] == '\0')
485 err
= got_path_dirname(&parent_path
, worktree_path
);
487 if (err
->code
!= GOT_ERR_BAD_PATH
) {
494 worktree_path
= parent_path
;
498 return got_error(GOT_ERR_NOT_WORKTREE
);
501 const struct got_error
*
502 got_worktree_close(struct got_worktree
*worktree
)
504 const struct got_error
*err
= NULL
;
506 if (worktree
->lockfd
!= -1) {
507 if (close(worktree
->lockfd
) == -1)
508 err
= got_error_from_errno2("close",
509 got_worktree_get_root_path(worktree
));
511 if (close(worktree
->root_fd
) == -1 && err
== NULL
)
512 err
= got_error_from_errno2("close",
513 got_worktree_get_root_path(worktree
));
514 free(worktree
->repo_path
);
515 free(worktree
->path_prefix
);
516 free(worktree
->base_commit_id
);
517 free(worktree
->head_ref_name
);
518 free(worktree
->root_path
);
519 free(worktree
->gotconfig_path
);
520 got_gotconfig_free(worktree
->gotconfig
);
526 got_worktree_get_root_path(struct got_worktree
*worktree
)
528 return worktree
->root_path
;
532 got_worktree_get_repo_path(struct got_worktree
*worktree
)
534 return worktree
->repo_path
;
537 got_worktree_get_path_prefix(struct got_worktree
*worktree
)
539 return worktree
->path_prefix
;
542 const struct got_error
*
543 got_worktree_match_path_prefix(int *match
, struct got_worktree
*worktree
,
544 const char *path_prefix
)
546 char *absprefix
= NULL
;
548 if (!got_path_is_absolute(path_prefix
)) {
549 if (asprintf(&absprefix
, "/%s", path_prefix
) == -1)
550 return got_error_from_errno("asprintf");
552 *match
= (strcmp(absprefix
? absprefix
: path_prefix
,
553 worktree
->path_prefix
) == 0);
559 got_worktree_get_head_ref_name(struct got_worktree
*worktree
)
561 return worktree
->head_ref_name
;
564 const struct got_error
*
565 got_worktree_set_head_ref(struct got_worktree
*worktree
,
566 struct got_reference
*head_ref
)
568 const struct got_error
*err
= NULL
;
569 char *path_got
= NULL
, *head_ref_name
= NULL
;
571 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
572 GOT_WORKTREE_GOT_DIR
) == -1) {
573 err
= got_error_from_errno("asprintf");
578 head_ref_name
= strdup(got_ref_get_name(head_ref
));
579 if (head_ref_name
== NULL
) {
580 err
= got_error_from_errno("strdup");
584 err
= write_head_ref(path_got
, head_ref
);
588 free(worktree
->head_ref_name
);
589 worktree
->head_ref_name
= head_ref_name
;
597 struct got_object_id
*
598 got_worktree_get_base_commit_id(struct got_worktree
*worktree
)
600 return worktree
->base_commit_id
;
603 const struct got_error
*
604 got_worktree_set_base_commit_id(struct got_worktree
*worktree
,
605 struct got_repository
*repo
, struct got_object_id
*commit_id
)
607 const struct got_error
*err
;
608 struct got_object
*obj
= NULL
;
610 char *path_got
= NULL
;
612 if (asprintf(&path_got
, "%s/%s", worktree
->root_path
,
613 GOT_WORKTREE_GOT_DIR
) == -1) {
614 err
= got_error_from_errno("asprintf");
619 err
= got_object_open(&obj
, repo
, commit_id
);
623 if (obj
->type
!= GOT_OBJ_TYPE_COMMIT
) {
624 err
= got_error(GOT_ERR_OBJ_TYPE
);
628 /* Record our base commit. */
629 err
= got_object_id_str(&id_str
, commit_id
);
632 err
= update_meta_file(path_got
, GOT_WORKTREE_BASE_COMMIT
, id_str
);
636 free(worktree
->base_commit_id
);
637 worktree
->base_commit_id
= got_object_id_dup(commit_id
);
638 if (worktree
->base_commit_id
== NULL
) {
639 err
= got_error_from_errno("got_object_id_dup");
644 got_object_close(obj
);
650 const struct got_gotconfig
*
651 got_worktree_get_gotconfig(struct got_worktree
*worktree
)
653 return worktree
->gotconfig
;
656 static const struct got_error
*
657 lock_worktree(struct got_worktree
*worktree
, int operation
)
659 if (flock(worktree
->lockfd
, operation
| LOCK_NB
) == -1)
660 return (errno
== EWOULDBLOCK
? got_error(GOT_ERR_WORKTREE_BUSY
)
661 : got_error_from_errno2("flock",
662 got_worktree_get_root_path(worktree
)));
666 static const struct got_error
*
667 add_dir_on_disk(struct got_worktree
*worktree
, const char *path
)
669 const struct got_error
*err
= NULL
;
672 if (asprintf(&abspath
, "%s/%s", worktree
->root_path
, path
) == -1)
673 return got_error_from_errno("asprintf");
675 err
= got_path_mkdir(abspath
);
676 if (err
&& err
->code
== GOT_ERR_ERRNO
&& errno
== EEXIST
) {
679 if (lstat(abspath
, &sb
) == -1) {
680 err
= got_error_from_errno2("lstat", abspath
);
681 } else if (!S_ISDIR(sb
.st_mode
)) {
682 /* TODO directory is obstructed; do something */
683 err
= got_error_path(abspath
, GOT_ERR_FILE_OBSTRUCTED
);
690 static const struct got_error
*
691 check_file_contents_equal(int *same
, FILE *f1
, FILE *f2
)
693 const struct got_error
*err
= NULL
;
696 size_t flen1
= 0, flen2
= 0;
701 flen1
= fread(fbuf1
, 1, sizeof(fbuf1
), f1
);
702 if (flen1
== 0 && ferror(f1
)) {
703 err
= got_error_from_errno("fread");
706 flen2
= fread(fbuf2
, 1, sizeof(fbuf2
), f2
);
707 if (flen2
== 0 && ferror(f2
)) {
708 err
= got_error_from_errno("fread");
715 } else if (flen2
== 0) {
719 } else if (flen1
== flen2
) {
720 if (memcmp(fbuf1
, fbuf2
, flen2
) != 0) {
733 static const struct got_error
*
734 check_files_equal(int *same
, FILE *f1
, FILE *f2
)
741 if (fstat(fileno(f1
), &sb
) != 0)
742 return got_error_from_errno("fstat");
745 if (fstat(fileno(f2
), &sb
) != 0)
746 return got_error_from_errno("fstat");
749 if (size1
!= size2
) {
754 if (fseek(f1
, 0L, SEEK_SET
) == -1)
755 return got_ferror(f1
, GOT_ERR_IO
);
756 if (fseek(f2
, 0L, SEEK_SET
) == -1)
757 return got_ferror(f2
, GOT_ERR_IO
);
759 return check_file_contents_equal(same
, f1
, f2
);
763 * Perform a 3-way merge where the file f_orig acts as the common
764 * ancestor, the file f_deriv acts as the first derived version,
765 * and the file f_deriv2 acts as the second derived version.
766 * The merge result will be written to a new file at ondisk_path; any
767 * existing file at this path will be replaced.
769 static const struct got_error
*
770 merge_file(int *local_changes_subsumed
, struct got_worktree
*worktree
,
771 FILE *f_orig
, FILE *f_deriv
, FILE *f_deriv2
, const char *ondisk_path
,
772 const char *path
, uint16_t st_mode
,
773 const char *label_orig
, const char *label_deriv
, const char *label_deriv2
,
774 enum got_diff_algorithm diff_algo
, struct got_repository
*repo
,
775 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
777 const struct got_error
*err
= NULL
;
779 FILE *f_merged
= NULL
;
780 char *merged_path
= NULL
, *base_path
= NULL
;
784 *local_changes_subsumed
= 0;
786 err
= got_path_dirname(&parent
, ondisk_path
);
790 if (asprintf(&base_path
, "%s/got-merged", parent
) == -1) {
791 err
= got_error_from_errno("asprintf");
795 err
= got_opentemp_named_fd(&merged_path
, &merged_fd
, base_path
);
799 err
= got_merge_diff3(&overlapcnt
, merged_fd
, f_deriv
, f_orig
,
800 f_deriv2
, label_deriv
, label_orig
, label_deriv2
, diff_algo
);
804 err
= (*progress_cb
)(progress_arg
,
805 overlapcnt
> 0 ? GOT_STATUS_CONFLICT
: GOT_STATUS_MERGE
, path
);
809 if (fsync(merged_fd
) != 0) {
810 err
= got_error_from_errno("fsync");
814 f_merged
= fdopen(merged_fd
, "r");
815 if (f_merged
== NULL
) {
816 err
= got_error_from_errno("fdopen");
821 /* Check if a clean merge has subsumed all local changes. */
822 if (overlapcnt
== 0) {
823 err
= check_files_equal(local_changes_subsumed
, f_deriv
,
829 if (fchmod(fileno(f_merged
), st_mode
) != 0) {
830 err
= got_error_from_errno2("fchmod", merged_path
);
834 if (rename(merged_path
, ondisk_path
) != 0) {
835 err
= got_error_from_errno3("rename", merged_path
,
844 if (merged_fd
!= -1 && close(merged_fd
) == -1 && err
== NULL
)
845 err
= got_error_from_errno("close");
846 if (f_merged
&& fclose(f_merged
) == EOF
&& err
== NULL
)
847 err
= got_error_from_errno("fclose");
854 static const struct got_error
*
855 update_symlink(const char *ondisk_path
, const char *target_path
,
858 /* This is not atomic but matches what 'ln -sf' does. */
859 if (unlink(ondisk_path
) == -1)
860 return got_error_from_errno2("unlink", ondisk_path
);
861 if (symlink(target_path
, ondisk_path
) == -1)
862 return got_error_from_errno3("symlink", target_path
,
868 * Overwrite a symlink (or a regular file in case there was a "bad" symlink)
869 * in the work tree with a file that contains conflict markers and the
870 * conflicting target paths of the original version, a "derived version"
871 * of a symlink from an incoming change, and a local version of the symlink.
873 * The original versions's target path can be NULL if it is not available,
874 * such as if both derived versions added a new symlink at the same path.
876 * The incoming derived symlink target is NULL in case the incoming change
877 * has deleted this symlink.
879 static const struct got_error
*
880 install_symlink_conflict(const char *deriv_target
,
881 struct got_object_id
*deriv_base_commit_id
, const char *orig_target
,
882 const char *label_orig
, const char *local_target
, const char *ondisk_path
)
884 const struct got_error
*err
;
885 char *id_str
= NULL
, *label_deriv
= NULL
, *path
= NULL
;
888 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
890 return got_error_from_errno("asprintf");
892 if (asprintf(&label_deriv
, "%s: commit %s",
893 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
894 err
= got_error_from_errno("asprintf");
898 err
= got_opentemp_named(&path
, &f
, "got-symlink-conflict");
902 if (fchmod(fileno(f
), GOT_DEFAULT_FILE_MODE
) == -1) {
903 err
= got_error_from_errno2("fchmod", path
);
907 if (fprintf(f
, "%s %s\n%s\n%s%s%s%s%s\n%s\n%s\n",
908 GOT_DIFF_CONFLICT_MARKER_BEGIN
, label_deriv
,
909 deriv_target
? deriv_target
: "(symlink was deleted)",
910 orig_target
? label_orig
: "",
911 orig_target
? "\n" : "",
912 orig_target
? orig_target
: "",
913 orig_target
? "\n" : "",
914 GOT_DIFF_CONFLICT_MARKER_SEP
,
915 local_target
, GOT_DIFF_CONFLICT_MARKER_END
) < 0) {
916 err
= got_error_from_errno2("fprintf", path
);
920 if (unlink(ondisk_path
) == -1) {
921 err
= got_error_from_errno2("unlink", ondisk_path
);
924 if (rename(path
, ondisk_path
) == -1) {
925 err
= got_error_from_errno3("rename", path
, ondisk_path
);
929 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
930 err
= got_error_from_errno2("fclose", path
);
937 /* forward declaration */
938 static const struct got_error
*
939 merge_blob(int *, struct got_worktree
*, struct got_blob_object
*,
940 const char *, const char *, uint16_t, const char *,
941 struct got_blob_object
*, struct got_object_id
*,
942 struct got_repository
*, got_worktree_checkout_cb
, void *);
945 * Merge a symlink into the work tree, where blob_orig acts as the common
946 * ancestor, deriv_target is the link target of the first derived version,
947 * and the symlink on disk acts as the second derived version.
948 * Assume that contents of both blobs represent symlinks.
950 static const struct got_error
*
951 merge_symlink(struct got_worktree
*worktree
,
952 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
953 const char *path
, const char *label_orig
, const char *deriv_target
,
954 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
955 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
957 const struct got_error
*err
= NULL
;
958 char *ancestor_target
= NULL
;
960 ssize_t ondisk_len
, deriv_len
;
961 char ondisk_target
[PATH_MAX
];
962 int have_local_change
= 0;
963 int have_incoming_change
= 0;
965 if (lstat(ondisk_path
, &sb
) == -1)
966 return got_error_from_errno2("lstat", ondisk_path
);
968 ondisk_len
= readlink(ondisk_path
, ondisk_target
,
969 sizeof(ondisk_target
));
970 if (ondisk_len
== -1) {
971 err
= got_error_from_errno2("readlink",
975 ondisk_target
[ondisk_len
] = '\0';
978 err
= got_object_blob_read_to_str(&ancestor_target
, blob_orig
);
983 if (ancestor_target
== NULL
||
984 (ondisk_len
!= strlen(ancestor_target
) ||
985 memcmp(ondisk_target
, ancestor_target
, ondisk_len
) != 0))
986 have_local_change
= 1;
988 deriv_len
= strlen(deriv_target
);
989 if (ancestor_target
== NULL
||
990 (deriv_len
!= strlen(ancestor_target
) ||
991 memcmp(deriv_target
, ancestor_target
, deriv_len
) != 0))
992 have_incoming_change
= 1;
994 if (!have_local_change
&& !have_incoming_change
) {
995 if (ancestor_target
) {
996 /* Both sides made the same change. */
997 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
999 } else if (deriv_len
== ondisk_len
&&
1000 memcmp(ondisk_target
, deriv_target
, deriv_len
) == 0) {
1001 /* Both sides added the same symlink. */
1002 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
1005 /* Both sides added symlinks which don't match. */
1006 err
= install_symlink_conflict(deriv_target
,
1007 deriv_base_commit_id
, ancestor_target
,
1008 label_orig
, ondisk_target
, ondisk_path
);
1011 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
1014 } else if (!have_local_change
&& have_incoming_change
) {
1015 /* Apply the incoming change. */
1016 err
= update_symlink(ondisk_path
, deriv_target
,
1017 strlen(deriv_target
));
1020 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
1021 } else if (have_local_change
&& have_incoming_change
) {
1022 if (deriv_len
== ondisk_len
&&
1023 memcmp(deriv_target
, ondisk_target
, deriv_len
) == 0) {
1024 /* Both sides made the same change. */
1025 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
,
1028 err
= install_symlink_conflict(deriv_target
,
1029 deriv_base_commit_id
, ancestor_target
, label_orig
,
1030 ondisk_target
, ondisk_path
);
1033 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
1039 free(ancestor_target
);
1043 static const struct got_error
*
1044 dump_symlink_target_path_to_file(FILE **outfile
, const char *ondisk_path
)
1046 const struct got_error
*err
= NULL
;
1047 char target_path
[PATH_MAX
];
1056 return got_error_from_errno("got_opentemp");
1057 target_len
= readlink(ondisk_path
, target_path
, sizeof(target_path
));
1058 if (target_len
== -1) {
1059 err
= got_error_from_errno2("readlink", ondisk_path
);
1062 n
= fwrite(target_path
, 1, target_len
, f
);
1063 if (n
!= target_len
) {
1064 err
= got_ferror(f
, GOT_ERR_IO
);
1067 if (fflush(f
) == EOF
) {
1068 err
= got_error_from_errno("fflush");
1071 if (fseek(f
, 0L, SEEK_SET
) == -1) {
1072 err
= got_ferror(f
, GOT_ERR_IO
);
1084 * Perform a 3-way merge where blob_orig acts as the common ancestor,
1085 * blob_deriv acts as the first derived version, and the file on disk
1086 * acts as the second derived version.
1088 static const struct got_error
*
1089 merge_blob(int *local_changes_subsumed
, struct got_worktree
*worktree
,
1090 struct got_blob_object
*blob_orig
, const char *ondisk_path
,
1091 const char *path
, uint16_t st_mode
, const char *label_orig
,
1092 struct got_blob_object
*blob_deriv
,
1093 struct got_object_id
*deriv_base_commit_id
, struct got_repository
*repo
,
1094 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1096 const struct got_error
*err
= NULL
;
1097 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
1098 char *blob_orig_path
= NULL
;
1099 char *blob_deriv_path
= NULL
, *base_path
= NULL
, *id_str
= NULL
;
1100 char *label_deriv
= NULL
, *parent
= NULL
;
1102 *local_changes_subsumed
= 0;
1104 err
= got_path_dirname(&parent
, ondisk_path
);
1109 if (asprintf(&base_path
, "%s/got-merge-blob-orig",
1111 err
= got_error_from_errno("asprintf");
1116 err
= got_opentemp_named(&blob_orig_path
, &f_orig
, base_path
);
1119 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_orig
,
1126 * No common ancestor exists. This is an "add vs add" conflict
1127 * and we simply use an empty ancestor file to make both files
1128 * appear in the merged result in their entirety.
1130 f_orig
= got_opentemp();
1131 if (f_orig
== NULL
) {
1132 err
= got_error_from_errno("got_opentemp");
1137 if (asprintf(&base_path
, "%s/got-merge-blob-deriv", parent
) == -1) {
1138 err
= got_error_from_errno("asprintf");
1143 err
= got_opentemp_named(&blob_deriv_path
, &f_deriv
, base_path
);
1146 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_deriv
,
1151 err
= got_object_id_str(&id_str
, deriv_base_commit_id
);
1154 if (asprintf(&label_deriv
, "%s: commit %s",
1155 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
1156 err
= got_error_from_errno("asprintf");
1161 * In order the run a 3-way merge with a symlink we copy the symlink's
1162 * target path into a temporary file and use that file with diff3.
1164 if (S_ISLNK(st_mode
)) {
1165 err
= dump_symlink_target_path_to_file(&f_deriv2
, ondisk_path
);
1170 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
);
1172 err
= got_error_from_errno2("open", ondisk_path
);
1175 f_deriv2
= fdopen(fd
, "r");
1176 if (f_deriv2
== NULL
) {
1177 err
= got_error_from_errno2("fdopen", ondisk_path
);
1183 err
= merge_file(local_changes_subsumed
, worktree
, f_orig
, f_deriv
,
1184 f_deriv2
, ondisk_path
, path
, st_mode
, label_orig
, label_deriv
,
1185 NULL
, GOT_DIFF_ALGORITHM_MYERS
, repo
, progress_cb
, progress_arg
);
1187 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
1188 err
= got_error_from_errno("fclose");
1189 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
1190 err
= got_error_from_errno("fclose");
1191 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
1192 err
= got_error_from_errno("fclose");
1194 if (blob_orig_path
) {
1195 unlink(blob_orig_path
);
1196 free(blob_orig_path
);
1198 if (blob_deriv_path
) {
1199 unlink(blob_deriv_path
);
1200 free(blob_deriv_path
);
1208 static const struct got_error
*
1209 create_fileindex_entry(struct got_fileindex_entry
**new_iep
,
1210 struct got_fileindex
*fileindex
, struct got_object_id
*base_commit_id
,
1211 int wt_fd
, const char *path
, struct got_object_id
*blob_id
)
1213 const struct got_error
*err
= NULL
;
1214 struct got_fileindex_entry
*new_ie
;
1218 err
= got_fileindex_entry_alloc(&new_ie
, path
);
1222 err
= got_fileindex_entry_update(new_ie
, wt_fd
, path
,
1223 blob_id
->sha1
, base_commit_id
->sha1
, 1);
1227 err
= got_fileindex_entry_add(fileindex
, new_ie
);
1230 got_fileindex_entry_free(new_ie
);
1237 get_ondisk_perms(int executable
, mode_t st_mode
)
1239 mode_t xbits
= S_IXUSR
;
1242 /* Map read bits to execute bits. */
1243 if (st_mode
& S_IRGRP
)
1245 if (st_mode
& S_IROTH
)
1247 return st_mode
| xbits
;
1250 return (st_mode
& ~(S_IXUSR
| S_IXGRP
| S_IXOTH
));
1253 /* forward declaration */
1254 static const struct got_error
*
1255 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1256 const char *path
, mode_t te_mode
, mode_t st_mode
,
1257 struct got_blob_object
*blob
, int restoring_missing_file
,
1258 int reverting_versioned_file
, int installing_bad_symlink
,
1259 int path_is_unversioned
, struct got_repository
*repo
,
1260 got_worktree_checkout_cb progress_cb
, void *progress_arg
);
1263 * This function assumes that the provided symlink target points at a
1264 * safe location in the work tree!
1266 static const struct got_error
*
1267 replace_existing_symlink(int *did_something
, const char *ondisk_path
,
1268 const char *target_path
, size_t target_len
)
1270 const struct got_error
*err
= NULL
;
1272 char etarget
[PATH_MAX
];
1278 * "Bad" symlinks (those pointing outside the work tree or into the
1279 * .got directory) are installed in the work tree as a regular file
1280 * which contains the bad symlink target path.
1281 * The new symlink target has already been checked for safety by our
1282 * caller. If we can successfully open a regular file then we simply
1283 * replace this file with a symlink below.
1285 fd
= open(ondisk_path
, O_RDWR
| O_EXCL
| O_NOFOLLOW
);
1288 return got_error_from_errno2("open", ondisk_path
);
1290 /* We are updating an existing on-disk symlink. */
1291 elen
= readlink(ondisk_path
, etarget
, sizeof(etarget
));
1293 return got_error_from_errno2("readlink", ondisk_path
);
1295 if (elen
== target_len
&&
1296 memcmp(etarget
, target_path
, target_len
) == 0)
1297 return NULL
; /* nothing to do */
1301 err
= update_symlink(ondisk_path
, target_path
, target_len
);
1302 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1303 err
= got_error_from_errno2("close", ondisk_path
);
1307 static const struct got_error
*
1308 is_bad_symlink_target(int *is_bad_symlink
, const char *target_path
,
1309 size_t target_len
, const char *ondisk_path
, const char *wtroot_path
)
1311 const struct got_error
*err
= NULL
;
1312 char canonpath
[PATH_MAX
];
1313 char *path_got
= NULL
;
1315 *is_bad_symlink
= 0;
1317 if (target_len
>= sizeof(canonpath
)) {
1318 *is_bad_symlink
= 1;
1323 * We do not use realpath(3) to resolve the symlink's target
1324 * path because we don't want to resolve symlinks recursively.
1325 * Instead we make the path absolute and then canonicalize it.
1326 * Relative symlink target lookup should begin at the directory
1327 * in which the blob object is being installed.
1329 if (!got_path_is_absolute(target_path
)) {
1330 char *abspath
, *parent
;
1331 err
= got_path_dirname(&parent
, ondisk_path
);
1334 if (asprintf(&abspath
, "%s/%s", parent
, target_path
) == -1) {
1336 return got_error_from_errno("asprintf");
1339 if (strlen(abspath
) >= sizeof(canonpath
)) {
1340 err
= got_error_path(abspath
, GOT_ERR_BAD_PATH
);
1344 err
= got_canonpath(abspath
, canonpath
, sizeof(canonpath
));
1349 err
= got_canonpath(target_path
, canonpath
, sizeof(canonpath
));
1354 /* Only allow symlinks pointing at paths within the work tree. */
1355 if (!got_path_is_child(canonpath
, wtroot_path
, strlen(wtroot_path
))) {
1356 *is_bad_symlink
= 1;
1360 /* Do not allow symlinks pointing into the .got directory. */
1361 if (asprintf(&path_got
, "%s/%s", wtroot_path
,
1362 GOT_WORKTREE_GOT_DIR
) == -1)
1363 return got_error_from_errno("asprintf");
1364 if (got_path_is_child(canonpath
, path_got
, strlen(path_got
)))
1365 *is_bad_symlink
= 1;
1371 static const struct got_error
*
1372 install_symlink(int *is_bad_symlink
, struct got_worktree
*worktree
,
1373 const char *ondisk_path
, const char *path
, struct got_blob_object
*blob
,
1374 int restoring_missing_file
, int reverting_versioned_file
,
1375 int path_is_unversioned
, struct got_repository
*repo
,
1376 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1378 const struct got_error
*err
= NULL
;
1379 char target_path
[PATH_MAX
];
1380 size_t len
, target_len
= 0;
1381 char *path_got
= NULL
;
1382 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1383 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1385 *is_bad_symlink
= 0;
1388 * Blob object content specifies the target path of the link.
1389 * If a symbolic link cannot be installed we instead create
1390 * a regular file which contains the link target path stored
1391 * in the blob object.
1394 err
= got_object_blob_read_block(&len
, blob
);
1395 if (len
+ target_len
>= sizeof(target_path
)) {
1396 /* Path too long; install as a regular file. */
1397 *is_bad_symlink
= 1;
1398 got_object_blob_rewind(blob
);
1399 return install_blob(worktree
, ondisk_path
, path
,
1400 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1401 restoring_missing_file
, reverting_versioned_file
,
1402 1, path_is_unversioned
, repo
, progress_cb
,
1406 /* Skip blob object header first time around. */
1407 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1409 target_len
+= len
- hdrlen
;
1413 target_path
[target_len
] = '\0';
1415 err
= is_bad_symlink_target(is_bad_symlink
, target_path
, target_len
,
1416 ondisk_path
, worktree
->root_path
);
1420 if (*is_bad_symlink
) {
1421 /* install as a regular file */
1422 got_object_blob_rewind(blob
);
1423 err
= install_blob(worktree
, ondisk_path
, path
,
1424 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1425 restoring_missing_file
, reverting_versioned_file
, 1,
1426 path_is_unversioned
, repo
, progress_cb
, progress_arg
);
1430 if (symlink(target_path
, ondisk_path
) == -1) {
1431 if (errno
== EEXIST
) {
1432 int symlink_replaced
;
1433 if (path_is_unversioned
) {
1434 err
= (*progress_cb
)(progress_arg
,
1435 GOT_STATUS_UNVERSIONED
, path
);
1438 err
= replace_existing_symlink(&symlink_replaced
,
1439 ondisk_path
, target_path
, target_len
);
1443 if (symlink_replaced
) {
1444 err
= (*progress_cb
)(progress_arg
,
1445 reverting_versioned_file
?
1447 GOT_STATUS_UPDATE
, path
);
1449 err
= (*progress_cb
)(progress_arg
,
1450 GOT_STATUS_EXISTS
, path
);
1453 goto done
; /* Nothing else to do. */
1456 if (errno
== ENOENT
) {
1458 err
= got_path_dirname(&parent
, ondisk_path
);
1461 err
= add_dir_on_disk(worktree
, parent
);
1466 * Retry, and fall through to error handling
1467 * below if this second attempt fails.
1469 if (symlink(target_path
, ondisk_path
) != -1) {
1470 err
= NULL
; /* success */
1475 /* Handle errors from first or second creation attempt. */
1476 if (errno
== ENAMETOOLONG
) {
1477 /* bad target path; install as a regular file */
1478 *is_bad_symlink
= 1;
1479 got_object_blob_rewind(blob
);
1480 err
= install_blob(worktree
, ondisk_path
, path
,
1481 GOT_DEFAULT_FILE_MODE
, GOT_DEFAULT_FILE_MODE
, blob
,
1482 restoring_missing_file
, reverting_versioned_file
, 1,
1483 path_is_unversioned
, repo
,
1484 progress_cb
, progress_arg
);
1485 } else if (errno
== ENOTDIR
) {
1486 err
= got_error_path(ondisk_path
,
1487 GOT_ERR_FILE_OBSTRUCTED
);
1489 err
= got_error_from_errno3("symlink",
1490 target_path
, ondisk_path
);
1492 } else if (progress_cb
)
1493 err
= (*progress_cb
)(progress_arg
, reverting_versioned_file
?
1494 GOT_STATUS_REVERT
: GOT_STATUS_ADD
, path
);
1500 static const struct got_error
*
1501 install_blob(struct got_worktree
*worktree
, const char *ondisk_path
,
1502 const char *path
, mode_t te_mode
, mode_t st_mode
,
1503 struct got_blob_object
*blob
, int restoring_missing_file
,
1504 int reverting_versioned_file
, int installing_bad_symlink
,
1505 int path_is_unversioned
, struct got_repository
*repo
,
1506 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
1508 const struct got_error
*err
= NULL
;
1512 char *tmppath
= NULL
;
1514 fd
= open(ondisk_path
, O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
,
1515 GOT_DEFAULT_FILE_MODE
);
1517 if (errno
== ENOENT
) {
1519 err
= got_path_dirname(&parent
, path
);
1522 err
= add_dir_on_disk(worktree
, parent
);
1526 fd
= open(ondisk_path
,
1527 O_RDWR
| O_CREAT
| O_EXCL
| O_NOFOLLOW
,
1528 GOT_DEFAULT_FILE_MODE
);
1530 return got_error_from_errno2("open",
1532 } else if (errno
== EEXIST
) {
1533 if (path_is_unversioned
) {
1534 err
= (*progress_cb
)(progress_arg
,
1535 GOT_STATUS_UNVERSIONED
, path
);
1538 if (!(S_ISLNK(st_mode
) && S_ISREG(te_mode
)) &&
1539 !S_ISREG(st_mode
) && !installing_bad_symlink
) {
1540 /* TODO file is obstructed; do something */
1541 err
= got_error_path(ondisk_path
,
1542 GOT_ERR_FILE_OBSTRUCTED
);
1545 err
= got_opentemp_named_fd(&tmppath
, &fd
,
1552 return got_error_from_errno2("open", ondisk_path
);
1555 if (fchmod(fd
, get_ondisk_perms(te_mode
& S_IXUSR
, st_mode
)) == -1) {
1556 err
= got_error_from_errno2("fchmod",
1557 update
? tmppath
: ondisk_path
);
1562 if (restoring_missing_file
)
1563 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MISSING
,
1565 else if (reverting_versioned_file
)
1566 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_REVERT
,
1569 err
= (*progress_cb
)(progress_arg
,
1570 update
? GOT_STATUS_UPDATE
: GOT_STATUS_ADD
, path
);
1575 hdrlen
= got_object_blob_get_hdrlen(blob
);
1577 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1578 err
= got_object_blob_read_block(&len
, blob
);
1582 /* Skip blob object header first time around. */
1583 ssize_t outlen
= write(fd
, buf
+ hdrlen
, len
- hdrlen
);
1585 err
= got_error_from_errno("write");
1587 } else if (outlen
!= len
- hdrlen
) {
1588 err
= got_error(GOT_ERR_IO
);
1595 if (fsync(fd
) != 0) {
1596 err
= got_error_from_errno("fsync");
1601 if (S_ISLNK(st_mode
) && unlink(ondisk_path
) == -1) {
1602 err
= got_error_from_errno2("unlink", ondisk_path
);
1605 if (rename(tmppath
, ondisk_path
) != 0) {
1606 err
= got_error_from_errno3("rename", tmppath
,
1615 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1616 err
= got_error_from_errno("close");
1617 if (tmppath
!= NULL
&& unlink(tmppath
) == -1 && err
== NULL
)
1618 err
= got_error_from_errno2("unlink", tmppath
);
1623 /* Upgrade STATUS_MODIFY to STATUS_CONFLICT if a conflict marker is found. */
1624 static const struct got_error
*
1625 get_modified_file_content_status(unsigned char *status
, FILE *f
)
1627 const struct got_error
*err
= NULL
;
1628 const char *markers
[3] = {
1629 GOT_DIFF_CONFLICT_MARKER_BEGIN
,
1630 GOT_DIFF_CONFLICT_MARKER_SEP
,
1631 GOT_DIFF_CONFLICT_MARKER_END
1635 size_t linesize
= 0;
1638 while (*status
== GOT_STATUS_MODIFY
) {
1639 linelen
= getline(&line
, &linesize
, f
);
1640 if (linelen
== -1) {
1643 err
= got_ferror(f
, GOT_ERR_IO
);
1647 if (strncmp(line
, markers
[i
], strlen(markers
[i
])) == 0) {
1648 if (strcmp(markers
[i
], GOT_DIFF_CONFLICT_MARKER_END
)
1650 *status
= GOT_STATUS_CONFLICT
;
1661 xbit_differs(struct got_fileindex_entry
*ie
, uint16_t st_mode
)
1663 mode_t ie_mode
= got_fileindex_perms_to_st(ie
);
1664 return ((ie_mode
& S_IXUSR
) != (st_mode
& S_IXUSR
));
1668 stat_info_differs(struct got_fileindex_entry
*ie
, struct stat
*sb
)
1670 return !(ie
->ctime_sec
== sb
->st_ctim
.tv_sec
&&
1671 ie
->ctime_nsec
== sb
->st_ctim
.tv_nsec
&&
1672 ie
->mtime_sec
== sb
->st_mtim
.tv_sec
&&
1673 ie
->mtime_nsec
== sb
->st_mtim
.tv_nsec
&&
1674 ie
->size
== (sb
->st_size
& 0xffffffff) &&
1675 !xbit_differs(ie
, sb
->st_mode
));
1678 static unsigned char
1679 get_staged_status(struct got_fileindex_entry
*ie
)
1681 switch (got_fileindex_entry_stage_get(ie
)) {
1682 case GOT_FILEIDX_STAGE_ADD
:
1683 return GOT_STATUS_ADD
;
1684 case GOT_FILEIDX_STAGE_DELETE
:
1685 return GOT_STATUS_DELETE
;
1686 case GOT_FILEIDX_STAGE_MODIFY
:
1687 return GOT_STATUS_MODIFY
;
1689 return GOT_STATUS_NO_CHANGE
;
1693 static const struct got_error
*
1694 get_symlink_modification_status(unsigned char *status
,
1695 struct got_fileindex_entry
*ie
, const char *abspath
,
1696 int dirfd
, const char *de_name
, struct got_blob_object
*blob
)
1698 const struct got_error
*err
= NULL
;
1699 char target_path
[PATH_MAX
];
1700 char etarget
[PATH_MAX
];
1702 size_t len
, target_len
= 0;
1703 const uint8_t *buf
= got_object_blob_get_read_buf(blob
);
1704 size_t hdrlen
= got_object_blob_get_hdrlen(blob
);
1706 *status
= GOT_STATUS_NO_CHANGE
;
1708 /* Blob object content specifies the target path of the link. */
1710 err
= got_object_blob_read_block(&len
, blob
);
1713 if (len
+ target_len
>= sizeof(target_path
)) {
1715 * Should not happen. The blob contents were OK
1716 * when this symlink was installed.
1718 return got_error(GOT_ERR_NO_SPACE
);
1721 /* Skip blob object header first time around. */
1722 memcpy(target_path
+ target_len
, buf
+ hdrlen
,
1724 target_len
+= len
- hdrlen
;
1728 target_path
[target_len
] = '\0';
1731 elen
= readlinkat(dirfd
, de_name
, etarget
, sizeof(etarget
));
1733 return got_error_from_errno2("readlinkat", abspath
);
1735 elen
= readlink(abspath
, etarget
, sizeof(etarget
));
1737 return got_error_from_errno2("readlink", abspath
);
1740 if (elen
!= target_len
|| memcmp(etarget
, target_path
, target_len
) != 0)
1741 *status
= GOT_STATUS_MODIFY
;
1746 static const struct got_error
*
1747 get_file_status(unsigned char *status
, struct stat
*sb
,
1748 struct got_fileindex_entry
*ie
, const char *abspath
,
1749 int dirfd
, const char *de_name
, struct got_repository
*repo
)
1751 const struct got_error
*err
= NULL
;
1752 struct got_object_id id
;
1757 struct got_blob_object
*blob
= NULL
;
1759 unsigned char staged_status
= get_staged_status(ie
);
1761 *status
= GOT_STATUS_NO_CHANGE
;
1762 memset(sb
, 0, sizeof(*sb
));
1765 * Whenever the caller provides a directory descriptor and a
1766 * directory entry name for the file, use them! This prevents
1767 * race conditions if filesystem paths change beneath our feet.
1770 if (fstatat(dirfd
, de_name
, sb
, AT_SYMLINK_NOFOLLOW
) == -1) {
1771 if (errno
== ENOENT
) {
1772 if (got_fileindex_entry_has_file_on_disk(ie
))
1773 *status
= GOT_STATUS_MISSING
;
1775 *status
= GOT_STATUS_DELETE
;
1778 err
= got_error_from_errno2("fstatat", abspath
);
1782 fd
= open(abspath
, O_RDONLY
| O_NOFOLLOW
);
1783 if (fd
== -1 && errno
!= ENOENT
&& errno
!= ELOOP
)
1784 return got_error_from_errno2("open", abspath
);
1785 else if (fd
== -1 && errno
== ELOOP
) {
1786 if (lstat(abspath
, sb
) == -1)
1787 return got_error_from_errno2("lstat", abspath
);
1788 } else if (fd
== -1 || fstat(fd
, sb
) == -1) {
1789 if (errno
== ENOENT
) {
1790 if (got_fileindex_entry_has_file_on_disk(ie
))
1791 *status
= GOT_STATUS_MISSING
;
1793 *status
= GOT_STATUS_DELETE
;
1796 err
= got_error_from_errno2("fstat", abspath
);
1801 if (!S_ISREG(sb
->st_mode
) && !S_ISLNK(sb
->st_mode
)) {
1802 *status
= GOT_STATUS_OBSTRUCTED
;
1806 if (!got_fileindex_entry_has_file_on_disk(ie
)) {
1807 *status
= GOT_STATUS_DELETE
;
1809 } else if (!got_fileindex_entry_has_blob(ie
) &&
1810 staged_status
!= GOT_STATUS_ADD
) {
1811 *status
= GOT_STATUS_ADD
;
1815 if (!stat_info_differs(ie
, sb
))
1818 if (S_ISLNK(sb
->st_mode
) &&
1819 got_fileindex_entry_filetype_get(ie
) != GOT_FILEIDX_MODE_SYMLINK
) {
1820 *status
= GOT_STATUS_MODIFY
;
1824 if (staged_status
== GOT_STATUS_MODIFY
||
1825 staged_status
== GOT_STATUS_ADD
)
1826 memcpy(id
.sha1
, ie
->staged_blob_sha1
, sizeof(id
.sha1
));
1828 memcpy(id
.sha1
, ie
->blob_sha1
, sizeof(id
.sha1
));
1830 err
= got_object_open_as_blob(&blob
, repo
, &id
, sizeof(fbuf
));
1834 if (S_ISLNK(sb
->st_mode
)) {
1835 err
= get_symlink_modification_status(status
, ie
,
1836 abspath
, dirfd
, de_name
, blob
);
1841 fd
= openat(dirfd
, de_name
, O_RDONLY
| O_NOFOLLOW
);
1843 err
= got_error_from_errno2("openat", abspath
);
1848 f
= fdopen(fd
, "r");
1850 err
= got_error_from_errno2("fdopen", abspath
);
1854 hdrlen
= got_object_blob_get_hdrlen(blob
);
1856 const uint8_t *bbuf
= got_object_blob_get_read_buf(blob
);
1857 err
= got_object_blob_read_block(&blen
, blob
);
1860 /* Skip length of blob object header first time around. */
1861 flen
= fread(fbuf
, 1, sizeof(fbuf
) - hdrlen
, f
);
1862 if (flen
== 0 && ferror(f
)) {
1863 err
= got_error_from_errno("fread");
1866 if (blen
- hdrlen
== 0) {
1868 *status
= GOT_STATUS_MODIFY
;
1870 } else if (flen
== 0) {
1871 if (blen
- hdrlen
!= 0)
1872 *status
= GOT_STATUS_MODIFY
;
1874 } else if (blen
- hdrlen
== flen
) {
1875 /* Skip blob object header first time around. */
1876 if (memcmp(bbuf
+ hdrlen
, fbuf
, flen
) != 0) {
1877 *status
= GOT_STATUS_MODIFY
;
1881 *status
= GOT_STATUS_MODIFY
;
1887 if (*status
== GOT_STATUS_MODIFY
) {
1889 err
= get_modified_file_content_status(status
, f
);
1890 } else if (xbit_differs(ie
, sb
->st_mode
))
1891 *status
= GOT_STATUS_MODE_CHANGE
;
1894 got_object_blob_close(blob
);
1895 if (f
!= NULL
&& fclose(f
) == EOF
&& err
== NULL
)
1896 err
= got_error_from_errno2("fclose", abspath
);
1897 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
1898 err
= got_error_from_errno2("close", abspath
);
1903 * Update timestamps in the file index if a file is unmodified and
1904 * we had to run a full content comparison to find out.
1906 static const struct got_error
*
1907 sync_timestamps(int wt_fd
, const char *path
, unsigned char status
,
1908 struct got_fileindex_entry
*ie
, struct stat
*sb
)
1910 if (status
== GOT_STATUS_NO_CHANGE
&& stat_info_differs(ie
, sb
))
1911 return got_fileindex_entry_update(ie
, wt_fd
, path
,
1912 ie
->blob_sha1
, ie
->commit_sha1
, 1);
1917 static const struct got_error
*
1918 update_blob(struct got_worktree
*worktree
,
1919 struct got_fileindex
*fileindex
, struct got_fileindex_entry
*ie
,
1920 struct got_tree_entry
*te
, const char *path
,
1921 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
1924 const struct got_error
*err
= NULL
;
1925 struct got_blob_object
*blob
= NULL
;
1927 unsigned char status
= GOT_STATUS_NO_CHANGE
;
1930 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, path
) == -1)
1931 return got_error_from_errno("asprintf");
1934 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
) {
1935 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
1938 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
1942 if (status
== GOT_STATUS_MISSING
|| status
== GOT_STATUS_DELETE
)
1943 sb
.st_mode
= got_fileindex_perms_to_st(ie
);
1945 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
1946 status
= GOT_STATUS_UNVERSIONED
;
1949 if (status
== GOT_STATUS_OBSTRUCTED
) {
1951 got_fileindex_entry_mark_skipped(ie
);
1952 err
= (*progress_cb
)(progress_arg
, status
, path
);
1955 if (status
== GOT_STATUS_CONFLICT
) {
1957 got_fileindex_entry_mark_skipped(ie
);
1958 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CANNOT_UPDATE
,
1963 if (ie
&& status
!= GOT_STATUS_MISSING
&& S_ISREG(sb
.st_mode
) &&
1964 (S_ISLNK(te
->mode
) ||
1965 (te
->mode
& S_IXUSR
) == (sb
.st_mode
& S_IXUSR
))) {
1967 * This is a regular file or an installed bad symlink.
1968 * If the file index indicates that this file is already
1969 * up-to-date with respect to the repository we can skip
1970 * updating contents of this file.
1972 if (got_fileindex_entry_has_commit(ie
) &&
1973 memcmp(ie
->commit_sha1
, worktree
->base_commit_id
->sha1
,
1974 SHA1_DIGEST_LENGTH
) == 0) {
1976 err
= sync_timestamps(worktree
->root_fd
,
1977 path
, status
, ie
, &sb
);
1980 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
1984 if (got_fileindex_entry_has_blob(ie
) &&
1985 memcmp(ie
->blob_sha1
, te
->id
.sha1
,
1986 SHA1_DIGEST_LENGTH
) == 0) {
1987 /* Different commit but the same blob. */
1988 err
= sync_timestamps(worktree
->root_fd
,
1989 path
, status
, ie
, &sb
);
1992 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_EXISTS
,
1998 err
= got_object_open_as_blob(&blob
, repo
, &te
->id
, 8192);
2002 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_ADD
) {
2003 int update_timestamps
;
2004 struct got_blob_object
*blob2
= NULL
;
2005 char *label_orig
= NULL
;
2006 if (got_fileindex_entry_has_blob(ie
)) {
2007 struct got_object_id id2
;
2008 memcpy(id2
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
2009 err
= got_object_open_as_blob(&blob2
, repo
, &id2
, 8192);
2013 if (got_fileindex_entry_has_commit(ie
)) {
2014 char id_str
[SHA1_DIGEST_STRING_LENGTH
];
2015 if (got_sha1_digest_to_str(ie
->commit_sha1
, id_str
,
2016 sizeof(id_str
)) == NULL
) {
2017 err
= got_error_path(id_str
,
2018 GOT_ERR_BAD_OBJ_ID_STR
);
2021 if (asprintf(&label_orig
, "%s: commit %s",
2022 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
2023 err
= got_error_from_errno("asprintf");
2027 if (S_ISLNK(te
->mode
) && S_ISLNK(sb
.st_mode
)) {
2029 err
= got_object_blob_read_to_str(&link_target
, blob
);
2032 err
= merge_symlink(worktree
, blob2
, ondisk_path
, path
,
2033 label_orig
, link_target
, worktree
->base_commit_id
,
2034 repo
, progress_cb
, progress_arg
);
2037 err
= merge_blob(&update_timestamps
, worktree
, blob2
,
2038 ondisk_path
, path
, sb
.st_mode
, label_orig
, blob
,
2039 worktree
->base_commit_id
, repo
,
2040 progress_cb
, progress_arg
);
2044 got_object_blob_close(blob2
);
2048 * Do not update timestamps of files with local changes.
2049 * Otherwise, a future status walk would treat them as
2050 * unmodified files again.
2052 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2053 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
,
2055 } else if (status
== GOT_STATUS_MODE_CHANGE
) {
2056 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2057 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
2058 } else if (status
== GOT_STATUS_DELETE
) {
2059 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, path
);
2062 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
, path
,
2063 blob
->id
.sha1
, worktree
->base_commit_id
->sha1
, 0);
2067 int is_bad_symlink
= 0;
2068 if (S_ISLNK(te
->mode
)) {
2069 err
= install_symlink(&is_bad_symlink
, worktree
,
2070 ondisk_path
, path
, blob
,
2071 status
== GOT_STATUS_MISSING
, 0,
2072 status
== GOT_STATUS_UNVERSIONED
, repo
,
2073 progress_cb
, progress_arg
);
2075 err
= install_blob(worktree
, ondisk_path
, path
,
2076 te
->mode
, sb
.st_mode
, blob
,
2077 status
== GOT_STATUS_MISSING
, 0, 0,
2078 status
== GOT_STATUS_UNVERSIONED
, repo
,
2079 progress_cb
, progress_arg
);
2085 err
= got_fileindex_entry_update(ie
,
2086 worktree
->root_fd
, path
, blob
->id
.sha1
,
2087 worktree
->base_commit_id
->sha1
, 1);
2089 err
= create_fileindex_entry(&ie
, fileindex
,
2090 worktree
->base_commit_id
, worktree
->root_fd
, path
,
2096 if (is_bad_symlink
) {
2097 got_fileindex_entry_filetype_set(ie
,
2098 GOT_FILEIDX_MODE_BAD_SYMLINK
);
2101 got_object_blob_close(blob
);
2107 static const struct got_error
*
2108 remove_ondisk_file(const char *root_path
, const char *path
)
2110 const struct got_error
*err
= NULL
;
2111 char *ondisk_path
= NULL
, *parent
= NULL
;
2113 if (asprintf(&ondisk_path
, "%s/%s", root_path
, path
) == -1)
2114 return got_error_from_errno("asprintf");
2116 if (unlink(ondisk_path
) == -1) {
2117 if (errno
!= ENOENT
)
2118 err
= got_error_from_errno2("unlink", ondisk_path
);
2120 size_t root_len
= strlen(root_path
);
2121 err
= got_path_dirname(&parent
, ondisk_path
);
2124 while (got_path_cmp(parent
, root_path
,
2125 strlen(parent
), root_len
) != 0) {
2127 ondisk_path
= parent
;
2129 if (rmdir(ondisk_path
) == -1) {
2130 if (errno
!= ENOTEMPTY
)
2131 err
= got_error_from_errno2("rmdir",
2135 err
= got_path_dirname(&parent
, ondisk_path
);
2146 static const struct got_error
*
2147 delete_blob(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2148 struct got_fileindex_entry
*ie
, struct got_repository
*repo
,
2149 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2151 const struct got_error
*err
= NULL
;
2152 unsigned char status
;
2156 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
2157 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
2159 if (asprintf(&ondisk_path
, "%s/%s", worktree
->root_path
, ie
->path
)
2161 return got_error_from_errno("asprintf");
2163 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, repo
);
2167 if (S_ISLNK(sb
.st_mode
) && status
!= GOT_STATUS_NO_CHANGE
) {
2168 char ondisk_target
[PATH_MAX
];
2169 ssize_t ondisk_len
= readlink(ondisk_path
, ondisk_target
,
2170 sizeof(ondisk_target
));
2171 if (ondisk_len
== -1) {
2172 err
= got_error_from_errno2("readlink", ondisk_path
);
2175 ondisk_target
[ondisk_len
] = '\0';
2176 err
= install_symlink_conflict(NULL
, worktree
->base_commit_id
,
2177 NULL
, NULL
, /* XXX pass common ancestor info? */
2178 ondisk_target
, ondisk_path
);
2181 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_CONFLICT
,
2186 if (status
== GOT_STATUS_MODIFY
|| status
== GOT_STATUS_CONFLICT
||
2187 status
== GOT_STATUS_ADD
) {
2188 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_MERGE
, ie
->path
);
2192 * Preserve the working file and change the deleted blob's
2193 * entry into a schedule-add entry.
2195 err
= got_fileindex_entry_update(ie
, worktree
->root_fd
,
2196 ie
->path
, NULL
, NULL
, 0);
2198 err
= (*progress_cb
)(progress_arg
, GOT_STATUS_DELETE
, ie
->path
);
2201 if (status
== GOT_STATUS_NO_CHANGE
) {
2202 err
= remove_ondisk_file(worktree
->root_path
, ie
->path
);
2206 got_fileindex_entry_remove(fileindex
, ie
);
2213 struct diff_cb_arg
{
2214 struct got_fileindex
*fileindex
;
2215 struct got_worktree
*worktree
;
2216 struct got_repository
*repo
;
2217 got_worktree_checkout_cb progress_cb
;
2219 got_cancel_cb cancel_cb
;
2223 static const struct got_error
*
2224 diff_old_new(void *arg
, struct got_fileindex_entry
*ie
,
2225 struct got_tree_entry
*te
, const char *parent_path
)
2227 struct diff_cb_arg
*a
= arg
;
2229 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2230 return got_error(GOT_ERR_CANCELLED
);
2232 return update_blob(a
->worktree
, a
->fileindex
, ie
, te
,
2233 ie
->path
, a
->repo
, a
->progress_cb
, a
->progress_arg
);
2236 static const struct got_error
*
2237 diff_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
2239 struct diff_cb_arg
*a
= arg
;
2241 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2242 return got_error(GOT_ERR_CANCELLED
);
2244 return delete_blob(a
->worktree
, a
->fileindex
, ie
,
2245 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2248 static const struct got_error
*
2249 diff_new(void *arg
, struct got_tree_entry
*te
, const char *parent_path
)
2251 struct diff_cb_arg
*a
= arg
;
2252 const struct got_error
*err
;
2255 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
2256 return got_error(GOT_ERR_CANCELLED
);
2258 if (got_object_tree_entry_is_submodule(te
))
2261 if (asprintf(&path
, "%s%s%s", parent_path
,
2262 parent_path
[0] ? "/" : "", te
->name
)
2264 return got_error_from_errno("asprintf");
2266 if (S_ISDIR(te
->mode
))
2267 err
= add_dir_on_disk(a
->worktree
, path
);
2269 err
= update_blob(a
->worktree
, a
->fileindex
, NULL
, te
, path
,
2270 a
->repo
, a
->progress_cb
, a
->progress_arg
);
2276 const struct got_error
*
2277 got_worktree_get_uuid(char **uuidstr
, struct got_worktree
*worktree
)
2279 uint32_t uuid_status
;
2281 uuid_to_string(&worktree
->uuid
, uuidstr
, &uuid_status
);
2282 if (uuid_status
!= uuid_s_ok
) {
2284 return got_error_uuid(uuid_status
, "uuid_to_string");
2290 static const struct got_error
*
2291 get_ref_name(char **refname
, struct got_worktree
*worktree
, const char *prefix
)
2293 const struct got_error
*err
= NULL
;
2294 char *uuidstr
= NULL
;
2298 err
= got_worktree_get_uuid(&uuidstr
, worktree
);
2302 if (asprintf(refname
, "%s-%s", prefix
, uuidstr
) == -1) {
2303 err
= got_error_from_errno("asprintf");
2310 const struct got_error
*
2311 got_worktree_get_base_ref_name(char **refname
, struct got_worktree
*worktree
)
2313 return get_ref_name(refname
, worktree
, GOT_WORKTREE_BASE_REF_PREFIX
);
2316 static const struct got_error
*
2317 get_rebase_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2319 return get_ref_name(refname
, worktree
,
2320 GOT_WORKTREE_REBASE_TMP_REF_PREFIX
);
2323 static const struct got_error
*
2324 get_newbase_symref_name(char **refname
, struct got_worktree
*worktree
)
2326 return get_ref_name(refname
, worktree
, GOT_WORKTREE_NEWBASE_REF_PREFIX
);
2329 static const struct got_error
*
2330 get_rebase_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2332 return get_ref_name(refname
, worktree
,
2333 GOT_WORKTREE_REBASE_BRANCH_REF_PREFIX
);
2336 static const struct got_error
*
2337 get_rebase_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2339 return get_ref_name(refname
, worktree
,
2340 GOT_WORKTREE_REBASE_COMMIT_REF_PREFIX
);
2343 static const struct got_error
*
2344 get_histedit_tmp_ref_name(char **refname
, struct got_worktree
*worktree
)
2346 return get_ref_name(refname
, worktree
,
2347 GOT_WORKTREE_HISTEDIT_TMP_REF_PREFIX
);
2350 static const struct got_error
*
2351 get_histedit_branch_symref_name(char **refname
, struct got_worktree
*worktree
)
2353 return get_ref_name(refname
, worktree
,
2354 GOT_WORKTREE_HISTEDIT_BRANCH_REF_PREFIX
);
2357 static const struct got_error
*
2358 get_histedit_base_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2360 return get_ref_name(refname
, worktree
,
2361 GOT_WORKTREE_HISTEDIT_BASE_COMMIT_REF_PREFIX
);
2364 static const struct got_error
*
2365 get_histedit_commit_ref_name(char **refname
, struct got_worktree
*worktree
)
2367 return get_ref_name(refname
, worktree
,
2368 GOT_WORKTREE_HISTEDIT_COMMIT_REF_PREFIX
);
2371 const struct got_error
*
2372 got_worktree_get_histedit_script_path(char **path
,
2373 struct got_worktree
*worktree
)
2375 if (asprintf(path
, "%s/%s/%s", worktree
->root_path
,
2376 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_HISTEDIT_SCRIPT
) == -1) {
2378 return got_error_from_errno("asprintf");
2384 * Prevent Git's garbage collector from deleting our base commit by
2385 * setting a reference to our base commit's ID.
2387 static const struct got_error
*
2388 ref_base_commit(struct got_worktree
*worktree
, struct got_repository
*repo
)
2390 const struct got_error
*err
= NULL
;
2391 struct got_reference
*ref
= NULL
;
2394 err
= got_worktree_get_base_ref_name(&refname
, worktree
);
2398 err
= got_ref_alloc(&ref
, refname
, worktree
->base_commit_id
);
2402 err
= got_ref_write(ref
, repo
);
2410 static const struct got_error
*
2411 get_fileindex_path(char **fileindex_path
, struct got_worktree
*worktree
)
2413 const struct got_error
*err
= NULL
;
2415 if (asprintf(fileindex_path
, "%s/%s/%s", worktree
->root_path
,
2416 GOT_WORKTREE_GOT_DIR
, GOT_WORKTREE_FILE_INDEX
) == -1) {
2417 err
= got_error_from_errno("asprintf");
2418 *fileindex_path
= NULL
;
2424 static const struct got_error
*
2425 open_fileindex(struct got_fileindex
**fileindex
, char **fileindex_path
,
2426 struct got_worktree
*worktree
)
2428 const struct got_error
*err
= NULL
;
2431 *fileindex_path
= NULL
;
2432 *fileindex
= got_fileindex_alloc();
2433 if (*fileindex
== NULL
)
2434 return got_error_from_errno("got_fileindex_alloc");
2436 err
= get_fileindex_path(fileindex_path
, worktree
);
2440 index
= fopen(*fileindex_path
, "rb");
2441 if (index
== NULL
) {
2442 if (errno
!= ENOENT
)
2443 err
= got_error_from_errno2("fopen", *fileindex_path
);
2445 err
= got_fileindex_read(*fileindex
, index
);
2446 if (fclose(index
) == EOF
&& err
== NULL
)
2447 err
= got_error_from_errno("fclose");
2451 free(*fileindex_path
);
2452 *fileindex_path
= NULL
;
2453 got_fileindex_free(*fileindex
);
2459 struct bump_base_commit_id_arg
{
2460 struct got_object_id
*base_commit_id
;
2463 const char *entry_name
;
2464 got_worktree_checkout_cb progress_cb
;
2468 /* Bump base commit ID of all files within an updated part of the work tree. */
2469 static const struct got_error
*
2470 bump_base_commit_id(void *arg
, struct got_fileindex_entry
*ie
)
2472 const struct got_error
*err
;
2473 struct bump_base_commit_id_arg
*a
= arg
;
2475 if (a
->entry_name
) {
2476 if (strcmp(ie
->path
, a
->path
) != 0)
2478 } else if (!got_path_is_child(ie
->path
, a
->path
, a
->path_len
))
2481 if (got_fileindex_entry_was_skipped(ie
))
2484 if (memcmp(ie
->commit_sha1
, a
->base_commit_id
->sha1
,
2485 SHA1_DIGEST_LENGTH
) == 0)
2488 if (a
->progress_cb
) {
2489 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_BUMP_BASE
,
2494 memcpy(ie
->commit_sha1
, a
->base_commit_id
->sha1
, SHA1_DIGEST_LENGTH
);
2498 static const struct got_error
*
2499 bump_base_commit_id_everywhere(struct got_worktree
*worktree
,
2500 struct got_fileindex
*fileindex
,
2501 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
2503 struct bump_base_commit_id_arg bbc_arg
;
2505 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2506 bbc_arg
.entry_name
= NULL
;
2508 bbc_arg
.path_len
= 0;
2509 bbc_arg
.progress_cb
= progress_cb
;
2510 bbc_arg
.progress_arg
= progress_arg
;
2512 return got_fileindex_for_each_entry_safe(fileindex
,
2513 bump_base_commit_id
, &bbc_arg
);
2516 static const struct got_error
*
2517 sync_fileindex(struct got_fileindex
*fileindex
, const char *fileindex_path
)
2519 const struct got_error
*err
= NULL
;
2520 char *new_fileindex_path
= NULL
;
2521 FILE *new_index
= NULL
;
2522 struct timespec timeout
;
2524 err
= got_opentemp_named(&new_fileindex_path
, &new_index
,
2529 err
= got_fileindex_write(fileindex
, new_index
);
2533 if (rename(new_fileindex_path
, fileindex_path
) != 0) {
2534 err
= got_error_from_errno3("rename", new_fileindex_path
,
2536 unlink(new_fileindex_path
);
2540 * Sleep for a short amount of time to ensure that files modified after
2541 * this program exits have a different time stamp from the one which
2542 * was recorded in the file index.
2545 timeout
.tv_nsec
= 1;
2546 nanosleep(&timeout
, NULL
);
2550 free(new_fileindex_path
);
2554 static const struct got_error
*
2555 find_tree_entry_for_checkout(int *entry_type
, char **tree_relpath
,
2556 struct got_object_id
**tree_id
, const char *wt_relpath
,
2557 struct got_worktree
*worktree
, struct got_repository
*repo
)
2559 const struct got_error
*err
= NULL
;
2560 struct got_object_id
*id
= NULL
;
2561 char *in_repo_path
= NULL
;
2562 int is_root_wt
= got_path_is_root_dir(worktree
->path_prefix
);
2564 *entry_type
= GOT_OBJ_TYPE_ANY
;
2565 *tree_relpath
= NULL
;
2568 if (wt_relpath
[0] == '\0') {
2569 /* Check out all files within the work tree. */
2570 *entry_type
= GOT_OBJ_TYPE_TREE
;
2571 *tree_relpath
= strdup("");
2572 if (*tree_relpath
== NULL
) {
2573 err
= got_error_from_errno("strdup");
2576 err
= got_object_id_by_path(tree_id
, repo
,
2577 worktree
->base_commit_id
, worktree
->path_prefix
);
2583 /* Check out a subset of files in the work tree. */
2585 if (asprintf(&in_repo_path
, "%s%s%s", worktree
->path_prefix
,
2586 is_root_wt
? "" : "/", wt_relpath
) == -1) {
2587 err
= got_error_from_errno("asprintf");
2591 err
= got_object_id_by_path(&id
, repo
, worktree
->base_commit_id
,
2597 in_repo_path
= NULL
;
2599 err
= got_object_get_type(entry_type
, repo
, id
);
2603 if (*entry_type
== GOT_OBJ_TYPE_BLOB
) {
2604 /* Check out a single file. */
2605 if (strchr(wt_relpath
, '/') == NULL
) {
2606 /* Check out a single file in work tree's root dir. */
2607 in_repo_path
= strdup(worktree
->path_prefix
);
2608 if (in_repo_path
== NULL
) {
2609 err
= got_error_from_errno("strdup");
2612 *tree_relpath
= strdup("");
2613 if (*tree_relpath
== NULL
) {
2614 err
= got_error_from_errno("strdup");
2618 /* Check out a single file in a subdirectory. */
2619 err
= got_path_dirname(tree_relpath
, wt_relpath
);
2622 if (asprintf(&in_repo_path
, "%s%s%s",
2623 worktree
->path_prefix
, is_root_wt
? "" : "/",
2624 *tree_relpath
) == -1) {
2625 err
= got_error_from_errno("asprintf");
2629 err
= got_object_id_by_path(tree_id
, repo
,
2630 worktree
->base_commit_id
, in_repo_path
);
2632 /* Check out all files within a subdirectory. */
2633 *tree_id
= got_object_id_dup(id
);
2634 if (*tree_id
== NULL
) {
2635 err
= got_error_from_errno("got_object_id_dup");
2638 *tree_relpath
= strdup(wt_relpath
);
2639 if (*tree_relpath
== NULL
) {
2640 err
= got_error_from_errno("strdup");
2648 *entry_type
= GOT_OBJ_TYPE_ANY
;
2649 free(*tree_relpath
);
2650 *tree_relpath
= NULL
;
2657 static const struct got_error
*
2658 checkout_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
2659 const char *relpath
, struct got_object_id
*tree_id
, const char *entry_name
,
2660 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
2661 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
2663 const struct got_error
*err
= NULL
;
2664 struct got_commit_object
*commit
= NULL
;
2665 struct got_tree_object
*tree
= NULL
;
2666 struct got_fileindex_diff_tree_cb diff_cb
;
2667 struct diff_cb_arg arg
;
2669 err
= ref_base_commit(worktree
, repo
);
2671 if (!(err
->code
== GOT_ERR_ERRNO
&&
2672 (errno
== EACCES
|| errno
== EROFS
)))
2674 err
= (*progress_cb
)(progress_arg
,
2675 GOT_STATUS_BASE_REF_ERR
, worktree
->root_path
);
2680 err
= got_object_open_as_commit(&commit
, repo
,
2681 worktree
->base_commit_id
);
2685 err
= got_object_open_as_tree(&tree
, repo
, tree_id
);
2690 got_object_tree_find_entry(tree
, entry_name
) == NULL
) {
2691 err
= got_error_path(entry_name
, GOT_ERR_NO_TREE_ENTRY
);
2695 diff_cb
.diff_old_new
= diff_old_new
;
2696 diff_cb
.diff_old
= diff_old
;
2697 diff_cb
.diff_new
= diff_new
;
2698 arg
.fileindex
= fileindex
;
2699 arg
.worktree
= worktree
;
2701 arg
.progress_cb
= progress_cb
;
2702 arg
.progress_arg
= progress_arg
;
2703 arg
.cancel_cb
= cancel_cb
;
2704 arg
.cancel_arg
= cancel_arg
;
2705 err
= got_fileindex_diff_tree(fileindex
, tree
, relpath
,
2706 entry_name
, repo
, &diff_cb
, &arg
);
2709 got_object_tree_close(tree
);
2711 got_object_commit_close(commit
);
2715 const struct got_error
*
2716 got_worktree_checkout_files(struct got_worktree
*worktree
,
2717 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
2718 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
2719 got_cancel_cb cancel_cb
, void *cancel_arg
)
2721 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
2722 struct got_commit_object
*commit
= NULL
;
2723 struct got_tree_object
*tree
= NULL
;
2724 struct got_fileindex
*fileindex
= NULL
;
2725 char *fileindex_path
= NULL
;
2726 struct got_pathlist_entry
*pe
;
2727 struct tree_path_data
{
2728 STAILQ_ENTRY(tree_path_data
) entry
;
2729 struct got_object_id
*tree_id
;
2734 STAILQ_HEAD(tree_paths
, tree_path_data
) tree_paths
;
2736 STAILQ_INIT(&tree_paths
);
2738 err
= lock_worktree(worktree
, LOCK_EX
);
2742 /* Map all specified paths to in-repository trees. */
2743 TAILQ_FOREACH(pe
, paths
, entry
) {
2744 tpd
= malloc(sizeof(*tpd
));
2746 err
= got_error_from_errno("malloc");
2750 err
= find_tree_entry_for_checkout(&tpd
->entry_type
,
2751 &tpd
->relpath
, &tpd
->tree_id
, pe
->path
, worktree
, repo
);
2757 if (tpd
->entry_type
== GOT_OBJ_TYPE_BLOB
) {
2758 err
= got_path_basename(&tpd
->entry_name
, pe
->path
);
2766 tpd
->entry_name
= NULL
;
2768 STAILQ_INSERT_TAIL(&tree_paths
, tpd
, entry
);
2772 * Read the file index.
2773 * Checking out files is supposed to be an idempotent operation.
2774 * If the on-disk file index is incomplete we will try to complete it.
2776 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
2780 tpd
= STAILQ_FIRST(&tree_paths
);
2781 TAILQ_FOREACH(pe
, paths
, entry
) {
2782 struct bump_base_commit_id_arg bbc_arg
;
2784 err
= checkout_files(worktree
, fileindex
, tpd
->relpath
,
2785 tpd
->tree_id
, tpd
->entry_name
, repo
,
2786 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
2790 bbc_arg
.base_commit_id
= worktree
->base_commit_id
;
2791 bbc_arg
.entry_name
= tpd
->entry_name
;
2792 bbc_arg
.path
= pe
->path
;
2793 bbc_arg
.path_len
= pe
->path_len
;
2794 bbc_arg
.progress_cb
= progress_cb
;
2795 bbc_arg
.progress_arg
= progress_arg
;
2796 err
= got_fileindex_for_each_entry_safe(fileindex
,
2797 bump_base_commit_id
, &bbc_arg
);
2801 tpd
= STAILQ_NEXT(tpd
, entry
);
2803 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
2804 if (sync_err
&& err
== NULL
)
2807 free(fileindex_path
);
2809 got_object_tree_close(tree
);
2811 got_object_commit_close(commit
);
2813 got_fileindex_free(fileindex
);
2814 while (!STAILQ_EMPTY(&tree_paths
)) {
2815 tpd
= STAILQ_FIRST(&tree_paths
);
2816 STAILQ_REMOVE_HEAD(&tree_paths
, entry
);
2821 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
2822 if (unlockerr
&& err
== NULL
)
2827 struct merge_file_cb_arg
{
2828 struct got_worktree
*worktree
;
2829 struct got_fileindex
*fileindex
;
2830 got_worktree_checkout_cb progress_cb
;
2832 got_cancel_cb cancel_cb
;
2834 const char *label_orig
;
2835 struct got_object_id
*commit_id2
;
2838 static const struct got_error
*
2839 merge_file_cb(void *arg
, struct got_blob_object
*blob1
,
2840 struct got_blob_object
*blob2
, struct got_object_id
*id1
,
2841 struct got_object_id
*id2
, const char *path1
, const char *path2
,
2842 mode_t mode1
, mode_t mode2
, struct got_repository
*repo
)
2844 static const struct got_error
*err
= NULL
;
2845 struct merge_file_cb_arg
*a
= arg
;
2846 struct got_fileindex_entry
*ie
;
2847 char *ondisk_path
= NULL
;
2849 unsigned char status
;
2850 int local_changes_subsumed
;
2851 FILE *f_orig
= NULL
, *f_deriv
= NULL
, *f_deriv2
= NULL
;
2852 char *id_str
= NULL
, *label_deriv2
= NULL
;
2854 if (blob1
&& blob2
) {
2855 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
2858 return (*a
->progress_cb
)(a
->progress_arg
,
2859 GOT_STATUS_MISSING
, path2
);
2861 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2863 return got_error_from_errno("asprintf");
2865 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2870 if (status
== GOT_STATUS_DELETE
) {
2871 err
= (*a
->progress_cb
)(a
->progress_arg
,
2872 GOT_STATUS_MERGE
, path2
);
2875 if (status
!= GOT_STATUS_NO_CHANGE
&&
2876 status
!= GOT_STATUS_MODIFY
&&
2877 status
!= GOT_STATUS_CONFLICT
&&
2878 status
!= GOT_STATUS_ADD
) {
2879 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path2
);
2883 if (S_ISLNK(mode1
) && S_ISLNK(mode2
)) {
2885 err
= got_object_blob_read_to_str(&link_target2
, blob2
);
2888 err
= merge_symlink(a
->worktree
, blob1
, ondisk_path
,
2889 path2
, a
->label_orig
, link_target2
, a
->commit_id2
,
2890 repo
, a
->progress_cb
, a
->progress_arg
);
2895 f_orig
= got_opentemp();
2896 if (f_orig
== NULL
) {
2897 err
= got_error_from_errno("got_opentemp");
2900 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2905 f_deriv2
= got_opentemp();
2906 if (f_deriv2
== NULL
)
2908 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
,
2913 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
);
2915 err
= got_error_from_errno2("open",
2919 f_deriv
= fdopen(fd
, "r");
2920 if (f_deriv
== NULL
) {
2921 err
= got_error_from_errno2("fdopen",
2926 err
= got_object_id_str(&id_str
, a
->commit_id2
);
2929 if (asprintf(&label_deriv2
, "%s: commit %s",
2930 GOT_MERGE_LABEL_MERGED
, id_str
) == -1) {
2931 err
= got_error_from_errno("asprintf");
2934 err
= merge_file(&local_changes_subsumed
, a
->worktree
,
2935 f_orig
, f_deriv
, f_deriv2
, ondisk_path
, path2
,
2936 sb
.st_mode
, a
->label_orig
, NULL
, label_deriv2
,
2937 GOT_DIFF_ALGORITHM_PATIENCE
, repo
,
2938 a
->progress_cb
, a
->progress_arg
);
2941 ie
= got_fileindex_entry_get(a
->fileindex
, path1
,
2944 return (*a
->progress_cb
)(a
->progress_arg
,
2945 GOT_STATUS_MISSING
, path1
);
2947 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
2949 return got_error_from_errno("asprintf");
2951 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
,
2957 case GOT_STATUS_NO_CHANGE
:
2958 err
= (*a
->progress_cb
)(a
->progress_arg
,
2959 GOT_STATUS_DELETE
, path1
);
2962 err
= remove_ondisk_file(a
->worktree
->root_path
, path1
);
2966 got_fileindex_entry_mark_deleted_from_disk(ie
);
2968 case GOT_STATUS_DELETE
:
2969 case GOT_STATUS_MISSING
:
2970 err
= (*a
->progress_cb
)(a
->progress_arg
,
2971 GOT_STATUS_DELETE
, path1
);
2975 got_fileindex_entry_mark_deleted_from_disk(ie
);
2977 case GOT_STATUS_ADD
: {
2978 struct got_object_id
*id
;
2981 * Delete the added file only if its content already
2982 * exists in the repository.
2984 err
= got_object_blob_file_create(&id
, &blob1_f
, path1
);
2987 if (got_object_id_cmp(id
, id1
) == 0) {
2988 err
= (*a
->progress_cb
)(a
->progress_arg
,
2989 GOT_STATUS_DELETE
, path1
);
2992 err
= remove_ondisk_file(a
->worktree
->root_path
,
2997 got_fileindex_entry_remove(a
->fileindex
,
3000 err
= (*a
->progress_cb
)(a
->progress_arg
,
3001 GOT_STATUS_CANNOT_DELETE
, path1
);
3003 if (fclose(blob1_f
) == EOF
&& err
== NULL
)
3004 err
= got_error_from_errno("fclose");
3010 case GOT_STATUS_MODIFY
:
3011 case GOT_STATUS_CONFLICT
:
3012 err
= (*a
->progress_cb
)(a
->progress_arg
,
3013 GOT_STATUS_CANNOT_DELETE
, path1
);
3017 case GOT_STATUS_OBSTRUCTED
:
3018 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path1
);
3026 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3028 return got_error_from_errno("asprintf");
3029 ie
= got_fileindex_entry_get(a
->fileindex
, path2
,
3032 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
3036 if (status
!= GOT_STATUS_NO_CHANGE
&&
3037 status
!= GOT_STATUS_MODIFY
&&
3038 status
!= GOT_STATUS_CONFLICT
&&
3039 status
!= GOT_STATUS_ADD
) {
3040 err
= (*a
->progress_cb
)(a
->progress_arg
,
3044 if (S_ISLNK(mode2
) && S_ISLNK(sb
.st_mode
)) {
3046 err
= got_object_blob_read_to_str(&link_target2
,
3050 err
= merge_symlink(a
->worktree
, NULL
,
3051 ondisk_path
, path2
, a
->label_orig
,
3052 link_target2
, a
->commit_id2
, repo
,
3053 a
->progress_cb
, a
->progress_arg
);
3055 } else if (S_ISREG(sb
.st_mode
)) {
3056 err
= merge_blob(&local_changes_subsumed
,
3057 a
->worktree
, NULL
, ondisk_path
, path2
,
3058 sb
.st_mode
, a
->label_orig
, blob2
,
3059 a
->commit_id2
, repo
, a
->progress_cb
,
3062 err
= got_error_path(ondisk_path
,
3063 GOT_ERR_FILE_OBSTRUCTED
);
3067 if (status
== GOT_STATUS_DELETE
) {
3068 err
= got_fileindex_entry_update(ie
,
3069 a
->worktree
->root_fd
, path2
, blob2
->id
.sha1
,
3070 a
->worktree
->base_commit_id
->sha1
, 0);
3075 int is_bad_symlink
= 0;
3076 sb
.st_mode
= GOT_DEFAULT_FILE_MODE
;
3077 if (S_ISLNK(mode2
)) {
3078 err
= install_symlink(&is_bad_symlink
,
3079 a
->worktree
, ondisk_path
, path2
, blob2
, 0,
3080 0, 1, repo
, a
->progress_cb
, a
->progress_arg
);
3082 err
= install_blob(a
->worktree
, ondisk_path
, path2
,
3083 mode2
, sb
.st_mode
, blob2
, 0, 0, 0, 1, repo
,
3084 a
->progress_cb
, a
->progress_arg
);
3088 err
= got_fileindex_entry_alloc(&ie
, path2
);
3091 err
= got_fileindex_entry_update(ie
,
3092 a
->worktree
->root_fd
, path2
, NULL
, NULL
, 1);
3094 got_fileindex_entry_free(ie
);
3097 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
3099 got_fileindex_entry_free(ie
);
3102 if (is_bad_symlink
) {
3103 got_fileindex_entry_filetype_set(ie
,
3104 GOT_FILEIDX_MODE_BAD_SYMLINK
);
3109 if (f_orig
&& fclose(f_orig
) == EOF
&& err
== NULL
)
3110 err
= got_error_from_errno("fclose");
3111 if (f_deriv
&& fclose(f_deriv
) == EOF
&& err
== NULL
)
3112 err
= got_error_from_errno("fclose");
3113 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
3114 err
= got_error_from_errno("fclose");
3121 struct check_merge_ok_arg
{
3122 struct got_worktree
*worktree
;
3123 struct got_repository
*repo
;
3126 static const struct got_error
*
3127 check_merge_ok(void *arg
, struct got_fileindex_entry
*ie
)
3129 const struct got_error
*err
= NULL
;
3130 struct check_merge_ok_arg
*a
= arg
;
3131 unsigned char status
;
3135 /* Reject merges into a work tree with mixed base commits. */
3136 if (memcmp(ie
->commit_sha1
, a
->worktree
->base_commit_id
->sha1
,
3137 SHA1_DIGEST_LENGTH
))
3138 return got_error(GOT_ERR_MIXED_COMMITS
);
3140 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
3142 return got_error_from_errno("asprintf");
3144 /* Reject merges into a work tree with conflicted files. */
3145 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
3148 if (status
== GOT_STATUS_CONFLICT
)
3149 return got_error(GOT_ERR_CONFLICTS
);
3154 static const struct got_error
*
3155 merge_files(struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
3156 const char *fileindex_path
, struct got_object_id
*commit_id1
,
3157 struct got_object_id
*commit_id2
, struct got_repository
*repo
,
3158 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
3159 got_cancel_cb cancel_cb
, void *cancel_arg
)
3161 const struct got_error
*err
= NULL
, *sync_err
;
3162 struct got_object_id
*tree_id1
= NULL
, *tree_id2
= NULL
;
3163 struct got_tree_object
*tree1
= NULL
, *tree2
= NULL
;
3164 struct merge_file_cb_arg arg
;
3165 char *label_orig
= NULL
;
3168 err
= got_object_id_by_path(&tree_id1
, repo
, commit_id1
,
3169 worktree
->path_prefix
);
3170 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
3176 err
= got_object_open_as_tree(&tree1
, repo
, tree_id1
);
3180 err
= got_object_id_str(&id_str
, commit_id1
);
3184 if (asprintf(&label_orig
, "%s: commit %s",
3185 GOT_MERGE_LABEL_BASE
, id_str
) == -1) {
3186 err
= got_error_from_errno("asprintf");
3193 err
= got_object_id_by_path(&tree_id2
, repo
, commit_id2
,
3194 worktree
->path_prefix
);
3198 err
= got_object_open_as_tree(&tree2
, repo
, tree_id2
);
3202 arg
.worktree
= worktree
;
3203 arg
.fileindex
= fileindex
;
3204 arg
.progress_cb
= progress_cb
;
3205 arg
.progress_arg
= progress_arg
;
3206 arg
.cancel_cb
= cancel_cb
;
3207 arg
.cancel_arg
= cancel_arg
;
3208 arg
.label_orig
= label_orig
;
3209 arg
.commit_id2
= commit_id2
;
3210 err
= got_diff_tree(tree1
, tree2
, "", "", repo
, merge_file_cb
, &arg
, 1);
3211 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
3212 if (sync_err
&& err
== NULL
)
3216 got_object_tree_close(tree1
);
3218 got_object_tree_close(tree2
);
3223 const struct got_error
*
3224 got_worktree_merge_files(struct got_worktree
*worktree
,
3225 struct got_object_id
*commit_id1
, struct got_object_id
*commit_id2
,
3226 struct got_repository
*repo
, got_worktree_checkout_cb progress_cb
,
3227 void *progress_arg
, got_cancel_cb cancel_cb
, void *cancel_arg
)
3229 const struct got_error
*err
, *unlockerr
;
3230 char *fileindex_path
= NULL
;
3231 struct got_fileindex
*fileindex
= NULL
;
3232 struct check_merge_ok_arg mok_arg
;
3234 err
= lock_worktree(worktree
, LOCK_EX
);
3238 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3242 mok_arg
.worktree
= worktree
;
3243 mok_arg
.repo
= repo
;
3244 err
= got_fileindex_for_each_entry_safe(fileindex
, check_merge_ok
,
3249 err
= merge_files(worktree
, fileindex
, fileindex_path
, commit_id1
,
3250 commit_id2
, repo
, progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
3253 got_fileindex_free(fileindex
);
3254 free(fileindex_path
);
3255 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
3256 if (unlockerr
&& err
== NULL
)
3261 struct diff_dir_cb_arg
{
3262 struct got_fileindex
*fileindex
;
3263 struct got_worktree
*worktree
;
3264 const char *status_path
;
3265 size_t status_path_len
;
3266 struct got_repository
*repo
;
3267 got_worktree_status_cb status_cb
;
3269 got_cancel_cb cancel_cb
;
3271 /* A pathlist containing per-directory pathlists of ignore patterns. */
3272 struct got_pathlist_head
*ignores
;
3273 int report_unchanged
;
3277 static const struct got_error
*
3278 report_file_status(struct got_fileindex_entry
*ie
, const char *abspath
,
3279 int dirfd
, const char *de_name
,
3280 got_worktree_status_cb status_cb
, void *status_arg
,
3281 struct got_repository
*repo
, int report_unchanged
)
3283 const struct got_error
*err
= NULL
;
3284 unsigned char status
= GOT_STATUS_NO_CHANGE
;
3285 unsigned char staged_status
= get_staged_status(ie
);
3287 struct got_object_id blob_id
, commit_id
, staged_blob_id
;
3288 struct got_object_id
*blob_idp
= NULL
, *commit_idp
= NULL
;
3289 struct got_object_id
*staged_blob_idp
= NULL
;
3291 err
= get_file_status(&status
, &sb
, ie
, abspath
, dirfd
, de_name
, repo
);
3295 if (status
== GOT_STATUS_NO_CHANGE
&&
3296 staged_status
== GOT_STATUS_NO_CHANGE
&& !report_unchanged
)
3299 if (got_fileindex_entry_has_blob(ie
)) {
3300 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3301 blob_idp
= &blob_id
;
3303 if (got_fileindex_entry_has_commit(ie
)) {
3304 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3305 commit_idp
= &commit_id
;
3307 if (staged_status
== GOT_STATUS_ADD
||
3308 staged_status
== GOT_STATUS_MODIFY
) {
3309 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
3310 SHA1_DIGEST_LENGTH
);
3311 staged_blob_idp
= &staged_blob_id
;
3314 return (*status_cb
)(status_arg
, status
, staged_status
,
3315 ie
->path
, blob_idp
, staged_blob_idp
, commit_idp
, dirfd
, de_name
);
3318 static const struct got_error
*
3319 status_old_new(void *arg
, struct got_fileindex_entry
*ie
,
3320 struct dirent
*de
, const char *parent_path
, int dirfd
)
3322 const struct got_error
*err
= NULL
;
3323 struct diff_dir_cb_arg
*a
= arg
;
3326 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3327 return got_error(GOT_ERR_CANCELLED
);
3329 if (got_path_cmp(parent_path
, a
->status_path
,
3330 strlen(parent_path
), a
->status_path_len
) != 0 &&
3331 !got_path_is_child(parent_path
, a
->status_path
, a
->status_path_len
))
3334 if (parent_path
[0]) {
3335 if (asprintf(&abspath
, "%s/%s/%s", a
->worktree
->root_path
,
3336 parent_path
, de
->d_name
) == -1)
3337 return got_error_from_errno("asprintf");
3339 if (asprintf(&abspath
, "%s/%s", a
->worktree
->root_path
,
3341 return got_error_from_errno("asprintf");
3344 err
= report_file_status(ie
, abspath
, dirfd
, de
->d_name
,
3345 a
->status_cb
, a
->status_arg
, a
->repo
, a
->report_unchanged
);
3350 static const struct got_error
*
3351 status_old(void *arg
, struct got_fileindex_entry
*ie
, const char *parent_path
)
3353 struct diff_dir_cb_arg
*a
= arg
;
3354 struct got_object_id blob_id
, commit_id
;
3355 unsigned char status
;
3357 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3358 return got_error(GOT_ERR_CANCELLED
);
3360 if (!got_path_is_child(ie
->path
, a
->status_path
, a
->status_path_len
))
3363 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
3364 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
3365 if (got_fileindex_entry_has_file_on_disk(ie
))
3366 status
= GOT_STATUS_MISSING
;
3368 status
= GOT_STATUS_DELETE
;
3369 return (*a
->status_cb
)(a
->status_arg
, status
, get_staged_status(ie
),
3370 ie
->path
, &blob_id
, NULL
, &commit_id
, -1, NULL
);
3374 free_ignorelist(struct got_pathlist_head
*ignorelist
)
3376 struct got_pathlist_entry
*pe
;
3378 TAILQ_FOREACH(pe
, ignorelist
, entry
)
3379 free((char *)pe
->path
);
3380 got_pathlist_free(ignorelist
);
3384 free_ignores(struct got_pathlist_head
*ignores
)
3386 struct got_pathlist_entry
*pe
;
3388 TAILQ_FOREACH(pe
, ignores
, entry
) {
3389 struct got_pathlist_head
*ignorelist
= pe
->data
;
3390 free_ignorelist(ignorelist
);
3391 free((char *)pe
->path
);
3393 got_pathlist_free(ignores
);
3396 static const struct got_error
*
3397 read_ignores(struct got_pathlist_head
*ignores
, const char *path
, FILE *f
)
3399 const struct got_error
*err
= NULL
;
3400 struct got_pathlist_entry
*pe
= NULL
;
3401 struct got_pathlist_head
*ignorelist
;
3402 char *line
= NULL
, *pattern
, *dirpath
= NULL
;
3403 size_t linesize
= 0;
3406 ignorelist
= calloc(1, sizeof(*ignorelist
));
3407 if (ignorelist
== NULL
)
3408 return got_error_from_errno("calloc");
3409 TAILQ_INIT(ignorelist
);
3411 while ((linelen
= getline(&line
, &linesize
, f
)) != -1) {
3412 if (linelen
> 0 && line
[linelen
- 1] == '\n')
3413 line
[linelen
- 1] = '\0';
3415 /* Git's ignores may contain comments. */
3419 /* Git's negated patterns are not (yet?) supported. */
3423 if (asprintf(&pattern
, "%s%s%s", path
, path
[0] ? "/" : "",
3425 err
= got_error_from_errno("asprintf");
3428 err
= got_pathlist_insert(NULL
, ignorelist
, pattern
, NULL
);
3433 err
= got_error_from_errno("getline");
3437 dirpath
= strdup(path
);
3438 if (dirpath
== NULL
) {
3439 err
= got_error_from_errno("strdup");
3442 err
= got_pathlist_insert(&pe
, ignores
, dirpath
, ignorelist
);
3445 if (err
|| pe
== NULL
) {
3447 free_ignorelist(ignorelist
);
3453 match_ignores(struct got_pathlist_head
*ignores
, const char *path
)
3455 struct got_pathlist_entry
*pe
;
3457 /* Handle patterns which match in all directories. */
3458 TAILQ_FOREACH(pe
, ignores
, entry
) {
3459 struct got_pathlist_head
*ignorelist
= pe
->data
;
3460 struct got_pathlist_entry
*pi
;
3462 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3463 const char *p
, *pattern
= pi
->path
;
3465 if (strncmp(pattern
, "**/", 3) != 0)
3470 if (fnmatch(pattern
, p
,
3471 FNM_PATHNAME
| FNM_LEADING_DIR
)) {
3472 /* Retry in next directory. */
3473 while (*p
&& *p
!= '/')
3485 * The ignores pathlist contains ignore lists from children before
3486 * parents, so we can find the most specific ignorelist by walking
3487 * ignores backwards.
3489 pe
= TAILQ_LAST(ignores
, got_pathlist_head
);
3491 if (got_path_is_child(path
, pe
->path
, pe
->path_len
)) {
3492 struct got_pathlist_head
*ignorelist
= pe
->data
;
3493 struct got_pathlist_entry
*pi
;
3494 TAILQ_FOREACH(pi
, ignorelist
, entry
) {
3495 const char *pattern
= pi
->path
;
3496 int flags
= FNM_LEADING_DIR
;
3497 if (strstr(pattern
, "/**/") == NULL
)
3498 flags
|= FNM_PATHNAME
;
3499 if (fnmatch(pattern
, path
, flags
))
3504 pe
= TAILQ_PREV(pe
, got_pathlist_head
, entry
);
3510 static const struct got_error
*
3511 add_ignores(struct got_pathlist_head
*ignores
, const char *root_path
,
3512 const char *path
, int dirfd
, const char *ignores_filename
)
3514 const struct got_error
*err
= NULL
;
3517 FILE *ignoresfile
= NULL
;
3519 if (asprintf(&ignorespath
, "%s/%s%s%s", root_path
, path
,
3520 path
[0] ? "/" : "", ignores_filename
) == -1)
3521 return got_error_from_errno("asprintf");
3524 fd
= openat(dirfd
, ignores_filename
, O_RDONLY
| O_NOFOLLOW
);
3526 if (errno
!= ENOENT
&& errno
!= EACCES
)
3527 err
= got_error_from_errno2("openat",
3530 ignoresfile
= fdopen(fd
, "r");
3531 if (ignoresfile
== NULL
)
3532 err
= got_error_from_errno2("fdopen",
3536 err
= read_ignores(ignores
, path
, ignoresfile
);
3540 ignoresfile
= fopen(ignorespath
, "r");
3541 if (ignoresfile
== NULL
) {
3542 if (errno
!= ENOENT
&& errno
!= EACCES
)
3543 err
= got_error_from_errno2("fopen",
3546 err
= read_ignores(ignores
, path
, ignoresfile
);
3549 if (ignoresfile
&& fclose(ignoresfile
) == EOF
&& err
== NULL
)
3550 err
= got_error_from_errno2("fclose", path
);
3551 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3552 err
= got_error_from_errno2("close", path
);
3557 static const struct got_error
*
3558 status_new(void *arg
, struct dirent
*de
, const char *parent_path
, int dirfd
)
3560 const struct got_error
*err
= NULL
;
3561 struct diff_dir_cb_arg
*a
= arg
;
3564 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
3565 return got_error(GOT_ERR_CANCELLED
);
3567 if (parent_path
[0]) {
3568 if (asprintf(&path
, "%s/%s", parent_path
, de
->d_name
) == -1)
3569 return got_error_from_errno("asprintf");
3574 if (de
->d_type
!= DT_DIR
&&
3575 got_path_is_child(path
, a
->status_path
, a
->status_path_len
)
3576 && !match_ignores(a
->ignores
, path
))
3577 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_UNVERSIONED
,
3578 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3584 static const struct got_error
*
3585 status_traverse(void *arg
, const char *path
, int dirfd
)
3587 const struct got_error
*err
= NULL
;
3588 struct diff_dir_cb_arg
*a
= arg
;
3593 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
,
3594 path
, dirfd
, ".cvsignore");
3598 err
= add_ignores(a
->ignores
, a
->worktree
->root_path
, path
,
3599 dirfd
, ".gitignore");
3604 static const struct got_error
*
3605 report_single_file_status(const char *path
, const char *ondisk_path
,
3606 struct got_fileindex
*fileindex
, got_worktree_status_cb status_cb
,
3607 void *status_arg
, struct got_repository
*repo
, int report_unchanged
,
3608 struct got_pathlist_head
*ignores
, int no_ignores
)
3610 struct got_fileindex_entry
*ie
;
3613 if (!no_ignores
&& match_ignores(ignores
, path
))
3616 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
3618 return report_file_status(ie
, ondisk_path
, -1, NULL
,
3619 status_cb
, status_arg
, repo
, report_unchanged
);
3621 if (lstat(ondisk_path
, &sb
) == -1) {
3622 if (errno
!= ENOENT
)
3623 return got_error_from_errno2("lstat", ondisk_path
);
3624 return (*status_cb
)(status_arg
, GOT_STATUS_NONEXISTENT
,
3625 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3629 if (S_ISREG(sb
.st_mode
) || S_ISLNK(sb
.st_mode
))
3630 return (*status_cb
)(status_arg
, GOT_STATUS_UNVERSIONED
,
3631 GOT_STATUS_NO_CHANGE
, path
, NULL
, NULL
, NULL
, -1, NULL
);
3636 static const struct got_error
*
3637 add_ignores_from_parent_paths(struct got_pathlist_head
*ignores
,
3638 const char *root_path
, const char *path
)
3640 const struct got_error
*err
;
3641 char *parent_path
, *next_parent_path
= NULL
;
3643 err
= add_ignores(ignores
, root_path
, "", -1,
3648 err
= add_ignores(ignores
, root_path
, "", -1,
3653 err
= got_path_dirname(&parent_path
, path
);
3655 if (err
->code
== GOT_ERR_BAD_PATH
)
3656 return NULL
; /* cannot traverse parent */
3660 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3664 err
= add_ignores(ignores
, root_path
, parent_path
, -1,
3668 err
= got_path_dirname(&next_parent_path
, parent_path
);
3670 if (err
->code
== GOT_ERR_BAD_PATH
)
3671 err
= NULL
; /* traversed everything */
3674 if (got_path_is_root_dir(parent_path
))
3677 parent_path
= next_parent_path
;
3678 next_parent_path
= NULL
;
3682 free(next_parent_path
);
3686 static const struct got_error
*
3687 worktree_status(struct got_worktree
*worktree
, const char *path
,
3688 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
3689 got_worktree_status_cb status_cb
, void *status_arg
,
3690 got_cancel_cb cancel_cb
, void *cancel_arg
, int no_ignores
,
3691 int report_unchanged
)
3693 const struct got_error
*err
= NULL
;
3695 struct got_fileindex_diff_dir_cb fdiff_cb
;
3696 struct diff_dir_cb_arg arg
;
3697 char *ondisk_path
= NULL
;
3698 struct got_pathlist_head ignores
;
3700 TAILQ_INIT(&ignores
);
3702 if (asprintf(&ondisk_path
, "%s%s%s",
3703 worktree
->root_path
, path
[0] ? "/" : "", path
) == -1)
3704 return got_error_from_errno("asprintf");
3706 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
| O_DIRECTORY
);
3708 if (errno
!= ENOTDIR
&& errno
!= ENOENT
&& errno
!= EACCES
&&
3710 err
= got_error_from_errno2("open", ondisk_path
);
3713 err
= add_ignores_from_parent_paths(&ignores
,
3714 worktree
->root_path
, ondisk_path
);
3718 err
= report_single_file_status(path
, ondisk_path
,
3719 fileindex
, status_cb
, status_arg
, repo
,
3720 report_unchanged
, &ignores
, no_ignores
);
3723 fdiff_cb
.diff_old_new
= status_old_new
;
3724 fdiff_cb
.diff_old
= status_old
;
3725 fdiff_cb
.diff_new
= status_new
;
3726 fdiff_cb
.diff_traverse
= status_traverse
;
3727 arg
.fileindex
= fileindex
;
3728 arg
.worktree
= worktree
;
3729 arg
.status_path
= path
;
3730 arg
.status_path_len
= strlen(path
);
3732 arg
.status_cb
= status_cb
;
3733 arg
.status_arg
= status_arg
;
3734 arg
.cancel_cb
= cancel_cb
;
3735 arg
.cancel_arg
= cancel_arg
;
3736 arg
.report_unchanged
= report_unchanged
;
3737 arg
.no_ignores
= no_ignores
;
3739 err
= add_ignores_from_parent_paths(&ignores
,
3740 worktree
->root_path
, path
);
3744 arg
.ignores
= &ignores
;
3745 err
= got_fileindex_diff_dir(fileindex
, fd
,
3746 worktree
->root_path
, path
, repo
, &fdiff_cb
, &arg
);
3749 free_ignores(&ignores
);
3750 if (fd
!= -1 && close(fd
) == -1 && err
== NULL
)
3751 err
= got_error_from_errno("close");
3756 const struct got_error
*
3757 got_worktree_status(struct got_worktree
*worktree
,
3758 struct got_pathlist_head
*paths
, struct got_repository
*repo
,
3759 int no_ignores
, got_worktree_status_cb status_cb
, void *status_arg
,
3760 got_cancel_cb cancel_cb
, void *cancel_arg
)
3762 const struct got_error
*err
= NULL
;
3763 char *fileindex_path
= NULL
;
3764 struct got_fileindex
*fileindex
= NULL
;
3765 struct got_pathlist_entry
*pe
;
3767 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3771 TAILQ_FOREACH(pe
, paths
, entry
) {
3772 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
3773 status_cb
, status_arg
, cancel_cb
, cancel_arg
,
3778 free(fileindex_path
);
3779 got_fileindex_free(fileindex
);
3783 const struct got_error
*
3784 got_worktree_resolve_path(char **wt_path
, struct got_worktree
*worktree
,
3787 const struct got_error
*err
= NULL
;
3788 char *resolved
= NULL
, *cwd
= NULL
, *path
= NULL
;
3791 char *abspath
= NULL
;
3792 char canonpath
[PATH_MAX
];
3796 cwd
= getcwd(NULL
, 0);
3798 return got_error_from_errno("getcwd");
3800 if (lstat(arg
, &sb
) == -1) {
3801 if (errno
!= ENOENT
) {
3802 err
= got_error_from_errno2("lstat", arg
);
3807 if (S_ISLNK(sb
.st_mode
)) {
3809 * We cannot use realpath(3) with symlinks since we want to
3810 * operate on the symlink itself.
3811 * But we can make the path absolute, assuming it is relative
3812 * to the current working directory, and then canonicalize it.
3814 if (!got_path_is_absolute(arg
)) {
3815 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3816 err
= got_error_from_errno("asprintf");
3821 err
= got_canonpath(abspath
? abspath
: arg
, canonpath
,
3825 resolved
= strdup(canonpath
);
3826 if (resolved
== NULL
) {
3827 err
= got_error_from_errno("strdup");
3831 resolved
= realpath(arg
, NULL
);
3832 if (resolved
== NULL
) {
3833 if (errno
!= ENOENT
) {
3834 err
= got_error_from_errno2("realpath", arg
);
3837 if (asprintf(&abspath
, "%s/%s", cwd
, arg
) == -1) {
3838 err
= got_error_from_errno("asprintf");
3841 err
= got_canonpath(abspath
, canonpath
,
3845 resolved
= strdup(canonpath
);
3846 if (resolved
== NULL
) {
3847 err
= got_error_from_errno("strdup");
3853 if (strncmp(got_worktree_get_root_path(worktree
), resolved
,
3854 strlen(got_worktree_get_root_path(worktree
)))) {
3855 err
= got_error_path(resolved
, GOT_ERR_BAD_PATH
);
3859 if (strlen(resolved
) > strlen(got_worktree_get_root_path(worktree
))) {
3860 err
= got_path_skip_common_ancestor(&path
,
3861 got_worktree_get_root_path(worktree
), resolved
);
3867 err
= got_error_from_errno("strdup");
3872 /* XXX status walk can't deal with trailing slash! */
3874 while (len
> 0 && path
[len
- 1] == '/') {
3875 path
[len
- 1] = '\0';
3889 struct schedule_addition_args
{
3890 struct got_worktree
*worktree
;
3891 struct got_fileindex
*fileindex
;
3892 got_worktree_checkout_cb progress_cb
;
3894 struct got_repository
*repo
;
3897 static const struct got_error
*
3898 schedule_addition(void *arg
, unsigned char status
, unsigned char staged_status
,
3899 const char *relpath
, struct got_object_id
*blob_id
,
3900 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
3901 int dirfd
, const char *de_name
)
3903 struct schedule_addition_args
*a
= arg
;
3904 const struct got_error
*err
= NULL
;
3905 struct got_fileindex_entry
*ie
;
3909 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
3911 return got_error_from_errno("asprintf");
3913 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
3915 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
,
3919 /* Re-adding an existing entry is a no-op. */
3920 if (status
== GOT_STATUS_ADD
)
3922 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
3927 if (status
!= GOT_STATUS_UNVERSIONED
) {
3928 err
= got_error_path(ondisk_path
, GOT_ERR_FILE_STATUS
);
3932 err
= got_fileindex_entry_alloc(&ie
, relpath
);
3935 err
= got_fileindex_entry_update(ie
, a
->worktree
->root_fd
,
3936 relpath
, NULL
, NULL
, 1);
3938 got_fileindex_entry_free(ie
);
3941 err
= got_fileindex_entry_add(a
->fileindex
, ie
);
3943 got_fileindex_entry_free(ie
);
3950 if (status
== GOT_STATUS_ADD
)
3952 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_ADD
, relpath
);
3955 const struct got_error
*
3956 got_worktree_schedule_add(struct got_worktree
*worktree
,
3957 struct got_pathlist_head
*paths
,
3958 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
3959 struct got_repository
*repo
, int no_ignores
)
3961 struct got_fileindex
*fileindex
= NULL
;
3962 char *fileindex_path
= NULL
;
3963 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
3964 struct got_pathlist_entry
*pe
;
3965 struct schedule_addition_args saa
;
3967 err
= lock_worktree(worktree
, LOCK_EX
);
3971 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
3975 saa
.worktree
= worktree
;
3976 saa
.fileindex
= fileindex
;
3977 saa
.progress_cb
= progress_cb
;
3978 saa
.progress_arg
= progress_arg
;
3981 TAILQ_FOREACH(pe
, paths
, entry
) {
3982 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
3983 schedule_addition
, &saa
, NULL
, NULL
, no_ignores
, 0);
3987 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
3988 if (sync_err
&& err
== NULL
)
3991 free(fileindex_path
);
3993 got_fileindex_free(fileindex
);
3994 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
3995 if (unlockerr
&& err
== NULL
)
4000 struct schedule_deletion_args
{
4001 struct got_worktree
*worktree
;
4002 struct got_fileindex
*fileindex
;
4003 got_worktree_delete_cb progress_cb
;
4005 struct got_repository
*repo
;
4006 int delete_local_mods
;
4008 const char *status_codes
;
4011 static const struct got_error
*
4012 schedule_for_deletion(void *arg
, unsigned char status
,
4013 unsigned char staged_status
, const char *relpath
,
4014 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4015 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4017 struct schedule_deletion_args
*a
= arg
;
4018 const struct got_error
*err
= NULL
;
4019 struct got_fileindex_entry
*ie
= NULL
;
4023 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4025 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
4027 staged_status
= get_staged_status(ie
);
4028 if (staged_status
!= GOT_STATUS_NO_CHANGE
) {
4029 if (staged_status
== GOT_STATUS_DELETE
)
4031 return got_error_path(relpath
, GOT_ERR_FILE_STAGED
);
4034 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
4036 return got_error_from_errno("asprintf");
4038 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, dirfd
, de_name
,
4043 if (a
->status_codes
) {
4044 size_t ncodes
= strlen(a
->status_codes
);
4046 for (i
= 0; i
< ncodes
; i
++) {
4047 if (status
== a
->status_codes
[i
])
4051 /* Do not delete files in non-matching status. */
4055 if (a
->status_codes
[i
] != GOT_STATUS_MODIFY
&&
4056 a
->status_codes
[i
] != GOT_STATUS_MISSING
) {
4057 static char msg
[64];
4058 snprintf(msg
, sizeof(msg
),
4059 "invalid status code '%c'", a
->status_codes
[i
]);
4060 err
= got_error_msg(GOT_ERR_FILE_STATUS
, msg
);
4065 if (status
!= GOT_STATUS_NO_CHANGE
) {
4066 if (status
== GOT_STATUS_DELETE
)
4068 if (status
== GOT_STATUS_MODIFY
&& !a
->delete_local_mods
) {
4069 err
= got_error_path(relpath
, GOT_ERR_FILE_MODIFIED
);
4072 if (status
!= GOT_STATUS_MODIFY
&&
4073 status
!= GOT_STATUS_MISSING
) {
4074 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
4079 if (!a
->keep_on_disk
&& status
!= GOT_STATUS_MISSING
) {
4083 if (unlinkat(dirfd
, de_name
, 0) != 0) {
4084 err
= got_error_from_errno2("unlinkat",
4088 } else if (unlink(ondisk_path
) != 0) {
4089 err
= got_error_from_errno2("unlink", ondisk_path
);
4093 root_len
= strlen(a
->worktree
->root_path
);
4096 err
= got_path_dirname(&parent
, ondisk_path
);
4100 ondisk_path
= parent
;
4101 if (rmdir(ondisk_path
) == -1) {
4102 if (errno
!= ENOTEMPTY
)
4103 err
= got_error_from_errno2("rmdir",
4107 } while (got_path_cmp(ondisk_path
, a
->worktree
->root_path
,
4108 strlen(ondisk_path
), root_len
) != 0);
4111 got_fileindex_entry_mark_deleted_from_disk(ie
);
4116 if (status
== GOT_STATUS_DELETE
)
4118 return (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_DELETE
,
4119 staged_status
, relpath
);
4122 const struct got_error
*
4123 got_worktree_schedule_delete(struct got_worktree
*worktree
,
4124 struct got_pathlist_head
*paths
, int delete_local_mods
,
4125 const char *status_codes
,
4126 got_worktree_delete_cb progress_cb
, void *progress_arg
,
4127 struct got_repository
*repo
, int keep_on_disk
)
4129 struct got_fileindex
*fileindex
= NULL
;
4130 char *fileindex_path
= NULL
;
4131 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
4132 struct got_pathlist_entry
*pe
;
4133 struct schedule_deletion_args sda
;
4135 err
= lock_worktree(worktree
, LOCK_EX
);
4139 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4143 sda
.worktree
= worktree
;
4144 sda
.fileindex
= fileindex
;
4145 sda
.progress_cb
= progress_cb
;
4146 sda
.progress_arg
= progress_arg
;
4148 sda
.delete_local_mods
= delete_local_mods
;
4149 sda
.keep_on_disk
= keep_on_disk
;
4150 sda
.status_codes
= status_codes
;
4152 TAILQ_FOREACH(pe
, paths
, entry
) {
4153 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4154 schedule_for_deletion
, &sda
, NULL
, NULL
, 0, 1);
4158 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4159 if (sync_err
&& err
== NULL
)
4162 free(fileindex_path
);
4164 got_fileindex_free(fileindex
);
4165 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4166 if (unlockerr
&& err
== NULL
)
4171 static const struct got_error
*
4172 copy_one_line(FILE *infile
, FILE *outfile
, FILE *rejectfile
)
4174 const struct got_error
*err
= NULL
;
4176 size_t linesize
= 0, n
;
4179 linelen
= getline(&line
, &linesize
, infile
);
4180 if (linelen
== -1) {
4181 if (ferror(infile
)) {
4182 err
= got_error_from_errno("getline");
4188 n
= fwrite(line
, 1, linelen
, outfile
);
4190 err
= got_ferror(outfile
, GOT_ERR_IO
);
4195 n
= fwrite(line
, 1, linelen
, rejectfile
);
4197 err
= got_ferror(outfile
, GOT_ERR_IO
);
4204 static const struct got_error
*
4205 skip_one_line(FILE *f
)
4208 size_t linesize
= 0;
4211 linelen
= getline(&line
, &linesize
, f
);
4212 if (linelen
== -1) {
4214 return got_error_from_errno("getline");
4221 static const struct got_error
*
4222 copy_change(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4223 int start_old
, int end_old
, int start_new
, int end_new
,
4224 FILE *outfile
, FILE *rejectfile
)
4226 const struct got_error
*err
;
4228 /* Copy old file's lines leading up to patch. */
4229 while (!feof(f1
) && *line_cur1
< start_old
) {
4230 err
= copy_one_line(f1
, outfile
, NULL
);
4235 /* Skip new file's lines leading up to patch. */
4236 while (!feof(f2
) && *line_cur2
< start_new
) {
4238 err
= copy_one_line(f2
, NULL
, rejectfile
);
4240 err
= skip_one_line(f2
);
4245 /* Copy patched lines. */
4246 while (!feof(f2
) && *line_cur2
<= end_new
) {
4247 err
= copy_one_line(f2
, outfile
, NULL
);
4252 /* Skip over old file's replaced lines. */
4253 while (!feof(f1
) && *line_cur1
<= end_old
) {
4255 err
= copy_one_line(f1
, NULL
, rejectfile
);
4257 err
= skip_one_line(f1
);
4266 static const struct got_error
*
4267 copy_remaining_content(FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4268 FILE *outfile
, FILE *rejectfile
)
4270 const struct got_error
*err
;
4273 /* Copy old file's lines until EOF. */
4275 err
= copy_one_line(f1
, outfile
, NULL
);
4282 /* Copy new file's lines until EOF. */
4284 err
= copy_one_line(f2
, NULL
, rejectfile
);
4294 static const struct got_error
*
4295 apply_or_reject_change(int *choice
, int *nchunks_used
,
4296 struct diff_result
*diff_result
, int n
,
4297 const char *relpath
, FILE *f1
, FILE *f2
, int *line_cur1
, int *line_cur2
,
4298 FILE *outfile
, FILE *rejectfile
, int changeno
, int nchanges
,
4299 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4301 const struct got_error
*err
= NULL
;
4302 struct diff_chunk_context cc
= {};
4303 int start_old
, end_old
, start_new
, end_new
;
4305 struct diff_output_unidiff_state
*diff_state
;
4306 struct diff_input_info diff_info
;
4309 *choice
= GOT_PATCH_CHOICE_NONE
;
4311 /* Get changed line numbers without context lines for copy_change(). */
4312 diff_chunk_context_load_change(&cc
, NULL
, diff_result
, n
, 0);
4313 start_old
= cc
.left
.start
;
4314 end_old
= cc
.left
.end
;
4315 start_new
= cc
.right
.start
;
4316 end_new
= cc
.right
.end
;
4318 /* Get the same change with context lines for display. */
4319 memset(&cc
, 0, sizeof(cc
));
4320 diff_chunk_context_load_change(&cc
, nchunks_used
, diff_result
, n
, 3);
4322 memset(&diff_info
, 0, sizeof(diff_info
));
4323 diff_info
.left_path
= relpath
;
4324 diff_info
.right_path
= relpath
;
4326 diff_state
= diff_output_unidiff_state_alloc();
4327 if (diff_state
== NULL
)
4328 return got_error_set_errno(ENOMEM
,
4329 "diff_output_unidiff_state_alloc");
4331 hunkfile
= got_opentemp();
4332 if (hunkfile
== NULL
) {
4333 err
= got_error_from_errno("got_opentemp");
4337 rc
= diff_output_unidiff_chunk(NULL
, hunkfile
, diff_state
, &diff_info
,
4339 if (rc
!= DIFF_RC_OK
) {
4340 err
= got_error_set_errno(rc
, "diff_output_unidiff_chunk");
4344 if (fseek(hunkfile
, 0L, SEEK_SET
) == -1) {
4345 err
= got_ferror(hunkfile
, GOT_ERR_IO
);
4349 err
= (*patch_cb
)(choice
, patch_arg
, GOT_STATUS_MODIFY
, relpath
,
4350 hunkfile
, changeno
, nchanges
);
4355 case GOT_PATCH_CHOICE_YES
:
4356 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4357 end_old
, start_new
, end_new
, outfile
, rejectfile
);
4359 case GOT_PATCH_CHOICE_NO
:
4360 err
= copy_change(f1
, f2
, line_cur1
, line_cur2
, start_old
,
4361 end_old
, start_new
, end_new
, rejectfile
, outfile
);
4363 case GOT_PATCH_CHOICE_QUIT
:
4366 err
= got_error(GOT_ERR_PATCH_CHOICE
);
4370 diff_output_unidiff_state_free(diff_state
);
4371 if (hunkfile
&& fclose(hunkfile
) == EOF
&& err
== NULL
)
4372 err
= got_error_from_errno("fclose");
4376 struct revert_file_args
{
4377 struct got_worktree
*worktree
;
4378 struct got_fileindex
*fileindex
;
4379 got_worktree_checkout_cb progress_cb
;
4381 got_worktree_patch_cb patch_cb
;
4383 struct got_repository
*repo
;
4386 static const struct got_error
*
4387 create_patched_content(char **path_outfile
, int reverse_patch
,
4388 struct got_object_id
*blob_id
, const char *path2
,
4389 int dirfd2
, const char *de_name2
,
4390 const char *relpath
, struct got_repository
*repo
,
4391 got_worktree_patch_cb patch_cb
, void *patch_arg
)
4393 const struct got_error
*err
, *free_err
;
4394 struct got_blob_object
*blob
= NULL
;
4395 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
;
4397 char link_target
[PATH_MAX
];
4398 ssize_t link_len
= 0;
4399 char *path1
= NULL
, *id_str
= NULL
;
4401 struct got_diffreg_result
*diffreg_result
= NULL
;
4402 int line_cur1
= 1, line_cur2
= 1, have_content
= 0;
4403 int i
= 0, n
= 0, nchunks_used
= 0, nchanges
= 0;
4405 *path_outfile
= NULL
;
4407 err
= got_object_id_str(&id_str
, blob_id
);
4412 fd2
= openat(dirfd2
, de_name2
, O_RDONLY
| O_NOFOLLOW
);
4414 if (errno
!= ELOOP
) {
4415 err
= got_error_from_errno2("openat", path2
);
4418 link_len
= readlinkat(dirfd2
, de_name2
,
4419 link_target
, sizeof(link_target
));
4421 return got_error_from_errno2("readlinkat", path2
);
4422 sb2
.st_mode
= S_IFLNK
;
4423 sb2
.st_size
= link_len
;
4426 fd2
= open(path2
, O_RDONLY
| O_NOFOLLOW
);
4428 if (errno
!= ELOOP
) {
4429 err
= got_error_from_errno2("open", path2
);
4432 link_len
= readlink(path2
, link_target
,
4433 sizeof(link_target
));
4435 return got_error_from_errno2("readlink", path2
);
4436 sb2
.st_mode
= S_IFLNK
;
4437 sb2
.st_size
= link_len
;
4441 if (fstat(fd2
, &sb2
) == -1) {
4442 err
= got_error_from_errno2("fstat", path2
);
4446 f2
= fdopen(fd2
, "r");
4448 err
= got_error_from_errno2("fdopen", path2
);
4454 f2
= got_opentemp();
4456 err
= got_error_from_errno2("got_opentemp", path2
);
4459 n
= fwrite(link_target
, 1, link_len
, f2
);
4460 if (n
!= link_len
) {
4461 err
= got_ferror(f2
, GOT_ERR_IO
);
4464 if (fflush(f2
) == EOF
) {
4465 err
= got_error_from_errno("fflush");
4471 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192);
4475 err
= got_opentemp_named(&path1
, &f1
, "got-patched-blob");
4479 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
4483 err
= got_diff_files(&diffreg_result
, f1
, id_str
, f2
, path2
, 3, 0, 1,
4488 err
= got_opentemp_named(path_outfile
, &outfile
, "got-patched-content");
4492 if (fseek(f1
, 0L, SEEK_SET
) == -1)
4493 return got_ferror(f1
, GOT_ERR_IO
);
4494 if (fseek(f2
, 0L, SEEK_SET
) == -1)
4495 return got_ferror(f2
, GOT_ERR_IO
);
4497 /* Count the number of actual changes in the diff result. */
4498 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4499 struct diff_chunk_context cc
= {};
4500 diff_chunk_context_load_change(&cc
, &nchunks_used
,
4501 diffreg_result
->result
, n
, 0);
4504 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
4506 err
= apply_or_reject_change(&choice
, &nchunks_used
,
4507 diffreg_result
->result
, n
, relpath
, f1
, f2
,
4508 &line_cur1
, &line_cur2
,
4509 reverse_patch
? NULL
: outfile
,
4510 reverse_patch
? outfile
: NULL
,
4511 ++i
, nchanges
, patch_cb
, patch_arg
);
4514 if (choice
== GOT_PATCH_CHOICE_YES
)
4516 else if (choice
== GOT_PATCH_CHOICE_QUIT
)
4520 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
4521 reverse_patch
? NULL
: outfile
,
4522 reverse_patch
? outfile
: NULL
);
4526 if (!S_ISLNK(sb2
.st_mode
)) {
4527 if (fchmod(fileno(outfile
), sb2
.st_mode
) == -1) {
4528 err
= got_error_from_errno2("fchmod", path2
);
4536 got_object_blob_close(blob
);
4537 free_err
= got_diffreg_result_free(diffreg_result
);
4540 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
4541 err
= got_error_from_errno2("fclose", path1
);
4542 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
4543 err
= got_error_from_errno2("fclose", path2
);
4544 if (fd2
!= -1 && close(fd2
) == -1 && err
== NULL
)
4545 err
= got_error_from_errno2("close", path2
);
4546 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
4547 err
= got_error_from_errno2("fclose", *path_outfile
);
4548 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
4549 err
= got_error_from_errno2("unlink", path1
);
4550 if (err
|| !have_content
) {
4551 if (*path_outfile
&& unlink(*path_outfile
) == -1 && err
== NULL
)
4552 err
= got_error_from_errno2("unlink", *path_outfile
);
4553 free(*path_outfile
);
4554 *path_outfile
= NULL
;
4560 static const struct got_error
*
4561 revert_file(void *arg
, unsigned char status
, unsigned char staged_status
,
4562 const char *relpath
, struct got_object_id
*blob_id
,
4563 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
4564 int dirfd
, const char *de_name
)
4566 struct revert_file_args
*a
= arg
;
4567 const struct got_error
*err
= NULL
;
4568 char *parent_path
= NULL
;
4569 struct got_fileindex_entry
*ie
;
4570 struct got_tree_object
*tree
= NULL
;
4571 struct got_object_id
*tree_id
= NULL
;
4572 const struct got_tree_entry
*te
= NULL
;
4573 char *tree_path
= NULL
, *te_name
;
4574 char *ondisk_path
= NULL
, *path_content
= NULL
;
4575 struct got_blob_object
*blob
= NULL
;
4577 /* Reverting a staged deletion is a no-op. */
4578 if (status
== GOT_STATUS_DELETE
&&
4579 staged_status
!= GOT_STATUS_NO_CHANGE
)
4582 if (status
== GOT_STATUS_UNVERSIONED
)
4583 return (*a
->progress_cb
)(a
->progress_arg
,
4584 GOT_STATUS_UNVERSIONED
, relpath
);
4586 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
4588 return got_error_path(relpath
, GOT_ERR_BAD_PATH
);
4590 /* Construct in-repository path of tree which contains this blob. */
4591 err
= got_path_dirname(&parent_path
, ie
->path
);
4593 if (err
->code
!= GOT_ERR_BAD_PATH
)
4595 parent_path
= strdup("/");
4596 if (parent_path
== NULL
) {
4597 err
= got_error_from_errno("strdup");
4601 if (got_path_is_root_dir(a
->worktree
->path_prefix
)) {
4602 tree_path
= strdup(parent_path
);
4603 if (tree_path
== NULL
) {
4604 err
= got_error_from_errno("strdup");
4608 if (got_path_is_root_dir(parent_path
)) {
4609 tree_path
= strdup(a
->worktree
->path_prefix
);
4610 if (tree_path
== NULL
) {
4611 err
= got_error_from_errno("strdup");
4615 if (asprintf(&tree_path
, "%s/%s",
4616 a
->worktree
->path_prefix
, parent_path
) == -1) {
4617 err
= got_error_from_errno("asprintf");
4623 err
= got_object_id_by_path(&tree_id
, a
->repo
,
4624 a
->worktree
->base_commit_id
, tree_path
);
4626 if (!(err
->code
== GOT_ERR_NO_TREE_ENTRY
&&
4627 (status
== GOT_STATUS_ADD
||
4628 staged_status
== GOT_STATUS_ADD
)))
4631 err
= got_object_open_as_tree(&tree
, a
->repo
, tree_id
);
4635 err
= got_path_basename(&te_name
, ie
->path
);
4639 te
= got_object_tree_find_entry(tree
, te_name
);
4641 if (te
== NULL
&& status
!= GOT_STATUS_ADD
&&
4642 staged_status
!= GOT_STATUS_ADD
) {
4643 err
= got_error_path(ie
->path
, GOT_ERR_NO_TREE_ENTRY
);
4649 case GOT_STATUS_ADD
:
4651 int choice
= GOT_PATCH_CHOICE_NONE
;
4652 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4653 status
, ie
->path
, NULL
, 1, 1);
4656 if (choice
!= GOT_PATCH_CHOICE_YES
)
4659 err
= (*a
->progress_cb
)(a
->progress_arg
, GOT_STATUS_REVERT
,
4663 got_fileindex_entry_remove(a
->fileindex
, ie
);
4665 case GOT_STATUS_DELETE
:
4667 int choice
= GOT_PATCH_CHOICE_NONE
;
4668 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
4669 status
, ie
->path
, NULL
, 1, 1);
4672 if (choice
!= GOT_PATCH_CHOICE_YES
)
4676 case GOT_STATUS_MODIFY
:
4677 case GOT_STATUS_MODE_CHANGE
:
4678 case GOT_STATUS_CONFLICT
:
4679 case GOT_STATUS_MISSING
: {
4680 struct got_object_id id
;
4681 if (staged_status
== GOT_STATUS_ADD
||
4682 staged_status
== GOT_STATUS_MODIFY
) {
4683 memcpy(id
.sha1
, ie
->staged_blob_sha1
,
4684 SHA1_DIGEST_LENGTH
);
4686 memcpy(id
.sha1
, ie
->blob_sha1
,
4687 SHA1_DIGEST_LENGTH
);
4688 err
= got_object_open_as_blob(&blob
, a
->repo
, &id
, 8192);
4692 if (asprintf(&ondisk_path
, "%s/%s",
4693 got_worktree_get_root_path(a
->worktree
), relpath
) == -1) {
4694 err
= got_error_from_errno("asprintf");
4698 if (a
->patch_cb
&& (status
== GOT_STATUS_MODIFY
||
4699 status
== GOT_STATUS_CONFLICT
)) {
4700 int is_bad_symlink
= 0;
4701 err
= create_patched_content(&path_content
, 1, &id
,
4702 ondisk_path
, dirfd
, de_name
, ie
->path
, a
->repo
,
4703 a
->patch_cb
, a
->patch_arg
);
4704 if (err
|| path_content
== NULL
)
4706 if (te
&& S_ISLNK(te
->mode
)) {
4707 if (unlink(path_content
) == -1) {
4708 err
= got_error_from_errno2("unlink",
4712 err
= install_symlink(&is_bad_symlink
,
4713 a
->worktree
, ondisk_path
, ie
->path
,
4714 blob
, 0, 1, 0, a
->repo
,
4715 a
->progress_cb
, a
->progress_arg
);
4717 if (rename(path_content
, ondisk_path
) == -1) {
4718 err
= got_error_from_errno3("rename",
4719 path_content
, ondisk_path
);
4724 int is_bad_symlink
= 0;
4725 if (te
&& S_ISLNK(te
->mode
)) {
4726 err
= install_symlink(&is_bad_symlink
,
4727 a
->worktree
, ondisk_path
, ie
->path
,
4728 blob
, 0, 1, 0, a
->repo
,
4729 a
->progress_cb
, a
->progress_arg
);
4731 err
= install_blob(a
->worktree
, ondisk_path
,
4733 te
? te
->mode
: GOT_DEFAULT_FILE_MODE
,
4734 got_fileindex_perms_to_st(ie
), blob
,
4735 0, 1, 0, 0, a
->repo
,
4736 a
->progress_cb
, a
->progress_arg
);
4740 if (status
== GOT_STATUS_DELETE
||
4741 status
== GOT_STATUS_MODE_CHANGE
) {
4742 err
= got_fileindex_entry_update(ie
,
4743 a
->worktree
->root_fd
, relpath
,
4745 a
->worktree
->base_commit_id
->sha1
, 1);
4749 if (is_bad_symlink
) {
4750 got_fileindex_entry_filetype_set(ie
,
4751 GOT_FILEIDX_MODE_BAD_SYMLINK
);
4765 got_object_blob_close(blob
);
4767 got_object_tree_close(tree
);
4772 const struct got_error
*
4773 got_worktree_revert(struct got_worktree
*worktree
,
4774 struct got_pathlist_head
*paths
,
4775 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
4776 got_worktree_patch_cb patch_cb
, void *patch_arg
,
4777 struct got_repository
*repo
)
4779 struct got_fileindex
*fileindex
= NULL
;
4780 char *fileindex_path
= NULL
;
4781 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
4782 const struct got_error
*sync_err
= NULL
;
4783 struct got_pathlist_entry
*pe
;
4784 struct revert_file_args rfa
;
4786 err
= lock_worktree(worktree
, LOCK_EX
);
4790 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
4794 rfa
.worktree
= worktree
;
4795 rfa
.fileindex
= fileindex
;
4796 rfa
.progress_cb
= progress_cb
;
4797 rfa
.progress_arg
= progress_arg
;
4798 rfa
.patch_cb
= patch_cb
;
4799 rfa
.patch_arg
= patch_arg
;
4801 TAILQ_FOREACH(pe
, paths
, entry
) {
4802 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
4803 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
4807 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
4808 if (sync_err
&& err
== NULL
)
4811 free(fileindex_path
);
4813 got_fileindex_free(fileindex
);
4814 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
4815 if (unlockerr
&& err
== NULL
)
4821 free_commitable(struct got_commitable
*ct
)
4824 free(ct
->in_repo_path
);
4825 free(ct
->ondisk_path
);
4827 free(ct
->base_blob_id
);
4828 free(ct
->staged_blob_id
);
4829 free(ct
->base_commit_id
);
4833 struct collect_commitables_arg
{
4834 struct got_pathlist_head
*commitable_paths
;
4835 struct got_repository
*repo
;
4836 struct got_worktree
*worktree
;
4837 struct got_fileindex
*fileindex
;
4838 int have_staged_files
;
4839 int allow_bad_symlinks
;
4842 static const struct got_error
*
4843 collect_commitable(struct got_pathlist_head
*commitable_paths
,
4844 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
4845 unsigned char status
, unsigned char staged_status
,
4846 int have_staged_files
, int allow_bad_symlinks
, const char *relpath
,
4847 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
4848 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
4850 const struct got_error
*err
= NULL
;
4851 struct got_commitable
*ct
= NULL
;
4852 struct got_pathlist_entry
*new = NULL
;
4853 char *parent_path
= NULL
, *path
= NULL
;
4856 if (have_staged_files
) {
4857 if (staged_status
!= GOT_STATUS_MODIFY
&&
4858 staged_status
!= GOT_STATUS_ADD
&&
4859 staged_status
!= GOT_STATUS_DELETE
)
4862 if (status
== GOT_STATUS_CONFLICT
)
4863 return got_error(GOT_ERR_COMMIT_CONFLICT
);
4865 if (status
!= GOT_STATUS_MODIFY
&&
4866 status
!= GOT_STATUS_MODE_CHANGE
&&
4867 status
!= GOT_STATUS_ADD
&&
4868 status
!= GOT_STATUS_DELETE
)
4872 if (asprintf(&path
, "/%s", relpath
) == -1) {
4873 err
= got_error_from_errno("asprintf");
4876 if (strcmp(path
, "/") == 0) {
4877 parent_path
= strdup("");
4878 if (parent_path
== NULL
)
4879 return got_error_from_errno("strdup");
4881 err
= got_path_dirname(&parent_path
, path
);
4886 ct
= calloc(1, sizeof(*ct
));
4888 err
= got_error_from_errno("calloc");
4892 if (asprintf(&ct
->ondisk_path
, "%s/%s", worktree
->root_path
,
4894 err
= got_error_from_errno("asprintf");
4898 if (staged_status
== GOT_STATUS_ADD
||
4899 staged_status
== GOT_STATUS_MODIFY
) {
4900 struct got_fileindex_entry
*ie
;
4901 ie
= got_fileindex_entry_get(fileindex
, path
, strlen(path
));
4902 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
4903 case GOT_FILEIDX_MODE_REGULAR_FILE
:
4904 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
4907 case GOT_FILEIDX_MODE_SYMLINK
:
4911 err
= got_error_path(path
, GOT_ERR_BAD_FILETYPE
);
4914 ct
->mode
|= got_fileindex_entry_perms_get(ie
);
4915 } else if (status
!= GOT_STATUS_DELETE
&&
4916 staged_status
!= GOT_STATUS_DELETE
) {
4918 if (fstatat(dirfd
, de_name
, &sb
,
4919 AT_SYMLINK_NOFOLLOW
) == -1) {
4920 err
= got_error_from_errno2("fstatat",
4924 } else if (lstat(ct
->ondisk_path
, &sb
) == -1) {
4925 err
= got_error_from_errno2("lstat", ct
->ondisk_path
);
4928 ct
->mode
= sb
.st_mode
;
4931 if (asprintf(&ct
->in_repo_path
, "%s%s%s", worktree
->path_prefix
,
4932 got_path_is_root_dir(worktree
->path_prefix
) ? "" : "/",
4934 err
= got_error_from_errno("asprintf");
4938 if (S_ISLNK(ct
->mode
) && staged_status
== GOT_STATUS_NO_CHANGE
&&
4939 status
== GOT_STATUS_ADD
&& !allow_bad_symlinks
) {
4941 char target_path
[PATH_MAX
];
4943 target_len
= readlink(ct
->ondisk_path
, target_path
,
4944 sizeof(target_path
));
4945 if (target_len
== -1) {
4946 err
= got_error_from_errno2("readlink",
4950 err
= is_bad_symlink_target(&is_bad_symlink
, target_path
,
4951 target_len
, ct
->ondisk_path
, worktree
->root_path
);
4954 if (is_bad_symlink
) {
4955 err
= got_error_path(ct
->ondisk_path
,
4956 GOT_ERR_BAD_SYMLINK
);
4962 ct
->status
= status
;
4963 ct
->staged_status
= staged_status
;
4964 ct
->blob_id
= NULL
; /* will be filled in when blob gets created */
4965 if (ct
->status
!= GOT_STATUS_ADD
&&
4966 ct
->staged_status
!= GOT_STATUS_ADD
) {
4967 ct
->base_blob_id
= got_object_id_dup(blob_id
);
4968 if (ct
->base_blob_id
== NULL
) {
4969 err
= got_error_from_errno("got_object_id_dup");
4972 ct
->base_commit_id
= got_object_id_dup(commit_id
);
4973 if (ct
->base_commit_id
== NULL
) {
4974 err
= got_error_from_errno("got_object_id_dup");
4978 if (ct
->staged_status
== GOT_STATUS_ADD
||
4979 ct
->staged_status
== GOT_STATUS_MODIFY
) {
4980 ct
->staged_blob_id
= got_object_id_dup(staged_blob_id
);
4981 if (ct
->staged_blob_id
== NULL
) {
4982 err
= got_error_from_errno("got_object_id_dup");
4986 ct
->path
= strdup(path
);
4987 if (ct
->path
== NULL
) {
4988 err
= got_error_from_errno("strdup");
4991 err
= got_pathlist_insert(&new, commitable_paths
, ct
->path
, ct
);
4993 if (ct
&& (err
|| new == NULL
))
4994 free_commitable(ct
);
5000 static const struct got_error
*
5001 collect_commitables(void *arg
, unsigned char status
,
5002 unsigned char staged_status
, const char *relpath
,
5003 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
5004 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
5006 struct collect_commitables_arg
*a
= arg
;
5007 return collect_commitable(a
->commitable_paths
, a
->worktree
,
5008 a
->fileindex
, status
, staged_status
, a
->have_staged_files
,
5009 a
->allow_bad_symlinks
, relpath
, blob_id
, staged_blob_id
,
5010 commit_id
, dirfd
, de_name
);
5013 static const struct got_error
*write_tree(struct got_object_id
**, int *,
5014 struct got_tree_object
*, const char *, struct got_pathlist_head
*,
5015 got_worktree_status_cb status_cb
, void *status_arg
,
5016 struct got_repository
*);
5018 static const struct got_error
*
5019 write_subtree(struct got_object_id
**new_subtree_id
, int *nentries
,
5020 struct got_tree_entry
*te
, const char *parent_path
,
5021 struct got_pathlist_head
*commitable_paths
,
5022 got_worktree_status_cb status_cb
, void *status_arg
,
5023 struct got_repository
*repo
)
5025 const struct got_error
*err
= NULL
;
5026 struct got_tree_object
*subtree
;
5029 if (asprintf(&subpath
, "%s%s%s", parent_path
,
5030 got_path_is_root_dir(parent_path
) ? "" : "/", te
->name
) == -1)
5031 return got_error_from_errno("asprintf");
5033 err
= got_object_open_as_tree(&subtree
, repo
, &te
->id
);
5037 err
= write_tree(new_subtree_id
, nentries
, subtree
, subpath
,
5038 commitable_paths
, status_cb
, status_arg
, repo
);
5039 got_object_tree_close(subtree
);
5044 static const struct got_error
*
5045 match_ct_parent_path(int *match
, struct got_commitable
*ct
, const char *path
)
5047 const struct got_error
*err
= NULL
;
5048 char *ct_parent_path
= NULL
;
5052 if (strchr(ct
->in_repo_path
, '/') == NULL
) {
5053 *match
= got_path_is_root_dir(path
);
5057 err
= got_path_dirname(&ct_parent_path
, ct
->in_repo_path
);
5060 *match
= (strcmp(path
, ct_parent_path
) == 0);
5061 free(ct_parent_path
);
5066 get_ct_file_mode(struct got_commitable
*ct
)
5068 if (S_ISLNK(ct
->mode
))
5071 return S_IFREG
| (ct
->mode
& ((S_IRWXU
| S_IRWXG
| S_IRWXO
)));
5074 static const struct got_error
*
5075 alloc_modified_blob_tree_entry(struct got_tree_entry
**new_te
,
5076 struct got_tree_entry
*te
, struct got_commitable
*ct
)
5078 const struct got_error
*err
= NULL
;
5082 err
= got_object_tree_entry_dup(new_te
, te
);
5086 (*new_te
)->mode
= get_ct_file_mode(ct
);
5088 if (ct
->staged_status
== GOT_STATUS_MODIFY
)
5089 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5090 sizeof((*new_te
)->id
));
5092 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5094 if (err
&& *new_te
) {
5101 static const struct got_error
*
5102 alloc_added_blob_tree_entry(struct got_tree_entry
**new_te
,
5103 struct got_commitable
*ct
)
5105 const struct got_error
*err
= NULL
;
5106 char *ct_name
= NULL
;
5110 *new_te
= calloc(1, sizeof(**new_te
));
5111 if (*new_te
== NULL
)
5112 return got_error_from_errno("calloc");
5114 err
= got_path_basename(&ct_name
, ct
->path
);
5117 if (strlcpy((*new_te
)->name
, ct_name
, sizeof((*new_te
)->name
)) >=
5118 sizeof((*new_te
)->name
)) {
5119 err
= got_error(GOT_ERR_NO_SPACE
);
5123 (*new_te
)->mode
= get_ct_file_mode(ct
);
5125 if (ct
->staged_status
== GOT_STATUS_ADD
)
5126 memcpy(&(*new_te
)->id
, ct
->staged_blob_id
,
5127 sizeof((*new_te
)->id
));
5129 memcpy(&(*new_te
)->id
, ct
->blob_id
, sizeof((*new_te
)->id
));
5132 if (err
&& *new_te
) {
5139 static const struct got_error
*
5140 insert_tree_entry(struct got_tree_entry
*new_te
,
5141 struct got_pathlist_head
*paths
)
5143 const struct got_error
*err
= NULL
;
5144 struct got_pathlist_entry
*new_pe
;
5146 err
= got_pathlist_insert(&new_pe
, paths
, new_te
->name
, new_te
);
5150 return got_error(GOT_ERR_TREE_DUP_ENTRY
);
5154 static const struct got_error
*
5155 report_ct_status(struct got_commitable
*ct
,
5156 got_worktree_status_cb status_cb
, void *status_arg
)
5158 const char *ct_path
= ct
->path
;
5159 unsigned char status
;
5161 while (ct_path
[0] == '/')
5164 if (ct
->staged_status
!= GOT_STATUS_NO_CHANGE
)
5165 status
= ct
->staged_status
;
5167 status
= ct
->status
;
5169 return (*status_cb
)(status_arg
, status
, GOT_STATUS_NO_CHANGE
,
5170 ct_path
, ct
->blob_id
, NULL
, NULL
, -1, NULL
);
5173 static const struct got_error
*
5174 match_modified_subtree(int *modified
, struct got_tree_entry
*te
,
5175 const char *base_tree_path
, struct got_pathlist_head
*commitable_paths
)
5177 const struct got_error
*err
= NULL
;
5178 struct got_pathlist_entry
*pe
;
5183 if (asprintf(&te_path
, "%s%s%s", base_tree_path
,
5184 got_path_is_root_dir(base_tree_path
) ? "" : "/",
5186 return got_error_from_errno("asprintf");
5188 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5189 struct got_commitable
*ct
= pe
->data
;
5190 *modified
= got_path_is_child(ct
->in_repo_path
, te_path
,
5200 static const struct got_error
*
5201 match_deleted_or_modified_ct(struct got_commitable
**ctp
,
5202 struct got_tree_entry
*te
, const char *base_tree_path
,
5203 struct got_pathlist_head
*commitable_paths
)
5205 const struct got_error
*err
= NULL
;
5206 struct got_pathlist_entry
*pe
;
5210 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5211 struct got_commitable
*ct
= pe
->data
;
5212 char *ct_name
= NULL
;
5215 if (ct
->staged_status
== GOT_STATUS_NO_CHANGE
) {
5216 if (ct
->status
!= GOT_STATUS_MODIFY
&&
5217 ct
->status
!= GOT_STATUS_MODE_CHANGE
&&
5218 ct
->status
!= GOT_STATUS_DELETE
)
5221 if (ct
->staged_status
!= GOT_STATUS_MODIFY
&&
5222 ct
->staged_status
!= GOT_STATUS_DELETE
)
5226 if (got_object_id_cmp(ct
->base_blob_id
, &te
->id
) != 0)
5229 err
= match_ct_parent_path(&path_matches
, ct
, base_tree_path
);
5235 err
= got_path_basename(&ct_name
, pe
->path
);
5239 if (strcmp(te
->name
, ct_name
) != 0) {
5252 static const struct got_error
*
5253 make_subtree_for_added_blob(struct got_tree_entry
**new_tep
,
5254 const char *child_path
, const char *path_base_tree
,
5255 struct got_pathlist_head
*commitable_paths
,
5256 got_worktree_status_cb status_cb
, void *status_arg
,
5257 struct got_repository
*repo
)
5259 const struct got_error
*err
= NULL
;
5260 struct got_tree_entry
*new_te
;
5262 struct got_object_id
*id
= NULL
;
5267 if (asprintf(&subtree_path
, "%s%s%s", path_base_tree
,
5268 got_path_is_root_dir(path_base_tree
) ? "" : "/",
5270 return got_error_from_errno("asprintf");
5272 new_te
= calloc(1, sizeof(*new_te
));
5274 return got_error_from_errno("calloc");
5275 new_te
->mode
= S_IFDIR
;
5277 if (strlcpy(new_te
->name
, child_path
, sizeof(new_te
->name
)) >=
5278 sizeof(new_te
->name
)) {
5279 err
= got_error(GOT_ERR_NO_SPACE
);
5282 err
= write_tree(&id
, &nentries
, NULL
, subtree_path
,
5283 commitable_paths
, status_cb
, status_arg
, repo
);
5288 memcpy(&new_te
->id
, id
, sizeof(new_te
->id
));
5297 static const struct got_error
*
5298 write_tree(struct got_object_id
**new_tree_id
, int *nentries
,
5299 struct got_tree_object
*base_tree
, const char *path_base_tree
,
5300 struct got_pathlist_head
*commitable_paths
,
5301 got_worktree_status_cb status_cb
, void *status_arg
,
5302 struct got_repository
*repo
)
5304 const struct got_error
*err
= NULL
;
5305 struct got_pathlist_head paths
;
5306 struct got_tree_entry
*te
, *new_te
= NULL
;
5307 struct got_pathlist_entry
*pe
;
5312 /* Insert, and recurse into, newly added entries first. */
5313 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5314 struct got_commitable
*ct
= pe
->data
;
5315 char *child_path
= NULL
, *slash
;
5317 if ((ct
->status
!= GOT_STATUS_ADD
&&
5318 ct
->staged_status
!= GOT_STATUS_ADD
) ||
5319 (ct
->flags
& GOT_COMMITABLE_ADDED
))
5322 if (!got_path_is_child(ct
->in_repo_path
, path_base_tree
,
5323 strlen(path_base_tree
)))
5326 err
= got_path_skip_common_ancestor(&child_path
, path_base_tree
,
5331 slash
= strchr(child_path
, '/');
5332 if (slash
== NULL
) {
5333 err
= alloc_added_blob_tree_entry(&new_te
, ct
);
5336 err
= report_ct_status(ct
, status_cb
, status_arg
);
5339 ct
->flags
|= GOT_COMMITABLE_ADDED
;
5340 err
= insert_tree_entry(new_te
, &paths
);
5345 *slash
= '\0'; /* trim trailing path components */
5346 if (base_tree
== NULL
||
5347 got_object_tree_find_entry(base_tree
, child_path
)
5349 err
= make_subtree_for_added_blob(&new_te
,
5350 child_path
, path_base_tree
,
5351 commitable_paths
, status_cb
, status_arg
,
5355 err
= insert_tree_entry(new_te
, &paths
);
5364 int i
, nbase_entries
;
5365 /* Handle modified and deleted entries. */
5366 nbase_entries
= got_object_tree_get_nentries(base_tree
);
5367 for (i
= 0; i
< nbase_entries
; i
++) {
5368 struct got_commitable
*ct
= NULL
;
5370 te
= got_object_tree_get_entry(base_tree
, i
);
5371 if (got_object_tree_entry_is_submodule(te
)) {
5372 /* Entry is a submodule; just copy it. */
5373 err
= got_object_tree_entry_dup(&new_te
, te
);
5376 err
= insert_tree_entry(new_te
, &paths
);
5383 if (S_ISDIR(te
->mode
)) {
5385 err
= got_object_tree_entry_dup(&new_te
, te
);
5388 err
= match_modified_subtree(&modified
, te
,
5389 path_base_tree
, commitable_paths
);
5392 /* Avoid recursion into unmodified subtrees. */
5394 struct got_object_id
*new_id
;
5396 err
= write_subtree(&new_id
,
5398 path_base_tree
, commitable_paths
,
5399 status_cb
, status_arg
, repo
);
5402 if (nsubentries
== 0) {
5403 /* All entries were deleted. */
5407 memcpy(&new_te
->id
, new_id
,
5408 sizeof(new_te
->id
));
5411 err
= insert_tree_entry(new_te
, &paths
);
5418 err
= match_deleted_or_modified_ct(&ct
, te
,
5419 path_base_tree
, commitable_paths
);
5423 /* NB: Deleted entries get dropped here. */
5424 if (ct
->status
== GOT_STATUS_MODIFY
||
5425 ct
->status
== GOT_STATUS_MODE_CHANGE
||
5426 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5427 err
= alloc_modified_blob_tree_entry(
5431 err
= insert_tree_entry(new_te
, &paths
);
5436 err
= report_ct_status(ct
, status_cb
,
5441 /* Entry is unchanged; just copy it. */
5442 err
= got_object_tree_entry_dup(&new_te
, te
);
5445 err
= insert_tree_entry(new_te
, &paths
);
5453 /* Write new list of entries; deleted entries have been dropped. */
5454 err
= got_object_tree_create(new_tree_id
, &paths
, *nentries
, repo
);
5456 got_pathlist_free(&paths
);
5460 static const struct got_error
*
5461 update_fileindex_after_commit(struct got_worktree
*worktree
,
5462 struct got_pathlist_head
*commitable_paths
,
5463 struct got_object_id
*new_base_commit_id
,
5464 struct got_fileindex
*fileindex
, int have_staged_files
)
5466 const struct got_error
*err
= NULL
;
5467 struct got_pathlist_entry
*pe
;
5468 char *relpath
= NULL
;
5470 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5471 struct got_fileindex_entry
*ie
;
5472 struct got_commitable
*ct
= pe
->data
;
5474 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
5476 err
= got_path_skip_common_ancestor(&relpath
,
5477 worktree
->root_path
, ct
->ondisk_path
);
5482 if (ct
->status
== GOT_STATUS_DELETE
||
5483 ct
->staged_status
== GOT_STATUS_DELETE
) {
5484 got_fileindex_entry_remove(fileindex
, ie
);
5485 } else if (ct
->staged_status
== GOT_STATUS_ADD
||
5486 ct
->staged_status
== GOT_STATUS_MODIFY
) {
5487 got_fileindex_entry_stage_set(ie
,
5488 GOT_FILEIDX_STAGE_NONE
);
5489 got_fileindex_entry_staged_filetype_set(ie
, 0);
5491 err
= got_fileindex_entry_update(ie
,
5492 worktree
->root_fd
, relpath
,
5493 ct
->staged_blob_id
->sha1
,
5494 new_base_commit_id
->sha1
,
5495 !have_staged_files
);
5497 err
= got_fileindex_entry_update(ie
,
5498 worktree
->root_fd
, relpath
,
5500 new_base_commit_id
->sha1
,
5501 !have_staged_files
);
5503 err
= got_fileindex_entry_alloc(&ie
, pe
->path
);
5506 err
= got_fileindex_entry_update(ie
,
5507 worktree
->root_fd
, relpath
, ct
->blob_id
->sha1
,
5508 new_base_commit_id
->sha1
, 1);
5510 got_fileindex_entry_free(ie
);
5513 err
= got_fileindex_entry_add(fileindex
, ie
);
5515 got_fileindex_entry_free(ie
);
5528 static const struct got_error
*
5529 check_out_of_date(const char *in_repo_path
, unsigned char status
,
5530 unsigned char staged_status
, struct got_object_id
*base_blob_id
,
5531 struct got_object_id
*base_commit_id
,
5532 struct got_object_id
*head_commit_id
, struct got_repository
*repo
,
5535 const struct got_error
*err
= NULL
;
5536 struct got_object_id
*id
= NULL
;
5538 if (status
!= GOT_STATUS_ADD
&& staged_status
!= GOT_STATUS_ADD
) {
5539 /* Trivial case: base commit == head commit */
5540 if (got_object_id_cmp(base_commit_id
, head_commit_id
) == 0)
5543 * Ensure file content which local changes were based
5544 * on matches file content in the branch head.
5546 err
= got_object_id_by_path(&id
, repo
, head_commit_id
,
5549 if (err
->code
== GOT_ERR_NO_TREE_ENTRY
)
5550 err
= got_error(ood_errcode
);
5552 } else if (got_object_id_cmp(id
, base_blob_id
) != 0)
5553 err
= got_error(ood_errcode
);
5555 /* Require that added files don't exist in the branch head. */
5556 err
= got_object_id_by_path(&id
, repo
, head_commit_id
,
5558 if (err
&& err
->code
!= GOT_ERR_NO_TREE_ENTRY
)
5560 err
= id
? got_error(ood_errcode
) : NULL
;
5567 const struct got_error
*
5568 commit_worktree(struct got_object_id
**new_commit_id
,
5569 struct got_pathlist_head
*commitable_paths
,
5570 struct got_object_id
*head_commit_id
, struct got_worktree
*worktree
,
5571 const char *author
, const char *committer
,
5572 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
5573 got_worktree_status_cb status_cb
, void *status_arg
,
5574 struct got_repository
*repo
)
5576 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
5577 struct got_pathlist_entry
*pe
;
5578 const char *head_ref_name
= NULL
;
5579 struct got_commit_object
*head_commit
= NULL
;
5580 struct got_reference
*head_ref2
= NULL
;
5581 struct got_object_id
*head_commit_id2
= NULL
;
5582 struct got_tree_object
*head_tree
= NULL
;
5583 struct got_object_id
*new_tree_id
= NULL
;
5585 struct got_object_id_queue parent_ids
;
5586 struct got_object_qid
*pid
= NULL
;
5587 char *logmsg
= NULL
;
5589 *new_commit_id
= NULL
;
5591 STAILQ_INIT(&parent_ids
);
5593 err
= got_object_open_as_commit(&head_commit
, repo
, head_commit_id
);
5597 err
= got_object_open_as_tree(&head_tree
, repo
, head_commit
->tree_id
);
5601 if (commit_msg_cb
!= NULL
) {
5602 err
= commit_msg_cb(commitable_paths
, &logmsg
, commit_arg
);
5607 if (logmsg
== NULL
|| strlen(logmsg
) == 0) {
5608 err
= got_error(GOT_ERR_COMMIT_MSG_EMPTY
);
5612 /* Create blobs from added and modified files and record their IDs. */
5613 TAILQ_FOREACH(pe
, commitable_paths
, entry
) {
5614 struct got_commitable
*ct
= pe
->data
;
5617 /* Blobs for staged files already exist. */
5618 if (ct
->staged_status
== GOT_STATUS_ADD
||
5619 ct
->staged_status
== GOT_STATUS_MODIFY
)
5622 if (ct
->status
!= GOT_STATUS_ADD
&&
5623 ct
->status
!= GOT_STATUS_MODIFY
&&
5624 ct
->status
!= GOT_STATUS_MODE_CHANGE
)
5627 if (asprintf(&ondisk_path
, "%s/%s",
5628 worktree
->root_path
, pe
->path
) == -1) {
5629 err
= got_error_from_errno("asprintf");
5632 err
= got_object_blob_create(&ct
->blob_id
, ondisk_path
, repo
);
5638 /* Recursively write new tree objects. */
5639 err
= write_tree(&new_tree_id
, &nentries
, head_tree
, "/",
5640 commitable_paths
, status_cb
, status_arg
, repo
);
5644 err
= got_object_qid_alloc(&pid
, worktree
->base_commit_id
);
5647 STAILQ_INSERT_TAIL(&parent_ids
, pid
, entry
);
5648 err
= got_object_commit_create(new_commit_id
, new_tree_id
, &parent_ids
,
5649 1, author
, time(NULL
), committer
, time(NULL
), logmsg
, repo
);
5650 got_object_qid_free(pid
);
5656 /* Check if a concurrent commit to our branch has occurred. */
5657 head_ref_name
= got_worktree_get_head_ref_name(worktree
);
5658 if (head_ref_name
== NULL
) {
5659 err
= got_error_from_errno("got_worktree_get_head_ref_name");
5662 /* Lock the reference here to prevent concurrent modification. */
5663 err
= got_ref_open(&head_ref2
, repo
, head_ref_name
, 1);
5666 err
= got_ref_resolve(&head_commit_id2
, repo
, head_ref2
);
5669 if (got_object_id_cmp(head_commit_id
, head_commit_id2
) != 0) {
5670 err
= got_error(GOT_ERR_COMMIT_HEAD_CHANGED
);
5673 /* Update branch head in repository. */
5674 err
= got_ref_change_ref(head_ref2
, *new_commit_id
);
5677 err
= got_ref_write(head_ref2
, repo
);
5681 err
= got_worktree_set_base_commit_id(worktree
, repo
, *new_commit_id
);
5685 err
= ref_base_commit(worktree
, repo
);
5690 got_object_tree_close(head_tree
);
5692 got_object_commit_close(head_commit
);
5693 free(head_commit_id2
);
5695 unlockerr
= got_ref_unlock(head_ref2
);
5696 if (unlockerr
&& err
== NULL
)
5698 got_ref_close(head_ref2
);
5703 static const struct got_error
*
5704 check_path_is_commitable(const char *path
,
5705 struct got_pathlist_head
*commitable_paths
)
5707 struct got_pathlist_entry
*cpe
= NULL
;
5708 size_t path_len
= strlen(path
);
5710 TAILQ_FOREACH(cpe
, commitable_paths
, entry
) {
5711 struct got_commitable
*ct
= cpe
->data
;
5712 const char *ct_path
= ct
->path
;
5714 while (ct_path
[0] == '/')
5717 if (strcmp(path
, ct_path
) == 0 ||
5718 got_path_is_child(ct_path
, path
, path_len
))
5723 return got_error_path(path
, GOT_ERR_BAD_PATH
);
5728 static const struct got_error
*
5729 check_staged_file(void *arg
, struct got_fileindex_entry
*ie
)
5731 int *have_staged_files
= arg
;
5733 if (got_fileindex_entry_stage_get(ie
) != GOT_FILEIDX_STAGE_NONE
) {
5734 *have_staged_files
= 1;
5735 return got_error(GOT_ERR_CANCELLED
);
5741 static const struct got_error
*
5742 check_non_staged_files(struct got_fileindex
*fileindex
,
5743 struct got_pathlist_head
*paths
)
5745 struct got_pathlist_entry
*pe
;
5746 struct got_fileindex_entry
*ie
;
5748 TAILQ_FOREACH(pe
, paths
, entry
) {
5749 if (pe
->path
[0] == '\0')
5751 ie
= got_fileindex_entry_get(fileindex
, pe
->path
, pe
->path_len
);
5753 return got_error_path(pe
->path
, GOT_ERR_BAD_PATH
);
5754 if (got_fileindex_entry_stage_get(ie
) == GOT_FILEIDX_STAGE_NONE
)
5755 return got_error_path(pe
->path
,
5756 GOT_ERR_FILE_NOT_STAGED
);
5762 const struct got_error
*
5763 got_worktree_commit(struct got_object_id
**new_commit_id
,
5764 struct got_worktree
*worktree
, struct got_pathlist_head
*paths
,
5765 const char *author
, const char *committer
, int allow_bad_symlinks
,
5766 got_worktree_commit_msg_cb commit_msg_cb
, void *commit_arg
,
5767 got_worktree_status_cb status_cb
, void *status_arg
,
5768 struct got_repository
*repo
)
5770 const struct got_error
*err
= NULL
, *unlockerr
= NULL
, *sync_err
;
5771 struct got_fileindex
*fileindex
= NULL
;
5772 char *fileindex_path
= NULL
;
5773 struct got_pathlist_head commitable_paths
;
5774 struct collect_commitables_arg cc_arg
;
5775 struct got_pathlist_entry
*pe
;
5776 struct got_reference
*head_ref
= NULL
;
5777 struct got_object_id
*head_commit_id
= NULL
;
5778 int have_staged_files
= 0;
5780 *new_commit_id
= NULL
;
5782 TAILQ_INIT(&commitable_paths
);
5784 err
= lock_worktree(worktree
, LOCK_EX
);
5788 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
5792 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
5796 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
5800 err
= got_fileindex_for_each_entry_safe(fileindex
, check_staged_file
,
5801 &have_staged_files
);
5802 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
5804 if (have_staged_files
) {
5805 err
= check_non_staged_files(fileindex
, paths
);
5810 cc_arg
.commitable_paths
= &commitable_paths
;
5811 cc_arg
.worktree
= worktree
;
5812 cc_arg
.fileindex
= fileindex
;
5814 cc_arg
.have_staged_files
= have_staged_files
;
5815 cc_arg
.allow_bad_symlinks
= allow_bad_symlinks
;
5816 TAILQ_FOREACH(pe
, paths
, entry
) {
5817 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
5818 collect_commitables
, &cc_arg
, NULL
, NULL
, 0, 0);
5823 if (TAILQ_EMPTY(&commitable_paths
)) {
5824 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
5828 TAILQ_FOREACH(pe
, paths
, entry
) {
5829 err
= check_path_is_commitable(pe
->path
, &commitable_paths
);
5834 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
5835 struct got_commitable
*ct
= pe
->data
;
5836 const char *ct_path
= ct
->in_repo_path
;
5838 while (ct_path
[0] == '/')
5840 err
= check_out_of_date(ct_path
, ct
->status
,
5841 ct
->staged_status
, ct
->base_blob_id
, ct
->base_commit_id
,
5842 head_commit_id
, repo
, GOT_ERR_COMMIT_OUT_OF_DATE
);
5848 err
= commit_worktree(new_commit_id
, &commitable_paths
,
5849 head_commit_id
, worktree
, author
, committer
,
5850 commit_msg_cb
, commit_arg
, status_cb
, status_arg
, repo
);
5854 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
5855 *new_commit_id
, fileindex
, have_staged_files
);
5856 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
5857 if (sync_err
&& err
== NULL
)
5861 got_fileindex_free(fileindex
);
5862 free(fileindex_path
);
5863 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
5864 if (unlockerr
&& err
== NULL
)
5866 TAILQ_FOREACH(pe
, &commitable_paths
, entry
) {
5867 struct got_commitable
*ct
= pe
->data
;
5868 free_commitable(ct
);
5870 got_pathlist_free(&commitable_paths
);
5875 got_commitable_get_path(struct got_commitable
*ct
)
5881 got_commitable_get_status(struct got_commitable
*ct
)
5886 struct check_rebase_ok_arg
{
5887 struct got_worktree
*worktree
;
5888 struct got_repository
*repo
;
5891 static const struct got_error
*
5892 check_rebase_ok(void *arg
, struct got_fileindex_entry
*ie
)
5894 const struct got_error
*err
= NULL
;
5895 struct check_rebase_ok_arg
*a
= arg
;
5896 unsigned char status
;
5900 /* Reject rebase of a work tree with mixed base commits. */
5901 if (memcmp(ie
->commit_sha1
, a
->worktree
->base_commit_id
->sha1
,
5902 SHA1_DIGEST_LENGTH
))
5903 return got_error(GOT_ERR_MIXED_COMMITS
);
5905 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, ie
->path
)
5907 return got_error_from_errno("asprintf");
5909 /* Reject rebase of a work tree with modified or staged files. */
5910 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
, -1, NULL
, a
->repo
);
5915 if (status
!= GOT_STATUS_NO_CHANGE
)
5916 return got_error(GOT_ERR_MODIFIED
);
5917 if (get_staged_status(ie
) != GOT_STATUS_NO_CHANGE
)
5918 return got_error_path(ie
->path
, GOT_ERR_FILE_STAGED
);
5923 const struct got_error
*
5924 got_worktree_rebase_prepare(struct got_reference
**new_base_branch_ref
,
5925 struct got_reference
**tmp_branch
, struct got_fileindex
**fileindex
,
5926 struct got_worktree
*worktree
, struct got_reference
*branch
,
5927 struct got_repository
*repo
)
5929 const struct got_error
*err
= NULL
;
5930 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
5931 char *branch_ref_name
= NULL
;
5932 char *fileindex_path
= NULL
;
5933 struct check_rebase_ok_arg ok_arg
;
5934 struct got_reference
*wt_branch
= NULL
, *branch_ref
= NULL
;
5935 struct got_object_id
*wt_branch_tip
= NULL
;
5937 *new_base_branch_ref
= NULL
;
5941 err
= lock_worktree(worktree
, LOCK_EX
);
5945 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
5949 ok_arg
.worktree
= worktree
;
5951 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
5956 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
5960 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
5964 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
5968 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
5973 err
= got_ref_resolve(&wt_branch_tip
, repo
, wt_branch
);
5976 if (got_object_id_cmp(worktree
->base_commit_id
, wt_branch_tip
) != 0) {
5977 err
= got_error(GOT_ERR_REBASE_OUT_OF_DATE
);
5981 err
= got_ref_alloc_symref(new_base_branch_ref
,
5982 new_base_branch_ref_name
, wt_branch
);
5985 err
= got_ref_write(*new_base_branch_ref
, repo
);
5989 /* TODO Lock original branch's ref while rebasing? */
5991 err
= got_ref_alloc_symref(&branch_ref
, branch_ref_name
, branch
);
5995 err
= got_ref_write(branch_ref
, repo
);
5999 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6000 worktree
->base_commit_id
);
6003 err
= got_ref_write(*tmp_branch
, repo
);
6007 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6011 free(fileindex_path
);
6012 free(tmp_branch_name
);
6013 free(new_base_branch_ref_name
);
6014 free(branch_ref_name
);
6016 got_ref_close(branch_ref
);
6018 got_ref_close(wt_branch
);
6019 free(wt_branch_tip
);
6021 if (*new_base_branch_ref
) {
6022 got_ref_close(*new_base_branch_ref
);
6023 *new_base_branch_ref
= NULL
;
6026 got_ref_close(*tmp_branch
);
6030 got_fileindex_free(*fileindex
);
6033 lock_worktree(worktree
, LOCK_SH
);
6038 const struct got_error
*
6039 got_worktree_rebase_continue(struct got_object_id
**commit_id
,
6040 struct got_reference
**new_base_branch
, struct got_reference
**tmp_branch
,
6041 struct got_reference
**branch
, struct got_fileindex
**fileindex
,
6042 struct got_worktree
*worktree
, struct got_repository
*repo
)
6044 const struct got_error
*err
;
6045 char *commit_ref_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6046 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
6047 struct got_reference
*commit_ref
= NULL
, *branch_ref
= NULL
;
6048 char *fileindex_path
= NULL
;
6049 int have_staged_files
= 0;
6052 *new_base_branch
= NULL
;
6057 err
= lock_worktree(worktree
, LOCK_EX
);
6061 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6065 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
6066 &have_staged_files
);
6067 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6069 if (have_staged_files
) {
6070 err
= got_error(GOT_ERR_STAGED_PATHS
);
6074 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6078 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6082 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6086 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6090 err
= got_ref_open(&branch_ref
, repo
, branch_ref_name
, 0);
6094 err
= got_ref_open(branch
, repo
,
6095 got_ref_get_symref_target(branch_ref
), 0);
6099 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6103 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
6107 err
= got_ref_open(new_base_branch
, repo
,
6108 new_base_branch_ref_name
, 0);
6112 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
6116 free(commit_ref_name
);
6117 free(branch_ref_name
);
6118 free(fileindex_path
);
6120 got_ref_close(commit_ref
);
6122 got_ref_close(branch_ref
);
6127 got_ref_close(*tmp_branch
);
6130 if (*new_base_branch
) {
6131 got_ref_close(*new_base_branch
);
6132 *new_base_branch
= NULL
;
6135 got_ref_close(*branch
);
6139 got_fileindex_free(*fileindex
);
6142 lock_worktree(worktree
, LOCK_SH
);
6147 const struct got_error
*
6148 got_worktree_rebase_in_progress(int *in_progress
, struct got_worktree
*worktree
)
6150 const struct got_error
*err
;
6151 char *tmp_branch_name
= NULL
;
6153 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6157 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
6158 free(tmp_branch_name
);
6162 static const struct got_error
*
6163 collect_rebase_commit_msg(struct got_pathlist_head
*commitable_paths
,
6164 char **logmsg
, void *arg
)
6170 static const struct got_error
*
6171 rebase_status(void *arg
, unsigned char status
, unsigned char staged_status
,
6172 const char *path
, struct got_object_id
*blob_id
,
6173 struct got_object_id
*staged_blob_id
, struct got_object_id
*commit_id
,
6174 int dirfd
, const char *de_name
)
6179 struct collect_merged_paths_arg
{
6180 got_worktree_checkout_cb progress_cb
;
6182 struct got_pathlist_head
*merged_paths
;
6185 static const struct got_error
*
6186 collect_merged_paths(void *arg
, unsigned char status
, const char *path
)
6188 const struct got_error
*err
;
6189 struct collect_merged_paths_arg
*a
= arg
;
6191 struct got_pathlist_entry
*new;
6193 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, path
);
6197 if (status
!= GOT_STATUS_MERGE
&&
6198 status
!= GOT_STATUS_ADD
&&
6199 status
!= GOT_STATUS_DELETE
&&
6200 status
!= GOT_STATUS_CONFLICT
)
6205 return got_error_from_errno("strdup");
6207 err
= got_pathlist_insert(&new, a
->merged_paths
, p
, NULL
);
6208 if (err
|| new == NULL
)
6214 got_worktree_rebase_pathlist_free(struct got_pathlist_head
*merged_paths
)
6216 struct got_pathlist_entry
*pe
;
6218 TAILQ_FOREACH(pe
, merged_paths
, entry
)
6219 free((char *)pe
->path
);
6221 got_pathlist_free(merged_paths
);
6224 static const struct got_error
*
6225 store_commit_id(const char *commit_ref_name
, struct got_object_id
*commit_id
,
6226 int is_rebase
, struct got_repository
*repo
)
6228 const struct got_error
*err
;
6229 struct got_reference
*commit_ref
= NULL
;
6231 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6233 if (err
->code
!= GOT_ERR_NOT_REF
)
6235 err
= got_ref_alloc(&commit_ref
, commit_ref_name
, commit_id
);
6238 err
= got_ref_write(commit_ref
, repo
);
6241 } else if (is_rebase
) {
6242 struct got_object_id
*stored_id
;
6245 err
= got_ref_resolve(&stored_id
, repo
, commit_ref
);
6248 cmp
= got_object_id_cmp(commit_id
, stored_id
);
6251 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6257 got_ref_close(commit_ref
);
6261 static const struct got_error
*
6262 rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6263 const char *commit_ref_name
, struct got_worktree
*worktree
,
6264 struct got_fileindex
*fileindex
, struct got_object_id
*parent_commit_id
,
6265 struct got_object_id
*commit_id
, struct got_repository
*repo
,
6266 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6267 got_cancel_cb cancel_cb
, void *cancel_arg
)
6269 const struct got_error
*err
;
6270 struct got_reference
*commit_ref
= NULL
;
6271 struct collect_merged_paths_arg cmp_arg
;
6272 char *fileindex_path
;
6274 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6276 err
= get_fileindex_path(&fileindex_path
, worktree
);
6280 cmp_arg
.progress_cb
= progress_cb
;
6281 cmp_arg
.progress_arg
= progress_arg
;
6282 cmp_arg
.merged_paths
= merged_paths
;
6283 err
= merge_files(worktree
, fileindex
, fileindex_path
,
6284 parent_commit_id
, commit_id
, repo
, collect_merged_paths
,
6285 &cmp_arg
, cancel_cb
, cancel_arg
);
6287 got_ref_close(commit_ref
);
6291 const struct got_error
*
6292 got_worktree_rebase_merge_files(struct got_pathlist_head
*merged_paths
,
6293 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6294 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
6295 struct got_repository
*repo
,
6296 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6297 got_cancel_cb cancel_cb
, void *cancel_arg
)
6299 const struct got_error
*err
;
6300 char *commit_ref_name
;
6302 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6306 err
= store_commit_id(commit_ref_name
, commit_id
, 1, repo
);
6310 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
6311 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
6312 progress_arg
, cancel_cb
, cancel_arg
);
6314 free(commit_ref_name
);
6318 const struct got_error
*
6319 got_worktree_histedit_merge_files(struct got_pathlist_head
*merged_paths
,
6320 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6321 struct got_object_id
*parent_commit_id
, struct got_object_id
*commit_id
,
6322 struct got_repository
*repo
,
6323 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
6324 got_cancel_cb cancel_cb
, void *cancel_arg
)
6326 const struct got_error
*err
;
6327 char *commit_ref_name
;
6329 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6333 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
6337 err
= rebase_merge_files(merged_paths
, commit_ref_name
, worktree
,
6338 fileindex
, parent_commit_id
, commit_id
, repo
, progress_cb
,
6339 progress_arg
, cancel_cb
, cancel_arg
);
6341 free(commit_ref_name
);
6345 static const struct got_error
*
6346 rebase_commit(struct got_object_id
**new_commit_id
,
6347 struct got_pathlist_head
*merged_paths
, struct got_reference
*commit_ref
,
6348 struct got_worktree
*worktree
, struct got_fileindex
*fileindex
,
6349 struct got_reference
*tmp_branch
, struct got_commit_object
*orig_commit
,
6350 const char *new_logmsg
, struct got_repository
*repo
)
6352 const struct got_error
*err
, *sync_err
;
6353 struct got_pathlist_head commitable_paths
;
6354 struct collect_commitables_arg cc_arg
;
6355 char *fileindex_path
= NULL
;
6356 struct got_reference
*head_ref
= NULL
;
6357 struct got_object_id
*head_commit_id
= NULL
;
6358 char *logmsg
= NULL
;
6360 TAILQ_INIT(&commitable_paths
);
6361 *new_commit_id
= NULL
;
6363 /* Work tree is locked/unlocked during rebase preparation/teardown. */
6365 err
= get_fileindex_path(&fileindex_path
, worktree
);
6369 cc_arg
.commitable_paths
= &commitable_paths
;
6370 cc_arg
.worktree
= worktree
;
6372 cc_arg
.have_staged_files
= 0;
6374 * If possible get the status of individual files directly to
6375 * avoid crawling the entire work tree once per rebased commit.
6376 * TODO: Ideally, merged_paths would contain a list of commitables
6377 * we could use so we could skip worktree_status() entirely.
6380 struct got_pathlist_entry
*pe
;
6381 TAILQ_FOREACH(pe
, merged_paths
, entry
) {
6382 err
= worktree_status(worktree
, pe
->path
, fileindex
,
6383 repo
, collect_commitables
, &cc_arg
, NULL
, NULL
, 1,
6389 err
= worktree_status(worktree
, "", fileindex
, repo
,
6390 collect_commitables
, &cc_arg
, NULL
, NULL
, 1, 0);
6395 if (TAILQ_EMPTY(&commitable_paths
)) {
6396 /* No-op change; commit will be elided. */
6397 err
= got_ref_delete(commit_ref
, repo
);
6400 err
= got_error(GOT_ERR_COMMIT_NO_CHANGES
);
6404 err
= got_ref_open(&head_ref
, repo
, worktree
->head_ref_name
, 0);
6408 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
6413 logmsg
= strdup(new_logmsg
);
6414 if (logmsg
== NULL
) {
6415 err
= got_error_from_errno("strdup");
6419 err
= got_object_commit_get_logmsg(&logmsg
, orig_commit
);
6424 /* NB: commit_worktree will call free(logmsg) */
6425 err
= commit_worktree(new_commit_id
, &commitable_paths
, head_commit_id
,
6426 worktree
, got_object_commit_get_author(orig_commit
),
6427 got_object_commit_get_committer(orig_commit
),
6428 collect_rebase_commit_msg
, logmsg
, rebase_status
, NULL
, repo
);
6432 err
= got_ref_change_ref(tmp_branch
, *new_commit_id
);
6436 err
= got_ref_delete(commit_ref
, repo
);
6440 err
= update_fileindex_after_commit(worktree
, &commitable_paths
,
6441 *new_commit_id
, fileindex
, 0);
6442 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6443 if (sync_err
&& err
== NULL
)
6446 free(fileindex_path
);
6447 free(head_commit_id
);
6449 got_ref_close(head_ref
);
6451 free(*new_commit_id
);
6452 *new_commit_id
= NULL
;
6457 const struct got_error
*
6458 got_worktree_rebase_commit(struct got_object_id
**new_commit_id
,
6459 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6460 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6461 struct got_commit_object
*orig_commit
,
6462 struct got_object_id
*orig_commit_id
, struct got_repository
*repo
)
6464 const struct got_error
*err
;
6465 char *commit_ref_name
;
6466 struct got_reference
*commit_ref
= NULL
;
6467 struct got_object_id
*commit_id
= NULL
;
6469 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6473 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6476 err
= got_ref_resolve(&commit_id
, repo
, commit_ref
);
6479 if (got_object_id_cmp(commit_id
, orig_commit_id
) != 0) {
6480 err
= got_error(GOT_ERR_REBASE_COMMITID
);
6484 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6485 worktree
, fileindex
, tmp_branch
, orig_commit
, NULL
, repo
);
6488 got_ref_close(commit_ref
);
6489 free(commit_ref_name
);
6494 const struct got_error
*
6495 got_worktree_histedit_commit(struct got_object_id
**new_commit_id
,
6496 struct got_pathlist_head
*merged_paths
, struct got_worktree
*worktree
,
6497 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
6498 struct got_commit_object
*orig_commit
,
6499 struct got_object_id
*orig_commit_id
, const char *new_logmsg
,
6500 struct got_repository
*repo
)
6502 const struct got_error
*err
;
6503 char *commit_ref_name
;
6504 struct got_reference
*commit_ref
= NULL
;
6506 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6510 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6514 err
= rebase_commit(new_commit_id
, merged_paths
, commit_ref
,
6515 worktree
, fileindex
, tmp_branch
, orig_commit
, new_logmsg
, repo
);
6518 got_ref_close(commit_ref
);
6519 free(commit_ref_name
);
6523 const struct got_error
*
6524 got_worktree_rebase_postpone(struct got_worktree
*worktree
,
6525 struct got_fileindex
*fileindex
)
6528 got_fileindex_free(fileindex
);
6529 return lock_worktree(worktree
, LOCK_SH
);
6532 static const struct got_error
*
6533 delete_ref(const char *name
, struct got_repository
*repo
)
6535 const struct got_error
*err
;
6536 struct got_reference
*ref
;
6538 err
= got_ref_open(&ref
, repo
, name
, 0);
6540 if (err
->code
== GOT_ERR_NOT_REF
)
6545 err
= got_ref_delete(ref
, repo
);
6550 static const struct got_error
*
6551 delete_rebase_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
6553 const struct got_error
*err
;
6554 char *tmp_branch_name
= NULL
, *new_base_branch_ref_name
= NULL
;
6555 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
6557 err
= get_rebase_tmp_ref_name(&tmp_branch_name
, worktree
);
6560 err
= delete_ref(tmp_branch_name
, repo
);
6564 err
= get_newbase_symref_name(&new_base_branch_ref_name
, worktree
);
6567 err
= delete_ref(new_base_branch_ref_name
, repo
);
6571 err
= get_rebase_branch_symref_name(&branch_ref_name
, worktree
);
6574 err
= delete_ref(branch_ref_name
, repo
);
6578 err
= get_rebase_commit_ref_name(&commit_ref_name
, worktree
);
6581 err
= delete_ref(commit_ref_name
, repo
);
6586 free(tmp_branch_name
);
6587 free(new_base_branch_ref_name
);
6588 free(branch_ref_name
);
6589 free(commit_ref_name
);
6593 const struct got_error
*
6594 create_backup_ref(const char *backup_ref_prefix
, struct got_reference
*branch
,
6595 struct got_object_id
*new_commit_id
, struct got_repository
*repo
)
6597 const struct got_error
*err
;
6598 struct got_reference
*ref
= NULL
;
6599 struct got_object_id
*old_commit_id
= NULL
;
6600 const char *branch_name
= NULL
;
6601 char *new_id_str
= NULL
;
6602 char *refname
= NULL
;
6604 branch_name
= got_ref_get_name(branch
);
6605 if (strncmp(branch_name
, "refs/heads/", 11) != 0)
6606 return got_error(GOT_ERR_BAD_REF_NAME
); /* should not happen */
6609 err
= got_object_id_str(&new_id_str
, new_commit_id
);
6613 if (asprintf(&refname
, "%s/%s/%s", backup_ref_prefix
, branch_name
,
6614 new_id_str
) == -1) {
6615 err
= got_error_from_errno("asprintf");
6619 err
= got_ref_resolve(&old_commit_id
, repo
, branch
);
6623 err
= got_ref_alloc(&ref
, refname
, old_commit_id
);
6627 err
= got_ref_write(ref
, repo
);
6631 free(old_commit_id
);
6637 const struct got_error
*
6638 got_worktree_rebase_complete(struct got_worktree
*worktree
,
6639 struct got_fileindex
*fileindex
, struct got_reference
*new_base_branch
,
6640 struct got_reference
*tmp_branch
, struct got_reference
*rebased_branch
,
6641 struct got_repository
*repo
, int create_backup
)
6643 const struct got_error
*err
, *unlockerr
, *sync_err
;
6644 struct got_object_id
*new_head_commit_id
= NULL
;
6645 char *fileindex_path
= NULL
;
6647 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
6651 if (create_backup
) {
6652 err
= create_backup_ref(GOT_WORKTREE_REBASE_BACKUP_REF_PREFIX
,
6653 rebased_branch
, new_head_commit_id
, repo
);
6658 err
= got_ref_change_ref(rebased_branch
, new_head_commit_id
);
6662 err
= got_ref_write(rebased_branch
, repo
);
6666 err
= got_worktree_set_head_ref(worktree
, rebased_branch
);
6670 err
= delete_rebase_refs(worktree
, repo
);
6674 err
= get_fileindex_path(&fileindex_path
, worktree
);
6677 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
6678 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6679 if (sync_err
&& err
== NULL
)
6682 got_fileindex_free(fileindex
);
6683 free(fileindex_path
);
6684 free(new_head_commit_id
);
6685 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6686 if (unlockerr
&& err
== NULL
)
6691 const struct got_error
*
6692 got_worktree_rebase_abort(struct got_worktree
*worktree
,
6693 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
6694 struct got_reference
*new_base_branch
,
6695 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
6697 const struct got_error
*err
, *unlockerr
, *sync_err
;
6698 struct got_reference
*resolved
= NULL
;
6699 struct got_object_id
*commit_id
= NULL
;
6700 char *fileindex_path
= NULL
;
6701 struct revert_file_args rfa
;
6702 struct got_object_id
*tree_id
= NULL
;
6704 err
= lock_worktree(worktree
, LOCK_EX
);
6708 err
= got_ref_open(&resolved
, repo
,
6709 got_ref_get_symref_target(new_base_branch
), 0);
6713 err
= got_worktree_set_head_ref(worktree
, resolved
);
6718 * XXX commits to the base branch could have happened while
6719 * we were busy rebasing; should we store the original commit ID
6720 * when rebase begins and read it back here?
6722 err
= got_ref_resolve(&commit_id
, repo
, resolved
);
6726 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
6730 err
= got_object_id_by_path(&tree_id
, repo
,
6731 worktree
->base_commit_id
, worktree
->path_prefix
);
6735 err
= delete_rebase_refs(worktree
, repo
);
6739 err
= get_fileindex_path(&fileindex_path
, worktree
);
6743 rfa
.worktree
= worktree
;
6744 rfa
.fileindex
= fileindex
;
6745 rfa
.progress_cb
= progress_cb
;
6746 rfa
.progress_arg
= progress_arg
;
6747 rfa
.patch_cb
= NULL
;
6748 rfa
.patch_arg
= NULL
;
6750 err
= worktree_status(worktree
, "", fileindex
, repo
,
6751 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
6755 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
6756 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
6758 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
6759 if (sync_err
&& err
== NULL
)
6762 got_ref_close(resolved
);
6766 got_fileindex_free(fileindex
);
6767 free(fileindex_path
);
6769 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
6770 if (unlockerr
&& err
== NULL
)
6775 const struct got_error
*
6776 got_worktree_histedit_prepare(struct got_reference
**tmp_branch
,
6777 struct got_reference
**branch_ref
, struct got_object_id
**base_commit_id
,
6778 struct got_fileindex
**fileindex
, struct got_worktree
*worktree
,
6779 struct got_repository
*repo
)
6781 const struct got_error
*err
= NULL
;
6782 char *tmp_branch_name
= NULL
;
6783 char *branch_ref_name
= NULL
;
6784 char *base_commit_ref_name
= NULL
;
6785 char *fileindex_path
= NULL
;
6786 struct check_rebase_ok_arg ok_arg
;
6787 struct got_reference
*wt_branch
= NULL
;
6788 struct got_reference
*base_commit_ref
= NULL
;
6792 *base_commit_id
= NULL
;
6795 err
= lock_worktree(worktree
, LOCK_EX
);
6799 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6803 ok_arg
.worktree
= worktree
;
6805 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
6810 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
6814 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
6818 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
6823 err
= got_ref_open(&wt_branch
, repo
, worktree
->head_ref_name
,
6828 err
= got_ref_alloc_symref(branch_ref
, branch_ref_name
, wt_branch
);
6832 err
= got_ref_write(*branch_ref
, repo
);
6836 err
= got_ref_alloc(&base_commit_ref
, base_commit_ref_name
,
6837 worktree
->base_commit_id
);
6840 err
= got_ref_write(base_commit_ref
, repo
);
6843 *base_commit_id
= got_object_id_dup(worktree
->base_commit_id
);
6844 if (*base_commit_id
== NULL
) {
6845 err
= got_error_from_errno("got_object_id_dup");
6849 err
= got_ref_alloc(tmp_branch
, tmp_branch_name
,
6850 worktree
->base_commit_id
);
6853 err
= got_ref_write(*tmp_branch
, repo
);
6857 err
= got_worktree_set_head_ref(worktree
, *tmp_branch
);
6861 free(fileindex_path
);
6862 free(tmp_branch_name
);
6863 free(branch_ref_name
);
6864 free(base_commit_ref_name
);
6866 got_ref_close(wt_branch
);
6869 got_ref_close(*branch_ref
);
6873 got_ref_close(*tmp_branch
);
6876 free(*base_commit_id
);
6878 got_fileindex_free(*fileindex
);
6881 lock_worktree(worktree
, LOCK_SH
);
6886 const struct got_error
*
6887 got_worktree_histedit_postpone(struct got_worktree
*worktree
,
6888 struct got_fileindex
*fileindex
)
6891 got_fileindex_free(fileindex
);
6892 return lock_worktree(worktree
, LOCK_SH
);
6895 const struct got_error
*
6896 got_worktree_histedit_in_progress(int *in_progress
,
6897 struct got_worktree
*worktree
)
6899 const struct got_error
*err
;
6900 char *tmp_branch_name
= NULL
;
6902 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
6906 *in_progress
= (strcmp(tmp_branch_name
, worktree
->head_ref_name
) == 0);
6907 free(tmp_branch_name
);
6911 const struct got_error
*
6912 got_worktree_histedit_continue(struct got_object_id
**commit_id
,
6913 struct got_reference
**tmp_branch
, struct got_reference
**branch_ref
,
6914 struct got_object_id
**base_commit_id
, struct got_fileindex
**fileindex
,
6915 struct got_worktree
*worktree
, struct got_repository
*repo
)
6917 const struct got_error
*err
;
6918 char *commit_ref_name
= NULL
, *base_commit_ref_name
= NULL
;
6919 char *tmp_branch_name
= NULL
, *branch_ref_name
= NULL
;
6920 struct got_reference
*commit_ref
= NULL
;
6921 struct got_reference
*base_commit_ref
= NULL
;
6922 char *fileindex_path
= NULL
;
6923 int have_staged_files
= 0;
6927 *base_commit_id
= NULL
;
6930 err
= lock_worktree(worktree
, LOCK_EX
);
6934 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
6938 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_staged_file
,
6939 &have_staged_files
);
6940 if (err
&& err
->code
!= GOT_ERR_CANCELLED
)
6942 if (have_staged_files
) {
6943 err
= got_error(GOT_ERR_STAGED_PATHS
);
6947 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
6951 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
6955 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
6959 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
6964 err
= got_ref_open(branch_ref
, repo
, branch_ref_name
, 0);
6968 err
= got_ref_open(&commit_ref
, repo
, commit_ref_name
, 0);
6971 err
= got_ref_resolve(commit_id
, repo
, commit_ref
);
6975 err
= got_ref_open(&base_commit_ref
, repo
, base_commit_ref_name
, 0);
6978 err
= got_ref_resolve(base_commit_id
, repo
, base_commit_ref
);
6982 err
= got_ref_open(tmp_branch
, repo
, tmp_branch_name
, 0);
6986 free(commit_ref_name
);
6987 free(branch_ref_name
);
6988 free(fileindex_path
);
6990 got_ref_close(commit_ref
);
6991 if (base_commit_ref
)
6992 got_ref_close(base_commit_ref
);
6996 free(*base_commit_id
);
6997 *base_commit_id
= NULL
;
6999 got_ref_close(*tmp_branch
);
7003 got_fileindex_free(*fileindex
);
7006 lock_worktree(worktree
, LOCK_EX
);
7011 static const struct got_error
*
7012 delete_histedit_refs(struct got_worktree
*worktree
, struct got_repository
*repo
)
7014 const struct got_error
*err
;
7015 char *tmp_branch_name
= NULL
, *base_commit_ref_name
= NULL
;
7016 char *branch_ref_name
= NULL
, *commit_ref_name
= NULL
;
7018 err
= get_histedit_tmp_ref_name(&tmp_branch_name
, worktree
);
7021 err
= delete_ref(tmp_branch_name
, repo
);
7025 err
= get_histedit_base_commit_ref_name(&base_commit_ref_name
,
7029 err
= delete_ref(base_commit_ref_name
, repo
);
7033 err
= get_histedit_branch_symref_name(&branch_ref_name
, worktree
);
7036 err
= delete_ref(branch_ref_name
, repo
);
7040 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7043 err
= delete_ref(commit_ref_name
, repo
);
7047 free(tmp_branch_name
);
7048 free(base_commit_ref_name
);
7049 free(branch_ref_name
);
7050 free(commit_ref_name
);
7054 const struct got_error
*
7055 got_worktree_histedit_abort(struct got_worktree
*worktree
,
7056 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7057 struct got_reference
*branch
, struct got_object_id
*base_commit_id
,
7058 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7060 const struct got_error
*err
, *unlockerr
, *sync_err
;
7061 struct got_reference
*resolved
= NULL
;
7062 char *fileindex_path
= NULL
;
7063 struct got_object_id
*tree_id
= NULL
;
7064 struct revert_file_args rfa
;
7066 err
= lock_worktree(worktree
, LOCK_EX
);
7070 err
= got_ref_open(&resolved
, repo
,
7071 got_ref_get_symref_target(branch
), 0);
7075 err
= got_worktree_set_head_ref(worktree
, resolved
);
7079 err
= got_worktree_set_base_commit_id(worktree
, repo
, base_commit_id
);
7083 err
= got_object_id_by_path(&tree_id
, repo
, base_commit_id
,
7084 worktree
->path_prefix
);
7088 err
= delete_histedit_refs(worktree
, repo
);
7092 err
= get_fileindex_path(&fileindex_path
, worktree
);
7096 rfa
.worktree
= worktree
;
7097 rfa
.fileindex
= fileindex
;
7098 rfa
.progress_cb
= progress_cb
;
7099 rfa
.progress_arg
= progress_arg
;
7100 rfa
.patch_cb
= NULL
;
7101 rfa
.patch_arg
= NULL
;
7103 err
= worktree_status(worktree
, "", fileindex
, repo
,
7104 revert_file
, &rfa
, NULL
, NULL
, 0, 0);
7108 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
,
7109 repo
, progress_cb
, progress_arg
, NULL
, NULL
);
7111 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7112 if (sync_err
&& err
== NULL
)
7115 got_ref_close(resolved
);
7117 free(fileindex_path
);
7119 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7120 if (unlockerr
&& err
== NULL
)
7125 const struct got_error
*
7126 got_worktree_histedit_complete(struct got_worktree
*worktree
,
7127 struct got_fileindex
*fileindex
, struct got_reference
*tmp_branch
,
7128 struct got_reference
*edited_branch
, struct got_repository
*repo
)
7130 const struct got_error
*err
, *unlockerr
, *sync_err
;
7131 struct got_object_id
*new_head_commit_id
= NULL
;
7132 struct got_reference
*resolved
= NULL
;
7133 char *fileindex_path
= NULL
;
7135 err
= got_ref_resolve(&new_head_commit_id
, repo
, tmp_branch
);
7139 err
= got_ref_open(&resolved
, repo
,
7140 got_ref_get_symref_target(edited_branch
), 0);
7144 err
= create_backup_ref(GOT_WORKTREE_HISTEDIT_BACKUP_REF_PREFIX
,
7145 resolved
, new_head_commit_id
, repo
);
7149 err
= got_ref_change_ref(resolved
, new_head_commit_id
);
7153 err
= got_ref_write(resolved
, repo
);
7157 err
= got_worktree_set_head_ref(worktree
, resolved
);
7161 err
= delete_histedit_refs(worktree
, repo
);
7165 err
= get_fileindex_path(&fileindex_path
, worktree
);
7168 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7169 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7170 if (sync_err
&& err
== NULL
)
7173 got_fileindex_free(fileindex
);
7174 free(fileindex_path
);
7175 free(new_head_commit_id
);
7176 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7177 if (unlockerr
&& err
== NULL
)
7182 const struct got_error
*
7183 got_worktree_histedit_skip_commit(struct got_worktree
*worktree
,
7184 struct got_object_id
*commit_id
, struct got_repository
*repo
)
7186 const struct got_error
*err
;
7187 char *commit_ref_name
;
7189 err
= get_histedit_commit_ref_name(&commit_ref_name
, worktree
);
7193 err
= store_commit_id(commit_ref_name
, commit_id
, 0, repo
);
7197 err
= delete_ref(commit_ref_name
, repo
);
7199 free(commit_ref_name
);
7203 const struct got_error
*
7204 got_worktree_integrate_prepare(struct got_fileindex
**fileindex
,
7205 struct got_reference
**branch_ref
, struct got_reference
**base_branch_ref
,
7206 struct got_worktree
*worktree
, const char *refname
,
7207 struct got_repository
*repo
)
7209 const struct got_error
*err
= NULL
;
7210 char *fileindex_path
= NULL
;
7211 struct check_rebase_ok_arg ok_arg
;
7215 *base_branch_ref
= NULL
;
7217 err
= lock_worktree(worktree
, LOCK_EX
);
7221 if (strcmp(refname
, got_worktree_get_head_ref_name(worktree
)) == 0) {
7222 err
= got_error_msg(GOT_ERR_SAME_BRANCH
,
7223 "cannot integrate a branch into itself; "
7224 "update -b or different branch name required");
7228 err
= open_fileindex(fileindex
, &fileindex_path
, worktree
);
7232 /* Preconditions are the same as for rebase. */
7233 ok_arg
.worktree
= worktree
;
7235 err
= got_fileindex_for_each_entry_safe(*fileindex
, check_rebase_ok
,
7240 err
= got_ref_open(branch_ref
, repo
, refname
, 1);
7244 err
= got_ref_open(base_branch_ref
, repo
,
7245 got_worktree_get_head_ref_name(worktree
), 1);
7249 got_ref_close(*branch_ref
);
7252 if (*base_branch_ref
) {
7253 got_ref_close(*base_branch_ref
);
7254 *base_branch_ref
= NULL
;
7257 got_fileindex_free(*fileindex
);
7260 lock_worktree(worktree
, LOCK_SH
);
7265 const struct got_error
*
7266 got_worktree_integrate_continue(struct got_worktree
*worktree
,
7267 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7268 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
,
7269 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
7270 got_cancel_cb cancel_cb
, void *cancel_arg
)
7272 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
7273 char *fileindex_path
= NULL
;
7274 struct got_object_id
*tree_id
= NULL
, *commit_id
= NULL
;
7276 err
= get_fileindex_path(&fileindex_path
, worktree
);
7280 err
= got_ref_resolve(&commit_id
, repo
, branch_ref
);
7284 err
= got_object_id_by_path(&tree_id
, repo
, commit_id
,
7285 worktree
->path_prefix
);
7289 err
= got_worktree_set_base_commit_id(worktree
, repo
, commit_id
);
7293 err
= checkout_files(worktree
, fileindex
, "", tree_id
, NULL
, repo
,
7294 progress_cb
, progress_arg
, cancel_cb
, cancel_arg
);
7298 err
= got_ref_change_ref(base_branch_ref
, commit_id
);
7302 err
= got_ref_write(base_branch_ref
, repo
);
7306 err
= bump_base_commit_id_everywhere(worktree
, fileindex
, NULL
, NULL
);
7308 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7309 if (sync_err
&& err
== NULL
)
7313 unlockerr
= got_ref_unlock(branch_ref
);
7314 if (unlockerr
&& err
== NULL
)
7316 got_ref_close(branch_ref
);
7318 unlockerr
= got_ref_unlock(base_branch_ref
);
7319 if (unlockerr
&& err
== NULL
)
7321 got_ref_close(base_branch_ref
);
7323 got_fileindex_free(fileindex
);
7324 free(fileindex_path
);
7327 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7328 if (unlockerr
&& err
== NULL
)
7333 const struct got_error
*
7334 got_worktree_integrate_abort(struct got_worktree
*worktree
,
7335 struct got_fileindex
*fileindex
, struct got_repository
*repo
,
7336 struct got_reference
*branch_ref
, struct got_reference
*base_branch_ref
)
7338 const struct got_error
*err
= NULL
, *unlockerr
= NULL
;
7340 got_fileindex_free(fileindex
);
7342 err
= lock_worktree(worktree
, LOCK_SH
);
7344 unlockerr
= got_ref_unlock(branch_ref
);
7345 if (unlockerr
&& err
== NULL
)
7347 got_ref_close(branch_ref
);
7349 unlockerr
= got_ref_unlock(base_branch_ref
);
7350 if (unlockerr
&& err
== NULL
)
7352 got_ref_close(base_branch_ref
);
7357 struct check_stage_ok_arg
{
7358 struct got_object_id
*head_commit_id
;
7359 struct got_worktree
*worktree
;
7360 struct got_fileindex
*fileindex
;
7361 struct got_repository
*repo
;
7365 const struct got_error
*
7366 check_stage_ok(void *arg
, unsigned char status
,
7367 unsigned char staged_status
, const char *relpath
,
7368 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
7369 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
7371 struct check_stage_ok_arg
*a
= arg
;
7372 const struct got_error
*err
= NULL
;
7373 struct got_fileindex_entry
*ie
;
7374 struct got_object_id base_commit_id
;
7375 struct got_object_id
*base_commit_idp
= NULL
;
7376 char *in_repo_path
= NULL
, *p
;
7378 if (status
== GOT_STATUS_UNVERSIONED
||
7379 status
== GOT_STATUS_NO_CHANGE
)
7381 if (status
== GOT_STATUS_NONEXISTENT
)
7382 return got_error_set_errno(ENOENT
, relpath
);
7384 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
7386 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
7388 if (asprintf(&in_repo_path
, "%s%s%s", a
->worktree
->path_prefix
,
7389 got_path_is_root_dir(a
->worktree
->path_prefix
) ? "" : "/",
7391 return got_error_from_errno("asprintf");
7393 if (got_fileindex_entry_has_commit(ie
)) {
7394 memcpy(base_commit_id
.sha1
, ie
->commit_sha1
,
7395 SHA1_DIGEST_LENGTH
);
7396 base_commit_idp
= &base_commit_id
;
7399 if (status
== GOT_STATUS_CONFLICT
) {
7400 err
= got_error_path(ie
->path
, GOT_ERR_STAGE_CONFLICT
);
7402 } else if (status
!= GOT_STATUS_ADD
&&
7403 status
!= GOT_STATUS_MODIFY
&&
7404 status
!= GOT_STATUS_DELETE
) {
7405 err
= got_error_path(ie
->path
, GOT_ERR_FILE_STATUS
);
7409 a
->have_changes
= 1;
7414 err
= check_out_of_date(p
, status
, staged_status
,
7415 blob_id
, base_commit_idp
, a
->head_commit_id
, a
->repo
,
7416 GOT_ERR_STAGE_OUT_OF_DATE
);
7422 struct stage_path_arg
{
7423 struct got_worktree
*worktree
;
7424 struct got_fileindex
*fileindex
;
7425 struct got_repository
*repo
;
7426 got_worktree_status_cb status_cb
;
7428 got_worktree_patch_cb patch_cb
;
7430 int staged_something
;
7431 int allow_bad_symlinks
;
7434 static const struct got_error
*
7435 stage_path(void *arg
, unsigned char status
,
7436 unsigned char staged_status
, const char *relpath
,
7437 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
7438 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
7440 struct stage_path_arg
*a
= arg
;
7441 const struct got_error
*err
= NULL
;
7442 struct got_fileindex_entry
*ie
;
7443 char *ondisk_path
= NULL
, *path_content
= NULL
;
7445 struct got_object_id
*new_staged_blob_id
= NULL
;
7448 if (status
== GOT_STATUS_UNVERSIONED
)
7451 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
7453 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
7455 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
,
7457 return got_error_from_errno("asprintf");
7460 case GOT_STATUS_ADD
:
7461 case GOT_STATUS_MODIFY
:
7462 /* XXX could sb.st_mode be passed in by our caller? */
7463 if (lstat(ondisk_path
, &sb
) == -1) {
7464 err
= got_error_from_errno2("lstat", ondisk_path
);
7468 if (status
== GOT_STATUS_ADD
) {
7469 int choice
= GOT_PATCH_CHOICE_NONE
;
7470 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
7471 status
, ie
->path
, NULL
, 1, 1);
7474 if (choice
!= GOT_PATCH_CHOICE_YES
)
7477 err
= create_patched_content(&path_content
, 0,
7478 staged_blob_id
? staged_blob_id
: blob_id
,
7479 ondisk_path
, dirfd
, de_name
, ie
->path
,
7480 a
->repo
, a
->patch_cb
, a
->patch_arg
);
7481 if (err
|| path_content
== NULL
)
7485 err
= got_object_blob_create(&new_staged_blob_id
,
7486 path_content
? path_content
: ondisk_path
, a
->repo
);
7489 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
7490 SHA1_DIGEST_LENGTH
);
7491 if (status
== GOT_STATUS_ADD
|| staged_status
== GOT_STATUS_ADD
)
7492 stage
= GOT_FILEIDX_STAGE_ADD
;
7494 stage
= GOT_FILEIDX_STAGE_MODIFY
;
7495 got_fileindex_entry_stage_set(ie
, stage
);
7496 if (S_ISLNK(sb
.st_mode
)) {
7497 int is_bad_symlink
= 0;
7498 if (!a
->allow_bad_symlinks
) {
7499 char target_path
[PATH_MAX
];
7501 target_len
= readlink(ondisk_path
, target_path
,
7502 sizeof(target_path
));
7503 if (target_len
== -1) {
7504 err
= got_error_from_errno2("readlink",
7508 err
= is_bad_symlink_target(&is_bad_symlink
,
7509 target_path
, target_len
, ondisk_path
,
7510 a
->worktree
->root_path
);
7513 if (is_bad_symlink
) {
7514 err
= got_error_path(ondisk_path
,
7515 GOT_ERR_BAD_SYMLINK
);
7520 got_fileindex_entry_staged_filetype_set(ie
,
7521 GOT_FILEIDX_MODE_BAD_SYMLINK
);
7523 got_fileindex_entry_staged_filetype_set(ie
,
7524 GOT_FILEIDX_MODE_SYMLINK
);
7526 got_fileindex_entry_staged_filetype_set(ie
,
7527 GOT_FILEIDX_MODE_REGULAR_FILE
);
7529 a
->staged_something
= 1;
7530 if (a
->status_cb
== NULL
)
7532 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
7533 get_staged_status(ie
), relpath
, blob_id
,
7534 new_staged_blob_id
, NULL
, dirfd
, de_name
);
7536 case GOT_STATUS_DELETE
:
7537 if (staged_status
== GOT_STATUS_DELETE
)
7540 int choice
= GOT_PATCH_CHOICE_NONE
;
7541 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
, status
,
7542 ie
->path
, NULL
, 1, 1);
7545 if (choice
== GOT_PATCH_CHOICE_NO
)
7547 if (choice
!= GOT_PATCH_CHOICE_YES
) {
7548 err
= got_error(GOT_ERR_PATCH_CHOICE
);
7552 stage
= GOT_FILEIDX_STAGE_DELETE
;
7553 got_fileindex_entry_stage_set(ie
, stage
);
7554 a
->staged_something
= 1;
7555 if (a
->status_cb
== NULL
)
7557 err
= (*a
->status_cb
)(a
->status_arg
, GOT_STATUS_NO_CHANGE
,
7558 get_staged_status(ie
), relpath
, NULL
, NULL
, NULL
, dirfd
,
7561 case GOT_STATUS_NO_CHANGE
:
7563 case GOT_STATUS_CONFLICT
:
7564 err
= got_error_path(relpath
, GOT_ERR_STAGE_CONFLICT
);
7566 case GOT_STATUS_NONEXISTENT
:
7567 err
= got_error_set_errno(ENOENT
, relpath
);
7570 err
= got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
7574 if (path_content
&& unlink(path_content
) == -1 && err
== NULL
)
7575 err
= got_error_from_errno2("unlink", path_content
);
7578 free(new_staged_blob_id
);
7582 const struct got_error
*
7583 got_worktree_stage(struct got_worktree
*worktree
,
7584 struct got_pathlist_head
*paths
,
7585 got_worktree_status_cb status_cb
, void *status_arg
,
7586 got_worktree_patch_cb patch_cb
, void *patch_arg
,
7587 int allow_bad_symlinks
, struct got_repository
*repo
)
7589 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
7590 struct got_pathlist_entry
*pe
;
7591 struct got_fileindex
*fileindex
= NULL
;
7592 char *fileindex_path
= NULL
;
7593 struct got_reference
*head_ref
= NULL
;
7594 struct got_object_id
*head_commit_id
= NULL
;
7595 struct check_stage_ok_arg oka
;
7596 struct stage_path_arg spa
;
7598 err
= lock_worktree(worktree
, LOCK_EX
);
7602 err
= got_ref_open(&head_ref
, repo
,
7603 got_worktree_get_head_ref_name(worktree
), 0);
7606 err
= got_ref_resolve(&head_commit_id
, repo
, head_ref
);
7609 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
7613 /* Check pre-conditions before staging anything. */
7614 oka
.head_commit_id
= head_commit_id
;
7615 oka
.worktree
= worktree
;
7616 oka
.fileindex
= fileindex
;
7618 oka
.have_changes
= 0;
7619 TAILQ_FOREACH(pe
, paths
, entry
) {
7620 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
7621 check_stage_ok
, &oka
, NULL
, NULL
, 0, 0);
7625 if (!oka
.have_changes
) {
7626 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
7630 spa
.worktree
= worktree
;
7631 spa
.fileindex
= fileindex
;
7633 spa
.patch_cb
= patch_cb
;
7634 spa
.patch_arg
= patch_arg
;
7635 spa
.status_cb
= status_cb
;
7636 spa
.status_arg
= status_arg
;
7637 spa
.staged_something
= 0;
7638 spa
.allow_bad_symlinks
= allow_bad_symlinks
;
7639 TAILQ_FOREACH(pe
, paths
, entry
) {
7640 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
7641 stage_path
, &spa
, NULL
, NULL
, 0, 0);
7645 if (!spa
.staged_something
) {
7646 err
= got_error(GOT_ERR_STAGE_NO_CHANGE
);
7650 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
7651 if (sync_err
&& err
== NULL
)
7655 got_ref_close(head_ref
);
7656 free(head_commit_id
);
7657 free(fileindex_path
);
7659 got_fileindex_free(fileindex
);
7660 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
7661 if (unlockerr
&& err
== NULL
)
7666 struct unstage_path_arg
{
7667 struct got_worktree
*worktree
;
7668 struct got_fileindex
*fileindex
;
7669 struct got_repository
*repo
;
7670 got_worktree_checkout_cb progress_cb
;
7672 got_worktree_patch_cb patch_cb
;
7676 static const struct got_error
*
7677 create_unstaged_content(char **path_unstaged_content
,
7678 char **path_new_staged_content
, struct got_object_id
*blob_id
,
7679 struct got_object_id
*staged_blob_id
, const char *relpath
,
7680 struct got_repository
*repo
,
7681 got_worktree_patch_cb patch_cb
, void *patch_arg
)
7683 const struct got_error
*err
, *free_err
;
7684 struct got_blob_object
*blob
= NULL
, *staged_blob
= NULL
;
7685 FILE *f1
= NULL
, *f2
= NULL
, *outfile
= NULL
, *rejectfile
= NULL
;
7686 char *path1
= NULL
, *path2
= NULL
, *label1
= NULL
;
7687 struct got_diffreg_result
*diffreg_result
= NULL
;
7688 int line_cur1
= 1, line_cur2
= 1, n
= 0, nchunks_used
= 0;
7689 int have_content
= 0, have_rejected_content
= 0, i
= 0, nchanges
= 0;
7691 *path_unstaged_content
= NULL
;
7692 *path_new_staged_content
= NULL
;
7694 err
= got_object_id_str(&label1
, blob_id
);
7697 err
= got_object_open_as_blob(&blob
, repo
, blob_id
, 8192);
7701 err
= got_opentemp_named(&path1
, &f1
, "got-unstage-blob-base");
7705 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f1
, blob
);
7709 err
= got_object_open_as_blob(&staged_blob
, repo
, staged_blob_id
, 8192);
7713 err
= got_opentemp_named(&path2
, &f2
, "got-unstage-blob-staged");
7717 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f2
, staged_blob
);
7721 err
= got_diff_files(&diffreg_result
, f1
, label1
, f2
,
7722 path2
, 3, 0, 1, NULL
);
7726 err
= got_opentemp_named(path_unstaged_content
, &outfile
,
7727 "got-unstaged-content");
7730 err
= got_opentemp_named(path_new_staged_content
, &rejectfile
,
7731 "got-new-staged-content");
7735 if (fseek(f1
, 0L, SEEK_SET
) == -1) {
7736 err
= got_ferror(f1
, GOT_ERR_IO
);
7739 if (fseek(f2
, 0L, SEEK_SET
) == -1) {
7740 err
= got_ferror(f2
, GOT_ERR_IO
);
7743 /* Count the number of actual changes in the diff result. */
7744 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
7745 struct diff_chunk_context cc
= {};
7746 diff_chunk_context_load_change(&cc
, &nchunks_used
,
7747 diffreg_result
->result
, n
, 0);
7750 for (n
= 0; n
< diffreg_result
->result
->chunks
.len
; n
+= nchunks_used
) {
7752 err
= apply_or_reject_change(&choice
, &nchunks_used
,
7753 diffreg_result
->result
, n
, relpath
, f1
, f2
,
7754 &line_cur1
, &line_cur2
,
7755 outfile
, rejectfile
, ++i
, nchanges
, patch_cb
, patch_arg
);
7758 if (choice
== GOT_PATCH_CHOICE_YES
)
7761 have_rejected_content
= 1;
7762 if (choice
== GOT_PATCH_CHOICE_QUIT
)
7765 if (have_content
|| have_rejected_content
)
7766 err
= copy_remaining_content(f1
, f2
, &line_cur1
, &line_cur2
,
7767 outfile
, rejectfile
);
7771 got_object_blob_close(blob
);
7773 got_object_blob_close(staged_blob
);
7774 free_err
= got_diffreg_result_free(diffreg_result
);
7775 if (free_err
&& err
== NULL
)
7777 if (f1
&& fclose(f1
) == EOF
&& err
== NULL
)
7778 err
= got_error_from_errno2("fclose", path1
);
7779 if (f2
&& fclose(f2
) == EOF
&& err
== NULL
)
7780 err
= got_error_from_errno2("fclose", path2
);
7781 if (outfile
&& fclose(outfile
) == EOF
&& err
== NULL
)
7782 err
= got_error_from_errno2("fclose", *path_unstaged_content
);
7783 if (rejectfile
&& fclose(rejectfile
) == EOF
&& err
== NULL
)
7784 err
= got_error_from_errno2("fclose", *path_new_staged_content
);
7785 if (path1
&& unlink(path1
) == -1 && err
== NULL
)
7786 err
= got_error_from_errno2("unlink", path1
);
7787 if (path2
&& unlink(path2
) == -1 && err
== NULL
)
7788 err
= got_error_from_errno2("unlink", path2
);
7789 if (err
|| !have_content
) {
7790 if (*path_unstaged_content
&&
7791 unlink(*path_unstaged_content
) == -1 && err
== NULL
)
7792 err
= got_error_from_errno2("unlink",
7793 *path_unstaged_content
);
7794 free(*path_unstaged_content
);
7795 *path_unstaged_content
= NULL
;
7797 if (err
|| !have_content
|| !have_rejected_content
) {
7798 if (*path_new_staged_content
&&
7799 unlink(*path_new_staged_content
) == -1 && err
== NULL
)
7800 err
= got_error_from_errno2("unlink",
7801 *path_new_staged_content
);
7802 free(*path_new_staged_content
);
7803 *path_new_staged_content
= NULL
;
7810 static const struct got_error
*
7811 unstage_hunks(struct got_object_id
*staged_blob_id
,
7812 struct got_blob_object
*blob_base
,
7813 struct got_object_id
*blob_id
, struct got_fileindex_entry
*ie
,
7814 const char *ondisk_path
, const char *label_orig
,
7815 struct got_worktree
*worktree
, struct got_repository
*repo
,
7816 got_worktree_patch_cb patch_cb
, void *patch_arg
,
7817 got_worktree_checkout_cb progress_cb
, void *progress_arg
)
7819 const struct got_error
*err
= NULL
;
7820 char *path_unstaged_content
= NULL
;
7821 char *path_new_staged_content
= NULL
;
7822 char *parent
= NULL
, *base_path
= NULL
;
7823 char *blob_base_path
= NULL
;
7824 struct got_object_id
*new_staged_blob_id
= NULL
;
7825 FILE *f
= NULL
, *f_base
= NULL
, *f_deriv2
= NULL
;
7828 err
= create_unstaged_content(&path_unstaged_content
,
7829 &path_new_staged_content
, blob_id
, staged_blob_id
,
7830 ie
->path
, repo
, patch_cb
, patch_arg
);
7834 if (path_unstaged_content
== NULL
)
7837 if (path_new_staged_content
) {
7838 err
= got_object_blob_create(&new_staged_blob_id
,
7839 path_new_staged_content
, repo
);
7844 f
= fopen(path_unstaged_content
, "r");
7846 err
= got_error_from_errno2("fopen",
7847 path_unstaged_content
);
7850 if (fstat(fileno(f
), &sb
) == -1) {
7851 err
= got_error_from_errno2("fstat", path_unstaged_content
);
7854 if (got_fileindex_entry_staged_filetype_get(ie
) ==
7855 GOT_FILEIDX_MODE_SYMLINK
&& sb
.st_size
< PATH_MAX
) {
7856 char link_target
[PATH_MAX
];
7858 r
= fread(link_target
, 1, sizeof(link_target
), f
);
7859 if (r
== 0 && ferror(f
)) {
7860 err
= got_error_from_errno("fread");
7863 if (r
>= sizeof(link_target
)) { /* should not happen */
7864 err
= got_error(GOT_ERR_NO_SPACE
);
7867 link_target
[r
] = '\0';
7868 err
= merge_symlink(worktree
, blob_base
,
7869 ondisk_path
, ie
->path
, label_orig
, link_target
,
7870 worktree
->base_commit_id
, repo
, progress_cb
,
7873 int local_changes_subsumed
;
7875 err
= got_path_dirname(&parent
, ondisk_path
);
7879 if (asprintf(&base_path
, "%s/got-unstage-blob-orig",
7881 err
= got_error_from_errno("asprintf");
7886 err
= got_opentemp_named(&blob_base_path
, &f_base
, base_path
);
7889 err
= got_object_blob_dump_to_file(NULL
, NULL
, NULL
, f_base
,
7895 * In order the run a 3-way merge with a symlink we copy the symlink's
7896 * target path into a temporary file and use that file with diff3.
7898 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
7899 err
= dump_symlink_target_path_to_file(&f_deriv2
,
7905 fd
= open(ondisk_path
, O_RDONLY
| O_NOFOLLOW
);
7907 err
= got_error_from_errno2("open", ondisk_path
);
7910 f_deriv2
= fdopen(fd
, "r");
7911 if (f_deriv2
== NULL
) {
7912 err
= got_error_from_errno2("fdopen", ondisk_path
);
7918 err
= merge_file(&local_changes_subsumed
, worktree
,
7919 f_base
, f
, f_deriv2
, ondisk_path
, ie
->path
,
7920 got_fileindex_perms_to_st(ie
),
7921 label_orig
, "unstaged", NULL
, GOT_DIFF_ALGORITHM_MYERS
,
7922 repo
, progress_cb
, progress_arg
);
7927 if (new_staged_blob_id
) {
7928 memcpy(ie
->staged_blob_sha1
, new_staged_blob_id
->sha1
,
7929 SHA1_DIGEST_LENGTH
);
7931 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
7932 got_fileindex_entry_staged_filetype_set(ie
, 0);
7935 free(new_staged_blob_id
);
7936 if (path_unstaged_content
&&
7937 unlink(path_unstaged_content
) == -1 && err
== NULL
)
7938 err
= got_error_from_errno2("unlink", path_unstaged_content
);
7939 if (path_new_staged_content
&&
7940 unlink(path_new_staged_content
) == -1 && err
== NULL
)
7941 err
= got_error_from_errno2("unlink", path_new_staged_content
);
7942 if (blob_base_path
&& unlink(blob_base_path
) == -1 && err
== NULL
)
7943 err
= got_error_from_errno2("unlink", blob_base_path
);
7944 if (f_base
&& fclose(f_base
) == EOF
&& err
== NULL
)
7945 err
= got_error_from_errno2("fclose", path_unstaged_content
);
7946 if (f
&& fclose(f
) == EOF
&& err
== NULL
)
7947 err
= got_error_from_errno2("fclose", path_unstaged_content
);
7948 if (f_deriv2
&& fclose(f_deriv2
) == EOF
&& err
== NULL
)
7949 err
= got_error_from_errno2("fclose", ondisk_path
);
7950 free(path_unstaged_content
);
7951 free(path_new_staged_content
);
7952 free(blob_base_path
);
7958 static const struct got_error
*
7959 unstage_path(void *arg
, unsigned char status
,
7960 unsigned char staged_status
, const char *relpath
,
7961 struct got_object_id
*blob_id
, struct got_object_id
*staged_blob_id
,
7962 struct got_object_id
*commit_id
, int dirfd
, const char *de_name
)
7964 const struct got_error
*err
= NULL
;
7965 struct unstage_path_arg
*a
= arg
;
7966 struct got_fileindex_entry
*ie
;
7967 struct got_blob_object
*blob_base
= NULL
, *blob_staged
= NULL
;
7968 char *ondisk_path
= NULL
;
7969 char *id_str
= NULL
, *label_orig
= NULL
;
7970 int local_changes_subsumed
;
7973 if (staged_status
!= GOT_STATUS_ADD
&&
7974 staged_status
!= GOT_STATUS_MODIFY
&&
7975 staged_status
!= GOT_STATUS_DELETE
)
7978 ie
= got_fileindex_entry_get(a
->fileindex
, relpath
, strlen(relpath
));
7980 return got_error_path(relpath
, GOT_ERR_FILE_STATUS
);
7982 if (asprintf(&ondisk_path
, "%s/%s", a
->worktree
->root_path
, relpath
)
7984 return got_error_from_errno("asprintf");
7986 err
= got_object_id_str(&id_str
,
7987 commit_id
? commit_id
: a
->worktree
->base_commit_id
);
7990 if (asprintf(&label_orig
, "%s: commit %s", GOT_MERGE_LABEL_BASE
,
7992 err
= got_error_from_errno("asprintf");
7996 switch (staged_status
) {
7997 case GOT_STATUS_MODIFY
:
7998 err
= got_object_open_as_blob(&blob_base
, a
->repo
,
8003 case GOT_STATUS_ADD
:
8005 if (staged_status
== GOT_STATUS_ADD
) {
8006 int choice
= GOT_PATCH_CHOICE_NONE
;
8007 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8008 staged_status
, ie
->path
, NULL
, 1, 1);
8011 if (choice
!= GOT_PATCH_CHOICE_YES
)
8014 err
= unstage_hunks(staged_blob_id
,
8015 blob_base
, blob_id
, ie
, ondisk_path
,
8016 label_orig
, a
->worktree
, a
->repo
,
8017 a
->patch_cb
, a
->patch_arg
,
8018 a
->progress_cb
, a
->progress_arg
);
8019 break; /* Done with this file. */
8022 err
= got_object_open_as_blob(&blob_staged
, a
->repo
,
8023 staged_blob_id
, 8192);
8026 switch (got_fileindex_entry_staged_filetype_get(ie
)) {
8027 case GOT_FILEIDX_MODE_BAD_SYMLINK
:
8028 case GOT_FILEIDX_MODE_REGULAR_FILE
:
8029 err
= merge_blob(&local_changes_subsumed
, a
->worktree
,
8030 blob_base
, ondisk_path
, relpath
,
8031 got_fileindex_perms_to_st(ie
), label_orig
,
8032 blob_staged
, commit_id
? commit_id
:
8033 a
->worktree
->base_commit_id
, a
->repo
,
8034 a
->progress_cb
, a
->progress_arg
);
8036 case GOT_FILEIDX_MODE_SYMLINK
:
8037 if (S_ISLNK(got_fileindex_perms_to_st(ie
))) {
8038 char *staged_target
;
8039 err
= got_object_blob_read_to_str(
8040 &staged_target
, blob_staged
);
8043 err
= merge_symlink(a
->worktree
, blob_base
,
8044 ondisk_path
, relpath
, label_orig
,
8045 staged_target
, commit_id
? commit_id
:
8046 a
->worktree
->base_commit_id
,
8047 a
->repo
, a
->progress_cb
, a
->progress_arg
);
8048 free(staged_target
);
8050 err
= merge_blob(&local_changes_subsumed
,
8051 a
->worktree
, blob_base
, ondisk_path
,
8052 relpath
, got_fileindex_perms_to_st(ie
),
8053 label_orig
, blob_staged
,
8054 commit_id
? commit_id
:
8055 a
->worktree
->base_commit_id
, a
->repo
,
8056 a
->progress_cb
, a
->progress_arg
);
8060 err
= got_error_path(relpath
, GOT_ERR_BAD_FILETYPE
);
8064 got_fileindex_entry_stage_set(ie
,
8065 GOT_FILEIDX_STAGE_NONE
);
8066 got_fileindex_entry_staged_filetype_set(ie
, 0);
8069 case GOT_STATUS_DELETE
:
8071 int choice
= GOT_PATCH_CHOICE_NONE
;
8072 err
= (*a
->patch_cb
)(&choice
, a
->patch_arg
,
8073 staged_status
, ie
->path
, NULL
, 1, 1);
8076 if (choice
== GOT_PATCH_CHOICE_NO
)
8078 if (choice
!= GOT_PATCH_CHOICE_YES
) {
8079 err
= got_error(GOT_ERR_PATCH_CHOICE
);
8083 got_fileindex_entry_stage_set(ie
, GOT_FILEIDX_STAGE_NONE
);
8084 got_fileindex_entry_staged_filetype_set(ie
, 0);
8085 err
= get_file_status(&status
, &sb
, ie
, ondisk_path
,
8086 dirfd
, de_name
, a
->repo
);
8089 err
= (*a
->progress_cb
)(a
->progress_arg
, status
, relpath
);
8095 got_object_blob_close(blob_base
);
8097 got_object_blob_close(blob_staged
);
8103 const struct got_error
*
8104 got_worktree_unstage(struct got_worktree
*worktree
,
8105 struct got_pathlist_head
*paths
,
8106 got_worktree_checkout_cb progress_cb
, void *progress_arg
,
8107 got_worktree_patch_cb patch_cb
, void *patch_arg
,
8108 struct got_repository
*repo
)
8110 const struct got_error
*err
= NULL
, *sync_err
, *unlockerr
;
8111 struct got_pathlist_entry
*pe
;
8112 struct got_fileindex
*fileindex
= NULL
;
8113 char *fileindex_path
= NULL
;
8114 struct unstage_path_arg upa
;
8116 err
= lock_worktree(worktree
, LOCK_EX
);
8120 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8124 upa
.worktree
= worktree
;
8125 upa
.fileindex
= fileindex
;
8127 upa
.progress_cb
= progress_cb
;
8128 upa
.progress_arg
= progress_arg
;
8129 upa
.patch_cb
= patch_cb
;
8130 upa
.patch_arg
= patch_arg
;
8131 TAILQ_FOREACH(pe
, paths
, entry
) {
8132 err
= worktree_status(worktree
, pe
->path
, fileindex
, repo
,
8133 unstage_path
, &upa
, NULL
, NULL
, 0, 0);
8138 sync_err
= sync_fileindex(fileindex
, fileindex_path
);
8139 if (sync_err
&& err
== NULL
)
8142 free(fileindex_path
);
8144 got_fileindex_free(fileindex
);
8145 unlockerr
= lock_worktree(worktree
, LOCK_SH
);
8146 if (unlockerr
&& err
== NULL
)
8151 struct report_file_info_arg
{
8152 struct got_worktree
*worktree
;
8153 got_worktree_path_info_cb info_cb
;
8155 struct got_pathlist_head
*paths
;
8156 got_cancel_cb cancel_cb
;
8160 static const struct got_error
*
8161 report_file_info(void *arg
, struct got_fileindex_entry
*ie
)
8163 struct report_file_info_arg
*a
= arg
;
8164 struct got_pathlist_entry
*pe
;
8165 struct got_object_id blob_id
, staged_blob_id
, commit_id
;
8166 struct got_object_id
*blob_idp
= NULL
, *staged_blob_idp
= NULL
;
8167 struct got_object_id
*commit_idp
= NULL
;
8170 if (a
->cancel_cb
&& a
->cancel_cb(a
->cancel_arg
))
8171 return got_error(GOT_ERR_CANCELLED
);
8173 TAILQ_FOREACH(pe
, a
->paths
, entry
) {
8174 if (pe
->path_len
== 0 || strcmp(pe
->path
, ie
->path
) == 0 ||
8175 got_path_is_child(ie
->path
, pe
->path
, pe
->path_len
))
8178 if (pe
== NULL
) /* not found */
8181 if (got_fileindex_entry_has_blob(ie
)) {
8182 memcpy(blob_id
.sha1
, ie
->blob_sha1
, SHA1_DIGEST_LENGTH
);
8183 blob_idp
= &blob_id
;
8185 stage
= got_fileindex_entry_stage_get(ie
);
8186 if (stage
== GOT_FILEIDX_STAGE_MODIFY
||
8187 stage
== GOT_FILEIDX_STAGE_ADD
) {
8188 memcpy(staged_blob_id
.sha1
, ie
->staged_blob_sha1
,
8189 SHA1_DIGEST_LENGTH
);
8190 staged_blob_idp
= &staged_blob_id
;
8193 if (got_fileindex_entry_has_commit(ie
)) {
8194 memcpy(commit_id
.sha1
, ie
->commit_sha1
, SHA1_DIGEST_LENGTH
);
8195 commit_idp
= &commit_id
;
8198 return a
->info_cb(a
->info_arg
, ie
->path
, got_fileindex_perms_to_st(ie
),
8199 (time_t)ie
->mtime_sec
, blob_idp
, staged_blob_idp
, commit_idp
);
8202 const struct got_error
*
8203 got_worktree_path_info(struct got_worktree
*worktree
,
8204 struct got_pathlist_head
*paths
,
8205 got_worktree_path_info_cb info_cb
, void *info_arg
,
8206 got_cancel_cb cancel_cb
, void *cancel_arg
)
8209 const struct got_error
*err
= NULL
, *unlockerr
;
8210 struct got_fileindex
*fileindex
= NULL
;
8211 char *fileindex_path
= NULL
;
8212 struct report_file_info_arg arg
;
8214 err
= lock_worktree(worktree
, LOCK_SH
);
8218 err
= open_fileindex(&fileindex
, &fileindex_path
, worktree
);
8222 arg
.worktree
= worktree
;
8223 arg
.info_cb
= info_cb
;
8224 arg
.info_arg
= info_arg
;
8226 arg
.cancel_cb
= cancel_cb
;
8227 arg
.cancel_arg
= cancel_arg
;
8228 err
= got_fileindex_for_each_entry_safe(fileindex
, report_file_info
,
8231 free(fileindex_path
);
8233 got_fileindex_free(fileindex
);
8234 unlockerr
= lock_worktree(worktree
, LOCK_UN
);
8235 if (unlockerr
&& err
== NULL
)