javagitjgit

Cannot Delete Repository Folder created by JGIT


I am unable to delete folder containing a cloned repository created using jgit. I have tried all kinds of utility delete methods but none works. The error thrown while using FileUtils.deleteDirectory(file) is as follows

java.nio.file.AccessDeniedException: \repositories\Test\Test\.git\objects\pack\pack-21cdd19e90e9e6bd2e8d295ea04201969594fe96.idx

Tried the following,

  1. I have seen a range of other answers, for example [1] and [2]. They are all concerned with cases wherein they created a repository with jgit first and then deleted it immediately after that. In my current scenario I want to check if a repository is already cloned at given path and delete if present. After doing this task, I want to clone a repository using jgit on the same path.
  2. I tried cases wherein I created the repository with jgit, shut down my server. Started it again and then simply called a function to delete the folder created earlier. This again failed with the same error.
  3. I also completely removed jgit from my initial code and from pom since it might be getting into loaded into classpath. I still get the same error when trying to delete. Tried again after restarting just to check, the issue still persists.
  4. However, when I run the same deletion code from another Java program, it succeeds.

[1] How to remove local repository by Java code that was cloned by JGit java library?
[2] How do I release file system locks after cloning repo via JGit

Here is the original code snippet for reference,

    File file = null;
    try {
        file = new File(localRepositoryPath);

        // Delete directory if already present
        String localRepositoryParentPath = GitUtils.getRepositoryPath(projectName, null);
        File parentDirectory = new File(localRepositoryParentPath);
        FileUtils.deleteDirectory(parentDirectory);

        // Create directory where repository will be cloned
        if(!file.mkdirs()) {
            throw new GitServiceException(
                GitUtils.getCloneFailureMessage("Unable to create directory",
                    projectName,
                    repoName));
        }
    } catch (NullPointerException | SecurityException | IOException e) {
        logger.info(Arrays.toString(e.getStackTrace()));
        logger.error("IO Error cloning repository {} and project {}. Stacktrace {} ",
            repoName,
            projectName,
            e.getStackTrace());
        throw new GitServiceException(
            GitUtils.getCloneFailureMessage("IO Error while cloning",
                projectName,
                repoName));
    }

    // Clone the git repository
    try (Git git = Git.cloneRepository()
            .setURI(repoUrl)
            .setDirectory(file)
            .setBranchesToClone(List.of("refs/heads/" + branchToClone))
            .setBranch("refs/heads/" + branchToClone)
            .setCredentialsProvider(new UsernamePasswordCredentialsProvider( "token", this.credentials.getGitToken()))
            .call();
    ) {
        logger.info("Successfully cloned branch {} on path {} for repository {} and project {}",
            branchToClone,
            localRepositoryPath,
            repoName,
            projectName);
    } catch (Exception exception) {
        logger.error("Error cloning repository {} and project {}. Stacktrace {} ",
            repoName,
            projectName,
            exception.getStackTrace());
        throw new GitServiceException(
            GitUtils.getCloneFailureMessage("Unable to clone repository locally",
                projectName,
                repoName));
    }

Edit

Adding error stacktrace

org.apache.commons.io.IOExceptionList: 1 exceptions: [java.io.IOException: Unable to delete file: \repositories\Test\Test\.git]
at org.apache.commons.io.FileUtils.cleanDirectory(FileUtils.java:345)
at org.apache.commons.io.FileUtils.deleteDirectory(FileUtils.java:1206)
at com.adobe.mdloc.controller.TestController.post(TestController.java:57)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.adobe.asr.filter.AsrRequestResponseFilter.doFilterInternal(AsrRequestResponseFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.adobe.asr.logging.http.servlet.AsrLoggingFilter.doFilter(AsrLoggingFilter.java:71)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.adobe.asr.filter.AsrRequestIdFilter.doFilterInternal(AsrRequestIdFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.adobe.asr.exception.AsrExceptionFilter.doFilterInternal(AsrExceptionFilter.java:82)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:834)

Caused by: java.io.IOException: Unable to delete file: \repositories\Test\Test\.git
at org.apache.commons.io.FileUtils.forceDelete(FileUtils.java:1425)
at org.apache.commons.io.FileUtils.cleanDirectory(FileUtils.java:338)
... 71 more

Caused by: java.nio.file.AccessDeniedException: \repositories\Test\Test\.git\objects\pack\pack-21cdd19e90e9e6bd2e8d295ea04201969594fe96.idx
at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:89)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108)
at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:274)
at java.base/sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:110)
at java.base/java.nio.file.Files.deleteIfExists(Files.java:1180)
at org.apache.commons.io.file.DeletingPathVisitor.visitFile(DeletingPathVisitor.java:142)
at org.apache.commons.io.file.DeletingPathVisitor.visitFile(DeletingPathVisitor.java:36)
at java.base/java.nio.file.Files.walkFileTree(Files.java:2724)
at java.base/java.nio.file.Files.walkFileTree(Files.java:2796)
at org.apache.commons.io.file.PathUtils.visitFileTree(PathUtils.java:687)
at org.apache.commons.io.file.PathUtils.deleteDirectory(PathUtils.java:328)
at org.apache.commons.io.file.PathUtils.delete(PathUtils.java:303)
at org.apache.commons.io.file.PathUtils.delete(PathUtils.java:280)
at org.apache.commons.io.FileUtils.forceDelete(FileUtils.java:1423)
... 72 more

Solution

  • Apparently the Apache Commons IO function was throwing the error. Recursively traversing all files and deleting them using the java.io delete command worked perfectly fine.

    Here is the code snippet used for reference,

    public static boolean deleteDirectory(File file) {
        File[] children = file.listFiles();
        if (children != null) {
            for (File child : children) {
                deleteDirectory(child);
            }
        }
        return file.delete();
    }