Initial commit to new repository
This commit is contained in:
151
src/AxCopilot/Services/StorageAnalyzer.cs
Normal file
151
src/AxCopilot/Services/StorageAnalyzer.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using System.IO;
|
||||
|
||||
namespace AxCopilot.Services;
|
||||
|
||||
/// <summary>
|
||||
/// 앱의 저장 공간 사용량을 분석하고 정리 기능을 제공합니다.
|
||||
/// </summary>
|
||||
public static class StorageAnalyzer
|
||||
{
|
||||
private static readonly string AppDataDir = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot");
|
||||
|
||||
/// <summary>저장 공간 분석 결과를 반환합니다.</summary>
|
||||
public static StorageReport Analyze()
|
||||
{
|
||||
var report = new StorageReport();
|
||||
|
||||
// 앱 데이터 폴더별 크기 계산
|
||||
report.Conversations = GetFolderSize(Path.Combine(AppDataDir, "conversations"));
|
||||
report.AuditLogs = GetFolderSize(Path.Combine(AppDataDir, "audit"));
|
||||
report.Logs = GetFolderSize(Path.Combine(AppDataDir, "logs"));
|
||||
report.CodeIndex = GetFolderSize(Path.Combine(AppDataDir, "code_index"));
|
||||
report.EmbeddingDb = GetFolderSize(Path.Combine(AppDataDir, "embeddings"));
|
||||
report.ClipboardHistory = GetFileSize(Path.Combine(AppDataDir, "clipboard_history.dat"));
|
||||
report.Plugins = GetFolderSize(Path.Combine(AppDataDir, "plugins"));
|
||||
report.Skills = GetFolderSize(Path.Combine(AppDataDir, "skills"));
|
||||
report.Settings = GetFileSize(Path.Combine(AppDataDir, "settings.json"));
|
||||
|
||||
// 앱 실행 파일 위치의 드라이브 여유 공간
|
||||
var exeDir = Path.GetDirectoryName(Environment.ProcessPath) ?? AppDataDir;
|
||||
try
|
||||
{
|
||||
var drive = new DriveInfo(Path.GetPathRoot(exeDir) ?? "C:");
|
||||
report.DriveLabel = drive.Name;
|
||||
report.DriveFreeSpace = drive.AvailableFreeSpace;
|
||||
report.DriveTotalSpace = drive.TotalSize;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/// <summary>지정된 기간보다 오래된 데이터를 삭제합니다.</summary>
|
||||
/// <param name="retainDays">보관 일수 (7/14/30). 0이면 전체 삭제.</param>
|
||||
/// <returns>삭제된 바이트 수</returns>
|
||||
public static long Cleanup(int retainDays, bool cleanConversations, bool cleanAuditLogs,
|
||||
bool cleanLogs, bool cleanCodeIndex, bool cleanClipboard)
|
||||
{
|
||||
long freed = 0;
|
||||
var cutoff = DateTime.Now.AddDays(-retainDays);
|
||||
|
||||
if (cleanConversations)
|
||||
freed += CleanFolder(Path.Combine(AppDataDir, "conversations"), cutoff, retainDays == 0);
|
||||
|
||||
if (cleanAuditLogs)
|
||||
freed += CleanFolder(Path.Combine(AppDataDir, "audit"), cutoff, retainDays == 0);
|
||||
|
||||
if (cleanLogs)
|
||||
freed += CleanFolder(Path.Combine(AppDataDir, "logs"), cutoff, retainDays == 0);
|
||||
|
||||
if (cleanCodeIndex)
|
||||
freed += CleanFolder(Path.Combine(AppDataDir, "code_index"), cutoff, true); // 인덱스는 전체 삭제
|
||||
|
||||
if (cleanClipboard)
|
||||
{
|
||||
var clipFile = Path.Combine(AppDataDir, "clipboard_history.dat");
|
||||
if (File.Exists(clipFile))
|
||||
{
|
||||
freed += new FileInfo(clipFile).Length;
|
||||
File.Delete(clipFile);
|
||||
}
|
||||
}
|
||||
|
||||
return freed;
|
||||
}
|
||||
|
||||
private static long GetFolderSize(string path)
|
||||
{
|
||||
if (!Directory.Exists(path)) return 0;
|
||||
try
|
||||
{
|
||||
return Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories)
|
||||
.Sum(f => { try { return new FileInfo(f).Length; } catch { return 0; } });
|
||||
}
|
||||
catch { return 0; }
|
||||
}
|
||||
|
||||
private static long GetFileSize(string path)
|
||||
{
|
||||
try { return File.Exists(path) ? new FileInfo(path).Length : 0; }
|
||||
catch { return 0; }
|
||||
}
|
||||
|
||||
private static long CleanFolder(string path, DateTime cutoff, bool deleteAll)
|
||||
{
|
||||
if (!Directory.Exists(path)) return 0;
|
||||
long freed = 0;
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fi = new FileInfo(file);
|
||||
if (deleteAll || fi.LastWriteTime < cutoff)
|
||||
{
|
||||
freed += fi.Length;
|
||||
fi.Delete();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// 빈 디렉토리 정리
|
||||
if (deleteAll)
|
||||
{
|
||||
try { Directory.Delete(path, true); Directory.CreateDirectory(path); } catch { }
|
||||
}
|
||||
|
||||
return freed;
|
||||
}
|
||||
|
||||
/// <summary>바이트를 읽기 좋은 형태로 변환합니다.</summary>
|
||||
public static string FormatSize(long bytes)
|
||||
{
|
||||
if (bytes < 1024) return $"{bytes} B";
|
||||
if (bytes < 1024 * 1024) return $"{bytes / 1024.0:F1} KB";
|
||||
if (bytes < 1024L * 1024 * 1024) return $"{bytes / (1024.0 * 1024):F1} MB";
|
||||
return $"{bytes / (1024.0 * 1024 * 1024):F2} GB";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>저장 공간 분석 결과.</summary>
|
||||
public class StorageReport
|
||||
{
|
||||
public long Conversations { get; set; }
|
||||
public long AuditLogs { get; set; }
|
||||
public long Logs { get; set; }
|
||||
public long CodeIndex { get; set; }
|
||||
public long EmbeddingDb { get; set; }
|
||||
public long ClipboardHistory { get; set; }
|
||||
public long Plugins { get; set; }
|
||||
public long Skills { get; set; }
|
||||
public long Settings { get; set; }
|
||||
|
||||
public string DriveLabel { get; set; } = "";
|
||||
public long DriveFreeSpace { get; set; }
|
||||
public long DriveTotalSpace { get; set; }
|
||||
|
||||
/// <summary>앱 전체 사용량.</summary>
|
||||
public long TotalAppUsage => Conversations + AuditLogs + Logs + CodeIndex + EmbeddingDb + ClipboardHistory + Plugins + Skills + Settings;
|
||||
}
|
||||
Reference in New Issue
Block a user