#!/usr/bin/env python2 import re import os import os.path import optparse import sys import time import socket #Define the command line options and parse the command line. parser = optparse.OptionParser() parser.add_option("-d","--dry-run",action="store_true", dest="dryRun",default=True, help="Determine the release versions, but do nothing.") parser.add_option("--apply",action="store_false", dest="dryRun", help="Create a frozen release branch and a new devel head.") parser.add_option("--trace",action="store_true", dest="trace", default=True, help="Print commands before executing them.") parser.add_option("--no-trace",action="store_false", dest="trace", help="Don't print commands before executing them.") (options,args) = parser.parse_args() def System(command): """Run a system command after apply the effect of command line options This responds to the --dry-run and --apply options. """ global options if options.trace: print " Trace: " + command if not options.dryRun: os.system(command) def UnpackVersion(versionString): """Regular Expressions to turn the text version string into a sequence of integers. """ version = 0 release = 0 patch = -1 # Determine the numeric version, release, and patch. # If patch is missing set it to -1. match = re.compile(r'v(\d+)r(\d+)p(\d+)').match(versionString) if match: version = int(match.group(1)) release = int(match.group(2)) patch = int(match.group(3)) match = re.compile(r'v(\d+)r(\d+)').match(versionString) if match: version = int(match.group(1)) release = int(match.group(2)) match = re.compile(r'v(\d+)').match(versionString) if match: version = int(match.group(1)) return (version, release, patch) def GetPackageNameAndVersion(): """Get the name and version of the current package. This will return a tuple of the path of the package root, the package name and the package version. """ # Check if the command is being run in a cmt controlled directory. if not os.path.exists("../cmt/requirements"): sys.exit("Not in a CMT package: You must be in" + " /cmt directory") (path, packageVersion) = os.path.split(os.path.dirname(os.getcwd())) (path, packageName) = os.path.split(path) return (path,packageName,packageVersion) def IncrementPatchNumber(curVer, curRel, curPat): """Increment the patch number to the next development version.""" """The patch number must be even.""" global options newVer = curVer newRel = curRel newPat = curPat + 1 if newPat%2 == 1 : newPat = newPat+1 return (newVer, newRel, newPat) def FormatVersion(ver): return "v%dr%dp%d" % ver ############################################################ def CheckUnusedVersion(ver,package): """Check the versionID ver isn't hasn't already been applied to this package. """ # Use cmt cvstags to check used versions. try: Versions = os.popen("cmt cvstags "+package) except: sys.exit("Could not run cmt") # Search the output for the requested version. match = re.compile(ver) for line in Versions: if match.match(line): return False return True ################################################################ def UpdateRequirementsFile(package,version): """ Rewrite the contents of requirements to ensure that the package and version number are correct. """ requirements = "package "+package+"\n" requirements += "version "+version+"\n" try: reqFile = open("requirements",'r') verCheck = re.compile(r'\Aversion') packCheck = re.compile(r'\Apackage') for line in reqFile: if not verCheck.match(line) and not packCheck.match(line): requirements += line reqFile.close() except IOError: sys.exit("Cannot read requirements file") return requirements ################################################################# def WriteRequirementsFile(contents): """ Write contents to the requirements file. """ print " Update Requirements version" if not options.dryRun: try: reqFile = open("requirements",'w') reqFile.write(contents) reqFile.close() except IOError: sys.exit("Cannot write requirements") return ################################################################# # START THE REAL SCRIPT # Get the current package information. (packagePath, packageName, packageVersion) = GetPackageNameAndVersion() # Set the various release versions. current = UnpackVersion(packageVersion) # Check the current CVS root so that there are no surprises if CVSROOT # isn't properly set. rootFile=open("CVS/Root",mode="r") cvsRoot=rootFile.readline().strip() rootFile.close() if os.environ["CVSROOT"] != cvsRoot: sys.exit("CVSROOT is not properly set") patch = IncrementPatchNumber(current[0], current[1], current[2]) if patch[1]%2 == 0: print "Package %s--%s is not a stable release." % (packageName, packageVersion) sys.exit("Patch releases can only be made against a stable release.") patchTag = FormatVersion(patch) print "Current Release Version: " + packageVersion print "Proposed Patch Version: " + patchTag if not CheckUnusedVersion(patchTag,packageName): sys.exit("Requested patch version "+patchTag+" already in use.\nCheck your versions and if in doubt contact the release manager") System("(cd ..; cvs tag -F -b " + patchTag + ")") System("(cd %s; cmt checkout -r %s %s)" % (packagePath,patchTag,packageName)); if not options.dryRun: os.chdir("../../"+patchTag+"/cmt") newRequirements = UpdateRequirementsFile(packageName,patchTag) WriteRequirementsFile(newRequirements) cvsCommand = "cvs commit -m \"Branch: " + patchTag + " Update version in requirements file for patch release.\" requirements" System(cvsCommand) if options.dryRun: print """ Use the --apply option to increment the patch release number of the package. 1) The new patch tag, %s, will be added to the current source for the package %s--%s. Run this command with the --help option for usage help.""" % (patchTag, packageName, packageVersion)