commit c90c8ce30c933a907f591ebe599ed6b7506f8217 from: Stefan Sperling date: Thu Jul 23 14:22:35 2020 UTC preserve unversioned files when merging added symlinks commit - 65b05cec5f251400ee165670853253a3629f4d28 commit + c90c8ce30c933a907f591ebe599ed6b7506f8217 blob - 2622e5a3f57c01d5c7c55e3ee70f1b92e04329bf blob + fa03c453a41b27d2fc77686b381c798275eb9f9c --- got/got.1 +++ got/got.1 @@ -1262,6 +1262,7 @@ Show the status of each affected file, using the follo .It d Ta file's deletion was obstructed by local modifications .It A Ta new file was added .It \(a~ Ta changes destined for a non-regular file were not merged +.It ? Ta changes destined for an unversioned file were not merged .El .Pp The merged changes will appear as local changes in the work tree, which @@ -1305,6 +1306,7 @@ Show the status of each affected file, using the follo .It d Ta file's deletion was obstructed by local modifications .It A Ta new file was added .It \(a~ Ta changes destined for a non-regular file were not merged +.It ? Ta changes destined for an unversioned file were not merged .El .Pp The reverse-merged changes will appear as local changes in the work tree, @@ -1380,6 +1382,7 @@ using the following status codes: .It d Ta file's deletion was obstructed by local modifications .It A Ta new file was added .It \(a~ Ta changes destined for a non-regular file were not merged +.It ? Ta changes destined for an unversioned file were not merged .El .Pp If merge conflicts occur the rebase operation is interrupted and may @@ -1509,6 +1512,7 @@ using the following status codes: .It d Ta file's deletion was obstructed by local modifications .It A Ta new file was added .It \(a~ Ta changes destined for a non-regular file were not merged +.It ? Ta changes destined for an unversioned file were not merged .El .Pp If merge conflicts occur the histedit operation is interrupted and may blob - d6fabd671ac83c50de598b8ca3a83411a51d303f blob + 437116fcd6048a862de574f7a76e6a3ae5c11309 --- lib/worktree.c +++ lib/worktree.c @@ -1204,7 +1204,7 @@ static const struct got_error * install_symlink(int *is_bad_symlink, struct got_worktree *worktree, const char *ondisk_path, const char *path, struct got_blob_object *blob, int restoring_missing_file, int reverting_versioned_file, - struct got_repository *repo, + int path_is_unversioned, struct got_repository *repo, got_worktree_checkout_cb progress_cb, void *progress_arg) { const struct got_error *err = NULL; @@ -1307,6 +1307,11 @@ install_symlink(int *is_bad_symlink, struct got_worktr if (symlink(target_path, ondisk_path) == -1) { if (errno == EEXIST) { + if (path_is_unversioned) { + err = (*progress_cb)(progress_arg, + GOT_STATUS_UNVERSIONED, path); + goto done; + } err = replace_existing_symlink(ondisk_path, target_path, target_len); if (err) @@ -1790,8 +1795,10 @@ update_blob(struct got_worktree *worktree, goto done; if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE) sb.st_mode = got_fileindex_perms_to_st(ie); - } else + } else { sb.st_mode = GOT_DEFAULT_FILE_MODE; + status = GOT_STATUS_UNVERSIONED; + } if (status == GOT_STATUS_OBSTRUCTED) { err = (*progress_cb)(progress_arg, status, path); @@ -1892,7 +1899,8 @@ update_blob(struct got_worktree *worktree, if (S_ISLNK(te->mode)) { err = install_symlink(&is_bad_symlink, worktree, ondisk_path, path, blob, - status == GOT_STATUS_MISSING, 0, repo, + status == GOT_STATUS_MISSING, 0, + status == GOT_STATUS_UNVERSIONED, repo, progress_cb, progress_arg); } else { err = install_blob(worktree, ondisk_path, path, @@ -2769,7 +2777,7 @@ merge_file_cb(void *arg, struct got_blob_object *blob1 if (S_ISLNK(mode2)) { err = install_symlink(&is_bad_symlink, a->worktree, ondisk_path, path2, blob2, 0, - 0, repo, a->progress_cb, a->progress_arg); + 0, 1, repo, a->progress_cb, a->progress_arg); } else { err = install_blob(a->worktree, ondisk_path, path2, mode2, sb.st_mode, blob2, 0, 0, 0, repo, @@ -4295,7 +4303,7 @@ revert_file(void *arg, unsigned char status, unsigned if (te && S_ISLNK(te->mode)) { err = install_symlink(&is_bad_symlink, a->worktree, ondisk_path, ie->path, - blob, 0, 1, a->repo, + blob, 0, 1, 0, a->repo, a->progress_cb, a->progress_arg); } else { err = install_blob(a->worktree, ondisk_path, @@ -5017,7 +5025,7 @@ reinstall_symlink_after_commit(int *is_bad_symlink, st } err = install_symlink(is_bad_symlink, worktree, ct->ondisk_path, - ct->path, blob, 0, 0, repo, NULL, NULL); + ct->path, blob, 0, 0, 0, repo, NULL, NULL); done: if (blob) got_object_blob_close(blob); blob - 0f286697ad1b06ad111fc5219182bebfe88e1ccc blob + f9b695d8cdef6863a73038a1bdbbe643d583bb80 --- regress/cmdline/cherrypick.sh +++ regress/cmdline/cherrypick.sh @@ -517,8 +517,7 @@ function test_cherrypick_symlink_conflicts { echo -n > $testroot/stdout.expected echo "C alpha.link" >> $testroot/stdout.expected echo "C epsilon/beta.link" >> $testroot/stdout.expected - # TODO: This is wrong! Unversioned file boo.link should be preserved. - echo "U boo.link" >> $testroot/stdout.expected + echo "? boo.link" >> $testroot/stdout.expected echo "C epsilon.link" >> $testroot/stdout.expected echo "C dotgotbar.link" >> $testroot/stdout.expected echo "U dotgotfoo.link" >> $testroot/stdout.expected @@ -568,14 +567,13 @@ EOF return 1 fi - # TODO: This is wrong! Unversioned file boo.link should be preserved. - if [ ! -h $testroot/wt/boo.link ]; then - echo "boo.link is not a symlink" + if [ -h $testroot/wt/boo.link ]; then + echo "boo.link is a symlink" test_done "$testroot" "1" return 1 fi - echo "beta" > $testroot/content.expected + echo "this is unversioned file boo" > $testroot/content.expected cp $testroot/wt/boo.link $testroot/content cmp -s $testroot/content.expected $testroot/content ret="$?"