Community
Participate
Working Groups
CCing Ed Merks as I am only half sure this is an EGit bug :p. I have a cloned repository somewhere on my disk, and an Eclipse workspace somewhere else. I import the projects from my git repository through the EGit Repository View's right-click > Import Projects... action. Thus the projects are not physically located in the workspace directory, but linked. Now If I open one of my models' history (right-click the model > Show In History), select a commit, then double-click (or right-click > Open In Editor) the model in the "file changed" area (bottom right of the history view), I get a "FileNotFoundException" with the trace pasted below. This exception does not happen with files other than models (I tested java, properties, plugin.xml, html, ant), it happens with _all_ models though : ecore, uml, custom metamodel... I still raise this against EGit as I believe the URL passed for this file is wrong : "plugins\org.eclipse.emf.compare.diff\model\diff.ecore" indeed does not exist in the workspace (as it stands, in the workspace, it should be "org.eclipse.emf.compare.diff\model\diff.ecore") ... it only exists in my cloned repository's folder. Not sure how other plugins handle "linked" files and folder though. I'll let you and Ed decide on the actions :). This bug can be observed with the following combinations : Window 7 - Eclipse 3.7 - EMF 2.7 - EGit 1.0.0 Window 7 - Eclipse 3.7 - EMF 2.7 - EGit "master" version retrieved from the repo Linux - Eclipse 3.6.2 - EMF 2.6.1 - EGit 1.0.0 java.io.FileNotFoundException: plugins\org.eclipse.emf.compare.diff\model\diff.ecore (Le chemin d’accès spécifié est introuvable) at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(Unknown Source) at org.eclipse.emf.ecore.resource.impl.FileURIHandlerImpl.createInputStream(FileURIHandlerImpl.java:105) at org.eclipse.emf.ecore.resource.impl.ExtensibleURIConverterImpl.createInputStream(ExtensibleURIConverterImpl.java:350) at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1262) at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoad(ResourceSetImpl.java:255) at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoadHelper(ResourceSetImpl.java:270) at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResource(ResourceSetImpl.java:397) at org.eclipse.emf.ecore.presentation.EcoreEditor.createModelGen(EcoreEditor.java:1062) at org.eclipse.emf.ecore.presentation.EcoreEditor.createModel(EcoreEditor.java:1082) at org.eclipse.emf.ecore.presentation.EcoreEditor.createPages(EcoreEditor.java:1147) at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:348) at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:670) at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:465) at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:595) at org.eclipse.ui.internal.PartPane.setVisible(PartPane.java:313) at org.eclipse.ui.internal.presentations.PresentablePart.setVisible(PresentablePart.java:180) at org.eclipse.ui.internal.presentations.util.PresentablePartFolder.select(PresentablePartFolder.java:270) at org.eclipse.ui.internal.presentations.util.LeftToRightTabOrder.select(LeftToRightTabOrder.java:65) at org.eclipse.ui.internal.presentations.util.TabbedStackPresentation.selectPart(TabbedStackPresentation.java:473) at org.eclipse.ui.internal.PartStack.refreshPresentationSelection(PartStack.java:1245) at org.eclipse.ui.internal.PartStack.setSelection(PartStack.java:1198) at org.eclipse.ui.internal.PartStack.showPart(PartStack.java:1597) at org.eclipse.ui.internal.PartStack.add(PartStack.java:493) at org.eclipse.ui.internal.EditorStack.add(EditorStack.java:103) at org.eclipse.ui.internal.PartStack.add(PartStack.java:479) at org.eclipse.ui.internal.EditorStack.add(EditorStack.java:112) at org.eclipse.ui.internal.EditorSashContainer.addEditor(EditorSashContainer.java:63) at org.eclipse.ui.internal.EditorAreaHelper.addToLayout(EditorAreaHelper.java:225) at org.eclipse.ui.internal.EditorAreaHelper.addEditor(EditorAreaHelper.java:213) at org.eclipse.ui.internal.EditorManager.createEditorTab(EditorManager.java:808) at org.eclipse.ui.internal.EditorManager.openEditorFromDescriptor(EditorManager.java:707) at org.eclipse.ui.internal.EditorManager.openEditor(EditorManager.java:666) at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2942) at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2850) at org.eclipse.ui.internal.WorkbenchPage.access$11(WorkbenchPage.java:2842) at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2793) at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2789) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2773) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2764) at org.eclipse.egit.ui.internal.EgitUiEditorUtils.openEditor(EgitUiEditorUtils.java:114) at org.eclipse.egit.ui.internal.EgitUiEditorUtils.openEditor(EgitUiEditorUtils.java:100) at org.eclipse.egit.ui.internal.EgitUiEditorUtils.openEditor(EgitUiEditorUtils.java:66) at org.eclipse.egit.ui.internal.history.CommitFileDiffViewer.openFileInEditor(CommitFileDiffViewer.java:352) at org.eclipse.egit.ui.internal.history.CommitFileDiffViewer.access$0(CommitFileDiffViewer.java:341) at org.eclipse.egit.ui.internal.history.CommitFileDiffViewer$4.run(CommitFileDiffViewer.java:192) at org.eclipse.jface.action.Action.runWithEvent(Action.java:498) at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:584) at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:501) at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:411) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4165) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3754) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2696) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2660) at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2494) at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:674) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:667) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577) at org.eclipse.equinox.launcher.Main.run(Main.java:1410) at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
I'm curious as to why EMF is trying to open a file (presumably to read it) when we are already providing the editor with a direct InputStream to the contents with an implementation of the IStorageEditorInput interface.
The generated editors always expect a URI that can be passed to the resource set's URI converter. URI resourceURI = EditUIUtil.getURI(getEditorInput()); Exception exception = null; Resource resource = null; try { // Load the resource through the editing domain. // resource = editingDomain.getResourceSet().getResource(resourceURI, true); } catch (Exception e) { exception = e; resource = editingDomain.getResourceSet().getResource(resourceURI, false); } The templates would need to handle the case there the editor input itself provides the input stream. All cross document references would be broken though, which would very often make the editors quite useless even as a viewer of the model... Why doesn't Egit support org.eclipse.team.core.history.IFileRevision adapters?
(In reply to comment #2) > The generated editors always expect a URI that can be passed to the resource > set's URI converter. Decoupling from EMF: The platform has an excellent system for normalizing workspace content using platform:/resource, and this mechanism is robust enough to avoid the problems that might have arisen through multiple GIT repositories fragmenting a previously flat workspace. Since the platform normalization works, it is very important that GIT respect it. In the "plugins\org.eclipse.emf.compare.diff\model\diff.ecore" example, "plugins" is a repository artefact that must not appear in the normalized representation. [Surely this bug is at least "major"?]
Both EMF and EGit are offenders here. From the EMF side, we are totally ignoring that the input of our editor can be a file which no longer exists in the workspace, or simply an older revision of the file that's in the workspace. The problem lies in EcoreEditor#createModelGen() which simply retrieves the URI from the editor input (URI resourceURI = EditUIUtil.getURI(getEditorInput());) and loads that URI, totally ignoring the input stream / IStorage attached to the input (input instanceof IStorageEditorInput). This is even more absurd considering that EMF _knows_ that this given editor input is a file revision (EclipseUtil#getURI(IEditorInput) : reflexive calls to IFileRevision#getURI() ... ignoring IFileRevision#getStorage(), which holds the _real_ content the user wanted to open). Of course, acknowledging that this kind of input exists means that EMF should be able to resolve references towards distant revision and/or ignore these and leave proxies unresolved. (If I load a version of ecore.genmodel corresponding to march 2012, resolving its references towards ecore.ecore should _also_ resolve the state ecore.ecore had on march 2012. Another option would be to give a more useful error message to the user since we can detect the offending use case... From the EGit side, the paths used are totally unresolvable by any Eclipse plugin. If I have a project named "EcoreModels", located on disk in a folder named "sampleProject" (the project name can be different from its location on disk), which contains a model in path "models/sample.ecore", everything "contained" by a git clone named "sandbox", EGit will use the path on disk : "sandbox/sampleProject/models/sample.ecore". No Eclipse plugin can resolve that without explicitely depending on EGit (and even like that, I doubt it will be able to find the corresponding "IResource"). EMF (and most eclipse plugins) will see that path as "platform:/resource/sandbox/sampleProject/models/sample.ecore". There is no way to resolve that either. I don't know what the right course of action is. A good start would be for EGit to return proper Eclipse URIs whenever it can be returned by its integration with outside API, such as Team IFileRevision#getURI(). In the current state of affairs, it is quite hard for any third-party plug-in to interact with EGit without explicitely depending on it.
(In reply to comment #4) > Both EMF and EGit are offenders here. > > From the EMF side, we are totally ignoring that the input of our editor can > be a file which no longer exists in the workspace Perhaps there may be a greater CDO domain in which non-existing EMF URIs have some useful meaning. > From the EGit side, the paths used are totally unresolvable by any Eclipse > plugin. I think that this should be a critical EGIT bug to which widespread publicity is given if a fastish response does not seem to be forthcoming. If EGIT paths are not fixed quickly we will find a dilemma whereby there is already legacy code depending on the bad paths. Must be fixed in Kepler.
Yes, I would expect that like for CVS this call would return a URI we can use to access the revision. return URI.createURI(((java.net.URI)FILE_REVISION_GET_URI_METHOD.invoke(fileRevision)).toString()); I would expect egit would register with the EFS its scheme for accessing storage so that as for CVS, the EFS-based URI handler would just work: org.eclipse.emf.ecore.resource.impl.EFSURIHandlerImpl.createInputStream(URI, Map<?, ?>)
(In reply to comment #5) > > From the EMF side, we are totally ignoring that the input of our editor can > > be a file which no longer exists in the workspace > > Perhaps there may be a greater CDO domain in which non-existing EMF URIs > have some useful meaning. I have not even the least bit of a clue what this is supposed to mean. Can you please elaborate?
(In reply to comment #7) > (In reply to comment #5) > > > From the EMF side, we are totally ignoring that the input of our editor can > > > be a file which no longer exists in the workspace > > > > Perhaps there may be a greater CDO domain in which non-existing EMF URIs > > have some useful meaning. > > I have not even the least bit of a clue what this is supposed to mean. Can > you please elaborate? I'm not sure I understand either. I was just suggesting that because CDO has more powerful Resource location mechanisms, it may have more interesting URIs.
(In reply to comment #6) > Yes, I would expect that like for CVS this call would return a URI we can > use to access the revision. > > return > URI.createURI(((java.net.URI)FILE_REVISION_GET_URI_METHOD. > invoke(fileRevision)).toString()); > > I would expect egit would register with the EFS its scheme for accessing > storage so that as for CVS, the EFS-based URI handler would just work: > > org.eclipse.emf.ecore.resource.impl.EFSURIHandlerImpl.createInputStream(URI, > Map<?, ?>) I did not know this worked with CVS, though I remember seeing the EFSURIHandler at times. However, I do not think this would work for EGit, as it has its own peculiarities... If I understand correctly how things work in Git/EGit/JGit, a given file may not be accessed for just any commit. Let's suppose I commit : file F1 and file F2 (both ecore files, F2 referencing F1) with commit C1, then F2 (changed) with commit C2. In this case F1 does not "exist" within commit C2. Then, if EGit gives EMF an input to load the version of F2 corresponding to C2 (with a git specific uri such as "git:/git.eclipse.org/sample.git,C2,models/F2") : EMF "sees" a relative reference to "F1". The way EMF resolves its URIs, it will think it can access F1 through the same URI : "git:/git.eclipse.org/sample.git,C2,models/F1" ... but that URI does not point to an existing file since F1 does not exist in C2; we would have needed to find that the latest version of F1 was in "C1". I might be wrong when I say that EGit cannot serve F1 when we try with a commit that did not directly affect it. I might also be wrong when I say that EMF cannot determine the exact URI at which it can find F1. Though I think I am pretty close to the truth.
Yes, EFS is a general way to handle additional schemes in a way that's well integrated with Eclipse... Of course everything has it's own peculiarities! :-P I imagine that git can do a better job than could CVS because related changes are committed as a composite so in theory at least you can always see the full state at any commit point. After all, you can check it out and get that complete image in your working tree... For your specific example of two commits, it's still the case that you could get a full working tree for the state after commit C1 as well as that for the state after commit C2. It is in such a working tree in which all references should resolve. CVS has nothing like this type of consistency... Ideally EGit would support something like this: git://<repo>/<commitID>:/<path-in-repo>. I.e., the repo is part of the authority as outline in the RFC http://www.ietf.org/rfc/rfc2396.txt That avoids it being used as part of a relative path (also as defined in the RFC). The commit ID also needs to be encoded either as part of the authority or as I showed above where it's represented more like a device (which is more an EMF URI specific thing to ensure that in something like file:/c:/<path> the c: is handled more like an authority that prevents relative paths from using that as a segment, i.e., you'd never get a relative path like ../../c:/<path> when deresolving URIs (where the deresolving process is also specified in the RFC). With this approach, relative references within committed file contents would always be resolved to the state of the repo for that same commit. And yes, you are correctly identifying the core problem. I think the above approach would complete address such a problem, not just for EMF but in a way that conforms well with how the RFC directs the representation and interpretation of URIs in general. If the scheme used with the team provided followed this approach, and that scheme was properly registered with EFS you could anticipate that not only EMF would work well, but any XML processor would work well, e.g., you could expect to open a brower on an HTML-based resource and could anticipate that relative references to other HTML resources would resolve correctly to the correct state for the commit. All that seems like goodness to strive for...
(In reply to comment #10) > And yes, you are correctly identifying the core problem. I think the above > approach would complete address such a problem, not just for EMF but in a > way that conforms well with how the RFC directs the representation and > interpretation of URIs in general. If the scheme used with the team > provided followed this approach, and that scheme was properly registered > with EFS you could anticipate that not only EMF would work well, but any XML > processor would work well, e.g., you could expect to open a brower on an > HTML-based resource and could anticipate that relative references to other > HTML resources would resolve correctly to the correct state for the commit. > All that seems like goodness to strive for... I can confirm that this would also solve the issue on my (EMF Compare) end.
(In reply to comment #10) > Yes, EFS is a general way to handle additional schemes in a way that's well > integrated with Eclipse... > > Of course everything has it's own peculiarities! :-P > > I imagine that git can do a better job than could CVS because related > changes are committed as a composite so in theory at least you can always > see the full state at any commit point. After all, you can check it out and > get that complete image in your working tree... > > For your specific example of two commits, it's still the case that you could > get a full working tree for the state after commit C1 as well as that for > the state after commit C2. It is in such a working tree in which all > references should resolve. CVS has nothing like this type of consistency... > > Ideally EGit would support something like this: > > git://<repo>/<commitID>:/<path-in-repo>. this should be easily possible, use a RevWalk to traverse history till the commit you are looking for and then use a TreeWalk to navigate the committed file tree as it was at the time when the commit was created. > > I.e., the repo is part of the authority as outline in the RFC > > http://www.ietf.org/rfc/rfc2396.txt How would you identify <repo> in a unique unambiguous way ? You may have multiple clones of the same repository on your disk. > That avoids it being used as part of a relative path (also as defined in the > RFC). The commit ID also needs to be encoded either as part of the authority > or as I showed above where it's represented more like a device (which is > more an EMF URI specific thing to ensure that in something like > file:/c:/<path> the c: is handled more like an authority that prevents > relative paths from using that as a segment, i.e., you'd never get a > relative path like ../../c:/<path> when deresolving URIs (where the > deresolving process is also specified in the RFC). With this approach, > relative references within committed file contents would always be resolved > to the state of the repo for that same commit. > > And yes, you are correctly identifying the core problem. I think the above > approach would complete address such a problem, not just for EMF but in a > way that conforms well with how the RFC directs the representation and > interpretation of URIs in general. If the scheme used with the team > provided followed this approach, and that scheme was properly registered > with EFS you could anticipate that not only EMF would work well, but any XML > processor would work well, e.g., you could expect to open a brower on an > HTML-based resource and could anticipate that relative references to other > HTML resources would resolve correctly to the correct state for the commit. > All that seems like goodness to strive for...
I imagine in the context of an Eclipse environment you have all the context information needed. I.e., you have clones in your Git Repositories view and you know you're working with those. When the team provider creates the URI, it knows exactly which thing in which clone it's dealing with with it creates the URI. Those URIs used with EFS also know this same Eclipse context so it seems a question of how you produce a URI that when handed back to EFS will allow you to identity the clone that you referenced when the URI was manufactured. One significant wrinkle (limitation) here is that references across workspace projects will generally use relative URIs based on each project being rooted in the workspace, but in the git repo, not all projects are rooted at the same folder, i.e., they'll typically be of the form ../{../}*/<project-name>/<path>/<file>.
I don't suppose this will ever be addressed directly be egit. With the changes for https://bugs.eclipse.org/bugs/show_bug.cgi?id=434808, at least the editor can open the direct resource, but cross references don't work. *** This bug has been marked as a duplicate of bug 434808 ***