commit f6764181d7e0fc68673b90cbc93d6064509d0bd7 from: Stefan Sperling date: Fri Sep 24 21:52:59 2021 UTC fix 'got update' of an added + obstructed file When 'got update' tried to add a new file to the work tree and this file was obstructed by, say, a directory on disk, the update failed: $ got update ? new got: new: Is a directory $ And the work tree was not updated. With this commit this situation is properly detected as an obstruction and the update succeeds: $ got update ~ new Updated to refs/heads/master: c1f85b4938dc4c668a88f13df2b98a520fc077cc File paths obstructed by a non-regular file: 1 $ Extend a corresponding test case to cover this issue. ok tracey commit - f365d76274ee1ae2b57225686a0733176fc4bfb2 commit + f6764181d7e0fc68673b90cbc93d6064509d0bd7 blob - f5bc677438d23ddca778382674edef04e09cb939 blob + 8699471c6069c7d4bc2a233ca24d70202cb6d22b --- lib/worktree.c +++ lib/worktree.c @@ -1942,8 +1942,20 @@ update_blob(struct got_worktree *worktree, if (status == GOT_STATUS_MISSING || status == GOT_STATUS_DELETE) sb.st_mode = got_fileindex_perms_to_st(ie); } else { - sb.st_mode = GOT_DEFAULT_FILE_MODE; - status = GOT_STATUS_UNVERSIONED; + if (stat(ondisk_path, &sb) == -1) { + if (errno != ENOENT) { + err = got_error_from_errno2("stat", + ondisk_path); + goto done; + } + sb.st_mode = GOT_DEFAULT_FILE_MODE; + status = GOT_STATUS_UNVERSIONED; + } else { + if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)) + status = GOT_STATUS_UNVERSIONED; + else + status = GOT_STATUS_OBSTRUCTED; + } } if (status == GOT_STATUS_OBSTRUCTED) { blob - cae602420f097ed69b049e9fffb3fc46510d2de5 blob + 946422e07ecfbb970b7b9f9264e7ee67e4b62d55 --- regress/cmdline/update.sh +++ regress/cmdline/update.sh @@ -2588,6 +2588,8 @@ test_update_file_skipped_due_to_obstruction() { blob_id0=`get_blob_id $testroot/repo "" beta` echo "changed beta" > $testroot/repo/beta + echo "new file" > $testroot/repo/new + (cd $testroot/repo && git add new) git_commit $testroot/repo -m "changed beta" local commit_id1=`git_show_head $testroot/repo` blob_id1=`get_blob_id $testroot/repo "" beta` @@ -2617,14 +2619,22 @@ test_update_file_skipped_due_to_obstruction() { rm $testroot/wt/beta mkdir -p $testroot/wt/beta/psi + mkdir -p $testroot/wt/new - # update to the latest commit; this skips beta + # update to the latest commit; this skips beta and the new file (cd $testroot/wt && got update > $testroot/stdout) + ret="$?" + if [ "$ret" != "0" ]; then + echo "update failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi echo "~ beta" > $testroot/stdout.expected + echo "~ new" >> $testroot/stdout.expected echo "Updated to refs/heads/master: $commit_id1" \ >> $testroot/stdout.expected - echo "File paths obstructed by a non-regular file: 1" \ + echo "File paths obstructed by a non-regular file: 2" \ >> $testroot/stdout.expected cmp -s $testroot/stdout.expected $testroot/stdout ret="$?" @@ -2656,8 +2666,11 @@ test_update_file_skipped_due_to_obstruction() { # updating to the latest commit should now update beta (cd $testroot/wt && got update > $testroot/stdout) echo "! beta" > $testroot/stdout.expected + echo "~ new" >> $testroot/stdout.expected echo "Updated to refs/heads/master: $commit_id1" \ >> $testroot/stdout.expected + echo "File paths obstructed by a non-regular file: 1" \ + >> $testroot/stdout.expected cmp -s $testroot/stdout.expected $testroot/stdout ret="$?" if [ "$ret" != "0" ]; then