Java (JGIT) Files.delete() 删除文件失败,但 file.delete() 成功
Java (JGIT) Files.delete() fails to delete a file, but file.delete() succeeds
我正在使用 jgit(版本 4.8.0.201706111038-r
)将 git 存储库克隆到临时目录中,并添加一个关闭钩子以在终止后删除临时目录。但是,关闭挂钩无法从 .git
子目录中删除某些文件(尽管关闭了 Git 对象,如 jgit 所要求)。
有趣的是,只有当我使用路径 API (Files.delete(<PATH>)
) 时删除才会失败,但如果我使用旧的 file.delete()
.[= 删除则不会20=]
这是一个最小的独立示例,其唯一依赖项是 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;
}
});
}
输出:
...
Failed to delete C:\Users\malt\AppData\Local\Temp08805853015958247\.git\objects\pack\pack-9cc3ec0769e34546bb7683f4e22ef67b3c800444.idx due to AccessDeniedException using Files.detlete().
Trying toFile().delete(): true
Failed to delete C:\Users\malt\AppData\Local\Temp08805853015958247\.git\objects\pack\pack-9cc3ec0769e34546bb7683f4e22ef67b3c800444.pack due to AccessDeniedException using Files.detlete().
Trying toFile().delete(): true
谁能解释为什么会这样?有没有办法让 JGIT 正确关闭这些文件,以便 Files.delete()
工作?
当从 CloneCommand
获得时,仅 Git::close
就足以释放 JGit 为给定存储库持有的所有文件句柄。在这种情况下,它只是委托给 Repository::close
。
我认为您看到的 Files::delete()
和 File::delete()
之间的区别在这里解释:
Difference between Files#delete(Path) and File#delete()
可能不相关,但我认为仍然值得一提的是最近引入的自动 gc 后台线程的问题。它还可能会阻止存储库被成功删除。查看此邮件列表线程:
https://dev.eclipse.org/mhonarc/lists/jgit-dev/msg03370.html
为了解决后一个问题,我在存储库的配置中禁用了自动 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();
常量是从 ConfigConstants
静态导入的。
这符合您的问题吗?
如果有人仍然面临同样的问题,对我有用的是强制调用 gc 释放文件锁定
gitReference.gc().call()
这里是我的全关闭方法:
public void close() {
if (gitReference != null) {
try {
gitReference.close();
gitReference.gc().call();
} catch (GitAPIException e) {
throw new RuntimeException(e);
}
gitReference = null;
}
}
祝你好运
贾拉尔
我正在使用 jgit(版本 4.8.0.201706111038-r
)将 git 存储库克隆到临时目录中,并添加一个关闭钩子以在终止后删除临时目录。但是,关闭挂钩无法从 .git
子目录中删除某些文件(尽管关闭了 Git 对象,如 jgit 所要求)。
有趣的是,只有当我使用路径 API (Files.delete(<PATH>)
) 时删除才会失败,但如果我使用旧的 file.delete()
.[= 删除则不会20=]
这是一个最小的独立示例,其唯一依赖项是 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;
}
});
}
输出:
...
Failed to delete C:\Users\malt\AppData\Local\Temp08805853015958247\.git\objects\pack\pack-9cc3ec0769e34546bb7683f4e22ef67b3c800444.idx due to AccessDeniedException using Files.detlete().
Trying toFile().delete(): true
Failed to delete C:\Users\malt\AppData\Local\Temp08805853015958247\.git\objects\pack\pack-9cc3ec0769e34546bb7683f4e22ef67b3c800444.pack due to AccessDeniedException using Files.detlete().
Trying toFile().delete(): true
谁能解释为什么会这样?有没有办法让 JGIT 正确关闭这些文件,以便 Files.delete()
工作?
当从 CloneCommand
获得时,仅 Git::close
就足以释放 JGit 为给定存储库持有的所有文件句柄。在这种情况下,它只是委托给 Repository::close
。
我认为您看到的 Files::delete()
和 File::delete()
之间的区别在这里解释:
Difference between Files#delete(Path) and File#delete()
可能不相关,但我认为仍然值得一提的是最近引入的自动 gc 后台线程的问题。它还可能会阻止存储库被成功删除。查看此邮件列表线程:
https://dev.eclipse.org/mhonarc/lists/jgit-dev/msg03370.html
为了解决后一个问题,我在存储库的配置中禁用了自动 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();
常量是从 ConfigConstants
静态导入的。
这符合您的问题吗?
如果有人仍然面临同样的问题,对我有用的是强制调用 gc 释放文件锁定
gitReference.gc().call()
这里是我的全关闭方法:
public void close() {
if (gitReference != null) {
try {
gitReference.close();
gitReference.gc().call();
} catch (GitAPIException e) {
throw new RuntimeException(e);
}
gitReference = null;
}
}
祝你好运
贾拉尔