Documentation
¶
Overview ¶
Package core implements the core pipeline functions for dodot. It provides the main execution flow from pack discovery through to filesystem operations.
Symlink Deployment Strategy ¶
dodot uses a two-symlink strategy for deploying configuration files:
Intermediate symlink in dodot's data directory: ~/.local/share/dodot/deployed/symlink/.vimrc -> ~/dotfiles/vim/vimrc
Target symlink in the user's home directory: ~/.vimrc -> ~/.local/share/dodot/deployed/symlink/.vimrc
This two-link approach provides several benefits:
- Atomic updates: The intermediate link can be updated without touching files in the user's home directory
- Clean uninstall: All dodot-managed symlinks point to a known location
- Conflict detection: dodot can distinguish between its own symlinks and user-created symlinks
- Pack organization: The intermediate directory maintains the structure of deployed files
Conflict Resolution ¶
When deploying symlinks, dodot handles conflicts intelligently:
If the target is already a dodot-managed symlink (points to the intermediate link), the operation is idempotent - no action needed
If the target is a regular file with identical content to the source, dodot automatically replaces it with a symlink. This makes adoption easier when users already have the same config files
If the target exists but differs (different symlink target or different file content), dodot protects user data by requiring the --force flag
The intermediate symlink is always safe to update since it's in dodot's private data directory
This strategy ensures that repeated deploys are idempotent (no errors on re-run) while protecting user data from accidental overwrites.
Package core provides the core processing pipeline for dodot.
IMPORTANT DESIGN PRINCIPLE: Pack Scanning is FLAT ================================================= Packs are scanned as flat directories - only top-level entries are processed. This is a fundamental design decision in dodot:
1. When scanning a pack, we read ONLY the immediate children 2. We do NOT recursively traverse subdirectories 3. Directories are processed as single units (e.g., for symlinking the entire dir) 4. Files inside subdirectories are NOT individually scanned or matched
This design allows powerups to handle entire directory trees (like symlinking a whole config directory) without dodot trying to process individual files within those directories.
Example:
pack/ ├── file.txt ✓ Processed ├── dir/ ✓ Processed as a unit │ └── nested.txt ✗ NOT processed (part of dir/) └── another.sh ✓ Processed
Index ¶
- Variables
- func CalculateActionChecksum(action types.Action) (string, error)
- func EnrichRunOnceActionsWithChecksums(actions []types.Action) []types.Action
- func FilterRunOnceActions(actions []types.Action, force bool, pathsInstance *paths.Paths) ([]types.Action, error)
- func FilterRunOnceTriggersEarly(triggers []types.TriggerMatch, force bool, pathsInstance *paths.Paths) []types.TriggerMatch
- func GetActions(matches []types.TriggerMatch) ([]types.Action, error)
- func GetFiringTriggers(packs []types.Pack) ([]types.TriggerMatch, error)
- func GetFiringTriggersFS(packs []types.Pack, filesystem types.FS) ([]types.TriggerMatch, error)
- func GetMultiPackStatus(packList []types.Pack, command string, fs types.FS, paths types.Pather) (*types.DisplayResult, error)
- func GetPackStatus(pack types.Pack, actions []types.Action, fs types.FS, paths types.Pather) (*types.DisplayPack, error)
- func ProcessMatchGroup(matches []types.TriggerMatch) ([]types.Action, error)
- func ProcessPackTriggers(pack types.Pack) ([]types.TriggerMatch, error)deprecated
- func ProcessPackTriggersFS(pack types.Pack, filesystem types.FS) ([]types.TriggerMatch, error)
- func ShouldRunOnceAction(action types.Action, force bool, pathsInstance *paths.Paths) (bool, error)
- type DirectExecutor
- type DirectExecutorOptions
- type PackTemplateFile
- type RunOnceStatus
Constants ¶
This section is empty.
Variables ¶
var ( GetPackCandidates = packs.GetPackCandidates GetPacks = packs.GetPacks ValidatePack = packs.ValidatePack SelectPacks = packs.SelectPacks )
Re-exports from pkg/packs for backwards compatibility
Functions ¶
func CalculateActionChecksum ¶
CalculateActionChecksum calculates the checksum for an action's source file. This is used to update the checksum metadata for run-once actions.
func EnrichRunOnceActionsWithChecksums ¶ added in v0.1.4
EnrichRunOnceActionsWithChecksums adds checksums to the metadata of run-once actions. This is needed so the executor can write checksums to sentinel files and FilterRunOnceActions can compare them on subsequent runs.
func FilterRunOnceActions ¶
func FilterRunOnceActions(actions []types.Action, force bool, pathsInstance *paths.Paths) ([]types.Action, error)
FilterRunOnceActions filters a list of actions based on their run-once status. It removes actions that have already been executed with the same checksum, unless the force flag is set.
func FilterRunOnceTriggersEarly ¶ added in v0.1.4
func FilterRunOnceTriggersEarly(triggers []types.TriggerMatch, force bool, pathsInstance *paths.Paths) []types.TriggerMatch
FilterRunOnceTriggersEarly filters out trigger matches for run-once powerups that have already been executed. This is the new approach that checks sentinel files before powerup processing, avoiding unnecessary work.
func GetActions ¶
func GetActions(matches []types.TriggerMatch) ([]types.Action, error)
GetActions converts trigger matches into concrete actions to perform
func GetFiringTriggers ¶
func GetFiringTriggers(packs []types.Pack) ([]types.TriggerMatch, error)
GetFiringTriggers processes packs and returns all triggers that match files Deprecated: Use GetFiringTriggersFS instead to support filesystem abstraction
func GetFiringTriggersFS ¶ added in v0.1.4
GetFiringTriggersFS processes packs and returns all triggers that match files using the provided filesystem
func GetMultiPackStatus ¶ added in v0.1.4
func GetMultiPackStatus(packList []types.Pack, command string, fs types.FS, paths types.Pather) (*types.DisplayResult, error)
GetMultiPackStatus processes multiple packs and returns a DisplayResult
func GetPackStatus ¶ added in v0.1.4
func GetPackStatus(pack types.Pack, actions []types.Action, fs types.FS, paths types.Pather) (*types.DisplayPack, error)
GetPackStatus generates display status for a single pack by checking all its actions
func ProcessMatchGroup ¶
func ProcessMatchGroup(matches []types.TriggerMatch) ([]types.Action, error)
ProcessMatchGroup processes a group of related matches with the same power-up
func ProcessPackTriggers
deprecated
func ProcessPackTriggers(pack types.Pack) ([]types.TriggerMatch, error)
ProcessPackTriggers processes triggers for a single pack IMPORTANT: This function performs FLAT scanning of pack directories. Only top-level files and directories within a pack are processed. Subdirectory contents are NOT recursively scanned or processed. This is a core design principle of dodot - packs are treated as flat directories.
Example:
nvim/ # pack
├── install.sh # ✓ processed - triggers install powerup
├── bin/ # ✓ processed - triggers path powerup
│ └── alias.sh # ✗ NOT processed - inside subdirectory
└── lua/ # ✓ processed - triggers symlink powerup
└── install.sh # ✗ NOT processed - inside subdirectory
Deprecated: Use ProcessPackTriggersFS instead to support filesystem abstraction
func ProcessPackTriggersFS ¶ added in v0.1.4
ProcessPackTriggersFS processes triggers for a single pack using the provided filesystem IMPORTANT: This function performs FLAT scanning of pack directories. Only top-level files and directories within a pack are processed. Subdirectory contents are NOT recursively scanned or processed. This is a core design principle of dodot - packs are treated as flat directories.
func ShouldRunOnceAction ¶
ShouldRunOnceAction checks if a run-once action should be executed based on its sentinel file and checksum. Returns true if the action should run, false if it has already run with the same checksum.
Types ¶
type DirectExecutor ¶ added in v0.1.4
type DirectExecutor struct {
// contains filtered or unexported fields
}
DirectExecutor executes actions directly without intermediate Operation type
func NewDirectExecutor ¶ added in v0.1.4
func NewDirectExecutor(opts *DirectExecutorOptions) *DirectExecutor
NewDirectExecutor creates a new direct executor
func (*DirectExecutor) ExecuteActions ¶ added in v0.1.4
func (e *DirectExecutor) ExecuteActions(actions []types.Action) ([]types.ActionResult, error)
ExecuteActions executes actions directly using synthfs
type DirectExecutorOptions ¶ added in v0.1.4
type DirectExecutorOptions struct {
Paths *paths.Paths
DryRun bool
Force bool
AllowHomeSymlinks bool
Config *config.Config
}
DirectExecutorOptions contains options for the direct executor
type PackTemplateFile ¶ added in v0.1.1
type PackTemplateFile struct {
Filename string // From matcher configuration
Content string // From powerup's GetTemplateContent()
Mode uint32
PowerUpName string
}
PackTemplateFile represents a template file for pack initialization
func GetCompletePackTemplate ¶ added in v0.1.1
func GetCompletePackTemplate(packName string) ([]PackTemplateFile, error)
GetCompletePackTemplate returns all template files available for a pack by iterating through default matchers and getting templates from powerups
func GetMissingTemplateFiles ¶ added in v0.1.1
func GetMissingTemplateFiles(packPath string, packName string) ([]PackTemplateFile, error)
GetMissingTemplateFiles returns template files that don't exist in the given pack directory
type RunOnceStatus ¶
type RunOnceStatus struct {
Executed bool
ExecutedAt time.Time
Checksum string
Changed bool // True if the source file has changed since execution
}
RunOnceStatus represents the execution status of a run-once power-up
func GetRunOnceStatus ¶
func GetRunOnceStatus(packPath, powerUpName string, pathsInstance *paths.Paths) (*RunOnceStatus, error)
GetRunOnceStatus checks the status of a run-once power-up for a specific pack