Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDariusz Luksza2011-11-30 00:18:48 +0000
committerMatthias Sohn2011-11-30 00:18:48 +0000
commit67f237ca0658dcd6ec2eef95dfe294578b2598ce (patch)
tree1802fc65df659f4415bd91589386855c14dee65d /org.eclipse.egit.ui/src
parent610529ce63191db6c8a2eb23a7d98968bfbd79db (diff)
downloadegit-67f237ca0658dcd6ec2eef95dfe294578b2598ce.tar.gz
egit-67f237ca0658dcd6ec2eef95dfe294578b2598ce.tar.xz
egit-67f237ca0658dcd6ec2eef95dfe294578b2598ce.zip
Allow to move changes in compare editor
All compare editors that compares working tree version against version in index can now move particular hunk from left to right and other way around. All changes are persisted to file system/git index after saving compare results. To add this functionality we need to wrap team's specific OpenInCompare action into our own (GitOpenInCompare) action, because team framework forces right hand side to be always read only. We want this writable instead since we want to move changes from working copy to git index. Also removes EditableSharedDocumentAdapter and LocalResourceTypedElement copied from Team Framework because of "instanceof" checks during compare editor create and save actions. Change-Id: Ib38ee2d05934aa0f5cb9ddec9b5be91cbbe38759 Signed-off-by: Dariusz Luksza <dariusz@luksza.org> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.egit.ui/src')
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java254
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableRevision.java1
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableSharedDocumentAdapter.java208
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitCompareFileRevisionEditorInput.java4
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/LocalResourceTypedElement.java336
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareIndexWithHeadActionHandler.java8
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexActionHandler.java120
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryActionHandler.java5
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitActionContributor.java20
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/action/GitOpenInCompareAction.java120
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCacheCompareInput.java20
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCompareInput.java2
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitLocalCompareInput.java72
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java167
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheFile.java7
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelWorkingFile.java12
17 files changed, 577 insertions, 782 deletions
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java
index 3f68f818df..aba0e91fba 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java
@@ -9,15 +9,23 @@
* Contributors:
* Dariusz Luksza - add getFileCachedRevisionTypedElement(String, Repository)
* Stefan Lay (SAP AG) - initial implementation
+ * Yann Simon <yann.simon.fr@gmail.com> - implementation of getHeadTypedElement
*******************************************************************************/
package org.eclipse.egit.ui.internal;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import org.eclipse.compare.CompareEditorInput;
import org.eclipse.compare.CompareUI;
+import org.eclipse.compare.IContentChangeListener;
+import org.eclipse.compare.IContentChangeNotifier;
import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.structuremergeviewer.DiffNode;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.compare.structuremergeviewer.IStructureComparator;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
@@ -35,13 +43,17 @@ import org.eclipse.egit.core.internal.storage.WorkspaceFileRevision;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIText;
+import org.eclipse.egit.ui.internal.actions.CompareWithCommitActionHandler;
import org.eclipse.egit.ui.internal.merge.GitCompareEditorInput;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
@@ -304,37 +316,6 @@ public class CompareUtils {
}
/**
- * Creates {@link ITypedElement} of file that was cached
- *
- * @param gitPath
- * @param db
- * @return {@link ITypedElement} instance for given cached file or
- * {@code null} if file isn't cached
- */
- public static ITypedElement getFileCachedRevisionTypedElement(String gitPath,
- Repository db) {
- try {
- DirCache dc = db.lockDirCache();
- DirCacheEntry entry = dc.getEntry(gitPath);
- dc.unlock();
-
- // check if file is staged
- if (entry != null) {
- GitFileRevision nextFile = GitFileRevision.inIndex(db, gitPath);
- String encoding = CompareCoreUtils.getResourceEncoding(db, gitPath);
- return new FileRevisionTypedElement(nextFile, encoding);
- }
- } catch (IOException e) {
- Activator.error(NLS.bind(UIText.GitHistoryPage_errorLookingUpPath,
- gitPath), e);
- }
-
- return new GitCompareFileRevisionEditorInput.EmptyTypedElement(NLS
- .bind(UIText.CompareWithIndexAction_FileNotInIndex,
- gitPath.substring(gitPath.lastIndexOf("/") + 1))); //$NON-NLS-1$
- }
-
- /**
* Opens a compare editor. The workspace version of the given file is
* compared with the version in the HEAD commit.
*
@@ -406,4 +387,215 @@ public class CompareUtils {
return headCommit;
}
+ /**
+ * Extracted from {@link CompareWithCommitActionHandler}
+ * @param baseFile
+ * @return typed element
+ * @throws IOException
+ */
+ public static ITypedElement getHeadTypedElement(final IFile baseFile)
+ throws IOException {
+ final RepositoryMapping mapping = RepositoryMapping.getMapping(baseFile);
+ final Repository repository = mapping.getRepository();
+ final String gitPath = mapping.getRepoRelativePath(baseFile);
+
+ DirCache dc = repository.lockDirCache();
+ final DirCacheEntry entry = dc.getEntry(gitPath);
+ dc.unlock();
+
+ IFileRevision nextFile = GitFileRevision.inIndex(repository, gitPath);
+ String encoding = CompareCoreUtils.getResourceEncoding(baseFile);
+ final EditableRevision next = new EditableRevision(nextFile, encoding);
+
+ IContentChangeListener listener = new IContentChangeListener() {
+ public void contentChanged(IContentChangeNotifier source) {
+ final byte[] newContent = next.getModifiedContent();
+ DirCache cache = null;
+ try {
+ cache = repository.lockDirCache();
+ DirCacheEditor editor = cache.editor();
+ if (newContent.length == 0)
+ editor.add(new DirCacheEditor.DeletePath(gitPath));
+ else
+ editor.add(new DirCacheEntryEditor(gitPath,
+ repository, entry, newContent));
+ try {
+ editor.commit();
+ } catch (RuntimeException e) {
+ if (e.getCause() instanceof IOException)
+ throw (IOException) e.getCause();
+ else
+ throw e;
+ }
+
+ } catch (IOException e) {
+ Activator.handleError(
+ UIText.CompareWithIndexAction_errorOnAddToIndex, e,
+ true);
+ } finally {
+ if (cache != null)
+ cache.unlock();
+ }
+ }
+ };
+
+ next.addContentChangeListener(listener);
+ return next;
+ }
+
+ /**
+ * Extracted from {@link CompareWithCommitActionHandler}
+ * @param actLeft
+ * @param actRight
+ * @return compare input
+ */
+ public static DiffNode prepareGitCompare(ITypedElement actLeft, ITypedElement actRight) {
+ if (actLeft.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ // return new MyDiffContainer(null, left,right);
+ DiffNode diffNode = new DiffNode(null,Differencer.CHANGE,null,actLeft,actRight);
+ ITypedElement[] lc = (ITypedElement[])((IStructureComparator)actLeft).getChildren();
+ ITypedElement[] rc = (ITypedElement[])((IStructureComparator)actRight).getChildren();
+ int li=0;
+ int ri=0;
+ while (li<lc.length && ri<rc.length) {
+ ITypedElement ln = lc[li];
+ ITypedElement rn = rc[ri];
+ int compareTo = ln.getName().compareTo(rn.getName());
+ // TODO: Git ordering!
+ if (compareTo == 0) {
+ if (!ln.equals(rn))
+ diffNode.add(prepareGitCompare(ln,rn));
+ ++li;
+ ++ri;
+ } else if (compareTo < 0) {
+ DiffNode childDiffNode = new DiffNode(Differencer.ADDITION, null, ln, null);
+ diffNode.add(childDiffNode);
+ if (ln.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)ln).getChildren();
+ if(children != null && children.length > 0) {
+ for (ITypedElement child : children) {
+ childDiffNode.add(addDirectoryFiles(child, Differencer.ADDITION));
+ }
+ }
+ }
+ ++li;
+ } else {
+ DiffNode childDiffNode = new DiffNode(Differencer.DELETION, null, null, rn);
+ diffNode.add(childDiffNode);
+ if (rn.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)rn).getChildren();
+ if(children != null && children.length > 0) {
+ for (ITypedElement child : children) {
+ childDiffNode.add(addDirectoryFiles(child, Differencer.DELETION));
+ }
+ }
+ }
+ ++ri;
+ }
+ }
+ while (li<lc.length) {
+ ITypedElement ln = lc[li];
+ DiffNode childDiffNode = new DiffNode(Differencer.ADDITION, null, ln, null);
+ diffNode.add(childDiffNode);
+ if (ln.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)ln).getChildren();
+ if(children != null && children.length > 0) {
+ for (ITypedElement child : children) {
+ childDiffNode.add(addDirectoryFiles(child, Differencer.ADDITION));
+ }
+ }
+ }
+ ++li;
+ }
+ while (ri<rc.length) {
+ ITypedElement rn = rc[ri];
+ DiffNode childDiffNode = new DiffNode(Differencer.DELETION, null, null, rn);
+ diffNode.add(childDiffNode);
+ if (rn.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)rn).getChildren();
+ if(children != null && children.length > 0) {
+ for (ITypedElement child : children) {
+ childDiffNode.add(addDirectoryFiles(child, Differencer.DELETION));
+ }
+ }
+ }
+ ++ri;
+ }
+ return diffNode;
+ } else {
+ return new DiffNode(actLeft, actRight);
+ }
+ }
+
+ /**
+ * Extracted from {@link CompareWithCommitActionHandler}
+ * @param elem
+ * @param diffType
+ * @return diffnode
+ */
+ private static DiffNode addDirectoryFiles(ITypedElement elem, int diffType) {
+ ITypedElement l = null;
+ ITypedElement r = null;
+ if (diffType == Differencer.DELETION) {
+ r = elem;
+ } else {
+ l = elem;
+ }
+
+ if (elem.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ DiffNode diffNode = null;
+ diffNode = new DiffNode(null,Differencer.CHANGE,null,l,r);
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)elem).getChildren();
+ for (ITypedElement child : children) {
+ diffNode.add(addDirectoryFiles(child, diffType));
+ }
+ return diffNode;
+ } else {
+ return new DiffNode(diffType, null, l, r);
+ }
+ }
+
+ private static class DirCacheEntryEditor extends DirCacheEditor.PathEdit {
+
+ private final Repository repo;
+
+ private final DirCacheEntry oldEntry;
+
+ private final byte[] newContent;
+
+ public DirCacheEntryEditor(String path, Repository repo,
+ DirCacheEntry oldEntry, byte[] newContent) {
+ super(path);
+ this.repo = repo;
+ this.oldEntry = oldEntry;
+ this.newContent = newContent;
+ }
+
+ @Override
+ public void apply(DirCacheEntry ent) {
+ ObjectInserter inserter = repo.newObjectInserter();
+ if (oldEntry != null)
+ ent.copyMetaData(oldEntry);
+ else
+ ent.setFileMode(FileMode.REGULAR_FILE);
+
+ ent.setLength(newContent.length);
+ ent.setLastModified(System.currentTimeMillis());
+ InputStream in = new ByteArrayInputStream(newContent);
+ try {
+ ent.setObjectId(inserter.insert(Constants.OBJ_BLOB,
+ newContent.length, in));
+ inserter.flush();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // ignore here
+ }
+ }
+ }
+ }
+
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableRevision.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableRevision.java
index b2bed95524..be2a09090e 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableRevision.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableRevision.java
@@ -24,6 +24,7 @@ import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.internal.ui.synchronize.EditableSharedDocumentAdapter;
/**
* @author simon
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableSharedDocumentAdapter.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableSharedDocumentAdapter.java
deleted file mode 100644
index c053208b2e..0000000000
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableSharedDocumentAdapter.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005, 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.egit.ui.internal;
-
-import org.eclipse.compare.SharedDocumentAdapter;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.texteditor.IDocumentProvider;
-import org.eclipse.ui.texteditor.IElementStateListener;
-
-/**
- * A shared document adapter that tracks whether the element is connected to a
- * shared document and whether the contents have been flushed from a compare
- * viewer. When contents are flushed, this adapter will connect to the document
- * provider to ensure that the changes are not lost (see
- * {@link #hasBufferedContents()}). In order to avoid a leak, the buffer must
- * either be saved (see
- * {@link #saveDocument(IEditorInput, boolean, IProgressMonitor)}) or released
- * (see {@link #releaseBuffer()}).
- * <p>
- * This adapter must have a one-to-one correspondence to a typed element.
- */
-class EditableSharedDocumentAdapter extends SharedDocumentAdapter
- implements IElementStateListener {
-
- private int connectionCount;
-
- private final ISharedDocumentAdapterListener listener;
-
- private IEditorInput bufferedKey;
-
- /**
- * Interface that provides this adapter with the state of the typed element
- * and supports call backs to the element when the adapter state changes.
- */
- public interface ISharedDocumentAdapterListener {
-
- /**
- * Method that is invoked when the adapter connects to the document
- * provider. This method is only invoked when the adapter first connects
- * to the document.
- */
- void handleDocumentConnected();
-
- /**
- * Method that is invoked when the adapter disconnects from the document
- * provider. This method is only invoked when the adapter no longer has
- * any connection to the document provider.
- */
- void handleDocumentDisconnected();
-
- /**
- * Method invoked when changes in the document are flushed to the
- * adapter.
- */
- void handleDocumentFlushed();
-
- /**
- * Method invoked when the file behind the shared document is deleted.
- */
- void handleDocumentDeleted();
-
- /**
- * Method invoked when the document dirty state changes from dirty to
- * clean.
- */
- void handleDocumentSaved();
- }
-
- /**
- * @param listener
- * access to element internals
- */
- public EditableSharedDocumentAdapter(ISharedDocumentAdapterListener listener) {
- super();
- this.listener = listener;
- }
-
- public void connect(IDocumentProvider provider, IEditorInput documentKey)
- throws CoreException {
- super.connect(provider, documentKey);
- connectionCount++;
- if (connectionCount == 1) {
- provider.addElementStateListener(this);
- listener.handleDocumentConnected();
- }
- }
-
- public void disconnect(IDocumentProvider provider, IEditorInput documentKey) {
- try {
- super.disconnect(provider, documentKey);
- } finally {
- if (connectionCount > 0)
- connectionCount--;
- if (connectionCount == 0) {
- provider.removeElementStateListener(this);
- listener.handleDocumentDisconnected();
- }
- }
- }
-
- /**
- * @return whether the element is connected to a shared document
- */
- public boolean isConnected() {
- return connectionCount > 0;
- }
-
- /**
- * @param input
- * the document key of the element.
- * @param overwrite
- * indicates whether overwrite should be performed while saving
- * the given element if necessary
- * @param monitor
- * a progress monitor
- * @return whether the save succeeded or not
- * @throws CoreException
- */
- public boolean saveDocument(IEditorInput input, boolean overwrite,
- IProgressMonitor monitor) throws CoreException {
- if (isConnected()) {
- IDocumentProvider provider = SharedDocumentAdapter
- .getDocumentProvider(input);
- try {
- saveDocument(provider, input, provider.getDocument(input),
- overwrite, monitor);
- } finally {
- // When we write the document, remove out hold on the buffer
- releaseBuffer();
- }
- return true;
- }
- return false;
- }
-
- /**
- * Release the buffer if this adapter has buffered the contents in response
- * to a
- * {@link #flushDocument(IDocumentProvider, IEditorInput, IDocument, boolean)}
- * .
- */
- public void releaseBuffer() {
- if (bufferedKey != null) {
- IDocumentProvider provider = SharedDocumentAdapter
- .getDocumentProvider(bufferedKey);
- provider.disconnect(bufferedKey);
- bufferedKey = null;
- }
- }
-
- public void flushDocument(IDocumentProvider provider,
- IEditorInput documentKey, IDocument document, boolean overwrite)
- throws CoreException {
- if (!hasBufferedContents()) {
- // On a flush, make an extra connection to the shared document so it
- // will be kept even
- // if it is no longer being viewed.
- bufferedKey = documentKey;
- provider.connect(bufferedKey);
- }
- this.listener.handleDocumentFlushed();
- }
-
- public void elementContentAboutToBeReplaced(Object element) {
- // Nothing to do
- }
-
- public void elementContentReplaced(Object element) {
- // Nothing to do
- }
-
- public void elementDeleted(Object element) {
- listener.handleDocumentDeleted();
- }
-
- public void elementDirtyStateChanged(Object element, boolean isDirty) {
- if (!isDirty) {
- this.listener.handleDocumentSaved();
- }
- }
-
- public void elementMoved(Object originalElement, Object movedElement) {
- // Nothing to do
- }
-
- /**
- * Return whether the adapter has buffered contents. The adapter buffers
- * contents by connecting to the document through the document provider.
- * This means that the adapter must be disconnected either by saving or
- * discarding the buffer.
- *
- * @return whether the adapter has buffered contents
- */
- public boolean hasBufferedContents() {
- return bufferedKey != null;
- }
-} \ No newline at end of file
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitCompareFileRevisionEditorInput.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitCompareFileRevisionEditorInput.java
index fccfdb0cda..2b46059ce4 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitCompareFileRevisionEditorInput.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitCompareFileRevisionEditorInput.java
@@ -31,6 +31,7 @@ import org.eclipse.egit.core.Activator;
import org.eclipse.egit.ui.UIText;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
+import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput;
import org.eclipse.ui.IWorkbenchPage;
@@ -282,8 +283,7 @@ public class GitCompareFileRevisionEditorInput extends SaveableCompareEditorInpu
if (element instanceof FileRevisionTypedElement){
FileRevisionTypedElement fileRevisionElement = (FileRevisionTypedElement) element;
return fileRevisionElement.getName();
- }
- else if (element instanceof LocalResourceTypedElement){
+ } else if (element instanceof LocalResourceTypedElement){
LocalResourceTypedElement typedContent = (LocalResourceTypedElement) element;
return typedContent.getResource().getName();
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/LocalResourceTypedElement.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/LocalResourceTypedElement.java
deleted file mode 100644
index f57a384976..0000000000
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/LocalResourceTypedElement.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.egit.ui.internal;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.eclipse.compare.ISharedDocumentAdapter;
-import org.eclipse.compare.ResourceNode;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.ui.IEditorInput;
-
-/**
- * A buffered resource node with the following characteristics:
- * <ul>
- * <li>Supports the use of file buffers (see {@link ISharedDocumentAdapter}).
- * <li>Does not support file systems hierarchies (i.e. should not be used to
- * represent a folder).
- * <li>Does not allow editing when the file does not exist (see
- * {@link #isEditable()}).
- * <li>Tracks whether the file has been changed on disk since it was loaded
- * through the element (see {@link #isSynchronized()}).
- * <li>Any buffered contents must either be saved or discarded when the element
- * is no longer needed (see {@link #commit(IProgressMonitor)},
- * {@link #saveDocument(boolean, IProgressMonitor)} and {@link #discardBuffer()}
- * ).
- * </ul>
- */
-public class LocalResourceTypedElement extends ResourceNode implements
- IAdaptable {
-
- private boolean fDirty = false;
-
- private EditableSharedDocumentAdapter sharedDocumentAdapter;
-
- private long timestamp;
-
- private boolean exists;
-
- private boolean useSharedDocument = true;
-
- private EditableSharedDocumentAdapter.ISharedDocumentAdapterListener sharedDocumentListener;
-
- /**
- * @param resource
- * the resource
- */
- public LocalResourceTypedElement(IResource resource) {
- super(resource);
- exists = resource.exists();
- }
-
- public void setContent(byte[] contents) {
- fDirty = true;
- super.setContent(contents);
- }
-
- /**
- * Commits buffered contents to the underlying resource. Note that if the
- * element has a shared document, the commit will not succeed since the
- * contents will be buffered in the shared document and will not be pushed
- * to this element using {@link #setContent(byte[])}. Clients should check
- * whether the element {@link #isConnected()} and, if it is, they should
- * call {@link #saveDocument(boolean, IProgressMonitor)} to save the
- * buffered contents to the underlying resource.
- *
- * @param monitor
- * a progress monitor
- * @throws CoreException
- */
- public void commit(IProgressMonitor monitor) throws CoreException {
- if (isDirty()) {
- if (isConnected()) {
- saveDocument(true, monitor);
- } else {
- IResource resource = getResource();
- if (resource instanceof IFile) {
- ByteArrayInputStream is = null;
- try {
- is = new ByteArrayInputStream(getContent());
- IFile file = (IFile) resource;
- if (file.exists())
- file.setContents(is, false, true, monitor);
- else
- file.create(is, false, monitor);
- fDirty = false;
- } finally {
- fireContentChanged();
- if (is != null)
- try {
- is.close();
- } catch (IOException ex) {
- // ignore
- }
- }
- }
- updateTimestamp();
- }
- }
- }
-
- public InputStream getContents() throws CoreException {
- if (exists)
- return super.getContents();
- return null;
- }
-
- public Object getAdapter(Class adapter) {
- if (adapter == ISharedDocumentAdapter.class) {
- if (isSharedDocumentsEnable())
- return getSharedDocumentAdapter();
- else
- return null;
- }
- return Platform.getAdapterManager().getAdapter(this, adapter);
- }
-
- private synchronized ISharedDocumentAdapter getSharedDocumentAdapter() {
- if (sharedDocumentAdapter == null)
- sharedDocumentAdapter = new EditableSharedDocumentAdapter(
- new EditableSharedDocumentAdapter.ISharedDocumentAdapterListener() {
- public void handleDocumentConnected() {
- LocalResourceTypedElement.this.updateTimestamp();
- if (sharedDocumentListener != null)
- sharedDocumentListener
- .handleDocumentConnected();
- }
-
- public void handleDocumentFlushed() {
- LocalResourceTypedElement.this.fireContentChanged();
- if (sharedDocumentListener != null)
- sharedDocumentListener.handleDocumentFlushed();
- }
-
- public void handleDocumentDeleted() {
- LocalResourceTypedElement.this.update();
- if (sharedDocumentListener != null)
- sharedDocumentListener.handleDocumentDeleted();
- }
-
- public void handleDocumentSaved() {
- LocalResourceTypedElement.this.updateTimestamp();
- if (sharedDocumentListener != null)
- sharedDocumentListener.handleDocumentSaved();
- }
-
- public void handleDocumentDisconnected() {
- if (sharedDocumentListener != null)
- sharedDocumentListener
- .handleDocumentDisconnected();
- }
- });
- return sharedDocumentAdapter;
- }
-
- public boolean isEditable() {
- // Do not allow non-existent files to be edited
- IResource resource = getResource();
- return resource.getType() == IResource.FILE && exists;
- }
-
- /**
- * @return whether the element is connected to a shared document<br>
- * When connected, the element can be saved using
- * {@link #saveDocument(boolean, IProgressMonitor)}. Otherwise,
- * {@link #commit(IProgressMonitor)} should be used to save the
- * buffered contents.
- */
- public boolean isConnected() {
- return sharedDocumentAdapter != null
- && sharedDocumentAdapter.isConnected();
- }
-
- /**
- * @param overwrite
- * indicates whether overwrite should be performed while saving
- * the given element if necessary
- * @param monitor
- * a progress monitor
- * @return whether the save succeeded or not <br>
- * The save can only be performed if the element is connected to a
- * shared document. If the element is not connected,
- * <code>false</code> is returned (see {@link #isConnected()}).
- *
- * @throws CoreException
- */
- public boolean saveDocument(boolean overwrite, IProgressMonitor monitor)
- throws CoreException {
- if (isConnected()) {
- IEditorInput input = sharedDocumentAdapter.getDocumentKey(this);
- sharedDocumentAdapter.saveDocument(input, overwrite, monitor);
- updateTimestamp();
- return true;
- }
- return false;
- }
-
- protected InputStream createStream() throws CoreException {
- InputStream inputStream = super.createStream();
- updateTimestamp();
- return inputStream;
- }
-
- /**
- * Update the cached timestamp of the resource.
- */
- void updateTimestamp() {
- if (getResource().exists())
- timestamp = getResource().getLocalTimeStamp();
- else
- exists = false;
- }
-
- /**
- * @return the cached timestamp of the resource
- */
- private long getTimestamp() {
- return timestamp;
- }
-
- public int hashCode() {
- return getResource().hashCode();
- }
-
- /**
- * Does not consider the content of the resources
- */
- public boolean equals(Object obj) {
- if (obj == this)
- return true;
- if (obj instanceof LocalResourceTypedElement) {
- LocalResourceTypedElement otherElement = (LocalResourceTypedElement) obj;
- return otherElement.getResource().equals(getResource())
- && exists == otherElement.exists;
- }
- return false;
- }
-
- /**
- * Method called to update the state of this element when the compare input
- * that contains this element is issuing a change event. It is not
- * necessarily the case that the {@link #isSynchronized()} will return
- * <code>true</code> after this call.
- */
- public void update() {
- exists = getResource().exists();
- }
-
- /**
- * @return whether the contents provided by this typed element are in-sync
- * with what is on disk <br>
- * Sill return <code>false</code> if the file has been changed
- * externally since the last time the contents were obtained or
- * saved through this element.
- */
- public boolean isSynchronized() {
- long current = getResource().getLocalTimeStamp();
- return current == getTimestamp();
- }
-
- /**
- * @return whether the resource of this element existed at the last time the
- * typed element was updated
- */
- public boolean exists() {
- return exists;
- }
-
- /**
- * Discard of any buffered contents. This must be called when the local
- * element is no longer needed but is dirty since a the element will connect
- * to a shared document when a merge viewer flushes its contents to the
- * element and it must be disconnected or the buffer will remain. #see
- * {@link #isDirty()}
- */
- public void discardBuffer() {
- if (sharedDocumentAdapter != null)
- sharedDocumentAdapter.releaseBuffer();
- super.discardBuffer();
- }
-
- /**
- * @return whether this element can use a shared document
- */
- public boolean isSharedDocumentsEnable() {
- return useSharedDocument && getResource().getType() == IResource.FILE
- && exists;
- }
-
- /**
- * @param enablement
- * whether this element can use shared documents <br>
- * This will only apply to files (i.e. shared documents never
- * apply to folders).
- */
- public void enableSharedDocument(boolean enablement) {
- this.useSharedDocument = enablement;
- }
-
- /**
- * @return whether this element is dirty <br>
- * The element is dirty if a merge viewer has flushed it's contents
- * to the element and the contents have not been saved.
- * @see #commit(IProgressMonitor)
- * @see #saveDocument(boolean, IProgressMonitor)
- * @see #discardBuffer()
- */
- public boolean isDirty() {
- return fDirty
- || (sharedDocumentAdapter != null && sharedDocumentAdapter
- .hasBufferedContents());
- }
-
- /**
- * @param sharedDocumentListener
- */
- public void setSharedDocumentListener(
- EditableSharedDocumentAdapter.ISharedDocumentAdapterListener sharedDocumentListener) {
- this.sharedDocumentListener = sharedDocumentListener;
- }
-
-}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareIndexWithHeadActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareIndexWithHeadActionHandler.java
index f677991fb4..3b40d7625f 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareIndexWithHeadActionHandler.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareIndexWithHeadActionHandler.java
@@ -1,5 +1,6 @@
/*******************************************************************************
* Copyright (C) 2011, Bernard Leach <leachbj@bouncycastle.org>
+ * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -47,12 +48,13 @@ public class CompareIndexWithHeadActionHandler extends RepositoryActionHandler {
return null;
final IResource[] resources = getSelectedResources(event);
final IFile baseFile = (IFile) resources[0];
- final String gitPath = RepositoryMapping.getMapping(
- baseFile.getProject()).getRepoRelativePath(baseFile);
- final ITypedElement base = CompareUtils.getFileCachedRevisionTypedElement(gitPath, repository);
+ final String gitPath = RepositoryMapping.getMapping(baseFile)
+ .getRepoRelativePath(baseFile);
+ ITypedElement base;
ITypedElement next;
try {
+ base = CompareUtils.getHeadTypedElement(baseFile);
Ref head = repository.getRef(Constants.HEAD);
RevWalk rw = new RevWalk(repository);
RevCommit commit = rw.parseCommit(head.getObjectId());
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexActionHandler.java
index da361a432a..136418e17f 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexActionHandler.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexActionHandler.java
@@ -1,5 +1,6 @@
/*******************************************************************************
* Copyright (C) 2009, Yann Simon <yann.simon.fr@gmail.com>
+ * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -9,35 +10,21 @@
package org.eclipse.egit.ui.internal.actions;
-import java.io.ByteArrayInputStream;
+import static org.eclipse.egit.core.internal.util.ResourceUtil.isNonWorkspace;
+
import java.io.IOException;
-import java.io.InputStream;
-import org.eclipse.compare.IContentChangeListener;
-import org.eclipse.compare.IContentChangeNotifier;
import org.eclipse.compare.ITypedElement;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
-import org.eclipse.egit.core.internal.CompareCoreUtils;
-import org.eclipse.egit.core.internal.storage.GitFileRevision;
-import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIText;
import org.eclipse.egit.ui.internal.CompareUtils;
-import org.eclipse.egit.ui.internal.EditableRevision;
import org.eclipse.egit.ui.internal.GitCompareFileRevisionEditorInput;
import org.eclipse.egit.ui.internal.dialogs.CompareTreeView;
-import org.eclipse.jgit.dircache.DirCache;
-import org.eclipse.jgit.dircache.DirCacheEditor;
-import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
-import org.eclipse.jgit.dircache.DirCacheEntry;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.osgi.util.NLS;
-import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.egit.ui.internal.synchronize.compare.LocalNonWorkspaceTypedElement;
import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
@@ -58,13 +45,10 @@ public class CompareWithIndexActionHandler extends RepositoryActionHandler {
if (resources.length == 1 && resources[0] instanceof IFile) {
final IFile baseFile = (IFile) resources[0];
-
- final ITypedElement base = SaveableCompareEditorInput
- .createFileElement(baseFile);
-
+ final ITypedElement base = getBaseTypeElement(baseFile);
final ITypedElement next;
try {
- next = getHeadTypedElement(baseFile);
+ next = CompareUtils.getHeadTypedElement(baseFile);
} catch (IOException e) {
Activator.handleError(
UIText.CompareWithIndexAction_errorOnAddToIndex, e,
@@ -90,88 +74,20 @@ public class CompareWithIndexActionHandler extends RepositoryActionHandler {
return null;
}
- private ITypedElement getHeadTypedElement(final IFile baseFile)
- throws IOException {
- final RepositoryMapping mapping = RepositoryMapping.getMapping(baseFile
- .getProject());
- final Repository repository = mapping.getRepository();
- final String gitPath = mapping.getRepoRelativePath(baseFile);
-
- DirCache dc = repository.lockDirCache();
- final DirCacheEntry entry = dc.getEntry(gitPath);
- dc.unlock();
- if (entry == null) {
- // the file cannot be found in the index
- return new GitCompareFileRevisionEditorInput.EmptyTypedElement(NLS
- .bind(UIText.CompareWithIndexAction_FileNotInIndex,
- baseFile.getName()));
- }
-
- IFileRevision nextFile = GitFileRevision.inIndex(repository, gitPath);
- String encoding = CompareCoreUtils.getResourceEncoding(baseFile);
- final EditableRevision next = new EditableRevision(nextFile, encoding);
-
- IContentChangeListener listener = new IContentChangeListener() {
- public void contentChanged(IContentChangeNotifier source) {
- final byte[] newContent = next.getModifiedContent();
- DirCache cache = null;
- try {
- cache = repository.lockDirCache();
- DirCacheEditor editor = cache.editor();
- editor.add(new PathEdit(gitPath) {
- @Override
- public void apply(DirCacheEntry ent) {
- ent.copyMetaData(entry);
-
- ObjectInserter inserter = repository
- .newObjectInserter();
- ent.copyMetaData(entry);
- ent.setLength(newContent.length);
- ent.setLastModified(System.currentTimeMillis());
- InputStream in = new ByteArrayInputStream(
- newContent);
- try {
- ent.setObjectId(inserter.insert(
- Constants.OBJ_BLOB, newContent.length,
- in));
- inserter.flush();
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- } finally {
- try {
- in.close();
- } catch (IOException e) {
- // ignore here
- }
- }
- }
- });
- try {
- editor.commit();
- } catch (RuntimeException e) {
- if (e.getCause() instanceof IOException)
- throw (IOException) e.getCause();
- else
- throw e;
- }
-
- } catch (IOException e) {
- Activator.handleError(
- UIText.CompareWithIndexAction_errorOnAddToIndex, e,
- true);
- } finally {
- if (cache != null)
- cache.unlock();
- }
- }
- };
-
- next.addContentChangeListener(listener);
- return next;
- }
-
@Override
public boolean isEnabled() {
return getRepository() != null;
}
+
+ private ITypedElement getBaseTypeElement(final IFile baseFile) {
+ final ITypedElement base;
+ if (isNonWorkspace(baseFile)) {
+ String path = baseFile.getFullPath().toOSString();
+ base = new LocalNonWorkspaceTypedElement(path);
+ } else
+ base = SaveableCompareEditorInput
+ .createFileElement(baseFile);
+ return base;
+ }
+
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryActionHandler.java
index 9a9ab4c956..e6c02c6e62 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryActionHandler.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryActionHandler.java
@@ -3,6 +3,7 @@
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
+ * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -228,9 +229,9 @@ abstract class RepositoryActionHandler extends AbstractHandler {
private Repository getRepository(boolean warn,
IStructuredSelection selection, Shell shell) {
RepositoryMapping mapping = null;
- for (IProject project : getProjectsForSelectedResources(selection)) {
+ for (IResource resource : getSelectedResources(selection)) {
RepositoryMapping repositoryMapping = RepositoryMapping
- .getMapping(project);
+ .getMapping(resource);
if (mapping == null)
mapping = repositoryMapping;
if (repositoryMapping == null)
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java
index 9a0789eefb..fab430d0eb 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/staging/StagingEntry.java
@@ -1,5 +1,6 @@
/*******************************************************************************
* Copyright (C) 2011, Bernard Leach <leachbj@bouncycastle.org>
+ * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -87,6 +88,8 @@ public class StagingEntry implements IAdaptable {
IPath absolutePath = new Path(repository.getWorkTree().getAbsolutePath()).append(path);
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IResource resource = root.getFileForLocation(absolutePath);
+ if (resource == null)
+ resource = root.getFile(absolutePath);
return resource;
}
return null;
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitActionContributor.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitActionContributor.java
index a0e20ee0a6..6ea7227c47 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitActionContributor.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitActionContributor.java
@@ -18,6 +18,7 @@ import static org.eclipse.egit.ui.internal.actions.ActionCommands.IGNORE_ACTION;
import static org.eclipse.egit.ui.internal.actions.ActionCommands.MERGE_TOOL_ACTION;
import static org.eclipse.egit.ui.internal.actions.ActionCommands.PUSH_ACTION;
import static org.eclipse.egit.ui.internal.synchronize.model.SupportedContextActionsHelper.canPush;
+import static org.eclipse.team.internal.ui.synchronize.SynchronizePageConfiguration.P_OPEN_ACTION;
import static org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration.NAVIGATE_GROUP;
import static org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration.P_TOOLBAR_MENU;
import static org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration.SYNCHRONIZE_GROUP;
@@ -28,11 +29,13 @@ import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.resources.IResource;
import org.eclipse.egit.ui.UIText;
import org.eclipse.egit.ui.internal.synchronize.action.ExpandAllModelAction;
+import org.eclipse.egit.ui.internal.synchronize.action.GitOpenInCompareAction;
import org.eclipse.egit.ui.internal.synchronize.action.OpenWorkingFileAction;
import org.eclipse.egit.ui.internal.synchronize.action.PullAction;
import org.eclipse.egit.ui.internal.synchronize.action.PushAction;
import org.eclipse.egit.ui.internal.synchronize.model.GitModelObject;
import org.eclipse.egit.ui.internal.synchronize.model.SupportedContextActionsHelper;
+import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.viewers.IStructuredSelection;
@@ -135,11 +138,20 @@ class GitActionContributor extends SynchronizePageActionGroup {
ISynchronizePageSite site = configuration.getSite();
IWorkbenchSite ws = site.getWorkbenchSite();
+ openWorkingFileAction = new OpenWorkingFileAction(ws.getWorkbenchWindow()
+ .getActivePage());
+
+ site.getSelectionProvider().addSelectionChangedListener(
+ openWorkingFileAction);
+
if (ws instanceof IViewSite) {
- openWorkingFileAction = new OpenWorkingFileAction(ws.getWorkbenchWindow()
- .getActivePage());
- site.getSelectionProvider().addSelectionChangedListener(
- openWorkingFileAction);
+ Object oldAction = configuration.getProperty(P_OPEN_ACTION);
+ if (!(oldAction instanceof Action))
+ return;
+
+ final GitOpenInCompareAction openInCompareAction = new GitOpenInCompareAction(
+ configuration, (Action) oldAction);
+ configuration.setProperty(P_OPEN_ACTION, openInCompareAction);
}
}
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/action/GitOpenInCompareAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/action/GitOpenInCompareAction.java
new file mode 100644
index 0000000000..9640375744
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/action/GitOpenInCompareAction.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org> and others
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - implementation of getWorkbenchPage
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.synchronize.action;
+
+import static org.eclipse.ui.PlatformUI.getWorkbench;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.egit.ui.internal.CompareUtils;
+import org.eclipse.egit.ui.internal.GitCompareFileRevisionEditorInput;
+import org.eclipse.egit.ui.internal.synchronize.compare.LocalNonWorkspaceTypedElement;
+import org.eclipse.egit.ui.internal.synchronize.model.GitModelBlob;
+import org.eclipse.egit.ui.internal.synchronize.model.GitModelWorkingFile;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.team.internal.ui.synchronize.actions.OpenInCompareAction;
+import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration;
+import org.eclipse.team.ui.synchronize.ISynchronizePageSite;
+import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+
+/**
+ * Action to open a compare editor from a SyncInfo object.
+ */
+public class GitOpenInCompareAction extends Action {
+
+ private final Action oldAction;
+
+ private final ISynchronizePageConfiguration conf;
+
+ /**
+ * @param configuration
+ * @param oldAction
+ */
+ public GitOpenInCompareAction(ISynchronizePageConfiguration configuration,
+ Action oldAction) {
+ this.conf = configuration;
+ this.oldAction = oldAction;
+ }
+
+ public void run() {
+ ISelection selection = conf.getSite().getSelectionProvider()
+ .getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection sel = ((IStructuredSelection) selection);
+ boolean reuseEditor = sel.size() == 1;
+ for (Iterator iterator = sel.iterator(); iterator.hasNext();) {
+ Object obj = iterator.next();
+ if (obj instanceof GitModelBlob)
+ handleGitObjectComparison((GitModelBlob) obj, reuseEditor);
+ else {
+ oldAction.run();
+ // we assume here that oldAction is instance of
+ // org.eclipse.team.internal.ui.synchronize.actions.OpenInCompareAction
+ // with in it's run method will also iterate over selected
+ // resources therefore we need to brake this loop when we
+ // meet not know object
+ break;
+ }
+ }
+ }
+ }
+
+ private void handleGitObjectComparison(GitModelBlob obj, boolean reuseEditor) {
+ ITypedElement left;
+ ITypedElement right;
+ if (obj instanceof GitModelWorkingFile) {
+ IFile file = (IFile) obj.getResource();
+ if (file.getLocation() == null)
+ left = new LocalNonWorkspaceTypedElement(file.getFullPath().toString());
+ else
+ left= SaveableCompareEditorInput.createFileElement(file);
+ right = getCachedFileElement(file);
+ } else {
+ oldAction.run();
+ return;
+ }
+
+ GitCompareFileRevisionEditorInput in = new GitCompareFileRevisionEditorInput(
+ left, right, null);
+
+ IWorkbenchPage page = getWorkbenchPage(conf.getSite());
+ OpenInCompareAction.openCompareEditor(in, page, reuseEditor);
+ }
+
+ private static IWorkbenchPage getWorkbenchPage(ISynchronizePageSite site) {
+ IWorkbenchPage page = null;
+ if (site == null || site.getWorkbenchSite() == null) {
+ IWorkbenchWindow window = getWorkbench().getActiveWorkbenchWindow();
+ if (window != null)
+ page = window.getActivePage();
+ } else
+ page = site.getWorkbenchSite().getPage();
+
+ return page;
+ }
+
+ private ITypedElement getCachedFileElement(IFile file) {
+ try {
+ return CompareUtils.getHeadTypedElement(file);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCacheCompareInput.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCacheCompareInput.java
index 8ca2328a18..4c7189e4b0 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCacheCompareInput.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCacheCompareInput.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org>
+ * Copyright (C) 2010,2011 Dariusz Luksza <dariusz@luksza.org>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,10 +8,13 @@
*******************************************************************************/
package org.eclipse.egit.ui.internal.synchronize.compare;
-import static org.eclipse.egit.ui.internal.CompareUtils.getFileCachedRevisionTypedElement;
+import static org.eclipse.egit.ui.internal.CompareUtils.getHeadTypedElement;
import static org.eclipse.egit.ui.internal.CompareUtils.getFileRevisionTypedElement;
+import java.io.IOException;
+
import org.eclipse.compare.ITypedElement;
+import org.eclipse.core.resources.IFile;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.team.ui.mapping.ISynchronizationCompareInput;
@@ -21,11 +24,15 @@ import org.eclipse.team.ui.mapping.ISynchronizationCompareInput;
*/
public class GitCacheCompareInput extends GitCompareInput {
+ private final IFile baseFile;
+
/**
* Creates {@link GitCacheCompareInput}
*
* @param repo
* repository that is connected with this object
+ * @param baseFile
+ * base file
* @param ancestorDataSource
* data that should be use to obtain common ancestor object data
* @param baseDataSource
@@ -36,15 +43,20 @@ public class GitCacheCompareInput extends GitCompareInput {
* repository relative path of object
*/
public GitCacheCompareInput(Repository repo,
- ComparisonDataSource ancestorDataSource,
+ IFile baseFile, ComparisonDataSource ancestorDataSource,
ComparisonDataSource baseDataSource,
ComparisonDataSource remoteDataSource, String gitPath) {
super(repo, ancestorDataSource, baseDataSource, remoteDataSource,
gitPath);
+ this.baseFile = baseFile;
}
public ITypedElement getLeft() {
- return getFileCachedRevisionTypedElement(gitPath, repo);
+ try {
+ return getHeadTypedElement(baseFile);
+ } catch (IOException e) {
+ return null;
+ }
}
public ITypedElement getRight() {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCompareInput.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCompareInput.java
index f94bd0b280..e7142b036b 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCompareInput.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitCompareInput.java
@@ -19,12 +19,12 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.egit.ui.UIText;
import org.eclipse.egit.ui.internal.CompareUtils;
import org.eclipse.egit.ui.internal.FileRevisionTypedElement;
-import org.eclipse.egit.ui.internal.LocalResourceTypedElement;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
+import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
import org.eclipse.team.ui.mapping.ISynchronizationCompareInput;
import org.eclipse.team.ui.mapping.SaveableComparison;
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitLocalCompareInput.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitLocalCompareInput.java
deleted file mode 100644
index 09a6996ac2..0000000000
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/GitLocalCompareInput.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org>
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *******************************************************************************/
-package org.eclipse.egit.ui.internal.synchronize.compare;
-
-import static org.eclipse.egit.ui.internal.CompareUtils.getFileCachedRevisionTypedElement;
-
-import org.eclipse.compare.ITypedElement;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.egit.ui.internal.LocalResourceTypedElement;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.team.ui.mapping.ISynchronizationCompareInput;
-
-/**
- * Specific implementation of {@link ISynchronizationCompareInput} for showing
- * locally changed files
- */
-public class GitLocalCompareInput extends GitCompareInput {
-
- private static final IWorkspaceRoot ROOT = ResourcesPlugin.getWorkspace().getRoot();
-
- /**
- * Creates {@link GitLocalCompareInput}
- *
- * @param repo
- * repository that is connected with this object
- * @param ancestorDataSource
- * data that should be use to obtain common ancestor object data
- * @param baseDataSource
- * data that should be use to obtain base object data
- * @param remoteDataSource
- * data that should be used to obtain remote object data
- * @param gitPath
- * repository relative path of object
- */
- public GitLocalCompareInput(Repository repo,
- ComparisonDataSource ancestorDataSource,
- ComparisonDataSource baseDataSource,
- ComparisonDataSource remoteDataSource, String gitPath) {
- super(repo, ancestorDataSource, baseDataSource, remoteDataSource,
- gitPath);
- }
-
- public ITypedElement getLeft() {
- String absoluteFilePath = repo.getWorkTree().getAbsolutePath()
- + "/" + gitPath; //$NON-NLS-1$
- IFile file = ROOT.getFileForLocation(new Path(absoluteFilePath));
-
- if (file == null)
- return new LocalNonWorkspaceTypedElement(absoluteFilePath);
-
- return new LocalResourceTypedElement(file);
- }
-
- public ITypedElement getRight() {
- return getFileCachedRevisionTypedElement(gitPath, repo);
- }
-
- @Override
- public ITypedElement getAncestor() {
- return getRight();
- }
-
-}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java
index 504bb24ba9..eb5d71cd24 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/compare/LocalNonWorkspaceTypedElement.java
@@ -1,33 +1,65 @@
/*******************************************************************************
- * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org>
+ * Copyright (C) 2011, Dariusz Luksza <dariusz@luksza.org> and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation of some methods
*******************************************************************************/
package org.eclipse.egit.ui.internal.synchronize.compare;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
+import org.eclipse.compare.ISharedDocumentAdapter;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.ui.Activator;
-import org.eclipse.egit.ui.internal.LocalResourceTypedElement;
+import org.eclipse.jgit.events.IndexChangedEvent;
+import org.eclipse.team.internal.ui.synchronize.EditableSharedDocumentAdapter;
+import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
-class LocalNonWorkspaceTypedElement extends LocalResourceTypedElement {
+/**
+ * Specialized resource node for non-workspace files
+ */
+public class LocalNonWorkspaceTypedElement extends LocalResourceTypedElement {
private final String path;
+ private boolean exists;
+
+ private boolean fDirty = false;
+
+ private boolean useSharedDocument = true;
+
+ private EditableSharedDocumentAdapter sharedDocumentAdapter;
+
+ private EditableSharedDocumentAdapter.ISharedDocumentAdapterListener sharedDocumentListener;
+
private static final IWorkspaceRoot ROOT = ResourcesPlugin.getWorkspace().getRoot();
+ /**
+ * @param path absolute path to non-workspace file
+ */
public LocalNonWorkspaceTypedElement(String path) {
super(ROOT.getFile(new Path(path)));
this.path = path;
+
+ exists = new File(path).exists();
}
@Override
@@ -41,6 +73,101 @@ class LocalNonWorkspaceTypedElement extends LocalResourceTypedElement {
return null;
}
+ /** {@inheritDoc} */
+ @Override
+ public boolean isEditable() {
+ IResource resource = getResource();
+ return resource.getType() == IResource.FILE && exists;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void update() {
+ exists = getResource().getFullPath().toFile().exists();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isSharedDocumentsEnable() {
+ return useSharedDocument && getResource().getType() == IResource.FILE && exists;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void enableSharedDocument(boolean enablement) {
+ this.useSharedDocument = enablement;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setContent(byte[] contents) {
+ fDirty = true;
+ super.setContent(contents);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void commit(IProgressMonitor monitor) throws CoreException {
+ if (isDirty()) {
+ if (isConnected()) {
+ super.commit(monitor);
+ } else {
+ IResource resource = getResource();
+ if (resource instanceof IFile) {
+ FileOutputStream out = null;
+ File file = ((IFile) resource).getFullPath().toFile();
+ try {
+ if (!file.exists())
+ file.createNewFile();
+ out = new FileOutputStream(file);
+ out.write(getContent());
+ fDirty = false;
+ } catch (FileNotFoundException e) {
+ throw new CoreException(null);
+ } catch (IOException e) {
+ throw new CoreException(null);
+ } finally {
+ fireContentChanged();
+ RepositoryMapping mapping = RepositoryMapping.getMapping(resource);
+ if (mapping != null) {
+ mapping.getRepository().fireEvent(new IndexChangedEvent());
+ }
+ if (out != null)
+ try {
+ out.close();
+ } catch (IOException ex) {
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isDirty() {
+ return fDirty || (sharedDocumentAdapter != null && sharedDocumentAdapter.hasBufferedContents());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class adapter) {
+ if (adapter == ISharedDocumentAdapter.class) {
+ if (isSharedDocumentsEnable())
+ return getSharedDocumentAdapter();
+ else
+ return null;
+ }
+ return Platform.getAdapterManager().getAdapter(this, adapter);
+ }
+
@Override
public int hashCode() {
final int prime = 31;
@@ -62,4 +189,38 @@ class LocalNonWorkspaceTypedElement extends LocalResourceTypedElement {
return false;
return true;
}
+
+ /*
+ * Returned the shared document adapter for this element. If one does not exist
+ * yet, it will be created.
+ */
+ private synchronized ISharedDocumentAdapter getSharedDocumentAdapter() {
+ if (sharedDocumentAdapter == null)
+ sharedDocumentAdapter = new EditableSharedDocumentAdapter(new EditableSharedDocumentAdapter.ISharedDocumentAdapterListener() {
+ public void handleDocumentConnected() {
+ if (sharedDocumentListener != null)
+ sharedDocumentListener.handleDocumentConnected();
+ }
+ public void handleDocumentFlushed() {
+ fireContentChanged();
+ if (sharedDocumentListener != null)
+ sharedDocumentListener.handleDocumentFlushed();
+ }
+ public void handleDocumentDeleted() {
+ LocalNonWorkspaceTypedElement.this.update();
+ if (sharedDocumentListener != null)
+ sharedDocumentListener.handleDocumentDeleted();
+ }
+ public void handleDocumentSaved() {
+ if (sharedDocumentListener != null)
+ sharedDocumentListener.handleDocumentSaved();
+ }
+ public void handleDocumentDisconnected() {
+ if (sharedDocumentListener != null)
+ sharedDocumentListener.handleDocumentDisconnected();
+ }
+ });
+ return sharedDocumentAdapter;
+ }
+
}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheFile.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheFile.java
index 096e294410..eaa8b58ea1 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheFile.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCacheFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org>
+ * Copyright (C) 2010,2011 Dariusz Luksza <dariusz@luksza.org>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -10,6 +10,7 @@ package org.eclipse.egit.ui.internal.synchronize.model;
import java.io.IOException;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.egit.ui.internal.synchronize.compare.ComparisonDataSource;
import org.eclipse.egit.ui.internal.synchronize.compare.GitCacheCompareInput;
@@ -30,8 +31,8 @@ public class GitModelCacheFile extends GitModelBlob {
@Override
protected GitCompareInput getCompareInput(ComparisonDataSource baseData,
ComparisonDataSource remoteData, ComparisonDataSource ancestorData) {
- return new GitCacheCompareInput(getRepository(), ancestorData,
- baseData, remoteData, gitPath);
+ return new GitCacheCompareInput(getRepository(), (IFile) getResource(),
+ ancestorData, baseData, remoteData, gitPath);
}
@Override
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelWorkingFile.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelWorkingFile.java
index 20fb7830ae..53c773d53f 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelWorkingFile.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelWorkingFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org>
+ * Copyright (C) 2010,2011 Dariusz Luksza <dariusz@luksza.org>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -17,9 +17,6 @@ import static org.eclipse.jgit.lib.ObjectId.zeroId;
import java.io.IOException;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.egit.ui.internal.synchronize.compare.ComparisonDataSource;
-import org.eclipse.egit.ui.internal.synchronize.compare.GitCompareInput;
-import org.eclipse.egit.ui.internal.synchronize.compare.GitLocalCompareInput;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -34,13 +31,6 @@ public class GitModelWorkingFile extends GitModelBlob {
}
@Override
- protected GitCompareInput getCompareInput(ComparisonDataSource baseData,
- ComparisonDataSource remoteData, ComparisonDataSource ancestorData) {
- return new GitLocalCompareInput(getRepository(), ancestorData,
- baseData, remoteData, gitPath);
- }
-
- @Override
public int getKind() {
if (kind != LEFT && kind != RIGHT)
return kind;

Back to the top