完成优化

This commit is contained in:
2025-10-23 16:24:04 +08:00
parent e091d846c1
commit 84352d65c7
2 changed files with 49 additions and 30 deletions

77
app.py
View File

@@ -1,11 +1,11 @@
from Convention.Convention.Runtime.GlobalConfig import * from Convention.Convention.Runtime.GlobalConfig import *
from Convention.Convention.Runtime.File import * from Convention.Convention.Runtime.File import *
from Convention.Convention.Runtime.String import GetEditorDistanceAndOperations, FillString from Convention.Convention.Runtime.String import GetDiffOperations, FillString
import argparse import argparse
from pydantic import BaseModel from pydantic import BaseModel
import hashlib import hashlib
import json import pickle
class HistoryBlock(BaseModel): class HistoryBlock(BaseModel):
mode: Literal["add","delete"] = "add" mode: Literal["add","delete"] = "add"
@@ -13,6 +13,14 @@ class HistoryBlock(BaseModel):
end: int = 0 end: int = 0
content: str = "" content: str = ""
def ToOperation(self) -> Tuple[Literal["add","delete"], int, int, str]:
return (self.mode, self.begin, self.end, self.content)
def FromOperation(self, operation:Tuple[Literal["add","delete"], int, int, str]) -> None:
self.mode = operation[0]
self.begin = operation[1]
self.end = operation[2]
self.content = operation[3]
class HistoryObject(BaseModel): class HistoryObject(BaseModel):
hashcode: str = "" hashcode: str = ""
blocks: List[HistoryBlock] = [] blocks: List[HistoryBlock] = []
@@ -21,7 +29,8 @@ class HistoryCommit:
def __init__(self, object_chain:List[HistoryObject]) -> None: def __init__(self, object_chain:List[HistoryObject]) -> None:
self.content = "" self.content = ""
for item in object_chain: for item in object_chain:
for block in item.blocks: # 从后往前应用操作,因为操作使用的是静态坐标系(基于原始字符串)
for block in reversed(item.blocks):
if block.mode == "add": if block.mode == "add":
self.content = self.content[:block.begin] + block.content + self.content[block.end:] self.content = self.content[:block.begin] + block.content + self.content[block.end:]
elif block.mode == "delete": elif block.mode == "delete":
@@ -54,7 +63,7 @@ class HistoryModel(BaseModel):
current_commit_file_path = commit_name current_commit_file_path = commit_name
while current_commit_file_path is not None: while current_commit_file_path is not None:
current_commit_file = parent_path|current_commit_file_path current_commit_file = parent_path|current_commit_file_path
node = HistoryObject.model_validate_json(current_commit_file.LoadAsText()) node = pickle.loads(current_commit_file.LoadAsBinary())
object_chain.append(node) object_chain.append(node)
current_commit_file_path = self.obj_paths[current_commit_file_path] current_commit_file_path = self.obj_paths[current_commit_file_path]
# 反转链 # 反转链
@@ -139,22 +148,13 @@ class Cli:
self.historys_file = self.config.GetFile(history_file if history_file is not None else break_down_path(self.file.GetAbsPath())|"history", False) self.historys_file = self.config.GetFile(history_file if history_file is not None else break_down_path(self.file.GetAbsPath())|"history", False)
if self.historys_file.Exists(): if self.historys_file.Exists():
self.historys = HistoryModel.model_validate_json(self.historys_file.LoadAsText()) self.historys = pickle.loads(self.historys_file.LoadAsBinary())
else: else:
self.historys = HistoryModel() self.historys = HistoryModel()
self.prints: str = "" self.prints: str = ""
def compare(self) -> None: def show_compare_result(self, head_commit:str, operations:List[Tuple[Literal["add","delete"], int, int, str]]) -> None:
if self.branch not in self.historys.branches:
self.config.Log("Error", f"Branch {self.branch} not found")
return
head_commit = str(self.historys.ReadBranchHeadCommit(self.branch, self.historys_file.GetDirToolFile()))
current_content = self.file.LoadAsText()
step, operations = GetEditorDistanceAndOperations(head_commit, current_content)
if step == 0:
PrintColorful(ConsoleFrontColor.LIGHTMAGENTA_EX, "No changes")
return
index = 0 index = 0
for operation in operations: for operation in operations:
# 显示操作前的不变内容 # 显示操作前的不变内容
@@ -162,14 +162,14 @@ class Cli:
if operation[0] == "add": if operation[0] == "add":
color = ConsoleFrontColor.GREEN color = ConsoleFrontColor.GREEN
eline = "[>>>]" eline = f"{ConsoleBackgroundColor.LIGHTGREEN_EX} {ConsoleBackgroundColor.RESET}"
etab = "[>>]" etab = f"{ConsoleBackgroundColor.GREEN}\t{ConsoleBackgroundColor.RESET}"
ewrite = "[>]" ewrite = f"{ConsoleBackgroundColor.GREEN} {ConsoleBackgroundColor.RESET}"
elif operation[0] == "delete": elif operation[0] == "delete":
color = ConsoleFrontColor.RED color = ConsoleFrontColor.RED
eline = "[<<<]" eline = f"{ConsoleBackgroundColor.LIGHTRED_EX} {ConsoleBackgroundColor.RESET}"
etab = "[<<]" etab = f"{ConsoleBackgroundColor.RED}\t{ConsoleBackgroundColor.RESET}"
ewrite = "[<]" ewrite = f"{ConsoleBackgroundColor.RED} {ConsoleBackgroundColor.RESET}"
else: else:
raise ValueError(f"Invalid operation: {operation}") raise ValueError(f"Invalid operation: {operation}")
@@ -187,6 +187,20 @@ class Cli:
index = operation[2] index = operation[2]
self.print(head_commit[index:]) self.print(head_commit[index:])
self.print_out() self.print_out()
def compare(self) -> None:
if self.branch not in self.historys.branches:
self.config.Log("Error", f"Branch {self.branch} not found")
return
head_commit = str(self.historys.ReadBranchHeadCommit(self.branch, self.historys_file.GetDirToolFile()))
current_content = self.file.LoadAsText()
operations = GetDiffOperations(head_commit, current_content)
if len(operations) == 0:
PrintColorful(ConsoleFrontColor.LIGHTMAGENTA_EX, "No changes")
return
self.show_compare_result(head_commit, operations)
if self.verbose: if self.verbose:
PrintColorful(ConsoleFrontColor.LIGHTMAGENTA_EX, "\noperations:") PrintColorful(ConsoleFrontColor.LIGHTMAGENTA_EX, "\noperations:")
@@ -206,7 +220,7 @@ class Cli:
PrintColorful(ConsoleFrontColor.LIGHTMAGENTA_EX, "\nAll content is new") PrintColorful(ConsoleFrontColor.LIGHTMAGENTA_EX, "\nAll content is new")
else: else:
head_commit = str(self.historys.ReadBranchHeadCommit(self.branch, self.historys_file.GetDirToolFile())) head_commit = str(self.historys.ReadBranchHeadCommit(self.branch, self.historys_file.GetDirToolFile()))
step, operations = GetEditorDistanceAndOperations(head_commit, content) operations = GetDiffOperations(head_commit, content)
for operation in operations: for operation in operations:
if operation[0] == "add": if operation[0] == "add":
root.blocks.append(HistoryBlock(mode="add",begin=operation[1],end=operation[2],content=operation[3])) root.blocks.append(HistoryBlock(mode="add",begin=operation[1],end=operation[2],content=operation[3]))
@@ -221,8 +235,8 @@ class Cli:
# 创建树节点, 并链接 # 创建树节点, 并链接
self.historys.obj_paths[commit_name] = self.historys.branches[self.branch] self.historys.obj_paths[commit_name] = self.historys.branches[self.branch]
self.historys.branches[self.branch] = commit_name self.historys.branches[self.branch] = commit_name
(self.historys_file.GetDirToolFile()|commit_name).SaveAsText(root.model_dump_json()) (self.historys_file.GetDirToolFile()|commit_name).SaveAsBinary(pickle.dumps(root))
(self.historys_file).SaveAsText(self.historys.model_dump_json()) (self.historys_file).SaveAsBinary(pickle.dumps(self.historys))
def view(self, commit_name:Optional[str]=None) -> None: def view(self, commit_name:Optional[str]=None) -> None:
if commit_name is None or commit_name == "": if commit_name is None or commit_name == "":
@@ -235,10 +249,15 @@ class Cli:
def restore(self) -> None: def restore(self) -> None:
head_commit = str(self.historys.ReadBranchHeadCommit(self.branch, self.historys_file.GetDirToolFile())) head_commit = str(self.historys.ReadBranchHeadCommit(self.branch, self.historys_file.GetDirToolFile()))
self.file.SaveAsText(head_commit) self.file.SaveAsText(head_commit)
PrintColorful(ConsoleFrontColor.LIGHTMAGENTA_EX, f"\nRestored {self.file.GetAbsPath()}")
def take(self, commit_name:str) -> None: def take(self, commit_name:Optional[str]=None) -> None:
commit = self.historys.ReadCommit(commit_name, self.historys_file.GetDirToolFile()) if commit_name is None or commit_name == "":
self.file.SaveAsText(commit.content) head_commit = str(self.historys.ReadBranchHeadCommit(self.branch, self.historys_file.GetDirToolFile()))
else:
head_commit = str(self.historys.ReadCommit(commit_name, self.historys_file.GetDirToolFile()))
self.file.SaveAsText(head_commit)
PrintColorful(ConsoleFrontColor.LIGHTMAGENTA_EX, f"\nTaken {self.file} to commit {"head" if commit_name is None or commit_name == "" else commit_name}")
def run() -> int: def run() -> int:
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@@ -278,7 +297,7 @@ def run() -> int:
cli.save() cli.save()
return 0 return 0
# 查看记录内容 # 查看记录内容
elif "view" in args: elif args.view is not None:
cli.view(args.view) cli.view(args.view)
return 0 return 0
# 恢复 # 恢复
@@ -286,7 +305,7 @@ def run() -> int:
cli.restore() cli.restore()
return 0 return 0
# 获取指定提交的文件 # 获取指定提交的文件
elif "take" in args: elif args.take is not None:
cli.take(args.take) cli.take(args.take)
return 0 return 0