From 5df72af92d27a565541b9950abe56499e61ac83b Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Sun, 26 Apr 2026 19:45:45 +0200 Subject: [PATCH] update docker --- elpa/docker-20251028.1026/docker-process.el | 119 ---------- elpa/docker-20260126.1212/README-elpa | 1 + .../docker-autoloads.el | 0 .../docker-compose.el | 4 +- .../docker-container.el | 22 +- .../docker-context.el | 0 .../docker-core.el | 36 ++- .../docker-faces.el | 0 .../docker-group.el | 0 .../docker-image.el | 104 ++++++++- .../docker-network.el | 0 .../docker-pkg.el | 6 +- elpa/docker-20260126.1212/docker-process.el | 212 ++++++++++++++++++ .../docker-utils.el | 14 +- .../docker-volume.el | 0 .../docker.el | 4 +- 16 files changed, 380 insertions(+), 142 deletions(-) delete mode 100644 elpa/docker-20251028.1026/docker-process.el create mode 100644 elpa/docker-20260126.1212/README-elpa rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-autoloads.el (100%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-compose.el (98%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-container.el (96%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-context.el (100%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-core.el (74%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-faces.el (100%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-group.el (100%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-image.el (73%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-network.el (100%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-pkg.el (78%) create mode 100644 elpa/docker-20260126.1212/docker-process.el rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-utils.el (94%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker-volume.el (100%) rename elpa/{docker-20251028.1026 => docker-20260126.1212}/docker.el (95%) diff --git a/elpa/docker-20251028.1026/docker-process.el b/elpa/docker-20251028.1026/docker-process.el deleted file mode 100644 index d929923c..00000000 --- a/elpa/docker-20251028.1026/docker-process.el +++ /dev/null @@ -1,119 +0,0 @@ -;;; docker-process.el --- Docker process -*- lexical-binding: t -*- - -;; Author: Philippe Vaucher - -;; This file is NOT part of GNU Emacs. - -;; 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, 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 GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. - -;;; Commentary: - -;;; Code: -(eval-when-compile - (setq-local byte-compile-warnings '(not docstrings))) - -(require 's) -(require 'aio) -(require 'dash) - -(require 'docker-group) -(require 'docker-utils) - -(defcustom docker-run-as-root nil - "Run docker as root." - :group 'docker - :type 'boolean) - -(defcustom docker-show-messages t - "If non-nil `message' docker commands which are run." - :group 'docker - :type 'boolean) - -(defcustom docker-run-async-with-buffer-function (if (featurep 'vterm) - 'docker-run-async-with-buffer-vterm - 'docker-run-async-with-buffer-shell) - "Function used to run a program with a live buffer attached to it." - :group 'docker - :type 'symbol) - - -(defmacro docker-with-sudo (&rest body) - "Ensure `default-directory' is set correctly according to `docker-run-as-root' then execute BODY." - (declare (indent defun)) - `(let ((default-directory (if (and docker-run-as-root (not (file-remote-p default-directory))) - "/sudo::" - default-directory))) - ,@body)) - -(defun docker-run-start-file-process-shell-command (program &rest args) - "Execute \"PROGRAM ARGS\" and return the process." - (docker-with-sudo - (let* ((process-args (-remove 's-blank? (-flatten args))) - (command (s-join " " (-insert-at 0 program process-args)))) - (when docker-show-messages (message "Running: %s" command)) - (start-file-process-shell-command command (apply #'docker-utils-generate-new-buffer-name program process-args) command)))) - -(defun docker-run-async (program &rest args) - "Execute \"PROGRAM ARGS\" and return a promise with the results." - (let* ((process (apply #'docker-run-start-file-process-shell-command program args)) - (promise (aio-promise))) - (set-process-query-on-exit-flag process nil) - (set-process-sentinel process (-partial #'docker-process-sentinel promise)) - promise)) - -(defun docker-run-async-with-buffer (program &rest args) - "Execute \"PROGRAM ARGS\" and display output in a new buffer." - (apply docker-run-async-with-buffer-function program args)) - -(defun docker-run-async-with-buffer-shell (program &rest args) - "Execute \"PROGRAM ARGS\" and display output in a new `shell' buffer." - (let* ((process (apply #'docker-run-start-file-process-shell-command program args)) - (buffer (process-buffer process))) - (set-process-query-on-exit-flag process nil) - (with-current-buffer buffer (shell-mode)) - (set-process-filter process 'comint-output-filter) - (switch-to-buffer-other-window buffer))) - -(defun docker-run-async-with-buffer-vterm (program &rest args) - "Execute \"PROGRAM ARGS\" and display output in a new `vterm' buffer." - (defvar vterm-kill-buffer-on-exit) - (defvar vterm-shell) - (if (fboundp 'vterm-other-window) - (let* ((process-args (-remove 's-blank? (-flatten args))) - (vterm-shell (s-join " " (-insert-at 0 program process-args))) - (vterm-kill-buffer-on-exit nil)) - (vterm-other-window - (apply #'docker-utils-generate-new-buffer-name program process-args))) - (error "The vterm package is not installed"))) - -(defun docker-process-sentinel (promise process event) - "Sentinel that resolves the PROMISE using PROCESS and EVENT." - (when (memq (process-status process) '(exit signal)) - (setq event (substring event 0 -1)) - (if (not (string-equal event "finished")) - (error "Error running: \"%s\" (%s)" (process-name process) event) - (aio-resolve promise - (lambda () - (when docker-show-messages - (message "Finished: %s" (process-name process))) - (run-with-timer 2 nil (lambda () (message nil))) - (with-current-buffer (process-buffer process) - (prog1 (buffer-substring-no-properties (point-min) (point-max)) - (kill-buffer)))))))) - -(provide 'docker-process) - -;;; docker-process.el ends here diff --git a/elpa/docker-20260126.1212/README-elpa b/elpa/docker-20260126.1212/README-elpa new file mode 100644 index 00000000..55901186 --- /dev/null +++ b/elpa/docker-20260126.1212/README-elpa @@ -0,0 +1 @@ +This package allows you to manipulate docker images, containers & more from Emacs. diff --git a/elpa/docker-20251028.1026/docker-autoloads.el b/elpa/docker-20260126.1212/docker-autoloads.el similarity index 100% rename from elpa/docker-20251028.1026/docker-autoloads.el rename to elpa/docker-20260126.1212/docker-autoloads.el diff --git a/elpa/docker-20251028.1026/docker-compose.el b/elpa/docker-20260126.1212/docker-compose.el similarity index 98% rename from elpa/docker-20251028.1026/docker-compose.el rename to elpa/docker-20260126.1212/docker-compose.el index 924c6779..dd2e42b5 100644 --- a/elpa/docker-20251028.1026/docker-compose.el +++ b/elpa/docker-20260126.1212/docker-compose.el @@ -49,7 +49,7 @@ (defun docker-compose-run-docker-compose-async-with-buffer (action &rest args) "Execute \"`docker-compose-command' ACTION ARGS\" and display output in a new buffer." - (apply #'docker-run-async-with-buffer docker-compose-command (docker-compose-arguments) action args)) + (apply #'docker-run-async-with-buffer-interactive docker-compose-command (docker-compose-arguments) action args)) (aio-defun docker-compose-services () "Return the list of services." @@ -69,7 +69,7 @@ prompt ;; in docker compose v2, we can obtain the list of ;; projects with 'ls' argument - (if (string-match-p "*?docker compose*?" docker-compose-command) + (if (string-match-p "\\bdocker\\s-+compose\\b" docker-compose-command) (split-string (shell-command-to-string (concat docker-compose-command " ls" " --all" " -q")) diff --git a/elpa/docker-20251028.1026/docker-container.el b/elpa/docker-20260126.1212/docker-container.el similarity index 96% rename from elpa/docker-20251028.1026/docker-container.el rename to elpa/docker-20260126.1212/docker-container.el index 48423c1b..c7cd9560 100644 --- a/elpa/docker-20251028.1026/docker-container.el +++ b/elpa/docker-20260126.1212/docker-container.el @@ -181,7 +181,7 @@ string that transforms the displayed values in the column." (defun docker-container-assert-tramp-docker () "Assert tramp docker support is available." - (unless (or (docker-utils-package-p 'docker-container) + (unless (or (assoc docker-container-tramp-method tramp-methods) (docker-utils-package-p 'docker-tramp)) (error "Tramp docker support was not detected, try installing docker-tramp"))) @@ -397,7 +397,12 @@ default directory set to workdir." (defun docker-container-shell-command (container) "Run exec of a CONTAINER." (interactive (list (docker-container-read-name))) - (shell-command (read-shell-command "Run: " (format "docker exec %s " container)))) + (let* ((default-command (string-join (append (list docker-command) + (docker-arguments) + (list "exec" container)) + " ")) + (command (read-shell-command "Run: " default-command))) + (shell-command command))) (defun docker-container-shell-command-selection () "Run `docker exec' on the containers selection." @@ -427,7 +432,7 @@ default directory set to workdir." ("n" "No STDIN" "--no-stdin") ("d" "Key sequence for detaching" "--detach-keys " read-string)] [:description docker-generic-action-description - ("a" "Attach" docker-generic-action-with-buffer)]) + ("a" "Attach" docker-generic-action-with-buffer-interactive)]) (docker-utils-transient-define-prefix docker-container-cp () "Transient for copying files from/to containers." @@ -456,6 +461,15 @@ default directory set to workdir." [:description docker-generic-action-description ("K" "Kill" docker-generic-action-multiple-ids)]) +(defun docker-container-logs-action (action args) + "Show container logs, streaming if -f flag is present, otherwise collect then display. +ACTION is the docker action, ARGS are the transient arguments." + (interactive (list (docker-get-transient-action) + (transient-args transient-current-command))) + (if (member "-f" args) + (docker-generic-action-with-buffer-noninteractive action args) + (aio-wait-for (docker-generic-action-with-buffer action args)))) + (docker-utils-transient-define-prefix docker-container-logs () "Transient for showing containers logs." :man-page "docker-container-logs" @@ -465,7 +479,7 @@ default directory set to workdir." ("t" "Tail" "--tail " read-string) ("u" "Until" "--until " read-string)] [:description docker-generic-action-description - ("L" "Logs" docker-generic-action-with-buffer)]) + ("L" "Logs" docker-container-logs-action)]) (docker-utils-define-transient-arguments docker-container-ls) diff --git a/elpa/docker-20251028.1026/docker-context.el b/elpa/docker-20260126.1212/docker-context.el similarity index 100% rename from elpa/docker-20251028.1026/docker-context.el rename to elpa/docker-20260126.1212/docker-context.el diff --git a/elpa/docker-20251028.1026/docker-core.el b/elpa/docker-20260126.1212/docker-core.el similarity index 74% rename from elpa/docker-20251028.1026/docker-core.el rename to elpa/docker-20260126.1212/docker-core.el index 27621292..a7d30b26 100644 --- a/elpa/docker-20251028.1026/docker-core.el +++ b/elpa/docker-20260126.1212/docker-core.el @@ -60,9 +60,13 @@ "Execute \"`docker-command' ARGS\" and return a promise with the results." (apply #'docker-run-async docker-command (docker-arguments) args)) -(defun docker-run-docker-async-with-buffer (&rest args) - "Execute \"`docker-command' ARGS\" and display the results in a buffer." - (apply #'docker-run-async-with-buffer docker-command (docker-arguments) args)) +(defun docker-run-docker-async-with-buffer-interactive (&rest args) + "Execute \"`docker-command' ARGS\" and display output in an interactive buffer." + (apply #'docker-run-async-with-buffer-interactive docker-command (docker-arguments) args)) + +(defun docker-run-docker-async-with-buffer-noninteractive (&rest args) + "Execute \"`docker-command' ARGS\" and display output in a non-interactive buffer." + (apply #'docker-run-async-with-buffer-noninteractive docker-command (docker-arguments) args)) (defun docker-get-transient-action () "Extract the action out of `transient-current-command'." @@ -91,12 +95,32 @@ (aio-await (docker-run-docker-async action args (docker-utils-get-marked-items-ids))) (tablist-revert)) -(defun docker-generic-action-with-buffer (action args) - "Run \"`docker-command' ACTION ARGS\" and print output to a new buffer." +(defun docker-generic-action-with-buffer-interactive (action args) + "Run \"`docker-command' ACTION ARGS\" and print output in an interactive buffer." + (interactive (list (docker-get-transient-action) + (transient-args transient-current-command))) + (--each (docker-utils-get-marked-items-ids) + (docker-run-docker-async-with-buffer-interactive (s-split " " action) args it))) + +(defun docker-generic-action-with-buffer-noninteractive (action args) + "Run \"`docker-command' ACTION ARGS\" and print output in a non-interactive buffer." (interactive (list (docker-get-transient-action) (transient-args transient-current-command))) (--each (docker-utils-get-marked-items-ids) - (docker-run-docker-async-with-buffer (s-split " " action) args it))) + (docker-run-docker-async-with-buffer-noninteractive (s-split " " action) args it))) + +(aio-defun docker-generic-action-with-buffer (action args) + "Run \"`docker-command' ACTION ARGS\", wait for completion, then display output. +This collects all output before displaying, suitable for non-interactive commands." + (interactive (list (docker-get-transient-action) + (transient-args transient-current-command))) + (--each (docker-utils-get-marked-items-ids) + (let* ((id it) + (output (aio-await (docker-run-docker-async (s-split " " action) args id)))) + (docker-utils-with-buffer (format "%s %s" action id) + ;; Strip carriage returns (Docker outputs CRLF line endings) + (insert (ansi-color-apply (replace-regexp-in-string "\r" "" output))) + (special-mode))))) (aio-defun docker-inspect (&optional subcmd) "Run \"`docker-command' inspect\" on the selected items." diff --git a/elpa/docker-20251028.1026/docker-faces.el b/elpa/docker-20260126.1212/docker-faces.el similarity index 100% rename from elpa/docker-20251028.1026/docker-faces.el rename to elpa/docker-20260126.1212/docker-faces.el diff --git a/elpa/docker-20251028.1026/docker-group.el b/elpa/docker-20260126.1212/docker-group.el similarity index 100% rename from elpa/docker-20251028.1026/docker-group.el rename to elpa/docker-20260126.1212/docker-group.el diff --git a/elpa/docker-20251028.1026/docker-image.el b/elpa/docker-20260126.1212/docker-image.el similarity index 73% rename from elpa/docker-20251028.1026/docker-image.el rename to elpa/docker-20260126.1212/docker-image.el index 6ebe8474..c2b6472b 100644 --- a/elpa/docker-20251028.1026/docker-image.el +++ b/elpa/docker-20260126.1212/docker-image.el @@ -86,6 +86,50 @@ displayed values in the column." (sexp :tag "Sort function") (sexp :tag "Format function")))) +(defconst docker-image-history-id-template + "{{ json .ID }}" + "This Go template extracts the history entry id.") + +(defcustom docker-image-history-default-sort-key '("Created" . t) + "Sort key for docker image history. + +This should be a cons cell (NAME . FLIP) where +NAME is a string matching one of the column names +and FLIP is a boolean to specify the sort order." + :group 'docker-image + :type '(cons (string :tag "Column Name" + :validate (lambda (widget) + (unless (--any-p (equal (plist-get it :name) (widget-value widget)) docker-image-history-columns) + (widget-put widget :error "Default Sort Key must match a column name") + widget))) + (choice (const :tag "Ascending" nil) + (const :tag "Descending" t)))) + +(defcustom docker-image-history-columns + '((:name "Id" :width 16 :template "{{ json .ID }}" :sort nil :format nil) + (:name "Created" :width 24 :template "{{ json .CreatedAt }}" :sort nil :format (lambda (x) (format-time-string "%F %T" (date-to-time x)))) + (:name "CreatedBy" :width 60 :template "{{ json .CreatedBy }}" :sort nil :format nil) + (:name "Size" :width 10 :template "{{ json .Size }}" :sort docker-utils-human-size-predicate :format nil) + (:name "Comment" :width 20 :template "{{ json .Comment }}" :sort nil :format nil)) + "Column specification for docker image history. + +The order of entries defines the displayed column order. +'Template' is the Go template passed to `docker-image-history' to create the column +data. It should return a string delimited with double quotes. +'Sort function' is a binary predicate that should return true when the first +argument should be sorted before the second. +'Format function' is a function from string to string that transforms the +displayed values in the column." + :group 'docker-image + :set 'docker-utils-columns-setter + :get 'docker-utils-columns-getter + :type '(repeat (list :tag "Column" + (string :tag "Name") + (integer :tag "Width") + (string :tag "Template") + (sexp :tag "Sort function") + (sexp :tag "Format function")))) + (defcustom docker-image-run-default-args '("-i" "-t" "--rm") "Default infix args used when docker run is invoked. @@ -174,6 +218,42 @@ The result is the tabulated list id for an entry is propertized with "Read an image name." (completing-read "Image: " (-map #'car (aio-wait-for (docker-image-entries))))) +(defvar-local docker-image-history-image nil + "Image name used by the current history buffer.") + +(defvar-local docker-image-history-args nil + "Arguments used by the current history buffer.") + +(aio-defun docker-image-history-entries (image &rest args) + "Return the docker image history data for `tabulated-list-entries'." + (let* ((fmt (docker-utils-make-format-string docker-image-history-id-template docker-image-history-columns)) + (data (aio-await (docker-run-docker-async "image" "history" args (format "--format=\"%s\"" fmt) image))) + (lines (s-split "\n" data t))) + (-map (-partial #'docker-utils-parse docker-image-history-columns) lines))) + +(aio-defun docker-image-history-refresh () + "Refresh the image history list." + (docker-utils-refresh-entries + (apply #'docker-image-history-entries docker-image-history-image docker-image-history-args))) + +(defun docker-image-history-show (image &optional args) + "Display history for IMAGE." + (let ((buffer (docker-utils-generate-new-buffer "docker-image-history" image))) + (with-current-buffer buffer + (docker-image-history-mode) + (setq docker-image-history-image image) + (setq docker-image-history-args args) + (tablist-revert)) + (pop-to-buffer buffer))) + +(defun docker-image-history-selection () + "Show image history for the selection." + (interactive) + (docker-utils-ensure-items) + (let ((args (transient-args 'docker-image-history))) + (--each (docker-utils-get-marked-items-ids) + (docker-image-history-show it args)))) + ;;;###autoload (autoload 'docker-image-pull-one "docker-image" nil t) (aio-defun docker-image-pull-one (name &optional all) "Pull the image named NAME. If ALL is set, use \"-a\"." @@ -186,7 +266,7 @@ The result is the tabulated list id for an entry is propertized with (interactive "sCommand: ") (docker-utils-ensure-items) (--each (docker-utils-get-marked-items-ids) - (docker-run-docker-async-with-buffer "container" "run" (transient-args 'docker-image-run) it command))) + (docker-run-docker-async-with-buffer-interactive "container" "run" (transient-args 'docker-image-run) it command))) (aio-defun docker-image-tag-selection () "Tag images." @@ -225,6 +305,17 @@ applied to the buffer." ["Actions" ("l" "List" tablist-revert)]) +(docker-utils-define-transient-arguments docker-image-history) + +(docker-utils-transient-define-prefix docker-image-history () + "Transient for showing image history." + :man-page "docker-history" + ["Arguments" + ("n" "Don't truncate" "--no-trunc") + ("r" "Raw sizes" "--human=false")] + [:description docker-generic-action-description + ("H" "History" docker-image-history-selection)]) + (transient-define-prefix docker-image-pull () "Transient for pulling images." :man-page "docker-image-pull" @@ -296,6 +387,7 @@ applied to the buffer." ["Docker images help" ("D" "Remove" docker-image-rm) ("F" "Pull" docker-image-pull) + ("H" "History" docker-image-history) ("I" "Inspect" docker-image-inspect) ("P" "Push" docker-image-push) ("R" "Run" docker-image-run) @@ -308,6 +400,7 @@ applied to the buffer." (define-key map "?" 'docker-image-help) (define-key map "D" 'docker-image-rm) (define-key map "F" 'docker-image-pull) + (define-key map "H" 'docker-image-history) (define-key map "I" 'docker-image-inspect) (define-key map "P" 'docker-image-push) (define-key map "R" 'docker-image-run) @@ -334,6 +427,15 @@ applied to the buffer." (tabulated-list-init-header) (tablist-minor-mode)) +(define-derived-mode docker-image-history-mode tabulated-list-mode "Image History" + "Major mode for handling docker image history." + (setq tabulated-list-format (docker-utils-columns-list-format docker-image-history-columns)) + (setq tabulated-list-padding 2) + (setq tabulated-list-sort-key docker-image-history-default-sort-key) + (add-hook 'tabulated-list-revert-hook 'docker-image-history-refresh nil t) + (tabulated-list-init-header) + (tablist-minor-mode)) + (provide 'docker-image) ;;; docker-image.el ends here diff --git a/elpa/docker-20251028.1026/docker-network.el b/elpa/docker-20260126.1212/docker-network.el similarity index 100% rename from elpa/docker-20251028.1026/docker-network.el rename to elpa/docker-20260126.1212/docker-network.el diff --git a/elpa/docker-20251028.1026/docker-pkg.el b/elpa/docker-20260126.1212/docker-pkg.el similarity index 78% rename from elpa/docker-20251028.1026/docker-pkg.el rename to elpa/docker-20260126.1212/docker-pkg.el index 44e0c1c3..9640b8c0 100644 --- a/elpa/docker-20251028.1026/docker-pkg.el +++ b/elpa/docker-20260126.1212/docker-pkg.el @@ -1,5 +1,5 @@ ;; -*- no-byte-compile: t; lexical-binding: nil -*- -(define-package "docker" "20251028.1026" +(define-package "docker" "20260126.1212" "Interface to Docker." '((aio "1.0") (dash "2.19.1") @@ -8,8 +8,8 @@ (tablist "1.1") (transient "0.4.3")) :url "https://github.com/Silex/docker.el" - :commit "375e0ed45bb1edc655d9ae2943a09864bec1fcba" - :revdesc "375e0ed45bb1" + :commit "916686b86e83a3bd2281fbc5e6f98962aa747429" + :revdesc "916686b86e83" :keywords '("filename" "convenience") :authors '(("Philippe Vaucher" . "philippe.vaucher@gmail.com")) :maintainers '(("Philippe Vaucher" . "philippe.vaucher@gmail.com"))) diff --git a/elpa/docker-20260126.1212/docker-process.el b/elpa/docker-20260126.1212/docker-process.el new file mode 100644 index 00000000..a0a91c6c --- /dev/null +++ b/elpa/docker-20260126.1212/docker-process.el @@ -0,0 +1,212 @@ +;;; docker-process.el --- Docker process -*- lexical-binding: t -*- + +;; Author: Philippe Vaucher + +;; This file is NOT part of GNU Emacs. + +;; 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, 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;;; Code: +(eval-when-compile + (setq-local byte-compile-warnings '(not docstrings))) + +(require 's) +(require 'aio) +(require 'dash) + +(require 'docker-group) +(require 'docker-utils) + +(defcustom docker-run-as-root nil + "Run docker as root." + :group 'docker + :type 'boolean) + +(defcustom docker-show-messages t + "If non-nil `message' docker commands which are run." + :group 'docker + :type 'boolean) + +(defcustom docker-terminal-backend 'auto + "Terminal backend used for commands that need a live buffer. +When set to `auto', prefer eat, then vterm, then shell." + :group 'docker + :type '(choice (const :tag "Auto (eat > vterm > shell)" auto) + (const :tag "Eat" eat) + (const :tag "Vterm" vterm) + (const :tag "Shell" shell))) + +(defcustom docker-run-async-with-buffer-function nil + "Obsolete; use `docker-terminal-backend' instead." + :group 'docker + :type 'symbol) + +(make-obsolete-variable 'docker-run-async-with-buffer-function 'docker-terminal-backend "2.5.0") + + +(defmacro docker-with-sudo (&rest body) + "Ensure `default-directory' is set correctly according to `docker-run-as-root' then execute BODY." + (declare (indent defun)) + `(let ((default-directory (if (and docker-run-as-root (not (file-remote-p default-directory))) + "/sudo::" + default-directory))) + ,@body)) + +(defun docker-run-start-file-process-shell-command (program &rest args) + "Execute \"PROGRAM ARGS\" and return the process." + (docker-with-sudo + (let* ((process-args (-remove 's-blank? (-flatten args))) + (command (s-join " " (-insert-at 0 program process-args)))) + (when docker-show-messages (message "Running: %s" command)) + (start-file-process-shell-command command (apply #'docker-utils-generate-new-buffer-name program process-args) command)))) + +(defun docker-run-async (program &rest args) + "Execute \"PROGRAM ARGS\" and return a promise with the results." + (let* ((process (apply #'docker-run-start-file-process-shell-command program args)) + (promise (aio-promise))) + (set-process-query-on-exit-flag process nil) + (set-process-sentinel process (-partial #'docker-process-sentinel promise)) + promise)) + +(defun docker-run-async-with-buffer (program interactive &rest args) + "Execute \"PROGRAM ARGS\" and display output in a new buffer. +INTERACTIVE selects an interactive terminal buffer when non-nil. +Prefer `docker-run-async-with-buffer-interactive' or +`docker-run-async-with-buffer-noninteractive'." + (if docker-run-async-with-buffer-function + (apply docker-run-async-with-buffer-function program interactive args) + (apply #'docker-run-async-with-buffer-dispatch + (docker--terminal-backend) + program interactive args))) + +(defun docker-run-async-with-buffer-interactive (program &rest args) + "Execute \"PROGRAM ARGS\" and display output in an interactive buffer." + (apply #'docker-run-async-with-buffer program t args)) + +(defun docker-run-async-with-buffer-noninteractive (program &rest args) + "Execute \"PROGRAM ARGS\" and display output in a non-interactive buffer." + (apply #'docker-run-async-with-buffer program nil args)) + +(defun docker--terminal-backend-available-p (backend) + "Return non-nil when BACKEND is available." + (pcase backend + ('eat (fboundp 'eat-other-window)) + ('vterm (fboundp 'vterm-other-window)) + ('shell t) + (_ nil))) + +(defun docker--terminal-backend () + "Return the selected backend symbol." + (pcase docker-terminal-backend + ('auto (cond + ((docker--terminal-backend-available-p 'eat) 'eat) + ((docker--terminal-backend-available-p 'vterm) 'vterm) + (t 'shell))) + (_ docker-terminal-backend))) + +(defun docker-run-async-with-buffer-dispatch (backend program interactive &rest args) + "Dispatch PROGRAM to BACKEND and display output in a new buffer." + (pcase backend + ('eat (if (docker--terminal-backend-available-p 'eat) + (apply #'docker-run-async-with-buffer-eat program interactive args) + (error "The eat package is not installed"))) + ('vterm (if (docker--terminal-backend-available-p 'vterm) + (apply #'docker-run-async-with-buffer-vterm program interactive args) + (error "The vterm package is not installed"))) + ('shell (apply #'docker-run-async-with-buffer-shell program interactive args)) + (_ (error "Unsupported docker terminal backend: %s" backend)))) + +(defun docker-run-async-with-buffer-shell (program &optional interactive &rest args) + "Execute \"PROGRAM ARGS\" and display output in a new buffer. +If INTERACTIVE is non-nil, use a `shell' buffer for interactive use. +Otherwise, use a non-interactive buffer with ANSI color support." + (let* ((process (apply #'docker-run-start-file-process-shell-command program args)) + (buffer (process-buffer process))) + (set-process-query-on-exit-flag process nil) + (if interactive + (with-current-buffer buffer (shell-mode)) + (with-current-buffer buffer (special-mode))) + (set-process-filter process + (if interactive + 'comint-output-filter + 'docker-process-filter-noninteractive)) + (switch-to-buffer-other-window buffer))) + +(defun docker-run-async-with-buffer-vterm (program &optional interactive &rest args) + "Execute \"PROGRAM ARGS\" and display output in a new `vterm' buffer. +If INTERACTIVE is nil, fall back to shell mode since vterm is interactive." + (if (not interactive) + ;; vterm is interactive only, fall back to shell for non-interactive output + (apply #'docker-run-async-with-buffer-shell program nil args) + (defvar vterm-kill-buffer-on-exit) + (defvar vterm-shell) + (if (fboundp 'vterm-other-window) + (let* ((process-args (-remove 's-blank? (-flatten args))) + (vterm-shell (s-join " " (-insert-at 0 program process-args))) + (vterm-kill-buffer-on-exit nil)) + (vterm-other-window + (apply #'docker-utils-generate-new-buffer-name program process-args))) + (error "The vterm package is not installed")))) + +(defun docker-run-async-with-buffer-eat (program &optional interactive &rest args) + "Execute \"PROGRAM ARGS\" and display output in a new `eat' buffer. +If INTERACTIVE is nil, fall back to shell mode since eat is interactive." + (if (not interactive) + (apply #'docker-run-async-with-buffer-shell program nil args) + (defvar eat-buffer-name) + (if (fboundp 'eat-other-window) + (let* ((process-args (-remove 's-blank? (-flatten args))) + (command (s-join " " (-insert-at 0 program process-args))) + (eat-buffer-name (apply #'docker-utils-generate-new-buffer-name + program process-args))) + (eat-other-window command)) + (error "The eat package is not installed")))) + +(defun docker-process-filter-noninteractive (proc string) + "Process filter for non-interactive streaming buffers. +Strips carriage returns and applies ANSI color codes." + (when (buffer-live-p (process-buffer proc)) + (with-current-buffer (process-buffer proc) + (let ((inhibit-read-only t) + (moving (= (point) (process-mark proc)))) + (save-excursion + (goto-char (process-mark proc)) + (insert (ansi-color-apply (replace-regexp-in-string "\r" "" string))) + (set-marker (process-mark proc) (point))) + (when moving (goto-char (process-mark proc))))))) + +(defun docker-process-sentinel (promise process event) + "Sentinel that resolves the PROMISE using PROCESS and EVENT." + (when (memq (process-status process) '(exit signal)) + (setq event (substring event 0 -1)) + (if (not (string-equal event "finished")) + (aio-resolve promise + (lambda () + (error "Error running: \"%s\" (%s)" (process-name process) event))) + (aio-resolve promise + (lambda () + (when docker-show-messages + (message "Finished: %s" (process-name process))) + (run-with-timer 2 nil (lambda () (message nil))) + (with-current-buffer (process-buffer process) + (prog1 (buffer-substring-no-properties (point-min) (point-max)) + (kill-buffer)))))))) + +(provide 'docker-process) + +;;; docker-process.el ends here diff --git a/elpa/docker-20251028.1026/docker-utils.el b/elpa/docker-20260126.1212/docker-utils.el similarity index 94% rename from elpa/docker-20251028.1026/docker-utils.el rename to elpa/docker-20260126.1212/docker-utils.el index 0f178667..25041cf3 100644 --- a/elpa/docker-20251028.1026/docker-utils.el +++ b/elpa/docker-20260126.1212/docker-utils.el @@ -101,14 +101,18 @@ Execute BODY in a buffer named with the help of NAME." (defun docker-utils-unit-multiplier (str) "Return the correct multiplier for STR." - (expt 1024 (-elem-index (upcase str) '("B" "KB" "MB" "GB" "TB" "PB" "EB")))) + (let* ((unit (or str "B")) + (idx (-elem-index (upcase unit) '("B" "KB" "MB" "GB" "TB" "PB" "EB")))) + (expt 1024 (or idx 0)))) (defun docker-utils-human-size-to-bytes (str) "Parse STR and return size in bytes." - (let* ((parts (s-match "^\\([0-9\\.]+\\)\\([A-Z]+\\)?$" str)) - (value (string-to-number (-second-item parts))) - (multiplier (docker-utils-unit-multiplier (-third-item parts)))) - (* value multiplier))) + (let* ((parts (s-match "^\\([0-9\\.]+\\)\\([A-Za-z]+\\)?$" str))) + (unless parts + (error "Unexpected size format: %s" str)) + (let* ((value (string-to-number (-second-item parts))) + (multiplier (docker-utils-unit-multiplier (-third-item parts)))) + (* value multiplier)))) (defun docker-utils-human-size-predicate (a b) "Sort A and B by image size." diff --git a/elpa/docker-20251028.1026/docker-volume.el b/elpa/docker-20260126.1212/docker-volume.el similarity index 100% rename from elpa/docker-20251028.1026/docker-volume.el rename to elpa/docker-20260126.1212/docker-volume.el diff --git a/elpa/docker-20251028.1026/docker.el b/elpa/docker-20260126.1212/docker.el similarity index 95% rename from elpa/docker-20251028.1026/docker.el rename to elpa/docker-20260126.1212/docker.el index ad9ec741..48d5929e 100644 --- a/elpa/docker-20251028.1026/docker.el +++ b/elpa/docker-20260126.1212/docker.el @@ -3,8 +3,8 @@ ;; Author: Philippe Vaucher ;; URL: https://github.com/Silex/docker.el ;; Keywords: filename, convenience -;; Package-Version: 20251028.1026 -;; Package-Revision: 375e0ed45bb1 +;; Package-Version: 20260126.1212 +;; Package-Revision: 916686b86e83 ;; Package-Requires: ((aio "1.0") (dash "2.19.1") (emacs "28.1") (s "1.13.0") (tablist "1.1") (transient "0.4.3")) ;; This file is NOT part of GNU Emacs. -- 2.47.3