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

Reply via email to