jarvis-ai-assistant 0.1.193__py3-none-any.whl → 0.1.195__py3-none-any.whl
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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +45 -41
- jarvis/jarvis_agent/builtin_input_handler.py +26 -4
- jarvis/jarvis_agent/jarvis.py +30 -19
- jarvis/jarvis_agent/main.py +20 -12
- jarvis/jarvis_agent/output_handler.py +7 -7
- jarvis/jarvis_agent/shell_input_handler.py +14 -11
- jarvis/jarvis_code_agent/code_agent.py +81 -79
- jarvis/jarvis_code_agent/lint.py +92 -105
- jarvis/jarvis_code_analysis/checklists/__init__.py +1 -1
- jarvis/jarvis_code_analysis/checklists/c_cpp.py +1 -1
- jarvis/jarvis_code_analysis/checklists/csharp.py +1 -1
- jarvis/jarvis_code_analysis/checklists/data_format.py +1 -1
- jarvis/jarvis_code_analysis/checklists/devops.py +1 -1
- jarvis/jarvis_code_analysis/checklists/docs.py +1 -1
- jarvis/jarvis_code_analysis/checklists/go.py +1 -1
- jarvis/jarvis_code_analysis/checklists/infrastructure.py +1 -1
- jarvis/jarvis_code_analysis/checklists/java.py +1 -1
- jarvis/jarvis_code_analysis/checklists/javascript.py +1 -1
- jarvis/jarvis_code_analysis/checklists/kotlin.py +1 -1
- jarvis/jarvis_code_analysis/checklists/loader.py +31 -29
- jarvis/jarvis_code_analysis/checklists/php.py +1 -1
- jarvis/jarvis_code_analysis/checklists/python.py +1 -1
- jarvis/jarvis_code_analysis/checklists/ruby.py +1 -1
- jarvis/jarvis_code_analysis/checklists/rust.py +1 -1
- jarvis/jarvis_code_analysis/checklists/shell.py +1 -1
- jarvis/jarvis_code_analysis/checklists/sql.py +1 -1
- jarvis/jarvis_code_analysis/checklists/swift.py +1 -1
- jarvis/jarvis_code_analysis/checklists/web.py +1 -1
- jarvis/jarvis_code_analysis/code_review.py +292 -190
- jarvis/jarvis_dev/main.py +73 -56
- jarvis/jarvis_git_details/main.py +29 -33
- jarvis/jarvis_git_squash/main.py +13 -11
- jarvis/jarvis_git_utils/git_commiter.py +15 -5
- jarvis/jarvis_mcp/__init__.py +8 -10
- jarvis/jarvis_mcp/sse_mcp_client.py +182 -205
- jarvis/jarvis_mcp/stdio_mcp_client.py +93 -120
- jarvis/jarvis_mcp/streamable_mcp_client.py +117 -142
- jarvis/jarvis_methodology/main.py +71 -39
- jarvis/jarvis_multi_agent/__init__.py +24 -16
- jarvis/jarvis_multi_agent/main.py +10 -4
- jarvis/jarvis_platform/__init__.py +1 -1
- jarvis/jarvis_platform/base.py +44 -18
- jarvis/jarvis_platform/human.py +15 -3
- jarvis/jarvis_platform/kimi.py +117 -81
- jarvis/jarvis_platform/openai.py +23 -28
- jarvis/jarvis_platform/registry.py +43 -29
- jarvis/jarvis_platform/tongyi.py +16 -10
- jarvis/jarvis_platform/yuanbao.py +197 -144
- jarvis/jarvis_platform_manager/main.py +4 -2
- jarvis/jarvis_smart_shell/main.py +35 -30
- jarvis/jarvis_tools/ask_user.py +8 -16
- jarvis/jarvis_tools/base.py +3 -2
- jarvis/jarvis_tools/chdir.py +7 -19
- jarvis/jarvis_tools/cli/main.py +14 -10
- jarvis/jarvis_tools/code_plan.py +10 -31
- jarvis/jarvis_tools/create_code_agent.py +6 -11
- jarvis/jarvis_tools/create_sub_agent.py +10 -22
- jarvis/jarvis_tools/edit_file.py +98 -76
- jarvis/jarvis_tools/execute_script.py +46 -46
- jarvis/jarvis_tools/file_analyzer.py +22 -34
- jarvis/jarvis_tools/file_operation.py +69 -62
- jarvis/jarvis_tools/generate_new_tool.py +0 -2
- jarvis/jarvis_tools/methodology.py +19 -23
- jarvis/jarvis_tools/read_code.py +35 -35
- jarvis/jarvis_tools/read_webpage.py +7 -16
- jarvis/jarvis_tools/registry.py +63 -30
- jarvis/jarvis_tools/rewrite_file.py +26 -29
- jarvis/jarvis_tools/search_web.py +5 -8
- jarvis/jarvis_tools/virtual_tty.py +133 -122
- jarvis/jarvis_utils/__init__.py +0 -1
- jarvis/jarvis_utils/builtin_replace_map.py +9 -9
- jarvis/jarvis_utils/config.py +60 -37
- jarvis/jarvis_utils/embedding.py +24 -19
- jarvis/jarvis_utils/file_processors.py +16 -9
- jarvis/jarvis_utils/git_utils.py +157 -107
- jarvis/jarvis_utils/globals.py +1 -1
- jarvis/jarvis_utils/input.py +85 -52
- jarvis/jarvis_utils/jarvis_history.py +43 -0
- jarvis/jarvis_utils/methodology.py +31 -24
- jarvis/jarvis_utils/output.py +164 -80
- jarvis/jarvis_utils/tag.py +2 -1
- jarvis/jarvis_utils/utils.py +84 -52
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/METADATA +362 -230
- jarvis_ai_assistant-0.1.195.dist-info/RECORD +98 -0
- jarvis/jarvis_agent/file_input_handler.py +0 -112
- jarvis/jarvis_event/__init__.py +0 -0
- jarvis_ai_assistant-0.1.193.dist-info/RECORD +0 -99
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/top_level.txt +0 -0
jarvis/jarvis_utils/git_utils.py
CHANGED
@@ -14,8 +14,7 @@ import re
|
|
14
14
|
import subprocess
|
15
15
|
from typing import Any, Dict, List, Tuple
|
16
16
|
|
17
|
-
from jarvis.jarvis_utils.config import
|
18
|
-
is_confirm_before_apply_patch)
|
17
|
+
from jarvis.jarvis_utils.config import get_auto_update, is_confirm_before_apply_patch
|
19
18
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
20
19
|
from jarvis.jarvis_utils.utils import user_confirm
|
21
20
|
|
@@ -42,29 +41,47 @@ def find_git_root(start_dir: str = ".") -> str:
|
|
42
41
|
git_root = os.path.abspath(".")
|
43
42
|
os.chdir(git_root)
|
44
43
|
return git_root
|
44
|
+
|
45
|
+
|
45
46
|
def has_uncommitted_changes() -> bool:
|
46
47
|
"""检查Git仓库中是否有未提交的更改
|
47
|
-
|
48
|
+
|
48
49
|
返回:
|
49
50
|
bool: 如果有未提交的更改返回True,否则返回False
|
50
51
|
"""
|
51
52
|
# 静默添加所有更改
|
52
|
-
subprocess.run(
|
53
|
+
subprocess.run(
|
54
|
+
["git", "add", "."], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
55
|
+
)
|
53
56
|
|
54
57
|
# 检查工作目录更改
|
55
|
-
working_changes =
|
56
|
-
|
57
|
-
|
58
|
+
working_changes = (
|
59
|
+
subprocess.run(
|
60
|
+
["git", "diff", "--exit-code"],
|
61
|
+
stdout=subprocess.DEVNULL,
|
62
|
+
stderr=subprocess.DEVNULL,
|
63
|
+
).returncode
|
64
|
+
!= 0
|
65
|
+
)
|
58
66
|
|
59
67
|
# 检查暂存区更改
|
60
|
-
staged_changes =
|
61
|
-
|
62
|
-
|
68
|
+
staged_changes = (
|
69
|
+
subprocess.run(
|
70
|
+
["git", "diff", "--cached", "--exit-code"],
|
71
|
+
stdout=subprocess.DEVNULL,
|
72
|
+
stderr=subprocess.DEVNULL,
|
73
|
+
).returncode
|
74
|
+
!= 0
|
75
|
+
)
|
63
76
|
|
64
77
|
# 静默重置更改
|
65
|
-
subprocess.run(
|
78
|
+
subprocess.run(
|
79
|
+
["git", "reset"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
80
|
+
)
|
66
81
|
|
67
82
|
return working_changes or staged_changes
|
83
|
+
|
84
|
+
|
68
85
|
def get_commits_between(start_hash: str, end_hash: str) -> List[Tuple[str, str]]:
|
69
86
|
"""获取两个提交哈希值之间的提交列表
|
70
87
|
|
@@ -78,103 +95,112 @@ def get_commits_between(start_hash: str, end_hash: str) -> List[Tuple[str, str]]
|
|
78
95
|
try:
|
79
96
|
# 使用git log和pretty格式获取哈希值和信息
|
80
97
|
result = subprocess.run(
|
81
|
-
[
|
98
|
+
["git", "log", f"{start_hash}..{end_hash}", "--pretty=format:%H|%s"],
|
82
99
|
stdout=subprocess.PIPE,
|
83
100
|
stderr=subprocess.PIPE,
|
84
|
-
text=False # 禁用自动文本解码
|
101
|
+
text=False, # 禁用自动文本解码
|
85
102
|
)
|
86
103
|
if result.returncode != 0:
|
87
|
-
error_msg = result.stderr.decode(
|
104
|
+
error_msg = result.stderr.decode("utf-8", errors="replace")
|
88
105
|
PrettyOutput.print(f"获取commit历史失败: {error_msg}", OutputType.ERROR)
|
89
106
|
return []
|
90
107
|
|
91
|
-
output = result.stdout.decode(
|
108
|
+
output = result.stdout.decode("utf-8", errors="replace")
|
92
109
|
commits = []
|
93
110
|
for line in output.splitlines():
|
94
|
-
if
|
95
|
-
commit_hash, message = line.split(
|
111
|
+
if "|" in line:
|
112
|
+
commit_hash, message = line.split("|", 1)
|
96
113
|
commits.append((commit_hash, message))
|
97
114
|
return commits
|
98
115
|
|
99
116
|
except Exception as e:
|
100
117
|
PrettyOutput.print(f"获取commit历史异常: {str(e)}", OutputType.ERROR)
|
101
118
|
return []
|
102
|
-
|
119
|
+
|
103
120
|
|
104
121
|
# 修改后的获取差异函数
|
105
122
|
|
106
123
|
|
107
124
|
def get_diff() -> str:
|
108
125
|
"""使用git获取工作区差异,包括修改和新增的文件内容
|
109
|
-
|
126
|
+
|
110
127
|
返回:
|
111
128
|
str: 差异内容或错误信息
|
112
129
|
"""
|
113
130
|
try:
|
114
|
-
#
|
115
|
-
subprocess.run(
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
['git', 'diff', 'HEAD'],
|
120
|
-
capture_output=True,
|
121
|
-
text=False,
|
122
|
-
check=True
|
131
|
+
# 检查是否为空仓库
|
132
|
+
head_check = subprocess.run(
|
133
|
+
["git", "rev-parse", "--verify", "HEAD"],
|
134
|
+
stderr=subprocess.PIPE,
|
135
|
+
stdout=subprocess.PIPE,
|
123
136
|
)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
137
|
+
if head_check.returncode != 0:
|
138
|
+
# 空仓库情况,直接获取工作区差异
|
139
|
+
result = subprocess.run(
|
140
|
+
["git", "diff"], capture_output=True, text=False, check=True
|
141
|
+
)
|
142
|
+
else:
|
143
|
+
# 暂存新增文件
|
144
|
+
subprocess.run(["git", "add", "-N", "."], check=True)
|
145
|
+
|
146
|
+
# 获取所有差异(包括新增文件)
|
147
|
+
result = subprocess.run(
|
148
|
+
["git", "diff", "HEAD"], capture_output=True, text=False, check=True
|
149
|
+
)
|
150
|
+
|
151
|
+
# 重置暂存区
|
152
|
+
subprocess.run(["git", "reset"], check=True)
|
153
|
+
|
128
154
|
try:
|
129
|
-
return result.stdout.decode(
|
155
|
+
return result.stdout.decode("utf-8")
|
130
156
|
except UnicodeDecodeError:
|
131
|
-
return result.stdout.decode(
|
132
|
-
|
157
|
+
return result.stdout.decode("utf-8", errors="replace")
|
158
|
+
|
133
159
|
except subprocess.CalledProcessError as e:
|
134
160
|
return f"获取差异失败: {str(e)}"
|
135
161
|
except Exception as e:
|
136
162
|
return f"发生意外错误: {str(e)}"
|
137
163
|
|
138
164
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
165
|
def revert_file(filepath: str) -> None:
|
143
166
|
"""增强版git恢复,处理新文件"""
|
144
167
|
import subprocess
|
168
|
+
|
145
169
|
try:
|
146
170
|
# 检查文件是否在版本控制中
|
147
171
|
result = subprocess.run(
|
148
|
-
[
|
172
|
+
["git", "ls-files", "--error-unmatch", filepath],
|
149
173
|
stderr=subprocess.PIPE,
|
150
|
-
text=False # 禁用自动文本解码
|
174
|
+
text=False, # 禁用自动文本解码
|
151
175
|
)
|
152
176
|
if result.returncode == 0:
|
153
|
-
subprocess.run([
|
154
|
-
'--', filepath], check=True)
|
177
|
+
subprocess.run(["git", "checkout", "HEAD", "--", filepath], check=True)
|
155
178
|
else:
|
156
179
|
if os.path.exists(filepath):
|
157
180
|
os.remove(filepath)
|
158
|
-
subprocess.run([
|
181
|
+
subprocess.run(["git", "clean", "-f", "--", filepath], check=True)
|
159
182
|
except subprocess.CalledProcessError as e:
|
160
|
-
error_msg = e.stderr.decode(
|
183
|
+
error_msg = e.stderr.decode("utf-8", errors="replace") if e.stderr else str(e)
|
161
184
|
PrettyOutput.print(f"恢复文件失败: {error_msg}", OutputType.ERROR)
|
185
|
+
|
186
|
+
|
162
187
|
# 修改后的恢复函数
|
163
188
|
|
164
189
|
|
165
190
|
def revert_change() -> None:
|
166
191
|
"""恢复所有未提交的修改到HEAD状态"""
|
167
192
|
import subprocess
|
193
|
+
|
168
194
|
try:
|
169
195
|
# 检查是否为空仓库
|
170
196
|
head_check = subprocess.run(
|
171
|
-
[
|
197
|
+
["git", "rev-parse", "--verify", "HEAD"],
|
172
198
|
stderr=subprocess.PIPE,
|
173
|
-
stdout=subprocess.PIPE
|
199
|
+
stdout=subprocess.PIPE,
|
174
200
|
)
|
175
201
|
if head_check.returncode == 0:
|
176
|
-
subprocess.run([
|
177
|
-
subprocess.run([
|
202
|
+
subprocess.run(["git", "reset", "--hard", "HEAD"], check=True)
|
203
|
+
subprocess.run(["git", "clean", "-fd"], check=True)
|
178
204
|
except subprocess.CalledProcessError as e:
|
179
205
|
PrettyOutput.print(f"恢复更改失败: {str(e)}", OutputType.ERROR)
|
180
206
|
|
@@ -188,27 +214,25 @@ def handle_commit_workflow() -> bool:
|
|
188
214
|
if is_confirm_before_apply_patch() and not user_confirm("是否要提交代码?", default=True):
|
189
215
|
revert_change()
|
190
216
|
return False
|
191
|
-
|
217
|
+
|
192
218
|
import subprocess
|
219
|
+
|
193
220
|
try:
|
194
221
|
# 获取当前分支的提交总数
|
195
222
|
commit_result = subprocess.run(
|
196
|
-
[
|
197
|
-
capture_output=True,
|
198
|
-
text=True
|
223
|
+
["git", "rev-list", "--count", "HEAD"], capture_output=True, text=True
|
199
224
|
)
|
200
225
|
if commit_result.returncode != 0:
|
201
226
|
return False
|
202
|
-
|
227
|
+
|
203
228
|
commit_count = int(commit_result.stdout.strip())
|
204
|
-
|
229
|
+
|
205
230
|
# 暂存所有修改
|
206
|
-
subprocess.run([
|
207
|
-
|
231
|
+
subprocess.run(["git", "add", "."], check=True)
|
232
|
+
|
208
233
|
# 提交变更
|
209
234
|
subprocess.run(
|
210
|
-
[
|
211
|
-
check=True
|
235
|
+
["git", "commit", "-m", f"CheckPoint #{commit_count + 1}"], check=True
|
212
236
|
)
|
213
237
|
return True
|
214
238
|
except subprocess.CalledProcessError as e:
|
@@ -224,24 +248,30 @@ def get_latest_commit_hash() -> str:
|
|
224
248
|
try:
|
225
249
|
# 首先检查是否存在HEAD引用
|
226
250
|
head_check = subprocess.run(
|
227
|
-
[
|
251
|
+
["git", "rev-parse", "--verify", "HEAD"],
|
228
252
|
stdout=subprocess.PIPE,
|
229
253
|
stderr=subprocess.PIPE,
|
230
|
-
text=False
|
254
|
+
text=False,
|
231
255
|
)
|
232
256
|
if head_check.returncode != 0:
|
233
257
|
return "" # 空仓库或无效HEAD
|
234
258
|
|
235
259
|
# 获取HEAD的完整哈希值
|
236
260
|
result = subprocess.run(
|
237
|
-
[
|
261
|
+
["git", "rev-parse", "HEAD"],
|
238
262
|
stdout=subprocess.PIPE,
|
239
263
|
stderr=subprocess.PIPE,
|
240
|
-
text=False
|
264
|
+
text=False,
|
265
|
+
)
|
266
|
+
return (
|
267
|
+
result.stdout.decode("utf-8", errors="replace").strip()
|
268
|
+
if result.returncode == 0
|
269
|
+
else ""
|
241
270
|
)
|
242
|
-
return result.stdout.decode('utf-8', errors='replace').strip() if result.returncode == 0 else ""
|
243
271
|
except Exception:
|
244
272
|
return ""
|
273
|
+
|
274
|
+
|
245
275
|
def get_modified_line_ranges() -> Dict[str, Tuple[int, int]]:
|
246
276
|
"""从Git差异中获取所有更改文件的修改行范围
|
247
277
|
|
@@ -274,18 +304,16 @@ def get_modified_line_ranges() -> Dict[str, Tuple[int, int]]:
|
|
274
304
|
return result
|
275
305
|
|
276
306
|
|
277
|
-
|
278
307
|
def is_file_in_git_repo(filepath: str) -> bool:
|
279
308
|
"""检查文件是否在当前Git仓库中"""
|
280
309
|
import subprocess
|
310
|
+
|
281
311
|
try:
|
282
312
|
# 获取Git仓库根目录
|
283
313
|
repo_root = subprocess.run(
|
284
|
-
[
|
285
|
-
capture_output=True,
|
286
|
-
text=True
|
314
|
+
["git", "rev-parse", "--show-toplevel"], capture_output=True, text=True
|
287
315
|
).stdout.strip()
|
288
|
-
|
316
|
+
|
289
317
|
# 检查文件路径是否在仓库根目录下
|
290
318
|
return os.path.abspath(filepath).startswith(os.path.abspath(repo_root))
|
291
319
|
except:
|
@@ -316,25 +344,49 @@ def check_and_update_git_repo(repo_path: str) -> bool:
|
|
316
344
|
# 获取远程tag更新
|
317
345
|
subprocess.run(["git", "fetch", "--tags"], cwd=git_root, check=True)
|
318
346
|
# 获取最新本地tag
|
319
|
-
local_tag_result = subprocess.run(
|
320
|
-
|
347
|
+
local_tag_result = subprocess.run(
|
348
|
+
["git", "describe", "--tags", "--abbrev=0"],
|
349
|
+
cwd=git_root,
|
350
|
+
capture_output=True,
|
351
|
+
text=True,
|
352
|
+
)
|
321
353
|
# 获取最新远程tag
|
322
354
|
remote_tag_result = subprocess.run(
|
323
355
|
["git", "ls-remote", "--tags", "--refs", "origin"],
|
324
|
-
cwd=git_root,
|
356
|
+
cwd=git_root,
|
357
|
+
capture_output=True,
|
358
|
+
text=True,
|
325
359
|
)
|
326
360
|
if remote_tag_result.returncode == 0:
|
327
361
|
# 提取最新的tag名称
|
328
362
|
tags = [ref.split("/")[-1] for ref in remote_tag_result.stdout.splitlines()]
|
329
|
-
tags = sorted(
|
363
|
+
tags = sorted(
|
364
|
+
tags,
|
365
|
+
key=lambda x: [
|
366
|
+
int(i) if i.isdigit() else i for i in re.split(r"([0-9]+)", x)
|
367
|
+
],
|
368
|
+
)
|
330
369
|
remote_tag = tags[-1] if tags else ""
|
331
370
|
remote_tag_result.stdout = remote_tag
|
332
371
|
|
333
|
-
if (
|
334
|
-
local_tag_result.
|
335
|
-
|
336
|
-
|
337
|
-
|
372
|
+
if (
|
373
|
+
local_tag_result.returncode == 0
|
374
|
+
and remote_tag_result.returncode == 0
|
375
|
+
and local_tag_result.stdout.strip() != remote_tag_result.stdout.strip()
|
376
|
+
):
|
377
|
+
PrettyOutput.print(
|
378
|
+
f"检测到新版本tag {remote_tag_result.stdout.strip()},正在更新Jarvis...",
|
379
|
+
OutputType.INFO,
|
380
|
+
)
|
381
|
+
subprocess.run(
|
382
|
+
["git", "checkout", remote_tag_result.stdout.strip()],
|
383
|
+
cwd=git_root,
|
384
|
+
check=True,
|
385
|
+
)
|
386
|
+
PrettyOutput.print(
|
387
|
+
f"Jarvis已更新到tag {remote_tag_result.stdout.strip()}",
|
388
|
+
OutputType.SUCCESS,
|
389
|
+
)
|
338
390
|
return True
|
339
391
|
return False
|
340
392
|
except Exception as e:
|
@@ -346,30 +398,28 @@ def check_and_update_git_repo(repo_path: str) -> bool:
|
|
346
398
|
|
347
399
|
def get_diff_file_list() -> List[str]:
|
348
400
|
"""获取HEAD到当前变更的文件列表,包括修改和新增的文件
|
349
|
-
|
401
|
+
|
350
402
|
返回:
|
351
403
|
List[str]: 修改和新增的文件路径列表
|
352
404
|
"""
|
353
405
|
try:
|
354
406
|
# 暂存新增文件
|
355
|
-
subprocess.run([
|
356
|
-
|
407
|
+
subprocess.run(["git", "add", "-N", "."], check=True)
|
408
|
+
|
357
409
|
# 获取所有差异文件(包括新增文件)
|
358
410
|
result = subprocess.run(
|
359
|
-
[
|
360
|
-
capture_output=True,
|
361
|
-
text=True
|
411
|
+
["git", "diff", "--name-only", "HEAD"], capture_output=True, text=True
|
362
412
|
)
|
363
|
-
|
413
|
+
|
364
414
|
# 重置暂存区
|
365
|
-
subprocess.run([
|
366
|
-
|
415
|
+
subprocess.run(["git", "reset"], check=True)
|
416
|
+
|
367
417
|
if result.returncode != 0:
|
368
418
|
PrettyOutput.print(f"获取差异文件列表失败: {result.stderr}", OutputType.ERROR)
|
369
419
|
return []
|
370
|
-
|
420
|
+
|
371
421
|
return [f for f in result.stdout.splitlines() if f]
|
372
|
-
|
422
|
+
|
373
423
|
except subprocess.CalledProcessError as e:
|
374
424
|
PrettyOutput.print(f"获取差异文件列表失败: {str(e)}", OutputType.ERROR)
|
375
425
|
return []
|
@@ -378,19 +428,18 @@ def get_diff_file_list() -> List[str]:
|
|
378
428
|
return []
|
379
429
|
|
380
430
|
|
381
|
-
|
382
431
|
def get_recent_commits_with_files() -> List[Dict[str, Any]]:
|
383
432
|
"""获取最近5次提交的commit信息和文件清单
|
384
|
-
|
433
|
+
|
385
434
|
返回:
|
386
435
|
List[Dict[str, Any]]: 包含commit信息和文件清单的字典列表,格式为:
|
387
436
|
[
|
388
437
|
{
|
389
|
-
'hash':
|
390
|
-
'message':
|
391
|
-
'author':
|
392
|
-
'date':
|
393
|
-
'files': [
|
438
|
+
'hash': str,
|
439
|
+
'message': str,
|
440
|
+
'author': str,
|
441
|
+
'date': str,
|
442
|
+
'files': List[str] # 修改的文件列表 (最多20个文件)
|
394
443
|
},
|
395
444
|
...
|
396
445
|
]
|
@@ -399,9 +448,9 @@ def get_recent_commits_with_files() -> List[Dict[str, Any]]:
|
|
399
448
|
try:
|
400
449
|
# 获取最近5次提交的基本信息
|
401
450
|
result = subprocess.run(
|
402
|
-
[
|
451
|
+
["git", "log", "-5", "--pretty=format:%H%n%s%n%an%n%ad"],
|
403
452
|
capture_output=True,
|
404
|
-
text=True
|
453
|
+
text=True,
|
405
454
|
)
|
406
455
|
if result.returncode != 0:
|
407
456
|
return []
|
@@ -413,26 +462,27 @@ def get_recent_commits_with_files() -> List[Dict[str, Any]]:
|
|
413
462
|
if i + 3 >= len(lines):
|
414
463
|
break
|
415
464
|
commit = {
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
465
|
+
"hash": lines[i],
|
466
|
+
"message": lines[i + 1],
|
467
|
+
"author": lines[i + 2],
|
468
|
+
"date": lines[i + 3],
|
469
|
+
"files": [],
|
421
470
|
}
|
422
471
|
commits.append(commit)
|
423
472
|
|
424
473
|
# 获取每个提交的文件修改清单
|
425
474
|
for commit in commits:
|
426
475
|
files_result = subprocess.run(
|
427
|
-
[
|
476
|
+
["git", "show", "--name-only", "--pretty=format:", commit["hash"]],
|
428
477
|
capture_output=True,
|
429
|
-
text=True
|
478
|
+
text=True,
|
430
479
|
)
|
431
480
|
if files_result.returncode == 0:
|
432
|
-
|
433
|
-
|
481
|
+
file_lines = files_result.stdout.splitlines()
|
482
|
+
unique_files = set(filter(None, file_lines))
|
483
|
+
commit["files"] = list(unique_files)[:20] # 限制最多20个文件
|
434
484
|
|
435
485
|
return commits
|
436
486
|
|
437
487
|
except subprocess.CalledProcessError:
|
438
|
-
return []
|
488
|
+
return []
|