import os.path
|
|
def getSeparatedGitLog(repo):
|
try:
|
stream = os.popen("git -C {} log --format=%B--SEP--%H--SEP--%d--END--".format(repo))
|
except:
|
raise ValueError("Not a valid git-repository!")
|
else:
|
gitLog = stream.read()
|
commitList = gitLog.split("--END--")
|
del commitList[-1]
|
return commitList
|
|
|
class RawCommit:
|
def __init__(self, completeCommit):
|
self.raw = completeCommit.split("--SEP--")
|
self.body = self.raw[0].strip()
|
self.hash = self.raw[1].strip()
|
self.tag = self.raw[2].strip()
|
|
|
class CommitBody:
|
commitTypes = ("build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "style", "test")
|
def __init__(self, completeMessage):
|
self.completeMessage = completeMessage
|
#self.subject = None
|
#self.body = None
|
#self.scope = None
|
#self.commitType = None
|
|
self.setSubjectAndBody()
|
self.setScope()
|
self.setCommitType()
|
|
def setSubjectAndBody(self):
|
subStart = self.completeMessage.index(": ")+2
|
try:
|
subEnd = self.completeMessage.index("\n")
|
except:
|
self.subject = self.completeMessage[subStart:]
|
self.body = None
|
else:
|
self.subject = self.completeMessage[subStart:subEnd]
|
self.body = self.completeMessage[subEnd:].strip()
|
|
def setScope(self):
|
try:
|
start = self.completeMessage.index("(")+1
|
end = self.completeMessage.index(")")
|
except:
|
self.scope = None
|
else:
|
self.scope = self.completeMessage[start:end]
|
|
def setCommitType(self):
|
for commitType in self.commitTypes:
|
if (self.completeMessage.startswith((commitType + ": "))) or (self.completeMessage.startswith((commitType + "("))):
|
self.commitType = commitType
|
break
|
|
|
class CommitTag:
|
def __init__(self, completeTag):
|
if not ("tag: " in completeTag):
|
self.completeTag = None
|
self.tagAsString = None
|
self.major = None
|
self.minor = None
|
self.bugfix = None
|
else:
|
self.completeTag = completeTag
|
self.setTagAsString()
|
self.setMajorMinorBugfix()
|
|
def setTagAsString(self):
|
try: ## this one is temporary
|
self.tagAsString = self.completeTag[(self.completeTag.rindex(": v.")+4):-1]
|
except:
|
try:
|
self.tagAsString = self.completeTag[(self.completeTag.rindex(": v")+3):-1]
|
except:
|
self.tagAsString = self.completeTag[(self.completeTag.rindex(": ")+2):-1]
|
|
def setMajorMinorBugfix(self):
|
versionList = self.tagAsString.split(".")
|
self.major = versionList[0]
|
self.minor = versionList[1]
|
self.bugfix = versionList[2]
|
|
@staticmethod
|
def getUpdateType(newTag, previousTag):
|
if newTag.major > previousTag.major:
|
return "major"
|
elif newTag.minor > previousTag.minor:
|
return "minor"
|
elif newTag.bugfix > previousTag.bugfix:
|
return "bugfix"
|
|
|
class Commit:
|
def __init__(self, rawCommit):
|
self.body = CommitBody(rawCommit.body)
|
self.tag = CommitTag(rawCommit.tag)
|
self.hash = rawCommit.hash
|
|
|
|
#### Main ####
|
|
commitList = getSeparatedGitLog("/Users/daniel/Desktop/testrepo")
|
|
# Create a list of commits
|
commitHistory = []
|
for commit in commitList:
|
commitHistory.append(Commit(RawCommit(commit)))
|
|
# Create a two-dimensional list by tags: [[tag, [commits]],[tag, [commits]],...]
|
taggedHistory = []
|
for commit in commitHistory:
|
if commit.tag.tagAsString:
|
taggedHistory.append([commit.tag, commit])
|
else:
|
if len(taggedHistory) == 0:
|
taggedHistory.append([None, commit])
|
else:
|
taggedHistory[-1].append(commit)
|
|
|
# Construction of the changelog-file
|
fileTemplate = ["# Changelog"]
|
for tag in taggedHistory:
|
# A Dictionairy to store grouped commits
|
commitsByType = {"Fixes":[], "Features":[], "Other":[]}
|
commitsByScope = {}
|
|
# If latest commit has no tag:
|
if not tag[0]:
|
fileTemplate.append("\n## No version number yet ")
|
else:
|
fileTemplate.append("\n## Version " + tag[0].tagAsString)
|
|
# Grouping by CommitTypes
|
for commit in tag[1:]:
|
# Dealing with scopes
|
if commit.body.scope:
|
if commit.body.scope not in commitsByScope:
|
commitsByScope[commit.body.scope] = [commit]
|
else:
|
commitsByScope[commit.body.scope].append(commit)
|
for scope in commitsByScope:
|
fileTemplate.append("\n### Scope: " + scope)
|
for commit in commitsByScope[scope]:
|
fileTemplate.append("\n- " + commit.body.commitType + ": " + commit.body.subject + " (" + commit.hash[:6] + ")")
|
else:
|
# Sorting in predifend groups
|
if commit.body.commitType == CommitBody.commitTypes[5]: # fix
|
commitsByType["Fixes"].append(commit)
|
elif commit.body.commitType == CommitBody.commitTypes[4]: # feat
|
commitsByType["Features"].append(commit)
|
else:
|
commitsByType["Other"].append(commit)
|
|
if len(commitsByType["Features"]) != 0:
|
fileTemplate.append("### Features")
|
for feature in commitsByType["Features"]:
|
fileTemplate.append("- " + feature.body.subject + " (" + feature.hash[:6] + ")")
|
if len(commitsByType["Fixes"]) != 0:
|
fileTemplate.append("### Fixes")
|
for fix in commitsByType["Fixes"]:
|
fileTemplate.append("- " + fix.body.subject + " (" + fix.hash[:6] + ")")
|
if len(commitsByType["Other"]) != 0:
|
fileTemplate.append("### Other")
|
for other in commitsByType["Other"]:
|
fileTemplate.append("\n- " + other.body.commitType + ": " + other.body.subject + " (" + other.hash[:6] + ")")
|
|
|
# write into changelog
|
with open("changelog.md", "w") as file:
|
for line in fileTemplate:
|
file.write(line + "\n")
|