light-fw-cli-core 0.7.0

Ядро CLI Light: анализ проекта, управление компонентами и light.lock
use thiserror::Error;

/// Ошибки CLI-операций `light`.
#[derive(Debug, Error)]
pub enum Error {
    /// Ошибка ввода-вывода.
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),

    /// Ошибка разбора TOML.
    #[error("TOML parse error: {0}")]
    Toml(#[from] toml_edit::TomlError),

    /// Ошибка сериализации TOML.
    #[error("TOML serialize error: {0}")]
    TomlSer(#[from] toml_edit::ser::Error),

    /// Ошибка JSON.
    #[error("JSON error: {0}")]
    Json(#[from] serde_json::Error),

    /// Ошибка разбора semver-версии или диапазона.
    #[error("Semver error: {0}")]
    Semver(#[from] semver::Error),

    /// Ошибка обхода каталога.
    #[error("Walkdir error: {0}")]
    Walkdir(#[from] walkdir::Error),

    /// Ошибка чтения `.gitignore`/`.ignore`.
    #[error("Ignore error: {0}")]
    Ignore(#[from] ignore::Error),

    /// Ошибка разбора HTML-шаблона.
    #[error("Template parse error: {0}")]
    TemplateParse(String),

    /// Ошибка манифеста компонента.
    #[error("Manifest error: {0}")]
    Manifest(String),

    /// Внешний процесс завершился с ненулевым кодом.
    #[error("команда `{program}` завершилась с кодом {code}: {stderr}")]
    CommandFailed {
        /// Имя запущенной программы.
        program: String,
        /// Код возврата.
        code: i32,
        /// Вывод в stderr.
        stderr: String,
    },

    /// Исполняемый файл не найден в `PATH`.
    #[error("команда `{0}` не найдена (установлен ли инструмент?)")]
    CommandNotFound(String),

    /// Компонент не найден ни в workspace, ни в vendor, ни в реестре.
    #[error("компонент `{0}` не найден")]
    ComponentNotFound(String),

    /// Имя не относится к компонентам Light (не `light-fw-*`).
    #[error("`{0}` не является компонентом Light: имя должно начинаться с `light-fw-`")]
    NotComponent(String),

    /// Компонент несовместим с текущим ядром проекта или другими компонентами.
    #[error("компонент `{component}` несовместим: {reason}")]
    Incompatible {
        /// Имя компонента.
        component: String,
        /// Причина несовместимости.
        reason: String,
    },

    /// Компонент не подключён к проекту.
    #[error("компонент `{0}` не установлен")]
    NotInstalled(String),

    /// Конфликт между компонентами (`conflicts`).
    #[error("конфликт компонентов: {0}")]
    Conflict(String),

    /// От него зависят другие компоненты.
    #[error("от компонента `{0}` зависят другие компоненты — удалите их вместе")]
    InUse(String),

    /// Операция отменена пользователем.
    #[error("операция отменена")]
    Aborted,

    /// Требуется сеть, но включён `--offline`.
    #[error(
        "компонент `{0}` не найден в vendor/, установите его без `--offline` на машине с сетью"
    )]
    Offline(String),

    /// Ошибка работы с `light.lock`.
    #[error("ошибка light.lock: {0}")]
    Lockfile(String),

    /// Ошибка резервного копирования/восстановления.
    #[error("ошибка резервной копии: {0}")]
    Backup(String),

    /// Ошибка публикации: граф зависимостей, версии, pre-flight.
    #[error("ошибка публикации: {0}")]
    Publish(String),

    /// Ошибка создания проекта (`light init`).
    #[error("ошибка init: {0}")]
    Init(String),

    /// Версия крейта уже опубликована на crates.io.
    #[error(
        "crate {name} v{version} already published; bump version in Cargo.toml before publishing"
    )]
    AlreadyPublished {
        /// Имя крейта.
        name: String,
        /// Уже опубликованная версия.
        version: String,
    },

    /// Сетевой запрос к crates.io завершился ошибкой.
    #[cfg(feature = "network")]
    #[error("сетевой запрос не удался: {0}")]
    Http(#[from] reqwest::Error),
}

/// Результат CLI-операции с [`enum@Error`].
pub type Result<T> = std::result::Result<T, Error>;