diff --git a/README.org b/README.org index 6a939bc..e6478ca 100644 --- a/README.org +++ b/README.org @@ -140,6 +140,8 @@ lsp: # (selected by a server id specified above) in stdio mode # Note: launch_command is not used with container subtype servers # as a command is embedded in a container itself and serves as an entrypoint + # Note: config path mappings are compared with an actual container (with container subtype servers): + # container mappings must contain all the config mappings (destination paths inside containers have to be absolute) mappings: - source: "/your/host/source/path" destination: "/your/local/path/inside/a/container" diff --git a/lsp-docker.el b/lsp-docker.el index 7ac7709..e772cd4 100644 --- a/lsp-docker.el +++ b/lsp-docker.el @@ -324,6 +324,35 @@ the docker container to run the language server." (f-same? (f-canonical (car it)) (f-canonical (lsp-workspace-root)))) path-mappings)) +(defun lsp-docker-verify-path-mappings-against-container (path-mappings container-name) + "Verify that specified path mappings are all included in container's path mappings" + (--all? (let ((source (car it)) + (destination (cdr it))) + (-any? (lambda (mapping) + (and (f-same? source (car mapping)) + (equal destination (cdr mapping)))) + (lsp-docker-get-path-mappings-from-container container-name))) + path-mappings)) + +(defun lsp-docker-get-path-mappings-from-container (container-name) + "Get path mappings from a container" + (-let (( + (inspection-command-program . inspection-command-arguments) + (--map-when + (equal it "'{{.Mounts}}'") + "'{{json .Mounts}}'" + (s-split " " (format "%s container inspect -f '{{.Mounts}}' %s" lsp-docker-command container-name))))) + (-let (((exit-code . raw-output) (with-temp-buffer + (cons + (apply #'call-process inspection-command-program nil (current-buffer) nil inspection-command-arguments) + (buffer-string))))) + (if (equal exit-code 0) + (let* ((output (s-chop-prefix "'" (s-chop-suffix "'" (s-chomp raw-output)))) + (raw-mappings (append (json-parse-string output) nil)) ; using append to convert a vector to a list + (bind-mappings (--filter (and (equal (gethash "Type" it) "bind") (equal (gethash "RW" it) t)) raw-mappings))) + (--map (cons (f-canonical (gethash "Source" it)) (f-canonical (gethash "Destination" it))) bind-mappings)) + (user-error "Cannot analyze the following container: %s, exit code: %d" container-name exit-code))))) + (defun lsp-docker-launch-existing-container (docker-container-name &rest _unused) "Return the docker command to be executed on host. Argument DOCKER-CONTAINER-NAME name to use for container." @@ -416,18 +445,20 @@ Argument DOCKER-CONTAINER-NAME name to use for container." :priority lsp-docker-default-priority :server-command server-launch-command :launch-server-cmd-fn #'lsp-docker-launch-new-container)) - ('container (lsp-docker-register-client-with-activation-fn - :server-id regular-server-id - :docker-server-id server-id - :path-mappings path-mappings - :docker-image-id nil - :docker-container-name server-container-name - :docker-container-name-suffix nil - :activation-fn (lsp-docker-create-activation-function-by-project-dir (lsp-workspace-root)) - :priority lsp-docker-default-priority - :server-command server-launch-command - :launch-server-cmd-fn #'lsp-docker-launch-existing-container)))))) - (user-error "Invalid LSP docker config: unsupported server type and/or subtype"))) + ('container (if (lsp-docker-verify-path-mappings-against-container path-mappings server-container-name) + (lsp-docker-register-client-with-activation-fn + :server-id regular-server-id + :docker-server-id server-id + :path-mappings path-mappings + :docker-image-id nil + :docker-container-name server-container-name + :docker-container-name-suffix nil + :activation-fn (lsp-docker-create-activation-function-by-project-dir (lsp-workspace-root)) + :priority lsp-docker-default-priority + :server-command server-launch-command + :launch-server-cmd-fn #'lsp-docker-launch-existing-container) + (user-error "Container path mappings don't match the config ones!"))))))) + (user-error "Invalid LSP docker config: unsupported server type and/or subtype or malformed mappings!"))) (user-error (format "Current file: %s is not in a registered project!" (buffer-file-name))))) (defun lsp-docker-start ()