2023-01-23 11:03:31 +01:00

271 lines
7.5 KiB
Python

#!/usr/bin/python -u
'''
ADOdb release build script
- Create release tag if it does not exist
- Copy release files to target directory
- Generate zip/tar balls
-
'''
import errno
import getopt
import re
import os
from os import path
import shutil
import subprocess
import sys
import tempfile
import updateversion
# ADOdb Repository reference
origin_repo = "https://github.com/ADOdb/ADOdb.git"
release_branch = "master"
release_prefix = "adodb"
# Directories and files to exclude from release tarballs
exclude_list = (".git*",
"replicate",
"scripts",
"tests",
# There are no png files in there...
# "cute_icons_for_site/*.png",
"hs~*.*",
"adodb-text.inc.php",
# This file does not exist in current repo
# 'adodb-lite.inc.php'
)
# Command-line options
options = "hb:dfk"
long_options = ["help", "branch", "debug", "fresh", "keep"]
# Global flags
debug_mode = False
fresh_clone = False
cleanup = True
def usage():
print '''Usage: %s [options] version release_path
Parameters:
version ADOdb version to bundle (e.g. v5.19)
release_path Where to save the release tarballs
Options:
-h | --help Show this usage message
-b | --branch <branch> Use specified branch (defaults to '%s' for '.0'
releases, or 'hotfix/<version>' for patches)
-d | --debug Debug mode (ignores upstream: no fetch, allows
build even if local branch is not in sync)
-f | --fresh Create a fresh clone of the repository
-k | --keep Keep build directories after completion
(useful for debugging)
''' % (
path.basename(__file__),
release_branch
)
#end usage()
def set_version_and_tag(version):
'''
'''
global release_branch, debug_mode, fresh_clone, cleanup
# Delete existing tag to force creation in debug mode
if debug_mode:
try:
updateversion.tag_delete(version)
except:
pass
# Checkout release branch
subprocess.call("git checkout %s" % release_branch, shell=True)
if not debug_mode:
# Make sure we're up-to-date, ignore untracked files
ret = subprocess.check_output(
"git status --branch --porcelain --untracked-files=no",
shell=True
)
if not re.search(release_branch + "$", ret):
print "\nERROR: branch must be aligned with upstream"
sys.exit(4)
# Update the code, create commit and tag
updateversion.version_set(version)
# Make sure we don't delete the modified repo
if fresh_clone:
cleanup = False
def main():
global release_branch, debug_mode, fresh_clone, cleanup
# Get command-line options
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], options, long_options)
except getopt.GetoptError, err:
print str(err)
usage()
sys.exit(2)
if len(args) < 2:
usage()
print "ERROR: please specify the version and release_path"
sys.exit(1)
for opt, val in opts:
if opt in ("-h", "--help"):
usage()
sys.exit(0)
elif opt in ("-b", "--branch"):
release_branch = val
elif opt in ("-d", "--debug"):
debug_mode = True
elif opt in ("-f", "--fresh"):
fresh_clone = True
elif opt in ("-k", "--keep"):
cleanup = False
# Mandatory parameters
version = updateversion.version_check(args[0])
release_path = args[1]
# Default release branch
if updateversion.version_is_patch(version):
release_branch = 'hotfix/' + version
# -------------------------------------------------------------------------
# Start the build
#
global release_prefix
print "Building ADOdb release %s into '%s'\n" % (
version,
release_path
)
if debug_mode:
print "DEBUG MODE: ignoring upstream repository status"
if fresh_clone:
# Create a new repo clone
print "Cloning a new repository"
repo_path = tempfile.mkdtemp(prefix=release_prefix + "-",
suffix=".git")
subprocess.call(
"git clone %s %s" % (origin_repo, repo_path),
shell=True
)
os.chdir(repo_path)
else:
repo_path = subprocess.check_output('git root', shell=True).rstrip()
os.chdir(repo_path)
# Check for any uncommitted changes
try:
subprocess.check_output(
"git diff --exit-code && "
"git diff --cached --exit-code",
shell=True
)
except:
print "ERROR: there are uncommitted changes in the repository"
sys.exit(3)
# Update the repository
if not debug_mode:
print "Updating repository in '%s'" % os.getcwd()
try:
subprocess.check_output("git fetch", shell=True)
except:
print "ERROR: unable to fetch\n"
sys.exit(3)
# Check existence of Tag for version in repo, create if not found
try:
updateversion.tag_check(version)
if debug_mode:
set_version_and_tag(version)
except:
set_version_and_tag(version)
# Copy files to release dir
release_files = release_prefix + version.split(".")[0]
release_tmp_dir = path.join(release_path, release_files)
print "Copying release files to '%s'" % release_tmp_dir
retry = True
while True:
try:
shutil.copytree(
repo_path,
release_tmp_dir,
ignore=shutil.ignore_patterns(*exclude_list)
)
break
except OSError, err:
# First try and file exists, try to delete dir
if retry and err.errno == errno.EEXIST:
print "WARNING: Directory '%s' exists, delete it and retry" % (
release_tmp_dir
)
shutil.rmtree(release_tmp_dir)
retry = False
continue
else:
# We already tried to delete or some other error occured
raise
# Create tarballs
print "Creating release tarballs..."
release_name = release_prefix + '-' + version
print release_prefix, version, release_name
os.chdir(release_path)
print "- tar"
subprocess.call(
"tar -czf %s.tar.gz %s" % (release_name, release_files),
shell=True
)
print "- zip"
subprocess.call(
"zip -rq %s.zip %s" % (release_name, release_files),
shell=True
)
if cleanup:
print "Deleting working directories"
shutil.rmtree(release_tmp_dir)
if fresh_clone:
shutil.rmtree(repo_path)
else:
print "\nThe following working directories were kept:"
if fresh_clone:
print "- '%s' (repo clone)" % repo_path
print "- '%s' (release temp dir)" % release_tmp_dir
print "Delete them manually when they are no longer needed."
# Done
print "\nADOdb release %s build complete, files saved in '%s'." % (
version,
release_path
)
print "Don't forget to generate a README file with the changelog"
#end main()
if __name__ == "__main__":
main()