forked from pfeuffer/GitCover
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support to check coverage on new code with jacoco reports. Reso…
…lves issue pfeuffer#2
- Loading branch information
Showing
11 changed files
with
554 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
core/src/main/java/de/pfeufferweb/gitcover/ChangedLines.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package de.pfeufferweb.gitcover; | ||
|
||
import static java.util.Collections.unmodifiableCollection; | ||
|
||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class ChangedLines | ||
{ | ||
private final Map<String, Map<Integer, String>> changedLines = new HashMap<String, Map<Integer, String>>(); | ||
|
||
public void addFile(String fileName, Map<Integer, String> lines) | ||
{ | ||
changedLines.put(fileName, new HashMap<Integer, String>(lines)); | ||
} | ||
|
||
public Collection<String> getFileNames() | ||
{ | ||
return unmodifiableCollection(changedLines.keySet()); | ||
} | ||
|
||
public Collection<Integer> getChangedLines(String changedFile) | ||
{ | ||
return unmodifiableCollection(changedLines.get(changedFile).keySet()); | ||
} | ||
|
||
public String getLine(String changedFile, int line) | ||
{ | ||
return changedLines.get(changedFile).get(line); | ||
} | ||
|
||
} |
125 changes: 125 additions & 0 deletions
125
core/src/main/java/de/pfeufferweb/gitcover/ChangedLinesBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package de.pfeufferweb.gitcover; | ||
|
||
import java.io.File; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import org.eclipse.jgit.api.Git; | ||
import org.eclipse.jgit.diff.DiffEntry; | ||
import org.eclipse.jgit.diff.DiffEntry.ChangeType; | ||
import org.eclipse.jgit.lib.AbbreviatedObjectId; | ||
import org.eclipse.jgit.lib.ObjectId; | ||
import org.eclipse.jgit.lib.ObjectLoader; | ||
import org.eclipse.jgit.lib.ObjectReader; | ||
import org.eclipse.jgit.lib.ObjectStream; | ||
import org.eclipse.jgit.lib.Repository; | ||
import org.eclipse.jgit.lib.RepositoryBuilder; | ||
import org.eclipse.jgit.treewalk.CanonicalTreeParser; | ||
|
||
import difflib.Delta; | ||
import difflib.DiffUtils; | ||
import difflib.Patch; | ||
|
||
public class ChangedLinesBuilder | ||
{ | ||
private final Repository repository; | ||
private boolean includeModified = true; | ||
private boolean includeAdded = true; | ||
|
||
public ChangedLinesBuilder(String repoFolder) throws Exception | ||
{ | ||
this.repository = new RepositoryBuilder().findGitDir(new File(repoFolder)).build(); | ||
} | ||
|
||
public ChangedLines build(String revision) throws Exception | ||
{ | ||
ChangedLines changedLines = new ChangedLines(); | ||
Git git = new Git(repository); | ||
|
||
ObjectId headId = repository.resolve("HEAD^{tree}"); | ||
ObjectId oldId = repository.resolve(revision + "^{tree}"); | ||
|
||
ObjectReader reader = repository.newObjectReader(); | ||
|
||
CanonicalTreeParser newTreeIter = new CanonicalTreeParser(); | ||
newTreeIter.reset(reader, headId); | ||
CanonicalTreeParser oldTreeIter = new CanonicalTreeParser(); | ||
oldTreeIter.reset(reader, oldId); | ||
|
||
List<DiffEntry> diffs = git.diff().setNewTree(newTreeIter).setOldTree(oldTreeIter).call(); | ||
|
||
for (DiffEntry diff : diffs) | ||
{ | ||
boolean isRelevantFile = diff.getNewPath().endsWith(".java"); | ||
if (isRelevantFile) | ||
{ | ||
if (includeModified && isModified(diff)) | ||
{ | ||
Map<Integer, String> lines = process(diff); | ||
changedLines.addFile(diff.getNewPath(), lines); | ||
} | ||
else if (includeAdded && isAdded(diff)) | ||
{ | ||
Map<Integer, String> lines = createLines(load(diff.getNewId())); | ||
changedLines.addFile(diff.getNewPath(), lines); | ||
} | ||
} | ||
} | ||
return changedLines; | ||
} | ||
|
||
public void setIncludeModified(boolean includeModified) | ||
{ | ||
this.includeModified = includeModified; | ||
} | ||
|
||
public void setIncludeAdded(boolean includeAdded) | ||
{ | ||
this.includeAdded = includeAdded; | ||
} | ||
|
||
private boolean isModified(DiffEntry diff) | ||
{ | ||
return diff.getChangeType() == ChangeType.MODIFY; | ||
} | ||
|
||
private boolean isAdded(DiffEntry diff) | ||
{ | ||
return diff.getChangeType() == ChangeType.ADD; | ||
} | ||
|
||
private Map<Integer, String> createLines(List<String> content) | ||
{ | ||
Map<Integer, String> lines = new HashMap<Integer, String>(); | ||
for (int i = 0; i < content.size(); ++i) | ||
{ | ||
lines.put(i + 1, content.get(i)); | ||
} | ||
return lines; | ||
} | ||
|
||
private Map<Integer, String> process(DiffEntry diff) throws Exception | ||
{ | ||
Patch patch = DiffUtils.diff(load(diff.getOldId()), load(diff.getNewId())); | ||
Map<Integer, String> lines = new HashMap<Integer, String>(); | ||
for (Delta delta : patch.getDeltas()) | ||
{ | ||
int initialPosition = delta.getRevised().getPosition(); | ||
int diffLength = delta.getRevised().getLines().size(); | ||
for (int i = 0; i < diffLength; ++i) | ||
{ | ||
lines.put(initialPosition + i + 1, delta.getRevised().getLines().get(i).toString()); | ||
} | ||
} | ||
return lines; | ||
} | ||
|
||
private List<String> load(AbbreviatedObjectId objectId) throws Exception | ||
{ | ||
ObjectLoader loader = repository.open(objectId.toObjectId()); | ||
|
||
ObjectStream stream = loader.openStream(); | ||
return new FileLoader(stream).load(); | ||
} | ||
} |
108 changes: 108 additions & 0 deletions
108
core/src/main/java/de/pfeufferweb/gitcover/CoberturaCoverageBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package de.pfeufferweb.gitcover; | ||
|
||
import static java.lang.Integer.parseInt; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.StringReader; | ||
import java.util.Collection; | ||
|
||
import javax.xml.parsers.DocumentBuilder; | ||
import javax.xml.parsers.DocumentBuilderFactory; | ||
import javax.xml.xpath.XPath; | ||
import javax.xml.xpath.XPathConstants; | ||
import javax.xml.xpath.XPathExpression; | ||
import javax.xml.xpath.XPathFactory; | ||
|
||
import org.apache.commons.io.FileUtils; | ||
import org.apache.commons.io.filefilter.IOFileFilter; | ||
import org.w3c.dom.Document; | ||
import org.w3c.dom.NamedNodeMap; | ||
import org.w3c.dom.NodeList; | ||
import org.xml.sax.EntityResolver; | ||
import org.xml.sax.InputSource; | ||
import org.xml.sax.SAXException; | ||
|
||
public class CoberturaCoverageBuilder | ||
{ | ||
public Coverage computeAll(File directory) throws Exception | ||
{ | ||
Coverage overallCoverage = new Coverage(); | ||
Collection<File> files = FileUtils.listFiles(directory, new IOFileFilter() | ||
{ | ||
|
||
@Override | ||
public boolean accept(File dir, String name) | ||
{ | ||
return false; | ||
} | ||
|
||
@Override | ||
public boolean accept(File file) | ||
{ | ||
return file.getName().equals("coverage.xml"); | ||
} | ||
}, new IOFileFilter() | ||
{ | ||
|
||
@Override | ||
public boolean accept(File dir, String name) | ||
{ | ||
return false; | ||
} | ||
|
||
@Override | ||
public boolean accept(File file) | ||
{ | ||
return true; | ||
} | ||
}); | ||
for (File file : files) | ||
{ | ||
overallCoverage.addAll(compute(file)); | ||
} | ||
return overallCoverage; | ||
} | ||
|
||
public Coverage compute(File file) throws Exception | ||
{ | ||
Coverage result = new Coverage(); | ||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | ||
DocumentBuilder builder = factory.newDocumentBuilder(); | ||
builder.setEntityResolver(new EntityResolver() | ||
{ | ||
@Override | ||
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException | ||
{ | ||
if (systemId.contains("cobertura.sourceforge.net")) | ||
{ | ||
return new InputSource(new StringReader("")); | ||
} | ||
else | ||
{ | ||
return null; | ||
} | ||
} | ||
}); | ||
Document doc = builder.parse(file); | ||
XPathFactory xPathfactory = XPathFactory.newInstance(); | ||
XPath xpath = xPathfactory.newXPath(); | ||
XPathExpression classExpr = xpath.compile("//class/@filename"); | ||
NodeList foundFileNodes = (NodeList) classExpr.evaluate(doc, XPathConstants.NODESET); | ||
for (int i = 0; i < foundFileNodes.getLength(); ++i) | ||
{ | ||
String fileName = foundFileNodes.item(i).getNodeValue(); | ||
result.addFile(fileName); | ||
XPathExpression linesExpr = xpath.compile("//class[@filename='" + fileName + "']//line"); | ||
NodeList foundLineNodes = (NodeList) linesExpr.evaluate(doc, XPathConstants.NODESET); | ||
for (int j = 0; j < foundLineNodes.getLength(); ++j) | ||
{ | ||
NamedNodeMap attributes = foundLineNodes.item(j).getAttributes(); | ||
int line = parseInt(attributes.getNamedItem("number").getNodeValue()); | ||
int hits = parseInt(attributes.getNamedItem("hits").getNodeValue()); | ||
result.addLine(fileName, line, hits); | ||
} | ||
} | ||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package de.pfeufferweb.gitcover; | ||
|
||
import static java.util.Collections.unmodifiableCollection; | ||
|
||
import java.util.Collection; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.NoSuchElementException; | ||
|
||
public class Coverage | ||
{ | ||
private final Map<String, Map<Integer, Integer>> coverage = new HashMap<String, Map<Integer, Integer>>(); | ||
|
||
void addFile(String fileName) | ||
{ | ||
coverage.put(fileName, new HashMap<Integer, Integer>()); | ||
} | ||
|
||
void addLine(String fileName, int line, int hits) | ||
{ | ||
coverage.get(fileName).put(line, hits); | ||
} | ||
|
||
public void addAll(Coverage subCoverage) | ||
{ | ||
this.coverage.putAll(subCoverage.coverage); | ||
} | ||
|
||
/** | ||
* @throws NoSuchElementException | ||
* whenever there is no coverage for the given file. | ||
*/ | ||
public Map<Integer, Integer> getCoverage(String name) | ||
{ | ||
for (String candidate : getFileNames()) | ||
{ | ||
if (name.endsWith(candidate) || candidate.endsWith(name)) | ||
{ | ||
return coverage.get(candidate); | ||
} | ||
} | ||
throw new NoSuchElementException("no coverage found for file " + name); | ||
} | ||
|
||
public Collection<String> getFileNames() | ||
{ | ||
return unmodifiableCollection(coverage.keySet()); | ||
} | ||
} |
Oops, something went wrong.