1+ import datetime
12import json
23import logging
34import os
45import random
6+ import shutil
57import subprocess
68import sys
79from datetime import timedelta , datetime
1012from PyQt5 .QtWidgets import (
1113 QApplication , QWidget , QLabel , QLineEdit , QPushButton ,
1214 QVBoxLayout , QFileDialog , QListWidget , QMessageBox , QComboBox , QDialog ,
13- QFormLayout , QDateTimeEdit , QDialogButtonBox , QListWidgetItem , QTextEdit
15+ QFormLayout , QDateTimeEdit , QDialogButtonBox , QListWidgetItem , QTextEdit , QInputDialog
1416)
1517
1618from authors import ManageAuthorsDialog
@@ -151,12 +153,12 @@ def __init__(self):
151153 self .start_time = QDateTimeEdit ()
152154 self .start_time .setCalendarPopup (True )
153155 self .start_time .setDateTime (QDateTime .currentDateTime ().addDays (- 7 ))
154- self .start_time .setDisplayFormat ("yyyy-MM-dd HH:mm:ss " )
156+ self .start_time .setDisplayFormat ("yyyy-MM-dd" )
155157
156158 self .end_time = QDateTimeEdit ()
157159 self .end_time .setCalendarPopup (True )
158160 self .end_time .setDateTime (QDateTime .currentDateTime ())
159- self .end_time .setDisplayFormat ("yyyy-MM-dd HH:mm:ss " )
161+ self .end_time .setDisplayFormat ("yyyy-MM-dd" )
160162
161163 buttons = QDialogButtonBox (QDialogButtonBox .Ok | QDialogButtonBox .Cancel )
162164 buttons .accepted .connect (self .accept )
@@ -227,6 +229,7 @@ class GitCommitEditor(QWidget):
227229 def __init__ (self ):
228230 super ().__init__ ()
229231 self .remote_url = None
232+ self .current_branch = None
230233 self .authors = load_authors ()
231234 self .setWindowTitle ("Git Commit Editor (全功能整合版)" )
232235
@@ -317,7 +320,7 @@ def get_branches():
317320 if "HEAD" in branch :
318321 continue
319322 if branch .startswith ("remotes/origin/" ):
320- branches .add (branch .replace ("remotes/origin/" ,"" ))
323+ branches .add (branch .replace ("remotes/origin/" , "" ))
321324 continue
322325 if branch .startswith ("*" ):
323326 current = branch .split ("*" )[- 1 ].strip ()
@@ -327,14 +330,14 @@ def get_branches():
327330 # 远程分支列表
328331 return branches , current
329332
330- branches , current = get_branches ()
333+ branches , self . current_branch = get_branches ()
331334 if not len (branches ):
332335 return
333336 self .branch_selector .clear ()
334337 self .branch_selector .addItems (branches )
335338 # 设置当前分支
336- if current != "" :
337- self .branch_selector .setCurrentText (current )
339+ if self . current_branch != "" :
340+ self .branch_selector .setCurrentText (self . current_branch )
338341 self .load_commits ()
339342 self .get_remote_url ()
340343
@@ -345,8 +348,10 @@ def load_commits(self):
345348 return
346349 result = subprocess .run (["git" , "checkout" , branch ], cwd = repo , capture_output = True , text = True )
347350 if result .returncode != 0 :
351+ self .branch_selector .setCurrentText (self .current_branch )
348352 QMessageBox .critical (self , "失败" , result .stderr )
349353 return
354+ self .current_branch = branch
350355 cmd = ["git" , "log" , branch , "--pretty=format:%h %an <%ae> %ad %s %d" , "--date=iso" ]
351356 output = run_git_command (cmd , cwd = repo )
352357 self .commit_listbox .clear ()
@@ -359,6 +364,9 @@ def load_commits(self):
359364 self .commit_listbox .addItems (commit_logs )
360365
361366 def rewrite_commits_randomly (self ):
367+ if not shutil .which ("git-filter-repo" ):
368+ QMessageBox .critical (self , "错误" , "请先安装 git-filter-repo 工具" )
369+ return
362370 dialog = BulkRewriteDialog ()
363371 if dialog .exec_ ():
364372 authors , start , end , base_commit = dialog .get_values ()
@@ -382,13 +390,15 @@ def rewrite_commits_randomly(self):
382390 commit_changes = {}
383391 # 忽略第一次提交,因为无法修改
384392 for i , commit in enumerate (commits ):
393+ _ , date , message = self .get_commit_info (commit )
394+ commit_date = datetime .strptime (date , "%Y-%m-%d %H:%M:%S +0800" )
385395 rand_time = start + timedelta (seconds = time_steps [i ])
386- formatted_date = rand_time .strftime ("%Y-%m-%dT%H:%M:%S" )
387-
396+ commit_date = datetime (year = rand_time .year , month = rand_time .month , day = rand_time .day ,
397+ hour = commit_date .hour , minute = commit_date .minute , second = commit_date .second )
398+ formatted_date = commit_date .strftime ("%Y-%m-%dT%H:%M:%S" )
388399 rand_author = random .choice (authors )
389400 name = rand_author .split ("<" )[0 ].strip ()
390401 email = rand_author .split ("<" )[1 ].strip (" >" )
391- _ , _ , message = self .get_commit_info (commit )
392402
393403 commit_changes [commit [:7 ]] = {
394404 "name" : name ,
@@ -419,20 +429,27 @@ def rewrite_commits_randomly(self):
419429 os .remove (callback_path )
420430
421431 def push_force (self ):
422- # 增减确认框 确认是否需要强推 这是一个危险操作
432+ remote_url , ok = QInputDialog .getText (self , "输入远程仓库地址" ,
433+ "请输入远程仓库地址(如 origin 或 https://xxx.git)" , text = "origin" )
434+ if not ok or remote_url .strip () == "" :
435+ QMessageBox .warning (self , "取消" , "未输入远程仓库地址,操作已取消" )
436+ return
423437 if QMessageBox .question (self , "确认" , "这个操作会导致原来的提交记录丢失,确定要强推吗?" ,
424438 QMessageBox .Yes | QMessageBox .No ) == QMessageBox .No :
425439 return
426440 repo = self .repo_path .text ()
427441 branch = self .branch_selector .currentText ()
428- result = subprocess .run (["git" , "push" , '--set-upstream' , "origin" , branch , "--force" ], cwd = repo ,
442+ result = subprocess .run (["git" , "push" , '--set-upstream' , remote_url . strip () , branch , "--force" ], cwd = repo ,
429443 capture_output = True , text = True )
430444 if result .returncode == 0 :
431445 QMessageBox .information (self , "成功" , "强推完成" )
432446 else :
433447 QMessageBox .critical (self , "失败" , result .stderr )
434448
435449 def edit_commit (self , item ):
450+ if not shutil .which ("git-filter-repo" ):
451+ QMessageBox .critical (self , "错误" , "请先安装 git-filter-repo 工具" )
452+ return
436453 selected_commit = item .text ().split ()[0 ]
437454
438455 author , date , message = self .get_commit_info (selected_commit )
0 commit comments