diff options
Diffstat (limited to 'modules/office/calcurse/calcurse-sync.sh')
| -rw-r--r-- | modules/office/calcurse/calcurse-sync.sh | 281 |
1 files changed, 0 insertions, 281 deletions
diff --git a/modules/office/calcurse/calcurse-sync.sh b/modules/office/calcurse/calcurse-sync.sh deleted file mode 100644 index 737ebfb..0000000 --- a/modules/office/calcurse/calcurse-sync.sh +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env bash -# Keeps calcurse's data directory in git, so you can back it up / sync -# it across machines via a remote (e.g. a private GitHub repo). -# -# Usage: -# calcurse-sync init [remote-url] Turn the calcurse data dir into a git -# repo and (optionally) attach a remote. -# Safe to re-run — no-ops if a repo -# already exists. If no remote is given, -# falls back to $CALCURSE_SYNC_REMOTE, -# then (if interactive) a prompt. -# calcurse-sync sync Commit any changes and push. Initializes -# the repo automatically on first run. -# calcurse-sync pull Pull down changes from the remote. -# calcurse-sync status Show git status of the data directory. -# calcurse-sync remote <url> Add/update the remote after the fact. -# calcurse-sync help Show this message. -# -# Defaults to $XDG_DATA_HOME/calcurse (usually ~/.local/share/calcurse). -# Override with $CALCURSE_DATA_DIR if yours lives elsewhere. -# Override the default remote used on first init with $CALCURSE_SYNC_REMOTE. - -set -euo pipefail - -DATA_DIR="${CALCURSE_DATA_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/calcurse}" -BRANCH="master" -SYNC_TIMEOUT="8" # seconds before a network op gives up - -info() { printf '\033[1;34m==>\033[0m %s\n' "$*"; } -warn() { printf '\033[1;33m==> warning:\033[0m %s\n' "$*" >&2; } -error() { printf '\033[1;31m==> error:\033[0m %s\n' "$*" >&2; } -die() { - error "$*" - exit 1 -} - -require_git() { - command -v git >/dev/null 2>&1 || - die "git is not installed or not on PATH. Install it and try again." -} - -require_data_dir() { - if [ ! -d "$DATA_DIR" ]; then - die "calcurse data directory not found at: $DATA_DIR -Run calcurse at least once so it can create its data files, or set -CALCURSE_DATA_DIR to point at the right location." - fi -} - -require_repo() { - if [ ! -d "$DATA_DIR/.git" ]; then - die "no git repository found in $DATA_DIR -Run 'calcurse-sync init' first to set one up." - fi -} - -repo_exists() { - [ -d "$DATA_DIR/.git" ] -} - -has_remote() { - git -C "$DATA_DIR" remote get-url origin >/dev/null 2>&1 -} - -has_upstream() { - git -C "$DATA_DIR" rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1 -} - -# e.g. "25th May, 2026 at 12:34 PM" -readable_timestamp() { - local day suffix month_year time_part - - day=$(date +%-d) - case "$day" in - 1 | 21 | 31) suffix="st" ;; - 2 | 22) suffix="nd" ;; - 3 | 23) suffix="rd" ;; - *) suffix="th" ;; - esac - - month_year=$(date +"%B, %Y") - time_part=$(date +"%I:%M %p" | sed 's/^0//') - - printf '%s%s %s at %s' "$day" "$suffix" "$month_year" "$time_part" -} - -# Initializes the git repo, makes an initial commit if there's anything to -# commit, and attaches a remote. The remote is resolved in this order: -# explicit arg > $CALCURSE_SYNC_REMOTE > interactive prompt (tty only) > -# skipped. Shared by `init` (explicit/manual) and `sync`/activation -# (automatic, first-run-on-a-new-device). -do_init() { - local remote_url="${1:-${CALCURSE_SYNC_REMOTE:-}}" - - info "No git repository found in $DATA_DIR — initializing one." - git -C "$DATA_DIR" init -b "$BRANCH" >/dev/null - - # calcurse sometimes drops lock/swap files in here; keep them out of git - if [ ! -e "$DATA_DIR/.gitignore" ]; then - cat >"$DATA_DIR/.gitignore" <<'EOF' -*.lock -*.swp -EOF - fi - - git -C "$DATA_DIR" add -A - if ! git -C "$DATA_DIR" diff --cached --quiet; then - git -C "$DATA_DIR" commit -m "sync: $(readable_timestamp)" >/dev/null - info "Created initial commit." - else - warn "Nothing to commit yet (data directory is empty)." - fi - - if [ -z "$remote_url" ] && [ -t 0 ]; then - read -r -p "Remote URL to push to (leave blank to skip): " remote_url - fi - - if [ -n "$remote_url" ]; then - git -C "$DATA_DIR" remote add origin "$remote_url" - info "Pushing initial commit to $remote_url" - if git -C "$DATA_DIR" push -u origin "$BRANCH"; then - info "Repo initialized and pushed." - else - error "Push failed. The remote was still added — check the URL and your" - error "credentials, then try 'calcurse-sync sync' again." - exit 1 - fi - else - warn "No remote configured. This repo will only track history locally" - warn "until you run 'calcurse-sync remote <url>' (or set CALCURSE_SYNC_REMOTE)." - fi -} - -cmd_init() { - require_git - require_data_dir - - if repo_exists; then - info "Repository already exists in $DATA_DIR — nothing to do." - return 0 - fi - - do_init "${1:-}" -} - -cmd_remote() { - require_git - require_repo - - local url="${1:-}" - [ -n "$url" ] || die "usage: calcurse-sync remote <url>" - - if has_remote; then - git -C "$DATA_DIR" remote set-url origin "$url" - info "Updated remote 'origin' to $url" - else - git -C "$DATA_DIR" remote add origin "$url" - info "Added remote 'origin' pointing to $url" - fi -} - -cmd_sync() { - require_git - require_data_dir - - if ! repo_exists; then - do_init - return 0 - fi - - cd "$DATA_DIR" - git add -A - - if ! git diff --cached --quiet; then - git commit -m "sync: $(readable_timestamp)" >/dev/null - info "Committed changes." - else - info "No local changes to commit." - fi - - if ! has_remote; then - warn "No remote configured for this repo — commit saved locally only." - warn "Run 'calcurse-sync remote <url>' to enable pushing." - return 0 - fi - - if has_upstream && [ -z "$(git log '@{u}..HEAD' --oneline)" ]; then - info "Already up to date with the remote." - return 0 - fi - - info "Pushing to remote..." - if has_upstream; then - push_cmd=(timeout "$SYNC_TIMEOUT" git push) - else - push_cmd=(timeout "$SYNC_TIMEOUT" git push -u origin "$BRANCH") - fi - - if "${push_cmd[@]}"; then - info "Sync complete." - else - status=$? - if [ "$status" -eq 124 ]; then - warn "Push timed out after ${SYNC_TIMEOUT}s — commit saved locally, will" - warn "retry on next sync." - return 0 - fi - error "Push failed." - error "This usually means the remote has commits you don't have locally" - error "(e.g. synced from another machine). Run 'calcurse-sync pull'" - error "to merge them in, then sync again. If that's not it, check your" - error "network connection and git credentials." - exit "$status" - fi -} - -cmd_pull() { - require_git - require_data_dir - require_repo - - if ! has_remote; then - warn "no remote configured for this repo — skipping pull." - return 0 - fi - - cd "$DATA_DIR" - - if [ -n "$(git status --porcelain)" ]; then - warn "You have uncommitted changes in $DATA_DIR." - warn "Run 'calcurse-sync sync' first so a pull can't clobber them." - die "aborting pull to avoid data loss." - fi - - info "Pulling from remote (timeout ${SYNC_TIMEOUT}s)..." - if timeout "$SYNC_TIMEOUT" git pull --rebase origin "$BRANCH"; then - info "Up to date." - else - status=$? - if [ "$status" -eq 124 ]; then - warn "Pull timed out after ${SYNC_TIMEOUT}s — continuing with local data." - warn 'Set $CALCURSE_SYNC_TIMEOUT to a higher value if your connection' - warn "is just slow, not down." - return 0 - fi - error "Pull failed — likely a merge conflict." - error "Resolve conflicts manually in $DATA_DIR, then run:" - error " git -C \"$DATA_DIR\" rebase --continue" - error "(or 'git rebase --abort' to back out)." - exit 1 - fi -} - -cmd_status() { - require_git - require_data_dir - require_repo - - git -C "$DATA_DIR" status -} - -cmd_help() { - sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//' -} - -main() { - local sub="${1:-help}" - shift || true - - case "$sub" in - init) cmd_init "$@" ;; - sync) cmd_sync "$@" ;; - pull) cmd_pull "$@" ;; - status) cmd_status "$@" ;; - remote) cmd_remote "$@" ;; - help | -h | --help) cmd_help ;; - *) die "unknown command: $sub (try 'calcurse-sync help')" ;; - esac -} - -main "$@" |
