### Eclipse Workspace Patch 1.0 #P org.eclipse.core.resources Index: src/org/eclipse/core/internal/events/BuildManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.resources/src/org/eclipse/core/internal/events/BuildManager.java,v retrieving revision 1.104 diff -u -r1.104 BuildManager.java --- src/org/eclipse/core/internal/events/BuildManager.java 3 Dec 2007 04:28:47 -0000 1.104 +++ src/org/eclipse/core/internal/events/BuildManager.java 21 Jan 2008 18:43:59 -0000 @@ -135,12 +135,32 @@ // Figure out want kind of build is needed boolean clean = trigger == IncrementalProjectBuilder.CLEAN_BUILD; currentLastBuiltTree = currentBuilder.getLastBuiltTree(); - // If no tree is available we have to do a full build - if (!clean && currentLastBuiltTree == null) - trigger = IncrementalProjectBuilder.FULL_BUILD; - //don't build if this builder doesn't respond to the given trigger - if (!builder.getCommand().isBuilding(trigger)) - return; + + // check if the builder responds to the given trigger + boolean doesRespond = builder.getCommand().isBuilding(trigger); + + if (clean) { + // don't build if the builder doesn't respond to the clean trigger + // and a clean is requested, just make sure that the build tree + // will be cleared during a clean + if (!doesRespond) { + currentBuilder.setLastBuiltTree(null); + return; + } + } else { + // if the builder doesn't respond to the given trigger + // and no tree is available, try to trigger a full build + if (!doesRespond && currentLastBuiltTree == null) { + trigger = IncrementalProjectBuilder.FULL_BUILD; + doesRespond = builder.getCommand().isBuilding(trigger); + } else if (doesRespond && currentLastBuiltTree == null) { + currentBuilder.setLastBuiltTree(new ElementTree()); + } + // don't build if the builder doesn't respond to the given triggers, + if (!doesRespond) + return; + } + // For incremental builds, grab a pointer to the current state before computing the delta currentTree = ((trigger == IncrementalProjectBuilder.FULL_BUILD) || clean) ? null : workspace.getElementTree(); int depth = -1; #P org.eclipse.core.tests.resources Index: src/org/eclipse/core/tests/internal/builders/CustomBuildTriggerTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.core.tests.resources/src/org/eclipse/core/tests/internal/builders/CustomBuildTriggerTest.java,v retrieving revision 1.8 diff -u -r1.8 CustomBuildTriggerTest.java --- src/org/eclipse/core/tests/internal/builders/CustomBuildTriggerTest.java 17 Apr 2007 22:26:49 -0000 1.8 +++ src/org/eclipse/core/tests/internal/builders/CustomBuildTriggerTest.java 21 Jan 2008 18:44:00 -0000 @@ -333,4 +333,151 @@ assertTrue("3.0", builder.wasIncrementalBuild()); } + + + + + + + /** + * Tests that a builder that responds only to the "full" trigger will be called + * on the first and only first build after a clean. + * See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=206540. + */ + public void testCleanBuild_AfterCleanBuilder() throws CoreException { + IWorkspace workspace = getWorkspace(); + IProject project = workspace.getRoot().getProject("PROJECT" + 1); + ICommand command = null; + + // Create some resources + project.create(getMonitor()); + project.open(getMonitor()); + + // Create and set a build specs for project + IProjectDescription desc = project.getDescription(); + command = createCommand(desc, CustomTriggerBuilder.BUILDER_NAME, "Build0"); + command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); + command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true); + command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false); + command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false); + desc.setBuildSpec(new ICommand[] {command}); + project.setDescription(desc, getMonitor()); + command = project.getDescription().getBuildSpec()[0]; + + // turn auto-building off + setAutoBuilding(false); + + // do an initial build to get the builder instance + try { + project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); + } catch (CoreException e) { + fail("1.0", e); + } + waitForBuild(); + CustomTriggerBuilder builder = CustomTriggerBuilder.getInstance(); + assertNotNull("2.0", builder); + assertTrue("2.1", builder.wasFullBuild()); + + // do a clean - builder should not be called + builder.clearBuildTrigger(); + builder.reset(); + workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); + assertTrue("3.0",!builder.wasCleanBuild()); + assertTrue("3.1",!builder.wasFullBuild()); + + // do an incremental build - FULL_BUILD should be triggered + builder.clearBuildTrigger(); + builder.reset(); + workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); + waitForBuild(); + assertTrue("4.0",!builder.wasCleanBuild()); + assertTrue("4.1",builder.wasFullBuild()); + + // add a file in the project before an incremental build is triggered again + IFile file = project.getFile("a.txt"); + try { + file.create(getRandomContents(), IResource.NONE, getMonitor()); + } catch (CoreException e) { + fail("5.00", e); + } + + // do an incremental build - build should NOT be triggered + builder.clearBuildTrigger(); + builder.reset(); + workspace.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, getMonitor()); + waitForBuild(); + assertTrue("6.0",!builder.wasCleanBuild()); + assertTrue("6.1",!builder.wasFullBuild()); + } + + /** + * Tests that a builder that responds only to the "full" trigger will be called + * on the first and only first build after a clean. + * See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=206540. + */ + public void testCleanAutoBuild_AfterCleanBuilder() throws CoreException { + IWorkspace workspace = getWorkspace(); + IProject project = workspace.getRoot().getProject("PROJECT" + 1); + ICommand command = null; + + // Create some resources + project.create(getMonitor()); + project.open(getMonitor()); + + // Create and set a build specs for project + IProjectDescription desc = project.getDescription(); + command = createCommand(desc, CustomTriggerBuilder.BUILDER_NAME, "Build0"); + command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); + command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true); + command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false); + command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false); + desc.setBuildSpec(new ICommand[] {command}); + project.setDescription(desc, getMonitor()); + command = project.getDescription().getBuildSpec()[0]; + + // turn auto-building on + setAutoBuilding(true); + waitForBuild(); + CustomTriggerBuilder builder = CustomTriggerBuilder.getInstance(); + assertNotNull("1.0", builder); + assertTrue("1.1", builder.wasFullBuild()); + + // do a clean - builder should not be called + builder.clearBuildTrigger(); + builder.reset(); + workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, getMonitor()); + assertTrue("2.0",!builder.wasCleanBuild()); + assertTrue("2.1",!builder.wasFullBuild()); + + + // add a file in the project to trigger an auto-build - FULL_BUILD should be triggered + builder.clearBuildTrigger(); + builder.reset(); + + IFile file = project.getFile("a.txt"); + try { + file.create(getRandomContents(), IResource.NONE, getMonitor()); + } catch (CoreException e) { + fail("3.00", e); + } + + waitForBuild(); + assertTrue("4.0",!builder.wasCleanBuild()); + assertTrue("4.1",builder.wasFullBuild()); + + // add another file in the project to trigger an auto-build - build should NOT be triggered + builder.clearBuildTrigger(); + builder.reset(); + + file = project.getFile("b.txt"); + try { + file.create(getRandomContents(), IResource.NONE, getMonitor()); + } catch (CoreException e) { + fail("5.00", e); + } + + waitForBuild(); + assertTrue("6.0",!builder.wasCleanBuild()); + assertTrue("6.1",!builder.wasFullBuild()); + } }