diff --git a/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionPropertiesSource.java b/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionPropertiesSource.java new file mode 100644 index 000000000..5e8906b58 --- /dev/null +++ b/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionPropertiesSource.java @@ -0,0 +1,34 @@ +package org.hibernate.reactive.env; + +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.provider.ValueSource; +import org.gradle.api.provider.ValueSourceParameters; + +import java.io.FileInputStream; +import java.util.Properties; + +/** + * Reads gradle/version.properties and returns the "projectVersion" property. + * Compatible with Configuration Cache (Gradle declares the file as input). + */ +public abstract class VersionPropertiesSource implements ValueSource { + public interface Params extends ValueSourceParameters { + RegularFileProperty getFile(); + } + + @Override + public String obtain() { + final var file = getParameters().getFile().getAsFile().get(); + if ( !file.exists() ) { + throw new RuntimeException( "Version file " + file.getAbsolutePath() + " does not exists" ); + } + final var props = new Properties(); + try (final var in = new FileInputStream( file )) { + props.load( in ); + } + catch (Exception e) { + throw new RuntimeException( "Unable to load properties from file - " + file.getAbsolutePath(), e ); + } + return props.getProperty( "projectVersion" ); + } +} diff --git a/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionsPlugin.java b/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionsPlugin.java index 883317d4a..f4552dc37 100644 --- a/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionsPlugin.java +++ b/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionsPlugin.java @@ -1,14 +1,15 @@ package org.hibernate.reactive.env; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; -import java.util.function.Consumer; +import java.util.Optional; import org.gradle.api.Plugin; import org.gradle.api.Project; +import org.gradle.api.artifacts.VersionCatalog; +import org.gradle.api.artifacts.VersionCatalogsExtension; +import org.gradle.api.artifacts.VersionConstraint; +import org.gradle.api.logging.Logger; +import org.gradle.api.provider.Provider; /** * Build plugin which applies some DSL extensions to the Project. Currently, these @@ -28,47 +29,71 @@ public class VersionsPlugin implements Plugin { public static final String SKIP_ORM_VERSION_PARSING = "skipOrmVersionParsing"; public static final String RELATIVE_FILE = "gradle/version.properties"; - public static final String RELATIVE_CATALOG = "gradle/libs.versions.toml"; @Override public void apply(Project project) { + final Logger log = project.getLogger(); + + // Expose the version file as an extension final File versionFile = project.getRootProject().file( RELATIVE_FILE ); project.getExtensions().add( VERSION_FILE, versionFile ); + // 1) release/development via -P if they come final ProjectVersion releaseVersion = determineReleaseVersion( project ); final ProjectVersion developmentVersion = determineDevelopmentVersion( project ); - final ProjectVersion projectVersion = determineProjectVersion( project, releaseVersion, versionFile ); - project.getLogger().lifecycle( "Project version: {} ({})", projectVersion.getFullName(), projectVersion.getFamily() ); + // 2) read projectVersion from version.properties using ValueSource (cacheable) + final var projectVersionString = project.getProviders().of( + VersionPropertiesSource.class, spec -> { + final var rf = project.getLayout() + .getProjectDirectory() + .file( RELATIVE_FILE ); + spec.getParameters().getFile().set( rf ); + } + ); + + final ProjectVersion projectVersion = determineProjectVersion( + project, releaseVersion, projectVersionString + ); + + log.lifecycle( "Project version: {} ({})", projectVersion.getFullName(), projectVersion.getFamily() ); project.getExtensions().add( PROJECT_VERSION, projectVersion ); if ( releaseVersion != null ) { - project.getLogger().lifecycle( "Release version: {} ({})", releaseVersion.getFullName(), releaseVersion.getFamily() ); + log.lifecycle( "Release version: {} ({})", releaseVersion.getFullName(), releaseVersion.getFamily() ); project.getExtensions().add( RELEASE_VERSION, releaseVersion ); } else { - project.getLogger().lifecycle( "Release version: n/a" ); + log.lifecycle( "Release version: n/a" ); } if ( developmentVersion != null ) { - project.getLogger().lifecycle( "Development version: {} ({})", developmentVersion.getFullName(), developmentVersion.getFamily() ); + log.lifecycle( + "Development version: {} ({})", + developmentVersion.getFullName(), + developmentVersion.getFamily() + ); project.getExtensions().add( DEVELOPMENT_VERSION, developmentVersion ); } else { - project.getLogger().lifecycle( "Development version: n/a" ); + log.lifecycle( "Development version: n/a" ); } - final VersionsTomlParser tomlParser = new VersionsTomlParser( project.getRootProject().file( RELATIVE_CATALOG ) ); - final String ormVersionString = determineOrmVersion( project, tomlParser ); + // 3) Version Catalog ("libs") See local-build-plugins/settings.gradle + final VersionCatalogsExtension catalogs = project.getExtensions().getByType( VersionCatalogsExtension.class ); + final VersionCatalog libs = catalogs.named( "libs" ); + + final String ormVersionString = determineOrmVersion( project, libs ); final Object ormVersion = resolveOrmVersion( ormVersionString, project ); - project.getLogger().lifecycle( "ORM version: {}", ormVersion ); + log.lifecycle( "ORM version: {}", ormVersion ); project.getExtensions().add( ORM_VERSION, ormVersion ); - final Object ormPluginVersion = determineOrmPluginVersion( ormVersion, project, tomlParser ); - project.getLogger().lifecycle( "ORM Gradle plugin version: {}", ormPluginVersion ); + final Object ormPluginVersion = determineOrmPluginVersion( ormVersion, project, libs ); + log.lifecycle( "ORM Gradle plugin version: {}", ormPluginVersion ); project.getExtensions().add( ORM_PLUGIN_VERSION, ormPluginVersion ); } + // --- Release / Development (with -P) -------------------------------------- private ProjectVersion determineReleaseVersion(Project project) { if ( project.hasProperty( RELEASE_VERSION ) ) { final Object version = project.property( RELEASE_VERSION ); @@ -89,74 +114,66 @@ private ProjectVersion determineDevelopmentVersion(Project project) { return null; } - public static ProjectVersion determineProjectVersion(Project project, ProjectVersion releaseVersion, File versionFile) { + // --- Project version (ValueSource for configuration cache) --------------- + + public static ProjectVersion determineProjectVersion( + Project project, + ProjectVersion releaseVersion, + Provider projectVersionString + ) { if ( releaseVersion != null ) { return releaseVersion; } - - final String fullName = readVersionProperties( versionFile ); - return new ProjectVersion( fullName ); - } - - private static String readVersionProperties(File file) { - if ( !file.exists() ) { - throw new RuntimeException( "Version file " + file.getAbsolutePath() + " does not exists" ); + // if don't have an explicit release, use value of file (with ValueSource) + final String fullName = projectVersionString.get(); + if ( fullName.isEmpty() ) { + final var file = project.getRootProject().file( RELATIVE_FILE ); + throw new RuntimeException( "Property 'projectVersion' is missing in " + file.getAbsolutePath() ); } - - final Properties versionProperties = new Properties(); - withInputStream( file, (stream) -> { - try { - versionProperties.load( stream ); - } - catch (IOException e) { - throw new RuntimeException( "Unable to load properties from file - " + file.getAbsolutePath(), e ); - } - } ); - - return versionProperties.getProperty( "projectVersion" ); + return new ProjectVersion( fullName ); } - private static void withInputStream(File file, Consumer action) { - try ( final FileInputStream stream = new FileInputStream( file ) ) { - action.accept( stream ); - } - catch (IOException e) { - throw new RuntimeException( "Error reading file stream = " + file.getAbsolutePath(), e ); - } - } + // --- ORM version from -P or catalogs ------------------------------------ - private String determineOrmVersion(Project project, VersionsTomlParser parser) { + private String determineOrmVersion(Project project, VersionCatalog libs) { // Check if it has been set in the project + // -PhibernateOrmVersion have priority if ( project.hasProperty( ORM_VERSION ) ) { return (String) project.property( ORM_VERSION ); } - - // Check in the catalog - final String version = parser.read( ORM_VERSION ); - if ( version != null ) { - return version; + // Find in Version Catalog + final Optional vc = libs.findVersion( ORM_VERSION ); + if ( vc.isPresent() ) { + final String required = vc.get().getRequiredVersion(); + if ( !required.isEmpty() ) { + return required; + } } throw new IllegalStateException( "Hibernate ORM version not specified on project" ); } private Object resolveOrmVersion(String stringForm, Project project) { if ( project.hasProperty( SKIP_ORM_VERSION_PARSING ) - && Boolean.parseBoolean( (String) project.property( SKIP_ORM_VERSION_PARSING ) ) ) { + && Boolean.parseBoolean( (String) project.property( SKIP_ORM_VERSION_PARSING ) ) + ) { return stringForm; } return new ProjectVersion( stringForm ); } - private Object determineOrmPluginVersion(Object ormVersion, Project project, VersionsTomlParser parser) { + private Object determineOrmPluginVersion(Object ormVersion, Project project, VersionCatalog libs) { // Check if it has been set in the project + // -PhibernateOrmGradlePluginVersion have priority if ( project.hasProperty( ORM_PLUGIN_VERSION ) ) { return project.property( ORM_PLUGIN_VERSION ); } - - // Check in the catalog - final String version = parser.read( ORM_PLUGIN_VERSION ); - if ( version != null ) { - return version; + // Find in Version Catalog + final Optional vc = libs.findVersion( ORM_PLUGIN_VERSION ); + if ( vc.isPresent() ) { + final String required = vc.get().getRequiredVersion(); + if ( !required.isEmpty() ) { + return required; + } } throw new IllegalStateException( "Hibernate ORM Gradle plugin version not specified on project" ); diff --git a/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionsTomlParser.java b/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionsTomlParser.java deleted file mode 100644 index 8833de6a6..000000000 --- a/local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionsTomlParser.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.hibernate.reactive.env; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * Read the versions section of the library catalog - */ -public class VersionsTomlParser { - - private final Map data = new HashMap<>(); - - public VersionsTomlParser(File filePath) { - parse( filePath ); - } - - private void parse(File filePath) { - - try ( BufferedReader reader = new BufferedReader( new FileReader( filePath ) ) ) { - String line; - String currentSection = null; - while ( ( line = reader.readLine() ) != null ) { - line = line.trim(); - - // Skip comments and blank lines - if ( line.isEmpty() || line.startsWith( "#" ) ) { - continue; - } - - // Handle [section] - if ( line.startsWith( "[" ) && line.endsWith( "]" ) ) { - currentSection = line.substring( 1, line.length() - 1 ).trim(); - continue; - } - - if ( "versions".equalsIgnoreCase( currentSection ) ) { - // Handle key = value - int equalsIndex = line.indexOf( '=' ); - if ( equalsIndex == -1 ) { - continue; - } - - String key = line.substring( 0, equalsIndex ).trim(); - String value = line.substring( equalsIndex + 1 ).trim(); - - // Remove optional quotes around string values - if ( value.startsWith( "\"" ) && value.endsWith( "\"" ) ) { - value = value.substring( 1, value.length() - 1 ); - } - - data.put( key, value ); - } - } - } - catch (IOException e) { - throw new RuntimeException( e ); - } - } - - /** - * Read the value of the property in the versions section of a toml file - */ - public String read(String property) { - return data.get( property ); - } -}