# nixos-config - My current NixOS configuration # # Copyright (C) 2025 Benedikt Peetz # SPDX-License-Identifier: GPL-3.0-or-later # # This file is part of my nixos-config. # # You should have received a copy of the License along with this program. # If not, see . { 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}" "\"$@\"" "${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 pkgs.writeShellApplication { name = "unison-sync"; text = script; runtimeEnv = { UNISON = cfg.dataDir; }; runtimeInputs = [ pkgs.unison pkgs.openssh # needed to connect to the other server pkgs.less # needed to show diffs pkgs.diffutils # needed to compute diffs ]; }