commit e6f4ba3109814ba43d3a9e9c9c9dc55c40149dbc from: Stefan Sperling via: Thomas Adam date: Fri Sep 24 22:01:09 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 - df3d7c3ef8853d0fa9182dd3f3023a4d5e222ce0 commit + e6f4ba3109814ba43d3a9e9c9c9dc55c40149dbc blob - 5e663edd2cd3e7e02e9b9ee302c595b926e20493 blob + 11f8c658d9a14769d0a5e48c2ef17c3d3ba107dc --- lib/worktree.c +++ lib/worktree.c @@ -1940,8 +1940,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 - 495406fdbcdfc1bcce4fe3a964b422ebaa832cff blob + 0437598f42eff21eee8777c77ae1f578a040eaf4 --- 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