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

no.entitas.gradle.git.GitVersion.groovy Maven / Gradle / Ivy

/*
 * Copyright 2011- the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package no.entitas.gradle.git

import no.entitas.gradle.Version
import no.entitas.gradle.VersionNumber
import org.gradle.api.Project
import org.gradle.process.internal.ExecException

class GitVersion implements Version {
    Project project
    String versionNumber
    def releaseTagPattern = ~/^\S+-REL-\d+$/

    def GitVersion(project) {
        this.project = project

        project.gradle.taskGraph.whenReady { graph ->
            if (graph.hasTask(':releasePrepare')) {
                releasePreConditions()
                versionNumber = getNextTagName()
            } else if (isOnReleaseTag() && !hasLocalModifications()) {
                versionNumber = getCurrentVersion()
            } else {
                versionNumber = getCurrentBranchName() + '-SNAPSHOT'
            }
        }
    }

    // TODO Ensure that we are on a branch
    def releasePreConditions() {
        if (hasLocalModifications()) {
            throw new RuntimeException('Uncommited changes found in the source tree:\n' + getLocalModifications())
        }

        if (isOnReleaseTag()) {
            throw new RuntimeException('No changes since last tag.')
        }


        if (branchIsAheadOfRemote()) {
            throw new RuntimeException('Project contains unpushed commits');
        }
    }

    boolean branchIsAheadOfRemote() {
        gitExec(['status']).contains('Your branch is ahead of')
    }

    String toString() {
        versionNumber
    }

    def releasePrepare() {
        tag(versionNumber, "Release Tag: ${versionNumber}")
    }

    def releasePerform() {
        pushTags()
    }

    def getLocalModifications() {
        gitExec(['status', '--porcelain'])
    }

    def hasLocalModifications() {
        getLocalModifications() != null
    }

    def isOnReleaseTag() {
        try {
            releaseTagPattern.matcher(tagNameOnCurrentRevision()).matches()
        } catch (ExecException e) {
            false
        }
    }

    def getCurrentVersion() {
        try {
            new VersionNumber(tagNameOnCurrentRevision())
        } catch (ExecException e) {
            throw new RuntimeException("Not on a tag.")
        }
    }

    def tagNameOnCurrentRevision() {
        gitExec(['describe', '--exact-match', 'HEAD'], true)
    }

    def getCurrentBranchName() {
        gitExec(['name-rev', '--name-only', 'HEAD'], true)
    }

    def getNextTagName() {
        def currentBranch = getCurrentBranchName()
        def latestTagVersion = getLatestTag(currentBranch)

        if (latestTagVersion == null) {
            "$currentBranch-REL-1"
        } else {
            latestTagVersion.nextVersionTag()
        }
    }

    def getLatestTag(String currentBranch) {
        def tagSearchPattern = "${currentBranch}-REL-*"
        def tags = getTagNames(tagSearchPattern)

        if (tags != null) {
            def versionNumbers = tags.collect {new VersionNumber(it)}
            GroovyCollections.max(versionNumbers)
        }
    }

    def getTagNames(String tagSearchPattern) {
        def allReleaseTagNames = gitExec(['tag', '-l', tagSearchPattern])
        
        if (allReleaseTagNames) {
            allReleaseTagNames.split('\n')
        }
    }

    def tag(String tag, String message) {
        project.logger.info("tagging with $tag")
        gitExec(['tag', '-a', tag, '-m', message])
    }

    def pushTags() {
        project.logger.info("pushing tags")
        gitExec(['push', '--tags'])
    }

    def gitExec(List gitArgs, boolean removeNewLines = false) {
        def stdout = new ByteArrayOutputStream()

        project.exec {
            executable = 'git'
            args = gitArgs
            standardOutput = stdout
        }

        if (stdout.toByteArray().length > 0) {
            def result = stdout.toString()

            if (removeNewLines) {
                result.replaceAll("\\n", "")
            } else {
                result
            }
        } else {
            null
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy