commit af0328d61e5353fc867c1731a5dcb969f805aaba from: Stefan Sperling via: Thomas Adam date: Mon Oct 07 19:25:20 2024 UTC fix a crash when unstaging a file which has been removed from disk reported by Johannes Thyssen Tishman commit - ad4a7050395834da81cd5e4715df04ebd5f06b6f commit + af0328d61e5353fc867c1731a5dcb969f805aaba blob - 66eeb4616f118b7eb6f6efe9724d0bc49cb3f838 blob + 5af05544443feda9e6394c57a8d8dbe7db88e27b --- lib/worktree.c +++ lib/worktree.c @@ -3685,7 +3685,7 @@ status_old(void *arg, struct got_fileindex_entry *ie, { const struct got_error *err; struct diff_dir_cb_arg *a = arg; - struct got_object_id blob_id, commit_id; + struct got_object_id blob_id, commit_id, staged_blob_id; unsigned char status; if (a->cancel_cb) { @@ -3699,12 +3699,13 @@ status_old(void *arg, struct got_fileindex_entry *ie, got_fileindex_entry_get_blob_id(&blob_id, ie); got_fileindex_entry_get_commit_id(&commit_id, ie); + got_fileindex_entry_get_staged_blob_id(&staged_blob_id, ie); if (got_fileindex_entry_has_file_on_disk(ie)) status = GOT_STATUS_MISSING; else status = GOT_STATUS_DELETE; return (*a->status_cb)(a->status_arg, status, get_staged_status(ie), - ie->path, &blob_id, NULL, &commit_id, -1, NULL); + ie->path, &blob_id, &staged_blob_id, &commit_id, -1, NULL); } static void @@ -9804,6 +9805,12 @@ unstage_path(void *arg, unsigned char status, break; /* fall through */ case GOT_STATUS_ADD: + if (status == GOT_STATUS_MISSING) { + /* Cannot merge changes into missing files. */ + err = (*a->progress_cb)(a->progress_arg, status, + relpath); + goto done; + } if (a->patch_cb) { if (staged_status == GOT_STATUS_ADD) { int choice = GOT_PATCH_CHOICE_NONE; blob - 5f9b7bb3b3a19f838ac5afc1984ab0cc09919ed9 blob + 797487d03ec67c7d78cb9ee815c911e4a58cbfe6 --- regress/cmdline/unstage.sh +++ regress/cmdline/unstage.sh @@ -179,7 +179,76 @@ test_unstage_nonexistent() { ret=$? if [ $ret -ne 0 ]; then diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 fi + + cat > $testroot/stdout.expected < $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + # removing a staged file from disk and then unstaging + # all changes in the work tree would trigger a segfault + rm $testroot/wt/alpha + + cat > $testroot/stdout.expected < $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + (cd $testroot/wt && got unstage > $testroot/stdout) + ret=$? + if [ $ret -ne 0 ]; then + echo "got unstage command failed unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + cat > $testroot/stdout.expected < $testroot/stdout.expected < $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" }