core

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2025 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package core implements the core pipeline functions for dodot. It provides the main execution flow from pack discovery through to filesystem operations.

dodot uses a two-symlink strategy for deploying configuration files:

  1. Intermediate symlink in dodot's data directory: ~/.local/share/dodot/deployed/symlink/.vimrc -> ~/dotfiles/vim/vimrc

  2. 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:

  1. If the target is already a dodot-managed symlink (points to the intermediate link), the operation is idempotent - no action needed

  2. 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

  3. If the target exists but differs (different symlink target or different file content), dodot protects user data by requiring the --force flag

  4. 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

Constants

This section is empty.

Variables

View Source
var (
	GetPackCandidates = packs.GetPackCandidates
	GetPacks          = packs.GetPacks
	ValidatePack      = packs.ValidatePack

	SelectPacks = packs.SelectPacks
)

Re-exports from pkg/packs for backwards compatibility

Functions

func CalculateActionChecksum

func CalculateActionChecksum(action types.Action) (string, error)

CalculateActionChecksum calculates the checksum for an action's source file. This is used to update the checksum metadata for run-once actions.

func DiscoverAndSelectPacks added in v0.2.0

func DiscoverAndSelectPacks(dotfilesRoot string, packNames []string) ([]types.Pack, error)

DiscoverAndSelectPacks is a helper that combines pack discovery and selection. It discovers all packs in dotfilesRoot and optionally filters by packNames. If packNames is empty, all discovered packs are returned. Pack names are normalized to handle trailing slashes from shell completion.

func DiscoverAndSelectPacksFS added in v0.2.0

func DiscoverAndSelectPacksFS(dotfilesRoot string, packNames []string, filesystem types.FS) ([]types.Pack, error)

DiscoverAndSelectPacksFS is a helper that combines pack discovery and selection with filesystem support. It discovers all packs in dotfilesRoot using the provided filesystem and optionally filters by packNames. If packNames is empty, all discovered packs are returned. Pack names are normalized to handle trailing slashes from shell completion.

func EnrichRunOnceActionsWithChecksums added in v0.1.4

func EnrichRunOnceActionsWithChecksums(actions []types.Action) []types.Action

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 FindPack added in v0.2.0

func FindPack(dotfilesRoot string, packName string) (*types.Pack, error)

FindPack discovers all packs and returns the one with the specified name. Returns an error if the pack is not found. Pack name is normalized to handle trailing slashes from shell completion.

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

func GetFiringTriggersFS(packs []types.Pack, filesystem types.FS) ([]types.TriggerMatch, error)

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

func ProcessPackTriggersFS(pack types.Pack, filesystem types.FS) ([]types.TriggerMatch, error)

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

func ShouldRunOnceAction(action types.Action, force bool, pathsInstance *paths.Paths) (bool, error)

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.

func ValidateDotfilesRoot added in v0.2.0

func ValidateDotfilesRoot(dotfilesRoot string) error

ValidateDotfilesRoot checks if the dotfiles root exists and is a directory. This centralizes the validation that multiple commands need.

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL