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

pl.project13.maven.git.GitDataProvider Maven / Gradle / Ivy

/*
 * This file is part of git-commit-id-plugin by Konrad 'ktoso' Malawski 
 *
 * git-commit-id-plugin 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 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.  If not, see .
 */

package pl.project13.maven.git;

import org.apache.http.client.utils.URIBuilder;
import org.jetbrains.annotations.NotNull;
import pl.project13.maven.git.log.LoggerBridge;
import pl.project13.maven.git.util.PropertyManager;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;

import static com.google.common.base.Strings.isNullOrEmpty;

public abstract class GitDataProvider {

  @NotNull
  protected final LoggerBridge log;

  protected String prefixDot;

  protected int abbrevLength;

  protected String dateFormat;

  protected String dateFormatTimeZone;

  protected GitDescribeConfig gitDescribe = new GitDescribeConfig();

  protected CommitIdGenerationMode commitIdGenerationMode;

  public GitDataProvider(@NotNull LoggerBridge log) {
    this.log = log;
  }

  public GitDataProvider setGitDescribe(GitDescribeConfig gitDescribe) {
    this.gitDescribe = gitDescribe;
    return this;
  }

  public GitDataProvider setPrefixDot(String prefixDot) {
    this.prefixDot = prefixDot;
    return this;
  }

  public GitDataProvider setAbbrevLength(int abbrevLength) {
    this.abbrevLength = abbrevLength;
    return this;
  }

  public GitDataProvider setDateFormat(String dateFormat) {
    this.dateFormat = dateFormat;
    return this;
  }

  public GitDataProvider setCommitIdGenerationMode(CommitIdGenerationMode commitIdGenerationMode) {
    this.commitIdGenerationMode = commitIdGenerationMode;
    return this;
  }

  public GitDataProvider setDateFormatTimeZone(String dateFormatTimeZone){
    this.dateFormatTimeZone = dateFormatTimeZone;
    return this;
  }

  protected abstract void init() throws GitCommitIdExecutionException;
  protected abstract String getBuildAuthorName() throws GitCommitIdExecutionException;
  protected abstract String getBuildAuthorEmail() throws GitCommitIdExecutionException;
  protected abstract void prepareGitToExtractMoreDetailedRepoInformation() throws GitCommitIdExecutionException;
  protected abstract String getBranchName() throws GitCommitIdExecutionException;
  protected abstract String getGitDescribe() throws GitCommitIdExecutionException;
  protected abstract String getCommitId() throws GitCommitIdExecutionException;
  protected abstract String getAbbrevCommitId() throws GitCommitIdExecutionException;
  protected abstract boolean isDirty() throws GitCommitIdExecutionException;
  protected abstract String getCommitAuthorName() throws GitCommitIdExecutionException;
  protected abstract String getCommitAuthorEmail() throws GitCommitIdExecutionException;
  protected abstract String getCommitMessageFull() throws GitCommitIdExecutionException;
  protected abstract String getCommitMessageShort() throws GitCommitIdExecutionException;
  protected abstract String getCommitTime() throws GitCommitIdExecutionException;
  protected abstract String getRemoteOriginUrl() throws GitCommitIdExecutionException;
  protected abstract String getTags() throws GitCommitIdExecutionException;
  protected abstract String getClosestTagName() throws GitCommitIdExecutionException;
  protected abstract String getClosestTagCommitCount() throws GitCommitIdExecutionException;
  protected abstract void finalCleanUp() throws GitCommitIdExecutionException;

  public void loadGitData(@NotNull Properties properties) throws GitCommitIdExecutionException {
    init();
    // git.user.name
    put(properties, GitCommitIdMojo.BUILD_AUTHOR_NAME, getBuildAuthorName());
    // git.user.email
    put(properties, GitCommitIdMojo.BUILD_AUTHOR_EMAIL, getBuildAuthorEmail());

    try {
      prepareGitToExtractMoreDetailedRepoInformation();
      validateAbbrevLength(abbrevLength);

      // git.branch
      put(properties, GitCommitIdMojo.BRANCH, determineBranchName(System.getenv()));
      // git.commit.id.describe
      maybePutGitDescribe(properties);
      // git.commit.id
      switch (commitIdGenerationMode) {
        case FULL: {
          put(properties, GitCommitIdMojo.COMMIT_ID_FULL, getCommitId());
          break;
        }
        case FLAT: {
          put(properties, GitCommitIdMojo.COMMIT_ID_FLAT, getCommitId());
          break;
        }
        default: {
          throw new GitCommitIdExecutionException("Unsupported commitIdGenerationMode: " + commitIdGenerationMode);
        }
      }
      // git.commit.id.abbrev
      put(properties, GitCommitIdMojo.COMMIT_ID_ABBREV, getAbbrevCommitId());
      // git.dirty
      put(properties, GitCommitIdMojo.DIRTY, Boolean.toString(isDirty()));
      // git.commit.author.name
      put(properties, GitCommitIdMojo.COMMIT_AUTHOR_NAME, getCommitAuthorName());
      // git.commit.author.email
      put(properties, GitCommitIdMojo.COMMIT_AUTHOR_EMAIL, getCommitAuthorEmail());
      // git.commit.message.full
      put(properties, GitCommitIdMojo.COMMIT_MESSAGE_FULL, getCommitMessageFull());
      // git.commit.message.short
      put(properties, GitCommitIdMojo.COMMIT_MESSAGE_SHORT, getCommitMessageShort());
      // git.commit.time
      put(properties, GitCommitIdMojo.COMMIT_TIME, getCommitTime());
      // git remote.origin.url
      put(properties, GitCommitIdMojo.REMOTE_ORIGIN_URL, getRemoteOriginUrl());

      //
      put(properties, GitCommitIdMojo.TAGS, getTags());
      
      put(properties,GitCommitIdMojo.CLOSEST_TAG_NAME, getClosestTagName());
      put(properties,GitCommitIdMojo.CLOSEST_TAG_COMMIT_COUNT, getClosestTagCommitCount());
    } finally {
      finalCleanUp();
    }
  }

