diff options
Diffstat (limited to 'src/cli.lisp')
-rw-r--r-- | src/cli.lisp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/cli.lisp b/src/cli.lisp new file mode 100644 index 0000000..2f03425 --- /dev/null +++ b/src/cli.lisp @@ -0,0 +1,135 @@ +(in-package :ybackup) + +#| +(defun fetch-configuration () + (let ((xdg (uiop:getenv "XDG_CONFIG_DIR"))) + (if xdg + (setf xdg (concatenate 'string xdg "/ybackup.lisp")) + (setf xdg (concatenate 'string (uiop:getenv "HOME") "/.config/ybackup.lisp"))) + (ensure-directories-exist xdg) + (with-open-file (file xdg :if-does-not-exist :create) + (uiop:with-safe-io-syntax + (uiop:slurp-stream-form :at nil))))) +|# +(opts:define-opts + (:name :help + :description "Print this text" + :short #\h + :long "help") + (:name :backup + :description "Directory to backup" + :short #\b + :long "backup" + :arg-parser #'identity + :meta-var "DIRECTORY") + (:name :read + :description "Read a backup to a directory" + :short #\r + :long "read" + :arg-parser #'identity + :meta-var "DIRECTORY") + (:name :list-files + :description "List the files in the repository." + :short #\l + :long "list") + (:name :file-backend + :description + "Use this for a file-based local backup. The argument is the directory that will +contain the ERIS chunks." + :long "file-backend" + :arg-parser #'identity + :meta-var "DIRECTORY") + (:name :http-backend + :description + "Use this for an HTTP-based backup. The argument is the URL which will accept +the ERIS chunks." + :long "http" + :arg-parser #'identity + :meta-var "URL") + (:name :backend + :description "An S-expression that returns a valid eris:backend object." + :long "backend" + :meta-var "SEXP" + :arg-parser #'read-from-string) + (:name :filter + :description + "A one-argument lambda S-expression that takes a filename as an argument and +returns nil if the file is to be read or t if it is to be skipped." + :long "filter" + :meta-var "SEXP" + :arg-parser #'read-from-string) + (:name :overwrite + :description "Set if the program should overwrite existing files when writing from backup. " + :long "overwrite") + (:name :incremental + :description "Set to enable incremental backup. Requires the --repo optio.." + :short #\i + :long "incremental") + (:name :repo + :description "The file that the URN will be written or read from." + :long "repo" + :meta-var "FILE OR URN" + :arg-parser #'identity) + (:name :secret + :description "The secret used for encryption." + :long "secret" + :short #\s + :meta-var "SECRET" + :arg-parser #'identity) + (:name :metadata + :description "Print repository metadata when reading or listing files." + :long "metadata" + :short #\m)) + +(defun file-or-urn-to-urn (file-or-urn) + (if (string-prefix-p "urn:" file-or-urn) + file-or-urn + (with-open-file (file file-or-urn :direction :input :if-does-not-exist :error) + (read-line file)))) + +(defun main () + (restart-case (destructuring-bind (&key help backup read list-files + file-backend http-backend backend + filter overwrite incremental repo + secret metadata) + (opts:get-opts) + ;; some sanity checks + ;; exclusive options + (when (or (and backup read) (and backup list-files) (and read list-files)) + (error "Choose one of read, backup, or list.")) + (when (or (and backend http-backend) (and backend file-backend) (and file-backend http-backend)) + (error "Choose one backend.")) + + (when help + (opts:describe :prefix #.(format nil "ybackup version ~a" version)) + (opts:exit)) + + ;; repo argument necessary except for backup + #|(when (and (not repo) backup) + (error "Please provide --repo argument."))|# + + ;; don't save urns to files named urn: + #|(when (and backup repo (string-prefix-p "urn:" repo)) + (error "No urns as filenames."))|# + + (let ((backend + (cond + (file-backend (make-instance 'eris:file-backend :directory file-backend)) + (http-backend (error "Unimplemented http-backend.")) + (backend (eval backend)) + (t (error "Choose backend."))))) + ;; TODO: + ;; ADD METADATA, SECRET HANDLING (!!!) + + (cond + (list-files + (print (list-files (file-or-urn-to-urn repo) backend)) + ()) + (backup (let ((urn (make-backup backup backend :incremental incremental))) + (if repo (with-open-file (file repo :direction :output :if-does-not-exist :create + :if-exists :new-version) + (write-string urn file)) + (princ urn)))) + (read (read-backup (file-or-urn-to-urn repo) backend read :overwrite overwrite))) + (opts:exit))) + (exit () (opts:exit)))) |