Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce2009-09-30 01:18:28 +0000
committerShawn O. Pearce2009-09-30 01:18:28 +0000
commitdfbdc456d8645fc0c310b5e15cf8d25d8ff7f84b (patch)
tree73461cd1d4e0481e18d25b0c75bd2a4b6d130e45 /org.eclipse.egit.core/src/org/eclipse/egit/core/internal
downloadegit-dfbdc456d8645fc0c310b5e15cf8d25d8ff7f84b.tar.gz
egit-dfbdc456d8645fc0c310b5e15cf8d25d8ff7f84b.tar.xz
egit-dfbdc456d8645fc0c310b5e15cf8d25d8ff7f84b.zip
Initial EGit contribution to eclipse.org
Per CQ 3393 this is the initial contribution of the EGit project (an Eclipse team provider for Git) to eclipse.org. This initial version is derived from the historial EGit repository at commit a9578ba7361b66ab403c6605a1b87fb7b2f94c6e. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'org.eclipse.egit.core/src/org/eclipse/egit/core/internal')
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/UpdateJob.java164
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/BlobStorage.java81
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/CommitFileRevision.java131
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistory.java187
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistoryProvider.java38
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileRevision.java91
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/IndexFileRevision.java88
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommit.java42
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommitList.java21
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidWalk.java26
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/WorkspaceFileRevision.java56
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ExceptionCollector.java128
12 files changed, 1053 insertions, 0 deletions
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/UpdateJob.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/UpdateJob.java
new file mode 100644
index 0000000000..de07e118ba
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/UpdateJob.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.jgit.errors.NotSupportedException;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.GitIndex.Entry;
+
+/**
+ * This job updates the index with the content of all specified
+ * and tracked resources. If a project is selected all tracked
+ * resources withing that container are updated.
+ */
+public class UpdateJob extends Job {
+
+ private final Collection rsrcList;
+
+ /**
+ * Construct an UpdateJob for the specified resources.
+ *
+ * @param rsrcList
+ */
+ public UpdateJob(Collection rsrcList) {
+ super("Update index");
+ this.rsrcList = rsrcList;
+ setPriority(Job.LONG);
+ }
+
+ protected IStatus run(IProgressMonitor m) {
+ if (m == null) {
+ m = new NullProgressMonitor();
+ }
+
+ trace("running");
+ try {
+ final IdentityHashMap<RepositoryMapping, Boolean> tomerge = new IdentityHashMap<RepositoryMapping, Boolean>();
+ try {
+ final int[] count=new int[1];
+ long t0=System.currentTimeMillis();
+ for (Object obj : rsrcList) {
+ obj = ((IAdaptable)obj).getAdapter(IResource.class);
+ if (obj instanceof IContainer) {
+ ((IContainer)obj).accept(new IResourceProxyVisitor() {
+ public boolean visit(IResourceProxy rp) throws CoreException {
+ if (rp.getType() == IResource.FILE) {
+ count[0]++;
+ }
+ return true;
+ }
+ }, IContainer.EXCLUDE_DERIVED);
+ } else if (obj instanceof IResource) {
+ count[0]++;
+ }
+ }
+ long t1=System.currentTimeMillis();
+ System.out.println("Counted "+count[0]+" items to update in "+(t1-t0)/1000.0+"s");
+ m.beginTask(CoreText.UpdateOperation_updating, count[0]);
+ final IProgressMonitor fm = m;
+ for (Object obj : rsrcList) {
+ if (obj instanceof IResource) {
+ final IResource r = (IResource)obj;
+ final RepositoryMapping rm = RepositoryMapping.getMapping(r);
+ final GitIndex index = rm.getRepository().getIndex();
+ tomerge.put(rm, Boolean.TRUE);
+ if (r instanceof IContainer) {
+ ((IContainer)r).accept(new IResourceVisitor() {
+ public boolean visit(IResource resource) throws CoreException {
+ try {
+ if (resource.getType() == IResource.FILE) {
+ String path = rm.getRepoRelativePath(resource);
+ Entry entry = index.getEntry(path);
+ if (entry != null) {
+ entry.update(new File(rm.getWorkDir(),path));
+ }
+ fm.worked(1);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw Activator.error(CoreText.UpdateOperation_failed, e);
+ }
+ return true;
+ }
+ },IResource.DEPTH_INFINITE, IContainer.EXCLUDE_DERIVED);
+ } else {
+ String path = rm.getRepoRelativePath(r);
+ Entry entry = index.getEntry(path);
+ if (entry != null) {
+ entry.update(new File(rm.getWorkDir(),path));
+ }
+ m.worked(1);
+ }
+ }
+ }
+ for (RepositoryMapping rm : tomerge.keySet()) {
+ m.setTaskName("Writing index for "+rm.getRepository().getDirectory());
+ rm.getRepository().getIndex().write();
+ }
+ } catch (NotSupportedException e) {
+ return Activator.error(e.getMessage(),e).getStatus();
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ return Activator.error(CoreText.UpdateOperation_failed, e).getStatus();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return Activator.error(CoreText.UpdateOperation_failed, e).getStatus();
+ } catch (CoreException e) {
+ e.printStackTrace();
+ return Activator.error(CoreText.UpdateOperation_failed, e).getStatus();
+ } finally {
+ try {
+ final Iterator i = tomerge.keySet().iterator();
+ while (i.hasNext()) {
+ final RepositoryMapping r = (RepositoryMapping) i.next();
+ r.getRepository().getIndex().read();
+ r.fireRepositoryChanged();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ m.done();
+ }
+ }
+ } finally {
+ trace("done");
+ m.done();
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ private void trace(final String m) {
+ Activator.trace("(UpdateJob)"+m);
+ }
+
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/BlobStorage.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/BlobStorage.java
new file mode 100644
index 0000000000..05aa0edf63
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/BlobStorage.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.core.internal.resources.ResourceException;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.Repository;
+
+/** Accesses a blob from Git. */
+class BlobStorage implements IStorage {
+ private final Repository db;
+
+ private final String path;
+
+ private final ObjectId blobId;
+
+ BlobStorage(final Repository repository, final String fileName,
+ final ObjectId blob) {
+ db = repository;
+ path = fileName;
+ blobId = blob;
+ }
+
+ public InputStream getContents() throws CoreException {
+ try {
+ return open();
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL,
+ getFullPath(), "IO error reading Git blob " + blobId + ".",
+ e);
+ }
+ }
+
+ private InputStream open() throws IOException, ResourceException,
+ IncorrectObjectTypeException {
+ final ObjectLoader reader = db.openBlob(blobId);
+ if (reader == null)
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL,
+ getFullPath(), "Git blob " + blobId + " not found.", null);
+ final byte[] data = reader.getBytes();
+ if (reader.getType() != Constants.OBJ_BLOB)
+ throw new IncorrectObjectTypeException(blobId, Constants.TYPE_BLOB);
+ return new ByteArrayInputStream(data);
+ }
+
+ public IPath getFullPath() {
+ return Path.fromPortableString(path);
+ }
+
+ public String getName() {
+ final int last = path.lastIndexOf('/');
+ return last >= 0 ? path.substring(last + 1) : path;
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public Object getAdapter(final Class adapter) {
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/CommitFileRevision.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/CommitFileRevision.java
new file mode 100644
index 0000000000..2771e889b2
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/CommitFileRevision.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import org.eclipse.core.internal.resources.ResourceException;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.egit.core.GitTag;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.core.history.ITag;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.treewalk.TreeWalk;
+
+/**
+ * An {@link IFileRevision} for a version of a specified resource in the
+ * specified commit (revision).
+ */
+class CommitFileRevision extends GitFileRevision {
+ private final Repository db;
+
+ private final RevCommit commit;
+
+ private final PersonIdent author;
+
+ private final String path;
+
+ private ObjectId blobId;
+
+ CommitFileRevision(final Repository repo, final RevCommit rc,
+ final String fileName) {
+ this(repo, rc, fileName, null);
+ }
+
+ CommitFileRevision(final Repository repo, final RevCommit rc,
+ final String fileName, final ObjectId blob) {
+ super(fileName);
+ db = repo;
+ commit = rc;
+ author = rc.getAuthorIdent();
+ path = fileName;
+ blobId = blob;
+ }
+
+ String getGitPath() {
+ return path;
+ }
+
+ public IStorage getStorage(final IProgressMonitor monitor)
+ throws CoreException {
+ if (blobId == null)
+ blobId = locateBlobObjectId();
+ return new BlobStorage(db, path, blobId);
+ }
+
+ public long getTimestamp() {
+ return author != null ? author.getWhen().getTime() : 0;
+ }
+
+ public String getContentIdentifier() {
+ return commit.getId().name();
+ }
+
+ public String getAuthor() {
+ return author != null ? author.getName() : null;
+ }
+
+ public String getComment() {
+ return commit.getShortMessage();
+ }
+
+ public String toString() {
+ return commit.getId() + ":" + path;
+ }
+
+ public ITag[] getTags() {
+ final Collection<GitTag> ret = new ArrayList<GitTag>();
+ for (final Map.Entry<String, Ref> tag : db.getTags().entrySet()) {
+ final ObjectId ref = tag.getValue().getPeeledObjectId();
+ if (ref == null)
+ continue;
+ if (!AnyObjectId.equals(ref, commit))
+ continue;
+ ret.add(new GitTag(tag.getKey()));
+ }
+ return ret.toArray(new ITag[ret.size()]);
+ }
+
+ /**
+ * Get the commit that introduced this file revision.
+ *
+ * @return the commit we most recently noticed this file in.
+ */
+ public RevCommit getRevCommit() {
+ return commit;
+ }
+
+ private ObjectId locateBlobObjectId() throws CoreException {
+ try {
+ final TreeWalk w = TreeWalk.forPath(db, path, commit.getTree());
+ if (w == null)
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL,
+ Path.fromPortableString(path), "Path not in "
+ + commit.getId() + ".", null);
+ return w.getObjectId(0);
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL, Path
+ .fromPortableString(path), "IO error looking up path in "
+ + commit.getId() + ".", e);
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistory.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistory.java
new file mode 100644
index 0000000000..377b6abcd1
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistory.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.team.core.history.IFileHistoryProvider;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.core.history.provider.FileHistory;
+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.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+
+/**
+ * A list of revisions for a specific resource according to some filtering
+ * criterion. Though git really does not do file tracking, this corresponds to
+ * listing all files with the same path.
+ */
+class GitFileHistory extends FileHistory implements IAdaptable {
+ private static final int SINGLE_REVISION = IFileHistoryProvider.SINGLE_REVISION;
+
+ private static final IFileRevision[] NO_REVISIONS = {};
+
+ private static final int BATCH_SIZE = 256;
+
+ private final IResource resource;
+
+ private String gitPath;
+
+ private final KidWalk walk;
+
+ private final IFileRevision[] revisions;
+
+ GitFileHistory(final IResource rsrc, final int flags,
+ final IProgressMonitor monitor) {
+ resource = rsrc;
+ walk = buildWalk();
+ revisions = buildRevisions(monitor, flags);
+ }
+
+ private KidWalk buildWalk() {
+ final RepositoryMapping rm = RepositoryMapping.getMapping(resource);
+ if (rm == null) {
+ Activator.logError("Git not attached to project "
+ + resource.getProject().getName() + ".", null);
+ return null;
+ }
+
+ final KidWalk w = new KidWalk(rm.getRepository());
+ gitPath = rm.getRepoRelativePath(resource);
+ w.setTreeFilter(AndTreeFilter.create(PathFilterGroup
+ .createFromStrings(Collections.singleton(gitPath)),
+ TreeFilter.ANY_DIFF));
+ return w;
+ }
+
+ private IFileRevision[] buildRevisions(final IProgressMonitor monitor,
+ final int flags) {
+ if (walk == null)
+ return NO_REVISIONS;
+
+ final Repository db = walk.getRepository();
+ final RevCommit root;
+ try {
+ final AnyObjectId headId = db.resolve(Constants.HEAD);
+ if (headId == null) {
+ Activator.logError("No HEAD revision available from Git"
+ + " for project " + resource.getProject().getName()
+ + ".", null);
+ return NO_REVISIONS;
+ }
+
+ root = walk.parseCommit(headId);
+ if ((flags & SINGLE_REVISION) == SINGLE_REVISION) {
+ // If all Eclipse wants is one revision it probably is
+ // for the editor "quick diff" feature. We can pass off
+ // just the repository HEAD, even though it may not be
+ // the revision that most recently modified the path.
+ //
+ final CommitFileRevision single;
+ single = new CommitFileRevision(db, root, gitPath);
+ return new IFileRevision[] { single };
+ }
+
+ walk.markStart(root);
+ } catch (IOException e) {
+ Activator.logError("Invalid HEAD revision for project "
+ + resource.getProject().getName() + ".", e);
+ return NO_REVISIONS;
+ }
+
+ final KidCommitList list = new KidCommitList();
+ list.source(walk);
+ try {
+ for (;;) {
+ final int oldsz = list.size();
+ list.fillTo(oldsz + BATCH_SIZE - 1);
+ if (oldsz == list.size())
+ break;
+ if (monitor != null && monitor.isCanceled())
+ break;
+ }
+ } catch (IOException e) {
+ Activator.logError("Error parsing history for "
+ + resource.getFullPath() + ".", e);
+ return NO_REVISIONS;
+ }
+
+ final IFileRevision[] r = new IFileRevision[list.size()];
+ for (int i = 0; i < r.length; i++)
+ r[i] = new CommitFileRevision(db, list.get(i), gitPath);
+ return r;
+ }
+
+ public IFileRevision[] getContributors(final IFileRevision ifr) {
+ if (!(ifr instanceof CommitFileRevision))
+ return NO_REVISIONS;
+
+ final CommitFileRevision rev = (CommitFileRevision) ifr;
+ final Repository db = walk.getRepository();
+ final String p = rev.getGitPath();
+ final RevCommit c = rev.getRevCommit();
+ final IFileRevision[] r = new IFileRevision[c.getParentCount()];
+ for (int i = 0; i < r.length; i++)
+ r[i] = new CommitFileRevision(db, c.getParent(i), p);
+ return r;
+ }
+
+ public IFileRevision[] getTargets(final IFileRevision ifr) {
+ if (!(ifr instanceof CommitFileRevision))
+ return NO_REVISIONS;
+
+ final CommitFileRevision rev = (CommitFileRevision) ifr;
+ final Repository db = walk.getRepository();
+ final String p = rev.getGitPath();
+ final RevCommit rc = rev.getRevCommit();
+ if (!(rc instanceof KidCommit))
+ return NO_REVISIONS;
+
+ final KidCommit c = (KidCommit) rc;
+ final IFileRevision[] r = new IFileRevision[c.children.length];
+ for (int i = 0; i < r.length; i++)
+ r[i] = new CommitFileRevision(db, c.children[i], p);
+ return r;
+ }
+
+ public IFileRevision getFileRevision(final String id) {
+ if (id == null || id.equals("") || GitFileRevision.WORKSPACE.equals(id))
+ return new WorkspaceFileRevision(resource);
+ if (GitFileRevision.INDEX.equals(id))
+ return new IndexFileRevision(walk.getRepository(), gitPath);
+
+ // Only return a revision if it was matched by this filtered history
+ for (IFileRevision r : revisions) {
+ if (r.getContentIdentifier().equals(id))
+ return r;
+ }
+ return null;
+ }
+
+ public IFileRevision[] getFileRevisions() {
+ final IFileRevision[] r = new IFileRevision[revisions.length];
+ System.arraycopy(revisions, 0, r, 0, r.length);
+ return r;
+ }
+
+ public Object getAdapter(Class adapter) {
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistoryProvider.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistoryProvider.java
new file mode 100644
index 0000000000..b85800d95a
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistoryProvider.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.history.IFileHistory;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.core.history.provider.FileHistoryProvider;
+
+/**
+ * A {@link FileHistoryProvider} for Git. This class has methods for retrieving
+ * specific versions of a tracked resource.
+ */
+public class GitFileHistoryProvider extends FileHistoryProvider {
+ public IFileHistory getFileHistoryFor(IResource resource, int flags,
+ IProgressMonitor monitor) {
+ return new GitFileHistory(resource, flags, monitor);
+ }
+
+ public IFileRevision getWorkspaceFileRevision(IResource resource) {
+ return new WorkspaceFileRevision(resource);
+ }
+
+ public IFileHistory getFileHistoryFor(IFileStore store, int flags,
+ IProgressMonitor monitor) {
+ // TODO: implement getFileHistoryFor(IFileStore ...)
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileRevision.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileRevision.java
new file mode 100644
index 0000000000..d9066573d9
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileRevision.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.core.history.provider.FileRevision;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+/**
+ * A Git related {@link IFileRevision}. It references a version and a resource,
+ * i.e. the version we think corresponds to the resource in specific version.
+ */
+public abstract class GitFileRevision extends FileRevision {
+ /** Content identifier for the working copy. */
+ public static final String WORKSPACE = "Workspace";
+
+ /** Content identifier for the content staged in the index. */
+ public static final String INDEX = "Index";
+
+ /**
+ * Obtain a file revision for a specific blob of an existing commit.
+ *
+ * @param db
+ * the repository this commit was loaded out of, and that this
+ * file's blob should also be reachable through.
+ * @param commit
+ * the commit the blob was identified to be within.
+ * @param path
+ * path within the commit's tree of the file.
+ * @param blobId
+ * unique name of the content.
+ * @return revision implementation for this file in the given commit.
+ */
+ public static GitFileRevision inCommit(final Repository db,
+ final RevCommit commit, final String path, final ObjectId blobId) {
+ return new CommitFileRevision(db, commit, path, blobId);
+ }
+
+ /**
+ * @param db
+ * the repository which contains the index to use.
+ * @param path
+ * path of the resource in the index
+ * @return revision implementation for the given path in the index
+ */
+ public static GitFileRevision inIndex(final Repository db, final String path) {
+ return new IndexFileRevision(db, path);
+ }
+
+ private final String path;
+
+ GitFileRevision(final String fileName) {
+ path = fileName;
+ }
+
+ public String getName() {
+ final int last = path.lastIndexOf('/');
+ return last >= 0 ? path.substring(last + 1) : path;
+ }
+
+ public boolean isPropertyMissing() {
+ return false;
+ }
+
+ public IFileRevision withAllProperties(final IProgressMonitor monitor)
+ throws CoreException {
+ return this;
+ }
+
+ public URI getURI() {
+ try {
+ return new URI(null, null, path, null);
+ } catch (URISyntaxException e) {
+ return null;
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/IndexFileRevision.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/IndexFileRevision.java
new file mode 100644
index 0000000000..8cf81c9ecb
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/IndexFileRevision.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com>
+ * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import java.io.IOException;
+
+import org.eclipse.core.internal.resources.ResourceException;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.GitIndex.Entry;
+
+/** An {@link IFileRevision} for the version in the Git index. */
+class IndexFileRevision extends GitFileRevision implements IFileRevision {
+ private final Repository db;
+
+ private final String path;
+
+ private ObjectId blobId;
+
+ IndexFileRevision(final Repository repo, final String fileName) {
+ super(fileName);
+ db = repo;
+ path = fileName;
+ }
+
+ public IStorage getStorage(IProgressMonitor monitor) throws CoreException {
+ if (blobId == null)
+ blobId = locateBlobObjectId();
+ return new BlobStorage(db, path, blobId);
+ }
+
+ public boolean isPropertyMissing() {
+ return false;
+ }
+
+ public IFileRevision withAllProperties(IProgressMonitor monitor)
+ throws CoreException {
+ return null;
+ }
+
+ public String getAuthor() {
+ return "";
+ }
+
+ public long getTimestamp() {
+ return -1;
+ }
+
+ public String getComment() {
+ return null;
+ }
+
+ public String getContentIdentifier() {
+ return INDEX;
+ }
+
+ private ObjectId locateBlobObjectId() throws CoreException {
+ try {
+ final GitIndex idx = db.getIndex();
+ final Entry e = idx.getEntry(path);
+ if (e == null)
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL,
+ Path.fromPortableString(path),
+ "Git index entry not found", null);
+ return e.getObjectId();
+
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL, Path
+ .fromPortableString(path),
+ "IO error looking up path in index.", e);
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommit.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommit.java
new file mode 100644
index 0000000000..b94faeac12
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommit.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+class KidCommit extends RevCommit {
+ static final KidCommit[] NO_CHILDREN = {};
+
+ KidCommit[] children = NO_CHILDREN;
+
+ KidCommit(final AnyObjectId id) {
+ super(id);
+ }
+
+ void addChild(final KidCommit c) {
+ final int cnt = children.length;
+ if (cnt == 0)
+ children = new KidCommit[] { c };
+ else if (cnt == 1)
+ children = new KidCommit[] { children[0], c };
+ else {
+ final KidCommit[] n = new KidCommit[cnt + 1];
+ System.arraycopy(children, 0, n, 0, cnt);
+ n[cnt] = c;
+ children = n;
+ }
+ }
+
+ @Override
+ public void reset() {
+ children = NO_CHILDREN;
+ super.reset();
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommitList.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommitList.java
new file mode 100644
index 0000000000..4bc9fe16c9
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommitList.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import org.eclipse.jgit.revwalk.RevCommitList;
+
+class KidCommitList extends RevCommitList<KidCommit> {
+ @Override
+ protected void enter(final int index, final KidCommit e) {
+ final int nParents = e.getParentCount();
+ for (int i = 0; i < nParents; i++)
+ ((KidCommit) e.getParent(i)).addChild(e);
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidWalk.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidWalk.java
new file mode 100644
index 0000000000..9865e377ad
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidWalk.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+class KidWalk extends RevWalk {
+ KidWalk(final Repository repo) {
+ super(repo);
+ }
+
+ @Override
+ protected RevCommit createCommit(final AnyObjectId id) {
+ return new KidCommit(id);
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/WorkspaceFileRevision.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/WorkspaceFileRevision.java
new file mode 100644
index 0000000000..e3f4500106
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/WorkspaceFileRevision.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com>
+ * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.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.internal.storage;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.history.IFileRevision;
+
+/** An {@link IFileRevision} for the current version in the workspace. */
+class WorkspaceFileRevision extends GitFileRevision implements IFileRevision {
+ private final IResource rsrc;
+
+ WorkspaceFileRevision(final IResource resource) {
+ super(resource.getName());
+ rsrc = resource;
+ }
+
+ public IStorage getStorage(IProgressMonitor monitor) throws CoreException {
+ return rsrc instanceof IStorage ? (IStorage) rsrc : null;
+ }
+
+ public boolean isPropertyMissing() {
+ return false;
+ }
+
+ public IFileRevision withAllProperties(IProgressMonitor monitor)
+ throws CoreException {
+ return null;
+ }
+
+ public String getAuthor() {
+ return "";
+ }
+
+ public long getTimestamp() {
+ return -1;
+ }
+
+ public String getComment() {
+ return "";
+ }
+
+ public String getContentIdentifier() {
+ return WORKSPACE;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ExceptionCollector.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ExceptionCollector.java
new file mode 100644
index 0000000000..a2cb287f42
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ExceptionCollector.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.egit.core.internal.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Collects exceptions and can be configured to ignore duplicates exceptions.
+ * Exceptions can be logged and a MultiStatus containing all collected
+ * exceptions can be returned.
+ *
+ * @see org.eclipse.core.runtime.MultiStatus
+ * @see org.eclipse.core.runtime.IStatus
+ *
+ * @since 3.0
+ */
+public class ExceptionCollector {
+
+ private final List<IStatus> statuses = new ArrayList<IStatus>();
+
+ private final String message;
+
+ private final String pluginId;
+
+ private final int severity;
+
+ private final ILog log;
+
+ /**
+ * Creates a collector and initializes the parameters for the top-level
+ * exception that would be returned from <code>getStatus</code> is
+ * exceptions are collected.
+ *
+ * @param message
+ * a human-readable message, localized to the current locale
+ * @param pluginId
+ * the unique identifier of the relevant plug-in
+ * @param severity
+ * the severity; one of <code>OK</code>, <code>ERROR</code>,
+ * <code>INFO</code>, or <code>WARNING</code>
+ * @param log
+ * the log to output the exceptions to, or <code>null</code> if
+ * exceptions should not be logged.
+ */
+ public ExceptionCollector(String message, String pluginId, int severity,
+ ILog log) {
+ this.message = message;
+ this.pluginId = pluginId;
+ this.severity = severity;
+ this.log = log;
+ }
+
+ /**
+ * Clears the exceptions collected.
+ */
+ public void clear() {
+ statuses.clear();
+ }
+
+ /**
+ * Returns a status that represents the exceptions collected. If the
+ * collector is empty <code>IStatus.OK</code> is returned. Otherwise a
+ * MultiStatus containing all collected exceptions is returned.
+ *
+ * @return a multistatus containing the exceptions collected or IStatus.OK
+ * if the collector is empty.
+ */
+ public IStatus getStatus() {
+ if (statuses.isEmpty()) {
+ return Status.OK_STATUS;
+ } else {
+ final MultiStatus multiStatus = new MultiStatus(pluginId, severity,
+ message, null);
+ final Iterator it = statuses.iterator();
+ while (it.hasNext()) {
+ final IStatus status = (IStatus) it.next();
+ multiStatus.merge(status);
+ }
+ return multiStatus;
+ }
+ }
+
+ /**
+ * Add this exception to the collector. If a log was specified in the
+ * constructor then the exception will be output to the log. You can
+ * retreive exceptions using <code>getStatus</code>.
+ *
+ * @param exception
+ * the exception to collect
+ */
+ public void handleException(CoreException exception) {
+ if (log != null) {
+ log.log(new Status(severity, pluginId, 0, message, exception));
+ }
+
+ // Record each status individually to flatten the resulting multi-status
+ final IStatus exceptionStatus = exception.getStatus();
+
+ // Wrap the exception so the stack trace is not lost.
+ final IStatus status = new Status(exceptionStatus.getSeverity(),
+ exceptionStatus.getPlugin(), exceptionStatus.getCode(),
+ exceptionStatus.getMessage(), exception);
+
+ recordStatus(status);
+ for (IStatus childStatus : status.getChildren())
+ recordStatus(childStatus);
+ }
+
+ private void recordStatus(IStatus status) {
+ statuses.add(status);
+ }
+}

Back to the top