Java (JGIT) Files.delete() 删除文件失败,但 file.delete() 成功

Mal*_*alt 7 java filesystems jgit

我正在使用 jgit (version 4.8.0.201706111038-r) 将git repo 克隆到临时目录中,并添加关闭挂钩以在终止后删除临时目录。但是,关闭挂钩无法从.git子目录中删除某些文件(尽管关闭了 jgit 要求的 Git 对象)。

有趣的是,只有当我使用 Path API ( Files.delete(<PATH>)) 时删除才会失败,但如果我使用旧的file.delete().

这是一个最小的独立示例,其唯一依赖项是 jgit 4.8.0.201706111038-r:

public static void main(String... args) throws Exception {
    String gitRepo = "https://github.com/netgloo/spring-boot-samples.git";
    Path localDir = Files.createTempDirectory(null);

    // Clone repo
    Git git = Git.cloneRepository().setURI(gitRepo).setBranch("master").setDirectory(localDir.toFile()).call();

    // Print some stuff to make sure that the git repo actually works
    for (RevCommit c : git.log().call()) {
        System.out.println(c);
    }

    git.getRepository().close(); // Close all the things!
    git.close(); // Close all the things!

    // Delete
    Files.walkFileTree(localDir, new SimpleFileVisitor<Path>() {
        void safeDelete(Path p) {
            try {
                Files.delete(p);
            } catch (Exception e) {
                try {
                    Files.delete(p);
                } catch (Exception e2) {
                    System.err.println("Failed to delete " + p + " due to " + e.getClass().getSimpleName() + " using Files.detlete().\nTrying toFile().delete(): " + p.toFile().delete());
                }
            }
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            safeDelete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
            safeDelete(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

输出:

...
Failed to delete C:\Users\malt\AppData\Local\Temp\7908805853015958247\.git\objects\pack\pack-9cc3ec0769e34546bb7683f4e22ef67b3c800444.idx due to AccessDeniedException using Files.detlete().
Trying toFile().delete(): true
Failed to delete C:\Users\malt\AppData\Local\Temp\7908805853015958247\.git\objects\pack\pack-9cc3ec0769e34546bb7683f4e22ef67b3c800444.pack due to AccessDeniedException using Files.detlete().
Trying toFile().delete(): true
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么会发生这种情况?有没有办法让 JGIT 正确关闭这些文件以便Files.delete()工作?

Rüd*_*ann 4

当从 a 获取时CloneCommandGit::close单独应该足以释放 JGit 为给定存储库持有的所有文件句柄。在这种情况下它只是委托给Repository::close

我认为您所看到的Files::delete()和之间的区别已解释如下:File::delete()

Files#delete(Path) 和 File#delete() 之间的区别

可能不相关,但我认为仍然值得一提的是最近引入的自动垃圾回收后台线程的问题。它还可能会阻止存储库被成功删除。请参阅此邮件列表主题:

https://dev.eclipse.org/mhonarc/lists/jgit-dev/msg03370.html

为了解决后一个问题,我在存储库的配置中禁用了 auto-gc,如下所示:

StoredConfig config = repository.getConfig();
config.setBoolean(CONFIG_GC_SECTION, null, CONFIG_KEY_AUTODETACH, false);
config.setInt(CONFIG_GC_SECTION, null, CONFIG_KEY_AUTOPACKLIMIT, -1);
config.setInt(CONFIG_GC_SECTION, null, CONFIG_KEY_AUTO, -1);
config.save();
Run Code Online (Sandbox Code Playgroud)

常量是从静态导入的ConfigConstants

这符合你的问题吗?