Jürgen Hötzel <[email protected]> writes: > Hi Michael,
Hi Juergen, enclosed are the patches for process handling. Works so far, when current-buffer is a remote one on your Android device. When you call "M-x shell", you shall apply in advance (setq shell-file-name "sh"); otherwise your local shell is called. I'm not an Android developer, so I don't know how useful it is. I have copied a lot of code from tramp-sh.el; likely this could be simplified if tramp-adb.el would be integrated tighter into Tramp. > Any ideas how we could handle copy-directory? I'll have a look on it. > Jürgen Best regards, Michael.
>From 1d9bf40583d748eeca85ac0b24e091ade934dbe0 Mon Sep 17 00:00:00 2001 From: Michael Albinus <[email protected]> Date: Tue, 31 May 2011 21:21:49 +0200 Subject: [PATCH 1/4] Add `tramp-adb-handle-process-file'. --- tramp-adb.el | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 113 insertions(+), 1 deletions(-) diff --git a/tramp-adb.el b/tramp-adb.el index 991567a..5a71aa7 100644 --- a/tramp-adb.el +++ b/tramp-adb.el @@ -98,7 +98,8 @@ (set-file-modes . tramp-adb-handle-set-file-modes) (set-file-times . ignore) (copy-file . tramp-adb-handle-copy-file) - (rename-file . tramp-adb-handle-rename-file)) + (rename-file . tramp-adb-handle-rename-file) + (process-file . tramp-adb-handle-process-file)) "Alist of handler functions for Tramp ADB method.") ;;;###tramp-autoload @@ -575,6 +576,117 @@ PRESERVE-UID-GID and PRESERVE-SELINUX-CONTEXT are completely ignored." (copy-file filename newname ok-if-already-exists t t) (delete-file filename))))) +(defun tramp-adb-handle-process-file + (program &optional infile destination display &rest args) + "Like `process-file' for Tramp files." + ;; The implementation is not complete yet. + (when (and (numberp destination) (zerop destination)) + (error "Implementation does not handle immediate return")) + + (with-parsed-tramp-file-name default-directory nil + (let (command input tmpinput stderr tmpstderr outbuf ret) + ;; Compute command. + (setq command (mapconcat 'tramp-shell-quote-argument + (cons program args) " ")) + ;; Determine input. + (if (null infile) + (setq input "/dev/null") + (setq infile (expand-file-name infile)) + (if (tramp-equal-remote default-directory infile) + ;; INFILE is on the same remote host. + (setq input (with-parsed-tramp-file-name infile nil localname)) + ;; INFILE must be copied to remote host. + (setq input (tramp-make-tramp-temp-file v) + tmpinput (tramp-make-tramp-file-name method user host input)) + (copy-file infile tmpinput t))) + (when input (setq command (format "%s <%s" command input))) + + ;; Determine output. + (cond + ;; Just a buffer. + ((bufferp destination) + (setq outbuf destination)) + ;; A buffer name. + ((stringp destination) + (setq outbuf (get-buffer-create destination))) + ;; (REAL-DESTINATION ERROR-DESTINATION) + ((consp destination) + ;; output. + (cond + ((bufferp (car destination)) + (setq outbuf (car destination))) + ((stringp (car destination)) + (setq outbuf (get-buffer-create (car destination)))) + ((car destination) + (setq outbuf (current-buffer)))) + ;; stderr. + (cond + ((stringp (cadr destination)) + (setcar (cdr destination) (expand-file-name (cadr destination))) + (if (tramp-equal-remote default-directory (cadr destination)) + ;; stderr is on the same remote host. + (setq stderr (with-parsed-tramp-file-name + (cadr destination) nil localname)) + ;; stderr must be copied to remote host. The temporary + ;; file must be deleted after execution. + (setq stderr (tramp-make-tramp-temp-file v) + tmpstderr (tramp-make-tramp-file-name + method user host stderr)))) + ;; stderr to be discarded. + ((null (cadr destination)) + (setq stderr "/dev/null")))) + ;; 't + (destination + (setq outbuf (current-buffer)))) + (when stderr (setq command (format "%s 2>%s" command stderr))) + + ;; Send the command. It might not return in time, so we protect + ;; it. Call it in a subshell, in order to preserve working + ;; directory. + (condition-case nil + (progn + (setq ret 0 + ret + (tramp-adb-barf-unless-okay + v (format "(cd %s; %s)" + (tramp-shell-quote-argument localname) + command) + "")) + ;; We should show the output anyway. + (when outbuf + (with-current-buffer outbuf + (insert-buffer-substring (tramp-get-connection-buffer v))) + (when display (display-buffer outbuf)))) + ;; When the user did interrupt, we should do it also. We use + ;; return code -1 as marker. + (quit + (kill-buffer (tramp-get-connection-buffer v)) + (setq ret -1)) + ;; Handle errors. + (error + (kill-buffer (tramp-get-connection-buffer v)) + (setq ret 1))) + + ;; Provide error file. + (when tmpstderr (rename-file tmpstderr (cadr destination) t)) + + ;; Cleanup. We remove all file cache values for the connection, + ;; because the remote process could have changed them. + (when tmpinput (delete-file tmpinput)) + + ;; `process-file-side-effects' has been introduced with GNU + ;; Emacs 23.2. If set to `nil', no remote file will be changed + ;; by `program'. If it doesn't exist, we assume its default + ;; value 't'. + (unless (and (boundp 'process-file-side-effects) + (not (symbol-value 'process-file-side-effects))) + (tramp-flush-directory-property v "")) + + ;; Return exit status. + (if (equal ret -1) + (keyboard-quit) + ret)))) + ;; Android doesn't provide test command (defun tramp-adb-handle-file-exists-p (filename) -- 1.7.4.1
>From a3178cb11feab7cd0c876c55158dd4df124d798d Mon Sep 17 00:00:00 2001 From: Michael Albinus <[email protected]> Date: Tue, 31 May 2011 21:52:53 +0200 Subject: [PATCH 2/4] Add `tramp-adb-handle-shell-command'. --- tramp-adb.el | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 78 insertions(+), 1 deletions(-) diff --git a/tramp-adb.el b/tramp-adb.el index 5a71aa7..856da96 100644 --- a/tramp-adb.el +++ b/tramp-adb.el @@ -99,7 +99,8 @@ (set-file-times . ignore) (copy-file . tramp-adb-handle-copy-file) (rename-file . tramp-adb-handle-rename-file) - (process-file . tramp-adb-handle-process-file)) + (process-file . tramp-adb-handle-process-file) + (shell-command . tramp-adb-handle-shell-command)) "Alist of handler functions for Tramp ADB method.") ;;;###tramp-autoload @@ -687,6 +688,82 @@ PRESERVE-UID-GID and PRESERVE-SELINUX-CONTEXT are completely ignored." (keyboard-quit) ret)))) +(defun tramp-adb-handle-shell-command + (command &optional output-buffer error-buffer) + "Like `shell-command' for Tramp files." + (let* ((asynchronous (string-match "[ \t]*&[ \t]*\\'" command)) + ;; We cannot use `shell-file-name' and `shell-command-switch', + ;; they are variables of the local host. + (args (list "sh" "-c" (substring command 0 asynchronous))) + current-buffer-p + (output-buffer + (cond + ((bufferp output-buffer) output-buffer) + ((stringp output-buffer) (get-buffer-create output-buffer)) + (output-buffer + (setq current-buffer-p t) + (current-buffer)) + (t (get-buffer-create + (if asynchronous + "*Async Shell Command*" + "*Shell Command Output*"))))) + (error-buffer + (cond + ((bufferp error-buffer) error-buffer) + ((stringp error-buffer) (get-buffer-create error-buffer)))) + (buffer + (if (and (not asynchronous) error-buffer) + (with-parsed-tramp-file-name default-directory nil + (list output-buffer (tramp-make-tramp-temp-file v))) + output-buffer)) + (p (get-buffer-process output-buffer))) + + ;; Check whether there is another process running. Tramp does not + ;; support 2 (asynchronous) processes in parallel. + (when p + (if (yes-or-no-p "A command is running. Kill it? ") + (ignore-errors (kill-process p)) + (error "Shell command in progress"))) + + (if current-buffer-p + (progn + (barf-if-buffer-read-only) + (push-mark nil t)) + (with-current-buffer output-buffer + (setq buffer-read-only nil) + (erase-buffer))) + + (if (and (not current-buffer-p) (integerp asynchronous)) + (prog1 + ;; Run the process. + (apply 'start-file-process "*Async Shell*" buffer args) + ;; Display output. + (pop-to-buffer output-buffer) + (setq mode-line-process '(":%s")) + (shell-mode)) + + (prog1 + ;; Run the process. + (apply 'process-file (car args) nil buffer nil (cdr args)) + ;; Insert error messages if they were separated. + (when (listp buffer) + (with-current-buffer error-buffer + (insert-file-contents (cadr buffer))) + (delete-file (cadr buffer))) + (if current-buffer-p + ;; This is like exchange-point-and-mark, but doesn't + ;; activate the mark. It is cleaner to avoid activation, + ;; even though the command loop would deactivate the mark + ;; because we inserted text. + (goto-char (prog1 (mark t) + (set-marker (mark-marker) (point) + (current-buffer)))) + ;; There's some output, display it. + (when (with-current-buffer output-buffer (> (point-max) (point-min))) + (if (functionp 'display-message-or-buffer) + (tramp-compat-funcall 'display-message-or-buffer output-buffer) + (pop-to-buffer output-buffer)))))))) + ;; Android doesn't provide test command (defun tramp-adb-handle-file-exists-p (filename) -- 1.7.4.1
>From a21235d23abbe859e41d8ff1b08dcb868e03f1f3 Mon Sep 17 00:00:00 2001 From: Michael Albinus <[email protected]> Date: Tue, 31 May 2011 22:27:26 +0200 Subject: [PATCH 3/4] Add `tramp-adb-handle-start-file-process'. --- tramp-adb.el | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 66 insertions(+), 2 deletions(-) diff --git a/tramp-adb.el b/tramp-adb.el index 856da96..f1e740e 100644 --- a/tramp-adb.el +++ b/tramp-adb.el @@ -77,6 +77,8 @@ (file-remote-p . tramp-handle-file-remote-p) (file-directory-p . tramp-adb-handle-file-directory-p) (file-symlink-p . tramp-handle-file-symlink-p) + ;; FIXME: This is too sloppy. + (file-executable-p . file-exists-p) (file-exists-p . tramp-adb-handle-file-exists-p) (file-readable-p . tramp-handle-file-exists-p) (file-writable-p . tramp-adb-handle-file-writable-p) @@ -100,7 +102,8 @@ (copy-file . tramp-adb-handle-copy-file) (rename-file . tramp-adb-handle-rename-file) (process-file . tramp-adb-handle-process-file) - (shell-command . tramp-adb-handle-shell-command)) + (shell-command . tramp-adb-handle-shell-command) + (start-file-process . tramp-adb-handle-start-file-process)) "Alist of handler functions for Tramp ADB method.") ;;;###tramp-autoload @@ -764,6 +767,67 @@ PRESERVE-UID-GID and PRESERVE-SELINUX-CONTEXT are completely ignored." (tramp-compat-funcall 'display-message-or-buffer output-buffer) (pop-to-buffer output-buffer)))))))) +;; We use BUFFER also as connection buffer during setup. Because of +;; this, its original contents must be saved, and restored once +;; connection has been setup. +(defun tramp-adb-handle-start-file-process (name buffer program &rest args) + "Like `start-file-process' for Tramp files." + (with-parsed-tramp-file-name default-directory nil + ;; When PROGRAM is nil, we just provide a tty. + (let ((command + (when (stringp program) + (format "cd %s; exec %s" + (tramp-shell-quote-argument localname) + (mapconcat 'tramp-shell-quote-argument + (cons program args) " ")))) + (tramp-process-connection-type + (or (null program) tramp-process-connection-type)) + (bmp (and (buffer-live-p buffer) (buffer-modified-p buffer))) + (name1 name) + (i 0)) + (unwind-protect + (save-excursion + (save-restriction + (unless buffer + ;; BUFFER can be nil. We use a temporary buffer. + (setq buffer (generate-new-buffer tramp-temp-buffer-name))) + (while (get-process name1) + ;; NAME must be unique as process name. + (setq i (1+ i) + name1 (format "%s<%d>" name i))) + (setq name name1) + ;; Set the new process properties. + (tramp-set-connection-property v "process-name" name) + (tramp-set-connection-property v "process-buffer" buffer) + ;; Activate narrowing in order to save BUFFER contents. + ;; Clear also the modification time; otherwise we might + ;; be interrupted by `verify-visited-file-modtime'. + (with-current-buffer (tramp-get-connection-buffer v) + (let ((buffer-undo-list t)) + (clear-visited-file-modtime) + (narrow-to-region (point-max) (point-max)) + (if command + ;; Send the command. + (tramp-adb-send-command v command) + ;; Open the connection. + (tramp-adb-maybe-open-connection v)))) + (let ((p (tramp-get-connection-process v))) + ;; Set sentinel and query flag for this process. + (tramp-set-connection-property p "vector" v) + (set-process-sentinel p 'tramp-process-sentinel) + (tramp-compat-set-process-query-on-exit-flag p t) + ;; Return process. + p))) + ;; Save exit. + (with-current-buffer (tramp-get-connection-buffer v) + (if (string-match tramp-temp-buffer-name (buffer-name)) + (progn + (set-process-buffer (tramp-get-connection-process v) nil) + (kill-buffer (current-buffer))) + (set-buffer-modified-p bmp))) + (tramp-set-connection-property v "process-name" nil) + (tramp-set-connection-property v "process-buffer" nil))))) + ;; Android doesn't provide test command (defun tramp-adb-handle-file-exists-p (filename) @@ -851,7 +915,7 @@ FMT and ARGS are passed to `error'." "Maybe open a connection VEC. Does not do anything if a connection is already open, but re-opens the connection if a previous connection has died for some reason." - (let* ((buf (tramp-get-buffer vec)) + (let* ((buf (tramp-get-connection-buffer vec)) (p (get-buffer-process buf))) (unless (and p (processp p) (memq (process-status p) '(run open))) -- 1.7.4.1
>From b251ace4fa4abe2bf279bd6e12861b502de6febf Mon Sep 17 00:00:00 2001 From: Michael Albinus <[email protected]> Date: Wed, 1 Jun 2011 21:36:44 +0200 Subject: [PATCH 4/4] Tuning for asynchronous processes. --- tramp-adb.el | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tramp-adb.el b/tramp-adb.el index f1e740e..010211f 100644 --- a/tramp-adb.el +++ b/tramp-adb.el @@ -776,7 +776,7 @@ PRESERVE-UID-GID and PRESERVE-SELINUX-CONTEXT are completely ignored." ;; When PROGRAM is nil, we just provide a tty. (let ((command (when (stringp program) - (format "cd %s; exec %s" + (format "cd %s; %s" (tramp-shell-quote-argument localname) (mapconcat 'tramp-shell-quote-argument (cons program args) " ")))) @@ -929,7 +929,7 @@ connection if a previous connection has died for some reason." (list "shell"))) (p (let ((default-directory (tramp-compat-temporary-file-directory))) - (apply 'start-process (tramp-buffer-name vec) buf + (apply 'start-process (tramp-get-connection-name vec) buf (tramp-adb-program) args)))) (tramp-message vec 6 "%s" (mapconcat 'identity (process-command p) " ")) -- 1.7.4.1
_______________________________________________ Tramp-devel mailing list [email protected] https://lists.gnu.org/mailman/listinfo/tramp-devel
