Daniel Fütterer
11.02.21 61574e05f72d7d4c8c8e634f4c692e9caf0d7618
commit | author | age
61574e 1 import os.path
DF 2
3 def getSeparatedGitLog(repo):
4     try:
5         stream = os.popen("git -C {} log --format=%B--SEP--%H--SEP--%d--END--".format(repo))
6     except:
7         raise ValueError("Not a valid git-repository!")
8     else:
9         gitLog = stream.read()
10         commitList = gitLog.split("--END--")
11         del commitList[-1]
12         return commitList
13      
14
15 class RawCommit:
16     def __init__(self, completeCommit):
17         self.raw = completeCommit.split("--SEP--")
18         self.body = self.raw[0].strip()
19         self.hash = self.raw[1].strip()
20         self.tag = self.raw[2].strip()
21
22
23 class CommitBody:
24     commitTypes = ("build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "style", "test")
25     def __init__(self, completeMessage):
26         self.completeMessage = completeMessage
27         #self.subject = None
28         #self.body = None
29         #self.scope = None
30         #self.commitType = None
31
32         self.setSubjectAndBody()
33         self.setScope()
34         self.setCommitType()
35     
36     def setSubjectAndBody(self):
37         subStart = self.completeMessage.index(": ")+2
38         try:
39             subEnd = self.completeMessage.index("\n")
40         except:
41             self.subject = self.completeMessage[subStart:]
42             self.body = None
43         else:
44             self.subject = self.completeMessage[subStart:subEnd]
45             self.body = self.completeMessage[subEnd:].strip()
46     
47     def setScope(self):
48         try:
49             start = self.completeMessage.index("(")+1
50             end = self.completeMessage.index(")")
51         except:
52             self.scope = None
53         else:
54             self.scope = self.completeMessage[start:end]
55     
56     def setCommitType(self):
57         for commitType in self.commitTypes:
58             if (self.completeMessage.startswith((commitType + ": "))) or (self.completeMessage.startswith((commitType + "("))):
59                 self.commitType = commitType
60                 break
61         
62
63 class CommitTag:
64     def __init__(self, completeTag):
65         if not ("tag: " in completeTag):
66             self.completeTag = None
67             self.tagAsString = None
68             self.major = None
69             self.minor = None
70             self.bugfix = None
71         else:
72             self.completeTag = completeTag
73             self.setTagAsString()
74             self.setMajorMinorBugfix()
75
76     def setTagAsString(self):
77         try: ## this one is temporary
78             self.tagAsString = self.completeTag[(self.completeTag.rindex(": v.")+4):-1]
79         except:
80             try:
81                 self.tagAsString = self.completeTag[(self.completeTag.rindex(": v")+3):-1]
82             except:
83                 self.tagAsString = self.completeTag[(self.completeTag.rindex(": ")+2):-1]
84
85     def setMajorMinorBugfix(self):
86         versionList = self.tagAsString.split(".")
87         self.major = versionList[0]
88         self.minor = versionList[1]
89         self.bugfix = versionList[2]
90     
91     @staticmethod
92     def getUpdateType(newTag, previousTag):
93         if newTag.major > previousTag.major:
94             return "major"
95         elif newTag.minor > previousTag.minor:
96             return "minor"
97         elif newTag.bugfix > previousTag.bugfix:
98             return "bugfix"
99
100
101 class Commit:
102     def __init__(self, rawCommit):
103         self.body = CommitBody(rawCommit.body)
104         self.tag = CommitTag(rawCommit.tag)
105         self.hash = rawCommit.hash
106
107
108
109 #### Main ####
110
111 commitList = getSeparatedGitLog("/Users/daniel/Desktop/testrepo")
112
113 # Create a list of commits
114 commitHistory = []
115 for commit in commitList:
116     commitHistory.append(Commit(RawCommit(commit)))
117
118 # Create a two-dimensional list by tags: [[tag, [commits]],[tag, [commits]],...]
119 taggedHistory = []
120 for commit in commitHistory:
121     if commit.tag.tagAsString:
122         taggedHistory.append([commit.tag, commit])
123     else:
124         if len(taggedHistory) == 0:
125             taggedHistory.append([None, commit])
126         else:
127             taggedHistory[-1].append(commit)
128
129
130 # Construction of the changelog-file
131 fileTemplate = ["# Changelog"]
132 for tag in taggedHistory:
133     # A Dictionairy to store grouped commits
134     commitsByType = {"Fixes":[], "Features":[], "Other":[]}
135     commitsByScope = {}
136
137     # If latest commit has no tag:
138     if not tag[0]:
139         fileTemplate.append("\n## No version number yet ")
140     else:
141         fileTemplate.append("\n## Version " + tag[0].tagAsString)
142
143     # Grouping by CommitTypes
144     for commit in tag[1:]:
145         # Dealing with scopes
146         if commit.body.scope:
147             if commit.body.scope not in commitsByScope:
148                 commitsByScope[commit.body.scope] = [commit]
149             else:
150                 commitsByScope[commit.body.scope].append(commit)
151             for scope in commitsByScope:
152                 fileTemplate.append("\n### Scope: " + scope)
153                 for commit in commitsByScope[scope]:
154                     fileTemplate.append("\n- " + commit.body.commitType + ": " + commit.body.subject + " (" + commit.hash[:6] + ")")
155         else:
156             # Sorting in predifend groups
157             if commit.body.commitType == CommitBody.commitTypes[5]: # fix
158                 commitsByType["Fixes"].append(commit)
159             elif commit.body.commitType == CommitBody.commitTypes[4]: # feat
160                 commitsByType["Features"].append(commit)
161             else:
162                 commitsByType["Other"].append(commit)
163     
164     if len(commitsByType["Features"]) != 0:
165         fileTemplate.append("### Features")
166         for feature in commitsByType["Features"]:
167             fileTemplate.append("- " + feature.body.subject + " (" + feature.hash[:6] + ")")
168     if len(commitsByType["Fixes"]) != 0:
169         fileTemplate.append("### Fixes")
170         for fix in commitsByType["Fixes"]:
171             fileTemplate.append("- " + fix.body.subject + " (" + fix.hash[:6] + ")")
172     if len(commitsByType["Other"]) != 0:
173         fileTemplate.append("### Other")
174         for other in commitsByType["Other"]:
175             fileTemplate.append("\n- " + other.body.commitType + ": " + other.body.subject + " (" + other.hash[:6] + ")")
176         
177
178 # write into changelog
179 with open("changelog.md", "w") as file:
180     for line in fileTemplate:
181         file.write(line + "\n")