eclipse / buildship

The Eclipse Plug-ins for Gradle project.
530 stars 169 forks source link

Synchronize with workspace loops infinitely if .classpath or .project file is read-only #840

Open eric-milles opened 5 years ago

eric-milles commented 5 years ago

When build.gradle is edited and saved with "Automatic Project Synchronization" preference enabled, if the .project or .classpath file is read-only the synchronization task repeats indefinitely.

image

!ENTRY org.eclipse.buildship.core 4 6 2019-01-13 10:49:40.719
!MESSAGE Synchronize Gradle projects with workspace failed due to an unexpected error.
!STACK 1
Java Model Exception: Core Exception [code 279] File /Gradle/.classpath is read-only.
    at org.eclipse.jdt.internal.core.JavaProject.writeFileEntries(JavaProject.java:3378)
    at org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.writeAndCacheClasspath(JavaModelManager.java:1520)
    at org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.writeAndCacheClasspath(JavaModelManager.java:1532)
    at org.eclipse.jdt.internal.core.SetClasspathOperation.executeOperation(SetClasspathOperation.java:81)
    at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:736)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2322)
    at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:807)
    at org.eclipse.jdt.internal.core.JavaProject.setRawClasspath(JavaProject.java:3574)
    at org.eclipse.jdt.internal.core.JavaProject.setRawClasspath(JavaProject.java:3534)
    at org.eclipse.jdt.internal.core.JavaProject.setRawClasspath(JavaProject.java:3590)
    at org.eclipse.buildship.core.internal.workspace.SourceFolderUpdater.updateSourceFolders(SourceFolderUpdater.java:73)
    at org.eclipse.buildship.core.internal.workspace.SourceFolderUpdater.update(SourceFolderUpdater.java:171)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeJavaProjectInTransaction(SynchronizeGradleBuildOperation.java:198)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.access$200(SynchronizeGradleBuildOperation.java:48)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation$4.run(SynchronizeGradleBuildOperation.java:187)
    at org.eclipse.jdt.internal.core.BatchOperation.executeOperation(BatchOperation.java:41)
    at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:736)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2322)
    at org.eclipse.jdt.core.JavaCore.run(JavaCore.java:5810)
    at org.eclipse.jdt.core.JavaCore.run(JavaCore.java:5767)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeJavaProject(SynchronizeGradleBuildOperation.java:183)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeOpenWorkspaceProject(SynchronizeGradleBuildOperation.java:173)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeWorkspaceProject(SynchronizeGradleBuildOperation.java:138)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeGradleProjectWithWorkspaceProject(SynchronizeGradleBuildOperation.java:128)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.access$000(SynchronizeGradleBuildOperation.java:48)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation$1.run(SynchronizeGradleBuildOperation.java:86)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2317)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeProjectsWithWorkspace(SynchronizeGradleBuildOperation.java:83)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.run(SynchronizeGradleBuildOperation.java:66)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildsOperation.run(SynchronizeGradleBuildsOperation.java:49)
    at org.eclipse.buildship.core.internal.workspace.DefaultGradleBuild.synchronize(DefaultGradleBuild.java:48)
    at org.eclipse.buildship.core.internal.DefaultGradleBuild$SynchronizeOperation.runInToolingApi(DefaultGradleBuild.java:113)
    at org.eclipse.buildship.core.internal.operation.DefaultToolingApiOperationManager$WorkspaceRunnableAdapter.run(DefaultToolingApiOperationManager.java:57)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2322)
    at org.eclipse.buildship.core.internal.operation.DefaultToolingApiOperationManager.run(DefaultToolingApiOperationManager.java:38)
    at org.eclipse.buildship.core.internal.DefaultGradleBuild.synchronize(DefaultGradleBuild.java:64)
    at org.eclipse.buildship.core.internal.workspace.SynchronizationJob.runInToolingApi(SynchronizationJob.java:68)
    at org.eclipse.buildship.core.internal.workspace.SynchronizationJob.runInToolingApi(SynchronizationJob.java:30)
    at org.eclipse.buildship.core.internal.operation.ToolingApiJob$1.runInToolingApi(ToolingApiJob.java:53)
    at org.eclipse.buildship.core.internal.operation.DefaultToolingApiOperationManager$WorkspaceRunnableAdapter.run(DefaultToolingApiOperationManager.java:57)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2322)
    at org.eclipse.buildship.core.internal.operation.DefaultToolingApiOperationManager.run(DefaultToolingApiOperationManager.java:38)
    at org.eclipse.buildship.core.internal.operation.ToolingApiJob.run(ToolingApiJob.java:64)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
