Don't autodelete directory after deleting the last file in it

Executing `git rm` on the last file in a directory makes Git remove not
only this file, but its parent directory as well.

Although it is Git's behavior, it is not convenient, and it is also
unexpected since `git rm` is not explicitly triggered by user who
deletes a file from the Project View.

GitVFSListener is triggered _after_ actual deletion of the file,
so the only thing Git should do is to delete the file from the index:
git rm --cached. This does the same as `git rm`, but prevents Git from
removing the directory (since files are not touched on disk, only
in the index).

Fixes IDEA-75590
This commit is contained in:
Kirill Likhodedov
2017-02-21 22:18:09 +00:00
parent 82dd4120c0
commit dcac402507
2 changed files with 61 additions and 1 deletions
@@ -180,7 +180,7 @@ public class GitVFSListener extends VcsVFSListener {
HashSet<File> filesToRefresh = new HashSet<>();
public void execute(@NotNull VirtualFile root, @NotNull List<FilePath> files) throws VcsException {
GitFileUtils.delete(myProject, root, files, "--ignore-unmatch");
GitFileUtils.delete(myProject, root, files, "--ignore-unmatch", "--cached");
if (!myProject.isDisposed()) {
VcsFileUtil.markFilesDirty(myProject, files);
}
@@ -0,0 +1,60 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package git4idea.checkin
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.vcs.FileStatus
import com.intellij.openapi.vcs.VcsVFSListener
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.testFramework.runInEdtAndWait
import com.intellij.vcsUtil.VcsUtil.getFilePath
import git4idea.test.GitSingleRepoTest
import git4idea.test.git
import java.io.File
class GitRmTest : GitSingleRepoTest() {
override fun getDebugLogCategories() = super.getDebugLogCategories().plus("#" + VcsVFSListener::class.java.name)
// IDEA-75590
fun `test empty directories are not removed on git rm`() {
val nestedDir = File(myProjectPath, "lib/subdir")
assertTrue("Directory $nestedDir wasn't created", nestedDir.mkdirs())
val file = File(nestedDir, "f.txt")
assertTrue("File $file wasn't created", file.createNewFile())
git("add .")
git("commit -m 'added file'")
val vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)
assertNotNull("VirtualFile not found for file $file", vf)
vf!!
runInEdtAndWait {
CommandProcessor.getInstance().executeCommand(myProject, {
runWriteAction {
vf.delete(this)
}
}, null, null)
}
updateChangeListManager()
assertFalse("File wasn't deleted", file.exists())
assertTrue("Directory shouldn't have been deleted", nestedDir.exists())
val change = changeListManager.getChange(getFilePath(vf))
assertNotNull(change)
assertEquals(FileStatus.DELETED, change!!.fileStatus)
}
}