|
4 | 4 | import random |
5 | 5 | import subprocess |
6 | 6 | import sys |
7 | | -import tempfile |
8 | 7 | from datetime import timedelta, datetime |
9 | 8 |
|
10 | 9 | from PyQt5.QtCore import QDateTime |
|
14 | 13 | QFormLayout, QDateTimeEdit, QDialogButtonBox, QListWidgetItem, QTextEdit |
15 | 14 | ) |
16 | 15 |
|
| 16 | +from callback_builder import CallbackScriptBuilder |
| 17 | + |
17 | 18 | CONFIG_PATH = "config.json" |
18 | 19 |
|
19 | 20 |
|
@@ -341,32 +342,45 @@ def rewrite_commits_randomly(self): |
341 | 342 | new_commits = [commit[:7] for commit in commits] |
342 | 343 | if base_commit != "" and base_commit in new_commits: |
343 | 344 | index = new_commits.index(base_commit) |
344 | | - index = index+1 if index<(len(commits)-1) else -1 |
| 345 | + index = index + 1 if index < (len(commits) - 1) else -1 |
345 | 346 | commits = commits[:index] |
346 | 347 |
|
347 | 348 | total = len(commits) |
348 | 349 | seconds_range = int((end - start).total_seconds()) |
349 | 350 | time_steps = sorted([random.randint(0, seconds_range) for _ in range(total)], reverse=True) |
350 | | - |
| 351 | + commit_changes = {} |
351 | 352 | # 忽略第一次提交,因为无法修改 |
352 | 353 | for i, commit in enumerate(commits): |
353 | 354 | rand_time = start + timedelta(seconds=time_steps[i]) |
354 | 355 | formatted_date = rand_time.strftime("%Y-%m-%dT%H:%M:%S") |
| 356 | + |
355 | 357 | rand_author = random.choice(authors) |
356 | 358 | name = rand_author.split("<")[0].strip() |
357 | 359 | email = rand_author.split("<")[1].strip(" >") |
358 | 360 | _, _, message = self.get_commit_info(commit) |
359 | | - script_path = os.path.join(tempfile.gettempdir(), f"editor_{commit}.py") |
360 | | - generate_rebase_editor_script(script_path) |
361 | | - env = build_env(name, email, formatted_date, script_path) |
362 | | - |
363 | | - rebase_interactive(repo, commit, env, self.root_commit_log in commit) |
364 | | - amend_commit(repo, env, message) |
365 | | - rebase_continue(repo, env) |
366 | | - delete_temp_file(script_path) |
367 | 361 |
|
368 | | - self.load_commits() |
369 | | - QMessageBox.information(self, "完成", "批量重写完成") |
| 362 | + commit_changes[commit[:7]] = { |
| 363 | + "name": name, |
| 364 | + "email": email, |
| 365 | + "date": formatted_date, |
| 366 | + "message": message, |
| 367 | + } |
| 368 | + callback_path = os.path.join(self.repo_path.text(), "rewrite_callback.py") |
| 369 | + CallbackScriptBuilder.build_bulk_commit_callback(callback_path, commit_changes) |
| 370 | + try: |
| 371 | + result = subprocess.run([ |
| 372 | + "git-filter-repo", |
| 373 | + "--commit-callback", callback_path |
| 374 | + , "--force" |
| 375 | + ], cwd=self.repo_path.text(), capture_output=True, text=True) |
| 376 | + |
| 377 | + if result.returncode == 0: |
| 378 | + self.load_commits() |
| 379 | + QMessageBox.information(self, "成功", "提交修改完成(使用 filter-repo)") |
| 380 | + else: |
| 381 | + QMessageBox.critical(self, "失败", result.stderr) |
| 382 | + finally: |
| 383 | + os.remove(callback_path) |
370 | 384 |
|
371 | 385 | def push_force(self): |
372 | 386 | repo = self.repo_path.text() |
@@ -396,42 +410,36 @@ def edit_commit(self, item): |
396 | 410 | return |
397 | 411 |
|
398 | 412 | repo_path = self.repo_path.text() |
| 413 | + file_name = "edit_commit_callback.py" |
| 414 | + script_path = os.path.join(repo_path, file_name) |
399 | 415 | try: |
400 | 416 | author_name = new_author.split("<")[0].strip() |
401 | 417 | author_email = new_author.split("<")[1].strip(" >") |
402 | | - |
403 | | - full_log = self.run_git_command( |
404 | | - ["git", "rev-list", self.branch_selector.currentText()], |
405 | | - cwd=repo_path |
406 | | - ).splitlines() |
407 | | - full_log = [v[:7] for v in full_log] |
408 | | - if selected_commit not in full_log: |
409 | | - QMessageBox.critical(self, "错误", "未能在分支中找到该提交") |
| 418 | + ok = CallbackScriptBuilder.build_single_commit_callback( |
| 419 | + filepath=script_path, |
| 420 | + target_hash=selected_commit, |
| 421 | + author_name=author_name, |
| 422 | + author_email=author_email, |
| 423 | + commit_message=new_msg, |
| 424 | + date_str=new_date # 格式:2024-01-01T10:00:00 |
| 425 | + ) |
| 426 | + |
| 427 | + if not ok: |
| 428 | + QMessageBox.critical(self, "失败", "生成 callback 脚本失败") |
410 | 429 | return |
411 | | - |
412 | | - index = full_log.index(selected_commit) |
413 | | - # if index == len(full_log) - 1: |
414 | | - # QMessageBox.warning(self, "提示", "无法 rebase 第一个提交") |
415 | | - # return |
416 | | - |
417 | | - rebase_start = full_log[index] |
418 | | - |
419 | | - editor_script = os.path.join(tempfile.gettempdir(), "rebase_editor.py") |
420 | | - generate_rebase_editor_script(editor_script) |
421 | | - env = build_env(author_name, author_email, new_date, editor_script) |
422 | | - |
423 | | - # 根提交记录的修改 |
424 | | - rebase_interactive(repo_path, rebase_start, env, self.root_commit_log in rebase_start) |
425 | | - |
426 | | - amend_commit(repo_path, env, new_msg) |
427 | | - |
428 | | - rebase_continue(repo_path, env) |
429 | | - |
430 | | - os.remove(editor_script) |
431 | | - self.load_commits() |
432 | | - QMessageBox.information(self, "成功", "提交修改成功!") |
433 | | - |
| 430 | + result = subprocess.run([ |
| 431 | + "git-filter-repo", |
| 432 | + "--commit-callback", script_path |
| 433 | + , "--force" |
| 434 | + ], cwd=repo_path, capture_output=True, text=True) |
| 435 | + |
| 436 | + if result.returncode == 0: |
| 437 | + self.load_commits() |
| 438 | + QMessageBox.information(self, "成功", "提交修改完成(使用 filter-repo)") |
| 439 | + else: |
| 440 | + QMessageBox.critical(self, "失败", result.stderr) |
434 | 441 | except Exception as e: |
| 442 | + os.remove(script_path) |
435 | 443 | QMessageBox.critical(self, "错误", str(e)) |
436 | 444 |
|
437 | 445 | def get_commit_info(self, selected_commit): |
|
0 commit comments