Infrastructure to retrieve all the branches that contain a commit, the children of a commit, tags and branches referencing a commit. It was added in the core package so it is easier to reuse it. Signed-off-by: Roger C. Soares <rogersoares@xxxxxxxxxxxxxxxx> --- org.spearce.egit.core/META-INF/MANIFEST.MF | 6 +- .../org/spearce/egit/core/util/CommitMetaInfo.java | 59 ++++++ .../org/spearce/egit/core/util/RepositoryUtil.java | 217 ++++++++++++++++++++ 3 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 org.spearce.egit.core/src/org/spearce/egit/core/util/CommitMetaInfo.java create mode 100644 org.spearce.egit.core/src/org/spearce/egit/core/util/RepositoryUtil.java diff --git a/org.spearce.egit.core/META-INF/MANIFEST.MF b/org.spearce.egit.core/META-INF/MANIFEST.MF index 48ddb91..6dfc2f7 100644 --- a/org.spearce.egit.core/META-INF/MANIFEST.MF +++ b/org.spearce.egit.core/META-INF/MANIFEST.MF @@ -11,10 +11,10 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, org.spearce.jgit, org.eclipse.core.filesystem -Export-Package: org.spearce.egit.core.internal.mapping;x-friends:="org.spearce.egit.ui", - org.spearce.egit.core, +Export-Package: org.spearce.egit.core, org.spearce.egit.core.internal.mapping, org.spearce.egit.core.op, - org.spearce.egit.core.project + org.spearce.egit.core.project, + org.spearce.egit.core.util Eclipse-LazyStart: true Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/util/CommitMetaInfo.java b/org.spearce.egit.core/src/org/spearce/egit/core/util/CommitMetaInfo.java new file mode 100644 index 0000000..48de3fb --- /dev/null +++ b/org.spearce.egit.core/src/org/spearce/egit/core/util/CommitMetaInfo.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 Roger C. Soares + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License, version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + */ +package org.spearce.egit.core.util; + +import java.util.Set; + +import org.spearce.jgit.lib.Commit; + +/** + * This class stores information that are not part of a commit and requires a + * walk through out the repository to be discovered. + */ +public class CommitMetaInfo { + + private Set<String> branchNamesContainingCommit; + + private Set<Commit> childrenCommits; + + CommitMetaInfo(Set<String> branchNamesContainingCommit, + Set<Commit> childrenCommits) { + this.branchNamesContainingCommit = branchNamesContainingCommit; + this.childrenCommits = childrenCommits; + } + + /** + * Returns all the branches that contain the commit. + * + * @return Set<String> a <code>Set</code> containing the branch names, + * sorted in ascending string order or null + */ + public Set<String> getBranchNamesContainingCommit() { + return branchNamesContainingCommit; + } + + /** + * Returns the children commits. + * + * @return Set<Commit> a <code>Set</code> containing the children commits + * or null. + */ + public Set<Commit> getChildrenCommits() { + return childrenCommits; + } + +} diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/util/RepositoryUtil.java b/org.spearce.egit.core/src/org/spearce/egit/core/util/RepositoryUtil.java new file mode 100644 index 0000000..9a08868 --- /dev/null +++ b/org.spearce.egit.core/src/org/spearce/egit/core/util/RepositoryUtil.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2008 Roger C. Soares + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License, version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + */ +package org.spearce.egit.core.util; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.CancellationException; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.spearce.jgit.lib.Commit; +import org.spearce.jgit.lib.ObjectId; +import org.spearce.jgit.lib.Repository; +import org.spearce.jgit.lib.Tag; + +/** + * This class provides convenience methods to retrieve Git repository data in a + * digested form. + */ +public class RepositoryUtil { + + private Repository repository; + + private Map<ObjectId, Set<String>> sha1ToTagsMap = new HashMap<ObjectId, Set<String>>(); + + private Map<ObjectId, Set<String>> headCommitToBranchesMap = new HashMap<ObjectId, Set<String>>(); + + /** + * Constructs a <code>RepositoryUtil</code> for the + * <code>repository</code>. + * + * @param repository + * the Git repository from where data will be retrieved. + * @throws IOException + */ + public RepositoryUtil(Repository repository) throws IOException { + this.repository = repository; + + refresh(); + } + + /** + * Retrieves a <code>Set</code> with all the tags referencing + * <code>commit<code>. + * + * @param commit to be checked for references + * @return Set<String> the tag names referencing the commit sorted in ascending string order or null + */ + public Set<String> getTagNamesForCommit(Commit commit) { + return sha1ToTagsMap.get(commit.getCommitId()); + } + + /** + * Retrieves a <code>Set</code> with all the branch names referencing + * <code>commit<code>. + * + * @param commit + * @return Set<String> the branch names referencing the commit sorted in ascending string order or null + */ + public Set<String> getBranchNamesForCommit(Commit commit) { + return headCommitToBranchesMap.get(commit.getCommitId()); + } + + /** + * Walks through all branches in the repository searching information + * related to <code>commit</code>. This information is stored in the + * <code>CommitMetaInfo</code>. + * + * @param commit + * to be checked for references + * @param monitor + * the monitor from where cancellation is checked or null + * @return CommitMetaInfo + * @throws IOException + * @throws CancellationException + * if <code>monitor.isCanceled()</code> returns true during + * the execution of this method + */ + public CommitMetaInfo getCommitMetaInfo(Commit commit, + IProgressMonitor monitor) throws IOException, CancellationException { + Set<Commit> childrenSet = new HashSet<Commit>(); + Map<String, String> allBranches = new HashMap<String, String>(); + ObjectId commitId = commit.getCommitId(); + Set<String> branchNameSet = headCommitToBranchesMap.get(commitId); + if (branchNameSet != null) { + for (String branchName : branchNameSet) { + allBranches.put(branchName, branchName); + } + } + + // Verifies all branches for the commit we want + List<ObjectId> commitsToWalk = new ArrayList<ObjectId>(); + commitsToWalk.addAll(headCommitToBranchesMap.keySet()); + Map<String, String> tempBranches = new HashMap<String, String>(); + Map<ObjectId, Map<String, String>> savedTempBranches = new HashMap<ObjectId, Map<String, String>>(); + while (commitsToWalk.size() > 0) { + ObjectId branchHead = commitsToWalk.remove(0); + Commit headCommit = repository.mapCommit(branchHead); + Map<String, String> tb = savedTempBranches.get(branchHead); + if (tb == null) { + tempBranches.clear(); + tb = tempBranches; + } + lookforMetaInfo(commitId, headCommit, allBranches, childrenSet, tb, + commitsToWalk, savedTempBranches, monitor); + } + + Set<String> keySet = null; + if (allBranches.size() > 0) { + keySet = new TreeSet<String>(); + keySet.addAll(allBranches.keySet()); + } + if (childrenSet.size() == 0) { + childrenSet = null; + } + + CommitMetaInfo metaInfo = new CommitMetaInfo(keySet, childrenSet); + return metaInfo; + } + + private void lookforMetaInfo(ObjectId targetCommitId, Commit headCommit, + Map<String, String> allBranches, Set<Commit> childrenSet, + Map<String, String> tempBranches, List<ObjectId> commitsToWalk, + Map<ObjectId, Map<String, String>> savedTempBranches, + IProgressMonitor monitor) throws IOException, CancellationException { + Commit child = null; + Commit commit = headCommit; + ObjectId commitId = commit.getCommitId(); + while (!commitId.equals(targetCommitId)) { + child = commit; + Set<String> branchNameSet = headCommitToBranchesMap.get(commit + .getCommitId()); + if (branchNameSet != null) { + for (String branchName : branchNameSet) { + tempBranches.put(branchName, branchName); + } + } + ObjectId[] pIds = commit.getParentIds(); + if (pIds != null && pIds.length > 0) { + commit = repository.mapCommit(pIds[0]); + commitId = commit.getCommitId(); + int parentCount = pIds.length; + if (parentCount > 1) { + for (int i = 1; i < parentCount; i++) { + commitsToWalk.add(pIds[i]); + Map<String, String> tb = savedTempBranches.get(pIds[i]); + if (tb == null) { + tb = new HashMap<String, String>(); + savedTempBranches.put(pIds[i], tb); + } + tb.putAll(tempBranches); + if (pIds[i].equals(targetCommitId)) { + childrenSet.add(child); + } + } + } + } else { + break; + } + if (monitor != null && monitor.isCanceled()) { + throw new CancellationException("getCommitMetaInfo cancelled"); + } + } + if (commitId.equals(targetCommitId)) { + allBranches.putAll(tempBranches); + if (child != null) { + childrenSet.add(child); + } + } + } + + private void refresh() throws IOException { + // Refresh tags + sha1ToTagsMap.clear(); + for (String tagName : repository.getTags()) { + Tag tag = repository.mapTag(tagName); + Set<String> tagSet = sha1ToTagsMap.get(tag.getObjId()); + if (tagSet == null) { + tagSet = new TreeSet<String>(); + sha1ToTagsMap.put(tag.getObjId(), tagSet); + } + tagSet.add(tag.getTag()); + } + + // Refresh branches + headCommitToBranchesMap.clear(); + for (String branchName : repository.getBranches()) { + ObjectId commitId = repository.resolve(branchName); + Set<String> branchSet = headCommitToBranchesMap.get(commitId); + if (branchSet == null) { + branchSet = new TreeSet<String>(); + headCommitToBranchesMap.put(commitId, branchSet); + } + branchSet.add(branchName); + } + } + +} -- 1.5.4.1 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html