diff options
author | John Stebbins <[email protected]> | 2015-08-28 11:16:56 -0700 |
---|---|---|
committer | John Stebbins <[email protected]> | 2015-09-23 11:45:42 -0700 |
commit | 25de99bb279ccf562b53765dfdc0bf459109aab8 (patch) | |
tree | 3b0693e5e1167bb9935ce4de7520aa46d7e704a1 | |
parent | d2aa5174694bf78040f41d2b3755549f37c31153 (diff) |
build: changes to version numbering and build process
Use date/time for snapshot version numbers, YYYYMMDDHHMMSS-hash-branch.
Add --snapshot configure option to force snapshot builds.
repo-info.sh and tag-release.sh improvements.
-rw-r--r-- | make/configure.py | 84 | ||||
-rw-r--r-- | pkg/linux/module.defs | 14 | ||||
-rw-r--r-- | pkg/linux/module.rules | 10 | ||||
-rwxr-xr-x | scripts/repo-info.sh | 122 | ||||
-rwxr-xr-x | scripts/tag-release.sh | 273 |
5 files changed, 344 insertions, 159 deletions
diff --git a/make/configure.py b/make/configure.py index ecb2816b0..e606f40c1 100644 --- a/make/configure.py +++ b/make/configure.py @@ -16,6 +16,7 @@ import re import subprocess import sys import time +from datetime import datetime, timedelta from optparse import OptionGroup from optparse import OptionGroup @@ -693,12 +694,13 @@ class RepoProbe( ShellProbe ): self.url = 'git://nowhere.com/project/unknown' self.tag = '' + self.tag_hash = 'deadbeaf' self.branch = 'unknown' self.remote = 'unknown' self.rev = 0 self.hash = 'deadbeaf' self.shorthash = 'deadbea' - self.date = '0000-00-00 00:00:00 -0000' + self.date = datetime(1, 1, 1) self.official = 0 self.type = 'developer' @@ -714,6 +716,8 @@ class RepoProbe( ShellProbe ): self.url = value elif name == 'TAG': self.tag = value + elif name == 'TAG_HASH': + self.tag_hash = value elif name == 'BRANCH': self.branch = value elif name == 'REMOTE': @@ -721,7 +725,20 @@ class RepoProbe( ShellProbe ): elif name == 'REV': self.rev = int( value ) elif name == 'DATE': - self.date = value + self.date = datetime.strptime(value[0:19], "%Y-%m-%d %H:%M:%S") + + # strptime can't handle UTC offset + m = re.match( '^([-+]?[0-9]{2})([0-9]{2})$', value[20:]) + (hh, mn) = m.groups() + utc_off_hour = int(hh) + utc_off_minute = int(mn) + if utc_off_hour >= 0: + utc_off = utc_off_hour * 60 + utc_off_minute + else: + utc_off = utc_off_hour * 60 - utc_off_minute + delta = timedelta(minutes=utc_off) + self.date = self.date - delta + elif name == 'HASH': self.hash = value self.shorthash = value[:7] @@ -733,7 +750,7 @@ class RepoProbe( ShellProbe ): if self.url == official_url: self.official = 1 - if self.branch == '' and self.rev == 0: + if not options.snapshot and self.hash == self.tag_hash: self.type = 'release' else: self.type = 'developer' @@ -788,6 +805,9 @@ class Project( Action ): self.vmajor = 0 self.vminor = 0 self.vpoint = 0 + self.spoint = 0 + self.suffix = '' + self.special = '' def _action( self ): ## add architecture to URL only for Mac @@ -796,33 +816,52 @@ class Project( Action ): else: url_arch = '' + suffix = '' if repo.tag != '': - m = re.match( '^([0-9]+)\.([0-9]+)\.([0-9]+)$', repo.tag ) + m = re.match( '^([0-9]+)\.([0-9]+)\.([0-9]+)-?(.*)?$', repo.tag ) if not m: cfg.errln( 'Invalid repo tag format %s\n', repo.tag ) sys.exit( 1 ) - (vmajor, vminor, vpoint) = m.groups() + (vmajor, vminor, vpoint, suffix) = m.groups() self.vmajor = int(vmajor) self.vminor = int(vminor) self.vpoint = int(vpoint) + self.suffix = suffix - if repo.type == 'release': - self.version = '%d.%d.%d' % (self.vmajor,self.vminor,self.vpoint) - url_ctype = '' - url_ntype = 'stable' - self.build = time.strftime('%Y%m%d') + '00' - self.title = '%s %s (%s)' % (self.name,self.version,self.build) - else: + if repo.type != 'release' or options.snapshot: + self.version = repo.date.strftime("%Y%m%d%H%M%S") + self.version += '-%s' % (repo.shorthash) if repo.branch != '': - self.version = '%d.%d.%d-%d-%s-%s' % (self.vmajor, self.vminor, - self.vpoint, repo.rev, repo.shorthash, repo.branch) - else: - self.version = '%d.%d.%d-%d-%s' % (self.vmajor, self.vminor, - self.vpoint, repo.rev, repo.shorthash) + self.version += '-%s' % (repo.branch) + + self.debversion = repo.date.strftime("%Y%m%d%H%M%S") + self.debversion += '-%s' % (repo.shorthash) + if repo.branch != '': + self.debversion += '-%s' % (repo.branch) + url_ctype = '_unstable' url_ntype = 'unstable' self.build = time.strftime('%Y%m%d') + '01' self.title = '%s %s (%s)' % (self.name,self.version,self.build) + else: + m = re.match('^([a-zA-Z]+)\.([0-9]+)$', suffix) + if not m: + # Regular release + self.version = '%d.%d.%d' % (self.vmajor,self.vminor,self.vpoint) + self.debversion = '%d.%d.%d' % (self.vmajor, self.vminor, self.vpoint) + url_ctype = '' + url_ntype = 'stable' + else: + (special, spoint,) = m.groups() + self.special = special + self.spoint = int(spoint) + self.version = '%d.%d.%d-%s.%d' % (self.vmajor,self.vminor,self.vpoint, self.special, self.spoint) + self.debversion = '%d.%d.%d~%s.%d' % (self.vmajor, self.vminor, self.vpoint, self.special, self.spoint) + url_ctype = '_unstable' + url_ntype = 'unstable' + + self.build = time.strftime('%Y%m%d') + '00' + self.title = '%s %s (%s)' % (self.name,self.version,self.build) self.url_appcast = 'https://handbrake.fr/appcast%s%s.xml' % (url_ctype,url_arch) self.url_appnote = 'https://handbrake.fr/appcast/%s.html' % (url_ntype) @@ -1278,6 +1317,13 @@ def createCLI(): for select in SelectTool.selects: select.cli_add_option( grp ) cli.add_option_group( grp ) + + ## add build options + grp = OptionGroup( cli, 'Build Options' ) + grp.add_option( '--snapshot', default=False, action='store_true', + help='Force a snapshot build' ) + cli.add_option_group( grp ) + return cli ############################################################################### @@ -1663,7 +1709,9 @@ int main () doc.add( 'HB.version.major', project.vmajor ) doc.add( 'HB.version.minor', project.vminor ) doc.add( 'HB.version.point', project.vpoint ) + doc.add( 'HB.version.suffix', project.suffix ) doc.add( 'HB.version', project.version ) + doc.add( 'HB.debversion', project.debversion ) doc.add( 'HB.version.hex', '%04x%02x%02x%08x' % (project.vmajor,project.vminor,project.vpoint,repo.rev) ) doc.add( 'HB.build', project.build ) @@ -1677,7 +1725,7 @@ int main () doc.add( 'HB.repo.remote', repo.remote ) doc.add( 'HB.repo.type', repo.type ) doc.add( 'HB.repo.official', repo.official ) - doc.add( 'HB.repo.date', repo.date ) + doc.add( 'HB.repo.date', repo.date.strftime("%Y-%m-%d %H:%M:%S") ) doc.addBlank() doc.add( 'HOST.spec', host.spec ) diff --git a/pkg/linux/module.defs b/pkg/linux/module.defs index 3b1a81f8e..2eea7feb9 100644 --- a/pkg/linux/module.defs +++ b/pkg/linux/module.defs @@ -28,15 +28,15 @@ PKG.rpm.src.tar.bz2 = $(STAGE.out.src/)rpm/$(PKG.rpm.basename).tar.bz2 STAGE.out.rpm.src/ = $(STAGE.out.src/)rpm/ PKG.debian = $(PKG.in/)linux/debian -PKG.cli.deb = $(PKG.out/)$(HB.name)-$(HB.version)-Ubuntu_CLI_$(BUILD.machine).deb -PKG.gui.deb = $(PKG.out/)$(HB.name)-$(HB.version)-Ubuntu_GUI_$(BUILD.machine).deb -PKG.deb.basename = $(HB.name.lower)-$(HB.version) -PKG.src.deb.tar = $(HB.name.lower)_$(HB.version).tar.gz +PKG.cli.deb = $(PKG.out/)$(HB.name)-$(HB.debversion)-Ubuntu_CLI_$(BUILD.machine).deb +PKG.gui.deb = $(PKG.out/)$(HB.name)-$(HB.debversion)-Ubuntu_GUI_$(BUILD.machine).deb +PKG.deb.basename = $(HB.name.lower)-$(HB.debversion) +PKG.src.deb.tar = $(HB.name.lower)_$(HB.debversion).tar.gz PKG.src.deb.stamp = $(STAGE.out.src/).debsrc.stamp -PKG.src.deb = $(PKG.out/)$(HB.name.lower)_$(HB.version).deb +PKG.src.deb = $(PKG.out/)$(HB.name.lower)_$(HB.debversion).deb -PKG.cli.tmp.deb = $(PKG.out/)$(HB.name.lower)-cli_$(HB.version)_$(PKG.deb.machine).deb -PKG.gui.tmp.deb = $(PKG.out/)$(HB.name.lower)-gtk_$(HB.version)_$(PKG.deb.machine).deb +PKG.cli.tmp.deb = $(PKG.out/)$(HB.name.lower)-cli_$(HB.debversion)_$(PKG.deb.machine).deb +PKG.gui.tmp.deb = $(PKG.out/)$(HB.name.lower)-gtk_$(HB.debversion)_$(PKG.deb.machine).deb PKG.native.rpm.stamp = $(RPM.out/).rpm.stamp PKG.rpm.stamp = $(PKG.out/).rpm.stamp diff --git a/pkg/linux/module.rules b/pkg/linux/module.rules index e0d823f17..a08db2517 100644 --- a/pkg/linux/module.rules +++ b/pkg/linux/module.rules @@ -65,7 +65,7 @@ $(PKG.gui.tmp.deb): GNUmakefile fakeroot $(MAKE) -C $(SRC/) -f debian/rules clean $(MAKE) BUILDDIR=$(PWD)/$(BUILD) CONFIGURE=configure -C $(SRC/) -f debian/rules build echo $(PKG.out/) - fakeroot $(MAKE) FORCEVERSION="-- -v$(HB.version)" BUILDDIR=$(PWD)/$(BUILD) CONFIGURE=configure PKGDESTDIR=$(PWD)/$(PKG.out/) -C $(SRC/) -f debian/rules binary + fakeroot $(MAKE) FORCEVERSION="-- -v$(HB.debversion)" BUILDDIR=$(PWD)/$(BUILD) CONFIGURE=configure PKGDESTDIR=$(PWD)/$(PKG.out/) -C $(SRC/) -f debian/rules binary $(PKG.gui.deb): | $(dir $(PKG.gui.deb)) $(PKG.gui.deb): $(PKG.gui.tmp.deb) @@ -79,8 +79,8 @@ $(PKG.cli.deb): $(PKG.gui.tmp.deb) # Debian source package rules # pkg.push.src.deb:: $(PKG.src.deb.stamp) - (cd $(STAGE.out.src/)vivid && dput handbrake-git-snapshots $(HB.name.lower)_$(HB.version)ppa1~vivid1_source.changes ) - (cd $(STAGE.out.src/)trusty && dput handbrake-git-snapshots $(HB.name.lower)_$(HB.version)ppa1~trusty1_source.changes ) + (cd $(STAGE.out.src/)vivid && dput handbrake-git-snapshots $(HB.name.lower)_$(HB.debversion)ppa1~vivid1_source.changes ) + (cd $(STAGE.out.src/)trusty && dput handbrake-git-snapshots $(HB.name.lower)_$(HB.debversion)ppa1~trusty1_source.changes ) $(PKG.src.deb.stamp): GNUmakefile -$(RM.exe) -rf $(STAGE.out.src/) @@ -92,7 +92,7 @@ $(PKG.src.deb.stamp): GNUmakefile cp -a $(PWD)/$(PKG.debian) $(STAGE.out.src/)vivid/$(PKG.deb.basename) $(CP.exe) $(STAGE.out.src/)vivid/$(PKG.deb.basename)/debian/control.vivid $(STAGE.out.src/)vivid/$(PKG.deb.basename)/debian/control $(CP.exe) $(STAGE.out.src/)vivid/$(PKG.deb.basename)/debian/rules.vivid $(STAGE.out.src/)vivid/$(PKG.deb.basename)/debian/rules - echo "$(HB.name.lower) ($(HB.version)ppa1~vivid1) vivid; urgency=low" > $(STAGE.out.src/)vivid/$(PKG.deb.basename)/debian/changelog + echo "$(HB.name.lower) ($(HB.debversion)-1ppa1~vivid1) vivid; urgency=low" > $(STAGE.out.src/)vivid/$(PKG.deb.basename)/debian/changelog echo " * Snapshot" >> $(STAGE.out.src/)vivid/$(PKG.deb.basename)/debian/changelog echo " - See timeline at http://trac.handbrake.fr/timeline" >> $(STAGE.out.src/)vivid/$(PKG.deb.basename)/debian/changelog echo "" >> $(STAGE.out.src/)vivid/$(PKG.deb.basename)/debian/changelog @@ -106,7 +106,7 @@ $(PKG.src.deb.stamp): GNUmakefile cp -a $(PWD)/$(PKG.debian) $(STAGE.out.src/)trusty/$(PKG.deb.basename) $(CP.exe) $(STAGE.out.src/)trusty/$(PKG.deb.basename)/debian/control.trusty $(STAGE.out.src/)trusty/$(PKG.deb.basename)/debian/control $(CP.exe) $(STAGE.out.src/)trusty/$(PKG.deb.basename)/debian/rules.trusty $(STAGE.out.src/)trusty/$(PKG.deb.basename)/debian/rules - echo "$(HB.name.lower) ($(HB.version)ppa1~trusty1) trusty; urgency=low" > $(STAGE.out.src/)trusty/$(PKG.deb.basename)/debian/changelog + echo "$(HB.name.lower) ($(HB.debversion)-1ppa1~trusty1) trusty; urgency=low" > $(STAGE.out.src/)trusty/$(PKG.deb.basename)/debian/changelog echo " * Snapshot" >> $(STAGE.out.src/)trusty/$(PKG.deb.basename)/debian/changelog echo " - See timeline at http://trac.handbrake.fr/timeline" >> $(STAGE.out.src/)trusty/$(PKG.deb.basename)/debian/changelog echo "" >> $(STAGE.out.src/)trusty/$(PKG.deb.basename)/debian/changelog diff --git a/scripts/repo-info.sh b/scripts/repo-info.sh index 0e402535d..4e8795344 100755 --- a/scripts/repo-info.sh +++ b/scripts/repo-info.sh @@ -2,66 +2,78 @@ # # Retrieves git repository info for directory ${1} using command ${2} -# Args -REPO_DIR='.' -if [[ ${1} ]]; then - REPO_DIR=${1} -fi -GIT_EXE='git' -if [[ ${2} ]]; then - GIT_EXE=${2} -fi +function repo_info() +{ + local repo_dir git_exe commit upstream err -# Switch to working directory -if ! cd ${REPO_DIR} 2>/dev/null; then - echo "Invalid directory ${REPO_DIR}." 1>&2 - exit 1 -fi + # Process args + repo_dir='.' + if [[ ${1} ]]; then + repo_dir=${1} + fi + git_exe='git' + if [[ ${2} ]]; then + git_exe=${2} + fi + + # Switch to working directory + if ! cd ${repo_dir} 2>/dev/null; then + echo "Invalid directory ${repo_dir}." 1>&2 + return 1 + fi -# Check whether we have git -if ! hash ${GIT_EXE} 2>/dev/null; then - echo "Command '${GIT_EXE}' not found." 1>&2 - exit 1 -fi + # Check whether we have git + if ! hash ${git_exe} 2>/dev/null; then + echo "Command '${git_exe}' not found." 1>&2 + return 1 + fi -# Check if there is a valid git repo here -HASH=$(${GIT_EXE} rev-parse HEAD) -ERR=$? -if [[ ${ERR} -ne 0 ]]; then - echo "Not a valid repository." 1>&2 - exit ${ERR} -elif [[ -z ${HASH} ]]; then - echo "Not a valid repository." 1>&2 - exit 1 -fi + # Check if there is a valid git repo here + HASH=$(${git_exe} rev-parse HEAD) + SHORTHASH=$(${git_exe} rev-parse --short HEAD) + err=$? + if [[ ${err} -ne 0 ]]; then + echo "Not a valid repository." 1>&2 + return ${err} + elif [[ -z ${HASH} ]]; then + echo "Not a valid repository." 1>&2 + return 1 + fi -# Retrieve info -URL=$(${GIT_EXE} config remote.origin.url) -TAG=$(${GIT_EXE} describe --tags --abbrev=0) -if [[ ${TAG} ]]; then - REV=$(${GIT_EXE} rev-list ${TAG}.. --count) -else - TAG=$(${GIT_EXE} describe --tags $(${GIT_EXE} rev-list --tags --max-count=1)) + # Retrieve info + URL=$(${git_exe} config remote.origin.url) + + # check if an annotated tag is reachable from HEAD + TAG=$(${git_exe} describe --tags --abbrev=0 --exact-match --match \[0-9\]\*.\[0-9\]\*.\[0-9\]\* HEAD 2> /dev/null) if [[ ${TAG} ]]; then - REV=$(${GIT_EXE} rev-list $(${GIT_EXE} merge-base ${TAG} HEAD).. --count) + # if TAG is a release tag and HASH == TAG_HASH, this is release code + TAG_HASH=$(${git_exe} rev-list ${TAG} --max-count=1) + REV=$(${git_exe} rev-list $(${git_exe} merge-base ${TAG} HEAD).. --count) else - REV=$(${GIT_EXE} rev-list HEAD --count) + REV=$(${git_exe} rev-list HEAD --count) + fi + + BRANCH=$(${git_exe} symbolic-ref -q --short HEAD) + REMOTE="${URL}" + upstream=$(${git_exe} config branch.${BRANCH}.remote) + if [[ ${upstream} ]]; then + REMOTE="${upstream}" fi -fi -BRANCH=$(${GIT_EXE} symbolic-ref -q --short HEAD) -REMOTE="${URL}" -UPSTREAM=$(${GIT_EXE} config branch.${BRANCH}.remote) -if [[ ${UPSTREAM} ]]; then - REMOTE="${UPSTREAM}" -fi -DATE=$(${GIT_EXE} log -1 --format="format:%ai") + DATE=$(${git_exe} log -1 --format="format:%ci") + + # Output + # Only write tag and rev if they exist. + echo "URL=${URL}" + echo "HASH=${HASH}" + echo "SHORTHASH=${SHORTHASH}" + if [[ ${TAG} ]]; then echo "TAG=${TAG}"; fi + if [[ ${TAG_HASH} ]]; then echo "TAG_HASH=${TAG_HASH}"; fi + if [[ ${REV} ]]; then echo "REV=${REV}"; fi + echo "BRANCH=${BRANCH}" + echo "REMOTE=${REMOTE}" + echo "DATE=${DATE}" + + return 0 +} -# Output -# Only write tag and rev if they exist. -echo "URL=${URL}" -echo "HASH=${HASH}" -if [[ ${TAG} ]]; then echo "TAG=${TAG}"; fi -if [[ ${REV} ]]; then echo "REV=${REV}"; fi -echo "BRANCH=${BRANCH}" -echo "REMOTE=${REMOTE}" -echo "DATE=${DATE}" +repo_info "$@" diff --git a/scripts/tag-release.sh b/scripts/tag-release.sh index 66e33e308..9f7d488f6 100755 --- a/scripts/tag-release.sh +++ b/scripts/tag-release.sh @@ -1,86 +1,211 @@ #! /bin/bash # -# Usage: tag-release.sh <release-ver> [<commit>] +# Usage: tag-release.sh <release-ver> [<ref>] # -# Creates a new branch and tag for the release -# Optionally, the release can be based off a specific git commit. +# Creates a new bugfix branch and release tag for a release. +# Optionally, the release can be based off a specific git ref. +# Default is HEAD of the current branch. +# +# The script does a lot of error checking, but boils down to +# the following actions. +# +# For major/minor releases (X.Y.0) from master branch: +# git checkout -b X.Y.x +# git tag -a X.Y.Z -m "X.Y.Z" HEAD +# and optionally: +# git push -u origin X.Y.x +# git push origin refs/tags/X.Y.Z +# +# For bugfix releases from associated branch (X.Y.x): +# git tag -a X.Y.Z -m "X.Y.Z" HEAD +# and optionally: +# git push origin refs/tags/X.Y.Z # -TAG=${1} -COMMIT=${2} - -if [ "x${TAG}" == "x" ]; then - echo "Missing release tag (e.g. 0.10.0)" -fi - -if [ "x${COMMIT}" == "x" ]; then - echo "Creating release tag ${TAG} and branch ${TAG}-dev from HEAD, proceed?" -else - echo "Creating release tag ${TAG} and branch ${TAG}-dev from ${COMMIT}, proceed?" -fi -read proceed -if [[ ( "x${proceed}" != "xy" ) && ( "x${proceed}" != "xY" ) ]] ; then - echo "Aborting..." - exit 0 -fi - -if [ "x${COMMIT}" != "x" ]; then - # create release branch from specific commit - git checkout "${COMMIT}" -b "${TAG}-dev" - ERR=$? -else - # create release branch from head of current branch - git checkout -b "${TAG}-dev" - ERR=$? -fi -if [ ${ERR} -ne 0 ]; then - echo "Failed to create branch ${TAG}-dev" - exit ${ERR} -fi - -# create tag -git tag -a "${TAG}" -m "Release ${TAG}" HEAD -ERR=$? -if [ ${ERR} -ne 0 ]; then - echo "Failed to create tag ${TAG}" - # cleanup... remove the branch that was created - git branch -d "${TAG}-dev" - exit ${ERR} -fi - -# checkout tag in preparation for building release -# this should put you in a "detached HEAD" state -git checkout "${TAG}" -ERR=$? -if [ ${ERR} -ne 0 ]; then - echo "Failed to checkout tag ${TAG}" - # cleanup... remove the branch that was created - git branch -d "${TAG}-dev" - exit ${ERR} -fi - -remote=$(git config remote.origin.url) -echo -echo "Do you wish to push this release branch and tag to $remote? (y/N)" -echo "You may want to do this manually after creating and verifying release." -echo "e.g." -echo " git push -u origin ${TAG}-dev" -echo " git push origin ${TAG}" -read proceed -if [[ ( "x${proceed}" == "xy" ) || ( "x${proceed}" == "xY" ) ]] ; then - git push -u origin "${TAG}-dev" +GIT_EXE='git' + +function validate_repo() +{ + local HASH err AHEAD BEHIND proceed + + # Check whether we have git + if ! hash ${GIT_EXE} 2>/dev/null; then + echo "Command '${GIT_EXE}' not found." 1>&2 + return 1 + fi + + # Check if there is a valid git repo here + HASH=$(${GIT_EXE} rev-parse HEAD) + err=$? + if [[ ${err} -ne 0 ]]; then + echo "Not a valid repository." 1>&2 + return ${err} + elif [[ -z ${HASH} ]]; then + echo "Not a valid repository." 1>&2 + return 1 + fi + + if [[ -n "$(${GIT_EXE} status --porcelain)" ]]; then + echo "There are uncommitted changes. Aborting." 1>&2 + return 1 + fi + + echo "Fetching repo data..." + ${GIT_EXE} fetch + err=$? + if [[ ${err} -ne 0 ]]; then + echo "Failed to fetch repo data." 1>&2 + return ${err} + fi + AHEAD=$(${GIT_EXE} rev-list @{u}..HEAD --count) + BEHIND=$(${GIT_EXE} rev-list HEAD..@{u} --count) + if [[ ${AHEAD} -ne 0 ]]; then + echo "There are unpushed changes. Continue anyway? (y/N)" + read proceed + if [[ ( "x${proceed}" != "xy" ) && ( "x${proceed}" != "xY" ) ]] ; then + echo "Aborting..." + return 1 + fi + fi + if [[ ${BEHIND} -ne 0 ]]; then + echo "There are unmerged upstream changes. Continue anyway? (y/N)" + read proceed + if [[ ( "x${proceed}" != "xy" ) && ( "x${proceed}" != "xY" ) ]] ; then + echo "Aborting..." + return 1 + fi + fi +} + +function tag_release() +{ + local TAG REF COMMIT BRANCH proceed new_branch ERR HASH + + TAG=${1} + REF=${2} + + if [ "x${TAG}" == "x" ]; then + echo "Missing release tag (e.g. 0.10.0)" + fi + + # bugfix branch name + BRANCH=${TAG%.[0-9]*}.x + + if [ "x${REF}" == "x" ]; then + echo "Creating release tag ${TAG} and branch ${BRANCH} from HEAD, proceed? (y/N)" + # retrive full hash of HEAD + COMMIT=$(${GIT_EXE} rev-list HEAD --max-count=1) + else + echo "Creating release tag ${TAG} and branch ${BRANCH} from ${REF}, proceed? (y/N)" + # retrieve full hash from ref or short hash + COMMIT=$(${GIT_EXE} rev-list ${REF} --max-count=1) + fi + read proceed + if [[ ( "x${proceed}" != "xy" ) && ( "x${proceed}" != "xY" ) ]] ; then + echo "Aborting..." + return 0 + fi + + # check if the remote branch already exists + ${GIT_EXE} rev-parse --quiet --verify origin/${BRANCH} > /dev/null + if [ $? -ne 0 ]; then + # remote branch does not exist + new_branch=1 + # does the branch already exist locally? + ${GIT_EXE} rev-parse --quiet --verify ${BRANCH} > /dev/null + if [ $? -ne 0 ]; then + # local branch does not exist + # create bugfix branch from commit + ${GIT_EXE} checkout "${COMMIT}" -b "${BRANCH}" + ERR=$? + if [ ${ERR} -ne 0 ]; then + echo "Failed to create branch ${BRANCH}" + return ${ERR} + fi + else + # local branch already exists + # When the branch already exists, make sure it is being used! + current_branch=$(${GIT_EXE} rev-parse --abbrev-ref HEAD) + if [ "$current_branch" != "${BRANCH}" ]; then + echo "You did not checkout the correct branch ${BRANCH} for tag ${TAG}" + return 1 + fi + fi + else + new_branch=0 + # When the branch already exists, make sure it is being used! + current_branch=$(${GIT_EXE} rev-parse --abbrev-ref HEAD) + if [ "$current_branch" != "${BRANCH}" ]; then + echo "You did not checkout the correct branch ${BRANCH} for tag ${TAG}" + return 1 + fi + fi + + # at this point we should be at the head of the tracking branch + # for this release. Make certain that HEAD matches COMMIT + HASH=$(${GIT_EXE} rev-list HEAD --max-count=1) + if [ ${HASH} != ${COMMIT} ]; then + echo "Commit specified does not match current branch HEAD" + return 1 + fi + + # create tag + ${GIT_EXE} tag -a "${TAG}" -m "${TAG}" HEAD ERR=$? if [ ${ERR} -ne 0 ]; then - echo "Failed to push branch ${TAG}-dev to remote" - exit ${ERR} + echo "Failed to create tag ${TAG}" + # cleanup... remove the branch that was created + ${GIT_EXE} branch -d "${BRANCH}" + return ${ERR} fi - git push origin "${TAG}" + + # checkout tag in preparation for building release + # this should put you in a "detached HEAD" state + ${GIT_EXE} checkout "${TAG}" ERR=$? if [ ${ERR} -ne 0 ]; then - echo "Failed to push tag ${TAG}-dev to remote" - exit ${ERR} + echo "Failed to checkout tag ${TAG}" + # cleanup... remove the branch that was created + ${GIT_EXE} branch -d "${BRANCH}" + return ${ERR} + fi + + remote=$(${GIT_EXE} config remote.origin.url) + echo + echo "Do you wish to push this release branch and tag to $remote? (y/N)" + echo "You may want to do this manually after creating and verifying release." + echo "e.g." + echo " git push -u origin ${BRANCH}" + echo " git push origin refs/tags/${TAG}" + read proceed + if [[ ( "x${proceed}" == "xy" ) || ( "x${proceed}" == "xY" ) ]] ; then + if [ $new_branch .eq 1 ]; then + ${GIT_EXE} push -u origin "${BRANCH}" + ERR=$? + if [ ${ERR} -ne 0 ]; then + echo "Failed to push branch ${BRANCH} to remote" + return ${ERR} + fi + fi + ${GIT_EXE} push origin refs/tags/"${TAG}" + ERR=$? + if [ ${ERR} -ne 0 ]; then + echo "Failed to push tag ${BRANCH} to remote" + return ${ERR} + fi + else + echo "Branch and tag are local, changes not pushed to remote!" + fi + +} + +function main() +{ + if validate_repo; then + tag_release "$@" + else + return $? fi -else - echo "Branch and tag are local, changes not pushed to remote!" -fi +} +main "$@" |