diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..ab8769f --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @renelink \ No newline at end of file diff --git a/multi-module-plugin/src/main/java/com/link_intersystems/gradle/project/plugin/ProjectNamingStrategies.java b/multi-module-plugin/src/main/java/com/link_intersystems/gradle/project/plugin/ProjectNamingStrategies.java index 7b43397..6e0bf48 100644 --- a/multi-module-plugin/src/main/java/com/link_intersystems/gradle/project/plugin/ProjectNamingStrategies.java +++ b/multi-module-plugin/src/main/java/com/link_intersystems/gradle/project/plugin/ProjectNamingStrategies.java @@ -13,6 +13,11 @@ public enum ProjectNamingStrategies implements ProjectNamingStrategy { public String getProjectName(Path rootDirectory, Path rootRelativeProjectPath) { return ProjectNamingStrategies.convertPath(rootRelativeProjectPath, PROJECT_PATH_DELIM); } + + @Override + public String toString() { + return "HIERARCHICAL_ROOTLESS"; + } }, /** * The same as {@link #HIERARCHICAL_ROOTLESS}, but includes the rootDirectory. E.g. @@ -28,6 +33,11 @@ public String getProjectName(Path rootDirectory, Path rootRelativeProjectPath) { } return ProjectNamingStrategies.convertPath(rootedProjectPath, PROJECT_PATH_DELIM); } + + @Override + public String toString() { + return "HIERARCHICAL"; + } }, /** * Resolves to project names where the path hierarchy is converted to a '-' separated string. @@ -38,6 +48,11 @@ public String getProjectName(Path rootDirectory, Path rootRelativeProjectPath) { public String getProjectName(Path rootDirectory, Path rootRelativeProjectPath) { return ProjectNamingStrategies.convertPath(rootRelativeProjectPath, "-"); } + + @Override + public String toString() { + return "FLAT_ROOTLESS"; + } }, /** * The same as {@link #FLAT_ROOTLESS}, but includes the rootDirectory. E.g. @@ -53,6 +68,11 @@ public String getProjectName(Path rootDirectory, Path rootRelativeProjectPath) { } return ProjectNamingStrategies.convertPath(rootedProjectPath, "-"); } + + @Override + public String toString() { + return "FLAT"; + } }, /** * The simple {@link ProjectNamingStrategy} resolves project paths to their simple name, which is the @@ -64,6 +84,11 @@ public String getProjectName(Path rootDirectory, Path rootRelativeProjectPath) { public String getProjectName(Path rootDirectory, Path rootRelativeProjectPath) { return ProjectNamingStrategies.convertPath(rootRelativeProjectPath.getFileName(), "-"); } + + @Override + public String toString() { + return "SIMPLE"; + } }; public static final String PROJECT_PATH_DELIM = ":"; diff --git a/multi-module-plugin/src/main/java/com/link_intersystems/gradle/project/sub/AbstractIncludeProjectConfigurer.java b/multi-module-plugin/src/main/java/com/link_intersystems/gradle/project/sub/AbstractIncludeProjectConfigurer.java index 2411e1c..6821860 100644 --- a/multi-module-plugin/src/main/java/com/link_intersystems/gradle/project/sub/AbstractIncludeProjectConfigurer.java +++ b/multi-module-plugin/src/main/java/com/link_intersystems/gradle/project/sub/AbstractIncludeProjectConfigurer.java @@ -6,14 +6,22 @@ import org.gradle.api.initialization.Settings; import org.slf4j.Logger; +import java.io.BufferedReader; import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.Properties; -import static java.util.Objects.*; +import static java.util.Objects.requireNonNull; public abstract class AbstractIncludeProjectConfigurer implements IncludeProjectConfigurer { + public static final String MODULE_PROPERTIES = "module.properties"; protected final Settings settings; protected final ConfigValues configValues; protected final Logger logger; @@ -26,12 +34,12 @@ public AbstractIncludeProjectConfigurer(Settings settings, ConfigValues configVa @Override public void configure(IncludePath includePath) { - ProjectNamingStrategy projectNamingStrategy = configValues.getProjectNamingStrategy(); File includeFile = includePath.getPath(); Path includeFilePath = includeFile.toPath(); String includeProjectPath = pathToNormalizedString(includeFilePath); - String projectName = projectNamingStrategy.getProjectName(settings.getRootDir().toPath(), includeFilePath); + String projectName = resolveProjectName(includeFilePath, includeProjectPath); + ProjectDescriptor existingProject = settings.findProject(":" + projectName); if (existingProject != null) { Path existingProjectPath = settings.getRootDir().toPath().relativize(existingProject.getProjectDir().toPath()); @@ -44,6 +52,59 @@ public void configure(IncludePath includePath) { } } + private String resolveProjectName(Path includeFilePath, String includeProjectPath) { + ProjectNamingStrategy projectNamingStrategy = configValues.getProjectNamingStrategy(); + String projectName = projectNamingStrategy.getProjectName(settings.getRootDir().toPath(), includeFilePath); + + Properties properties = getProperties(includeFilePath); + + if (properties.containsKey("name")) { + String modulePropertiesProjectName = properties.getProperty("name"); + String msg = "Module '{}' name '{}', resolved by project naming strategy '{}', is overridden by module.properties name '{}'"; + logger.info(msg, includeProjectPath, projectName, projectNamingStrategy, modulePropertiesProjectName); + projectName = modulePropertiesProjectName; + } + + return projectName; + } + + private Properties getProperties(Path includeFilePath) { + Properties properties = new Properties(); + File rootDir = settings.getRootDir(); + Path rootPath = rootDir.toPath(); + Path absoluteIncludeFilePath = rootPath.resolve(includeFilePath); + Path modulePropertiesFilepath = absoluteIncludeFilePath.resolve(MODULE_PROPERTIES); + if (Files.exists(modulePropertiesFilepath)) { + logger.info("Reading {} file at '{}'", MODULE_PROPERTIES, modulePropertiesFilepath); + try (BufferedReader modulePropertiesReader = Files.newBufferedReader(modulePropertiesFilepath, StandardCharsets.UTF_8)) { + properties.load(modulePropertiesReader); + } catch (IOException e) { + logger.error("Unable to read {} file at '{}'", MODULE_PROPERTIES, modulePropertiesFilepath, e); + } + + logModulePropertiesRead(properties, modulePropertiesFilepath); + } else { + logger.debug("{} file at '{}' does not exist", MODULE_PROPERTIES, modulePropertiesFilepath); + } + return properties; + } + + private void logModulePropertiesRead(Properties properties, Path modulePropertiesFilepath) { + StringWriter stringWriter = new StringWriter(); + + try (stringWriter) { + properties.store(stringWriter, null); + } catch (IOException e) { + try (PrintWriter printWriter = new PrintWriter(stringWriter)) { + e.printStackTrace(printWriter); + } catch (Exception ex) { + logger.error("Unable to print stack trace of exception", ex); + } + } + + logger.info("Read {} file at '{}': {}", MODULE_PROPERTIES, modulePropertiesFilepath, "\n" + stringWriter); + } + protected abstract void doConfigure(Settings settings, String projectName, File includeFile); private String pathToNormalizedString(Path path) { diff --git a/multi-module-plugin/src/test/java/com/link_intersystems/gradle/project/plugin/HierarchicalProjectNamingTest.java b/multi-module-plugin/src/test/java/com/link_intersystems/gradle/project/plugin/HierarchicalProjectNamingTest.java index 48efcec..95f5ad3 100644 --- a/multi-module-plugin/src/test/java/com/link_intersystems/gradle/project/plugin/HierarchicalProjectNamingTest.java +++ b/multi-module-plugin/src/test/java/com/link_intersystems/gradle/project/plugin/HierarchicalProjectNamingTest.java @@ -1,5 +1,7 @@ package com.link_intersystems.gradle.project.plugin; +import com.link_intersystems.gradle.project.builder.FileBuilder; +import com.link_intersystems.gradle.project.builder.GradleSubprojectBuilder; import org.assertj.core.api.AbstractStringAssert; import org.assertj.core.api.Condition; import org.gradle.testkit.runner.BuildResult; @@ -23,6 +25,9 @@ void smokeTest() throws Exception { }); projectBuilder.createSubproject("moduleA/api"); projectBuilder.createSubproject("moduleA/impl"); + GradleSubprojectBuilder moduleBImpl = projectBuilder.createSubproject("moduleB/impl"); + FileBuilder modulePropertiesBuilder = moduleBImpl.file("module.properties"); + modulePropertiesBuilder.append(writer -> writer.println("name = moduleB-impl")); projectBuilder.createSubproject("moduleB/subB/api"); @@ -32,6 +37,7 @@ void smokeTest() throws Exception { outputAssert.contains("Including 'moduleA/api' as ':api'"); outputAssert.contains("Including 'moduleA/impl' as ':impl'"); + outputAssert.contains("Including 'moduleB/impl' as ':moduleB-impl'"); outputAssert.contains("Omitting 'moduleB/subB/api'"); } }