EMF Compare/Logical model support
The goal is here to provide a decent implementation of what is called "logical model" in Eclipse. The word "model" in "logical model" has nothing to do with the EMF concept of model. Sometimes in this document, we'll talk about logical resources interchangeably.
For more details about how logical model support has to be implemented relating to Team, you should read the document Team Support for Logical Model Integration.
We have implemented two of three extension point from the Team Support for Logical Model Integration document. We managed to be called by CVS by adding an "enablement" (it is valued to false by default).
We then tested the three SCM shipped with Eclipse release trains: CVS, SVN, Git. Conclusions are:
- CVS: the code is called consistently from everywhere (Compare With, Synchronize, Commit, Update, ...)
- SVN (Subversive): the code is only called from the "Synchronize with repository" action on a folder. Compare With/Synchronize on a single file does not call it.
- Git: tested with a local and distant repository. We are (consistently) called from nowhere: push, pull, revert, fetch, compare with, diff...
The API give us the ability to solve some problems we already (mis)addressed with the "Compare entire resource set" action. Sadly, it is not compatible with this behavior. We may not any longer be able to give the choice to the user between the comparison of the single resource and the entire resource set. This legacy action has been implemented to simulate something similar to the logical models (do a resolveAll, see that more than one resource is loaded and try to ask to the team API to give us those other resources in the well suited revision...). So far, these two mechanism could not co exist in EMF Compare. Eventually, replacement of the legacy action by logical models should give us the ability to insure the integrity of merge, update, commit... operations (i.e. no more model corruption).
The logical model support is great piece of engineering. Out of team, it is called on delete, move, save... actions. In team, it is called from everywhere in CVS (commit, update, synchronise...). Actions on fragmented models can really be applied atomically. But:
- To fullfil the contract of logical model, we will need to browse the whole EMF model three times during each [commit/update/...] operations: local, remote and ancestor. For instance, let's have a model A depending on local fragment B and C. I select A and ask to commit it. We need to browse it entirely to discover its two fragment B and C, then we need to get A' on the server, browse it to discover its two fragment B' and C' , download those two fragments and browse them to check if they do not depend on other fragments. Then, we have to do the same thing with the ancestor of A and A'. It can be very time consumming on very big models.
- Computation is done outside EMF Compare. We have to determine what is given to EMF Compare in the case we have this kind of thing as input. Moreover, is it really feasible to accept ResourceMapping instead of Resource with our current architecture? Currently, EMFCompare is computing the differences when the comparison editor is opening... this may be too late. Eclipse Compare should provide a specific API to compute the diff before the opening of the editor... We have to investigate on this side.
- The API of logical models is happening before comparison algorithm. We then have to define how to isolate "scopedMapping" algorithms et linked resources searching within EMF Compare. ScopedMapping contributed last year by Itemis must be adapated to fit our future implementation of logical models.
We are now sure that logical model support in EMF Compare will not be compatible with 1.x version. We have to do this in a new 2.0 (see after for more details).
By providing logical model support, we will provide much more than EMF Compare, it is a little bit more like an "EMF Team". Parts of current features implementations are to be reviewed:
- Resource Filtering: we no longer need to try to handle binary identical resources. We are now able to tell which IResource are parts of a logical model and which ones do contain changes and this before EMFCompare match/diff operations calls (even if the root is binary identical to the one on the SCM, case that coudl not be supported before). This feature must be deleted, and it is an API break (and feature break, it was extensible by extension point).
- Scoped matching: numerous changes had been done to be able to ignore some resources/elements during the matching phase. This feature may have to be changed as resource loading is not done at the same place anymore. We may need to remove all resource-specific scoping from this feature as our need is to make models operations atomic.
- Single-resource comparison: EMF Compare offered the ability to compare only a single resource or an entire resource set. "Resource only" must not be done if we want to insure the atomicity of the operations and avoid the corruption of models.
We had two options for this second prototype: explode everything (mark match & diff as deprecated) and do something clean by only using Eclipse APIs for the whole comparison, either load the three resourceSet (local, remote, ancestor) when Eclipse is asking for the logical model, then give those three resourceSets to the current EMF Compare API, retrieve the diff model, and then adapt it to the Eclipse API. We chose the second one to keep the largest backward compatibility.
This second prototype does not affect the comparison only, but every operations on resources within the workspace. For the special case of comparison, it is not done at the same time as previously: it was done during the opening of the comparison editor (after the opening in fact, when the setInput was called). Now it is done before that, when the comparison editor configuration is created. It may raise issues with the current implementation if some references were done to the editor. Also, our comparison triggers are not the same: we must not react to the setInput call or to the input change... but let Eclipse tell us when to compare. We have also to investigate how is it compatible with our specific merge API related to the Eclipse API.
Notice: We do not had a look to what is done in Eclipse 4 regarding those APIs.
Until EGit has integrated logical model support, this implementation will be working on CVS only (and msot probably on ClearCase, as the logical model API comes from IBM ;)).
We made some tests on this second prototype.
We had a file named "My.library" depending on the file "My.books". Those two files are committed on a CVS repository. Then, we locally rename the file "My.books" into "books.books", et we rename the Library EObject wihtin "My.library" file from "Libra" to "Scopio". We tested two scenarios:
We then attempted to commit "My.library" as depicted on the following picture:
A dialog opened (picture below) to force us to commit "My.library" and "books.books". Even it is not displayed, "My.books" is also part of the commit and will be deleted on the repository.
We attempted to replace "My.library" (picture below)
The same dialog box opened to force the update of the three files. The results of the replace operation is depicted on the following picture. The file books.books is deleted and replaced by "My.books", and "My.library" is rollbacked to its previous state (before the renamming of the library from "Libra" to "Scropio"). The whole model had not been corrupted.
Development occurs on https://github.com/eclipse/emf.compare/tree/logical_resources