forked from TouK/sputnik
-
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.
Add "local" connector type (TouK#206)
Add local connector type. Runs analysis tools on the HEAD of the local git repository and reports to the log. Fixes TouK#195
- Loading branch information
1 parent
5b42b05
commit 08df113
Showing
10 changed files
with
276 additions
and
4 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
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
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 |
---|---|---|
@@ -1,5 +1,5 @@ | ||
package pl.touk.sputnik.connector; | ||
|
||
public enum Connectors { | ||
STASH, GERRIT, GITHUB, SAAS | ||
STASH, GERRIT, GITHUB, SAAS, LOCAL | ||
} |
102 changes: 102 additions & 0 deletions
102
src/main/java/pl/touk/sputnik/connector/local/LocalFacade.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,102 @@ | ||
package pl.touk.sputnik.connector.local; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.eclipse.jgit.diff.DiffEntry; | ||
import org.eclipse.jgit.diff.DiffEntry.ChangeType; | ||
import org.eclipse.jgit.diff.DiffFormatter; | ||
import org.eclipse.jgit.lib.Constants; | ||
import org.eclipse.jgit.lib.ObjectId; | ||
import org.eclipse.jgit.lib.Repository; | ||
import org.jetbrains.annotations.NotNull; | ||
import pl.touk.sputnik.configuration.Configuration; | ||
import pl.touk.sputnik.configuration.GeneralOption; | ||
import pl.touk.sputnik.configuration.GeneralOptionNotSupportedException; | ||
import pl.touk.sputnik.connector.ConnectorFacade; | ||
import pl.touk.sputnik.connector.ConnectorValidator; | ||
import pl.touk.sputnik.connector.Connectors; | ||
import pl.touk.sputnik.connector.ReviewPublisher; | ||
import pl.touk.sputnik.review.Comment; | ||
import pl.touk.sputnik.review.Review; | ||
import pl.touk.sputnik.review.ReviewFile; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
|
||
import static java.util.stream.Collectors.toList; | ||
|
||
@AllArgsConstructor | ||
@Slf4j | ||
public class LocalFacade implements ConnectorFacade, ConnectorValidator, ReviewPublisher { | ||
private final Repository repository; | ||
private final DiffFormatter diffFormatter; | ||
private final LocalFacadeOutput output; | ||
|
||
@NotNull | ||
@Override | ||
public List<ReviewFile> listFiles() { | ||
try { | ||
ObjectId head = repository.resolve(Constants.HEAD); | ||
ObjectId headParent = repository.resolve(Constants.HEAD + "^"); | ||
List<DiffEntry> diffs = diffFormatter.scan(headParent, head); | ||
return diffs.stream() | ||
.filter(this::isNotDeleted) | ||
.map(DiffEntry::getNewPath) | ||
.map(ReviewFile::new) | ||
.collect(toList()); | ||
} catch (IOException e) { | ||
throw new RuntimeException("Error when listing files", e); | ||
} | ||
} | ||
|
||
private boolean isNotDeleted(DiffEntry aDiffEntry) { | ||
return aDiffEntry.getChangeType() != ChangeType.DELETE; | ||
} | ||
|
||
@Override | ||
public void publish(@NotNull Review review) { | ||
long numFilesWithComments = review.getFiles().stream().filter(files -> !files.getComments().isEmpty()).count(); | ||
if (numFilesWithComments == 0) { | ||
output.info("No sputnik comments"); | ||
return; | ||
} | ||
|
||
for (String message : review.getMessages()) { | ||
output.warn(message); | ||
} | ||
|
||
for (ReviewFile file : review.getFiles()) { | ||
if (file.getComments().isEmpty()) { | ||
continue; | ||
} | ||
|
||
output.warn(""); | ||
|
||
output.warn("{} comment(s) on {}", file.getComments().size(), file.getReviewFilename()); | ||
for (Comment comment : file.getComments()) { | ||
output.warn("Line {}: {}", comment.getLine(), comment.getMessage()); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public Connectors name() { | ||
return Connectors.LOCAL; | ||
} | ||
|
||
@Override | ||
public void validate(Configuration configuration) throws GeneralOptionNotSupportedException { | ||
boolean commentOnlyChangedLines = Boolean.parseBoolean(configuration | ||
.getProperty(GeneralOption.COMMENT_ONLY_CHANGED_LINES)); | ||
|
||
if (commentOnlyChangedLines) { | ||
throw new GeneralOptionNotSupportedException("This connector does not support " | ||
+ GeneralOption.COMMENT_ONLY_CHANGED_LINES.getKey()); | ||
} | ||
} | ||
|
||
@Override | ||
public void setReview(@NotNull Review review) { | ||
publish(review); | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
src/main/java/pl/touk/sputnik/connector/local/LocalFacadeBuilder.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,21 @@ | ||
package pl.touk.sputnik.connector.local; | ||
|
||
import org.eclipse.jgit.diff.DiffFormatter; | ||
import org.eclipse.jgit.lib.Repository; | ||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder; | ||
import org.eclipse.jgit.util.io.NullOutputStream; | ||
|
||
import java.io.IOException; | ||
|
||
public class LocalFacadeBuilder { | ||
public LocalFacade build() { | ||
try (Repository repository = new FileRepositoryBuilder().readEnvironment().findGitDir().build()) { | ||
try (DiffFormatter diffFormatter = new DiffFormatter(NullOutputStream.INSTANCE)) { | ||
diffFormatter.setRepository(repository); | ||
return new LocalFacade(repository, diffFormatter, new LocalFacadeOutput()); | ||
} | ||
} catch (IOException e) { | ||
throw new RuntimeException("Error getting git repository", e); | ||
} | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/pl/touk/sputnik/connector/local/LocalFacadeOutput.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,16 @@ | ||
package pl.touk.sputnik.connector.local; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@AllArgsConstructor | ||
@Slf4j | ||
public class LocalFacadeOutput { | ||
void info(String message, Object ... arguments) { | ||
log.info(message, arguments); | ||
} | ||
|
||
void warn(String message, Object ... arguments) { | ||
log.warn(message, arguments); | ||
} | ||
} |
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
128 changes: 128 additions & 0 deletions
128
src/test/java/pl/touk/sputnik/connector/local/LocalFacadeTest.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,128 @@ | ||
package pl.touk.sputnik.connector.local; | ||
|
||
import com.google.common.collect.ImmutableList; | ||
import org.eclipse.jgit.diff.DiffEntry; | ||
import org.eclipse.jgit.diff.DiffEntry.ChangeType; | ||
import org.eclipse.jgit.diff.DiffFormatter; | ||
import org.eclipse.jgit.lib.Constants; | ||
import org.eclipse.jgit.lib.ObjectId; | ||
import org.eclipse.jgit.lib.Repository; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.InOrder; | ||
import org.mockito.Mock; | ||
import org.mockito.Mockito; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import pl.touk.sputnik.review.Comment; | ||
import pl.touk.sputnik.review.Review; | ||
import pl.touk.sputnik.review.ReviewFile; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.mockito.Answers.RETURNS_DEEP_STUBS; | ||
import static org.mockito.ArgumentMatchers.anyString; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.never; | ||
import static org.mockito.Mockito.verify; | ||
import static org.mockito.Mockito.when; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
class LocalFacadeTest { | ||
@Mock(answer = RETURNS_DEEP_STUBS) | ||
private Repository repo; | ||
@Mock | ||
private DiffFormatter diffFormatter; | ||
@Mock | ||
private DiffEntry modifiedFile; | ||
@Mock | ||
private DiffEntry deletedFile; | ||
@Mock | ||
private DiffEntry newFile; | ||
@Mock | ||
private Review review; | ||
@Mock | ||
private LocalFacadeOutput output; | ||
|
||
private LocalFacade localFacade; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
localFacade = new LocalFacade(repo, diffFormatter, output); | ||
} | ||
|
||
private void setUpDiff() throws IOException { | ||
when(modifiedFile.getNewPath()).thenReturn("/path/to/modifiedFile"); | ||
when(modifiedFile.getChangeType()).thenReturn(ChangeType.MODIFY); | ||
|
||
when(newFile.getNewPath()).thenReturn("/path/to/newFile"); | ||
when(newFile.getChangeType()).thenReturn(ChangeType.ADD); | ||
|
||
when(deletedFile.getChangeType()).thenReturn(ChangeType.DELETE); | ||
|
||
ObjectId head = mock(ObjectId.class); | ||
ObjectId headParent = mock(ObjectId.class); | ||
when(repo.resolve(Constants.HEAD)).thenReturn(head); | ||
when(repo.resolve(Constants.HEAD + "^")).thenReturn(headParent); | ||
when(diffFormatter.scan(headParent, head)).thenReturn(ImmutableList.of(modifiedFile, deletedFile, newFile)); | ||
} | ||
|
||
@Test | ||
void shouldParseListFilesResponse() throws IOException { | ||
setUpDiff(); | ||
|
||
List<ReviewFile> reviewFiles = localFacade.listFiles(); | ||
assertThat(reviewFiles).isNotEmpty(); | ||
} | ||
|
||
@Test | ||
void shouldNotListDeletedFiles() throws IOException { | ||
setUpDiff(); | ||
|
||
List<ReviewFile> reviewFiles = localFacade.listFiles(); | ||
assertThat(reviewFiles) | ||
.hasSize(2) | ||
.extracting(ReviewFile::getReviewFilename).containsExactly(modifiedFile.getNewPath(), newFile.getNewPath()); | ||
} | ||
|
||
@Test | ||
void shouldPublishNoCommentsIfAllFilesHaveNoComments() { | ||
ReviewFile review1 = mock(ReviewFile.class); | ||
ReviewFile review2 = mock(ReviewFile.class); | ||
when(review.getFiles()).thenReturn(ImmutableList.of(review1, review2)); | ||
|
||
localFacade.publish(review); | ||
|
||
verify(output).info("No sputnik comments"); | ||
verify(output, never()).warn(anyString()); | ||
} | ||
|
||
@Test | ||
void shouldWarnWithCommentsAndLineNumbers() { | ||
ReviewFile review1 = mock(ReviewFile.class); | ||
when(review1.getReviewFilename()).thenReturn("/path/to/file1"); | ||
ReviewFile review2 = mock(ReviewFile.class); | ||
ReviewFile review3 = mock(ReviewFile.class); | ||
when(review3.getReviewFilename()).thenReturn("/path/to/file3"); | ||
when(review1.getComments()).thenReturn(ImmutableList.of(new Comment(11, "Comment 1"), new Comment(14, "Comment 2"))); | ||
when(review3.getComments()).thenReturn(ImmutableList.of(new Comment(15, "Comment 3"))); | ||
when(review.getMessages()).thenReturn(ImmutableList.of("message 1", "message 2")); | ||
when(review.getFiles()).thenReturn(ImmutableList.of(review1, review2, review3)); | ||
|
||
localFacade.publish(review); | ||
|
||
verify(output, never()).info(anyString()); | ||
InOrder order = Mockito.inOrder(output); | ||
order.verify(output).warn("message 1"); | ||
order.verify(output).warn("message 2"); | ||
order.verify(output).warn(""); | ||
order.verify(output).warn("{} comment(s) on {}", 2, "/path/to/file1"); | ||
order.verify(output).warn("Line {}: {}", 11, "Comment 1"); | ||
order.verify(output).warn("Line {}: {}", 14, "Comment 2"); | ||
order.verify(output).warn(""); | ||
order.verify(output).warn("{} comment(s) on {}", 1, "/path/to/file3"); | ||
order.verify(output).warn("Line {}: {}", 15, "Comment 3"); | ||
} | ||
} |