Files
AX-Copilot-Codex/src/AxCopilot/Services/StorageAnalyzer.cs

152 lines
5.4 KiB
C#

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;
}