Dotfiles in git

Mit wachsender Anzahl potentieller Arbeitscomputer in verschiedenen (Uni) Systemen und auf meinen eigenen Computern, wurde das  aktuell halten meiner Konfigurationsdaten auf allen Systemen langsam etwas aufwendig. Die Lösung für dieses Problem wurde schon von diversen Personen vor mir genutzt, dennoch hat mein Ansatz einige Besonderheiten, welche ich hier ausführen möchte.
Die Grundidee ist einfach, git als Werkzeug der Synchronisierung nutzen und alle Dateien mittels ln als Links an den erwarteten Stellen verlinken.
Der entscheidende Punkt ist nun, wie man die Links möglichst bequem anlegt und dies auf beliebig vielen Systemen installieren kann.

  1. In einem Skript einfach X Zeilen der Form ln -s $quelle $ziel nutzen, unbequem zu pflegen und unflexibel.
  2. Mit einer Schleife ln für jede Datei in einem Ordner aufrufen, bequem, aber unflexibel
  3. Listen als Quelle für ln nutzen, etwas aufwand in der Pflege, dafür aber sehr flexibel
    Meine Lösung gehört offensichtlich in die 3. Kategorie, dabei kommen auf jedem Host 3 Listen zum Einsatz.
    files enthält alle Dateien, welche ich auf allen Computern nutzen möchte$HOSTNAME enthält Dateien, welche ich speziell auf diesem System haben möchte."$HOSTNAME"-not enthält Dateien, welche eigentlich in der Liste stehen, dennoch auf diesem System nicht installiert werden sollen.Da die Listen alle eigene Dateien sind, lassen sie sich auch ohne Editor erweitern.Die allgemeine Logik, wie mit der Liste umgegangen wird, stammt aus onthoughtbots dotfiles, meine derzeitige Version gibt es hier oder zum lesen jetzt auch einfach im Anschluss
    =1: #!/bin/bash
    =2:
    =3: #read content of files to decide, which files should be installed
    =4: #files contains files for all hosts
    =5: #$HOSTNAME contains host specific files
    =6: #$HOSTNAME-not contains files excluded for this host,
    =7: #overwrites everything else
    =8:
    =9: DOTFILES="cat files"
    10:
    11:
    12: if [ -f $HOSTNAME ]; then
    13: DOTFILES="$DOTFILES cat $HOSTNAME"
    14: else
    15: touch $HOSTNAME
    16: fi
    17:
    18: if [ -f "$HOSTNAME"-not ]; then
    19: if [ -f $HOSTNAME ]; then
    20: DOTFILES=$(comm -3 cat files $HOSTNAME|sort) sort "$HOSTNAME"-not))
    21: else
    22: DOTFILES=$(comm -3 sort "files") sort "$HOSTNAME"-not))
    23: fi
    24: else
    25: touch "$HOSTNAME"-not
    26: fi
    27:
    28:
    29:
    30: cutstring="DO NOT EDIT BELOW THIS LINE"
    31:
    32: for name in $DOTFILES; do
    33: target="$HOME/.$name"
    34: #echo "trying to install $HOME/.$name"
    35: if [ -e "$target" ]; then
    36: if [ ! -L "$target" ]; then
    37: cutline=grep -n -m1 "$cutstring" "$target" | sed "s/:.*//"
    38: if [ -n "$cutline" ]; then
    39: cutline=$((cutline-1))
    40: echo "Updating $target"
    41: head -n $cutline "$target" > update_tmp
    42: startline=sed '1!G;h;$!d' "$name" | grep -n -m1 "$cutstring" | sed "s/:.*//"
    43: if [ -n "$startline" ]; then
    44: tail -n $startline "$name" >> update_tmp
    45: else
    46: cat "$name" >> update_tmp
    47: fi
    48: mv update_tmp "$target"
    49: else
    50: echo "WARNING: $target exists but is not a symlink."
    51: fi
    52: fi
    53: else
    54: if [ "$name" != 'install.sh' ]; then
    55: echo "Creating $target"
    56: if [ -n "$(grep "$cutstring" "$name")" ]; then
    57: cp "$PWD/$name" "$target"
    58: else
    59: ln -s "$PWD/$name" "$target"
    60: fi
    61: fi
    62: fi
    63: done
    64:
    65:
Kommentare anzeigen