  private void maybePutGitDescribe(@NotNull Properties properties) throws GitCommitIdExecutionException{
    boolean isGitDescribeOptOutByDefault = (gitDescribe == null);
    boolean isGitDescribeOptOutByConfiguration = (gitDescribe != null && !gitDescribe.isSkip());

    if (isGitDescribeOptOutByDefault || isGitDescribeOptOutByConfiguration) {
      put(properties, GitCommitIdMojo.COMMIT_DESCRIBE, getGitDescribe());
    }
  }

  void validateAbbrevLength(int abbrevLength) throws GitCommitIdExecutionException {
    if (abbrevLength < 2 || abbrevLength > 40) {
      throw new GitCommitIdExecutionException(String.format("Abbreviated commit id length must be between 2 and 40, inclusive! Was [%s]. ", abbrevLength) +
                                           "Please fix your configuration (the  element).");
    }
  }

  /**
   * If running within Jenkins/Hudson, honor the branch name passed via GIT_BRANCH env var.
   * This is necessary because Jenkins/Hudson always invoke build in a detached head state.
   *
   * @param env environment settings
   * @return results of getBranchName() or, if in Jenkins/Hudson, value of GIT_BRANCH
   */
  protected String determineBranchName(Map env) throws GitCommitIdExecutionException {
    if (runningOnBuildServer(env)) {
      return determineBranchNameOnBuildServer(env);
    } else {
      return getBranchName();
    }
  }

  /**
   * Detects if we're running on Jenkins or Hudson, based on expected env variables.
   *
   * TODO: How can we detect Bamboo, TeamCity etc? Pull requests welcome.
   *
   * @return true if running
   * @see JenkinsSetEnvironmentVariables
   * @param env environment settings
   */
  private boolean runningOnBuildServer(Map env) {
    return env.containsKey("HUDSON_URL") || env.containsKey("JENKINS_URL");
  }

  /**
   * Is "Jenkins aware", and prefers {@code GIT_BRANCH} to getting the branch via git if that environment variable is set.
   * The {@code GIT_BRANCH} variable is set by Jenkins/Hudson when put in detached HEAD state, but it still knows which branch was cloned.
   */
  protected String determineBranchNameOnBuildServer(Map env) throws GitCommitIdExecutionException {
    String environmentBasedBranch = env.get("GIT_BRANCH");
    if (isNullOrEmpty(environmentBasedBranch)) {
      log.info("Detected that running on CI environment, but using repository branch, no GIT_BRANCH detected.");
      return getBranchName();
    } else {
      log.info("Using environment variable based branch name. GIT_BRANCH = {}", environmentBasedBranch);
      return environmentBasedBranch;
    }
  }

  protected SimpleDateFormat getSimpleDateFormatWithTimeZone(){
    SimpleDateFormat smf = new SimpleDateFormat(dateFormat);
    if (dateFormatTimeZone != null){
      smf.setTimeZone(TimeZone.getTimeZone(dateFormatTimeZone));
    }
    return smf;
  }

  protected void put(@NotNull Properties properties, String key, String value) {
    String keyWithPrefix = prefixDot + key;
    log.info("{} {}", keyWithPrefix, value);
    PropertyManager.putWithoutPrefix(properties, keyWithPrefix, value);
  }

  /**
   * Regex to check for SCP-style SSH+GIT connection strings such as '[email protected]'
   */
  static final Pattern GIT_SCP_FORMAT = Pattern.compile("^([a-zA-Z0-9_.+-])+@(.*)");
  /**
   * If the git remote value is a URI and contains a user info component, strip the password from it if it exists.
   *
   * @param gitRemoteString The value of the git remote
   * @return
   * @throws GitCommitIdExecutionException
     */
  protected static String stripCredentialsFromOriginUrl(String gitRemoteString) throws GitCommitIdExecutionException {

    // The URL might be null if the repo hasn't set a remote
    if (gitRemoteString == null) {
      return gitRemoteString;
    }

    // Remotes using ssh connection strings in the 'git@github' format aren't
    // proper URIs and won't parse . Plus since you should be using SSH keys,
    // credentials like are not in the URL.
    if (GIT_SCP_FORMAT.matcher(gitRemoteString).matches()) {
      return gitRemoteString;
    }
    // At this point, we should have a properly formatted URL
    try {
      URI original = new URI(gitRemoteString);
      String userInfoString = original.getUserInfo();
      if (null == userInfoString) {
        return gitRemoteString;
      }
      URIBuilder b = new URIBuilder(gitRemoteString);
      String[] userInfo = userInfoString.split(":");
      // Build a new URL from the original URL, but nulling out the password
      // component of the userinfo. We keep the username so that ssh uris such
      // ssh://[email protected] will retain 'git@'.
      b.setUserInfo(userInfo[0]);
      return b.build().toString();

    } catch (URISyntaxException e) {
      throw new GitCommitIdExecutionException(e);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy