{ lib, config, nixosConfig, sysLib, pkgs, ... }: let unisonPath = "${config.xdg.dataHome}/unison"; # These are only used for the script unisonOptions = { sshcmd = "ssh"; ui = "text"; auto = "true"; }; paths_to_keep = [ "~/.local/state/mpv" "~/.local/state/nvim" "~/.local/share" "~/.local/.Trash-1000" "~/.mozilla/.Trash-1000" "~/.mozilla/firefox" "~/media" "~/school" "~/repos" ]; hostName = let hn = nixosConfig.networking.hostName; in if hn == "tiamat" then "apzu" else if hn == "apzu" then "tiamat" else builtins.throw "Host (${hn}) not yet covered in the unison host mapping."; mkPath = path: if lib.strings.hasPrefix "~" path then "${builtins.elemAt (builtins.attrNames config.home.persistence) 0}${lib.strings.removePrefix "~" path}" else builtins.throw "Every pathname needs to start with a '~'"; mkPair = pathname: let path = mkPath pathname; in { name = "${pathname}"; value = { stateDirectory = unisonPath; roots = [ "${path}" "ssh://${config.home.username}@${hostName}.fritz.box/${path}" ]; }; }; serialiseArg = key: val: lib.strings.concatStringsSep " " (lib.forEach (lib.toList val) (x: lib.strings.escapeShellArg "-${key}=${lib.escape ["="] x}")); serialiseArgs = args: lib.strings.concatStringsSep " " (lib.mapAttrsToList serialiseArg args); esa = a: lib.strings.escapeShellArg a; mkScriptLine = pathname: let path = mkPath pathname; in lib.strings.concatStringsSep " " [ "unison" "${serialiseArgs unisonOptions}" "${esa path}" (esa "ssh://${config.home.username}@${hostName}.fritz.box/${path}") ]; script = lib.strings.concatStringsSep "\n" (builtins.map mkScriptLine paths_to_keep); pairs = builtins.listToAttrs (builtins.map mkPair paths_to_keep); in { home.packages = [ (sysLib.writeShellScript { name = "unison-backup"; src = builtins.toFile "unison-backup" ('' #!/usr/bin/env sh export UNISON=${esa unisonPath}; '' + script); dependencies = with pkgs; [unison openssh]; }) ]; services.unison = { enable = true; inherit pairs; }; }