From 505ae456c346a5c09c4fcddf0799ed4572c7cc36 Mon Sep 17 00:00:00 2001 From: Ryan Patterson Date: Tue, 29 Oct 2019 02:28:02 +0400 Subject: [PATCH] README and minor tweaks --- .gitignore | 1 + Makefile | 10 +++++ README.md | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/test.sh | 3 +- version.go | 2 +- 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba077a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7abb65c --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +.PHONY: test + +bin/dfm: $(wildcard *.go) go.mod go.sum + mkdir -p bin + go build -o bin/dfm . + +test: bin/dfm + go test . + ./test/snapshot.sh + diff --git a/README.md b/README.md new file mode 100644 index 0000000..61925d6 --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +# dfm - Dotfiles Manager + +dfm is a generic file syncing utility to keep two directories in sync, using symbolic links. It's targeted at keeping a home directory in sync with a dotfiles repository, but can be used in other circumstances as well. + +**Features:** + +- No dependency on git. dfm works fine with git or any other RCS. +- No configuration files. Add files to be tracked just by placing them in the directory. +- No runtime dependencies. dfm can be run directly from the single binary file on a brand new machine. +- Overlay multiple repositories on top of each other. +- Automatically clean up removed files. + +## Quick Start + +To get started with dfm from a blank slate (to see how it works), try these commands: + +```bash +$ mkdir -p ~/dotfiles/files +$ export DFM_DIR=~/dotfiles +$ dfm init --repos files +$ dfm add ~/.bashrc ~/.vimrc +$ ls -la ~/.bashrc ~/.vimrc ~/dotfiles/files +``` + +Notice that `~/.bashrc` and `~/.vimrc` have been replaced with symlinks, and the real files live in `~/dotfiles/files`. You can store `~/dotfiles/files` in a source control system, or even the entire `~/dotfiles` directory, if you have extra scripts that you would like to add. Note that `.dfm.toml` is machine-specific and should not be added to source control. + +When you are setting up a new machine, assuming you have already created `~/dotfiles/files` on that machine (e.g. by cloning your git repository, syncing, whatever): + +```bash +export DFM_DIR=~/dotfiles +dfm init --repos files +dfm link -n +dfm link +``` + +`dfm link` will scan `~/dotfiles/files` and create symlinks in your home folder for each file found. If you have removed files from the repository, running `dfm link` again will automatically delete those broken symlinks. + +## Usage Guide + +This is the recommended workflow to effectively use dfm with your dotfiles. + +1. Write a bootstrap script that installs dfm. I recommend downloading the binary from github via curl, but `go get` might be an option if you prefer. The single binary can be placed anywhere; I prefer to place it in `~/dotfiles/bin`. +2. Configure the dfm directory. It's best to make a shell function: `function dfm() { ~/dotfiles/bin/dfm --dfm-dir=~/dotfiles "$@" }` If you don't mind global configuration, you can also place dfm anywhere in your `$PATH` and set a global environment variable `DFM_DIR=~/dotfiles`. +3. Run `dfm init --repos=files` on each machine to configure it to use `~/dotfiles/files` as the main file repository. +4. Use `dfm add` to add all of your existing configuration to `~/dotfiles/files`, or copy them from your existing dotfiles repository. dfm does not rename files, so the file structure in `~/dotfiles/files` should look exactly like you want it to appear in `~/`. +5. Run `dfm link` to synchronize all of the symlinks in your home directory. + +### Multiple repositories + +dfm supports multiple repositories of files. When multiple repositories are configured, `dfm link` will link to the file in the last listed repository which has the file in question. For example: + +```bash +$ export DFM_DIR=~/dotfiles +# Assume this directory structure: +# ~/dotfiles +# /shared +# /.bashrc +# /.my.cnf +# /work +# /.my.cnf +$ dfm init --repos=shared,work +$ dfm link +shared/.bashrc -> ~/.bashrc +work/.my.cnf -> ~/.my.cnf +``` + +Notice that `.my.cnf` was listed in both `shared` and `work`. Because `work` was listed second in the `dfm init` call, it is the repository that was used for `.my.cnf`. + +**Tip:** repos are just paths relative to the dfm directory. You could use `machines/web` as a repo, or even an absolute path like `~/other-dotfiles`. + +### Ejecting + +dfm has two modes for tracking files: link and copy. The method used in this documentation is link, where files are tracked by using symlinks into the repos. With copy, files are copied directly to the target location from the repos. Copying files is useful if you want to dtop using dfm to migrate to another dotfiles solution. + +```bash +export DFM_DIR=~/dotfiles +dfm copy --force +rm -rf ~/dotfiles +``` + +Once you run `dfm copy --force`, dfm replaces all of the symlinks with hard copies, so it's safe to simply delete the dfm directory afterwards. + +**Note:** `dfm copy` and `dfm link` both have automatic cleanup behavior. If you use `dfm copy`, remove a file from a repo, and run `dfm copy` again, the automatic cleanup will remove the file from your home directory. It's recommended to only use `dfm copy` when you are uninstalling dfm. + +### Managing other directories + +Each dfm directory manages a single target directory. For dotfiles, the target directory is your home folder, but dfm can manage any directory you choose, by configuring that directory in `dfm init`. + +```bash +dfm -d ~/vhosts init --repos files --target /etc/nginx/vhost.d +dfm -d ~/vhosts link +``` + +## Development + +To test: + +```bash +make test +``` + diff --git a/test/test.sh b/test/test.sh index 6f772a9..ddc9dec 100755 --- a/test/test.sh +++ b/test/test.sh @@ -14,9 +14,10 @@ fail() { } cd "$(dirname "$0")" +export DFM_DIR=dfmdir dfm() { echo "\$ dfm" "$@" - ../dfm -d dfmdir "$@" + ../bin/dfm "$@" } rm -rf dfmdir test_home diff --git a/version.go b/version.go index 707b10c..cb02c88 100644 --- a/version.go +++ b/version.go @@ -1,4 +1,4 @@ package main // Version is the version of the running dfm. -const Version = "1.0.0" +const Version = "0.9.0"