ITK Release 4/MigrationGuideDeveloperTutorial/InitializeXMLGuide
<source lang="python">
- InitializeXMLGuide.py
- This script will parse the Git commits on the current branch and initializes
- an XML migration guide document with the apropriate content.
import os.path import sys import subprocess
- Helper Functions #
- strip the prefix from the string in order
def stripPrefix(string, prefix):
if string[0:len(prefix)] == prefix: return string[len(prefix):len(string)] else: return string
- strip the suffix from the string in order
def stripSuffix(string, suffix):
if string[len(string)-len(suffix):len(string)] == suffix: return string[0:len(string)-len(suffix)] else: return string
- test the start of a string
def startsWith(string, prefix):
return (string.find(prefix) == 0)
- test the end of a string
def endsWith(string, suffix):
return (string.rfind(suffix) == len(string) - len(suffix))
- get the output of an external command
def runCommand(command):
args = command.split() process = subprocess.Popen(args, stdout = subprocess.PIPE) while process.returncode == None: process.poll() return process.communicate()[0]
- add proper number of indents
def getIndent(indent):
if indent: return " " else: return ""
- sub out protected characters
def prepXMLString(string):
out = string.replace("<", "<") out = out.replace("&", "&") out = out.replace(">", ">") out = out.replace('"', """) return out.replace("'", "'")
- add an element to the XML file string
def addXMLElement(xmlString, elementName, elementText, indent=False, comment = ""):
# comment if comment != "": xmlString = xmlString + getIndent(indent) + "\n" # opening tag xmlString = xmlString + getIndent(indent) + "<" + elementName + ">\n" # body for line in elementText.splitlines(): xmlString = xmlString + getIndent(indent) + " " + line + "\n" # closing tag return xmlString + getIndent(indent) + "</" + elementName + ">\n\n"
- add spaces for camel case string
def addCamelCaseSpaces(string):
firstLetter = True out = "" for letter in string: if not firstLetter and letter.isupper(): out = out + " " + letter else: out = out + letter firstLetter = False return out
- Main execution point #
if __name__ == '__main__':
# # Get a unique XMLFileName from the user #
# get directory info migrationDir = sys.path[0] baseDir = stripSuffix(migrationDir, "/Migration")
# get XMLFileName (loop until name is unique) uniqueName = False XMLFileName = "" XMLFilePath = "" print "Please enter a unique name for the XML document" while uniqueName == False:
# get the user's input nameCandidate = raw_input(">> ") if not endsWith(nameCandidate, ".xml"): nameCandidate = nameCandidate + ".xml" pathCandidate = migrationDir + "/" + nameCandidate
# check uniqueness if not os.path.exists(pathCandidate): uniqueName = True XMLFileName = nameCandidate XMLFilePath = pathCandidate else: print '"' + nameCandidate + '" already exists. Please specify a differnt name'
# split the name for the title tag titleText = addCamelCaseSpaces(stripSuffix(XMLFileName, ".xml"))
# # Get list of commits on current branch #
# Get the current branch name HEADfilename = baseDir + "/.git/HEAD" try: HEADfile = open(HEADfilename, "r") except IOError: print "I/O error: Could not open .git/HEAD" sys.exit() branchName = HEADfile.readline() branchName = stripPrefix(branchName, "ref: refs/heads/") branchName = stripSuffix(branchName, "\n")
# parse file in .git/logs/refs/heads/BRANCH_NAME branchLogFilename = baseDir + "/.git/logs/refs/heads/" + branchName try: branchLogFile = open(branchLogFilename, "r") except IOError: print "I/O error: Could not open branch log file" sys.exit()
# grab the commit lines, but ignore ammended ones commitList = [] for line in branchLogFile.readlines(): if line.find("commit (amend):") == -1: commitList.append(line.split()[1]) else: commitList.pop() commitList.append(line.split()[1])
# # Parse each commit's log # descriptionText = "" changeIdText = "" sampleCodeOldText = "" sampleCodeNewText = "" changedFileList = [] exampleAndTestChangedFileList = []
firstCommit = commitList[0]; commitList.remove(firstCommit)
for commit in commitList:
# get the log for the commit logCommand = "git log " + commit + " -n1 --stat" log = runCommand(logCommand)
descriptionText = descriptionText + "---- " + commit + " ----\n"
for line in log.splitlines():
# commit message lines and change id lines if startsWith(line, " "): if startsWith(line.strip(), "Change-Id: "): changeId = stripPrefix(line.strip(), "Change-Id: ") changeIdText = changeIdText + changeId + "\n" else: descriptionText = descriptionText + line.strip() + '\n'
# changed file lines elif startsWith(line, " "): splits = line.split("|") if len(splits) == 2: filename = splits[0].strip() if not filename in changedFileList: changedFileList.append(filename) if startsWith(filename, "Examples") or startsWith(filename, "Testing"): exampleAndTestChangedFileList.append(filename)
# # parse the diff of each Example or Testing file # for filename in exampleAndTestChangedFileList:
# Add filename sampleCodeOldText = sampleCodeOldText + "---- " + filename + " ----\n" sampleCodeNewText = sampleCodeNewText + "---- " + filename + " ----\n"
# get the log for the commit fullPath = baseDir + "/" + filename diffCommand = "git diff " + firstCommit + " " + commitList[len(commitList)-1] \ + " -- " + fullPath diff = runCommand(diffCommand)
# parse lines into old and new for line in diff.splitlines():
# old line if (not startsWith(line, "--")) and startsWith(line, "-"): sampleCodeOldText = sampleCodeOldText + line.lstrip("-").strip() + "\n"
# new line elif (not startsWith(line, "++")) and startsWith(line, "+"): sampleCodeNewText = sampleCodeNewText + line.lstrip("+").strip() + "\n"
# # Create XMl file text #
xmlString = '<?xml version="1.0" encoding="UTF-8"?>\n\n' changeElementBody = ""
# <Title> element titleComment = "Title for the online migration page" changeElementBody = addXMLElement(changeElementBody, "Title", titleText, True, titleComment)
# <Description> element descriptionComment = "Plain text description of the change\n-->Extracted from git commit messages" changeElementBody = \ addXMLElement(changeElementBody, "Description",\ prepXMLString(des# InitializeXMLGuide.py
- This script will parse the Git commits on the current branch and initializes
- an XML migration guide document with the apropriate content.
import os.path import sys import subprocess
- Helper Functions #
- strip the prefix from the string in order
def stripPrefix(string, prefix):
if string[0:len(prefix)] == prefix: return string[len(prefix):len(string)] else: return string
- strip the suffix from the string in order
def stripSuffix(string, suffix):
if string[len(string)-len(suffix):len(string)] == suffix: return string[0:len(string)-len(suffix)] else: return string
- test the start of a string
def startsWith(string, prefix):
return (string.find(prefix) == 0)
- test the end of a string
def endsWith(string, suffix):
return (string.rfind(suffix) == len(string) - len(suffix))
- get the output of an external command
def runCommand(command):
args = command.split() process = subprocess.Popen(args, stdout = subprocess.PIPE) while process.returncode == None: process.poll() return process.communicate()[0]
- add proper number of indents
def getIndent(indent):
if indent: return " " else: return ""
- sub out protected characters
def prepXMLString(string):
out = string.replace("<", "<") out = out.replace("&", "&") out = out.replace(">", ">") out = out.replace('"', """) return out.replace("'", "'")
- add an element to the XML file string
def addXMLElement(xmlString, elementName, elementText, indent=False, comment = ""):
# comment if comment != "": xmlString = xmlString + getIndent(indent) + "\n" # opening tag xmlString = xmlString + getIndent(indent) + "<" + elementName + ">\n" # body for line in elementText.splitlines(): xmlString = xmlString + getIndent(indent) + " " + line + "\n" # closing tag return xmlString + getIndent(indent) + "</" + elementName + ">\n\n"
- add spaces for camel case string
def addCamelCaseSpaces(string):
firstLetter = True out = "" for letter in string: if not firstLetter and letter.isupper(): out = out + " " + letter else: out = out + letter firstLetter = False return out
- Main execution point #
if __name__ == '__main__':
# # Get a unique XMLFileName from the user #
# get directory info migrationDir = sys.path[0] baseDir = stripSuffix(migrationDir, "/Migration")
# get XMLFileName (loop until name is unique) uniqueName = False XMLFileName = "" XMLFilePath = "" print "Please enter a unique name for the XML document" while uniqueName == False:
# get the user's input nameCandidate = raw_input(">> ") if not endsWith(nameCandidate, ".xml"): nameCandidate = nameCandidate + ".xml" pathCandidate = migrationDir + "/" + nameCandidate
# check uniqueness if not os.path.exists(pathCandidate): uniqueName = True XMLFileName = nameCandidate XMLFilePath = pathCandidate else: print '"' + nameCandidate + '" already exists. Please specify a differnt name'
# split the name for the title tag titleText = addCamelCaseSpaces(stripSuffix(XMLFileName, ".xml"))
# # Get list of commits on current branch #
# Get the current branch name HEADfilename = baseDir + "/.git/HEAD" try: HEADfile = open(HEADfilename, "r") except IOError: print "I/O error: Could not open .git/HEAD" sys.exit() branchName = HEADfile.readline() branchName = stripPrefix(branchName, "ref: refs/heads/") branchName = stripSuffix(branchName, "\n")
# parse file in .git/logs/refs/heads/BRANCH_NAME branchLogFilename = baseDir + "/.git/logs/refs/heads/" + branchName try: branchLogFile = open(branchLogFilename, "r") except IOError: print "I/O error: Could not open branch log file" sys.exit()
# grab the commit lines, but ignore ammended ones commitList = [] for line in branchLogFile.readlines(): if line.find("commit (amend):") == -1: commitList.append(line.split()[1]) else: commitList.pop() commitList.append(line.split()[1])
# # Parse each commit's log # descriptionText = "" changeIdText = "" sampleCodeOldText = "" sampleCodeNewText = "" changedFileList = [] exampleAndTestChangedFileList = []
firstCommit = commitList[0]; commitList.remove(firstCommit)
for commit in commitList:
# get the log for the commit logCommand = "git log " + commit + " -n1 --stat" log = runCommand(logCommand)
descriptionText = descriptionText + "---- " + commit + " ----\n"
for line in log.splitlines():
# commit message lines and change id lines if startsWith(line, " "): if startsWith(line.strip(), "Change-Id: "): changeId = stripPrefix(line.strip(), "Change-Id: ") changeIdText = changeIdText + changeId + "\n" else: descriptionText = descriptionText + line.strip() + '\n'
# changed file lines elif startsWith(line, " "): splits = line.split("|") if len(splits) == 2: filename = splits[0].strip() if not filename in changedFileList: changedFileList.append(filename) if startsWith(filename, "Examples") or startsWith(filename, "Testing"): exampleAndTestChangedFileList.append(filename)
# # parse the diff of each Example or Testing file # for filename in exampleAndTestChangedFileList:
# Add filename sampleCodeOldText = sampleCodeOldText + "---- " + filename + " ----\n" sampleCodeNewText = sampleCodeNewText + "---- " + filename + " ----\n"
# get the log for the commit fullPath = baseDir + "/" + filename diffCommand = "git diff " + firstCommit + " " + commitList[len(commitList)-1] \ + " -- " + fullPath diff = runCommand(diffCommand)
# parse lines into old and new for line in diff.splitlines():
# old line if (not startsWith(line, "--")) and startsWith(line, "-"): sampleCodeOldText = sampleCodeOldText + line.lstrip("-").strip() + "\n"
# new line elif (not startsWith(line, "++")) and startsWith(line, "+"): sampleCodeNewText = sampleCodeNewText + line.lstrip("+").strip() + "\n"
# # Create XMl file text #
xmlString = '<?xml version="1.0" encoding="UTF-8"?>\n\n' changeElementBody = ""
# <Title> element titleComment = "Title for the online migration page" changeElementBody = addXMLElement(changeElementBody, "Title", titleText, True, titleComment)
# <Description> element descriptionComment = "Plain text description of the change\n-->Extracted from git commit messages" changeElementBody = \ addXMLElement(changeElementBody, "Description",\ prepXMLString(descriptionText), True, descriptionComment)
# <SampleCode> element sampleCodeComment = "Sample code snippets\n-->Extracted from git diff of changed files in Examples and Testing" sampleCodeElementBody = "" sampleCodeElementBody = \ addXMLElement(sampleCodeElementBody, "Old", prepXMLString(sampleCodeOldText)) sampleCodeElementBody = \ addXMLElement(sampleCodeElementBody, "New", prepXMLString(sampleCodeNewText)) changeElementBody = addXMLElement(changeElementBody, "SampleCode",\ sampleCodeElementBody, True, sampleCodeComment)
# <Gerrit-ChangeId> element changeIdComment = "The change-ids for all commits in the topic branch" changeElementBody = \ addXMLElement(changeElementBody, "Gerrit-ChangeId",\ changeIdText, True, changeIdComment)
# <FileList> element fileListComment = "List of all changed files from the topic branch" fileListText = "" for f in changedFileList: fileListText = fileListText + f + "\n" changeElementBody = \ addXMLElement(changeElementBody, "FileList",\ fileListText, True, fileListComment)
# <Change> element changeComment = "\n" + XMLFileName + "\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nTHIS FILE HAS BEEN AUTOMATICALLY GENERATED. EDIT IT BEFORE COMMITING\n<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n" xmlString = addXMLElement(xmlString, "Change", changeElementBody, False, changeComment) xmlString = xmlString.strip()
# # Save the file # try: xmlFile = open(XMLFilePath, "w") xmlFile.write(xmlString) except IOError: print "I/O Error: Could not write to " + XMLFilePath sys.exit()criptionText), True, descriptionComment)
# <SampleCode> element sampleCodeComment = "Sample code snippets\n-->Extracted from git diff of changed files in Examples and Testing" sampleCodeElementBody = "" sampleCodeElementBody = \ addXMLElement(sampleCodeElementBody, "Old", prepXMLString(sampleCodeOldText)) sampleCodeElementBody = \ addXMLElement(sampleCodeElementBody, "New", prepXMLString(sampleCodeNewText)) changeElementBody = addXMLElement(changeElementBody, "SampleCode",\ sampleCodeElementBody, True, sampleCodeComment)
# <Gerrit-ChangeId> element changeIdComment = "The change-ids for all commits in the topic branch" changeElementBody = \ addXMLElement(changeElementBody, "Gerrit-ChangeId",\ changeIdText, True, changeIdComment)
# <FileList> element fileListComment = "List of all changed files from the topic branch" fileListText = "" for f in changedFileList: fileListText = fileListText + f + "\n" changeElementBody = \ addXMLElement(changeElementBody, "FileList",\ fileListText, True, fileListComment)
# <Change> element changeComment = "\n" + XMLFileName + "\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nTHIS FILE HAS BEEN AUTOMATICALLY GENERATED. EDIT IT BEFORE COMMITING\n<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n" xmlString = addXMLElement(xmlString, "Change", changeElementBody, False, changeComment) xmlString = xmlString.strip()
# # Save the file # try: xmlFile = open(XMLFilePath, "w") xmlFile.write(xmlString) except IOError: print "I/O Error: Could not write to " + XMLFilePath sys.exit()
</source>