Skip to content

Commit 2ec028f

Browse files
committed
Restore natures and buildspec for project descriptions
Currently a private project description does not store natures and builder, but these are mostly important these days. This now also stores natures and builder specs.
1 parent 15b942c commit 2ec028f

File tree

4 files changed

+110
-20
lines changed

4 files changed

+110
-20
lines changed

resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/LocalMetaArea.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@
2424
import java.io.IOException;
2525
import java.net.URI;
2626
import java.util.HashMap;
27+
import java.util.LinkedHashMap;
2728
import java.util.Map;
29+
import java.util.Map.Entry;
2830
import org.eclipse.core.filesystem.URIUtil;
31+
import org.eclipse.core.internal.events.BuildCommand;
2932
import org.eclipse.core.internal.localstore.SafeChunkyInputStream;
3033
import org.eclipse.core.internal.localstore.SafeChunkyOutputStream;
3134
import org.eclipse.core.internal.utils.Messages;
3235
import org.eclipse.core.internal.utils.Policy;
3336
import org.eclipse.core.resources.IBuildConfiguration;
37+
import org.eclipse.core.resources.ICommand;
3438
import org.eclipse.core.resources.IProject;
3539
import org.eclipse.core.resources.IResource;
3640
import org.eclipse.core.resources.IResourceStatus;
@@ -330,6 +334,8 @@ public ProjectDescription readOldDescription(IProject project) throws CoreExcept
330334
* location should be used. In the case of failure, log the exception and
331335
* return silently, thus reverting to using the default location and no
332336
* dynamic references. The current format of the location file is:
337+
*
338+
* <pre>
333339
* UTF - project location
334340
* int - number of dynamic project references
335341
* UTF - project reference 1
@@ -347,6 +353,19 @@ public ProjectDescription readOldDescription(IProject project) throws CoreExcept
347353
* UTF - configName if hasConfigName
348354
* ... repeat for number of referenced configurations
349355
* ... repeat for number of build configurations with references
356+
* since 3.23:
357+
* bool - private flag if project should only be read from its private project configuration
358+
* int - number of natures
359+
* UTF - nature id
360+
* ... repeated for N natures
361+
* int - number of buildspecs
362+
* byte - type of buildspec
363+
* (type 1) UTF - name of builder
364+
* int - number of arguments
365+
* UTF arg key
366+
* UTF arg value
367+
* UTF - triggers string
368+
* </pre>
350369
*/
351370
public void readPrivateDescription(IProject target, ProjectDescription description) {
352371
IPath locationFile = locationFor(target).append(F_PROJECT_LOCATION);
@@ -357,6 +376,7 @@ public void readPrivateDescription(IProject target, ProjectDescription descripti
357376
if (!file.exists())
358377
return;
359378
}
379+
description.setName(target.getName());
360380
try (DataInputStream dataIn = new DataInputStream(new SafeChunkyInputStream(file, 500))) {
361381
try {
362382
String location = dataIn.readUTF();
@@ -408,6 +428,33 @@ public void readPrivateDescription(IProject target, ProjectDescription descripti
408428
m.put(configName, refs);
409429
}
410430
description.setBuildConfigReferences(m);
431+
// read parts since 3.23
432+
String[] natureIds = new String[dataIn.readInt()];
433+
for (int i = 0; i < natureIds.length; i++) {
434+
natureIds[i] = dataIn.readUTF();
435+
}
436+
description.setNatureIds(natureIds);
437+
int buildspecs = dataIn.readInt();
438+
ICommand[] buildSpecData = new ICommand[buildspecs];
439+
for (int i = 0; i < buildSpecData.length; i++) {
440+
BuildCommand command = new BuildCommand();
441+
buildSpecData[i] = command;
442+
int type = dataIn.read();
443+
if (type == 1) {
444+
command.setName(dataIn.readUTF());
445+
int args = dataIn.readInt();
446+
Map<String, String> map = new LinkedHashMap<>();
447+
for (int j = 0; j < args; j++) {
448+
map.put(dataIn.readUTF(), dataIn.readUTF());
449+
}
450+
command.setArguments(map);
451+
String trigger = dataIn.readUTF();
452+
if (!trigger.isEmpty()) {
453+
ProjectDescriptionReader.parseBuildTriggers(command, trigger);
454+
}
455+
}
456+
description.setBuildSpec(buildSpecData);
457+
}
411458
} catch (IOException e) {
412459
//ignore - this is an old location file or an exception occurred
413460
// closing the stream
@@ -470,6 +517,34 @@ public void writePrivateDescription(IProject target) throws CoreException {
470517
}
471518
}
472519
}
520+
// write parts since 3.23
521+
String[] natureIds = desc.getNatureIds();
522+
dataOut.writeInt(natureIds.length);
523+
for (String id : natureIds) {
524+
dataOut.writeUTF(id);
525+
}
526+
ICommand[] buildSpec = desc.getBuildSpec(false);
527+
dataOut.write(buildSpec.length);
528+
for (ICommand command : buildSpec) {
529+
if (command instanceof BuildCommand b) {
530+
dataOut.write(1);
531+
dataOut.writeUTF(b.getName());
532+
Map<String, String> arguments = b.getArguments();
533+
dataOut.writeInt(arguments.size());
534+
for (Entry<String, String> entry : arguments.entrySet()) {
535+
dataOut.writeUTF(entry.getKey());
536+
dataOut.writeUTF(entry.getValue());
537+
}
538+
if (ModelObjectWriter.shouldWriteTriggers(b)) {
539+
dataOut.writeUTF(ModelObjectWriter.triggerString(b));
540+
} else {
541+
dataOut.writeUTF(""); //$NON-NLS-1$
542+
}
543+
} else {
544+
dataOut.write(0);
545+
}
546+
}
547+
dataOut.flush();
473548
output.succeed();
474549
} catch (IOException e) {
475550
String message = NLS.bind(Messages.resources_exSaveProjectLocation, target.getName());

resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ModelObjectWriter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public class ModelObjectWriter implements IModelObjectConstants {
4444
* Returns the string representing the serialized set of build triggers for
4545
* the given command
4646
*/
47-
private static String triggerString(BuildCommand command) {
47+
static String triggerString(BuildCommand command) {
4848
StringBuilder buf = new StringBuilder();
4949
if (command.isBuilding(IncrementalProjectBuilder.AUTO_BUILD))
5050
buf.append(TRIGGER_AUTO).append(',');
@@ -83,7 +83,7 @@ protected void write(BuildCommand command, XMLWriter writer) {
8383
/**
8484
* Returns whether the build triggers for this command should be written.
8585
*/
86-
private boolean shouldWriteTriggers(BuildCommand command) {
86+
static boolean shouldWriteTriggers(BuildCommand command) {
8787
//only write triggers if command is configurable and there exists a trigger
8888
//that the builder does NOT respond to. I.e., don't write out on the default
8989
//cases to avoid dirtying .project files unnecessarily.

resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectDescription.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.List;
3030
import java.util.Map;
3131
import java.util.Map.Entry;
32+
import java.util.Objects;
3233
import java.util.Set;
3334
import org.eclipse.core.filesystem.URIUtil;
3435
import org.eclipse.core.internal.events.BuildCommand;
@@ -546,6 +547,14 @@ public boolean hasPrivateChanges(ProjectDescription description) {
546547
// Configuration level references
547548
if (configRefsHaveChanges(dynamicConfigRefs, description.dynamicConfigRefs))
548549
return true;
550+
// has natures changed?
551+
if (!Set.of(natures).equals(Set.of(description.natures))) {
552+
return true;
553+
}
554+
// has buildspec changed?
555+
if (!Objects.deepEquals(buildSpec, description.buildSpec)) {
556+
return true;
557+
}
549558

550559
return false;
551560
}
@@ -978,4 +987,5 @@ private static IProject[] computeDynamicReferencesForProject(IBuildConfiguration
978987
}
979988
return result.toArray(new IProject[0]);
980989
}
990+
981991
}

resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/ProjectDescriptionReader.java

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -233,26 +233,31 @@ private void endBuildTriggersElement(String elementName) {
233233
state = S_BUILD_COMMAND;
234234
BuildCommand command = (BuildCommand) objectStack.peek();
235235
//presence of this element indicates the builder is configurable
236+
String string = charBuffer.toString();
236237
command.setConfigurable(true);
237238
//clear all existing values
238-
command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false);
239-
command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false);
240-
command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, false);
241-
command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false);
242-
243-
//set new values according to value in the triggers element
244-
StringTokenizer tokens = new StringTokenizer(charBuffer.toString(), ","); //$NON-NLS-1$
245-
while (tokens.hasMoreTokens()) {
246-
String next = tokens.nextToken();
247-
if (next.equalsIgnoreCase(TRIGGER_AUTO)) {
248-
command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, true);
249-
} else if (next.equalsIgnoreCase(TRIGGER_CLEAN)) {
250-
command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, true);
251-
} else if (next.equalsIgnoreCase(TRIGGER_FULL)) {
252-
command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true);
253-
} else if (next.equalsIgnoreCase(TRIGGER_INCREMENTAL)) {
254-
command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, true);
255-
}
239+
parseBuildTriggers(command, string);
240+
}
241+
}
242+
243+
static void parseBuildTriggers(BuildCommand command, String string) {
244+
command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false);
245+
command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false);
246+
command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, false);
247+
command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false);
248+
249+
// set new values according to value in the triggers element
250+
StringTokenizer tokens = new StringTokenizer(string, ","); //$NON-NLS-1$
251+
while (tokens.hasMoreTokens()) {
252+
String next = tokens.nextToken();
253+
if (next.equalsIgnoreCase(TRIGGER_AUTO)) {
254+
command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, true);
255+
} else if (next.equalsIgnoreCase(TRIGGER_CLEAN)) {
256+
command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, true);
257+
} else if (next.equalsIgnoreCase(TRIGGER_FULL)) {
258+
command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true);
259+
} else if (next.equalsIgnoreCase(TRIGGER_INCREMENTAL)) {
260+
command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, true);
256261
}
257262
}
258263
}

0 commit comments

Comments
 (0)