From a6096c25ef9edea46d958876f077d4dd06d783be Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Wed, 17 Jun 2020 21:00:41 +0200 Subject: [PATCH] [services] Make git-sync script more universal Can now sync any folder, passed in on the command line. --- .../.config/systemd/user/commit_notes.service | 11 ++-- services/.local/share/services/git-sync | 65 ++++++++++++------- services/README.md | 40 ++++++++++++ 3 files changed, 89 insertions(+), 27 deletions(-) create mode 100644 services/README.md diff --git a/services/.config/systemd/user/commit_notes.service b/services/.config/systemd/user/commit_notes.service index 7101a8f..fc84b69 100644 --- a/services/.config/systemd/user/commit_notes.service +++ b/services/.config/systemd/user/commit_notes.service @@ -1,12 +1,13 @@ [Unit] Description=Automatically commit notes in directory -After=graphical.target +After=default.target [Service] Type=simple -Environment=TIME_TO_COMMIT=120 UNCHANGED_RUNS_TO_PUSH=30 -ExecStart=/bin/bash -c '%h/.local/share/services/git-sync' -Restart=on-failure +Environment=GS_TIME_TO_COMMIT=120 GS_UNCHANGED_RUNS_TO_PUSH=30 +# workaround to allow relative executable invocation (i.e. current users' home dir) +ExecStart=/bin/bash -c '%h/.local/share/services/git-sync %h/documents/notes/uni' +# Restart=on-failure [Install] -WantedBy=multi-user.target +WantedBy=default.target diff --git a/services/.local/share/services/git-sync b/services/.local/share/services/git-sync index f3ecb42..66a6745 100755 --- a/services/.local/share/services/git-sync +++ b/services/.local/share/services/git-sync @@ -1,17 +1,23 @@ #!/usr/bin/env sh +# +# Keeps a git directory synced by automatically committing every x seconds. +# After y number of runs without changes automatically pushes the directory to a remote. # time in seconds to check for changes to commit TIME_TO_COMMIT=${GS_TIME_TO_COMMIT:-120} # amount of times to check for changes *without changes occurring* to push to origin UNCHANGED_RUNS_TO_PUSH=${GS_UNCHANGED_RUNS_TO_PUSH:-30} -NOTEDIR=${WIKIROOT:-"$HOME/documents/notes"}/uni -[ -z "$NOTEDIR" ] && [ -z "$1" ] && { - msg "ERROR: Please supply a directory to sync." - exit 1 -} +# logging verbosity level -- 0=error, 1=info, 2=debug +VERBOSITY=${GS_LOG_VERBOSITY:-1} -DIR="${NOTEDIR:-$1}" +set_target() { + [ -z "$GS_TARGETDIR" ] && [ -z "$1" ] && { + msg "ERROR: git-sync requires a target directory to keep in sync to be passed in." 0 + exit 1 + } + DIR="${GS_TARGETDIR:-$1}" +} commit() { run_git pull --ff-only --ff @@ -28,8 +34,8 @@ push() { } should_commit() { - if [ "$(run_git status --porcelain | wc -l)" -eq 0 ]; then - msg "No changes to commit in $DIR" + if [ "$(run_git diff-files --name-only | wc -l)" -eq 0 ]; then + msg "No changes to commit in $DIR" 2 false else msg "Found changes to commit in $DIR" @@ -49,24 +55,39 @@ run_git() { git -C "$DIR" "$@" } +# echos its first argument +# verbosity level optionally set through second argument msg() { + lvl=${2:-1} + [ "$lvl" -gt "$VERBOSITY" ] && return 0 + echo "$1" } -no_change_cycle=0 -while true; do - if should_commit; then - commit - no_change_cycle=0 - fi +watch_changes() { + no_change_cycle=0 + while true; do + if should_commit; then + commit + no_change_cycle=0 + fi - if should_push; then - push - no_change_cycle=-9999 - fi + if should_push; then + push + no_change_cycle=-9999 + fi - msg "No changes for $((no_change_cycle * TIME_TO_COMMIT)) of $((UNCHANGED_RUNS_TO_PUSH * TIME_TO_COMMIT)) seconds, going back to sleep for $((TIME_TO_COMMIT)) seconds." + msg "No changes for $((no_change_cycle * TIME_TO_COMMIT)) of $((UNCHANGED_RUNS_TO_PUSH * TIME_TO_COMMIT)) seconds, going back to sleep for $((TIME_TO_COMMIT)) seconds." 2 - no_change_cycle=$((no_change_cycle + 1)) - sleep "$TIME_TO_COMMIT" -done + no_change_cycle=$((no_change_cycle + 1)) + sleep "$TIME_TO_COMMIT" + done +} + +main() { + set_target "$1" + + watch_changes +} + +main "$1" diff --git a/services/README.md b/services/README.md new file mode 100644 index 0000000..5582e39 --- /dev/null +++ b/services/README.md @@ -0,0 +1,40 @@ +# User services + +This module uses `systemd` to provide various services for the user running the dotfiles. +The services will get moved into the correct `.config` directory for `systemd` to pick them up as user services. + +They will, for now, *not* be automatically enabled when installing the dotfiles. This is pending changes. +They can be enabled as needed by invoking `systemctl --user enable [service]`. Be aware that + +## Why systemd + +There are two reasons for the service module making use of `systemd` to manage its services: + +The machine(s) these dotfiles are currently targeting are both archlinux-based. +That means, pragmatically, I will adhere to using `systemd` since it is what arch uses as init manager. +I *am* eye-ing alternatives like [Artix Linux](https://artixlinux.org/) but adopting it is, if it happens at all, still a way out due to my current time constraints. + +Secondly, I am using this opportunity to learn more about `systemd`. +There are various arcane-seeming invocations in `systemd` which are beginning to make more sense to me as time goes on +(looking at you, `journalctl`). +I do not want to dismiss a program without having given it a fair shake (especially if it enjoys *such* widespread adoption). +Additionally, process watching and automatic maintenance, as well as the entire `.timer` system that it can provide for services are pretty fantastic, even if their syntax takes some getting used to for me. + +That said, there are also many moments where I am envious of the simplicity and straightforward nature of something like [runit](http://smarden.org/runit/). +So what that essentially means: this service module uses `systemd` *for now*. +It might change to something else in the future. +It might also not be written very well, since I am using it to adopt a mental mapping of `systemd` at the same time. + +## Commit Notes service + +This service keeps my university note directory in sync with a remote origin. +The script behind it (`git-sync`) can be used more generally to keep any git directory in sync. + +The idea behind the services is: commit asap, push when finished. +It basically runs on two different timers, every x seconds (120 by default, can be changed with `GS_TIME_TO_COMMIT` env var) it will commit whatever changes took place in the directory. +After x runs of the commit timer *without changes* (30 by default, can be changed with `GS_UNCHANGED_RUNS_TO_PUSH`) it will push the git index to its default remote. + +In effect this means, using the default values, the service will commit any changes made every two minutes and when *no* changes were made for an hour (±2minutes), it will push it to remote. + +The two cycles can be changed independently from each other via the environment variables mentioned above so that, for example, the repository can be pushed every single time a commit takes place, or commits can be checked for on faster or shorter intervals. +As another example, if you want to check for changes every 30 seconds but still push every hour, you would do `GS_TIME_TO_COMMIT=30` and `GS_UNCHANGED_RUNS_TO_PUSH=120`.