eazygit 0.5.1

A fast TUI for Git with staging, conflicts, rebase, and palette-first UX
Documentation
//! Effect types for side effects in TEA pattern.
//!
//! Effects represent operations that cannot be done purely:
//! - Git operations (stage, commit, push, etc.)
//! - File I/O
//! - Async operations
//!
//! Effects are returned from the update function and executed by the runtime.

use std::path::PathBuf;

/// Side effects that need to be executed outside the pure update function.
/// 
/// Each variant represents an async or I/O operation that the runtime
/// will execute and dispatch a result message when complete.
#[derive(Debug, Clone)]
pub enum Effect {
    // =========================================================================
    // Git Operations
    // =========================================================================
    
    /// Stage a file at the given path.
    GitStage { path: PathBuf },
    
    /// Unstage a file at the given path.
    GitUnstage { path: PathBuf },
    
    /// Stage all changes.
    GitStageAll,
    
    /// Unstage all changes.
    GitUnstageAll,
    
    /// Commit with the given message and options.
    GitCommit {
        message: String,
        amend: bool,
        author_name: Option<String>,
        author_email: Option<String>,
    },
    
    /// Push to remote.
    GitPush { force_with_lease: bool },
    
    /// Pull from remote.
    GitPull { rebase: bool },
    
    /// Fetch from remote.
    GitFetch,
    
    /// Checkout a branch.
    GitCheckout { branch: String },
    
    /// Create a new branch.
    GitCreateBranch { name: String, start_point: Option<String> },
    
    /// Delete a branch.
    GitDeleteBranch { name: String, force: bool },
    
    /// Start interactive rebase.
    GitRebaseStart { 
        base: String,
        use_root: bool,
        todo_content: String,
    },
    
    /// Continue rebase with optional message.
    GitRebaseContinue {
        message: Option<String>,
        author_name: Option<String>,
        author_email: Option<String>,
    },
    
    /// Abort the current rebase.
    GitRebaseAbort,
    
    /// Skip the current rebase step.
    GitRebaseSkip,
    
    /// Cherry-pick a commit.
    GitCherryPick { hash: String },
    
    /// Revert a commit.
    GitRevert { hash: String },
    
    /// Reset to a commit.
    GitReset { target: String, mode: ResetMode },
    
    /// Stash changes.
    GitStash { message: Option<String> },
    
    /// Pop a stash.
    GitStashPop { index: usize },
    
    /// Drop a stash.
    GitStashDrop { stash_ref: String },
    
    // =========================================================================
    // Refresh Operations
    // =========================================================================
    
    /// Refresh the status (working tree, staging area).
    RefreshStatus,
    
    /// Refresh the commit log.
    RefreshLog,
    
    /// Refresh the branch list.
    RefreshBranches,
    
    /// Refresh the stash list.
    RefreshStashes,
    
    /// Refresh everything.
    RefreshAll,
    
    /// Compute diff for a file.
    ComputeDiff { path: PathBuf, staged: bool },
    
    // =========================================================================
    // System Operations
    // =========================================================================
    
    /// Open a file in the external editor.
    OpenInEditor { path: PathBuf },
    
    /// Save configuration (e.g., persist theme choice).
    SaveConfig { key: String, value: String },
    
    /// Execute a custom command.
    ExecuteCustomCommand { name: String, command: String },
    
    // =========================================================================
    // Batch Operations
    // =========================================================================
    
    /// Execute multiple effects in sequence.
    Batch(Vec<Effect>),
    
    /// No-op effect (useful for conditional logic).
    None,
}

/// Reset mode for git reset operations.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResetMode {
    Soft,
    Mixed,
    Hard,
}

impl Effect {
    /// Create a batch of effects.
    pub fn batch(effects: Vec<Effect>) -> Self {
        Effect::Batch(effects)
    }
    
    /// Check if this is a no-op effect.
    pub fn is_none(&self) -> bool {
        matches!(self, Effect::None)
    }
}