diff --git a/README.org b/README.org index add5608..e0e804e 100644 --- a/README.org +++ b/README.org @@ -4,30 +4,30 @@ After trying several approaches and switching between different setups, this method finally met all of my requirements: - As simple as possible - - Multiple hosts are managed in one repository - - Identical configurations for one program on several hosts only need to be adjusted in one place - - Different configurations for one program on several hosts are no problem + - Multiple machines are managed in one repository + - Identical configurations for one program on several machines only need to be adjusted in one place + - Different configurations for one program on several machines are no problem - Set everything up with one command - Updating configurations shall require nothing more than =git pull= - This is a reference repository which contains a bash script (=dotlink=) and some example dotfiles for two hosts (=host1= and =host2=). + This is a reference repository which contains a bash script (=dotlink=) and some example dotfiles for two machines (=host1= and =host2=). *Warning*: If you want to try this make a backup of your dotfiles! The script doesn't overwrite existing files but you never know. ** Concept - The concept is based on symlinks and two directories, =common= and =hosts=. + The concept is based on symlinks and two directories, =common= and =machines=. - The =hosts= directory contains subdirectories for all hosts on which dotfiles are managed. - They need to match the /hostname/ of the host (in this repository =host1= and =host2=) and mimic the corresponding =$HOME= directories. + The =machines= directory contains subdirectories for all machines on which dotfiles are managed. + They need to match the /hostname/ of the machine (in this repository =host1= and =host2=) and mimic the corresponding =$HOME= directories. - The =common= directory contains configs which are present on multiple hosts. + The =common= directory contains configs which are present on multiple machines. It doesn't follow any specific structure, you can choose what suits your setup. Subdirectories with program names, followed by the configuration files (in this repository only =mpv=) make probably the most sense but its up to you. The =common= directory should never contain symlinks. - Symlinks from the =hosts= directory to the =common= directory make the configs available on multiple hosts and they can be adjusted in one place (see =mpv= in this repository). + Symlinks from the =machines= directory to the =common= directory make the configs available on multiple machines and they can be adjusted in one place (see =mpv= in this repository). Here is the tree output from this repository: @@ -37,7 +37,7 @@ │   └── mpv │   ├── input.conf │   └── mpv.conf - ├── hosts + ├── machines │   ├── host1 │   │   ├── .config │   │   │   └── mpv -> ../../../common/mpv/ @@ -52,38 +52,38 @@ The *mpv* configuration is shared between hosts, =host1= has an *OfflineIMAP* configuration in his home directory and =host2= has a *beets* configuration in his =.config= directory. - Every file from every =hosts/= directory can then be linked to the corresponding path into the home directory of the host. + Every file from every =machines/= directory can then be linked to the corresponding path into the home directory of the machine. This can be done by hand or with help of the =dotlink= script. If you updated a configuration somewhere else just call =git pull= and thats it. ** Script usage - When the =dotlink= script is executed, all files from the =hosts/= directory, which matches the current /hostname/, are linked to their destination in the =$HOME= directory. + When the =dotlink= script is executed, all files from the =machines/= directory, which matches the current /hostname/, are linked to their destination in the =$HOME= directory. Executing the script is only neccessary when new files were added which are not linked yet. - The script can be executed from everywhere, it is just important that it's stored next to a =hosts= directory like in this repository. + The script can be executed from everywhere, it is just important that it's stored next to a =machines= directory like in this repository. #+begin_example Usage: dotlink [OPTIONS] - Link all files from hosts/$HOSTNAME to $HOME. + Simple dotfile management based on symlinks. OPTIONS - -h, --help Show this help message and exit + -h, --help Show this help message -u, --unlink Remove current links #+end_example -** Add configuration files for only one host +** Adding configuration files for only one host - Add the files to =hosts//= and execute the =dotlink= script on the modified host. - If you want to keep all configuration files in the =common= directory and just use symlinks in the =hosts= directory, you can follow the instructions below. + Add the files to =machines//=. + If you want to keep all configuration files in the =common= directory and just use symlinks in the =machines= directory, you can follow the instructions below. -** Add configuration files for multiple hosts +** Adding configuration files for multiple host - It is important that the links from the =hosts= directory to the =common= directory are relative. - Follow these steps to add new configurations for multiple hosts: + It is important that the links from the =machines= directory to the =common= directory are relative. + Follow these steps to add new configurations for multiple machines: 1. Add the files somewhere to the =common= directory - 2. Execute =ln -rs common/ hosts//= for every host on which the files should be present - 3. Execute the =dotlink= script on every modified host + 2. Execute =ln -rs common/ machines//= for every machine on which the files should be present + 3. Execute the =dotlink= script on every modified machine diff --git a/dotlink b/dotlink index 797fcda..79f584c 100755 --- a/dotlink +++ b/dotlink @@ -24,10 +24,10 @@ function print_usage { cat < /dev/null && pwd )" -# Check if dotfiles for host exist -if [ ! -d "${dotfiles}/hosts/${hostname}" ]; then - error "No dotfiles for host ${text_bold}${hostname}${text_reset} found, make sure the directory ${text_bold}${dotfiles}/hosts/${hostname}${text_reset} exists" +# Check if dotfiles for machine exist +if [ ! -d "$dotfiles/machines/$HOSTNAME" ]; then + error "No dotfiles for machine $text_bold$HOSTNAME$text_reset found" + exit 1 fi -# Get dotfiles for current host -mapfile -t files < <(find -L "${dotfiles}/hosts/${hostname}" -type f -printf '%P\n') +# Get dotfiles for current machine +cd "$dotfiles/machines/$HOSTNAME" +files=( $(find -L -type f -printf '%P\n')) if [ "$unlink" == true ]; then - log "Unlinking ${text_bold}${#files[@]}${text_reset} files..\n" + log "Unlinking $text_bold${#files[@]}$text_reset files..\n" else - log "Linking ${text_bold}${#files[@]}${text_reset} files..\n" + log "Linking $text_bold${#files[@]}$text_reset files..\n" fi for file in "${files[@]}"; do - src="${dotfiles}/hosts/${hostname}/${file}" - trgt="${HOME}/${file}" - # Unlink files if [ "$unlink" == true ]; then - if [ -L "$trgt" ] && [ "$(readlink "$trgt")" == "$src" ]; then + if [ -L "$HOME/$file" ] && [ "$(readlink $HOME/$file)" == "$dotfiles/machines/$HOSTNAME/$file" ]; then - rm "$trgt" - log "Unlinked ${text_bold}${trgt}${text_reset}" + rm "$HOME/$file" + log "Unlinked $text_bold$HOME/$file$text_reset" - # Remove target directory if empty - if ! [ "$(ls -A "$(dirname "$trgt")")" ]; then - rmdir "$(dirname "$trgt")" - log "Removed empty directory ${text_bold}$(dirname "$trgt")${text_reset}" + # Remove base directory if empty + if ! [ "$(ls -A $(dirname $HOME/$file))" ]; then + rmdir "$(dirname $HOME/$file)" + log "Removed empty directory $text_bold$(dirname $HOME/$file)$text_reset" fi fi @@ -100,28 +95,28 @@ for file in "${files[@]}"; do else # Check if target is a link - if [ -L "$trgt" ]; then + if [ -L "$HOME/$file" ]; then - if [ "$(readlink "$trgt")" != "$src" ]; then - warning "${text_bold}${trgt}${text_reset} is a link but doesn't point to this repository, it will not be linked" + if [ "$(readlink $HOME/$file)" != "$dotfiles/machines/$HOSTNAME/$file" ]; then + warning "$text_bold$HOME/$file$text_reset is a link but doesn't point to this repository, it will not be linked" continue fi # Check if target is a file or directory - elif [ -f "$trgt" ]; then + elif [ -f "$HOME/$file" ]; then - warning "${text_bold}${trgt}${text_reset} exists and will not be linked" + warning "$text_bold$HOME/$file$text_reset exists and will not be linked" continue # Create link else # Create target directory if not existent - mkdir -p "$(dirname "$trgt")" + mkdir -p "$(dirname $HOME/$file)" # Link file - ln -s "$src" "$trgt" - log "Linked ${text_bold}${src}${text_reset} to ${text_bold}${trgt}${text_reset}" + ln -s "$dotfiles/machines/$HOSTNAME/$file" "$HOME/$file" + log "Linked $text_bold$dotfiles/$file$text_reset to $text_bold$HOME/$file$text_reset" fi fi diff --git a/hosts/host1/.config/mpv b/machines/host1/.config/mpv similarity index 100% rename from hosts/host1/.config/mpv rename to machines/host1/.config/mpv diff --git a/hosts/host1/.offlineimaprc b/machines/host1/.offlineimaprc similarity index 100% rename from hosts/host1/.offlineimaprc rename to machines/host1/.offlineimaprc diff --git a/hosts/host2/.config/beets/config.yaml b/machines/host2/.config/beets/config.yaml similarity index 100% rename from hosts/host2/.config/beets/config.yaml rename to machines/host2/.config/beets/config.yaml diff --git a/hosts/host2/.config/mpv b/machines/host2/.config/mpv similarity index 100% rename from hosts/host2/.config/mpv rename to machines/host2/.config/mpv