blob: a52e244b65d56846541f4a3206794149c8501892 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Build">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<title>Eclipse Platform Core RFC 0006 - Omnibus Resource Improvements</title>
</head>
<body>
<h1>
Omnibus Resource Improvements</h1>
<i><font size=-1>Last revised 10:00 Wednesday February 27, 2002</font></i>
<p>This note summarizes a series of proposed additions and changes to Eclipse to improve the resource
story and address several Eclipse 2.0 plan items.
<h2>
Reify project description as project resource</h2>
A project's project description contains important information about the
project.
<p>The proposal is to reify the project description in a file, named
&quot;.project&quot;,
in the root of each project's content area. The contents of the file would
be a well-specified XML format, and contain Core project description information:
project name, project description, list of project nature ids, list of
required project names, and the project build spec.
<p>The .project file in the root folder would be considered the master
copy. IProject.setDescription would overwrite this file. If a team provider
(or a user) changes the .project file through means other than IProject.setDescription,
this eventually affects the project much as if IProject.setDescription
had been called. The one exception is changes to the project name, which
would be disallowed [alternative: rename the project]. After the fact resource
change events are reported on the .project file resource as well as being
flagged as a description change on the project resource.
<p>Note that the location of the project's content directory is <i>not</i>
represented in the .project file. Rather, the .project file is found in
the project's content directory.
<p>As a consequence of this change, Core should drop its internal
.prj file.
<p>For open projects, core would keep the project description in memory
at all times. IProject.getDescription uses the in-memory information -
it does not access the local file system. Core would also remember a timestamp
for the .project file. When refreshLocal picks up a change to a .project
file, Core reads the modified .project file and changes the in-memory project
description. Resource change events are reported much as if the project
description had been changed via IProject.setDescription.
<p>Problems addressed:
<ul>
<li>
Projects are now more self-contained in the local file system. This means
it is easier to give a project to someone else simply by copying the project
content directory.</li>
<li>
Meets Team (VCM) request for a real file containing project description.
Team would no longer need to treat project description as special in any
way; instead, it simply saves and restores the .project file exactly as
it would any other file.</li>
</ul>
New wrinkles created:
<ul>
<li>
When a project's resources, which now might include a&nbsp; .project file,
already exist on disk but are not a part of a workspace, how does a user import this project to their workspace?<br>
When the designated directory contains a .project file, it should be read and
honored. When the designated directory does not contain a .project file, one
should be created (the user would normally supply crucial information as input,
including the project's list of capabilities/natures). This will require new Core
API, and a new Import wizard.</li>
<li>
What happens if a project's .project file gets deleted?<br>
This is a serious error which may cause the user to lose other important
data. If the project is to be opened (or remain open), Core should reconstruct
a .project file from available information. However, the user is in trouble, and
it is important that the facts be reported back to the user so that she can
rectify the situation.</li>
<li>
What happens if a project's .project file is busy and cannot be read?<br>
The
Core operation that is causing the description to be read from disk fails.
If attempting to open a project, the open fails.</li>
<li>
What happens if a project's .project file contains mangled XML?<br>
The Core
operation that is causing the description to be read from disk fails. If
attempting to open a project, the open fails.</li>
<li>
What happens if a project's .project file is busy or something else prevents it
from being written
to disk?<br>
The Core operation that is causing the description to be written
to disk (IProject.setDescription) fails. (The alternative of proceeding with the
information held in memory was considered. It requires a more complex
interaction with the user to ensure that the changes eventually do get written
to disk after the user has rectified the situation.)</li>
<li>
What happens when IFile.setContents is called on the .project file?<br>
This operation should overwrite the file in the local file system, and then
behave as if refresh local had just discovered the changed file.</li>
<li>
What happens if there is a conflict on the .project file (user's outgoing
change being met by incoming change from team repository)?<br>
Ideally, there should be a specialized merge conflict viewer that would show
the user the changes in terms that they would understand and allow the
user to resolve the conflict. For 2.0, a standard text merge viewer on
the XML .project file contents would show the user the conflict (as it
does with conflicting .classpath files).</li>
<li>
What is the relationship between operations that change the .project file and
the validateSave hook in IFile.setContents?<br>
Setting the project description via a Core operation should hit the validateSave
hook as it would if IFile.setContents were called to write out the .project
file. This hook would not be triggered when changes to the .project file (or any
other file) are discovered, as by refresh local.</li>
</ul>
<h2>
Derived resources</h2>
Derived resources are regular files and folders in a project that are created
in the course of translating, compiling, copying, or otherwise processing other files. Derived resources are not original data, and can be recreated
from other resources.
<p>It is commonplace to exclude derived resources from VCM because they
clutter the repository with ever-changing files that each user appears
to modify regularly. Each team provider typically provides the user with
a way to include certain files under VCM and exclude others. If plug-ins
that create derived resources mark them as such, the team provider can
do a better job of excluding by default those resources that any user is
unlikely to want in the repository.
<p>The proposal is there be a way for non-Team-clients to provide hints
that certain resource subtrees are likely to contain derived resources.
This would be done by setting a mark bit on a folder or file; the mark
would mean that the resource, and any present or future descendents, should be considered derived
resources <i>by default</i>. Note that this is only a default. A user should
still be able to place any resource under management even if marked as,
or sits below, a derived resource.
<p>Example: JDT would set this bit on the project's output folder (or on
individual generated *.class files when the output folder coincides with the
project root).
<p>Example: An editor or utility that creates a backup copy of a file in
the same folder should mark the copy as a derived file.
<p>Derived marks would be recorded in the resource tree, and saved to disk
along with the in-memory resource tree. Derived marks would not be recorded
in a Team repository.
<p>To mark (or unmark) a resource as derived, the resource would need to
exist. There would be no resource delta for setting or resetting this bit;
default is off (i.e., not derived).
However, the fact that the bit would be retained in memory at all times
means that a Team provider can quickly discover whether a plug-in has marked
a resource or one of its ancestors as derived.<p>The user would be able see and change a resource's derived flag via
the Properties dialogs. It would not warrant anything more obvious since
users are unlikely to ever be interested in this property. However, letting the
user mark a resource as derived would allow them to indicate that certain files
(such as certain metadata files) are not prime candidates for version
management.
<p>In addition to this basic support for derived resources, the Team component
will maintain a list of excluded file and folder name patterns. Any files or
folders in the project
with names that match these patterns would be considered unmanaged (or unmanaged
by default).</p>
<p>Problems addressed:
<ul>
<li>
There is a simple way for client plug-ins to indicate that certain resource
which they create are derived resources that should not be put into a repository
by default. The mechanism is independent of any Team provider, and can be
used unconditionaly even when there is no Team provider for the project.</li>
<li>
There is a simple way for Team providers to find out the whereabouts
of derived resources that should not be put into a repository by default.</li>
<li>
Specifically, JDT would mark project output folders as derived. This would
hint that generated .class files and copied resource files should not be
placed in the repository.</li>
</ul>
<h2>
Team-private resources</h2>
Some Team providers have extra files and folders that are created
in the project by the team provider to satisfy certain external requirements
of that provider. For example, CVS uses a CVS/ subfolder in each managed
folder to store CVS-specific information. Although these files are needed
by the team provider, they are of no interest to other plug-ins. Indeed,
other plug-ins should not even know of their existence.
<p>The proposal is to provide a way for a Team provider to hide certain resources in the resource
tree so that they are not seen by other plug-ins. This is achieved with a new <b>team-private
member</b> flag in the in-memory resource
tree. When a file or folder is marked as a team-private member, it is omitted
from the list of resources returned from IContainer.members (a variant method
includes team-private members upon request). In all other regards, a
team-private member is like any other file or folder resource that exists in the
workspace.</p>
<p>Team-private member marks are recorded in the resource tree, and saved to disk
along with the in-memory resource tree. Team-private member marks are not be recorded
in a Team repository. To mark (or unmark) a resource as a team-private member, the resource needs to
exist. The bit
defaults to off (i.e., not team-private).<p>Creations, deletions, and changes to
team-private member resources are reflected in resource deltas. Like IContainer.members,
the deltas seen by normal delta clients omit all mention of team-private member
resources (the unfiltered list of child deltas is available on request). A
change to the team-private member flag of a resource is reflected in the delta
(indicated as a change to the resource's team-private member property), and will
be seen by all delta clients (because the resource was a non-team-private member
either before or after the change).<p>The mechanism is intended to be used by Team providers.
Team providers are in the unique position of being able to set this flag to hide
any extra files or folders they might create. Team providers can do this without
needing to store additional metadata in the repository.
<p>Example: the CVS team provider would set this bit on the extra
&quot;CVS&quot; folders that it creates in most folders. By doing so at the time
a CVS folder first enters the workspace, the folder does not show up in the
normal resource delta, and therefore slips in to the workspace without other
plug-ins noticing. Since the CVS folders contain special metadata, the CVS team
provider may need to protect these files from being moved or deleted; the new
move/delete hook (described in a separate proposal) is useful in this regard.<p>Note
that other plug-ins are not is a similar position because team-private member marks
are not recorded
in team repositories. If a non-Team provider plug-in was to set this flag, the
resource does disappear from general view in the workspace. The hiding is only
for that workspace, however. When a resource propagates to another workspace via
a Team repository, the team-private member flag does not propagate along with
it. Thus, <i>this mechanism cannot be used by other plug-ins to hide their resources.</i>
<p>The workbench resource navigator does not show team-private members by
default, although the user can ask to see team-private members if they want
(similar to the way &quot;.*&quot; metadata resources are hidden from the user
by default). The user can see (but not change) a resource's team-private member flag via
the Properties dialogs. It does not warrant anything more obvious as users are unlikely to ever be interested in this property.
The user is not allowed to
change the setting is this flag.</p>
<p>Problems addressed:
<ul>
<li>
Team providers can include additional files and folders in a project without
impacting normal plug-in clients.</li>
</ul>
<h2>
Java builder resource file copying</h2>
The Java incremental project builder copies resource files from source
folders to the Java project's output folder. This allows the runtime classpath
to be shorter, and makes the output folder more closely resemble a typical
JAR contents used when deploying a Java program.
<p>However, this resource copying can have undesirable consequences when
it copies files willy-nilly to the output folder, and can create a situation
that confounds the user who peers into the project's output folder.<p>The proposal is for JDT to provide a mechanism for excluding certain
files from being copied. This would take the form of a list of file name
patterns to be excluded. This would make it easy to exclude files with certain names (e.g.,
&quot;*_EN_US.properties&quot;) or certain types of files (e.g., "*.antlr"). The list would be primed with
the pattern ".*", which would exclude all folders and files matching the
common Eclipse metadata naming convention. Through the UI, users would
be able to remove this pattern if it was too strong, and add additional
patterns to exclude other files.
<p>Note that the derived bit is unsuitable for controlling JDT copying behavior
(a derived resource file might very well need to be copied to the output folder).
<p>A global list of exclusion patterns would be persisted by JDT core.
This information would remembered with the workspace as JDT Core metadata
(it would not be in the .classpath file, and would not be shareable across
workspaces).
<p>Problems addressed:
<ul>
<li>
The JDT builder would no longer have to copy all resources to the output
folder. The user could better control this copying behavior.</li>
<li>
The &quot;.*&quot; default pattern will prevent metadata files from being copied
into the output folder, thereby reducing one common source of user confusion.</li>
<li>
Note that Team provider-specific files (e.g., &quot;CVS&quot; folders) would be invisible
under another proposal, so these would not be an issue.</li>
</ul>
<h2>
Other issues</h2>
<h3>
Project archive files</h3>
Given the project
description is reified as a file in the project, there is no longer as great a
need for a special form of project archive. Users can create a zip archive
containing the project's resources, which would now include its .project file.
After unzipping into the local file system, the project can be added to a
different workspace.&nbsp;
<h3>
Read-only projects</h3>
No changes are planned to support read-only projects.
<p>The notion of a read-only Eclipse project is somewhat of an oxymoron. An
Eclipse project is for doing work, and must be located in a read-write
file system. The binary library projects employed by Java development tooling
are an admitted abberation to facilitate people working on large-scale
products spread across several related Eclipse projects. The idea is that
it is easy for the user to replace a binary library project in their workspace
with the real, source code project from a team repository if for some reason
they decide to do so.
<p>PDE uses binary library projects for plug-ins. For self-hosting convenience,
PDE provides the option to locate an Eclipse plug-in project directly in
the directory where the plug-in is installed. Doing so requires creating
additional files in that directory (including JDT's .classpath file), and
can only be done when the plug-ins are installed in a read-write directory.
For shared plug-in installs on, or plug-in installs on read-only drives,
there is no option but to have PDE create projects elsewhere and copy over
the necessary files from the plug-in.
</body>
</html>