diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 2d840ec0e..2d46797c5 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -238,6 +238,8 @@
/modules/services/fluidsynth.nix @Valodim
+/modules/services/git-sync.nix @IvanMalison
+
/modules/services/gnome-keyring.nix @rycee
/modules/services/gpg-agent.nix @rycee
diff --git a/modules/misc/news.nix b/modules/misc/news.nix
index 177fd47b2..183db4472 100644
--- a/modules/misc/news.nix
+++ b/modules/misc/news.nix
@@ -2172,6 +2172,14 @@ in
A new module is available: 'services.easyeffects'.
'';
}
+
+ {
+ time = "2021-08-16T21:59:02+00:00";
+ condition = hostPlatform.isLinux;
+ message = ''
+ A new module is available: 'services.git-sync'.
+ '';
+ }
];
};
}
diff --git a/modules/modules.nix b/modules/modules.nix
index 707b6d881..ad311ac85 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -163,6 +163,7 @@ let
./services/flameshot.nix
./services/fluidsynth.nix
./services/getmail.nix
+ ./services/git-sync.nix
./services/gnome-keyring.nix
./services/gpg-agent.nix
./services/grobi.nix
diff --git a/modules/services/git-sync.nix b/modules/services/git-sync.nix
new file mode 100644
index 000000000..e97d8cc50
--- /dev/null
+++ b/modules/services/git-sync.nix
@@ -0,0 +1,100 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.git-sync;
+
+ mkUnit = name: repo: {
+ Unit.Description = "Git Sync ${name}";
+
+ Install.WantedBy = [ "default.target" ];
+
+ Service = {
+ Environment = [
+ "GIT_SYNC_DIRECTORY=${repo.path}"
+ "GIT_SYNC_COMMAND=${cfg.package}/bin/git-sync"
+ "GIT_SYNC_REPOSITORY=${repo.uri}"
+ "GIT_SYNC_INTERVAL=${toString repo.interval}"
+ ];
+ ExecStart = "${cfg.package}/bin/git-sync-on-inotify";
+ Restart = "on-abort";
+ };
+ };
+
+ services = mapAttrs' (name: repo: {
+ name = "git-sync-${name}";
+ value = mkUnit name repo;
+ }) cfg.repositories;
+
+ repositoryType = types.submodule ({ name, ... }: {
+ options = {
+ name = mkOption {
+ internal = true;
+ default = name;
+ type = types.str;
+ description = "The name that should be given to this unit.";
+ };
+
+ path = mkOption {
+ type = types.path;
+ description = "The path at which to sync the repository";
+ };
+
+ uri = mkOption {
+ type = types.str;
+ example = "git+ssh://user@example.com:/~[user]/path/to/repo.git";
+ description = ''
+ The URI of the remote to be synchronized. This is only used in the
+ event that the directory does not already exist. See
+
+ for the supported URIs.
+ '';
+ };
+
+ interval = mkOption {
+ type = types.int;
+ default = 500;
+ description = ''
+ The interval, specified in seconds, at which the synchronization will
+ be triggered even without filesystem changes.
+ '';
+ };
+ };
+ });
+
+in {
+ meta.maintainers = [ maintainers.imalison ];
+
+ options = {
+ services.git-sync = {
+ enable = mkEnableOption "git-sync services";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.git-sync;
+ defaultText = literalExample "pkgs.git-sync";
+ description = ''
+ Package containing the git-sync program.
+ '';
+ };
+
+ repositories = mkOption {
+ type = with types; attrsOf repositoryType;
+ description = ''
+ The repositories that should be synchronized.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ assertions = [
+ (lib.hm.assertions.assertPlatform "services.git-sync" pkgs
+ lib.platforms.linux)
+ ];
+
+ systemd.user.services = services;
+ };
+}
diff --git a/tests/default.nix b/tests/default.nix
index b95f8f736..b2b6be6bf 100644
--- a/tests/default.nix
+++ b/tests/default.nix
@@ -120,6 +120,7 @@ import nmt {
./modules/services/dropbox
./modules/services/emacs
./modules/services/fluidsynth
+ ./modules/services/git-sync
./modules/services/kanshi
./modules/services/lieer
./modules/services/pantalaimon
diff --git a/tests/modules/services/git-sync/basic.nix b/tests/modules/services/git-sync/basic.nix
new file mode 100644
index 000000000..2e9ec9ad7
--- /dev/null
+++ b/tests/modules/services/git-sync/basic.nix
@@ -0,0 +1,37 @@
+{ config, pkgs, ... }:
+
+{
+ config = {
+ services.git-sync = {
+ enable = true;
+ package = pkgs.writeScriptBin "dummy" "" // { outPath = "@git-sync@"; };
+ repositories.test = {
+ path = "/a/path";
+ uri = "git+ssh://user@example.com:/~user/path/to/repo.git";
+ };
+ };
+
+ nmt.script = ''
+ serviceFile=home-files/.config/systemd/user/git-sync-test.service
+
+ assertFileExists $serviceFile
+ assertFileContent $serviceFile ${
+ builtins.toFile "expected" ''
+ [Install]
+ WantedBy=default.target
+
+ [Service]
+ Environment=GIT_SYNC_DIRECTORY=/a/path
+ Environment=GIT_SYNC_COMMAND=@git-sync@/bin/git-sync
+ Environment=GIT_SYNC_REPOSITORY=git+ssh://user@example.com:/~user/path/to/repo.git
+ Environment=GIT_SYNC_INTERVAL=500
+ ExecStart=@git-sync@/bin/git-sync-on-inotify
+ Restart=on-abort
+
+ [Unit]
+ Description=Git Sync test
+ ''
+ }
+ '';
+ };
+}
diff --git a/tests/modules/services/git-sync/default.nix b/tests/modules/services/git-sync/default.nix
new file mode 100644
index 000000000..0e9db79d0
--- /dev/null
+++ b/tests/modules/services/git-sync/default.nix
@@ -0,0 +1 @@
+{ git-sync = ./basic.nix; }