Files
2026-05-10 10:56:52 +08:00

227 lines
9.1 KiB
Python

import os
# 1. 给 SSHManager 添加 upload_directory 方法
ssh_path = "src/virtualbox_client/utils/ssh_manager.py"
with open(ssh_path, "r", encoding="utf-8") as f:
content = f.read()
old_method = """ def upload_file(self, local_path, remote_path):
\"\"\"上传本地文件到远程服务器,返回是否成功\"\"\"
client = self.get_ssh_client()
if not client:
return False
try:
sftp = client.open_sftp()
sftp.put(local_path, remote_path)
sftp.close()
print(f\"✔ 上传成功: {local_path} -> {remote_path}\")
return True
except Exception as e:
if self._cancelled.is_set():
return False
print(f\"✘ 上传失败: {e}\")
return False
"""
new_method = """ def upload_file(self, local_path, remote_path):
\"\"\"上传本地文件到远程服务器,返回是否成功\"\"\"
client = self.get_ssh_client()
if not client:
return False
try:
sftp = client.open_sftp()
sftp.put(local_path, remote_path)
sftp.close()
print(f\"✔ 上传成功: {local_path} -> {remote_path}\")
return True
except Exception as e:
if self._cancelled.is_set():
return False
print(f\"✘ 上传失败: {e}\")
return False
def upload_directory(self, local_dir, remote_dir):
\"\"\"递归上传整个文件夹到远程服务器,返回是否成功\"\"\"
import os as _os
client = self.get_ssh_client()
if not client:
return False
try:
sftp = client.open_sftp()
local_dir = _os.path.normpath(local_dir)
remote_dir = remote_dir.rstrip('/')
# 创建远程根目录
self.exec_command(f'mkdir -p \"{remote_dir}\"')
for root, dirs, files in _os.walk(local_dir):
# 计算相对路径
rel_path = _os.path.relpath(root, local_dir)
if rel_path == '.':
rel_path = ''
# 创建远程子目录
target_dir = remote_dir + ('/' + rel_path.replace('\\\\', '/') if rel_path else '')
self.exec_command(f'mkdir -p \"{target_dir}\"')
for fname in files:
if self._cancelled.is_set():
sftp.close()
return False
local_file = _os.path.join(root, fname)
remote_file = target_dir + '/' + fname
sftp.put(local_file, remote_file)
print(f\" ✔ {local_file} -> {remote_file}\")
sftp.close()
print(f\"✔ 文件夹上传成功: {local_dir} -> {remote_dir}\")
return True
except Exception as e:
if self._cancelled.is_set():
return False
print(f\"✘ 文件夹上传失败: {e}\")
return False
"""
content = content.replace(old_method, new_method)
with open(ssh_path, "w", encoding="utf-8") as f:
f.write(content)
print("✅ SSHManager 已添加 upload_directory")
# 2. 给 VBoxSSHManager 添加 upload_directory 方法
vbox_path = "src/virtualbox_client/utils/vbox_ssh_manager.py"
with open(vbox_path, "r", encoding="utf-8") as f:
content = f.read()
content = content.replace(old_method, new_method)
with open(vbox_path, "w", encoding="utf-8") as f:
f.write(content)
print("✅ VBoxSSHManager 已添加 upload_directory")
# 3. 修改 gui.py - 添加上传文件夹功能
gui_path = "src/virtualbox_client/gui.py"
with open(gui_path, "r", encoding="utf-8") as f:
content = f.read()
# 在 WorkspaceWorker 中添加 OPERATION_UPLOAD_DIR
old_op = ' OPERATION_UPLOAD = "upload"\n'
new_op = ' OPERATION_UPLOAD = "upload"\n OPERATION_UPLOAD_DIR = "upload_dir"\n'
content = content.replace(old_op, new_op)
# 在 run 方法中添加分支
old_run = """ elif self.operation == WorkspaceWorker.OPERATION_UPLOAD:
result = self._upload_file(vm)"""
new_run = """ elif self.operation == WorkspaceWorker.OPERATION_UPLOAD:
result = self._upload_file(vm)
elif self.operation == WorkspaceWorker.OPERATION_UPLOAD_DIR:
result = self._upload_directory(vm)"""
content = content.replace(old_run, new_run)
# 在 _upload_file 之后添加 _upload_directory 方法
old_upload = """ def _upload_file(self, vm) -> bool:
local_path = self.kwargs.get("local_path", "")
remote_path = self.kwargs.get("remote_path", "")
if not local_path or not remote_path:
return False
remote_dir = remote_path.rsplit('/', 1)[0] if '/' in remote_path else remote_path.rsplit('\\\\', 1)[0]
vm.exec_command(f'mkdir -p "{remote_dir}"')
return vm.upload_file(local_path, remote_path)"""
new_upload = """ def _upload_file(self, vm) -> bool:
local_path = self.kwargs.get("local_path", "")
remote_path = self.kwargs.get("remote_path", "")
if not local_path or not remote_path:
return False
remote_dir = remote_path.rsplit('/', 1)[0] if '/' in remote_path else remote_path.rsplit('\\\\', 1)[0]
vm.exec_command(f'mkdir -p "{remote_dir}"')
return vm.upload_file(local_path, remote_path)
def _upload_directory(self, vm) -> bool:
local_dir = self.kwargs.get("local_path", "")
remote_dir = self.kwargs.get("remote_path", "")
if not local_dir or not remote_dir:
return False
return vm.upload_directory(local_dir, remote_dir)"""
content = content.replace(old_upload, new_upload)
# 修改 _on_worker_finished 添加 UPLOAD_DIR 处理
old_finish = """ elif (
self._worker and self._worker.operation == WorkspaceWorker.OPERATION_UPLOAD
):
if result:
self.log_panel.append_log("✅ 上传成功", "success")
else:
self.log_panel.append_log("❌ 上传失败", "error")
QTimer.singleShot(500, self._soft_refresh)"""
new_finish = """ elif (
self._worker
and self._worker.operation
in (WorkspaceWorker.OPERATION_UPLOAD, WorkspaceWorker.OPERATION_UPLOAD_DIR)
):
if result:
self.log_panel.append_log("✅ 上传成功", "success")
else:
self.log_panel.append_log("❌ 上传失败", "error")
QTimer.singleShot(500, self._soft_refresh)"""
content = content.replace(old_finish, new_finish)
# 在 WorkspacePanel.setup_ui 的工具栏中添加"上传文件夹"按钮
old_upload_btn = """ self.upload_btn = QPushButton("📤 上传文件")"""
new_upload_btn = """ self.upload_btn = QPushButton("📤 上传文件")"""
# 保持原样,在后面添加新按钮
# 在 upload_btn 后面添加 upload_dir_btn
old_toolbar = """ toolbar.addWidget(self.upload_btn)
self.mkdir_btn = QPushButton("📂 新建文件夹")"""
new_toolbar = """ toolbar.addWidget(self.upload_btn)
self.upload_dir_btn = QPushButton("📁 上传文件夹")
self.upload_dir_btn.setStyleSheet(\"\"\"
QPushButton { background-color: #16a085; color: white; padding: 6px 14px;
font-size: 12px; font-weight: bold; border: none; border-radius: 4px; }
QPushButton:hover { background-color: #1abc9c; }
QPushButton:disabled { background-color: #555; color: #999; }
\"\"\")
self.upload_dir_btn.clicked.connect(self._upload_folder_to_workspace)
toolbar.addWidget(self.upload_dir_btn)
self.mkdir_btn = QPushButton("📂 新建文件夹")"""
content = content.replace(old_toolbar, new_toolbar)
# 更新 _set_busy 禁用 upload_dir_btn
old_set_busy = """ self.upload_btn.setEnabled(not busy)
self.mkdir_btn.setEnabled(not busy)
self.home_btn.setEnabled(not busy)"""
new_set_busy = """ self.upload_btn.setEnabled(not busy)
self.upload_dir_btn.setEnabled(not busy)
self.mkdir_btn.setEnabled(not busy)
self.home_btn.setEnabled(not busy)"""
content = content.replace(old_set_busy, new_set_busy)
# 在 _upload_to_workspace 方法之后添加 _upload_folder_to_workspace
old_upload_workspace = """ def _upload_to_workspace(self):"""
new_upload_workspace = """ def _upload_folder_to_workspace(self):
if not self._config_panel or not self._validate_ssh_config():
return
local_dir = QFileDialog.getExistingDirectory(self, "选择要上传到工作区的文件夹")
if not local_dir:
return
folder_name = os.path.basename(local_dir.rstrip('/\\\\'))
remote_path = f"~/workspace/{folder_name}"
self._start_worker(
WorkspaceWorker.OPERATION_UPLOAD_DIR,
local_path=local_dir,
remote_path=remote_path,
)
def _upload_to_workspace(self):"""
content = content.replace(old_upload_workspace, new_upload_workspace)
with open(gui_path, "w", encoding="utf-8") as f:
f.write(content)
print("✅ gui.py 已添加上传文件夹功能")
print("\\n所有修改完成!")