aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2020-02-01 14:29:45 +0100
committerMichael Albinus2020-02-01 14:29:45 +0100
commitbb1d42b955629487537dee9423d5a4fc837033ae (patch)
tree68024f1fbcb916db0b12957aa54d727cf270595b
parentd3ead375092e2690c1d1d6a5dd82e6e89cdf4f4c (diff)
downloademacs-bb1d42b955629487537dee9423d5a4fc837033ae.tar.gz
emacs-bb1d42b955629487537dee9423d5a4fc837033ae.zip
Implement `shell-command-dont-erase-buffer' in Tramp. (Bug#39067)
* lisp/net/tramp.el (tramp-handle-shell-command): Handle `shell-command-dont-erase-buffer'. (Bug#39067) * test/lisp/net/tramp-tests.el (shell-command-dont-erase-buffer): Declare. (tramp-test10-write-region, tramp-test21-file-links): Use function symbols. (tramp--test-async-shell-command): Don't assume that `async-shell-command' returns the process object. (tramp-test32-shell-command): Rework `async-shell-command-width' test. (tramp-test32-shell-command-dont-erase-buffer): New test.
-rw-r--r--lisp/net/tramp.el73
-rw-r--r--test/lisp/net/tramp-tests.el141
2 files changed, 159 insertions, 55 deletions
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 70d0fb070d8..a38b3c6e51c 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3621,8 +3621,13 @@ support symbolic links."
3621 (output-buffer-p output-buffer) 3621 (output-buffer-p output-buffer)
3622 (output-buffer 3622 (output-buffer
3623 (cond 3623 (cond
3624 ((bufferp output-buffer) output-buffer) 3624 ((bufferp output-buffer)
3625 ((stringp output-buffer) (get-buffer-create output-buffer)) 3625 (setq current-buffer-p (eq (current-buffer) output-buffer))
3626 output-buffer)
3627 ((stringp output-buffer)
3628 (setq current-buffer-p
3629 (eq (buffer-name (current-buffer)) output-buffer))
3630 (get-buffer-create output-buffer))
3626 (output-buffer 3631 (output-buffer
3627 (setq current-buffer-p t) 3632 (setq current-buffer-p t)
3628 (current-buffer)) 3633 (current-buffer))
@@ -3634,6 +3639,11 @@ support symbolic links."
3634 (cond 3639 (cond
3635 ((bufferp error-buffer) error-buffer) 3640 ((bufferp error-buffer) error-buffer)
3636 ((stringp error-buffer) (get-buffer-create error-buffer)))) 3641 ((stringp error-buffer) (get-buffer-create error-buffer))))
3642 (error-file
3643 (and error-buffer
3644 (with-parsed-tramp-file-name default-directory nil
3645 (tramp-make-tramp-file-name
3646 v (tramp-make-tramp-temp-file v)))))
3637 (bname (buffer-name output-buffer)) 3647 (bname (buffer-name output-buffer))
3638 (p (get-buffer-process output-buffer)) 3648 (p (get-buffer-process output-buffer))
3639 (dir default-directory) 3649 (dir default-directory)
@@ -3641,7 +3651,7 @@ support symbolic links."
3641 3651
3642 ;; The following code is taken from `shell-command', slightly 3652 ;; The following code is taken from `shell-command', slightly
3643 ;; adapted. Shouldn't it be factored out? 3653 ;; adapted. Shouldn't it be factored out?
3644 (when p 3654 (when (and (integerp asynchronous) p)
3645 (cond 3655 (cond
3646 ((eq async-shell-command-buffer 'confirm-kill-process) 3656 ((eq async-shell-command-buffer 'confirm-kill-process)
3647 ;; If will kill a process, query first. 3657 ;; If will kill a process, query first.
@@ -3677,22 +3687,21 @@ support symbolic links."
3677 (with-current-buffer output-buffer 3687 (with-current-buffer output-buffer
3678 (setq default-directory dir))) 3688 (setq default-directory dir)))
3679 3689
3680 (setq buffer (if error-buffer 3690 (setq buffer (if error-file (list output-buffer error-file) output-buffer))
3681 (with-parsed-tramp-file-name default-directory nil 3691
3682 (list output-buffer 3692 (with-current-buffer output-buffer
3683 (tramp-make-tramp-file-name 3693 (when current-buffer-p
3684 v (tramp-make-tramp-temp-file v)))) 3694 (barf-if-buffer-read-only)
3685 output-buffer)) 3695 (push-mark nil t))
3686 3696 ;; `shell-command-save-pos-or-erase' has been introduced with
3687 (if current-buffer-p 3697 ;; Emacs 27.1.
3688 (progn 3698 (if (fboundp 'shell-command-save-pos-or-erase)
3689 (barf-if-buffer-read-only) 3699 (tramp-compat-funcall
3690 (push-mark nil t)) 3700 'shell-command-save-pos-or-erase current-buffer-p)
3691 (with-current-buffer output-buffer
3692 (setq buffer-read-only nil) 3701 (setq buffer-read-only nil)
3693 (erase-buffer))) 3702 (erase-buffer)))
3694 3703
3695 (if (and (not current-buffer-p) (integerp asynchronous)) 3704 (if (integerp asynchronous)
3696 (let ((tramp-remote-process-environment 3705 (let ((tramp-remote-process-environment
3697 ;; `async-shell-command-width' has been introduced with 3706 ;; `async-shell-command-width' has been introduced with
3698 ;; Emacs 27.1. 3707 ;; Emacs 27.1.
@@ -3706,9 +3715,9 @@ support symbolic links."
3706 (setq p (start-file-process-shell-command 3715 (setq p (start-file-process-shell-command
3707 (buffer-name output-buffer) buffer command)) 3716 (buffer-name output-buffer) buffer command))
3708 ;; Insert error messages if they were separated. 3717 ;; Insert error messages if they were separated.
3709 (when (consp buffer) 3718 (when error-file
3710 (with-current-buffer error-buffer 3719 (with-current-buffer error-buffer
3711 (insert-file-contents-literally (cadr buffer)))) 3720 (insert-file-contents-literally error-file)))
3712 (if (process-live-p p) 3721 (if (process-live-p p)
3713 ;; Display output. 3722 ;; Display output.
3714 (with-current-buffer output-buffer 3723 (with-current-buffer output-buffer
@@ -3717,34 +3726,40 @@ support symbolic links."
3717 (shell-mode) 3726 (shell-mode)
3718 (set-process-filter p #'comint-output-filter) 3727 (set-process-filter p #'comint-output-filter)
3719 (set-process-sentinel p #'shell-command-sentinel) 3728 (set-process-sentinel p #'shell-command-sentinel)
3720 (when (consp buffer) 3729 (when error-file
3721 (add-function 3730 (add-function
3722 :after (process-sentinel p) 3731 :after (process-sentinel p)
3723 (lambda (_proc _string) 3732 (lambda (_proc _string)
3724 (with-current-buffer error-buffer 3733 (with-current-buffer error-buffer
3725 (insert-file-contents-literally 3734 (insert-file-contents-literally
3726 (cadr buffer) nil nil nil 'replace)) 3735 error-file nil nil nil 'replace))
3727 (delete-file (cadr buffer)))))) 3736 (delete-file error-file)))))
3728 3737
3729 (when (consp buffer) 3738 (when error-file
3730 (delete-file (cadr buffer)))))) 3739 (delete-file error-file)))))
3731 3740
3732 (prog1 3741 (prog1
3733 ;; Run the process. 3742 ;; Run the process.
3734 (process-file-shell-command command nil buffer nil) 3743 (process-file-shell-command command nil buffer nil)
3735 ;; Insert error messages if they were separated. 3744 ;; Insert error messages if they were separated.
3736 (when (consp buffer) 3745 (when error-file
3737 (with-current-buffer error-buffer 3746 (with-current-buffer error-buffer
3738 (insert-file-contents-literally (cadr buffer))) 3747 (insert-file-contents-literally error-file))
3739 (delete-file (cadr buffer))) 3748 (delete-file error-file))
3740 (if current-buffer-p 3749 (if current-buffer-p
3741 ;; This is like exchange-point-and-mark, but doesn't 3750 ;; This is like exchange-point-and-mark, but doesn't
3742 ;; activate the mark. It is cleaner to avoid activation, 3751 ;; activate the mark. It is cleaner to avoid activation,
3743 ;; even though the command loop would deactivate the mark 3752 ;; even though the command loop would deactivate the mark
3744 ;; because we inserted text. 3753 ;; because we inserted text.
3745 (goto-char (prog1 (mark t) 3754 (progn
3746 (set-marker (mark-marker) (point) 3755 (goto-char (prog1 (mark t)
3747 (current-buffer)))) 3756 (set-marker (mark-marker) (point)
3757 (current-buffer))))
3758 ;; `shell-command-set-point-after-cmd' has been
3759 ;; introduced with Emacs 27.1.
3760 (if (fboundp 'shell-command-set-point-after-cmd)
3761 (tramp-compat-funcall
3762 'shell-command-set-point-after-cmd)))
3748 ;; There's some output, display it. 3763 ;; There's some output, display it.
3749 (when (with-current-buffer output-buffer (> (point-max) (point-min))) 3764 (when (with-current-buffer output-buffer (> (point-max) (point-min)))
3750 (display-message-or-buffer output-buffer))))))) 3765 (display-message-or-buffer output-buffer)))))))
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 7ffd22e77be..89ab493c062 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -72,6 +72,8 @@
72(defvar connection-local-profile-alist) 72(defvar connection-local-profile-alist)
73;; Needed for Emacs 26. 73;; Needed for Emacs 26.
74(defvar async-shell-command-width) 74(defvar async-shell-command-width)
75;; Needed for Emacs 27.
76(defvar shell-command-dont-erase-buffer)
75 77
76;; Beautify batch mode. 78;; Beautify batch mode.
77(when noninteractive 79(when noninteractive
@@ -2389,14 +2391,14 @@ This checks also `file-name-as-directory', `file-name-directory',
2389 tramp--test-messages)))))))) 2391 tramp--test-messages))))))))
2390 2392
2391 ;; Do not overwrite if excluded. 2393 ;; Do not overwrite if excluded.
2392 (cl-letf (((symbol-function 'y-or-n-p) (lambda (_prompt) t)) 2394 (cl-letf (((symbol-function #'y-or-n-p) (lambda (_prompt) t))
2393 ;; Ange-FTP. 2395 ;; Ange-FTP.
2394 ((symbol-function 'yes-or-no-p) (lambda (_prompt) t))) 2396 ((symbol-function 'yes-or-no-p) (lambda (_prompt) t)))
2395 (write-region "foo" nil tmp-name nil nil nil 'mustbenew)) 2397 (write-region "foo" nil tmp-name nil nil nil 'mustbenew))
2396 ;; `mustbenew' is passed to Tramp since Emacs 26.1. 2398 ;; `mustbenew' is passed to Tramp since Emacs 26.1.
2397 (when (tramp--test-emacs26-p) 2399 (when (tramp--test-emacs26-p)
2398 (should-error 2400 (should-error
2399 (cl-letf (((symbol-function 'y-or-n-p) 'ignore) 2401 (cl-letf (((symbol-function #'y-or-n-p) #'ignore)
2400 ;; Ange-FTP. 2402 ;; Ange-FTP.
2401 ((symbol-function 'yes-or-no-p) 'ignore)) 2403 ((symbol-function 'yes-or-no-p) 'ignore))
2402 (write-region "foo" nil tmp-name nil nil nil 'mustbenew)) 2404 (write-region "foo" nil tmp-name nil nil nil 'mustbenew))
@@ -3416,11 +3418,11 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
3416 :type 'file-already-exists)) 3418 :type 'file-already-exists))
3417 (when (tramp--test-expensive-test) 3419 (when (tramp--test-expensive-test)
3418 ;; A number means interactive case. 3420 ;; A number means interactive case.
3419 (cl-letf (((symbol-function 'yes-or-no-p) #'ignore)) 3421 (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
3420 (should-error 3422 (should-error
3421 (make-symbolic-link tmp-name1 tmp-name2 0) 3423 (make-symbolic-link tmp-name1 tmp-name2 0)
3422 :type 'file-already-exists))) 3424 :type 'file-already-exists)))
3423 (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t))) 3425 (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_prompt) t)))
3424 (make-symbolic-link tmp-name1 tmp-name2 0) 3426 (make-symbolic-link tmp-name1 tmp-name2 0)
3425 (should 3427 (should
3426 (string-equal 3428 (string-equal
@@ -3492,11 +3494,11 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
3492 (add-name-to-file tmp-name1 tmp-name2) 3494 (add-name-to-file tmp-name1 tmp-name2)
3493 :type 'file-already-exists) 3495 :type 'file-already-exists)
3494 ;; A number means interactive case. 3496 ;; A number means interactive case.
3495 (cl-letf (((symbol-function 'yes-or-no-p) #'ignore)) 3497 (cl-letf (((symbol-function #'yes-or-no-p) #'ignore))
3496 (should-error 3498 (should-error
3497 (add-name-to-file tmp-name1 tmp-name2 0) 3499 (add-name-to-file tmp-name1 tmp-name2 0)
3498 :type 'file-already-exists)) 3500 :type 'file-already-exists))
3499 (cl-letf (((symbol-function 'yes-or-no-p) (lambda (_prompt) t))) 3501 (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_prompt) t)))
3500 (add-name-to-file tmp-name1 tmp-name2 0) 3502 (add-name-to-file tmp-name1 tmp-name2 0)
3501 (should (file-regular-p tmp-name2))) 3503 (should (file-regular-p tmp-name2)))
3502 (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists) 3504 (add-name-to-file tmp-name1 tmp-name2 'ok-if-already-exists)
@@ -4437,7 +4439,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
4437 (command output-buffer &optional error-buffer input) 4439 (command output-buffer &optional error-buffer input)
4438 "Like `async-shell-command', reading the output. 4440 "Like `async-shell-command', reading the output.
4439INPUT, if non-nil, is a string sent to the process." 4441INPUT, if non-nil, is a string sent to the process."
4440 (let ((proc (async-shell-command command output-buffer error-buffer)) 4442 (async-shell-command command output-buffer error-buffer)
4443 (let ((proc (get-buffer-process output-buffer))
4441 (delete-exited-processes t)) 4444 (delete-exited-processes t))
4442 (when (stringp input) 4445 (when (stringp input)
4443 (process-send-string proc input)) 4446 (process-send-string proc input))
@@ -4532,25 +4535,111 @@ INPUT, if non-nil, is a string sent to the process."
4532 (buffer-string)))) 4535 (buffer-string))))
4533 4536
4534 ;; Cleanup. 4537 ;; Cleanup.
4535 (ignore-errors (delete-file tmp-name))) 4538 (ignore-errors (delete-file tmp-name)))))
4536 4539
4537 ;; Test `async-shell-command-width'. Since Emacs 27.1. 4540 ;; Test `async-shell-command-width'. It exists since Emacs 26.1,
4538 (when (ignore-errors 4541 ;; but seems to work since Emacs 27.1 only.
4539 (and (boundp 'async-shell-command-width) 4542 (when (and (tramp--test-sh-p) (tramp--test-emacs27-p))
4540 (zerop (call-process "tput" nil nil nil "cols")) 4543 (let* ((async-shell-command-width 1024)
4541 (zerop (process-file "tput" nil nil nil "cols")))) 4544 (cols (ignore-errors
4542 (let (async-shell-command-width) 4545 (read (tramp--test-shell-command-to-string-asynchronously
4543 (should 4546 "tput cols")))))
4544 (string-equal 4547 (when (natnump cols)
4545 (format "%s\n" (car (process-lines "tput" "cols"))) 4548 (should (= cols async-shell-command-width))))))
4546 (tramp--test-shell-command-to-string-asynchronously 4549
4547 "tput cols"))) 4550(ert-deftest tramp-test32-shell-command-dont-erase-buffer ()
4548 (setq async-shell-command-width 1024) 4551 "Check `shell-command'."
4549 (should 4552 :tags '(:expensive-test)
4550 (string-equal 4553 (skip-unless (tramp--test-enabled))
4551 "1024\n" 4554 (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
4552 (tramp--test-shell-command-to-string-asynchronously 4555 ;; Prior Emacs 27, `shell-command-dont-erase-buffer' wasn't working properly.
4553 "tput cols")))))))) 4556 (skip-unless (tramp--test-emacs27-p))
4557
4558 ;; We check both the local and remote case, in order to guarantee
4559 ;; that they behave similar.
4560 (dolist (default-directory
4561 `(,temporary-file-directory ,tramp-test-temporary-file-directory))
4562 (let ((buffer (generate-new-buffer "foo"))
4563 ;; Suppress nasty messages.
4564 (inhibit-message t)
4565 point kill-buffer-query-functions)
4566 (unwind-protect
4567 (progn
4568 ;; Don't erase if buffer is the current one. Point is not moved.
4569 (let (shell-command-dont-erase-buffer)
4570 (with-temp-buffer
4571 (insert "bar")
4572 (setq point (point))
4573 (should (string-equal "bar" (buffer-string)))
4574 (should (= (point) (point-max)))
4575 (shell-command "echo baz" (current-buffer))
4576 (should (string-equal "barbaz\n" (buffer-string)))
4577 (should (= point (point)))))
4578
4579 ;; Erase if the buffer is not current one.
4580 (let (shell-command-dont-erase-buffer)
4581 (with-current-buffer buffer
4582 (erase-buffer)
4583 (insert "bar")
4584 (setq point (point))
4585 (should (string-equal "bar" (buffer-string)))
4586 (should (= (point) (point-max)))
4587 (with-temp-buffer
4588 (shell-command "echo baz" buffer))
4589 (should (string-equal "baz\n" (buffer-string)))
4590 (should (= point (point)))))
4591
4592 ;; Erase if buffer is the current one, but
4593 ;; `shell-command-dont-erase-buffer' is set to `erase'.
4594 (let ((shell-command-dont-erase-buffer 'erase))
4595 (with-temp-buffer
4596 (insert "bar")
4597 (setq point (point))
4598 (should (string-equal "bar" (buffer-string)))
4599 (should (= (point) (point-max)))
4600 (shell-command "echo baz" (current-buffer))
4601 (should (string-equal "baz\n" (buffer-string)))
4602 (should (= (point) (point-max)))))
4603
4604 ;; Don't erase if `shell-command-dont-erase-buffer' is set
4605 ;; to `beg-last-out'. Check point.
4606 (let ((shell-command-dont-erase-buffer 'beg-last-out))
4607 (with-temp-buffer
4608 (insert "bar")
4609 (setq point (point))
4610 (should (string-equal "bar" (buffer-string)))
4611 (should (= (point) (point-max)))
4612 (shell-command "echo baz" (current-buffer))
4613 (should (string-equal "barbaz\n" (buffer-string)))
4614 (should (= point (point)))))
4615
4616 ;; Don't erase if `shell-command-dont-erase-buffer' is set
4617 ;; to `end-last-out'. Check point.
4618 (let ((shell-command-dont-erase-buffer 'end-last-out))
4619 (with-temp-buffer
4620 (insert "bar")
4621 (setq point (point))
4622 (should (string-equal "bar" (buffer-string)))
4623 (should (= (point) (point-max)))
4624 (shell-command "echo baz" (current-buffer))
4625 (should (string-equal "barbaz\n" (buffer-string)))
4626 (should (= (point) (point-max)))))
4627
4628 ;; Don't erase if `shell-command-dont-erase-buffer' is set
4629 ;; to `save-point'. Check point.
4630 (let ((shell-command-dont-erase-buffer 'save-point))
4631 (with-temp-buffer
4632 (insert "bar")
4633 (goto-char (1- (point-max)))
4634 (setq point (point))
4635 (should (string-equal "bar" (buffer-string)))
4636 (should (= (point) (1- (point-max))))
4637 (shell-command "echo baz" (current-buffer))
4638 (should (string-equal "barbaz\n" (buffer-string)))
4639 (should (= point (point))))))
4640
4641 ;; Cleanup.
4642 (ignore-errors (kill-buffer buffer))))))
4554 4643
4555;; This test is inspired by Bug#23952. 4644;; This test is inspired by Bug#23952.
4556(ert-deftest tramp-test33-environment-variables () 4645(ert-deftest tramp-test33-environment-variables ()