tgit 0.5.2__tar.gz → 0.7.0__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.
@@ -3,3 +3,4 @@ dist
3
3
  *.egg-info
4
4
  *.egg
5
5
  __pycache__
6
+ .DS_Store
@@ -1,8 +1,4 @@
1
1
  {
2
- "black-formatter.args": [
3
- "--line-length",
4
- "160"
5
- ],
6
2
  "[python]": {
7
3
  "editor.defaultFormatter": "ms-python.black-formatter",
8
4
  "editor.formatOnSave": true,
@@ -0,0 +1,135 @@
1
+ ## v0.6.1
2
+
3
+ [v0.6.0...v0.6.1](https://github.com/Jannchie/tgit/compare/v0.6.0...v0.6.1)
4
+
5
+ ### :adhesive_bandage: Fixes
6
+
7
+ - **changelog**: simplify sort by scope logic and validate diff before AI command - By [Jannchie](mailto:panjianqi@preferred.jp) in [32dd4e3](https://github.com/Jannchie/tgit/commit/32dd4e3)
8
+
9
+ ### :wrench: Chores
10
+
11
+ - update gitignore, vscode settings, and pyproject.toml - By [Jannchie](mailto:panjianqi@preferred.jp) in [103271e](https://github.com/Jannchie/tgit/commit/103271e)
12
+
13
+ ## v0.6.0
14
+
15
+ [v0.5.2...v0.6.0](https://github.com/Jannchie/tgit/compare/v0.5.2...v0.6.0)
16
+
17
+ ### :sparkles: Features
18
+
19
+ - **version**: introduce auto-detection of version bump based on commit types - By [Jannchie](mailto:panjianqi@preferred.jp) in [910107f](https://github.com/Jannchie/tgit/commit/910107f)
20
+
21
+ ### :art: Refactors
22
+
23
+ - extract git commit range logic into separate function for better readability - By [Jannchie](mailto:panjianqi@preferred.jp) in [44f9c94](https://github.com/Jannchie/tgit/commit/44f9c94)
24
+
25
+ ## v0.5.2
26
+
27
+ [v0.5.1...v0.5.2](https://github.com/Jannchie/tgit/compare/v0.5.1...v0.5.2)
28
+
29
+ ### :adhesive_bandage: Fixes
30
+
31
+ - **commit**: correct commit message formatting and emoji usage - By [Jannchie](mailto:panjianqi@preferred.jp) in [34b58a9](https://github.com/Jannchie/tgit/commit/34b58a9)
32
+
33
+ ## v0.5.1
34
+
35
+ [v0.5.0...v0.5.1](https://github.com/Jannchie/tgit/compare/v0.5.0...v0.5.1)
36
+
37
+ ### :sparkles: Features
38
+
39
+ - **commit**: add rich print for missing commit message - By [Jannchie](mailto:panjianqi@preferred.jp) in [686cf4a](https://github.com/Jannchie/tgit/commit/686cf4a)
40
+
41
+ ## v0.5.0
42
+
43
+ [v0.4.3...v0.5.0](https://github.com/Jannchie/tgit/compare/v0.4.3...v0.5.0)
44
+
45
+ ### :sparkles: Features
46
+
47
+ - **tgit**: add ai-powered commit message suggestion using openai - By [Jannchie](mailto:panjianqi@preferred.jp) in [93299f1](https://github.com/Jannchie/tgit/commit/93299f1)
48
+
49
+ ## v0.4.3
50
+
51
+ [v0.4.2...v0.4.3](https://github.com/Jannchie/tgit/compare/v0.4.2...v0.4.3)
52
+
53
+ ### :art: Refactors
54
+
55
+ - **version**: make the code clearer - By [Jianqi Pan](mailto:jannchie@gmail.com) in [68d626e](https://github.com/Jannchie/tgit/commit/68d626e)
56
+
57
+ ### :memo: Documentation
58
+
59
+ - add codetime badge - By [Jianqi Pan](mailto:jannchie@gmail.com) in [984b9d3](https://github.com/Jannchie/tgit/commit/984b9d3)
60
+
61
+ ## v0.4.2
62
+
63
+ [v0.4.1...v0.4.2](https://github.com/Jannchie/tgit/compare/v0.4.1...v0.4.2)
64
+
65
+ ### :adhesive_bandage: Fixes
66
+
67
+ - **depeendencies**: need python 3.11 because of tomllib - By [Jianqi Pan](mailto:jannchie@gmail.com) in [d7b3c0a](https://github.com/Jannchie/tgit/commit/d7b3c0a)
68
+
69
+ ## v0.4.1
70
+
71
+ [v0.4.0...v0.4.1](https://github.com/Jannchie/tgit/compare/v0.4.0...v0.4.1)
72
+
73
+ ### :adhesive_bandage: Fixes
74
+
75
+ - **depeendencies**: add gitpython as dependencies - By [Jianqi Pan](mailto:jannchie@gmail.com) in [51bbcb1](https://github.com/Jannchie/tgit/commit/51bbcb1)
76
+
77
+ ## v0.4.0
78
+
79
+ [v0.3.0...v0.4.0](https://github.com/Jannchie/tgit/compare/v0.3.0...v0.4.0)
80
+
81
+ ### :sparkles: Features
82
+
83
+ - **changelog**: implement basic changelog features - By [Jianqi Pan](mailto:jannchie@gmail.com) in [cf623c6](https://github.com/Jannchie/tgit/commit/cf623c6)
84
+
85
+ ### :adhesive_bandage: Fixes
86
+
87
+ - **changelog**: check whether the latest commit has a tag - By [Jianqi Pan](mailto:jannchie@gmail.com) in [310a306](https://github.com/Jannchie/tgit/commit/310a306)
88
+
89
+ ### :memo: Documentation
90
+
91
+ - add readme - By [Jianqi Pan](mailto:jannchie@gmail.com) in [1b31cbf](https://github.com/Jannchie/tgit/commit/1b31cbf)
92
+
93
+ ### :wrench: Chores
94
+
95
+ - **build**: use poetry - By [Jianqi Pan](mailto:jannchie@gmail.com) in [656de25](https://github.com/Jannchie/tgit/commit/656de25)
96
+ - **version**: clean the useless code - By [Jianqi Pan](mailto:jannchie@gmail.com) in [0c24d69](https://github.com/Jannchie/tgit/commit/0c24d69)
97
+
98
+ ## v0.3.0
99
+
100
+ [v0.2.2...v0.3.0](https://github.com/Jannchie/tgit/compare/v0.2.2...v0.3.0)
101
+
102
+ ### :sparkles: Features
103
+
104
+ - **version**: update more version files - By [Jianqi Pan](mailto:jannchie@gmail.com) in [3a87374](https://github.com/Jannchie/tgit/commit/3a87374)
105
+ - add gitt as a alias - By [Jianqi Pan](mailto:jannchie@gmail.com) in [bacd8fe](https://github.com/Jannchie/tgit/commit/bacd8fe)
106
+
107
+ ### :wrench: Chores
108
+
109
+ - **commit**: do not show type choices because they are too long - By [Jianqi Pan](mailto:jannchie@gmail.com) in [886ed07](https://github.com/Jannchie/tgit/commit/886ed07)
110
+ - **scripts**: update build script - By [Jianqi Pan](mailto:jannchie@gmail.com) in [89702cd](https://github.com/Jannchie/tgit/commit/89702cd)
111
+
112
+ ## v0.2.2
113
+
114
+ [v0.2.1...v0.2.2](https://github.com/Jannchie/tgit/compare/v0.2.1...v0.2.2)
115
+
116
+ ### :adhesive_bandage: Fixes
117
+
118
+ - **commit**: add tag - By [Jianqi Pan](mailto:jannchie@gmail.com) in [8ea1e80](https://github.com/Jannchie/tgit/commit/8ea1e80)
119
+
120
+ ## v0.2.1
121
+
122
+ [0c6d5b32aad9f01678b114120e7530dfebf4fb85...v0.2.1](https://github.com/Jannchie/tgit/compare/0c6d5b32aad9f01678b114120e7530dfebf4fb85...v0.2.1)
123
+
124
+ ### :sparkles: Features
125
+
126
+ - **commit**: enable emoji settings - By [Jianqi Pan](mailto:jannchie@gmail.com) in [6acd0dc](https://github.com/Jannchie/tgit/commit/6acd0dc)
127
+ - **version**: detect version from file or git tags - By [Jianqi Pan](mailto:jannchie@gmail.com) in [5b4d4aa](https://github.com/Jannchie/tgit/commit/5b4d4aa)
128
+
129
+ ### :adhesive_bandage: Fixes
130
+
131
+ - **commit**: push tag - By [Jianqi Pan](mailto:jannchie@gmail.com) in [35c96a8](https://github.com/Jannchie/tgit/commit/35c96a8)
132
+
133
+ ### :wrench: Chores
134
+
135
+ - **format**: use sourcery - By [Jianqi Pan](mailto:jannchie@gmail.com) in [03f2078](https://github.com/Jannchie/tgit/commit/03f2078)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: tgit
3
- Version: 0.5.2
3
+ Version: 0.7.0
4
4
  Summary: Tool for Git Interaction Temptation (tgit): An elegant CLI tool that simplifies and streamlines your Git workflow, making version control a breeze.
5
5
  Author-email: Jannchie <jannchie@gmail.com>
6
6
  License-Expression: MIT
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Topic :: Software Development :: Version Control
13
13
  Classifier: Topic :: Utilities
14
14
  Classifier: Typing :: Typed
15
- Requires-Python: >=3.8
15
+ Requires-Python: >=3.11
16
16
  Requires-Dist: gitpython
17
17
  Requires-Dist: inquirer
18
18
  Requires-Dist: openai>=1.51.0
@@ -1,17 +1,11 @@
1
1
  [project]
2
2
  name = "tgit"
3
- version = "0.5.2"
3
+ version = "0.7.0"
4
4
  description = "Tool for Git Interaction Temptation (tgit): An elegant CLI tool that simplifies and streamlines your Git workflow, making version control a breeze."
5
5
  authors = [{ name = "Jannchie", email = "jannchie@gmail.com" }]
6
- dependencies = [
7
- "rich",
8
- "PyYAML",
9
- "inquirer",
10
- "gitpython",
11
- "openai>=1.51.0",
12
- ]
6
+ dependencies = ["rich", "PyYAML", "inquirer", "gitpython", "openai>=1.51.0"]
13
7
  readme = "README.md"
14
- requires-python = ">= 3.8"
8
+ requires-python = ">= 3.11"
15
9
  classifiers = [
16
10
  "Development Status :: 3 - Alpha",
17
11
  "Intended Audience :: Developers",
@@ -30,7 +24,10 @@ build-backend = "hatchling.build"
30
24
 
31
25
  [tool.rye]
32
26
  managed = true
33
- dev-dependencies = []
27
+ dev-dependencies = ["black>=24.8.0", "isort>=5.13.2"]
28
+
29
+ [tool.black]
30
+ line-length = 160
34
31
 
35
32
  [tool.hatch.metadata]
36
33
  allow-direct-references = true
@@ -38,6 +35,5 @@ allow-direct-references = true
38
35
  [tool.hatch.build.targets.wheel]
39
36
  packages = ["tgit"]
40
37
 
41
-
42
38
  [project.scripts]
43
39
  tgit = "tgit:cli.main"
@@ -15,11 +15,14 @@ annotated-types==0.7.0
15
15
  anyio==4.6.0
16
16
  # via httpx
17
17
  # via openai
18
+ black==24.8.0
18
19
  blessed==1.20.0
19
20
  # via inquirer
20
21
  certifi==2024.8.30
21
22
  # via httpcore
22
23
  # via httpx
24
+ click==8.1.7
25
+ # via black
23
26
  distro==1.9.0
24
27
  # via openai
25
28
  editor==1.6.6
@@ -39,14 +42,23 @@ idna==3.10
39
42
  # via httpx
40
43
  inquirer==3.4.0
41
44
  # via tgit
45
+ isort==5.13.2
42
46
  jiter==0.5.0
43
47
  # via openai
44
48
  markdown-it-py==3.0.0
45
49
  # via rich
46
50
  mdurl==0.1.2
47
51
  # via markdown-it-py
52
+ mypy-extensions==1.0.0
53
+ # via black
48
54
  openai==1.51.0
49
55
  # via tgit
56
+ packaging==24.1
57
+ # via black
58
+ pathspec==0.12.1
59
+ # via black
60
+ platformdirs==4.3.6
61
+ # via black
50
62
  pydantic==2.9.2
51
63
  # via openai
52
64
  pydantic-core==2.23.4
@@ -41,6 +41,16 @@ def define_changelog_parser(subparsers):
41
41
  parser_changelog.add_argument("-f", "--from", help="From hash/tag", type=str, dest="from_raw")
42
42
  parser_changelog.add_argument("-t", "--to", help="To hash/tag", type=str, dest="to_raw")
43
43
  parser_changelog.add_argument("-v", "--verbose", action="count", default=0, help="increase output verbosity", dest="verbose")
44
+ parser_changelog.add_argument(
45
+ "-o",
46
+ "--output",
47
+ help="output file",
48
+ type=str,
49
+ dest="output",
50
+ nargs="?", # 表示参数值是可选的
51
+ const="CHANGELOG.md",
52
+ default=None,
53
+ )
44
54
  parser_changelog.add_argument("path", help="repository path", type=str, nargs="?", default=".")
45
55
  parser_changelog.set_defaults(func=handle_changelog)
46
56
 
@@ -51,6 +61,7 @@ class ChangelogArgs:
51
61
  to_raw: str
52
62
  verbose: int
53
63
  path: str
64
+ output: str
54
65
 
55
66
 
56
67
  def get_simple_hash(repo: git.Repo, hash, length=7):
@@ -202,7 +213,7 @@ def generate_changelog(commits_by_type: dict[str, list[TGITCommit]], from_ref: s
202
213
  title = f"### {names[i]}\n\n"
203
214
  out_str += title
204
215
  # Sort commits by scope, if scope is None, put it to last
205
- commits.sort(key=lambda c: "zzzzz" if c.scope is None else c.scope)
216
+ commits.sort(key=lambda c: c.scope or "zzzzz")
206
217
  for commit in commits:
207
218
 
208
219
  authors_str = format_names([f"[{a.name}](mailto:{a.email})" for a in commit.authors])
@@ -217,22 +228,32 @@ def generate_changelog(commits_by_type: dict[str, list[TGITCommit]], from_ref: s
217
228
 
218
229
  def handle_changelog(args: ChangelogArgs):
219
230
  repo = git.Repo(args.path)
220
- from_ref = resolve_from_ref(repo, args.from_raw)
221
- to_ref = "HEAD" if args.to_raw is None else args.to_raw
222
- if to_ref == "HEAD":
223
- latest_commit = repo.head.commit
231
+
232
+ if args.output:
233
+ output_file = open(args.output, "w")
234
+ # 获取所有 tags
224
235
  tags = repo.tags
225
- latest_commit_tags = [tag for tag in tags if tag.commit == latest_commit]
226
- if latest_commit_tags:
227
- to_ref = from_ref
228
- from_ref = get_tag_by_idx(repo, -2)
229
- if from_ref is None:
230
- from_ref = get_first_commit_hash(repo)
231
- else:
232
- warnings.warn("HEAD is not a tag, changelog will be generated from the last tag to HEAD.")
233
- from_hash = ref_to_hash(repo, from_ref)
234
- to_hash = ref_to_hash(repo, to_ref)
236
+ # 获取第一个 commit
237
+ first_commit = get_first_commit_hash(repo)
238
+ points = [first_commit] + [tag.name for tag in tags]
239
+ points.reverse()
240
+ changelogs = ""
241
+ for i in range(len(points) - 1):
242
+ to_ref = points[i]
243
+ from_ref = points[i + 1]
244
+ changelog = get_changelog_by_range(repo, from_ref, to_ref)
245
+ changelogs += changelog
246
+ output_file.write(changelogs.strip("\n") + "\n")
247
+ from_raw = args.from_raw
248
+ to_raw = args.to_raw
249
+
250
+ from_ref, to_ref = get_git_commits_range(repo, from_raw, to_raw)
251
+ changelog = get_changelog_by_range(repo, from_ref, to_ref)
252
+ print()
253
+ print(changelog)
254
+
235
255
 
256
+ def get_changelog_by_range(repo: git.Repo, from_ref: str, to_ref: str):
236
257
  try:
237
258
  origin_url = repo.remote().url
238
259
  remote_uri = get_remote_uri(origin_url)
@@ -240,8 +261,22 @@ def handle_changelog(args: ChangelogArgs):
240
261
  warnings.warn("Origin not found, some of the link generation functions could not be enabled.")
241
262
  remote_uri = None
242
263
 
243
- tgit_commits = get_commits(repo, from_hash, to_hash)
264
+ tgit_commits = get_commits(repo, from_ref, to_ref)
244
265
  commits_by_type = group_commits_by_type(tgit_commits)
245
- changelog = generate_changelog(commits_by_type, from_ref, to_ref, remote_uri)
246
- print()
247
- print(changelog)
266
+ return generate_changelog(commits_by_type, from_ref, to_ref, remote_uri)
267
+
268
+
269
+ def get_git_commits_range(repo: git.Repo, from_raw: str, to_raw: str):
270
+ from_ref = resolve_from_ref(repo, from_raw)
271
+ to_ref = "HEAD" if to_raw is None else to_raw
272
+ if to_ref == "HEAD":
273
+ latest_commit = repo.head.commit
274
+ tags = repo.tags
275
+ latest_commit_tags = [tag for tag in tags if tag.commit == latest_commit]
276
+ if latest_commit_tags:
277
+ to_ref = from_ref
278
+ from_ref = get_tag_by_idx(repo, -2)
279
+ if from_ref is None:
280
+ from_ref = get_first_commit_hash(repo)
281
+
282
+ return from_ref, to_ref
@@ -51,12 +51,15 @@ class CommitData(BaseModel):
51
51
  is_breaking: bool
52
52
 
53
53
 
54
- def get_ai_command():
54
+ def get_ai_command() -> str | None:
55
55
  client = OpenAI()
56
56
  # 获取用户执行该脚本所在的目录
57
57
  current_dir = os.getcwd()
58
58
  repo = git.Repo(current_dir, search_parent_directories=True)
59
- diff = repo.git.diff("HEAD")
59
+ diff = repo.git.diff("--cached")
60
+ if not diff:
61
+ print("[yellow]No changes to commit, please add some changes before using AI[/yellow]")
62
+ return
60
63
  types = "|".join(commit_type)
61
64
  chat_completion = client.beta.chat.completions.parse(
62
65
  messages=[
@@ -82,6 +85,8 @@ def handle_commit(args: CommitArgs):
82
85
 
83
86
  if args.ai:
84
87
  command = get_ai_command()
88
+ if not command:
89
+ return
85
90
  else:
86
91
  messages = args.message
87
92
  if len(messages) == 0:
@@ -7,9 +7,11 @@ from dataclasses import dataclass
7
7
  from difflib import Differ
8
8
  from typing import Optional
9
9
 
10
+ import git
10
11
  import inquirer
11
12
  from rich.panel import Panel
12
13
 
14
+ from tgit.changelog import get_commits, get_git_commits_range, group_commits_by_type
13
15
  from tgit.settings import settings
14
16
  from tgit.utils import console, get_commit_command, run_command
15
17
 
@@ -123,13 +125,22 @@ def get_prev_version():
123
125
  return Version(major=0, minor=0, patch=0)
124
126
 
125
127
 
128
+ def get_default_bump_by_commits_dict(commits_by_type: dict[str, list[git.Commit]]) -> str:
129
+ if commits_by_type.get("breaking"):
130
+ return "major"
131
+ elif commits_by_type.get("feat"):
132
+ return "minor"
133
+ return "patch"
134
+
135
+
126
136
  def handle_version(args: VersionArgs):
127
137
  verbose = args.verbose
128
138
 
129
- # 注释掉的部分
130
- # check_uncommitted_changes(verbose)
139
+ # if not check_uncommitted_changes(verbose):
140
+ # return
131
141
 
132
142
  prev_version = get_current_version(verbose)
143
+
133
144
  if next_version := get_next_version(args, prev_version, verbose):
134
145
  update_version_files(next_version, verbose)
135
146
  execute_git_commands(args, next_version, verbose)
@@ -158,16 +169,27 @@ def get_current_version(verbose: int) -> Optional[Version]:
158
169
 
159
170
 
160
171
  def get_next_version(args, prev_version, verbose):
172
+
173
+ repo = git.Repo(os.getcwd())
174
+ from_ref, to_ref = get_git_commits_range(repo, None, None)
175
+ tgit_commits = get_commits(repo, from_ref, to_ref)
176
+ commits_by_type = group_commits_by_type(tgit_commits)
177
+ default_bump = get_default_bump_by_commits_dict(commits_by_type)
178
+
179
+ choices = [VersionChoice(prev_version, bump) for bump in ["patch", "minor", "major", "prepatch", "preminor", "premajor", "previous", "custom"]]
180
+ default_choice = next((choice for choice in choices if choice.bump == default_bump), None)
161
181
  next_version = deepcopy(prev_version)
182
+
183
+ console.print(f"Auto bump based on commits: [cyan bold]{default_bump}")
184
+
162
185
  if not any([args.version, args.patch, args.minor, args.major, args.prepatch, args.preminor, args.premajor]):
163
186
  ans = inquirer.prompt(
164
187
  [
165
188
  inquirer.List(
166
189
  "target",
167
190
  message="Select the version to bump to",
168
- choices=[
169
- VersionChoice(prev_version, bump) for bump in ["patch", "minor", "major", "prepatch", "preminor", "premajor", "previous", "custom"]
170
- ],
191
+ choices=choices,
192
+ default=default_choice,
171
193
  carousel=True,
172
194
  ),
173
195
  ]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes