diff options
| author | Dariusz Luksza | 2010-07-24 20:26:58 +0000 |
|---|---|---|
| committer | Dariusz Luksza | 2010-08-10 17:22:00 +0000 |
| commit | c5e296c4ef629c948958b0f03b11e1e97af1bb30 (patch) | |
| tree | 74115735eb5118c50bc7b848be572a2c05ca8495 | |
| parent | 96faaecf12d7e42fb2058b583472b4b733e08594 (diff) | |
| download | egit-c5e296c4ef629c948958b0f03b11e1e97af1bb30.tar.gz egit-c5e296c4ef629c948958b0f03b11e1e97af1bb30.tar.xz egit-c5e296c4ef629c948958b0f03b11e1e97af1bb30.zip | |
Preliminary support for ChangeSets
Adds proper representation of git changes that occurs between two ref's.
Changes are displayed as Team ChangeSet instance. All commits are listed
as a child's of node that represent repository. Every commit node
contains tree-list of all changed, added or deleted resources.
Bug: 318473
CQ: 4400
Change-Id: I198bb3859463ee7e0e230e22cf06761391436cd8
Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
Signed-off-by: Dariusz Luksza <dariusz@luksza.org>
42 files changed, 2171 insertions, 56 deletions
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparatorTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparatorTest.java index 4fdcca3a97..904333aa02 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparatorTest.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparatorTest.java @@ -172,15 +172,15 @@ public class GitResourceVariantComparatorTest extends GitTestCase { + "keep"); RevCommit commit = testRepo.addAndCommit(iProject, file, "initial commit"); - String path = Repository.stripWorkDir(repo.getWorkTree(), file); - IPath iPath = new Path(path); + String path = Repository.stripWorkDir(repo.getWorkTree(), file.getParentFile()); + IPath iPath = new Path(File.separator + path); IContainer local = createMock(IContainer.class); - expect(local.exists()).andReturn(true); - expect(local.getFullPath()).andReturn(iPath); + expect(local.exists()).andReturn(true).anyTimes(); + expect(local.getFullPath()).andReturn(iPath).anyTimes(); replay(local); - GitFolderResourceVariant remote = new GitFolderResourceVariant(repo, + GitFolderResourceVariant remote = new GitFolderResourceVariant(repo, commit, path); // then diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest.java index 32ef364248..4c889f5525 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest.java @@ -13,6 +13,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; +import java.io.IOException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -177,7 +178,7 @@ public class GitResourceVariantTreeSubscriberTest extends GitTestCase { } private GitResourceVariantTreeSubscriber createGitResourceVariantTreeSubscriber( - String src, String dst) { + String src, String dst) throws IOException { GitSynchronizeData gsd = new GitSynchronizeData(repo, src, dst, false); GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd); new GitResourceVariantTreeSubscriber(gsds); diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest1.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest1.java index dd4cb7db16..7010d675ce 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest1.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest1.java @@ -13,6 +13,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; +import java.io.IOException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -93,7 +94,7 @@ public class GitResourceVariantTreeSubscriberTest1 extends GitTestCase { } private GitResourceVariantTreeSubscriber createGitResourceVariantTreeSubscriber( - String src, String dst) { + String src, String dst) throws IOException { GitSynchronizeData gsd = new GitSynchronizeData(repo, src, dst, false); GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd); new GitResourceVariantTreeSubscriber(gsds); diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest2.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest2.java index 4a12d331bb..b00c0cb722 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest2.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeSubscriberTest2.java @@ -13,6 +13,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; +import java.io.IOException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -104,7 +105,7 @@ public class GitResourceVariantTreeSubscriberTest2 extends GitTestCase { } private GitResourceVariantTreeSubscriber createGitResourceVariantTreeSubscriber( - String src, String dst) { + String src, String dst) throws IOException { GitSynchronizeData gsd = new GitSynchronizeData(repo, src, dst, false); GitSynchronizeDataSet gsds = new GitSynchronizeDataSet(gsd); new GitResourceVariantTreeSubscriber(gsds); diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeTest.java index f18972b66c..073117a809 100644 --- a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeTest.java +++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/synchronize/GitResourceVariantTreeTest.java @@ -16,6 +16,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.util.Arrays; @@ -70,9 +71,11 @@ public class GitResourceVariantTreeTest extends GitTestCase { * roots() method should return list of projects that are associated with * given repository. In this case there is only one project associated with * this repository therefore only one root should be returned. + * + * @throws IOException */ @Test - public void shouldReturnOneRoot() { + public void shouldReturnOneRoot() throws IOException { // when GitSynchronizeData data = new GitSynchronizeData(repo, "", "", false); GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data); @@ -214,8 +217,10 @@ public class GitResourceVariantTreeTest extends GitTestCase { "initial commit"); IFile mainJava = testRepo.getIFile(iProject, file); - testRepo.createAndCheckoutBranch(Constants.R_HEADS + Constants.MASTER, Constants.R_HEADS + "test"); - testRepo.appendContentAndCommit(iProject, file, "// test", "first commit"); + testRepo.createAndCheckoutBranch(Constants.R_HEADS + Constants.MASTER, + Constants.R_HEADS + "test"); + testRepo.appendContentAndCommit(iProject, file, "// test", + "first commit"); GitSynchronizeData data = new GitSynchronizeData(repo, Constants.HEAD, Constants.MASTER, false); GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data); @@ -229,7 +234,7 @@ public class GitResourceVariantTreeTest extends GitTestCase { assertEquals(fileName, actual.getName()); InputStream actualIn = actual.getStorage(new NullProgressMonitor()) - .getContents(); + .getContents(); byte[] actualByte = getBytesAndCloseStream(actualIn); InputStream expectedIn = mainJava.getContents(); byte[] expectedByte = getBytesAndCloseStream(expectedIn); diff --git a/org.eclipse.egit.core/META-INF/MANIFEST.MF b/org.eclipse.egit.core/META-INF/MANIFEST.MF index a42ebcba92..6b4b26d83a 100644 --- a/org.eclipse.egit.core/META-INF/MANIFEST.MF +++ b/org.eclipse.egit.core/META-INF/MANIFEST.MF @@ -12,7 +12,6 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)", org.eclipse.core.filesystem;bundle-version="[1.2.0,2.0.0)" Export-Package: org.eclipse.egit.core;version="0.9.0", org.eclipse.egit.core.internal;version="0.9.0";x-internal:=true, - org.eclipse.egit.core.internal;version="0.9.0";x-internal:=true, org.eclipse.egit.core.internal.storage;version="0.9.0";x-friends:="org.eclipse.egit.ui,org.eclipse.egit.core.test", org.eclipse.egit.core.internal.trace;version="0.9.0";x-internal:=true, org.eclipse.egit.core.internal.util;version="0.9.0";x-friends:="org.eclipse.egit.ui", diff --git a/org.eclipse.egit.core/plugin.xml b/org.eclipse.egit.core/plugin.xml index 9b9b1f71aa..2d23a5a1e1 100644 --- a/org.eclipse.egit.core/plugin.xml +++ b/org.eclipse.egit.core/plugin.xml @@ -16,5 +16,5 @@ <ignore enabled="true" pattern=".git"/> - </extension> + </extension> </plugin> diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/RevUtils.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/RevUtils.java new file mode 100644 index 0000000000..1af91635a9 --- /dev/null +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/RevUtils.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * 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.core; + +import java.io.IOException; + +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.revwalk.filter.RevFilter; + +/** + * Utility class for obtaining Rev object instances. + */ +public class RevUtils { + + private RevUtils() { + // non instanciable utility class + } + + /** + * Finds and returns instance of common ancestor commit for given to + * commit's + * + * @param repo + * @param commit1 + * @param commit2 + * @return common ancestor for commit1 and commit2 parameters + * @throws IOException + */ + public static RevCommit getCommonAncestor(Repository repo, + AnyObjectId commit1, AnyObjectId commit2) throws IOException { + RevWalk rw = new RevWalk(repo); + rw.setRevFilter(RevFilter.MERGE_BASE); + + RevCommit srcRev = rw.parseCommit(commit1); + RevCommit dstRev = rw.parseCommit(commit2); + + rw.markStart(dstRev); + rw.markStart(srcRev); + + RevCommit result; + result = rw.next(); + + return result != null ? result : null; + } + +} diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitBaseResourceVariantTree.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitBaseResourceVariantTree.java index 3439028e66..a2736d6dda 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitBaseResourceVariantTree.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitBaseResourceVariantTree.java @@ -13,13 +13,10 @@ package org.eclipse.egit.core.synchronize; import java.io.IOException; +import org.eclipse.egit.core.RevUtils; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; -import org.eclipse.jgit.lib.Ref; -import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.revwalk.RevWalk; -import org.eclipse.jgit.revwalk.filter.RevFilter; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.variants.SessionResourceVariantByteStore; @@ -32,27 +29,12 @@ class GitBaseResourceVariantTree extends GitResourceVariantTree { @Override protected RevCommit getRevCommit(GitSynchronizeData gsd) throws TeamException { - RevCommit result; - Repository repo = gsd.getRepository(); - RevWalk rw = new RevWalk(repo); - rw.setRevFilter(RevFilter.MERGE_BASE); - try { - Ref srcRef = repo.getRef(gsd.getSrcRev()); - Ref dstRef = repo.getRef(gsd.getDstRev()); - - RevCommit srcRev = rw.parseCommit(srcRef.getObjectId()); - RevCommit dstRev = rw.parseCommit(dstRef.getObjectId()); - - rw.markStart(dstRev); - rw.markStart(srcRev); - - result = rw.next(); + return RevUtils.getCommonAncestor(gsd.getRepository(), gsd + .getSrcRev().getObjectId(), gsd.getDstRev().getObjectId()); } catch (IOException e) { throw new TeamException(e.getMessage(), e); } - - return result != null ? result : null; } } diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitBlobResourceVariant.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitBlobResourceVariant.java index ff25e50fc3..e8fe895fe0 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitBlobResourceVariant.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitBlobResourceVariant.java @@ -37,7 +37,7 @@ import org.eclipse.team.core.TeamException; /** * This is a representation of a file's blob in some branch. */ -class GitBlobResourceVariant extends GitResourceVariant { +public class GitBlobResourceVariant extends GitResourceVariant { private IStorage storage; diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitFolderResourceVariant.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitFolderResourceVariant.java index 2d408e1eb1..f1b406f755 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitFolderResourceVariant.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitFolderResourceVariant.java @@ -28,7 +28,10 @@ import org.eclipse.osgi.util.NLS; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.variants.IResourceVariant; -class GitFolderResourceVariant extends GitResourceVariant { +/** + * + */ +public class GitFolderResourceVariant extends GitResourceVariant { private TreeWalk tw; @@ -51,6 +54,11 @@ class GitFolderResourceVariant extends GitResourceVariant { return getName().getBytes(); } + /** + * @param progress + * @return members + * @throws IOException + */ public IResourceVariant[] getMembers(IProgressMonitor progress) throws IOException { if (members != null) diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitRemoteResourceVariantTree.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitRemoteResourceVariantTree.java index ae90e15697..abcfdb8f3b 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitRemoteResourceVariantTree.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitRemoteResourceVariantTree.java @@ -37,7 +37,7 @@ class GitRemoteResourceVariantTree extends GitResourceVariantTree { rw.setRevFilter(RevFilter.MERGE_BASE); try { - Ref dstRef = repo.getRef(gsd.getDstRev()); + Ref dstRef = gsd.getDstRev(); if (dstRef == null) result = null; else diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariant.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariant.java index fa32e2743c..8ddfc96740 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariant.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariant.java @@ -11,8 +11,12 @@ *******************************************************************************/ package org.eclipse.egit.core.synchronize; +import java.io.File; import java.io.IOException; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jgit.lib.ObjectId; @@ -32,10 +36,15 @@ abstract class GitResourceVariant implements IResourceVariant { private final RevCommit revCommit; + private final String path; + private String name; private IPath fullPath; + private static final IWorkspaceRoot workspaceRoot = ResourcesPlugin + .getWorkspace().getRoot(); + /** * Construct Git representation of {@link IResourceVariant}. * @@ -49,6 +58,7 @@ abstract class GitResourceVariant implements IResourceVariant { throws IOException { this.repo = repo; this.revCommit = revCommit; + this.path = path; TreeWalk tw = getTreeWalk(repo, revCommit.getTree(), path); if (tw == null) { objectId = null; @@ -125,8 +135,21 @@ abstract class GitResourceVariant implements IResourceVariant { } protected IPath getFullPath() { - if (fullPath == null) - fullPath = new Path(variantPath); + if (fullPath == null) { + IResource resource; + IPath location = new Path(repo.getWorkTree() + File.separator + + path); + + if (isContainer()) + resource = workspaceRoot.getContainerForLocation(location); + else + resource = workspaceRoot.getFileForLocation(location); + + if (resource != null) + fullPath = resource.getFullPath(); + else + fullPath = new Path(path); + } return fullPath; } diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparator.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparator.java index ae8cf69eb1..9270382a9b 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparator.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitResourceVariantComparator.java @@ -99,7 +99,9 @@ class GitResourceVariantComparator implements IResourceVariantComparator { GitResourceVariant gitRemote = (GitResourceVariant) remote; boolean exists = gitBase.exists() && gitRemote.exists(); - return exists && gitBase.getObjectId().equals(gitRemote.getObjectId()); + boolean equalType = !(gitBase.isContainer() ^ gitRemote.isContainer()); + return equalType && exists + && gitBase.getObjectId().equals(gitRemote.getObjectId()); } public boolean isThreeWay() { diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitSubscriberMergeContext.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitSubscriberMergeContext.java new file mode 100644 index 0000000000..248223237c --- /dev/null +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitSubscriberMergeContext.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * 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.core.synchronize; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; +import org.eclipse.team.core.diff.IDiff; +import org.eclipse.team.core.mapping.ISynchronizationScopeManager; +import org.eclipse.team.core.subscribers.Subscriber; +import org.eclipse.team.core.subscribers.SubscriberMergeContext; + +/** + * + */ +public class GitSubscriberMergeContext extends SubscriberMergeContext { + + private final GitSynchronizeDataSet gsds; + + /** + * @param subscriber + * @param manager + * @param gsds + */ + public GitSubscriberMergeContext(Subscriber subscriber, + ISynchronizationScopeManager manager, GitSynchronizeDataSet gsds) { + super(subscriber, manager); + this.gsds = gsds; + + initialize(); + } + + public void markAsMerged(IDiff node, boolean inSyncHint, + IProgressMonitor monitor) throws CoreException { + // TODO Auto-generated method stub + + } + + public void reject(IDiff diff, IProgressMonitor monitor) + throws CoreException { + // TODO Auto-generated method stub + + } + + /** + * @return git synchronization data + */ + public GitSynchronizeDataSet getSyncData() { + return gsds; + } + + @Override + protected void makeInSync(IDiff diff, IProgressMonitor monitor) + throws CoreException { + // TODO Auto-generated method stub + + } + +} diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitSubscriberResourceMappingContext.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitSubscriberResourceMappingContext.java new file mode 100644 index 0000000000..f24a1892b1 --- /dev/null +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/GitSubscriberResourceMappingContext.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * 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.core.synchronize; + +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; +import org.eclipse.team.core.subscribers.SubscriberResourceMappingContext; + +/** + * + */ +public class GitSubscriberResourceMappingContext extends + SubscriberResourceMappingContext { + + private final GitSynchronizeDataSet data; + + /** + * @param data + */ + public GitSubscriberResourceMappingContext(GitSynchronizeDataSet data) { + super(new GitResourceVariantTreeSubscriber(data), true); + this.data = data; + } + + /** + * @return git synchronize data set + */ + public GitSynchronizeDataSet getSyncData() { + return data; + } + +} diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/dto/GitSynchronizeData.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/dto/GitSynchronizeData.java index e1296b391d..10d1e06c21 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/dto/GitSynchronizeData.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/synchronize/dto/GitSynchronizeData.java @@ -9,6 +9,7 @@ package org.eclipse.egit.core.synchronize.dto; import java.io.File; +import java.io.IOException; import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -16,6 +17,7 @@ import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.egit.core.project.RepositoryMapping; +import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; /** @@ -28,9 +30,9 @@ public class GitSynchronizeData { private final Repository repo; - private final String srcRev; + private final Ref srcRev; - private final String dstRev; + private final Ref dstRev; private final Set<IProject> projects; @@ -45,12 +47,13 @@ public class GitSynchronizeData { * @param includeLocal * <code>true</code> if local changes should be included in * comparison + * @throws IOException */ public GitSynchronizeData(Repository repository, String srcRev, - String dstRev, boolean includeLocal) { + String dstRev, boolean includeLocal) throws IOException { repo = repository; - this.srcRev = srcRev; - this.dstRev = dstRev; + this.srcRev = repo.getRef(srcRev); + this.dstRev = repo.getRef(dstRev); this.includeLocal = includeLocal; repoParentPath = repo.getDirectory().getParentFile().getAbsolutePath(); @@ -75,14 +78,14 @@ public class GitSynchronizeData { /** * @return synchronize source rev name */ - public String getSrcRev() { + public Ref getSrcRev() { return srcRev; } /** * @return synchronize destination rev name */ - public String getDstRev() { + public Ref getDstRev() { return dstRev; } diff --git a/org.eclipse.egit.ui/icons/obj16/changelog_obj.gif b/org.eclipse.egit.ui/icons/obj16/changelog_obj.gif Binary files differnew file mode 100644 index 0000000000..f988003212 --- /dev/null +++ b/org.eclipse.egit.ui/icons/obj16/changelog_obj.gif diff --git a/org.eclipse.egit.ui/plugin.properties b/org.eclipse.egit.ui/plugin.properties index ce920a1597..26665be07d 100644 --- a/org.eclipse.egit.ui/plugin.properties +++ b/org.eclipse.egit.ui/plugin.properties @@ -126,6 +126,8 @@ GitRepositoriesView_name = Git Repositories GitCategory_name = Git GitRepositoryPerspective_name = Git Repository Exploring Synchronize_Name=Git +Synchronize_ModelName=Git model participant +Synchronize_ChangeSet=Git Change Sets ApplyPatchAction_label=Appl&y Patch... GitRepositoriesContentName = Git Repositories diff --git a/org.eclipse.egit.ui/plugin.xml b/org.eclipse.egit.ui/plugin.xml index c2cf8f1698..e8f48adc52 100644 --- a/org.eclipse.egit.ui/plugin.xml +++ b/org.eclipse.egit.ui/plugin.xml @@ -212,6 +212,64 @@ type="org.eclipse.team.ui.history.IHistoryPageSource"> </adapter> </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelRoot" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter + type="org.eclipse.ui.model.IWorkbenchAdapter"/> + </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelRepository" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter + type="org.eclipse.ui.model.IWorkbenchAdapter"/> + </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelCommit" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter + type="org.eclipse.ui.model.IWorkbenchAdapter"/> + </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelTree" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter + type="org.eclipse.ui.model.IWorkbenchAdapter"/> + </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelBlob" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter + type="org.eclipse.ui.model.IWorkbenchAdapter"/> + </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelObject" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/> + <adapter type="org.eclipse.core.resources.IResource"/> + </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelRepository" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/> + </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelCommit" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/> + </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelTree" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/> + <adapter type="org.eclipse.core.resources.IResource"/> + </factory> + <factory + adaptableType="org.eclipse.egit.ui.internal.synchronize.model.GitModelBlob" + class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory"> + <adapter type="org.eclipse.core.resources.mapping.ResourceMapping"/> + <adapter type="org.eclipse.core.resources.IResource"/> + </factory> </extension> <extension point="org.eclipse.ui.preferencePages"> @@ -1586,6 +1644,18 @@ </linkHelper> </extension> <extension + id="changeSetModel" + name="Git Change Set" + point="org.eclipse.core.resources.modelProviders"> + <modelProvider + class="org.eclipse.egit.ui.internal.synchronize.GitChangeSetModelProvider"/> + <enablement> + <instanceof + value="org.eclipse.core.resources.IResource" /> + </enablement> + <extends-model id="org.eclipse.core.resources.modelProvider"/> + </extension> + <extension point="org.eclipse.team.ui.synchronizeWizards"> <wizard class="org.eclipse.egit.ui.internal.synchronize.GitSynchronizeWizard" @@ -1604,6 +1674,37 @@ name="%Synchronize_Name" persistent="false"> </participant> + <participant + class="org.eclipse.egit.ui.internal.synchronize.GitModelSynchronizeParticipant" + id="org.eclipse.egit.ui.modelCompareParticipant" + name="%Synchronize_ModelName" + persistent="false"/> + </extension> + <extension + point="org.eclipse.ui.navigator.navigatorContent"> + <navigatorContent + activeByDefault="true" + contentProvider="org.eclipse.egit.ui.internal.synchronize.mapping.GitChangeSetContentProvider" + icon="$nl$/icons/obj16/changelog_obj.gif" + id="org.eclipse.egit.ui.changeSetContent" + labelProvider="org.eclipse.egit.ui.internal.synchronize.mapping.GitChangeSetLabelProvider" + name="%Synchronize_ChangeSet" + priority="normal"> + <enablement> + <or> + <instanceof value="org.eclipse.egit.ui.internal.synchronize.GitChangeSetModelProvider"/> + </or> + </enablement> + <commonSorter + class="org.eclipse.egit.ui.internal.synchronize.mapping.GitCommitChangeSetSorter"/> + </navigatorContent> + </extension> + <extension + point="org.eclipse.team.ui.teamContentProviders"> + <teamContentProvider + contentExtensionId="org.eclipse.egit.ui.changeSetContent" + icon="$nl$/icons/obj16/changelog_obj.gif" + modelProviderId="org.eclipse.egit.ui.changeSetModel"/> </extension> <extension name="%TeamMenuCommandsLabel" diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWithActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWithActionHandler.java index 80e94f2bf9..f869539dc8 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWithActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SynchronizeWithActionHandler.java @@ -17,11 +17,18 @@ import java.util.Set; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.mapping.RemoteResourceMappingContext; +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.egit.core.synchronize.GitResourceVariantTreeSubscriber; +import org.eclipse.egit.core.synchronize.GitSubscriberMergeContext; +import org.eclipse.egit.core.synchronize.GitSubscriberResourceMappingContext; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIText; -import org.eclipse.egit.ui.internal.synchronize.GitSynchronize; +import org.eclipse.egit.ui.internal.synchronize.GitModelSynchronizeParticipant; import org.eclipse.egit.ui.internal.synchronize.SelectSynchronizeResourceDialog; import org.eclipse.egit.ui.internal.synchronize.SyncRepoEntity; import org.eclipse.egit.ui.internal.synchronize.SyncRepoEntity.SyncRefEntity; @@ -31,6 +38,16 @@ import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.RemoteConfig; +import org.eclipse.team.core.RepositoryProvider; +import org.eclipse.team.core.mapping.provider.SynchronizationContext; +import org.eclipse.team.core.subscribers.SubscriberScopeManager; +import org.eclipse.team.internal.ui.TeamUIPlugin; +import org.eclipse.team.internal.ui.Utils; +import org.eclipse.team.internal.ui.actions.TeamAction; +import org.eclipse.team.ui.TeamUI; +import org.eclipse.team.ui.synchronize.ISynchronizeParticipant; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; /** * An action that launch synchronization with selected repository @@ -67,7 +84,19 @@ public class SynchronizeWithActionHandler extends RepositoryActionHandler { } } - new GitSynchronize(gsdSet); + GitResourceVariantTreeSubscriber subscriber = new GitResourceVariantTreeSubscriber( + gsdSet); + ResourceMapping[] mappings = getSelectedResourceMappings(event); + RemoteResourceMappingContext remoteContext = new GitSubscriberResourceMappingContext(gsdSet); + SubscriberScopeManager manager = new SubscriberScopeManager( + subscriber.getName(), mappings, subscriber, remoteContext, true); + SynchronizationContext context = new GitSubscriberMergeContext( + subscriber, manager, gsdSet); + GitModelSynchronizeParticipant participant = new GitModelSynchronizeParticipant(context); + TeamUI.getSynchronizeManager().addSynchronizeParticipants( + new ISynchronizeParticipant[] { participant }); + participant.run(getTargetPart()); + return null; } @@ -121,4 +150,72 @@ public class SynchronizeWithActionHandler extends RepositoryActionHandler { return refDb.getRefs(Constants.R_REMOTES + remoteName + "/").values(); //$NON-NLS-1$ } + + /** + * Based on {@link TeamAction#getSelectedResourceMappings} + * + * @param event + * @return the resource mappings that contain resources associated with the given provider + * @throws ExecutionException + */ + private ResourceMapping[] getSelectedResourceMappings(ExecutionEvent event) throws ExecutionException { + Object[] elements = getSelectedResources(event); + ArrayList providerMappings = new ArrayList(); + for (int i = 0; i < elements.length; i++) { + Object object = elements[i]; + Object adapted = getResourceMapping(object); + if (adapted instanceof ResourceMapping) { + ResourceMapping mapping = (ResourceMapping) adapted; + if (isMappedToProvider(mapping, "org.eclipse.egit.core.GitProvider")) { //$NON-NLS-1$ + providerMappings.add(mapping); + } + } + } + return (ResourceMapping[]) providerMappings.toArray(new ResourceMapping[providerMappings.size()]); + } + + /** + * Copied from TeamAction#getResourceMapping(Object) + * + * @param object + * @return resource mapping + */ + private Object getResourceMapping(Object object) { + if (object instanceof ResourceMapping) + return object; + + if (object instanceof IAdaptable) + return ((IAdaptable) object).getAdapter(ResourceMapping.class); + + return Utils.getResourceMapping(object); + } + + /** + * Copied from TeamAction#isMappedToProvider(ResourceMapping, String) + * + * @param element + * @param providerId + * @return TODO + */ + private boolean isMappedToProvider(ResourceMapping element, String providerId) { + IProject[] projects = element.getProjects(); + for (int k = 0; k < projects.length; k++) { + IProject project = projects[k]; + RepositoryProvider provider = RepositoryProvider.getProvider(project); + if (provider != null && provider.getID().equals(providerId)) { + return true; + } + } + return false; + } + + private IWorkbenchPart getTargetPart() { + IWorkbenchPart targetPart = null; + IWorkbenchPage page = TeamUIPlugin.getActivePage(); + if (page != null) { + targetPart = page.getActivePart(); + } + return targetPart; + } + } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/factories/GitAdapterFactory.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/factories/GitAdapterFactory.java index 5df0448dad..36ac91af77 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/factories/GitAdapterFactory.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/factories/GitAdapterFactory.java @@ -1,6 +1,7 @@ /******************************************************************************* * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com> * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org> + * 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 @@ -9,9 +10,20 @@ *******************************************************************************/ package org.eclipse.egit.ui.internal.factories; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.egit.ui.GitHistoryPageSource; +import org.eclipse.egit.ui.internal.synchronize.mapping.GitModelWorkbenchAdapter; +import org.eclipse.egit.ui.internal.synchronize.mapping.GitObjectMapping; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelBlob; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelObject; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelTree; import org.eclipse.team.ui.history.IHistoryPageSource; +import org.eclipse.team.ui.mapping.ISynchronizationCompareAdapter; +import org.eclipse.ui.model.IWorkbenchAdapter; /** * This class is an intelligent "cast" operation for getting @@ -21,18 +33,45 @@ import org.eclipse.team.ui.history.IHistoryPageSource; public class GitAdapterFactory implements IAdapterFactory { private Object historyPageSource = new GitHistoryPageSource(); + private GitModelWorkbenchAdapter gitModelWorkbenchAdapter; + + private static final IWorkspaceRoot root = ResourcesPlugin.getWorkspace() + .getRoot(); @SuppressWarnings("unchecked") public Object getAdapter(Object adaptableObject, Class adapterType) { if (adapterType.isAssignableFrom(IHistoryPageSource.class)) { return historyPageSource; } + + if (IWorkbenchAdapter.class == adapterType) { + if (gitModelWorkbenchAdapter == null) + gitModelWorkbenchAdapter = new GitModelWorkbenchAdapter(); + return gitModelWorkbenchAdapter; + } + + if (adaptableObject instanceof GitModelObject + && adapterType == ResourceMapping.class) + return GitObjectMapping.create((GitModelObject) adaptableObject); + + if (adaptableObject instanceof GitModelObject + && adapterType == IResource.class) { + GitModelObject obj = (GitModelObject) adaptableObject; + + if (obj instanceof GitModelBlob) + return root.getFileForLocation(obj.getLocation()); + + if (obj instanceof GitModelTree) + return root.getContainerForLocation(obj.getLocation()); + } + return null; } public Class[] getAdapterList() { - // TODO Auto-generated method stub - return null; + return new Class[] { IHistoryPageSource.class, + ISynchronizationCompareAdapter.class, ResourceMapping.class, + IResource.class }; } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/SynchronizeCommand.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/SynchronizeCommand.java index ff7f79dfb5..e4474520d4 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/SynchronizeCommand.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/SynchronizeCommand.java @@ -11,12 +11,15 @@ *******************************************************************************/ package org.eclipse.egit.ui.internal.repository.tree.command; +import java.io.IOException; + import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.egit.core.Activator; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode; @@ -46,10 +49,15 @@ public class SynchronizeCommand extends @Override protected IStatus run(IProgressMonitor monitor) { - GitSynchronizeData data = new GitSynchronizeData(node - .getRepository(), Constants.HEAD, ref.getName(), false); + GitSynchronizeData data; + try { + data = new GitSynchronizeData(node + .getRepository(), Constants.HEAD, ref.getName(), false); - new GitSynchronize(data); + new GitSynchronize(data); + } catch (IOException e) { + Activator.logError(e.getMessage(), e); + } return Status.OK_STATUS; } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitChangeSetModelProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitChangeSetModelProvider.java new file mode 100644 index 0000000000..6ce5725da0 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitChangeSetModelProvider.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * 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; + +import java.io.IOException; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.mapping.ModelProvider; +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.core.resources.mapping.ResourceMappingContext; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.core.synchronize.GitSubscriberResourceMappingContext; +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelObject; + +/** + * Represents the provider of Git logical model. + */ +public class GitChangeSetModelProvider extends ModelProvider { + + /** + * Id of model provider + */ + public static final String ID = "org.eclipse.egit.ui.changeSetModel"; //$NON-NLS-1$ + + private static GitChangeSetModelProvider provider; + + /** + * @return provider instance or <code>null</code> if provider was not + * initialized + */ + public static GitChangeSetModelProvider getProvider() { + if (provider == null) { + ModelProvider modelProvider; + try { + modelProvider = ModelProvider.getModelProviderDescriptor(ID) + .getModelProvider(); + provider = (GitChangeSetModelProvider) modelProvider; + } catch (CoreException e) { + Activator.logError(e.getMessage(), e); + } + } + + return provider; + } + + @Override + public ResourceMapping[] getMappings(IResource resource, + ResourceMappingContext context, IProgressMonitor monitor) + throws CoreException { + if (context instanceof GitSubscriberResourceMappingContext) { + GitSubscriberResourceMappingContext gitContext = (GitSubscriberResourceMappingContext) context; + GitSynchronizeDataSet gsds = gitContext.getSyncData(); + GitSynchronizeData data = gsds.getData(resource.getProject()); + + if (data != null) { + GitModelObject object = null; + try { + object = GitModelObject.createRoot(data); + } catch (IOException e) { + Activator.logError(e.getMessage(), e); + } + + if (object != null) { + ResourceMapping rm = (ResourceMapping) object + .getAdapter(ResourceMapping.class); + return new ResourceMapping[] { rm }; + } + } + } + + return super.getMappings(resource, context, monitor); + } +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitModelSynchronizeParticipant.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitModelSynchronizeParticipant.java new file mode 100644 index 0000000000..f7204b35c2 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitModelSynchronizeParticipant.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * 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; + +import org.eclipse.core.resources.mapping.ModelProvider; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.egit.core.Activator; +import org.eclipse.team.core.mapping.provider.SynchronizationContext; +import org.eclipse.team.ui.TeamUI; +import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; +import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipant; + +/** + * Git model synchronization participant + */ +public class GitModelSynchronizeParticipant extends ModelSynchronizeParticipant { + + /** + * Id of model compare participant + */ + public static final String ID = "org.eclipse.egit.ui.modelCompareParticipant"; //$NON-NLS-1$ + + /** + * Id of model synchronization participant + */ + public static final String VIEWER_ID = "org.eclipse.egit.ui.compareSynchronization"; //$NON-NLS-1$ + + /** + * Creates {@link GitModelSynchronizeParticipant} for given context + * + * @param context + */ + public GitModelSynchronizeParticipant(SynchronizationContext context) { + super(context); + try { + setInitializationData(TeamUI.getSynchronizeManager() + .getParticipantDescriptor(ID)); + } catch (CoreException e) { + Activator.logError(e.getMessage(), e); + } + + setSecondaryId(Long.toString(System.currentTimeMillis())); + } + + protected void initializeConfiguration( + ISynchronizePageConfiguration configuration) { + configuration.setProperty(ISynchronizePageConfiguration.P_VIEWER_ID, + VIEWER_ID); + super.initializeConfiguration(configuration); + } + + @Override + public ModelProvider[] getEnabledModelProviders() { + ModelProvider[] enabledProviders = super.getEnabledModelProviders(); + for (int i = 0; i < enabledProviders.length; i++) { + ModelProvider provider = enabledProviders[i]; + if (provider.getId().equals(GitChangeSetModelProvider.ID)) + return enabledProviders; + } + + ModelProvider[] extended = new ModelProvider[enabledProviders.length + 1]; + for (int i = 0; i < enabledProviders.length; i++) { + extended[i] = enabledProviders[i]; + } + + GitChangeSetModelProvider provider = GitChangeSetModelProvider + .getProvider(); + + if (provider == null) + return enabledProviders; + + extended[extended.length - 1] = provider; + return extended; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitSynchronizeWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitSynchronizeWizard.java index 42e418c654..5cdd0b81de 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitSynchronizeWizard.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/GitSynchronizeWizard.java @@ -11,8 +11,10 @@ *******************************************************************************/ package org.eclipse.egit.ui.internal.synchronize; +import java.io.IOException; import java.util.Map; +import org.eclipse.egit.core.Activator; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; import org.eclipse.egit.ui.UIText; @@ -47,7 +49,11 @@ public class GitSynchronizeWizard extends Wizard { Map<Repository, String> branches = page.getSelectedBranches(); for (Repository repo : branches.keySet()) - gsdSet.add(new GitSynchronizeData(repo, Constants.HEAD, branches.get(repo), false)); + try { + gsdSet.add(new GitSynchronizeData(repo, Constants.HEAD, branches.get(repo), false)); + } catch (IOException e) { + Activator.logError(e.getMessage(), e); + } new GitSynchronize(gsdSet); diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitBlobMapping.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitBlobMapping.java new file mode 100644 index 0000000000..e8c59d9d64 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitBlobMapping.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * 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.mapping; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.mapping.ResourceMappingContext; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelBlob; + +class GitBlobMapping extends GitObjectMapping { + + private final GitModelBlob gitBlob; + + private final static IWorkspaceRoot workspaceRoot = ResourcesPlugin + .getWorkspace().getRoot(); + + GitBlobMapping(GitModelBlob gitBlob) { + super(gitBlob); + this.gitBlob = gitBlob; + } + + @Override + public ResourceTraversal[] getTraversals(ResourceMappingContext context, + IProgressMonitor monitor) throws CoreException { + IPath path = gitBlob.getLocation(); + IResource file = workspaceRoot.getFileForLocation(path); + + if (file != null) + return new ResourceTraversal[] { new ResourceTraversal( + new IResource[] { file }, IResource.DEPTH_ZERO, + IResource.ALLOW_MISSING_LOCAL) }; + + return new ResourceTraversal[0]; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitChangeSetContentProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitChangeSetContentProvider.java new file mode 100644 index 0000000000..db1119a437 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitChangeSetContentProvider.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * 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.mapping; + +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.core.resources.mapping.ResourceMappingContext; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.core.synchronize.GitSubscriberMergeContext; +import org.eclipse.egit.core.synchronize.GitSubscriberResourceMappingContext; +import org.eclipse.egit.ui.internal.synchronize.GitChangeSetModelProvider; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelRoot; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.team.core.mapping.ISynchronizationContext; +import org.eclipse.team.ui.mapping.SynchronizationContentProvider; +import org.eclipse.ui.model.WorkbenchContentProvider; + +/** + * Git's variant of {@link SynchronizationContentProvider}. This class creates + * model root of change set and base {@link ResourceTraversal}'s. + */ +public class GitChangeSetContentProvider extends SynchronizationContentProvider { + + private ITreeContentProvider provider; + + private GitModelRoot modelRoot; + + @Override + protected ITreeContentProvider getDelegateContentProvider() { + if (provider == null) + provider = new WorkbenchContentProvider(); + + return provider; + } + + @Override + protected String getModelProviderId() { + return GitChangeSetModelProvider.ID; + } + + @Override + protected Object getModelRoot() { + if (modelRoot == null) { + GitSubscriberMergeContext context = (GitSubscriberMergeContext) getContext(); + modelRoot = new GitModelRoot(context.getSyncData()); + } + + return modelRoot; + } + + @Override + protected ResourceTraversal[] getTraversals( + ISynchronizationContext context, Object object) { + if (object instanceof IAdaptable) { + ResourceMapping rm = getResourceMapping(object); + GitSubscriberMergeContext ctx = (GitSubscriberMergeContext) getContext(); + ResourceMappingContext rmCtx = new GitSubscriberResourceMappingContext( + ctx.getSyncData()); + try { + return rm.getTraversals(rmCtx, new NullProgressMonitor()); + } catch (CoreException e) { + Activator.logError(e.getMessage(), e); + } + } + return null; + } + + private ResourceMapping getResourceMapping(Object object) { + return (ResourceMapping) ((IAdaptable) object) + .getAdapter(ResourceMapping.class); + } + + @Override + public void dispose() { + if (provider != null) + provider.dispose(); + + super.dispose(); + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitChangeSetLabelProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitChangeSetLabelProvider.java new file mode 100644 index 0000000000..11da2aeb21 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitChangeSetLabelProvider.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * 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.mapping; + +import org.eclipse.core.resources.IResource; +import org.eclipse.egit.ui.UIIcons; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelBlob; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelCommit; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelObject; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelRepository; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelTree; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.resource.LocalResourceManager; +import org.eclipse.jface.resource.ResourceManager; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.team.ui.mapping.SynchronizationLabelProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; + +/** + * Label provider for Git ChangeSet model. + */ +public class GitChangeSetLabelProvider extends SynchronizationLabelProvider { + + private static final ILabelProvider workbenchLabelProvider = WorkbenchLabelProvider + .getDecoratingWorkbenchLabelProvider(); + + private LabelProvider delegateLabelProvider; + + @Override + protected ILabelProvider getDelegateLabelProvider() { + if (delegateLabelProvider == null) + delegateLabelProvider = new DelegateLabelProvider(); + + return delegateLabelProvider; + } + + private static class DelegateLabelProvider extends LabelProvider { + + private final ResourceManager fImageCache = new LocalResourceManager( + JFaceResources.getResources()); + + public String getText(Object element) { + if (element instanceof GitModelObject) + return ((GitModelObject) element).getName(); + + return null; + } + + public Image getImage(Object element) { + if (element instanceof GitModelBlob) { + Object adapter = ((GitModelBlob) element) + .getAdapter(IResource.class); + return workbenchLabelProvider.getImage(adapter); + } + + if (element instanceof GitModelTree) { + Object adapter = ((GitModelTree) element) + .getAdapter(IResource.class); + return workbenchLabelProvider.getImage(adapter); + } + + if (element instanceof GitModelCommit) + return fImageCache.createImage(UIIcons.PUSH); + + if (element instanceof GitModelRepository) + return fImageCache.createImage(UIIcons.REPOSITORY); + + return super.getImage(element); + } + + @Override + public void dispose() { + fImageCache.dispose(); + super.dispose(); + } + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitCommitChangeSetSorter.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitCommitChangeSetSorter.java new file mode 100644 index 0000000000..2e15581278 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitCommitChangeSetSorter.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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.mapping; + +import org.eclipse.egit.ui.internal.synchronize.model.GitModelCommit; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.jgit.revwalk.RevCommit; + +/** + * Sorter that order commits in Git Change Set by commit time; + */ +public class GitCommitChangeSetSorter extends ViewerSorter { + + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + if (e1 instanceof GitModelCommit && e2 instanceof GitModelCommit) { + RevCommit rc1 = ((GitModelCommit) e1).getRemoteCommit(); + RevCommit rc2 = ((GitModelCommit) e2).getRemoteCommit(); + + return rc2.getCommitTime() - rc1.getCommitTime(); + } + + return super.compare(viewer, e1, e2); + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitCommitMapping.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitCommitMapping.java new file mode 100644 index 0000000000..77fb2ef783 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitCommitMapping.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * 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.mapping; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IContainer; +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.resources.mapping.ResourceMappingContext; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelCommit; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.TreeFilter; + +class GitCommitMapping extends GitObjectMapping { + + private final GitModelCommit gitCommit; + + public GitCommitMapping(GitModelCommit gitCommit) { + super(gitCommit); + this.gitCommit = gitCommit; + } + + @Override + public ResourceTraversal[] getTraversals(ResourceMappingContext context, + IProgressMonitor monitor) throws CoreException { + Repository repo = gitCommit.getRepository(); + TreeWalk tw = new TreeWalk(repo); + List<ResourceTraversal> result = new ArrayList<ResourceTraversal>(); + IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); + + tw.reset(); + tw.setRecursive(false); + tw.setFilter(TreeFilter.ANY_DIFF); + try { + RevCommit commit = gitCommit.getRemoteCommit(); + tw.addTree(commit.getParent(0).getTree()); + int nth = tw.addTree(commit.getTree()); + + while (tw.next()) { + ResourceTraversal traversal = getTraversal(tw, workspaceRoot, + nth); + + if (traversal != null) + result.add(traversal); + } + } catch (IOException e) { + Activator.logError(e.getMessage(), e); + } + + return result.toArray(new ResourceTraversal[result.size()]); + } + + private ResourceTraversal getTraversal(TreeWalk tw, + IWorkspaceRoot workspaceRoot, int nth) { + IPath path = gitCommit.getLocation().append(tw.getPathString()); + int objectType = tw.getFileMode(nth).getObjectType(); + + ResourceTraversal traversal = null; + if (objectType == Constants.OBJ_BLOB) { + IFile file = workspaceRoot.getFileForLocation(path); + if (file != null) + traversal = new ResourceTraversal(new IResource[] { file }, + IResource.DEPTH_ZERO, IResource.ALLOW_MISSING_LOCAL); + } else if (objectType == Constants.OBJ_TREE) { + IContainer folder = workspaceRoot.getContainerForLocation(path); + if (folder != null) + traversal = new ResourceTraversal(new IResource[] { folder }, + IResource.DEPTH_INFINITE, IResource.ALLOW_MISSING_LOCAL); + } + + return traversal; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitModelWorkbenchAdapter.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitModelWorkbenchAdapter.java new file mode 100644 index 0000000000..55fd9d0217 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitModelWorkbenchAdapter.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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.mapping; + +import org.eclipse.egit.ui.internal.synchronize.model.GitModelObject; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelRoot; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.model.IWorkbenchAdapter; + +/** + * Adapts Git ChangeSet model into workbench + */ +public class GitModelWorkbenchAdapter implements IWorkbenchAdapter { + + private GitChangeSetLabelProvider gitLabelProvider; + + public Object[] getChildren(Object o) { + if (o instanceof GitModelObject) + return ((GitModelObject) o).getChildren(); + + if (o instanceof GitModelRoot) + return ((GitModelRoot) o).getChildren(); + + return null; + } + + public ImageDescriptor getImageDescriptor(Object object) { + if (gitLabelProvider == null) + gitLabelProvider = new GitChangeSetLabelProvider(); + + Image image = gitLabelProvider.getImage(object); + + return ImageDescriptor.createFromImage(image); + } + + public String getLabel(Object o) { + if (o instanceof GitModelObject) + return ((GitModelObject) o).getName(); + + return null; + } + + public Object getParent(Object o) { + if (o instanceof GitModelObject) + return ((GitModelObject) o).getParent(); + + return null; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitObjectMapping.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitObjectMapping.java new file mode 100644 index 0000000000..808ab7b119 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitObjectMapping.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * 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.mapping; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.mapping.ResourceMapping; +import org.eclipse.egit.ui.internal.synchronize.GitChangeSetModelProvider; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelBlob; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelCommit; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelObject; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelRepository; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelTree; + +/** + * Maps Git's objects onto proper {@link ResourceMapping} instants. It allows + * traverse over repository content provides resources for Git ChangeSet. + */ +public abstract class GitObjectMapping extends ResourceMapping { + + private final GitModelObject object; + + /** + * @param object + * @return resource mapping + */ + public static ResourceMapping create(GitModelObject object) { + if (object instanceof GitModelBlob) + return new GitBlobMapping((GitModelBlob) object); + if (object instanceof GitModelTree) + return new GitTreeMapping((GitModelTree) object); + if (object instanceof GitModelCommit) + return new GitCommitMapping((GitModelCommit) object); + if (object instanceof GitModelRepository) + return new GitRepositoryMapping((GitModelRepository) object); + + return null; + } + + /** + * @param parent instance of parent object + */ + protected GitObjectMapping(GitModelObject parent) { + this.object = parent; + } + + @Override + public boolean contains(ResourceMapping mapping) { + if (mapping.getModelProviderId().equals(getModelProviderId())) { + GitModelObject obj = (GitModelObject) mapping.getModelObject(); + return obj.getRepository().equals(object.getRepository()); + } + + return false; + } + + @Override + public Object getModelObject() { + return object; + } + + @Override + public String getModelProviderId() { + return GitChangeSetModelProvider.ID; + } + + @Override + public IProject[] getProjects() { + return object.getProjects(); + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitRepositoryMapping.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitRepositoryMapping.java new file mode 100644 index 0000000000..f86a7383fa --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitRepositoryMapping.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * 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.mapping; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.mapping.ResourceMappingContext; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelCommit; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelObject; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelRepository; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; + +class GitRepositoryMapping extends GitObjectMapping { + + private final GitModelRepository gitRepo; + + protected GitRepositoryMapping(GitModelRepository gitRepo) { + super(gitRepo); + this.gitRepo = gitRepo; + } + + @Override + public ResourceTraversal[] getTraversals(ResourceMappingContext context, + IProgressMonitor monitor) throws CoreException { + Repository repo = gitRepo.getRepository(); + List<ResourceTraversal> result = new ArrayList<ResourceTraversal>(); + + for (GitModelObject obj : gitRepo.getChildren()) + if (obj instanceof GitModelCommit) { + RevCommit revCommit = ((GitModelCommit) obj).getRemoteCommit(); + result.add(new GitTreeTraversal(repo, revCommit)); + } + + return result.toArray(new ResourceTraversal[result.size()]); + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitTreeMapping.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitTreeMapping.java new file mode 100644 index 0000000000..8ecc716cec --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitTreeMapping.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * 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.mapping; + +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.resources.mapping.ResourceMappingContext; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelBlob; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelObject; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelTree; + +class GitTreeMapping extends GitObjectMapping { + + private final GitModelTree tree; + + private static final IWorkspaceRoot root = ResourcesPlugin.getWorkspace() + .getRoot(); + + protected GitTreeMapping(GitModelTree object) { + super(object); + tree = object; + } + + @Override + public ResourceTraversal[] getTraversals(ResourceMappingContext context, + IProgressMonitor monitor) throws CoreException { + GitModelObject[] objects = tree.getChildren(); + ResourceTraversal[] result = new ResourceTraversal[objects.length]; + + for (int i = 0; i < objects.length; i++) { + if (objects[i] instanceof GitModelTree) + result[i] = new GitTreeTraversal((GitModelTree) objects[i]); + else { + IResource[] resources = getResources((GitModelBlob) objects[i]); + result[i] = new ResourceTraversal(resources, + IResource.DEPTH_ZERO, IResource.ALLOW_MISSING_LOCAL); + } + } + + return result; + } + + private IResource[] getResources(GitModelBlob modelBlob) { + IFile file = root.getFileForLocation(modelBlob.getLocation()); + + return new IResource[] { file }; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitTreeTraversal.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitTreeTraversal.java new file mode 100644 index 0000000000..467f18fbc3 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/mapping/GitTreeTraversal.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * 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.mapping; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.resources.mapping.ResourceTraversal; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.ui.internal.synchronize.model.GitModelTree; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.TreeFilter; + +class GitTreeTraversal extends ResourceTraversal { + + public GitTreeTraversal(GitModelTree modelTree) { + this(modelTree.getRepository(), modelTree.getBaseId(), modelTree + .getRemoteId(), modelTree.getLocation()); + } + + public GitTreeTraversal(Repository repo, RevCommit commit) { + this(repo, commit.getParent(0).getTree().getId(), commit.getTree() + .getId(), new Path(repo.getWorkTree().toString())); + } + + private GitTreeTraversal(Repository repo, AnyObjectId baseId, + AnyObjectId actualId, IPath path) { + super(getResourcesImpl(repo, path, baseId, actualId), + IResource.DEPTH_INFINITE, IResource.NONE); + } + + private static IResource[] getResourcesImpl(Repository repo, IPath path, + AnyObjectId baseId, AnyObjectId remoteId) { + TreeWalk tw = new TreeWalk(repo); + List<IResource> result = new ArrayList<IResource>(); + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + + tw.reset(); + tw.setRecursive(false); + tw.setFilter(TreeFilter.ANY_DIFF); + try { + tw.addTree(baseId); + int actualNth = tw.addTree(remoteId); + + while (tw.next()) { + int objectType = tw.getFileMode(actualNth).getObjectType(); + IPath childPath = path.append(tw.getNameString()); + + IResource resource = null; + if (objectType == Constants.OBJ_BLOB) + resource = root.getFileForLocation(childPath); + else if (objectType == Constants.OBJ_TREE) + resource = root.getContainerForLocation(childPath); + + if (resource != null) + result.add(resource); + } + } catch (IOException e) { + Activator.logError(e.getMessage(), e); + } + + return result.toArray(new IResource[result.size()]); + } +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelBlob.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelBlob.java new file mode 100644 index 0000000000..fc42b5ec70 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelBlob.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * 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.model; + +import static org.eclipse.jgit.lib.ObjectId.zeroId; + +import java.io.IOException; + +import org.eclipse.compare.ITypedElement; +import org.eclipse.compare.structuremergeviewer.Differencer; +import org.eclipse.compare.structuremergeviewer.ICompareInput; +import org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; +import org.eclipse.egit.ui.internal.CompareUtils; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.swt.graphics.Image; + +/** + * Git blob object representation in Git ChangeSet + */ +public class GitModelBlob extends GitModelCommit implements ICompareInput { + + private final String name; + + private final ObjectId baseId; + + private final ObjectId remoteId; + + private final ObjectId ancestorId; + + private final IPath location; + + private final String gitPath; + + private static final GitModelObject[] empty = new GitModelObject[0]; + + /** + * + * @param parent + * parent of this object + * @param commit + * remote commit + * @param ancestorId + * common ancestor id + * @param baseId + * id of base object variant + * @param remoteId + * id of remote object variant + * @param name + * human readable blob name (file name) + * @throws IOException + */ + public GitModelBlob(GitModelObject parent, RevCommit commit, + ObjectId ancestorId, ObjectId baseId, ObjectId remoteId, String name) + throws IOException { + super(parent, commit); + this.name = name; + this.baseId = baseId; + this.remoteId = remoteId; + this.ancestorId = ancestorId; + location = getParent().getLocation().append(name); + gitPath = Repository.stripWorkDir(getRepository().getWorkTree(), + getLocation().toFile()); + } + + @Override + public GitModelObject[] getChildren() { + return empty; + } + + @Override + public String getName() { + return name; + } + + @Override + public IProject[] getProjects() { + return getParent().getProjects(); + } + + @Override + public IPath getLocation() { + return location; + } + + public Image getImage() { + // currently itsn't used + return null; + } + + public int getKind() { + return Differencer.CONFLICTING; + } + + public ITypedElement getAncestor() { + if (objectExist(getAncestorCommit(), ancestorId)) + return CompareUtils.getFileRevisionTypedElement(gitPath, + getAncestorCommit(), getRepository(), ancestorId); + + return null; + } + + public ITypedElement getLeft() { + if (objectExist(getRemoteCommit(), remoteId)) + return CompareUtils.getFileRevisionTypedElement(gitPath, + getRemoteCommit(), getRepository(), remoteId); + + return null; + } + + public ITypedElement getRight() { + if (objectExist(getBaseCommit(), baseId)) + return CompareUtils.getFileRevisionTypedElement(gitPath, + getBaseCommit(), getRepository(), baseId); + + return null; + } + + public void addCompareInputChangeListener( + ICompareInputChangeListener listener) { + // data in commit will never change, therefore change listeners are + // useless + } + + public void removeCompareInputChangeListener( + ICompareInputChangeListener listener) { + // data in commit will never change, therefore change listeners are + // useless + } + + public void copy(boolean leftToRight) { + // do nothing, we should disallow coping content between commits + } + + private boolean objectExist(RevCommit commit, ObjectId id) { + return commit != null && id != null && !id.equals(zeroId()); + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCommit.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCommit.java new file mode 100644 index 0000000000..9e4c56add5 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelCommit.java @@ -0,0 +1,216 @@ +/******************************************************************************* + * 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.model; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; +import org.eclipse.egit.core.Activator; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.revwalk.filter.RevFilter; +import org.eclipse.jgit.treewalk.TreeWalk; + +/** + * Git commit object representation in Git ChangeSet + */ +public class GitModelCommit extends GitModelObject { + + private final RevCommit baseCommit; + + private final RevCommit remoteCommit; + + private final RevCommit ancestorCommit; + + private String name; + + private GitModelObject[] children; + + /** + * @param parent + * instance of repository model object that is parent for this + * commit + * @param commit + * instance of commit that will be associated with this model + * object + * @throws IOException + */ + public GitModelCommit(GitModelRepository parent, RevCommit commit) + throws IOException { + super(parent); + remoteCommit = commit; + ancestorCommit = calculateAncestor(remoteCommit); + + RevCommit[] parents = remoteCommit.getParents(); + if (parents != null && parents.length > 0) + baseCommit = remoteCommit.getParent(0); + else { + baseCommit = null; + } + } + + /** + * Constructor for child classes. + * + * @param parent + * instance of repository model object that is parent for this + * commit + * @param commit + * instance of commit that will be associated with this model + * object + * @throws IOException + */ + protected GitModelCommit(GitModelObject parent, RevCommit commit) + throws IOException { + super(parent); + remoteCommit = commit; + ancestorCommit = calculateAncestor(remoteCommit); + + RevCommit[] parents = remoteCommit.getParents(); + if (parents != null && parents.length > 0) + baseCommit = remoteCommit.getParent(0); + else { + baseCommit = null; + } + } + + @Override + public GitModelObject[] getChildren() { + if (children == null) + getChildrenImpl(); + + return children; + + } + + @Override + public String getName() { + if (name == null) + name = remoteCommit.getName().substring(0, 6) + + ": " + remoteCommit.getShortMessage();//$NON-NLS-1$ + + return name; + } + + @Override + public IProject[] getProjects() { + return getParent().getProjects(); + } + + /** + * Returns common ancestor for this commit and all it parent's commits. + * + * @return common ancestor commit + */ + public RevCommit getAncestorCommit() { + return ancestorCommit; + } + + /** + * Returns instance of commit that is parent for one that is associated with + * this model object. + * + * @return base commit + */ + public RevCommit getBaseCommit() { + return baseCommit; + } + + /** + * Resurns instance of commit that is associated with this model object. + * + * @return rev commit + */ + public RevCommit getRemoteCommit() { + return remoteCommit; + } + + @Override + public IPath getLocation() { + return getParent().getLocation(); + } + + @Override + public boolean equals(Object obj) { + return remoteCommit.equals(obj); + } + + @Override + public int hashCode() { + return remoteCommit.hashCode(); + } + + private RevCommit calculateAncestor(RevCommit actual) throws IOException { + RevWalk rw = new RevWalk(getRepository()); + rw.setRevFilter(RevFilter.MERGE_BASE); + + for (RevCommit parent : actual.getParents()) { + RevCommit parentCommit = rw.parseCommit(parent.getId()); + rw.markStart(parentCommit); + } + + rw.markStart(rw.parseCommit(actual.getId())); + + RevCommit result = rw.next(); + return result != null ? result : rw.parseCommit(ObjectId.zeroId()); + } + + private void getChildrenImpl() { + TreeWalk tw = createTreeWalk(); + List<GitModelObject> result = new ArrayList<GitModelObject>(); + try { + int ancestorNth = tw.addTree(ancestorCommit.getTree()); + int baseNth = -1; + if (baseCommit != null) + baseNth = tw.addTree(baseCommit.getTree()); + int actualNth = tw.addTree(remoteCommit.getTree()); + + while (tw.next()) { + GitModelObject obj = getModelObject(tw, ancestorNth, baseNth, + actualNth); + if (obj != null) + result.add(obj); + } + } catch (IOException e) { + Activator.logError(e.getMessage(), e); + } + + children = result.toArray(new GitModelObject[result.size()]); + } + + private GitModelObject getModelObject(TreeWalk tw, int ancestorNth, + int baseNth, int actualNth) throws IOException { + String objName = tw.getNameString(); + + ObjectId objBaseId; + if (baseNth > -1) + objBaseId = tw.getObjectId(baseNth); + else + objBaseId = null; + + ObjectId objRemoteId = tw.getObjectId(actualNth); + ObjectId objAncestorId = tw.getObjectId(ancestorNth); + int objectType = tw.getFileMode(actualNth).getObjectType(); + + if (objectType == Constants.OBJ_BLOB) + return new GitModelBlob(this, remoteCommit, objAncestorId, + objBaseId, objRemoteId, objName); + else if (objectType == Constants.OBJ_TREE) + return new GitModelTree(this, remoteCommit, objAncestorId, + objBaseId, objRemoteId, objName); + + return null; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelObject.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelObject.java new file mode 100644 index 0000000000..dc688e0e72 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelObject.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * 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.model; + +import java.io.IOException; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.TreeFilter; + +/** + * Abstract representation of all object that are included in Git ChangeSet + * model. + */ +public abstract class GitModelObject extends PlatformObject { + + private final GitModelObject parent; + + /** + * Creates root of Git ChangeSet model. + * + * @param data + * synchronization data + * @return Git ChangeSet model root + * @throws IOException + * @throws MissingObjectException + */ + public static GitModelObject createRoot(GitSynchronizeData data) + throws MissingObjectException, IOException { + return new GitModelRepository(data); + } + + /** + * @return child's of particular model object + */ + public abstract GitModelObject[] getChildren(); + + /** + * Returns name of model object, in case of: + * <ul> + * <li>root node it will return repository path + * <li>commit node it will return first 6 characters of commit's SHA-1 + * connected with short commit message + * <li>tree node it will return folder name + * <li>blob node it will return file name + * </ul> + * + * @return name of model object + */ + public abstract String getName(); + + /** + * @return list of projects that are connected with particular object model + */ + public abstract IProject[] getProjects(); + + /** + * @return location of resource associated with particular model object + */ + public abstract IPath getLocation(); + + /** + * + * @param parent + * of particular model object + */ + protected GitModelObject(GitModelObject parent) { + this.parent = parent; + } + + /** + * @return parent of particular model object, or <code>null</code> if object + * is root node + */ + public GitModelObject getParent() { + return parent; + } + + /** + * @return repository associated with particular model object + */ + public Repository getRepository() { + return parent.getRepository(); + } + + /** + * Returns preinitialized instance of {@link TreeWalk}. Set of + * initialization call's is common for all model object's. + * + * @return tree walk + */ + protected TreeWalk createTreeWalk() { + TreeWalk tw = new TreeWalk(getRepository()); + + tw.reset(); + tw.setRecursive(false); + tw.setFilter(TreeFilter.ANY_DIFF); + + return tw; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRepository.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRepository.java new file mode 100644 index 0000000000..7de3519927 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRepository.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * 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.model; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.core.RevUtils; +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.JGitInternalException; +import org.eclipse.jgit.api.NoHeadException; +import org.eclipse.jgit.errors.IncorrectObjectTypeException; +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.ObjectWalk; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevCommitList; +import org.eclipse.jgit.revwalk.RevObject; + +/** + * Representation of Git repository in Git ChangeSet model. + */ +public class GitModelRepository extends GitModelObject { + + private final Repository repo; + + private final ObjectId srcRev; + + private final ObjectId dstRev; + + private final IProject[] projects; + + private GitModelObject[] childrens; + + private IPath location; + + /** + * @param data + * synchronization data + * @throws IOException + * @throws MissingObjectException + */ + public GitModelRepository(GitSynchronizeData data) + throws MissingObjectException, IOException { + super(null); + repo = data.getRepository(); + Set<IProject> projectSet = data.getProjects(); + projects = projectSet.toArray(new IProject[projectSet.size()]); + + ObjectWalk ow = new ObjectWalk(repo); + ow.markStart(ow.parseAny(data.getSrcRev().getObjectId())); + srcRev = ow.next(); + + ow.reset(); + ow.markStart(ow.parseAny(data.getDstRev().getObjectId())); + dstRev = ow.next(); + } + + @Override + public GitModelObject[] getChildren() { + if (childrens == null) + getChildrenImpl(); + + return childrens; + } + + @Override + public String getName() { + return repo.getWorkTree().toString(); + } + + @Override + public IProject[] getProjects() { + return projects; + } + + /** + * @return repository + */ + public Repository getRepository() { + return repo; + } + + /** + * @return source {@link RevObject} + */ + public ObjectId getSrcRev() { + return srcRev; + } + + /** + * @return destination {@link RevObject} + */ + public ObjectId getDstRev() { + return dstRev; + } + + @Override + public IPath getLocation() { + if (location == null) + location = new Path(repo.getWorkTree().toString()); + + return location; + } + + private void getChildrenImpl() { + List<GitModelCommit> result = new ArrayList<GitModelCommit>(); + + try { + RevCommit ancestorCommit = RevUtils.getCommonAncestor(repo, srcRev, + dstRev); + RevCommitList<RevCommit> commits = getRevCommits(ancestorCommit, dstRev); + commits.addAll(getRevCommits(ancestorCommit, srcRev)); + + for (RevCommit commit : commits) + result.add(new GitModelCommit(this, commit)); + } catch (IOException e) { + Activator.logError(e.getMessage(), e); + } + + childrens = result.toArray(new GitModelCommit[result.size()]); + } + + private RevCommitList<RevCommit> getRevCommits(AnyObjectId since, AnyObjectId until) { + Git git = new Git(repo); + RevCommitList<RevCommit> result = new RevCommitList<RevCommit>(); + try { + Iterable<RevCommit> call = git.log().addRange(since, until).call(); + + for (RevCommit commit : call) + result.add(commit); + + } catch (NoHeadException e) { + Activator.logError(e.getMessage(), e); + } catch (JGitInternalException e) { + Activator.logError(e.getMessage(), e); + } catch (MissingObjectException e) { + Activator.logError(e.getMessage(), e); + } catch (IncorrectObjectTypeException e) { + Activator.logError(e.getMessage(), e); + } + + return result; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRoot.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRoot.java new file mode 100644 index 0000000000..0e5fde41aa --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelRoot.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * 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.model; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.egit.core.Activator; +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData; +import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet; + +/** + * Root of all model objects. + */ +public class GitModelRoot { + + private final GitSynchronizeDataSet gsds; + + /** + * @param gsds + */ + public GitModelRoot(GitSynchronizeDataSet gsds) { + this.gsds = gsds; + } + + /** + * @return git synchronization data + */ + public GitSynchronizeDataSet getGsds() { + return gsds; + } + + /** + * @return children + */ + public GitModelRepository[] getChildren() { + List<GitModelRepository> restult = new ArrayList<GitModelRepository>(); + for (GitSynchronizeData data : gsds) { + try { + restult.add(new GitModelRepository(data)); + } catch (IOException e) { + Activator.logError(e.getMessage(), e); + } + } + + return restult.toArray(new GitModelRepository[restult.size()]); + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelTree.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelTree.java new file mode 100644 index 0000000000..e47a109435 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/synchronize/model/GitModelTree.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * 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.model; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; +import org.eclipse.egit.core.Activator; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.treewalk.TreeWalk; + +/** + * Representation of Git tree's in Git ChangeSet model + */ +public class GitModelTree extends GitModelCommit { + + private final String name; + + private final ObjectId baseId; + + private final ObjectId remoteId; + + private final ObjectId ancestorId; + + private GitModelObject[] children; + + private IPath location; + + /** + * @param parent + * parent of this tree + * @param commit + * commit associated with this tree + * @param ancestorId + * id of common ancestor tree for this on + * @param baseId + * id of base tree + * @param remoteId + * this tree id + * @param name + * name resource associated with this tree + * @throws IOException + */ + public GitModelTree(GitModelObject parent, RevCommit commit, + ObjectId ancestorId, ObjectId baseId, ObjectId remoteId, String name) + throws IOException { + super(parent, commit); + this.name = name; + this.baseId = baseId; + this.remoteId = remoteId; + this.ancestorId = ancestorId; + } + + @Override + public GitModelObject[] getChildren() { + if (children == null) + getChildrenImpl(); + + return children; + } + + @Override + public String getName() { + return name; + } + + @Override + public IProject[] getProjects() { + return getParent().getProjects(); + } + + /** + * Return id of tree that should be used as a base variant in + * three-way-compare. + * + * @return base id + */ + public ObjectId getBaseId() { + return baseId; + } + + /** + * Returns id of tree that should be used as a remote in three-way-compare + * + * @return object id + */ + public ObjectId getRemoteId() { + return remoteId; + } + + @Override + public IPath getLocation() { + if (location == null) + location = getParent().getLocation().append(name); + + return location; + } + + private void getChildrenImpl() { + TreeWalk tw = createTreeWalk(); + List<GitModelObject> result = new ArrayList<GitModelObject>(); + + try { + int ancestorNth = tw.addTree(ancestorId); + int baseNth = tw.addTree(baseId); + int remoteNth = tw.addTree(remoteId); + + while (tw.next()) { + GitModelObject obj = createChildren(tw, ancestorNth, baseNth, + remoteNth); + if (obj != null) + result.add(obj); + } + } catch (IOException e) { + Activator.logError(e.getMessage(), e); + } + + children = result.toArray(new GitModelObject[result.size()]); + } + + private GitModelObject createChildren(TreeWalk tw, int ancestorNth, + int baseNth, int remoteNth) throws IOException { + String objName = tw.getNameString(); + ObjectId objBaseId = tw.getObjectId(baseNth); + ObjectId objRemoteId = tw.getObjectId(remoteNth); + ObjectId objAncestorId = tw.getObjectId(ancestorNth); + int objectType = tw.getFileMode(remoteNth).getObjectType(); + + if (objectType == Constants.OBJ_BLOB) + return new GitModelBlob(this, getRemoteCommit(), objAncestorId, + objBaseId, objRemoteId, objName); + else if (objectType == Constants.OBJ_TREE) + return new GitModelTree(this, getRemoteCommit(), objAncestorId, + objBaseId, objRemoteId, objName); + + return null; + } + +} |
