diff options
-rw-r--r-- | lib/eos/jao-borgmatic.el | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/lib/eos/jao-borgmatic.el b/lib/eos/jao-borgmatic.el new file mode 100644 index 0000000..e9fc79f --- /dev/null +++ b/lib/eos/jao-borgmatic.el @@ -0,0 +1,148 @@ +;;; jao-borgmatic.el --- Simple access to borgmatic -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 jao + +;; Author: jao <mail@jao.io> +;; Keywords: convenience + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; An emacs front-end for borgmatic + +;;; Code: + +(defconst jao-borgmatic--buffer "*borgmatic*") +(defun jao-borgmatic--buffer () + (get-buffer-create jao-borgmatic--buffer)) + +(defvar jao-borgmatic-extract-path "/tmp/borgmatic") + +(defvar jao-borgmatic-mode-map + (let ((map (make-keymap))) + (suppress-keymap map) + (define-key map [?q] 'bury-buffer) + (define-key map [?n] 'next-line) + (define-key map [?p] 'previous-line) + (define-key map [?g] 'jao-borgmatic-list) + (define-key map [?x] 'jao-borgmatic-extract) + (define-key map [?c] 'jao-borgmatic-check) + map)) + +;;;###autoload +(defun jao-borgmatic-mode () + "A very simple mode to show the output of borgmatic commands." + (interactive) + (kill-all-local-variables) + (buffer-disable-undo) + (use-local-map jao-borgmatic-mode-map) + ;; (setq-local font-lock-defaults '(jao-borgmatic-font-lock-keywords)) + (setq-local truncate-lines t) + (setq-local next-line-add-newlines nil) + (setq major-mode 'jao-bormagtic-mode) + (setq mode-name "borgmatic") + (read-only-mode 1)) + +(defun jao-borgmatic--do (things &optional buffer) + "Execute a borgmatic command THINGS in the given BUFFER." + (let ((b (or buffer (pop-to-buffer (get-buffer-create jao-borgmatic--buffer))))) + (let ((inhibit-read-only t) + (cmd (format "borgmatic %s" things))) + (unless buffer + (with-current-buffer b (delete-region (point-min) (point-max)))) + (message "Running: %s ...." cmd) + (shell-command cmd b) + (message "")))) + +(defun jao-borgmatic--archive-at-point () + (save-excursion + (beginning-of-line) + (when (looking-at "- \\([^ ]+\\)") + (match-string-no-properties 1)))) + +(defvar jao-borgmatic--archive-history nil) +(defvar-local jao-borgmatic--archives nil) + +(defun jao-borgmatic--archives (&optional retrieve) + (or (and (not retrieve) jao-borgmatic--archives) + (let ((c (shell-command-to-string + "borgmatic list --format '{archive} {time}*'"))) + (setq jao-borgmatic--archives (cdr (split-string c "\\*\\|\n")))))) + +(defun jao-borgmatic--read-archive (&optional retrieve) + (car (split-string (completing-read "Archive: " + (jao-borgmatic--archives retrieve) + nil + nil + nil + 'jao-borgmatic--archive-history + (jao-borgmatic--archive-at-point))))) + +;;;###autoload +(defun jao-borgmatic-list () + (interactive) + (with-current-buffer (jao-borgmatic--buffer) + (jao-borgmatic-mode) + (let ((inhibit-read-only t) + (archives (with-temp-message "Retrieving archives list..." + (jao-borgmatic--archives t)))) + (delete-region (point-min) (point-max)) + (insert "Archives: \n\n") + (dolist (a archives) + (unless (string-blank-p a) (insert "- " a "\n"))) + (insert "\n" (with-temp-buffer + (jao-borgmatic--do "info" (current-buffer)) + (buffer-string))))) + (pop-to-buffer (jao-borgmatic--buffer)) + (goto-line 3)) + +(defconst jao-borgmatic--extract-output " *borgmatic-extract output*") + +(defun jao-borgmatic--extract-sentinel (paths) + (lambda (proc &rest _) + (when (and (eq (process-status proc) 'exit) + (y-or-n-p "Borg extraction finished, show?")) + (if (eq (process-exit-status proc) 0) + (let ((d (file-name-directory (car paths)))) + (dired (expand-file-name d jao-borgmatic-extract-path))) + (pop-to-buffer jao-borgmatic--extract-output))))) + +(defvar jao-borgmatic--extract-history nil) + +;;;###autoload +(defun jao-borgmatic-extract () + (interactive) + (let* ((archive (jao-borgmatic--read-archive)) + (path (read-string "Path(s) (e.g. home/jao/emacs.d/init.el): " + nil 'jao-borgmatic--extract-history)) + (paths (if (string-blank-p path) + (not (or (y-or-n-p "Extract the full archive?") + (error "Cancelled"))) + (split-string path))) + (default-directory jao-borgmatic-extract-path)) + (make-directory default-directory t) + (message "Extracting %s/%s to directory %s in the background" + archive path default-directory) + (make-process :name "borgmatic-extract" + :buffer jao-borgmatic--extract-output + :command (append `("borgmatic" "extract" + "--archive" ,archive + "--destination" ,default-directory) + (when paths (cons "--path" paths))) + :sentinel (jao-borgmatic--extract-sentinel paths) + :stderr nil))) + +(provide 'jao-borgmatic) +;;; jao-borgmatic.el ends here |