From 0ce1b0a3ea39caf7cf2d2fabc3f1ee65637ed977 Mon Sep 17 00:00:00 2001 From: Rey <89825425+kingg22@users.noreply.github.com> Date: Sat, 30 Aug 2025 12:45:14 -0500 Subject: [PATCH] build: perf parse of versions local plugin With this change remove manual parser of libs.versions.toml file and use java Properties API. Additional retrieve data of the file with PropertiesSource of gradle to be ready with configuration cache. --- .../reactive/env/VersionPropertiesSource.java | 34 +++++ .../reactive/env/VersionsPlugin.java | 135 ++++++++++-------- .../reactive/env/VersionsTomlParser.java | 70 --------- 3 files changed, 110 insertions(+), 129 deletions(-) create mode 100644 local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionPropertiesSource.java delete mode 100644 local-build-plugins/src/main/java/org/hibernate/reactive/env/VersionsTomlParser.java 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 ); - } -}