GIT.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. import tkinter
  2. import tkinter.messagebox
  3. from tkinter import ttk
  4. from tkinter.filedialog import askopenfilename, asksaveasfilename,askdirectory,askopenfilenames
  5. import os
  6. import Git_Ctrl
  7. from tkinter.scrolledtext import ScrolledText
  8. import time
  9. import threading
  10. str_code = 'utf-8'
  11. Git = Git_Ctrl.git_Ctrol()#需要去掉
  12. def Main():
  13. global top,Git,PATH,bg,bbg,fg,Git_List,Last_Name
  14. PATH = os.getcwd()
  15. Git = Git_Ctrl.git_Ctrol()
  16. Git_List = []
  17. top = tkinter.Tk()
  18. Last_Name = None
  19. bg = '#FFFAFA' # 主颜色
  20. bbg = '#FFFAFA' # 按钮颜色
  21. fg = '#000000' # 文字颜色
  22. top["bg"] = bg
  23. FONT = ('黑体', 11) # 设置字体
  24. top.title('CoTan仓库管理器')
  25. top.resizable(width=False, height=False)
  26. top.geometry('+10+10') # 设置所在位置
  27. width_B = 13 # 标准宽度
  28. height_B = 2
  29. a_y = 0
  30. a_x = 0
  31. global clone_url,Git_Box,Git_Dir
  32. global commit_m,head,master,no_ff
  33. global TagName,TagMessage,TagCommit,Show_Key
  34. global RemoteSSH,RemoteName,RemoteBranch,LocalBranch,push_bind,allow_history
  35. global BranchName, StashName, CommitName, BranchNOrigin
  36. tkinter.Button(top, bg=bbg, fg=fg, text='克隆仓库', command=clone_git, font=FONT, width=width_B,
  37. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  38. tkinter.Button(top, bg=bbg, fg=fg, text='打开仓库', command=init_git, font=FONT, width=width_B,
  39. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  40. tkinter.Button(top, bg=bbg, fg=fg, text='查看文件', command=get_Git_Dir, font=FONT, width=width_B,
  41. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  42. a_y += 1
  43. tkinter.Label(top, text='克隆URL:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  44. Dic_Var = tkinter.StringVar()#当前的Dic
  45. clone_url = tkinter.Entry(top, width=width_B * 2, textvariable=Dic_Var)
  46. clone_url.grid(column=a_x+1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
  47. a_y += 1
  48. Git_Box = tkinter.Listbox(top, width=width_B * 3, height=height_B * 4)
  49. Git_Box.grid(column=a_x, row=a_y, columnspan=3, rowspan=4, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
  50. a_y += 4
  51. tkinter.Label(top, text='【仓库文件列表】', bg=bg, fg=fg, font=FONT, width=width_B * 3, height=height_B).grid(
  52. column=a_x,columnspan=3,row=a_y,sticky=tkinter.E + tkinter.W + tkinter.W + tkinter.S + tkinter.N) # 设置说明
  53. a_y += 1
  54. Git_Dir = tkinter.Listbox(top, width=width_B * 3, height=height_B * 4)
  55. Git_Dir.grid(column=a_x, row=a_y, columnspan=3, rowspan=4, sticky=tkinter.E + tkinter.W + tkinter.S + tkinter.N)
  56. a_y += 4
  57. tkinter.Button(top, bg=bbg, fg=fg, text='添加暂存区文件', command=Add_File, font=FONT, width=width_B,
  58. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  59. tkinter.Button(top, bg=bbg, fg=fg, text='移除暂存区文件', command=Reset_File, font=FONT, width=width_B,
  60. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  61. tkinter.Button(top, bg=bbg, fg=fg, text='提交到git', command=Commit_File, font=FONT, width=width_B,
  62. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  63. a_y += 1
  64. tkinter.Button(top, bg=bbg, fg=fg, text='查看执行日志', command=lambda :not_Args(Git.reflog), font=FONT, width=width_B,
  65. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  66. tkinter.Button(top, bg=bbg, fg=fg, text='查看文件日志', command=log, font=FONT, width=width_B,
  67. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  68. tkinter.Button(top, bg=bbg, fg=fg, text='查看状态', command=lambda :not_Args(Git.status), font=FONT, width=width_B,
  69. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  70. global log_Type,reset_Type
  71. a_y += 1
  72. log_Type = []
  73. lable = ['显示轴','commit完全显示','简化显示']#复选框
  74. for i in range(3):
  75. log_Type.append(tkinter.IntVar())
  76. tkinter.Checkbutton(top,bg = bg,fg = fg,activebackground=bg,activeforeground=fg,selectcolor=bg, text=lable[i],
  77. variable=log_Type[-1]).grid(column=a_x+i, row=a_y, sticky=tkinter.W)
  78. log_Type[-1].set(1)
  79. a_y += 1
  80. tkinter.Button(top, bg=bbg, fg=fg, text='版本回退', command=Back_version, font=FONT, width=width_B,
  81. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  82. tkinter.Button(top, bg=bbg, fg=fg, text='文件回退', command=Back_File, font=FONT, width=width_B,
  83. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  84. tkinter.Button(top, bg=bbg, fg=fg, text='删除文件', command=rm_file, font=FONT, width=width_B,
  85. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  86. a_y += 1
  87. reset_Type = tkinter.IntVar()#正,负,0
  88. lable = ['回退到工作区','回退到暂存区','无痕回退']#复选框
  89. for i in range(3):
  90. tkinter.Radiobutton(top,bg = bg,fg = fg,activebackground=bg,activeforeground=fg,selectcolor=bg,text=lable[i],
  91. variable=reset_Type, value=i).grid(column=a_x+i, row=a_y, sticky=tkinter.W)
  92. a_y += 1
  93. tkinter.Button(top, bg=bbg, fg=fg, text='查看分支', command=lambda :not_Args(Git.check_Branch), font=FONT, width=width_B,
  94. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  95. tkinter.Button(top, bg=bbg, fg=fg, text='新建分支', command=make_Branch, font=FONT, width=width_B,
  96. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  97. tkinter.Button(top, bg=bbg, fg=fg, text='切换分支', command=switch_Branch, font=FONT, width=width_B,
  98. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  99. a_y += 1
  100. tkinter.Button(top, bg=bbg, fg=fg, text='删除分支', command=lambda :Delete_Branch(1), font=FONT, width=width_B,
  101. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  102. tkinter.Button(top, bg=bbg, fg=fg, text='丢弃分支', command=lambda :Delete_Branch(0), font=FONT, width=width_B,
  103. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  104. tkinter.Button(top, bg=bbg, fg=fg, text='合并分支', command=switch_Branch, font=FONT, width=width_B,
  105. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  106. no_ff = tkinter.Variable()
  107. a_y += 1
  108. tkinter.Button(top, bg=bbg, fg=fg, text='合并分支', command=merge_Branch, font=FONT, width=width_B,
  109. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  110. tkinter.Button(top, bg=bbg, fg=fg, text='退出冲突处理', command=lambda :not_Args(Git.merge_abort), font=FONT, width=width_B,
  111. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  112. tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='使用快速合并',
  113. variable=no_ff).grid(column=a_x + 1, row=a_y, sticky=tkinter.W)
  114. no_ff.set(0)
  115. a_y += 1
  116. tkinter.Button(top, bg=bbg, fg=fg, text='保存工作区', command=lambda :not_Args(Git.Save_stash), font=FONT, width=width_B,
  117. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  118. tkinter.Button(top, bg=bbg, fg=fg, text='恢复工作区', command=lambda :Open_Stash(1), font=FONT, width=width_B,
  119. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  120. tkinter.Button(top, bg=bbg, fg=fg, text='删除工作区', command=lambda :Open_Stash(0), font=FONT, width=width_B,
  121. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  122. a_x += 3
  123. tkinter.Label(top, text='', bg=bg, fg=fg, font=FONT, width=1).grid(column=a_x, row=a_y) # 设置说明
  124. a_x += 1
  125. a_y = 0
  126. tkinter.Label(top, text='【参数操作】', bg=bg, fg=fg, font=FONT, width=width_B * 3, height=height_B).grid(
  127. column=a_x,columnspan=3,row=a_y,sticky=tkinter.E + tkinter.W + tkinter.W + tkinter.S + tkinter.N) # 设置说明
  128. a_y += 1
  129. tkinter.Label(top, text='提交描述:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  130. commit_m = tkinter.Entry(top, width=width_B * 2)
  131. commit_m.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
  132. a_y += 1
  133. tkinter.Label(top, text='diff分支:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  134. master = tkinter.Entry(top, width=width_B * 2)
  135. master.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
  136. a_y += 1
  137. tkinter.Label(top, text='回退版本号:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  138. head = tkinter.Entry(top, width=width_B * 2)
  139. head.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
  140. a_y += 1
  141. tkinter.Label(top, text='本地分支:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  142. BranchName = tkinter.Entry(top, width=width_B * 2)
  143. BranchName.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
  144. a_y += 1
  145. tkinter.Label(top, text='远程分支:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  146. BranchNOrigin = tkinter.Entry(top, width=width_B * 2)
  147. BranchNOrigin.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
  148. a_y += 1
  149. tkinter.Label(top, text='远程仓库链接:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  150. RemoteSSH = tkinter.Entry(top, width=width_B)
  151. RemoteSSH.grid(column=a_x + 1,columnspan=2, row=a_y, sticky=tkinter.E + tkinter.W)
  152. a_y += 1
  153. tkinter.Label(top, text='远程仓库名:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  154. RemoteName = tkinter.Entry(top, width=width_B)
  155. RemoteName.grid(column=a_x + 1, row=a_y, columnspan=2,sticky=tkinter.E + tkinter.W)
  156. a_y += 1
  157. tkinter.Label(top, text='commit:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  158. CommitName = tkinter.Entry(top, width=width_B)
  159. CommitName.grid(column=a_x + 1, row=a_y, columnspan=2, sticky=tkinter.E + tkinter.W)
  160. a_y += 1
  161. tkinter.Label(top, text='标签名字:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  162. TagName = tkinter.Entry(top, width=width_B)
  163. TagName.grid(column=a_x + 1,columnspan=2, row=a_y, sticky=tkinter.E + tkinter.W)
  164. a_y += 1
  165. tkinter.Label(top, text='查询关键字:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  166. Show_Key = tkinter.Entry(top, width=width_B)
  167. Show_Key.grid(column=a_x + 1,columnspan=2, row=a_y, sticky=tkinter.E + tkinter.W)
  168. a_y += 1
  169. tkinter.Label(top, text='工作区序号:', bg=bg, fg=fg, font=FONT, width=width_B, height=height_B).grid(column=a_x,row=a_y)
  170. StashName = tkinter.Entry(top, width=width_B)
  171. StashName.grid(column=a_x + 1, row=a_y,columnspan=2, sticky=tkinter.E + tkinter.W)
  172. a_y += 1
  173. tkinter.Button(top, bg=bbg, fg=fg, text='连接远程仓库', command=Add_remote, font=FONT, width=width_B,
  174. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  175. tkinter.Button(top, bg=bbg, fg=fg, text='推送到远程仓库', command=lambda :Pull_Push_remote(1), font=FONT, width=width_B,
  176. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  177. tkinter.Button(top, bg=bbg, fg=fg, text='从远程仓库抓取', command=lambda :Pull_Push_remote(0), font=FONT, width=width_B,
  178. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  179. push_bind = tkinter.Variable()
  180. allow_history = tkinter.Variable()
  181. a_y += 1
  182. tkinter.Button(top, bg=bbg, fg=fg, text='分支绑定', command=Bind_remote, font=FONT, width=width_B,
  183. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  184. tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='无视历史记录',
  185. variable=allow_history).grid(column=a_x + 1, row=a_y, sticky=tkinter.W)
  186. tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='推送时绑定',
  187. variable=push_bind).grid(column=a_x + 2, row=a_y, sticky=tkinter.W)
  188. allow_history.set(0)
  189. push_bind.set(0)
  190. a_y += 1
  191. tkinter.Button(top, bg=bbg, fg=fg, text='应用标签', command=add_tag, font=FONT, width=width_B,
  192. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  193. tkinter.Button(top, bg=bbg, fg=fg, text='查看已有标签', command=lambda :show_tag(1), font=FONT, width=width_B,
  194. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  195. tkinter.Button(top, bg=bbg, fg=fg, text='查询commit记录',command=lambda :show_tag(0), font=FONT, width=width_B,
  196. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  197. a_y += 1
  198. tkinter.Button(top, bg=bbg, fg=fg, text='推送标签', command=push_tag, font=FONT, width=width_B,
  199. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  200. tkinter.Button(top, bg=bbg, fg=fg, text='推送所有标签', command=push_alltag, font=FONT, width=width_B,
  201. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  202. tkinter.Button(top, bg=bbg, fg=fg, text='删除本地标签',command=del_Tag, font=FONT, width=width_B,
  203. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  204. a_y += 1
  205. tkinter.Button(top, bg=bbg, fg=fg, text='删除远程标签', command=del_Tag_remote, font=FONT, width=width_B,
  206. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  207. tkinter.Button(top, bg=bbg, fg=fg, text='删除远程分支', command=del_Branch_remote, font=FONT, width=width_B,
  208. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  209. tkinter.Button(top, bg=bbg, fg=fg, text='刷新远程分支', command=Fetch_remote, font=FONT, width=width_B,
  210. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  211. a_y += 1
  212. tkinter.Button(top, bg=bbg, fg=fg, text='commit补丁', command=cherry_pick, font=FONT, width=width_B,
  213. height=height_B).grid(column=a_x, row=a_y, sticky=tkinter.E + tkinter.W)
  214. tkinter.Button(top, bg=bbg, fg=fg, text='删除远程仓库', command=Del_remote, font=FONT, width=width_B,
  215. height=height_B).grid(column=a_x+1, row=a_y, sticky=tkinter.E + tkinter.W)
  216. tkinter.Button(top, bg=bbg, fg=fg, text='工作区列表', command=lambda :not_Args(Git.Stash_List), font=FONT, width=width_B,
  217. height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  218. # global Customize_Input, th_do, wait_do
  219. # a_y += 1
  220. # th_do = tkinter.Variable()
  221. # wait_do = tkinter.Variable()
  222. # tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='多进程刷新',
  223. # variable=th_do).grid(column=0, row=a_y, sticky=tkinter.W)
  224. # tkinter.Checkbutton(top, bg=bg, fg=fg, activebackground=bg, activeforeground=fg, selectcolor=bg, text='异步显示',
  225. # variable=wait_do).grid(column=1, row=a_y, sticky=tkinter.W)
  226. # Customize_Input = tkinter.Entry(top, width=width_B * 3)
  227. # Customize_Input.grid(column=2, row=a_y, columnspan=4, sticky=tkinter.E + tkinter.W + tkinter.N + tkinter.S)
  228. #
  229. # tkinter.Button(top, bg=bbg, fg=fg, text='执行操作', command=Customize, font=FONT, width=width_B,
  230. # height=height_B).grid(column=a_x+2, row=a_y, sticky=tkinter.E + tkinter.W)
  231. # th_do.set(0)
  232. # wait_do.set(1)
  233. TagMessage = commit_m
  234. TagCommit = CommitName
  235. RemoteBranch = BranchNOrigin
  236. LocalBranch = BranchName
  237. top.mainloop()
  238. def clone_git():#克隆仓库
  239. global clone_url
  240. new_Dic = askdirectory(title = '选择仓库地址')
  241. if new_Dic == '':return False
  242. name = Git.Clone_init(new_Dic)
  243. Clone(name, clone_url.get())
  244. Updata_GitBox()
  245. def Clone(name,url):
  246. do_Sys(Git.Clone, (name, url),
  247. break_time=0,text_n=f'{url}:正在执行克隆操作',th=True,wait=True)
  248. Git.After_Clone(name)
  249. update_Git_Dir()
  250. def Customize():
  251. global Git, Customize_Input, th_do, wait_do
  252. command = Customize_Input.get()
  253. do_Sys(Git.Customize, (get_Name(), command),
  254. break_time=0,text_n=f'{command}:操作进行中',th=bool(th_do.get()),wait=bool(wait_do.get()))
  255. update_Git_Dir()
  256. def Fetch_remote():
  257. global RemoteBranch, LocalBranch, Git, RemoteName
  258. Branch = RemoteBranch.get()
  259. Remote = RemoteName.get()
  260. Local = LocalBranch.get()
  261. do_Sys(Git.Fetch, (get_Name(), Local, Remote, Branch),
  262. break_time=0,text_n=f'此操作需要连接远程仓库,请稍等...',th=True,wait=True)
  263. update_Git_Dir()
  264. def del_Tag():
  265. global Git, RemoteName, TagName
  266. Tag = TagName.get()
  267. do_Sys(Git.del_tag, (get_Name(),Tag))
  268. update_Git_Dir()
  269. def del_Branch_remote():
  270. global Git, RemoteName, TagName
  271. Remoto = RemoteName.get()
  272. Remoto_Branch = RemoteBranch.get()
  273. do_Sys(Git.del_Branch_remote, (get_Name(),Remoto,Remoto_Branch),break_time=0,text_n=f'此操作需要连接远程仓库,请稍等...',
  274. th=True,wait=True)
  275. update_Git_Dir()
  276. def del_Tag_remote():
  277. global Git, RemoteName, TagName
  278. Remoto = RemoteName.get()
  279. Tag = TagName.get()
  280. do_Sys(Git.del_Tag_remote, (get_Name(),Remoto,Tag),break_time=0,text_n=f'此操作需要连接远程仓库,请稍等...',
  281. th=True,wait=True)
  282. update_Git_Dir()
  283. def push_alltag():
  284. global Git, RemoteName
  285. Remoto = RemoteName.get()
  286. do_Sys(Git.push_allTag, (get_Name(),Remoto),break_time=0,text_n=f'此操作需要连接远程仓库,请稍等...',
  287. th=True,wait=True)
  288. update_Git_Dir()
  289. def push_tag():
  290. global TagName, Git, RemoteName
  291. tag_name = TagName.get()
  292. Remoto = RemoteName.get()
  293. do_Sys(Git.push_Tag, (get_Name(), tag_name,Remoto),break_time=0,text_n=f'此操作需要连接远程仓库,请稍等...',
  294. th=True,wait=True)
  295. update_Git_Dir()
  296. def add_tag():
  297. global TagName, Git, commit, tag_message
  298. tag_name = TagName.get()
  299. commit = TagCommit.get()
  300. tag_message = TagMessage.get()
  301. do_Sys(Git.Add_Tag, (get_Name(), tag_name,commit,tag_message),show=False)
  302. update_Git_Dir()
  303. def show_tag(type_):
  304. global Show_Key, Git
  305. key = Show_Key.get()
  306. do_Sys({1:Git.Tag,0:Git.show_new}.get(type_,Git.show_new), (get_Name(), key))
  307. update_Git_Dir()
  308. def Pull_Push_remote(type_):
  309. global RemoteBranch, LocalBranch, Git, allow_history, RemoteName
  310. Branch = RemoteBranch.get()
  311. Remote = RemoteName.get()
  312. Local = LocalBranch.get()
  313. allow = bool(allow_history.get())
  314. u = bool(push_bind.get())
  315. f = tkinter.messagebox.askokcancel('提示', f'是否需要强制推送?(强制推送不被建议)')
  316. do_Sys({0:Git.Pull_remote,1:Git.Push_remote}.get(type_,Git.Pull_remote), (get_Name(), Local, Remote, Branch, allow, u, f),
  317. break_time=0,text_n=f'此操作需要连接远程仓库,请稍等...',th=True,wait=True)
  318. update_Git_Dir()
  319. def Bind_remote():
  320. global RemoteBranch, LocalBranch, Git
  321. Remote = RemoteBranch.get()
  322. Local = LocalBranch.get()
  323. do_Sys(Git.Bind_remote, (get_Name(), Local, Remote))
  324. update_Git_Dir()
  325. def Del_remote():
  326. global RemoteSSH, RemoteName, Git
  327. name = RemoteName.get()
  328. do_Sys(Git.Del_remote, (get_Name(), name))
  329. update_Git_Dir()
  330. def Add_remote():
  331. global RemoteSSH, RemoteName, Git
  332. SSH = RemoteSSH.get()
  333. name = RemoteName.get()
  334. do_Sys(Git.Add_remote, (get_Name(), SSH, name))
  335. update_Git_Dir()
  336. def cherry_pick():
  337. global CommitName, Git
  338. commit = CommitName.get()
  339. do_Sys(Git.cherry_pick, (get_Name(), commit))
  340. update_Git_Dir()
  341. def Open_Stash(type_):
  342. global StashName, Git
  343. stash_num = StashName.get()
  344. if stash_num == '':stash_num = '0'
  345. do_Sys([Git.Drop_stash,Git.Apply_stash][type_], (get_Name(), stash_num))
  346. update_Git_Dir()
  347. def merge_Branch():
  348. global BranchName, Git, no_ff,commit_m
  349. m = commit_m.get()
  350. no = not bool(no_ff.get()) # 对于no_ff来说,True - 使用快速合并,所以要翻转
  351. if m.replace(' ','') == '' and no:
  352. tkinter.messagebox.showinfo('警告!', '非常遗憾,我不同意你commit而不添加任何描述!\n描述是很重要的!'
  353. '(如果你不想添加描述,请使用快速合并,但我并不建议!)')
  354. return False
  355. name = BranchName.get()
  356. do_Sys(Git.merge_Branch, (get_Name(), name, no, m))
  357. update_Git_Dir()
  358. def Delete_Branch(type_):
  359. global BranchName, Git
  360. name = BranchName.get()
  361. do_Sys(Git.Del_Branch, (get_Name(), name, type_))
  362. update_Git_Dir()
  363. def switch_Branch():
  364. global BranchName,Git
  365. name = BranchName.get()
  366. do_Sys(Git.switch_Branch, (get_Name(), name),break_time=1,show=False)
  367. update_Git_Dir()
  368. def make_Branch():
  369. global BranchName,Git,BranchNOrigin
  370. name = BranchName.get()
  371. origin = BranchNOrigin.get()
  372. do_Sys(Git.new_Branch, (get_Name(), name, origin),break_time=1,show=False)
  373. update_Git_Dir()
  374. def check_Branch():
  375. global Git,head
  376. dic = askopenfilenames(title=f'选择要删除的文件(取消为全选)')
  377. if dic == '': return False
  378. do_Sys(Git.rm,(get_Name(),dic))
  379. update_Git_Dir()
  380. def rm_file():
  381. global Git,head
  382. dic = askopenfilenames(title=f'选择要删除的文件(取消为全选)')
  383. if dic == '': return False
  384. do_Sys(Git.rm,(get_Name(),dic))
  385. update_Git_Dir()
  386. def Back_File():
  387. global Git,head
  388. dic = askopenfilenames(title=f'选择要add的文件(取消为全选)')
  389. if dic == '': return False
  390. do_Sys(Git.checkout_version,(get_Name(),dic))
  391. update_Git_Dir()
  392. def Back_version():
  393. global Git,head,reset_Type
  394. HEAD = head.get()
  395. if HEAD == '': HEAD = 'HEAD~1'
  396. Type = reset_Type.get()
  397. do_Sys(Git.back_version,(get_Name(),HEAD,Type))
  398. update_Git_Dir()
  399. def do_Sys(func,args,name='CoTan Git',break_time=0,show=True,text_n='',th=False,wait=False,stop=True):
  400. p = func(*args)
  401. flat = True
  402. stopKey = Git_Ctrl.stopKey
  403. def Out_Txt():
  404. nonlocal data
  405. dic = asksaveasfilename(title='选择文件保存位置',filetypes=[("TXT", ".txt")])
  406. try:
  407. if dic == '':return False
  408. if dic[-4] == '.txt':pass
  409. else:raise Exception
  410. except:
  411. dic += '.txt'
  412. with open(dic,'w',encoding='utf-8') as f:
  413. f.write(data)
  414. kb = True
  415. sb = True
  416. def update_b():
  417. if not kb:
  418. b_list[1].config(state=tkinter.DISABLED)
  419. if not sb:
  420. b_list[0].config(state=tkinter.DISABLED)
  421. def Stop():
  422. nonlocal start,kb,sb
  423. start = 0
  424. sb = False
  425. kb = False
  426. update_b()
  427. def keep():
  428. nonlocal start,kb
  429. start = float('inf')
  430. kb = False
  431. update_b()
  432. def pipe():pass
  433. def not_out():
  434. nonlocal text,out_data,data,flat
  435. text.clear()
  436. if flat:
  437. text.insert(tkinter.END,data)
  438. else:
  439. text.insert(tkinter.END, out_data)
  440. flat = not flat
  441. start = time.time()
  442. data = ''
  443. out_data = ''#包含out的data
  444. if show:
  445. text, new_top, b_list = show_Now(Out_Txt,Stop,keep,not_out,pipe,name=name)#[close,keep]
  446. update_b()
  447. if text_n != '':
  448. text.insert('0.0',f'载入前提示>>> {text_n}\n')
  449. out_data += f'载入前提示>>> {text_n}\n'
  450. data += f'{text_n}\n'
  451. new_top.update()
  452. else:
  453. u = threading.Thread(target=up)
  454. u.start()
  455. top.update()
  456. def Update():
  457. nonlocal start
  458. while True:
  459. try:
  460. top.update()
  461. if show:
  462. try:
  463. new_top.update()
  464. except:pass
  465. if time.time() - start >= break_time and break_time != 0:
  466. raise Exception
  467. elif break_time == 0 and start == 0:
  468. raise Exception
  469. except:
  470. start = 0
  471. break
  472. if th or not wait:
  473. j = threading.Thread(target=Update)#如果没有启动到多进程的效果,请检查Update是不是加了(),这里需要回调
  474. j.start()
  475. if wait:#等待后显示
  476. if break_time == 0:break_ti = None# 此处break_ti是为了别面覆盖break_time,因为Update进程需要用
  477. else:break_ti = break_time
  478. def wait_p():
  479. nonlocal start
  480. p.wait(break_ti)
  481. start = 0
  482. j = threading.Thread(target=wait_p) # 这么做不是多此一举,如果没有wait,进程并不会退出
  483. j.start()
  484. Update()#遇到sleep等主线程阻塞,top.update等会阻塞子线程,因此,必须保证主线程不会被wait所阻塞
  485. out = p.stdout.read().split('\n')
  486. for i in out:
  487. if show:
  488. try: # 如果界面被关掉了,会报错
  489. new_top.title(f'{name} : 运行中')
  490. except:
  491. text, new_top, b_list = show_Now(Out_Txt, Stop, keep, not_out, pipe,
  492. name=f'{name} : 运行中')
  493. update_b()
  494. text.insert(tkinter.END, out_data)
  495. if stop and i.replace(' ', '').replace('\n', '') != stopKey:
  496. text.insert(tkinter.END, f'[out]> {i}\n')
  497. data += i + '\n'
  498. out_data += f'[out]> {i}\n'
  499. if show:
  500. text.insert(tkinter.END, '[END]')
  501. out_data += f'[END]'
  502. data += f'[END]'
  503. start = 0
  504. else:#即时显示
  505. while True:
  506. #界面设置
  507. try:#如果界面被关掉了,会报错
  508. if show: new_top.title(f'{name} : 运行中')
  509. except:
  510. text, new_top, b_list = show_Now(Out_Txt, Stop, keep, not_out, pipe,
  511. name=f'{name} : 运行中')
  512. update_b()
  513. text.insert(tkinter.END,out_data)
  514. #界面刷新
  515. try:
  516. if not th:
  517. top.update()
  518. if show: new_top.update()
  519. except:
  520. break
  521. #输出字符
  522. try:
  523. i = p.stdout.readline()#.decode(str_code)#不需要decode,因为Popen已经设置了universal_newlines=True
  524. bool_text = i.replace(' ','').replace('\n','')
  525. if bool_text != '':
  526. if stop and bool_text == stopKey:
  527. start = 0
  528. else:
  529. if show: text.insert(tkinter.END, f'[out]> {i}')
  530. data += i
  531. out_data += f'[out]> {i}'
  532. if p.returncode == 0 or (time.time() - start >= break_time and break_time != 0) or (break_time == 0 and start == 0):
  533. if show:
  534. text.insert(tkinter.END,'[END]')
  535. out_data += f'[END]'
  536. data += f'[END]'
  537. break
  538. elif p.returncode != None:
  539. raise Exception
  540. except:
  541. try:
  542. if show:
  543. text.insert(tkinter.END, '[ERROR]')
  544. out_data += f'[ERROR]'
  545. data += f'[ERROR]'
  546. raise Exception
  547. except:break
  548. try: # 如果界面被关掉了,会报错
  549. if show: new_top.title(f'{name} : 运行完毕')
  550. except:pass
  551. p.kill()
  552. try:
  553. if show:
  554. b_list[0].config(state=tkinter.DISABLED)
  555. b_list[1].config(state=tkinter.DISABLED)
  556. except:pass
  557. return data
  558. def log():
  559. global Git,log_Type
  560. name = get_Name()
  561. graph = bool(log_Type[0].get())
  562. abbrev = bool(log_Type[1].get())
  563. pretty = bool(log_Type[2].get())
  564. do_Sys(Git.log,(name,graph,pretty,abbrev))
  565. update_Git_Dir()
  566. def not_Args(func):
  567. global Git
  568. name = get_Name()
  569. do_Sys(func,(name,))
  570. update_Git_Dir()
  571. def Commit_File():
  572. global Git,commit_m
  573. m = commit_m.get()
  574. if m.replace(' ','') == '':
  575. tkinter.messagebox.showinfo('警告!', '非常遗憾,我不同意你commit而不添加任何描述!\n描述是很重要的!')
  576. return False
  577. name = get_Name()
  578. do_Sys(Git.commit_File,(name,m))
  579. update_Git_Dir()
  580. def Diff_File():
  581. global Git,master
  582. MASTER = master.get()
  583. if MASTER == '':MASTER = 'HEAD'
  584. do_Sys(Git.diff_File,(get_Name(),MASTER))
  585. update_Git_Dir()
  586. def Reset_File():
  587. global Git,Last_Name
  588. dic = askopenfilenames(title=f'选择要撤销add的文件(取消为全选)')
  589. if dic == '':dic = '.'
  590. do_Sys(Git.reset_File,(get_Name(),dic))
  591. update_Git_Dir()
  592. def Add_File():
  593. global Git,Last_Name
  594. dic = askopenfilenames(title=f'选择要add的文件(取消为全选)')
  595. if dic == '':dic = '.'
  596. do_Sys(Git.add_File,(get_Name(),dic))
  597. update_Git_Dir()
  598. def update_Git_Dir():
  599. global Last_Name
  600. if Last_Name == None:return False
  601. Git_dir(Last_Name)
  602. def get_Git_Dir():
  603. name = get_Name()
  604. Git_dir(name)
  605. def Git_dir(name):
  606. global Git, Git_Dir,Last_Name
  607. dir_list = Git.get_Dir(name)
  608. try:#窗口可能已经关闭
  609. Git_Dir.delete(0,tkinter.END)
  610. Git_Dir.insert(tkinter.END,*dir_list)
  611. except:
  612. pass
  613. Last_Name = name
  614. def init_git():#创建仓库
  615. global Git
  616. new_Dic = askdirectory(title = '选择仓库地址')
  617. if new_Dic == '':return False
  618. Git.Add_init(new_Dic,)
  619. Updata_GitBox()
  620. def get_Name(): # 获得名字统一接口
  621. global Git,Git_List,Git_Box
  622. try:
  623. return Git_List[Git_Box.curselection()[0]]
  624. except:
  625. try:
  626. return Git_List[0]
  627. except:
  628. return None
  629. def Updata_GitBox():
  630. global Git,Git_List,Git_Box
  631. Git_List = list(Git.get_git_Dic().keys())
  632. Git_Box.delete(0,tkinter.END)
  633. Git_Box.insert(tkinter.END,*Git_List)
  634. def show_Now(out_func,close_func,keepFunc,not_out,pipeFunc,name='CoTan_Git >>> 命令行'):
  635. global bg
  636. new_top = tkinter.Toplevel(bg=bg)
  637. new_top.title(name)
  638. new_top.geometry('+10+10') # 设置所在位置
  639. new_top.resizable(width=False, height=False)
  640. class ScrolledText_new(ScrolledText):
  641. def __init__(self,*args,**kwargs):
  642. super(ScrolledText_new, self).__init__(*args,**kwargs)
  643. def insert(self, index, chars, *args):
  644. text.config(state=tkinter.NORMAL)
  645. super(ScrolledText_new, self).insert(index, chars, *args)
  646. text.config(state=tkinter.DISABLED)
  647. def clear(self):
  648. text.config(state=tkinter.NORMAL)
  649. self.delete('0.0',tkinter.END)
  650. text.config(state=tkinter.DISABLED)
  651. text = ScrolledText_new(new_top, font=('黑体', 11), height=30,width=100)
  652. text.grid(column=0, row=0,columnspan=5, sticky=tkinter.E + tkinter.W)
  653. text.config(state=tkinter.DISABLED)
  654. tkinter.Button(new_top, bg=bg, fg=fg, text='输出文档', font=('黑体', 11),width=20, height=2, command=out_func).grid(
  655. column=4, row=1, sticky=tkinter.E + tkinter.W)
  656. close = tkinter.Button(new_top, bg=bg, fg=fg, text='关闭子线程连接', font=('黑体', 11),width=20, height=2, command=close_func)
  657. close.grid(column=0, row=1, sticky=tkinter.E + tkinter.W)
  658. keep = tkinter.Button(new_top, bg=bg, fg=fg, text='保持线程连接', font=('黑体', 11),width=20, height=2, command=keepFunc)
  659. keep.grid(column=1, row=1, sticky=tkinter.E + tkinter.W)
  660. tkinter.Button(new_top, bg=bg, fg=fg, text='格式化输出', font=('黑体', 11),width=20, height=2, command=not_out).grid(
  661. column=2, row=1, sticky=tkinter.E + tkinter.W)
  662. tkinter.Button(new_top, bg=bg, fg=fg, text='启动CoTan命令行', font=('黑体', 11),width=20, height=2,
  663. command=pipeFunc,state=tkinter.DISABLED).grid(column=3, row=1, sticky=tkinter.E + tkinter.W)
  664. new_top.update()
  665. return text,new_top,[close,keep]
  666. def up(*args,name='CoTan_Git >>> 高级命令行',**kwargs):
  667. new_top = tkinter.Toplevel(bg=bg)
  668. new_top.title(name)
  669. new_top.geometry('+10+10') # 设置所在位置
  670. new_top.resizable(width=False, height=False)
  671. new_top.title(name)
  672. mpb = ttk.Progressbar(new_top, orient="horizontal", length=300, mode="determinate")
  673. mpb.pack()
  674. mpb["maximum"] = 100
  675. mpb["value"] = 0
  676. for i in range(100):
  677. mpb["value"] = i + 1
  678. new_top.update()
  679. top.update()
  680. time.sleep(0.001)
  681. new_top.destroy()
  682. if __name__ == '__main__':
  683. Main()