Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.core.resources; singleton:=true
Bundle-Version: 3.22.200.qualifier
Bundle-Version: 3.23.0.qualifier
Bundle-Activator: org.eclipse.core.resources.ResourcesPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ public boolean internalWrite(IProject target, IProjectDescription description, i
if (hasPrivateChanges)
getWorkspace().getMetaArea().writePrivateDescription(target);
//can't do anything if there's no description
if (!hasPublicChanges || (description == null))
if (!hasPublicChanges || (description == null) || description.isWorkspacePrivate())
return false;

//write the model to a byte array
Expand Down Expand Up @@ -938,9 +938,15 @@ public ProjectDescription read(IProject target, boolean creation) throws CoreExc
if (creation) {
privateDescription = new ProjectDescription();
getWorkspace().getMetaArea().readPrivateDescription(target, privateDescription);
if (privateDescription.isWorkspacePrivate()) {
return privateDescription;
}
projectLocation = privateDescription.getLocationURI();
} else {
IProjectDescription description = ((Project) target).internalGetDescription();
if (description instanceof ProjectDescription impl && impl.isWorkspacePrivate()) {
return impl;
}
if (description != null && description.getLocationURI() != null) {
projectLocation = description.getLocationURI();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.events.BuildCommand;
import org.eclipse.core.internal.localstore.SafeChunkyInputStream;
import org.eclipse.core.internal.localstore.SafeChunkyOutputStream;
import org.eclipse.core.internal.utils.Messages;
import org.eclipse.core.internal.utils.Policy;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
Expand Down Expand Up @@ -322,14 +326,15 @@ public ProjectDescription readOldDescription(IProject project) throws CoreExcept
}

/**
* Returns the portions of the project description that are private, and
* adds them to the supplied project description. In particular, the
* project location, the project's dynamic references and build configurations
* are stored here.
* The project location will be set to <code>null</code> if the default
* location should be used. In the case of failure, log the exception and
* return silently, thus reverting to using the default location and no
* Returns the portions of the project description that are private, and adds
* them to the supplied project description. In particular, the project
* location, the project's dynamic references and build configurations are
* stored here. The project location will be set to <code>null</code> if the
* default location should be used. In the case of failure, log the exception
* and return silently, thus reverting to using the default location and no
* dynamic references. The current format of the location file is:
*
* <pre>
* UTF - project location
* int - number of dynamic project references
* UTF - project reference 1
Expand All @@ -347,9 +352,24 @@ public ProjectDescription readOldDescription(IProject project) throws CoreExcept
* UTF - configName if hasConfigName
* ... repeat for number of referenced configurations
* ... repeat for number of build configurations with references
* since 3.23:
* bool - private flag if project should only be read from its private project configuration
* int - number of natures
* UTF - nature id
* ... repeated for N natures
* int - number of buildspecs
* byte - type of buildspec
* (type 1) UTF - name of builder
* int - number of arguments
* UTF arg key
* UTF arg value
* UTF - triggers string
* </pre>
*/
public void readPrivateDescription(IProject target, ProjectDescription description) {
IPath locationFile = locationFor(target).append(F_PROJECT_LOCATION);
String name = target.getName();
description.setName(name);
java.io.File file = locationFile.toFile();
if (!file.exists()) {
locationFile = getBackupLocationFor(locationFile);
Expand All @@ -370,7 +390,7 @@ public void readPrivateDescription(IProject target, ProjectDescription descripti
}
} catch (Exception e) {
//don't allow failure to read the location to propagate
String msg = NLS.bind(Messages.resources_exReadProjectLocation, target.getName());
String msg = NLS.bind(Messages.resources_exReadProjectLocation, name);
Policy.log(new ResourceStatus(IStatus.ERROR, IResourceStatus.FAILED_READ_METADATA, target.getFullPath(), msg, e));
}
//try to read the dynamic references - will fail for old location files
Expand Down Expand Up @@ -408,6 +428,34 @@ public void readPrivateDescription(IProject target, ProjectDescription descripti
m.put(configName, refs);
}
description.setBuildConfigReferences(m);
// read parts since 3.23
description.setWorkspacePrivate(dataIn.readBoolean());
String[] natureIds = new String[dataIn.readInt()];
for (int i = 0; i < natureIds.length; i++) {
natureIds[i] = dataIn.readUTF();
}
description.setNatureIds(natureIds);
int buildspecs = dataIn.readInt();
ICommand[] buildSpecData = new ICommand[buildspecs];
for (int i = 0; i < buildSpecData.length; i++) {
BuildCommand command = new BuildCommand();
buildSpecData[i] = command;
int type = dataIn.read();
if (type == 1) {
command.setName(dataIn.readUTF());
int args = dataIn.readInt();
Map<String, String> map = new LinkedHashMap<>();
for (int j = 0; j < args; j++) {
map.put(dataIn.readUTF(), dataIn.readUTF());
}
command.setArguments(map);
String trigger = dataIn.readUTF();
if (!trigger.isEmpty()) {
ProjectDescriptionReader.parseBuildTriggers(command, trigger);
}
}
description.setBuildSpec(buildSpecData);
}
} catch (IOException e) {
//ignore - this is an old location file or an exception occurred
// closing the stream
Expand Down Expand Up @@ -470,6 +518,35 @@ public void writePrivateDescription(IProject target) throws CoreException {
}
}
}
// write parts since 3.23
dataOut.writeBoolean(desc.isWorkspacePrivate());
String[] natureIds = desc.getNatureIds();
dataOut.writeInt(natureIds.length);
for (String id : natureIds) {
dataOut.writeUTF(id);
}
ICommand[] buildSpec = desc.getBuildSpec(false);
dataOut.write(buildSpec.length);
for (ICommand command : buildSpec) {
if (command instanceof BuildCommand b) {
dataOut.write(1);
dataOut.writeUTF(b.getName());
Map<String, String> arguments = b.getArguments();
dataOut.writeInt(arguments.size());
for (Entry<String, String> entry : arguments.entrySet()) {
dataOut.writeUTF(entry.getKey());
dataOut.writeUTF(entry.getValue());
}
if (ModelObjectWriter.shouldWriteTriggers(b)) {
dataOut.writeUTF(ModelObjectWriter.triggerString(b));
} else {
dataOut.writeUTF(""); //$NON-NLS-1$
}
} else {
dataOut.write(0);
}
}
dataOut.flush();
output.succeed();
} catch (IOException e) {
String message = NLS.bind(Messages.resources_exSaveProjectLocation, target.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class ModelObjectWriter implements IModelObjectConstants {
* Returns the string representing the serialized set of build triggers for
* the given command
*/
private static String triggerString(BuildCommand command) {
static String triggerString(BuildCommand command) {
StringBuilder buf = new StringBuilder();
if (command.isBuilding(IncrementalProjectBuilder.AUTO_BUILD))
buf.append(TRIGGER_AUTO).append(',');
Expand Down Expand Up @@ -83,7 +83,7 @@ protected void write(BuildCommand command, XMLWriter writer) {
/**
* Returns whether the build triggers for this command should be written.
*/
private boolean shouldWriteTriggers(BuildCommand command) {
static boolean shouldWriteTriggers(BuildCommand command) {
//only write triggers if command is configurable and there exists a trigger
//that the builder does NOT respond to. I.e., don't write out on the default
//cases to avoid dirtying .project files unnecessarily.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ public void create(IProjectDescription description, int updateFlags, IProgressMo
updateDescription();
// make sure the .location file is written
workspace.getMetaArea().writePrivateDescription(this);
} else {
} else if (!desc.isWorkspacePrivate()) {
// write out the project
writeDescription(IResource.FORCE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.internal.events.BuildCommand;
Expand Down Expand Up @@ -124,6 +125,7 @@ public class ProjectDescription extends ModelObject implements IProjectDescripti
protected URI location = null;
protected volatile String[] natures = EMPTY_STRING_ARRAY;
protected URI snapshotLocation = null;
private boolean privateFlag;

public ProjectDescription() {
super();
Expand Down Expand Up @@ -546,6 +548,14 @@ public boolean hasPrivateChanges(ProjectDescription description) {
// Configuration level references
if (configRefsHaveChanges(dynamicConfigRefs, description.dynamicConfigRefs))
return true;
// has natures changed?
if (!Set.of(natures).equals(Set.of(description.natures))) {
return true;
}
// has buildspec changed?
if (!Objects.deepEquals(buildSpec, description.buildSpec)) {
return true;
}

return false;
}
Expand Down Expand Up @@ -978,4 +988,14 @@ private static IProject[] computeDynamicReferencesForProject(IBuildConfiguration
}
return result.toArray(new IProject[0]);
}

@Override
public boolean isWorkspacePrivate() {
return privateFlag;
}

@Override
public void setWorkspacePrivate(boolean privateFlag) {
this.privateFlag = privateFlag;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,26 +233,31 @@ private void endBuildTriggersElement(String elementName) {
state = S_BUILD_COMMAND;
BuildCommand command = (BuildCommand) objectStack.peek();
//presence of this element indicates the builder is configurable
String string = charBuffer.toString();
command.setConfigurable(true);
//clear all existing values
command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false);
command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false);
command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, false);
command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false);

//set new values according to value in the triggers element
StringTokenizer tokens = new StringTokenizer(charBuffer.toString(), ","); //$NON-NLS-1$
while (tokens.hasMoreTokens()) {
String next = tokens.nextToken();
if (next.equalsIgnoreCase(TRIGGER_AUTO)) {
command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, true);
} else if (next.equalsIgnoreCase(TRIGGER_CLEAN)) {
command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, true);
} else if (next.equalsIgnoreCase(TRIGGER_FULL)) {
command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true);
} else if (next.equalsIgnoreCase(TRIGGER_INCREMENTAL)) {
command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, true);
}
parseBuildTriggers(command, string);
}
}

static void parseBuildTriggers(BuildCommand command, String string) {
command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false);
command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, false);
command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, false);
command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, false);

