All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.project13.core.GitCommitIdPlugin Maven / Gradle / Ivy

The newest version!
/*
 * This file is part of git-commit-id-plugin-core by Konrad 'ktoso' Malawski 
 *
 * git-commit-id-plugin-core is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * git-commit-id-plugin-core is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with git-commit-id-plugin-core.  If not, see .
 */

package pl.project13.core;

import pl.project13.core.cibuild.BuildServerDataProvider;
import pl.project13.core.git.GitDescribeConfig;
import pl.project13.core.log.LogInterface;
import pl.project13.core.util.BuildFileChangeListener;
import pl.project13.core.util.GitDirLocator;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Supplier;
import java.util.regex.Pattern;

public class GitCommitIdPlugin {
  public interface Callback {

    /**
     * The system environment variables.
     * Implementations usually do not need to set or overwrite this,
     * this is mainly meant for testing purposes...
     * @return unmodifiable string map view of the current system environment {@link System#getenv}.
     */
    default Map getSystemEnv() {
      return System.getenv();
    }

    /**
     * @return Supplier that provides the version of the project that is currently evaluated.
     *         Used to determine {@link GitCommitPropertyConstant#BUILD_VERSION}.
     */
    Supplier supplyProjectVersion();

    /**
     * @return Logging Interface
     */
    @Nonnull
    LogInterface getLogInterface();

    /**
     * @return The date format to be used for any dates exported by this plugin.
     *         It should be a valid {@link SimpleDateFormat} string.
     */
    @Nonnull
    String getDateFormat();

    /**
     * 

The timezone used in the date format of dates exported by this plugin. * It should be a valid Timezone string such as {@code 'America/Los_Angeles'}, {@code 'GMT+10'} or {@code 'PST'}.

* *

Try to avoid three-letter time zone IDs because the same abbreviation is often used for multiple time zones. * Please review https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html for more information on this issue.

* * @return The timezone used in the date format of dates exported by this plugin. */ @Nonnull String getDateFormatTimeZone(); /** * The prefix to expose the properties on. For example {@code 'git'} would allow you to access {@code ${git.branch}}. * * @return The prefix to expose the properties on. */ @Nonnull String getPrefixDot(); /** *

List of properties to exclude from the resulting file. * May be useful when you want to hide {@code 'git.remote.origin.url'} (maybe because it contains your repo password?) * or the email of the committer.

* *

Supports wildcards: you can write {@code 'git.commit.user.*'} to exclude both the {@code 'name'} * as well as {@code 'email'} properties from being emitted into the resulting files.

* *

Note: The strings here are Java regular expressions: {@code '.*'} is a wildcard, not plain {@code '*'}.

* * @return List of properties to exclude */ List getExcludeProperties(); /** *

List of properties to include into the resulting file. Only properties specified here will be included. * This list will be overruled by the {@code 'excludeProperties'}.

* *

Supports wildcards: you can write {@code 'git.commit.user.*'} to include both the {@code 'name'} * as well as {@code 'email'} properties into the resulting files.

* *

Note: The strings here are Java regular expressions: {@code '.*'} is a wildcard, not plain {@code '*'}.

* * @return List of properties to include */ List getIncludeOnlyProperties(); /** * Timestamp for reproducible output archive entries * (https://maven.apache.org/guides/mini/guide-reproducible-builds.html). * The value from ${project.build.outputTimestamp} is either formatted as ISO 8601 * yyyy-MM-dd'T'HH:mm:ssXXX or as an int representing seconds since the epoch (like * SOURCE_DATE_EPOCH. * * @throws GitCommitIdExecutionException In case the user provided time stamp is invalid a GitCommitIdExecutionException is thrown * @return Timestamp for reproducible output archive entries. */ @Nullable Date getReproducibleBuildOutputTimestamp() throws GitCommitIdExecutionException; /** * Set this to {@code 'true'} to use native Git executable to fetch information about the repository. * It is in most cases faster but requires a git executable to be installed in system. * By default the plugin will use jGit implementation as a source of information about the repository. * * @return Controls if this plugin should use the native Git executable. */ boolean useNativeGit(); /** * Allow to specify a timeout (in milliseconds) for fetching information with the native Git executable. * Note that {@code useNativeGit} needs to be set to {@code 'true'} to use native Git executable. * * @return A timeout (in milliseconds) for fetching information with the native Git executable. */ long getNativeGitTimeoutInMs(); /** *

Minimum length of {@code 'git.commit.id.abbrev'} property. * Value must be from 2 to 40 (inclusive), other values will result in an exception.

* *

An abbreviated commit is a shorter version of commit id. However, it is guaranteed to be unique. * To keep this contract, the plugin may decide to print an abbreviated version * that is longer than the value specified here.

* *

Example: You have a very big repository, yet you set this value to 2. It's very probable that you'll end up * getting a 4 or 7 char long abbrev version of the commit id. If your repository, on the other hand, * has just 4 commits, you'll probably get a 2 char long abbreviation.

* * @return Minimum length of {@code 'git.commit.id.abbrev'} property. */ int getAbbrevLength(); /** * Configuration for the {@code 'git-describe'} command. * You can modify the dirty marker, abbrev length and other options here. * * @return Configuration for the {@code 'git-describe'} command. */ GitDescribeConfig getGitDescribe(); /** *

The mode of {@code 'git.commit.id'} property generation.

* * {@code 'git.commit.id'} property name is incompatible with json export * (see issue #122). * This property allows one either to preserve backward compatibility or to enable fully valid json export: * *
    *
  1. {@code 'flat'} (default) generates the property {@code 'git.commit.id'}, preserving backwards compatibility.
  2. *
  3. {@code 'full'} generates the property {@code 'git.commit.id.full'}, enabling fully valid json object export.
  4. *
* *

Note: Depending on your plugin configuration you obviously can choose the `prefix` of your properties * by setting it accordingly in the plugin's configuration. As a result this is therefore only an illustration * what the switch means when the 'prefix' is set to it's default value.

*

Note: If you set the value to something that's not equal to {@code 'flat'} or {@code 'full'} (ignoring the case) * the plugin will output a warning and will fallback to the default {@code 'flat'} mode.

* * @return The mode of {@code 'git.commit.id'} property generation. */ CommitIdGenerationMode getCommitIdGenerationMode(); /** * Use branch name from build environment. Set to {@code 'false'} to use JGit/GIT to get current branch name. * Useful when using the JGitflow maven plugin. * Note: If not using "Check out to specific local branch' and setting this to false may result in getting * detached head state and therefore a commit id as branch name. * * @return Controls if the branch name from build environment should be used. */ boolean getUseBranchNameFromBuildEnvironment(); /** * Controls whether the git plugin tries to access remote repos to fetch latest information * or only use local information. * * :warning: Before version 5.X.X the default was set to {@code false} causing the plugin to operate * in online-mode by default. * * @return Controls whether the git plugin tries to access remote repos to fetch latest information. */ boolean isOffline(); /** * Allow to tell the plugin what commit should be used as reference to generate the properties from. * By default this property is simply set to

HEAD

which should reference to the latest commit in your repository. * * In general this property can be set to something generic like

HEAD^1

or point to a branch or tag-name. * To support any kind or use-case this configuration can also be set to an entire commit-hash or it's abbreviated version. * * A use-case for this feature can be found in https://github.com/git-commit-id/git-commit-id-maven-plugin/issues/338. * * Please note that for security purposes not all references might be allowed as configuration. * If you have a specific use-case that is currently not white listed feel free to file an issue. * * @return Tell the plugin what commit should be used as reference to generate the properties from. */ String getEvaluateOnCommit(); /** * @return The root directory of the repository we want to check. */ File getDotGitDirectory(); /** * Set this to {@code 'true'} to generate a {@code 'git.properties'} file. * By default plugin only adds properties to maven project properties. * * @return Control if the plugin should generate a {@code 'git.properties'} file. */ boolean shouldGenerateGitPropertiesFile(); /** * Callback when the plugin wants to publish a set of properties. * @param properties The properties the plugin want's to publish to the user. */ void performPublishToAllSystemEnvironments(Properties properties); /** * Callback when the plugin wants to perform the properties replacement. * @param properties The current set of properties. */ void performPropertiesReplacement(Properties properties); /** * @return The output format of the generated properties file. */ CommitIdPropertiesOutputFormat getPropertiesOutputFormat(); /** * @return The BuildFileChangeListener that will be called when an output file of the plugin has changed */ BuildFileChangeListener getBuildFileChangeListener(); /** * @return The project name */ String getProjectName(); /** * @return The project base dir */ File getProjectBaseDir(); /** * @return The optional properties file where properties should be dumped into */ File getGenerateGitPropertiesFile(); /** * @return The Charset in which format the properties should be dumped (e.g. 'UTF-8') */ Charset getPropertiesSourceCharset(); boolean shouldPropertiesEscapeUnicode(); boolean shouldFailOnNoGitDirectory(); } protected static final Pattern allowedCharactersForEvaluateOnCommit = Pattern.compile("[a-zA-Z0-9\\_\\-\\^\\/\\.]+"); public static void runPlugin(@Nonnull Callback cb, @Nullable Properties contextProperties) throws GitCommitIdExecutionException { PropertiesFilterer propertiesFilterer = new PropertiesFilterer(cb.getLogInterface()); // The properties we store our data in and then expose them. Properties properties = contextProperties == null ? new Properties() : contextProperties; loadGitData(cb, properties); loadBuildData(cb, properties); // first round of publication and filtering // (we need to make variables available for the ParameterExpressionEvaluator) propertiesFilterer.filter(properties, cb.getIncludeOnlyProperties(), cb.getPrefixDot()); propertiesFilterer.filterNot(properties, cb.getExcludeProperties(), cb.getPrefixDot()); cb.performPublishToAllSystemEnvironments(properties); cb.performPropertiesReplacement(properties); if (cb.shouldGenerateGitPropertiesFile()) { new PropertiesFileGenerator( cb.getLogInterface(), cb.getBuildFileChangeListener(), cb.getPropertiesOutputFormat(), cb.getPrefixDot(), cb.getProjectName() ).maybeGeneratePropertiesFile( properties, cb.getProjectBaseDir(), cb.getGenerateGitPropertiesFile(), cb.getPropertiesSourceCharset(), cb.shouldPropertiesEscapeUnicode() ); } // publish properties again since we might have new properties gained by the replacement cb.performPublishToAllSystemEnvironments(properties); } protected static void loadBuildData(@Nonnull Callback cb, @Nonnull Properties properties) throws GitCommitIdExecutionException { Map> additionalProperties = Collections.singletonMap( GitCommitPropertyConstant.BUILD_VERSION, cb.supplyProjectVersion()); BuildServerDataProvider buildServerDataProvider = BuildServerDataProvider.getBuildServerProvider( cb.getSystemEnv(), cb.getLogInterface()); buildServerDataProvider .setDateFormat(cb.getDateFormat()) .setDateFormatTimeZone(cb.getDateFormatTimeZone()) .setAdditionalProperties(additionalProperties) .setPrefixDot(cb.getPrefixDot()) .setExcludeProperties(cb.getExcludeProperties()) .setIncludeOnlyProperties(cb.getIncludeOnlyProperties()); buildServerDataProvider.loadBuildData(properties, cb.getReproducibleBuildOutputTimestamp()); } protected static void loadGitData(@Nonnull Callback cb, @Nonnull Properties properties) throws GitCommitIdExecutionException { String evaluateOnCommit = cb.getEvaluateOnCommit(); if ((evaluateOnCommit == null) || !allowedCharactersForEvaluateOnCommit.matcher(evaluateOnCommit).matches()) { throw new GitCommitIdExecutionException("suspicious argument for evaluateOnCommit, aborting execution!"); } File dotGitDirectory = new GitDirLocator( cb.getProjectBaseDir(), cb.useNativeGit(), cb.shouldFailOnNoGitDirectory() ).lookupGitDirectory(cb.getDotGitDirectory()); if (dotGitDirectory != null) { cb.getLogInterface().info("dotGitDirectory '" + dotGitDirectory.getAbsolutePath() + "'"); } else { cb.getLogInterface().info("dotGitDirectory is null, aborting execution!"); return; } if (cb.useNativeGit()) { loadGitDataWithNativeGit(cb, dotGitDirectory, properties); } else { loadGitDataWithJGit(cb, dotGitDirectory, properties); } } private static void loadGitDataWithNativeGit( @Nonnull Callback cb, @Nonnull File dotGitDirectory, @Nonnull Properties properties) throws GitCommitIdExecutionException { GitDataProvider nativeGitProvider = NativeGitProvider .on(dotGitDirectory, cb.getNativeGitTimeoutInMs(), cb.getLogInterface()) .setPrefixDot(cb.getPrefixDot()) .setAbbrevLength(cb.getAbbrevLength()) .setDateFormat(cb.getDateFormat()) .setDateFormatTimeZone(cb.getDateFormatTimeZone()) .setGitDescribe(cb.getGitDescribe()) .setCommitIdGenerationMode(cb.getCommitIdGenerationMode()) .setUseBranchNameFromBuildEnvironment(cb.getUseBranchNameFromBuildEnvironment()) .setExcludeProperties(cb.getExcludeProperties()) .setIncludeOnlyProperties(cb.getIncludeOnlyProperties()) .setOffline(cb.isOffline()); nativeGitProvider.loadGitData(cb.getEvaluateOnCommit(), cb.getSystemEnv(), properties); } private static void loadGitDataWithJGit( @Nonnull Callback cb, @Nonnull File dotGitDirectory, @Nonnull Properties properties) throws GitCommitIdExecutionException { GitDataProvider jGitProvider = JGitProvider .on(dotGitDirectory, cb.getLogInterface()) .setPrefixDot(cb.getPrefixDot()) .setAbbrevLength(cb.getAbbrevLength()) .setDateFormat(cb.getDateFormat()) .setDateFormatTimeZone(cb.getDateFormatTimeZone()) .setGitDescribe(cb.getGitDescribe()) .setCommitIdGenerationMode(cb.getCommitIdGenerationMode()) .setUseBranchNameFromBuildEnvironment(cb.getUseBranchNameFromBuildEnvironment()) .setExcludeProperties(cb.getExcludeProperties()) .setIncludeOnlyProperties(cb.getIncludeOnlyProperties()) .setOffline(cb.isOffline()); jGitProvider.loadGitData(cb.getEvaluateOnCommit(), cb.getSystemEnv(), properties); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy