1use std::fmt;
2use std::path::PathBuf;
3
4use chrono::{DateTime, Local};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub enum ProjectKind {
10 Rust,
11 Node,
12 Python,
13 Java,
14 DotNet,
15 Go,
16 Zig,
17 CMake,
18 Swift,
19 Elixir,
20 Haskell,
21 Dart,
22 Ruby,
23 Scala,
24 Unity,
25 Godot,
26 Terraform,
27}
28
29impl ProjectKind {
30 pub fn marker_files(&self) -> &[&str] {
32 match self {
33 Self::Rust => &["Cargo.toml"],
34 Self::Node => &["package.json"],
35 Self::Python => &["pyproject.toml", "setup.py", "requirements.txt"],
36 Self::Java => &["pom.xml", "build.gradle", "build.gradle.kts"],
37 Self::DotNet => &["*.csproj", "*.fsproj", "*.sln"],
38 Self::Go => &["go.mod"],
39 Self::Zig => &["build.zig"],
40 Self::CMake => &["CMakeLists.txt"],
41 Self::Swift => &["Package.swift"],
42 Self::Elixir => &["mix.exs"],
43 Self::Haskell => &["stack.yaml", "*.cabal"],
44 Self::Dart => &["pubspec.yaml"],
45 Self::Ruby => &["Gemfile"],
46 Self::Scala => &["build.sbt"],
47 Self::Unity => &["ProjectSettings/ProjectVersion.txt"],
48 Self::Godot => &["project.godot"],
49 Self::Terraform => &["main.tf", "*.tf"],
50 }
51 }
52
53 pub fn cleanable_dirs(&self) -> &[&str] {
55 match self {
56 Self::Rust => &["target"],
57 Self::Node => &["node_modules", ".next", ".nuxt", "dist", ".cache"],
58 Self::Python => &["__pycache__", ".venv", "venv", ".tox", "*.egg-info", ".mypy_cache", ".pytest_cache"],
59 Self::Java => &["target", "build", ".gradle"],
60 Self::DotNet => &["bin", "obj"],
61 Self::Go => &[], Self::Zig => &["zig-cache", "zig-out"],
63 Self::CMake => &["build", "cmake-build-debug", "cmake-build-release"],
64 Self::Swift => &[".build"],
65 Self::Elixir => &["_build", "deps"],
66 Self::Haskell => &[".stack-work"],
67 Self::Dart => &[".dart_tool", "build"],
68 Self::Ruby => &["vendor/bundle"],
69 Self::Scala => &["target", "project/target"],
70 Self::Unity => &["Library", "Temp", "Obj", "Logs"],
71 Self::Godot => &[".godot"],
72 Self::Terraform => &[".terraform"],
73 }
74 }
75
76 pub fn all() -> &'static [ProjectKind] {
78 &[
79 Self::Rust,
80 Self::Node,
81 Self::Python,
82 Self::Java,
83 Self::DotNet,
84 Self::Go,
85 Self::Zig,
86 Self::CMake,
87 Self::Swift,
88 Self::Elixir,
89 Self::Haskell,
90 Self::Dart,
91 Self::Ruby,
92 Self::Scala,
93 Self::Unity,
94 Self::Godot,
95 Self::Terraform,
96 ]
97 }
98}
99
100impl fmt::Display for ProjectKind {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 let name = match self {
103 Self::Rust => "Rust",
104 Self::Node => "Node.js",
105 Self::Python => "Python",
106 Self::Java => "Java",
107 Self::DotNet => ".NET",
108 Self::Go => "Go",
109 Self::Zig => "Zig",
110 Self::CMake => "CMake",
111 Self::Swift => "Swift",
112 Self::Elixir => "Elixir",
113 Self::Haskell => "Haskell",
114 Self::Dart => "Dart",
115 Self::Ruby => "Ruby",
116 Self::Scala => "Scala",
117 Self::Unity => "Unity",
118 Self::Godot => "Godot",
119 Self::Terraform => "Terraform",
120 };
121 write!(f, "{name}")
122 }
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct CleanTarget {
128 pub path: PathBuf,
130 pub name: String,
132 pub size_bytes: u64,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct ScannedProject {
139 pub path: PathBuf,
141 pub kind: ProjectKind,
143 pub name: String,
145 pub last_modified: DateTime<Local>,
147 pub clean_targets: Vec<CleanTarget>,
149 pub total_cleanable_bytes: u64,
151}