-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathproject_manager.py
More file actions
154 lines (128 loc) · 4.79 KB
/
project_manager.py
File metadata and controls
154 lines (128 loc) · 4.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import os
import fnmatch
class ProjectManager:
def __init__(self):
"""初始化项目管理器"""
# 忽略的文件和目录模式
self.ignore_patterns = [
"__pycache__",
"*.pyc",
".git",
".vscode",
"venv",
"env",
"*.exe",
"*.dll",
"*.so",
"*.dylib",
"node_modules",
"*.zip",
"*.tar.gz",
"*.rar"
]
# 支持的文本文件扩展名
self.text_extensions = [
".py", ".js", ".html", ".css", ".json", ".xml", ".md", ".txt",
".yml", ".yaml", ".toml", ".ini", ".cfg", ".conf", ".sh", ".bat",
".c", ".cpp", ".h", ".hpp", ".java", ".go", ".rs", ".ts", ".jsx", ".tsx"
]
# 最大文件大小(字节)
self.max_file_size = 1024 * 1024 # 1MB
def scan_project(self, project_path):
"""扫描项目文件夹,返回所有文本文件的路径
Args:
project_path: 项目文件夹路径
Returns:
文本文件路径列表
"""
text_files = []
for root, dirs, files in os.walk(project_path):
# 过滤掉忽略的目录
dirs[:] = [d for d in dirs if not self._should_ignore(d)]
for file in files:
if self._should_ignore(file):
continue
file_path = os.path.join(root, file)
# 检查文件大小
try:
if os.path.getsize(file_path) > self.max_file_size:
continue
except OSError:
continue
# 检查是否为文本文件
if self._is_text_file(file_path):
text_files.append(file_path)
return text_files
def read_file(self, file_path):
"""读取文件内容
Args:
file_path: 文件路径
Returns:
文件内容,如果读取失败则返回None
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
return f.read()
except Exception as e:
print(f"无法读取文件 {file_path}: {str(e)}")
try:
# 尝试使用其他编码
with open(file_path, 'r', encoding='gbk') as f:
return f.read()
except Exception:
return None
def save_file(self, file_path, content):
"""保存文件内容
Args:
file_path: 文件路径
content: 文件内容
Returns:
是否保存成功
"""
try:
# 确保目录存在
os.makedirs(os.path.dirname(file_path), exist_ok=True)
with open(file_path, 'w', encoding='utf-8') as f:
f.write(content)
return True
except Exception as e:
print(f"无法保存文件 {file_path}: {str(e)}")
return False
def _should_ignore(self, name):
"""检查文件或目录是否应该被忽略
Args:
name: 文件或目录名
Returns:
是否应该被忽略
"""
return any(fnmatch.fnmatch(name, pattern) for pattern in self.ignore_patterns)
def _is_text_file(self, file_path):
"""检查是否为文本文件
Args:
file_path: 文件路径
Returns:
是否为文本文件
"""
# 检查扩展名
ext = os.path.splitext(file_path)[1].lower()
if ext in self.text_extensions:
return True
# 如果没有扩展名或扩展名不在列表中,尝试读取文件的前几个字节
try:
with open(file_path, 'rb') as f:
sample = f.read(1024)
# 检查是否包含空字节(二进制文件通常包含空字节)
if b'\x00' in sample:
return False
# 尝试解码为文本
try:
sample.decode('utf-8')
return True
except UnicodeDecodeError:
try:
sample.decode('gbk')
return True
except UnicodeDecodeError:
return False
except Exception:
return False