Open eposse opened 6 months ago
When doing a comparison or a merge, the Eclipse Compare framework has to decide how to display the elements being compared, and in particular, it has to create viewers for the left hand-side, right hand-side and possibly the common ancestor or origin. This is done on-demand, by trying to find the appropriate "content viewer". This is done by looking for a "content viewer descriptor", which is selected based on the content type. The content viewer descriptors exist in one of several "content registries", associating content types or "extensions" (i.e. file extensions or other symbolic extension names) to descriptors. These are registered via plug-in extension points. Depending on the descriptor, you get the right kind of viewer.
But finding the viewer descriptor, depends on the content type. And the content type depends on the input to the comparison, and this input has three parts: left, right and common ancestor. This will be resources, but they can be stored in different ways. When the comparison is initiated from the Git History View with "Compare to Each Other", the files are stored in commits. But when the comparison is done with "Compare with Workspace Version" or in the "Synchronize View" (launched from the Project Explorer with right-click "Compare with ..." option), one of the sources (typically the left side) is going to be the local workspace. And this makes a difference, because that determines which resources are discovered to determine the content type. In both cases, the content of a .uml file will be a "Model Type", but in order to pick the Papyrus Compare viewer, it has to determine that the "context" is a Papyrus context, which means that the .uml file has a corresponding .di file. When checking the local workspace, it finds it without a problem, but when checking a git commit, it doesn't (unless the .di file is explicitly in the commit). So in the later case, it determines that the content type is a Model Type but not a Papyrus Context Content Type, and therefore it selects the generic EMF Compare viewer descriptor and therefore the generic EMF Compare viewer, instead of the correct Papyrus Compare viewer.
Now, the key thing here is why it doesn't find the .di file when checking the commit? The reason is that the .di file is not in the commit. A component of EMF Compare, called the ModelResolver is responsible for building the "Comparison Scope", the collection of all resources needed for the comparison. And it is this comparison scope the one that is used to determine if the context is a Papyrus context or not. So the issue is that in the case of a git commit, the model resolver doesn't find the .di file.
This means that we might have to make changes to the ModelResolver in order to detect .di files even when they are not in the commit. I do not know if that is possible yet. But the good news is that it is possible to override the ModelResolver via an extension point.
I haven't posted anything here in a while, but I've been working on this issue all this time, and I wanted to try to give a status update. But first, the reason I haven't posted or committed anything yet is because this bug turned out to be extremely tricky as it involves several tools: Eclipse Team, Eclipse Compare, EMF Compare, Papyrus Compare, Papyrus and EGit, and the interaction between all these. I will not go into a full explanation of the problem, as there are too many details and too many elements at play, so I will just try to summarize and give an overview.
First, we need to understand the context and the scenarios in which this bug occurs, as well as its consequences.
As the title suggests, this bug has to do with model comparison (and merge). There are two main ways to compare (and merge) models in Papyrus CX: (1) using the "Synchronize View", and (2) using EGit. The "Synchronize View" is used when the user selects a model in the Project Explorer, right-clicks and selects "Compare With...". The EGit approach is invoked when the user opens the "Git History View", selects one or two commits, right-clicks and then selects one of the "Compare ..." options.
This bug arises when using EGit (2).
Approach (1) is the original way provided by Eclipse, and it is implemented by a combination of the core "Eclipse Compare" functionality and the "Eclipse Team" plugins. It was originally designed to deal with Version Control Systems (VCS) such as CVS and SVN, long before git became mainstream and EGit existed. This turns out to be important. In particular, it only supports comparing something that you have opened in the workspace with either something else in the workspace, or something in the "remote repository". But this doesn't match well with the git approach to VCS, where you have a local copy of the remote repository (or even just a local repository), and where you can compare things that are not checked out. More on this later.
So Eclipse Compare provides the generic "compare" logic and UI, and was originally designed for the purpose of comparing text files such as source code. The Eclipse Team feature was designed to provide support for collaborative development by providing a UI for managing code repositories from traditional VCS systems (CVS, SVN). Later, EMF Compare was introduced to support compare/merge of EMF models. EMF Compare included extensions to Eclipse Compare and Eclipse Team, to integrate it with the UI. Separately, EGit introduced git support to Eclipse, both using a Java re-implementation of git called JGit and providing the UI, integrating with Eclipse Compare and Extending Eclipse Team to support Git repositories. Finally there is Papyrus Compare, which extends EMF Compare with support for Papyrus UML models and profiles. This is because, while UML models are EMF models, they are richer, and viewing them as simply EMF models is taking a relatively low-level perspective. The idea is that for a modelling tool based on Papyrus, when comparing models, the user shouldn't have to deal with EMF details, and only see the model at the UML level. Furthermore, it adds a "visual compare" viewer, so that a user can compare not only the tree-structure of the models, but also the diagrams.
Now, here's the heart of the problem: Papyrus Compare was designed to support approach (1), comparisons with the traditional "Synchronize View" from Eclipse Team, but it was not designed to support approach (2), comparisons using EGit. While Papyrus Compare sort of works with EGit, the lack of direct support meant that when a user tries to compare models from EGit, they get a different and possibly confusing user experience. For example, while they will see a model comparison as provided by EMF, that shows the differences at the EMF level, those differences may appear slightly different (or very different) from the ones shown using approach (1). Furthermore, the user may not always be able to see diagram differences. Now, while these differences might be minimal or very subtle in many cases, internally it means that when a comparison is made, the exact behaviour is very different depending on whether it was triggered by an action in (1) or an action in (2). This means that debugging model compare issues is quite tricky and depends significantly on which approach was used to trigger the comparison.
From what I have been investigating, it seems like at least part of the reason for why Papyrus Compare doesn't provide direct support for EGit has to do with how Eclipse Compare, Eclipse Team and EMF Compare were designed to support older systems like CVS and SVN, rather than git. In particular, in older versions (the ones included with Papyrus 4.8, the basis of Papyrus CX 2.X), include code in Eclipse Compare, Eclipse Team and EMF Compare, that hard-codes the kinds of input editors used, disallowing the editors provided by EGit. And the code that contains such logic cannot be overriden by a plugin extension. It can only be modified by a patch. More recent versions (the ones included in Papyrus 6.5, the basis of Papyrus CX 3.X) do seem to allow some of that logic to be overriden by a plugin extension.
Another element that is fundamental to this issue is what I alluded before regarding comparisons of models that are not checked out into the workspace. As I said before, approach (1) only allows you to compare something that exists and is open in the local workspace with something else, in the workspace or in a repository (say a specific commit). On the other hand, when using approach (2), it is natural to be able to compare files or models from two different commits even if neither of them is checked out and imported in the local workspace. However, after a very long investigation, I have been able to determine that none of the tools (Eclipse Compare, Eclipse Team, EMF Compare, or Papyrus Compare) will work properly in approach (2) unless at least one of the models and its dependent files exist in the workspace. In Papyrus a model is stored as a set of at least three files: a .di, a .uml and a .notation file. These are the dependent files. In order to activate Papyrus Compare for a model, it needs to determine that it the file selected is indeed a Papyrus model, which means that the dependent files must be present. The problem with EGit is that typically not all the dependent files may be present in a commit selected for comparison. For example, if you select a commit where you changed only a structural aspect, then the commit will contain only the .uml file, but not the .notation or .di files. This means that from the point of view of EMF Compare, you are comparing only a .uml file, not a Papyrus model, so it activates the standard EMF Compare viewers, instead of the Papyrus Compare viewers.
To address this, I have implemented a logic that tries to look for dependent files in the repository by traversing the selected commit's history. I have now partial success with this, but it still requires the counterparts to exist in the workspace. So while it is not a fully satisfactory resolution, it seems like the best possible available now. I am not yet sure if this can be fully resolved, but at least I have now a partial solution, which I'm in the process of integrating and testing. I should be able to commit it in the next week or two.
Thank you for all of this information. It is discouraging, yet again, to see another part of Eclipse so unmaintained that it doesn't work with modern-ish technologies like Git. I appreciate your perseverance on this issue as it is a large issue for us and a solution could make a big difference in our development.
Another update. While my partial solution seems to pick up the Papyrus ContentMergeViewer when using EGit, it fails to detect differences, even if the model is in the workspace. So it seems like the solution doesn't really work. I'm investigating.
Issue and tracking information
Developer's time Estimated effort to fix (hours):
Developer's Actual time spent on fix (hours)
Issue reporter to provide a detailed description of the issue in the space below
When performing a comparison of two commits in the Git History view provided by EGit, the side-by-side panel meant to show the model from the two commits uses the default EMF Compare ContentMergeViewer, instead of the customized PapyrusTreeContentMerge viewer. This has several consequences: