Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify project synchronization #196

Merged
merged 22 commits into from
Dec 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
10cc210
Improve build command updater
oehme Aug 27, 2016
f515066
Let ProjectNatureUpdater always override if model is present
oehme Aug 27, 2016
b1f7822
Use persistent property to remember linked resources
oehme Aug 27, 2016
c89cd63
Use persistent property to remember derived resources
oehme Aug 27, 2016
71d5eb9
Improve source folder synchronization
oehme Aug 27, 2016
580c857
Simplify classpath container upate
oehme Oct 27, 2016
3301bc9
Remove unnecessary null check
oehme Oct 27, 2016
f7e8e15
Reduce scope of workspace and Java model transactions
oehme Oct 27, 2016
308111d
Use cached task view model when projects are added/removed
oehme Oct 27, 2016
56299b9
Adjust tests
donat Nov 28, 2016
a745edd
Add @param to public method
donat Nov 28, 2016
a2886a2
Extract common load-store functionality from updaters into base class
donat Nov 28, 2016
1c1338e
Persist updater info in platfrom state location
donat Nov 28, 2016
37bbe43
Introduce ProjectPluginStatePreferences
donat Dec 1, 2016
01e5d79
Use ProjectPluginStatePreferences in updater classes
donat Dec 1, 2016
480005c
Fix test failures
donat Dec 1, 2016
66c974e
Relax assertion in TaskViewContentSpec
donat Dec 1, 2016
c52e84c
Resolve review items
donat Dec 2, 2016
b237469
Remove existing descriptor dialog
donat Dec 6, 2016
cb740cf
Remove unused NewProjectHandler.IMPORT_AND_OVERRIDE option
donat Dec 6, 2016
fb0b9e7
Remove unused NewProjectHandler.shouldOverwriteDescriptor() method
donat Dec 6, 2016
dcbd57f
Strengthen assertion in TaskViewContentSpec
donat Dec 7, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.eclipse.buildship.core.preferences.internal

import org.eclipse.core.resources.IProject
import org.eclipse.core.runtime.NullProgressMonitor

import org.eclipse.buildship.core.CorePlugin
import org.eclipse.buildship.core.preferences.PersistentModel
import org.eclipse.buildship.core.test.fixtures.WorkspaceSpecification

