diff --git a/dev/release.py b/dev/release.py
new file mode 100755
index 0000000..801afd8
--- /dev/null
+++ b/dev/release.py
@@ -0,0 +1,722 @@
+#! /usr/bin/env python
+# ==========================================================================
+# ctools release manager
+#
+# Copyright (C) 2016 Juergen Knoedlseder
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License
+# along with this program. If not, see .
+#
+# ==========================================================================
+import os
+import sys
+import commands
+
+
+# ================= #
+# Confirm something #
+# ================= #
+def confirm(text):
+ """
+ Confirm something
+
+ Parameters
+ ----------
+ text : str
+ Thing to confirm
+
+ Returns
+ -------
+ flag : bool
+ True if something is confirmed
+ """
+ # Confirmation loop
+ waiting = True
+ while waiting:
+ confirmation = str(raw_input(text+' (y/n): '))
+ if confirmation == 'q':
+ sys.exit()
+ elif confirmation == 'y':
+ flag = True
+ waiting = False
+ elif confirmation == 'n':
+ flag = False
+ waiting = False
+
+ # Return confirmation flag
+ return flag
+
+
+# ============== #
+# Commit changes #
+# ============== #
+def commit(message):
+ """
+ Commit changes into git repo
+
+ Parameters
+ ----------
+ message : str
+ Commit message
+ """
+ # Show changes
+ print("The following files have been changed:")
+ os.system('git status -s')
+
+ # Ask again whether the changes should be committed
+ if confirm("Commit all changes?"):
+
+ # Optionally enter a commit message
+ if len(message) == 0:
+ message = str(raw_input("Please enter a commit message: "))
+
+ # Stage all files
+ os.system('git add -u')
+
+ # Commit all changes
+ os.system('git commit -m "%s"' % message)
+
+ # Return
+ return
+
+
+# ========================== #
+# Check if git branch exists #
+# ========================== #
+def git_branch_exists(branch):
+ """
+ Check if git branch exists
+
+ Parameters
+ ----------
+ branch : str
+ Branch name
+
+ Returns
+ -------
+ exists : bool
+ True if git branch exists
+ """
+ # Check if git branch exists
+ rc = os.system('git rev-parse --verify %s >/dev/null 2>&1' % branch)
+
+ # Set exists flag
+ if rc == 0:
+ exists = True
+ else:
+ exists = False
+
+ # Return flag
+ return exists
+
+
+# ================= #
+# Create git branch #
+# ================= #
+def create_git_branch(branch):
+ """
+ Create a git branch
+
+ Parameters
+ ----------
+ branch : str
+ Branch name
+ """
+ # If branch exists already then ask whether it should be deleted
+ if git_branch_exists(branch):
+ if confirm("Git branch '%s' exists already, do you want to delete "
+ "it?" % branch):
+ os.system('git branch -D %s' % branch)
+
+ # If branch exists already then switch to the new branch, otherwise create
+ # new branch and switch to it
+ if git_branch_exists(branch):
+ os.system('git checkout %s' % branch)
+ else:
+ print("Created new branch '%s'" % branch)
+ os.system('git checkout -b %s' % branch)
+
+ # Return
+ return
+
+
+# ======================================= #
+# Check whether version string is correct #
+# ======================================= #
+def check_version(version):
+ """
+ Check whether version string is correct
+
+ Parameters
+ ----------
+ version : str
+ Version number
+
+ Returns
+ -------
+ check : bool
+ True if version string is correct
+ """
+ # Initialise check with False
+ check = False
+
+ # Split version string
+ split = version.split('.')
+
+ # If there are three elements or four elements we may have a valid version
+ # string
+ if len(split) == 3 or len(split) == 4:
+
+ # If the three first elements are integers we may have a valid version
+ # string
+ if split[0].isdigit() and split[1].isdigit() and split[2].isdigit():
+
+ # If we have three elements the version is valid and we are done
+ if len(split) == 3:
+ check = True
+
+ # Otherwise check if the 4th element is of format devn, where n
+ # is an integer number
+ elif split[3][0:3] == 'dev':
+ if split[3][3:].isdigit():
+ check = True
+
+ # Return check
+ return check
+
+
+# ========================== #
+# Get current version number #
+# ========================== #
+def get_current_version():
+ """
+ Get current version number
+
+ Returns
+ -------
+ version : str
+ Version number
+ """
+ # Initialse version number of empty string
+ version = ''
+
+ # Open configure.ac file
+ f = open('configure.ac', 'r')
+
+ # Read all lines
+ for line in f:
+
+ # Search for pattern
+ if line.startswith('AC_INIT('):
+
+ # Extract version number
+ start = line.find(',')+1
+ stop = line.find(',', start)
+ version = line[start:stop].strip().lstrip('[').rstrip(']')
+
+ # Close file
+ f.close()
+
+ # Return version
+ return version
+
+
+# ========================== #
+# Get libtool version number #
+# ========================== #
+def get_libtool_version():
+ """
+ Get libtools version number
+
+ Returns
+ -------
+ version : str
+ Version number
+ """
+ # Initialse version number of empty string
+ version = ''
+
+ # Open configure.ac file
+ f = open('configure.ac', 'r')
+
+ # Read all lines
+ for line in f:
+
+ # Search for pattern
+ if line.startswith('CTOOLS_LT_VERSION='):
+
+ # Extract version number
+ start = line.find('"')+1
+ stop = line.find('"', start)
+ version = line[start:stop].strip()
+
+ # Close file
+ f.close()
+
+ # Return version
+ return version
+
+
+# =============================================== #
+# Set libtool version number in configure.ac file #
+# =============================================== #
+def set_libtool_version(library=False, added=False, removed=False, changed=False):
+ """
+ Set special version numbers in configure.ac file
+
+ Parameters
+ ----------
+ library : bool, optional
+ Library source code changed
+ added : bool, optional
+ Interfaces added
+ removed : bool, optional
+ Interfaces removed
+ changed : bool, optional
+ Interfaces changed
+ """
+ # Get libtool version number
+ old = get_libtool_version()
+ split = old.split(':')
+
+ # Decompose libtool version number
+ current = int(split[0])
+ revision = int(split[1])
+ age = int(split[2])
+
+ # If the library source code has changed at all since the last update, then
+ # increment revision
+ if library:
+ revision += 1
+
+ # If any interfaces have been added, removed, or changed since the last
+ # update, increment current, and set revision to 0
+ if added or removed or changed:
+ current += 1
+ revision = 0
+
+ # If any interfaces have been added since the last public release, then
+ # increment age
+ if added:
+ age += 1
+
+ # If any interfaces have been removed or changed since the last public
+ # release, then set age to 0
+ if removed or changed:
+ age = 0
+
+ # Build new libtool version number
+ version = '%d:%d:%d' % (current, revision, age)
+
+ # Set libtool version number
+ set_version_in_file('configure.ac', version, old)
+
+ # Return
+ return
+
+
+# ============================== #
+# Set version number in one file #
+# ============================== #
+def set_version_in_file(filename, version, current):
+ """
+ Set version number in one file
+
+ The function replaces all current version numbers in a file by a new
+ version number.
+
+ Parameters
+ ----------
+ filename : str
+ File name
+ version : str
+ New version number
+ current : str
+ Current version number
+ """
+ # Open file in read mode
+ f = open(filename, 'r')
+
+ # Read file content
+ content = f.read()
+
+ # Close file
+ f.close()
+
+ # Replace version number
+ new_content = content.replace(current, version)
+
+ # Open file in write mode
+ f = open(filename, 'w')
+
+ # Write file content
+ f.write(new_content)
+
+ # Close file
+ f.close()
+
+ # Return
+ return
+
+
+# ======================= #
+# Set the package version #
+# ======================= #
+def set_package_version(version):
+ """
+ Set the package version
+
+ Parameters
+ ----------
+ version : str
+ Version number
+ """
+ # List of all files in which the version numbers should be changed. The
+ # file name should include their access paths with respect to the source
+ # directory
+ filenames = ['configure.ac',
+ 'ctools.pc.in',
+ 'README.md',
+ 'sonar-project.properties',
+ 'doc/Doxyfile',
+ 'doc/source/conf.py']
+
+
+ # Get the current package version
+ current = get_current_version()
+
+ # Set versions by loop over all files
+ for filename in filenames:
+ set_version_in_file(filename, version, current)
+
+ # Generate current version number
+ split = current.split('.')
+ cur = '%s.%s' % (split[0], split[1])
+
+ # Generate new version number
+ split = version.split('.')
+ ver = '%s.%s' % (split[0], split[1])
+
+ # Set version number in doc/source/conf.py file
+ set_version_in_file('doc/source/conf.py', ver, cur)
+
+ # Return
+ return
+
+
+# ============= #
+# Build tarball #
+# ============= #
+def build_tarball():
+ """
+ Build tarball using 'make dist'
+ """
+ # Set base path
+ base_path = os.getcwd()
+
+ # Enable/disable logging
+ if confirm("Log actions in logfile?"):
+ verbosity = ' >> %s/make_dist.log 2>&1' % (base_path)
+ os.system('rm -rf make_dist.log >/dev/null 2>&1')
+ else:
+ verbosity = ' >/dev/null 2>&1'
+
+ # Configure package
+ print("Configure package")
+ rc = os.system('./configure%s' % verbosity)
+ if rc == 0:
+ print("Package configuration successful")
+ else:
+ print("*** Failure in package configuration")
+
+ # Check package
+ print("Create tarball")
+ rc = os.system('make dist%s' % verbosity)
+ if rc == 0:
+ print("Tarball creation successful")
+ else:
+ print("*** Failure in creation of tarball")
+
+ # Return
+ return
+
+
+# ============= #
+# Check tarball #
+# ============= #
+def check_tarball():
+ """
+ Check tarball using 'make distcheck'
+
+ Parameters
+ ----------
+ filename : str
+ Tarball file name
+ """
+ # Set base path
+ base_path = os.getcwd()
+
+ # Enable/disable logging
+ if confirm("Log check in logfile?"):
+ verbosity = ' >> %s/make_distcheck.log 2>&1' % (base_path)
+ os.system('rm -rf make_distcheck.log >/dev/null 2>&1')
+ else:
+ verbosity = ' >/dev/null 2>&1'
+
+ # Configure package
+ print("Configure package")
+ rc = os.system('./configure%s' % verbosity)
+ if rc == 0:
+ print("Package configuration successful")
+ else:
+ print("*** Failure in package configuration")
+
+ # Check tarball
+ print("Check tarball")
+ rc = os.system('make distcheck%s' % verbosity)
+ if rc == 0:
+ print("Tarball checking successful")
+ else:
+ print("*** Failure in checking of tarball")
+
+ # Return
+ return
+
+
+# ================ #
+# Manage main menu #
+# ================ #
+def main_menu():
+ """
+ Manage main menu
+ """
+ # Print main menu
+ print('[1] Make a new release')
+ print('[2] Set the package version in current branch')
+ print('[3] Set the libtool version in current branch')
+ print('[4] Commit changes in current branch')
+ print('[5] Create tarball from current branch')
+ print('[6] Check tarball')
+ print('[q] Quit')
+
+ # Wait for the input
+ waiting = True
+ while waiting:
+ choice = str(raw_input('Enter your choice: '))
+ if choice == '1' or choice == '2' or choice == '3' or choice == '4' or \
+ choice == '5' or choice == '6' or choice == 'q':
+ waiting = False
+
+ # Return choice
+ return choice
+
+
+# ====================== #
+# Manage package release #
+# ====================== #
+def release_menu(branch='release'):
+ """
+ Manage package release
+
+ Parameters
+ ----------
+ branch : str, optional
+ Release branch name
+ """
+ # Annonce actions
+ print("")
+ print("Make a new release")
+ print("------------------")
+
+ # Step 1: Create a release branch
+ if confirm("Step 1: Do you want to create a '%s' branch?" % branch):
+ create_git_branch(branch)
+ else:
+ if git_branch_exists(branch):
+ os.system('git checkout %s' % branch)
+ else:
+ requested = branch
+ branch = commands.getoutput('git rev-parse --abbrev-ref HEAD')
+ print("WARNING: No '%s' branch found, continue working on "
+ "current branch '%s'" % (requested, branch))
+
+ # Get current package version
+ current = get_current_version()
+
+ # Step 2: Set package version
+ print("")
+ if confirm("Step 2: Current ctools version is '%s'. Do you want to "
+ "change the package version?" % current):
+ package_version_menu()
+
+ # Get current libtool version
+ current = get_libtool_version()
+
+ # Step 3: Set libtool version
+ print("")
+ if confirm("Step 3: Current Libtool version is '%s'. Do you want to "
+ "change the libtool version?" % current):
+ libtool_version_menu()
+
+ # Step 4: Commit changes
+ print("")
+ if confirm("Step 4: Commit changes?"):
+ package = get_current_version()
+ libtool = get_libtool_version()
+ message = "ctools package version set to '%s' and libtool version "\
+ "set to '%s'" % (package, libtool)
+ commit(message)
+
+ # Step 5: Push branch into git
+ print("")
+ if confirm("Step 5: Push changes?"):
+ os.system('git push origin %s' % branch)
+
+ # Step 6: Build tarball
+ print("")
+ if confirm("Step 6: Build tarball?"):
+ build_tarball()
+
+ # Step 7: Check tarball
+ print("")
+ if confirm("Step 7: Check tarball?"):
+ check_tarball()
+
+ # Print separator
+ print("")
+
+ # Return
+ return
+
+
+# ============================== #
+# Manage package version setting #
+# ============================== #
+def package_version_menu():
+ """
+ Manage package version setting
+ """
+ # Get the current package version
+ current = get_current_version()
+
+ # Looping until the version change is accepted
+ looping = True
+ while looping:
+
+ # Get package version from input
+ waiting = True
+ while waiting:
+ version = str(raw_input("Current ctools version is '%s'. Please "
+ "enter new ctools version: " % current))
+ if version == "q":
+ sys.exit()
+ if check_version(version) == False:
+ print("*** Invalid ctools version. "
+ "Please enter the version in the format x.y.z[.devn]")
+ else:
+ waiting = False
+
+ # If the version number change is confirmed then do the change
+ if confirm("Change version to '%s'?" % version):
+
+ # Set package version
+ set_package_version(version)
+
+ # Get new package and libtool versions
+ version = get_current_version()
+
+ # Inform about version change
+ print("ctools version changed to '%s'" % (version))
+
+ # Signal that we can exit looping
+ looping = False
+
+ # Return
+ return
+
+
+# ============================== #
+# Manage libtool version setting #
+# ============================== #
+def libtool_version_menu():
+ """
+ Manage libtool version setting
+ """
+ # Get current libtool version
+ current = get_libtool_version()
+
+ # Continue only if libtool version should be changed
+ if confirm("Current libtool version is '%s'. Do you want to change the "
+ "version?" % current):
+
+ # Determine package changes
+ library = confirm(" Has the source code changed since last release?")
+ added = confirm(" Have interfaces been added since last release?")
+ removed = confirm(" Have interfaces been removed since last release?")
+ changed = confirm(" Have interfaces changed since last release?")
+
+ # Set libtool version
+ set_libtool_version(library=library, added=added, removed=removed,
+ changed=changed)
+
+ # Get new libtool version
+ version = get_libtool_version()
+
+ # Print new libtool version
+ print("Libtool version changed to '%s'" % version)
+
+ # Return
+ return
+
+
+# ======================== #
+# Main routine entry point #
+# ======================== #
+if __name__ == '__main__':
+
+ # Clear console
+ os.system('clear')
+
+ # Print header
+ print('ctools release manager')
+ print('======================')
+ print('')
+
+ # Enter endless loop
+ while True:
+
+ # Show main menu
+ choice = main_menu()
+
+ # Dispatch according to choice
+ if choice == '1':
+ release_menu()
+ print('')
+ elif choice == '2':
+ package_version_menu()
+ print('')
+ elif choice == '3':
+ libtool_version_menu()
+ print('')
+ elif choice == '4':
+ commit('')
+ print('')
+ elif choice == '5':
+ build_tarball()
+ print('')
+ elif choice == '6':
+ check_tarball()
+ print('')
+ elif choice == 'q':
+ break
+
diff --git a/dev/set_version.py b/dev/set_version.py
deleted file mode 100755
index 4dc399d..0000000
--- a/dev/set_version.py
+++ /dev/null
@@ -1,302 +0,0 @@
-#! /usr/bin/env python
-# ==========================================================================
-# Set the version number of the software
-#
-# Copyright (C) 2016 Juergen Knoedlseder
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program 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 General Public License
-# along with this program. If not, see .
-#
-# ==========================================================================
-import sys
-
-
-# ========================== #
-# Get current version number #
-# ========================== #
-def get_current():
- """
- Get current version number
-
- Returns
- -------
- version : str
- Version number
- """
- # Initialse version number of empty string
- version = ''
-
- # Open configure.ac file
- f = open('configure.ac', 'r')
-
- # Read all lines
- for line in f:
-
- # Search for pattern
- if line.startswith('AC_INIT('):
-
- # Extract version number
- start = line.find(',')+1
- stop = line.find(',', start)
- version = line[start:stop].strip().lstrip('[').rstrip(']')
-
- # Close file
- f.close()
-
- # Return version
- return version
-
-
-# ========================== #
-# Get libtool version number #
-# ========================== #
-def get_libtool():
- """
- Get libtools version number
-
- Returns
- -------
- version : str
- Version number
- """
- # Initialse version number of empty string
- version = ''
-
- # Open configure.ac file
- f = open('configure.ac', 'r')
-
- # Read all lines
- for line in f:
-
- # Search for pattern
- if line.startswith('CTOOLS_LT_VERSION='):
-
- # Extract version number
- start = line.find('"')+1
- stop = line.find('"', start)
- version = line[start:stop].strip()
-
- # Close file
- f.close()
-
- # Return version
- return version
-
-
-# ============================== #
-# Set version number in one file #
-# ============================== #
-def set_version(filename, version, current):
- """
- Set version number
-
- Parameters
- ----------
- filename : str
- File name
- version : str
- Version number
- current : str
- Current version number
- """
- # Open file in read mode
- f = open(filename, 'r')
-
- # Read file content
- content = f.read()
-
- # Close file
- f.close()
-
- # Replace version number
- new_content = content.replace(current, version)
-
- # Open file in write mode
- f = open(filename, 'w')
-
- # Write file content
- f.write(new_content)
-
- # Close file
- f.close()
-
- # Return
- return
-
-
-# =============================== #
-# Set version number in all files #
-# =============================== #
-def set_versions(version, current):
- """
- Set version numbers in all files
-
- Parameters
- ----------
- version : str
- Version number
- current : str
- Current version number
- """
- # List of all relevant files, including their access paths from the
- # source directory
- filenames = ['configure.ac',
- 'ctools.pc.in',
- 'README.md',
- 'sonar-project.properties',
- 'doc/Doxyfile',
- 'doc/source/conf.py']
-
- # Set versions by loop over all files
- for filename in filenames:
- set_version(filename, version, current)
-
- # Return
- return
-
-
-# =============================================== #
-# Set libtool version number in configure.ac file #
-# =============================================== #
-def set_libtool_version(library=False, added=False, removed=False, changed=False):
- """
- Set special version numbers in configure.ac file
-
- Parameters
- ----------
- library : bool, optional
- Library source code changed
- added : bool, optional
- Interfaces added
- removed : bool, optional
- Interfaces removed
- changed : bool, optional
- Interfaces changed
- """
- # Get libtool version number
- old = get_libtool()
- split = old.split(':')
-
- # Decompose libtool version number
- current = int(split[0])
- revision = int(split[1])
- age = int(split[2])
-
- # If the library source code has changed at all since the last update, then
- # increment revision
- if library:
- revision += 1
-
- # If any interfaces have been added, removed, or changed since the last
- # update, increment current, and set revision to 0
- if added or removed or changed:
- current += 1
- revision = 0
-
- # If any interfaces have been added since the last public release, then
- # increment age
- if added:
- age += 1
-
- # If any interfaces have been removed or changed since the last public
- # release, then set age to 0
- if removed or changed:
- age = 0
-
- # Build new libtool version number
- version = '%d:%d:%d' % (current, revision, age)
-
- # Set libtool version number
- set_version('configure.ac', version, old)
-
- # Return
- return
-
-
-# ===================================================== #
-# Set special version number in doc/source/conf.py file #
-# ===================================================== #
-def set_special_conf(version, current):
- """
- Set special version numbers in doc/source/conf.py file
-
- Parameters
- ----------
- version : str
- Version number
- current : str
- Current version number
- """
- # Generate current version number
- split = current.split('.')
- cur = '%s.%s' % (split[0], split[1])
-
- # Generate new version number
- split = version.split('.')
- ver = '%s.%s' % (split[0], split[1])
-
- # Set version number
- set_version('doc/source/conf.py', ver, cur)
-
- # Return
- return
-
-
-# ======================== #
-# Main routine entry point #
-# ======================== #
-if __name__ == '__main__':
-
- # Check for version number
- if len(sys.argv) < 3:
- print('Usage: set_version.py version [larc]')
- print(' l : source code changed')
- print(' a : interface(s) added')
- print(' r : interface(s) removed')
- print(' c : interface(s) changed')
- sys.exit()
-
- # Extract version number
- version = sys.argv[1]
-
- # Extract code change flags
- if len(sys.argv) == 3:
- flags = sys.argv[2]
-
- # Set change flags
- library = False
- added = False
- removed = False
- changed = False
- if flags.find('l') != -1:
- library = True
- if flags.find('a') != -1:
- added = True
- if flags.find('r') != -1:
- removed = True
- if flags.find('c') != -1:
- changed = True
-
- # Get the current version
- current = get_current()
-
- # Set versions
- set_versions(version, current)
-
- # Set libtool version
- set_libtool_version(library=library, added=added, removed=removed,
- changed=changed)
-
- # Set special version number in doc/source/conf.py file
- set_special_conf(version, current)
-