org.openrewrite.jgit.revplot.PlotWalk Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jgit Show documentation
Show all versions of jgit Show documentation
Fork of jgit to maintain Java 8 compatibility
The newest version!
/*
* Copyright (C) 2008-2018, Robin Rosenberg
* Copyright (C) 2008, Shawn O. Pearce and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
* https://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package org.openrewrite.jgit.revplot;
import static org.openrewrite.jgit.lib.Constants.R_HEADS;
import static org.openrewrite.jgit.lib.Constants.R_REMOTES;
import static org.openrewrite.jgit.lib.Constants.R_TAGS;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.openrewrite.jgit.errors.IncorrectObjectTypeException;
import org.openrewrite.jgit.errors.MissingObjectException;
import org.openrewrite.jgit.internal.JGitText;
import org.openrewrite.jgit.lib.AnyObjectId;
import org.openrewrite.jgit.lib.PersonIdent;
import org.openrewrite.jgit.lib.Ref;
import org.openrewrite.jgit.lib.Repository;
import org.openrewrite.jgit.revwalk.RevCommit;
import org.openrewrite.jgit.revwalk.RevObject;
import org.openrewrite.jgit.revwalk.RevSort;
import org.openrewrite.jgit.revwalk.RevTag;
import org.openrewrite.jgit.revwalk.RevWalk;
/**
* Specialized RevWalk for visualization of a commit graph.
*/
public class PlotWalk extends RevWalk {
private Map> additionalRefMap;
private Map> reverseRefMap;
private Repository repository;
/** {@inheritDoc} */
@Override
public void dispose() {
super.dispose();
if (reverseRefMap != null) {
reverseRefMap.clear();
reverseRefMap = null;
}
if (additionalRefMap != null) {
additionalRefMap.clear();
additionalRefMap = null;
}
repository = null;
}
/**
* Create a new revision walker for a given repository.
*
* @param repo
* the repository the walker will obtain data from.
*/
public PlotWalk(Repository repo) {
super(repo);
super.sort(RevSort.TOPO, true);
additionalRefMap = new HashMap<>();
repository = repo;
}
/**
* Add additional refs to the walk
*
* @param refs
* additional refs
* @throws java.io.IOException
*/
public void addAdditionalRefs(Iterable refs) throws IOException {
for (Ref ref : refs) {
Set set = additionalRefMap.get(ref.getObjectId());
if (set == null)
set = Collections.singleton(ref);
else {
set = new HashSet<>(set);
set.add(ref);
}
additionalRefMap.put(ref.getObjectId(), set);
}
}
/** {@inheritDoc} */
@Override
public void sort(RevSort s, boolean use) {
if (s == RevSort.TOPO && !use)
throw new IllegalArgumentException(JGitText.get().topologicalSortRequired);
super.sort(s, use);
}
/** {@inheritDoc} */
@Override
protected RevCommit createCommit(AnyObjectId id) {
return new PlotCommit(id);
}
/** {@inheritDoc} */
@Override
public RevCommit next() throws MissingObjectException,
IncorrectObjectTypeException, IOException {
PlotCommit> pc = (PlotCommit) super.next();
if (pc != null)
pc.refs = getRefs(pc);
return pc;
}
private Ref[] getRefs(AnyObjectId commitId) {
if (reverseRefMap == null) {
reverseRefMap = repository.getAllRefsByPeeledObjectId();
for (Map.Entry> entry : additionalRefMap
.entrySet()) {
Set set = reverseRefMap.get(entry.getKey());
Set additional = entry.getValue();
if (set != null) {
if (additional.size() == 1) {
// It's an unmodifiable singleton set...
additional = new HashSet<>(additional);
}
additional.addAll(set);
}
reverseRefMap.put(entry.getKey(), additional);
}
additionalRefMap.clear();
additionalRefMap = null;
}
Collection list = reverseRefMap.get(commitId);
if (list == null) {
return PlotCommit.NO_REFS;
}
Ref[] tags = list.toArray(new Ref[0]);
Arrays.sort(tags, new PlotRefComparator());
return tags;
}
class PlotRefComparator implements Comparator {
@Override
public int compare(Ref o1, Ref o2) {
try {
RevObject obj1 = parseAny(o1.getObjectId());
RevObject obj2 = parseAny(o2.getObjectId());
long t1 = timeof(obj1);
long t2 = timeof(obj2);
if (t1 > t2)
return -1;
if (t1 < t2)
return 1;
} catch (IOException e) {
// ignore
}
int cmp = kind(o1) - kind(o2);
if (cmp == 0)
cmp = o1.getName().compareTo(o2.getName());
return cmp;
}
long timeof(RevObject o) {
if (o instanceof RevCommit)
return ((RevCommit) o).getCommitTime();
if (o instanceof RevTag) {
RevTag tag = (RevTag) o;
try {
parseBody(tag);
} catch (IOException e) {
return 0;
}
PersonIdent who = tag.getTaggerIdent();
return who != null ? who.getWhen().getTime() : 0;
}
return 0;
}
int kind(Ref r) {
if (r.getName().startsWith(R_TAGS))
return 0;
if (r.getName().startsWith(R_HEADS))
return 1;
if (r.getName().startsWith(R_REMOTES))
return 2;
return 3;
}
}
}