Skip to content

Commit

Permalink
Issue checkstyle#3: Git component
Browse files Browse the repository at this point in the history
  • Loading branch information
Luolc committed Jun 9, 2017
1 parent 3af72eb commit 58573f9
Show file tree
Hide file tree
Showing 8 changed files with 360 additions and 11 deletions.
27 changes: 18 additions & 9 deletions config/findbugs-exclude.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<Match>
<!-- that CLI class so we need system exit code there, but only in main(...) method -->
<Class name="com.puppycrawl.tools.checkstyle.Main" />
<Method name="main" />
<Bug pattern="DM_EXIT" />
</Match>
</FindBugsFilter>
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<Match>
<!-- that CLI class so we need system exit code there, but only in main(...) method -->
<Class name="com.puppycrawl.tools.checkstyle.Main"/>
<Method name="main"/>
<Bug pattern="DM_EXIT"/>
</Match>
<Match>
<!-- This is a false positive. It is no problem to do that cast. In fact the cast is
in JGit library. There is no reason to raise this warning. -->
<Class name="com.github.checkstyle.regression.git.DiffParser"/>
<Or>
<Bug pattern="BC_UNCONFIRMED_CAST"/>
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE"/>
</Or>
</Match>
</FindBugsFilter>
5 changes: 5 additions & 0 deletions config/import-control.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@
"http://www.puppycrawl.com/dtds/import_control_1_1.dtd">

<import-control pkg="com.github.checkstyle.regression">
<allow pkg="java.io"/>
<allow pkg="java.util"/>
<subpackage name="git">
<allow pkg="org.eclipse.jgit"/>
</subpackage>
</import-control>
23 changes: 21 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-jxr</artifactId>
Expand Down Expand Up @@ -146,7 +158,8 @@
<configLocation>
https://raw.githubusercontent.com/checkstyle/checkstyle/checkstyle-${checkstyle.version}/config/checkstyle_sevntu_checks.xml
</configLocation>
<propertyExpansion>project.basedir=${project.basedir}</propertyExpansion>
<propertyExpansion>project.basedir=${project.basedir}
</propertyExpansion>
<failOnViolation>true</failOnViolation>
<logViolationsToConsole>true</logViolationsToConsole>
<maxAllowedViolations>0</maxAllowedViolations>
Expand Down Expand Up @@ -205,7 +218,7 @@
<format>xml</format>
<format>html</format>
</formats>
<check />
<check/>
</configuration>
</plugin>

Expand Down Expand Up @@ -254,6 +267,12 @@
<branchRate>0</branchRate>
<lineRate>0</lineRate>
</regex>
<regex>
<pattern>com.github.checkstyle.regression.git.DiffParser
</pattern>
<branchRate>50</branchRate>
<lineRate>100</lineRate>
</regex>
</regexes>
</check>
<instrumentation>
Expand Down
104 changes: 104 additions & 0 deletions src/main/java/com/github/checkstyle/regression/git/DiffParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////

package com.github.checkstyle.regression.git;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;

/**
* Git diff parser.
* @author LuoLiangchen
*/
public class DiffParser {
/** The path of checkstyle repository. */
private final String repositoryPath;

/**
* Creates a new {@code DiffParser} instance.
* @param repositoryPath the path of checkstyle repository
*/
public DiffParser(String repositoryPath) {
this.repositoryPath = repositoryPath;
}

/**
* Parses the diff between a given branch and the master.
* @param branchName the name of the branch to be compared with master
* @return a list of {@code GitChange} to represent the changes
* @throws IOException JGit library exception
* @throws GitAPIException JGit library exception
*/
public List<GitChange> parse(String branchName) throws IOException, GitAPIException {
final File gitDir = new File(repositoryPath, ".git");
try (Repository repository = new FileRepositoryBuilder().setGitDir(gitDir)
.readEnvironment().findGitDir().build()) {
try (Git git = new Git(repository)) {
final AbstractTreeIterator featureTreeParser =
prepareTreeParser(repository, Constants.R_HEADS + branchName);
final AbstractTreeIterator masterTreeParser =
prepareTreeParser(repository, Constants.R_HEADS + "master");
return git.diff()
.setOldTree(masterTreeParser)
.setNewTree(featureTreeParser)
.call()
.stream()
.map(GitChange::new)
.collect(Collectors.toList());
}
}
}

/**
* Creates a tree parser from a commit, to be used by diff command.
* @param repository the repository to parse diff
* @param ref the name of the ref to the commit; e.g., "refs/heads/master"
* @return the tree parser
* @throws IOException JGit library exception
*/
private static AbstractTreeIterator prepareTreeParser(Repository repository, String ref)
throws IOException {
final Ref head = repository.exactRef(ref);
try (RevWalk walk = new RevWalk(repository)) {
final RevCommit commit = walk.parseCommit(head.getObjectId());
final RevTree tree = walk.parseTree(commit.getTree().getId());
final CanonicalTreeParser treeParser = new CanonicalTreeParser();
try (ObjectReader reader = repository.newObjectReader()) {
treeParser.reset(reader, tree.getId());
}
walk.dispose();
return treeParser;
}
}
}
47 changes: 47 additions & 0 deletions src/main/java/com/github/checkstyle/regression/git/GitChange.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////

package com.github.checkstyle.regression.git;

import org.eclipse.jgit.diff.DiffEntry;

/**
* Represents git changes of a file.
* @author LuoLiangchen
*/
public class GitChange {
/** The path of the changed file. */
private final String path;

/**
* Creates a new {@code GitChange} instance from a {@code DiffEntry}.
* @param diff the {@code DiffEntry}
*/
GitChange(DiffEntry diff) {
path = diff.getNewPath();
}

/**
* Gets the path of the changed file.
* @return the path of the changed file
*/
public String getPath() {
return path;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////

/**
* Contains git related classes.
*/
package com.github.checkstyle.regression.git;
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////

package com.github.checkstyle.regression.git;

import static org.junit.Assert.assertEquals;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.List;

import org.eclipse.jgit.lib.Repository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.github.checkstyle.regression.internal.GitUtils;

public class DiffParserTest {
private Repository repository;

@Before
public void setUp() throws Exception {
repository = GitUtils.newRepository();
final File helloWorld = GitUtils.addAnEmptyFileAndCommit(repository, "HelloWorld");
GitUtils.createNewBranchAndCheckout(repository, "foo");
Files.write(helloWorld.toPath(), "hello world!".getBytes(), StandardOpenOption.APPEND);
GitUtils.addAllAndCommit(repository, "append text to HelloWorld");
}

@After
public void tearDown() throws Exception {
repository.close();
}

@Test
public void testParse() throws Exception {
final DiffParser diffParser = new DiffParser(repository.getDirectory().getParent());
final List<GitChange> changes = diffParser.parse("foo");
assertEquals(1, changes.size());
assertEquals("HelloWorld", changes.iterator().next().getPath());
}
}
Loading

0 comments on commit 58573f9

Please sign in to comment.