aboutsummaryrefslogtreecommitdiffstats
path: root/modules/home/soispha/conf/unison
diff options
context:
space:
mode:
Diffstat (limited to 'modules/home/soispha/conf/unison')
-rw-r--r--modules/home/soispha/conf/unison/default.nix184
1 files changed, 184 insertions, 0 deletions
diff --git a/modules/home/soispha/conf/unison/default.nix b/modules/home/soispha/conf/unison/default.nix
new file mode 100644
index 00000000..64dd50c2
--- /dev/null
+++ b/modules/home/soispha/conf/unison/default.nix
@@ -0,0 +1,184 @@
+{
+ 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";
+ # This is useless, with hm links
+ links = "false";
+
+ backupdir = "${unisonPath}/backups";
+ backuploc = "central";
+ backupcurr = paths_to_merge;
+ # merge =
+ # builtins.map (x: ''${x} -> diff3 --text --merge CURRENT1 CURRENTARCH CURRENT2 > NEW'')
+ # paths_to_merge;
+ };
+
+ paths_to_merge = mkPathName {
+ file_names = ["log" "history" "harpoon.json" "file_frecency.bin" "main.shada"];
+ extensions = ["log"];
+ };
+
+ paths_to_keep = [
+ "~/.local/state/mpv"
+ "~/.local/state/nvim"
+ "~/.local/share"
+ "~/.local/.Trash-1000"
+
+ "~/.mozilla/.Trash-1000"
+ "~/.mozilla/firefox"
+
+ "~/media"
+ "~/school"
+ "~/repos"
+ ];
+ paths_to_ignore = [
+ # already synchronized by the taskserver
+ "~/.local/share/task"
+
+ # Should not be synchronized
+ "~/.local/share/unison"
+ ];
+
+ 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.";
+
+ mkPathName = {
+ file_names,
+ extensions,
+ }:
+ builtins.map (x: ''Name ${x}'') (
+ (builtins.map (x: ''*.${x}'') extensions)
+ ++ file_names
+ );
+
+ unitName = name: builtins.replaceStrings ["/"] ["-"] name;
+
+ 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 = unitName "${pathname}";
+ value = {
+ stateDirectory = unisonPath;
+ roots = [
+ "${path}"
+ "ssh://${config.home.username}@${hostName}.fritz.box/${path}"
+ ];
+ };
+ };
+
+ getIgnoredSingle = path: path_to_ignore: let
+ clean_path_to_ignore = mkPath path_to_ignore;
+ 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;
+
+ getIgnored = paths_to_ignore: path:
+ serialiseArgs {
+ ignore =
+ builtins.filter (x: x != null) (builtins.map (getIgnoredSingle path) paths_to_ignore);
+ };
+
+ serialiseArg = key: val:
+ if builtins.typeOf val == "string"
+ then lib.strings.escapeShellArg "-${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
+ );
+
+ esa = a: lib.strings.escapeShellArg a;
+
+ mkScriptLine = pathname: let
+ path =
+ mkPath pathname;
+ in
+ lib.strings.concatStringsSep " " [
+ "unison"
+ "${serialiseArgs unisonOptions}"
+ "$EXTRA_OPTIONS"
+ "${getIgnored paths_to_ignore path}"
+ "${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.sessionVariables = {
+ UNISON = unisonPath;
+ };
+ home.packages = [
+ pkgs.unison
+ (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 unisonPath};
+
+ 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
+ ];
+ })
+ ];
+ services.unison = {
+ enable = false;
+ inherit pairs;
+ };
+}