summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Stebbins <[email protected]>2015-08-28 11:16:56 -0700
committerJohn Stebbins <[email protected]>2015-09-23 11:45:42 -0700
commit25de99bb279ccf562b53765dfdc0bf459109aab8 (patch)
tree3b0693e5e1167bb9935ce4de7520aa46d7e704a1
parentd2aa5174694bf78040f41d2b3755549f37c31153 (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.py84
-rw-r--r--pkg/linux/module.defs14
-rw-r--r--pkg/linux/module.rules10
-rwxr-xr-xscripts/repo-info.sh122
-rwxr-xr-xscripts/tag-release.sh273
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 "$@"