class DefaultModelPersistenceTest extends WorkspaceSpecification {

IProject project

void setup() {
project = newProject('sample-project')
PersistentModel model = CorePlugin.modelPersistence().loadModel(project)
model.setValue('existing-key', 'existing-value')
model.flush()
}

def "Can store values for a project"() {
given:
PersistentModel model = CorePlugin.modelPersistence().loadModel(project)
model.setValue('key', 'value')
model.flush()

expect:
CorePlugin.modelPersistence().loadModel(project).getValue('key', 'default-value') == 'value'
}

def "Default value is returned for non-existing key"() {
given:
PersistentModel model = CorePlugin.modelPersistence().loadModel(project)

expect:
model.getValue('nonexisting-key', 'default-value') == 'default-value'
}

def "Default value can be null"() {
given:
PersistentModel model = CorePlugin.modelPersistence().loadModel(project)

expect:
model.getValue('nonexisting-key', null) == null
}

def "Setting a null value removes the entry from the model"() {
when:
PersistentModel model = CorePlugin.modelPersistence().loadModel(project)
model.setValue('existing-key', null)
model.flush()

then:
CorePlugin.modelPersistence().loadModel(project).getValue('existing-key', 'default-value') == 'default-value'
}

def "Storage stays intact if a project is renamed"() {
when:
project = CorePlugin.workspaceOperations().renameProject(project, 'new-project-name', new NullProgressMonitor())

then:
CorePlugin.modelPersistence().loadModel(project).getValue('existing-key', null) == 'existing-value'
}

def "Storage is cleaned up if a project is deleted from the workspace"() {
when:
deleteAllProjects(true)

then:
CorePlugin.modelPersistence().loadModel(project).getValue('existing-key', 'default-value') == 'default-value'
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package org.eclipse.buildship.core.workspace.internal

import com.google.common.base.Optional

import com.gradleware.tooling.toolingmodel.OmniEclipseBuildCommand
import org.eclipse.buildship.core.CorePlugin
import org.eclipse.buildship.core.test.fixtures.EclipseProjects
import org.eclipse.buildship.core.test.fixtures.WorkspaceSpecification;

import org.eclipse.core.resources.ICommand
import org.eclipse.core.runtime.NullProgressMonitor
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import spock.lang.Specification

import org.eclipse.buildship.core.test.fixtures.WorkspaceSpecification

class BuildCommandUpdaterTest extends WorkspaceSpecification {

Expand All @@ -19,27 +16,51 @@ class BuildCommandUpdaterTest extends WorkspaceSpecification {
def project = newProject('sample-project')

when:
BuildCommandUpdater.update(project, buildCommand('customBuildCommand', ['key' : 'value']), new NullProgressMonitor())
BuildCommandUpdater.update(project, Optional.of([buildCommand('customBuildCommand', ['key' : 'value'])]), new NullProgressMonitor())

then:
project.description.buildSpec.length == 1
project.description.buildSpec[0].builderName == 'customBuildCommand'
project.description.buildSpec[0].arguments == ['key' : 'value']
}

def "Can have two build commands with same id and different arguments"() {
given:
def project = newProject('sample-project')

when:
BuildCommandUpdater.update(
project,
Optional.of(
[
buildCommand('customBuildCommand', ['key' : 'value']),
buildCommand('customBuildCommand', ['key' : 'otherValue']),
]
),
new NullProgressMonitor()
)

then:
project.description.buildSpec.length == 2
project.description.buildSpec[0].builderName == 'customBuildCommand'
project.description.buildSpec[0].arguments == ['key' : 'value']
project.description.buildSpec[0].builderName == 'customBuildCommand'
project.description.buildSpec[1].arguments == ['key' : 'otherValue']
}

def "Build commands are removed if they no longer exist in the Gradle model"() {
given:
def project = newProject('sample-project')

when:
BuildCommandUpdater.update(project, buildCommand('customBuildCommand', ['key' : 'value']), new NullProgressMonitor())
BuildCommandUpdater.update(project, Optional.of([buildCommand('customBuildCommand', ['key' : 'value'])]), new NullProgressMonitor())
BuildCommandUpdater.update(project, Optional.of([]), new NullProgressMonitor())

then:
project.description.buildSpec.length == 0
}

def "Manually added build commands are preserved"() {
def "Manually added build commands are preserved if Gradle model does not provide them"() {
given:
def project = newProject('sample-project')
def description = project.description
Expand All @@ -51,38 +72,37 @@ class BuildCommandUpdaterTest extends WorkspaceSpecification {
project.setDescription(description, new NullProgressMonitor())

when:
BuildCommandUpdater.update(project, Optional.of([]), new NullProgressMonitor())
BuildCommandUpdater.update(project, Optional.absent(), new NullProgressMonitor())

then:
project.description.buildSpec.length == 1
project.description.buildSpec[0].builderName == 'manuallyCreatedBuildCommand'
project.description.buildSpec[0].arguments == [:]
}

def "Build commands that were previously defined manually are transformed to model elements"() {
def "Manually added build commands are removed if Gradle model provides them"() {
given:
def project = newProject('sample-project')
def description = project.description
def command = description.newCommand()
command.setBuilderName('buildCommand')
command.setBuilderName('manuallyCreatedBuildCommand')
command.setArguments([:])
def commands = description.buildSpec + command
description.setBuildSpec(commands as ICommand[])
project.setDescription(description, new NullProgressMonitor())

when:
BuildCommandUpdater.update(project, buildCommand('buildCommand'), new NullProgressMonitor())
BuildCommandUpdater.update(project, Optional.of([]), new NullProgressMonitor())

then:
project.description.buildSpec == []
project.description.buildSpec.length == 0
}

private def buildCommand(name, arguments = [:]) {
def mockedBuildCommand = Mock(OmniEclipseBuildCommand)
mockedBuildCommand.name >> name
mockedBuildCommand.arguments >> arguments
Optional.of([mockedBuildCommand])
mockedBuildCommand
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import com.google.common.base.Optional
import com.gradleware.tooling.toolingmodel.OmniAccessRule
import com.gradleware.tooling.toolingmodel.OmniClasspathAttribute
import com.gradleware.tooling.toolingmodel.OmniEclipseClasspathContainer
import com.gradleware.tooling.toolingmodel.OmniJavaRuntime;
import com.gradleware.tooling.toolingmodel.OmniJavaRuntime
import com.gradleware.tooling.toolingmodel.OmniJavaSourceSettings
import com.gradleware.tooling.toolingmodel.OmniJavaVersion;
import com.gradleware.tooling.toolingmodel.OmniJavaVersion

import org.eclipse.core.runtime.IPath
import org.eclipse.core.runtime.NullProgressMonitor
Expand All @@ -28,7 +28,7 @@ class ClasspathContainerUpdaterTest extends WorkspaceSpecification {
static IPath CUSTOM_USER_CONTAINER = new Path('user.classpath.container')
static IPath GRADLE_CLASSPATH_CONTAINER = GradleClasspathContainer.CONTAINER_PATH
static IPath DEFAULT_JRE_CONTAINER = JavaRuntime.newDefaultJREContainerPath()
static IPath STANDARD_JRE_CONTAINER = new Path('org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8')
static IPath DEFAULT_JAVA_8_CONTAINER = new Path('org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8')
static IPath CUSTOM_JRE_CONTAINER = new Path('org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/Java SE 6 [1.6.0_65-b14-462]')

def "Can set classpath containers"() {
Expand Down Expand Up @@ -64,7 +64,7 @@ class ClasspathContainerUpdaterTest extends WorkspaceSpecification {
!findContainer(project, CUSTOM_MODEL_CONTAINER)
}

def "Preserves manually added classpath containers"() {
def "Overwrites manually added classpath containers if model contains container information"() {
setup:
IJavaProject project = newJavaProject('project-with-classpath-container')
IAccessRule[] rules = [JavaCore.newAccessRule(new Path('accessiblePattern'), IAccessRule.K_ACCESSIBLE)]
Expand All @@ -76,35 +76,30 @@ class ClasspathContainerUpdaterTest extends WorkspaceSpecification {
executeContainerUpdate(project)

then:
IClasspathEntry container = findContainer(project, CUSTOM_USER_CONTAINER)
container != null
container.exported == true
container.accessRules.length == 1
container.accessRules[0].pattern.toPortableString() == 'accessiblePattern'
container.accessRules[0].kind == IAccessRule.K_ACCESSIBLE
container.extraAttributes.length == 1
container.extraAttributes[0].name == 'attributeKey'
container.extraAttributes[0].value == 'attributeValue'

!findContainer(project, CUSTOM_USER_CONTAINER)
}

def "Classpath containers that were previously defined manually are transformed to model elements"() {
def "Preserves manually added classpath containers if model contains no container information"() {
setup:
IJavaProject project = newJavaProject('project-with-classpath-container')
IClasspathEntry[] classpath = project.rawClasspath + JavaCore.newContainerEntry(CUSTOM_USER_CONTAINER, false)
IAccessRule[] rules = [JavaCore.newAccessRule(new Path('accessiblePattern'), IAccessRule.K_ACCESSIBLE)]
IClasspathAttribute[] attributes = [JavaCore.newClasspathAttribute('attributeKey', 'attributeValue')]
IClasspathEntry[] classpath = project.rawClasspath + JavaCore.newContainerEntry(CUSTOM_USER_CONTAINER, rules, attributes, true)
project.setRawClasspath(classpath, new NullProgressMonitor())

when:
executeContainerUpdate(project, container(CUSTOM_USER_CONTAINER))

then:
findContainer(project, CUSTOM_USER_CONTAINER)

when:
executeContainerUpdate(project)
executeContainerUpdateWithOldGradle(project)

then:
!findContainer(project, CUSTOM_USER_CONTAINER)
IClasspathEntry container = findContainer(project, CUSTOM_USER_CONTAINER)
container != null
container.exported == true
container.accessRules.length == 1
container.accessRules[0].pattern.toPortableString() == 'accessiblePattern'
container.accessRules[0].kind == IAccessRule.K_ACCESSIBLE
container.extraAttributes.length == 1
container.extraAttributes[0].name == 'attributeKey'
container.extraAttributes[0].value == 'attributeValue'
}

def "Adds Gradle classpath container by default"() {
Expand Down Expand Up @@ -145,44 +140,65 @@ class ClasspathContainerUpdaterTest extends WorkspaceSpecification {
path << [ CUSTOM_MODEL_CONTAINER, GRADLE_CLASSPATH_CONTAINER ]
}

def "Keeps user-defined JRE entries if model doesn't contain JRE"() {
def "Updates JRE entry based on source level if containers are not supported"() {
setup:
IJavaProject project = newJavaProject('sample-project')
def updatedClasspath = project.rawClasspath.findAll { !it.path.segment(0).equals(JavaRuntime.JRE_CONTAINER) }
updatedClasspath += JavaCore.newContainerEntry(STANDARD_JRE_CONTAINER)
updatedClasspath += JavaCore.newContainerEntry(DEFAULT_JAVA_8_CONTAINER)
updatedClasspath += JavaCore.newContainerEntry(CUSTOM_JRE_CONTAINER)
project.setRawClasspath(updatedClasspath as IClasspathEntry[], null)

expect:
findContainer(project, STANDARD_JRE_CONTAINER)
findContainer(project, DEFAULT_JAVA_8_CONTAINER)
findContainer(project, CUSTOM_JRE_CONTAINER)

when:
executeContainerUpdate(project)
executeContainerUpdateWithOldGradle(project)

then:
findContainer(project, STANDARD_JRE_CONTAINER)
findContainer(project, new Path('org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6'))
!findContainer(project, DEFAULT_JAVA_8_CONTAINER)
!findContainer(project, CUSTOM_JRE_CONTAINER)
}

def "Removes user-defined JRE entries if model doesn't contain JRE"() {
setup:
IJavaProject project = newJavaProject('sample-project')
def updatedClasspath = project.rawClasspath.findAll { !it.path.segment(0).equals(JavaRuntime.JRE_CONTAINER) }
updatedClasspath += JavaCore.newContainerEntry(DEFAULT_JAVA_8_CONTAINER)
updatedClasspath += JavaCore.newContainerEntry(CUSTOM_JRE_CONTAINER)
project.setRawClasspath(updatedClasspath as IClasspathEntry[], null)

expect:
findContainer(project, DEFAULT_JAVA_8_CONTAINER)
findContainer(project, CUSTOM_JRE_CONTAINER)

when:
executeContainerUpdate(project)

then:
!findContainer(project, DEFAULT_JAVA_8_CONTAINER)
!findContainer(project, CUSTOM_JRE_CONTAINER)
}

def "Removes user-defined JRE entries if model contains JRE"() {
setup:
IJavaProject project = newJavaProject('project-with-classpath-container')
def updatedClasspath = project.rawClasspath.findAll { !it.path.segment(0).equals(JavaRuntime.JRE_CONTAINER) }
updatedClasspath += JavaCore.newContainerEntry(STANDARD_JRE_CONTAINER)
updatedClasspath += JavaCore.newContainerEntry(DEFAULT_JAVA_8_CONTAINER)
updatedClasspath += JavaCore.newContainerEntry(CUSTOM_JRE_CONTAINER)
project.setRawClasspath(updatedClasspath as IClasspathEntry[], null)

expect:
findContainer(project, STANDARD_JRE_CONTAINER)
findContainer(project, DEFAULT_JAVA_8_CONTAINER)
findContainer(project, CUSTOM_JRE_CONTAINER)

when:
executeContainerUpdate(project, container(DEFAULT_JRE_CONTAINER))

then:
findContainer(project, DEFAULT_JRE_CONTAINER)
!findContainer(project, STANDARD_JRE_CONTAINER)
!findContainer(project, DEFAULT_JAVA_8_CONTAINER)
!findContainer(project, CUSTOM_JRE_CONTAINER)
}

Expand Down Expand Up @@ -242,11 +258,11 @@ class ClasspathContainerUpdaterTest extends WorkspaceSpecification {

where:
containerPaths << [
[ STANDARD_JRE_CONTAINER, GRADLE_CLASSPATH_CONTAINER ],
[ GRADLE_CLASSPATH_CONTAINER, STANDARD_JRE_CONTAINER ],
[ CUSTOM_USER_CONTAINER, STANDARD_JRE_CONTAINER, CUSTOM_MODEL_CONTAINER ],
[ STANDARD_JRE_CONTAINER, CUSTOM_USER_CONTAINER, CUSTOM_MODEL_CONTAINER ],
[ CUSTOM_USER_CONTAINER, CUSTOM_MODEL_CONTAINER, STANDARD_JRE_CONTAINER ],
[ DEFAULT_JAVA_8_CONTAINER, GRADLE_CLASSPATH_CONTAINER ],
[ GRADLE_CLASSPATH_CONTAINER, DEFAULT_JAVA_8_CONTAINER ],
[ CUSTOM_USER_CONTAINER, DEFAULT_JAVA_8_CONTAINER, CUSTOM_MODEL_CONTAINER ],
[ DEFAULT_JAVA_8_CONTAINER, CUSTOM_USER_CONTAINER, CUSTOM_MODEL_CONTAINER ],
[ CUSTOM_USER_CONTAINER, CUSTOM_MODEL_CONTAINER, DEFAULT_JAVA_8_CONTAINER ],
]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class ClasspathPersistenceTest extends ProjectSynchronizationSpecification {
}

expect:
CorePlugin.instance.stateLocation.append("classpath-persistence").append("sample-project").toFile().delete()
CorePlugin.instance.stateLocation.append("project-preferences").append("sample-project").toFile().delete()

when:
reimportWithoutSynchronization(findProject("sample-project"))
Expand Down Expand Up @@ -102,7 +102,7 @@ class ClasspathPersistenceTest extends ProjectSynchronizationSpecification {

expect:
new File(projectDir, ".settings/org.eclipse.buildship.core.prefs").delete()
CorePlugin.instance.stateLocation.append("classpath-persistence").append("sample-project").toFile().delete()
CorePlugin.instance.stateLocation.append("project-preferences").append("sample-project").toFile().delete()

when:
reimportWithoutSynchronization(project)
Expand All @@ -113,8 +113,12 @@ class ClasspathPersistenceTest extends ProjectSynchronizationSpecification {

private reimportWithoutSynchronization(IProject project) {
def descriptor = project.description
def classpath = CorePlugin.modelPersistence().loadModel(project).getValue('classpath', null)
project.delete(false, true, null)
project.create(descriptor, null)
def preferences = CorePlugin.modelPersistence().loadModel(project)
preferences.setValue('classpath', classpath)
preferences.flush()
project.open(null)
waitForGradleJobsToFinish()
}
Expand Down
Loading