// set new values according to value in the triggers element
StringTokenizer tokens = new StringTokenizer(string, ","); //$NON-NLS-1$
while (tokens.hasMoreTokens()) {
String next = tokens.nextToken();
if (next.equalsIgnoreCase(TRIGGER_AUTO)) {
command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, true);
} else if (next.equalsIgnoreCase(TRIGGER_CLEAN)) {
command.setBuilding(IncrementalProjectBuilder.CLEAN_BUILD, true);
} else if (next.equalsIgnoreCase(TRIGGER_FULL)) {
command.setBuilding(IncrementalProjectBuilder.FULL_BUILD, true);
} else if (next.equalsIgnoreCase(TRIGGER_INCREMENTAL)) {
command.setBuilding(IncrementalProjectBuilder.INCREMENTAL_BUILD, true);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,9 @@ protected void saveMetaInfo(MultiStatus problems, IProgressMonitor monitor) thro
* @return Status object containing non-critical warnings, or an OK status.
*/
protected IStatus saveMetaInfo(Project project, IProgressMonitor monitor) throws CoreException {
if (project.internalGetDescription().isWorkspacePrivate()) {
return Status.OK_STATUS;
}
long start = System.currentTimeMillis();
//if there is nothing on disk, write the description
if (!workspace.getFileSystemManager().hasSavedDescription(project)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ public interface IProjectDescription {
*/
ICommand newCommand();

/**
* @return <code>true</code> if this project is only persisted in the private
* workspace area
* @since 3.23
*/
boolean isWorkspacePrivate();

/**
* Sets the active configuration for the described project.
* <p>
Expand Down Expand Up @@ -385,4 +392,12 @@ public interface IProjectDescription {
* @see #getReferencedProjects()
*/
void setReferencedProjects(IProject[] projects);

/**
* Sets the project to be only persisted into the private workspace area and not
* into a physical <code>.project</code> file in the root of the project folder.
*
* @since 3.23
*/
void setWorkspacePrivate(boolean privateFlag);
}
Loading