use std::{
fmt,
path::{Path, PathBuf},
sync::Arc,
};
use schemars::JsonSchema;
use serde::Serialize;
use smol_str::SmolStr;
use crate::{
config_files::{ConfigFileDirs, ConfigFilePath},
git::GitFileStatus,
};
#[derive(Debug, Clone, PartialEq, Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum PkgEntry {
Pkg {
name: SmolStr,
key: SmolStr,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
state: PkgEntryState,
#[serde(skip_serializing_if = "Option::is_none")]
matched_detect: Option<String>,
install_hints: PkgInstallHints,
},
AggregateInstall {
pkg_manager: String,
command: String,
packages: Vec<String>,
},
NoPackageManagerDetected {
supported: Vec<String>,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum PkgEntryState {
Disabled,
Installed,
Missing,
}
#[derive(Debug, Clone, PartialEq, Default, Serialize, JsonSchema)]
pub struct PkgInstallHints {
#[serde(skip_serializing_if = "Vec::is_empty")]
pub brew: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum DoctorCheck {
Check {
section: DoctorSection,
label: SmolStr,
severity: DoctorSeverity,
value: String,
#[serde(skip_serializing_if = "Option::is_none")]
hint: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
detail: Vec<String>,
},
SectionHeader {
section: DoctorSection,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum DoctorSection {
System,
Repo,
Config,
PkgManager,
User,
Shell,
Packages,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum DoctorSeverity {
Ok,
Info,
Warn,
Bad,
}
#[derive(Debug, Clone, PartialEq, Serialize, JsonSchema)]
pub struct InitSummary {
pub clone_path: PathBuf,
#[serde(skip_serializing_if = "Option::is_none")]
pub remote: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub shell: Option<String>,
pub pkg_count: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ImportType {
DotConfig,
Home,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ImportFileAction {
MoveAndSymlink {
rel: PathBuf,
},
Skip {
path: PathBuf,
reason: SmolStr,
},
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum ImportTomlChange {
CreatePkg {
pkg: SmolStr,
brew_packages: Vec<String>,
block_preview: String,
},
AppendConfigsEntry {
pkg: SmolStr,
entry_preview: String,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, JsonSchema)]
pub struct ImportPlan {
pub pkg: SmolStr,
pub created_pkg: bool,
pub r#type: ImportType,
pub source: PathBuf,
pub repo_dest: PathBuf,
pub file_actions: Vec<ImportFileAction>,
pub toml_changes: Vec<ImportTomlChange>,
}
#[derive(Debug, Clone, PartialEq, Serialize, JsonSchema)]
pub struct ImportApplied {
pub pkg: SmolStr,
}
#[derive(Debug, Clone, PartialEq, Serialize, JsonSchema)]
pub struct BootstrapSummary {
pub repo_path: PathBuf,
#[serde(skip_serializing_if = "Option::is_none")]
pub shell: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
}
#[derive(Debug, PartialEq, Clone, Serialize, JsonSchema)]
#[serde(tag = "kind", content = "data", rename_all = "snake_case")]
pub enum SymlinkStatus {
Ok,
WrongLink(PathBuf),
New,
IsFile,
IsDir,
IsOther,
RealPathIsMissing,
DstDirIsMissing {
dir: ResolvedConfigFilePath,
},
}
#[derive(Debug, PartialEq, Clone, Eq, PartialOrd, Ord, Serialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum FileStatus {
Ok,
Modified,
New,
}
#[derive(Debug, PartialEq, Clone, Serialize, JsonSchema)]
#[serde(tag = "kind", content = "data", rename_all = "snake_case")]
pub enum PkgStatus {
Ok,
Missing {
install_command: Option<String>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, JsonSchema)]
pub struct ResolvedConfigFilePath {
pub path: ConfigFilePath,
pub full: Arc<Path>,
}
impl ResolvedConfigFilePath {
pub fn resolve(path: ConfigFilePath, dirs: &ConfigFileDirs) -> Self {
let full = Arc::from(path.resolved(dirs));
Self { path, full }
}
pub fn parent(&self) -> Option<Self> {
Some(Self {
path: self.path.parent()?,
full: self.full.parent().map(Arc::from)?,
})
}
}
impl fmt::Display for ResolvedConfigFilePath {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.path.human_path(), f)
}
}
#[derive(Debug, PartialEq, Clone, Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum Status {
Generated {
want_content: Arc<str>,
cur_content: Option<String>,
path: ResolvedConfigFilePath,
status: FileStatus,
},
Symlink {
real: ResolvedConfigFilePath,
symlink: ResolvedConfigFilePath,
status: SymlinkStatus,
},
Git {
repo: ResolvedConfigFilePath,
status: GitFileStatus,
},
GitRepoClean {
repo: ResolvedConfigFilePath,
},
Pkg {
pkg: SmolStr,
status: PkgStatus,
},
}
#[derive(Debug, PartialEq, Serialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum AppliedAction {
UpdatedFile(ResolvedConfigFilePath),
CreatedFile(ResolvedConfigFilePath),
CreatedSymlink {
real: ResolvedConfigFilePath,
symlink: ResolvedConfigFilePath,
},
ReplacedSymlink {
real: ResolvedConfigFilePath,
symlink: ResolvedConfigFilePath,
},
CreatedDir(ResolvedConfigFilePath),
}