Skip to content

Commit b0063da

Browse files
authored
Merge pull request #66 from qianmoQ/dev-25.0.5
2 parents 9bc965c + 986a239 commit b0063da

File tree

13 files changed

+432
-37
lines changed

13 files changed

+432
-37
lines changed

src-tauri/capabilities/default.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@
1111
{
1212
"identifier": "opener:allow-open-path",
1313
"allow": [
14+
{
15+
"path": "$HOME/.codeforge/**"
16+
},
17+
{
18+
"path": "$APPDATA/**"
19+
},
20+
{
21+
"path": "$LOCALAPPDATA/**"
22+
},
1423
{
1524
"path": "**"
1625
}
@@ -20,9 +29,19 @@
2029
"shell:allow-open",
2130
"dialog:default",
2231
"fs:allow-read-text-file",
32+
"fs:allow-read-dir",
33+
"fs:allow-read-file",
34+
"fs:allow-write-file",
35+
"fs:allow-write-text-file",
36+
"fs:allow-remove",
37+
"fs:allow-mkdir",
38+
"fs:allow-exists",
2339
{
2440
"identifier": "fs:scope",
2541
"allow": [
42+
{
43+
"path": "$HOME/.codeforge/**"
44+
},
2645
{
2746
"path": "/var/folders/**"
2847
},
@@ -32,6 +51,12 @@
3251
{
3352
"path": "/private/var/folders/**"
3453
},
54+
{
55+
"path": "$APPDATA/**"
56+
},
57+
{
58+
"path": "$LOCALAPPDATA/**"
59+
},
3560
{
3661
"path": "**"
3762
}

src-tauri/src/cache.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use log::info;
2+
use serde::{Deserialize, Serialize};
3+
use std::fs;
4+
use std::path::PathBuf;
5+
6+
#[derive(Debug, Serialize, Deserialize)]
7+
pub struct CacheInfo {
8+
pub plugins_cache_size: u64,
9+
pub total_cache_size: u64,
10+
}
11+
12+
// 获取缓存目录
13+
fn get_cache_dir() -> Result<PathBuf, String> {
14+
let home_dir = dirs::home_dir().ok_or("无法获取用户主目录")?;
15+
Ok(home_dir.join(".codeforge").join("cache"))
16+
}
17+
18+
// 获取插件缓存目录
19+
fn get_plugins_cache_dir() -> Result<PathBuf, String> {
20+
let cache_dir = get_cache_dir()?;
21+
Ok(cache_dir.join("plugins"))
22+
}
23+
24+
// 计算目录大小
25+
fn calculate_dir_size(path: &PathBuf) -> u64 {
26+
if !path.exists() {
27+
return 0;
28+
}
29+
30+
let mut total_size = 0u64;
31+
32+
if let Ok(entries) = fs::read_dir(path) {
33+
for entry in entries.flatten() {
34+
let path = entry.path();
35+
if path.is_file() {
36+
if let Ok(metadata) = fs::metadata(&path) {
37+
total_size += metadata.len();
38+
}
39+
} else if path.is_dir() {
40+
total_size += calculate_dir_size(&path);
41+
}
42+
}
43+
}
44+
45+
total_size
46+
}
47+
48+
// 获取缓存信息
49+
#[tauri::command]
50+
pub fn get_cache_info() -> Result<CacheInfo, String> {
51+
info!("获取缓存信息");
52+
53+
let cache_dir = get_cache_dir()?;
54+
let plugins_cache_dir = get_plugins_cache_dir()?;
55+
56+
let plugins_cache_size = calculate_dir_size(&plugins_cache_dir);
57+
let total_cache_size = calculate_dir_size(&cache_dir);
58+
59+
Ok(CacheInfo {
60+
plugins_cache_size,
61+
total_cache_size,
62+
})
63+
}
64+
65+
// 清理插件缓存
66+
#[tauri::command]
67+
pub fn clear_plugins_cache() -> Result<(), String> {
68+
info!("清理插件缓存");
69+
70+
let plugins_cache_dir = get_plugins_cache_dir()?;
71+
72+
if plugins_cache_dir.exists() {
73+
fs::remove_dir_all(&plugins_cache_dir)
74+
.map_err(|e| format!("删除插件缓存目录失败: {}", e))?;
75+
76+
// 重新创建空目录
77+
fs::create_dir_all(&plugins_cache_dir)
78+
.map_err(|e| format!("创建插件缓存目录失败: {}", e))?;
79+
}
80+
81+
info!("插件缓存已清理");
82+
Ok(())
83+
}
84+
85+
// 清理所有缓存
86+
#[tauri::command]
87+
pub fn clear_all_cache() -> Result<(), String> {
88+
info!("清理所有缓存");
89+
90+
let cache_dir = get_cache_dir()?;
91+
92+
if cache_dir.exists() {
93+
fs::remove_dir_all(&cache_dir).map_err(|e| format!("删除缓存目录失败: {}", e))?;
94+
95+
// 重新创建空目录
96+
fs::create_dir_all(&cache_dir).map_err(|e| format!("创建缓存目录失败: {}", e))?;
97+
}
98+
99+
info!("所有缓存已清理");
100+
Ok(())
101+
}

src-tauri/src/env_providers/clojure.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl ClojureEnvironmentProvider {
5151

5252
fn get_default_install_dir() -> PathBuf {
5353
let home_dir = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
54-
home_dir.join(".codeforge").join("clojure")
54+
home_dir.join(".codeforge").join("plugins").join("clojure")
5555
}
5656

5757
fn read_cache(&self) -> Option<Vec<GithubRelease>> {

src-tauri/src/env_providers/metadata.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub async fn fetch_metadata_from_cdn(language: &str) -> Result<Metadata, String>
6666
.and_then(|m| m.base_url.as_ref())
6767
.ok_or("CDN 地址未配置")?;
6868

69-
let metadata_url = format!("{}/{}/metadata.json", base_url, language);
69+
let metadata_url = format!("{}/global/plugins/{}/metadata.json", base_url, language);
7070
info!("从 CDN 获取 {} metadata: {}", language, metadata_url);
7171

7272
let client = reqwest::Client::builder()

src-tauri/src/env_providers/scala.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl ScalaEnvironmentProvider {
5555

5656
fn get_default_install_dir() -> PathBuf {
5757
let home_dir = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
58-
home_dir.join(".codeforge").join("scala")
58+
home_dir.join(".codeforge").join("plugins").join("scala")
5959
}
6060

6161
// 从缓存读取版本列表

src-tauri/src/execution.rs

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use log::{error, info, warn};
33
use std::collections::HashMap;
44
use std::fs;
55
use std::io::{BufRead, BufReader};
6+
use std::path::PathBuf;
67
use std::process::{Command, Stdio};
78
use std::sync::{Arc, OnceLock, mpsc};
89
use std::thread;
@@ -34,6 +35,39 @@ fn init_task_manager() -> TaskManager {
3435
.clone()
3536
}
3637

38+
// 获取 .codeforge 缓存目录
39+
fn get_codeforge_cache_dir(language: &str) -> Result<PathBuf, String> {
40+
let home_dir = dirs::home_dir().ok_or("无法获取用户主目录")?;
41+
let cache_dir = home_dir
42+
.join(".codeforge")
43+
.join("cache")
44+
.join("plugins")
45+
.join(language);
46+
47+
// 确保目录存在
48+
fs::create_dir_all(&cache_dir).map_err(|e| format!("创建缓存目录失败: {}", e))?;
49+
50+
Ok(cache_dir)
51+
}
52+
53+
// 检查是否应该过滤 stderr 行
54+
fn should_filter_stderr_line(language: &str, line: &str) -> bool {
55+
match language {
56+
"clojure" => {
57+
// 过滤 Clojure 的常见警告信息
58+
line.contains("WARNING: Implicit use of clojure.main")
59+
|| line.contains("WARNING: name already refers to:")
60+
}
61+
"scala" => {
62+
// 过滤 Scala 的编译信息
63+
line.contains("[0m[0m[33mCompiling project")
64+
|| line.contains("[0m[0m")
65+
|| line.starts_with("\u{001b}")
66+
}
67+
_ => false,
68+
}
69+
}
70+
3771
// 停止执行命令
3872
#[tauri::command]
3973
pub async fn stop_execution(language: String) -> Result<bool, String> {
@@ -80,13 +114,17 @@ pub async fn execute_code(
80114
.get_plugin(&request.language)
81115
.ok_or_else(|| format!("Unsupported language: {}", request.language))?;
82116

83-
let temp_dir = std::env::temp_dir();
84-
let file_name = format!(
85-
"Codeforge_{}.{}",
86-
request.language,
87-
plugin.get_file_extension()
88-
);
89-
let file_path = temp_dir.join(file_name.clone());
117+
// 使用 .codeforge/cache/plugin/<language> 目录
118+
let temp_dir = get_codeforge_cache_dir(&request.language)?;
119+
let timestamp = SystemTime::now()
120+
.duration_since(UNIX_EPOCH)
121+
.unwrap()
122+
.as_secs();
123+
let file_work = format!("Codeforge_{}_{}", request.language, timestamp);
124+
let work_dir = temp_dir.join(&file_work);
125+
fs::create_dir_all(&work_dir).map_err(|e| format!("创建工作目录失败: {}", e))?;
126+
let file_name = format!("{}.{}", file_work, plugin.get_file_extension());
127+
let file_path = work_dir.join(&file_name);
90128

91129
// 写入代码到临时文件
92130
fs::write(&file_path, &request.code)
@@ -274,14 +312,17 @@ pub async fn execute_code(
274312
// 读取并发送 stderr
275313
while let Ok(line) = stderr_rx.try_recv() {
276314
stderr_lines.push(line.clone());
277-
let _ = app.emit(
278-
"code-output",
279-
serde_json::json!({
280-
"type": "stderr",
281-
"content": line,
282-
"language": request.language
283-
}),
284-
);
315+
// 过滤掉特定语言的警告信息
316+
if !should_filter_stderr_line(&request.language, &line) {
317+
let _ = app.emit(
318+
"code-output",
319+
serde_json::json!({
320+
"type": "stderr",
321+
"content": line,
322+
"language": request.language
323+
}),
324+
);
325+
}
285326
}
286327

287328
// 检查进程是否结束
@@ -301,14 +342,17 @@ pub async fn execute_code(
301342
}
302343
while let Ok(line) = stderr_rx.try_recv() {
303344
stderr_lines.push(line.clone());
304-
let _ = app.emit(
305-
"code-output",
306-
serde_json::json!({
307-
"type": "stderr",
308-
"content": line,
309-
"language": request.language
310-
}),
311-
);
345+
// 过滤掉特定语言的警告信息
346+
if !should_filter_stderr_line(&request.language, &line) {
347+
let _ = app.emit(
348+
"code-output",
349+
serde_json::json!({
350+
"type": "stderr",
351+
"content": line,
352+
"language": request.language
353+
}),
354+
);
355+
}
312356
}
313357

314358
let execution_time = start_time.elapsed().as_millis();

src-tauri/src/logger.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,24 @@ fn get_effective_log_directory(app: &AppHandle) -> PathBuf {
107107
}
108108

109109
// 获取默认日志目录
110-
fn get_default_log_directory(app: &AppHandle) -> PathBuf {
111-
app.path()
112-
.app_data_dir()
113-
.expect("Failed to get app data dir")
114-
.join("logs")
110+
fn get_default_log_directory(_app: &AppHandle) -> PathBuf {
111+
let home_dir = dirs::home_dir().expect("Failed to get home directory");
112+
let log_dir = home_dir.join(".codeforge").join("logs");
113+
114+
// 确保目录存在
115+
if !log_dir.exists() {
116+
if let Err(e) = fs::create_dir_all(&log_dir) {
117+
eprintln!("Failed to create log directory: {}", e);
118+
// 如果创建失败,回退到应用数据目录
119+
return _app
120+
.path()
121+
.app_data_dir()
122+
.expect("Failed to get app data dir")
123+
.join("logs");
124+
}
125+
}
126+
127+
log_dir
115128
}
116129

117130
// 公共函数,供其他模块调用

src-tauri/src/main.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
windows_subsystem = "windows"
44
)]
55

6+
mod cache;
67
mod config;
78
mod env_commands;
89
mod env_manager;
@@ -17,6 +18,7 @@ mod setup;
1718
mod update;
1819
mod utils;
1920

21+
use crate::cache::{clear_all_cache, clear_plugins_cache, get_cache_info};
2022
use crate::env_commands::{
2123
EnvironmentManagerState, download_and_install_version, get_environment_info,
2224
get_supported_environment_languages, switch_environment_version, uninstall_environment_version,
@@ -107,6 +109,10 @@ fn main() {
107109
get_app_config,
108110
update_app_config,
109111
get_config_path,
112+
// 缓存相关命令
113+
get_cache_info,
114+
clear_plugins_cache,
115+
clear_all_cache,
110116
// 更新相关命令
111117
check_for_updates,
112118
start_update,

src/components/Settings.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
<template #network>
2626
<Network v-if="activeTab === 'network'" @settings-changed="handleNetworkSettingsChanged" @error="handleEditorError"/>
2727
</template>
28+
29+
<!-- 缓存管理 -->
30+
<template #cache>
31+
<Cache v-if="activeTab === 'cache'"/>
32+
</template>
2833
</Tabs>
2934
</Modal>
3035
</template>
@@ -37,6 +42,7 @@ import General from './setting/General.vue'
3742
import Language from './setting/Language.vue'
3843
import Editor from './setting/Editor.vue'
3944
import Network from './setting/Network.vue'
45+
import Cache from './setting/Cache.vue'
4046
import { useSettings } from '../composables/useSettings.ts'
4147
4248
const emit = defineEmits<{

0 commit comments

Comments
 (0)