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..3f70a4858 --- /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 ); + return props.getProperty( "projectVersion" ); + } + catch (Exception e) { + throw new RuntimeException( "Unable to load properties from file - " + file.getAbsolutePath(), e ); + } + } +} 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..9399462a1 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,50 +29,63 @@ 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 (used during releases) final File versionFile = project.getRootProject().file( RELATIVE_FILE ); project.getExtensions().add( VERSION_FILE, versionFile ); - 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() ); - project.getExtensions().add( PROJECT_VERSION, projectVersion ); - + // 1) Read release/development via -P if they come + final ProjectVersion releaseVersion = findProjectVersion( RELEASE_VERSION, project ); 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" ); } + final ProjectVersion developmentVersion = findProjectVersion( DEVELOPMENT_VERSION, project ); 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 ); + // 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 ); + + // 3) Version Catalog ("libs"): see gradle/libs.versions.toml + final VersionCatalogsExtension catalogs = project.getExtensions().getByType( VersionCatalogsExtension.class ); + final VersionCatalog libs = catalogs.named( "libs" ); + + final String ormVersionString = determineVersion( ORM_VERSION, 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 String ormPluginVersion = determineVersion( ORM_PLUGIN_VERSION, project, libs ); + log.lifecycle( "ORM Gradle plugin version: {}", ormPluginVersion ); project.getExtensions().add( ORM_PLUGIN_VERSION, ormPluginVersion ); } - private ProjectVersion determineReleaseVersion(Project project) { - if ( project.hasProperty( RELEASE_VERSION ) ) { - final Object version = project.property( RELEASE_VERSION ); + private ProjectVersion findProjectVersion(String property, Project project) { + if ( project.hasProperty( property ) ) { + final Object version = project.property( property ); if ( version != null ) { return new ProjectVersion( (String) version ); } @@ -79,64 +93,36 @@ private ProjectVersion determineReleaseVersion(Project project) { return null; } - private ProjectVersion determineDevelopmentVersion(Project project) { - if ( project.hasProperty( DEVELOPMENT_VERSION ) ) { - final Object version = project.property( DEVELOPMENT_VERSION ); - if ( version != null ) { - return new ProjectVersion( (String) version ); - } - } - 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 ); + // if we don't have an explicit release, use value from 'version/gradle.properties' (with ValueSource) + final String fullName = projectVersionString.get(); + if ( fullName.isEmpty() ) { + final var file = project.getRootProject().file( RELATIVE_FILE ); + throw new RuntimeException( "Property 'projectVersion' not found in " + file.getAbsolutePath() ); + } return new ProjectVersion( fullName ); } - private static String readVersionProperties(File file) { - if ( !file.exists() ) { - throw new RuntimeException( "Version file " + file.getAbsolutePath() + " does not exists" ); + private String determineVersion(String property, Project project, VersionCatalog libs) { + // Check if the property is defined in the project + if ( project.hasProperty( property ) ) { + return (String) project.property( property ); } - 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 ); + // Otherwise, look for it in the catalog + final Optional vc = libs.findVersion( property ); + if ( vc.isPresent() ) { + final String required = vc.get().getRequiredVersion(); + if ( !required.isEmpty() ) { + return required; } - } ); - - return versionProperties.getProperty( "projectVersion" ); - } - - 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 ); - } - } - - private String determineOrmVersion(Project project, VersionsTomlParser parser) { - // Check if it has been set in the project - 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; - } - throw new IllegalStateException( "Hibernate ORM version not specified on project" ); + throw new IllegalStateException( "Property '" + property + "' not found in version catalog" ); } private Object resolveOrmVersion(String stringForm, Project project) { @@ -146,19 +132,4 @@ private Object resolveOrmVersion(String stringForm, Project project) { } return new ProjectVersion( stringForm ); } - - private Object determineOrmPluginVersion(Object ormVersion, Project project, VersionsTomlParser parser) { - // Check if it has been set in the project - 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; - } - - 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 ); - } -}