Caused by: org.eclipse.core.internal.resources.ResourceException: File /Gradle/.classpath is read-only.
    at org.eclipse.core.internal.resources.Workspace.validateSave(Workspace.java:2610)
    at org.eclipse.core.internal.resources.File.setContents(File.java:334)
    at org.eclipse.jdt.internal.core.JavaProject.setSharedProperty(JavaProject.java:3629)
    at org.eclipse.jdt.internal.core.JavaProject.writeFileEntries(JavaProject.java:3375)
    at org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.writeAndCacheClasspath(JavaModelManager.java:1520)
    at org.eclipse.jdt.internal.core.JavaModelManager$PerProjectInfo.writeAndCacheClasspath(JavaModelManager.java:1532)
    at org.eclipse.jdt.internal.core.SetClasspathOperation.executeOperation(SetClasspathOperation.java:81)
    at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:736)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2322)
    at org.eclipse.jdt.internal.core.JavaModelOperation.runOperation(JavaModelOperation.java:807)
    at org.eclipse.jdt.internal.core.JavaProject.setRawClasspath(JavaProject.java:3574)
    at org.eclipse.jdt.internal.core.JavaProject.setRawClasspath(JavaProject.java:3534)
    at org.eclipse.jdt.internal.core.JavaProject.setRawClasspath(JavaProject.java:3590)
    at org.eclipse.buildship.core.internal.workspace.SourceFolderUpdater.updateSourceFolders(SourceFolderUpdater.java:73)
    at org.eclipse.buildship.core.internal.workspace.SourceFolderUpdater.update(SourceFolderUpdater.java:171)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeJavaProjectInTransaction(SynchronizeGradleBuildOperation.java:198)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.access$200(SynchronizeGradleBuildOperation.java:48)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation$4.run(SynchronizeGradleBuildOperation.java:187)
    at org.eclipse.jdt.internal.core.BatchOperation.executeOperation(BatchOperation.java:41)
    at org.eclipse.jdt.internal.core.JavaModelOperation.run(JavaModelOperation.java:736)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2322)
    at org.eclipse.jdt.core.JavaCore.run(JavaCore.java:5810)
    at org.eclipse.jdt.core.JavaCore.run(JavaCore.java:5767)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeJavaProject(SynchronizeGradleBuildOperation.java:183)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeOpenWorkspaceProject(SynchronizeGradleBuildOperation.java:173)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeWorkspaceProject(SynchronizeGradleBuildOperation.java:138)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeGradleProjectWithWorkspaceProject(SynchronizeGradleBuildOperation.java:128)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.access$000(SynchronizeGradleBuildOperation.java:48)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation$1.run(SynchronizeGradleBuildOperation.java:86)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2317)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.synchronizeProjectsWithWorkspace(SynchronizeGradleBuildOperation.java:83)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildOperation.run(SynchronizeGradleBuildOperation.java:66)
    at org.eclipse.buildship.core.internal.workspace.SynchronizeGradleBuildsOperation.run(SynchronizeGradleBuildsOperation.java:49)
    at org.eclipse.buildship.core.internal.workspace.DefaultGradleBuild.synchronize(DefaultGradleBuild.java:48)
    at org.eclipse.buildship.core.internal.DefaultGradleBuild$SynchronizeOperation.runInToolingApi(DefaultGradleBuild.java:113)
    at org.eclipse.buildship.core.internal.operation.DefaultToolingApiOperationManager$WorkspaceRunnableAdapter.run(DefaultToolingApiOperationManager.java:57)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2322)
    at org.eclipse.buildship.core.internal.operation.DefaultToolingApiOperationManager.run(DefaultToolingApiOperationManager.java:38)
    at org.eclipse.buildship.core.internal.DefaultGradleBuild.synchronize(DefaultGradleBuild.java:64)
    at org.eclipse.buildship.core.internal.workspace.SynchronizationJob.runInToolingApi(SynchronizationJob.java:68)
    at org.eclipse.buildship.core.internal.workspace.SynchronizationJob.runInToolingApi(SynchronizationJob.java:30)
    at org.eclipse.buildship.core.internal.operation.ToolingApiJob$1.runInToolingApi(ToolingApiJob.java:53)
    at org.eclipse.buildship.core.internal.operation.DefaultToolingApiOperationManager$WorkspaceRunnableAdapter.run(DefaultToolingApiOperationManager.java:57)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2295)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2322)
    at org.eclipse.buildship.core.internal.operation.DefaultToolingApiOperationManager.run(DefaultToolingApiOperationManager.java:38)
    at org.eclipse.buildship.core.internal.operation.ToolingApiJob.run(ToolingApiJob.java:64)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
