gitflow-manager 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gitflow_manager-1.0.1/PKG-INFO +72 -0
- gitflow_manager-1.0.1/README.md +61 -0
- gitflow_manager-1.0.1/gitflow_manager/__init__.py +1 -0
- gitflow_manager-1.0.1/gitflow_manager/changelog.py +280 -0
- gitflow_manager-1.0.1/gitflow_manager/errors.py +2 -0
- gitflow_manager-1.0.1/gitflow_manager/file_utils.py +35 -0
- gitflow_manager-1.0.1/gitflow_manager/git_hosts.py +484 -0
- gitflow_manager-1.0.1/gitflow_manager/gitflow_manager.py +685 -0
- gitflow_manager-1.0.1/gitflow_manager/run.py +127 -0
- gitflow_manager-1.0.1/gitflow_manager/start.py +114 -0
- gitflow_manager-1.0.1/gitflow_manager.egg-info/PKG-INFO +72 -0
- gitflow_manager-1.0.1/gitflow_manager.egg-info/SOURCES.txt +16 -0
- gitflow_manager-1.0.1/gitflow_manager.egg-info/dependency_links.txt +1 -0
- gitflow_manager-1.0.1/gitflow_manager.egg-info/entry_points.txt +2 -0
- gitflow_manager-1.0.1/gitflow_manager.egg-info/requires.txt +4 -0
- gitflow_manager-1.0.1/gitflow_manager.egg-info/top_level.txt +3 -0
- gitflow_manager-1.0.1/pyproject.toml +50 -0
- gitflow_manager-1.0.1/setup.cfg +4 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gitflow_manager
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: This package contains the Anacision Git Manager.
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: gitpython>=3.1.24
|
|
8
|
+
Requires-Dist: pystache>=0.6.0
|
|
9
|
+
Requires-Dist: requests>=2.27.1
|
|
10
|
+
Requires-Dist: toml>=0.10.2
|
|
11
|
+
|
|
12
|
+
# Anacision Gitflow Manager
|
|
13
|
+
|
|
14
|
+
## Description
|
|
15
|
+
|
|
16
|
+
The gitflow manager is a tool that helps maintaining clean versioning and documentation in code projects.
|
|
17
|
+
By using the gitflow manager one can make sure to stick to the
|
|
18
|
+
[GitFlow](https://nvie.com/posts/a-successful-git-branching-model) rules. Furthermore, it helps maintain a good
|
|
19
|
+
changelog and documentation.
|
|
20
|
+
Whenever you want to start a new branch or merging it back to dev/main run the `gfm` command.
|
|
21
|
+
It uses a dialog to define the type of new branch (feature, bugfix, hotfix, release) or merge option as well as setting
|
|
22
|
+
the required changelog messages.
|
|
23
|
+
It then automatically updates version numbers, checks out corresponding branches and commits/merges according to the
|
|
24
|
+
GitFlow.
|
|
25
|
+
Changes are also pushed to the Git Host via ssh or https and for protected branches merge requests are initialized.
|
|
26
|
+
Currently, the gitflow manager supports Gitlab and Bitbucket as hosting platforms.
|
|
27
|
+
|
|
28
|
+
### Versioning
|
|
29
|
+
|
|
30
|
+
- Utilize the gitflow manager in projects to make sure that you easily stick to these rules:
|
|
31
|
+
- Versions are defined in the format *Major.Minor.Hotfix*. New versions are created when opening the hotfix or release
|
|
32
|
+
branch.
|
|
33
|
+
- The hotfix branch is only allowed to be started from main branch, to increase the Hotfix version digit only and to
|
|
34
|
+
be merged into main (+ dev thereafter).
|
|
35
|
+
- The release branch is only allowed to be started from dev, to increase the minor or major version digit and to be
|
|
36
|
+
merged into main (+ dev thereafter). In case of a new major version, the minor and hotfix digit is reset to 0. In case
|
|
37
|
+
of a new minor version, the hotfix digit is reset to 0.
|
|
38
|
+
- The bugfix and feature branches are only allowed to be started from dev, increase no version number and are merged
|
|
39
|
+
back to dev.
|
|
40
|
+
- All new branches need a description in the change log, which has separate "Added", "Changed" and "Fixed" sections.
|
|
41
|
+
|
|
42
|
+
### Supported branches with gitflow manager
|
|
43
|
+
|
|
44
|
+
- **main**: Permanent, stable, (normally) protected branch used for deployment. Each commit has a new version. Merge
|
|
45
|
+
requests only come from release or hotfix branch.
|
|
46
|
+
- **dev**: Permanent development branch. Gets merge requests from feature, hotfix and release branch.
|
|
47
|
+
- **release/vX.X.X**: Release branch. Branched off from dev branch with new minor or major version. When the branch is
|
|
48
|
+
finished, it is merged into main and dev branch. Intermediate merges into dev are allowed, too. Merges from dev into
|
|
49
|
+
release branch are not allowed.
|
|
50
|
+
- **feature/xxxxxx**: For features to be developed. Branched off from dev branch and will be merged back into dev after
|
|
51
|
+
finishing feature.
|
|
52
|
+
- **bugfix/xxxxxx**: For bugs to be fixed. Branched off from dev branch and will be merged back into dev after
|
|
53
|
+
finishing the fix.
|
|
54
|
+
- **hotfix/vX.X.X**: Hotfix branch for fixes from deployed code. Branched off from main branch with new hotfix
|
|
55
|
+
version. When done, is merged into main and dev branch.
|
|
56
|
+
|
|
57
|
+
### Tagging
|
|
58
|
+
|
|
59
|
+
- Currently, tagging is not done automatically. You can configure yourself a CI pipeline, that does the job for you.
|
|
60
|
+
|
|
61
|
+
## Getting started
|
|
62
|
+
|
|
63
|
+
### Installation
|
|
64
|
+
|
|
65
|
+
1. Install gitflow manager with pip: `pip install gitflow-manager`
|
|
66
|
+
2. Restart terminal
|
|
67
|
+
|
|
68
|
+
### Usage
|
|
69
|
+
|
|
70
|
+
- When using the first time, run `gfm --init` in the root of the project.
|
|
71
|
+
- Subsequently, just type `gfm` each time you need to branch or merge (or add change log information), and follow the
|
|
72
|
+
dialog
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Anacision Gitflow Manager
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
The gitflow manager is a tool that helps maintaining clean versioning and documentation in code projects.
|
|
6
|
+
By using the gitflow manager one can make sure to stick to the
|
|
7
|
+
[GitFlow](https://nvie.com/posts/a-successful-git-branching-model) rules. Furthermore, it helps maintain a good
|
|
8
|
+
changelog and documentation.
|
|
9
|
+
Whenever you want to start a new branch or merging it back to dev/main run the `gfm` command.
|
|
10
|
+
It uses a dialog to define the type of new branch (feature, bugfix, hotfix, release) or merge option as well as setting
|
|
11
|
+
the required changelog messages.
|
|
12
|
+
It then automatically updates version numbers, checks out corresponding branches and commits/merges according to the
|
|
13
|
+
GitFlow.
|
|
14
|
+
Changes are also pushed to the Git Host via ssh or https and for protected branches merge requests are initialized.
|
|
15
|
+
Currently, the gitflow manager supports Gitlab and Bitbucket as hosting platforms.
|
|
16
|
+
|
|
17
|
+
### Versioning
|
|
18
|
+
|
|
19
|
+
- Utilize the gitflow manager in projects to make sure that you easily stick to these rules:
|
|
20
|
+
- Versions are defined in the format *Major.Minor.Hotfix*. New versions are created when opening the hotfix or release
|
|
21
|
+
branch.
|
|
22
|
+
- The hotfix branch is only allowed to be started from main branch, to increase the Hotfix version digit only and to
|
|
23
|
+
be merged into main (+ dev thereafter).
|
|
24
|
+
- The release branch is only allowed to be started from dev, to increase the minor or major version digit and to be
|
|
25
|
+
merged into main (+ dev thereafter). In case of a new major version, the minor and hotfix digit is reset to 0. In case
|
|
26
|
+
of a new minor version, the hotfix digit is reset to 0.
|
|
27
|
+
- The bugfix and feature branches are only allowed to be started from dev, increase no version number and are merged
|
|
28
|
+
back to dev.
|
|
29
|
+
- All new branches need a description in the change log, which has separate "Added", "Changed" and "Fixed" sections.
|
|
30
|
+
|
|
31
|
+
### Supported branches with gitflow manager
|
|
32
|
+
|
|
33
|
+
- **main**: Permanent, stable, (normally) protected branch used for deployment. Each commit has a new version. Merge
|
|
34
|
+
requests only come from release or hotfix branch.
|
|
35
|
+
- **dev**: Permanent development branch. Gets merge requests from feature, hotfix and release branch.
|
|
36
|
+
- **release/vX.X.X**: Release branch. Branched off from dev branch with new minor or major version. When the branch is
|
|
37
|
+
finished, it is merged into main and dev branch. Intermediate merges into dev are allowed, too. Merges from dev into
|
|
38
|
+
release branch are not allowed.
|
|
39
|
+
- **feature/xxxxxx**: For features to be developed. Branched off from dev branch and will be merged back into dev after
|
|
40
|
+
finishing feature.
|
|
41
|
+
- **bugfix/xxxxxx**: For bugs to be fixed. Branched off from dev branch and will be merged back into dev after
|
|
42
|
+
finishing the fix.
|
|
43
|
+
- **hotfix/vX.X.X**: Hotfix branch for fixes from deployed code. Branched off from main branch with new hotfix
|
|
44
|
+
version. When done, is merged into main and dev branch.
|
|
45
|
+
|
|
46
|
+
### Tagging
|
|
47
|
+
|
|
48
|
+
- Currently, tagging is not done automatically. You can configure yourself a CI pipeline, that does the job for you.
|
|
49
|
+
|
|
50
|
+
## Getting started
|
|
51
|
+
|
|
52
|
+
### Installation
|
|
53
|
+
|
|
54
|
+
1. Install gitflow manager with pip: `pip install gitflow-manager`
|
|
55
|
+
2. Restart terminal
|
|
56
|
+
|
|
57
|
+
### Usage
|
|
58
|
+
|
|
59
|
+
- When using the first time, run `gfm --init` in the root of the project.
|
|
60
|
+
- Subsequently, just type `gfm` each time you need to branch or merge (or add change log information), and follow the
|
|
61
|
+
dialog
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__="1.0.1"
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
import pystache
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Sections(Enum):
|
|
11
|
+
"""
|
|
12
|
+
Enumerator to define possible change log sections
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
added = "Added"
|
|
16
|
+
changed = "Changed"
|
|
17
|
+
fixed = "Fixed"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ChangeLog:
|
|
21
|
+
"""
|
|
22
|
+
A class to create a formatted markdown change log from a mustache template and the changes as json
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
file: str = "docs/source/change_log.rst",
|
|
28
|
+
template_file: str = "docs/source/change_log.tpl",
|
|
29
|
+
compare_url=None,
|
|
30
|
+
version_prefix: str = "",
|
|
31
|
+
):
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
:param file: File name of the change log file. Has to have the rst ending
|
|
35
|
+
:param template_file: File name of the change log template. Has to be in mustache format
|
|
36
|
+
:param compare_url: Git url that is used to compare commits/branches with each other. Mostly ends with /compare/
|
|
37
|
+
:param version_prefix: Optional prefix that will be added to the version string before creating the log data
|
|
38
|
+
"""
|
|
39
|
+
assert file.endswith(".rst"), 'Change log file name has to end with ".rst"'
|
|
40
|
+
self.file_name = file
|
|
41
|
+
self.data = {}
|
|
42
|
+
if not os.path.isfile(self.file_name.replace(".rst", ".json")):
|
|
43
|
+
self.create_empty_json()
|
|
44
|
+
if not os.path.isfile(template_file):
|
|
45
|
+
self.create_default_tpl(template_file)
|
|
46
|
+
self.read_json()
|
|
47
|
+
self.compare_url = compare_url
|
|
48
|
+
self.version_prefix = version_prefix
|
|
49
|
+
with open(template_file) as fh:
|
|
50
|
+
self.template = fh.read()
|
|
51
|
+
self.renderer = pystache.Renderer()
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def create_default_tpl(template_file):
|
|
55
|
+
with open(template_file, "w") as fh:
|
|
56
|
+
fh.write(
|
|
57
|
+
"{{#general}}\n"
|
|
58
|
+
"{{{title}}}\n"
|
|
59
|
+
"------------------\n"
|
|
60
|
+
"{{{description}}}\n"
|
|
61
|
+
"{{/general}}\n\n"
|
|
62
|
+
"{{#versions}}\n"
|
|
63
|
+
"{{{version}}}\n"
|
|
64
|
+
"-------------\n"
|
|
65
|
+
"**Release Date:** {{{date}}}\n\n"
|
|
66
|
+
"{{#sections}}\n"
|
|
67
|
+
"{{{label}}}\n"
|
|
68
|
+
"~~~~~~~~~~~~~\n"
|
|
69
|
+
"{{#entries}}\n"
|
|
70
|
+
"- {{{message}}} [{{{author}}}]\n"
|
|
71
|
+
"{{/entries}}\n\n"
|
|
72
|
+
"{{/sections}}\n"
|
|
73
|
+
"{{/versions}}\n\n"
|
|
74
|
+
"Changes comparison\n"
|
|
75
|
+
"------------------\n"
|
|
76
|
+
"{{#version_comparison}}\n"
|
|
77
|
+
"- **[{{version}}]**: `<{{{url}}}>`_\n"
|
|
78
|
+
"{{/version_comparison}}\n"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def create_empty_json(self):
|
|
82
|
+
json_path = self.file_name.replace(".rst", ".json")
|
|
83
|
+
os.makedirs(os.path.dirname(json_path), exist_ok=True)
|
|
84
|
+
with open(json_path, "w") as fh:
|
|
85
|
+
json.dump({"versions": []}, fh, indent=4)
|
|
86
|
+
|
|
87
|
+
def read_json(self):
|
|
88
|
+
"""
|
|
89
|
+
Read JSON data from a file and ensure version info is sorted in descending date order.
|
|
90
|
+
|
|
91
|
+
"""
|
|
92
|
+
with open(self.file_name.replace(".rst", ".json")) as fh:
|
|
93
|
+
data = json.load(fh)
|
|
94
|
+
# assert version info sorted in descending date order
|
|
95
|
+
data["versions"] = sorted(
|
|
96
|
+
data["versions"],
|
|
97
|
+
key=lambda x: x["date"] if x["date"] != "" else "Z",
|
|
98
|
+
reverse=True,
|
|
99
|
+
)
|
|
100
|
+
self.data = data
|
|
101
|
+
|
|
102
|
+
def write_json(self):
|
|
103
|
+
with open(self.file_name.replace(".rst", ".json"), "w") as fh:
|
|
104
|
+
json.dump(self.data, fh, indent=4)
|
|
105
|
+
|
|
106
|
+
def get_version(self, version: str) -> None | dict:
|
|
107
|
+
"""
|
|
108
|
+
Returns a copy of the change log for the requested version
|
|
109
|
+
|
|
110
|
+
:param version: The requested version as string
|
|
111
|
+
:return: The version's change log as dict
|
|
112
|
+
"""
|
|
113
|
+
for version_dict in self.data["versions"]:
|
|
114
|
+
if version_dict["version"] == self.version_prefix + version:
|
|
115
|
+
return deepcopy(version_dict)
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def ask_for_changes(user: str, sections: list[Sections], app_specific_changes, app_specific_text) -> list:
|
|
120
|
+
"""
|
|
121
|
+
This method asks interactively for changes and returns a section list ready to be handed over to ChangeLog
|
|
122
|
+
|
|
123
|
+
:param user: Name of the user, who did the changes. Should be the git user name if possible
|
|
124
|
+
:param sections: A list of sections that should be added
|
|
125
|
+
:param app_specific_changes:
|
|
126
|
+
:param app_specific_text:
|
|
127
|
+
:return: A list of sections and changes to add into ChangeLog.
|
|
128
|
+
"""
|
|
129
|
+
section_list = []
|
|
130
|
+
for section in sections:
|
|
131
|
+
assert isinstance(section, Sections), 'List entries have to be values from the Enum "Sections"!'
|
|
132
|
+
sec_string = section.value
|
|
133
|
+
entries = []
|
|
134
|
+
while True:
|
|
135
|
+
if not app_specific_changes:
|
|
136
|
+
answer = input(
|
|
137
|
+
f"Any (more) changes to document for section \n'{sec_string}'\n? "
|
|
138
|
+
f"(Type the change or enter nothing for continuing)\n"
|
|
139
|
+
)
|
|
140
|
+
else:
|
|
141
|
+
app_specific_text = app_specific_text.format(sec_string)
|
|
142
|
+
answer = input(app_specific_text)
|
|
143
|
+
if answer == "":
|
|
144
|
+
break
|
|
145
|
+
else:
|
|
146
|
+
entries.append({"author": user, "message": answer})
|
|
147
|
+
if entries:
|
|
148
|
+
section_list.append({"label": sec_string, "entries": entries})
|
|
149
|
+
return section_list
|
|
150
|
+
|
|
151
|
+
@staticmethod
|
|
152
|
+
def _add_sections(version_dict: dict, sections: dict) -> dict:
|
|
153
|
+
"""
|
|
154
|
+
Add sections and their entries to an existing version dictionary.
|
|
155
|
+
|
|
156
|
+
:param version_dict: The versions as a dictionary to which sections and entries will be added.
|
|
157
|
+
:param sections: A dictionary containing sections and their entries to be added to the versions.
|
|
158
|
+
:return: The updated version dictionary with sections and entries.
|
|
159
|
+
"""
|
|
160
|
+
label_dict = {}
|
|
161
|
+
for n, section in enumerate(version_dict["sections"]):
|
|
162
|
+
label_dict[section["label"]] = n
|
|
163
|
+
for section in sections:
|
|
164
|
+
label = section["label"]
|
|
165
|
+
if label not in label_dict:
|
|
166
|
+
# create section
|
|
167
|
+
version_dict["sections"].append({"label": label, "entries": []})
|
|
168
|
+
label_dict[label] = len(version_dict["sections"]) - 1
|
|
169
|
+
# add all messages of unrel_dicts section to this section
|
|
170
|
+
version_dict["sections"][label_dict[label]]["entries"].extend(section["entries"])
|
|
171
|
+
return version_dict
|
|
172
|
+
|
|
173
|
+
def create_new_version(self, new_version: str, new_sections=None):
|
|
174
|
+
"""
|
|
175
|
+
Adds a new version to the change log
|
|
176
|
+
|
|
177
|
+
:param new_version: String of the new version, such as v0.5.2 . If the changes are still for an unreleased \
|
|
178
|
+
state, use None!
|
|
179
|
+
:param new_sections: A formatted list of new_sections, obtained from method ask_for_changes
|
|
180
|
+
"""
|
|
181
|
+
if new_version is None or new_version=="Unreleased":
|
|
182
|
+
new_version = "Unreleased"
|
|
183
|
+
else:
|
|
184
|
+
new_version = self.version_prefix + new_version
|
|
185
|
+
date_ = datetime.now().strftime("%Y-%m-%d %H:%M") if new_version != "Unreleased" else ""
|
|
186
|
+
|
|
187
|
+
found = False
|
|
188
|
+
# search for existing version with same string (forbidden) or Unreleased tag (will be moved into new version)
|
|
189
|
+
for version_dict in self.data["versions"]:
|
|
190
|
+
# remember, self.data is a dict (i.e. mutable) so all changes directly apply to it
|
|
191
|
+
if version_dict["version"] == new_version and new_version != "Unreleased":
|
|
192
|
+
raise Exception(
|
|
193
|
+
f"Version {new_version} already exists! Use method add_to_version if you want to add "
|
|
194
|
+
f"sections to an existing version!"
|
|
195
|
+
)
|
|
196
|
+
elif version_dict["version"] == "Unreleased":
|
|
197
|
+
found = True
|
|
198
|
+
version_dict["version"] = new_version
|
|
199
|
+
version_dict["date"] = date_
|
|
200
|
+
if new_sections is not None:
|
|
201
|
+
# add new sections. No need to get result as dicts are mutable
|
|
202
|
+
self._add_sections(version_dict, new_sections)
|
|
203
|
+
|
|
204
|
+
if not found:
|
|
205
|
+
if new_sections is None:
|
|
206
|
+
raise Exception(
|
|
207
|
+
"No entry found for Unreleased version and no new version information added. "
|
|
208
|
+
"Adding empty new version is not allowed!"
|
|
209
|
+
)
|
|
210
|
+
else:
|
|
211
|
+
self.data["versions"].insert(0, {"version": new_version, "date": date_, "sections": new_sections})
|
|
212
|
+
|
|
213
|
+
# update the json file
|
|
214
|
+
self.write_json()
|
|
215
|
+
|
|
216
|
+
def add_to_version(self, version: str | None, new_sections):
|
|
217
|
+
"""
|
|
218
|
+
Adds change logs to an existing version
|
|
219
|
+
|
|
220
|
+
:param version: String of the version to add changes to, such as v0.5.2 . If the changes are still for an \
|
|
221
|
+
unreleased state, use None!
|
|
222
|
+
:param new_sections: A formatted list of new_sections, obtained from method ask_for_changes
|
|
223
|
+
"""
|
|
224
|
+
if version is None or version=="Unreleased":
|
|
225
|
+
version = "Unreleased"
|
|
226
|
+
else:
|
|
227
|
+
version = self.version_prefix + version
|
|
228
|
+
found = False
|
|
229
|
+
for version_dict in self.data["versions"]:
|
|
230
|
+
# remember, self.data is a dict (i.e. mutable) so all changes directly apply to it
|
|
231
|
+
if version_dict["version"] == version:
|
|
232
|
+
found = True
|
|
233
|
+
# add new sections. No need to get result as dicts are mutable
|
|
234
|
+
self._add_sections(version_dict, new_sections)
|
|
235
|
+
|
|
236
|
+
if not found:
|
|
237
|
+
if version == "Unreleased":
|
|
238
|
+
self.create_new_version(new_version=version, new_sections=new_sections)
|
|
239
|
+
else:
|
|
240
|
+
raise Exception(
|
|
241
|
+
f"No entry found for version {version}! If you want to create a new version, use method "
|
|
242
|
+
"create_new_version!"
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# update the json file
|
|
246
|
+
self.write_json()
|
|
247
|
+
|
|
248
|
+
def _add_branch_comparison(self, data: dict):
|
|
249
|
+
"""
|
|
250
|
+
Add a list of comparisons between commits/branches in data dictionary.
|
|
251
|
+
:param data: The dictionary to which the comparison info will be added, also contains the version info
|
|
252
|
+
:return: The updated data dictionary with branch comparison information.
|
|
253
|
+
"""
|
|
254
|
+
if self.compare_url is not None:
|
|
255
|
+
if "version_comparison" in data:
|
|
256
|
+
data.pop("version_comparison")
|
|
257
|
+
# assumes the dict is ordered by date!!
|
|
258
|
+
newer_version = None
|
|
259
|
+
comparison_list = []
|
|
260
|
+
for version_dict in data["versions"]:
|
|
261
|
+
if newer_version is None:
|
|
262
|
+
newer_version = version_dict["version"]
|
|
263
|
+
else:
|
|
264
|
+
comparison_list.append(
|
|
265
|
+
{
|
|
266
|
+
"version": newer_version,
|
|
267
|
+
"url": f"{self.compare_url}/diff?targetBranch=tags/{version_dict['version']}&sourceBranch="
|
|
268
|
+
f"{'tags/'+newer_version if newer_version != 'Unreleased' else 'heads/dev'}",
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
data["version_comparison"] = comparison_list
|
|
272
|
+
return data
|
|
273
|
+
|
|
274
|
+
def write_log(self):
|
|
275
|
+
"""
|
|
276
|
+
Write changes to the ChangeLog file.
|
|
277
|
+
"""
|
|
278
|
+
extended_data = self._add_branch_comparison(self.data)
|
|
279
|
+
with open(self.file_name, "w") as fh:
|
|
280
|
+
fh.write(self.renderer.render(self.template, extended_data))
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import toml
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def read_file(path: str):
|
|
5
|
+
"""Read a file and return the content.
|
|
6
|
+
|
|
7
|
+
:param path: _description_
|
|
8
|
+
:type path: str
|
|
9
|
+
"""
|
|
10
|
+
with open(path, encoding="utf8") as file:
|
|
11
|
+
file_content = file.read()
|
|
12
|
+
return file_content
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def write_to_file(path: str, content):
|
|
16
|
+
"""Write given content to the path.
|
|
17
|
+
|
|
18
|
+
:param path: _description_
|
|
19
|
+
:type path: str
|
|
20
|
+
:param content: _description_
|
|
21
|
+
:type content: _type_
|
|
22
|
+
"""
|
|
23
|
+
with open(path, "w", encoding="utf8") as fhh:
|
|
24
|
+
fhh.write(content)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def read_toml(path):
|
|
28
|
+
with open(path, encoding="utf8") as file:
|
|
29
|
+
content = toml.load(file)
|
|
30
|
+
return content
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def write_to_toml(path: str, content):
|
|
34
|
+
with open(path, "w", encoding="utf8") as file:
|
|
35
|
+
toml.dump(content, file)
|