Dynamicfiles¶
Dynamicfiles are used whenever one or more dotfiles need to be altered
before they are symlinked. Because the original shall not be altered by
uberdot, uberdot processes the specified dotfiles and stores the
altered version in a subdirectory of data/
. There are different
types of dynamicfiles, each one using their own subdirectory:
data/decrypted
: dotfiles that were decrypteddata/merged
: dotfiles that were merged from multiple dotfilesdata/piped
: dotfiles that were piped into a shell command
To make use of a dynamicfile you can either use one of the helper
commands like decrypt()
or merge()
which will return a
dynamicfile or create an instance of a dynamicfile by yourself for more
advanced usage (see the example at the bottom). Every time you do this,
the dynamicfile will be updated immediately (even if you only do a
dry-run) and the generated result will be written to the corresponding
subdirectory.
Because the generated file that will be linked is now outside of your repository, the repository is obviously not able to track changes anymore. Also editing a symlink to this file won’t update the original dotfile(s) in your repository. To circumvent this disadvantage, uberdot will track changes that you apply to the symlinked generated file and warns you if you would overwrite those changes when you install a profile. To do so, uberdot appends the md5 hash of the file to its filename and stores a backup file next to it. That way changes won’t be lost and uberdot can calculate a diff for you if you like.
Workflow explained on an example¶
Suppose you have the following profile:
class Main(Profile):
def generate():
link(decrypt("test.txt"))
The first time that you install this profile decrypt()
will search
for the file “text.txt” in your repository, decrypt it and calculate
it’s hash (in this example bb6a0d9da197de74db91745fb9b433e1). It then
writes the decrypted file to
- data/decrypted/test.txt#bb6a0d9da197de74db91745fb9b433e1 and
- data/decrypted/test.txt#bb6a0d9da197de74db91745fb9b433e1.bak
uberdot will later link to “data/decrypted/test.txt#bb6a0d9da197de74db91745fb9b433e1”. Now every time this profile is updated or removed, uberdot will update the dynamic file - which again creates new files with a new hash if the file content changed - and checks if the calculated hash differs from the current installed hash. If so uberdot warns you that you could lose changes and helps you to write back the changes to the original file by giving you the following options:
- Abort: Abort the installation/removal process to fix changes manually
- Diff: Displays a diff of the changes and lets you decide again what to do
- Ignore: Ignore the warning. The link will be updated/removed but the changes to the old dynamicfile will stay.
- Patch: Write a git diff of the changes to a desired location. In some cases you can apply it to the original directly with git.
- Undo: Discards all changes made to the file and proceed with updating/removing the link.
Creating an instance of a dynamicfile manually¶
from uberdot.dynamicfile import EncryptedFile
# Create an instance of EncryptedFile with the name "test.txt"
encrypt = EncryptedFile("test.txt")
# Add the source files that shall be processed (in this case its only one)
encrypt.add_source("~/dotfile_repo/test.txt")
# Update the dynamicfile to process the source and write the resulting file
encrypt.update()
Instead of using the absolute path to the dotfile you could use
self.find()
of the profile to find the file automatically.
from uberdot.dynamicfile import EncryptedFile
encrypt = EncryptedFile("test.txt")
encrypt.add_source(self.find("test.txt"))
encrypt.update()