!SUBENTRY 1 org.eclipse.team.core 4 279 2019-01-13 10:49:40.720
!MESSAGE File /Gradle/.classpath is read-only.
donat commented 5 years ago

What's the use-case for setting the .project or .classpath file read-only? IIUC that would mean any Core/JDT UI that stores information in those files would be useless.

eric-milles commented 5 years ago

If a project is stored in TFS source control, files are ready-only unless checked out for edit. And just in general, files can be marked read-only to prevent modification -- strange I have to state that explicitly.

eric-milles commented 5 years ago

When the Maven integration encounters read-only .classpath or .project that it wants to modify, user is prompted to make file(s) writeable. Buildship/Gradle just loops running the synchronization task over and over, spiking my CPU and making Eclipse unresponsive.

donat commented 5 years ago

I haven't encountered this scenario before. The synchronization failure would make sense to me but the infinite looping is unexpected. I'll look into this.

donat commented 5 years ago

I'm trying to reproduce this but setting the .project and .classpath file read-only doesn't trigger the infinite loop. I also tried making the entire project read-only and I got the same results. I do get however the dialog you mentioned.

image

If I accept the file permission change the synchronization succeeds. If not, the sync finishes with a failure, and no looping is kicking in.

Any idea, what could be different in your setup?

eric-milles commented 5 years ago

In my build.gradle, I have the following:

plugins {
  id 'groovy'
  id 'eclipse'
}

ext {
  guavaVersion = '27.0.1'
  jUnitVersion = '4.12'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
  jcenter()
}

dependencies {
  compile 'org.codehaus.groovy:groovy:2.4.16:indy'
  compile "com.google.guava:guava:${guavaVersion}-jre",{
    transitive = false
  }
  testCompile "junit:junit:$jUnitVersion"
}

compileGroovy {
  groovyOptions.optimizationOptions.indy = true
}

eclipse {
  classpath.file.whenMerged {
    println '.classpath merged'
    entries.findAll { entry ->
      entry.class.name in [
        'org.gradle.plugins.ide.eclipse.model.Library',
        'org.gradle.plugins.ide.eclipse.model.SourceFolder'
      ]
    }.each { entry ->
      if (entry.entryAttributes['gradle_used_by_scope'] == 'test') {
        entry.entryAttributes['test'] = 'true'
      }
    }
  }

  project.file.whenMerged {
    println '.project merged'
  }

  jdt.file.whenMerged {
    println '.settings/org.eclipse.jdt.core.prefs merged'
  }
}
eric-milles commented 5 years ago

Also thanks for looking into this so quickly. :)

donat commented 5 years ago

Still no 'luck' on my side. Can you do me just one more favor: please check out if installing Buildship 3.0.1 fixes the issue. There, we fixed some file locking issues which might affect this scenario too.

eric-milles commented 5 years ago

Buildship 3.0.1 gives different behavior. If .project is locked, there is an error in the Error Log view, but the refresh task does complete and a new one is not scheduled. If .classpath is locked, the prompt to make it writable is displayed.

Could the prompt be displayed for the .project file as well?

donat commented 5 years ago

The prompt for the .classpath file comes from the platform (probably JDT).

aleksandarsusnjar commented 5 years ago

I see the same problem without .project files being read-only, after upgrading from Photon with Buildship 2.2.1.v20180125-1441 to Eclipse 2018-12 with Buildship 3.0.0.v20181106-1441-m. Will try 3.0.1.v20181217-1543.

haeuserd commented 5 years ago

I had the same problem and upgrading to Buildship 3.0.1 fixed it. However in my case the issue did not originate from read-only .classpath or .project files.