File indexing completed on 2024-07-14 14:25:33

0001 #!/usr/bin/env python
0002 # -*- coding: utf-8 -*-
0003 
0004 # SPDX-License-Identifier: LGPL-2.1-or-later
0005 #
0006 # SPDX-FileCopyrightText: 2015 Dennis Nienhüser <nienhueser@kde.org>
0007 #
0008 
0009 """
0010 Modifies version numbers and related constants in cmake and C++ code
0011 to simplify version bumping for Marble releases.
0012 """
0013 
0014 import argparse, re, sys, os.path, subprocess
0015 from tempfile import mkstemp
0016 from shutil import move
0017 from os import remove, close
0018 
0019 def printUsage():
0020     print ('Usage: ' + sys.argv[0] + ' version')
0021     print ('\tWhere version is a version number in major.minor.patch format, e.g. 0.19.1')
0022 
0023 def versionNumber(version):
0024     match = re.search('([0-4])\\.([0-9]+)\\.([0-9]+)', version)
0025     if not match:
0026         raise argparse.ArgumentTypeError('Cannot parse version number ' + version)
0027     else:
0028         major = int(match.group(1)) 
0029         minor = int(match.group(2))
0030         patch = int(match.group(3))
0031         
0032         if minor < 10:
0033             msg = 'Minor version number too small: Application version is minor version - 10, which should not be smaller than 0.'
0034             raise argparse.ArgumentTypeError(msg)
0035         return major, minor, patch
0036     
0037 def generateVersionString(major, minor, patch):
0038     humanReadable = 'stable release'
0039     if patch >= 20:
0040         humanReadable = '{}.{} development version'.format(major, minor+1)
0041     if patch >= 80:
0042         humanReadable = '{}.{} Beta 1'.format(major, minor+1)
0043     if patch >= 90:
0044         humanReadable = '{}.{} Beta 2'.format(major, minor+1)
0045     if patch >= 95:
0046         humanReadable = '{}.{} Beta 3'.format(major, minor+1)
0047     if patch >= 97:
0048         humanReadable = '{}.{} Release Candidate'.format(major, minor+1)
0049     if patch >= 98:
0050         humanReadable = '{}.{} Release Candidate {}'.format(major, minor+1, patch-96)
0051     return '{}.{}.{} ({})'.format(major, minor, patch, humanReadable)
0052 
0053 def replaceInFile(fileName, searchTerm, replacement):
0054     fh, abs_path = mkstemp()
0055     with open(abs_path,'w') as newFile:
0056         with open(fileName) as oldFile:
0057             for line in oldFile:
0058                 if re.search(searchTerm, line):
0059                     newFile.write(replacement + '\n')
0060                 else:
0061                     newFile.write(line)
0062     close(fh)
0063     remove(fileName)
0064     move(abs_path, fileName)
0065     
0066 def ensureCleanOrExit(rootDir, fileName):
0067     status = subprocess.check_output(['git', 'status', '--short', '--porcelain', fileName], cwd=rootDir)
0068     if len(status.strip()) > 0:
0069         print ('File ' + fileName + ' contains local modifications. Please undo or stash them before proceeding.')
0070         sys.exit(1)
0071 
0072 ## Main script
0073 
0074 parser = argparse.ArgumentParser(description='Update Marble library and application version numbers')
0075 parser.add_argument('version', type=versionNumber, help='New version number in major.minor.patch format, e.g. 0.19.1')
0076 parser.add_argument('--commit', action='store_true', help='Commit changed files automatically')
0077 args = parser.parse_args()
0078 
0079 major, minor, patch = args.version
0080 rootDir = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..'))
0081 
0082 # CMake is responsible to set the so version of the library files
0083 libFileName = os.path.join(rootDir, 'src', 'lib', 'marble', 'CMakeLists.txt')
0084 ensureCleanOrExit(rootDir, libFileName)
0085 libVersionFile = os.path.join(rootDir, 'src', 'lib', 'marble', 'MarbleGlobal.h')
0086 ensureCleanOrExit(rootDir, libVersionFile)
0087 appVersionFile = os.path.join(rootDir, 'src', 'apps', 'marble-ui', 'ControlView.cpp')
0088 ensureCleanOrExit(rootDir, appVersionFile)
0089 winappVersionFile = os.path.join(rootDir, 'install', 'windows', 'marble-common.iss')
0090 ensureCleanOrExit(rootDir, winappVersionFile)
0091 
0092 replaceInFile(libFileName, 
0093               'set\\(MARBLE_LIB_VERSION_MAJOR "[0-9]"\\)',
0094               'set(MARBLE_LIB_VERSION_MAJOR "{}")'.format(major))
0095 soVersion = minor + 1 if patch > 19 else minor
0096 replaceInFile(libFileName,
0097               'set\\(MARBLE_LIB_VERSION_MINOR "[0-9]+"\\)',
0098               'set(MARBLE_LIB_VERSION_MINOR "{}")'.format(soVersion))
0099 replaceInFile(libFileName,
0100               'set\\(MARBLE_LIB_VERSION_PATCH "[0-9]+"\\)',
0101               'set(MARBLE_LIB_VERSION_PATCH "{}")'.format(0))
0102 replaceInFile(libFileName, 
0103               'set\\(MARBLE_ABI_VERSION "[0-9]+"\\)',
0104               'set(MARBLE_ABI_VERSION "{}")'.format(soVersion))
0105 
0106 # We have version constants in MarbleGlobal.h
0107 libVersionOld = 'const QString MARBLE_VERSION_STRING = QString::fromLatin1\( ".*" \);'
0108 libVersionNew = 'const QString MARBLE_VERSION_STRING = QString::fromLatin1( "{}" );'.format(generateVersionString(major, minor, patch))
0109 replaceInFile(libVersionFile, libVersionOld, libVersionNew)
0110 libVersionHexOld = '#define MARBLE_VERSION 0x[0-9a-f]{6}'
0111 libVersionHexNew = '#define MARBLE_VERSION 0x{:02x}{:02x}{:02x}'.format(major, minor, patch)
0112 replaceInFile(libVersionFile, libVersionHexOld, libVersionHexNew)
0113 
0114 appVersionOld = '    return "[0-5]\\.[0-9]+\\.[0-9]+ (.*)";'
0115 appVersionNew = '    return "{}";'.format(generateVersionString(major+2, minor-25, patch))
0116 replaceInFile(appVersionFile, appVersionOld, appVersionNew)
0117 
0118 winappVersionOld = '#define MyAppVersion "[0-5]\\.[0-9]+\\.[0-9]+"'
0119 winappVersionNew = '#define MyAppVersion "{}.{}.{}"'.format(major+2, minor-25, patch)
0120 replaceInFile(winappVersionFile, winappVersionOld, winappVersionNew)
0121 
0122 if args.commit:
0123     versionStringNew = generateVersionString(major, minor, patch)
0124     subprocess.call(['git', 'commit', '--message=Version bump to {}'.format(versionStringNew), libFileName, libVersionFile, appVersionFile], winappVersionFile, cwd=rootDir)
0125     print ('Version bump committed. Please check the output of "git show HEAD".')