Documentation
¶
Index ¶
- Constants
- func IsValidHandlerName(name string) bool
- type BaseHandler
- func (h *BaseHandler) Category() HandlerCategory
- func (h *BaseHandler) CheckStatus(file FileInput, checker StatusChecker) (HandlerStatus, error)
- func (h *BaseHandler) FormatClearedItem(item ClearedItem, dryRun bool) string
- func (h *BaseHandler) GetClearConfirmation(ctx ClearContext) *ConfirmationRequest
- func (h *BaseHandler) GetStateDirectoryName() string
- func (h *BaseHandler) Name() string
- func (h *BaseHandler) ValidateOperations(ops []Operation) error
- type ClearContext
- type ClearedItem
- type ConfirmationRequest
- type DataStoreStatusChecker
- type Executor
- type FileInput
- type Handler
- type HandlerCategory
- type HandlerMetadata
- type HandlerStatus
- type Operation
- type OperationResult
- type OperationType
- type StatusChecker
- type StatusState
Constants ¶
const ( // Configuration handlers HandlerSymlink = "symlink" HandlerPath = "path" HandlerShell = "shell" HandlerShellProfile = "shell_profile" // Provisioning handlers HandlerInstall = "install" HandlerHomebrew = "homebrew" )
Handler name constants to avoid hardcoded strings throughout the codebase. These constants centralize handler identification and reduce coupling. They will be used during the migration phases and can be removed once all handlers are migrated to the new architecture.
Variables ¶
This section is empty.
Functions ¶
func IsValidHandlerName ¶ added in v0.3.0
IsValidHandlerName checks if a handler name is recognized.
Types ¶
type BaseHandler ¶ added in v0.3.0
type BaseHandler struct {
// contains filtered or unexported fields
}
BaseHandler provides default implementations for optional handler methods. This is crucial for keeping handlers simple - they only override what they need.
func NewBaseHandler ¶ added in v0.3.0
func NewBaseHandler(name string, category HandlerCategory) BaseHandler
NewBaseHandler creates a new BaseHandler with the given name and category.
func (*BaseHandler) Category ¶ added in v0.3.0
func (h *BaseHandler) Category() HandlerCategory
func (*BaseHandler) CheckStatus ¶ added in v0.3.0
func (h *BaseHandler) CheckStatus(file FileInput, checker StatusChecker) (HandlerStatus, error)
CheckStatus provides a default implementation that returns unknown status Handlers should override this to provide specific status checking logic
func (*BaseHandler) FormatClearedItem ¶ added in v0.3.0
func (h *BaseHandler) FormatClearedItem(item ClearedItem, dryRun bool) string
func (*BaseHandler) GetClearConfirmation ¶ added in v0.3.0
func (h *BaseHandler) GetClearConfirmation(ctx ClearContext) *ConfirmationRequest
Default implementations return empty/nil to use system defaults
func (*BaseHandler) GetStateDirectoryName ¶ added in v0.3.0
func (h *BaseHandler) GetStateDirectoryName() string
func (*BaseHandler) Name ¶ added in v0.3.0
func (h *BaseHandler) Name() string
func (*BaseHandler) ValidateOperations ¶ added in v0.3.0
func (h *BaseHandler) ValidateOperations(ops []Operation) error
type ClearContext ¶ added in v0.3.0
type ClearContext struct {
Pack types.Pack // The pack being cleared
FS types.FS // For file operations
Paths types.Pather // For path resolution
DryRun bool // Whether this is a dry run
}
ClearContext provides all the resources needed for a handler to clean up
type ClearedItem ¶ added in v0.3.0
type ClearedItem struct {
Type string // "symlink", "brew_package", "script_output", etc.
Path string // What was removed/affected
Description string // Human-readable description
}
ClearedItem represents something that was removed during a clear operation
type ConfirmationRequest ¶ added in v0.3.0
type ConfirmationRequest struct {
ID string // Unique identifier for the confirmation
Title string // Question to ask the user
Description string // Additional context
Items []string // List of items affected (e.g., packages to uninstall)
}
ConfirmationRequest represents a request for user confirmation. This allows handlers like homebrew to customize their confirmation flow.
type DataStoreStatusChecker ¶ added in v0.3.0
type DataStoreStatusChecker struct {
// contains filtered or unexported fields
}
DataStoreStatusChecker implements StatusChecker using the datastore
func NewDataStoreStatusChecker ¶ added in v0.3.0
func NewDataStoreStatusChecker(dataStore datastore.DataStore, fs types.FS, pathsInstance types.Pather) *DataStoreStatusChecker
NewDataStoreStatusChecker creates a new status checker that uses the datastore
func (*DataStoreStatusChecker) GetMetadata ¶ added in v0.3.0
func (d *DataStoreStatusChecker) GetMetadata(packName, handlerName, key string) (string, error)
GetMetadata retrieves metadata for future extensibility
func (*DataStoreStatusChecker) HasDataLink ¶ added in v0.3.0
func (d *DataStoreStatusChecker) HasDataLink(packName, handlerName, relativePath string) (bool, error)
HasDataLink checks if a data link exists in the datastore
func (*DataStoreStatusChecker) HasSentinel ¶ added in v0.3.0
func (d *DataStoreStatusChecker) HasSentinel(packName, handlerName, sentinel string) (bool, error)
HasSentinel checks if a sentinel exists for tracking operation completion
type Executor ¶ added in v0.3.0
type Executor struct {
// contains filtered or unexported fields
}
Executor orchestrates the execution of operations. This is where the complexity lives - handlers just declare what they want, the executor figures out how to make it happen.
func NewExecutor ¶ added in v0.3.0
NewExecutor creates a new operation executor.
func (*Executor) Execute ¶ added in v0.3.0
func (e *Executor) Execute(operations []Operation, handler Handler) ([]OperationResult, error)
Execute runs a list of operations, handling validation, confirmations, and execution. This is the main entry point that commands use after handlers generate operations.
func (*Executor) ExecuteClear ¶ added in v0.3.0
func (e *Executor) ExecuteClear(handler Handler, ctx ClearContext) ([]ClearedItem, error)
ExecuteClear handles the clear operation for a handler. Phase 3: Simplified to use generic state management.
type FileInput ¶ added in v0.3.0
type FileInput struct {
PackName string // Name of the pack containing this file
SourcePath string // Absolute path to the file
RelativePath string // Path relative to pack root
Options map[string]interface{} // Handler-specific options from rules
}
FileInput represents the minimal information handlers need about a file. This decouples handlers from the matching/rules system.
type Handler ¶ added in v0.3.0
type Handler interface {
// Core identification
Name() string
Category() HandlerCategory
// Core responsibility: transform file inputs to operations
// This is the heart of the simplification - handlers just declare
// what operations they need, not how to perform them.
ToOperations(files []FileInput) ([]Operation, error)
// Status checking: handlers know how to check their own status
CheckStatus(file FileInput, checker StatusChecker) (HandlerStatus, error)
// Metadata for UI/UX
GetMetadata() HandlerMetadata
// Optional customization points with sensible defaults.
// Most handlers won't need to implement these.
GetClearConfirmation(ctx ClearContext) *ConfirmationRequest
FormatClearedItem(item ClearedItem, dryRun bool) string
ValidateOperations(ops []Operation) error
GetStateDirectoryName() string
}
Handler is the simplified interface that all handlers implement. The key insight: handlers are just data transformers, not orchestrators.
type HandlerCategory ¶ added in v0.3.0
type HandlerCategory string
HandlerCategory represents the fundamental nature of a handler's operations
const ( // CategoryConfiguration handlers manage configuration files/links // These are safe to run repeatedly without side effects CategoryConfiguration HandlerCategory = "configuration" // CategoryCodeExecution handlers run arbitrary code/scripts // These require user consent for repeated execution CategoryCodeExecution HandlerCategory = "code_execution" )
type HandlerMetadata ¶ added in v0.3.0
type HandlerMetadata struct {
Description string // Human-readable description
RequiresConfirm bool // Whether operations need user confirmation
CanRunMultiple bool // Whether handler supports multiple executions
}
HandlerMetadata provides UI/UX information about a handler. This separates presentation concerns from operation logic.
type HandlerStatus ¶ added in v0.3.0
type HandlerStatus struct {
State StatusState // Current state of the handler's operations
Message string // Human-readable status message
Details interface{} // Optional handler-specific details
}
HandlerStatus represents the status of a handler's operations for a file
type Operation ¶ added in v0.3.0
type Operation struct {
Type OperationType
Pack string
Handler string
Source string // For link operations: source file path
Target string // For link operations: target path
Command string // For RunCommand: command to execute
Sentinel string // For RunCommand/CheckSentinel: completion marker
Metadata map[string]interface{} // Handler-specific data for customization
}
Operation represents a single atomic unit of work to be performed. Operations are the bridge between handlers (which understand file patterns) and the datastore (which only knows how to perform these 4 operations).
type OperationResult ¶ added in v0.3.0
OperationResult captures the outcome of executing an operation. This is used for status reporting and dry-run output.
type OperationType ¶ added in v0.3.0
type OperationType int
OperationType represents the fundamental operations that dodot performs. This is the core insight: dodot only does 4 things, everything else is orchestration.
const ( // CreateDataLink creates a link in the datastore pointing to a source file. // This is used by symlink, path, and shell handlers to stage files. CreateDataLink OperationType = iota // CreateUserLink creates a user-visible symlink pointing to the datastore. // This is the final step for symlink handler to make files accessible. CreateUserLink // RunCommand executes a command and records completion with a sentinel. // This is used by install and homebrew handlers for provisioning. RunCommand // CheckSentinel queries if an operation has been completed. // This prevents re-running expensive operations. CheckSentinel )
type StatusChecker ¶ added in v0.3.0
type StatusChecker interface {
// HasDataLink checks if a data link exists in the datastore
// Used by configuration handlers (symlink, shell, path)
HasDataLink(packName, handlerName, relativePath string) (bool, error)
// HasSentinel checks if a sentinel exists for tracking operation completion
// Used by code execution handlers (install, homebrew)
HasSentinel(packName, handlerName, sentinel string) (bool, error)
// GetMetadata retrieves metadata for future extensibility
GetMetadata(packName, handlerName, key string) (string, error)
}
StatusChecker provides an interface for handlers to check their status without direct filesystem access or datastore implementation knowledge
type StatusState ¶ added in v0.3.0
type StatusState string
StatusState represents the state of a handler's operations
const ( StatusStatePending StatusState = "pending" // Operations not yet applied StatusStateReady StatusState = "ready" // Operations successfully applied StatusStateError StatusState = "error" // Error checking or applying operations StatusStateUnknown StatusState = "unknown" // Status cannot be determined )