diff options
Diffstat (limited to 'modules/by-name/un/unison/shellScript.nix')
-rw-r--r-- | modules/by-name/un/unison/shellScript.nix | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/modules/by-name/un/unison/shellScript.nix b/modules/by-name/un/unison/shellScript.nix new file mode 100644 index 00000000..5ff0c219 --- /dev/null +++ b/modules/by-name/un/unison/shellScript.nix @@ -0,0 +1,95 @@ +{ + sysLib, + lib, + pkgs, + cfg, +}: let + esa = lib.strings.escapeShellArg; + + expandHomePath = path: + if lib.strings.hasPrefix "~" path + then "${cfg.userSourceDir}${lib.strings.removePrefix "~" path}" + else + builtins.throw + '' + BUG: Every pathname needs to start with a '~'. + This should have been checked by the NixOS module system? + ''; + + getIgnored = paths_to_ignore: path: + serialiseArgs { + ignore = + builtins.filter (x: x != null) (builtins.map (getIgnoredSingle path) paths_to_ignore); + }; + + getIgnoredSingle = path: pathToIgnore: let + clean_path_to_ignore = expandHomePath pathToIgnore; + commonPath = builtins.substring 0 (builtins.stringLength path) clean_path_to_ignore; + in + if commonPath == path + then let + preFinalPath = + builtins.substring (builtins.stringLength commonPath) + (builtins.stringLength clean_path_to_ignore) + clean_path_to_ignore; + finalPath = + if lib.strings.hasPrefix "/" preFinalPath + then lib.strings.removePrefix "/" preFinalPath + else preFinalPath; + in "BelowPath ${finalPath}" + else null; + + serialiseArg = key: val: + if builtins.typeOf val == "string" + then esa "-${key}=${lib.strings.escape ["="] val}" + else if builtins.typeOf val == "list" + then lib.strings.concatStringsSep " " (builtins.map (serialiseArg key) val) + else builtins.throw "Unsupported type: ${builtins.typeOf val}"; + + serialiseArgs = args: + lib.strings.concatStringsSep " " ( + lib.attrsets.mapAttrsToList + serialiseArg + args + ); + + mkScriptLine = pathname: let + path = + expandHomePath pathname; + in + lib.strings.concatStringsSep " " [ + "unison" + "${serialiseArgs cfg.unisonOptions}" + "$EXTRA_OPTIONS" + "${getIgnored cfg.pathsToIgnore path}" + "${esa path}" + (esa "ssh://${cfg.foreign.userName}@${cfg.foreign.address}/${path}") + ]; + + script = lib.strings.concatStringsSep "\n" (builtins.map mkScriptLine cfg.pathsToSync); +in + sysLib.writeShellScript { + name = "unison-sync"; + src = builtins.toFile "unison-backup" ('' + #!/usr/bin/env dash + + # shellcheck source=/dev/null + SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH + + export UNISON=${esa cfg.dataDir}; + + if [ "$1" = "links" ]; then + shift 1; + EXTRA_OPTIONS="-links=true"; + fi + EXTRA_OPTIONS="$EXTRA_OPTIONS $*" + '' + + script); + + dependencies = with pkgs; [ + unison + openssh # needed to connect to the other server + less # needed to show diffs + diffutils # needed to compute diffs + ]; + } |