Files and directories
Files
Use dots.file to manage a file from a source in the dots project:
dots.file("~/.ssh/config", {
source = "ssh/config",
mode = "0600",
})Relative source paths are resolved from the directory containing dots.lua.
Dots creates the target when it is missing. If the target already has the same content and mode, dots check shows it for tracking. Tracking records the file in state without rewriting it. A different unmanaged file is a conflict.
The source and any existing target must be regular files. Dots will not replace a directory, symlink, or special file.
Once the file is tracked, changes to the source or mode are applied to the target. Without mode, dots preserves existing permissions; new files use the platform default.
Directories
Use dots.directory when a program needs a directory with specific permissions:
local acme = dots.directory("/opt/traefik/acme", {
mode = "0755",
})
dots.file("/opt/traefik/acme/config.json", {
source = "traefik/config.json",
needs = { acme },
})Both dots.file and dots.directory return references for needs. Here, the directory is created before the file is written.
Dots creates missing directories, including their parents. An existing directory is shown for tracking when its mode matches. A different mode is a conflict until the directory is tracked; after that, dots corrects mode changes. Files, symlinks, and other non-directory targets are conflicts.
Without mode, dots manages only whether the directory exists. The mode applies to the declared directory, not to parents created along the way.
Removing declarations
Removing a file declaration schedules the target for deletion. Dots deletes it only when its content and managed mode still match what was applied. If the file was edited outside dots, removal is a conflict.
Removing a directory declaration deletes it when empty. Managed files and directories inside it can be removed in the same apply, but anything else makes removal a conflict. Nested directories count as managed only when they have their own dots.directory(...) declaration. Dots never deletes a directory recursively.
Keep the target
To keep /srv/myapp/uploads but stop managing it, first remove its dots.directory(...) declaration, then run:
dots state forget directory:/srv/myapp/uploadsFor a file:
dots state forget file:/etc/myapp/config.tomlforget removes only the state entry. The file or directory stays in place. Use dots state list to find the exact entry name. If the declaration remains, the next dots apply offers to track the target again.