Skip to content

Commit 50bfd88

Browse files
committed
Add support for creating workspace private project descriptions
Currently importing a project into eclipse requires the creation of a physical file name .project in the root of the project. this has several drawbacks for tools that automatically discover projects and import them for the user as it creates new files and possibly dirty their working tree. Other tools use a single folder for this purpose or don't require any permanent files in the working-tree itself. Even Eclipse has already such concept that is used when a project is located outside the workspace. This now adds a new feature called "workspace private project" that only holds the basic information in the location file in the workspace directory, any additional information might be needed to restore by a tool that uses workspace private projects.
1 parent a791b17 commit 50bfd88

File tree

7 files changed

+66
-4
lines changed

7 files changed

+66
-4
lines changed

resources/bundles/org.eclipse.core.resources/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.core.resources; singleton:=true
5-
Bundle-Version: 3.22.200.qualifier
5+
Bundle-Version: 3.23.0.qualifier
66
Bundle-Activator: org.eclipse.core.resources.ResourcesPlugin
77
Bundle-Vendor: %providerName
88
Bundle-Localization: plugin

resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ public boolean internalWrite(IProject target, IProjectDescription description, i
683683
if (hasPrivateChanges)
684684
getWorkspace().getMetaArea().writePrivateDescription(target);
685685
//can't do anything if there's no description
686-
if (!hasPublicChanges || (description == null))
686+
if (!hasPublicChanges || (description == null) || description.isWorkspacePrivate())
687687
return false;
688688

689689
//write the model to a byte array
@@ -938,9 +938,15 @@ public ProjectDescription read(IProject target, boolean creation) throws CoreExc
938938
if (creation) {
939939
privateDescription = new ProjectDescription();
940940
getWorkspace().getMetaArea().readPrivateDescription(target, privateDescription);
941+
if (privateDescription.isWorkspacePrivate()) {
942+
return privateDescription;
943+
}
941944
projectLocation = privateDescription.getLocationURI();
942945
} else {
943946
IProjectDescription description = ((Project) target).internalGetDescription();
947+
if (description instanceof ProjectDescription impl && impl.isWorkspacePrivate()) {
948+
return impl;
949+
}
944950
if (description != null && description.getLocationURI() != null) {
945951
projectLocation = description.getLocationURI();
946952
}

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,16 @@ public ProjectDescription readOldDescription(IProject project) throws CoreExcept
347347
* UTF - configName if hasConfigName
348348
* ... repeat for number of referenced configurations
349349
* ... repeat for number of build configurations with references
350+
* since 3.23:
351+
* bool - private flag if project should only be read from its private project configuration
352+
* int - number of natures
353+
* UTF - nature id
354+
* ... repeated for N natures
350355
*/
351356
public void readPrivateDescription(IProject target, ProjectDescription description) {
352357
IPath locationFile = locationFor(target).append(F_PROJECT_LOCATION);
358+
String name = target.getName();
359+
description.setName(name);
353360
java.io.File file = locationFile.toFile();
354361
if (!file.exists()) {
355362
locationFile = getBackupLocationFor(locationFile);
@@ -370,7 +377,7 @@ public void readPrivateDescription(IProject target, ProjectDescription descripti
370377
}
371378
} catch (Exception e) {
372379
//don't allow failure to read the location to propagate
373-
String msg = NLS.bind(Messages.resources_exReadProjectLocation, target.getName());
380+
String msg = NLS.bind(Messages.resources_exReadProjectLocation, name);
374381
Policy.log(new ResourceStatus(IStatus.ERROR, IResourceStatus.FAILED_READ_METADATA, target.getFullPath(), msg, e));
375382
}
376383
//try to read the dynamic references - will fail for old location files
@@ -408,6 +415,14 @@ public void readPrivateDescription(IProject target, ProjectDescription descripti
408415
m.put(configName, refs);
409416
}
410417
description.setBuildConfigReferences(m);
418+
// read parts since 3.23
419+
description.setWorkspacePrivate(dataIn.readBoolean());
420+
int natures = dataIn.readInt();
421+
String[] natureIds = new String[natures];
422+
for (int i = 0; i < natureIds.length; i++) {
423+
natureIds[i] = dataIn.readUTF();
424+
}
425+
description.setNatureIds(natureIds);
411426
} catch (IOException e) {
412427
//ignore - this is an old location file or an exception occurred
413428
// closing the stream
@@ -470,6 +485,14 @@ public void writePrivateDescription(IProject target) throws CoreException {
470485
}
471486
}
472487
}
488+
// write parts since 3.23
489+
dataOut.writeBoolean(desc.isWorkspacePrivate());
490+
String[] natureIds = desc.getNatureIds();
491+
dataOut.writeInt(natureIds.length);
492+
for (String id : natureIds) {
493+
dataOut.writeUTF(id);
494+
}
495+
dataOut.flush();
473496
output.succeed();
474497
} catch (IOException e) {
475498
String message = NLS.bind(Messages.resources_exSaveProjectLocation, target.getName());

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ public void create(IProjectDescription description, int updateFlags, IProgressMo
326326
updateDescription();
327327
// make sure the .location file is written
328328
workspace.getMetaArea().writePrivateDescription(this);
329-
} else {
329+
} else if (!desc.isWorkspacePrivate()) {
330330
// write out the project
331331
writeDescription(IResource.FORCE);
332332
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ public class ProjectDescription extends ModelObject implements IProjectDescripti
124124
protected URI location = null;
125125
protected volatile String[] natures = EMPTY_STRING_ARRAY;
126126
protected URI snapshotLocation = null;
127+
private boolean privateFlag;
127128

128129
public ProjectDescription() {
129130
super();
@@ -546,6 +547,10 @@ 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+
}
549554

550555
return false;
551556
}
@@ -978,4 +983,14 @@ private static IProject[] computeDynamicReferencesForProject(IBuildConfiguration
978983
}
979984
return result.toArray(new IProject[0]);
980985
}
986+
987+
@Override
988+
public boolean isWorkspacePrivate() {
989+
return privateFlag;
990+
}
991+
992+
@Override
993+
public void setWorkspacePrivate(boolean privateFlag) {
994+
this.privateFlag = privateFlag;
995+
}
981996
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,9 @@ protected void saveMetaInfo(MultiStatus problems, IProgressMonitor monitor) thro
13711371
* @return Status object containing non-critical warnings, or an OK status.
13721372
*/
13731373
protected IStatus saveMetaInfo(Project project, IProgressMonitor monitor) throws CoreException {
1374+
if (project.internalGetDescription().isWorkspacePrivate()) {
1375+
return Status.OK_STATUS;
1376+
}
13741377
long start = System.currentTimeMillis();
13751378
//if there is nothing on disk, write the description
13761379
if (!workspace.getFileSystemManager().hasSavedDescription(project)) {

resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/resources/IProjectDescription.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ public interface IProjectDescription {
175175
*/
176176
ICommand newCommand();
177177

178+
/**
179+
* @return <code>true</code> if this project is only persisted in the private
180+
* workspace area
181+
* @since 3.23
182+
*/
183+
boolean isWorkspacePrivate();
184+
178185
/**
179186
* Sets the active configuration for the described project.
180187
* <p>
@@ -385,4 +392,12 @@ public interface IProjectDescription {
385392
* @see #getReferencedProjects()
386393
*/
387394
void setReferencedProjects(IProject[] projects);
395+
396+
/**
397+
* Sets the project to be only persisted into the private workspace area and not
398+
* into a physical <code>.project</code> file in the root of the project folder.
399+
*
400+
* @since 3.23
401+
*/
402+
void setWorkspacePrivate(boolean privateFlag);
388403
}

0 commit comments

Comments
 (0)