GH-861 - JUnit change detection now properly detects changes in current working directory.
Added a decorating FileModificationDetector implementation that filters changes to only return those that affect the current working directory, so that the detection works properly if executed from a nested folder in multi-module projects.
This commit is contained in:
@@ -52,6 +52,10 @@ public interface FileModificationDetector {
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public static FileModificationDetector getDetector(PropertyResolver propertyResolver) {
|
||||
return WorkingDirectoryChangesDetector.of(getTargetDetector(propertyResolver));
|
||||
}
|
||||
|
||||
static FileModificationDetector getTargetDetector(PropertyResolver propertyResolver) {
|
||||
|
||||
Assert.notNull(propertyResolver, "PropertyResolver must not be null!");
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.modulith.junit.diff;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -39,4 +40,20 @@ public record ModifiedFile(String path) {
|
||||
public static Stream<ModifiedFile> of(String... paths) {
|
||||
return Arrays.stream(paths).map(ModifiedFile::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current {@link ModifiedFile} as relative to the given reference path. I.e., a {@code foo/bar.txt} with
|
||||
* a reference of {@code foo} would result in {@code bar.txt}.
|
||||
*
|
||||
* @param reference must not be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
ModifiedFile asRelativeTo(String reference) {
|
||||
|
||||
Assert.notNull(reference, "Path must not be null!");
|
||||
Assert.isTrue(reference.startsWith(reference),
|
||||
() -> "Modified file at %s is not located in %s!".formatted(reference, reference));
|
||||
|
||||
return reference.isEmpty() ? this : new ModifiedFile(this.path.substring(reference.length() + 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.junit.diff;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link FileModificationDetector} that filters the {@link ModifiedFile} instances returned by a delegate
|
||||
* {@link FileModificationDetector} to only contain those nested in the current, repository-relative working directory.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @since 1.3
|
||||
*/
|
||||
class WorkingDirectoryChangesDetector implements FileModificationDetector {
|
||||
|
||||
private final FileModificationDetector delegate;
|
||||
private final String workingDirectory;
|
||||
|
||||
/**
|
||||
* Creates a new {@link WorkingDirectoryChangesDetector} for the given {@link FileModificationDetector} delegate and
|
||||
* directory;
|
||||
*
|
||||
* @param delegate must not be {@literal null}.
|
||||
* @param workingDirectory must not be {@literal null}.
|
||||
*/
|
||||
WorkingDirectoryChangesDetector(FileModificationDetector delegate, String workingDirectory) {
|
||||
|
||||
Assert.notNull(delegate, "FileModificationDetector must not be null!");
|
||||
Assert.notNull(workingDirectory, "Working folder must not be null!");
|
||||
|
||||
this.delegate = delegate;
|
||||
this.workingDirectory = workingDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link WorkingDirectoryChangesDetector} for the current Git repository-relative working directory.
|
||||
*
|
||||
* @param delegate must not be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public static WorkingDirectoryChangesDetector of(FileModificationDetector delegate) {
|
||||
|
||||
var pathToRepo = JGitUtil.withRepository(it -> it.getDirectory().getParent());
|
||||
|
||||
// someFolder/.
|
||||
var currentWorkingDirectory = new File(".").getAbsolutePath();
|
||||
|
||||
// Strip repository base and /.
|
||||
var repositoryRelative = currentWorkingDirectory.substring(pathToRepo.length() + 1,
|
||||
currentWorkingDirectory.length() - 2);
|
||||
|
||||
return new WorkingDirectoryChangesDetector(delegate, repositoryRelative);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.modulith.junit.diff.FileModificationDetector#getModifiedFiles()
|
||||
*/
|
||||
@Override
|
||||
public Stream<ModifiedFile> getModifiedFiles() {
|
||||
|
||||
return delegate.getModifiedFiles()
|
||||
.filter(it -> it.path().startsWith(workingDirectory))
|
||||
.map(it -> it.asRelativeTo(workingDirectory));
|
||||
}
|
||||
}
|
||||
@@ -56,9 +56,9 @@ class FileModificationDetectorUnitTests {
|
||||
@Test // GH-31
|
||||
void selectingDefaultExplicitlyUsesDefault() {
|
||||
|
||||
var explicitDetector = FileModificationDetector.getDetector(setupEnvironment("default", null));
|
||||
var explicitDetector = FileModificationDetector.getTargetDetector(setupEnvironment("default", null));
|
||||
|
||||
assertThat(FileModificationDetector.getDetector(setupEnvironment(null, null)))
|
||||
assertThat(FileModificationDetector.getTargetDetector(setupEnvironment(null, null)))
|
||||
.isEqualTo(explicitDetector);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ class FileModificationDetectorUnitTests {
|
||||
|
||||
var environment = setupEnvironment(detector, referenceCommit);
|
||||
|
||||
assertThat(FileModificationDetector.getDetector(environment)).isInstanceOf(expected);
|
||||
assertThat(FileModificationDetector.getTargetDetector(environment)).isInstanceOf(expected);
|
||||
}
|
||||
|
||||
private static Environment setupEnvironment(String detector, String referenceCommit) {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.junit.diff;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ModifiedFile}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @since 1.3
|
||||
*/
|
||||
class ModifiedFileUnitTest {
|
||||
|
||||
@Test // GH-861
|
||||
void returnsRelativeFile() {
|
||||
|
||||
assertThat(new ModifiedFile("foo/bar.txt").asRelativeTo("foo"))
|
||||
.isEqualTo(new ModifiedFile("bar.txt"));
|
||||
}
|
||||
|
||||
@Test // GH-861
|
||||
void returnsFileAsIsForEmptyReference() {
|
||||
|
||||
assertThat(new ModifiedFile("foo/bar.txt").asRelativeTo(""))
|
||||
.isEqualTo(new ModifiedFile("foo/bar.txt"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.modulith.junit.diff;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link WorkingDirectoryChangesDetector}.
|
||||
*
|
||||
* @author Oliver Drotbohm
|
||||
* @since 1.3
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class WorkingDirectoryChangesDetectorUnitTests {
|
||||
|
||||
@Mock FileModificationDetector delegate;
|
||||
|
||||
@Test // GH-861
|
||||
void filtersFilesContainedInReferenceFolder() {
|
||||
|
||||
when(delegate.getModifiedFiles())
|
||||
.thenReturn(Stream.of("rootPom.xml", "nested/nestedPom.xml").map(ModifiedFile::new));
|
||||
|
||||
var detector = new WorkingDirectoryChangesDetector(delegate, "nested");
|
||||
|
||||
assertThat(detector.getModifiedFiles())
|
||||
.extracting(ModifiedFile::path)
|
||||
.containsExactly("nestedPom.xml");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user