summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lib/eos/jao-borgmatic.el148
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